Compiling Sdr for Linux

Saturday May 15th, 2004.
 

The following describes a procedure for compiling sdr from the source code to run under the standard Linux kernel (2.4 series) and also describes the extra steps needed to compile sdr to run under the USAGI kernel. USAGI is an advanced IPv6 stack for Linux developed in Japan (http://www.linux-ipv6.org). Some source code and header file adaptations are needed to enable sdr to run under USAGI because USAGI has a different implementation of the bind system call.

What is needed to compile sdr and the rest of the Mbone tools (MICE tools) are the source code of the tool itself, the source code of the common multimedia library, the source code of TCL and the source code of TK. All of those can be found in the MICE webpage in UCL’s site (University College London): http://www-mice.cs.ucl.ac.uk/multimedia/software.

The TCL and TK libraries maintained by the site are special versions that are patched by UCL to work with the Mbone tools.

The following steps are required to compile sdr:

1- Start by downloading the source code from UCL’s MICE tools page (http://www-mice.cs.ucl.ac.uk/multimedia/software). The current sdr version is sdr 3.0.

2- Also download the source code of the common multimedia library from the same site (common). This code is used by all MICE tools.

3- Download the UCL patched versions of TCL and TK.

4- Create a work directory for the compilation process and copy all tarballs to it:

cd
mkdir mice
cp sdr-3.0.tar.gz mice
cp common-1.2.14.tar.gz  mice
cp tcl-8.0.3ucl8.tar.gz  mice
cp tk-8.0.3ucl8.tar.gz   mice

5- Uncompress and extract (unzip and untar) all four tarballs (tcl, tk, common, sdr).

6- Start configuring and compiling.

a. Configure and compile the UCL-patched TCL:

cd mice/tcl-8.0/unix
./configure
make

b. Configure and compile the UCL-patched TK:

cd mice/tk-8.0/unix
./configure
make

c. Change the name of the Common Multimedia Library, configure it and compile it:

mv common-1.2.14 common
cd mice/common/
./configure --enable-ipv6
make

d. Configure and compile sdr itself. You’ll need some slight modifications to the file Makefile.linux as the path of the include files and the libraries is incorrectly specified. In particular, the include directory common should be common/src and the library directory common should be " common/src ":

cd mice/sdr/linux

The content of the file Makefile.linux is:

CC          = gcc -g -O
INCLUDES    = -I../../tk-8.0/generic -I../../tcl-8.0/generic -I../../common
LIBS        = ../../tk-8.0/unix/libtk8.0.a ../../tcl-8.0/unix/libtcl8.0.a ../../common/libuclmmbase.a -L/usr/X11R6/lib -lX11 -lc -lm -ldl -lresolv
CFLAGS = $(INCLUDES) -Wall -DNORANDPROTO -DDIFF_BYTE_ORDER -DAUTH -DLinux $(IFLAGS)

all::        sdr

It has to be changed to:

CC          = gcc -g -O
INCLUDES    = -I../../tk-8.0/generic -I../../tcl-8.0/generic -I../../common/src
LIBS        = ../../tk-8.0/unix/libtk8.0.a ../../tcl-8.0/unix/libtcl8.0.a ../../common/src/libuclmmbase.a -L/usr/X11R6/lib -lX11 -lc -lm -ldl -lresolv
CFLAGS = $(INCLUDES) -Wall -DNORANDPROTO -DDIFF_BYTE_ORDER -DAUTH -DLinux $(IFLAGS)

all::        sdr

After modifying the file, configure and compile:

./configure --enable-ipv6
make

If the compilation succefully concludes, you should find the sdr executable in the current directory.

7- Test sdr by performing the following:

a. Prepare your machine for launching sdr by making sure that:

-  You have the IPv6 stack enabled either by having it compiled into the kernel or by inserting the IPv6 module ( insmod ipv6 ).

-  You have this IPv4 route:

route add -net 224.0.0.0 netmask 224.0.0.0 dev eth0

-  You have a global IPv6 address configured on your interface (either manually or through router advertisements).

b. Launch sdr: ./sdr &

c. Check IPv4 and IPv6 ports open by sdr to verify that sdr is working for both IPv4 and IPv6 multicast:

-  Check that sdr is listening for IPv4 multicast (use lsof or netstat )

lsof -i4 | grep sdr

sdr      1210 root    4u  IPv4   2912       UDP *:9859
sdr      1210 root    5u  IPv4   2914       UDP sap.mcast.net:9875
sdr      1210 root    6u  IPv4   2915       UDP 10.13.60.6:32772->sap.mcast.net:9875
sdr      1210 root    9u  IPv4   2918       UDP 239.255.255.255:9875
sdr      1210 root   12u  IPv4   2921       UDP *:5060
sdr      1210 root   13u  IPv4   2922       TCP *:5060 (LISTEN)

-  Check that sdr is listening for IPv6 multicast (use lsof or netstat )

lsof -i6 | grep sdr

sdr     1210 root    7u  IPv6   2916       UDP *:9875
sdr     1210 root    8u  IPv6   2917       UDP [3000::1]:32773->[ff0e::2:7ffe]:9875
sdr     1210 root   10u  IPv6   2919       UDP *:9875
sdr     1210 root   11u  IPv6   2920       UDP *:9875

Special USAGI Considerations:

While an IPv6 multicast experimenter might elect to use the USAGI IPv6 stack as it is superior to the standard Linux IPv6 stack, sdr compiled using the procedure above will not work properly under USAGI. A typical error message that can be generated when trying to launch sdr when a USAGI kernel is running:

bind: Address already in use
Address: 0, Port: 9875

The short explanation for this behavior is that USAGI uses a different implementation of the bind(2) system call which necessities the use of special socket options to avoid conflicts. A more detailed explanation can be found in the IMPLEMENTATION file contained within the USAGI kit.

To configure sdr to run properly under USAGI:

1- Patch the sdr source code with the following patch:

cd mice
patch -p0 < patchfile

Where patchfile contains the following:

diff -uNr sdr/src/sd_listen.c sdr.usagi/src/sd_listen.c
--- sdr/src/sd_listen.c

+++ sdr.usagi/src/sd_listen.c
@@ -216,7 +216,13 @@
        perror("socket");
        exit(1);
    }
-
+#ifdef LINUX_IPV6
+            if (af == AF_INET6) {
+                int on = 1;
+        setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
+               
+        }
+#endif

    if (s >= sizeof(rfd2sock)) {
        fprintf(stderr, "socket fd too large (%d)\n", s);
@@ -244,12 +250,20 @@

    if (addr_fam == IPv6) {
#ifdef HAVE_IPv6
+        static int already_binded_port_9875 = 0;
+
                inet_pton(AF_INET6, address, &group6);
        memset((char *)&name6, 0, sizeof (name6));
        name6.sin6_family = AF_INET6;
        name6.sin6_addr = in6addr_any;
        name6.sin6_port = htons((short)port);
-        i = bind(s, (struct sockaddr *)&name6, sizeof(name6));
+        if (!already_binded_port_9875) {
+                i = bind(s, (struct sockaddr *)&name6, sizeof(name6));
+                already_binded_port_9875 = 1;
+        } else {
+                i = 0;
+                fatal = 0;
+        }
#endif
    } else {
        group = inet_addr(address);

2- Change /usr/include/bits/in.h: Append the following at the end of the file /usr/include/bits/in.h: #define IPV6_V6ONLY                26

3- Change the file mice/common/net_udp.c:

In mice/common/net_udp.c, just above the lines:

     memset((char *)&s_in, 0, sizeof(s_in));
       s_in.sin6_family = AF_INET6;
       s_in.sin6_port   = htons(rx_port);

Insert the following:

#ifdef IPV6_V6ONLY
      {
              int on = 1;
              setsockopt(s->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
      }
#endif

4- Start applying the procedure outlined above for compiling and testing sdr.

Salah M. S. Al-Buraiky

Dhahran

May 12, 2004


Reply to this article

Forum