Custom Search

Monday, August 4, 2014

Howto Connect two network namespaces using linux bridge and veth pairs

1)
Add two namespaces "ns1" and "ns2"
#sudo ip netns add ns1
#sudo ip netns add ns2


2)
List all namespaces
#sudo ip netns list

3)
List all interfaces in the global namespace
#ifconfig  -a
OR
#ifconfig -a | less

4)
Create a Linux Bridge

4a)
Create the bridge br-test
#sudo brctl addbr br-test

4b)
Run following command in global naamespace to see the bridge interface
#ifconfig br-test

4c)
Disable the Spanning Tree Protocol for bridge interface "br-test"
#sudo brctl stp br-test off

*The Spanning Tree Protocol (STP) is created so that only one path exists between any pair of LAN segments. It was developed to prevent routing loops in network. Loops can happen when there is more than one route to a destination. Bridges by default are not capable of handling more than one route to a destination address.STP is used on a bridge, it is either placed into a forwarding state or a blocking state

4d)
Bring up the bridge interface "br-test".
#sudo ip link set dev br-test up

* At this point, the port/interface "br-test" is UP. You can see the status as "UP BROADCAST MULTICAST" in the output of command "#ifconfig br-test", that means UP.

5)
Create first veth/port interface pairs (Pipe) "tap1"======="br-tap1" and connect to namespace "ns1" and linux bridge "br-test".

5a)
Create veth/port interface pairs (Pipe) "tap1" and "br-tap1" in the global namespace
#sudo ip link add tap1 type veth peer name br-tap1

* Pipe: "tap1"======="br-tap1"

5b)
List all interfaces in the global namespace
#ifconfig  -a
OR
#ifconfig -a | less

* At this point the interface "tap1" and "br-tap1" don't have IP associated with it.

5c)
Move "tap1" interface from global namespace to the "ns1" namespace.
OR
Attach one side of the Pipe "tap1=======br-tap1" to "ns1" namespace.

#sudo ip link set tap1 netns ns1

* At this point run "#ifconfig -a" in global namespace an you would not able to see the "tap1" interface there.
* Run "#ifconfig -a" in "ns1" namespace to see "tap1" interface.
* Example:#sudo ip netns exec ns1 ifconfig -a

5d)
List interfaces in the linux bridge "br-test"
#brctl show br-test

* At this point you can see that there is no interfaces atatched to the linux bridge "br-test"

5e)
Move "br-tap1" interface from global namespace to the Linux Bridge "br-test".
OR
Attach other side of the Pipe "tap1=======br-tap1" to Linux Bridge "br-test".
#sudo brctl addif br-test br-tap1

5f)
List interfaces in the linux bridge "br-test"
#brctl show br-test

* At this point you can see that the interface "br-tap1" is atatched to the linux bridge "br-test"

5g)
Check the IP Address of linux bridge "br-test" and interface "br-tap1"
#sudo ifconfig br-test
#sudo ifconfig br-tap1

* You can see that, there is no IP address associated with linux bridge "br-test" and interface "br-tap1".

5h)
Check the IP Address of interface "tap1" in the namespace "ns1"
#sudo ip netns exec ns1 ifconfig -a tap1

* You can see that, there is no IP address associated with the interface "tap1"

5i)
Set interfaces "tap1" and "br-tap1" to UP
#sudo ip netns exec ns1 ip link set dev tap1 up
#sudo ip link set dev br-tap1 up

5j)
Again Check the interfaces "tap1" and "br-tap1".
#sudo ip netns exec ns1 ifconfig -a tap1
#sudo ifconfig -a br-tap1

* At this point, the ports/interfaces "br-tap1" and "tap1" are UP. You can see the status as "UP BROADCAST MULTICAST" in the output of command, that means UP. 


6)
Create second veth/port interface pairs (Pipe) "tap2"======="br-tap2" and connect to namespace "ns2" and linux bridge "br-test".

6a)
Create veth/port interface pairs (Pipe) "tap2" and "br-tap2" in the global namespace
#sudo ip link add tap2 type veth peer name br-tap2

