def _handle_PacketIn (event): packet = event.parsed if packet.find("arp"): # Reply to ARP a = packet.find("arp") if a.opcode == a.REQUEST: r = pkt.arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = r.REPLY r.hwdst = a.hwsrc r.protodst = a.protosrc r.protosrc = a.protodst r.hwsrc = EthAddr("02:00:DE:AD:BE:EF") e = pkt.ethernet(type=packet.type, src=r.hwsrc, dst=a.hwsrc) e.payload = r msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = event.port event.connection.send(msg) log.info("%s ARPed for %s", r.protodst, r.protosrc) elif packet.find("icmp"): # Reply to pings # Make the ping reply icmp = pkt.icmp() icmp.type = pkt.TYPE_ECHO_REPLY icmp.payload = packet.find("icmp").payload # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = packet.find("ipv4").dstip ipp.dstip = packet.find("ipv4").srcip # Ethernet around that... e = pkt.ethernet() e.src = packet.dst e.dst = packet.src e.type = e.IP_TYPE # Hook them up... ipp.payload = icmp e.payload = ipp # Send it back to the input port msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = event.port event.connection.send(msg) log.debug("%s pinged %s", ipp.dstip, ipp.srcip)
def send_to_switch(self,packet): switch = packet["switch"] outport = packet["outport"] try: inport = packet["inport"] if inport == -1 or inport == outport: inport = inport_value_hack(outport) except KeyError: inport = inport_value_hack(outport) msg = of.ofp_packet_out() msg.in_port = inport msg.data = self.packet_to_network(packet) msg.actions.append(of.ofp_action_output(port = outport)) if self.show_traces: print "========= POX/OF SEND ================" print msg print packetlib.ethernet(msg._get_data()) print ## HANDLE PACKETS SEND ON LINKS THAT HAVE TIMED OUT try: self.switches[switch]['connection'].send(msg) except Runtimerror, e: print "ERROR:send_to_switch: %s to switch %d" % (str(e),switch)
def packet_to_network(self, packet): self.trace("packet_to_network: packet=%s\n" % packet, timeStamped=True) if len(packet["raw"]) == 0: if packet["ethtype"] == packetlib.ethernet.ARP_TYPE: p_begin = p = self.make_arp(packet) else: # BLANK PACKET FOR NOW - MAY NEED TO SUPPORT OTHER PACKETS LATER p_begin = p = packetlib.ethernet() else: p_begin = p = packetlib.ethernet(packet["raw"]) # ETHERNET PACKET IS OUTERMOST p.src = packet["srcmac"] p.dst = packet["dstmac"] if 'vlan_id' in packet: if isinstance(p.next, packetlib.vlan): p = p.next else: # Make a vlan header old_eth_type = p.type p.type = 0x8100 p.next = packetlib.vlan(next=p.next) p = p.next p.eth_type = old_eth_type p.id = packet['vlan_id'] p.pcp = packet['vlan_pcp'] else: if isinstance(p.next, packetlib.vlan): p.type = p.next.eth_type # Restore encapsulated eth type p.next = p.next.next # Remove vlan from header # GET PACKET INSIDE ETHERNET/VLAN p = p.next if isinstance(p, packetlib.ipv4): p.srcip = packet["srcip"] p.dstip = packet["dstip"] p.protocol = packet["protocol"] p.tos = packet["tos"] p = p.next if isinstance(p, packetlib.udp) or isinstance(p, packetlib.tcp): p.srcport = packet["srcport"] p.dstport = packet["dstport"] elif isinstance(p, packetlib.icmp): p.type = packet["srcport"] p.code = packet["dstport"] elif isinstance(p, packetlib.arp): if 'vlan_id' in packet: p.opcode = packet["protocol"] p.protosrc = packet["srcip"] p.protodst = packet["dstip"] else: p_begin = self.make_arp(packet) return p_begin.pack()
def icmp_ping(self, interface, destination_interface): # randomly choose an in_port. e = ethernet() e.src = interface.hw_addr if destination_interface is not None: e.dst = destination_interface.hw_addr else: # TODO(cs): need a better way to create random MAC addresses e.dst = EthAddr(struct.pack("Q",self.random.randint(1,0xFF))[:6]) e.type = ethernet.IP_TYPE ipp = ipv4() ipp.protocol = ipv4.ICMP_PROTOCOL if hasattr(interface, 'ips'): ipp.srcip = self.random.choice(interface.ips) else: ipp.srcip = IPAddr(self.random.randint(0,0xFFFFFFFF)) if destination_interface is not None and hasattr(destination_interface, 'ips'): ipp.dstip = self.random.choice(destination_interface.ips) else: ipp.dstip = IPAddr(self.random.randint(0,0xFFFFFFFF)) ping = icmp() ping.type = self.random.choice([TYPE_ECHO_REQUEST,TYPE_ECHO_REPLY]) ping.payload = "PingPing" * 6 ipp.payload = ping e.payload = ipp return e
def send_icmp_msg_large(self, event, src_ip = IP_ANY, dst_ip = IP_ANY, src_mac = ETHER_BROADCAST, dst_mac = ETHER_BROADCAST, payload = None, icmp_type = pkt.TYPE_ECHO_REPLY): icmp = pkt.icmp() icmp.type = icmp_type icmp.payload = payload # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = src_ip ipp.dstip = dst_ip e = pkt.ethernet() e.src = src_mac e.dst = dst_mac e.type = e.IP_TYPE ipp.payload = icmp e.payload = ipp msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = event.port event.connection.send(msg)
def create_discovery_packet (self, dpid, port_num, port_addr): """ Build discovery packet """ chassis_id = pkt.chassis_id(subtype=pkt.chassis_id.SUB_LOCAL) chassis_id.id = bytes('dpid:' + hex(long(dpid))[2:-1]) # Maybe this should be a MAC. But a MAC of what? Local port, maybe? port_id = pkt.port_id(subtype=pkt.port_id.SUB_PORT, id=str(port_num)) ttl = pkt.ttl(ttl = self._ttl) sysdesc = pkt.system_description() sysdesc.payload = bytes('dpid:' + hex(long(dpid))[2:-1]) discovery_packet = pkt.lldp() discovery_packet.tlvs.append(chassis_id) discovery_packet.tlvs.append(port_id) discovery_packet.tlvs.append(ttl) discovery_packet.tlvs.append(sysdesc) discovery_packet.tlvs.append(pkt.end_tlv()) eth = pkt.ethernet(type=pkt.ethernet.LLDP_TYPE) eth.src = port_addr eth.dst = pkt.ETHERNET.NDP_MULTICAST eth.payload = discovery_packet po = of.ofp_packet_out(action = of.ofp_action_output(port=port_num)) po.data = eth.pack() return po.pack()
def send_icmp_msg_small(self, packet, match, event, icmp_type = pkt.TYPE_ECHO_REPLY, payload = None): pload = payload if payload is not None or packet is None or packet.find("icmp") is None else packet.find("icmp").payload return self.send_icmp_msg_large(event, packet.find("ipv4").dstip, packet.find("ipv4").srcip, packet.dst, packet.src, pload, icmp_type) icmp = pkt.icmp() icmp.type = pkt.TYPE_ECHO_REPLY icmp.payload = packet.find("icmp").payload # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = packet.find("ipv4").dstip ipp.dstip = packet.find("ipv4").srcip e = pkt.ethernet() e.src = packet.dst e.dst = packet.src e.type = e.IP_TYPE ipp.payload = icmp e.payload = ipp msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = event.port event.connection.send(msg) log.debug("%s pinged %s", ipp.dstip, ipp.srcip)
def _handle_arp(self, event, ether_pkt, arp_pkt): # Update the ARP table with the info for the sender. self._packet_logger.action('Add ARP Entry', [ ('IP Address', arp_pkt.protosrc), ('MAC Address', arp_pkt.hwsrc) ]) self._arp_table.add(arp_pkt.protosrc, arp_pkt.hwsrc) if not is_special_mac(arp_pkt.hwdst): # If the hardware destination is a normal MAC address, add it to the ARP table. self._packet_logger.action('Add ARP Entry', [ ('IP Address', arp_pkt.protodst), ('MAC Address', arp_pkt.hwdst) ]) self._arp_table.add(arp_pkt.protodst, arp_pkt.hwdst) if arp_pkt.opcode == arp.REQUEST: # Try to find a known MAC address for the requested IP address and send a reply ourselves. requested_ip = arp_pkt.protodst requested_mac = self._arp_table.lookup(requested_ip) self._packet_logger.metric('ARP Target', [ ('IP', requested_ip), ('MAC', requested_mac) ]) if requested_mac: self._packet_logger.action('ARP Reply', [ ('Requested MAC', requested_mac), ('Out Port', event.ofp.in_port) ]) arp_reply = arp(hwsrc = requested_mac, hwdst = arp_pkt.hwsrc, opcode = arp.REPLY, protosrc = requested_ip, protodst = arp_pkt.protosrc) ether = ethernet(type = ethernet.ARP_TYPE, dst = arp_pkt.hwsrc, src = requested_mac, payload = arp_reply) self._send_packet(ether, event.ofp.in_port) return True
def arpReply(self, e): ''' This method builds and sends ARP reply in response to ARP Request. e = payload of original IP packet received ''' # Create ARP reply header (Ethernet) if (e.protodst in self.interface): dev = self.interface[e.protodst][1] ethpkt = pktlib.ethernet() ethpkt.src = self.interface[e.protodst][2] ethpkt.dst = e.hwsrc ethpkt.type = ethpkt.ARP_TYPE arp_rep = pktlib.arp() arp_rep.opcode = pktlib.arp.REPLY arp_rep.protosrc = e.protodst arp_rep.protodst = e.protosrc arp_rep.hwsrc = self.interface[e.protodst][2] arp_rep.hwdst = e.hwsrc # Encapsulate eth packet ethpkt.set_payload(arp_rep) # Send it back to the src address self.net.send_packet(dev,ethpkt) return
def pi_cb (data, parser): global _pis, _pos packet = pkt.ethernet(data) if packet.find('tcp'): if packet.find('tcp').dstport == _of_port or \ packet.find('tcp').srcport == _of_port: p = packet.find('tcp').payload assert p[0] == '\x01' t = ord(p[1]) packet_length = ord(p[2]) << 8 | ord(p[3]) if packet_length != len(p): log.error("%s != %s" % (packet_length, len(p))) if t == of.OFPT_PACKET_IN: if _out_only: return l,p = of.ofp_packet_in.unpack_new(p) _pis += 1 elif t == of.OFPT_PACKET_OUT: if _in_only: return l,p = of.ofp_packet_out.unpack_new(p) _pos += 1 else: return assert l == len(p) _writer.write(p.data, time=parser._time, wire_size=parser._wire_size)
def _rx_packet(self, rx_packet): """ process a dataplane packet data: an instance of packet data in_port: the integer port number packet_data: packed version of packet if available :param in_packet: :param in_port: :param packet_data: :return: """ in_port = rx_packet['inport'] in_packet = rx_packet['raw'] p = self.ports.get(in_port) if p is None: log.warn("Got packet on missing port %i", in_port) return _packet = ethernet(in_packet) log.debug(_packet.dump()) if self.policy: in_concrete_packet = rx_packet in_pyretic_packet = concrete_to_pydatapath(in_concrete_packet) out_pyretic_packets = self.policy.eval(in_pyretic_packet) out_concrete_packets = map(pydatapath_to_concrete, out_pyretic_packets) map(self._tx_packet, out_concrete_packets) else: log.warn("Switch (%s) target.datapath policy not defined", self.name)
def create_eth_header(self, pkt, dstMAC, srcMAC): ether = ethernet() #creates an ethernet packet ether.type = ethernet.IP_TYPE #NECESSARY?? ether.src = srcMAC #SRC is own mac addr ether.dst = dstMAC #MACaddress ether.set_payload(pkt.payload) #adds the payload which == None return ether
def reply_to_ping(self, event): # Reply to pings packet=event.parsed # Make the ping reply icmp = pkt.icmp() icmp.type = pkt.TYPE_ECHO_REPLY icmp.payload = packet.find("icmp").payload # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL packet=event.parsed ipp.srcip = packet.find("ipv4").dstip ipp.dstip = packet.find("ipv4").srcip # Ethernet around that... e = pkt.ethernet() e.src = packet.dst e.dst = packet.src e.type = e.IP_TYPE # Hook them up... ipp.payload = icmp e.payload = ipp # Send it back to the input port msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = event.port event.connection.send(msg) log.debug("%s pinged %s", ipp.dstip, ipp.srcip)
def perform(self, event): packet = event.parse() n = packet.find("ipv4") i = packet.find("icmp") # Create echo reply icmp. icmp = pkt.icmp() icmp.type = pkt.TYPE_ECHO_REPLY icmp.payload = i.payload # Create ipv4 packet ipp. ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = n.dstip ipp.dstip = n.srcip # Create ethernet packet e. e = pkt.ethernet() e.src = packet.dst e.dst = packet.src e.type = e.IP_TYPE # Link the payloads. ipp.payload = icmp e.payload = ipp # Create PacketOut msg. msg = of.ofp_packet_out() msg.data = e.pack() msg.in_port = event.port msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) event.connection.send(msg)
def perform(self, event): packet = event.parse() a = packet.find("arp") # Create arp reply r. r = pkt.arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = r.REPLY r.hwdst = a.hwsrc r.protodst = a.protosrc r.protosrc = a.protodst r.hwsrc = self.macAddr # Create ethernet packet e. e = pkt.ethernet(type=packet.type, src=self.macAddr, dst=packet.src) e.payload = r # Create PacketOut msg. msg = of.ofp_packet_out() msg.data = e.pack() msg.in_port = event.port msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) event.connection.send(msg)
def gratuitousARP(self,vs): if vs is None: vswitches = self.net[0xaabbcc].vswitch else: vswitches = dict(only=vs) for k in vswitches.keys(): v = vswitches[k] pkt_eth = pkt.ethernet(dst=pkt.ETHER_BROADCAST,src=v.hw_addr) pkt_eth.type = pkt.ethernet.VLAN_TYPE pkt_vlan = pkt.vlan(id=v.vstag) pkt_vlan.eth_type = pkt.ethernet.ARP_TYPE grat = pkt.arp() grat.opcode = pkt.arp.REQUEST grat.hwsrc = pkt_eth.src grat.hwdst = pkt_eth.dst grat.payload = b'\x0f' * 8 pkt_eth.payload=pkt_vlan pkt_vlan.payload=grat dpid = self.net[0xaabbcc].getDPID(v) msg = of.ofp_packet_out(data=pkt_eth) msg.actions.append(of.ofp_action_output(port = v.uplink)) try: conn = core.openflow.getConnection(dpid) self.log.debug("Sending gratuitousARP for %s" % v) conn.send(msg) except: raise RuntimeError("can't send msg to vSwitch %s" % v)
def reply (self, event, msg): orig = event.parsed.find('dhcp') broadcast = (orig.flags & orig.BROADCAST_FLAG) != 0 msg.op = msg.BOOTREPLY msg.chaddr = event.parsed.src msg.htype = 1 msg.hlen = 6 msg.xid = orig.xid msg.add_option(pkt.DHCP.DHCPServerIdentifierOption(self.ip_addr)) ethp = pkt.ethernet(src=ip_for_event(event),dst=event.parsed.src) ethp.type = pkt.ethernet.IP_TYPE ipp = pkt.ipv4(srcip = self.ip_addr) ipp.dstip = event.parsed.find('ipv4').srcip if broadcast: ipp.dstip = IP_BROADCAST ethp.dst = pkt.ETHERNET.ETHER_BROADCAST ipp.protocol = ipp.UDP_PROTOCOL udpp = pkt.udp() udpp.srcport = pkt.dhcp.SERVER_PORT udpp.dstport = pkt.dhcp.CLIENT_PORT udpp.payload = msg ipp.payload = udpp ethp.payload = ipp po = of.ofp_packet_out(data=ethp.pack()) po.actions.append(of.ofp_action_output(port=event.port)) event.connection.send(po)
def arpBuilder(self, dev, pkt, nexthop, retry): ''' This method builds and sends ARP request ''' if (pkt.type == pkt.IP_TYPE): e=pkt.payload if dev in self.devInterface: tempeth = self.devInterface[dev][0] tempip = self.devInterface[dev][1] ethpkt = pktlib.ethernet() ethpkt.src = tempeth ethpkt.dst = ETHER_BROADCAST ethpkt.type = ethpkt.ARP_TYPE # arp header arp_req = pktlib.arp() arp_req.opcode = pktlib.arp.REQUEST arp_req.protosrc = tempip if (nexthop==IPAddr("0")): arp_req.protodst = e.dstip else: arp_req.protodst = nexthop arp_req.hwsrc = tempeth arp_req.hwdst = EthAddr('ff:ff:ff:ff:ff:ff') # Encapsulate the packet and send it ethpkt.set_payload(arp_req) self.arpRequest(dev, pkt, ethpkt, retry)
def sendICMP(self,type_,code,ip,packet): icm = icmp() icm.type=type_ icm.code=code d = packet.next.pack() d = d[:packet.next.hl * 4+8] d = struct.pack("!HH", 0,0) + d icm.payload = d # icmp.type = pkt.TYPE_DEST_UNREACH # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = self.ip ipp.dstip = ip.srcip # Ethernet around that... e = pkt.ethernet() e.src = self.mac e.dst = packet.src e.type = e.IP_TYPE # Hook them up... ipp.set_payload(icm) e.set_payload(ipp) # Send it back to the input port msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = self.event_port self.connection.send(msg)
def handle_icmp(self,event): print "Replying to Ping: ",event.dpid packet = event.parsed icmp_reply = icmp() icmp_reply.type = pkt.TYPE_ECHO_REPLY icmp_reply.payload = packet.find("icmp").payload # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = packet.find("ipv4").dstip ipp.dstip = packet.find("ipv4").srcip # Ethernet around that... e = pkt.ethernet() e.src = packet.dst e.dst = packet.src e.type = e.IP_TYPE # Hook them up... ipp.payload = icmp_reply e.payload = ipp # Send it back to the input port msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = event.port event.connection.send(msg)
def examineStalled(self): keys = self.arp_ip.keys() #Can/will lose keys during iteration for dst in keys: stalled = self.arp_ip.pop(dst) if dst in self.ip_to_ether: #We've since figured this one out dst_eth = self.ip_to_ether[dst] for ether_pkt in stalled.getList(): #Send out all the waiting packets ether_pkt.dst = dst_eth self.net.send_packet(stalled.intf_name, ether_pkt) else: difference = time.time() - stalled.start_time sentICMP = False if difference/stalled.tries > 1: if stalled.tries >=5: #Timeout, send ICMP timeout ether = stalled.packet_list[0] # one of the ethernet packets that are queued up is all we need to get IP info icmp_error = self.makeICMP(pktlib.TYPE_DEST_UNREACH, pktlib.CODE_UNREACH_HOST, ether.payload) ip_reply = self.makeIP(icmp_error, ether.payload.srcip, self.nameMap[stalled.dev][1]) ether = ethernet() #wrap ip in ether because forward_packet uses ethernet packets ether.type = ether.IP_TYPE ether.set_payload(ip_reply) self.forward_packet(ether, stalled.intf_name) sentICMP = True else: self.net.send_packet(stalled.intf_name, stalled.arp_req) #Send ARP again stalled.tries += 1 if not sentICMP: self.arp_ip[dst] = stalled #Add stalled back to the dict
def send_udp_packet_out(self, conn, payload, tp_src, tp_dst,src_ip, dst_ip, src_mac, dst_mac, fw_port = of.OFPP_ALL): msg = of.ofp_packet_out(in_port=of.OFPP_NONE) msg.buffer_id = None #Make the udp packet udpp = pkt.udp() udpp.srcport = tp_src udpp.dstport = tp_dst udpp.payload = payload #Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.UDP_PROTOCOL ipp.srcip = IPAddr(src_ip) ipp.dstip = IPAddr(dst_ip) # Ethernet around that... ethp = pkt.ethernet() ethp.src = EthAddr(src_mac) ethp.dst = EthAddr(dst_mac) ethp.type = ethp.IP_TYPE # Hook them up... ipp.payload = udpp ethp.payload = ipp # Send it to the sw msg.actions.append(of.ofp_action_output(port = fw_port)) msg.data = ethp.pack() #show msg before sending """ print '*******************' print 'msg.show(): ',msg.show() print '*******************' """ #print "send_udp_packet_out; sw%s and fw_port:%s" %(conn.dpid, fw_port) conn.send(msg)
def reply_icmp_error(self, event, icmp_type, code): print "Replying Host Unreachable from ", event.dpid packet = event.parsed icmp_reply = icmp() icmp_reply.type = icmp_type icmp_reply.code = code # icmp_reply.payload = packet.find("icmp").payload d = packet.next.pack() d = d[:packet.next.hl*4+8] d = struct.pack("!HH", 0, 0) + d icmp_reply.payload = d # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = self.ip ipp.dstip = packet.find("ipv4").srcip # Ethernet around that... e = pkt.ethernet() e.src = self.mac e.dst = packet.src e.type = e.IP_TYPE # Hook them up... ipp.payload = icmp_reply e.payload = ipp # Send it back to the input port msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = event.port print "Sending to (fromIP, toIP, fromMAC, toMAC) : ", ipp.srcip, ipp.dstip, e.src, e.dst event.connection.send(msg)
def _send_arp_request(self, nw_dst): # If the ARP is for an IP on the internal network, use the internal gateway IP # address as the source and flood it. if IPAddr(nw_dst).in_network(self._network, netmask = self._netmask): proto_src = self._gateway_ip out_port = of.OFPP_FLOOD else: # Otherwise, use the external NAT IP address and send it out the uplink. proto_src = self._nat_ip out_port = self._uplink_port self._packet_logger.action('Send ARP Request', [ ('Source MAC', self._gateway_mac), ('Dest MAC', SpecialMacs.ARP_REQUEST_DESTINATION), ('Source IP', proto_src), ('Dest IP', nw_dst) ]) arp_request = arp( hwsrc = self._gateway_mac, hwdst = SpecialMacs.ARP_REQUEST_DESTINATION, opcode = arp.REQUEST, protosrc = proto_src, protodst = nw_dst) ether = ethernet(type = ethernet.ARP_TYPE, src = self._gateway_mac, dst = SpecialMacs.BROADCAST, payload = arp_request) self._send_packet(ether, out_port)
def generate_example_trace_fat_tree(num_pods=4): # TODO(cs): highly redundant fat_tree = topo.FatTree(num_pods) (_, _, hosts, access_links) = (fat_tree.switches, fat_tree.network_links, fat_tree.hosts, fat_tree.access_links) host2pings = defaultdict(lambda: []) payload = "ping" for access_link in access_links: host = access_link.host other_hosts = list((set(hosts) - set([access_link.host]))) for other_host in other_hosts: eth = ethernet(src=access_link.host.interfaces[0].hw_addr,dst=other_host.interfaces[0].hw_addr,type=ethernet.IP_TYPE) dst_ip_addr = other_host.interfaces[0].ips[0] ipp = ipv4(protocol=ipv4.ICMP_PROTOCOL, srcip=access_link.host.interfaces[0].ips[0], dstip=dst_ip_addr) ping = icmp(type=TYPE_ECHO_REQUEST, payload=payload) ipp.payload = ping eth.payload = ipp host2pings[host].append(DataplaneEvent(access_link.interface, eth)) # ping pong (no responses) between fake hosts # (Some large number: TODO(cs): serialize a generator to disk) # Trace is [one ping from every host to a random other host] * 50000 trace = [] for _ in range(50000): for host, pings in host2pings.iteritems(): trace.append(random.choice(pings)) write_trace_log(trace, "dataplane_traces/ping_pong_fat_tree.trace")
def generate_example_trace(): trace = [] mesh = topo.MeshTopology(num_switches=2) hosts = mesh.hosts access_links = mesh.access_links packet_events = [] ping_or_pong = "ping" for access_link in access_links: other_host = (set(hosts) - set([access_link.host])).pop() eth = ethernet(src=access_link.host.interfaces[0].hw_addr,dst=access_link.switch_port.hw_addr,type=ethernet.IP_TYPE) dst_ip_addr = other_host.interfaces[0].ips[0] ipp = ipv4(protocol=ipv4.ICMP_PROTOCOL, srcip=access_link.host.interfaces[0].ips[0], dstip=dst_ip_addr) if ping_or_pong == "ping": ping = icmp(type=TYPE_ECHO_REQUEST, payload=ping_or_pong) else: ping = icmp(type=TYPE_ECHO_REPLY, payload=ping_or_pong) ipp.payload = ping eth.payload = ipp packet_events.append(DataplaneEvent(access_link.interface, eth)) # ping ping (no responses) between fake hosts for _ in range(40): trace.append(packet_events[0]) trace.append(packet_events[1]) write_trace_log(trace, "dataplane_traces/ping_pong.trace")
def router_main(self): while True: try: dev,ts,pkt = self.net.recv_packet(timeout=1.0) except SrpyNoPackets: # log_debug("Timeout waiting for packets") continue except SrpyShutdown: return if pkt.type == pkt.ARP_TYPE: arp_request = pkt.payload for intf in self.net.interfaces(): if (intf.ipaddr==arp_request.protodst): arp_reply = pktlib.arp() arp_reply.protodst = arp_request.protosrc arp_reply.protosrc = intf.ipaddr arp_reply.hwsrc = intf.ethaddr arp_reply.hwdst = arp_request.hwsrc arp_reply.opcode = pktlib.arp.REPLY ether = pktlib.ethernet() ether.type = ether.ARP_TYPE ether.src = intf.ethaddr ether.dst = arp_request.hwsrc ether.set_payload(arp_reply) self.net.send_packet(dev, ether) #self.net.send_packet(dev, arp_reply) break
def generate_example_trace_same_subnet(): # TODO: highly redundant trace = [] (patch_panel, switches, network_links, hosts, access_links) = topo_gen.create_mesh(num_switches=2) packet_events = [] ping_or_pong = "ping" for access_link in access_links: other_host = (set(hosts) - set([access_link.host])).pop() eth = ethernet(src=access_link.host.interfaces[0].mac,dst=other_host.interfaces[0].mac,type=ethernet.IP_TYPE) dst_ip_addr = other_host.interfaces[0].ips[0] ipp = ipv4(protocol=ipv4.ICMP_PROTOCOL, srcip=access_link.host.interfaces[0].ips[0], dstip=dst_ip_addr) if ping_or_pong == "ping": ping = icmp(type=TYPE_ECHO_REQUEST, payload=ping_or_pong) else: ping = icmp(type=TYPE_ECHO_REPLY, payload=ping_or_pong) ipp.payload = ping eth.payload = ipp packet_events.append(DataplaneEvent(access_link.interface, eth)) # ping ping (no responses) between fake hosts for _ in range(40): trace.append(packet_events[0]) trace.append(packet_events[1]) write_trace_log(trace, "traces/ping_pong_same_subnet.trace")
def _create_broadcast_discovery_packet (dpid, port_num, port_addr, ttl): chassis_id = pkt.chassis_id(subtype=pkt.chassis_id.SUB_LOCAL) chassis_id.id = bytes('dpid:' + hex(long(dpid))[2:-1]) # Maybe this should be a MAC. But a MAC of what? Local port, maybe? port_id = pkt.port_id(subtype=pkt.port_id.SUB_PORT, id=str(port_num)) ttl = pkt.ttl(ttl = ttl) sysdesc = pkt.system_description() sysdesc.payload = bytes('dpid:' + hex(long(dpid))[2:-1]) discovery_packet = pkt.lldp() discovery_packet.tlvs.append(chassis_id) discovery_packet.tlvs.append(port_id) discovery_packet.tlvs.append(ttl) discovery_packet.tlvs.append(sysdesc) discovery_packet.tlvs.append(pkt.end_tlv()) eth = pkt.ethernet(type=pkt.ethernet.LLDP_TYPE) eth.src = port_addr eth.dst = pkt.ETHERNET.ETHER_BROADCAST eth.payload = discovery_packet return eth
def send_discovery_packet(event): """ Sends the discovery packet used to identity the links present between the switches""" for p in event.ofp.ports: chass_id = event.dpid src = str(p.hw_addr) portno = p.port_no chassis_id = pktt.chassis_id(subtype=pktt.chassis_id.SUB_LOCAL, id = str(chass_id)) port_id = pktt.port_id(subtype = pktt.port_id.SUB_PORT, id = str(portno)) ttl = pktt.ttl(ttl = lldp_ttl) discovery_packet = pktt.lldp() discovery_packet.tlvs.append(chassis_id) discovery_packet.tlvs.append(port_id) discovery_packet.tlvs.append(ttl) discovery_packet.tlvs.append(pktt.end_tlv()) eth = pktt.ethernet(type = pktt.ethernet.LLDP_TYPE) eth.src = src eth.dst = pktt.ETHERNET.NDP_MULTICAST eth.payload = discovery_packet pkt = of.ofp_packet_out(action = of.ofp_action_output(port = portno)) pkt.data = eth.pack() event.connection.send(pkt.pack())
def act_like_router(self, packet, packet_in): #handle ARP Requests and replies etherPayload = packet.payload #the stripped ethFrame, contains ipv4 or arp packet src_mac = packet.src dst_mac = packet.dst if packet.type == pkt.ethernet.ARP_TYPE: src_ip = etherPayload.protosrc dst_ip = etherPayload.protodst if etherPayload.opcode == pkt.arp.REQUEST: print( "received ARP REQUEST checking if i have info on sender: " + str(src_mac)) if src_mac not in self.mac_to_port: print("sender mac unknown, adding to mac table...") self.mac_to_port[src_mac] = packet_in.in_port if src_ip not in self.arp_table: print("sender ip unknown, adding to arp table...") self.arp_table[src_ip] = src_mac if src_ip not in self.ip_to_port: print("sender ip unknown, adding to ip table...") self.ip_to_port[src_ip] = packet_in.in_port self.displayTables() #creating arp reply to send back arp_reply = pkt.arp() arp_reply.hwsrc = adr.EthAddr( "11:12:13:14:15:16") # fake mac in response arp_reply.hwdst = etherPayload.hwsrc arp_reply.opcode = pkt.arp.REPLY arp_reply.protosrc = etherPayload.protodst arp_reply.protodst = etherPayload.protosrc # encapsulate in ethernet frame now ether = pkt.ethernet() ether.type = pkt.ethernet.ARP_TYPE ether.dst = packet.src ether.src = packet.dst ether.payload = arp_reply #sending packet to switch self.resend_packet(ether, packet_in.in_port) elif packet.type == pkt.ethernet.IP_TYPE: if etherPayload.protocol == pkt.ipv4.ICMP_PROTOCOL: icmp_packet = etherPayload.payload src_ip = etherPayload.srcip dst_ip = etherPayload.dstip k = 0 #subnet holder if icmp_packet.type == pkt.TYPE_ECHO_REQUEST: if src_mac not in self.mac_to_port: print("sender mac unknown, adding to mac table...") self.mac_to_port[src_mac] = packet_in.in_port if src_ip not in self.arp_table: print("sender ip unknown, adding to arp table...") self.arp_table[src_ip] = src_mac if src_ip not in self.ip_to_port: print("sender ip unknown, adding to ip table...") self.ip_to_port[src_ip] = packet_in.in_port self.displayTables() for subnet in self.routing_table: if dst_ip.inNetwork(subnet): k = subnet if k != 0: #create ping reply # create echo fields ech = pkt.echo() # echo contained in pkt.icmp ech.id = icmp_packet.payload.id ech.seq = icmp_packet.payload.seq + 1 # encapsulates in icmp icmp_reply = pkt.icmp() icmp_reply.type = pkt.TYPE_ECHO_REPLY # code 0 icmp_reply.payload = ech # encapsulates in ipv4 ip_p = pkt.ipv4() ip_p.protocol = pkt.ipv4.ICMP_PROTOCOL ip_p.srcip = dst_ip ip_p.dstip = src_ip ip_p.payload = icmp_reply # encapsulates in ethernet eth_p = pkt.ethernet() eth_p.type = pkt.ethernet.IP_TYPE eth_p.src = packet.dst eth_p.dst = packet.src eth_p.payload = ip_p msg = of.ofp_packet_out() msg.data = eth_p.pack() action = of.ofp_action_output(port=packet_in.in_port) msg.actions.append(action) self.connection.send(msg) print("echo Reply sent!") self.createflow(packet_in, eth_p, packet_in.in_port) else: print("ICMP destination unreachable") unr = pkt.unreach() unr.payload = etherPayload icmp_reply = pkt.icmp() icmp_reply.type = pkt.TYPE_DEST_UNREACH icmp_reply.payload = unr ip_p = pkt.ipv4() ip_p.srcip = dst_ip ip_p.dstip = src_ip ip_p.protocol = pkt.ipv4.ICMP_PROTOCOL ip_p.payload = icmp_reply eth_p = pkt.ethernet() eth_p.type = pkt.ethernet.IP_TYPE eth_p.dst = packet.src eth_p.src = packet.dst eth_p.payload = ip_p msg = of.ofp_packet_out() msg.data = eth_p.pack() action = of.ofp_action_output(port=packet_in.in_port) msg.actions.append(action) self.connection.send(msg) print("echo Unreachable Reply sent!") self.createflow(packet_in, eth_p, packet_in.in_port) #other type of ip packet maybe udp or tcp else: src_ip = etherPayload.srcip dst_ip = etherPayload.dstip if dst_ip in self.ip_to_port and dst_ip in self.arp_table: print("received other type of packet sending reply...") out_port = self.ip_to_port[dst_ip] eth_dest = self.arp_table[dst_ip] msg = of.ofp_packet_out() packet.src = packet.dst #since who received the packet is sending the reply set src = dst packet.dst = adr.EthAddr(eth_dest) msg.data = packet.pack() action = of.ofp_action_output(port=out_port) msg.actions.append(action) self.connection.send(msg) self.createflow(packet_in, packet, out_port) else: print("who do i send this to I am switch: " + str(self.connection.dpid)) print("packet src ip: " + str(src_ip) + " to: " + str(dst_ip)) self.resend_packet(packet, of.OFPP_ALL) self.createflow(packet_in, packet, of.OFPP_ALL)
''' ''' This is a Client. Can be an IoT Device and use CoAP communication. We just send an IP packet without actually knowing IPv6 with just a tag in the IP packet payload. ''' #Create an IP packet ipv6_packet = ipv6() ipv6_packet.srcip = IPAddr6("::0") #Random IP destination address ipv6_packet.dstip = IPAddr6("::7") ipv6_packet.next_header_type = 0xFD # Set a tag in IP payload. e.g color = red. Tag-Based Forwarding ipv6_packet.payload = "[color='red']" ether = ethernet() ether.type = 0x86DD # Because we don't know the destination mac address we set :00 as mac ether.dst = EthAddr(b"\x00\x00\x00\x00\x00\x00") ether.src = EthAddr(b"\x08\x00\x27\xc8\x18\xa5") ether.payload = ipv6_packet # Open a socket and send the packet through it s = socket(AF_PACKET, SOCK_RAW) s.bind(('h1-eth0', 0)) s.send(ether.pack())
def install_path (self, dst_sw, last_port, match, event): """ Attempts to install a path between this switch and some destination """ p = _get_path(self, dst_sw, event.port, last_port) if p is None: log.warning("Can't get from %s to %s", match.dl_src, match.dl_dst) import pox.lib.packet as pkt if (match.dl_type == pkt.ethernet.IP_TYPE and event.parsed.find('ipv4')): # It's IP -- let's send a destination unreachable log.debug("Dest unreachable (%s -> %s)", match.dl_src, match.dl_dst) e = pkt.ethernet() e.src = EthAddr(dpid_to_str(self.dpid)) #FIXME: Hmm... e.dst = match.dl_src e.type = e.IP_TYPE ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = match.nw_dst #FIXME: Ridiculous ipp.dstip = match.nw_src icmp = pkt.icmp() icmp.type = pkt.ICMP.TYPE_DEST_UNREACH icmp.code = pkt.ICMP.CODE_UNREACH_HOST orig_ip = event.parsed.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] import struct d = struct.pack("!HH", 0,0) + d #FIXME: MTU icmp.payload = d ipp.payload = icmp e.payload = ipp msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = event.port)) msg.data = e.pack() self.connection.send(msg) return if match.nw_dst in virtual_server: vs_ip = match.nw_dst rs_ip = real_servers.get(match.dl_dst) log.debug("Virtual server path %s -> %s(serving by %s, %i hops)", match.nw_src, match.nw_dst, rs_ip, len(p)) self._install_path_mod_dst(p, match.clone(), rs_ip, event.ofp) # Now reverse it and install it backwards # Works well for IPv4 packets # The packet coming back is from the real server. Re-write header # on the last hop. p = [(sw,out_port,in_port) for sw,in_port,out_port in p] match.set_nw_dst(rs_ip) self._install_path_mod_src(p, match.flip(), vs_ip) else: log.debug("Installing path for %s -> %s %04x (%i hops)", match.dl_src, match.dl_dst, match.dl_type, len(p)) # We have a path -- install it self._install_path(p, match, event.ofp) # Now reverse it and install it backwards # (we'll just assume that will work) p = [(sw,out_port,in_port) for sw,in_port,out_port in p] self._install_path(p, match.flip())
def install_path(self, dst_sw, last_port, match, event): """ Attempts to install a path between this switch and some destination """ #print "inside install_path and switches in sequence are self,dst_sw,event.port,last_port" #print str(self)+" "+str(dst_sw)+" "+str(event.port)+" "+str(last_port) print "printing mac_map again" #for key in mac_map: #print key #print mac_map[key] p = _get_path(self, dst_sw, event.port, last_port) print p if p is None: log.warning("Can't get from %s to %s", match.dl_src, match.dl_dst) import pox.lib.packet as pkt if (match.dl_type == pkt.ethernet.IP_TYPE and event.parsed.find('ipv4')): # It's IP -- let's send a destination unreachable log.debug("Dest unreachable (%s -> %s)", match.dl_src, match.dl_dst) from pox.lib.addresses import EthAddr e = pkt.ethernet() e.src = EthAddr(dpid_to_str(self.dpid)) #FIXME: Hmm... e.dst = match.dl_src e.type = e.IP_TYPE ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = match.nw_dst #FIXME: Ridiculous ipp.dstip = match.nw_src icmp = pkt.icmp() icmp.type = pkt.ICMP.TYPE_DEST_UNREACH icmp.code = pkt.ICMP.CODE_UNREACH_HOST orig_ip = event.parsed.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] import struct d = struct.pack("!HH", 0, 0) + d #FIXME: MTU icmp.payload = d ipp.payload = icmp e.payload = ipp msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=event.port)) msg.data = e.pack() self.connection.send(msg) return log.debug("Installing path for %s -> %s %04x (%i hops)", match.dl_src, match.dl_dst, match.dl_type, len(p)) # We have a path -- install it self._install_path(p, match, event.ofp) # Now reverse it and install it backwards # (we'll just assume that will work) #Sumit : We need a reverse path for getting the packets but the reverse path (host B to host A) shouldn't go via service VMs..that should go directly between switchs p = [(sw, out_port, in_port) for sw, in_port, out_port in p] self._install_path(p, match.flip())
def packet_handler (self, frame, packet_in): "process every packet\n" # disposal of different kinds of packet, including a default drop # generates prompt text for non-data packets and all invalid packets isHandled = False if frame.type == Packet.ethernet.ARP_TYPE: arpPkt = frame.payload if arpPkt.opcode == Packet.arp.REQUEST: # check if the arp request has a valid target arp_req = arpPkt srcIPStr = str(arp_req.protosrc) prefix = srcIPStr[0:srcIPStr.rfind(".")] expectedIPdest = prefix + ".1" if expectedIPdest == str(arp_req.protodst): # a valid arp req log.info("a valid arp request is got") arpReply = Packet.arp() macInterface = Addr.EthAddr("00:00:00:00:00:" + prefix[-1]*2) arpReply.hwsrc = macInterface arpReply.hwdst = arp_req.hwsrc arpReply.opcode = Packet.arp.REPLY arpReply.protosrc = Addr.IPAddr(expectedIPdest) arpReply.protodst = arp_req.protosrc ether = Packet.ethernet() ether.type = Packet.ethernet.ARP_TYPE ether.dst = frame.src ether.src = macInterface ether.payload = arpReply msg = of.ofp_packet_out() msg.data = ether action = of.ofp_action_output(port = packet_in.in_port) msg.actions.append(action) self.connection.send(msg) isHandled = True elif frame.type == frame.IP_TYPE: datagram = frame.payload # if it's a valid icmp echo request, reply to it if datagram.protocol == datagram.ICMP_PROTOCOL: segment = datagram.payload if segment.type == Packet.TYPE_ECHO_REQUEST: # check if the destination IP is correct dstIPStr = str(datagram.dstip) if dstIPStr in self.interface_IPs: log.info("an icmp request to router interfaces is got") # generate a reply and send it icmpReply = Packet.icmp() icmpReply.type = Packet.TYPE_ECHO_REPLY icmpReply.payload = segment.payload ipp = Packet.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = datagram.dstip ipp.dstip = datagram.srcip e = Packet.ethernet() e.src = frame.dst e.dst = frame.src e.type = e.IP_TYPE ipp.payload = icmpReply e.payload = ipp msg = of.ofp_packet_out() msg.data = e msg.actions.append( of.ofp_action_output(port = packet_in.in_port)) self.connection.send(msg) isHandled = True # if it's a packet sent to one of the other two hosts dstIPStr = str(datagram.dstip) if dstIPStr in self.routing_table: log.info("a packet between hosts is got") tableEntry = self.routing_table[dstIPStr] # # # flow mod # msg = of.ofp_flow_mod(match = of.ofp_match.from_packet(frame)) # msg.actions.append( # of.ofp_action_dl_addr.set_src(Addr.EthAddr(tableEntry["intMAC"]))) # msg.actions.append( # of.ofp_action_dl_addr.set_dst(Addr.EthAddr(tableEntry["hostMAC"]))) # msg.actions.append(of.ofp_action_output(port = tableEntry["port"])) # self.connection.send(msg) # log.info("a flow entry is installed") # modify data link src and dst frame.src = Addr.EthAddr(tableEntry["intMAC"]) frame.dst = Addr.EthAddr(tableEntry["hostMAC"]) # resend it out self.resend_packet(frame, tableEntry["port"]) isHandled = True if not isHandled: # drop it log.info("an invalid frame is got")
def ICMP_Request_handler(self, packet, packet_in): ip_packet = packet.payload icmp_segment = ip_packet.payload ipSrcAdd = self.route_table.get(str(ip_packet.srcip)) ipDstAdd = self.route_table.get(str(ip_packet.dstip)) if ipDstAdd != None: # router if str(packet.dst) == '00:00:00:00:00:11': if str(ip_packet.dstip) == '10.0.1.1': echo_segment = pkt.echo() echo_segment.seq = icmp_segment.payload.seq + 1 echo_segment.id = icmp_segment.payload.id #icmp packt|echo icmp_reply = pkt.icmp() icmp_reply.type = pkt.TYPE_ECHO_REPLY icmp_reply.payload = echo_segment #ip packet|icmp|echo ip_pack = pkt.ipv4() ip_pack.srcip = ip_packet.dstip ip_pack.dstip = ip_packet.srcip ip_pack.protocol = pkt.ipv4.ICMP_PROTOCOL ip_pack.payload = icmp_reply #frame|ip|icmp|echo ether_pack = pkt.ethernet() ether_pack.dst = packet.src ether_pack.src = packet.dst ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.payload = ip_pack self.send_Packet(frame=ether_pack, out_port=packet_in.in_port) elif ipDstAdd[1] == '10.0.1.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr(ipDstAdd[0]) ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=ipDstAdd[3]) elif ipDstAdd[1] == '10.0.2.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr('00:00:00:00:00:22') ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=3) elif str(packet.dst) == '00:00:00:00:00:22': #echo rely to source Router -> H5 if str(ip_packet.dstip) == '10.0.2.1': echo_segment = pkt.echo() echo_segment.seq = icmp_segment.payload.seq + 1 echo_segment.id = icmp_segment.payload.id #icmp packt|echo icmp_reply = pkt.icmp() icmp_reply.type = pkt.TYPE_ECHO_REPLY icmp_reply.payload = echo_segment #ip packet|icmp|echo ip_pack = pkt.ipv4() ip_pack.srcip = ip_packet.dstip ip_pack.dstip = ip_packet.srcip ip_pack.protocol = pkt.ipv4.ICMP_PROTOCOL ip_pack.payload = icmp_reply #frame|ip|icmp|echo ether_pack = pkt.ethernet() ether_pack.dst = packet.src ether_pack.src = packet.dst ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.payload = ip_pack self.send_Packet(frame=ether_pack, out_port=packet_in.in_port) elif ipDstAdd[1] == '10.0.2.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr(ipDstAdd[0]) ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=ipDstAdd[3]) elif ipDstAdd[1] == '10.0.1.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr('00:00:00:00:00:11') ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=1) else: self.send_Packet(frame=packet, out_port=ipDstAdd[3]) else: #unreach ICMP packet unreachPacket = pkt.unreach() unreachPacket.payload = packet.payload icmp_unreReply = pkt.icmp() icmp_unreReply.type = pkt.TYPE_DEST_UNREACH icmp_unreReply.payload = unreachPacket ip_unrePack = pkt.ipv4() ip_unrePack.srcip = ip_packet.dstip ip_unrePack.dstip = ip_packet.srcip ip_unrePack.protocol = pkt.ipv4.ICMP_PROTOCOL ip_unrePack.payload = icmp_unreReply ether_unrePack = pkt.ethernet() ether_unrePack.src = packet.dst ether_unrePack.dst = packet.src ether_unrePack.type = pkt.ethernet.IP_TYPE ether_unrePack.payload = ip_unrePack self.send_Packet(frame=ether_unrePack, out_port=packet_in.in_port)
def IP_handler(self, packet, packet_in): ip_packet = packet.payload ipSrcAdd = self.route_table.get(str(ip_packet.srcip)) ipDstAdd = self.route_table.get(str(ip_packet.dstip)) if ipDstAdd != None: if str(packet.dst) == '00:00:00:00:00:11': if ipDstAdd[1] == '10.0.1.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr(ipDstAdd[0]) ether_pack.payload = packet.payload msg = of.ofp_flow_mod() msg.match.in_port = packet_in.in_port msg.match = of.ofp_match.from_packet(packet) msg.actions.append( of.ofp_action_dl_addr.set_dst(adr.EthAddr( ipDstAdd[0]))) msg.actions.append( of.ofp_action_dl_addr.set_src(packet.dst)) msg.actions.append(of.ofp_action_output(port=ipDstAdd[3])) self.connection.send(msg) elif ipDstAdd[1] == '10.0.2.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr('00:00:00:00:00:22') ether_pack.payload = packet.payload msg = of.ofp_flow_mod() msg.match.in_port = packet_in.in_port msg.match = of.ofp_match.from_packet(packet) msg.actions.append( of.ofp_action_dl_addr.set_dst(adr.EthAddr( ipDstAdd[0]))) msg.actions.append( of.ofp_action_dl_addr.set_src(packet.dst)) msg.actions.append(of.ofp_action_output(port=3)) self.connection.send(msg) elif str(packet.dst) == '00:00:00:00:00:22': if ipDstAdd[1] == '10.0.2.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr(ipDstAdd[0]) ether_pack.payload = packet.payload msg = of.ofp_flow_mod() msg.match.in_port = packet_in.in_port msg.match = of.ofp_match.from_packet(packet) msg.actions.append( of.ofp_action_dl_addr.set_dst(adr.EthAddr( ipDstAdd[0]))) msg.actions.append( of.ofp_action_dl_addr.set_src(packet.dst)) msg.actions.append(of.ofp_action_output(port=ipDstAdd[3])) self.connection.send(msg) elif ipDstAdd[1] == '10.0.1.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr('00:00:00:00:00:11') ether_pack.payload = packet.payload msg = of.ofp_flow_mod() msg.match.in_port = packet_in.in_port msg.match = of.ofp_match.from_packet(packet) msg.actions.append( of.ofp_action_dl_addr.set_dst(adr.EthAddr( ipDstAdd[0]))) msg.actions.append( of.ofp_action_dl_addr.set_src(packet.dst)) msg.actions.append(of.ofp_action_output(port=1)) self.connection.send(msg) else: msg = of.ofp_flow_mod() msg.match.in_port = packet_in.in_port msg.match = of.ofp_match.from_packet(packet) msg.actions.append( of.ofp_action_dl_addr.set_dst(adr.EthAddr(ipDstAdd[0]))) msg.actions.append(of.ofp_action_dl_addr.set_src(packet.dst)) msg.actions.append(of.ofp_action_output(port=ipDstAdd[3])) self.connection.send(msg)
def act_like_router(self, frame, packet_in, dpid): if frame.type == 0x0806: # ARP type packet = frame.payload network = 0 # arp request and in /30 subnet if packet.opcode == 1 and str(packet.protodst) in self.exterior: arp_data = pocket.arp( hwtype=packet.hwtype, prototype=packet.prototype, hwlen=packet.hwlen, protolen=packet.protolen, opcode=2, hwdst=packet.hwsrc, protodst=packet.protosrc, protosrc=packet.protodst, hwsrc=addresses.EthAddr('FA:DE:DD:ED:AF:AA')) e_frame = ethernet(type=0x0806, src=addresses.EthAddr('FA:DE:DD:ED:AF:AA'), dst=packet.hwsrc) e_frame.payload = arp_data out_packet = of.ofp_packet_out() out_packet.data = e_frame.pack() action = of.ofp_action_output(port=packet_in.in_port) out_packet.actions.append(action) self.connection.send(out_packet) log.debug("arp...") # arp reply and in /30 subnet elif (packet.opcode == 2) and str( packet.protodst) in self.exterior: self.arp_cache[packet.protosrc] = packet.hwsrc to_send = self.store.payload """ for nw in self.routing_table[dpid]: nw1 = self.routing_table[dpid][nw] if str(to_send.dstip) in nw1: network = nw break """ message = of.ofp_packet_out() my_port = self.routing_table[dpid][str(to_send.dstip)][3] action = of.ofp_action_output(port=my_port) self.store.src = addresses.EthAddr('FA:DE:DD:ED:AF:AA') self.store.dst = self.arp_cache[to_send.dstip] message.data = self.store.pack() message.actions.append(action) self.connection.send(message) log.debug("ICMP: sent from router to host") """ message = of.ofp_flow_mod() message.match.nw_dst = to_send.dstip message.match.dl_type = 0x0800 message.actions.append(of.ofp_action_dl_addr.set_src(self.store.src)) message.actions.append(of.ofp_action_dl_addr.set_dst(self.store.dst)) message.actions.append(of.ofp_action_output(port = self.routing_table[dpid][network][3])) log.debug("Flow Mode install Successfully") self.connection.send(message) """ self.store = None elif packet.protodst in self.interior: """ msg = of.ofp_packet_out() msg.data = frame.pack() my_port = self.routing_table[dpid][str(packet.protodst)][3] action = of.ofp_action_output(port = my_port) msg.actions.append(action) self.connection.send(msg) """ msg = of.ofp_flow_mod() msg.match = of.ofp_match.from_packet(frame) msg.data = packet_in action = of.ofp_action_output( port=self.routing_table[dpid][str(packet.protodst)][3]) msg.actions.append(action) self.connection.send(msg) elif frame.type == 0x0800: # IP type """ network = 0 for nw in self.interior: nw1 = nw if str(frame.payload.dstip) in nw1: network = nw break """ packet = frame.payload if str(packet.dstip) not in self.interior: # dst unreachable log.debug("dst %s is unreachable" % (frame.payload.dstip)) unreachable_type = pocket.unreach() unreachable_type.payload = frame.payload icmp_type = pocket.icmp() icmp_type.type = 3 icmp_type.payload = unreachable_type ip_type = pocket.ipv4(srcip=frame.payload.dstip, dstip=frame.payload.srcip, protocol=1, payload=icmp_type) ethernet_type = pocket.ethernet(type=0x0800, src=frame.dst, dst=frame.src, payload=ip_type) message = of.ofp_packet_out() message.data = ethernet_type.pack() message.actions.append( of.ofp_action_output(port=packet_in.in_port)) self.connection.send(message) # if ICMP type elif packet.protocol == 1 and packet.payload.type == 8 and str( packet.dstip) == self.exterior[dpid - 1]: data_icmp = packet.payload # if data_icmp.type == 8 and str(packet.dstip) in self.exterior: #if echo_request and dstip is in exterior echo_type = pocket.echo(seq=data_icmp.payload.seq + 1, id=data_icmp.payload.id) icmp_type = pocket.icmp(type=0, payload=echo_type) ip_type = pocket.ipv4(srcip=packet.dstip, dstip=packet.srcip, protocol=1, payload=icmp_type) ethernet_type = pocket.ethernet(type=0x0800, src=frame.dst, dst=frame.src, payload=ip_type) message = of.ofp_packet_out() message.data = ethernet_type.pack() message.actions.append( of.ofp_action_output(port=packet_in.in_port)) self.connection.send(message) elif packet.dstip in self.dirconnex[dpid]: port_num = self.routing_table[dpid][str(packet.dstip)][3] if packet.dstip not in self.arp_cache: # mapping of dstip not present self.store = frame arp_type = arp( hwlen=6, hwdst=ETHER_BROADCAST, protodst=packet.dstip, hwsrc=addresses.EthAddr('FA:DE:DD:ED:AF:AA'), protosrc=addresses.IPAddr(self.routing_table[dpid][str( packet.dstip)][2])) arp_type.opcode = 1 ethernet_type = ethernet( type=0x0806, src=addresses.EthAddr('FA:DE:DD:ED:AF:AA'), dst=ETHER_BROADCAST) ethernet_type.set_payload(arp_type) message = of.ofp_packet_out() message.data = ethernet_type.pack() message.actions.append( of.ofp_action_output(port=self.routing_table[dpid][str( packet.dstip)][3])) message.in_port = packet_in.in_port self.connection.send(message) elif packet.dstip in self.arp_cache: # mapping present in arp cache message = of.ofp_packet_out() action = of.ofp_action_output( port=self.routing_table[dpid][str(packet.dstip)][3]) frame.src = addresses.EthAddr('FA:DE:DD:ED:AF:AA') frame.dst = self.arp_cache[packet.dstip] message.data = frame.pack() message.actions.append(action) self.connection.send(message) """ message = of.ofp_flow_mod() message.match.nw_dst = packet.dstip message.match.dl_type = 0x0800 message.actions.append(of.ofp_action_dl_addr.set_src(frame.src)) message.actions.append(of.ofp_action_dl_addr.set_dst(frame.dst)) message.actions.append(of.ofp_action_output(port = self.routing_table[network][3])) self.connection.send(message) """ else: # route to the next hop log.debug("the packet proceeds to the next hop") port_to_send = self.routing_table[dpid][str(packet.dstip)][3] next_ip = self.routing_table[dpid][str(packet.dstip)][0] msg = of.ofp_packet_out() action = of.ofp_action_output(port=port_to_send) frame.dst = ETHER_BROADCAST frame.src = addresses.EthAddr('FA:DE:DD:ED:AF:AA') msg.data = frame.pack() msg.actions.append(action) self.connection.send(msg) log.debug("IPv4 has been sent")
def act_like_router(self, packet, packet_in): #handle arp if packet.type == pkt.ethernet.ARP_TYPE: if packet.payload.opcode == pkt.arp.REQUEST: log.debug("ARP request received") arp_reply = pkt.arp() arp_reply.hwsrc = adr.EthAddr("40:10:40:10:40:10") #fake MAC arp_reply.hwdst = packet.payload.hwsrc arp_reply.opcode = pkt.arp.REPLY arp_reply.protosrc = packet.payload.protodst arp_reply.protodst = packet.payload.protosrc ether = pkt.ethernet() ether.type = pkt.ethernet.ARP_TYPE ether.dst = packet.src ether.src = packet.dst ether.payload = arp_reply msg = of.ofp_packet_out() msg.data = ether.pack() # Add an action to send to the specified port action = of.ofp_action_output(port=packet_in.in_port) msg.actions.append(action) #msg.in_port = event.port # Send message to switch self.connection.send(msg) log.debug("ARP reply sent") elif packet.payload.opcode == pkt.arp.REPLY: log.debug("It's a reply!") self.mac_to_port[packet.src] = packet_in.in_port else: log.debug("Some other ARP opcode") elif packet.type == pkt.ethernet.IP_TYPE: ip_packet = packet.payload if ip_packet.protocol == pkt.ipv4.ICMP_PROTOCOL: icmp_packet = ip_packet.payload if icmp_packet.type == pkt.TYPE_ECHO_REQUEST: log.debug("ICMP request received") src_ip = ip_packet.srcip dst_ip = ip_packet.dstip k = 0 for key in self.routing_table.keys(): if dst_ip.inNetwork(key): k = key break if k != 0: log.debug("ICMP reply sent") log.debug("network containing host: " + k) ech = pkt.echo() ech.seq = icmp_packet.payload.seq + 1 ech.id = icmp_packet.payload.id icmp_reply = pkt.icmp() icmp_reply.type = pkt.TYPE_ECHO_REPLY icmp_reply.payload = ech ip_p = pkt.ipv4() ip_p.srcip = dst_ip ip_p.dstip = src_ip ip_p.protocol = pkt.ipv4.ICMP_PROTOCOL ip_p.payload = icmp_reply eth_p = pkt.ethernet() eth_p.type = pkt.ethernet.IP_TYPE eth_p.dst = packet.src eth_p.src = packet.dst eth_p.payload = ip_p msg = of.ofp_packet_out() msg.data = eth_p.pack() # Add an action to send to the specified port action = of.ofp_action_output(port=packet_in.in_port) #fl2.actions.append(action) msg.actions.append(action) #msg.in_port = event.port # Send message to switch self.connection.send(msg) else: log.debug("ICMP destination unreachable") unr = pkt.unreach() unr.payload = ip_packet icmp_reply = pkt.icmp() icmp_reply.type = pkt.TYPE_DEST_UNREACH icmp_reply.payload = unr ip_p = pkt.ipv4() ip_p.srcip = dst_ip ip_p.dstip = src_ip ip_p.protocol = pkt.ipv4.ICMP_PROTOCOL ip_p.payload = icmp_reply eth_p = pkt.ethernet() eth_p.type = pkt.ethernet.IP_TYPE eth_p.dst = packet.src eth_p.src = packet.dst eth_p.payload = ip_p msg = of.ofp_packet_out() msg.data = eth_p.pack() # Add an action to send to the specified port action = of.ofp_action_output(port=packet_in.in_port) #fl2.actions.append(action) msg.actions.append(action) #msg.in_port = event.port # Send message to switch self.connection.send(msg) else: src_ip = ip_packet.srcip dst_ip = ip_packet.dstip k = 0 for key in self.routing_table.keys(): if dst_ip.inNetwork(key): k = key break if k != 0: port1 = self.routing_table[k][3] dsteth = adr.EthAddr(self.routing_table[k][4]) msg = of.ofp_packet_out() action = of.ofp_action_output(port=port1) packet.src = packet.dst packet.dst = dsteth msg.data = packet.pack() msg.actions.append(action) self.connection.send(msg) self.FlowMode(packet_in, packet_in.in_port)
def _handle_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed if not packet.parsed: log.warning("DPID %i PORT %i ignoring unparsed packet", dpid, inport) return if dpid not in self.arpTable: # New switch -- create an empty table self.arpTable[dpid] = {} for fake in self.fakeways: self.arpTable[dpid][IPAddr(fake)] = Entry( of.OFPP_NONE, dpid_to_mac(dpid)) if packet.type == ethernet.LLDP_TYPE: # Ignore LLDP packets return if isinstance(packet.next, ipv4): log.debug("DPID %i PORT %i IP %s => %s", dpid, inport, packet.next.srcip, packet.next.dstip) # Send any waiting packets... self._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport) # Learn or update port/MAC info if packet.next.srcip in self.arpTable[dpid]: if self.arpTable[dpid][packet.next.srcip] != (inport, packet.src): log.info("DPID %i PORT %i RE-learned %s", dpid, inport, packet.next.srcip) else: log.debug("DPID %i PORT %i learned %s", dpid, inport, str(packet.next.srcip)) self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src) # Try to forward dstaddr = packet.next.dstip if (packet.find("icmp") and (dstaddr in switch)): # Reply to pings # Make the ping reply icmp = pkt.icmp() icmp.type = pkt.TYPE_ECHO_REPLY icmp.payload = packet.find("icmp").payload # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = packet.find("ipv4").dstip ipp.dstip = packet.find("ipv4").srcip # Ethernet around that... e = pkt.ethernet() e.src = packet.dst e.dst = packet.src e.type = e.IP_TYPE # Hook them up... ipp.payload = icmp e.payload = ipp # Send it back to the input port msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = event.port event.connection.send(msg) log.debug("%s pinged %s", ipp.dstip, ipp.srcip) if dstaddr in self.arpTable[dpid]: # We have info about what port to send it out on... prt = self.arpTable[dpid][dstaddr].port mac = self.arpTable[dpid][dstaddr].mac if prt == inport: log.warning( "DPID %i PORT %i not sending packet for %s back out of the " + "input port" % (dpid, inport, str(dstaddr))) else: log.debug( "DPID %i PORT %i installing flow for %s => %s out port %i" % (dpid, inport, packet.next.srcip, dstaddr, prt)) actions = [] actions.append(of.ofp_action_dl_addr.set_dst(mac)) actions.append(of.ofp_action_output(port=prt)) match = of.ofp_match.from_packet(packet, inport) match.dl_src = None # Wildcard source MAC msg = of.ofp_flow_mod(command=of.OFPFC_ADD, idle_timeout=FLOW_IDLE_TIMEOUT, hard_timeout=of.OFP_FLOW_PERMANENT, buffer_id=event.ofp.buffer_id, actions=actions, match=of.ofp_match.from_packet( packet, inport)) event.connection.send(msg.pack()) elif (dstaddr not in self.arpTable[dpid]) and (dstaddr not in switch): # We don't know this destination. # First, we track this buffer so that we can try to resend it later # if we learn the destination, second we ARP for the destination, # which should ultimately result in it responding and us learning # where it is # Add to tracked buffers if (dpid, dstaddr) not in self.lost_buffers: self.lost_buffers[(dpid, dstaddr)] = [] bucket = self.lost_buffers[(dpid, dstaddr)] entry = (time.time() + MAX_BUFFER_TIME, event.ofp.buffer_id, inport) bucket.append(entry) while len(bucket) > MAX_BUFFERED_PER_IP: del bucket[0] # Expire things from our outstanding ARP list... self.outstanding_arps = { k: v for k, v in self.outstanding_arps.iteritems() if v > time.time() } # Check if we've already ARPed recently if (dpid, dstaddr) in self.outstanding_arps: # Oop, we've already done this one recently. return # And ARP... self.outstanding_arps[(dpid, dstaddr)] = time.time() r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REQUEST r.hwdst = ETHER_BROADCAST r.protodst = dstaddr r.hwsrc = packet.src r.protosrc = packet.next.srcip e = ethernet(type=ethernet.ARP_TYPE, src=packet.src, dst=ETHER_BROADCAST) e.set_payload(r) log.debug("DPID %i PORT %i ARPing for %s on behalf of %s" % (dpid, inport, str(r.protodst), str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) msg.in_port = inport event.connection.send(msg) if (packet.find("ipv4").dstip not in node): icmp = pkt.icmp() icmp.type = pkt.TYPE_DEST_UNREACH icmp.code = pkt.CODE_UNREACH_HOST orig_ip = event.parsed.find('ipv4') pay = orig_ip.pack() pay = pay[:orig_ip.hl * 4 + 8] import struct pay = struct.pack("!HH", 0, 0) + pay icmp.payload = pay # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = packet.find("ipv4").dstip ipp.dstip = packet.find("ipv4").srcip # Ethernet around that... e = pkt.ethernet() e.src = packet.dst e.dst = packet.src e.type = e.IP_TYPE # Hook them up... ipp.payload = icmp e.payload = ipp # Send it back to the input port msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = event.port event.connection.send(msg) log.debug("%s pinged %s", ipp.dstip, ipp.srcip) elif isinstance(packet.next, arp): a = packet.next log.debug("DPID %i PORT %i ARP %s %s => %s", dpid, inport, { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc), str(a.protodst)) if a.prototype == arp.PROTO_TYPE_IP: if a.hwtype == arp.HW_TYPE_ETHERNET: if a.protosrc != 0: # Learn or update port/MAC info if a.protosrc in self.arpTable[dpid]: if self.arpTable[dpid][a.protosrc] != (inport, packet.src): log.info("DPID %i PORT %i RE-learned %s", dpid, inport, str(a.protosrc)) else: log.debug("DPID %i PORT %i learned %s", dpid, inport, str(a.protosrc)) self.arpTable[dpid][a.protosrc] = Entry( inport, packet.src) # Send any waiting packets... self._send_lost_buffers(dpid, a.protosrc, packet.src, inport) if a.opcode == arp.REQUEST: # Maybe we can answer if a.protodst != None: #if a.protodst in self.arpTable[dpid]: # We have an answer... #if not self.arpTable[dpid][a.protodst].isExpired(): # .. and it's relatively current, so we'll reply ourselves r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwdst = a.hwsrc r.protodst = a.protosrc r.protosrc = a.protodst r.hwsrc = dpid_to_mac(dpid) e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwsrc) e.payload = r #e.set_payload(r) log.debug( "DPID %i PORT %i answering ARP for %s" % (dpid, inport, str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) return # Didn't know how to answer or otherwise handle this ARP, so just flood it log.debug("DPID %i PORT %i flooding ARP %s %s => %s" % (dpid, inport, { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc), str(a.protodst))) msg = of.ofp_packet_out( in_port=inport, data=event.ofp, action=of.ofp_action_output(port=of.OFPP_FLOOD)) event.connection.send(msg)
def install_path(self, dst_sw, last_port, match, event): p = _get_path(self, dst_sw, event.port, last_port) if p is None: log.warning("Can't get from %s to %s", match.dl_src, match.dl_dst) import pox.lib.packet as pkt if (match.dl_type == pkt.ethernet.IP_TYPE and event.parsed.find('ipv4')): log.debug("Dest unreachable (%s -> %s)", match.dl_src, match.dl_dst) from pox.lib.addresses import EthAddr e = pkt.ethernet() e.src = EthAddr(dpid_to_str(self.dpid)) e.dst = match.dl_src e.type = e.IP_TYPE ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = match.nw_dst ipp.dstip = match.nw_src icmp = pkt.icmp() icmp.type = pkt.ICMP.TYPE_DEST_UNREACH icmp.code = pkt.ICMP.CODE_UNREACH_HOST orig_ip = event.parsed.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] import struct d = struct.pack("!HH", 0, 0) + d icmp.payload = d ipp.payload = icmp e.payload = ipp msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=event.port)) msg.data = e.pack() self.connection.send(msg) return log.debug("Installing path for %s -> %s %04x (%i hops)", match.dl_src, match.dl_dst, match.dl_type, len(p)) self._install_path(p, match, event.ofp) p = [(sw, out_port, in_port) for sw, in_port, out_port in p] self._install_path(p, match.flip())
def ifReach(dstip, event, self): packet = event.parsed ipLoad = packet.payload dpid = self.connection.dpid #search the routeTable for subRouteTable in self.routeTable: #extract the network address dstnetwork = subRouteTable[DST_Network] if dstip == fireWall[dpid]: return False if ipLoad.srcip == fireWall[dpid]: return False #if destination IP in network address in the routetable if dstip.inNetwork(dstnetwork): log.debug('------ip dst %s is in the routeTable-----' % dstip) nextPort = subRouteTable[NEXTHOP_PORT] log.debug('------IP dst port %s is in the routeTable-----' % nextPort) #if routeTable tells to send it back, do nothing and continue loop if nextPort == event.ofp.in_port: continue nextHopIp = IPAddr(subRouteTable[NETX_HOP_IP]) nextPortIp = IPAddr(subRouteTable[NEXT_PORT_IP]) srcMac = arpCache[dpid][nextPort][nextPortIp] #if router knows desIP's MAC address, forwarding the packet if nextHopIp in arpCache[dpid][nextPort]: log.debug('------I know the next dst %s mac-----' % nextHopIp) nextHopMac = arpCache[dpid][nextPort][nextHopIp] msg = of.ofp_flow_mod() msg.match = of.ofp_match() msg.match.dl_type = ethernet.IP_TYPE msg.match.nw_dst = dstip msg.command = 0 msg.idle_timeout = 10 msg.hard_timeout = 30 msg.buffer_id = event.ofp.buffer_id msg.actions.append(of.ofp_action_dl_addr.set_src(srcMac)) msg.actions.append(of.ofp_action_dl_addr.set_dst(nextHopMac)) msg.actions.append(of.ofp_action_output(port=nextPort)) self.connection.send(msg) log.debug('------install a flow-----') #else router does not knows detIP's MAC address, send ARP request. else: log.debug( '------I do not know the next dst %s mac,make an arp request' % IPAddr(subRouteTable[NETX_HOP_IP])) ARPrequest = arp() ARPrequest.opcode = arp.REQUEST ARPrequest.protosrc = nextPortIp ARPrequest.hwsrc = srcMac ARPrequest.protodst = nextHopIp arpPacket = ethernet(type=ethernet.ARP_TYPE, src=ARPrequest.hwsrc, dst=ETHER_BROADCAST) arpPacket.set_payload(ARPrequest) msg = of.ofp_packet_out() msg.data = arpPacket.pack() msg.actions.append(of.ofp_action_output(port=nextPort)) msg.in_port = event.ofp.in_port event.connection.send(msg) log.debug('------Arp request has been snet-----') nextHopMac = ETHER_BROADCAST msg = of.ofp_packet_out() msg.in_port = event.port msg.buffer_id = event.ofp.buffer_id msg.actions.append(of.ofp_action_dl_addr.set_src(srcMac)) msg.actions.append(of.ofp_action_dl_addr.set_dst(nextHopMac)) msg.actions.append(of.ofp_action_output(port=nextPort)) self.connection.send(msg) return True return False
def from_json(json_hash): interface = HostInterface.from_json(json_hash['interface']) raw = base64.b64decode(json_hash['packet']) packet = ethernet(raw=raw) return DataplaneEvent(interface, packet)
def _handle_PacketIn (self, event): """ Handle packet in messages from the switch to implement above algorithm. """ packet = event.parsed if self.dpidToIP.get((event.dpid, event.port), None) is None: self.dpidToIP[(event.dpid, event.port)] = "10.10.{:d}.{:d}".format((6-event.dpid%2), self.addr); self.addr += 1; if (str(type(packet.next)) == "<class 'pox.lib.packet.ipv4.ipv4'>"): packet.next.ttl -= 1; if ((str(type(packet.next)) == "<class 'pox.lib.packet.ipv4.ipv4'>") and (packet.next.ttl == 0)): log.debug ("TTL expired!!!"); # Create ICMP Time Exceeded Message icmp = pkt.icmp(); icmp.type = pkt.TYPE_TIME_EXCEED; log.debug ("This is the ICMP error message {:s}".format(icmp.payload)); # Create IP Payload ipp = pkt.ipv4(); ipp.protocol = ipp.ICMP_PROTOCOL; ipp.srcip = IPAddr(self.dpidToIP[(event.dpid, event.port)]); ipp.dstip = packet.next.srcip; ipp.payload = icmp; log.debug ("This is the IP payload {:s}".format(ipp.payload)); # Create Ethernet Payload e = pkt.ethernet(); e.src = packet.dst; e.dst = packet.src; e.type = e.IP_TYPE; e.payload = ipp; log.debug ("This is the Ethernet payload {:s}".format(e.payload)); # Send Packet Back through the Same Port msg = of.ofp_packet_out(); msg.actions.append(of.ofp_action_output(port=event.port)); msg.date = e.pack(); msg.in_port = of.OFPP_NONE;event.connection.send(msg); else: def flood (message = None): """ Floods the packet """ msg = of.ofp_packet_out() if time.time() - self.connection.connect_time >= _flood_delay: # Only flood if we've been connected for a little while... if self.hold_down_expired is False: # Oh yes it is! self.hold_down_expired = True log.info("%s: Flood hold-down expired -- flooding", dpid_to_str(event.dpid)) if message is not None: log.debug(message) #log.debug("%i: flood %s -> %s", event.dpid,packet.src,packet.dst) # OFPP_FLOOD is optional; on some switches you may need to change # this to OFPP_ALL. msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) else: pass #log.info("Holding down flood for %s", dpid_to_str(event.dpid)) msg.data = event.ofp msg.in_port = event.port self.connection.send(msg) def drop (duration = None): """ Drops this packet and optionally installs a flow to continue dropping similar ones for a while """ if duration is not None: if not isinstance(duration, tuple): duration = (duration,duration) msg = of.ofp_flow_mod() msg.match = of.ofp_match.from_packet(packet) msg.idle_timeout = duration[0] msg.hard_timeout = duration[1] msg.buffer_id = event.ofp.buffer_id self.connection.send(msg) elif event.ofp.buffer_id is not None: msg = of.ofp_packet_out() msg.buffer_id = event.ofp.buffer_id msg.in_port = event.port self.connection.send(msg) self.macToPort[packet.src] = event.port # 1 if not self.transparent: # 2 if packet.type == packet.LLDP_TYPE or packet.dst.isBridgeFiltered(): drop() # 2a return if packet.dst.is_multicast: flood() # 3a else: if packet.dst not in self.macToPort: # 4 flood("Port for %s unknown -- flooding" % (packet.dst,)) # 4a else: port = self.macToPort[packet.dst] if port == event.port: # 5 # 5a log.warning("Same port for packet from %s -> %s on %s.%s. Drop." % (packet.src, packet.dst, dpid_to_str(event.dpid), port)) drop(10) return # 6 log.debug("installing flow for %s.%i -> %s.%i" % (packet.src, event.port, packet.dst, port)) msg = of.ofp_flow_mod() msg.match = of.ofp_match.from_packet(packet, event.port) msg.idle_timeout = 10 msg.hard_timeout = 30 msg.actions.append(of.ofp_action_output(port = port)) msg.data = event.ofp # 6a self.connection.send(msg)
def _handle_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed if not packet.parsed: log.warning("%i %i ignoring unparsed packet", dpid, inport) return if dpid not in self.arpTable: self.arpTable[dpid] = {} if packet.type == ethernet.LLDP_TYPE: return if isinstance(packet.next, ipv4): log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip, packet.next.dstip) self.sendWaitingPackets(dpid, packet.next.srcip, packet.src, inport) if packet.next.srcip in self.arpTable[dpid]: if self.arpTable[dpid][packet.next.srcip] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid, inport, packet.next.srcip) else: log.debug("%i %i learned %s", dpid, inport, str(packet.next.srcip)) self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src) prt = 0 dstaddr = packet.next.dstip prt = self.ip_to_port.get(dstaddr) if prt != None: log.debug("Got port %i from dictionary", prt) mac = None if dstaddr in self.arpTable[dpid]: mac = self.arpTable[dpid][dstaddr].mac if mac != None: actions = [] actions.append(of.ofp_action_dl_addr.set_dst(mac)) actions.append( of.ofp_action_dl_addr.set_src(dpid_to_mac(dpid))) actions.append(of.ofp_action_output(port=prt)) match = of.ofp_match.from_packet(packet, inport) match.dl_src = None msg = of.ofp_flow_mod(command=of.OFPFC_ADD, buffer_id=event.ofp.buffer_id, actions=actions, match=of.ofp_match.from_packet( packet, inport)) event.connection.send(msg.pack()) return else: # Add to tracked buffers if (dpid, dstaddr) not in self.message_queue: self.message_queue[(dpid, dstaddr)] = [] bucket = self.message_queue[(dpid, dstaddr)] entry = (None, event.ofp.buffer_id, inport) bucket.append(entry) r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REQUEST r.hwdst = ETHER_BROADCAST r.protodst = dstaddr r.hwsrc = dpid_to_mac(dpid) r.protosrc = packet.next.srcip e = ethernet(type=ethernet.ARP_TYPE, src=packet.src, dst=ETHER_BROADCAST) e.set_payload(r) log.debug("%i %i ARPing for %s on behalf of %s" % (dpid, inport, str(r.protodst), str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_FLOOD)) msg.in_port = inport event.connection.send(msg) else: icmpflag = 0 for list in self.routingTable: if list[0] == str(dstaddr): log.debug( "Searching Routing Table for IP address: %s ", str(dstaddr)) prt = list[4] if list[3] == str(dstaddr): prt = list[4] icmpflag = 1 self.arpTable[dpid][dstaddr] = Entry( prt, dpid_to_mac(dpid)) if icmpflag == 1: icmp = pkt.icmp() icmp.type = pkt.TYPE_ECHO_REPLY icmp.payload = packet.find("icmp").payload # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = packet.find("ipv4").dstip ipp.dstip = packet.find("ipv4").srcip # Ethernet around that... e = pkt.ethernet() e.src = packet.dst e.dst = packet.src e.type = e.IP_TYPE # Hook them up... ipp.payload = icmp e.payload = ipp # Send it back to the input port msg = of.ofp_packet_out() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = event.port event.connection.send(msg) return if prt == None: log.debug("Unreachable IP Address : %s", str(dstaddr)) icmp = pkt.icmp() icmp.type = 3 #icmp.payload = packet.find("icmp").payload # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = packet.find("ipv4").dstip ipp.dstip = packet.find("ipv4").srcip # Ethernet around that... e = pkt.ethernet() e.src = packet.dst e.dst = packet.src e.type = e.IP_TYPE # Hook them up... ipp.payload = icmp e.payload = ipp # Send it back to the input port msg = of.ofp_packet_out() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = event.port event.connection.send(msg) return log.debug("Got Port Number : %s from routing table", prt) self.ip_to_port[dstaddr] = prt mac = None if dstaddr in self.arpTable[dpid]: mac = self.arpTable[dpid][dstaddr].mac if mac != None: actions = [] actions.append(of.ofp_action_dl_addr.set_dst(mac)) actions.append( of.ofp_action_dl_addr.set_src(dpid_to_mac(dpid))) actions.append(of.ofp_action_output(port=prt)) match = of.ofp_match.from_packet(packet, inport) match.dl_src = None # Wildcard source MAC msg = of.ofp_flow_mod(command=of.OFPFC_ADD, buffer_id=event.ofp.buffer_id, actions=actions, match=of.ofp_match.from_packet( packet, inport)) event.connection.send(msg.pack()) return else: if (dpid, dstaddr) not in self.message_queue: self.message_queue[(dpid, dstaddr)] = [] bucket = self.message_queue[(dpid, dstaddr)] entry = (None, event.ofp.buffer_id, inport) bucket.append(entry) r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REQUEST r.hwdst = ETHER_BROADCAST r.protodst = dstaddr r.hwsrc = dpid_to_mac(dpid) r.protosrc = packet.next.srcip e = ethernet(type=ethernet.ARP_TYPE, src=packet.src, dst=ETHER_BROADCAST) e.set_payload(r) log.debug("%i %i ARPing for %s on behalf of %s" % (dpid, inport, str(r.protodst), str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_FLOOD)) msg.in_port = inport event.connection.send(msg) elif isinstance(packet.next, arp): a = packet.next log.debug("%i %i ARP %s %s => %s", dpid, inport, { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc), str(a.protodst)) dstaddr = a.protodst prt = None for list in self.routingTable: if list[0] == str(dstaddr): log.debug("Searching Routing Table for IP address: %s ", str(dstaddr)) prt = list[4] if list[3] == str(dstaddr): prt = list[4] #icmpflag = 1 self.arpTable[dpid][dstaddr] = Entry( prt, dpid_to_mac(dpid)) if prt == None: log.debug("Unreachable IP Address : %s", str(dstaddr)) return if a.prototype == arp.PROTO_TYPE_IP: if a.hwtype == arp.HW_TYPE_ETHERNET: if a.protosrc != 0: # Learn or update port/MAC info if a.protosrc in self.arpTable[dpid]: if self.arpTable[dpid][a.protosrc] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid, inport, str(a.protosrc)) else: log.debug("%i %i learned %s", dpid, inport, str(a.protosrc)) self.arpTable[dpid][a.protosrc] = Entry( inport, packet.src) # Send any waiting packets... self.sendWaitingPackets(dpid, a.protosrc, packet.src, inport) if a.opcode == arp.REQUEST: # Maybe we can answer if a.protodst in self.arpTable[dpid]: # We have an answer... r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwdst = a.hwsrc r.protodst = a.protosrc r.protosrc = a.protodst r.hwsrc = self.arpTable[dpid][a.protodst].mac e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwsrc) e.set_payload(r) log.debug("%i %i answering ARP from %s to %s" % (dpid, inport, str( r.protosrc), str(r.protodst))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) return if a.opcode == arp.REPLY: for list in self.routingTable: if list[0] == str(a.protodst): log.debug( "Searching Routing Table for IP address: %s ", str(a.protodst)) prt = list[4] msg = of.ofp_packet_out( in_port=inport, action=of.ofp_action_output(port=prt)) log.debug("%i %i flooding ARP %s %s => %s" % (dpid, inport, { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc), str(a.protodst))) msg = of.ofp_packet_out( in_port=inport, action=of.ofp_action_output(port=of.OFPP_FLOOD)) if event.ofp.buffer_id is of.NO_BUFFER: # Try sending the (probably incomplete) raw data msg.data = event.data else: msg.buffer_id = event.ofp.buffer_id event.connection.send(msg.pack())
def process_data(msg): if msg.data == b'': return () else: dp_packet = ethernet(msg.data) return DPFingerprint.from_pkt(dp_packet)
def ICMP_Reply_handler(self, packet, packet_in): ip_packet = packet.payload ipSrcAdd = self.route_table.get(str(ip_packet.srcip)) ipDstAdd = self.route_table.get(str(ip_packet.dstip)) if ipDstAdd != None: if str(packet.dst) == '00:00:00:00:11:05': if ipDstAdd[1] == '10.0.1.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr(ipDstAdd[0]) ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=ipDstAdd[3]) elif ipDstAdd[1] == '10.0.2.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr('00:00:00:00:11:06') ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=3) elif ipDstAdd[1] == '10.0.3.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr('00:00:00:00:11:07') ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=4) elif str(packet.dst) == '00:00:00:00:11:06': if ipDstAdd[1] == '10.0.2.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr(ipDstAdd[0]) ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=ipDstAdd[3]) elif ipDstAdd[1] == '10.0.1.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr('00:00:00:00:11:05') ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=2) elif ipDstAdd[1] == '10.0.3.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr('00:00:00:00:11:07') ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=3) elif str(packet.dst) == '00:00:00:00:11:07': if ipDstAdd[1] == '10.0.3.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr(ipDstAdd[0]) ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=ipDstAdd[3]) elif ipDstAdd[1] == '10.0.1.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr('00:00:00:00:11:05') ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=3) elif ipDstAdd[1] == '10.0.2.0/24': ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr('00:00:00:00:11:06') ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=2) else: self.send_Packet(frame=packet, out_port=ipDstAdd[3])
def ICMP_Request_handler(self, packet, packet_in): ip_packet = packet.payload icmp_segment = ip_packet.payload ipDstAdd = self.route_table.get(str(ip_packet.dstip)) #ICMP reach if ipDstAdd != None: #ICMP -> router if ipDstAdd[2] == 'R': log.debug("----------ICMP echo packet----------") #echo packet echo_segment = pkt.echo() echo_segment.seq = icmp_segment.payload.seq + 1 echo_segment.id = icmp_segment.payload.id #icmp packt|echo icmp_reply = pkt.icmp() icmp_reply.type = pkt.TYPE_ECHO_REQUEST icmp_reply.payload = echo_segment #ip packet|icmp|echo ip_pack = pkt.ipv4() ip_pack.srcip = ip_packet.dstip ip_pack.dstip = ip_packet.srcip ip_pack.protocol = pkt.ipv4.ICMP_PROTOCOL ip_pack.payload = icmp_reply #frame|ip|icmp|echo ether_pack = pkt.ethernet() ether_pack.dst = packet.src ether_pack.src = packet.dst ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.payload = ip_pack self.send_Packet(frame=ether_pack, out_port=packet_in.in_port) elif ipDstAdd[2] == 'H': #router -> can reache ipadd #frame|original packet send to dst ether_pack = pkt.ethernet() ether_pack.type = pkt.ethernet.IP_TYPE ether_pack.src = packet.dst ether_pack.dst = adr.EthAddr(ipDstAdd[0]) ether_pack.payload = packet.payload self.send_Packet(frame=ether_pack, out_port=ipDstAdd[1]) #ICMP unreach else: #log.debug("----------ICMP unreach----------") unreachPacket = pkt.unreach() unreachPacket.payload = packet.payload icmp_unreReply = pkt.icmp() icmp_unreReply.type = pkt.TYPE_DEST_UNREACH icmp_unreReply.payload = unreachPacket ip_unrePack = pkt.ipv4() ip_unrePack.srcip = ip_packet.dstip ip_unrePack.dstip = ip_packet.srcip ip_unrePack.protocol = pkt.ipv4.ICMP_PROTOCOL ip_unrePack.payload = icmp_unreReply ether_unrePack = pkt.ethernet() ether_unrePack.src = packet.dst ether_unrePack.dst = packet.src ether_unrePack.type = pkt.ethernet.IP_TYPE ether_unrePack.payload = ip_unrePack self.send_Packet(frame=ether_unrePack, out_port=packet_in.in_port)
def _do_ctl2(event): def errf(msg, *args): raise RuntimeError(msg % args) args = event.args def ra(low, high=None): if high is None: high = low if len(args) < low or len(args) > high: raise RuntimeError("Wrong number of arguments") return False def get_sw(arg, fail=True): r = _switches.get(arg) if r is not None: return r try: dpid = str_to_dpid(arg) except Exception: raise RuntimeError("No such switch as %s" % (arg, )) r = core.datapaths.get(dpid) if r is None and fail: raise RuntimeError("No such switch as %s" % (dpid_to_str(dpid), )) return r try: if event.first == "add-port": ra(1, 2) if len(event.args) == 1 and len(_switches) == 1: sw = _switches[_switches.keys()[0]] p = args[0] else: ra(2) sw = get_sw(args[0]) p = args[1] sw.add_interface(p, start=True, on_error=errf) elif event.first == "del-port": ra(1, 2) if len(event.args) == 1: for sw in _switches.values(): for p in sw.ports.values(): if p.name == event.args[0]: sw.remove_interface(event.args[0]) return raise RuntimeError("No such interface") sw = _switches[event.args[0]] sw.remove_interface(args[1]) elif event.first == "show": ra(0) s = [] for sw in _switches.values(): s.append("Switch %s" % (sw.name, )) for no, p in sw.ports.iteritems(): stats = sw.port_stats[no] s.append(" %3s %-16s rx:%-20s tx:%-20s" % (no, p.name, "%s (%s)" % (stats.rx_packets, stats.rx_bytes), "%s (%s)" % (stats.tx_packets, stats.tx_bytes))) return "\n".join(s) elif event.first == "show-table": ra(0, 1) sw = None if len(args) == 1: sw = get_sw(args[0]) s = [] for switch in _switches.values(): if sw is None or switch is sw: s.append("== " + switch.name + " ==") for entry in switch.table.entries: s.append(entry.show()) return "\n".join(s) elif event.first == "wire-port": # Wire a virtual port to a channel: wire-port [sw] port channel ra(2, 3) if len(event.args) == 2 and len(_switches) == 1: sw = _switches[_switches.keys()[0]] p = args[0] c = args[1] else: ra(3) sw = get_sw(args[0]) p = args[1] c = args[2] for port in sw.ports.values(): if port.name == p: px = sw.px.get(port.port_no) if not isinstance(px, VirtualPort): raise RuntimeError("Port is not a virtual port") px.channel = c return raise RuntimeError("No such interface") elif event.first == "unwire-port": # Unhook the virtual port: unwire-port [sw] port ra(1, 2) if len(event.args) == 1 and len(_switches) == 1: sw = _switches[_switches.keys()[0]] p = args[0] else: ra(2) sw = get_sw(args[0]) p = args[1] for port in sw.ports.values(): if port.name == p: px = sw.px.get(port.port_no) if not isinstance(px, VirtualPort): raise RuntimeError("Port is not a virtual port") px.channel = None return raise RuntimeError("No such interface") elif event.first == "sendraw": # sendraw sw src-port <raw hex bytes> if len(args) < 3: ra(3) sw = get_sw(args[0]) p = args[1] data = [] for x in args[2:]: x = x.strip() #print "<",x,">" if len(x) < 2: data.append(int(x, 16)) else: assert len(x) & 1 == 0 for y, z in zip(x[::2], x[1::2]): data.append(int(y + z, 16)) data = "".join(chr(x) for x in data) for port in sw.ports.values(): if port.name == p: px = sw.px.get(port.port_no) sw._pcap_rx(px, data, 0, 0, len(data)) return raise RuntimeError("No such interface") elif event.first == "ping": # ping [sw] dst-mac dst-ip [-I src-ip] [--port src-port] # [-s byte-count] [-p pad] [-t ttl] from pox.lib.addresses import EthAddr, IPAddr kvs = dict(s=(int, 56), p=(str, chr(0x42)), port=(str, ""), I=(IPAddr, IPAddr("1.1.1.1")), t=(int, 64)) ai = list(event.args) ai.append(None) args[:] = [] skip = False for k, v in zip(ai[:-1], ai[1:]): if skip: skip = False continue if not k.startswith("-"): args.append(k) continue k = k.lstrip("-").replace("-", "_") if "=" in k: k, v = k.split("=", 1) else: if v is None: raise RuntimeError("Expected argument for '%s'" % (k, )) skip = True if k not in kvs: raise RuntimeError("Unknown option '%s'" % (k, )) kvs[k] = (kvs[k][0], kvs[k][0](v)) kvs = {k: v[1] for k, v in kvs.items()} ra(2, 3) pad = (kvs['p'] * kvs['s'])[:kvs['s']] if len(args) == 2 and len(_switches) == 1: sw = _switches[_switches.keys()[0]] mac, ip = args else: ra(3) sw = get_sw(args[0]) mac, ip = args[1:] mac = EthAddr(mac) ip = IPAddr(ip) srcport = kvs['port'] for p in sw.ports.values(): if srcport == "" or p.name == srcport: echo = pkt.echo() echo.payload = pad icmp = pkt.icmp() icmp.type = pkt.TYPE_ECHO_REQUEST icmp.payload = echo # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = kvs['I'] ipp.dstip = ip ipp.ttl = kvs['t'] ipp.payload = icmp # Ethernet around that... e = pkt.ethernet() e.src = p.hw_addr e.dst = mac e.type = e.IP_TYPE e.payload = ipp data = e.pack() px = sw.px.get(p.port_no) sw._pcap_rx(px, data, 0, 0, len(data)) return raise RuntimeError("No such interface") else: raise RuntimeError("Unknown command") except Exception as e: log.exception("While processing command") return "Error: " + str(e)
def _handle_openflow_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed log.warning("Inho #5168 : %s %s ", type(dpid), dpid) if not packet.parsed: log.warning("%i %i ignoring unparsed packet", dpid, inport) return if dpid not in self.arpTable: # New switch -- create an empty table self.arpTable[dpid] = {} for fake in self.fakeways: self.arpTable[dpid][IPAddr(fake)] = Entry( of.OFPP_NONE, dpid_to_mac(dpid)) if packet.type == ethernet.LLDP_TYPE: # Ignore LLDP packets return if isinstance(packet.next, ipv4): log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip, packet.next.dstip) # Send any waiting packets... self._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport) # Learn or update port/MAC info if packet.next.srcip in self.arpTable[dpid]: if self.arpTable[dpid][packet.next.srcip] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid, inport, packet.next.srcip) if self.wide: # Make sure we don't have any entries with the old info... msg = of.ofp_flow_mod(command=of.OFPFC_DELETE) msg.match.nw_dst = packet.next.srcip msg.match.dl_type = ethernet.IP_TYPE event.connection.send(msg) else: log.debug("%i %i learned %s", dpid, inport, packet.next.srcip) self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src) # Try to forward dstaddr = packet.next.dstip if dstaddr not in self.arpTable[dpid]: if packet.next.srcip == IPAddr("10.0.0.1"): self.arpTable[dpid][packet.next.dstip] = Entry( inport, packet.src) self.arpTable[dpid][packet.next.dstip].mac = EthAddr( "32:d5:a3:be:19:77") else: self.arpTable[dpid][packet.next.dstip] = Entry( inport, packet.src) self.arpTable[dpid][packet.next.dstip].mac = EthAddr( "08:00:27:2a:87:c3") if packet.next.protocol == ipv4.TCP_PROTOCOL: if packet.next.dstip == "10.0.0.1": e = pkt.ethernet() e.src = EthAddr(packet.src) e.dst = self.arpTable[dpid][dstaddr].mac e.type = e.IP_TYPE tcpp = pkt.tcp() tcpp.srcport = packet.next.payload.srcport #packet.next.payload = tcpp, packet.next = ip, packet = E tcpp.dstport = packet.next.payload.dstport tcpp.seq = packet.next.payload.seq tcpp.ack = packet.next.payload.ack tcpp.win = 29200 tcpp.SYN = True #send SYN tcpp.ACK = False tcp = pkt.ipv4() tcp.protocol = tcp.TCP_PROTOCOL tcp.srcip = packet.next.srcip tcp.dstip = packet.next.dstip tcp.payload = tcpp e.payload = tcp msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) print(e.dst) print(packet.next.dstip) if packet.next.protocol == ipv4.ICMP_PROTOCOL: e = pkt.ethernet() e.src = self.arpTable[dpid][dstaddr].mac e.dst = EthAddr(packet.src) e.type = e.IP_TYPE ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = packet.next.dstip print(ipp.srcip) ipp.dstip = packet.next.srcip icmp = pkt.icmp() icmp.type = pkt.ICMP.TYPE_ECHO_REPLY icmp.payload = packet.next.payload.payload #copy the ping payload of the packet that they receive ipp.payload = icmp e.payload = ipp msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) return if packet.next.protocol == ipv4.TCP_PROTOCOL and packet.next.dstip != "10.0.0.1": if packet.next.payload.SYN and not packet.next.payload.ACK: #this is to send SYN, ACK print "SYN packet", packet.next.payload e = pkt.ethernet() e.src = self.arpTable[dpid][dstaddr].mac e.dst = EthAddr(packet.src) e.type = e.IP_TYPE tcpp = pkt.tcp() tcpp.srcport = packet.next.payload.dstport #packet.next.payload = tcpp, packet.next = ip, packet = E tcpp.dstport = packet.next.payload.srcport tcpp.seq = 0 tcpp.ack = packet.next.payload.seq + 1 tcpp.win = 29200 tcpp.SYN = True #send SYN tcpp.ACK = True #send ACK tcp = pkt.ipv4() tcp.protocol = tcp.TCP_PROTOCOL tcp.srcip = packet.next.dstip tcp.dstip = packet.next.srcip tcp.payload = tcpp e.payload = tcp msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) time.sleep(0.15) e = pkt2.ethernet() e.src = self.arpTable[dpid][dstaddr].mac e.dst = EthAddr(packet.src) e.type = e.IP_TYPE tcpp = pkt2.tcp() tcpp.srcport = packet.next.payload.dstport tcpp.dstport = packet.next.payload.srcport #print(packet.next.payload.ack) tcpp.seq = 1 tcpp.ack = packet.next.payload.seq + 127 tcpp.win = 29200 tcpp.PSH = True #send PSH tcpp.ACK = True #send ACK tcpp.payload = makeMessage( magic, "version", makeVersionPayload(str(packet.next.dstip), str(packet.next.srcip))) tcp = pkt2.ipv4() tcp.protocol = tcp.TCP_PROTOCOL tcp.srcip = packet.next.dstip tcp.dstip = packet.next.srcip tcp.payload = tcpp e.payload = tcp print "*****" msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) return # if not packet.next.payload.SYN and packet.next.payload.ACK: # print "ACK packet", packet.next.payload # e = pkt.ethernet() # e.src = self.arpTable[dpid][dstaddr].mac # e.dst = EthAddr(packet.src) # e.type = e.IP_TYPE # tcpp = pkt.tcp() # tcpp.srcport = packet.next.payload.dstport # tcpp.dstport = packet.next.payload.srcport # # tcpp.seq = 1 # will be random # tcpp.ack = packet.next.payload.ack+1 # # tcpp.SYN = True # tcpp.ACK = True # tcp = pkt.ipv4() # tcp.protocol = tcp.TCP_PROTOCOL # tcp.srcip = packet.next.dstip # tcp.dstip = packet.next.srcip # tcp.payload = tcpp # e.payload = tcp # msg = of.ofp_packet_out() # msg.data = e.pack() # msg.actions.append(of.ofp_action_output(port = # of.OFPP_IN_PORT)) # msg.in_port = inport # event.connection.send(msg) # return else: print "Not SYN", packet.next.payload elif self.arp_for_unknowns: # We don't know this destination. # First, we track this buffer so that we can try to resend it later # if we learn the destination, second we ARP for the destination, # which should ultimately result in it responding and us learning # where it is # Add to tracked buffers if (dpid, dstaddr) not in self.lost_buffers: self.lost_buffers[(dpid, dstaddr)] = [] bucket = self.lost_buffers[(dpid, dstaddr)] entry = (time.time() + MAX_BUFFER_TIME, event.ofp.buffer_id, inport) bucket.append(entry) while len(bucket) > MAX_BUFFERED_PER_IP: del bucket[0] # Expire things from our outstanding ARP list... self.outstanding_arps = { k: v for k, v in self.outstanding_arps.iteritems() if v > time.time() } # Check if we've already ARPed recently if (dpid, dstaddr) in self.outstanding_arps: # Oop, we've already done this one recently. return # And ARP... self.outstanding_arps[(dpid, dstaddr)] = time.time() + 4 r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REQUEST r.hwdst = ETHER_BROADCAST r.protodst = dstaddr r.hwsrc = packet.src r.protosrc = packet.next.srcip e = ethernet(type=ethernet.ARP_TYPE, src=packet.src, dst=ETHER_BROADCAST) e.set_payload(r) log.debug("%i %i ARPing for %s on behalf of %s" % (dpid, inport, r.protodst, r.protosrc)) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) msg.in_port = inport event.connection.send(msg) elif isinstance(packet.next, arp): a = packet.next log.debug("%i %i ARP %s %s => %s", dpid, inport, { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, a.protodst) if a.protosrc == IPAddr("10.0.0.1"): if a.opcode == arp.REQUEST: if a.protodst not in self.arpTable[dpid]: self.arpTable[dpid][a.protodst] = Entry( inport, packet.src) self.arpTable[dpid][a.protodst].mac = EthAddr( "32:d5:a3:be:19:77") r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwdst = a.hwsrc r.protodst = a.protosrc r.protosrc = a.protodst r.hwsrc = self.arpTable[dpid][a.protodst].mac e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwsrc) e.set_payload(r) log.debug("%i %i answering ARP for %s: %s" % (dpid, inport, r.protosrc, r.hwsrc)) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) return # Didn't know how to answer or otherwise handle this ARP, so just flood it log.debug("%i %i flooding ARP %s %s => %s" % (dpid, inport, { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, a.protodst)) msg = of.ofp_packet_out( in_port=inport, data=event.ofp, action=of.ofp_action_output(port=of.OFPP_FLOOD)) event.connection.send(msg)
def install_path(self, src, dst, match, event): """ Attempts to install a path between this switch and some destination """ global file p = _get_path(src, dst) if p is None: log.warning("Can't get from %s to %s", match.dl_src, match.dl_dst) file.write("Can't get from %s to %s \n" % (match.dl_src, match.dl_dst)) import pox.lib.packet as pkt if (match.dl_type == pkt.ethernet.IP_TYPE and event.parsed.find('ipv4')): # It's IP -- let's send a destination unreachable log.debug("Dest unreachable (%s -> %s)", match.dl_src, match.dl_dst) file.write("Dest unreachable (%s -> %s \n)" % (match.dl_src, match.dl_dst)) from pox.lib.addresses import EthAddr e = pkt.ethernet() e.src = EthAddr(dpid_to_str(self.dpid)) #FIXME: Hmm... e.dst = match.dl_src e.type = e.IP_TYPE ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = match.nw_dst #FIXME: Ridiculous ipp.dstip = match.nw_src icmp = pkt.icmp() icmp.type = pkt.ICMP.TYPE_DEST_UNREACH icmp.code = pkt.ICMP.CODE_UNREACH_HOST orig_ip = event.parsed.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] import struct d = struct.pack("!HH", 0, 0) + d #FIXME: MTU icmp.payload = d ipp.payload = icmp e.payload = ipp msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=event.port)) msg.data = e.pack() self.connection.send(msg) return log.debug("Installing path for %s -> %s %04x (%i hops)", match.dl_src, match.dl_dst, match.dl_type, len(p)) file.write("Installing path for %s -> %s %04x (%i hops) \n" % (match.dl_src, match.dl_dst, match.dl_type, len(p))) # We have a path -- install it self._install_path(p, match, event.ofp) # Now reverse it and install it backwards # (we'll just assume that will work) p = [(sw, out_port, in_port) for sw, in_port, out_port in p] ##############the path order is important,change it c = [] for i in range(0, len(p)): c.append(p[len(p) - 1 - i]) self._install_path(c, match.flip())
def _handle_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed flag = 1 packet_in = event.ofp self.connection = event.connection if not packet.parsed: log.warning("Router %i, input port = %i: ignoring unparsed packet", dpid, inport) return icmp_packet = packet.find('icmp') if icmp_packet is not None: if icmp_packet.type == pkt.TYPE_ECHO_REQUEST: log.debug("Received ICMP request message") found = 0 #To check if destination is reachable by ping for node in self.node_list: if packet.payload.dstip.inNetwork( node): #If the destination IP is in the network found = node break if found == 0: log.debug("Destination Unreachable") icmp_reply = pkt.icmp() icmp_reply.type = pkt.TYPE_DEST_UNREACH icmp_reply.code = pkt.ICMP.CODE_UNREACH_HOST icmp_reply_payload = packet.find('ipv4').pack() icmp_reply_payload = icmp_reply_payload[:packet.find('ipv4' ).hl * 4 + 8] import struct icmp_reply_payload = struct.pack("!HH", 0, 0) + icmp_reply_payload icmp_reply.payload = icmp_reply_payload #Making the IPv4 packet around it icmp_reply_packet = pkt.ipv4() icmp_reply_packet.protocol = icmp_reply_packet.ICMP_PROTOCOL icmp_reply_packet.srcip = packet.find("ipv4").dstip icmp_reply_packet.dstip = packet.find("ipv4").srcip #Putting this packet in an ethernet frame icmp_ethernet_frame = pkt.ethernet() icmp_ethernet_frame.type = pkt.ethernet.IP_TYPE icmp_ethernet_frame.dst = packet.src icmp_ethernet_frame.src = packet.dst #Encapsulating... icmp_reply_packet.payload = icmp_reply icmp_ethernet_frame.payload = icmp_reply_packet #Sending the ping reply back through the port it came in at msg = of.ofp_packet_out() msg.data = icmp_ethernet_frame.pack() msg.actions.append( of.ofp_action_output(port=packet_in.in_port)) self.connection.send(msg) log.debug("Sent 'Dest Unreachable' message") else: if found == "10.0.1.1" or "10.0.2.1": log.debug("Trying to reach router = %s" % found) #Making the ping reply icmp_reply = pkt.icmp() icmp_reply.type = pkt.TYPE_ECHO_REPLY icmp_reply.payload = icmp_packet.payload #Making the IPv4 packet around it icmp_reply_packet = pkt.ipv4() icmp_reply_packet.protocol = icmp_reply_packet.ICMP_PROTOCOL icmp_reply_packet.srcip = packet.find("ipv4").dstip icmp_reply_packet.dstip = packet.find("ipv4").srcip #Putting this packet in an ethernet frame icmp_ethernet_frame = pkt.ethernet() icmp_ethernet_frame.type = pkt.ethernet.IP_TYPE icmp_ethernet_frame.dst = packet.src icmp_ethernet_frame.src = packet.dst #Encapsulating... icmp_reply_packet.payload = icmp_reply icmp_ethernet_frame.payload = icmp_reply_packet #Sending the ping reply back through the port it came in at msg = of.ofp_packet_out() msg.data = icmp_ethernet_frame.pack() msg.actions.append( of.ofp_action_output(port=packet_in.in_port)) self.connection.send(msg) log.debug("Sent ICMP reply") flag = 0 if dpid not in self.mac_table: # New switch -- create an empty table self.mac_table[dpid] = {} for subnet in self.subnets: self.mac_table[dpid][addr.IPAddr(subnet)] = Entry( of.OFPP_NONE, dpid_to_mac(dpid)) if isinstance(packet.next, pkt.ipv4): log.debug( "Router %i, input port = %i: Received an IP packet from %s to %s", dpid, inport, packet.next.srcip, packet.next.dstip) # Learn or update port/MAC info self.mac_table[dpid][packet.next.srcip] = Entry(inport, packet.src) # Try to forward dstaddr = packet.next.dstip if dstaddr in self.mac_table[dpid]: # We know where to send it prt = self.mac_table[dpid][dstaddr].port mac = self.mac_table[dpid][dstaddr].mac log.debug( "Router %i:Forwarding the packet to dst_MAC address = %s through port = %i", dpid, mac, prt) if flag == 1: actions = [] actions.append(of.ofp_action_dl_addr.set_dst(mac)) actions.append(of.ofp_action_output(port=prt)) match = of.ofp_match.from_packet(packet, inport) match.dl_src = None msg = of.ofp_flow_mod(command=of.OFPFC_ADD, idle_timeout=FLOW_IDLE_TIMEOUT, hard_timeout=of.OFP_FLOW_PERMANENT, buffer_id=event.ofp.buffer_id, actions=actions, match=of.ofp_match.from_packet( packet, inport)) event.connection.send(msg.pack()) elif self.arp_for_unknowns: r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REQUEST r.hwdst = ETHER_BROADCAST r.protodst = dstaddr r.hwsrc = packet.src r.protosrc = packet.next.srcip e = pkt.ethernet(type=pkt.ethernet.ARP_TYPE, src=packet.src, dst=ETHER_BROADCAST) e.set_payload(r) log.debug("Router %i: ARPing for %s on behalf of %s" % (dpid, str(r.protodst), str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) msg.in_port = inport event.connection.send(msg) elif isinstance(packet.next, arp): a = packet.next log.debug("Router %i, received an ARP packet at port = %i", dpid, inport) if a.prototype == arp.PROTO_TYPE_IP: if a.hwtype == arp.HW_TYPE_ETHERNET: if a.protosrc != 0: #Update MAC table self.mac_table[dpid][a.protosrc] = Entry( inport, packet.src) if a.opcode == arp.REQUEST: if a.protodst in self.mac_table[dpid]: #We know how to answer the ARP ourselves r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwdst = a.hwsrc r.protodst = a.protosrc r.protosrc = a.protodst r.hwsrc = self.mac_table[dpid][a.protodst].mac e = pkt.ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwsrc) e.set_payload(r) log.debug( "Router %i, input port %i answering ARP for %s" % (dpid, inport, str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) return else: # Didn't know how to answer or otherwise handle this ARP, so just flood it log.debug( "Flooding to all ports since we don't have the MAC address in mac_table" ) msg = of.ofp_packet_out( in_port=inport, data=event.ofp, action=of.ofp_action_output( port=of.OFPP_FLOOD)) event.connection.send(msg)
def _handle_PacketIn(self, event): """ Handle packet in messages from the switch to implement above algorithm. """ global file packet = event.parsed def flood(): """ Floods the packet """ if self.is_holding_down: log.warning("Not flooding -- holddown active") file.write("Not flooding -- holddown active\n") msg = of.ofp_packet_out() # OFPP_FLOOD is optional; some switches may need OFPP_ALL msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) #print '**************************************************************' #print 'THe packetIn is flooding!!!' #print '**************************************************************' file.write( '**************************************************************\n' ) file.write('THe packetIn is flooding!!!\n') file.write( '**************************************************************\n' ) msg.buffer_id = event.ofp.buffer_id msg.in_port = event.port self.connection.send(msg) def drop(): # Kill the buffer if event.ofp.buffer_id is not None: msg = of.ofp_packet_out() msg.buffer_id = event.ofp.buffer_id event.ofp.buffer_id = None # Mark is dead msg.in_port = event.port print '**************************************************************' print 'THe packetIn is drop!!!' print '**************************************************************' file.write( '**************************************************************\n' ) file.write('THe packetIn is drop!!!\n') file.write( '**************************************************************\n' ) self.connection.send(msg) self.macToPort[packet.src] = event.port # 1 match = of.ofp_match.from_packet(packet) iptomac[match.nw_src] = match.dl_src if match.dl_dst != EthAddr("ff:ff:ff:ff:ff:ff"): iptomac[match.nw_dst] = match.dl_dst global mac_map for key, value in self.macToPort.iteritems(): if value != 6: mac_map[key] = (self, value ) #note the sw which client is connected with #print '********************************************************************' #print 'switch dpid:'+str(self.dpid) #print 'nw_src:'+str(match.nw_src) #print 'inport:'+str(event.port) #print 'dl_dst:'+str(match.dl_dst) #file.write('********************************************************************\n') #file.write('switch dpid:'+str(self.dpid)+'\n') #file.write('nw_src:'+str(match.nw_src)+'\n') #file.write('inport:'+str(event.port)+'\n') #file.write('dl_dst:'+str(match.dl_dst)+'\n') if match.dl_type == 2054: #0x0806 print '********************************************************************' print 'switch dpid:' + str(self.dpid) print 'nw_src:' + str(match.nw_src) print 'inport:' + str(event.port) print 'dl_dst:' + str(match.dl_dst) file.write( '********************************************************************\n' ) file.write('switch dpid:' + str(self.dpid) + '\n') file.write('nw_src:' + str(match.nw_src) + '\n') file.write('inport:' + str(event.port) + '\n') file.write('dl_dst:' + str(match.dl_dst) + '\n') if match.nw_proto == 1: print 'arp request' file.write('arp request\n') elif match.nw_proto == 2: print 'arp answer' file.write('arp answer\n') else: print 'arp unknown' file.write('arp unknown\n') elif match.dl_type == 2048: #0x0800 if match.nw_proto == 1: print '********************************************************************' print 'switch dpid:' + str(self.dpid) print 'nw_src:' + str(match.nw_src) print 'inport:' + str(event.port) print 'dl_dst:' + str(match.dl_dst) print 'icmp' file.write( '********************************************************************\n' ) file.write('switch dpid:' + str(self.dpid) + '\n') file.write('nw_src:' + str(match.nw_src) + '\n') file.write('inport:' + str(event.port) + '\n') file.write('dl_dst:' + str(match.dl_dst) + '\n') file.write('icmp\n') ''' elif match.nw_proto == 6: print 'tcp' file.write('tcp\n') elif match.nw_proto == 17: print 'udp' file.write('udp\n') else: print 'ip unknown' file.write('ip unknown\n') elif match.dl_type == 34525: #0x86DD print 'ipv6' file.write('ipv6\n') else: print 'unknown' file.write('unknown\n') ''' #print '********************************************************************' file.write( '********************************************************************\n' ) #print self.dpid #print match #print iptomac #print self.macToPort #print mac_map #loc = (self, event.port) # Place we saw this ethaddr #oldloc = mac_map.get(packet.src) # Place we last saw this ethaddr if packet.effective_ethertype == packet.LLDP_TYPE: drop() return if match.dl_type == 2054 and match.nw_proto == 1 and match.nw_dst in iptomac.keys( ): import pox.lib.packet as pkt if match.dl_type == pkt.ethernet.ARP_TYPE: e = pkt.ethernet() e.src = EthAddr(dpid_to_str(self.dpid)) #FIXME: Hmm... e.dst = match.dl_src e.type = e.ARP_TYPE arpp = pkt.arp() arpp.opcode = arpp.REPLY arpp.hwsrc = iptomac[match.nw_dst] arpp.hwdst = match.dl_src arpp.protosrc = match.nw_dst arpp.protodst = match.nw_src e.payload = arpp msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=event.port)) msg.data = e.pack() self.connection.send(msg) print '**********************************************************' print 'arp reply to ' + str(match.nw_src) print '**********************************************************' file.write( '**********************************************************\n' ) file.write('arp reply to ' + str(match.nw_src) + '\n') file.write( '**********************************************************\n' ) return if packet.dst.is_multicast: #if match.dl_dst == Ethaddr('ff:ff:ff:ff:ff:ff') if match.dl_type == 2054 and match.nw_proto == 1 and match.nw_dst in iptomac.keys( ): import pox.lib.packet as pkt if match.dl_type == pkt.ethernet.ARP_TYPE: e = pkt.ethernet() e.src = EthAddr(dpid_to_str(self.dpid)) #FIXME: Hmm... e.dst = match.dl_src e.type = e.ARP_TYPE arpp = pkt.arp() arpp.opcode = arpp.REPLY arpp.hwsrc = iptomac[match.nw_dst] arpp.hwdst = match.dl_src arpp.protosrc = match.nw_dst arpp.protodst = match.nw_src e.payload = arpp msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=event.port)) msg.data = e.pack() self.connection.send(msg) print '**********************************************************' print 'arp reply to' + str(match.nw_src) print '**********************************************************' file.write( '**********************************************************\n' ) file.write('arp reply to' + str(match.nw_src) + '\n') file.write( '**********************************************************\n' ) else: flood() # 3a else: if packet.dst not in mac_map: if packet.dst in mesh_bat0_mac.values(): drop() else: flood() else: #dest = mac_map[packet.dst] ###ycj #match = of.ofp_match.from_packet(packet) ###ycj #print match #print 'packet.src' #print packet.src #print packet.dst #print mac_map[packet.src][0].dpid print '********************************************' print 'install dl_type: ' + str( match.dl_type) + ' install nw_proto: ' + str( match.nw_proto) print '********************************************' file.write('*******************************************\n') file.write('install dl_type: ' + str(match.dl_type) + ' install nw_proto: ' + str(match.nw_proto) + '\n') file.write('*******************************************\n') self.install_path(packet.src, packet.dst, match, event)
def cb(obj, data, sec, usec, length): p = pkt.ethernet(data) print p.dump()
def install_path (self, dst_sw, last_port, match, event): """ Attempts to install a path between this switch and some destination """ # p = _get_path(self.dpid, dst_sw.dpid, event.port, last_port) # log.info("their path: %s", str(p)) our_p = _our_get_path(self.dpid, dst_sw.dpid, event.port, last_port) log.info("our path: %s", str(our_p)) # if p is not None and our_p is None: # pdb.set_trace() # for n1, n2 in zip(p, our_p): # assert n1 == n2 p = our_p if p is None: log.warning("Can't get from %s to %s", match.dl_src, match.dl_dst) import pox.lib.packet as pkt if (match.dl_type == pkt.ethernet.IP_TYPE and event.parsed.find('ipv4')): # It's IP -- let's send a destination unreachable log.info("Dest unreachable (%s -> %s)", match.dl_src, match.dl_dst) from pox.lib.addresses import EthAddr e = pkt.ethernet() e.src = EthAddr(_dpid_to_str(self.dpid)) #FIXME: Hmm... e.dst = match.dl_src e.type = e.IP_TYPE ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = match.nw_dst #FIXME: Ridiculous ipp.dstip = match.nw_src icmp = pkt.icmp() icmp.type = pkt.ICMP.TYPE_DEST_UNREACH icmp.code = pkt.ICMP.CODE_UNREACH_HOST orig_ip = event.parsed.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] import struct d = struct.pack("!HH", 0,0) + d #FIXME: MTU icmp.payload = d ipp.payload = icmp e.payload = ipp msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = event.port)) msg.data = e.pack() self.connection.send(msg) return log.info("Installing path for %s -> %s %04x (%i hops)", match.dl_src, match.dl_dst, match.dl_type, len(p)) # log.info("path: %s", str(p)) # We have a path -- install it self._install_path(p, match, event.ofp) # Now reverse it and install it backwards # (we'll just assume that will work) p = [(sw,out_port,in_port) for sw,in_port,out_port in p] self._install_path(p, match.flip())
def ifReach(dstip, event, self): dpid = self.connection.dpid for subRouteTable in self.routeTable: dstnetwork = subRouteTable[DST_Network] if dstip.inNetwork(dstnetwork): log.debug('------ip dst %s is in the routeTable-----' % dstip) nextPort = subRouteTable[NEXTHOP_PORT] log.debug('------ip dst %s is in the routeTable-----' % nextPort) if nextPort == event.ofp.in_port: continue nextHopIp = IPAddr(subRouteTable[NETX_HOP_IP]) nextPortIp = IPAddr(subRouteTable[NEXT_PORT_IP]) srcMac = arpCache[dpid][nextPort][nextPortIp] if nextHopIp in arpCache[dpid][nextPort]: log.debug('------I know the next dst %s mac-----' % nextHopIp) nextHopMac = arpCache[dpid][nextPort][nextHopIp] msg = of.ofp_flow_mod() msg.match = of.ofp_match() msg.match.dl_type = ethernet.IP_TYPE msg.match.nw_dst = dstip msg.command = 0 msg.idle_timeout = 10 msg.hard_timeout = 30 msg.buffer_id = event.ofp.buffer_id msg.actions.append(of.ofp_action_dl_addr.set_src(srcMac)) msg.actions.append(of.ofp_action_dl_addr.set_dst(nextHopMac)) msg.actions.append(of.ofp_action_output(port=nextPort)) self.connection.send(msg) log.debug('-----install a flow-----') else: log.debug( '------I don\'t know the next dst %s mac,make an arp request-----' % IPAddr(subRouteTable[NETX_HOP_IP])) ARPrequest = arp() ARPrequest.opcode = arp.REQUEST ARPrequest.protosrc = nextPortIp ARPrequest.hwsrc = srcMac ARPrequest.protodst = nextHopIp arpPacket = ethernet(type=ethernet.ARP_TYPE, src=ARPrequest.hwsrc, dst=ETHER_BROADCAST) arpPacket.set_payload(ARPrequest) msg = of.ofp_packet_out() msg.data = arpPacket.pack() msg.actions.append(of.ofp_action_output(port=nextPort)) msg.in_port = event.ofp.in_port event.connection.send(msg) log.debug('------Arp request has been snet-----') nextHopMac = ETHER_BROADCAST msg = of.ofp_packet_out() msg.in_port = event.port msg.buffer_id = event.ofp.buffer_id msg.actions.append(of.ofp_action_dl_addr.set_src(srcMac)) msg.actions.append(of.ofp_action_dl_addr.set_dst(nextHopMac)) msg.actions.append(of.ofp_action_output(port=nextPort)) self.connection.send(msg) return True return False
def _handle_PacketIn(self, event): packet = event.parsed def drop(duration=None): if duration is not None: if not isinstance(duration, tuple): duration = (duration, duration) msg = of.ofp_flow_mod() msg.match = of.ofp_match.from_packet(packet) msg.idle_timeout = duration[0] msg.hard_timeout = duration[1] msg.buffer_id = event.ofp.buffer_id self.connection.send(msg) elif event.ofp.buffer_id is not None: msg = of.ofp_packet_out() msg.buffer_id = event.ofp.buffer_id msg.in_port = event.port self.connection.send(msg) def flood(message=None): msg = of.ofp_packet_out() if time.time() - self.connection.connect_time >= _flood_delay: if self.hold_down_expired is False: self.hold_down_expired = True log.info("%s: Flood hold-down expired -- flooding", dpid_to_str(event.dpid)) if message is not None: log.debug(message) msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) else: pass msg.data = event.ofp msg.in_port = event.port self.connection.send(msg) """Add MAC & IP to Tables""" self.macToPort[packet.src] = event.port if (self.macToIP.get(packet.src, None)) is None: self.macToIP[packet.src] = "10.10.{:d}.{:d}".format( (6 - event.dpid % 2), self.addr) self.addr += 1 """Catch and Process IPv4 Packets""" ip = packet.find("ipv4") if ip is not None: ip.ttl -= 1 """Handle ICMP Time Exceeded Event""" if (ip.ttl == 0): log.debug("TTL expired!!!") """Create ICMP Time Exceeded Message""" icmp = pkt.icmp() icmp.type = pkt.TYPE_TIME_EXCEED log.debug("This is the ICMP error message {:s}".format( icmp.payload)) """Create IP Payload""" ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = IPAddr(self.macToIP[packet.src]) ipp.dstip = packet.next.srcip ipp.payload = icmp log.debug("This is the IP payload {:s}".format(ipp.payload)) """Create Ethernet Payload""" e = pkt.ethernet() e.src = packet.dst e.dst = packet.src e.type = e.IP_TYPE e.payload = ipp log.debug("This is the Ethernet payload {:s}".format( e.payload)) """Send Packet the Original Source""" msg = of.ofp_packet_out() msg.actions.append( of.ofp_action_output(port=self.macToPort[packet.src])) msg.date = e.pack() msg.in_port = of.OFPP_NONE event.connection.send(msg)
def install_path (self, dst_sw, last_port, match, event): """ Attempts to install a path between this switch and some destination """ p = _get_path(self, dst_sw, event.port, last_port) if p is None: log.warning("Can't get from %s to %s", match.dl_src, match.dl_dst) import pox.lib.packet as pkt if (match.dl_type == pkt.ethernet.IP_TYPE and event.parsed.find('ipv4')): # It's IP -- let's send a destination unreachable log.debug("Dest unreachable (%s -> %s)", match.dl_src, match.dl_dst) from pox.lib.addresses import EthAddr e = pkt.ethernet() e.src = EthAddr(dpid_to_str(self.dpid)) #FIXME: Hmm... e.dst = match.dl_src e.type = e.IP_TYPE ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = match.nw_dst #FIXME: Ridiculous ipp.dstip = match.nw_src icmp = pkt.icmp() icmp.type = pkt.ICMP.TYPE_DEST_UNREACH icmp.code = pkt.ICMP.CODE_UNREACH_HOST orig_ip = event.parsed.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] import struct d = struct.pack("!HH", 0,0) + d #FIXME: MTU icmp.payload = d ipp.payload = icmp e.payload = ipp msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = event.port)) msg.data = e.pack() self.connection.send(msg) return log.debug("Installing path for %s -> %s %04x (%i hops)", match.dl_src, match.dl_dst, match.dl_type, len(p)) print "maryam dest ip is" , match.nw_dst #calling the statcolect function when a new flow is to be installed. This function collects statisctics to monitor the network behavior to detect DDOS attacks. send_path = p tuple(send_path) self.statcolect(send_path, match.nw_dst, match.nw_src) # We have a path -- install it self._install_path(p, match, event.ofp) # Now reverse it and install it backwards # (we'll just assume that will work) p = [(sw,out_port,in_port) for sw,in_port,out_port in p] self._install_path(p, match.flip()) def _handle_PacketIn (self, event): def flood (): """ Floods the packet """ if self.is_holding_down: log.warning("Not flooding -- holddown active") msg = of.ofp_packet_out() # OFPP_FLOOD is optional; some switches may need OFPP_ALL msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) msg.buffer_id = event.ofp.buffer_id msg.in_port = event.port self.connection.send(msg) def drop (): # Kill the buffer if event.ofp.buffer_id is not None: msg = of.ofp_packet_out() msg.buffer_id = event.ofp.buffer_id event.ofp.buffer_id = None # Mark is dead msg.in_port = event.port self.connection.send(msg) packet = event.parsed loc = (self, event.port) # Place we saw this ethaddr oldloc = mac_map.get(packet.src) # Place we last saw this ethaddr if packet.effective_ethertype == packet.LLDP_TYPE: drop() return if oldloc is None: if packet.src.is_multicast == False: mac_map[packet.src] = loc # Learn position for ethaddr log.debug("Learned %s at %s.%i", packet.src, loc[0], loc[1]) elif oldloc != loc: # ethaddr seen at different place! if loc[1] not in adjacency[loc[0]].values(): # New place is another "plain" port (probably) log.debug("%s moved from %s.%i to %s.%i?", packet.src, dpid_to_str(oldloc[0].connection.dpid), oldloc[1], dpid_to_str( loc[0].connection.dpid), loc[1]) if packet.src.is_multicast == False: mac_map[packet.src] = loc # Learn position for ethaddr log.debug("Learned %s at %s.%i", packet.src, loc[0], loc[1]) elif packet.dst.is_multicast == False: # New place is a switch-to-switch port! #TODO: This should be a flood. It'd be nice if we knew. We could # check if the port is in the spanning tree if it's available. # Or maybe we should flood more carefully? log.warning("Packet from %s arrived at %s.%i without flow", packet.src, dpid_to_str(self.dpid), event.port) #drop() #return if packet.dst.is_multicast: log.debug("Flood multicast from %s", packet.src) flood() else: if packet.dst not in mac_map: log.debug("%s unknown -- flooding" % (packet.dst,)) flood() else: dest = mac_map[packet.dst] match = of.ofp_match.from_packet(packet) self.install_path(dest[0], dest[1], match, event) def disconnect (self): if self.connection is not None: log.debug("Disconnect %s" % (self.connection,)) self.connection.removeListeners(self._listeners) self.connection = None self._listeners = None def connect (self, connection): if self.dpid is None: self.dpid = connection.dpid assert self.dpid == connection.dpid if self.ports is None: self.ports = connection.features.ports self.disconnect() log.debug("Connect %s" % (connection,)) self.connection = connection self._listeners = self.listenTo(connection) self._connected_at = time.time() @property def is_holding_down (self): if self._connected_at is None: return True if time.time() - self._connected_at > FLOOD_HOLDDOWN: return False return True def _handle_ConnectionDown (self, event): self.disconnect() class l2_multi (EventMixin): _eventMixin_events = set([ PathInstalled, ]) def __init__ (self): # Listen to dependencies def startup (): core.openflow.addListeners(self, priority=0) core.openflow_discovery.addListeners(self) core.call_when_ready(startup, ('openflow','openflow_discovery')) def _handle_LinkEvent (self, event): def flip (link): return Discovery.Link(link[2],link[3], link[0],link[1]) l = event.link sw1 = switches[l.dpid1] sw2 = switches[l.dpid2] # Invalidate all flows and path info. # For link adds, this makes sure that if a new link leads to an # improved path, we use it. # For link removals, this makes sure that we don't use a # path that may have been broken. #NOTE: This could be radically improved! (e.g., not *ALL* paths break) clear = of.ofp_flow_mod(command=of.OFPFC_DELETE) for sw in switches.itervalues(): if sw.connection is None: continue sw.connection.send(clear) path_map.clear() if event.removed: # This link no longer okay if sw2 in adjacency[sw1]: del adjacency[sw1][sw2] if sw1 in adjacency[sw2]: del adjacency[sw2][sw1] # But maybe there's another way to connect these... for ll in core.openflow_discovery.adjacency: if ll.dpid1 == l.dpid1 and ll.dpid2 == l.dpid2: if flip(ll) in core.openflow_discovery.adjacency: # Yup, link goes both ways adjacency[sw1][sw2] = ll.port1 adjacency[sw2][sw1] = ll.port2 # Fixed -- new link chosen to connect these break else: # If we already consider these nodes connected, we can # ignore this link up. # Otherwise, we might be interested... if adjacency[sw1][sw2] is None: # These previously weren't connected. If the link # exists in both directions, we consider them connected now. if flip(l) in core.openflow_discovery.adjacency: # Yup, link goes both ways -- connected! adjacency[sw1][sw2] = l.port1 adjacency[sw2][sw1] = l.port2 # If we have learned a MAC on this port which we now know to # be connected to a switch, unlearn it. bad_macs = set() for mac,(sw,port) in mac_map.iteritems(): #print sw,sw1,port,l.port1 if sw is sw1 and port == l.port1: if mac not in bad_macs: log.debug("Unlearned %s", mac) bad_macs.add(mac) if sw is sw2 and port == l.port2: if mac not in bad_macs: log.debug("Unlearned %s", mac) bad_macs.add(mac) for mac in bad_macs: del mac_map[mac] def _handle_ConnectionUp (self, event): sw = switches.get(event.dpid) if sw is None: # New switch sw = Switch() switches[event.dpid] = sw sw.connect(event.connection) else: sw.connect(event.connection) def _handle_BarrierIn (self, event): wp = waiting_paths.pop((event.dpid,event.xid), None) if not wp: #log.info("No waiting packet %s,%s", event.dpid, event.xid) return #log.debug("Notify waiting packet %s,%s", event.dpid,event.xid) wp.notify(event) def launch (): core.registerNew(l2_multi) core.registerNew(Cleanswitch) core.Cleanswitch._do_sleep() timeout = min(max(PATH_SETUP_TIME, 5) * 2, 15) Timer(timeout, WaitingPath.expire_waiting_paths, recurring=True) print "will go to execute the timer for sent_sw" #we will call the cleaning_sent_sw function in the switch class to erase the list of the switches that have been already polled for statistics. As long as the switches are in the sent_sw list no statistics request will be sent to them. Timer(10, Switch.cleaning_sent_sw, recurring=True) core.openflow.addListenerByName("FlowStatsReceived", Switch()._handle_flowstats_received)
def gestisciPacketIn(self, packet, packet_in, dpid, event): #eseguendo una gestione manuale delle ARP, bisogna salvane le info importanti if packet.type == packet.ARP_TYPE: self.registraHost(packet.src, event.connection.dpid, event.port, packet.payload.protosrc) ipSource = str(packet.payload.protosrc) ipDest = str(packet.payload.protodst) macSource = str(packet.src) #se non e' presente il mittente in tabella, viene aggiunto if ipSource not in self.tabellaC.keys(): self.tabellaC[ipSource] = (macSource, dpid) #se e' un arp request if packet.payload.opcode == pkt.arp.REQUEST: if ipDest in self.tabellaC.keys( ): #trovato destinatario nella tabella, rispondi direttamente con arp reply arp_reply = pkt.arp() coppia = self.tabellaC[ ipDest] #ottieni coppia (MAC, SWITCH) del destinatario macDest = coppia[0] #prendi MAC del destinatario arp_reply.hwsrc = EthAddr(macDest) arp_reply.hwdst = EthAddr(macSource) arp_reply.opcode = pkt.arp.REPLY arp_reply.protosrc = IPAddr(ipDest) arp_reply.protodst = IPAddr(ipSource) ether = pkt.ethernet() ether.type = pkt.ethernet.ARP_TYPE ether.src = EthAddr(macDest) ether.dst = EthAddr(macSource) ether.payload = arp_reply self.sendPacketToDPID(ether, dpid) else: #non c'e in tabella manda una arp request a tutti gli switch arp_request = pkt.arp() arp_request.hwsrc = EthAddr(macSource) arp_request.opcode = pkt.arp.REQUEST arp_request.protosrc = IPAddr(ipSource) arp_request.protodst = IPAddr(ipDest) ether = pkt.ethernet() ether.type = pkt.ethernet.ARP_TYPE ether.src = EthAddr(macSource) ether.dst = pkt.ETHER_BROADCAST ether.payload = arp_request self.sendPacketAll(ether) else: # e' una arp reply, viene inoltrata al destinatario arp_reply = pkt.arp() coppia = self.tabellaC[ ipDest] #ottieni coppia (MAC, SWITCH) del destinatario macDest = coppia[0] #prendi MAC del destinatario arp_reply.hwsrc = EthAddr(macDest) arp_reply.hwdst = EthAddr(macSource) arp_reply.opcode = pkt.arp.REPLY arp_reply.protosrc = IPAddr(ipDest) arp_reply.protodst = IPAddr(ipSource) ether = pkt.ethernet() ether.type = pkt.ethernet.ARP_TYPE ether.src = EthAddr(macDest) ether.dst = EthAddr(macSource) ether.payload = arp_reply self.sendPacketToDPID(ether, coppia[1]) #il pacchetto non e' un ARP else: #prende le info dal pacchetto ipDest = str(packet.payload.dstip) ipSrc = str(packet.payload.srcip) coppia_dst = self.tabellaC[ ipDest] #ottieni lo coppia (MAC, DPID) del destinatario dpid_dst = coppia_dst[ 1] #ottieni il dpid dello switch destinatario mac_dst = coppia_dst[0] coppia_src = self.tabellaC[ipSrc] mac_src = coppia_src[0] #calcola il percorso per la destinazione con dijkstra percorso = self.dijkstra(dpid, dpid_dst) #avvia l'installazione negli switch del percorso self.avvia_instal(percorso, ipDest, ipSrc) #riesegui il procedimento, ma sul percorso inverso percorso.reverse() self.avvia_instal(percorso, ipSrc, ipDest) print percorso #dato che si conosce il dpid destinatario, inoltra direttamente il pacchetto, senza passare per la rete self.sendPacketToDPID(packet, dpid_dst)
def _handle_PacketIn(self, event): dpid = self.connection.dpid log.debug('-' * 50 + "dpid=" + str(dpid) + '-' * 50) log.debug("A PacketIn Message Recieved") packet = event.parsed # arp if packet.type == ethernet.ARP_TYPE: log.debug('---It\'s an arp packet') arppacket = packet.payload # arp回应 if arppacket.opcode == arp.REPLY: arpTable[self.connection.dpid][event.ofp.in_port][ arppacket.protosrc] = arppacket.hwsrc arpTable[self.connection.dpid][event.ofp.in_port][ arppacket.protodst] = arppacket.hwdst # 更新后的arp表 log.debug('------arpTable learned form arp Reply srt and dst') log.debug('------' + str(arpTable)) # arp请求 if arppacket.opcode == arp.REQUEST: log.debug('------Arp request') log.debug('------' + arppacket._to_str()) arpTable[self.connection.dpid][event.ofp.in_port][ arppacket.protosrc] = arppacket.hwsrc # 更新后的arp表 log.debug('------arpTable learned form arp Request srt') log.debug('------' + str(arpTable)) # 发送arp回应 if arppacket.protodst in arpTable[self.connection.dpid][ event.ofp.in_port]: log.debug('------I know that ip %s,send reply' % arppacket.protodst) #构造arp回应 a = arppacket r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwdst = a.hwsrc r.protodst = a.protosrc r.protosrc = a.protodst r.hwsrc = arpTable[self.connection.dpid][ event.ofp.in_port][arppacket.protodst] e = ethernet(type=packet.type, src=r.hwsrc, dst=a.hwsrc) e.set_payload(r) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=event.ofp.in_port)) self.connection.send(msg) # ip包 if packet.type == ethernet.IP_TYPE: log.debug('---It\'s an ip packet') ippacket = packet.payload # 目的ip dstip = ippacket.dstip # 查找端口映射表,判断目的ip是否为路由器本身,回应icmp echo reply for t in portTable[dpid]: selfip = t[pPORT_IP] # 如果目的ip地址为当前路由器拥有的地址 if dstip == selfip: #如果是icmp echo request报文 if ippacket.protocol == ipv4.ICMP_PROTOCOL: log.debug('!!!!!!!!!!An icmp for me!!!!!!!!!!!') icmppacket = ippacket.payload #是否为icmp echo request if icmppacket.type == TYPE_ECHO_REQUEST: selfmac = t[pPORT_MAC] log.debug( '!!!!!!!!!!An icmp echo request for me!!!!!!!!!!!' ) # 构造icmp包 r = icmppacket r.type = TYPE_ECHO_REPLY #构造ip包 s = ipv4() s.protocol = ipv4.ICMP_PROTOCOL s.srcip = selfip s.dstip = ippacket.srcip s.payload = r #构造以太网帧 e = ethernet() e.type = ethernet.IP_TYPE e.src = selfmac e.dst = packet.src e.payload = s # 构造PacketOut消息 # 回发icmp包 msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=event.port)) self.connection.send(msg) log.debug('!!!!!!!!!!Reply it!!!!!!!!!!!') return else: #对发往路由器的icmp包,除了icmp echo request之外,均不理会 return #发往路由器的非icmp包 else: #直接丢包,这里控制器暂时不做回应 return # 搜索路由表 for t in self.routeTable: # 路由表项中的网络前缀 dstnetwork = t[rDST_NETWORK] # 如果目的ip在路由表中 if dstip.inNetwork(dstnetwork): log.debug('------ip dst %s is in the routeTable' % dstip) # 找到对应的下一跳信息 nh_port = t[rNEXTHOP_PORT] if nh_port == event.ofp.in_port: return # 应该下达丢包动作 nh_ip = IPAddr(t[rNEXTHOP_IP]) # 直接交付 if nh_ip == IPAddr('0.0.0.0'): nh_ip = dstip nh_port_ip = IPAddr(t[rNEXTHOP_PORT_IP]) # 查找arp表 nh_mac_src = arpTable[dpid][nh_port][nh_port_ip] # 若下一跳目的主机的mac已知,添加流表 if nh_ip in arpTable[dpid][nh_port]: log.debug('------I know the next dst %s mac' % nh_ip) nh_mac_dst = arpTable[dpid][nh_port][nh_ip] # 下发流表 msg1 = of.ofp_flow_mod() # 匹配 msg1.match = of.ofp_match() msg1.match.dl_type = ethernet.IP_TYPE msg1.match.nw_dst = dstip # Flow actions msg1.command = 0 msg1.idle_timeout = 10 msg1.hard_timeout = 30 msg1.buffer_id = event.ofp.buffer_id msg1.flags = 3 # of.ofp_flow_mod_flags_rev_map('OFPFF_CHECK_OVERLAP') | of.ofp_flow_mod_flags_rev_map('OFPFF_CHECK_OVERLAP') msg1.actions.append( of.ofp_action_dl_addr.set_src(nh_mac_src)) msg1.actions.append( of.ofp_action_dl_addr.set_dst(nh_mac_dst)) msg1.actions.append(of.ofp_action_output(port=nh_port)) self.connection.send(msg1) log.debug('###Add a flow###') # 若下一跳目的主机的mac未知,发送arp请求,并广播ip包 else: log.debug( '------I don\'t know the next dst %s mac,make an arp request' % IPAddr(t[rNEXTHOP_IP])) # 构造arp请求 r = arp() r.opcode = arp.REQUEST r.protosrc = nh_port_ip r.hwsrc = nh_mac_src r.protodst = nh_ip e_arp = ethernet(type=ethernet.ARP_TYPE, src=r.hwsrc, dst=ETHER_BROADCAST) e_arp.set_payload(r) msg = of.ofp_packet_out() msg.data = e_arp.pack() msg.actions.append(of.ofp_action_output(port=nh_port)) msg.in_port = event.ofp.in_port event.connection.send(msg) # 广播ip包,不下发流表 nh_mac_dst = ETHER_BROADCAST msg1 = of.ofp_packet_out() msg1.in_port = event.port msg1.buffer_id = event.ofp.buffer_id msg1.actions.append( of.ofp_action_dl_addr.set_src(nh_mac_src)) msg1.actions.append( of.ofp_action_dl_addr.set_dst(nh_mac_dst)) msg1.actions.append(of.ofp_action_output(port=nh_port)) self.connection.send(msg1) return # 在路由表中未找到匹配项,发送icmp网络不可达报文 r = icmp() r.type = TYPE_DEST_UNREACH r.code = CODE_UNREACH_NET d = ippacket.pack()[:ippacket.iplen + 8] import struct d = struct.pack("!I", 0) + d #不可达报文的unused字段,也包含在icmp的payload中 #这里大写的I代表4字节无符号整形,0代表数值, # struct.pack("!I", 0)的返回值是4个字节的0,正好填在不可达报文未用字段 r.payload = d s = ipv4() s.protocol = ipv4.ICMP_PROTOCOL for t in portTable[dpid]: selfip = t[pPORT_IP] if (event.port == t[pPORT]): s.srcip = selfip break s.dstip = ippacket.srcip s.payload = r e = ethernet() e.type = ethernet.IP_TYPE e.src = packet.dst e.dst = packet.src e.payload = s # 构造PacketOut消息 # 回发icmp包 msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port=event.port)) self.connection.send(msg)