通过控制器的逻辑解决ARP包的洪泛问题
通过Ryu的API可以发现全局的拓扑信息,将交换机的端⼝信息记录下来,当控制器收到⼀个未学习的Arp Request时,直接发给所有交换机连接主机的那些端⼝。
重写 ryu.controller.handler.set_ev_cls(ev_cls, dispatchers=None) 的内建类,官网对第二个参数的解释是 dispatchers argument specifies one of the following negotiation phases (or a list of them) for which events should be generated for this handler.
参考官网 stp 的实现。
learn a mac address to avoid FLOOD next time.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# @set_ev_cls(stplib.EventPacketIn, MAIN_DISPATCHER)
# dpid = ev.msg.datapath.id
# dst = ryu.lib.packet.Packet(msg.data).get_protocols(ethernet.ethernet)[0]
self.mac_to_port[dpid][src] = in_port
if dst in self.mac_to_port[dpid]:
out_port = self.mac_to_port[dpid][dst]
else:
out_port = ofproto.OFPP_FLOOD
actions = [parser.OFPActionOutput(out_port)]
|
install a flow to avoid packet_in next time
1
2
3
4
5
6
7
8
9
10
11
|
if out_port != ofproto.OFPP_FLOOD:
match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
self.add_flow(datapath, 1, match, actions)
data = None
if msg.buffer_id == ofproto.OFP_NO_BUFFER:
data = msg.data
out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
in_port=in_port, actions=actions, data=data)
datapath.send_msg(out)
|
得到

根据讲义,前面两个包不到是因为沉默主机的原因,Ryu 还在学习,为正常现象。
参考 networkx 使用教程,使用最短路径算法
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
|
@set_ev_cls(event.EventSwitchEnter,[CONFIG_DISPATCHER,MAIN_DISPATCHER])
def get_topology(self,ev):
#store nodes info into the Graph
switch_list = get_switch(self.topology_api_app,None)
switches = [switch.dp.id for switch in switch_list]
self.network.add_nodes_from(switches)
link_list = get_link(self.topology_api_app,None)
links = [(link.src.dpid,link.dst.dpid,{'attr_dict':{'port':link.dst.port_no}}) for link in link_list]
self.network.add_edges_from(links)
links = [(link.dst.dpid,link.src.dpid,{'attr_dict':{'port':link.dst.port_no}}) for link in link_list]
self.network.add_edges_from(links)
def get_out_port(self,datapath,src,dst,in_port):
dpid = datapath.id
if src not in self.network:
self.network.add_node(src)
self.network.add_edge(dpid, src, attr_dict={'port':in_port})
self.network.add_edge(src, dpid)
self.paths.setdefault(src, {})
if dst in self.network:
if dst not in self.paths[src]:
path = nx.shortest_path(self.network,src,dst)
self.paths[src][dst]=path
path = self.paths[src][dst]
next_hop = path[path.index(dpid)+1]
out_port = self.network[dpid][next_hop]['attr_dict']['port']
print(path)
else:
out_port = datapath.ofproto.OFPP_FLOOD
return out_port
|
pingall 结果仍然一样,查看 UCLA 对应控制器的流表
1
|
sudo ovs-ofctl dump-flows s20
|
随着主机间的不断 ping,可以发现所有的流表都在不断增长,最终,s20 稳定在

s25(MIT 对应的控制器)稳定在


输出

Author
magictomagic
LastMod
2020-04-25
License
Creative Commons Attribution-ShareAlike License