def install_path(self, datapath, tcp_pkt, ip, cesta): parser = datapath.ofproto_parser fullpath = copy.deepcopy(cesta) tmppath = cesta[1:-1] print "Installing path from", ip.src, "to", ip.dst, "and backwards. Path is: ", fullpath for s in tmppath: match = parser.OFPMatch(eth_type=0x0800, ip_proto=6, ipv4_src=ip.src, ipv4_dst=ip.dst, tcp_src=tcp_pkt.src_port, tcp_dst=tcp_pkt.dst_port) next = fullpath[fullpath.index(s) + 1] out_port = self.net[s][next]['port'] actions = [parser.OFPActionOutput(out_port)] self.add_flow(get_datapath(self, s), 4, match, actions) match = parser.OFPMatch(eth_type=0x0800, ip_proto=6, ipv4_src=ip.dst, ipv4_dst=ip.src, tcp_src=tcp_pkt.dst_port, tcp_dst=tcp_pkt.src_port) prev = fullpath[fullpath.index(s) - 1] out_port = self.net[s][prev]['port'] actions = [parser.OFPActionOutput(out_port)] self.add_flow(get_datapath(self, s), 4, match, actions)
def _handle_arp_packets(self, switches, datapath, dpid_src, pkt, src, dst, in_port): """Handling of an ARP packet.""" arp_packet = pkt.get_protocol(arp.arp) arp_src_ip = arp_packet.src_ip arp_dst_ip = arp_packet.dst_ip if arp_packet.opcode == 1: #self.logger.info("ARP request") if arp_dst_ip in self.ip_to_mac: #self.logger.info("The address is inside the IP TO MAC table") src_ip = arp_dst_ip dst_ip = arp_src_ip src_mac = self.ip_to_mac[arp_dst_ip] dst_mac = src out_port = in_port # Send an ARP reply opcode = 2 self.send_arp(datapath, opcode, src_mac, src_ip, dst_mac, dst_ip, out_port) #self.logger.info("Packet in %s %s %s %s", src_mac, src_ip, dst_mac, dst_ip) else: #self.logger.info("The address is NOT inside the IP TO MAC table") src_ip = arp_src_ip dst_ip = arp_dst_ip src_mac = src dst_mac = dst self.ip_to_mac.setdefault(src_ip, {}) self.ip_to_mac[src_ip] = src_mac opcode = 1 for id_switch in switches: datapath_dst = get_datapath(self, id_switch) for port in range(1, NUMBER_OF_SWITCH_PORTS + 1): if self.port_occupied[id_switch][port] == 0: out_port = port if id_switch == dpid_src: if out_port != in_port: self.send_arp(datapath_dst, opcode, src_mac, src_ip, dst_mac, dst_ip, out_port) else: self.send_arp(datapath_dst, opcode, src_mac, src_ip, dst_mac, dst_ip, out_port) else: #self.logger.info("ARP reply") src_ip = arp_src_ip dst_ip = arp_dst_ip src_mac = src dst_mac = dst if arp_dst_ip in self.ip_to_mac: self.ip_to_mac.setdefault(src_ip, {}) self.ip_to_mac[src_ip] = src_mac opcode = 2 out_port = self.mac_to_port[self.mac_to_dpid[dst_mac]][dst_mac] datapath_dst = get_datapath(self, self.mac_to_dpid[dst_mac]) self.send_arp(datapath_dst, opcode, src_mac, src_ip, dst_mac, dst_ip, out_port)
def handle_host_add(self, ev): # 主机上线 """ Event handler indiciating a host has joined the network This handler is automatically triggered when a host sends an ARP response. """ host = ev.host self.logger.warn("Host Added: %s (IPs: %s) on switch%s/%s (%s)", host.mac, host.ipv4, host.port.dpid, host.port.port_no, host.port.hw_addr) # 1 记录这个主机对应的switch 增加转发表 # 相当于终端 self.belong[host.mac] = (host.port.dpid, host.port.port_no) self.add_forwaring_rule( ofctl_api.get_datapath(self, dpid=host.port.dpid), host.mac, host.port.port_no) # 2 更新其他switch上的转发表 for dpid in self.res: # 最短路的计算结果? dp = ofctl_api.get_datapath(self, dpid=dpid) # 如果是自己 就跳过 if dpid == host.port.dpid: continue # 从图上更新其他switch self.add_forwaring_rule(dp, host.mac, self.res[dpid][host.port.dpid]) # JL: 增加ip-mac对应 self.ip_mac_dict[host.ipv4[0]] = host.mac self.tm.add_host(host) # 增加switch-host记录 print("[DEBUG ADD] add switch-host before", (host.port.dpid not in self.switch_contain_host)) if host.port.dpid not in self.switch_contain_host: # 如果这个host相连的switch还没有被记录过 self.switch_contain_host[host.port.dpid] = [] self.switch_contain_host[host.port.dpid].append( (host.mac, host.port.port_no)) print("[BELONG]", self.belong) self.calc_spanning_tree() self.one_switch_special_case() self.show_topology() self.show_shortest_path() self.show_spanning_tree()
def _packet_in_handler(self, ev): msg = ev.msg in_port = msg.match['in_port'] datapath = msg.datapath ofp = datapath.ofproto ofp_parser = datapath.ofproto_parser pkt = packet.Packet(msg.data) eth = pkt.get_protocol(ethernet.ethernet) if eth.ethertype == ether_types.ETH_TYPE_ARP: #Send arp packets out over all switches assert msg.buffer_id == ofp.OFP_NO_BUFFER arp_ = pkt.get_protocol(arp.arp) ctime = time.time() key = (arp_.hwtype, arp_.proto, arp_.hlen, arp_.plen, arp_.opcode, arp_.src_mac, arp_.src_ip, arp_.dst_mac, arp_.dst_ip) if (ctime < self.arp.get(key, float('-inf')) + self.CONF.debounce): return self.arp.get(key, float('inf')) for dpid in self.topo: datapath = api.get_datapath(self, dpid) datapath.send_msg( ofp_parser.OFPPacketOut( datapath, buffer_id=ofp.OFP_NO_BUFFER, in_port=ofp.OFPP_CONTROLLER, actions=[ ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD) ], data=msg.data ) ) self.arp[key] = time.time() elif eth.ethertype == ether_types.ETH_TYPE_IP: ipv4_ = pkt.get_protocol(ipv4.ipv4) dscp = ipv4_.tos >> 2 if dscp != 0: for _,odpid,(ipt,_) in ( self.topo.out_edges_iter(datapath.id, data='pt')): if ipt == in_port: self.rewrite = (datapath.id, in_port) msg.datapath = api.get_datapath(self, odpid) replace_fields(ofp_parser, msg, in_port=dscp_in(dscp)) ipv4_.tos = ipv4_.tos & 3 assert self.rewrite is not None self._packet_in_handler_short(ev) self.rewrite = None
def handle_link_delete(self, ev): """ Event handler indicating when a link between two switches has been deleted """ link = ev.link src_port = link.src dst_port = link.dst print("[*] delete happened") self.logger.warn("Deleted Link: switch%s/%s (%s) -> switch%s/%s (%s)", src_port.dpid, src_port.port_no, src_port.hw_addr, dst_port.dpid, dst_port.port_no, dst_port.hw_addr) self.graph.remove(src_port.dpid, dst_port.dpid) self.graph.remove(dst_port.dpid, src_port.dpid) self.shortest_path() # 全部flow清空 for switch in self.switch_list: datapath = ofctl_api.get_datapath(self, dpid = host.port.dpid) empty_match = parser.OFPMatch() instructions = [] flow_mod = self.remove_table_flows(datapath, 0, empty_match, instructions) # print "deleting all flow entries in table ", 0 datapath.send_msg(flow_mod) # flow重建 for host_mac in self.belong: host_port_dpid, host_port_no = self.belong[host_mac] self.add_forwaring_rule( ofctl_api.get_datapath(self, dpid=host_port_dpid), host_mac, host_port_no ) for dpid in self.res: # 最短路的计算结果? dp = ofctl_api.get_datapath(self, dpid=dpid) # 如果是自己 就跳过 if dpid == host_port_dpid: continue # 从图上更新其他switch self.add_forwaring_rule( dp, host_mac, self.res[dpid][host_port_dpid] )
def switch_get_datapath(self, datapath_id): """Return a datapath object given its datapath ID. :param datapath_id: ID of a datapath i.e. switch ID. :return: Datapath object. """ return api.get_datapath(self, datapath_id)
def get_topology_data(self, ev): # """ # Get topology data. Links and switches. # """ switch_list = get_switch(self.topology_api_app, None) switches=[switch.dp.id for switch in switch_list] for s in switches: print(get_datapath(self,s)) self.net.add_nodes_from(switches) print("Switches: ", switches) links_list = get_link(self.topology_api_app, None) print("Links_list from ryu: ",links_list) links = [(link.src.dpid,link.dst.dpid,{'port':link.src.port_no}) for link in links_list] print("Linky: ",links) self.net.add_edges_from(links) links=[(link.dst.dpid,link.src.dpid,{'port':link.dst.port_no}) for link in links_list] print("Linky znova: ",links) self.net.add_edges_from(links) print("Linky z programu: ",self.net.edges()) print("Nodes z programu: ",self.net.nodes())
def _send_packet(self, ev): """ First install drop flows if they are not there yet. Then send the packet through the switch :param ev: EventSendPacket """ self.install_drop_flows() pkt = ev.packet imsi = ev.imsi if isinstance(pkt, (bytes, bytearray)): data = bytearray(pkt) elif isinstance(pkt, Packet): pkt.serialize() data = pkt.data else: raise ValueError('Could not handle packet of type: ' '{}'.format(type(pkt))) self.logger.debug('Tracer sending packet: %s', str(Packet(data))) datapath = get_datapath(self, dpid=self._datapath.id) ofp = datapath.ofproto ofp_parser = datapath.ofproto_parser actions = [ # Turn on test-packet as we're just tracing it ofp_parser.NXActionRegLoad2(dst=TEST_PACKET_REG, value=TestPacket.ON.value), # Add IMSI metadata ofp_parser.NXActionRegLoad2(dst=IMSI_REG, value=encode_imsi(imsi)), # Submit to table=0 because otherwise the packet will be dropped! ofp_parser.NXActionResubmitTable(table_id=0), ] datapath.send_packet_out(in_port=ofp.OFPP_LOCAL, actions=actions, data=data)
def _set_redundancy(self, dpid, redundancy): self.logger.info("Setting redundancy to: {}".format(redundancy)) datapath = get_datapath(self, dpid) ofp = datapath.ofproto ofp_parser = datapath.ofproto_parser self.logger.info("Create OAM packet") # pkt = copy.deepcopy(self.config_pkt) pkt = packet.Packet() pkt.add_protocol( ethernet.ethernet(ethertype=ether_types.ETH_TYPE_IP, dst='ff:ff:ff:ff:ff:ff', src='00:00:00:00:00:0c')) pkt.add_protocol( ipv4.ipv4(dst="255.255.255.255", src="0.0.0.0", proto=in_proto.IPPROTO_UDP)) pkt.add_protocol(udp.udp(dst_port=common.UDP_PORT_OAM)) payload = struct.pack(">i", int(redundancy)) pkt.add_protocol(payload) pkt.serialize() data = pkt.data in_port = ofp.OFPP_CONTROLLER actions = [ofp_parser.OFPActionOutput(1)] req = ofp_parser.OFPPacketOut(datapath, ofp.OFP_NO_BUFFER, in_port, actions, data) self.logger.info("Send OAM packet to encoder") datapath.send_msg(req)
def add_group_flows(self, parser, ofproto, group_entries): for dpid in group_entries: ports = group_entries[dpid] for port in ports: entry = ports[port] if entry: self.logger.info('entry for dpid {0}: {1}'.format(dpid, entry)) entry_match = entry['match'] datapath = api.get_datapath(self, dpid) group_mod_command = ofproto.OFPGC_ADD group_id = None if entry_match['ipv4_dst'] in self._group_ids[dpid]: group_id = self._group_ids[dpid][entry_match['ipv4_dst']] group_mod_command = ofproto.OFPGC_MODIFY else: group_id = self.get_next_group_id(dpid, entry_match['ipv4_dst']) match = parser.OFPMatch(in_port=entry_match['in_port'], eth_type=entry_match['eth_type'], ipv4_dst=entry_match['ipv4_dst']) actions = [parser.OFPActionOutput(output_port) for output_port in entry['actions_output_ports']] buckets = [parser.OFPBucket(actions=[action]) for action in actions] req_group = parser.OFPGroupMod(datapath=datapath, command=group_mod_command, type_=ofproto.OFPGT_ALL, group_id=group_id, buckets=buckets) inst = [ parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, [parser.OFPActionGroup(group_id=group_id)])] req_flow = parser.OFPFlowMod(datapath=datapath, priority=1, match=match, instructions=inst) datapath.send_msg(req_group) datapath.send_msg(req_flow)
def one_switch_special_case(self): # 只有一个 switch 的时候 没有生成树 if (len(self.switch_list) == 1): for switch in self.switch_list: for host_mac in self.belong: host_port_dpid, host_port_no = self.belong[host_mac] datapath = ofctl_api.get_datapath(self, dpid=host_port_dpid) match = datapath.ofproto_parser.OFPMatch( dl_dst=haddr_to_bin(ETHERNET_MULTICAST), # 这是一个广播包 dl_src=haddr_to_bin(host_mac), # 来源 MAC 地址 ) actions = [ datapath.ofproto_parser.OFPActionOutput(i[1]) for i in self.switch_contain_host[host_port_dpid] ] ofp_parser = datapath.ofproto_parser flow_mod = datapath.ofproto_parser.OFPFlowMod( datapath, match=match, cookie=0, priority=50, actions=actions) datapath.send_msg(flow_mod)
def _packet_in_handler(self, ev): msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto pkt = packet.Packet(msg.data) eth = pkt.get_protocol(ethernet.ethernet) pkt_arp = pkt.get_protocol(arp.arp) dst = eth.dst src = eth.src dpid = datapath.id datapath_s2 = api.get_datapath(self,2) if eth.ethertype == ether_types.ETH_TYPE_LLDP: # ignore lldp packet return if eth.ethertype == ether_types.ETH_TYPE_ARP: self.logger.info("arp dpid %s", datapath.id) if pkt_arp.opcode == arp.ARP_REQUEST: dst_ip = pkt_arp.dst_ip src_ip = pkt_arp.src_ip if dpid == 1: self.arp_reply(datapath, src, '00:00:00:00:00:02', dst_ip, src_ip, eth, msg) #arp reply to h1 self.add_entry(datapath, 1, '00:00:00:00:00:02', 2) #adding entries to switch 1 and 2 self.add_entry(datapath, 2, '00:00:00:00:00:01', 1) self.add_entry(datapath_s2, 1, '00:00:00:00:00:01', 2) self.add_entry(datapath_s2, 2, '00:00:00:00:00:02', 1) if dpid == 2: self.arp_reply(datapath, src, '00:00:00:00:00:01', dst_ip, src_ip, eth, msg) #arp reply to h2
def _packet_in_handler(self, ev): msg = ev.msg # ev.msg is an object that represents a packet_in data structure. datapath = msg.datapath # msg.datapath is an object that represents a datapath (switch) ofproto = datapath.ofproto # datapath.ofproto is an object that represent the OpenFlow protocol that Ryu and the switch negotiated pkt = packet.Packet(msg.data) eth = pkt.get_protocol(ethernet.ethernet) pkt_arp = pkt.get_protocol(arp.arp) dst = eth.dst src = eth.src dpid = datapath.id #datapath to add the entry to datapathswitch2 = api.get_datapath(self,2) if eth.ethertype == ether_types.ETH_TYPE_LLDP: # ignore lldp packet return if eth.ethertype == ether_types.ETH_TYPE_ARP: if pkt_arp.opcode == arp.ARP_REQUEST: dst_ip = pkt_arp.dst_ip src_ip = pkt_arp.src_ip # ARP spoofing if dpid == 1: # ARP reply to host 1 self.arp_rep(datapath, src, '00:00:00:00:00:02', dst_ip, src_ip, eth, msg) self.add_ent(datapath, 1, '00:00:00:00:00:02', 2) self.add_ent(datapath, 2, '00:00:00:00:00:01', 1) self.add_ent(datapathswitch2, 1, '00:00:00:00:00:01', 2) self.add_ent(datapathswitch2, 2, '00:00:00:00:00:02', 1) if dpid == 2: # ARP reply to host 2 self.arp_rep(datapath, src, '00:00:00:00:00:01', dst_ip, src_ip, eth, msg)
def _event_switch_enter_handler(self, ev): self.logger.info("switch enter: %s", ev.switch.dp.id) self.topo.add_node(ev.switch.dp.id) datapath = api.get_datapath(self, ev.switch.dp.id) ofp = datapath.ofproto ofp_parser = datapath.ofproto_parser datapath.send_msg( ofp_parser.OFPFlowMod( datapath, command=ofp.OFPFC_ADD, match=ofp_parser.OFPMatch(), instructions=[ ofp_parser.OFPInstructionActions( ofp.OFPIT_APPLY_ACTIONS, actions=[ ofp_parser.OFPActionOutput( port=ofp.OFPP_CONTROLLER, max_len=ofp.OFPCML_NO_BUFFER ) ] ) ], priority=1 ) )
def flow_recreate(self): # flow 重建 for host_mac in self.belong: host_port_dpid, host_port_no = self.belong[host_mac] self.add_forwaring_rule( ofctl_api.get_datapath(self, dpid=host_port_dpid), host_mac, host_port_no) for dpid in self.res: # 最短路的计算结果? dp = ofctl_api.get_datapath(self, dpid=dpid) # 如果是自己 就跳过 if dpid == host_port_dpid: continue # 从图上更新其他switch self.add_forwaring_rule(dp, host_mac, self.res[dpid][host_port_dpid])
def distribute_single_rule(self, rule): for switch in self.connected_switches: switch_roles = self.connected_switches[switch] if rule.role not in switch_roles: continue datapath = api.get_datapath(self, switch) priority = self.OFP_MAX_PRIORITY actions = [] match = self.create_match(rule) self.add_flow(datapath, priority, match, actions)
def apply_rules_for_all(self): datapaths = get_datapath(self) for datapath in datapaths: self.reset_flow_table(datapath) # install table-miss entry here with open(firewall_rule_file) as frfile: rules = list(csv.DictReader(frfile)) priority = len(rules) for r in rules: self.apply_rule_for(datapath, r, priority) priority -= 1
def get_datapath(self, retry_max=cfg.CONF.AGENT.get_datapath_retry_times): retry = 0 while self.datapath is None: self.datapath = ryu_api.get_datapath(self.ryuapp, int(self.datapath_id, 16)) retry += 1 if retry >= retry_max: LOG.error(_LE("Agent terminated!: Failed to get a datapath.")) raise SystemExit(1) time.sleep(1) self.set_dp(self.datapath)
def _port_state_change_handler(self, ev): #print "EventOFPPortStatus detected" msg = ev.msg datapath = msg.datapath for dpid in self.mac_to_port.keys(): datapath = api.get_datapath(self, dpid) self.del_flow(datapath) del self.mac_to_port[dpid] self.mac_to_port.setdefault(dpid, {})
def get_datapath(self, retry_max=cfg.CONF.AGENT.get_datapath_retry_times): retry = 0 while self.datapath is None: self.datapath = ryu_api.get_datapath(self.ryuapp, int(self.datapath_id, 16)) retry += 1 if retry >= retry_max: LOG.error(_('Agent terminated!: Failed to get a datapath.')) raise SystemExit(1) time.sleep(1) self.set_dp(self.datapath)
def _monitor(self): while True: for dpid in list(self.topo.nodes_iter()): datapath = api.get_datapath(self, dpid) if datapath is None: continue ofp = datapath.ofproto ofp_parser = datapath.ofproto_parser datapath.send_msg(ofp_parser.OFPPortStatsRequest( datapath, 0, ofp.OFPP_ANY)) datapath.send_msg(ofp_parser.OFPTableStatsRequest(datapath, 0)) hub.sleep(self.CONF.dc)
def handle_host_add(self, ev): # 主机上线 """ Event handler indiciating a host has joined the network This handler is automatically triggered when a host sends an ARP response. """ host = ev.host self.logger.warn("Host Added: %s (IPs: %s) on switch%s/%s (%s)", host.mac, host.ipv4, host.port.dpid, host.port.port_no, host.port.hw_addr) # 1 记录这个主机对应的switch 增加转发表 # 相当于终端 self.belong[host.mac] = (host.port.dpid, host.port.port_no) self.add_forwaring_rule( ofctl_api.get_datapath(self, dpid=host.port.dpid), host.mac, host.port.port_no ) # 2 更新其他switch上的转发表 for dpid in self.res: # 最短路的计算结果? dp = ofctl_api.get_datapath(self, dpid=dpid) # 如果是自己 就跳过 if dpid == host.port.dpid: continue # 从图上更新其他switch self.add_forwaring_rule( dp, host.mac, self.res[dpid][host.port.dpid] ) # JL: 增加ip-mac对应 self.ip_mac_dict[host.ipv4[0]] = host.mac self.tm.add_host(host) print("[BELONG]", self.belong)
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 forward_frame(self, dpid, out_port, frame): datapath = ofctl_api.get_datapath(self, dpid=dpid) ofproto = datapath.ofproto parser = datapath.ofproto_parser match = parser.OFPMatch(in_port=ofproto.OFPP_ANY) actions = [parser.OFPActionOutput(out_port)] out = parser.OFPPacketOut(datapath=datapath, match=match, actions=actions, data=bytes(frame)) datapath.send_msg(out)
def switch_role_assign(self, switch_id, new_role): if new_role not in self.role_to_rules: return (False, "Role " + new_role + " does not exist.") if switch_id not in self.connected_switches: return (False, "Switch " + str(switch_id) + " does not exist.") if new_role in self.connected_switches[switch_id]: return (False, "Switch " + str(switch_id) + " already has role " + str(new_role) + ".") self.connected_switches[switch_id].append(new_role) datapath = api.get_datapath(self, switch_id) self.distribute_rules_role_set(datapath, new_role) print("[+] Switch " + str(switch_id) + " assigned role: " + new_role) return (True, "Switch " + str(switch_id) + " given role " + new_role + ".")
def _send(self, dpid, msg): datapath = api.get_datapath(self, dpid) ofp = datapath.ofproto ofp_parser = datapath.ofproto_parser if isinstance(msg, ofp_parser.OFPFlowMod): k = (dpid, msg.match['in_port']) self.count_arrv[k] = 1 + self.count_arrv.get(k, 0) if k in self.evports: dlport = self.evports[k] for _,odpid,(ipt,opt) in ( self.topo.out_edges_iter(dpid, data='pt')): if ipt == dlport: dlport = None rewrite_msg(datapath, msg, opt) dpid = odpid break assert dlport is None elif isinstance(msg, ofp_parser.OFPPacketOut): if self.rewrite is not None: dpid, export = self.rewrite rewrite_msg(datapath, msg, export) api.get_datapath(self, dpid).send_msg(msg)
def policy_switch_assign(self, switch_id, new_policy): if new_policy not in self._policy_to_rules: return (False, "Policy " + new_policy + " does not exist.") if switch_id not in self._connected_switches: return (False, "Switch " + str(switch_id) + " does not exist.") if new_policy in self._connected_switches[switch_id]: return (False, "Switch " + str(switch_id) + " already has policy " + str(new_policy) + ".") self._connected_switches[switch_id].append(new_policy) datapath = api.get_datapath(self, switch_id) self._distribute_rules_policy_set(datapath, new_policy) print("[+] Switch " + str(switch_id) + " assigned policy: " + new_policy) return (True, "Switch " + str(switch_id) + " given policy " + new_policy + ".")
def delete_acl_rule(self, rule_id): if rule_id not in self.access_control_list: return (False, "Invalid rule id given: " + rule_id + ".") # The user passed through a valid rule_id so we can proceed rule = self.access_control_list[rule_id] del self.access_control_list[rule_id] self.role_to_rules[rule.role].remove(rule_id) for switch in self.connected_switches: if rule.role not in self.connected_switches[switch]: continue match = self.create_match(rule) datapath = api.get_datapath(self, switch) self.delete_flow(datapath, self.OFP_MAX_PRIORITY, match) print("[+] Rule " + str(rule) + " with id: " + str(rule_id) + " removed.") return (True, "Rule with id \'" + rule_id + "\' was deleted.")
def _distribute_single_rule(self, rule): for switch in self._connected_switches: switch_policies = self._connected_switches[switch] if rule.policy not in switch_policies: continue datapath = api.get_datapath(self, switch) priority = self.OFP_MAX_PRIORITY actions = [] match = self._create_match(rule) if rule.time_duration == "N/A": self._add_flow(datapath, priority, match, actions, table_id=self.TABLE_ID_ACL) else: self._add_flow(datapath, priority, match, actions, time_limit=(int(rule.time_duration)), table_id=self.TABLE_ID_ACL)
def flow_reset(self): # flow 清空 for switch in self.switch_list: datapath = ofctl_api.get_datapath(self, dpid=switch.dp.id) empty_match = datapath.ofproto_parser.OFPMatch() cmd = datapath.ofproto.OFPFC_DELETE actions = [] ofp_parser = datapath.ofproto_parser flow_mod = datapath.ofproto_parser.OFPFlowMod(datapath, match=empty_match, cookie=0, command=cmd, priority=65535, actions=actions) datapath.send_msg(flow_mod)
def switch_role_remove(self, switch_id, old_role): if old_role not in self.role_to_rules: return (False, "Role " + old_role + " does not exist.") if switch_id not in self.connected_switches: return (False, "Switch " + str(switch_id) + " does not exist.") if old_role not in self.connected_switches[switch_id]: return (False, "Switch " + str(switch_id) + " does not have role " + str(old_role) + ".") self.connected_switches[switch_id].remove(old_role) datapath = api.get_datapath(self, switch_id) for rule_id in self.role_to_rules[old_role]: rule = self.access_control_list[rule_id] match = self.create_match(rule) self.delete_flow(datapath, self.OFP_MAX_PRIORITY, match) print("[+] Switch " + str(switch_id) + " removed role: " + old_role) return (True, "Switch " + str(switch_id) + " had role " + old_role + " removed.")
def _get_dp_by_dpid(self, dpid_int): """Get Ryu datapath object for the switch.""" timeout_sec = cfg.CONF.OVS.of_connect_timeout start_time = timeutils.now() while True: dp = ofctl_api.get_datapath(self._app, dpid_int) if dp is not None: break # The switch has not established a connection to us. # Wait for a little. if timeutils.now() > start_time + timeout_sec: m = _("Switch connection timeout") LOG.error(m) # NOTE(yamamoto): use RuntimeError for compat with ovs_lib raise RuntimeError(m) eventlet.sleep(1) return dp
def policy_switch_remove(self, switch_id, old_policy): if old_policy not in self._policy_to_rules: return (False, "policy " + old_policy + " does not exist.") if switch_id not in self._connected_switches: return (False, "Switch " + str(switch_id) + " does not exist.") if old_policy not in self._connected_switches[switch_id]: return (False, "Switch " + str(switch_id) + " does not have policy " + str(old_policy) + ".") self._connected_switches[switch_id].remove(old_policy) datapath = api.get_datapath(self, switch_id) for rule_id in self._policy_to_rules[old_policy]: rule = self._access_control_list[rule_id] match = self._create_match(rule) self._delete_flow(datapath, self.OFP_MAX_PRIORITY, match) print("[+] Switch " + str(switch_id) + " removed policy: " + old_policy) return (True, "Switch " + str(switch_id) + " had policy " + old_policy + " removed.")
def policy_switch_remove(self, switch_id, old_policy): if old_policy not in self._policy_to_rules: return (False, "policy " + old_policy + " does not exist.") if switch_id not in self._connected_switches: return (False, "Switch " + str(switch_id) + " does not " "exist.") if old_policy not in self._connected_switches[switch_id]: return (False, "Switch " + str(switch_id) + " does not have " "policy " + str(old_policy) + ".") self._connected_switches[switch_id].remove(old_policy) datapath = api.get_datapath(self, switch_id) for rule_id in self._policy_to_rules[old_policy]: rule = self._access_control_list[rule_id] match = self._create_match(rule) self._delete_flow(datapath, self.OFP_MAX_PRIORITY, match) print("[+] Switch " + str(switch_id) + " removed policy: " + old_policy) return (True, "Switch " + str(switch_id) + " had policy " + old_policy + " removed.")
def clean_flows(self): dps = api.get_datapath(self) for dp in dps: ofp = dp.ofproto parser = dp.ofproto_parser match = parser.OFPMatch() # Delete all flows instructions = [] flow_mod = parser.OFPFlowMod(dp, 0, 0, 0, ofp.OFPFC_DELETE, 0, 0, 1, ofp.OFPCML_NO_BUFFER, ofp.OFPP_ANY, OFPG_ANY, 0, match, instructions) dp.send_msg(flow_mod) # Install the table-miss flow entry actions = [ parser.OFPActionOutput(ofp.OFPP_CONTROLLER, ofp.OFPCML_NO_BUFFER) ] self.add_flow(dp, 0, match, actions) del self.packet_log[:]
def port_status_handler(self, ev): msg = ev.msg dp = msg.datapath ofp = dp.ofproto ofp_parser = dp.ofproto_parser swid = dp.id port = msg.desc if port.state == ofp.OFPPS_LINK_DOWN: # 1.2 : host removed from network; update mac table bad_MAC = self.get_MAC(self.MAC_table[swid], port.port_no) if bad_MAC != None: self.MAC_table[swid].pop(bad_MAC) print('Removed from MAC table: MAC: {}'.format(bad_MAC)) # 1.3: all flow entries related to that host should be removed; match = ofp_parser.OFPMatch(eth_dst=bad_MAC) dp_list = get_datapath(self, None) for dp_item in dp_list: self.remove_flow(dp_item, match)
def acl_rule_delete(self, rule_id): if rule_id not in self._access_control_list: return (False, "Invalid rule id given: " + rule_id + ".") # The user passed through a valid rule_id so we can proceed rule = self._access_control_list[rule_id] del self._access_control_list[rule_id] self._policy_to_rules[rule.policy].remove(rule_id) # The rule had time enforcement, it must be removed from the queue if rule.time_start != "N/A": self._remove_from_queue(rule_id) # Send off delete flow messages to switches that hold the rule for switch in self._connected_switches: if rule.policy not in self._connected_switches[switch]: continue match = self._create_match(rule) datapath = api.get_datapath(self, switch) self._delete_flow(datapath, self.OFP_MAX_PRIORITY, match, rule.dst_list) print("[+] Rule " + str(rule) + " with id: " + str(rule_id) + " removed.") return (True, "Rule with id \'" + rule_id + "\' was deleted.")
def acl_rule_delete(self, rule_id): if rule_id not in self._access_control_list: return (False, "Invalid rule id given: " + rule_id + ".") # The user passed through a valid rule_id so we can proceed rule = self._access_control_list[rule_id] del self._access_control_list[rule_id] self._policy_to_rules[rule.policy].remove(rule_id) # The rule had time enforcement, it must be removed from the # queue. if rule.time_start != "N/A": self._remove_from_queue(rule_id) # Send off delete flow messages to switches that hold the rule for switch in self._connected_switches: if rule.policy not in self._connected_switches[switch]: continue match = self._create_match(rule) datapath = api.get_datapath(self, switch) self._delete_flow(datapath, self.OFP_MAX_PRIORITY, match) print("[+] Rule " + str(rule) + " with id: " + str(rule_id) + " removed.") return (True, "Rule with id \'" + rule_id + "\' was deleted.")
def _packet_in_handler(self, ev): msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto pkt = packet.Packet(msg.data) eth = pkt.get_protocol(ethernet.ethernet) pkt_arp = pkt.get_protocol(arp.arp) dst = eth.dst src = eth.src dpid = datapath.id datapath_s2 = api.get_datapath(self,2) datapath_s1 = api.get_datapath(self,1) if eth.ethertype == ether_types.ETH_TYPE_LLDP: # ignore lldp packet return if eth.ethertype == ether_types.ETH_TYPE_ARP: self.logger.info("arp dpid %s", datapath.id) if pkt_arp.opcode == arp.ARP_REQUEST and dpid == 1: dst_ip = pkt_arp.dst_ip src_ip = pkt_arp.src_ip self.logger.info("%s sends arp request to %s through %s with opcode %s in port %s", src_ip, dst_ip, dpid, pkt_arp.opcode, msg.in_port) self.arp_reply(datapath, src, '00:00:00:00:00:02', dst_ip, src_ip, eth, msg) #2 entries for switch 1 self.add_entry(datapath, 1, '10.0.0.1','10.0.0.2', 2, eth) self.add_entry(datapath, 2, '10.0.0.2','10.0.0.1', 1, eth) #2 entries for switch 2 datapath = datapath_s2 self.add_entry(datapath, 1, '10.0.0.2','10.0.0.1', 2, eth) self.add_entry(datapath, 2, '10.0.0.1','10.0.0.2', 1, eth) if pkt_arp.opcode == arp.ARP_REQUEST and dpid == 2: dst_ip = pkt_arp.dst_ip src_ip = pkt_arp.src_ip self.logger.info("%s sends arp request to %s through %s with opcode %s in port %s", src_ip, dst_ip, dpid, pkt_arp.opcode, msg.in_port) self.arp_reply(datapath_s2, src, '00:00:00:00:00:01', dst_ip, src_ip, eth, msg) #2 entries for switch 2 self.add_entry(datapath, 1, '10.0.0.2','10.0.0.1', 2, eth) self.add_entry(datapath, 2, '10.0.0.1','10.0.0.2', 1, eth) #2 entries for switch 1 datapath = datapath_s1 self.add_entry(datapath, 1, '10.0.0.1','10.0.0.2', 2, eth) self.add_entry(datapath, 2, '10.0.0.2','10.0.0.1', 1, eth)
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) #Get protocols eth = pkt.get_protocol(ethernet.ethernet) ip = pkt.get_protocol(ipv4.ipv4) p_arp = pkt.get_protocol(arp.arp) #Ignore LLDP packets if eth.ethertype == ether_types.ETH_TYPE_LLDP: return dst = eth.dst src = eth.src dpid = datapath.id self.mac_to_port.setdefault(dpid, {}) if src not in self.net: self.net.add_node(src) self.net.add_edge(dpid,src,port=in_port) self.net.add_edge(src,dpid) if p_arp: ipv4_src = ip.src if ip != None else p_arp.src_ip ipv4_dst = ip.dst if ip != None else p_arp.dst_ip target_mac = ip_to_mac[ipv4_dst] print "ARP!", ipv4_src, ipv4_dst self.send_arp(datapath, arp.ARP_REPLY, target_mac ,src, ipv4_dst, ipv4_src,src, ofproto.OFPP_CONTROLLER, in_port) return if dst in self.net: if ip != None and ip.dst in SFCs.keys(): if (ip.dst,ip.src) in SFC_flows.keys(): #print "Reflowing: DPID", dpid, ":", in_port, " ", ip.src, "->", ip.dst #print PoPs #print SFC_flows return #self.remove_flow(SFC_flows[(ip.dst,ip.src)]) else: SFC_flows[(ip.dst,ip.src)] = self.flow_id path_source = src whole_path = SFCs[ip.dst] whole_path.append(ip.dst) for pop in whole_path: if pop == ip.dst: path_target = ip_to_mac[pop] else: path_target = ip_to_mac[self.select_closest_pop(pop,self.flow_id,src)] try: path=nx.shortest_path(self.net,path_source,path_target) except nx.NetworkXError: print "NX Error:" print nx.edges() first = True for i in path: if isinstance(i,int): switchDP = api.get_datapath(self, i) next = path[path.index(i)+1] pathes=self.net[i][next] out_port=[pathes[p]['port'] for p in pathes if 'port' in pathes[p]][0] actions = [] if first: first = False if path_source == src: paths=self.net[i][src] #may not work for multiple connections between 2 switches in_port=[paths[p]['port'] for p in paths if 'port' in paths[p]][0] #print "Src switch:", switchDP first_packet_actions = [datapath.ofproto_parser.OFPActionSetField(ip_dscp=1), datapath.ofproto_parser.OFPActionOutput(out_port) ] actions.append(switchDP.ofproto_parser.OFPActionSetField(ip_dscp=1)) match = switchDP.ofproto_parser.OFPMatch(eth_type=0x800,in_port=in_port, ipv4_src=ip.src,ipv4_dst=ip.dst) else: match = switchDP.ofproto_parser.OFPMatch(eth_type=0x800,in_port=2, ipv4_src=ip.src,ipv4_dst=ip.dst)#Later match for dscp #match correct in_port else: match = switchDP.ofproto_parser.OFPMatch(eth_type=0x800,in_port=in_port, ipv4_src=ip.src,ipv4_dst=ip.dst)#Later match for dscp actions.append(switchDP.ofproto_parser.OFPActionOutput(out_port)) self.add_flow(switchDP, match, actions, 2049,self.flow_id) if next != path_target: #Last of segment paths=self.net[next][i] #may not work for multiple connections between 2 switches in_port=[paths[p]['port'] for p in paths if 'port' in paths[p]][0] #if next != dst: #Last of All # #add_flow #else # #add_flow path_source = path_target #print SFC_flows[(ip.dst,ip.src)] self.flow_id+=1 if self.flow_id >= 254: self.flow_id=1 out = datapath.ofproto_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port,actions=first_packet_actions, data=msg.data) datapath.send_msg(out) return else: #Local hop mac redirection (non-SFC traffic) path=nx.shortest_path(self.net,src,dst) next=path[path.index(dpid)+1] paths=self.net[dpid][next] out_port=[paths[p]['port'] for p in paths if 'port' in paths[p]][0] match = datapath.ofproto_parser.OFPMatch(eth_type=0x800,in_port=in_port, eth_dst=dst) actions = [datapath.ofproto_parser.OFPActionOutput(out_port)] self.add_flow(datapath, match, actions,2048,0) #Clausula de ataque: if next == dst and in_port == 2 and "01:0" in dst: print "Ataque: ", dst actions.append(datapath.ofproto_parser.OFPActionOutput(out_port)) #Fim da clausula de ataque #print "b", src, "->", dst #print " path: ", path #print " outport: ", out_port #print " next: ", next #print " dpid: ", dpid #print self.net.edges(data=True, keys=True) out = datapath.ofproto_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port,actions=actions, data=msg.data) datapath.send_msg(out)
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_protocol(ethernet.ethernet) eth = pkt.get_protocols(ethernet.ethernet)[0] #p_arp = self._find_protocol(pkt, "arp") if eth.ethertype == ether_types.ETH_TYPE_LLDP: # print "lldp" # ignore lldp packet return ip = pkt.get_protocol(ipv4.ipv4) dst = eth.dst src = eth.src dpid = datapath.id self.mac_to_port.setdefault(dpid, {}) #print "nodes" #print self.net.nodes() #print "edges" #print self.net.edges() p_arp = pkt.get_protocol(arp.arp) if p_arp: ipv4_src = ip.src if ip != None else p_arp.src_ip ipv4_dst = ip.dst if ip != None else p_arp.dst_ip target_mac = ip_to_mac[ipv4_dst] print "ARP!", ipv4_src, ipv4_dst self.send_arp(datapath, arp.ARP_REPLY, target_mac ,src, ipv4_dst, ipv4_src,src, ofproto.OFPP_CONTROLLER, in_port) return if src not in self.net: #print "1 Src:", src self.net.add_node(src) self.net.add_edge(dpid,src,port=in_port) self.net.add_edge(src,dpid) if dst in self.net: #print "2" if dst in SFCs.keys() and ip != None: #path=(nx.shortest_path(self.net,src,SFCs[dst]), nx.shortest_path(self.net,SFCs[dst],dst)) #Tag the flow! #if dpid == 3: # if in_port == 2: #actions = [ # datapath.ofproto_parser.OFPActionSetField(ip_dscp=0), # datapath.ofproto_parser.OFPActionOutput(out_port) # ] #self.add_sfc_flow(datapath, in_port, dst, actions,0) #if dpid == 3: # actions = [ # datapath.ofproto_parser.OFPActionSetField(ip_dscp=1), # datapath.ofproto_parser.OFPActionOutput(out_port) # ] # self.add_sfc_flow(datapath, in_port, dst, actions,0) #actions = [ # datapath.ofproto_parser.OFPActionSetField(ip_dscp=0), # datapath.ofproto_parser.OFPActionOutput(out_port) # ] #self.add_flow(datapath, in_port, dst, actions) path=nx.shortest_path(self.net,src,SFCs[dst]) print path for i in path: if isinstance(i,int): switchDP = api.get_datapath(self, i) #switchId = switchDP.id next = path[path.index(i)+1] pathes=self.net[i][next] out_port=[pathes[p]['port'] for p in pathes if 'port' in pathes[p]][0] #out_port = self.net[i][next][0]['port'] print i, out_port, next if i == dpid: print "First" actions = [ switchDP.ofproto_parser.OFPActionSetField(ip_dscp=0), switchDP.ofproto_parser.OFPActionOutput(out_port) ] self.add_first_flow(datapath,in_port, dst, actions) out = datapath.ofproto_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port,actions=actions, data=msg.data) elif next == SFCs[dst]: print "next" actions = [ switchDP.ofproto_parser.OFPActionSetField(ip_dscp=1), switchDP.ofproto_parser.OFPActionOutput(1) ] self.add_sfc_pop_flow(switchDP, 3, dst, actions,0) else: actions = [ #switchDP.ofproto_parser.OFPActionSetField(ip_dscp=0), switchDP.ofproto_parser.OFPActionOutput(out_port) ] self.add_sfc_flow(switchDP, dst, actions,0) last = i print "POP: ", last actions = [ switchDP.ofproto_parser.OFPActionSetField(ip_dscp=1), switchDP.ofproto_parser.OFPActionOutput(4) ] self.add_sfc_pop_flow(switchDP, 2, dst, actions,1) path=nx.shortest_path(self.net,SFCs[dst],dst) #path=nx.shortest_path(self.net,src,dst) for i in path: if isinstance(i,int) and i != last: switchDP = api.get_datapath(self, i) #switchId = switchDP.id next = path[path.index(i)+1] pathes=self.net[i][next] out_port=[pathes[p]['port'] for p in pathes if 'port' in pathes[p]][0] #out_port = self.net[i][next][0]['port'] print i, out_port, next if next == dst: actions = [ switchDP.ofproto_parser.OFPActionSetField(ip_dscp=0), switchDP.ofproto_parser.OFPActionOutput(out_port) ] self.add_sfc_flow(switchDP, dst, actions,1) else: actions = [ switchDP.ofproto_parser.OFPActionOutput(out_port) ] self.add_sfc_flow(switchDP, dst, actions,1) #self.add_flow_debug(switchDP, dst, actions) datapath.send_msg(out) return else: print "b:", dst path=nx.shortest_path(self.net,src,dst) next=path[path.index(dpid)+1] pathes=self.net[dpid][next] out_port=[pathes[p]['port'] for p in pathes if 'port' in pathes[p]][0] #out_port=self.net[dpid][next][0]['port'] #path=nx.shortest_path(self.net,src,'00:00:00:00:00:03') actions = [datapath.ofproto_parser.OFPActionOutput(out_port)] self.add_flow(datapath, in_port, dst, actions) print " path: ", path print " outport: ", out_port print " next: ", next print " dpid: ", dpid #print self.net.edges(data=True, keys=True) else: #print "3" out_port = ofproto.OFPP_FLOOD return # install a flow to avoid packet_in next time #if out_port != ofproto.OFPP_FLOOD: # self.add_flow(datapath, in_port, dst, actions) out = datapath.ofproto_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port,actions=actions, data=msg.data) datapath.send_msg(out)