玩转Openvswitch之综合篇

勿忘初心2018-11-12 13:40

此文已由作者刘超授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验


这是一个Openvswitch的综合实例。


1. 创建一个bridge


ovs-vsctl add-br helloworld

创建四个veth pair

ip link add first_br type veth peer name first_if

ip link add second_br type veth peer name second_if

ip link add third_br type veth peer name third_if

ip link add forth_br type veth peer name forth_if

添加四个端口port,ofport_request是指定端口号

ovs-vsctl add-port helloworld first_br -- set Interface first_br ofport_request=1

ovs-vsctl add-port helloworld second_br -- set Interface second_br ofport_request=2

ovs-vsctl add-port helloworld third_br -- set Interface third_br ofport_request=3

ovs-vsctl add-port helloworld forth_br -- set Interface forth_br ofport_request=4

新添加的port都是出于DOWN的状态,设成up

ip link set first_if up

ip link set first_br up

ip link set second_br up

ip link set second_if up

ip link set third_if up

ip link set third_br up

ip link set forth_br up

ip link set forth_if up


2. 实现第一个Table 0,Admission control


包进入vswitch的时候首先进入Table 0,我们在这里可以设定规则,控制那些包可以进入,那些包不可以进入。

multicast的不允许进入

ovs-ofctl add-flow helloworld "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"

STP的也不接受

ovs-ofctl add-flow helloworld "table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"

添加最后一个flow,这个flow的priority低于default,如果上面两个不匹配,则我们进入table 1

ovs-ofctl add-flow helloworld "table=0, priority=0, actions=resubmit(,1)"


测试Table 0

不满足条件DROP

ovs-appctl ofproto/trace helloworld in_port=1,dl_dst=01:80:c2:00:00:05

满足条件RESUBMIT

ovs-appctl ofproto/trace helloworld in_port=1,dl_dst=01:80:c2:00:00:10


3. 实现第二个Table 1:VLAN Input Processing


添加一个最低优先级的DROP的规则

ovs-ofctl add-flow helloworld "table=1, priority=0, actions=drop"

对于port 1,是trunk口,无论有没有VLAN Header都接受

ovs-ofctl add-flow helloworld "table=1, priority=99, in_port=1, actions=resubmit(,2)"

对于port 2, 3, 4, 我们希望没有VLAN Tag,然后我们给打上VLAN Tag

ovs-ofctl add-flows helloworld - <<'EOF' 

table=1, priority=99, in_port=2, vlan_tci=0, actions=mod_vlan_vid:20, resubmit(,2) 

table=1, priority=99, in_port=3, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2) 

table=1, priority=99, in_port=4, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2) 

EOF


测试Table 1

从port 1进入,tag为5

ovs-appctl ofproto/trace helloworld in_port=1,vlan_tci=5

从port 2进入,没有打Tag的

ovs-appctl ofproto/trace helloworld in_port=2

从port 2进入,带Tag 5的

ovs-appctl ofproto/trace helloworld in_port=2,vlan_tci=5


4. 实现第三个Table 2: MAC, VLAN learning for ingress port


对于普通的switch,都会有这个学习的过程,当一个包到来的时候,由于包里面有MAC,VLAN Tag,以及从哪个口进来的这个信息。

于是switch学习后,维护了一个表格port –> MAC –> VLAN Tag。

这样以后如果有需要发给这个MAC的包,不用ARP,switch自然之道应该发给哪个port,应该打什么VLAN Tag。

OVS也要学习这个,并维护三个之间的mapping关系。

ovs-ofctl add-flow helloworld "table=2 actions=learn(table=10, NXM_OF_VLAN_TCI[0..11], NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]), resubmit(,3)"


  • learn表示这是一个学习的action

  • table 10,这是一个MAC learning table,学习的结果会放在这个table中。

  • NXM_OF_VLAN_TCI这个是VLAN Tag,在MAC Learning table中,每一个entry都是仅仅对某一个VLAN来说的,不同VLAN的learning table是分开的。在学习的结果的entry中,会标出这个entry是对于哪个VLAN的。

  • NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]这个的意思是当前包里面的MAC Source Address会被放在学习结果的entry里面的dl_dst里面。这是因为每个switch都是通过Ingress包来学习,某个MAC从某个port进来,switch就应该记住以后发往这个MAC的包要从这个port出去,因而MAC source address就被放在了Mac destination address里面,因为这是为发送用的。

  • NXM_OF_IN_PORT[]->NXM_NX_REG0将portf放入register.

  • 一般对于学习的entry还需要有hard_timeout,这是的每个学习结果都会expire,需要重新学习。


