1. 解决方案一[1]
1)解决环路拓扑的广播风暴
以(dpid, eth_src,arp_dst_ip)为key,记录第一个数据包的in_port,并将从网络中返回的数据包丢弃,保证同一个交换机中的某一个广播数据包只能有一个入口,从而防止成环。在此应用中默认网络中发起通信的第一个数据包都是ARP数据包,具体代码实现如下:
if eth_dst == ETHERNET_MULTICAST and ARP in header_list:
arp_dst_ip = header_list[ARP].dst_ip
if (datapath.id, eth_src, arp_dst_ip) in self.sw: # Break the loop
if self.sw[(datapath.id, eth_src, arp_dst_ip)] != in_port:
out = datapath.ofproto_parser.OFPPacketOut(
datapath=datapath,
buffer_id=datapath.ofproto.OFP_NO_BUFFER,
in_port=in_port,
actions=[], data=None)
datapath.send_msg(out)
return True
else:
self.sw[(datapath.id, eth_src, arp_dst_ip)] = in_port
2)减少网络中泛洪的ARP请求数据
解决完环路拓扑中存在的广播风暴问题之后,我们还需要利用SDN控制器可获取网络全局的信息的能力,去代理回复ARP请求,从而减少网络中泛洪的ARP请求数据。这个逻辑非常简单,和二层学习原理基本一样,也是通过自学习主机ARP记录,再通过查询记录并回复。具体代码实现如下:
if ARP in header_list:
hwtype = header_list[ARP].hwtype
proto = header_list[ARP].proto
hlen = header_list[ARP].hlen
plen = header_list[ARP].plen
opcode = header_list[ARP].opcode
arp_src_ip = header_list[ARP].src_ip
arp_dst_ip = header_list[ARP].dst_ip
actions = []
if opcode == arp.ARP_REQUEST:
if arp_dst_ip in self.arp_table: # arp reply
actions.append(datapath.ofproto_parser.OFPActionOutput(
in_port))
ARP_Reply = packet.Packet()
ARP_Reply.add_protocol(ethernet.ethernet(
ethertype=header_list[ETHERNET].ethertype,
dst=eth_src,
src=self.arp_table[arp_dst_ip]))
ARP_Reply.add_protocol(arp.arp(
opcode=arp.ARP_REPLY,
src_mac=self.arp_table[arp_dst_ip],
src_ip=arp_dst_ip,
dst_mac=eth_src,
dst_ip=arp_src_ip))
ARP_Reply.serialize()
out = datapath.ofproto_parser.OFPPacketOut(
datapath=datapath,
buffer_id=datapath.ofproto.OFP_NO_BUFFER,
in_port=datapath.ofproto.OFPP_CONTROLLER,
actions=actions, data=ARP_Reply.data)
datapath.send_msg(out)
return True
return False
参考文献
1.基于SDN的RYU应用——ARP_PROXY. http://www.muzixing.com/pages/2014/10/19/ji-yu-sdnde-ryuying-yong-arp_proxy.html.