Tuesday, February 12, 2013

Multipath OLSRd (SEREADMO)

Some years ago patch for OLSRd v0.5.6-r2 surfaced that added support for loadbalancing single flow over multiple paths. Documentation on how to set it up is scarce. I did get it working to some extent. It's somewhat unstable and doesn't really like single mesh node having multiple network interfaces, but it does loadbalance traffic over multiple paths as promised.



Rarball of patched OLSRd contains actually two different implentations of multipath code. On is kernel module (ser_iptables) and another is implemented as userspace process (ser_routing) communicating with kernel using nfnetlink_queue. To use kernel version manual editing of OLSRd multipath plugin is required.

See http://www.jiaziyi.com/documents/MP-OLSR_thesis_full.pdf for more details.

###########################

# Install CentOS 5.9 i386

# Enable extra repos
wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.i386.rpm
rpm -Uvh rpmforge*

# Install some tools and update system
yum -y install joe screen wget bison flex unrar kernel-devel gcc automake
yum -y update

# Install vanilla kernel 2.6.21.5
yum -y install rpm-build
mkdir -p /usr/src/vanilla
cd /usr/src/vanilla
wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.21.tar.bz2
wget http://pkgs.fedoraproject.org/repo/pkgs/kernel/patch-2.6.21.5.bz2/0a8b2823c5758f39fcc627d5f1b771b1/patch-2.6.21.5.bz2
tar xjf linux-2.6.21.tar.bz2
bunzip2 patch-2.6.21.5.bz2 
mv linux-2.6.21 linux-2.6.21.5
ln -sf /usr/src/vanilla/linux-2.6.21.5 /usr/src/linux
cd linux-2.6.21.5
patch -p1 <../patch-2.6.21.5
make clean && make mrproper 
cp /boot/config-`uname -r` .config
make oldconfig
make rpm
rpm -ivh --nodeps /usr/src/redhat/RPMS/i386/kernel-2.6.21.5-1.i386.rpm
mkinitrd /boot/initrd-2.6.21.5.img 2.6.21.5

# Add following lines to /etc/grub.conf before other kernels
title CentOS (2.6.21.5-1)
        root (hd0,0)
        kernel /vmlinuz-2.6.21.5 ro root=/dev/VolGroup00/LogVol00
        initrd /initrd-2.6.21.5.img
# Reboot

###########################

# Download and compile boost 1.38
mkdir -p /opt/boost
cd /opt/boost
wget http://sourceforge.net/projects/boost/files/boost/1.38.0/boost_1_38_0.tar.gz/download
tar xvzf boost_1_38_0.tar.gz
cd boost_1_38_0
./configure
make
make install
echo "/usr/local/lib/" >>/etc/ld.so.conf
ldconfig

# Download and unpack mpolsr 
mkdir -p /opt/mpolsr
cd /opt/mpolsr
wget http://www.irccyn.ec-nantes.fr/IMG/zip/mpolsr_testbed.rar.zip
unzip mpolsr_testbed.rar.zip
unrar x mpolsr_testbed.rar

# Compile kernel module
cd /opt/mpolsr/mpolsr_testbed/src_iptables/ser_module
make

# Module config
cat <<'__EOF__'>/etc/modprobe.d/ser_iptables.conf
options ser_iptables act_hook=1
options ser_iptables act_device=1
options ser_iptables act_recovery=1
options ser_iptables dbg_hook=3
options ser_iptables dbg_device=9
options ser_iptables dbg_module=9
options ser_iptables dbg_djk=9
options ser_iptables nb_path=3
options ser_iptables coef_fe=2
options ser_iptables coef_fp=2
options ser_iptables udp_port=104
__EOF__

# Compile mpolsrd
cd /opt/mpolsr/mpolsr_testbed/src_olsr/olsrd-0.5.6-r2/
chmod a+x gcc-warnings ld-warnings
make
make libs

# Compile sereadmo plugin manually
cd lib
rm -rf old_sereadmo
cd sereadmo
make clean
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -c -o src/olsrd_plugin.o src/olsrd_plugin.c
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -c -o src/ser_data.o src/ser_data.c
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -c -o src/ser_print.o src/ser_print.c
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -c -o src/ser_tc.o src/ser_tc.c
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -I/usr/local/include/boost-1_38/ \
                                                                                     -c -o src/ser_device.o src/ser_device.cpp
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -I/usr/local/include/boost-1_38/ \
                                                                                     -c -o src/eventlistener.o src/eventlistener.cpp
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -I/usr/local/include/boost-1_38/ \
                                                                                     -c -o src/olsreventserver.o src/olsreventserver.cpp