测试Table 2:

从port 1来一个vlan为20的mac为50:00:00:00:00:01的包

ovs-appctl ofproto/trace helloworld in_port=1,vlan_tci=20,dl_src=50:00:00:00:00:01 -generate

ovs-ofctl dump-flows helloworld

table 10多了一条,vlan为20,dl_dst为50:00:00:00:00:01,发送的时候从port 1出去

从port 2进来,被打上了vlan 20,mac为50:00:00:00:00:02

ovs-appctl ofproto/trace helloworld in_port=2,dl_src=50:00:00:00:00:02 -generate


5. 实现第四个table 3: Look Up Destination Port


在table 2中,vswtich通过进入的包,学习了vlanid –> mac –> port的映射后,对于要发送的包,可以根据学习到的table 10里面的内容,根据destination mac和vlan,来找到相应的port发送出去,而不用每次都flood。

ovs-ofctl add-flow helloworld "table=3 priority=50 actions=resubmit(,10), resubmit(,4)"

添加这条规则,首先到table 10中查找learn table entry,如果找不到则到table 4

如果包本身就是multicast的或者broadcast的,则不用去table 10里面取查找。

ovs-ofctl add-flow helloworld "table=3 priority=99 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,4)"


测试Table 3:

ovs-appctl ofproto/trace helloworld in_port=1,dl_vlan=20,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01 -generate

由于目标地址f0:00:00:00:00:01没有在table 10中找到,因而到达table 4。

但是这次测试使得table 10中学习到了mac地址90:00:00:00:00:01

ovs-appctl ofproto/trace helloworld in_port=2,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01 -generate

因为刚才学习到了mac地址f0:00:00:00:00:01,所以这次在table 10中找到了这条记录,这次同时也学习到了mac地址90:00:00:00:00:01

再发送第一次的包

ovs-appctl ofproto/trace helloworld in_port=1,dl_vlan=20,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01 -generate

也在table 10中找到了记录


6. 实现第五个table 4: Output Processing


这个时候,register 0中包含了output port,如果是0则说明是flood

对于port 1来讲,是trunk port,所以携带的vlan tag就让他带着,从port 1出去

ovs-ofctl add-flow helloworld "table=4 reg0=1 actions=1"

对于port 2来讲,是vlan 20的,然而出去的时候,vlan tag会被抹掉,从port 2发出去

对于port 3, 4来讲,是vlan 30的,然而出去的时候,vlan tag会被抹掉,从port 3, 4出去

ovs-ofctl add-flows helloworld - <<'EOF'   

        table=4 reg0=2 actions=strip_vlan,2 

        table=4 reg0=3 actions=strip_vlan,3 

        table=4 reg0=4 actions=strip_vlan,4 

EOF

对于broadcast来讲,我们希望一个vlan的broadcast仅仅在这个vlan里面发送,不影响其他的vlan

ovs-ofctl add-flows helloworld - <<'EOF'   

        table=4 reg0=0 priority=99 dl_vlan=20 actions=1,strip_vlan,2 

        table=4 reg0=0 priority=99 dl_vlan=30 actions=1,strip_vlan,3,4 

        table=4 reg0=0 priority=50 actions=1 

EOF

所以对于register = 0的,也即是broadcast的,属于vlan 20的,则从port 1, 2出去,属于vlan 30的,则从port 1, 3, 4出去。


测试Table 4

如果是一个port 1来的vlan 30的broadcast

ovs-appctl ofproto/trace helloworld in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=30

结果是port 1就不发送了,发送给了port 3, 4

ovs-appctl ofproto/trace helloworld in_port=3,dl_dst=ff:ff:ff:ff:ff:ff

接着测试mac learning

ovs-appctl ofproto/trace helloworld in_port=1,dl_vlan=30,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01 -generate

由于这两个地址没有出现过,则除了进行学习以外,广播发送给port 3,4

ovs-appctl ofproto/trace helloworld in_port=4,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:01 -generate

回复的时候,由于学习过了,则仅仅从port 1发送出去

ovs-appctl ofproto/trace helloworld in_port=1,dl_vlan=30,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01 -generate

由于在回复中进行了学习,因而发送的时候,仅仅发送port 4


11.1—11.15云计算基础服务全场5折起

免费体验云安全(易盾)内容安全、验证码等服务

更多网易技术、产品、运营经验分享请点击