Virtual Routing and Forwarding VRF on Linux Using ip netns

In the Linux world, the VRFs of the professional networking world got the name “network namespace”

In L2 switching World, More than one switch instance runs on single switch by VLAN

In L3 Routing World, More than one Router instance also known as Virtual router runs on one Real Router got the name Virtual Routing and Forwarding- VRF and in Linux World known as “network namespace”

And VRF is now possible in Linux by tools known as “iproute” rpm with version 2.X and release “X.netns.2

Each network namespace has it’s own routing table, it’s own iptables setup providing nat and filtering. Linux network namespaces offer in addition the capability to run processes within the network namespace.

Command to manage network space : – ip netns

and for help: # ip netns help

Check your Linux OS support this feature or not, by adding one namespace

Creating a network namespace

# add a new namespace

ip netnas add <network namespace name>

#Example:

ip netns add  lwnet

 

Listing all existing network namespaces in the system

# list all namespaces

ip netns list

#will show the namespace from above

lwnet

 

Deleting a network namespace

# ip netns delete <network namespace name>

 

Executing a command in a network namespace

The command ip offers the “black magic” to execute commands in the network namespace. The following is used:

# execute a command in a namespace

ip netns exec <network namespace name> <command>

#Example using the namespace from above:

ip netns exec  lwnet  ip addr

 

shows all ip interfaces and addresses in the namespace

3: lo: <LOOPBACK> mtu 16436 qdisc noop state DOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

Note: if you create one more namespace and check its interface details , it show ID 4, ie. VLAN id to separate this network from other namespace at L2 layer by VLAN number

# ip netns add test
# ip netns exec test ip a
4: lo: <LOOPBACK> mtu 16436 qdisc noop state DOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

———————————————————————————————————————————————————————

A “dirty” trick is to not start each command with the prefix ip netns exec…. Start a shell in the network namespace using

# ip netns exec <network namespace name> bash

[root@openstack ~]# ip netns exec lwnet bash

