使用Linux Network NameSpace, Open vSwitch, ip link搭建虚拟网络拓扑
背景知识介绍
1. linux网络命名空间
简单来说,linux网络命名空间是linux内核实现的一种虚拟化技术,不同的网络命名空间的网络资源是互相隔离的,彼此之间互不影响,从网络角度看,一个网络命名空间就相当于一个轻量级的虚拟机,一台宿主机上的不同网络命名空间可以拥有相同的网络接口.在linux中创建网络命名空间的命令如下:
sudo ip netns add h1 #创建一个名字为h1的网络命名空间
#进入这个h1看看
sudo ip netns exec h1 bash
#查看一下网络配置信息
ifconfig -a
默认情况下,刚被创建的网络命名空间中只有一个默认down状态的网络设备lo
2. Open vSwitch
Open vSwitch是一个开源的openflow交换机软件,简称为ovs,相比物理交换机,ovs使用方便,成本低廉,可以用来组成虚拟网络。
vs-vsctl, vs-ofctl操作:
# 创建s1
ovs-vsctl add-br s1
# 查看s1的流表
ovs-ofctl ovs-ofctl -O OpenFlow13 dump-flows s1
#输出:
cookie=0x0, duration=124.089s, table=0, n_packets=130, n_bytes=8548, priority=0 actions=CONTROLLER:65535
# 给s1添加流表
ovs-ofctl -O OpenFlow13 add-flow s1 in_port=1,dl_type=0x800,priority=200,nw_src=10.0.0.1,nw_dst=100.0.0.1,actions=output:2
ovs-ofctl -O OpenFlow13 add-flow s1 in_port=2,dl_type=0x800,priority=200,nw_src=100.0.0.1,nw_dst=10.0.0.1,actions=output:1
# 给s1删除流表 (根据Match项来删除流表)
ovs-ofctl -O OpenFlow13 add-flow s1 in_port=1,dl_type=0x800,nw_src=10.0.0.1,nw_dst=100.0.0.1
#再次查看s1的流表
ovs-ofctl ovs-ofctl -O OpenFlow13 dump-flows s1
#输出:
cookie=0xa00000ec6a7509, duration=426.708s, table=0, n_packets=351, n_bytes=34398, send_flow_rem priority=200,ip,in_port="s1-eth1",nw_src=10.0.0.1,nw_dst=100.0.0.1 actions=output:"s1-eth2"
cookie=0xa00000ec6a7510, duration=426.305s, table=0, n_packets=351, n_bytes=34398, send_flow_rem priority=200,ip,in_port="s1-eth2",nw_src=100.0.0.1,nw_dst=10.0.0.1 actions=output:"s1-eth1"
cookie=0x0, duration=458.439s, table=0, n_packets=205, n_bytes=13458, priority=0 actions=CONTROLLER:65535
3. ip link
本文主要涉及到peer类型的ip link,例如现在有两个网络命名空间h1,h2,如何使得它们能互相通信?这是ip link就派上用场了,ip link不光可以用来连接网络命名空间与网络命名空间,也可以用来链接网络命名空间与ovs,ovs与ovs
搭建虚拟网络拓扑
本文搭建一个由一个openflow交换机与两个主机构成的拓扑,拓扑如下图:
过程如下:
## 1.创建网络命名空间(相当于搬来两台主机)
ip netns add h1
ip netns add h2
## 2.创建ovs (相当于搬来一台openflow交换机)
ovs-vsctl add-br s1
#设置openflow版本
ovs-vsctl set bridge s1 protocols=OpenFlow13
#设置DPID
ovs-vsctl set bridge s1 other_config:datapath-id=0000000000000001
## 3.创建ip link (相当于拿来两根网线,并且标记好网线的两端插头,这种link可以连接switch与host,也可以连接switch与switch,只要定义好两端的端口标记即可)
ip link add h1-eth0 type veth peer name s1-eth1
ip link add h2-eth0 type veth peer name s1-eth2
## 4.设置h1,h2的网络设备 (相当于把网线对应标记的插头插到主机)
ip link set h1-eth0 netns h1
ip link set h2-eth0 netns h2
## 5.给ovs添加端口 (相当于把对应标记的插头插到openflow交换机)
ovs-vsctl add-port s1 s1-eth1
ovs-vsctl add-port s1 s1-eth2
## 6.配置网络
ip netns exec h1 ifconfig h1-eth0 10.0.0.1/24 up
ip netns exec h2 ifconfig h2-eth0 10.0.0.2/24 up
ip netns exec h1 ifconfig lo up
ip netns exec h2 ifconfig lo up
至此虚拟网络就搭建起来了,不过现在h1,h2之间还无法进行通信,因为还没有下发openflow流表,如下:
ovs-ofctl -O OpenFlow13 add-flow s1 in_port=1,dl_type=0x806,arp_spa=10.0.0.1,arp_tpa=10.0.0.2,actions=output:2
ovs-ofctl -O OpenFlow13 add-flow s1 in_port=2,dl_type=0x806,arp_spa=10.0.0.2,arp_tpa=10.0.0.1,actions=output:1
ovs-ofctl -O OpenFlow13 add-flow s1 in_port=1,dl_type=0x800,nw_src=10.0.0.1,nw_dst=10.0.0.2,actions=output:2
ovs-ofctl -O OpenFlow13 add-flow s1 in_port=2,dl_type=0x800,nw_src=10.0.0.2,nw_dst=10.0.0.1,actions=output:1
至此,h1,h2之间可以互相通信了.
也可以给ovs关联SDN控制器,通过控制器进行下发openflow流表.
熟悉mininet的朋友看到这儿,应该会发现这上面的过程实际上是实现了类似mininet的功能,基本等同于sudo mn --topo=single,2.
不过本文的这种方式的优势就是更加灵活,例如如果想要搭建一个包含多个域的网络拓扑,不同的域由不同的SDN控制器控制,基于mininet的话会较难实现,而本文的方式理论上可以搭建出任意结构的网络(虽然步骤比较繁琐).