作者简介:徐小冰:毕业于河北大学,主要从事嵌入式软件开发,虚拟化,SDN。目前基于ODL和Open vSwitch进行二次开发,希望与广大网友一起探讨学习。作者系OpenDaylihgt群(194240432)资深活跃用户,@IT难人
虽然在去年研究过OpenvSwitch(ovs)源码,但是真正玩ovs还是最近这两个多月。为了记录学习历程(呕心沥血),为了后者少陷入深坑(无底洞),特地总结一下。本篇主要是介绍以下两个方向:跨子网流表和vlan操作。
一、跨子网流表
虽然网络上有很多关于如何下发流表,如何把多个主机互联的文章,但是关于跨子网多主机互联的场景,却是凤毛菱角啊,我们要玩就模拟真实网络,对于简单网络没有任何意义。
在研究跨子网应该如何下发流表,这边博客受益匪浅http://hwchiu.logdown.com/posts/203260-mininet-and-network-subnet (台湾同胞),下面进入正题
网络topo环境
1)以上环境均在一台机器上,这台机器有多个物理网卡。
2)两个虚拟机交换机:brA和brB
Mac地址自动生成,ip地址手动配上。为什么要给他们配上ip地址呢?虚拟交换机作为三层转发工能,换句话说就是交换机当网关路由器用。
3)四台kvm虚拟机:a1,a2,b1,b2
网上有很多例子都是基于mininet,这种组网虽然很方便,但也有很多缺陷和不足,所以一开始定位就是要搞真实网络环境。虚拟机ip地址、mac地址手动配置好。
4)交换机互联
使用其中两个网卡:em3、em4,分别加入到brA,brB中,并且将em3和em4用网线连接。如果没有多余网卡,可以采用patch方式连接,可以参考:http://blog.csdn.net/qiqishuang/article/details/51546673
1、创建topo
下面是操作命令行:
1)创建网桥
1 2 |
ovs-vsctl add-br brA ovs-vsctl add-br brB |
2)将物理网卡em3 em4 托管到网桥中
1 2 |
ovs-vsctl add-port brA em3 ovs-vsctl add-port brB em4 |
3)网桥设置ip地址
1 2 |
ifconfig brA 172.63.10.1/24 ifconfig brB 172.63.20.1/24 |
2、下发流表(命令行)
在下发流表之前,需要先启动虚拟机,按照如下顺序启动:a1,a2,b1,b2。启动完成后,查看网桥brA信息,为什么要查看端口编号呢?下发流表的时候需要使用到。
这个实验中,我们只用命令行,不连接控制器,原因有2个:
- 连接控制器后,控制器会下发一些默认流表,可能会影响到我们实验过程。
- 由于流表项内容比多,通过控制器下发流表比较麻烦。
ovs有两种工作模式:standalone和secure
standalone(默认):
在三次探测控制器连接不成功后,此时ovs-vswitchd将会接管转发逻辑(后台仍然尝试连接到控制器,一旦连接则退出fail状态),OpenvSwitch将作为一个正常的mac 学习的二层交换机。
secure:ovs-vswitchd将不会自动配置新的转发流表,OpenvSwitch将按照原先有的流表转发。
因此需要设置ovs模式为secure,这样能保证ovs完全按照我们自己下发的流表规则进行转发,不会有其他的干扰。
以上流程如果正确的话,查看流表信息,应该是这样的(流表空):
1 2 3 4 |
[root@localhost ~]# [root@localhost ~]# ovs-ofctl dump-flows brA NXST_FLOW reply (xid=0x4): [root@localhost ~]# |
I:打通同一子网
通过vnc登录虚拟机a1,然后ping a2,会发现无法ping通,如下图:
我们开始配置流表:
这个时候我在ping a2,仍发现无法ping通。原因是:需要处理arp请求。
配置完arp流表项,此时在去ping a2 发现可以通了!!
对于网桥brB下发类似,请自行参考。
II:打通跨子网
对于同一个网络,下发的流表比较简单,跨子网就比较麻烦了,需要打通两个网桥之间路由转发(对于码农的我,不了解网络,陷入这个坑很长一段时间)。
若实现跨子网通信(a1和b1),必须存在网关和路由才行。针对在我们的模拟环境根本没有网关,因此需给brA,brB设置两个ip地址,让对应的vm虚拟机把br当做网关,这就是为什么在文章开始的时候给brA,brB设置IP的原因。
我们需要把vm和br之间的路由打通,因此需要进行如下配置:
我们需要把vm和br之间的路由打通,因此需要进行如下配置:
对于brB流表配置类似,请自行尝试。我们现在将a1和b1打通网络,下发如下命令:
brA增加流表:
brB增加流表:
下面是ping结果:
对于a1和b2,a2和b2之间流表使类似的,可以自行尝试。
为了方便测试,下面是流表最终内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
[root@localhost ~]# [root@localhost ~]# ovs-ofctl dump-flows brA NXST_FLOW reply (xid=0x4): cookie=0x0, duration=83674.085s, table=0, n_packets=11, n_bytes=1078, idle_age=4815, hard_age=65534, ip,nw_dst=172.63.10.18 actions=mod_dl_dst:00:16:3e:64:a2:00,output:3 cookie=0x0, duration=83663.878s, table=0, n_packets=48, n_bytes=4704, idle_age=59, hard_age=65534, ip,nw_dst=172.63.10.15 actions=mod_dl_dst:00:16:3e:64:a1:00,output:2 cookie=0x0, duration=83503.296s, table=0, n_packets=4, n_bytes=168, idle_age=4811, hard_age=65534, priority=100,arp,arp_tpa=172.63.10.18 actions=output:3 cookie=0x0, duration=13450.367s, table=0, n_packets=5, n_bytes=490, idle_age=4917, priority=200,ip,nw_dst=172.63.10.1 actions=NORMAL cookie=0x0, duration=4935.186s, table=0, n_packets=13, n_bytes=546, idle_age=61, priority=65535,arp,arp_tpa=172.63.10.1 actions=LOCAL cookie=0x0, duration=4639.048s, table=0, n_packets=1365, n_bytes=57618, idle_age=192, priority=100,arp,arp_tpa=172.63.20.1 actions=mod_dl_src:b8:2a:72:d9:4d:d5,output:1 cookie=0x0, duration=724.183s, table=0, n_packets=5, n_bytes=264, idle_age=61, priority=100,arp,arp_tpa=172.63.10.15 actions=output:2 cookie=0x0, duration=376.285s, table=0, n_packets=3, n_bytes=126, idle_age=152, arp,arp_tpa=172.63.20.15 actions=mod_dl_src:b8:2a:72:d9:4d:d5,output:1 cookie=0x0, duration=363.815s, table=0, n_packets=16, n_bytes=1568, idle_age=59, ip,nw_dst=172.63.20.0/24 actions=mod_dl_src:b8:2a:72:d9:4d:d5,mod_dl_dst:b8:2a:72:d9:4d:d7,dec_ttl,output:1 [root@localhost ~]# [root@localhost ~]# [root@localhost ~]# [root@localhost ~]# ovs-ofctl dump-flows brB NXST_FLOW reply (xid=0x4): cookie=0x0, duration=12855.939s, table=0, n_packets=10, n_bytes=980, idle_age=2012, priority=200,ip,nw_dst=172.63.20.1 actions=NORMAL cookie=0x0, duration=12706.924s, table=0, n_packets=448, n_bytes=24378, idle_age=154, priority=100,arp,arp_tpa=172.63.20.15 actions=output:2 cookie=0x0, duration=12692.659s, table=0, n_packets=5, n_bytes=210, idle_age=12499, priority=100,arp,arp_tpa=172.63.20.18 actions=output:3 cookie=0x0, duration=12652.033s, table=0, n_packets=4, n_bytes=392, idle_age=12411, ip,nw_dst=172.63.20.18 actions=mod_dl_dst:00:16:3e:64:b2:00,output:3 cookie=0x0, duration=12640.223s, table=0, n_packets=373, n_bytes=36554, idle_age=61, ip,nw_dst=172.63.20.15 actions=mod_dl_dst:00:16:3e:64:b1:00,output:2 cookie=0x0, duration=3654.809s, table=0, n_packets=428, n_bytes=25392, idle_age=194, priority=65535,arp,arp_tpa=172.63.20.1 actions=NORMAL cookie=0x0, duration=218.411s, table=0, n_packets=3, n_bytes=126, idle_age=154, priority=1,arp,arp_tpa=172.63.10.15 actions=output:1,mod_dl_src:b8:2a:72:d9:4d:d7 cookie=0x0, duration=205.288s, table=0, n_packets=16, n_bytes=1568, idle_age=61, ip,nw_dst=172.63.10.15 actions=output:1,mod_dl_src:b8:2a:72:d9:4d:d7 [root@localhost ~]# [root@localhost ~]# |
【遗留问题--需要网友帮忙支持】
虽然a1可以ping通b1,但是a1 不能ping通brB,即使我增加了对应流表处理
brA:增加的处理:
1 |
cookie=0x0, duration=4823.583s, table=0, n_packets=1365, n_bytes=57618, idle_age=377, priority=100,arp,arp_tpa=172.63.20.1 actions=mod_dl_src:b8:2a:72:d9:4d:d5,output:1 |
brB增加的处理:
1 |
cookie=0x0, duration=3923.683s, table=0, n_packets=430, n_bytes=25512, idle_age=51, priority=65535,arp,arp_tpa=172.63.20.1 actions=NORMAL |
通过抓em4网卡数据报文,arp reply没有回:
如果有哪位朋友知道如何解决,请帮忙支招,不胜感激!!
二、Vlan操作
接下来研究一下vlan,vlan的拓扑图和上面类似:
组网介绍:
1)brA,brB不在拥有ip地址。
2)通过ovs命令行,将em3,em4设置trunk,vlan取值为10和20
3)通过ovs命令行,让brA,brB连接控制器,控制器采用floodlight(odl太复杂,太臃肿)。
一切环境都弄好之后,连接控制器,然后a1 ping b1,发现是可以ping通,此时候查看流表:
但是会发现第一个包响应时间很长,这是为什么呢?查看流表得知:
从图中可知有一个默认流表项,默认是把不识别的报文转发给控制器,当我们用h1 ping h3的时候会发现,流表项多了几条:
为了保证不影响测试,避免控制器自动下发流表,将默认流表项删除掉:
1 2 |
[root@localhost ~]# ovs-ofctl del-flows brA [root@localhost ~]# ovs-ofctl del-flows brB |
通过控制器下发流表,最终显示结果如下,发现有802.1Q头:
对于h2和h4的流表配置,可参考下面流表内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# set vlan flow_vlan_tag_1 = { "switch":"00:00:b8:2a:72:d9:4d:d5", "name":"brA-flow-vlan-tag-1", "cookie":"0", "priority":"200", "eth_type":"0x0800", "in_port":"2", "eth_dst":"00:16:3e:64:b1:00", "ipv4_dst":"172.63.10.16", "active":"true", "actions":"push_vlan=0x8100,set_field=eth_vlan_vid->10,output=normal" } flow_vlan_tag_2 = { "switch":"00:00:b8:2a:72:d9:4d:d5", "name":"brA-flow-vlan-tag-2", "cookie":"0", "priority":"200", "eth_type":"0x0800", "in_port":"1", "eth_vlan_vid":"4106", "eth_dst":"00:16:3e:64:a1:00", "ipv4_dst":"172.63.10.15", "active":"true", "instruction_apply_actions":"pop_vlan,output=2" } flow_vlan_tag_3 = { "switch":"00:00:b8:2a:72:d9:4d:d5", "name":"brA-flow-vlan-tag-3", "cookie":"0", "priority":"200", "eth_type":"0x0800", "in_port":"3", "eth_dst":"00:16:3e:64:b2:00", "ipv4_dst":"172.63.10.17", "active":"true", "actions":"push_vlan=0x8100,set_field=eth_vlan_vid->20,output=normal" } flow_vlan_tag_4 = { "switch":"00:00:b8:2a:72:d9:4d:d5", "name":"brA-flow-vlan-tag-4", "cookie":"0", "priority":"200", "eth_type":"0x0800", "in_port":"1", "eth_vlan_vid":"4116", "eth_dst":"00:16:3e:64:a2:00", "ipv4_dst":"172.63.10.18", "active":"true", "instruction_apply_actions":"pop_vlan,output=3" } pusher.set(flow_vlan_tag_1) pusher.set(flow_vlan_tag_2) pusher.set(flow_vlan_tag_3) pusher.set(flow_vlan_tag_4) #set arp flow_arp_1 = { "switch":"00:00:b8:2a:72:d9:4d:d5", "name":"brA-flow-arp-1", "cookie":"0", "priority":"200", "eth_type":"0x0806", "in_port":"2", "arp_tpa":"172.63.10.16", "active":"true", "instruction_apply_actions":"output=1" } flow_arp_2 = { "switch":"00:00:b8:2a:72:d9:4d:d5", "name":"brA-flow-arp-2", "cookie":"0", "priority":"200", "eth_type":"0x0806", "in_port":"1", "arp_tpa":"172.63.10.15", "eth_dst":"00:16:3e:64:a1:00", "active":"true", "instruction_apply_actions":"output=2" } pusher.set(flow_arp_1) pusher.set(flow_arp_2) #pusher.remove("aa",flow_arp_1) #pusher.remove("aa",flow_arp_2) flow_vlan_del = { "switch":"00:00:b8:2a:72:d9:4d:d5", "name":"brA-flow-vlan-tag-2", "cookie":"0", "priority":"200", "eth_type":"0x0800" } flow_vlan_del_2 = { "switch":"00:00:b8:2a:72:d9:4d:d5", "name":"brA-flow-vlan-tag-1", } #pusher.remove("aa",flow_vlan_del) #pusher.remove("aa",flow_vlan_del_2) |
【大坑】
例如flow_vlan_tag_3,流表项中set_field=eth_vlan_vid->20,这个地方20,就是vlan值,是不包含第13bit的有效标志位。
例如flow_vlan_tag_4,match域中"eth_vlan_vid":"4116",这个4116是包含第13bit的有效标志位
例如flow_vlan_tag_4,如果想增加pop_vlan这个操作必须,在match域中有eth_vlan_vid和eth_type两个,并且这两个参数要设置对,否则ovs会报错的!!
验证vlan trunk功能:
通过ovs命令行将em3,em4的trunk范围改成100,20,然后h1 ping h3是无法ping通的!!此处不再展示演示结果
三、感谢网友
由于本人不是网工,不是很了解网络,因此在研究二层转发、三层路由的时候很费劲,再此期间,感谢广东-Jino(QQ群),星月-我们最终毕业(QQ群),张东亚(微信群)以及其他帮助我的网友。希望这篇文章能够帮助更多的人。