0
点赞
收藏
分享

微信扫一扫

Openflow学习笔记

小贴贴纸happy 2022-01-14 阅读 14

工具:Mininet

拓扑:

一开始设想的拓扑是这样的

实验目的:

实现将fowarding路线从h1-s1-s2-h2(default)改成h1-s1-s3-h2,反过来也一样

使用mininet提供的接口写的python脚本来建立这个拓扑,这一步很简单

from mininet.topo import Topo

class MyTopo(Topo):

    def build(self):

        #Add hosts and switches
        leftHost = self.addHost('h1')
        rightHost = self.addHost('h2')
        leftSwitch = self.addSwitch('s1')
        rightSwitch1 = self.addSwitch('s2')
        rightSwitch2 = self.addSwitch('s3')

        #Add links
        self.addLink(leftHost, leftSwitch)
        self.addLink(leftSwitch, rightSwitch1)
        self.addLink(leftSwitch, rightSwitch2)
        self.addLink(rightSwitch1, rightHost)
        self.addLink(rightSwitch2, rightHost)


topos = {'mytopo':(lambda:MyTopo() ) }

sudo mn --custom FILE_PATH --topo mytopo --mac

创建topo时可选的几个实用选项,这些在mininet walkthrough里都可以找到:

--custom: 按后面FILE_PATH对应的文件里给的脚本自定义拓扑

--topo mytopo:指定使用脚本文件中的哪个topo

--mac:这个对于简化实验来说很关键,在这个实验里它把H1的eth0和H2的eth0的mac地址分别设置为了00:00:00:00:00:01和00:00:00:00:00:02(注意,h2的eth1并没有被设置为00:00:00:00:00:02或00:00:00:00:00:03)

--test pingall:可以让所有host节点互ping,看网络是不是通的

此时,h1 ping h2,是可以ping通的,但是走的path是h1-s1-s2-h2,

下面我打算把

建立完成之后使用open flow提供的ovs-vsctl手动写command line

###icmp

s1:
1.
#把h1的request消息发给h2:
sudo ovs-ofctl add-flow s1 priority=65535,icmp,in_port="s1-eth1",vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=10.0.0.1,nw_dst=10.0.0.2,nw_tos=0,icmp_type=8,icmp_code=0,actions=output:"s1-eth3"

2.
#把h2的reply消息发给h1:
sudo ovs-ofctl add-flow s1 priority=65535,icmp,in_port="s1-eth3",vlan_tci=0x0000,dl_src=00:00:00:00:00:02,dl_dst=00:00:00:00:00:01,nw_src=10.0.0.2,nw_dst=10.0.0.1,nw_tos=0,icmp_type=0,icmp_code=0,actions=output:"s1-eth1"


###arp

3.
#把h1的arp request 发给h2
sudo ovs-ofctl add-flow s1 priority=65535,arp,in_port="s1-eth1",vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,arp_spa=10.0.0.1,arp_tpa=10.0.0.2,arp_op=1,action=output:"s1-eth3"

4.
#把h1的arp reply 发给h2
sudo ovs-ofctl add-flow s1 priority=65535,arp,in_port="s1-eth1",vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,arp_spa=10.0.0.1,arp_tpa=10.0.0.2,arp_op=2,actions=output:"s1-eth3"

5.
#把h2的arp request发给h1
sudo ovs-ofctl add-flow s1 priority=65535,arp,in_port="s1-eth3",vlan_tci=0x0000,dl_src=00:00:00:00:00:02,dl_dst=00:00:00:00:00:01,arp_spa=10.0.0.2,arp_tpa=10.0.0.1,arp_op=1,actions=output:"s1-eth1"

6.
#把h2的arp reply发给h1
sudo ovs-ofctl add-flow s1 priority=65535,arp,in_port="s1-eth3",vlan_tci=0x0000,dl_src=00:00:00:00:00:02,dl_dst=00:00:00:00:00:01,arp_spa=10.0.0.2,arp_tpa=10.0.0.1,arp_op=2,actions=output:"s1-eth1"



s2:让它不接受广播

sudo ovs-ofctl add-flow s2 priority=65535,arp,in_port="s2-eth1",vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,arp_spa=10.0.0.1,arp_tpa=10.0.0.2,arp_op=1,actions=DROP

在这一步里我做了很多花里胡哨的设置,然而h1 ping h2不通了

感觉自己的逻辑没有问题,使用wireshark抓包之后发现出现了一个让人费解的问题:

h1发request确实是按照规定的h1-s1-s3-h2路线走的,可是h2收到包之后从来不发reply

h2(10.0.0.2)表现得像不认识这个包

问题的特点是:

(1)

沿h1-s1-s2-h2转发,既有request又有reply

(2)

沿h1-s1-s3-h2转发,request正常,h2不进行reply,h2不报错,只是“不认识”这个icmp reques

那么问题出在哪里呢?

(1)