* Pipe: "tap2"======="br-tap2"

6b)
List all interfaces in the global namespace
#ifconfig  -a
OR
#ifconfig -a | less

* At this point the interface "tap2" and "br-tap2" don't have IP associated with it.

6c)
Move "tap2" interface from global namespace to the "ns2" namespace.
OR
Attach one side of the Pipe "tap2=======br-tap2" to "ns2" namespace.

#sudo ip link set tap2 netns ns2

* At this point run "#ifconfig -a" in global namespace an you would not able to see the "tap2" interface there.
* Run "#ifconfig -a" in "ns2" namespace to see "tap2" interface.
* Example:#sudo ip netns exec ns2 ifconfig -a

6d)
List interfaces in the linux bridge "br-test"
#brctl show br-test

* At this point you can see that there is only one interface "br-tap1" is atatched to the linux bridge "br-test"

6e)
Move "br-tap2" interface from global namespace to the Linux Bridge "br-test".
OR
Attach other side of the Pipe "tap2=======br-tap2" to Linux Bridge "br-test".
#sudo brctl addif br-test br-tap2

6f)
List interfaces in the linux bridge "br-test"
#brctl show br-test
bridge name    bridge id        STP enabled    interfaces
br-test        8000.822e41140e4c    no        br-tap1
                                        br-tap2

* At this point you can see that the interfaces "br-tap1" and "br-tap2" are atatched to the linux bridge "br-test"

6g)
Check the IP Address of linux bridge "br-test" and interface "br-tap2"
#sudo ifconfig br-test
#sudo ifconfig br-tap2

* You can see that, there is no IP address associated with linux bridge "br-test" and interface "br-tap2".

6h)
Check the IP Address of interface "tap2" in the namespace "ns2"
#sudo ip netns exec ns2 ifconfig -a tap2

* You can see that, there is no IP address associated with the interface "tap2"

6i)
Set interfaces "tap2" and "br-tap2" to UP
#sudo ip netns exec ns2 ip link set dev tap2 up
#sudo ip link set dev br-tap2 up

6j)
Again Check the interfaces "tap2" and "br-tap2".
#sudo ip netns exec ns2 ifconfig -a tap2
#sudo ifconfig -a br-tap2

* At this point, the ports/interfaces "br-tap2" and "tap2" are UP. You can see the status as "UP BROADCAST MULTICAST" in the output of command, that means UP.  

7)
Assign IP address to the interfaces "tap1" in the namespace "ns1 and "tap2" in the namespace "ns2" and ping from "ns1" to "ns2".

7a)
Assign IP address to the interface "tap1" in the namespace "ns1".
#sudo ip netns exec ns1 ip addr add 10.1.1.4/24 dev tap1

7b)
Assign IP address to the interface "tap2" in the namespace "ns2".
#sudo ip netns exec ns2 ip addr add 10.1.1.5/24 dev tap2

7c)
Check the IP address of the interfaces "tap1" and "tap2"
#sudo ip netns exec ns1 ifconfig -a tap1
#sudo ip netns exec ns2 ifconfig -a tap2

7d)
Ping from "ns1" to "ns2".
#sudo ip netns exec ns1 ping 10.1.1.5

* Ping works

7d,a)
Capture Ping (ICMP) packets from interfaces "tap1", "tap1" and bridge "br-test". 

#sudo ip netns exec ns1 tshark -i tap1 icmp
#sudo ip netns exec ns2 tshark -i tap2 icmp

#sudo tshark -i br-tap1 icmp
#sudo tshark -i br-tap2 icmp

#sudo tshark -i br-test icmp

* You can see that packets are going from "tap1" to "tap2" through "br-tap1" and "br-tap2".
* You can also able to capture ICMP packets from interfaces "tap1", "tap2", "br-tap1" and "br-tap2".
* But you can't able to see/capture the ICMP packets from bridge interface "br-test", because destination IP/network 10.1.1.5 is local to the bridge, so packet will not flow outside the bridge through "br-test" and routing table. See the picture.




