def run(self, src, src_gateway, dst, dst_gateway, **kwargs): sdp_id = dpid_lib.str_to_dpid(src_gateway["datapath_id"]) ddp_id = dpid_lib.str_to_dpid(dst_gateway["datapath_id"]) if self.ryuapp.dps.has_key(sdp_id): sdp = self.ryuapp.dps[sdp_id] sofp, sofp_parser, sofp_set, sofp_out = self.ofp_get(sdp) sport = self.port_get(sdp, src.devname) if sport: smatch = sofp_parser.OFPMatch( in_port=sport.port_no, eth_type=ether.ETH_TYPE_IP, eth_src=src.mac_address, ipv4_src=src.address, ipv4_dst=dst.address, ) self.delete_flow(sdp, smatch) if self.ryuapp.dps.has_key(ddp_id): ddp = self.ryuapp.dps[ddp_id] dofp, dofp_parser, dofp_set, dofp_out = self.ofp_get(ddp) dport = self.port_get(ddp, dst.devname) if dport: dmatch = dofp_parser.OFPMatch( in_port=dport.port_no, eth_type=ether.ETH_TYPE_IP, eth_src=dst.mac_address, ipv4_src=dst.address, ipv4_dst=src.address, ) self.delete_flow(ddp, dmatch)
def _route(self, req, **kwargs): srcdpid=dpid_lib.str_to_dpid(kwargs['srcdpid']) srcport=port_no_lib.str_to_port_no(kwargs['srcport']) dstdpid=dpid_lib.str_to_dpid(kwargs['dstdpid']) dstport=port_no_lib.str_to_port_no(kwargs['dstport']) links = get_link(self.topology_api_app, None) topology = nx.MultiDiGraph() for link in links: print link topology.add_edge(link.src.dpid, link.dst.dpid, src_port=link.src.port_no, dst_port=link.dst.port_no) try: shortest_path = nx.shortest_path(topology, srcdpid, dstdpid) except (nx.NetworkXError, nx.NetworkXNoPath): body = json.dumps([]) print "Error" return Response(content_type='application/json', body=body) ingressPort = NodePortTuple(srcdpid, srcport) egressPort = NodePortTuple(dstdpid, dstport) route = [] route.append(ingressPort) for i in range(0, len(shortest_path)-1): link = topology[shortest_path[i]][shortest_path[i+1]] index = randrange(len(link)) dstPort = NodePortTuple(shortest_path[i], link[index]['src_port']) srcPort = NodePortTuple(shortest_path[i+1], link[index]['dst_port']) route.append(dstPort) route.append(srcPort) route.append(egressPort) body = json.dumps([hop.to_dict() for hop in route]) return Response(content_type='application/json', body=body)
def handle(self, dhcp_header, raw_data, txn): # Process DHCP packet LOGGER.info("Handle DHCP packet") if self.switch_dpid is None or self.switch_port is None: LOGGER.warning("No DHCP server has been found!") return # Do ARP learning on a DHCP ACK message for option in dhcp_header.options.option_list: if option.tag == dhcp.DHCP_MESSAGE_TYPE_OPT: option_value = ord(option.value) if option_value == dhcp.DHCP_ACK: ip_addr = dhcp_header.yiaddr mac_addr = dhcp_header.chaddr if not self.arp_manager.mapping_exist(ip_addr): self.arp_manager.learn_arp_mapping(ip_addr, mac_addr) icp_rpc = self.inception.inception_rpc rpc_func_name = icp_rpc.update_arp_mapping.__name__ rpc_args = (ip_addr, mac_addr) self.rpc_manager.do_rpc(rpc_func_name, rpc_args) self.zk_manager.log_arp_mapping(ip_addr, mac_addr, txn) break # A packet received from client. Find out the switch connected # to dhcp server and forward the packet if dhcp_header.op == dhcp.DHCP_BOOT_REQUEST: LOGGER.info("Forward DHCP message to server at (switch=%s) " "(port=%s)", self.switch_dpid, self.switch_port) datapath = self.dpset.get(str_to_dpid(self.switch_dpid)) action_out = [ datapath.ofproto_parser.OFPActionOutput( int(self.switch_port))] datapath.send_msg( datapath.ofproto_parser.OFPPacketOut( datapath=datapath, buffer_id=0xffffffff, in_port=datapath.ofproto.OFPP_LOCAL, data=raw_data, actions=action_out)) # A packet received from server. Find out the mac address of # the client and forward the packet to it. elif dhcp_header.op == dhcp.DHCP_BOOT_REPLY: _, dpid, port = self.vm_manager.get_position(dhcp_header.chaddr) LOGGER.info("Forward DHCP message to client (mac=%s) at " "(switch=%s, port=%s)", dhcp_header.chaddr, dpid, port) datapath = self.dpset.get(str_to_dpid(dpid)) action_out = [datapath.ofproto_parser.OFPActionOutput(int(port))] datapath.send_msg( datapath.ofproto_parser.OFPPacketOut( datapath=datapath, buffer_id=0xffffffff, in_port=datapath.ofproto.OFPP_LOCAL, data=raw_data, actions=action_out))
def handle(self, dhcp_header, raw_data): # Process DHCP packet LOGGER.info("Handle DHCP packet") if self.switch_dpid is None or self.switch_port is None: LOGGER.warning("No DHCP server has been found!") return # Do ARP learning on a DHCP ACK message for option in dhcp_header.options.option_list: if option.tag == dhcp.DHCP_MESSAGE_TYPE_OPT: option_value = ord(option.value) if option_value == dhcp.DHCP_ACK: ip_addr = dhcp_header.yiaddr mac_addr = dhcp_header.chaddr if ip_addr not in self.ip_to_mac: self.ip_to_mac[ip_addr] = mac_addr self.mac_to_ip[mac_addr] = ip_addr if CONF.zookeeper_storage: zk_path = os.path.join(i_conf.IP_TO_MAC, ip_addr) self.inception.zk.create(zk_path, mac_addr) break # A packet received from client. Find out the switch connected # to dhcp server and forward the packet if dhcp_header.op == dhcp.DHCP_BOOT_REQUEST: LOGGER.info("Forward DHCP message to server at (switch=%s) " "(port=%s)", self.switch_dpid, self.switch_port) datapath = self.dpset.get(str_to_dpid(self.switch_dpid)) action_out = [ datapath.ofproto_parser.OFPActionOutput( int(self.switch_port))] datapath.send_msg( datapath.ofproto_parser.OFPPacketOut( datapath=datapath, buffer_id=0xffffffff, in_port=datapath.ofproto.OFPP_LOCAL, data=raw_data, actions=action_out)) # A packet received from server. Find out the mac address of # the client and forward the packet to it. elif dhcp_header.op == dhcp.DHCP_BOOT_REPLY: _, dpid, port, _ = self.mac_to_position[dhcp_header.chaddr] LOGGER.info("Forward DHCP message to client (mac=%s) at " "(switch=%s, port=%s)", dhcp_header.chaddr, dpid, port) datapath = self.dpset.get(str_to_dpid(dpid)) action_out = [datapath.ofproto_parser.OFPActionOutput(int(port))] datapath.send_msg( datapath.ofproto_parser.OFPPacketOut( datapath=datapath, buffer_id=0xffffffff, in_port=datapath.ofproto.OFPP_LOCAL, data=raw_data, actions=action_out))
def update(self, _req, dpid, port_id, remote_dpid, **_kwargs): dpid = dpid_lib.str_to_dpid(dpid) port_id = int(port_id) remote_dpid = dpid_lib.str_to_dpid(remote_dpid) try: self.tunnels.update_port(dpid, port_id, remote_dpid) except tunnels.RemoteDPIDAlreadyExist: return Response(status=409) return Response(status=200)
def create(self, _req, dpid, port_id, remote_dpid, **_kwargs): dpid = dpid_lib.str_to_dpid(dpid) port_id = int(port_id) remote_dpid = dpid_lib.str_to_dpid(remote_dpid) try: self.tunnels.register_port(dpid, port_id, remote_dpid) except ryu_exc.PortAlreadyExist: return Response(status=409) return Response(status=200)
def __init__(self, *args, **kwargs): super(SimpleSwitch13, self).__init__(*args, **kwargs) self.mac_to_port = {} self.stp = kwargs['stplib'] config = {dpid_lib.str_to_dpid('0000000000000001'): {'bridge': {'priority':0x8000}}, dpid_lib.str_to_dpid('0000000000000002'): {'bridge': {'priority':0x9000}}, dpid_lib.str_to_dpid('0000000000000003'): {'bridge': {'priority':0xa000}}} self.stp.set_config(config)
def oxp_lldp_parse(data): pkt = packet.Packet(data) i = iter(pkt) eth_pkt = i.next() assert type(eth_pkt) == ethernet.ethernet lldp_pkt = i.next() if type(lldp_pkt) != lldp.lldp: raise LLDPPacket.LLDPUnknownFormat() tlv_chassis_id = lldp_pkt.tlvs[0] if tlv_chassis_id.subtype != lldp.ChassisID.SUB_LOCALLY_ASSIGNED: raise LLDPPacket.LLDPUnknownFormat( msg='unknown chassis id subtype %d' % tlv_chassis_id.subtype) chassis_id = tlv_chassis_id.chassis_id if not chassis_id.startswith(LLDPPacket.CHASSIS_ID_PREFIX): raise LLDPPacket.LLDPUnknownFormat( msg='unknown chassis id format %s' % chassis_id) src_dpid = str_to_dpid(chassis_id[LLDPPacket.CHASSIS_ID_PREFIX_LEN:]) tlv_port_id = lldp_pkt.tlvs[1] if tlv_port_id.subtype != lldp.PortID.SUB_PORT_COMPONENT: raise LLDPPacket.LLDPUnknownFormat( msg='unknown port id subtype %d' % tlv_port_id.subtype) port_id = tlv_port_id.port_id if len(port_id) != LLDPPacket.PORT_ID_SIZE: raise LLDPPacket.LLDPUnknownFormat( msg='unknown port id %d' % port_id) (src_port_no, ) = struct.unpack(LLDPPacket.PORT_ID_STR, port_id) # oxp related. tlv_domain_id = lldp_pkt.tlvs[3] if tlv_domain_id.subtype != lldp.DomainID.SUB_LOCALLY_ASSIGNED: raise LLDPPacket.LLDPUnknownFormat( msg='unknown domain id subtype %d' % tlv_domain_id.subtype) domain_id = tlv_domain_id.domain_id if not domain_id.startswith(LLDPPacket.DOMAIN_ID_PREFIX): raise LLDPPacket.LLDPUnknownFormat( msg='unknown domain id format %s' % domain_id) src_domain_id = str_to_dpid(domain_id[ LLDPPacket.DOMAIN_ID_PREFIX_LEN:]) tlv_vport_id = lldp_pkt.tlvs[4] if tlv_vport_id.subtype != lldp.VPortID.SUB_PORT_COMPONENT: raise LLDPPacket.LLDPUnknownFormat( msg='unknown vport id subtype %d' % tlv_vport_id.subtype) vport_id = tlv_vport_id.vport_id if len(vport_id) != LLDPPacket.VPORT_ID_SIZE: raise LLDPPacket.LLDPUnknownFormat( msg='unknown vport id %d' % vport_id) (src_vport_no, ) = struct.unpack(LLDPPacket.VPORT_ID_STR, vport_id) return src_dpid, src_port_no, src_domain_id, src_vport_no
def __init__(self, *args, **kwargs): super(SimpleSwitchStp13, self).__init__(*args, **kwargs) self.mac_to_port = {} self.stp = kwargs['stplib'] #sample of stplib config # please refer to stplib.Stp.set_config() for detail. config = {dpid_lib.str_to_dpid('000000000000001'): {'bridge': {'priority': 0x8000}}, dpid_lib.str_to_dpid('000000000000002'): {'bridge': {'priority': 0x9000}}, dpid_lib.str_to_dpid('000000000000003'): {'bridge': {'priority': 0xa000}}} self.stp.set_config(config)
def __init__(self, *args, **kwargs): super(SimpleSwitchLacp, self).__init__(*args, **kwargs) self.mac_to_port = {} self._lacp = kwargs['lacplib'] # in this sample application, bonding i/fs of the switchs # shall be set up as follows: # - the port 1 and 2 of the datapath 1 face the slave i/fs. # - the port 3, 4 and 5 of the datapath 1 face the others. # - the port 1 and 2 of the datapath 2 face the others. self._lacp.add( dpid=str_to_dpid('0000000000000001'), ports=[1, 2]) self._lacp.add( dpid=str_to_dpid('0000000000000001'), ports=[3, 4, 5]) self._lacp.add( dpid=str_to_dpid('0000000000000002'), ports=[1, 2])
def _links(self, req, **kwargs): dpid = None if 'dpid' in kwargs: dpid = dpid_lib.str_to_dpid(kwargs['dpid']) links = get_link(self.topology_api_app, dpid) body = json.dumps([link.to_dict() for link in links]) return Response(content_type='application/json', body=body)
def create_vxlan_tunnel(self, req, **kwargs): app = self.cluster_controller_app dpid = libdpid.str_to_dpid(kwargs['dpid']) tunnel_name = kwargs['tunnel_name'] port_number = kwargs['port_number'] peer_ip = kwargs['peer_ip'] app.create_vxlan_tunnel(dpid, tunnel_name, port_number, peer_ip)
def _add_nat_entry(self, req, dpid, **kwargs): logging.info('[REST_API : NAT ENTRY ADD] Calling') dp_id = dpid_lib.str_to_dpid(dpid) if dp_id in self.ofuro_spp._OFSW_LIST.keys(): ofsw = self.ofuro_spp._OFSW_LIST[dp_id] else: logging.info('[** NAT ADD REQUEST : ERROR] OFSW Not Found') return wsgi.Response(status=400) new_nat_entry =eval(req.body) ret = self.check_entry(ofsw, new_nat_entry) if ret != "": logging.info('[** NAT ADD REQUEST : ERROR] Same Entry Found :SW_IP %s', ret) return wsgi.Response(status=400) try: entry_uuid = Nat_Ready(ofsw, "NULL", new_nat_entry) nat_entry = ofsw.ofuro_data.get_nat_entry(entry_uuid) content_body = json.dumps(nat_entry, indent=4) return wsgi.Response(status=200, body=content_body, headers=self.headers) except: logging.info('[** NAT ADD REQUEST : ERROR] ENTRY Can not set') return wsgi.Response(status=400)
def _switches(self, req, **kwargs): dpid = None if 'dpid' in kwargs: dpid = dpid_lib.str_to_dpid(kwargs['dpid']) switches = get_switch(self.topology_api_app, dpid) body = json.dumps([switch.to_dict() for switch in switches]) return Response(content_type='application/json', body=body)
def _hosts(self, req, **kwargs): body = None db = database(DB_PATH) if 'dpid' in kwargs: dpid = dpid_lib.str_to_dpid(kwargs['dpid']) rcd_dpid = selectDPID(dpid=dpid) host_of_dpid = [] tmp = {'mac':'a', 'port':0,'ip':'a', 'slave':1} for x in rcd_dpid: tmp['mac'], tmp['port'], tmp['ip'], tmp['slave'] = x[0].encode('utf-8'), x[1], x[2].encode('utf-8'), x[3] hosts_of_dpid.append(dict(tmp)) body = json.dumps(hosts_of_dpid) else: rcd_dev = db.selectDEVICE() hosts = [] tmp = {'user_id':0, 'dpid':0,'mac':'a', 'vlan':0, 'ip': 'a', 'port':0} #add gateway tmp['mac'] = db.selectGATEWAY()[0][0].encode('utf-8') tmp['ip'] = db.selectGATEWAY()[0][1].encode('utf-8') gw_dpid = db.getDPIDBySlave(mac_addr=tmp['mac']) if None != gw_dpid: tmp['port'] = db.findDPIDByX(gw_dpid,'MAC_ADDR',tmp['mac'])[0][0] tmp['dpid'] = dpid_lib.dpid_to_str(gw_dpid) hosts.append(dict(tmp)) #add host for dev in rcd_dev: tmp['mac'], tmp['vlan'], tmp['user_id'] = dev[0].encode('utf-8'), dev[1], dev[2] dpid = db.getDPIDBySlave(mac_addr=tmp['mac']) tmp['dpid'] = dpid_lib.dpid_to_str(dpid) rcd_host = db.findDPIDByX(dpid,'MAC_ADDR',tmp['mac']) tmp['port'], tmp['ip'] = rcd_host[0][0], rcd_host[0][1].encode('utf-8') hosts.append(dict(tmp)) body = json.dumps(hosts) return Response(content_type='application/json', body=body)
def _add_arp_entry(self, req, dpid, **kwargs): logging.info('[REST_API : ARP ENTRY ADD] Calling') dp_id = dpid_lib.str_to_dpid(dpid) if dp_id in self.ofuro_spp._OFSW_LIST.keys(): ofsw = self.ofuro_spp._OFSW_LIST[dp_id] else: logging.info('[** ARP ADD REQUEST : ERROR] OFSW Not Found') return wsgi.Response(status=400) new_arp_entry =eval(req.body) # ret = self.check_arp_entry(ofsw, new_arp_entry) # if ret != "": # logging.info('[** ARP ADD REQUEST : ERROR] Same Entry Found :SW_IP %s', ret) # return wsgi.Response(status=400) logging.info("ARP DATA = %s", new_arp_entry) try: entry = Add_Arp_Entry(ofsw, new_arp_entry) content_body = json.dumps(entry, indent=4) return wsgi.Response(status=200, body=content_body, headers=self.headers) except: logging.info('[** ARP ADD REQUEST : ERROR] ENTRY Can not set') return wsgi.Response(status=400)
def lldp_parse(data): pkt = packet.Packet(data) i = iter(pkt) eth_pkt = six.next(i) assert type(eth_pkt) == ethernet.ethernet lldp_pkt = six.next(i) if type(lldp_pkt) != lldp.lldp: raise LLDPPacket.LLDPUnknownFormat() tlv_chassis_id = lldp_pkt.tlvs[0] if tlv_chassis_id.subtype != lldp.ChassisID.SUB_LOCALLY_ASSIGNED: raise LLDPPacket.LLDPUnknownFormat( msg='unknown chassis id subtype %d' % tlv_chassis_id.subtype) chassis_id = tlv_chassis_id.chassis_id.decode('utf-8') if not chassis_id.startswith(LLDPPacket.CHASSIS_ID_PREFIX): raise LLDPPacket.LLDPUnknownFormat( msg='unknown chassis id format %s' % chassis_id) src_dpid = str_to_dpid(chassis_id[LLDPPacket.CHASSIS_ID_PREFIX_LEN:]) tlv_port_id = lldp_pkt.tlvs[1] if tlv_port_id.subtype != lldp.PortID.SUB_PORT_COMPONENT: raise LLDPPacket.LLDPUnknownFormat( msg='unknown port id subtype %d' % tlv_port_id.subtype) port_id = tlv_port_id.port_id if len(port_id) != LLDPPacket.PORT_ID_SIZE: raise LLDPPacket.LLDPUnknownFormat( msg='unknown port id %d' % port_id) (src_port_no, ) = struct.unpack(LLDPPacket.PORT_ID_STR, port_id) return src_dpid, src_port_no
def __init__(self, *args, **kwargs): super(Valve, self).__init__(*args, **kwargs) self.mac_to_port = {} self._snoop = kwargs['igmplib'] # if you want a switch to operate as a querier, # set up as follows: self._snoop.set_querier_mode( dpid=str_to_dpid('0000000000000001'), server_port=2) # dpid the datapath id that will operate as a querier. # server_port a port number which connect to the multicast # server. # # NOTE: you can set up only the one querier. # when you called this method several times, # only the last one becomes effective. # Read in config file self.portdb = None self.vlandb = {} with open('valve.yaml', 'r') as stream: self.portdb = yaml.load(stream) for port in self.portdb: vlans = self.portdb[port]['vlans'] ptype = self.portdb[port]['type'] if type(vlans) is list: for vlan in vlans: if vlan not in self.vlandb: self.vlandb[vlan] = {'tagged': [], 'untagged': []} self.vlandb[vlan][ptype].append(port) else: if vlans not in self.vlandb: self.vlandb[vlans] = {'tagged': [], 'untagged': []} self.vlandb[vlans][ptype].append(port)
def _hosts(self, req, **kwargs): dpid = None if 'dpid' in kwargs: dpid = dpid_lib.str_to_dpid(kwargs['dpid']) hosts = get_host(self.topology_api_app, dpid) body = json.dumps([host.to_dict() for host in hosts]) return Response(content_type='application/json', body=body)
def send_arp_reply(self, src_ip, src_mac, dst_ip, dst_mac): """ Construct an arp reply given the specific arguments and send it through switch connecting dst_mac """ pos = self.vm_manager.get_position(dst_mac) if pos is not None: # If I know to whom to forward back this ARP reply _, dst_dpid, dst_port = pos # Forward ARP reply packet_reply = self.create_arp_packet(src_mac, dst_mac, dst_ip, src_ip, arp.ARP_REPLY) dst_datapath = self.dpset.get(str_to_dpid(dst_dpid)) dst_ofproto_parser = dst_datapath.ofproto_parser dst_ofproto = dst_datapath.ofproto actions_out = [dst_ofproto_parser.OFPActionOutput(int(dst_port))] dst_datapath.send_msg( dst_ofproto_parser.OFPPacketOut( datapath=dst_datapath, buffer_id=0xffffffff, in_port=dst_ofproto.OFPP_LOCAL, data=packet_reply.data, actions=actions_out)) LOGGER.info("Send ARP reply of (ip=%s) to (ip=%s): ", src_ip, dst_ip)
def set_gateway_bounce_flow(self, dpid, vmac_new, vmac_old, topology): """Set up a flow at gateway towards local dpid_old during live migration to prevent unnecessary multi-datacenter traffic""" dpid_gws = topology.get_gateways() for dpid_gw in dpid_gws: gw_fwd_port = topology.get_fwd_port(dpid_gw, dpid) datapath_gw = self.dpset.get(str_to_dpid(dpid_gw)) ofproto = datapath_gw.ofproto ofproto_parser = datapath_gw.ofproto_parser actions = [ofproto_parser.OFPActionSetField(eth_dst=vmac_new), ofproto_parser.OFPActionOutput(int(gw_fwd_port))] instructions = [ datapath_gw.ofproto_parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, actions)] match_gw = ofproto_parser.OFPMatch(eth_dst=vmac_old) self.set_flow(datapath=datapath_gw, match=match_gw, table_id=FlowManager.PRIMARY_TABLE, priority=i_priority.DATA_FWD_LOCAL, flags=ofproto.OFPFF_SEND_FLOW_REM, hard_timeout=CONF.arp_timeout, command=ofproto.OFPFC_ADD, instructions=instructions)
def set_topology_flow(self, dpid, mac, mask, port): """Set up a microflow for unicast on switch DPID towards MAC""" datapath = self.dpset.get(str_to_dpid(dpid)) ofproto = datapath.ofproto ofproto_parser = datapath.ofproto_parser priority = i_priority.DATA_FWD_DCENTER if self.multi_tenancy: table_id = FlowManager.SECONDARY_TABLE else: table_id = FlowManager.PRIMARY_TABLE actions = [ofproto_parser.OFPActionOutput(int(port))] instructions_src = [ datapath.ofproto_parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, actions)] match_src = ofproto_parser.OFPMatch(eth_dst=(mac, mask)) self.set_flow(datapath=datapath, match=match_src, table_id=table_id, priority=priority, flags=ofproto.OFPFF_SEND_FLOW_REM, command=ofproto.OFPFC_ADD, instructions=instructions_src) LOGGER.info("New forward flow: (switch=%s) -> (mac=%s, mask=%s)", dpid, mac, mask)
def analyze_switch(switches): nodes_swt = [] i = 1 for swt in switches: tmp = {'name':dpid_lib.str_to_dpid(swt['dpid']),'flag':0 } i = i + 1 nodes_swt.append(dict(tmp)) return nodes_swt
def __init__(self, *args, **kwargs): super(SimpleSwitch13, self).__init__(*args, **kwargs) # super(SimpleMonitor13, self).__init__(*args, *kwargs) self.mac_to_port = {} self.stp = kwargs['stplib'] self.datapath = {} # self.monitor_thread = hub.spawn(self._monitor) ##amostra do stplib config ##referencia stplib.stp.set_config() para detalhes config = {dpid_lib.str_to_dpid('0000000000000001'): {'bridge': {'priority': 0x8000}}, dpid_lib.str_to_dpid('0000000000000002'): {'bridge': {'priority': 0x9000}}, dpid_lib.str_to_dpid('0000000000000003'): {'bridge': {'priority': 0xa000}}} self.stp.set_config(config)
def __init__(self, *args, **kwargs): super(SimpleSwitchIgmp, self).__init__(*args, **kwargs) self.mac_to_port = {} self._snoop = kwargs['igmplib'] # if you want a switch to operate as a querier, # set up as follows: self._snoop.set_querier_mode( dpid=str_to_dpid('0000000000000001'), server_port=2)
def _do_key(dpid, key, func, ret_func): dpid = dpid_lib.str_to_dpid(dpid) try: ret = func(dpid, key) except KeyError: return Response(status=httplib.NOT_FOUND, body='no dpid/key is found %s %s' % (dpid_lib.dpid_to_str(dpid), key)) return ret_func(ret)
def _handler_get_switch_neigh(self, req, **kwargs): if 'dpid' not in kwargs: return Response(status=400) dpid = dpid_lib.str_to_dpid(kwargs['dpid']) neighs = self._get_neigh(dpid) body = json.dumps([neigh.to_dict() for neigh in neighs]) return Response(content_type = 'application/json', body = body)
def _put_stat_info(self, req, **kwargs): logging.log(logging.INFO, "[INFO %s] SimpleSwitchController._put_stat_info" % time.strftime("%Y-%m-%d %H:%M:%S")) new_entry = eval(req.body) logging.log(logging.INFO, "[INFO %s] SimpleSwitchController._put_stat_info %s" % (time.strftime("%Y-%m-%d %H:%M:%S"), str(new_entry))) datapath_id = dpid_lib.str_to_dpid(kwargs['dpid']) flow_count = eval(kwargs['count'])
def _handler_get_links(self, req, **kwargs): if 'dpid' not in kwargs: return Response(status=400) dpid = dpid_lib.str_to_dpid(kwargs['dpid']) links = self._get_link(dpid) body = json.dumps([link.to_dict() for link in links]) return Response(content_type = 'application/json', body = body)
def update(self, req, network_id, dpid, port_id, **_kwargs): dpid = dpid_lib.str_to_dpid(dpid) port_id = int(port_id) try: self.nw.update_port(network_id, dpid, port_id) except NetworkNotFound: return Response(status=404) return Response(status=200)
def get_ofs(self, dp_id): if len(self) == 0: raise ValueError('qos sw is not connected.') dps = {} if dp_id == REST_ALL: dps = self else: try: dpid = dpid_lib.str_to_dpid(dp_id) except: raise ValueError('Invalid switchID.') if dpid in self: dps = {dpid: self[dpid]} else: msg = 'qos sw is not connected. : switchID=%s' % dp_id raise ValueError(msg) return dps
def list_ip_table(self, req, **kwargs): simple_switch = self.simple_switch_app dpid = dpid_lib.str_to_dpid(kwargs['dpid']) if dpid not in simple_switch.ipv4_to_port: return Response(status=404) if dpid not in simple_switch.mac_to_port: return Response(status=404) #Adding ip_to_port and mac_to_port as output of query # ip_table = simple_switch.ipv4_to_port.get(dpid, {}) mac_table = simple_switch.mac_to_port.get(dpid, {}) bodyResponse = { #"ip_table": ip_table, "mac_table": mac_table } return Response(content_type='application/json', body=json.dumps(bodyResponse))
def set_config(self, req, **kwargs): dpid = dpid_lib.str_to_dpid(kwargs['dpid']) try: new_config = req.json if req.body else {} except ValueError: raise Response(status=400) if dpid not in self.ctrl.switches: self.ctrl.switches[dpid] = SwitchStatus() LOG.info("%016x: post %s", dpid, new_config) status = self.ctrl.switches[dpid] if 'disused' in new_config: for p in new_config['disused']: LOG.info("%016x: dropping %d", dpid, p) status.discard_port(p) if 'slices' in new_config: for ps in new_config['slices']: ps = set(ps) LOG.info("%016x: creating %s", dpid, list(ps)) status.create_slice(ps) if 'dhcp' in new_config: dp = api.get_datapath(self.ctrl, dpid) if new_config['dhcp']: self.ctrl.pass_dhcp(dp) else: self.ctrl.drop_dhcp(dp) status.revalidate() LOG.info("%016x: completed changes", dpid) if 'learn' in new_config: dp = api.get_datapath(self.ctrl, dpid) mac = new_config['learn']['mac'] port = new_config['learn']['port'] timeout = new_config['learn']['timeout'] \ if 'timeout' in new_config['learn'] \ else 600 self.ctrl._learn(dp, port, mac, timeout=timeout); body = json.dumps(status.get_config()) + "\n" return Response(content_type='application/json', body=body)
def set_tenant_filter(self, dpid, vmac, mac): """Set up a microflow on a switch (dpid) to only allow intra-tenant unicast""" if not self.multi_tenancy: return datapath = self.dpset.get(str_to_dpid(dpid)) ofproto = datapath.ofproto ofproto_parser = datapath.ofproto_parser match = ofproto_parser.OFPMatch(eth_src=mac, eth_dst=(vmac, VmacManager.TENANT_MASK)) inst = [ofproto_parser.OFPInstructionGotoTable( FlowManager.SECONDARY_TABLE)] self.set_flow(datapath=datapath, match=match, table_id=FlowManager.PRIMARY_TABLE, priority=i_priority.DATA_FWD_TENANT, flags=ofproto.OFPFF_SEND_FLOW_REM, command=ofproto.OFPFC_ADD, instructions=inst)
def __init__(self, switches_json=None, links_json=None): super(Topology, self).__init__() self['switches'] = [] if switches_json: for s in json.loads(switches_json): ports = [] for p in s['ports']: ports.append(Port.from_rest_dict(p)) switch = Switch(str_to_dpid(s['dpid']), ports) self['switches'].append(switch) self['links'] = [] if links_json: for l in json.loads(links_json): link = Link(Port.from_rest_dict(l['src']), Port.from_rest_dict(l['dst'])) self['links'].append(link) self['ports'] = [] for switch in self['switches']: self['ports'].extend(switch.ports)
def _regist_ovs_fw(dp): try: dpid = dpid_lib.str_to_dpid(dp) except: raise ValueError('Invalid switchID') datapath = MainController.LIST_Nodes[dpid] try: ovs_fw = Firewall_module(datapath) except OFPUnknownVersion as message: MainController._LOGGER.info('dpid=%s: %s', dpid_str, message) return MainController.LIST_FW.setdefault(dpid, ovs_fw) ovs_fw.flush_all(datapath) ovs_fw.set_arp_flow() # ovs_fw.set_log_enable() MainController._LOGGER.info('Node dpid=%s: Joined as firewall.',dp) msg = {'result': 'success', 'details': 'firewall running.'} body = json.dumps(msg) return Response(content_type='application/json', body=body)
def set_local_flow(self, dpid, vmac, mac, port, flow_add=True, timeout=0): """Set up a microflow on a switch (dpid) towards a guest (mac) The rule matches on dst vmac, rewrites it to mac and forwards to the appropriate port. mac can be another vmac. """ datapath = self.dpset.get(str_to_dpid(dpid)) ofproto = datapath.ofproto ofproto_parser = datapath.ofproto_parser if flow_add: flow_cmd = ofproto.OFPFC_ADD else: flow_cmd = ofproto.OFPFC_MODIFY_STRICT actions = [ofproto_parser.OFPActionSetField(eth_dst=mac), ofproto_parser.OFPActionOutput(int(port))] instructions = [ datapath.ofproto_parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, actions)] match = ofproto_parser.OFPMatch(eth_dst=vmac) self.set_flow(datapath=datapath, match=match, table_id=FlowManager.PRIMARY_TABLE, priority=i_priority.DATA_FWD_LOCAL, flags=ofproto.OFPFF_SEND_FLOW_REM, hard_timeout=timeout, command=flow_cmd, instructions=instructions) if self.multi_tenancy: self.set_flow(datapath=datapath, match=match, table_id=FlowManager.SECONDARY_TABLE, priority=i_priority.DATA_FWD_LOCAL, hard_timeout=timeout, flags=ofproto.OFPFF_SEND_FLOW_REM, command=flow_cmd, instructions=instructions)
def insert_dhcp_netinformation(self, req, **kwargs): dpid = dpid_lib.str_to_dpid(kwargs['dpid']) try: new_entry = req.json if req.body else {} except ValueError: return Response(status=400) if new_entry: dns = '8.8.8.8' for field in ["ipaddress", "netmask", "address"]: if field not in new_entry: return Response(status=400) if 'dns' in new_entry: dns = new_entry['dns'] available_address = [] if 'startip' in new_entry and 'endip' in new_entry: startip = int(new_entry['startip'].split('.')[-1]) endip = int(new_entry['endip'].split('.')[-1]) base = ".".join(new_entry['startip'].split('.')[:-1]) if startip >= endip: return Response(status=400) for i in range(startip, endip + 1): available_address.append(base + "." + "%02.0f" % (i)) if dpid not in self.dhcp_server.switches: self.dhcp_server.switches[dpid] = { "available_address": available_address, "hosts": {} } self.dhcp_server.switches[dpid][ 'ipaddress'] = new_entry['ipaddress'] self.dhcp_server.switches[dpid]['netmask'] = new_entry['netmask'] self.dhcp_server.switches[dpid]['address'] = new_entry['address'] self.dhcp_server.switches[dpid]['dns'] = dns body = json.dumps(self.dhcp_server.switches[dpid]) return Response(content_type='application/json', body=body) return Response(status=404)
def list_mac_table(self, req, **kwargs) -> Response: """ Retrieves and returns the MAC address table of the specified switch. The REST API is called by the URL specified by the second argument. If the HTTP method at that time is GET, the list_mac_table method is called. This method acquires the MAC address table corresponding to the data path ID specified in the {dpid} part, converts it to the JSON format and returns it to the caller. If the data path ID of an unknown switch, which is not connected to Ryu, is specified, response code 404 is returned. :param kwargs: Expects an argument called dpid which contains the dpid of the switch from which you want to dump the MAC address table :return: Returns JSON containing the MAC address table of the specified switch. """ simple_switch = self.simple_switch_app dpid = dpid_lib.str_to_dpid(kwargs['dpid']) if dpid not in simple_switch.mac_to_port: return Response(status=404) mac_table = simple_switch.mac_to_port.get(dpid, {}) body = json.dumps(mac_table) return Response(content_type='application/json', body=body)
def _unregist_ovs_fw(dp): try: dpid = dpid_lib.str_to_dpid(dp) except: raise ValueError('Invalid switchID.') datapath = MainController.LIST_Nodes[dpid] if dpid in MainController.LIST_FW: del MainController.LIST_FW[dpid] try: ovs_fw = Firewall_module(datapath) except OFPUnknownVersion as message: MainController._LOGGER.info('dpid=%s: %s', dpid_str, message) return ovs_fw.flush_all(datapath) Switch_module(datapath).add_table_miss(datapath) MainController._LOGGER.info('Node dpid=%s: Removed as firewall.',dp) msg = {'result': 'success', 'details': 'firewall stopped.'} else: msg = {'result': 'failed', 'details': 'switch is not firewall.'} body = json.dumps(msg) return Response(content_type='application/json', body=body)
def _set_flow_table(self, dpid_str, entry): try: dpid = dpid_lib.str_to_dpid(dpid_str) contr_inst = self.fcapf_network_controller if dpid not in contr_inst.mac_to_port: return Response(status=404) datapath = contr_inst.switches.get(dpid) dl_type = entry['dltype'] action = entry['action'] if action == 'normal': action = ofproto_v1_3.OFPP_NORMAL ip_src = entry['ipsrc'] ip_dest = entry['ipdest'] if datapath is not None: parser = datapath.ofproto_parser # from known device to new device actions = [parser.OFPActionOutput(action)] if dl_type == "ip": port = entry['inport'] match = parser.OFPMatch(in_port=port, ipv4_src=ip_src, ipv4_dst=ip_dest, eth_type=0x0800) elif dl_type == "arp": match = parser.OFPMatch(arp_spa=ip_src, arp_tpa=ip_dest, eth_type=0x0806) else: LOG.error("Wrong input!!") self._add_flow(datapath, 1, match, actions) else: LOG.error("Datapath not found!!") except: LOG.error("Unexpected error in _set_flow_table:", sys.exc_info()[0]) raise
def lldp_parse(data): pkt = packet.Packet(data) i = iter(pkt) eth_pkt = six.next(i) assert type(eth_pkt) == ethernet.ethernet lldp_pkt = six.next(i) # return 2333, 2333, topo if type(lldp_pkt) != lldp.lldp: raise LLDPPacket.LLDPUnknownFormat() tlvs = lldp_pkt.tlvs tlv_chassis_id = lldp_pkt.tlvs[0] if tlv_chassis_id.subtype != lldp.ChassisID.SUB_LOCALLY_ASSIGNED: raise LLDPPacket.LLDPUnknownFormat( msg='unknown chassis id subtype %d' % tlv_chassis_id.subtype) chassis_id = tlv_chassis_id.chassis_id.decode('utf-8') if not chassis_id.startswith(LLDPPacket.CHASSIS_ID_PREFIX): raise LLDPPacket.LLDPUnknownFormat( msg='unknown chassis id format %s' % chassis_id) src_dpid = str_to_dpid(chassis_id[LLDPPacket.CHASSIS_ID_PREFIX_LEN:]) tlv_port_id = lldp_pkt.tlvs[1] if tlv_port_id.subtype != lldp.PortID.SUB_PORT_COMPONENT: raise LLDPPacket.LLDPUnknownFormat( msg='unknown port id subtype %d' % tlv_port_id.subtype) port_id = tlv_port_id.port_id if len(port_id) != LLDPPacket.PORT_ID_SIZE: raise LLDPPacket.LLDPUnknownFormat(msg='unknown port id %d' % port_id) (src_port_no, ) = struct.unpack(LLDPPacket.PORT_ID_STR, port_id) if len(lldp_pkt.tlvs) == 5: tlv_topo = lldp_pkt.tlvs[3] return src_dpid, src_port_no, tlv_topo return src_dpid, src_port_no
def port_status_handler(self, ev): msg = ev.msg reason = msg.reason datapath = msg.datapath ofproto = datapath.ofproto ofpport = msg.desc dpid = datapath.id dpid_str = dpid_lib.dpid_to_str(dpid) # Detecting a host down (Possibly moving?) if reason == ofproto.OFPPR_DELETE: port_no = ofpport.port_no mac = False try: mac = [ dst for src, dst, attrib in self.net.edges(data=True) if src == dpid and attrib['port'] == port_no ][0] #for edges in self.net.edges(data=True): except IndexError: mac = '' self.logger.info('There isn\'t a known host with mac %s', mac) # Deleting Flows from switches if mac: for switch in self.switches: # Removing datapath = ofctl_api.get_datapath( self, dpid_lib.str_to_dpid(switch)) pprint.pprint(mac) self.delete_flow(datapath, mac) # Deleting host from NetworkX self.net.remove_node(mac) self.logger.debug('[Event] Host Down: dpid=%s,port=%d,mac=%s]', dpid_str, port_no, mac) else: self.logger.debug('[Event] Port status change: %s:%s', dpid_str, ofpport.port_no)
def show_queue_status(self, req, **kwargs): simple_switch = self.simpl_switch_spp dpid = dpid_lib.str_to_dpid(kwargs['dpid']) table = open('file.txt', 'r') print 'dpid is "%s"' % dpid i = 0 method = 'GET' #tmp for line in table.readlines(): if line.split(';')[0] == str(dpid): drv = line.split(';')[1] drv_list.gotodrv(drv, method, url) #print line.split(';')[1]#debug i += 1 table.close() if i == 0: print 'not found' #return Response(status=404) elif i == 1: print 'done' #return Response(status=200) else: print 'table err' #return Response(status=500)
def change_rule(self, req, **kwargs): simple_switch = self.simpl_switch_spp dpid = dpid_lib.str_to_dpid(kwargs['dpid']) content = req.body xml_file = ET.ElementTree(ET.fromstring(content)) my_parser = etree.XMLParser(remove_blank_text = True) ID = [] cookies = xml_file.find('.//Cookie') if cookies is not None: for cookie in cookies: my_id = cookie.attrib['id'] ID.append(my_id) cookie_tag = int(ID[0]) xpath_IP_source = "descendant::Source/descendant::address" source['IP'] = root_node.xpath(xpath_IP_source)[0].text xpath_IP_target = "descendant::Target/descendant::address" target['IP'] = root_node.xpath(xpath_IP_target)[0].text security = xml_file.find('.//security') my_class = security.attrib['class'] impact = xml_file.find('.//Impact') my_impact = impact.attrib['severity'] ## Get the impact severity from security alert customer = xml_file.find('.//Customer') my_customer = customer.attrib['network'] act = xml_file.find('.//Action') my_act = act.attrib['request'] ## Get the action requested from the security alert event = xml_file.find('.//event') my_event = security.attrib['type'] ## Get the type of event from the security alert if(my_event == 'icmp-flood' my_class == 'suspicious' and my_impact == 'high'): xml_file1 = etree.parse("security.xml") action = xml_file1.find('.//action') my_action = action.attrib['action']
def __init__(self, *args, **kwargs): super(SimpleSwitch13, self).__init__(*args, **kwargs) self.mac_to_port = {} self.mac_table = [] self.stp = kwargs['stplib'] config = { dpid_lib.str_to_dpid('0000000000000301'): { 'bridge': { 'priority': 0x8000 } }, dpid_lib.str_to_dpid('0000000000000302'): { 'bridge': { 'priority': 0x9000 } }, dpid_lib.str_to_dpid('0000000000000303'): { 'bridge': { 'priority': 0xa000 } }, dpid_lib.str_to_dpid('0000000000000304'): { 'bridge': { 'priority': 0xb000 } }, dpid_lib.str_to_dpid('0000000000000305'): { 'bridge': { 'priority': 0xc000 } }, dpid_lib.str_to_dpid('0000000000000306'): { 'bridge': { 'priority': 0xd000 } } } self.stp.set_config(config)
def _match_fn(row): row_dpid = dpidlib.str_to_dpid(str(row.datapath_id[0])) return row_dpid == datapath_id
def __init__(self, *args, **kwargs): super(SimpleSwitchLACP13, self).__init__(*args, **kwargs) self.mac_to_port = {} self._lacp = kwargs['lacplib'] self._lacp.add(dpid=str_to_dpid('0000000000000001'), ports=[1, 2])
def get_switch_by_id(self, **kwargs): if 'dpid' in kwargs: dpid = dpid_lib.str_to_dpid(kwargs['dpid']) switches = api.get_datapath(self, dpid) body = json.dumps([switch.to_dict() for switch in switches]) return Response(content_type='application/json', body=body)
def _add_flows(self): ofp_datapath = self._dpset.get(dpid_lib.str_to_dpid(self._DATAPATH_ID)) ofp_protocol = ofp_datapath.ofproto ofp_parser = ofp_datapath.ofproto_parser self.logger.info("add flows: [dp=%s]", dpid_lib.dpid_to_str(ofp_datapath.id)) # Flow 1: ARP Request H1 -> H2 flow1_match = ofp_parser.OFPMatch(in_port=0, dl_type=0x0000, dl_src='aa:bb:cc:dd:ee:ff', dl_dst='ff:ee:dd:cc:bb:aa', nw_src='1.2.3.4', nw_dst='4.3.2.1') flow1_actions = [ofp_parser.OFPActionOutput(port=0)] # flow1_actions = [ofp_parser.OFPActionOutput(ofp_protocol.OFPP_FLOOD)] flow1_mod = ofp_parser.OFPFlowMod(datapath=ofp_datapath, match=flow1_match, command=ofp_protocol.OFPFC_ADD, actions=flow1_actions) ofp_datapath.send_msg(flow1_mod) # Flow 2: ARP Reply H1 -> H2 flow2_match = ofp_parser.OFPMatch(in_port=0, dl_type=0x0000, dl_src='aa:bb:cc:dd:ee:ff', dl_dst='ff:ee:dd:cc:bb:aa', nw_src='1.2.3.4', nw_dst='4.3.2.1') flow2_actions = [ofp_parser.OFPActionOutput(port=0)] # flow2_actions = [ofp_parser.OFPActionOutput(ofp_protocol.OFPP_FLOOD)] flow2_mod = ofp_parser.OFPFlowMod(datapath=ofp_datapath, match=flow2_match, command=ofp_protocol.OFPFC_ADD, actions=flow2_actions) ofp_datapath.send_msg(flow2_mod) # Flow 3: IP H1 -> H2 flow3_match = ofp_parser.OFPMatch(in_port=0, dl_type=0x0000, dl_src='aa:bb:cc:dd:ee:ff', dl_dst='ff:ee:dd:cc:bb:aa', nw_src='1.2.3.4', nw_dst='4.3.2.1') flow3_actions = [ofp_parser.OFPActionOutput(port=0)] # flow3_actions = [ofp_parser.OFPActionOutput(ofp_protocol.OFPP_FLOOD)] flow3_mod = ofp_parser.OFPFlowMod(datapath=ofp_datapath, match=flow3_match, command=ofp_protocol.OFPFC_ADD, actions=flow3_actions) ofp_datapath.send_msg(flow3_mod) # Flow 4: ARP Request H2 -> H1 flow4_match = ofp_parser.OFPMatch(in_port=0, dl_type=0x0000, dl_src='ff:ee:dd:cc:bb:aa', dl_dst='aa:bb:cc:dd:ee:ff', nw_src='4.3.2.1', nw_dst='1.2.3.4') flow4_actions = [ofp_parser.OFPActionOutput(port=0)] # flow4_actions = [ofp_parser.OFPActionOutput(ofp_protocol.OFPP_FLOOD)] flow4_mod = ofp_parser.OFPFlowMod(datapath=ofp_datapath, match=flow4_match, command=ofp_protocol.OFPFC_ADD, actions=flow4_actions) ofp_datapath.send_msg(flow4_mod) # Flow 5: ARP Reply H2 -> H1 flow5_match = ofp_parser.OFPMatch(in_port=0, dl_type=0x0000, dl_src='ff:ee:dd:cc:bb:aa', dl_dst='aa:bb:cc:dd:ee:ff', nw_src='4.3.2.1', nw_dst='1.2.3.4') flow5_actions = [ofp_parser.OFPActionOutput(port=0)] # flow5_actions = [ofp_parser.OFPActionOutput(ofp_protocol.OFPP_FLOOD)] flow5_mod = ofp_parser.OFPFlowMod(datapath=ofp_datapath, match=flow5_match, command=ofp_protocol.OFPFC_ADD, actions=flow5_actions) ofp_datapath.send_msg(flow5_mod) # Flow 6: IP H2 -> H1 flow6_match = ofp_parser.OFPMatch(in_port=0, dl_type=0x0000, dl_src='ff:ee:dd:cc:bb:aa', dl_dst='aa:bb:cc:dd:ee:ff', nw_src='4.3.2.1', nw_dst='1.2.3.4') flow6_actions = [ofp_parser.OFPActionOutput(port=0)] # flow6_actions = [ofp_parser.OFPActionOutput(ofp_protocol.OFPP_FLOOD)] flow6_mod = ofp_parser.OFPFlowMod(datapath=ofp_datapath, match=flow6_match, command=ofp_protocol.OFPFC_ADD, actions=flow6_actions) ofp_datapath.send_msg(flow6_mod)
def _upstream_collector(self, pkt): (version, msg_type, msg_len, xid) = ofproto_parser.header(pkt) # Switch configuration messages if msg_type == ofproto_v1_0.OFPT_FEATURES_REPLY: # print("Reply xid: " + hex(xid)) msg = ofproto_v1_0_parser.OFPSwitchFeatures.parser(self.datapath, version, msg_type, msg_len, xid, pkt) match = ofproto_v1_0_parser.OFPMatch(dl_type=ETH_TYPE_LLDP, dl_dst=lldp.LLDP_MAC_NEAREST_BRIDGE) cookie = 0 command = ofproto_v1_0.OFPFC_ADD idle_timeout = hard_timeout = 0 priority = 0 buffer_id = ofproto_v1_0.OFP_NO_BUFFER out_port = ofproto_v1_0.OFPP_NONE flags = 0 actions = [ofproto_v1_0_parser.OFPActionOutput(ofproto_v1_0.OFPP_CONTROLLER)] mod = ofproto_v1_0_parser.OFPFlowMod(self.datapath, match, cookie, command, idle_timeout, hard_timeout, priority, buffer_id, out_port, flags, actions) mod.serialize() self.id = msg.datapath_id self.ports = msg.ports # print(str(self.id) + " : Receive Features Reply Message") # print(msg) for port in self.ports.values(): db_message = {"switch_id": hex(self.id), "port_no": port.port_no, "hw_addr": port.hw_addr, "timestamp": datetime.datetime.utcnow()} try: self.db.switch_port.insert_one(db_message) except: if(self.id != None): print(datetime.datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S') + " : ERROR [" + str(hex(self.id)) + "] --- Failed to write data into database") else: print(datetime.datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S') + " : ERROR [" + str(self.id) + "] --- Failed to write data into database") pkt_lldp = packet.Packet() dst = BROADCAST_STR src = port.hw_addr ethertype = ETH_TYPE_LLDP eth_pkt = ethernet.ethernet(dst, src, ethertype) pkt_lldp.add_protocol(eth_pkt) tlv_chassis_id = lldp.ChassisID( subtype=lldp.ChassisID.SUB_LOCALLY_ASSIGNED, chassis_id='dpid:%s' % dpid_to_str(self.id)) tlv_port_id = lldp.PortID(subtype=lldp.PortID.SUB_PORT_COMPONENT, port_id=struct.pack('!I', port.port_no)) tlv_ttl = lldp.TTL(ttl=120) tlv_desc = lldp.PortDescription(port_description="ProxyTopologyMonitorLLDP") tlv_end = lldp.End() tlvs = (tlv_chassis_id, tlv_port_id, tlv_ttl, tlv_desc, tlv_end) lldp_pkt = lldp.lldp(tlvs) pkt_lldp.add_protocol(lldp_pkt) pkt_lldp.serialize() actions = [ofproto_v1_0_parser.OFPActionOutput(port.port_no)] out = ofproto_v1_0_parser.OFPPacketOut( datapath=self.datapath, in_port=ofproto_v1_0.OFPP_CONTROLLER, buffer_id=ofproto_v1_0.OFP_NO_BUFFER, actions=actions, data=pkt_lldp.data) out.serialize() try: self.switch_socket.send(out.buf) except: if(self.id != None): print(datetime.datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S') + " : ERROR [" + str(hex(self.id)) + "] --- Broken Pipe (Downstream : LLDP Message)") else: print(datetime.datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S') + " : ERROR [" + str(self.id) + "] --- Broken Pipe (Downstream : LLDP Message)") # self._close() pass elif msg_type == ofproto_v1_0.OFPT_STATS_REPLY: msg = ofproto_v1_0_parser.OFPPortStatsReply.parser(self.datapath, version, msg_type, msg_len, xid, pkt) if(type(msg) is ofproto_v1_0_parser.OFPFlowStatsReply): # print(str(self.id) + " : Receive Flow Stats Message") # print(msg.body) for flow in msg.body: db_message = {"switch": hex(self.id), "message": { "header": { "version": msg.version, "type": msg.msg_type, "length": msg.msg_len, "xid": msg.xid }, "match": { "wildcards": flow.match.wildcards, "in_port": flow.match.in_port, "dl_src": mac.haddr_to_str(flow.match.dl_src), "dl_dst": mac.haddr_to_str(flow.match.dl_dst), "dl_vlan": flow.match.dl_vlan, "dl_vlan_pcp": flow.match.dl_vlan_pcp, "dl_type": flow.match.dl_type, "nw_tos": flow.match.nw_tos, "nw_proto": flow.match.nw_proto, "nw_src": ip.ipv4_to_str(flow.match.nw_src), "nw_dst": ip.ipv4_to_str(flow.match.nw_dst), "tp_src": flow.match.tp_src, "tp_dst": flow.match.tp_dst }, "cookie": flow.cookie, "idle_timeout": flow.idle_timeout, "hard_timeout": flow.hard_timeout, "priority": flow.priority, "flags": msg.flags, "actions": [] }, "timestamp": datetime.datetime.utcnow()} for action in flow.actions: db_message["message"]["actions"].append(vars(action)); try: self.db.flow_stats.insert_one(db_message) except: if(self.id != None): print(datetime.datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S') + " : ERROR [" + str(hex(self.id)) + "] --- Failed to write data into database") else: print(datetime.datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S') + " : ERROR [" + str(self.id) + "] --- Failed to write data into database") pass if(type(msg) is ofproto_v1_0_parser.OFPPortStatsReply): # print(str(self.id) + " : Receive Port Stats Message") # print(msg.body) for port in msg.body: # print(port) db_message = {"switch": hex(self.id), "port_no": port.port_no, "rx_packets": port.rx_packets, "tx_packets": port.tx_packets, "rx_bytes": port.rx_bytes, "tx_bytes": port.tx_bytes, "rx_dropped": port.rx_dropped, "tx_dropped": port.tx_dropped, "rx_errors": port.rx_errors, "tx_errors": port.tx_errors, "rx_frame_err": port.rx_frame_err, "rx_over_err": port.rx_over_err, "rx_crc_err": port.rx_crc_err, "collisions": port.collisions, "timestamp": datetime.datetime.utcnow()} try: self.db.port_stats.insert_one(db_message) except: if(self.id != None): print(datetime.datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S') + " : ERROR [" + str(hex(self.id)) + "] --- Failed to write data into database") else: print(datetime.datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S') + " : ERROR [" + str(self.id) + "] --- Failed to write data into database") pass # Asynchronous messages elif msg_type == ofproto_v1_0.OFPT_PACKET_IN: msg = ofproto_v1_0_parser.OFPPacketIn.parser(self.datapath, version, msg_type, msg_len, xid, pkt) pkt_msg = packet.Packet(msg.data) if pkt_msg.get_protocol(ethernet.ethernet).ethertype == ETH_TYPE_LLDP: lldp_msg = pkt_msg.get_protocol(lldp.lldp) if lldp_msg != None: if lldp_msg.tlvs[3].tlv_info == "ProxyTopologyMonitorLLDP": (port,) = struct.unpack('!I', lldp_msg.tlvs[1].port_id) switch_src = str_to_dpid(lldp_msg.tlvs[0].chassis_id[5:]) # print(str(self.id) + " : Receive Proxy LLDP Packet") # print(lldp_msg) # Write to database try: self.db.topology.insert_one({"switch_dst": hex(self.id), "port_dst": port, "switch_src": hex(switch_src), "port_src": msg.in_port, "timestamp": datetime.datetime.utcnow()}) except: if(self.id != None): print(datetime.datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S') + " : ERROR [" + str(hex(self.id)) + "] --- Failed to write data into database") else: print(datetime.datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S') + " : ERROR [" + str(self.id) + "] --- Failed to write data into database") return elif lldp_msg.tlvs[3].tlv_info != "ProxyTopologyMonitorLLDP": # print(lldp_msg) # print("Controller LLDP packet") pass
def install_path(self, paths, src, dst, type, in_dpid, parser, ofproto, msg, tcp_dst=0): nodes = list(paths.keys()) out_port = 0 #nodes = [int(node) for node in list(paths.keys())] # if in_dpid not in nodes: # return self.logger.debug("try to install path for : %s", nodes) self.logger.debug("origin dpid is %s", in_dpid) # for node in nodes: for i in range(len(nodes)): node = nodes[i] if i < len(nodes) - 1: node2 = nodes[i + 1] else: node2 = dst target_dpid = str_to_dpid(node) if target_dpid == in_dpid: out_port = paths[node][1] target_in_port = paths[node][0] target_out_port = paths[node][1] target_actions = [parser.OFPActionOutput(target_out_port)] # target_match = parser.OFPMatch(in_port=target_in_port, eth_dst=dst) if tcp_dst != 0: # if tcp_dst >= 0 and tcp_dst < 5000: if tcp_dst >= 0: item = {'eth_src': src, 'eth_dst': dst, 'tcp_dst': tcp_dst} # switch = target_dpid switch = 'switch' + str(target_dpid) if item not in self.flow_set_all: self.flow_set_all.append(item) # flow_set中没有switch键则加入,设为列表 self.flow_set.setdefault(switch, []) if item not in self.flow_set[switch]: self.flow_set[switch].append(item) self.flow_set_dst.setdefault(switch, {}) self.flow_set_dst[switch].setdefault(dst, []) if item not in self.flow_set_dst[switch][dst]: self.flow_set_dst[switch][dst].append(item) item = { 'eth_src': src, 'eth_dst': dst, 'tcp_dst': tcp_dst, 'next': node2 } self.flow_set_next.setdefault(switch, {}) self.flow_set_next[switch].setdefault(dst, []) if item not in self.flow_set_next[switch][dst]: self.flow_set_next[switch][dst].append(item) target_match = parser.OFPMatch(eth_src=src, eth_dst=dst, eth_type=type, ip_proto=6, tcp_dst=tcp_dst) else: target_match = parser.OFPMatch(eth_src=src, eth_dst=dst, eth_type=type, ip_proto=1) target_datapath = self._get_datapath(target_dpid) if msg.buffer_id != ofproto.OFP_NO_BUFFER: self.add_flow(target_datapath, 1, target_match, target_actions, msg.buffer_id) else: self.add_flow(target_datapath, 1, target_match, target_actions) return out_port
def __init__(self, *args, **kwargs): super(SimpleSwitch13, self).__init__(*args, **kwargs) self.mac_to_port = {} """ When the STP library (Stp class instance) detects connection of an OpenFlow switch to the controller, a Bridge class instance and Port class instance are generated. After each class instance is generated and started, - Notification of the OpenFlow message reception from the Stp class instance - STP calculation of the Bridge class instance (loot bridge selection and selection of the role of each port) - Status change of the port of the Port class instance and send/receive of BPDU packets work together to achieve the spanning tree function. """ self.stp = kwargs['stplib'] """ Use this API if you want to set up configuration of each bridge(switch) and ports. Set configuration with 'config' parameter as follows. config = {<dpid>: {'bridge': {'priority': <value>, 'sys_ext_id': <value>, 'max_age': <value>, 'hello_time': <value>, 'fwd_delay': <value>} 'ports': {<port_no>: {'priority': <value>, 'path_cost': <value>, 'enable': <True/False>}, <port_no>: {...},,,}} <dpid>: {...}, <dpid>: {...},,,} NOTE: You may omit each field. If omitted, a default value is set up. It becomes effective when a bridge starts. Default values: ------------------------------------------------------------------ | bridge | priority | bpdu.DEFAULT_BRIDGE_PRIORITY -> 0x8000 | Bridge priority | | sys_ext_id | 0 | Sets VLAN-ID | | max_age | bpdu.DEFAULT_MAX_AGE -> 20[sec] | Timer value to wait to receive BPDU packets | | hello_time | bpdu.DEFAULT_HELLO_TIME -> 2 [sec] | Send intervals of BPDU packets | | fwd_delay | bpdu.DEFAULT_FORWARD_DELAY -> 15[sec] | Period that each port stays in LISTEN or LEARN status |--------|------------|------------------------------------------| | port | priority | bpdu.DEFAULT_PORT_PRIORITY -> 0x80 | Port priority | | path_cost | (Set up automatically | Link cost value | | | according to link speed.) | | | enable | True | Port enable/disable setting ------------------------------------------------------------------ """ """ Use the set_config() method of the STP library to set configuration. Here, the following values are set as a sample. OpenFlow switch Item Setting dpid=0000000000000001 bridge.priority 0x8000 dpid=0000000000000002 bridge.priority 0x9000 dpid=0000000000000003 bridge.priority 0xa000 Using these settings, the bridge ID of the dpid=0000000000000001 OpenFlow switch is always the smallest value and is selected as the root bridge. """ config = { dpid_lib.str_to_dpid('0000000000000001'): { 'bridge': { 'priority': 0x8000 } }, dpid_lib.str_to_dpid('0000000000000002'): { 'bridge': { 'priority': 0x9000 } }, dpid_lib.str_to_dpid('0000000000000003'): { 'bridge': { 'priority': 0xa000 } } } self.stp.set_config(config)
def lists(self, _req, dpid, **_kwargs): dpid = dpid_lib.str_to_dpid(dpid) ports = self.tunnels.list_ports(dpid) body = json.dumps(ports) return Response(content_type='application/json', body=body)
def get_switch_arp(self, req, **kwargs): body = json.dumps(self.routing_flow_app.switches[dpid_lib.str_to_dpid( kwargs['dpid'])].get_arp_list()) return Response(content_type='application/json', body=body)
def _links(self, req, **kwargs): dpid = None if 'dpid' in kwargs: dpid = dpid_lib.str_to_dpid(kwargs['dpid']) links = get_link(self.topology_api_app, dpid) return json_response([link.to_dict() for link in links])
def from_rest_dict(cls, p): return cls(str_to_dpid(p['dpid']), str_to_port_no(p['port_no']), p['hw_addr'], p['name'])
def reconfigure_rules(self): ''' Reconfiguring OF rules on all switches in current topology ''' # for each TAP rule form app config reconfigure relevant OF flows end-to-end for rule_name in sorted(self.rules_config.keys()): rule = self.rules_config[rule_name] self.logger.info('Processing rule "{}"...'.format(rule_name)) # get ingress and egress switches DPID from app configuration in_switch = lib_dpid.str_to_dpid(rule['in_switch']) out_switch = lib_dpid.str_to_dpid(rule['out_switch']) # get relevant Ryu Datapath objects for these switches in_switch_dp = self.get_switch_dp(in_switch) out_switch_dp = self.get_switch_dp(out_switch) # skip if ingress or egress switch is not in current topology if not in_switch_dp: self.logger.info( 'Ingress switch {} is not in the topology'.format( rule['in_switch'])) continue if not out_switch_dp: self.logger.info( 'Egress switch {} is not in the topology'.format( rule['out_switch'])) continue # build shortest path between ingress and egress switch try: path = nx.shortest_path(self.net, in_switch, out_switch) # skip if no path except nx.exception.NetworkXNoPath as e: self.logger.warning( 'No path found between switches: {}'.format(e)) continue # get ingress and egress port_no from app configuration in_port = self.get_of_port_no(in_switch, rule['in_port']) out_port = self.get_of_port_no(in_switch, rule['out_port']) next_dpid = None next_port = None # add relevant flow if ingress switch == egress switch if path[0] == in_switch == out_switch: self.logger.info( 'dpid = {}, next_dpid = {}, in_port = {} ({}), out_port = {} ({})' .format(dpid_to_str(in_switch), dpid_to_str(in_switch), in_port, self.get_of_port_name(in_switch, in_port), out_port, self.get_of_port_name(in_switch, out_port))) # add OF flow for ingress switch self.flow_inport_to_outport(self.get_switch_dp(in_switch), in_port, out_port) continue # process flows hop-by-hop starting from ingress switch dpid = path.pop(0) while path: next_dpid = path.pop(0) # if we're in the beginning at ingress switch, get port_no from app configuration if dpid == in_switch: in_port = self.get_of_port_no(dpid, rule['in_port']) out_port = self.net[dpid][next_dpid]['s_port'] # if we're processing transit switches, compute ingress and egress ports from network topology graph else: in_port = next_port out_port = self.net[dpid][next_dpid]['s_port'] self.logger.info( 'dpid = {}, next_dpid = {}, in_port = {} ({}), out_port = {} ({})' .format(dpid_to_str(dpid), dpid_to_str(next_dpid), in_port, self.get_of_port_name(dpid, in_port), out_port, self.get_of_port_name(dpid, out_port))) # add OF flow for transit switch self.flow_inport_to_outport(self.get_switch_dp(dpid), in_port, out_port) next_port = self.net[dpid][next_dpid]['d_port'] dpid = next_dpid # if we're at egress switch, take egress port from app configuration in_port = next_port out_port = self.get_of_port_no(dpid, rule['out_port']) self.logger.info( 'dpid = {}, next_dpid = {}, in_port = {} ({}), out_port = {} ({})' .format(dpid_to_str(dpid), dpid_to_str(next_dpid), in_port, self.get_of_port_name(dpid, in_port), out_port, self.get_of_port_name(dpid, out_port))) # add OF flow for last (egress) switch self.flow_inport_to_outport(self.get_switch_dp(dpid), in_port, out_port) return True
def __init__(self, *args, **kwargs): super(SimpleSwitchIgmp13, self).__init__(*args, **kwargs) self.mac_address_table = {} self._snoop = kwargs['igmplib'] self._snoop.set_querier_mode(dpid=str_to_dpid('0000000000000001'), server_port=2)
def __init__(self, *args, **kwargs): super(SimpleSwitch13, self).__init__(*args, **kwargs) self.mac_to_port = {} self.arp_table = {} self.sw = {} self.port_tx = {} self.datapaths = {} self.datapath_list = {} self.topology_api_app = self self.stp = kwargs['stplib'] # Sample of stplib config. # please refer to stplib.Stp.set_config() for details. config = { dpid_lib.str_to_dpid('0000000000000001'): { 'bridge': { 'priority': 0x8000 }, 'ports': { 1: { 'priority': 0x80 }, 2: { 'priority': 0x80 }, 3: { 'priority': 0x80 }, 4: { 'priority': 0x80 } } }, dpid_lib.str_to_dpid('0000000000000002'): { 'bridge': { 'priority': 0x9000 }, 'ports': { 1: { 'priority': 0x80 }, 2: { 'priority': 0x80 }, 3: { 'priority': 0x80 }, 4: { 'priority': 0x80 } } }, dpid_lib.str_to_dpid('0000000000000003'): { 'bridge': { 'priority': 0xa000 }, 'ports': { 1: { 'priority': 0x80 }, 2: { 'priority': 0x80 }, 3: { 'priority': 0x80 }, 4: { 'priority': 0x80 } } }, dpid_lib.str_to_dpid('0000000000000006'): { 'bridge': { 'priority': 0xb000 }, 'ports': { 1: { 'priority': 0x80 }, 2: { 'priority': 0x80 }, 3: { 'priority': 0x80 }, 4: { 'priority': 0x80 } } }, dpid_lib.str_to_dpid('0000000000000007'): { 'bridge': { 'priority': 0xc000 }, 'ports': { 1: { 'priority': 0x80 }, 2: { 'priority': 0x80 }, 3: { 'priority': 0x80 }, 4: { 'priority': 0x80 } } }, dpid_lib.str_to_dpid('0000000000000008'): { 'bridge': { 'priority': 0xd000 }, 'ports': { 1: { 'priority': 0x80 }, 2: { 'priority': 0x80 }, 3: { 'priority': 0x80 }, 4: { 'priority': 0x80 } } } } # config = {} self.stp.set_config(config)