g++ -shared -Wl,-soname,olsrd_sereadmo -Wl,--version-script=version-script.txt  -Wl,--warn-common -fPIC \
    -o olsrd_sereadmo.so.0.1 src/olsrd_plugin.o src/ser_data.o src/ser_print.o -lpthread \
    -L/usr/local/lib -lboost_thread-gcc41-mt -lboost_serialization-gcc41-mt -lboost_system-gcc41-mt \
    src/ser_tc.o src/ser_device.o src/eventlistener.o src/olsreventserver.o

# Install mpolsrd and plugins
cd ../..
make install_all

# Configure mpolsrd
sed -i.bak /etc/olsrd.conf \
    -e's/"XXX" "YYY"/"eth1" "eth2" "eth3"/g' \
    -e's/ClearScreen     yes/ClearScreen     no/g'
cat <<'__EOF__'>>/etc/olsrd.conf
LoadPlugin "olsrd_sereadmo.so.0.1"
{
PlParam "device" "/dev/sereadmo"
}
__EOF__

# libnfnetlink
mkdir -p /opt/libnfnetlink
cd /opt/libnfnetlink
wget http://ftp.netfilter.org/pub/libnfnetlink/libnfnetlink-0.0.41.tar.bz2
tar xvjf libnfnetlink-0.0.41.tar.bz2
cd libnfnetlink-0.0.41
./configure
make
make install

# libnetfilter_queue 0.0.17
mkdir -p /opt/libnetfilter_queue
cd /opt/libnetfilter_queue
wget http://ftp.netfilter.org/pub/libnetfilter_queue/libnetfilter_queue-0.0.17.tar.bz2
tar xvjf libnetfilter_queue-0.0.17.tar.bz2 
cd libnetfilter_queue-0.0.17
PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure
make
make install

# ser_routing
cd /opt/mpolsr/mpolsr_testbed/src_iptables/ser_routing
chmod a+x configure
./configure
make

# Config file for ser_routing (same defaults as in source)
cd /opt/mpolsr/mpolsr_testbed/src_iptables/ser_routing/src
cat <<'__EOF__'>ser_routing.conf
udp_port=104
DebugLevel_nfqueue=10
DebugLevel_olsrevent=10
DebugLevel_dijkstra=10
Dijkstra_nb_path=3
Dijkstra_coef_fe=2
Dijkstra_coef_fp=2
__EOF__

# Configure mesh network interfaces eth1, eth2 and eth3
# Reboot

###########################


# Launch mpolsrd
olsrd -nofork

# Launch ser_routing
cd /opt/mpolsr/mpolsr_testbed/src_iptables/ser_routing/src
./ser_routing

# Set iptables rules
iptables -I INPUT -p udp --dport 104 -j NFQUEUE
iptables -I OUTPUT -p udp --dport 104 -j NFQUEUE
iptables -I FORWARD -p udp --dport 104 -j NFQUEUE
iptables -I INPUT --protocol 99 -j NFQUEUE
iptables -I OUTPUT --protocol 99 -j NFQUEUE
iptables -I FORWARD --protocol 99 -j NFQUEUE

# Test connection (server)
nc -v -u -l 0.0.0.0 104

# Test connection (client)
# 10.99.2.2 is our mesh interface IP and 10.99.2.1 is destination via mesh
echo foo | nc -v -u -s 10.99.2.2 10.99.2.1 104


###########################

# For kernel module version do NOT start ser_routing but instead load
# ser_iptables module. This WILL NOT work unless you have also hacked
# OLSRd plugin to switch from 7171/tcp communication channel with ser_routing
# back to /dev/sereadmo based communication.

# Load module and create /dev/sereadmo
cd /opt/mpolsr/mpolsr_testbed/src_iptables/ser_module
sh ./inst_module.csh 

###########################


It's also possible to run multipath modules with OLSRd v0.6.4 requiring minimal changes.

# Grab clean olsrd sources
mkdir -p /opt/mpupdate
cd /opt/mpupdate
wget http://www.olsr.org/releases/0.5/olsrd-0.5.6-r2.tar.bz2
wget http://www.olsr.org/releases/0.6/olsrd-0.6.4.tar.bz2

# Unpack mpolsrd source
unrar x -y ../mpolsr/mpolsr_testbed.rar
mv mpolsr_testbed/src_olsr/olsrd-0.5.6-r2 ./olsrd-0.5.6-r2.mp
rm -rf mpolsr_testbed

# Create backup of patched source
tar cvjf olsrd-0.5.6-r2.mp.tar.bz2 olsrd-0.5.6-r2.mp/

# Extract clean 0.5.6-r2
tar xvjf olsrd-0.5.6-r2.tar.bz2

# Remove unneeded files prior diff from mp version
rm -rf \
 olsrd-0.5.6-r2.mp/lib/old_sereadmo/ \
 olsrd-0.5.6-r2.mp/lib/sereadmo/Doxyfile \
 olsrd-0.5.6-r2.mp/lib/sereadmo/sereadmo.kdev* \
 olsrd-0.5.6-r2.mp/olsrd.conf

