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]#