http://www.microhowto.info/troubleshooting/troubleshooting_ethernet_bridging_on_linux.html

7e)
Debug bridge


http://www.microhowto.info/troubleshooting/troubleshooting_ethernet_bridging_on_linux.html

In the course of its operation a bridge must attempt to determine which MAC addresses are reachable through each of its attached interfaces. It does this by inspecting the source address of each packet that arrives at the bridge and recording it in a table. In the case of the Linux bridging module it is possible to inspect the content of this table using the brctl showmacs command:

#brctl showmacs br-test
port no    mac addr        is local?    ageing timer
1    82:2e:41:14:0e:4c    yes           0.00
2    ea:9a:12:97:cb:89    yes           0.00

* Here "82:2e:41:14:0e:4c" is the MAC of "br-tap1" interface.
* Here "ea:9a:12:97:cb:89" is the MAC of "br-tap2" interface.



8)
Try to ping to differen IP/Network from namespace "ns1"


 
8a)
Ping to "173.194.36.16" (www.google.com) from namespace "ns1"
#sudo ip netns exec ns1 ping 173.194.36.16
connect: Network is unreachabl

* You will get error like "connect: Network is unreachable"

8b)
Check routing table in the namespace "ns1".
#sudo ip netns exec ns1 route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 tap1

* Routing table has only one entry for the network 10.1.1.x.
* So we need to define the default gateway in the routing table to ping to another network. So the packets for different networks will flow through that gateway to outside.

8c)
Check the IP of Lnux bridge "br-test"
#ifconfig br-test

8d)
Set IP Address for the bridge "br-test"
#sudo ip addr add 10.1.1.3/24 dev br-test

8e)
Check the IP of Lnux bridge "br-test"
#ifconfig br-test

8f)
Add a default gateway to flow packets which are not destined for the network 10.1.1.x to outside.
#sudo ip netns exec ns1 route add default gw 10.1.1.3 tap1

* Defalut gateway has set to the IP address of the linux bridge "br-test"

8g)
Check routing table in the namespace "ns1".
#sudo ip netns exec ns1 route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.1.1.3        0.0.0.0         UG    0      0        0 tap1
10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 tap1

* Packets which are not destined for the network 10.1.1.x will flow through the default gateway "10.1.1.3" (linux bridge) to outside.

8h)
Ping to 173.194.36.16 from namespace "ns1"
#sudo ip netns exec ns1 ping 173.194.36.16
PING 173.194.36.16 (173.194.36.16) 56(84) bytes of data.

* Ping will not work.
* But, if you capture the packets from the interface "tap1", "br-tap1" and "br-test", you can see that request packets are flowing from "tap1" to "br-test" via "br-tap1".
* That means reply packets are not routing properly. So we need to add SNAT in global namespace for packet which has source IP:10.1.1.4 or 10.1.1.x. OR we need to add MASQURIDE rule for interface "eth0"(virtualBox NAT).



8h,a)
Capture the packets from the interface "tap1", "br-tap1" and "br-test".

#sudo ip netns exec ns1 tshark -i tap1 icmp
1   0.000000     10.1.1.4 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a07, seq=1/256, ttl=64
2   1.008723     10.1.1.4 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a07, seq=2/512, ttl=64
3   2.016698     10.1.1.4 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a07, seq=3/768, ttl=64

* Note: Here, You can see only the request packets.

#sudo tshark -i br-tap1 icmp
1   0.000000     10.1.1.4 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a07, seq=1/256, ttl=64
2   1.008766     10.1.1.4 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a07, seq=2/512, ttl=64
3   2.016713     10.1.1.4 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a07, seq=3/768, ttl=64

* Note: Here, You can see only the request packets.

#sudo tshark -i br-test icmp
1   0.000000     10.1.1.4 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a07, seq=1/256, ttl=64
2   1.008766     10.1.1.4 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a07, seq=2/512, ttl=64
3   2.016713     10.1.1.4 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a07, seq=3/768, ttl=64