Now below commands only show results on “lwnet” namespace
[root@openstack ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
[root@openstack ~]# ip a
3: lo: <LOOPBACK> mtu 16436 qdisc noop state DOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
[root@openstack ~]# ifconfig -a
lo        Link encap:Local Loopback
LOOPBACK  MTU:16436  Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

[root@openstack ~]# iptables -t nat -nvL

But do not forget, that you are now “trapped” in the network namespace. Just type exit to leave

———————————————————————————————————————————————————

 

Exploring the network namespace

After creating the namespace with the command above, the first task is to bring up the loopback interface of the new namespace. You may have noticed from the output above, that the loopback interface is DOWN after creating the network namespace

# set the link of lo in the namespace to up

ip netns exec lwnet ip link set dev lo up

# list all interfaces and the state in the namespace

ip netns exec lwnet  ip link

and the loopback interface is now UP. Now it’s time to connect the network namespace to the outside world.

 

Adding interfaces to a network namespace

It is not possible to assign physical interfaces of your Linux box to a network namespace. It’s only possible to attach virtual interfaces. So we have to create a virtual interface. The tool is – again – ip. The command

# ip link add veth-a type veth peer name veth-b

creates two virtual interfaces veth-a and veth-b, which are connected using “a virtual cable”. The command ip link shows both interfaces in the default namespace.

 

# ip link

veth-b: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000

link/ether 72:01:ad:c5:67:84 brd ff:ff:ff:ff:ff:ff

veth-a: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000

link/ether 8e:8b:bd:b1:88:e5 brd ff:ff:ff:ff:ff:ff

 

We can now take one end of this construct and attach it to the created namespace nstest using the command

 

# ip link set veth-b netns lwnet

 

Now ip link in the default namespace does not show this interface any more. It shows up now in the network namespace lwnet, Verify this using the command

 

# list all interfaces in the namespace lwnet

# ip netns exec lwnet  ip link

 

lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

veth-b: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000

link/ether 72:01:ad:c5:67:84 brd ff:ff:ff:ff:ff:ff

 

Assign ip addresses to the veth interfaces

Now it’s time to assign ip addresses to the veth interfaces and bring the interfaces up

# default namespace

ip addr add 10.0.0.1/24 dev veth-a

ip link set dev veth-a up

#

# namespace lwnet

ip netns exec lwnet ip addr add 10.0.0.2/24 dev veth-b

ip netns exec lwnet ip link set dev veth-b up

 

Verify, that the interfaces are up (use ip link), have ip addresses assigned (use ip addr) and a route is existing (use ip route).Now you can ping from the default namespace interface veth-a  to the lwnet namespace interface veth-b:
ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_req=1 ttl=64 time=0.054 ms
64 bytes from 10.0.0.2: icmp_req=2 ttl=64 time=0.034 ms

 

And from the lwnet namespace interface veth-b to the default namespace interface veth-a:
ip netns exec lwnet ping 10.0.0.1
PING 10.0.0.1 (100.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_req=1 ttl=64 time=0.064 ms
64 bytes from 10.0.0.1: icmp_req=2 ttl=64 time=0.036 ms

 

Which software is using network namespaces?

Network namespaces are used by many container and virtualization techniques. LXC is one of the virtualization container techniques. Openstack neutron is also using the Linux network namespaces.Virtual inferfaces and network namespaces are very useful, when a virtual switch, e.g. Openvswitch, is installed.

 

Linux Switching – Interconnecting Namespaces :
The software switching classical tool is the linuxbridge, which is available in the Linux kernel for a long time. The frontend to manage the linuxbridge is brctl. The newer tool is the Openvswitch (at http://openvswitch.org/). The main frontend is ovs-vsctl.
I will show multiple solutions to interconnect Linux namespaces using a software based switch.

 

tap interfaces
Linux tap interfaces created with ip tun / tap cannot be used to attach network namespaces to linuxbridges or the openvswitch.

 

Solution 1 : veth pair

The simple solution to connect two network namespaces is the usage of one veth pair.

 

# add the namespaces

ip netns add ns1

ip netns add ns2

# create the veth pair

ip link add tap1 type veth peer name tap2

# move the interfaces to the namespaces

ip link set tap1 netns ns1

ip link set tap2 netns ns2

# bring up the links

ip netns exec ns1 ip link set dev tap1 up

ip netns exec ns2 ip link set dev tap2 up

# now assign the ip addresses

 

 

Solution 2 : linux bridge and two veth pairs

When more than two network namespaces (or KVM or LXC instances) must be connected a switch should be used. Linux offers as one solution the well known linux bridge.

We need for this setup one switch, and two connectors. In this setup we use a linuxbridge and two veth pairs.

# add the namespaces

ip netns add ns1

ip netns add ns2

# create the switch

$BRIDGE=br-test

brctl addbr $BRIDGE

brctl stp   $BRIDGE off

ip link set dev $BRIDGE up

#

#### PORT 1

# create a port pair

ip link add tap1 type veth peer name br-tap1

# attach one side to linuxbridge

brctl addif br-test br-tap1

# attach the other side to namespace

ip link set tap1 netns ns1

# set the ports to up

ip netns exec ns1 ip link set dev tap1 up

ip link set dev br-tap1 up

#

#### PORT 2

# create a port pair

ip link add tap2 type veth peer name br-tap2

# attach one side to linuxbridge

brctl addif br-test br-tap2

# attach the other side to namespace

ip link set tap2 netns ns2

# set the ports to up

ip netns exec ns2 ip link set dev tap2 up

ip link set dev br-tap2 up

#

 

Solution 3 : openvswitch and two veth pairs

Another solution is to use the openvswitch instead of the “old” linuxbrige. The configuration is nearly the same as for the linuxbridge.

We need for this setup one switch, and two connectors. In this setup we use an openvswitch and two veth pairs.

# add the namespaces

ip netns add ns1

ip netns add ns2

# create the switch

$BRIDGE=ovs-test

ovs-vsctl add-br $BRIDGE

#

#### PORT 1

# create a port pair

ip link add tap1 type veth peer name ovs-tap1

# attach one side to ovs

ovs-vsctl add-port $BRIDGE ovs-tap1

# attach the other side to namespace

ip link set tap1 netns ns1

# set the ports to up

ip netns exec ns1 ip link set dev tap1 up

ip link set dev ovs-tap1 up

#

#### PORT 2

# create a port pair

ip link add tap2 type veth peer name ovs-tap2

# attach one side to ovs

ovs-vsctl add-port $BRIDGE ovs-tap2

# attach the other side to namespace

ip link set tap2 netns ns2

# set the ports to up

ip netns exec ns2 ip link set dev tap2 up

ip link set dev ovs-tap2 up

#

 

Solution 4 : openvswitch and two openvswitch ports

Another solution is to use the openvswitch and make use of the openvswitch internal ports. This avoids the usage of the veth pairs, which must be used in all other solutions.

We need for this setup one switch, and two connectors. In this setup we use an openvswitch and two openvswitch ports.

 

# add the namespaces

ip netns add ns1

ip netns add ns2

# create the switch

$BRIDGE=ovs-test

ovs-vsctl add-br$BRIDGE

#

#### PORT 1

# create an internal ovs port

ovs-vsctl add-port$BRIDGEtap1–set Interfacetap1 type=internal

# attach it to namespace

ip linkset tap1 netns ns1

# set the ports to up

ip netns exec ns1 ip linkset dev tap1 up

#

#### PORT 2

# create an internal ovs port

ovs-vsctl add-port$BRIDGEtap2–set Interfacetap2 type=internal

# attach it to namespace

ip linkset tap2 netns ns2

# set the ports to up

ip netns exec ns2 ip linkset dev tap2 up

 

openvswitch and two openvswitch ports

Another solution is to use the openvswitch and make use of the openvswitch internal ports. This avoids the usage of the veth pairs, which must be used in all other solutions.

We need for this setup one switch, and two connectors. In this setup we use an openvswitch and two openvswitch ports.

# add the namespaces

ip netns add ns1

ip netns add ns2

# create the switch

$BRIDGE=ovs-test

ovs-vsctl add-br $BRIDGE

#

#### PORT 1

# create an internal ovs port

ovs-vsctl add-port $BRIDGE tap1 — set Interface tap1 type=internal

# attach it to namespace

ip link set tap1 netns ns1

# set the ports to up

ip netns exec ns1 ip link set dev tap1 up

#

#### PORT 2

# create an internal ovs port

ovs-vsctl add-port $BRIDGE tap2 — set Interface tap2 type=internal

# attach it to namespace

ip link set tap2 netns ns2

# set the ports to up

ip netns exec ns2 ip link set dev tap2 up

 

Switching Performance : Connecting Linux Network Namespaces

 

The openvswitch using two internal openvswitch ports has the best throughput and the best efficiency.

So if you are using a server platform, you should avoid veth pairs and linuxbridges. They just suck CPU cycles and are doing nothing useful.

Use the openvswitch together with ovs internal ports.

Openstack

If you are running Openstack Neutron, you should use the Openvswitch. Avoid linuxbridges. When connecting the Neutron networking Router/LBaas/DHCP namespaces DO NOT enable ovs_use_veth. If you enable this, the performance impact will be huge.