====== Aggregating multiple ISP links with ML PPP ======
This lab shows an example of aggregating multiple independent ISP links with [[http://mpd.sourceforge.net/ | MPD5]].
===== Network diagram ====
Here is the concept:
{{:documentation:examples:bsdrp.lab.aggregate.isp.links.concept.png|}}
And here is this lab detailed diagram:
{{:documentation:examples:bsdrp.lab.aggregate.isp.links.detail.png|}}
===== Virtual Lab =====
This chapter will describe how to start each routers and configuring the 3 central routers.
More information on these BSDRP lab scripts available on [[documentation:examples:How to build a BSDRP router lab]].
Start the Virtual lab (example using bhyve):
# ./tools/BSDRP-lab-bhyve.sh -n 6
Setting-up a virtual lab with 6 VM(s):
- Working directory: /tmp/BSDRP
- Each VM has 1 core(s) and 512M RAM
- Emulated NIC: virtio-net
- Switch mode: bridge + tap
- 0 LAN(s) between all VM
- Full mesh Ethernet links between each VM
VM 1 has the following NIC:
- vtnet0 connected to VM 2
- vtnet1 connected to VM 3
- vtnet2 connected to VM 4
- vtnet3 connected to VM 5
- vtnet4 connected to VM 6
VM 2 has the following NIC:
- vtnet0 connected to VM 1
- vtnet1 connected to VM 3
- vtnet2 connected to VM 4
- vtnet3 connected to VM 5
- vtnet4 connected to VM 6
VM 3 has the following NIC:
- vtnet0 connected to VM 1
- vtnet1 connected to VM 2
- vtnet2 connected to VM 4
- vtnet3 connected to VM 5
- vtnet4 connected to VM 6
VM 4 has the following NIC:
- vtnet0 connected to VM 1
- vtnet1 connected to VM 2
- vtnet2 connected to VM 3
- vtnet3 connected to VM 5
- vtnet4 connected to VM 6
VM 5 has the following NIC:
- vtnet0 connected to VM 1
- vtnet1 connected to VM 2
- vtnet2 connected to VM 3
- vtnet3 connected to VM 4
- vtnet4 connected to VM 6
VM 6 has the following NIC:
- vtnet0 connected to VM 1
- vtnet1 connected to VM 2
- vtnet2 connected to VM 3
- vtnet3 connected to VM 4
- vtnet4 connected to VM 5
For connecting to VM'serial console, you can use:
- VM 1 : cu -l /dev/nmdm1B
- VM 2 : cu -l /dev/nmdm2B
- VM 4 : cu -l /dev/nmdm4B
- VM 3 : cu -l /dev/nmdm3B
- VM 5 : cu -l /dev/nmdm5B
- VM 6 : cu -l /dev/nmdm6B
==== Backbone routers configuration ====
=== Router 2 ===
Router 2 is configured for rate-limiting traffic at 1 Mb/s on interface to/from R1.
sysrc hostname=R2
sysrc ifconfig_vtnet0="inet 10.0.12.2/24"
sysrc ifconfig_vtnet3="inet 10.0.25.2/24"
sysrc defaultrouter="10.0.25.5"
sysrc firewall_enable=YES
sysrc firewall_script="/etc/ipfw.rules"
cat > /etc/ipfw.rules <
=== Router 3 ===
Router 3 is configured for rate-limiting traffic at 20 Mb/s on interface to/from R1.
sysrc hostname=R3
sysrc ifconfig_vtnet0="inet 10.0.13.3/24"
sysrc ifconfig_vtnet3="inet 10.0.35.3/24"
sysrc defaultrouter="10.0.35.5"
sysrc firewall_enable=YES
sysrc firewall_script="/etc/ipfw.rules"
cat > /etc/ipfw.rules <
=== Router 4 ===
Router 4 is configured for rate-limiting traffic at 3 Mb/s on interface to/from R1.
sysrc hostname=R4
sysrc ifconfig_vtnet0="inet 10.0.14.4/24"
sysrc ifconfig_vtnet3="inet 10.0.45.4/24"
sysrc defaultrouter="10.0.45.5"
sysrc firewall_enable=YES
sysrc firewall_script="/etc/ipfw.rules"
cat > /etc/ipfw.rules <
=== Router 5 ===
Router 5 is the MLPPP server default gateway.
sysrc hostname=R5
sysrc ifconfig_vtnet1="inet 10.0.25.5/24"
sysrc ifconfig_vtnet2="inet 10.0.35.5/24"
sysrc ifconfig_vtnet3="inet 10.0.45.5/24"
sysrc ifconfig_vtnet4="inet 10.0.56.5/24"
sysrc static_routes="ISP1 ISP2 ISP3"
sysrc route_ISP1="-host 10.0.12.1 10.0.25.2"
sysrc route_ISP2="-host 10.0.13.1 10.0.35.3"
sysrc route_ISP3="-host 10.0.14.1 10.0.45.4"
service netif restart
service routing restart
hostname R5
config save
==== Router 6 : L2TP MLPPP server ====
Router 6 is configured as a L2TP server.
sysrc hostname=R6
sysrc cloned_interfaces="lo1"
sysrc ifconfig_lo1="inet 10.6.6.6/32"
sysrc ifconfig_vtnet4="inet 10.0.56.62/24"
sysrc ifconfig_vtnet4_alias1="inet 10.0.56.63/32"
sysrc ifconfig_vtnet4_alias2="inet 10.0.56.64/32"
sysrc defaultrouter="10.0.56.5"
sysrc mpd_enable=YES
sysrc mpd_flags="-b -s ppp"
cat > /usr/local/etc/mpd5/mpd.conf <
==== Router 1 : L2TP MLPPP client ====
Router 1 is configured as a simple L2TP MLPPP client router connected to 3 Internet link.
sysrc hostname=R1
sysrc ifconfig_vtnet0="inet 10.0.12.1/24"
sysrc ifconfig_vtnet1="inet 10.0.13.1/24"
sysrc ifconfig_vtnet2="inet 10.0.14.1/24"
sysrc static_routes="ISP1 ISP2 ISP3"
sysrc route_ISP1="-host 10.0.56.62 10.0.12.2"
sysrc route_ISP2="-host 10.0.56.63 10.0.13.3"
sysrc route_ISP3="-host 10.0.56.64 10.0.14.4"
sysrc mpd_enable=YES
sysrc mpd_flags="-b -s ppp"
cat > /usr/local/etc/mpd5/mpd.conf <
===== Final testing =====
==== Each ISP link bandwidth ====
Start iperf in server mode on R6:
[root@R6]~# iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Now check the correct limited bandwitdh for each different links:
  * Link to R6 across R2: 1Mb/s
  * Link to R6 across R3: 2Mb/s
  * Link to R6 across R4: 3Mb/s
[root@R1]~# iperf3 -i 0 -c 10.0.56.62
Connecting to host 10.0.56.62, port 5201
[  5] local 10.0.12.1 port 30648 connected to 10.0.56.62 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-10.00  sec  1.21 MBytes  1.02 Mbits/sec    0   65.1 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  1.21 MBytes  1.02 Mbits/sec    0             sender
[  5]   0.00-10.51  sec  1.19 MBytes   953 Kbits/sec                  receiver
iperf Done.
[root@R1]~# iperf3 -i 0 -c 10.0.56.63
Connecting to host 10.0.56.63, port 5201
[  5] local 10.0.13.1 port 13090 connected to 10.0.56.63 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-10.00  sec  2.35 MBytes  1.97 Mbits/sec    0   65.1 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  2.35 MBytes  1.97 Mbits/sec    0             sender
[  5]   0.00-10.26  sec  2.33 MBytes  1.91 Mbits/sec                  receiver
iperf Done.
[root@R1]~# iperf3 -i 0 -c 10.0.56.64
Connecting to host 10.0.56.64, port 5201
[  5] local 10.0.14.1 port 57319 connected to 10.0.56.64 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-10.00  sec  3.48 MBytes  2.92 Mbits/sec    0   65.1 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  3.48 MBytes  2.92 Mbits/sec    0             sender
[  5]   0.00-10.16  sec  3.46 MBytes  2.86 Mbits/sec                  receiver
iperf Done.
==== Aggregated ISP link bandwidth ====
The aggregated link bandwidth should be negotiated to 6Mb/s (1+2+3):
[root@R1]~# grep Bundle /var/log/ppp.log
Nov 12 06:04:54 router ppp[87823]: [B-1] Bundle: Interface ng0 created
Nov 12 06:04:54 router ppp[87823]: [B-1] Bundle: Status update: up 1 link, total bandwidth 2000000 bps
Nov 12 06:04:54 router ppp[87823]: [B-1] Bundle: Status update: up 2 links, total bandwidth 3000000 bps
Nov 12 06:04:54 router ppp[87823]: [B-1] Bundle: Status update: up 3 links, total bandwidth 6000000 bps
and iperf measurement close to 6Mb/s:
[root@R1]~# iperf3 -i 0 -c 10.6.6.6
Connecting to host 10.6.6.6, port 5201
[  5] local 10.0.16.10 port 51350 connected to 10.6.6.6 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-10.00  sec  6.42 MBytes  5.38 Mbits/sec    0   65.1 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  6.42 MBytes  5.38 Mbits/sec    0             sender
[  5]   0.00-10.09  sec  6.40 MBytes  5.32 Mbits/sec                  receiver
iperf Done.
In the same time, if you start a "netstat -ihw 1" on R2, R3 and R4, you should see distributed traffic between them.
	   
===== Performance lab =====
This lab will test mpd5 performance by aggregating 2 gigabit links.
Here is the concept:
{{:documentation:examples:bsdrp.lab.mpd5.performance.png|}}
This lab use 3 [[IBM System x3550 M3]] with **quad** cores (Intel Xeon L5630 2.13GHz, hyper-threading disabled), quad NIC 82580 connected to the PCI-Express Bus and dual port Intel 10-Gigabit X540-AT2 connected to the PCI-Express Bus.
==== Router 1 ====
Router 1 is configured a a simple end-point.
Set the base parameters:
sysrc hostname=R1
sysrc ifconfig_ix0="1.1.1.1/24"
sysrc ifconfig_ix0_ipv6="inet6 2001:db8:1::1/64"
sysrc defaultrouter="1.1.1.2"
sysrc ipv6_defaultrouter="2001:db8:1::2"
service netif restart
service routing restart
config save
==== Router 2 ====
Router 2 is configured as a L2TP MLPPP client router.
Configure global parameters:
sysrc hostname=R2
sysrc ifconfig_ix0="1.1.1.2/24"
sysrc ifconfig_ix0_ipv6="inet6 2001:db8:1::2/64"
sysrc ifconfig_igb2="10.0.23.2/24"
sysrc ifconfig_igb3="10.1.23.2/24"
sysrc mpd_enable=YES
sysrc mpd_flags="-b -s ppp"
Configure mpd:
cat > /usr/local/etc/mpd5/mpd.conf <<'EOF'
default:
        load l2tp_client
l2tp_client:
        # Create the bundle
        create bundle template B
        # Enable IPv6
        set bundle enable ipv6cp
        # Disable compression (for iperf test)
        #set bundle enable compression
        #set ccp yes deflate
        # Enable TCP MSS fix
        set iface enable tcpmssfix
        # Use this interface as default route
        set iface route default
        # Disable IPCP configuration for the iperf test
        #set ipcp yes vjcomp
        # Create clonable template link
        create link template L l2tp
        set link action bundle B
        set link enable multilink
        set link keep-alive 10 30
        set link mtu 1460
        set l2tp secret blah
        set link max-redial 0
        # LINK1
        create link static link1 L
        set l2tp peer 10.0.23.3
        open link
        # LINK2
        create link static link2 L
        set l2tp peer 10.1.23.3
        open link
'EOF'
And apply your changes:
service netif restart
service routing restart
service mpd5 start
config save
==== Router 3 ====
Router 3 is configured as a (L2TP server).
Set the global parameters:
sysrc hostname=R3
sysrc cloned_interfaces="lo1"
sysrc ifconfig_lo1="inet 3.3.3.3/32"
sysrc ifconfig_lo1_ipv6="inet6 2001:db8:3::3/64"
sysrc ifconfig_igb2="10.0.23.3/24"
sysrc ifconfig_igb3="10.1.23.3/24"
sysrc mpd_enable=YES
sysrc mpd_flags="-b -s ppp"
Configure mpd5:
cat > /usr/local/etc/mpd5/mpd.conf <<'EOF'
default:
        load l2tp_server
l2tp_server:
        # IP Pool
        set ippool add pool1 10.3.23.10 10.3.23.100
        # Create bundle template named B
        create bundle template B
        # Enable compression (disabled on the client)
        set bundle enable compression
        set ccp yes deflate
        # Enable IPv6
        set bundle enable ipv6cp
        # Configure interface
        set iface enable tcpmssfix
        # Handle IPCP configuration
        set ipcp yes vjcomp
        # Handle the IPCP configuration
        set ipcp ranges 10.3.23.1/24 ippool pool1
        # Create clonable link template
        create link template L l2tp
        set link action bundle B
        set link enable multilink
        set link keep-alive 10 30
        set link mtu 1460
        set l2tp secret blah
        # LINK1
        create link static link1 L
        set l2tp self 10.0.23.3
        set link enable incoming
        # LINK2
        create link static link2 L
        set l2tp self 10.1.23.3
        set link enable incoming
'EOF'
if-up script (for installing routes to R1 subnet):
cat > /usr/local/etc/mpd5/if-up.sh <<'EOF'
#!/bin/sh
#mpd5 call script with options:
#interface proto local-ip remote-ip authname [ dns1 server-ip ] [ dns2 server-ip ] peer-address
#Examples
#command "/usr/local/etc/mpd5/if-up.sh ng0 inet 10.3.23.1/32 10.3.23.10 '-' '' '' '10.1.23.2'"
#command "/usr/local/etc/mpd5/if-up.sh ng0 inet6 fe80::5ef3:fcff:fee5:a4c0%ng0 fe80::5ef3:fcff:fee5:7338%ng0 '-' '10.1.23.2'"
#mpd5 wait for 0 as successful
set -e
logger "$0 called with parameters: $@"
remote_inet="1.1.1.0/24"
remote_inet6="2001:db8:1:: -prefixlen 64"
eval "
        if route get -net -\$2 \${remote_$2}; then
                logger \"route \${remote_$2} already present\"
                return 0
        else
                cmd=\"route add -\$2 \${remote_$2} \$4\"
        fi
"
if $cmd; then
        logger "$0: $cmd successfull"
        return 0
else
        logger "$0: $cmd failed"
        return 1
fi
'EOF'
chmod +x /usr/local/etc/mpd5/if-up.sh
Then the if-down script:
cat > /usr/local/etc/mpd5/if-down.sh <<'EOF'
#!/bin/sh
#mpd5 call script with options:
#interface proto local-ip remote-ip authname peer-address
#example:
#command "/urs/local/etc/mpd5/if-down.sh ng0 inet 10.3.23.1/32 10.3.23.10 '-' '10.0.23.2'"
logger "$0 called with parameters: $@"
remote_inet="1.1.1.0/24"
remote_net6="2001:db8:1::1 -prefixlen 64"
eval "
        if ! route get -net -\$2 ${remote_$2}; then
                logger "Route ${remote_inet} not in table"
                return 0
        else
                cmd=\"route del \${remote_$2} \$4\"
        fi
"
if $cmd; then
        logger "if-down: ${cmd} succesfull"
        return 0
else
        logger "if-down: ${cmd} failed"
        return 1
fi
'EOF'
chmod +x /usr/local/etc/mpd5/if-down.sh
And apply your changes:
service netif restart
service routing restart
service mpd5 start
config save
==== Performance tests ====
=== Checking perf tool ===
== Direct tests between R1 and R2 ===
[root@bsdrp1]~# iperf -c 1.1.1.2 -t 60
------------------------------------------------------------
Client connecting to 1.1.1.2, TCP port 5001
TCP window size: 32.5 KByte (default)
------------------------------------------------------------
[  3] local 1.1.1.1 port 57149 connected with 1.1.1.2 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-60.0 sec  24.5 GBytes  3.50 Gbits/sec
==== Direct tests between R2 and R3 ====
We start by testing each Gigabit links between R2 and R3 for measuring iperf value on standard gigabit link:
[root@R2]~# iperf -c 10.0.23.3 -t 60
------------------------------------------------------------
Client connecting to 10.0.23.3, TCP port 5001
TCP window size: 32.5 KByte (default)
------------------------------------------------------------
[  3] local 10.0.23.2 port 21046 connected with 10.0.23.3 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-60.0 sec  6.54 GBytes   936 Mbits/sec
[root@R2]~# iperf -c 10.1.23.3 -t 60
------------------------------------------------------------
Client connecting to 10.1.23.3, TCP port 5001
TCP window size: 32.5 KByte (default)
------------------------------------------------------------
[  3] local 10.1.23.2 port 50717 connected with 10.1.23.3 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-60.0 sec  6.55 GBytes   937 Mbits/sec
==== mpd5 perfs ===
=== between R2 and R3 ==
Iperf will use the MPPP tunnel extremity:
[root@R2]~# set DEST=`ifconfig ng0 | grep 'inet ' | cut -d ' ' -f 4`
[root@R2]~# iperf -c $DEST -t 60
------------------------------------------------------------
Client connecting to 10.3.23.1, TCP port 5001
TCP window size: 32.5 KByte (default)
------------------------------------------------------------
[  3] local 10.3.23.10 port 19383 connected with 10.3.23.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-60.1 sec  6.14 GBytes   878 Mbits/sec
The value is almost the same than without MLPPP aggregated link, but correctly load-balanced across each link.
iR2 stats during this test:
                    /0   /1   /2   /3   /4   /5   /6   /7   /8   /9   /10
     Load Average   ||||
      Interface           Traffic               Peak                Total
            ng0  in     17.271 Mb/s         18.694 Mb/s            3.743 GB
                 out   974.656 Mb/s       1055.503 Mb/s            7.324 GB
           igb3  in     11.405 Mb/s         12.261 Mb/s            3.456 GB
                 out   507.970 Mb/s        550.255 Mb/s           27.449 GB
           igb2  in     11.389 Mb/s         12.274 Mb/s            3.422 GB
                 out   508.061 Mb/s        550.328 Mb/s           18.673 GB
And the load show:
[root@R2]~# top -nCHSIzs1
last pid: 14152;  load averages:  0.94,  0.48,  0.21  up 0+23:54:56    12:40:23
155 processes: 5 running, 99 sleeping, 51 waiting
Mem: 3564K Active, 26M Inact, 384M Wired, 256K Cache, 17M Buf, 15G Free
Swap:
  PID USERNAME   PRI NICE   SIZE    RES STATE   C   TIME     CPU COMMAND
 8524 root       -16    -     0K    64K sleep   0   2:04  25.68% ng_queue{ng_queue2}
 8524 root       -16    -     0K    64K sleep   1   1:47  25.49% ng_queue{ng_queue1}
 8524 root       -16    -     0K    64K sleep   3   2:03  22.36% ng_queue{ng_queue0}
14149 root        36    0 32136K  3092K sbwait  1   0:06  21.88% iperf{iperf}
 8524 root       -16    -     0K    64K sleep   2   1:56  20.26% ng_queue{ng_queue3}
   11 root       -92    -     0K   816K WAIT    3   0:20   7.57% intr{irq286: igb3:que}
   11 root       -92    -     0K   816K WAIT    1   0:17   5.96% intr{irq279: igb2:que}
   11 root       -92    -     0K   816K WAIT    3   0:09   0.78% intr{irq281: igb2:que}
   11 root       -92    -     0K   816K WAIT    2   0:05   0.59% intr{irq280: igb2:que}
   11 root       -92    -     0K   816K WAIT    0   0:06   0.39% intr{irq278: igb2:que}
    0 root       -92    0     0K   560K -       1   0:00   0.10% kernel{igb3 que}
For information, using netblast (UDP packet generator) disturb the links:
netblast $DEST 9090 1470 30 `sysctl -n hw.ncpu`
and measure the bandwidth received on R3:
         0 pps    0.000 Mbps - 0 pkts in 0.522753682 ns
      2149 pps   25.277 Mbps - 1079 pkts in 0.501997052 ns
         0 pps    0.000 Mbps - 0 pkts in 0.501999569 ns
        45 pps    0.539 Mbps - 23 pkts in 0.502000238 ns
         0 pps    0.000 Mbps - 0 pkts in 0.502000362 ns
       713 pps    8.387 Mbps - 358 pkts in 0.501999604 ns
      2107 pps   24.786 Mbps - 1077 pkts in 0.511002670 ns
         0 pps    0.000 Mbps - 0 pkts in 0.501998712 ns
         0 pps    0.000 Mbps - 0 pkts in 0.501998967 ns
        21 pps    0.255 Mbps - 11 pkts in 0.508000385 ns
         0 pps    0.000 Mbps - 0 pkts in 0.501998785 ns
The packet generator prevent to manage keepalive:
Jan 27 10:50:38 R2 ppp: [link1] LCP: no reply to 1 echo request(s)
Jan 27 10:50:38 R2 ppp: [link2] LCP: no reply to 1 echo request(s)
Jan 27 10:50:48 R2 ppp: [link2] LCP: no reply to 2 echo request(s)
Jan 27 10:50:48 R2 ppp: [link2] LCP: peer not responding to echo requests
Jan 27 10:50:48 R2 ppp: [link2] LCP: state change Opened --> Stopping
Jan 27 10:50:48 R2 ppp: [link2] Link: Leave bundle "B-1"