* Note: Here, You can see only the request packets.

8h,b)
Check routing table in the golbal namespace
#route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.2.2        0.0.0.0         UG    0      0        0 eth0
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 br-test
192.168.56.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1
192.168.122.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr0

* You can see that, global namespace has 3 interfaces "eth0"(virtualBox NAT), "eth1"(VirtualBox HostOnly) and Linux bridge "br-test".
* According to this routing table, request packets from the interface "br-test"(10.1.1.0) will go through the gateway 10.0.2.2 of interface "eth0"(virtualBox NAT).

#So try to capture the packets from the interface "eth0"(virtualBox NAT)
#sudo tshark -i eth0 icmp
1   0.000000     10.1.1.4 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a32, seq=1/256, ttl=63
2   1.009619     10.1.1.4 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a32, seq=2/512, ttl=63
3   2.017055     10.1.1.4 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a32, seq=3/768, ttl=63

* Note: Here, You can see only the request packets.

#Capture packets from the "wlan0" WIFI interface in the laptop.
#sudo tshark -i wlan0 icmp
1   0.000000 100.112.28.126 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a40, seq=1/256, ttl=62
    0.041521 173.194.36.16 -> 100.112.28.126 ICMP 98 Echo (ping) reply    id=0x1a40, seq=1/256, ttl=56 (request in 1)
2   1.007943 100.112.28.126 -> 173.194.36.16 ICMP 98 Echo (ping) request  id=0x1a40, seq=2/512, ttl=62
    1.065012 173.194.36.16 -> 100.112.28.126 ICMP 98 Echo (ping) reply    id=0x1a40, seq=2/512, ttl=56 (request in 3)

* Note: Here, you can see both the request and reply packets.


Links
=======

http://www.microhowto.info/troubleshooting/troubleshooting_ethernet_bridging_on_linux.html

http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge

http://www.tldp.org/HOWTO/Ethernet-Bridge-netfilter-HOWTO-3.html



3 comments:

  1. create_2_namespaces_and_1_bridge()
    {
    echo "Creating namespace and bridge......"

    sudo ip netns add ns1
    sudo ip netns add ns2
    sudo brctl addbr br-test
    sudo brctl stp br-test off
    sudo ip link set dev br-test up
    sudo ip link add tap1 type veth peer name br-tap1
    sudo ip link set tap1 netns ns1
    sudo brctl addif br-test br-tap1
    sudo ip netns exec ns1 ip link set dev tap1 up
    sudo ip link set dev br-tap1 up
    sudo ip link add tap2 type veth peer name br-tap2
    sudo ip link set tap2 netns ns2
    sudo brctl addif br-test br-tap2
    sudo ip netns exec ns2 ip link set dev tap2 up
    sudo ip link set dev br-tap2 up
    sudo ip netns exec ns1 ip addr add 10.1.1.4/24 dev tap1
    sudo ip netns exec ns2 ip addr add 10.1.1.5/24 dev tap2
    sudo ip netns exec ns1 ping 10.1.1.5 -c 1

    if [ $? -eq 0 ]; then
    echo "Ping working from ns1 (10.1.1.4) to ns2 (10.1.1.5)"
    echo "Created namespace and bridge......"
    else
    echo "Failed to Create namespace and bridge......"
    fi
    }


    delete_2_namespaces_and_1_bridge()
    {
    echo "Deleting namespace and bridge......"

    sudo ip netns del ns1
    sudo ip netns del ns2
    sudo ip link set dev br-test down
    sudo brctl delbr br-test

    if [ $? -eq 0 ]; then
    echo "Deleted namespace and bridge......"
    else
    echo "Failed to delete namespace and bridge......"
    fi
    }


    #create_2_namespaces_and_1_bridge
    #delete_2_namespaces_and_1_bridge

    ReplyDelete
  2. http://www.opencloudblog.com/?p=66

    ReplyDelete
  3. Great writeup. Alternatively, you can connect two namespaces directly using one veth pair. No connection to outside though. So yeah, your method works great.

    ReplyDelete