实验结论:想不懂的东西就当它是玄学,要相信玄学
实验拓扑:
一开始在Cloudlab上建立的拓扑是这样婶儿的:
在cloudlab里其实这三个是三个完全一样的虚拟机,只不过我给他们起了不一样的名字,中间的叫switch,左右两边分别是两个host: h1,h2,他们仨的子网掩码都是255.255.255.0,换言之,h1和switch_eth1处于1.0子网,h2和switch_eth2处于2.0子网,h1和h2互相ping通需要switch给他们当网关,这里,switch充当一个router的作用。
在这里回忆一下ping(icmp)的过程,当前还没对拓扑进行任何ovs相关设置,根据对计算机网络知识回忆,我们知道,h1 ping h2 时,会有以下几个阶段:
(1)h1已知自己是10.10.1.1/24,它发现10.10.2.2不在自己的网段中,
| (a)一种可能是它不知道到2.0的网关是什么,于是它发送arp到ff:ff:ff:ff:ff:ff(广播),arp_tpa是10.10.2.2,以此来寻找到2.0网络的网关 |
| (b)另一种可能是它知道自己到2.0的网关是10.10.1.2(route table),和10.10.1.2的mac地址(arp table),此时它会直接发icmp request到10.10.1.2 |
| (c)还有一种可能是它知道到2.0的网关是10.10.1.2,但它不知道10.10.1.2的mac,此时它发送arp到ff:ff:ff:ff:ff:ff寻找10.10.1.2的mac |
#route -n 查看路由表, route -add 添加路由,route -del 删除路由...
#arp -n 查看arp表...
(2)arp的部分结束后,h1发送icmp request到10.10.1.2,此时,这个packet的source mac是h1-eth1的mac地址,destination mac是switch-eth1的mac地址
(3)switch节点作为router,从switch-eth1接收该packet,把packet的source mac换成switch-eth2的mac,把packet的destination mac换成h2-eth1(10.10.2.2)的mac,再把包从switch-eth2发出去
(4)h2从h2-eth1收到icmp request packet,检查一下感觉没有问题,从h2-eth1发送icmp reply到switch-eth2,此时src mac是h2-eth1的mac,dst mac是switch-eth2的mac
(5)switch从switch-eth2接收到icmp reply packet,把src mac换成 switch-eth1的mac,把dst mac 换成h1-eth1的mac,然后把该reply packet从switch-eth1发出去
(6)h1从h1-eth1收到reply,一次ping完成。
复习完了icmp,我们看一下怎么把中间的Switch节点真正作为openvSwitch来使用吧:
(1)首先在Switch上安装ovs(软件方式在虚拟机上搭建ovs)
(2)创建一个bridge:
sudo ovs-vsctl add-br br0
(3)把Switch节点的两个网卡eth1和eth2绑定到br0:
sudo ovs-vsctl add-port br0 eth1 sudo ovs-vsctl add-port br0 eth2
到这一步,h1 ping不通h2了,真是恭喜我自己呢!!
看了网上的资料,大概知道,物理网卡被绑到ovs里时,会失去原来的网络层属性,即失去自己的网络层ip地址,因此h1和h2都找不到自己的网关了(本来分别为switch-eth1和switch-eth2),自然ping不通。
看了网上的其他一些资料,大概知道下面的魔法可以解决这个问题:
(魔法:做了会对,但不知道为什么的方法)
(4)添加两个internal port给 br0:
sudo ovs-vsctl add-port br0 vp1 -- set Interface vp1 type=internal sudo ovs-vsctl add-port br0 vp2 -- set Interface vp2 type=internal
(5)把eth1的ip:10.10.1.2送给vp1,把eth2的ip:10.10.2.1送给vp2, 同时eth1和eth2功成身退,彻底退位为链路层端口(通过把ip置为0.0.0.0)
sudo ifconfig vp1 10.10.1.2 sudo ifconfig vp2 10.10.2.1 sudo ifconfig eth1 0.0.0.0 sudo ifconfig eth2 0.0.0.0
搭完OVS基础设施后的拓扑长这样:
到这里,虽然我们还没对流表进行任何设置但是因为ovs自带了一个actions=Normal的流表表项,因此我们,又能ping通了,h1 ping h2时所有流都从Normal这一项走。
Normal代表传统的链路、网络层转发方式,如果删掉Normal这一项之后会table-miss,h1不再能ping通h2,在这里不再多加叙述。
下面添加流表项,上面的Normal的优先级=0,是最低的优先级,添加的流表项的优先级大于0时就可以匹配到了。
sudo ovs-ofctl add-flow br0 in_port=eth1,icmp,nw_src=10.10.1.1,nw_dst=10.10.2.2,priority=65535,actions=mod_dl_src:5a:c7:06:f9:5a:e2,mod_dl_dst:02:80:83:31:22:2c,output:eth2 sudo ovs-ofctl add-flow br0 in_port=eth2,icmp,nw_src=10.10.2.2,nw_dst=10.10.1.1,priority=65535,actions=mod_dl_src:46:3e:2f:98:fd:a7,mod_dl_dst:02:d7:85:c3:d6:81,output:eth1
上面两句分别代表
从eth1传来的源ip为h1,目的ip为h2的icmp packet,修改源mac为vp2的mac,目的mac为h2的mac,并把它发送到eth2端口
从eth2端口传来的源ip为h2,目的ip为h1的icmp packet,修改源mac为vp1的mac,目的mac为h1的mac,并把它发送到eth1端口
#注意流表match匹配或者actions里设置的mac一定是internal port vp1/vp2的mac,这是在这个环境下,所有节点都需要通过网络层ip协议通信,因为ip地址挂载在vp1、vp2上,vp1,vp2的mac地址是网络层可见的mac,即网络里其他节点可见的mac,vp1和vp2对应的ip-mac配对会被记录在h1、h2的arp table里,而eth1、eth2的mac不会被感知。
#但是实际上data frame(packet在链路层的叫法),链路层数据报是通过eth1、eth2发送的,所以match里的in_port和actions里的output只能写eth1/eth2而不能写vp1/vp2。
后面再用h1 ping h2发现是可以被ping通的,使用ovs-ofctl dump-flows br0可以看到icmp packet们是通过新加的两条流表项走的。
#实际实验时switch的vp1/vp2、eth1/eth2的命名和上面写的是反的(eth1是eth2,vp1是vp2,eth2是eth1,vp2是vp1),为了方便理解记忆前面没按真实命名写。。。