# Diff mpolsrd and olsrd excluding files with uninteresting changes
diff -bBurN -x'tc_set.c' -x'process_routes.c' \
 -x'process_package.c' -x'mid_set.c' \
 olsrd-0.5.6-r2 olsrd-0.5.6-r2.mp >mpolsrd-0.5.6-r2.patch

# Extract clean 0.6.4
tar xvjf olsrd-0.6.4.tar.bz2

# Compile 0.6.4
cd olsrd-0.6.4
make
# Skip broken "pud" plugin, compile fails at least on Centos5
sed -i.bak -e's/ pud / /g' Makefile
make libs

# Apply mpolsrd plugin patch
patch -p1 <../mpolsrd-0.5.6-r2.patch

# Fix plugin compatibility with 0.6.4
sed -i.bak src/ser_tc.c -e's/olsr_u32_t/uint32_t/g'
sed -i.bak src/ser_device.cpp -e's/#include <stdio.h>/#include <stdio.h>\n#include <stdbool.h>/g'

# Compile sereadmo plugin manually
cd lib/sereadmo
make clean
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -c -o src/olsrd_plugin.o src/olsrd_plugin.c
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -c -o src/ser_data.o src/ser_data.c
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -c -o src/ser_print.o src/ser_print.c
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -c -o src/ser_tc.o src/ser_tc.c
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -I/usr/local/include/boost-1_38/ \
                                                                                     -c -o src/ser_device.o src/ser_device.cpp
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -I/usr/local/include/boost-1_38/ \
                                                                                     -c -o src/eventlistener.o src/eventlistener.cpp
gcc    -fPIC -Isrc -I../../src -pthread -DOLSR_PLUGIN  -DUSE_FPM -Dlinux -DNDEBUG    -I/usr/local/include/boost-1_38/ \
                                                                                     -c -o src/olsreventserver.o src/olsreventserver.cpp
g++ -shared -Wl,-soname,olsrd_sereadmo -Wl,--version-script=version-script.txt  -Wl,--warn-common -fPIC \
    -o olsrd_sereadmo.so.0.1 src/olsrd_plugin.o src/ser_data.o src/ser_print.o -lpthread \
    -L/usr/local/lib -lboost_thread-gcc41-mt -lboost_serialization-gcc41-mt -lboost_system-gcc41-mt \
    src/ser_tc.o src/ser_device.o src/eventlistener.o src/olsreventserver.o

# Little cleanup before installing new version in case 0.5.x was already there
rm -f /usr/sbin/olsrd /usr/lib/olsrd_*
mv /etc/olsrd.conf /etc/olsrd.conf.old

# Install 0.6.4
cd /opt/mpupdate/olsrd-0.6.4
make install_all

# Don't forget sereadmo part
cp -a lib/sereadmo/olsrd_sereadmo.so.0.1 /usr/local/lib/

# Update config
sed -i.bak /etc/olsrd.conf \
  -e's/<OLSRd-Interface1>/eth1/g' \
  -e's/<OLSRd-Interface2>/eth2/g' 
cat <<'__EOF__'>>/etc/olsrd.conf
ClearScreen     no
LinkQualityLevel       0 # or 2? olsrd uses 2 while sereadmo sample config uses 0.
LoadPlugin "olsrd_sereadmo.so.0.1"
{
}
__EOF__

############################

# Launch mpolsrd
olsrd -nofork

# Launch ser_routing
cd /opt/mpolsr/mpolsr_testbed/src_iptables/ser_routing/src
./ser_routing

# Set iptables rules
iptables -I INPUT -p udp --dport 104 -j NFQUEUE
iptables -I OUTPUT -p udp --dport 104 -j NFQUEUE
iptables -I FORWARD -p udp --dport 104 -j NFQUEUE
iptables -I INPUT --protocol 99 -j NFQUEUE
iptables -I OUTPUT --protocol 99 -j NFQUEUE
iptables -I FORWARD --protocol 99 -j NFQUEUE

# Test connection (server)
nc -v -u -l 0.0.0.0 104

# Test connection (client)
# 10.99.7.10 is our mesh interface IP and 10.99.1.1 is destination via mesh
# You must use "primary" olsr interface IP, secondaries don't work due some
# reason, likely problem with my config
echo foo | nc -v -u -s 10.99.7.10 10.99.1.1 104

# remember there's 36 bytes overhead due sereadmo wrapping udp packets with
# extra headers.

###########################


1 comment:

  1. Hi,

    I reached your page by google - thanks very much for the documentation.

    It's absolutely true that the MP-OLSR is very in lack of documentation - the original installation guide is in French, and ranked as "confidential" (I don't understand how the administration works -- they can make the code available, but not the documentation), so I couldn't published it on line.

    I have added a link to this page.

    thanks

    Jiazi

    ReplyDelete

Got something to say?!