Vincent Bernat: Network virtualization with VXLAN
Virtual eXtensible Local Area Network (VXLAN) is a protocol to
overlay a virtualized L2 network over an existing IP network with
little setup. It is currently described in an
Internet-Draft. It adds the following perks to VLANs
while still providing isolation:
- It uses a 24-bit VXLAN Network Identifier (VNI) which should be enough to address any scale-based concerns of multitenancy.
- It wraps L2 frames into UDP datagrams. This allows one to rely on some interesting properties of IP networks like availability and scalability. A VXLAN segment can be extended far beyond the typical reach of today VLANs.
About IPv6
When possible, I try to use IPv6 for my labs. This is not the case
here for several reasons:
- IP multicast is required and PIM-SM implementations for IPv6 are
not widespread yet. However, they exist. This explains why I use
XORP for this lab: it supports PIM-SM for both IPv4 and IPv6.
- VXLAN Internet-Draft specifically addresses only
IPv4. This seems a bit odd for a protocol running on top of UDP
and I hope this will be fixed soon. This is not a major
stopper since
some VXLAN implementations support IPv6.
- However, the current implementation for Linux does not support
IPv6. IPv6 support will be added later.
Once IPv6 support is available, the lab should be easy to adapt.
Lab
So, here is the lab used. R1, R2 and R3 will act as VTEPs. They
do not make use of PIM-SM. Instead, they have a generic multicast route
on eth0. E1, E2 and E3 are edge routers while C1, C2 and
C3 are core routers. The proposed lab is not resilient but
convenient to explain how things work. It is built on top of KVM
hosts. Have a look at my previous article for more details on this.
The lab is hosted on GitHub. I have made the lab easier to try by
including the kernel I have used for my tests. XORP comes
preconfigured, you just have to configure the VXLAN part. For this,
you need a recent version of ip.
$ sudo apt-get install screen vde2 kvm iproute xorp git
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
$ cd iproute2
$ ./configure && make
You get ip' as ip/ip' and bridge' as bridge/bridge'.
$ cd ..
$ git clone git://github.com/vincentbernat/network-lab.git
$ cd network-lab/lab-vxlan
$ ./setup
Unicast routing
The first step is to setup unicast routing. OSPF is used for this
purpose. The chosen routing daemon is XORP. With xorpsh, we can
check if OSPF is working as expected:
root@c1# xorpsh
root@c1$ show ospf4 neighbor
Address Interface State ID Pri Dead
192.168.11.11 eth0/eth0 Full 3.0.0.1 128 36
192.168.12.22 eth1/eth1 Full 3.0.0.2 128 33
192.168.101.133 eth2/eth2 Full 2.0.0.3 128 36
192.168.102.122 eth3/eth3 Full 2.0.0.2 128 38
root@c1$ show route table ipv4 unicast ospf
192.168.1.0/24 [ospf(110)/2]
> to 192.168.11.11 via eth0/eth0
192.168.2.0/24 [ospf(110)/2]
> to 192.168.12.22 via eth1/eth1
192.168.3.0/24 [ospf(110)/3]
> to 192.168.102.122 via eth3/eth3
192.168.13.0/24 [ospf(110)/2]
> to 192.168.102.122 via eth3/eth3
192.168.21.0/24 [ospf(110)/2]
> to 192.168.101.133 via eth2/eth2
192.168.22.0/24 [ospf(110)/2]
> to 192.168.12.22 via eth1/eth1
192.168.23.0/24 [ospf(110)/2]
> to 192.168.101.133 via eth2/eth2
192.168.103.0/24 [ospf(110)/2]
> to 192.168.102.122 via eth3/eth3
Multicast routing
Once unicast routing is up and running, we need to setup multicast
routing. There are two protocols for this: IGMP and PIM-SM. The
former one allows routers to forward multicast datagrams while the
first one allows hosts to subscribe to a multicast group.
IGMP
IGMP is used by hosts and adjacent routers to establish multicast
group membership. In our case, it will be used by R2 to let E2
know it subscribed to 239.0.0.11 (a multicast group).
Configuring XORP to support IGMP is simple. Let s test with iperf to
have a multicast listener on R2:
root@r2# iperf -u -s -l 1000 -i 1 -B 239.0.0.11
------------------------------------------------------------
Server listening on UDP port 5001
Binding to local address 239.0.0.11
Joining multicast group 239.0.0.11
Receiving 1000 byte datagrams
UDP buffer size: 208 KByte (default)
------------------------------------------------------------
On E2, we can now check that R2 is properly registered for
239.0.0.11:
root@e2$ show igmp group
Interface Group Source LastReported Timeout V State
eth0 239.0.0.11 0.0.0.0 192.168.2.2 248 2 E
XORP documentation contains a good overview of IGMP.
PIM-SM
PIM-SM is far more complex. It does not have its own topology
discovery protocol and relies on routing information from other
protocols, OSPF in our case.
I will describe here a simplified view on how PIM-SM works. XORP
documentation contains more details about PIM-SM.
The first step for all PIM-SM routers is to elect a rendez-vous
point (RP). In our lab, only C1, C2 and C3 have been
configured to be elected as a RP. Moreover, we give better priority to
C3 to ensure it wins.
root@e1$ show pim rps
RP Type Pri Holdtime Timeout ActiveGroups GroupPrefix
192.168.101.133 bootstrap 100 150 135 0 239.0.0.0/8
Let s suppose we start iperf on both R2 and R3. Using IGMP, they
subscribe to multicast group 239.0.0.11 with E2 and E3
respectively. Then, E2 and E3 send a join message (also known as a
(*,G) join) to the RP (C3) for that multicast group. Using the
unicast path from E2 and E3 to the RP, the routers along the
paths build the RP tree (RPT), rooted at C3. Each router in the
tree knows how to send multicast packets to 239.0.0.11: it will send
them to the leaves.
root@e3$ show pim join
Group Source RP Flags
239.0.0.11 0.0.0.0 192.168.101.133 WC
Upstream interface (RP): eth2
Upstream MRIB next hop (RP): 192.168.23.133
Upstream RPF'(*,G): 192.168.23.133
Upstream state: Joined
Join timer: 5
Local receiver include WC: O...
Joins RP: ....
Joins WC: ....
Join state: ....
Prune state: ....
Prune pending state: ....
I am assert winner state: ....
I am assert loser state: ....
Assert winner WC: ....
Assert lost WC: ....
Assert tracking WC: O.O.
Could assert WC: O...
I am DR: O..O
Immediate olist RP: ....
Immediate olist WC: O...
Inherited olist SG: O...
Inherited olist SG_RPT: O...
PIM include WC: O...
Let s suppose that R1 wants to send multicast packets to
239.0.0.11. It sends them to R1 which does not have any
information on how to contact all the members of the multicast group
because it is not the RP. Therefore, it encapsulates the multicast
packets into PIM Register packets and sends them to the RP. The RP
decapsulates them and sends them natively. The multicast packets are
routed from the RP to R2 and R3 using the reverse path formed by
the join messages.
root@r1# iperf -c 239.0.0.11 -u -b 10k -t 30 -T 10
------------------------------------------------------------
Client connecting to 239.0.0.11, UDP port 5001
Sending 1470 byte datagrams
Setting multicast TTL to 10
UDP buffer size: 208 KByte (default)
------------------------------------------------------------
root@e1# tcpdump -pni eth0
10:58:23.424860 IP 192.168.1.1.35277 > 239.0.0.11.5001: UDP, length 1470
root@c3# tcpdump -pni eth0
10:58:23.552903 IP 192.168.11.11 > 192.168.101.133: PIMv2, Register, length 1480
root@e2# tcpdump -pni eth0
10:58:23.896171 IP 192.168.1.1.35277 > 239.0.0.11.5001: UDP, length 1470
root@e3# tcpdump -pni eth0
10:58:23.824647 IP 192.168.1.1.35277 > 239.0.0.11.5001: UDP, length 1470
As presented here, the routing is not optimal: packets from R1 to
R2 could avoid the RP. Moreover, encapsulating multicast packets
into unicast packets is not efficient either. At some point, the RP
will decide to switch to native multicast1. Rooted at R1,
the shortest-path tree (SPT) for the multicast group will be built
using source-specific join messages (also known as a (S,G) join).
From here, each router in the tree knows how to handle multicast
packets from R1 to the group without involving the RP. For example,
E1 knows it must duplicate the packet and sends one through the
interface to C3 and the other one through the interface to C1:
root@e1$ show pim join
Group Source RP Flags
239.0.0.11 192.168.1.1 192.168.101.133 SG SPT DirectlyConnectedS
Upstream interface (S): eth0
Upstream interface (RP): eth1
Upstream MRIB next hop (RP): 192.168.11.111
Upstream MRIB next hop (S): UNKNOWN
Upstream RPF'(S,G): UNKNOWN
Upstream state: Joined
Register state: RegisterPrune RegisterCouldRegister
Join timer: 7
KAT(S,G) running: true
Local receiver include WC: ....
Local receiver include SG: ....
Local receiver exclude SG: ....
Joins RP: ....
Joins WC: ....
Joins SG: .OO.
Join state: .OO.
Prune state: ....
Prune pending state: ....
I am assert winner state: ....
I am assert loser state: ....
Assert winner WC: ....
Assert winner SG: ....
Assert lost WC: ....
Assert lost SG: ....
Assert lost SG_RPT: ....
Assert tracking SG: OOO.
Could assert WC: ....
Could assert SG: .OO.
I am DR: O..O
Immediate olist RP: ....
Immediate olist WC: ....
Immediate olist SG: .OO.
Inherited olist SG: .OO.
Inherited olist SG_RPT: ....
PIM include WC: ....
PIM include SG: ....
PIM exclude SG: ....
root@e1$ show pim mfc
Group Source RP
239.0.0.11 192.168.1.1 192.168.101.133
Incoming interface : eth0
Outgoing interfaces: .OO.
root@e1$ exit
[Connection to XORP closed]
root@e1# ip mroute
(192.168.1.1, 239.0.0.11) Iif: eth0 Oifs: eth1 eth2
Setting up VXLAN
Once IP multicast is running, setting up VXLAN is quite easy. Here are the software requirements:
- A recent kernel. Pick at least 3.7-rc3. You need to enable
CONFIG_VXLAN option. You also currently need a patch on top of it
to be able to specify a TTL greater than 1 for
multicast packets.
- A recent version of
ip. Currently, you need the version from git.
On R1, R2 and R3, we create a vxlan42 interface with the following commands:
root@rX# ./ip link add vxlan42 type vxlan id 42 \
> group 239.0.0.42 \
> ttl 10 dev eth0
root@rX# ip link set up dev vxlan42
root@rX# ./ip -d link show vxlan42
10: vxlan42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc noqueue state UNKNOWN mode DEFAULT
link/ether 3e:09:1c:e1:09:2e brd ff:ff:ff:ff:ff:ff
vxlan id 42 group 239.0.0.42 dev eth0 port 32768 61000 ttl 10 ageing 300
Let s assign an IP in 192.168.99.0/24 for each router and check they can ping each other:
root@r1# ip addr add 192.168.99.1/24 dev vxlan42
root@r2# ip addr add 192.168.99.2/24 dev vxlan42
root@r3# ip addr add 192.168.99.3/24 dev vxlan42
root@r1# ping 192.168.99.2
PING 192.168.99.2 (192.168.99.2) 56(84) bytes of data.
64 bytes from 192.168.99.2: icmp_req=1 ttl=64 time=3.90 ms
64 bytes from 192.168.99.2: icmp_req=2 ttl=64 time=1.38 ms
64 bytes from 192.168.99.2: icmp_req=3 ttl=64 time=1.82 ms
--- 192.168.99.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 1.389/2.375/3.907/1.098 ms
We can check the packets are encapsulated:
root@r1# tcpdump -pni eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
11:30:36.561185 IP 192.168.1.1.43349 > 192.168.2.2.8472: UDP, length 106
11:30:36.563179 IP 192.168.2.2.33894 > 192.168.1.1.8472: UDP, length 106
11:30:37.562677 IP 192.168.1.1.43349 > 192.168.2.2.8472: UDP, length 106
11:30:37.564316 IP 192.168.2.2.33894 > 192.168.1.1.8472: UDP, length 106
Moreover, if we send broadcast packets (with ping -b or ARP
requests), they are encapsulated into multicast packets:
root@r1# tcpdump -pni eth0
11:31:27.464198 IP 192.168.1.1.41958 > 239.0.0.42.8472: UDP, length 106
11:31:28.463584 IP 192.168.1.1.41958 > 239.0.0.42.8472: UDP, length 106
Recent versions of iproute also comes with bridge, an utility
allowing one to inspect the FDB of bridge-like interfaces:
root@r1# ../bridge/bridge fdb show vxlan42
3e:09:1c:e1:09:2e dev vxlan42 dst 192.168.2.2 self
0e:98:40:c6:58:10 dev vxlan42 dst 192.168.3.3 self
Demo
For a demo, have a look at the following video (it is also available
as an Ogg Theora video).
<iframe frameborder="0" height="270" src="http://www.dailymotion.com/embed/video/xusell" width="480"></iframe>
-
The decision is usually done when the bandwidth used by the
follow reachs some threshold. With XORP, this can be
controlled with
switch-to-spt-threshold. However, I was
unable to make this works as expected. XORP never sends the
appropriate PIM packets to make the switch. Therefore, for
this lab, it has been configured to switch to native
multicast at the first received packet.
R1, R2 and R3 will act as VTEPs. They
do not make use of PIM-SM. Instead, they have a generic multicast route
on eth0. E1, E2 and E3 are edge routers while C1, C2 and
C3 are core routers. The proposed lab is not resilient but
convenient to explain how things work. It is built on top of KVM
hosts. Have a look at my previous article for more details on this.
The lab is hosted on GitHub. I have made the lab easier to try by
including the kernel I have used for my tests. XORP comes
preconfigured, you just have to configure the VXLAN part. For this,
you need a recent version of ip.
$ sudo apt-get install screen vde2 kvm iproute xorp git $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git $ cd iproute2 $ ./configure && make You get ip' as ip/ip' and bridge' as bridge/bridge'. $ cd .. $ git clone git://github.com/vincentbernat/network-lab.git $ cd network-lab/lab-vxlan $ ./setup
Unicast routing
The first step is to setup unicast routing. OSPF is used for this
purpose. The chosen routing daemon is XORP. With xorpsh, we can
check if OSPF is working as expected:
root@c1# xorpsh
root@c1$ show ospf4 neighbor
Address Interface State ID Pri Dead
192.168.11.11 eth0/eth0 Full 3.0.0.1 128 36
192.168.12.22 eth1/eth1 Full 3.0.0.2 128 33
192.168.101.133 eth2/eth2 Full 2.0.0.3 128 36
192.168.102.122 eth3/eth3 Full 2.0.0.2 128 38
root@c1$ show route table ipv4 unicast ospf
192.168.1.0/24 [ospf(110)/2]
> to 192.168.11.11 via eth0/eth0
192.168.2.0/24 [ospf(110)/2]
> to 192.168.12.22 via eth1/eth1
192.168.3.0/24 [ospf(110)/3]
> to 192.168.102.122 via eth3/eth3
192.168.13.0/24 [ospf(110)/2]
> to 192.168.102.122 via eth3/eth3
192.168.21.0/24 [ospf(110)/2]
> to 192.168.101.133 via eth2/eth2
192.168.22.0/24 [ospf(110)/2]
> to 192.168.12.22 via eth1/eth1
192.168.23.0/24 [ospf(110)/2]
> to 192.168.101.133 via eth2/eth2
192.168.103.0/24 [ospf(110)/2]
> to 192.168.102.122 via eth3/eth3
Multicast routing
Once unicast routing is up and running, we need to setup multicast
routing. There are two protocols for this: IGMP and PIM-SM. The
former one allows routers to forward multicast datagrams while the
first one allows hosts to subscribe to a multicast group.
IGMP
IGMP is used by hosts and adjacent routers to establish multicast
group membership. In our case, it will be used by R2 to let E2
know it subscribed to 239.0.0.11 (a multicast group).
Configuring XORP to support IGMP is simple. Let s test with iperf to
have a multicast listener on R2:
root@r2# iperf -u -s -l 1000 -i 1 -B 239.0.0.11
------------------------------------------------------------
Server listening on UDP port 5001
Binding to local address 239.0.0.11
Joining multicast group 239.0.0.11
Receiving 1000 byte datagrams
UDP buffer size: 208 KByte (default)
------------------------------------------------------------
On E2, we can now check that R2 is properly registered for
239.0.0.11:
root@e2$ show igmp group
Interface Group Source LastReported Timeout V State
eth0 239.0.0.11 0.0.0.0 192.168.2.2 248 2 E
XORP documentation contains a good overview of IGMP.
PIM-SM
PIM-SM is far more complex. It does not have its own topology
discovery protocol and relies on routing information from other
protocols, OSPF in our case.
I will describe here a simplified view on how PIM-SM works. XORP
documentation contains more details about PIM-SM.
The first step for all PIM-SM routers is to elect a rendez-vous
point (RP). In our lab, only C1, C2 and C3 have been
configured to be elected as a RP. Moreover, we give better priority to
C3 to ensure it wins.
root@e1$ show pim rps
RP Type Pri Holdtime Timeout ActiveGroups GroupPrefix
192.168.101.133 bootstrap 100 150 135 0 239.0.0.0/8
Let s suppose we start iperf on both R2 and R3. Using IGMP, they
subscribe to multicast group 239.0.0.11 with E2 and E3
respectively. Then, E2 and E3 send a join message (also known as a
(*,G) join) to the RP (C3) for that multicast group. Using the
unicast path from E2 and E3 to the RP, the routers along the
paths build the RP tree (RPT), rooted at C3. Each router in the
tree knows how to send multicast packets to 239.0.0.11: it will send
them to the leaves.
root@e3$ show pim join
Group Source RP Flags
239.0.0.11 0.0.0.0 192.168.101.133 WC
Upstream interface (RP): eth2
Upstream MRIB next hop (RP): 192.168.23.133
Upstream RPF'(*,G): 192.168.23.133
Upstream state: Joined
Join timer: 5
Local receiver include WC: O...
Joins RP: ....
Joins WC: ....
Join state: ....
Prune state: ....
Prune pending state: ....
I am assert winner state: ....
I am assert loser state: ....
Assert winner WC: ....
Assert lost WC: ....
Assert tracking WC: O.O.
Could assert WC: O...
I am DR: O..O
Immediate olist RP: ....
Immediate olist WC: O...
Inherited olist SG: O...
Inherited olist SG_RPT: O...
PIM include WC: O...
Let s suppose that R1 wants to send multicast packets to
239.0.0.11. It sends them to R1 which does not have any
information on how to contact all the members of the multicast group
because it is not the RP. Therefore, it encapsulates the multicast
packets into PIM Register packets and sends them to the RP. The RP
decapsulates them and sends them natively. The multicast packets are
routed from the RP to R2 and R3 using the reverse path formed by
the join messages.
root@r1# iperf -c 239.0.0.11 -u -b 10k -t 30 -T 10
------------------------------------------------------------
Client connecting to 239.0.0.11, UDP port 5001
Sending 1470 byte datagrams
Setting multicast TTL to 10
UDP buffer size: 208 KByte (default)
------------------------------------------------------------
root@e1# tcpdump -pni eth0
10:58:23.424860 IP 192.168.1.1.35277 > 239.0.0.11.5001: UDP, length 1470
root@c3# tcpdump -pni eth0
10:58:23.552903 IP 192.168.11.11 > 192.168.101.133: PIMv2, Register, length 1480
root@e2# tcpdump -pni eth0
10:58:23.896171 IP 192.168.1.1.35277 > 239.0.0.11.5001: UDP, length 1470
root@e3# tcpdump -pni eth0
10:58:23.824647 IP 192.168.1.1.35277 > 239.0.0.11.5001: UDP, length 1470
As presented here, the routing is not optimal: packets from R1 to
R2 could avoid the RP. Moreover, encapsulating multicast packets
into unicast packets is not efficient either. At some point, the RP
will decide to switch to native multicast1. Rooted at R1,
the shortest-path tree (SPT) for the multicast group will be built
using source-specific join messages (also known as a (S,G) join).
From here, each router in the tree knows how to handle multicast
packets from R1 to the group without involving the RP. For example,
E1 knows it must duplicate the packet and sends one through the
interface to C3 and the other one through the interface to C1:
root@e1$ show pim join
Group Source RP Flags
239.0.0.11 192.168.1.1 192.168.101.133 SG SPT DirectlyConnectedS
Upstream interface (S): eth0
Upstream interface (RP): eth1
Upstream MRIB next hop (RP): 192.168.11.111
Upstream MRIB next hop (S): UNKNOWN
Upstream RPF'(S,G): UNKNOWN
Upstream state: Joined
Register state: RegisterPrune RegisterCouldRegister
Join timer: 7
KAT(S,G) running: true
Local receiver include WC: ....
Local receiver include SG: ....
Local receiver exclude SG: ....
Joins RP: ....
Joins WC: ....
Joins SG: .OO.
Join state: .OO.
Prune state: ....
Prune pending state: ....
I am assert winner state: ....
I am assert loser state: ....
Assert winner WC: ....
Assert winner SG: ....
Assert lost WC: ....
Assert lost SG: ....
Assert lost SG_RPT: ....
Assert tracking SG: OOO.
Could assert WC: ....
Could assert SG: .OO.
I am DR: O..O
Immediate olist RP: ....
Immediate olist WC: ....
Immediate olist SG: .OO.
Inherited olist SG: .OO.
Inherited olist SG_RPT: ....
PIM include WC: ....
PIM include SG: ....
PIM exclude SG: ....
root@e1$ show pim mfc
Group Source RP
239.0.0.11 192.168.1.1 192.168.101.133
Incoming interface : eth0
Outgoing interfaces: .OO.
root@e1$ exit
[Connection to XORP closed]
root@e1# ip mroute
(192.168.1.1, 239.0.0.11) Iif: eth0 Oifs: eth1 eth2
Setting up VXLAN
Once IP multicast is running, setting up VXLAN is quite easy. Here are the software requirements:
- A recent kernel. Pick at least 3.7-rc3. You need to enable
CONFIG_VXLAN option. You also currently need a patch on top of it
to be able to specify a TTL greater than 1 for
multicast packets.
- A recent version of
ip. Currently, you need the version from git.
On R1, R2 and R3, we create a vxlan42 interface with the following commands:
root@rX# ./ip link add vxlan42 type vxlan id 42 \
> group 239.0.0.42 \
> ttl 10 dev eth0
root@rX# ip link set up dev vxlan42
root@rX# ./ip -d link show vxlan42
10: vxlan42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc noqueue state UNKNOWN mode DEFAULT
link/ether 3e:09:1c:e1:09:2e brd ff:ff:ff:ff:ff:ff
vxlan id 42 group 239.0.0.42 dev eth0 port 32768 61000 ttl 10 ageing 300
Let s assign an IP in 192.168.99.0/24 for each router and check they can ping each other:
root@r1# ip addr add 192.168.99.1/24 dev vxlan42
root@r2# ip addr add 192.168.99.2/24 dev vxlan42
root@r3# ip addr add 192.168.99.3/24 dev vxlan42
root@r1# ping 192.168.99.2
PING 192.168.99.2 (192.168.99.2) 56(84) bytes of data.
64 bytes from 192.168.99.2: icmp_req=1 ttl=64 time=3.90 ms
64 bytes from 192.168.99.2: icmp_req=2 ttl=64 time=1.38 ms
64 bytes from 192.168.99.2: icmp_req=3 ttl=64 time=1.82 ms
--- 192.168.99.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 1.389/2.375/3.907/1.098 ms
We can check the packets are encapsulated:
root@r1# tcpdump -pni eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
11:30:36.561185 IP 192.168.1.1.43349 > 192.168.2.2.8472: UDP, length 106
11:30:36.563179 IP 192.168.2.2.33894 > 192.168.1.1.8472: UDP, length 106
11:30:37.562677 IP 192.168.1.1.43349 > 192.168.2.2.8472: UDP, length 106
11:30:37.564316 IP 192.168.2.2.33894 > 192.168.1.1.8472: UDP, length 106
Moreover, if we send broadcast packets (with ping -b or ARP
requests), they are encapsulated into multicast packets:
root@r1# tcpdump -pni eth0
11:31:27.464198 IP 192.168.1.1.41958 > 239.0.0.42.8472: UDP, length 106
11:31:28.463584 IP 192.168.1.1.41958 > 239.0.0.42.8472: UDP, length 106
Recent versions of iproute also comes with bridge, an utility
allowing one to inspect the FDB of bridge-like interfaces:
root@r1# ../bridge/bridge fdb show vxlan42
3e:09:1c:e1:09:2e dev vxlan42 dst 192.168.2.2 self
0e:98:40:c6:58:10 dev vxlan42 dst 192.168.3.3 self
Demo
For a demo, have a look at the following video (it is also available
as an Ogg Theora video).
<iframe frameborder="0" height="270" src="http://www.dailymotion.com/embed/video/xusell" width="480"></iframe>
-
The decision is usually done when the bandwidth used by the
follow reachs some threshold. With XORP, this can be
controlled with
switch-to-spt-threshold. However, I was
unable to make this works as expected. XORP never sends the
appropriate PIM packets to make the switch. Therefore, for
this lab, it has been configured to switch to native
multicast at the first received packet.
root@c1# xorpsh root@c1$ show ospf4 neighbor Address Interface State ID Pri Dead 192.168.11.11 eth0/eth0 Full 3.0.0.1 128 36 192.168.12.22 eth1/eth1 Full 3.0.0.2 128 33 192.168.101.133 eth2/eth2 Full 2.0.0.3 128 36 192.168.102.122 eth3/eth3 Full 2.0.0.2 128 38 root@c1$ show route table ipv4 unicast ospf 192.168.1.0/24 [ospf(110)/2] > to 192.168.11.11 via eth0/eth0 192.168.2.0/24 [ospf(110)/2] > to 192.168.12.22 via eth1/eth1 192.168.3.0/24 [ospf(110)/3] > to 192.168.102.122 via eth3/eth3 192.168.13.0/24 [ospf(110)/2] > to 192.168.102.122 via eth3/eth3 192.168.21.0/24 [ospf(110)/2] > to 192.168.101.133 via eth2/eth2 192.168.22.0/24 [ospf(110)/2] > to 192.168.12.22 via eth1/eth1 192.168.23.0/24 [ospf(110)/2] > to 192.168.101.133 via eth2/eth2 192.168.103.0/24 [ospf(110)/2] > to 192.168.102.122 via eth3/eth3
IGMP
IGMP is used by hosts and adjacent routers to establish multicast
group membership. In our case, it will be used by R2 to let E2
know it subscribed to 239.0.0.11 (a multicast group).
Configuring XORP to support IGMP is simple. Let s test with iperf to
have a multicast listener on R2:
root@r2# iperf -u -s -l 1000 -i 1 -B 239.0.0.11
------------------------------------------------------------
Server listening on UDP port 5001
Binding to local address 239.0.0.11
Joining multicast group 239.0.0.11
Receiving 1000 byte datagrams
UDP buffer size: 208 KByte (default)
------------------------------------------------------------
On E2, we can now check that R2 is properly registered for
239.0.0.11:
root@e2$ show igmp group
Interface Group Source LastReported Timeout V State
eth0 239.0.0.11 0.0.0.0 192.168.2.2 248 2 E
XORP documentation contains a good overview of IGMP.
PIM-SM
PIM-SM is far more complex. It does not have its own topology
discovery protocol and relies on routing information from other
protocols, OSPF in our case.
I will describe here a simplified view on how PIM-SM works. XORP
documentation contains more details about PIM-SM.
The first step for all PIM-SM routers is to elect a rendez-vous
point (RP). In our lab, only C1, C2 and C3 have been
configured to be elected as a RP. Moreover, we give better priority to
C3 to ensure it wins.
root@e1$ show pim rps
RP Type Pri Holdtime Timeout ActiveGroups GroupPrefix
192.168.101.133 bootstrap 100 150 135 0 239.0.0.0/8
Let s suppose we start iperf on both R2 and R3. Using IGMP, they
subscribe to multicast group 239.0.0.11 with E2 and E3
respectively. Then, E2 and E3 send a join message (also known as a
(*,G) join) to the RP (C3) for that multicast group. Using the
unicast path from E2 and E3 to the RP, the routers along the
paths build the RP tree (RPT), rooted at C3. Each router in the
tree knows how to send multicast packets to 239.0.0.11: it will send
them to the leaves.
root@e3$ show pim join
Group Source RP Flags
239.0.0.11 0.0.0.0 192.168.101.133 WC
Upstream interface (RP): eth2
Upstream MRIB next hop (RP): 192.168.23.133
Upstream RPF'(*,G): 192.168.23.133
Upstream state: Joined
Join timer: 5
Local receiver include WC: O...
Joins RP: ....
Joins WC: ....
Join state: ....
Prune state: ....
Prune pending state: ....
I am assert winner state: ....
I am assert loser state: ....
Assert winner WC: ....
Assert lost WC: ....
Assert tracking WC: O.O.
Could assert WC: O...
I am DR: O..O
Immediate olist RP: ....
Immediate olist WC: O...
Inherited olist SG: O...
Inherited olist SG_RPT: O...
PIM include WC: O...
Let s suppose that R1 wants to send multicast packets to
239.0.0.11. It sends them to R1 which does not have any
information on how to contact all the members of the multicast group
because it is not the RP. Therefore, it encapsulates the multicast
packets into PIM Register packets and sends them to the RP. The RP
decapsulates them and sends them natively. The multicast packets are
routed from the RP to R2 and R3 using the reverse path formed by
the join messages.
root@r1# iperf -c 239.0.0.11 -u -b 10k -t 30 -T 10
------------------------------------------------------------
Client connecting to 239.0.0.11, UDP port 5001
Sending 1470 byte datagrams
Setting multicast TTL to 10
UDP buffer size: 208 KByte (default)
------------------------------------------------------------
root@e1# tcpdump -pni eth0
10:58:23.424860 IP 192.168.1.1.35277 > 239.0.0.11.5001: UDP, length 1470
root@c3# tcpdump -pni eth0
10:58:23.552903 IP 192.168.11.11 > 192.168.101.133: PIMv2, Register, length 1480
root@e2# tcpdump -pni eth0
10:58:23.896171 IP 192.168.1.1.35277 > 239.0.0.11.5001: UDP, length 1470
root@e3# tcpdump -pni eth0
10:58:23.824647 IP 192.168.1.1.35277 > 239.0.0.11.5001: UDP, length 1470
As presented here, the routing is not optimal: packets from R1 to
R2 could avoid the RP. Moreover, encapsulating multicast packets
into unicast packets is not efficient either. At some point, the RP
will decide to switch to native multicast1. Rooted at R1,
the shortest-path tree (SPT) for the multicast group will be built
using source-specific join messages (also known as a (S,G) join).
From here, each router in the tree knows how to handle multicast
packets from R1 to the group without involving the RP. For example,
E1 knows it must duplicate the packet and sends one through the
interface to C3 and the other one through the interface to C1:
root@e1$ show pim join
Group Source RP Flags
239.0.0.11 192.168.1.1 192.168.101.133 SG SPT DirectlyConnectedS
Upstream interface (S): eth0
Upstream interface (RP): eth1
Upstream MRIB next hop (RP): 192.168.11.111
Upstream MRIB next hop (S): UNKNOWN
Upstream RPF'(S,G): UNKNOWN
Upstream state: Joined
Register state: RegisterPrune RegisterCouldRegister
Join timer: 7
KAT(S,G) running: true
Local receiver include WC: ....
Local receiver include SG: ....
Local receiver exclude SG: ....
Joins RP: ....
Joins WC: ....
Joins SG: .OO.
Join state: .OO.
Prune state: ....
Prune pending state: ....
I am assert winner state: ....
I am assert loser state: ....
Assert winner WC: ....
Assert winner SG: ....
Assert lost WC: ....
Assert lost SG: ....
Assert lost SG_RPT: ....
Assert tracking SG: OOO.
Could assert WC: ....
Could assert SG: .OO.
I am DR: O..O
Immediate olist RP: ....
Immediate olist WC: ....
Immediate olist SG: .OO.
Inherited olist SG: .OO.
Inherited olist SG_RPT: ....
PIM include WC: ....
PIM include SG: ....
PIM exclude SG: ....
root@e1$ show pim mfc
Group Source RP
239.0.0.11 192.168.1.1 192.168.101.133
Incoming interface : eth0
Outgoing interfaces: .OO.
root@e1$ exit
[Connection to XORP closed]
root@e1# ip mroute
(192.168.1.1, 239.0.0.11) Iif: eth0 Oifs: eth1 eth2
Setting up VXLAN
Once IP multicast is running, setting up VXLAN is quite easy. Here are the software requirements:
- A recent kernel. Pick at least 3.7-rc3. You need to enable
CONFIG_VXLAN option. You also currently need a patch on top of it
to be able to specify a TTL greater than 1 for
multicast packets.
- A recent version of
ip. Currently, you need the version from git.
On R1, R2 and R3, we create a vxlan42 interface with the following commands:
root@rX# ./ip link add vxlan42 type vxlan id 42 \
> group 239.0.0.42 \
> ttl 10 dev eth0
root@rX# ip link set up dev vxlan42
root@rX# ./ip -d link show vxlan42
10: vxlan42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc noqueue state UNKNOWN mode DEFAULT
link/ether 3e:09:1c:e1:09:2e brd ff:ff:ff:ff:ff:ff
vxlan id 42 group 239.0.0.42 dev eth0 port 32768 61000 ttl 10 ageing 300
Let s assign an IP in 192.168.99.0/24 for each router and check they can ping each other:
root@r1# ip addr add 192.168.99.1/24 dev vxlan42
root@r2# ip addr add 192.168.99.2/24 dev vxlan42
root@r3# ip addr add 192.168.99.3/24 dev vxlan42
root@r1# ping 192.168.99.2
PING 192.168.99.2 (192.168.99.2) 56(84) bytes of data.
64 bytes from 192.168.99.2: icmp_req=1 ttl=64 time=3.90 ms
64 bytes from 192.168.99.2: icmp_req=2 ttl=64 time=1.38 ms
64 bytes from 192.168.99.2: icmp_req=3 ttl=64 time=1.82 ms
--- 192.168.99.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 1.389/2.375/3.907/1.098 ms
We can check the packets are encapsulated:
root@r1# tcpdump -pni eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
11:30:36.561185 IP 192.168.1.1.43349 > 192.168.2.2.8472: UDP, length 106
11:30:36.563179 IP 192.168.2.2.33894 > 192.168.1.1.8472: UDP, length 106
11:30:37.562677 IP 192.168.1.1.43349 > 192.168.2.2.8472: UDP, length 106
11:30:37.564316 IP 192.168.2.2.33894 > 192.168.1.1.8472: UDP, length 106
Moreover, if we send broadcast packets (with ping -b or ARP
requests), they are encapsulated into multicast packets:
root@r1# tcpdump -pni eth0
11:31:27.464198 IP 192.168.1.1.41958 > 239.0.0.42.8472: UDP, length 106
11:31:28.463584 IP 192.168.1.1.41958 > 239.0.0.42.8472: UDP, length 106
Recent versions of iproute also comes with bridge, an utility
allowing one to inspect the FDB of bridge-like interfaces:
root@r1# ../bridge/bridge fdb show vxlan42
3e:09:1c:e1:09:2e dev vxlan42 dst 192.168.2.2 self
0e:98:40:c6:58:10 dev vxlan42 dst 192.168.3.3 self
Demo
For a demo, have a look at the following video (it is also available
as an Ogg Theora video).
<iframe frameborder="0" height="270" src="http://www.dailymotion.com/embed/video/xusell" width="480"></iframe>
-
The decision is usually done when the bandwidth used by the
follow reachs some threshold. With XORP, this can be
controlled with
switch-to-spt-threshold. However, I was
unable to make this works as expected. XORP never sends the
appropriate PIM packets to make the switch. Therefore, for
this lab, it has been configured to switch to native
multicast at the first received packet.
root@r2# iperf -u -s -l 1000 -i 1 -B 239.0.0.11 ------------------------------------------------------------ Server listening on UDP port 5001 Binding to local address 239.0.0.11 Joining multicast group 239.0.0.11 Receiving 1000 byte datagrams UDP buffer size: 208 KByte (default) ------------------------------------------------------------
root@e2$ show igmp group Interface Group Source LastReported Timeout V State eth0 239.0.0.11 0.0.0.0 192.168.2.2 248 2 E
C1, C2 and C3 have been
configured to be elected as a RP. Moreover, we give better priority to
C3 to ensure it wins.
root@e1$ show pim rps RP Type Pri Holdtime Timeout ActiveGroups GroupPrefix 192.168.101.133 bootstrap 100 150 135 0 239.0.0.0/8
iperf on both R2 and R3. Using IGMP, they
subscribe to multicast group 239.0.0.11 with E2 and E3
respectively. Then, E2 and E3 send a join message (also known as a
(*,G) join) to the RP (C3) for that multicast group. Using the
unicast path from E2 and E3 to the RP, the routers along the
paths build the RP tree (RPT), rooted at C3. Each router in the
tree knows how to send multicast packets to 239.0.0.11: it will send
them to the leaves.
root@e3$ show pim join Group Source RP Flags 239.0.0.11 0.0.0.0 192.168.101.133 WC Upstream interface (RP): eth2 Upstream MRIB next hop (RP): 192.168.23.133 Upstream RPF'(*,G): 192.168.23.133 Upstream state: Joined Join timer: 5 Local receiver include WC: O... Joins RP: .... Joins WC: .... Join state: .... Prune state: .... Prune pending state: .... I am assert winner state: .... I am assert loser state: .... Assert winner WC: .... Assert lost WC: .... Assert tracking WC: O.O. Could assert WC: O... I am DR: O..O Immediate olist RP: .... Immediate olist WC: O... Inherited olist SG: O... Inherited olist SG_RPT: O... PIM include WC: O...
R1 wants to send multicast packets to
239.0.0.11. It sends them to R1 which does not have any
information on how to contact all the members of the multicast group
because it is not the RP. Therefore, it encapsulates the multicast
packets into PIM Register packets and sends them to the RP. The RP
decapsulates them and sends them natively. The multicast packets are
routed from the RP to R2 and R3 using the reverse path formed by
the join messages.
root@r1# iperf -c 239.0.0.11 -u -b 10k -t 30 -T 10 ------------------------------------------------------------ Client connecting to 239.0.0.11, UDP port 5001 Sending 1470 byte datagrams Setting multicast TTL to 10 UDP buffer size: 208 KByte (default) ------------------------------------------------------------ root@e1# tcpdump -pni eth0 10:58:23.424860 IP 192.168.1.1.35277 > 239.0.0.11.5001: UDP, length 1470 root@c3# tcpdump -pni eth0 10:58:23.552903 IP 192.168.11.11 > 192.168.101.133: PIMv2, Register, length 1480 root@e2# tcpdump -pni eth0 10:58:23.896171 IP 192.168.1.1.35277 > 239.0.0.11.5001: UDP, length 1470 root@e3# tcpdump -pni eth0 10:58:23.824647 IP 192.168.1.1.35277 > 239.0.0.11.5001: UDP, length 1470
R1 to
R2 could avoid the RP. Moreover, encapsulating multicast packets
into unicast packets is not efficient either. At some point, the RP
will decide to switch to native multicast1. Rooted at R1,
the shortest-path tree (SPT) for the multicast group will be built
using source-specific join messages (also known as a (S,G) join).
From here, each router in the tree knows how to handle multicast
packets from R1 to the group without involving the RP. For example,
E1 knows it must duplicate the packet and sends one through the
interface to C3 and the other one through the interface to C1:
root@e1$ show pim join Group Source RP Flags 239.0.0.11 192.168.1.1 192.168.101.133 SG SPT DirectlyConnectedS Upstream interface (S): eth0 Upstream interface (RP): eth1 Upstream MRIB next hop (RP): 192.168.11.111 Upstream MRIB next hop (S): UNKNOWN Upstream RPF'(S,G): UNKNOWN Upstream state: Joined Register state: RegisterPrune RegisterCouldRegister Join timer: 7 KAT(S,G) running: true Local receiver include WC: .... Local receiver include SG: .... Local receiver exclude SG: .... Joins RP: .... Joins WC: .... Joins SG: .OO. Join state: .OO. Prune state: .... Prune pending state: .... I am assert winner state: .... I am assert loser state: .... Assert winner WC: .... Assert winner SG: .... Assert lost WC: .... Assert lost SG: .... Assert lost SG_RPT: .... Assert tracking SG: OOO. Could assert WC: .... Could assert SG: .OO. I am DR: O..O Immediate olist RP: .... Immediate olist WC: .... Immediate olist SG: .OO. Inherited olist SG: .OO. Inherited olist SG_RPT: .... PIM include WC: .... PIM include SG: .... PIM exclude SG: .... root@e1$ show pim mfc Group Source RP 239.0.0.11 192.168.1.1 192.168.101.133 Incoming interface : eth0 Outgoing interfaces: .OO. root@e1$ exit [Connection to XORP closed] root@e1# ip mroute (192.168.1.1, 239.0.0.11) Iif: eth0 Oifs: eth1 eth2
Setting up VXLAN
Once IP multicast is running, setting up VXLAN is quite easy. Here are the software requirements:
- A recent kernel. Pick at least 3.7-rc3. You need to enable
CONFIG_VXLAN option. You also currently need a patch on top of it
to be able to specify a TTL greater than 1 for
multicast packets.
- A recent version of
ip. Currently, you need the version from git.
On R1, R2 and R3, we create a vxlan42 interface with the following commands:
root@rX# ./ip link add vxlan42 type vxlan id 42 \
> group 239.0.0.42 \
> ttl 10 dev eth0
root@rX# ip link set up dev vxlan42
root@rX# ./ip -d link show vxlan42
10: vxlan42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc noqueue state UNKNOWN mode DEFAULT
link/ether 3e:09:1c:e1:09:2e brd ff:ff:ff:ff:ff:ff
vxlan id 42 group 239.0.0.42 dev eth0 port 32768 61000 ttl 10 ageing 300
Let s assign an IP in 192.168.99.0/24 for each router and check they can ping each other:
root@r1# ip addr add 192.168.99.1/24 dev vxlan42
root@r2# ip addr add 192.168.99.2/24 dev vxlan42
root@r3# ip addr add 192.168.99.3/24 dev vxlan42
root@r1# ping 192.168.99.2
PING 192.168.99.2 (192.168.99.2) 56(84) bytes of data.
64 bytes from 192.168.99.2: icmp_req=1 ttl=64 time=3.90 ms
64 bytes from 192.168.99.2: icmp_req=2 ttl=64 time=1.38 ms
64 bytes from 192.168.99.2: icmp_req=3 ttl=64 time=1.82 ms
--- 192.168.99.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 1.389/2.375/3.907/1.098 ms
We can check the packets are encapsulated:
root@r1# tcpdump -pni eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
11:30:36.561185 IP 192.168.1.1.43349 > 192.168.2.2.8472: UDP, length 106
11:30:36.563179 IP 192.168.2.2.33894 > 192.168.1.1.8472: UDP, length 106
11:30:37.562677 IP 192.168.1.1.43349 > 192.168.2.2.8472: UDP, length 106
11:30:37.564316 IP 192.168.2.2.33894 > 192.168.1.1.8472: UDP, length 106
Moreover, if we send broadcast packets (with ping -b or ARP
requests), they are encapsulated into multicast packets:
root@r1# tcpdump -pni eth0
11:31:27.464198 IP 192.168.1.1.41958 > 239.0.0.42.8472: UDP, length 106
11:31:28.463584 IP 192.168.1.1.41958 > 239.0.0.42.8472: UDP, length 106
Recent versions of iproute also comes with bridge, an utility
allowing one to inspect the FDB of bridge-like interfaces:
root@r1# ../bridge/bridge fdb show vxlan42
3e:09:1c:e1:09:2e dev vxlan42 dst 192.168.2.2 self
0e:98:40:c6:58:10 dev vxlan42 dst 192.168.3.3 self
Demo
For a demo, have a look at the following video (it is also available
as an Ogg Theora video).
<iframe frameborder="0" height="270" src="http://www.dailymotion.com/embed/video/xusell" width="480"></iframe>
-
The decision is usually done when the bandwidth used by the
follow reachs some threshold. With XORP, this can be
controlled with
switch-to-spt-threshold. However, I was
unable to make this works as expected. XORP never sends the
appropriate PIM packets to make the switch. Therefore, for
this lab, it has been configured to switch to native
multicast at the first received packet.
CONFIG_VXLAN option. You also currently need a patch on top of it
to be able to specify a TTL greater than 1 for
multicast packets.ip. Currently, you need the version from git.root@rX# ./ip link add vxlan42 type vxlan id 42 \ > group 239.0.0.42 \ > ttl 10 dev eth0 root@rX# ip link set up dev vxlan42 root@rX# ./ip -d link show vxlan42 10: vxlan42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc noqueue state UNKNOWN mode DEFAULT link/ether 3e:09:1c:e1:09:2e brd ff:ff:ff:ff:ff:ff vxlan id 42 group 239.0.0.42 dev eth0 port 32768 61000 ttl 10 ageing 300
root@r1# ip addr add 192.168.99.1/24 dev vxlan42 root@r2# ip addr add 192.168.99.2/24 dev vxlan42 root@r3# ip addr add 192.168.99.3/24 dev vxlan42 root@r1# ping 192.168.99.2 PING 192.168.99.2 (192.168.99.2) 56(84) bytes of data. 64 bytes from 192.168.99.2: icmp_req=1 ttl=64 time=3.90 ms 64 bytes from 192.168.99.2: icmp_req=2 ttl=64 time=1.38 ms 64 bytes from 192.168.99.2: icmp_req=3 ttl=64 time=1.82 ms --- 192.168.99.2 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2003ms rtt min/avg/max/mdev = 1.389/2.375/3.907/1.098 ms
root@r1# tcpdump -pni eth0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 11:30:36.561185 IP 192.168.1.1.43349 > 192.168.2.2.8472: UDP, length 106 11:30:36.563179 IP 192.168.2.2.33894 > 192.168.1.1.8472: UDP, length 106 11:30:37.562677 IP 192.168.1.1.43349 > 192.168.2.2.8472: UDP, length 106 11:30:37.564316 IP 192.168.2.2.33894 > 192.168.1.1.8472: UDP, length 106
root@r1# tcpdump -pni eth0 11:31:27.464198 IP 192.168.1.1.41958 > 239.0.0.42.8472: UDP, length 106 11:31:28.463584 IP 192.168.1.1.41958 > 239.0.0.42.8472: UDP, length 106
root@r1# ../bridge/bridge fdb show vxlan42 3e:09:1c:e1:09:2e dev vxlan42 dst 192.168.2.2 self 0e:98:40:c6:58:10 dev vxlan42 dst 192.168.3.3 self
<iframe frameborder="0" height="270" src="http://www.dailymotion.com/embed/video/xusell" width="480"></iframe>
-
The decision is usually done when the bandwidth used by the
follow reachs some threshold. With XORP, this can be
controlled with
switch-to-spt-threshold. However, I was unable to make this works as expected. XORP never sends the appropriate PIM packets to make the switch. Therefore, for this lab, it has been configured to switch to native multicast at the first received packet.
Since October 2011 my flatmate and I where quite busy realizing a little pet project of ours called 

