zoukankan      html  css  js  c++  java
  • sdn控制器拓扑发现(二)

    from ryu.base import app_manager
    from ryu.ofproto import ofproto_v1_3
    from ryu.controller.handler import set_ev_cls
    from ryu.controller import ofp_event
    from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER
    from ryu.lib.packet import ether_types,lldp,packet,ethernet
    
    
    class MySwitch(app_manager.RyuApp):
        OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
        link = []
    
        def __init__(self, *args,**kwargs):
            super(MySwitch,self).__init__(*args,**kwargs)
            self.mac_to_port = {} # Mac address is defined
        @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
    
            #set if packet is lldp, send to controller
            actions = [parser.OFPActionOutput(port=ofproto.OFPP_CONTROLLER,
                                              max_len=ofproto.OFPCML_NO_BUFFER)]
            inst = [parser.OFPInstructionActions(type_=ofproto.OFPIT_APPLY_ACTIONS,actions=actions)]
            match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_LLDP)
            //lib/packet/ether_types.py:25:ETH_TYPE_LLDP = 0x88cc
            mod = parser.OFPFlowMod(datapath=datapath,
                                    priority=1,
                                    match=match,
                                    instructions=inst)
            datapath.send_msg(mod)
    
            self.send_port_desc_stats_request(datapath)# send the request
    
    
        def add_flow(self, datapath, priority, match, actions):
            ofproto = datapath.ofproto
            parser = datapath.ofproto_parser
    
            inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,actions)]
    
            mod = parser.OFPFlowMod(datapath=datapath,priority=priority,match=match,instructions=inst)
            datapath.send_msg(mod)
    
    
        def send_port_desc_stats_request(self, datapath):
            ofproto = datapath.ofproto
            ofp_parser = datapath.ofproto_parser
        
            req = ofp_parser.OFPPortDescStatsRequest(datapath, 0)
            datapath.send_msg(req)
    
    
        # Send the lldp packet
        def send_lldp_packet(self, datapath, port, hw_addr, ttl):
            ofproto = datapath.ofproto
            ofp_parser = datapath.ofproto_parser
    
            pkt = packet.Packet()
            pkt.add_protocol(ethernet.ethernet(ethertype=ether_types.ETH_TYPE_LLDP,src=hw_addr ,dst=lldp.LLDP_MAC_NEAREST_BRIDGE))
    
            #chassis_id = lldp.ChassisID(subtype=lldp.ChassisID.SUB_LOCALLY_ASSIGNED, chassis_id=str(datapath.id))
            chassis_id = lldp.ChassisID(subtype=lldp.ChassisID.SUB_LOCALLY_ASSIGNED, chassis_id=str(datapath.id).encode('utf-8'))
            #port_id = lldp.PortID(subtype=lldp.PortID.SUB_LOCALLY_ASSIGNED, port_id=str(port))
            port_id = lldp.PortID(subtype=lldp.PortID.SUB_LOCALLY_ASSIGNED, port_id=str(port).encode('utf-8'))
            #port_id = lldp.PortID(subtype=lldp.PortID.SUB_LOCALLY_ASSIGNED, port_id=b'1/3')
            ttl = lldp.TTL(ttl=1)
            end = lldp.End()
            tlvs = (chassis_id,port_id,ttl,end)
            pkt.add_protocol(lldp.lldp(tlvs))
            pkt.serialize()
            self.logger.info("packet-out %s" % pkt)
            data = pkt.data
            actions = [ofp_parser.OFPActionOutput(port=port)]
            out = ofp_parser.OFPPacketOut(datapath=datapath,
                                      buffer_id=ofproto.OFP_NO_BUFFER,
                                      in_port=ofproto.OFPP_CONTROLLER,
                                      actions=actions,
                                      data=data)
            datapath.send_msg(out)
        '''
        @set_ev_cls(ofp_event.EventOFPPortDescStatsReply, MAIN_DISPATCHER)
        def port_desc_stats_reply_handler(self, ev):
            datapath = ev.msg.datapath
            ofproto = datapath.ofproto
            ports = []
            for p in ev.msg.body:
                if p.port_no <=ofproto.OFPP_MAX: 
                    ports.append('port_no=%d hw_addr=%s name=%s config=0x%08x '
                         'state=0x%08x curr=0x%08x advertised=0x%08x '
                         'supported=0x%08x peer=0x%08x curr_speed=%d '
                         'max_speed=%d' %
                         (p.port_no, p.hw_addr,
                          p.name, p.config,
                          p.state, p.curr, p.advertised,
                          p.supported, p.peer, p.curr_speed,
                          p.max_speed))
            self.logger.debug('OFPPortDescStatsReply received: %s', ports)
        '''
        @set_ev_cls(ofp_event.EventOFPPortDescStatsReply, MAIN_DISPATCHER)
        def port_desc_stats_reply_handler(self, ev):
            datapath = ev.msg.datapath
            ofproto = datapath.ofproto
            ofp_parser = datapath.ofproto_parser
            ports = []
            for stat in ev.msg.body:
                if stat.port_no <=ofproto.OFPP_MAX: 
                    ports.append({'port_no':stat.port_no,'hw_addr':stat.hw_addr})
            for no in ports:
                in_port = no['port_no']
                match = ofp_parser.OFPMatch(in_port = in_port)
                for other_no in ports:
                    if other_no['port_no'] != in_port:
                        out_port = other_no['port_no']            ###适用于线性结构
                self.logger.debug('port 0x%08x  send lldp  to 0x%08x ', no['port_no'], out_port)
                self.send_lldp_packet(datapath,no['port_no'],no['hw_addr'],10)
                actions = [ofp_parser.OFPActionOutput(out_port)]
                self.add_flow(datapath, 1, match, actions)
    
        @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
    
    
            pkt = packet.Packet(data=msg.data)
            dpid = datapath.id # switch id which send the packetin
            in_port  = msg.match['in_port']
    
            pkt_ethernet = pkt.get_protocol(ethernet.ethernet)
            pkt_lldp = pkt.get_protocol(lldp.lldp)
            if not pkt_ethernet:
                return 
            #print(pkt_lldp)
            if pkt_lldp:
                self.handle_lldp(dpid,in_port,pkt_lldp.tlvs[0].chassis_id,pkt_lldp.tlvs[1].port_id)
    
    
            #self.logger.info("packet-in %s" % (pkt,))
    
        # Link two switch
        def switch_link(self,s_a,s_b):
            return s_a + '<--->' + s_b
                
        def handle_lldp(self,dpid,in_port,lldp_dpid,lldp_in_port):
            switch_a = 'switch'+str(dpid)+', port'+str(in_port)
            switch_b = 'switch'+lldp_dpid.decode('utf-8')+', port'+lldp_in_port.decode('utf-8')
            link = self.switch_link(switch_a,switch_b)
    
            # Check the switch link is existed
            if not any(self.switch_link(switch_b,switch_a) == search for search in self.link):
                self.link.append(link)
    
    
            print(self.link)

     没有连接controller之前

    [root@kunpeng82 devuser]# ovs-ofctl dump-flows s1 -O openflow13
    [root@kunpeng82 devuser]# ovs-ofctl dump-flows s2 -O openflow13
    [root@kunpeng82 devuser]# ovs-ofctl dump-flows s3 -O openflow13
    [root@kunpeng82 devuser]# ovs-ofctl show s1 -O openflow13
    OFPT_FEATURES_REPLY (OF1.3) (xid=0x2): dpid:0000000000000001
    n_tables:254, n_buffers:0
    capabilities: FLOW_STATS TABLE_STATS PORT_STATS GROUP_STATS QUEUE_STATS
    OFPST_PORT_DESC reply (OF1.3) (xid=0x3):
     1(s1-eth1): addr:ae:a5:76:f3:e8:ae
         config:     0
         state:      LIVE
         current:    10GB-FD COPPER
         speed: 10000 Mbps now, 0 Mbps max
     2(s1-eth2): addr:be:6e:15:28:3c:5e
         config:     0
         state:      LIVE
         current:    10GB-FD COPPER
         speed: 10000 Mbps now, 0 Mbps max
     LOCAL(s1): addr:ea:00:dc:11:d4:4d
         config:     PORT_DOWN
         state:      LINK_DOWN
         speed: 0 Mbps now, 0 Mbps max
    OFPT_GET_CONFIG_REPLY (OF1.3) (xid=0x9): frags=normal miss_send_len=0
    [root@kunpeng82 devuser]# ovs-ofctl show s2 -O openflow13
    OFPT_FEATURES_REPLY (OF1.3) (xid=0x2): dpid:0000000000000002
    n_tables:254, n_buffers:0
    capabilities: FLOW_STATS TABLE_STATS PORT_STATS GROUP_STATS QUEUE_STATS
    OFPST_PORT_DESC reply (OF1.3) (xid=0x3):
     1(s2-eth1): addr:8e:9d:b7:2d:ed:93
         config:     0
         state:      LIVE
         current:    10GB-FD COPPER
         speed: 10000 Mbps now, 0 Mbps max
     2(s2-eth2): addr:6e:24:f3:05:31:c7
         config:     0
         state:      LIVE
         current:    10GB-FD COPPER
         speed: 10000 Mbps now, 0 Mbps max
     LOCAL(s2): addr:ca:51:08:ec:4d:4e
         config:     PORT_DOWN
         state:      LINK_DOWN
         speed: 0 Mbps now, 0 Mbps max
    OFPT_GET_CONFIG_REPLY (OF1.3) (xid=0x9): frags=normal miss_send_len=0
    [root@kunpeng82 devuser]# ovs-ofctl show s3 -O openflow13
    OFPT_FEATURES_REPLY (OF1.3) (xid=0x2): dpid:0000000000000003
    n_tables:254, n_buffers:0
    capabilities: FLOW_STATS TABLE_STATS PORT_STATS GROUP_STATS QUEUE_STATS
    OFPST_PORT_DESC reply (OF1.3) (xid=0x3):
     1(s3-eth1): addr:52:fd:e6:ed:97:13
         config:     0
         state:      LIVE
         current:    10GB-FD COPPER
         speed: 10000 Mbps now, 0 Mbps max
     2(s3-eth2): addr:5e:3f:0d:6d:7d:e6
         config:     0
         state:      LIVE
         current:    10GB-FD COPPER
         speed: 10000 Mbps now, 0 Mbps max
     LOCAL(s3): addr:fe:56:82:c2:fa:4c
         config:     PORT_DOWN
         state:      LINK_DOWN
         speed: 0 Mbps now, 0 Mbps max
    OFPT_GET_CONFIG_REPLY (OF1.3) (xid=0x9): frags=normal miss_send_len=0
    [root@kunpeng82 devuser]# 
    lib/packet/lldp.py:59:LLDP_MAC_NEAREST_BRIDGE = '01:80:c2:00:00:0e'

    connected socket:<eventlet.greenio.base.GreenSocket object at 0xffff7970ad68> address:('127.0.0.1', 47426)
    hello ev <ryu.controller.ofp_event.EventOFPHello object at 0xffff7970a780>
    move onto config mode
    connected socket:<eventlet.greenio.base.GreenSocket object at 0xffff7970ab38> address:('127.0.0.1', 47428)
    hello ev <ryu.controller.ofp_event.EventOFPHello object at 0xffff7970a0b8>
    move onto config mode
    connected socket:<eventlet.greenio.base.GreenSocket object at 0xffff7970a160> address:('127.0.0.1', 47430)
    hello ev <ryu.controller.ofp_event.EventOFPHello object at 0xffff796f5a90>
    move onto config mode
    EVENT ofp_event->MySwitch EventOFPSwitchFeatures
    switch features ev version=0x4,msg_type=0x6,msg_len=0x20,xid=0xa860fcf3,OFPSwitchFeatures(auxiliary_id=0,capabilities=79,datapath_id=3,n_buffers=0,n_tables=254)
    EVENT ofp_event->MySwitch EventOFPSwitchFeatures
    switch features ev version=0x4,msg_type=0x6,msg_len=0x20,xid=0x2e031d87,OFPSwitchFeatures(auxiliary_id=0,capabilities=79,datapath_id=1,n_buffers=0,n_tables=254)
    move onto main mode
    EVENT ofp_event->MySwitch EventOFPPortDescStatsReply
    port b's1-eth1' 0x00000001  send lldp  to 0x00000002 
    packet-out ethernet(dst='01:80:c2:00:00:0e',ethertype=35020,src='9e:48:6a:42:e7:e6'), lldp(tlvs=(ChassisID(chassis_id=b'1',len=2,subtype=7,typelen=514), PortID(len=2,port_id=b'1',subtype=7,typelen=1026), TTL(len=2,ttl=1,typelen=1538), End(len=0,typelen=0)))
    port b's1-eth2' 0x00000002  send lldp  to 0x00000001 
    packet-out ethernet(dst='01:80:c2:00:00:0e',ethertype=35020,src='26:fe:ef:c1:d1:cd'), lldp(tlvs=(ChassisID(chassis_id=b'1',len=2,subtype=7,typelen=514), PortID(len=2,port_id=b'2',subtype=7,typelen=1026), TTL(len=2,ttl=1,typelen=1538), End(len=0,typelen=0)))
    move onto main mode
    EVENT ofp_event->MySwitch EventOFPPortDescStatsReply
    EVENT ofp_event->MySwitch EventOFPSwitchFeatures
    switch features ev version=0x4,msg_type=0x6,msg_len=0x20,xid=0x8f906e6f,OFPSwitchFeatures(auxiliary_id=0,capabilities=79,datapath_id=2,n_buffers=0,n_tables=254)
    port b's3-eth1' 0x00000001  send lldp  to 0x00000002 
    packet-out ethernet(dst='01:80:c2:00:00:0e',ethertype=35020,src='1a:d2:d5:c9:3c:5e'), lldp(tlvs=(ChassisID(chassis_id=b'3',len=2,subtype=7,typelen=514), PortID(len=2,port_id=b'1',subtype=7,typelen=1026), TTL(len=2,ttl=1,typelen=1538), End(len=0,typelen=0)))
    port b's3-eth2' 0x00000002  send lldp  to 0x00000001 
    packet-out ethernet(dst='01:80:c2:00:00:0e',ethertype=35020,src='8a:d2:8d:2f:4c:21'), lldp(tlvs=(ChassisID(chassis_id=b'3',len=2,subtype=7,typelen=514), PortID(len=2,port_id=b'2',subtype=7,typelen=1026), TTL(len=2,ttl=1,typelen=1538), End(len=0,typelen=0)))
    move onto main mode
    EVENT ofp_event->MySwitch EventOFPPortDescStatsReply
    port b's2-eth1' 0x00000001  send lldp  to 0x00000002 
    packet-out ethernet(dst='01:80:c2:00:00:0e',ethertype=35020,src='d6:63:a2:0c:7f:70'), lldp(tlvs=(ChassisID(chassis_id=b'2',len=2,subtype=7,typelen=514), PortID(len=2,port_id=b'1',subtype=7,typelen=1026), TTL(len=2,ttl=1,typelen=1538), End(len=0,typelen=0)))
    port b's2-eth2' 0x00000002  send lldp  to 0x00000001 
    packet-out ethernet(dst='01:80:c2:00:00:0e',ethertype=35020,src='d2:3e:f9:67:b5:a0'), lldp(tlvs=(ChassisID(chassis_id=b'2',len=2,subtype=7,typelen=514), PortID(len=2,port_id=b'2',subtype=7,typelen=1026), TTL(len=2,ttl=1,typelen=1538), End(len=0,typelen=0)))
    EVENT ofp_event->MySwitch EventOFPPacketIn
    ['switch2, port2<--->switch3, port1']
    EVENT ofp_event->MySwitch EventOFPPacketIn
    ['switch2, port2<--->switch3, port1', 'switch1, port2<--->switch2, port1']
    EVENT ofp_event->MySwitch EventOFPPacketIn
    ['switch2, port2<--->switch3, port1', 'switch1, port2<--->switch2, port1']
    [root@kunpeng82 app]# ovs-ofctl dump-flows s1
    2020-06-19T06:34:16Z|00001|vconn|WARN|unix:/var/run/openvswitch/s1.mgmt: version negotiation failed (we support version 0x01, peer supports version 0x04)
    ovs-ofctl: s1: failed to connect to socket (Broken pipe)
    [root@kunpeng82 app]# 
    [root@kunpeng82 app]# ovs-ofctl dump-flows s1 -O OpenFlow13
     cookie=0x0, duration=1435.263s, table=0, n_packets=2, n_bytes=120, priority=1,dl_type=0x88cc actions=CONTROLLER:65535
     cookie=0x0, duration=1435.255s, table=0, n_packets=3, n_bytes=210, priority=1,in_port="s1-eth1" actions=output:"s1-eth2"
     cookie=0x0, duration=1435.254s, table=0, n_packets=9, n_bytes=630, priority=1,in_port="s1-eth2" actions=output:"s1-eth1"


    lib/packet/ether_types.py:25:ETH_TYPE_LLDP = 0x88cc
           The following shorthand notations are also available:
    
           ip     Same as dl_type=0x0800.
    
           ipv6   Same as dl_type=0x86dd.
    
           icmp   Same as dl_type=0x0800,nw_proto=1.
    
           icmp6  Same as dl_type=0x86dd,nw_proto=58.
    
           tcp    Same as dl_type=0x0800,nw_proto=6.
    
           tcp6   Same as dl_type=0x86dd,nw_proto=6.
    
           udp    Same as dl_type=0x0800,nw_proto=17.
    
           udp6   Same as dl_type=0x86dd,nw_proto=17.
    
           sctp   Same as dl_type=0x0800,nw_proto=132.
    
           sctp6  Same as dl_type=0x86dd,nw_proto=132.
    
           arp    Same as dl_type=0x0806.
    
           rarp   Same as dl_type=0x8035.
    
           mpls   Same as dl_type=0x8847.
    
           mplsm  Same as dl_type=0x8848.
    [root@kunpeng82 ryu]# ovs-ofctl dump-flows s1 -O OpenFlow13
     cookie=0x0, duration=1950.532s, table=0, n_packets=2, n_bytes=120, priority=1,dl_type=0x88cc actions=CONTROLLER:65535
     cookie=0x0, duration=1950.524s, table=0, n_packets=3, n_bytes=210, priority=1,in_port="s1-eth1" actions=output:"s1-eth2"
     cookie=0x0, duration=1950.523s, table=0, n_packets=9, n_bytes=630, priority=1,in_port="s1-eth2" actions=output:"s1-eth1"
    [root@kunpeng82 ryu]# ovs-ofctl dump-flows s2 -O OpenFlow13
     cookie=0x0, duration=1955.206s, table=0, n_packets=4, n_bytes=240, priority=1,dl_type=0x88cc actions=CONTROLLER:65535
     cookie=0x0, duration=1955.199s, table=0, n_packets=6, n_bytes=420, priority=1,in_port="s2-eth1" actions=output:"s2-eth2"
     cookie=0x0, duration=1955.199s, table=0, n_packets=6, n_bytes=420, priority=1,in_port="s2-eth2" actions=output:"s2-eth1"
    [root@kunpeng82 ryu]# ovs-ofctl dump-flows s3 -O OpenFlow13
     cookie=0x0, duration=1958.804s, table=0, n_packets=2, n_bytes=120, priority=1,dl_type=0x88cc actions=CONTROLLER:65535
     cookie=0x0, duration=1958.789s, table=0, n_packets=9, n_bytes=630, priority=1,in_port="s3-eth1" actions=output:"s3-eth2"
     cookie=0x0, duration=1958.789s, table=0, n_packets=3, n_bytes=210, priority=1,in_port="s3-eth2" actions=output:"s3-eth1"
    [root@kunpeng82 ryu]# 
  • 相关阅读:
    linux(centos 6.4)下安装php memcache服务端及其客户端(详细教程)
    linux下swap问题处理
    mysql锁表查询,binlog日志清理
    Centos7上安装部署frp内网穿透
    配置frp实现内网穿透,域名再也不用备案了
    xp激活码 windows xp产品密钥 xp sp3专业版正版序列号
    windows不能使用剪贴板解决办法
    mysql多主一从配置
    给mysql的root %用户添加grant权限和创建的用户权限
    redis主从及集群配置密码
  • 原文地址:https://www.cnblogs.com/dream397/p/13162306.html
Copyright © 2011-2022 走看看