专栏名称: SDNLAB
SDNLAB是专注网络创新技术的先锋媒体和实践平台,涵盖SDN、NFV、CCN、软件定义安全、软件定义数据中心等相关领域,提供新闻资讯、技术交流、在线实验、行业分析、求职招聘、教育培训、方案咨询、创业融资等多元服务。
目录
相关文章推荐
51好读  ›  专栏  ›  SDNLAB

OVN实战二之Overlay实现

SDNLAB  · 公众号  ·  · 2017-09-01 17:53

正文

请到「今天看啥」查看全文


邢森: Java、Python码农,运营“写程序的康德”自媒体。现就职于上海电信信息网络部任职架构师,主要负责网络相关产品的研发工作。

前言

上一章介绍了GNS3的使用以及OVN系统的架构,搭建了实验环境,阐述了OVN各个进程的用途、彼此之间的关系,以及产生的日志(OVN实战一之GNS3操作指南及OVN入门,http://www.sdnlab.com/19765.html)。本章主要介绍我们实验的拓扑结构,然后实现拓扑中的相应功能。

一、实验环境

1.1 拓扑结构


上面拓扑中有四个“虚拟机(VM)”,分别属于两个广播域(二层交换机,SW),SW1和SW2通过R1连接起来。本章先实现SW1和SW2两个网络。

为了验证实验网络的Overlay功能(VXLAN封包、解包),这里故意把VM1和VM2分配到不同的物理机上,物理上的分布如下:



VM1、VM3运行在ovn-node2上;VM2、VM4运行在ovn-node3上。


1.2 准备虚拟机

笔者的实验资源有限,所以就不通过Hypervisor来创建虚拟机而是通过Linux network namespace模拟虚拟机。

Linux network namespace是Linux从2.6.24开始提供的一种“隔离技术”,它允许一个Linux内核可以拥有多个隔离的网络空间(独立的ARP表、路由表、IP地址、接口)。通过下面命令分别在ovn-node2、ovn-node3上创建VM1和VM2:

在ovn-node2上执行创建虚拟机VM1:



1

2

3

4

5

sudo ip netns add vm1

sudo ip link add vm1 - eth0 type veth peer name veth - vm1

sudo ip link set

veth - vm1 up

sudo ip link set vm1 - eth0 netns vm1


为了便于测试此处使用固定MAC地址



1

2

3

4

5

6

7

8

9

10

11

sudo ip netns exec vm1 ip link set vm1 - eth0 addres 00 : 00 : 00 : 00 : 00 : 01

sudo ip netns exec vm1 ip link set vm1 - eth0 up

sudo ovs - vsctl add - port br - int veth - vm1

sudo ip netns add vm3

sudo ip link add vm3 - eth0 type veth peer name veth - vm3

sudo ip link set veth - vm3 up

sudo ip link set vm3 - eth0 netns vm3

sudo ip netns exec vm3 ip link set vm3 - eth0 address 00 : 00 : 00 : 00 : 00 : 03

sudo ip netns exec vm3 ip link set vm3 - eth0 up

sudo ovs - vsctl add - port br - int veth - vm3


在ovn-node3上执行创建虚拟机VM2:



1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

sudo ip netns add vm2

sudo ip link add vm2 - eth0 type veth peer name veth - vm2

sudo ip link set veth - vm2 up

sudo ip link set vm2 - eth0 netns vm2

sudo ip netns exec vm2 ifconfig vm2 - eth0 hw ether 00 : 00 : 00 : 00 : 00 : 02

sudo ip netns exec vm2 ip link set vm2 - eth0 up

sudo ovs - vsctl add - port br - int veth - vm2

sudo ip netns add vm4

sudo ip link add vm4 - eth0 type veth peer name veth - vm4

sudo ip link set veth - vm4 up

sudo ip link set vm4 - eth0 netns vm4

sudo ip netns exec vm4 ip link set vm4 - eth0 address 00 : 00 : 00 : 00 : 00 : 04

sudo ip netns exec vm4 ip link set vm4 - eth0 up

sudo ovs - vsctl add - port br - int veth - vm4


我们用VETH来模拟模拟虚拟机的网卡,这是Linux提供的一种虚拟网络设备,它通常成对出现,送到一端请求发送的数据总是从另一端以请求接受的形式出现。我们一般把VETH的一端用于连接网桥,一段放入到net namespace中作为网卡。用同样的命令上创建VM3、VM4。

1.3创建SW1搭建拓扑

OVN的所有操作都在ovn-central节点完成,当需要操作网络拓扑中的“虚拟机”的时候我们才会用到ovn-host节点。OVN提供了两个命令行工具叫ovn-sbctl、ovn-nbctl,根据名字不难想到,ovn-sbctl是用来操作SB的;ovn-nbctl是用来操作NB的。逻辑交换机、逻辑路由器是放在NB中的所以和我们经常打交道的是ovn-nbctl。

在ovn-node1上执行:



1

2

3

4

5

sudo ovn - nbctl ls - add sw1

sudo ovn - nbctl lsp - add sw1 sw1 - vm1

sudo ovn - nbctl lsp - set - addresses sw1 - vm1 "00:00:00:00:00:01 192.168.100.10"

sudo ovn - nbctl lsp - add sw1 sw1 - vm2

sudo ovn - nbctl lsp - set - addresses sw1 - vm2 "00:00:00:00:00:02 192.168.100.20"


ls-add命令用于添加逻辑交换机,lsp-add命令用于为逻辑交换机添加端口,在OVN中每个逻辑交换机都有一个唯一的命名。 lsp-set-addresses为逻辑交换机端口配置MAC地址和IP地址,这一步骤是不可省略的,OVN会根据这两个信息生成流表
上述命令通过ovn-nbctl工具在NB中添加了一个逻辑交换机、两个逻辑交换机端口;ovn-northd进程会“发现”这个改变,然后读取NB中的数据把它转换成流表写入到SB数据库中(可以通过ovn-sbctl list Logical_Flow查看相关流表)。但是此时流表并没有下发到ovn-host中,需要通过下面命令建立逻辑交换机端口和OVS端口(ovn-host上的OVS)的关联。

在ovn-node2上执行



1

sudo ovs - vsctl set Interface veth - vm1 external_ids : iface - id = sw1 - vm1

设置IP地址,必须和lsp-set-addresses 中的一致


1

sudo ip netns exec vm1 ip addr add 192.168.100.10 / 24 dev vm1 - eth0

在ovn-node3上执行


1

2

sudo ovs - vsctl set Interface veth - vm2 external_ids : iface - id = sw1 - vm2

sudo ip netns exec vm2 ip addr add 192.168.100.20 / 24 dev vm2 - eth0


二、验证结果

在node2上执行ping命令发送ICMP数据包;在GNS3中右击ovn-node2到SW1之间的链路选择“start capture”,GNS3会自动启动Wireshark抓取这段链路上的数据包。
ping命令正常执行,说明vm1和vm2之间可以互相通讯


Wireshark抓取的数据包显示,网络中传送的数据包是VxLAN封装后的Overlay数据包(VNI是1)


注意,Wireshark并没有抓到vm1和vm2之间的ARP数据包,这是OVN的一个特性叫“ARP Responder”,它的实现原理在 调试 部分说明。

2.1 调试

OVS提供了一个叫ofproto/trace的流表分析工具,用于分析数据包在流表中如何被“处理”。

在ovn-node2上执行


1

sudo ovs - appctl ofproto / trace br - int in_port = 3 , icmp , nw_src = 192.168.100.10 , nw_dst = 192.168.100.20 , dl_dst = 00 : 00 : 00 : 00 : 00 : 02 , dl_src = 00 : 00 : 00 : 00 : 00 : 01


in_port指定数据包从哪个端口进来的,可以通过 sudo ovs-ofctl dump-ports-desc br-int 查看veth-vm1对应的port编号,在我的环境中它是3。
icmp指定了数据包类型
nw_src源IP地址
nw_dst是目标IP地址
dl_src是源MAC地址
dl_dst是目标MAC地址。


完整的输出太长,这里截取最后一部分,数据包最终被设置上tun_id=1从port2中发送出去。
通过 sudo ovs-dpctl show 可以查看DataPath和Port的对应关系,port 2对应的是vxlan_sys_xxxx,它是一种特殊的ovs port用于VXLAN的封包。




下面看一下ARP数据包是如何处理的

ovn-node2上执行


1

sudo ovs - appctl ofproto / trace br - int in_port = 3 , arp , arp_tpa = 192.168.100.20 , arp_op = 1 , dl_src = 00 : 00 : 00 : 00 : 00 : 01


arp_tpa是目标IP地址
arp_op是ARP数据包类型,1表示request数据包,2表示reply数据包


ARP数据并没有被发送到到ovn-node3而直接在ovn-node2就终结了,流表自动构造了一个ARP Reply数据包回送到来源端口,这个特性就叫ARP Responder。


创建SW2

SW2的创建过程和SW1很像,此处直接罗列命令:

在ovn-node1上执行


1

2

3

4

5

sudo ovn - nbctl ls - add sw2

sudo ovn - nbctl lsp - add sw2 sw2 - vm3

sudo ovn - nbctl lsp - set - addresses sw2 - vm3 "00:00:00:00:00:03 192.168.200.30"

sudo ovn - nbctl lsp - add sw2 sw2 - vm4

sudo ovn - nbctl lsp - set - addresses sw2 - vm4 "00:00:00:00:00:04 192.168.200.40"

在ovn-node2上执行


1

2

sudo ovs - vsctl set Interface veth - vm3 external_ids : iface - id = sw2 - vm3

sudo ip netns exec vm3 ip addr add 192.168.200.30 / 24 dev vm3 - eth0

在ovn-node3上执行


1

2

sudo ovs - vsctl set Interface veth - vm4 external_ids : iface - id = sw2 - vm4

sudo ip netns exec vm4 ip addr add 192.168.200.40 / 24 dev vm4 - eth0


验证WWW服务

这组环境用于验证TCP服务是否能正常工作,笔者在vm4上启动一个WWW服务,在vm3上通过curl访问。

在ovn-node3上执行


1

sudo ip netns exec vm4 python - m SimpleHTTPServer 8080

在ovn-node2上执行


1

sudo ip netns exec vm3 curl http : //192.168.200.40:8080


执行结果如下图所示,说明WWW服务正常工作


创建R1

在ovn-node1上执行


1

sudo ovn - nbctl lr - add r1

此处的IP地址相当于路由表,输入格式是CIRD


1

2

3

4

5

6

7

8

9

10

11

sudo ovn - nbctl lrp - add r1 r1 - sw1 00 : 00 : 00 : 00 : 10 : 00 192.168.100.1 / 24

sudo ovn - nbctl lsp - add sw1 sw1 - r1

sudo ovn - nbctl lsp - set - type sw1 - r1 router

sudo ovn - nbctl lsp - set - addresses sw1 - r1 00 : 00 : 00 : 00 : 10 : 00

sudo ovn - nbctl lsp - set - options sw1 - r1 router - port = r1 - sw1

sudo ovn - nbctl lrp - add r1 r1 - sw2 00 : 00 : 00 : 00 : 20 : 00 192.168.200.1 / 24

sudo ovn - nbctl lsp - add sw2 sw2 - r1

sudo ovn - nbctl lsp - set - type sw2 - r1 router

sudo ovn - nbctl lsp - set - addresses sw2 - r1 00 : 00 : 00 : 00 : 20 : 00

sudo ovn - nbctl lsp - set - options sw2 - r1 router - port = r1 - sw2


由于Linux namespace没有默认网关,所以需要为vm1、vm2、vm3、vm4配置默认网关

ovn-node2


1

2

sudo ip netns exec vm1 ip route add default via 192.168.100.1

sudo ip netns exec vm3 ip route add default via 192.168.200.1

ovn-node3


1

2

sudo ip netns exec vm2 ip route add default via 192.168.100.1

sudo ip netns exec vm4 ip route add default via 192.168.200.1


通过vm1访问vm4的WWW服务,说明R1已经生效。


参考资料

OVS每个字段的说明,流表的语法规则 http://openvswitch.org/support/dist-docs/ovs-ofctl.8.html
NB数据库结构 http://openvswitch.org/support/dist-docs/ovn-nb.5.html
SB数据库结构 http://openvswitch.org/support/dist-docs/ovn-sb.5.html








请到「今天看啥」查看全文