Just after the
(This post contains some discussion of rape and sexual assault but does not go into any specifics)
Over the years, I have had many different blogs. I mainly use them to post updates regarding my work in the FOSS community, with most of these relating to Ubuntu/Debian. My most recent blog was a Wordpress instance I ran on a VPS provided by a friend. This worked pretty well, but for various reasons, I no longer have access to that box.
Earlier today, I started thinking about launching a new blog. The first problem I had to overcome was deciding where to host it. Many of the groups I am involved with provide members with a ~/public_html directory that can be used to host simple HTML+Javascript+CSS websites. However, most of these sites do not have the ability to use PHP, CGI, or access databases. I realized rather quickly that if I were to find a blogging platform that I could run from a ~/public_html directory on one of those machines, I would never have the problem of not having a host for my blog ever again. There is a near infinite number of free web hosts that can handle simple HTML sites.
One key feature of any blog is the ability for readers to subscribe to it. Usually, the blogging platform handles automatically updating the feed when a new post is published. However, my simple HTML blog would not be able to do that. Since I knew I did not want to manually update the feeds, I started looking for a way to generate the feed locally on my personal machine and then push it to the remote site that is hosting my blog.
About this time, I started compiling a list of features I would need to make this blogging platform usable. In no particular order, they included:
here's the short overview about my activities around release-critical bugs
for the last week:
The
PS: yes, I'm talking here about GitHub, which is not Open Source
software itself. I regard that as a (temporary) inconvenience, which
dies not detract from the significant advantage it brings to the
table.
[1]
During the Squeeze release cycle, Alexander Reichle-Schmehl used to blog every week about this. Let s try to continue the tradition.
The
There have been a few interesting discussions going on in parallel
about my
A few days ago,
Synaps
Synaps is written in around 7k lines of Python (with 28 % of which are
comments), reuses at least one common module of OpenStack
(openstack.common.cfg) and copy some modules from Nova. One thing that
strikes me, is that there seems to be only a few unit tests compared to most
OpenStack projects. Also, many parts of the code and documentation contains
text written in korean, which won't be very helpful for most people! :-)
It uses some external technologies, like
Overlap with Heat
For now, there's not a lot of overlap with Heat, because Heat does not
implement completely the CloudWatch API. Heat actually still misses a lot of
the CloudWatch functions. But as soon as it will implement the CloudWatch
API completely, the overlap will be complete with Synaps in this regard.
One divergence point however, is that Heat uses RPC to access data from the
storage back-end via its engine (the central daemon), whereas Synaps
directly connects to Cassandra. Also, Heat relies on SQLAlchemy, like most
OpenStack projects needing a database.
Overlap with Ceilometer
One of the goal of Ceilometer is to provide data probes and pollsters for
all OpenStack components (Nova, Swift, Quantum ) whereas Synaps let the
OpenStack users to put any kind of metric inside it, and therefore doesn't
provide anything for now.
But the storage of metrics is the main common point between Synaps and
Ceilometer. Synaps chose only one technology, Cassandra, to store its
metrics, whereas Ceilometer took care of building an abstraction layer for
the storage engine. Ceilometer currently allows an operator to use SQL or
MongoDB, but Cassandra could likely be added.
Data metric consolidation is done by Synaps. This makes sense, since Synaps
don't need to have the full data history to trigger alarms. On the opposite,
Ceilometer needs to have a full history to allow things like billing, and
don't do any aggregation on data.
Also, in Synaps, the data analysis is done using Pandas. This means the data
used are retrieved from the Cassandra back-end, and then transformed by
Pandas inside Synaps in something else. It's likely that in such a case,
Synaps should use CQL to achieve that. Ceilometer manipulates the data near
their storage: it means that the computation are done by back-end to be
efficient (SQL, mapreduce ).
Conclusion
Considering Samsung open-sourced Synaps late in the development process, I
don't feel like they aimed to have it becoming a core component. This is
always sad, because the effort put into this implementation are big and it
would have probably little to add some abstraction layers to follow what
other OpenStack projects do. But this takes time and energy, and it's
understandable that Samsung didn't want to achieve this in a short time
frame.
There's a part of the code and architecture that overlaps with Ceilometer
and Heat. Ceilometer is becoming a specialized point to store data metrics
from any source: so it's sad, but understandable, that Synaps did not tried
to reuse it. Fortunately, Heat is working with Ceilometer to achieve exactly
that. This means OpenStack would have only one metrics storage point, used
for billing, for monitoring and alarming.
Therefore, I think Synaps is an implementation of CloudWatch that should be
looked at as an inspiration for Heat and Ceilometer to build a better and
more integrated solution!
For long-winded reasons I'd rather not explain nor defend, my partner uses
Dropbox for a large set of important files (~70G), which are stored on a
removable drive. She is also a Windows user. Recently, by introducing a few
new drives, I inadvertently changed the drive letter that is assigned to her
portable device, which stopped Dropbox from working. Solving this properly is
rather finicky so I thought I'd write down what I did.
The end goal is to try and ensure that the portable drive always gets the same
drive letter and that Dropbox is configured to use that drive letter, but
before I can get that far I need to get Dropbox syncing again. It used to be