h1-s1-s3-h2的路线上switch的转发是正常、open flow 在链路层的转发中不涉及改变包的目的mac地址和源mac地址(在转发过程中一直是h1的mac地址、h2的mac地址),只是重复从一个port送到另一个port的简单动作-->暂且认为不是switch上出现的问题

(2)

mininet很多人都在用、没有搜到mininet在这方面有重大bug、这是一个很简单的forwarding path实验-->暂且认为不是虚拟机的问题。

(3)

学了一下icmp协议,没有发现什么和这个问题看起来有联系的问题 -->坑应该不在icmp上

(4)

看了一下网上的类似问题,那个是checksum有问题,这边看wireshark好像并没有这方面的问题-->request一直传到h2都是正常被转发的

(5)

怀疑了一下可能是spanning Tree的问题,(或许根据spanning Tree, request包只能发给h2的eth0端口)--->师兄告诉我因为这个h2有两个网卡接入网络,所以不存在spanning Tree冲突问题

看到这里我明白了,icmp没有reply的原因是目的mac地址是00:00:00:00:00:02,这个是h2-eth0的mac,所以当包被发到h2-eth1的时候,h2不对这个icmp request做响应

到这里,我想到了两个方法解决这个问题

(1)

在s1转发流表中的action中加入mod_dl_dst="h2-eth1的mac地址",这个还没尝试,后面更新

(2)

改拓扑,在s2-h2和s3-h2中加一个s4,拓扑被改成这样:

 这时候出了一个问题,h1 ping h2不通了,我马上去检查了topo文件是不是有错,盯着这短短的几行代码,看不出任何问题,我重启了网络加入了参数--test pingall,发现真的ping不通,

不写--test pingall,仅仅是建立mininet网络,打开wireshark发现h1和h2一直在互相广播icmpv6和mdns消息,同时所有设备的所有端口都充满了一样的icmpv6和mdns消息,而在正常情况下,如果不进行任何操作,仅仅打开网络,所有设备的所有端口应该是几乎收不到任何消息的。现在的情况看起来,所有的节点一直在保持商讨某种东西,而没有能达成一个一致的结果。

为什么会这样呢,为什么不加s4的时候(上面的topo),就是正常的,加入s4之后就会发生这样的问题呢?

解释是,新的拓扑里有环路,在没写flow table时,mininet如果存在环路,则无法确定一个各个节点之间转发的路径。

而上面的3switch网络看似是有环路的,其实因为使用了h2的两个端口,是一个树形结构,因此不存在成环的问题。

所以接下来我们对switches的流表进行设置:

#topo:


          s2     
        /    \
h1 - s1        s4 - h2
        \    /
          s3 

#开启wireshark方法:xterm h1/xterm s1 打开host的shell或 switch的shell
#运行wireshark -n

#(1)所有消息都从s3转发:

sudo ovs-ofctl add-flow s1 in_port='s1-eth1',actions=output:'s1-eth3'
sudo ovs-ofctl add-flow s3 in_port='s3-eth1',actions=output:'s3-eth2'
sudo ovs-ofctl add-flow s4 in_port='s4-eth2',actions=output:'s4-eth3'
sudo ovs-ofctl add-flow s2 in_port='s2-eth1',actions=DROP
sudo ovs-ofctl add-flow s1 in_port='s1-eth2',actions=output:'s1-eth1'
sudo ovs-ofctl add-flow s3 in_port='s3-eth2',actions=output:'s3-eth1'
sudo ovs-ofctl add-flow s4 in_port='s4-eth3',actions=output:'s4-eth1'
sudo ovs-ofctl add-flow s2 in_port='s2-eth2',actions=DROP

#打开wireshark可以看到icmp request和icmp reply都是从s3转发的

#(2)h1-h2的消息从s3转发,h2-h1的消息从s2转发:



sudo ovs-ofctl add-flow s1 in_port='s1-eth1',actions=output:'s1-eth3'
sudo ovs-ofctl add-flow s3 in_port='s3-eth1',actions=output:'s3-eth2'
sudo ovs-ofctl add-flow s4 in_port='s4-eth2',actions=output:'s4-eth3'
sudo ovs-ofctl add-flow s2 in_port='s2-eth1',actions=DROP
sudo ovs-ofctl add-flow s1 in_port='s1-eth2',actions=output:'s1-eth1'
sudo ovs-ofctl add-flow s2 in_port='s2-eth2',actions=output:'s2-eth1'
sudo ovs-ofctl add-flow s4 in_port='s4-eth3',actions=output:'s4-eth1'
sudo ovs-ofctl add-flow s3 in_port='s3-eth2',actions=DROP

#打开wireshark可以看到:request的路线是h1-s1-s3-s4-h2,reply的路线是h2-s4-s2-s1-h1

到此,一个简单的通过ofctl命令添加流表的方式控制转发的实验就已经完成了,后面做完再更新通过ryu controller文件下发流表控制转发的实验。

举报

相关推荐

0 条评论