ryu 环路

[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]# 
原文地址:https://www.cnblogs.com/dream397/p/12986164.html