[root@kunpeng82 demo1]# cat group.py from mininet.topo import Topo class MininetTopo(Topo): def __init__(self,**opts): Topo.__init__(self, **opts) host1 = self.addHost('h1') host2 = self.addHost('h2') host3 = self.addHost('h3') host4 = self.addHost('h4') self.switch = {} for s in range(1,5): self.switch[s-1] = self.addSwitch('s%s' %(s)) self.addLink(self.switch[0], self.switch[1]) self.addLink(self.switch[0], self.switch[2]) self.addLink(self.switch[0], self.switch[3]) #Adding host self.addLink(self.switch[0], host1) self.addLink(self.switch[1], host2) self.addLink(self.switch[2], host3) self.addLink(self.switch[3], host4) topos = {'group':(lambda:MininetTopo())} [root@kunpeng82 demo1]#
[root@kunpeng82 demo1]# mn --custom group.py --topo group *** Creating network *** Adding controller *** Adding hosts: h1 h2 h3 h4 *** Adding switches: s1 s2 s3 s4 *** Adding links: (s1, h1) (s1, s2) (s1, s3) (s1, s4) (s2, h2) (s3, h3) (s4, h4) *** Configuring hosts h1 h2 h3 h4 *** Starting controller c0 *** Starting 4 switches s1 s2 s3 s4 ... *** Starting CLI: mininet> h1 ping h2 PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data. 64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=134 ms 64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.434 ms 64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.053 ms ^C --- 10.0.0.2 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2026ms rtt min/avg/max/mdev = 0.053/45.037/134.626/63.349 ms mininet> h1 ping -c 3 h3 PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data. 64 bytes from 10.0.0.3: icmp_seq=1 ttl=64 time=137 ms 64 bytes from 10.0.0.3: icmp_seq=2 ttl=64 time=0.371 ms 64 bytes from 10.0.0.3: icmp_seq=3 ttl=64 time=0.032 ms --- 10.0.0.3 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2034ms rtt min/avg/max/mdev = 0.032/45.905/137.312/64.634 ms mininet> Interrupt mininet> h1 ping -c 3 h4 PING 10.0.0.4 (10.0.0.4) 56(84) bytes of data. 64 bytes from 10.0.0.4: icmp_seq=1 ttl=64 time=133 ms 64 bytes from 10.0.0.4: icmp_seq=2 ttl=64 time=0.458 ms 64 bytes from 10.0.0.4: icmp_seq=3 ttl=64 time=0.040 ms --- 10.0.0.4 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2070ms rtt min/avg/max/mdev = 0.040/44.570/133.212/62.679 ms mininet>
[root@kunpeng82 demo1]# ovs-ofctl dump-flows s1 cookie=0x0, duration=54.568s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s1-eth1",vlan_tci=0x0000,dl_src=62:ca:42:08:6d:78,dl_dst=c2:9d:dc:1d:d4:93,arp_spa=10.0.0.2,arp_tpa=10.0.0.1,arp_op=2 actions=output:"s1-eth4" cookie=0x0, duration=49.511s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s1-eth1",vlan_tci=0x0000,dl_src=62:ca:42:08:6d:78,dl_dst=c2:9d:dc:1d:d4:93,arp_spa=10.0.0.2,arp_tpa=10.0.0.1,arp_op=1 actions=output:"s1-eth4" cookie=0x0, duration=49.497s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s1-eth4",vlan_tci=0x0000,dl_src=c2:9d:dc:1d:d4:93,dl_dst=62:ca:42:08:6d:78,arp_spa=10.0.0.1,arp_tpa=10.0.0.2,arp_op=2 actions=output:"s1-eth1" cookie=0x0, duration=40.001s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s1-eth2",vlan_tci=0x0000,dl_src=f2:5e:27:69:32:00,dl_dst=c2:9d:dc:1d:d4:93,arp_spa=10.0.0.3,arp_tpa=10.0.0.1,arp_op=2 actions=output:"s1-eth4" cookie=0x0, duration=34.858s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s1-eth2",vlan_tci=0x0000,dl_src=f2:5e:27:69:32:00,dl_dst=c2:9d:dc:1d:d4:93,arp_spa=10.0.0.3,arp_tpa=10.0.0.1,arp_op=1 actions=output:"s1-eth4" cookie=0x0, duration=34.844s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s1-eth4",vlan_tci=0x0000,dl_src=c2:9d:dc:1d:d4:93,dl_dst=f2:5e:27:69:32:00,arp_spa=10.0.0.1,arp_tpa=10.0.0.3,arp_op=2 actions=output:"s1-eth2" cookie=0x0, duration=54.555s, table=0, n_packets=2, n_bytes=196, idle_timeout=60, priority=65535,icmp,in_port="s1-eth4",vlan_tci=0x0000,dl_src=c2:9d:dc:1d:d4:93,dl_dst=62:ca:42:08:6d:78,nw_src=10.0.0.1,nw_dst=10.0.0.2,nw_tos=0,icmp_type=8,icmp_code=0 actions=output:"s1-eth1" cookie=0x0, duration=54.514s, table=0, n_packets=2, n_bytes=196, idle_timeout=60, priority=65535,icmp,in_port="s1-eth1",vlan_tci=0x0000,dl_src=62:ca:42:08:6d:78,dl_dst=c2:9d:dc:1d:d4:93,nw_src=10.0.0.2,nw_dst=10.0.0.1,nw_tos=0,icmp_type=0,icmp_code=0 actions=output:"s1-eth4" cookie=0x0, duration=39.987s, table=0, n_packets=2, n_bytes=196, idle_timeout=60, priority=65535,icmp,in_port="s1-eth4",vlan_tci=0x0000,dl_src=c2:9d:dc:1d:d4:93,dl_dst=f2:5e:27:69:32:00,nw_src=10.0.0.1,nw_dst=10.0.0.3,nw_tos=0,icmp_type=8,icmp_code=0 actions=output:"s1-eth2" cookie=0x0, duration=39.946s, table=0, n_packets=2, n_bytes=196, idle_timeout=60, priority=65535,icmp,in_port="s1-eth2",vlan_tci=0x0000,dl_src=f2:5e:27:69:32:00,dl_dst=c2:9d:dc:1d:d4:93,nw_src=10.0.0.3,nw_dst=10.0.0.1,nw_tos=0,icmp_type=0,icmp_code=0 actions=output:"s1-eth4" [root@kunpeng82 demo1]# ovs-ofctl dump-flows s2 cookie=0x0, duration=59.597s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s2-eth2",vlan_tci=0x0000,dl_src=62:ca:42:08:6d:78,dl_dst=c2:9d:dc:1d:d4:93,arp_spa=10.0.0.2,arp_tpa=10.0.0.1,arp_op=1 actions=output:"s2-eth1" cookie=0x0, duration=59.556s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s2-eth1",vlan_tci=0x0000,dl_src=c2:9d:dc:1d:d4:93,dl_dst=62:ca:42:08:6d:78,arp_spa=10.0.0.1,arp_tpa=10.0.0.2,arp_op=2 actions=output:"s2-eth2" [root@kunpeng82 demo1]# ovs-ofctl dump-flows s3 cookie=0x0, duration=58.050s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s3-eth2",vlan_tci=0x0000,dl_src=f2:5e:27:69:32:00,dl_dst=c2:9d:dc:1d:d4:93,arp_spa=10.0.0.3,arp_tpa=10.0.0.1,arp_op=2 actions=output:"s3-eth1" cookie=0x0, duration=52.921s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s3-eth2",vlan_tci=0x0000,dl_src=f2:5e:27:69:32:00,dl_dst=c2:9d:dc:1d:d4:93,arp_spa=10.0.0.3,arp_tpa=10.0.0.1,arp_op=1 actions=output:"s3-eth1" cookie=0x0, duration=52.866s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s3-eth1",vlan_tci=0x0000,dl_src=c2:9d:dc:1d:d4:93,dl_dst=f2:5e:27:69:32:00,arp_spa=10.0.0.1,arp_tpa=10.0.0.3,arp_op=2 actions=output:"s3-eth2" cookie=0x0, duration=58.009s, table=0, n_packets=2, n_bytes=196, idle_timeout=60, priority=65535,icmp,in_port="s3-eth1",vlan_tci=0x0000,dl_src=c2:9d:dc:1d:d4:93,dl_dst=f2:5e:27:69:32:00,nw_src=10.0.0.1,nw_dst=10.0.0.3,nw_tos=0,icmp_type=8,icmp_code=0 actions=output:"s3-eth2" cookie=0x0, duration=57.996s, table=0, n_packets=2, n_bytes=196, idle_timeout=60, priority=65535,icmp,in_port="s3-eth2",vlan_tci=0x0000,dl_src=f2:5e:27:69:32:00,dl_dst=c2:9d:dc:1d:d4:93,nw_src=10.0.0.3,nw_dst=10.0.0.1,nw_tos=0,icmp_type=0,icmp_code=0 actions=output:"s3-eth1" [root@kunpeng82 demo1]# ovs-ofctl dump-flows s4 cookie=0x0, duration=6.190s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s4-eth2",vlan_tci=0x0000,dl_src=7a:eb:f1:92:31:a0,dl_dst=c2:9d:dc:1d:d4:93,arp_spa=10.0.0.4,arp_tpa=10.0.0.1,arp_op=2 actions=output:"s4-eth1" cookie=0x0, duration=1.117s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s4-eth2",vlan_tci=0x0000,dl_src=7a:eb:f1:92:31:a0,dl_dst=c2:9d:dc:1d:d4:93,arp_spa=10.0.0.4,arp_tpa=10.0.0.1,arp_op=1 actions=output:"s4-eth1" cookie=0x0, duration=1.076s, table=0, n_packets=0, n_bytes=0, idle_timeout=60, priority=65535,arp,in_port="s4-eth1",vlan_tci=0x0000,dl_src=c2:9d:dc:1d:d4:93,dl_dst=7a:eb:f1:92:31:a0,arp_spa=10.0.0.1,arp_tpa=10.0.0.4,arp_op=2 actions=output:"s4-eth2" cookie=0x0, duration=6.150s, table=0, n_packets=2, n_bytes=196, idle_timeout=60, priority=65535,icmp,in_port="s4-eth1",vlan_tci=0x0000,dl_src=c2:9d:dc:1d:d4:93,dl_dst=7a:eb:f1:92:31:a0,nw_src=10.0.0.1,nw_dst=10.0.0.4,nw_tos=0,icmp_type=8,icmp_code=0 actions=output:"s4-eth2" cookie=0x0, duration=6.136s, table=0, n_packets=2, n_bytes=196, idle_timeout=60, priority=65535,icmp,in_port="s4-eth2",vlan_tci=0x0000,dl_src=7a:eb:f1:92:31:a0,dl_dst=c2:9d:dc:1d:d4:93,nw_src=10.0.0.4,nw_dst=10.0.0.1,nw_tos=0,icmp_type=0,icmp_code=0 actions=output:"s4-eth1" [root@kunpeng82 demo1]#
重新建立一个toop
Topo.__init__(self, **opts) host1 = self.addHost('h1') host2 = self.addHost('h2') host3 = self.addHost('h3') host4 = self.addHost('h4') self.switch = {} for s in range(1,6): self.switch[s-1] = self.addSwitch('s%s' %(s)) self.addLink(self.switch[0], self.switch[1]) self.addLink(self.switch[0], self.switch[2]) self.addLink(self.switch[0], self.switch[3]) self.addLink(self.switch[4], self.switch[1]) self.addLink(self.switch[4], self.switch[2]) self.addLink(self.switch[4], self.switch[3]) #Adding host self.addLink(self.switch[0], host1) self.addLink(self.switch[4], host2) self.addLink(self.switch[4], host3) self.addLink(self.switch[4], host4) topos = {'group':(lambda:MininetTopo())} [root@kunpeng82 demo1]# mn --custom group2.py --topo group *** Creating network *** Adding controller *** Adding hosts: h1 h2 h3 h4 *** Adding switches: s1 s2 s3 s4 s5 *** Adding links: (s1, h1) (s1, s2) (s1, s3) (s1, s4) (s5, h2) (s5, h3) (s5, h4) (s5, s2) (s5, s3) (s5, s4) *** Configuring hosts h1 h2 h3 h4 *** Starting controller c0 *** Starting 5 switches s1 s2 s3 s4 s5 ... *** Starting CLI:
不通了哦 mininet> h1 ping h2 PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data. From 10.0.0.1 icmp_seq=1 Destination Host Unreachable From 10.0.0.1 icmp_seq=5 Destination Host Unreachable ^C --- 10.0.0.2 ping statistics --- 8 packets transmitted, 0 received, +2 errors, 100% packet loss, time 7241ms pipe 4 mininet> h1 ip n 10.0.0.2 dev h1-eth0 FAILED mininet>
demo2
[root@kunpeng82 demo1]# cat group2.py from mininet.topo import Topo class MininetTopo(Topo): def __init__(self,**opts): Topo.__init__(self, **opts) host1 = self.addHost('h1') host2 = self.addHost('h2') self.switch = {} for s in range(1,3): self.switch[s-1] = self.addSwitch('s%s' %(s)) self.addLink(self.switch[0], self.switch[1]) #Adding host self.addLink(self.switch[0], host1) self.addLink(self.switch[1], host2) topos = {'group':(lambda:MininetTopo())} [root@kunpeng82 demo1]#
mininet> net h1 h1-eth0:s1-eth2 h2 h2-eth0:s2-eth2 s1 lo: s1-eth1:s2-eth1 s1-eth2:h1-eth0 s2 lo: s2-eth1:s1-eth1 s2-eth2:h2-eth0 c0 mininet> h1 ping h2 PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data. 64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=54.3 ms 64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=27.1 ms 64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.198 ms 64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.471 ms 64 bytes from 10.0.0.2: icmp_seq=5 ttl=64 time=0.035 ms 64 bytes from 10.0.0.2: icmp_seq=6 ttl=64 time=0.069 ms 64 bytes from 10.0.0.2: icmp_seq=7 ttl=64 time=0.048 ms 64 bytes from 10.0.0.2: icmp_seq=8 ttl=64 time=0.027 ms 64 bytes from 10.0.0.2: icmp_seq=9 ttl=64 time=0.027 ms 64 bytes from 10.0.0.2: icmp_seq=10 ttl=64 time=0.027 ms
demo3
1、 采用arp proxy
2、 环路检测保证同一个交换机中的某一个广播数据包只能有一个入口,从而防止成环
from ryu.base import app_manager from ryu.controller import ofp_event from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER from ryu.controller.handler import set_ev_cls from ryu.ofproto import ofproto_v1_3 from ryu.lib.packet import packet from ryu.lib.packet import ethernet from ryu.lib.packet import arp from ryu.lib.packet import ipv6 from ryu.lib import mac class SimpleARPProxy13(app_manager.RyuApp): OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] def __init__(self, *args, **kwargs): super(SimpleARPProxy13, self).__init__(*args, **kwargs) self.mac_to_port = {} self.arp_table = {} self.sw = {} @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) def switch_features_handler(self, ev): datapath = ev.msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser # install table-miss flow entry # # We specify NO BUFFER to max_len of the output action due to # OVS bug. At this moment, if we specify a lesser number, e.g., # 128, OVS will send Packet-In with invalid buffer_id and # truncated packet data. In that case, we cannot output packets # correctly. match = parser.OFPMatch() actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, ofproto.OFPCML_NO_BUFFER)] self.add_flow(datapath, 0, match, actions) self.logger.info("switch:%s connected", datapath.id) def add_flow(self, datapath, priority, match, actions, buffer_id=None): ofproto = datapath.ofproto parser = datapath.ofproto_parser inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] if buffer_id: mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id, priority=priority, match=match, instructions=inst) else: mod = parser.OFPFlowMod(datapath=datapath, priority=priority, match=match, instructions=inst) datapath.send_msg(mod) @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) def _packet_in_handler(self, ev): msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser in_port = msg.match['in_port'] pkt = packet.Packet(msg.data) eth = pkt.get_protocols(ethernet.ethernet)[0] dst = eth.dst src = eth.src dpid = datapath.id self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port) if pkt.get_protocol(ipv6.ipv6): # Drop the IPV6 Packets. match = parser.OFPMatch(eth_type=eth.ethertype) actions = [] self.add_flow(datapath, 1, match, actions) return None arp_pkt = pkt.get_protocol(arp.arp) if arp_pkt: self.arp_table[arp_pkt.src_ip] = src # ARP learning self.logger.info(" ARP: %s -> %s", arp_pkt.src_ip, arp_pkt.dst_ip) if self.arp_handler(msg): # answer or drop return None self.mac_to_port.setdefault(dpid, {}) self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port) # Learn a mac address to avoid FLOOD next time. if src not in self.mac_to_port[dpid]: self.mac_to_port[dpid][src] = in_port #print self.mac_to_port if dst in self.mac_to_port[dpid]: out_port = self.mac_to_port[dpid][dst] #else: #if self.arp_handler(msg): # 1:reply or drop; 0: flood # return None else: print(self.mac_to_port[dpid]) out_port = ofproto.OFPP_FLOOD print("Flood") actions = [parser.OFPActionOutput(out_port)] # Install a flow to avoid packet_in next time if out_port != ofproto.OFPP_FLOOD: self.logger.info(" install flow_mod:%s -> %s ", in_port, out_port) 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) def arp_handler(self, msg): datapath = msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser in_port = msg.match['in_port'] pkt = packet.Packet(msg.data) eth = pkt.get_protocols(ethernet.ethernet)[0] arp_pkt = pkt.get_protocol(arp.arp) if eth: eth_dst = eth.dst eth_src = eth.src # Break the loop for avoiding ARP broadcast storm if eth_dst == mac.BROADCAST_STR: # and arp_pkt: arp_dst_ip = arp_pkt.dst_ip arp_src_ip = arp_pkt.src_ip if (datapath.id, arp_src_ip, arp_dst_ip) in self.sw: # packet come back at different port. if self.sw[(datapath.id, arp_src_ip, arp_dst_ip)] != in_port: #drop datapath.send_packet_out(in_port=in_port, actions=[]) return True else: # self.sw.setdefault((datapath.id, eth_src, arp_dst_ip), None) self.sw[(datapath.id, arp_src_ip, arp_dst_ip)] = in_port print(self.sw) self.mac_to_port.setdefault(datapath.id, {}) self.mac_to_port[datapath.id][eth_src] = in_port # Try to reply arp request if arp_pkt: if arp_pkt.opcode == arp.ARP_REQUEST: hwtype = arp_pkt.hwtype proto = arp_pkt.proto hlen = arp_pkt.hlen plen = arp_pkt.plen arp_src_ip = arp_pkt.src_ip arp_dst_ip = arp_pkt.dst_ip if arp_dst_ip in self.arp_table: actions = [parser.OFPActionOutput(in_port)] ARP_Reply = packet.Packet() ARP_Reply.add_protocol(ethernet.ethernet( ethertype=eth.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 = parser.OFPPacketOut( datapath=datapath, buffer_id=ofproto.OFP_NO_BUFFER, in_port=ofproto.OFPP_CONTROLLER, actions=actions, data=ARP_Reply.data) datapath.send_msg(out) print("ARP_Reply") return True return False [root@kunpeng82 app]#