def send_icmp(self, tp, code, dest_ip, dest_mac, dest_port, orig_packet): # Should be able to send echo reply (tp=0,code=0), # destination unreachable (tp=3,code=0(network unreachable)/1(host unreachable)/3(port unreachable)), # TTL expired (tp=11,code=0) msg = None if tp == 0: p = orig_packet.payload while p is not None and not isinstance(p, echo): p = p.next if p is None: return r = echo(id=p.id, seq=p.seq) r.set_payload(p.next) msg = icmp(type=0, code=0) msg.set_payload(r) elif tp == 3: msg = icmp() msg.type = 3 msg.code = code d = orig_packet.payload.pack() d = d[:orig_packet.payload.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d msg.payload = d elif tp == 11: msg = icmp() msg.type = 11 msg.code = 0 d = orig_packet.payload.pack() d = d[:orig_packet.payload.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d msg.payload = d # Make the IP packet around it ipp = ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = IPAddr(dest_port.ip) ipp.dstip = IPAddr(dest_ip) # Ethernet around that... e = ethernet() e.src = EthAddr(dest_port.mac) e.dst = EthAddr(dest_mac) e.type = e.IP_TYPE # Hook them up... ipp.payload = msg e.payload = ipp # send this packet to the switch log.debug('router {}; Sending ICMP TYPE {}; code {}; dest_ip {}; output_port {}'.format(self.connection.dpid, tp, code, dest_ip, dest_port.id)) self.send_packet(None, e, dest_port.id, of.OFPP_NONE)
def _handle_icmp_reply(self, dpid, p, srcip, dstip, icmp_type): p_icmp = icmp() p_icmp.type = icmp_type if icmp_type == pkt.TYPE_ECHO_REPLY: p_icmp.payload = p.find('icmp').payload elif icmp_type == pkt.TYPE_DEST_UNREACH: orig_ip = p.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d p_icmp.payload = d p_ip = ipv4() p_ip.protocol = p_ip.ICMP_PROTOCOL p_ip.srcip = dstip p_ip.dstip = srcip e = ethernet() e.src = p.dst e.dst = p.src e.type = e.IP_TYPE p_ip.payload = p_icmp e.payload = p_ip 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.routingTable[dpid][srcip] self.connections[dpid].send(msg) log.debug('DPID : IP %s pings router at %s, send icmp reply'% (str(srcip), str(dstip)))
def handleIcmpRequest(self, dpid, p, srcip, dstip, icmpType): pIcmp = icmp() pIcmp.type = icmpType if icmpType == pkt.TYPE_ECHO_REPLY: pIcmp.payload = p.find('icmp').payload elif icmpType == pkt.TYPE_DEST_UNREACH: oriIp = p.find('ipv4') d = oriIp.pack() d = d[:oriIp.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d pIcmp.payload = d pIp = ipv4() pIp.protocol = pIp.ICMP_PROTOCOL pIp.srcip = dstip pIp.dstip = srcip e = ethernet() e.src = p.dst e.dst = p.src e.type = e.IP_TYPE pIp.payload = pIcmp e.payload = pIp 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.routingTable[dpid][srcip] self.connections[dpid].send(msg) log.debug("dpid %d: IP %s ping router at %s" % (dpid, str(srcip), str(dstip)))
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 icmp_unreach(self, dpid, packet, inport): icmp_pkt = icmp() #icmp_pkt = pkt.unreach() #icmp_pkt.payload = packet.find("icmp").payload #print str(icmp_pkt.payload.pack().encode('hex')) icmp_pkt.type = 3 icmp_pkt.code = 0 orig_ip = packet.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d icmp_pkt.payload = d #print str(d.encode('hex')) ip_pkt = ipv4() srcip = IPAddr(self.fakeways[dpid - 1][0]) ip_pkt.srcip = IPAddr(self.fakeways[dpid - 1][0]) ip_pkt.dstip = packet.payload.srcip ip_pkt.protocol = ip_pkt.ICMP_PROTOCOL ip_pkt.set_payload(icmp_pkt) #print str(ip_pkt.payload) e = ethernet(type=ethernet.IP_TYPE, src=self.arpTable[dpid][srcip].mac, dst=packet.src) #print str(self.arpTable[dpid][ip_pkt.srcip].mac) e.set_payload(ip_pkt) action = of.ofp_action_output(port=inport) po = of.ofp_packet_out(actions=action, data=e.pack()) core.openflow.sendToDPID(dpid, po)
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 handle_ICMP_packets (self, packet, packet_in): """ Controller may receive ICMP echo (ping) requests for the router, which it should respond to. """ ppacket = packet.payload icmp_request_packet = ppacket.payload # make new icmp reply to the received icmp request if icmp_request_packet.type == 8: # (8 type number is for icmp request) icmp_echo_reply_packet = icmp() icmp_echo_reply_packet.code = 0 icmp_echo_reply_packet.type = 0 # (0 type number is for icmp reply) icmp_echo_reply_packet.payload = icmp_request_packet.payload # make ipv4 header ip = ipv4() # set it's fields ip.srcip = ppacket.dstip ip.dstip = ppacket.srcip ip.protocol = ipv4.ICMP_PROTOCOL ip.payload = icmp_echo_reply_packet # make the new packet to send newPacket = ethernet() # set it's fields newPacket.type = ethernet.IP_TYPE newPacket.src = ethernet_frame.dst newPacket.dst = ethernet_frame.src newPacket.payload = ip self.resend_packet(newPacket, packet_in.in_port)
def icmp_message(self, dpid, p, srcip, dstip, icmp_type,event): p_icmp = icmp() p_icmp.type = icmp_type if icmp_type == pkt.TYPE_ECHO_REPLY: p_icmp.payload = p.find('icmp').payload elif icmp_type == pkt.TYPE_DEST_UNREACH: #print dir(p.next) orig_ip = p.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d # network, unsigned short, unsigned short p_icmp.payload = d #print dir(p) #print type(p.payload) p_ip = ipv4() p_ip.protocol = p_ip.ICMP_PROTOCOL p_ip.srcip = dstip # srcip, dstip in the argument is from the ping p_ip.dstip = srcip e = ethernet() e.src = p.dst e.dst = p.src e.type = e.IP_TYPE p_ip.payload = p_icmp e.payload = p_ip 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.routing[dpid][srcip] event.connection.send(msg)
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_Reply(self, dpid, ethernet_packet, srcip, dstip, icmpType): ICMP_packet = icmp() ICMP_packet.type = icmpType if icmpType == pkt.TYPE_ECHO_REPLY: ICMP_packet.payload = ethernet_packet.find('icmp').payload elif icmpType == pkt.TYPE_DEST_UNREACH: oriIp = ethernet_packet.find('ipv4') d = oriIp.pack() d = d[:oriIp.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d ICMP_packet.payload = d IP_packet = ipv4() IP_packet.protocol = IP_packet.ICMP_PROTOCOL IP_packet.srcip = dstip IP_packet.dstip = srcip IP_packet.payload = ICMP_packet e = ethernet() e.src = ethernet_packet.dst if (srcip in subnet1 and self.routerIP[dpid] in subnet1) or (srcip in subnet2 and self.routerIP[dpid] in subnet2) or (srcip in subnet2 and self.routerIP[dpid] in subnet): e.dst = ethernet_packet.src else: gatewayIP = IPAddr(self._find_gatewayIP(IP_packet.dstip)) e.dst = self.arpTable[dpid][gatewayIP] e.type = e.IP_TYPE e.payload = IP_packet 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.routingTable[dpid][srcip] self.connections[dpid].send(msg) log.debug("Router {0}: {1} ping router at {2}".format(dpid, srcip, dstip))
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 ICMP_Handler(self, packet, packet_in): ethernet_frame = packet ip_packet = packet.payload icmp_request_packet = ip_packet.payload # ICMP Echo Request (8) -> ICMP Echo Reply (0) if icmp_request_packet.type == 8: icmp_echo_reply_packet = icmp() icmp_echo_reply_packet.code = 0 icmp_echo_reply_packet.type = 0 icmp_echo_reply_packet.payload = icmp_request_packet.payload ip = ipv4() ip.srcip = ip_packet.dstip ip.dstip = ip_packet.srcip ip.protocol = ipv4.ICMP_PROTOCOL ip.payload = icmp_echo_reply_packet ether = ethernet() ether.type = ethernet.IP_TYPE ether.src = ethernet_frame.dst ether.dst = ethernet_frame.src ether.payload = ip self.resend_packet(ether, packet_in.in_port) log.debug("%s ICMP ECHO REPLY SENT!" % self.dpid)
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 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 _handle_ICMP(self, IP_packet, inport, org_packet): if IP_packet.payload.type == pkt.TYPE_ECHO_REQUEST: log.debug("A ICMP REQUEST packet") dst_ip = IP_packet.dstip # find dst_ip in routing table if dst_ip in self.my_port_to_ip: # to one of switch port log.debug("not ") p = icmp() p.type = pkt.TYPE_ECHO_REPLY p.payload = IP_packet.payload.payload IP_packet.srcip, IP_packet.dstip = IP_packet.dstip, IP_packet.srcip IP_packet.payload = p self._send_frame(IP_packet, ethernet.IP_TYPE, self.port_list[inport].mac, org_packet.src, inport) pass elif dst_ip not in self.ip_to_port: # unreachable log.debug("The ip address {0} is not reachable".format(dst_ip)) p = self._create_icmp_unreachable(IP_packet, inport) self._send_frame(p, ethernet.IP_TYPE, self.port_list[inport].mac, org_packet.src, inport) else: outport = self.ip_to_port[dst_ip] # ip packet enqueue/list? with identifier?: dst_ip self.arp_cache.add(IP_packet) # send arp request to that port arp_rq = self._create_arp_packet(arp.REQUEST, EthAddr("ff:ff:ff:ff:ff:ff"), dst_ip, outport) self._send_frame(arp_rq, ethernet.ARP_TYPE, self.port_list[outport].mac, EthAddr("ff:ff:ff:ff:ff:ff"), outport) elif IP_packet.payload.type == pkt.TYPE_ECHO_REPLY: log.debug("A ICMP REPLY packet") log.debug(IP_packet) out_port = self.ip_to_port[IP_packet.dstip] log.debug(self.ip_to_mac) dst_mac = self.ip_to_mac[IP_packet.dstip] self._send_frame(IP_packet, ethernet.IP_TYPE, self.port_list[out_port].mac, dst_mac, out_port) pass
def _create_icmp_unreachable(self, ip_packet, inport): p = icmp() p.type = pkt.TYPE_DEST_UNREACH data = ip_packet.pack() data = data[:ip_packet.hl * 4 + 8] data = struct.pack("!HH", 0, 0) + data p.payload = data p_ip = ipv4() p_ip.protocol = p_ip.ICMP_PROTOCOL p_ip.srcip = self.port_list[inport].ip p_ip.dstip = ip_packet.srcip p_ip.payload = p return p_ip
def isValidIpPacket(self,event): # ipv4_packet = event.parsed.find("ipv4") ipv4_packet = event.parsed.find("ipv4") # Do more processing of the IPv4 packet src_ip = ipv4_packet.srcip dst_ip = ipv4_packet.dstip if(ipv4_packet.csum!=ipv4_packet.checksum()): print "Ip packet checksum not macthing" return False if(ipv4_packet.ttl<=1): if(dst_ip==self.IPAddr or dst_ip.toStr()=='255.255.255.255'): print "My Packet accept at ",self.IPAddr print ipv4_packet if(packet.payload.protocol==packet.payload.ICMP_PROTOCOL): self.handle_icmp(event) return False print "TTL Invalid" icmp_rep = icmp() icmp_rep.type = 11 # TYPE_TIME_EXCEED #icmp_rep.code=0 icmp_rep.next=unreach() # icmp_rep.next.seq=packet.payload.next.next.seq # icmp_rep.next.id=packet.payload.next.next.id # icmp_rep.next.raw=packet.payload.next.next.raw # Show the client that it's actually the me rep=ipv4() rep.srcip=self.IPAddr rep.dstip=ipv4_packet.srcip rep.next=icmp_rep rep.protocol=ipv4_packet.ICMP_PROTOCOL eth = ethernet() eth.dst = event.parsed.src eth.src = self.EthAddr eth.set_payload(rep) eth.type = ethernet.IP_TYPE msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = event.port self.connection.send(msg) return False if(ipv4_packet.iplen<20): print "Length Invalid" return False # len > min_len return True
def ICMP_Request_Router_local(self, packet, packet_in): icmp_reply = icmp() icmp_reply.code = 0 icmp_reply.type = 0 icmp_reply.payload = packet.payload.payload.payload ip_reply = ipv4() ip_reply.srcip = packet.payload.dstip ip_reply.dstip = packet.payload.srcip ip_reply.protocol = ipv4.ICMP_PROTOCOL ip_reply.payload = icmp_reply ether_packet = ethernet() ether_packet.type = ethernet.IP_TYPE ether_packet.src = packet.dst ether_packet.dst = packet.src ether_packet.payload = ip_reply self.resend_packet(ether_packet, packet_in.in_port) log.debug('ICMP/TCP/UDP reply has sent')
def ICMP_Unreachable(self, packet, packet_in): icmp_reply_unreachable = icmp() icmp_reply_unreachable.code = 0 icmp_reply_unreachable.type = 3 icmp_reply_unreachable.payload = packet.payload.payload.payload ip_reply_unreachable = ipv4() ip_reply_unreachable.srcip = packet.payload.dstip ip_reply_unreachable.dstip = packet.payload.srcip ip_reply_unreachable.protocol = ipv4.ICMP_PROTOCOL ip_reply_unreachable.payload = icmp_reply_unreachable ether_packet = ethernet() ether_packet.type = ethernet.IP_TYPE ether_packet.src = packet.dst ether_packet.dst = packet.src ether_packet.payload = ip_reply_unreachable self.resend_packet(ether_packet, packet_in.in_port) log.debug('ICMP reply for unreachable packet has sent')
def handle_icmp(self,event): print "ICMP Packet Arrived" packet=event.parsed src_mac = packet.src dst_mac = packet.dst ipv4_packet = event.parsed.find("ipv4") src_ip = ipv4_packet.srcip dst_ip = ipv4_packet.dstip if packet.payload.next.type==8: print "handing" icmp_rep = icmp() # icmp_rep.type = 3 icmp_rep.next=echo() icmp_rep.next.seq=packet.payload.next.next.seq icmp_rep.next.id=packet.payload.next.next.id icmp_rep.next.raw=packet.payload.next.next.raw # Show the client that it's actually the me rep=ipv4() rep.srcip=self.IPAddr rep.dstip=src_ip rep.next=icmp_rep rep.protocol=packet.payload.ICMP_PROTOCOL eth = ethernet() eth.dst = packet.src eth.src = self.EthAddr eth.set_payload(rep) eth.type = ethernet.IP_TYPE msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = event.port self.connection.send(msg) print "done handing" return if packet.payload.next.type==3: if packet.payload.next.code==1: print "Destination Host Unreachable" if packet.payload.next.code==0: print "Destination Network Unreachable" return
def _generate_icmp_reply(self, dpid, p, srcip, dstip, icmp_type): p_icmp = icmp() p_icmp.type = icmp_type if icmp_type == pkt.TYPE_ECHO_REPLY: p_icmp.payload = p.find('icmp').payload elif icmp_type == pkt.TYPE_DEST_UNREACH: #print dir(p.next) orig_ip = p.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d # network, unsigned short, unsigned short p_icmp.payload = d p_ip = ipv4() p_ip.protocol = p_ip.ICMP_PROTOCOL p_ip.srcip = dstip # srcip, dstip in the argument is from the ping p_ip.dstip = srcip e = ethernet() e.src = p.dst if is_same_subnet(srcip, self.routerIP[dpid]): e.dst = p.src else: gatewayip = dpid_to_ip(3 - dpid) e.dst = self.arpTable[dpid][gatewayip] e.type = e.IP_TYPE p_ip.payload = p_icmp e.payload = p_ip 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.routingTable[dpid][srcip] self.connections[dpid].send(msg) log.debug( 'DPID %d: IP %s pings router at %s, generating icmp reply with code %d...', dpid, str(srcip), str(dstip), icmp_type)
def _generate_icmp_reply(self, dpid, p, srcip, dstip, icmp_type): p_icmp = icmp() p_icmp.type = icmp_type if icmp_type == pkt.TYPE_ECHO_REPLY: p_icmp.payload = p.find('icmp').payload elif icmp_type == pkt.TYPE_DEST_UNREACH: #print dir(p.next) orig_ip = p.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d # network, unsigned short, unsigned short p_icmp.payload = d p_ip = ipv4() p_ip.protocol = p_ip.ICMP_PROTOCOL p_ip.srcip = dstip # srcip, dstip in the argument is from the ping p_ip.dstip = srcip e = ethernet() e.src = p.dst if is_same_subnet(srcip, self.routerIP[dpid]): e.dst = p.src else: gatewayip = dpid_to_ip( 3-dpid ) e.dst = self.arpTable[dpid][gatewayip] e.type = e.IP_TYPE p_ip.payload = p_icmp e.payload = p_ip 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.routingTable[dpid][srcip] self.connections[dpid].send(msg) log.debug('DPID %d: IP %s pings router at %s, generating icmp reply with code %d...', dpid, str(srcip), str(dstip), icmp_type)
def _handle_icmp_reply(self, dpid, p, srcip, dstip, icmp_type): pic = icmp() pic.type = icmp_type if icmp_type == pkt.TYPE_ECHO_REPLY: pic.payload = p.find('icmp').payload elif icmp_type == pkt.TYPE_DEST_UNREACH: orig_ip = p.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d pic.payload = d #p_ip = ipv4() ipv4().protocol = ipv4().ICMP_PROTOCOL ipv4().srcip = dstip ipv4().dstip = srcip e = ethernet() e.src = p.dst if (srcip in Subnet1 and self.routerIP[dpid] in Subnet1) or (srcip in Subnet2 and self.routerIP[dpid] in Subnet2): e.dst = p.src else: gatewayip = IPAddr('10.0.%d.1' % (3-dpid)) e.dst = self.arpTable[dpid][gatewayip] e.type = e.IP_TYPE p_ip.payload = p_icmp e.payload = p_ip 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.routingTable[dpid][srcip] self.connections[dpid].send(msg) log.debug('DPID %d: IP %s pings router at %s, generating icmp reply', dpid, str(srcip), str(dstip))
def _router_handle_icmp(self, event): # NOTE handles ECHO messages for now only packet = event.parsed ipPacket = packet.next icmpPacket = ipPacket.next replied = False if icmpPacket.type == TYPE_ECHO_REQUEST: for port in self.ports: if port.ip == ipPacket.dstip: # ping reply reply = icmp() reply.type = TYPE_ECHO_REPLY reply.payload = icmpPacket.payload # seq, id, etc. # ip packet i = ipv4() i.protocol = i.ICMP_PROTOCOL i.srcip = ipPacket.dstip i.dstip = ipPacket.srcip i.payload = reply # ethernet e = ethernet(type = ethernet.IP_TYPE, src = packet.dst, dst = packet.src) e.payload = i # openflow msg 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 self.connection.send(msg) # break the for-loop replied = True break if not replied: # this must be other's ping self._router_handle_ipv4(event)
def _handle_PacketIn(self, event): """ Handles packet in messages from the switch. """ etherFrame = event.parsed # This is the parsed packet data. if not etherFrame.parsed: log.warning("Ignoring incomplete packet") return packet_in = event.ofp # The actual ofp_packet_in message. # Add the new MAC into CAM table if str(etherFrame.src) not in self.mac_to_port: log.debug('Adding %s into CAM' % str(etherFrame.src)) self.mac_to_port[str(etherFrame.src)] = packet_in.in_port # ARP if etherFrame.type == ethernet.ARP_TYPE: log.debug('RECEIVED: EtherType -> ARP') self.ARP_Handler(etherFrame, packet_in) # IP elif etherFrame.type == ethernet.IP_TYPE: log.debug('RECEIVED: EtherType -> IP') # Extract IP Packet from Ethernet Frame ip_packet = etherFrame.payload # Routable? destination_ip = str(ip_packet.dstip) source_ip = str(ip_packet.srcip) log.debug('DESTIP of THE CURRENT PACKET: ' + destination_ip + ' FROM SRCIP ' + source_ip) routable, destination_network = self.checkRoutableDestination( destination_ip) if routable: # Destined for router if self.routing_table[str(destination_network)][ 'RouterInterface'] == destination_ip: if ip_packet.protocol == ipv4.ICMP_PROTOCOL: log.debug('ICMP ECHO -> ROUTER INTERFACE') self.ICMP_Handler(etherFrame, packet_in) elif ip_packet.protocol == 0x11: log.debug('UDP PACKET DETECTED!') udp_packet = ip_packet.payload print "\nRECEIVED UDP PACKET IN PORT NUMBER : " + str( udp_packet.dstport) if udp_packet.dstport == 9999: print "\nUDP PAYLOAD : " + str(udp_packet.payload) self.handleBandwidthRequest(udp_packet.payload) # Check if any there's any routable networks for the destination IP elif routable: # Route the packet to it's respective ports output_port = self.routing_table[destination_network][ 'Port'] # ARP if host MAC Address is not present if destination_ip not in self.arp_table: # Push frame to buffer self.buffer[destination_ip] = { 'IP_Packet': ip_packet, 'DestinationNetwork': destination_network } self.ARPResolve(destination_ip, destination_network, output_port) if destination_ip in self.arp_table: if destination_ip == "10.0.2.100": print "\n--DETECTED NEW PACKET TO APPLY QOS FLOW. PROCEEDING ...--" else: print "\n--DETECTED NEW PACKET TO APPLY NORMAL FLOW. PROCEEDING ...--" self.buffer[destination_ip] = { 'IP_Packet': ip_packet, 'DestinationNetwork': destination_network } self.push_flow_label(source_ip, destination_ip, output_port) print "\n--FLOW LABEL SUCCESSFULLY PUSHED FOR NEWLY DETECTED PACKET!--" etherFrame.src = EthAddr(self.arp_table[ self.routing_table[destination_network] ['RouterInterface']]) etherFrame.dst = EthAddr( self.arp_table[destination_ip]) self.resend_packet(etherFrame, output_port) # ICMP Destination Unreachable for non-routable networks else: #if source_ip != '0.0.0.0': log.debug('PACKET IS NOT ROUTABLE for IPdest' + str(ip_packet.dstip) + ' from IPsrc ' + str(ip_packet.srcip)) ethernet_frame = etherFrame ip_packet = etherFrame.payload icmp_request_packet = ip_packet.payload icmp_echo_reply_packet = icmp() icmp_echo_reply_packet.code = 0 icmp_echo_reply_packet.type = 3 icmp_echo_reply_packet.payload = icmp_request_packet.payload ip = ipv4() ip.srcip = ip_packet.dstip ip.dstip = ip_packet.srcip ip.protocol = ipv4.ICMP_PROTOCOL ip.payload = icmp_echo_reply_packet ether = ethernet() ether.type = ethernet.IP_TYPE ether.src = ethernet_frame.dst ether.dst = ethernet_frame.src ether.payload = ip self.resend_packet(ether, packet_in.in_port) log.debug("ICMP DESTINATION UNREACHABLE SENT") log.debug("Ignoring packet with src ip 0.0.0.0")
def custom_switch(self,packet,packet_in): """ Implement switch-like behavior. """ self.mac_to_port[packet.src]=self.event_port ip=packet.find('ipv4') if self.is_router(): if isinstance(packet.next,arp): a=packet.next if packet.payload.opcode==arp.REQUEST: if not a.protosrc.inNetwork(self.network,netmask=24): log.debug("dropping ARP request from separate subnet") elif not a.protodst.inNetwork(self.network,netmask=24): 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 e = ethernet(type=packet.type, src=dpid_to_mac(self.dpid), dst=a.hwsrc) e.set_payload(r) log.debug("ARP request to different network replying my IP") msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = self.event_port self.connection.send(msg) else: log.debug("ARP Request from same network dropping packet") elif packet.payload.opcode==arp.REPLY : log.debug("arp reply arrived with %s > %s and my ip=%s"% (a.protosrc,a.protodst,self.ip)) # if a.protodst == self.ip: ##send all waiting packets to that mac address through the port for waiting_packet in self.arpBuffer[a.protosrc]: e = ethernet(type=ethernet.IP_TYPE, src=dpid_to_mac(self.dpid), dst=a.hwsrc) e.set_payload(waiting_packet.payload) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT )) msg.in_port = self.event_port self.connection.send(msg) # self.resend_packet(waiting_packet,of.OFPP_IN_PORT) self.arpBuffer[a.protosrc]=[] elif ip is not None: if ip.csum == ip.checksum() and ip.iplen >= ipv4.MIN_LEN : pass else: print 'Garbled packet' return ip.ttl-=1 if(ip.ttl<=0): print 'TTL 0 throwing packet' # return #ICMP packet # Make the ping reply icm = icmp() icm.type=11 icm.code=0 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) return ip.csum=ip.checksum() ip_net = IPAddr(ip.dstip.toUnsigned() & ~((1 << (32-24))-1)) print ip_net if ip.dstip not in self.routeTable and ip_net not in self.routeTable and not ip.dstip.inNetwork(self.network,netmask=24): #send icmp unreachable # print self.routeTable log.debug("Unreacheable %s",(ip.dstip)) ##ICMP packet # Make the ping reply icm = icmp() icm.type=3 icm.code=0 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.payload = icm 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 = self.event_port self.connection.send(msg) elif ip.dstip.inNetwork(self.network,netmask=24) and ip.dstip not in self.routeTable: #ICMP host unreachable self.sendICMP(3,1,ip,packet) else: if ip.dstip in self.routeTable: dpid = self.routeTable[ip.dstip] else: dpid = self.routeTable[ip_net] if dpid==50: #host ip send ARP if not ip.dstip in self.arpBuffer: self.arpBuffer[ip.dstip]=[] self.arpBuffer[ip.dstip].append(packet) r = arp() r.hwsrc = self.mac r.hwdst = ETHER_BROADCAST r.opcode = arp.REQUEST r.protodst = ip.dstip r.protosrc = self.ip e = ethernet(type=ethernet.ARP_TYPE, src=dpid_to_mac(self.dpid), dst=ETHER_BROADCAST) e.set_payload(r) log.debug("ARP request to find host ") msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD )) msg.in_port = self.event_port self.connection.send(msg) else: # print self.mac,self.mac_to_port if dpid_to_mac(dpid) in self.mac_to_port: self.resend_packet(packet.pack(), self.mac_to_port[ dpid_to_mac(dpid) ]) else: self.act_like_hub(packet, packet_in) else: # self.act_like_hub(packet,packet_in) self.addEntryOrFlood(packet,packet_in)
def _handle_PacketIn(self, event): """ Handles packet in messages from the switch. """ etherFrame = event.parsed # This is the parsed packet data. if not etherFrame.parsed: log.warning("Ignoring incomplete packet") return packet_in = event.ofp # The actual ofp_packet_in message. # Add the new MAC into CAM table if str(etherFrame.src) not in self.mac_to_port: log.debug('Adding %s into CAM' % str(etherFrame.src)) self.mac_to_port[str(etherFrame.src)] = packet_in.in_port # ARP if etherFrame.type == ethernet.ARP_TYPE: log.debug('RECEIVED: EtherType -> ARP') self.ARP_Handler(etherFrame, packet_in) # IP elif etherFrame.type == ethernet.IP_TYPE: log.debug('RECEIVED: EtherType -> IP') # Extract IP Packet from Ethernet Frame ip_packet = etherFrame.payload # Routable? destination_ip = str(ip_packet.dstip) source_ip = str(ip_packet.srcip) log.debug('DESTIP of THE CURRENT PACKET: ' + destination_ip) routable = False for netaddr in self.routing_table: destination_network = netaddr if IPAddress(destination_ip) in IPNetwork(destination_network): log.debug('PACKET IS ROUTABLE!') routable = True break if routable: # Destined for router if self.routing_table[str(destination_network)][ 'RouterInterface'] == destination_ip: if ip_packet.protocol == ipv4.ICMP_PROTOCOL: log.debug('ICMP ECHO -> ROUTER INTERFACE') self.ICMP_Handler(etherFrame, packet_in) elif ip_packet.protocol == 0x11: log.debug('UDP PACKET DETECTED!') handleBandwidthRequest(ip_packet) udp_packet = ip_packet.payload print "\nRECEIVED UDP PACKET IN PORT NUMBER : " + str( udp_packet.dstport) print "\nUDP PAYLOAD : " + str(udp_packet.payload) # Check if any there's any routable networks for the destination IP elif routable: # Route the packet to it's respective ports output_port = self.routing_table[destination_network][ 'Port'] # ARP if host MAC Address is not present if destination_ip not in self.arp_table: # Push frame to buffer self.buffer[destination_ip] = { 'IP_Packet': ip_packet, 'DestinationNetwork': destination_network } # Construct ARP Packet arp_request = arp() arp_request.opcode = arp.REQUEST arp_request.protosrc = IPAddr( self.routing_table[destination_network] ['RouterInterface']) arp_request.protodst = IPAddr(destination_ip) arp_request.hwsrc = EthAddr(self.arp_table[ self.routing_table[destination_network] ['RouterInterface']]) arp_request.hwdst = EthAddr('00:00:00:00:00:00') ether = ethernet() ether.type = ether.ARP_TYPE ether.src = EthAddr(self.arp_table[self.routing_table[ destination_network]['RouterInterface']]) ether.dst = EthAddr('FF:FF:FF:FF:FF:FF') ether.payload = arp_request self.resend_packet(ether, output_port) if destination_ip in self.arp_table: if destination_ip == "10.0.4.100" and source_ip not in self.allocated_bandwidths.keys( ): print "\n--DETECTED NEW PACKET TO APPLY QOS FLOW. PROCEEDING ...--" self.buffer[destination_ip] = { 'IP_Packet': ip_packet, 'DestinationNetwork': destination_network } self.push_flow_label(source_ip, destination_ip, output_port) print "\n--QOS SUCCESSFULLY PUSHED FOR NEWLY DETECTED PACKET!--" etherFrame.src = EthAddr(self.arp_table[ self.routing_table[destination_network] ['RouterInterface']]) etherFrame.dst = EthAddr( self.arp_table[destination_ip]) self.resend_packet(etherFrame, output_port) # ICMP Destination Unreachable for non-routable networks else: log.debug('PACKET IS NOT ROUTABLE!') ethernet_frame = etherFrame ip_packet = etherFrame.payload icmp_request_packet = ip_packet.payload icmp_echo_reply_packet = icmp() icmp_echo_reply_packet.code = 0 icmp_echo_reply_packet.type = 3 icmp_echo_reply_packet.payload = icmp_request_packet.payload ip = ipv4() ip.srcip = ip_packet.dstip ip.dstip = ip_packet.srcip ip.protocol = ipv4.ICMP_PROTOCOL ip.payload = icmp_echo_reply_packet ether = ethernet() ether.type = ethernet.IP_TYPE ether.src = ethernet_frame.dst ether.dst = ethernet_frame.src ether.payload = ip self.resend_packet(ether, packet_in.in_port) log.debug("ICMP DESTINATION UNREACHABLE SENT")
def _handle_PacketIn(self, event): """ Handles packet in messages from the switch. """ etherFrame = event.parsed # This is the parsed packet data. if not etherFrame.parsed: log.warning("Ignoring incomplete packet") return packet_in = event.ofp # The actual ofp_packet_in message. # Add the new MAC into CAM table if str(etherFrame.src) not in self.mac_to_port: log.debug('Adding %s into CAM' % str(etherFrame.src)) self.mac_to_port[str(etherFrame.src)] = packet_in.in_port # ARP if etherFrame.type == ethernet.ARP_TYPE: log.debug('RECEIVED: EtherType -> ARP') self.ARP_Handler(etherFrame, packet_in) # IP elif etherFrame.type == ethernet.IP_TYPE: log.debug('RECEIVED: EtherType -> IP') # Extract IP Packet from Ethernet Frame ip_packet = etherFrame.payload # Routable? destination_ip = str(ip_packet.dstip) routable = False for netaddr in self.routing_table: destination_network = netaddr if IPAddress(destination_ip) in IPNetwork(destination_network): log.debug('PACKET IS ROUTABLE!') routable = True break if routable: # Destined for router if self.routing_table[str(destination_network)][ 'RouterInterface'] == destination_ip: if ip_packet.protocol == ipv4.ICMP_PROTOCOL: log.debug('ICMP ECHO -> ROUTER INTERFACE') self.ICMP_Handler(etherFrame, packet_in) # Check if any there's any routable networks for the destination IP elif routable: # Route the packet to it's respective ports output_port = self.routing_table[destination_network][ 'Port'] # ARP if host MAC Address is not present if destination_ip not in self.arp_table: # Push frame to buffer self.buffer[destination_ip] = { 'IP_Packet': ip_packet, 'DestinationNetwork': destination_network } # Construct ARP Packet arp_request = arp() arp_request.opcode = arp.REQUEST arp_request.protosrc = IPAddr( self.routing_table[destination_network] ['RouterInterface']) arp_request.protodst = IPAddr(destination_ip) arp_request.hwsrc = EthAddr(self.arp_table[ self.routing_table[destination_network] ['RouterInterface']]) arp_request.hwdst = EthAddr('00:00:00:00:00:00') ether = ethernet() ether.type = ether.ARP_TYPE ether.src = EthAddr(self.arp_table[self.routing_table[ destination_network]['RouterInterface']]) ether.dst = EthAddr('FF:FF:FF:FF:FF:FF') ether.payload = arp_request self.resend_packet(ether, output_port) if destination_ip in self.arp_table: etherFrame.src = EthAddr(self.arp_table[ self.routing_table[destination_network] ['RouterInterface']]) etherFrame.dst = EthAddr( self.arp_table[destination_ip]) self.resend_packet(etherFrame, output_port) # ICMP Destination Unreachable for non-routable networks else: log.debug('PACKET IS NOT ROUTABLE!') ethernet_frame = etherFrame ip_packet = etherFrame.payload icmp_request_packet = ip_packet.payload icmp_echo_reply_packet = icmp() icmp_echo_reply_packet.code = 0 icmp_echo_reply_packet.type = 3 icmp_echo_reply_packet.payload = icmp_request_packet.payload ip = ipv4() ip.srcip = ip_packet.dstip ip.dstip = ip_packet.srcip ip.protocol = ipv4.ICMP_PROTOCOL ip.payload = icmp_echo_reply_packet ether = ethernet() ether.type = ethernet.IP_TYPE ether.src = ethernet_frame.dst ether.dst = ethernet_frame.src ether.payload = ip self.resend_packet(ether, packet_in.in_port) log.debug("ICMP DESTINATION UNREACHABLE SENT")
def custom_switch(self, packet, packet_in): """ Implement switch-like behavior. """ self.mac_to_port[packet.src] = self.event_port ip = packet.find('ipv4') if self.is_router(): if isinstance(packet.next, arp): a = packet.next if packet.payload.opcode == arp.REQUEST: if not a.protosrc.inNetwork(self.network, netmask=24): log.debug("dropping ARP request from separate subnet") elif not a.protodst.inNetwork(self.network, netmask=24): 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 e = ethernet(type=packet.type, src=dpid_to_mac(self.dpid), dst=a.hwsrc) e.set_payload(r) log.debug( "ARP request to different network replying my IP") msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = self.event_port self.connection.send(msg) else: log.debug( "ARP Request from same network dropping packet") elif packet.payload.opcode == arp.REPLY: log.debug("arp reply arrived with %s > %s and my ip=%s" % (a.protosrc, a.protodst, self.ip)) # if a.protodst == self.ip: ##send all waiting packets to that mac address through the port for waiting_packet in self.arpBuffer[a.protosrc]: e = ethernet(type=ethernet.IP_TYPE, src=dpid_to_mac(self.dpid), dst=a.hwsrc) e.set_payload(waiting_packet.payload) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = self.event_port self.connection.send(msg) # self.resend_packet(waiting_packet,of.OFPP_IN_PORT) self.arpBuffer[a.protosrc] = [] elif ip is not None: if ip.csum == ip.checksum() and ip.iplen >= ipv4.MIN_LEN: pass else: print 'Garbled packet' return ip.ttl -= 1 if (ip.ttl <= 0): print 'TTL 0 throwing packet' # return #ICMP packet # Make the ping reply icm = icmp() icm.type = 11 icm.code = 0 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) return ip.csum = ip.checksum() ip_net = IPAddr(ip.dstip.toUnsigned() & ~((1 << (32 - 24)) - 1)) print ip_net if ip.dstip not in self.routeTable and ip_net not in self.routeTable and not ip.dstip.inNetwork( self.network, netmask=24): #send icmp unreachable # print self.routeTable log.debug("Unreacheable %s", (ip.dstip)) ##ICMP packet # Make the ping reply icm = icmp() icm.type = 3 icm.code = 0 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.payload = icm 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 = self.event_port self.connection.send(msg) elif ip.dstip.inNetwork( self.network, netmask=24) and ip.dstip not in self.routeTable: #ICMP host unreachable self.sendICMP(3, 1, ip, packet) else: if ip.dstip in self.routeTable: dpid = self.routeTable[ip.dstip] else: dpid = self.routeTable[ip_net] if dpid == 50: #host ip send ARP if not ip.dstip in self.arpBuffer: self.arpBuffer[ip.dstip] = [] self.arpBuffer[ip.dstip].append(packet) r = arp() r.hwsrc = self.mac r.hwdst = ETHER_BROADCAST r.opcode = arp.REQUEST r.protodst = ip.dstip r.protosrc = self.ip e = ethernet(type=ethernet.ARP_TYPE, src=dpid_to_mac(self.dpid), dst=ETHER_BROADCAST) e.set_payload(r) log.debug("ARP request to find host ") msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_FLOOD)) msg.in_port = self.event_port self.connection.send(msg) else: # print self.mac,self.mac_to_port if dpid_to_mac(dpid) in self.mac_to_port: self.resend_packet( packet.pack(), self.mac_to_port[dpid_to_mac(dpid)]) else: self.act_like_hub(packet, packet_in) else: # self.act_like_hub(packet,packet_in) self.addEntryOrFlood(packet, packet_in)
def _handle_PacketIn (self, event): """ Handles packet in messages from the switch. """ packet = event.parsed # This is the parsed packet data. if not packet.parsed: log.warning("Ignoring incomplete packet") return packet_in = event.ofp # The actual ofp_packet_in message. # Add the new MAC to mac_to_port table if str(packet.src) not in self.mac_to_port: log.debug("mac_to_port table was updated by mac: {} -> port: {}".format(packet.src, hwsrc)) self.mac_to_port[str(packet.src)] = packet_in.in_port # ARP if packet.type == ethernet.ARP_TYPE: log.debug("in _handle_PacketIn func: an ARP requeset received.") # send to it's function self.handle_ARP_requests(packet, packet_in) # Static Routing -> handle all ipv4 traffic that comes through the router # by forwarding it to the correct subnet. elif packet.type == ethernet.IP_TYPE: log.debug("in _handle_PacketIn func: an IPv4 packet received.") ppayload = packet.payload dst_ip = str(ppayload.dstip) routable, dst_network = isRoutable (dst_ip) if routable: # Check if our router's routing_table knows the dst_network # and the dst_ip is match to dst_network if self.routing_table[str(dst_network)]['interfaceAddr'] == dst_ip: if ip_packet.protocol == ipv4.ICMP_PROTOCOL: self.handle_ICMP_packets(packet, packet_in) else: # Route the packet to it's port output_port = self.routing_table[dst_network]['Port'] # ARP if host MAC Address is not present if dst_ip not in self.arp_table: # Push frame to buffer self.buffer[dst_ip] = {'IP_Packet': ppayload, 'DestinationNetwork': dst_network} # Construct ARP Packet arp_request = arp() # now set ARP structure fields arp_request.hwdst = EthAddr('00:00:00:00:00:00') RouterInterfaceAddr = self.routing_table[dst_network]['interfaceAddr'] arp_request.hwsrc = EthAddr(self.arp_table[RouterInterfaceAddr]) arp_request.protodst = IPAddr(dst_ip) arp_request.protosrc = IPAddr(self.routing_table[dst_network]['interfaceAddr']) arp_request.opcode = arp.REQUEST # make the new pavket to send newPacket = ethernet() # set it's fields newPacket.type = newPacket.ARP_TYPE newPacket.src = EthAddr(self.arp_table[RouterInterfaceAddr]) newPacket.dst = EthAddr('FF:FF:FF:FF:FF:FF') newPacket.payload = arp_request # send the packet self.resend_packet(newPacket, output_port) if dst_ip in self.arp_table: packet.src = EthAddr(self.arp_table[self.routing_table[dst_network]['interfaceAddr']]) packet.dst = EthAddr(self.arp_table[dst_ip]) self.resend_packet(packet, output_port) # message of ICMP destination unreachable else: ethernet_frame = packet ppacket = packet.payload icmp_request_packet = ppacket.payload # make an icmp packet icmp_echo_reply_packet = icmp() icmp_echo_reply_packet.code = 0 icmp_echo_reply_packet.type = 3 # (3 type number is for icmp destination unreachable) icmp_echo_reply_packet.payload = icmp_request_packet.payload # make ipv4 header ip = ipv4() # set it's fields ip.srcip = ppacket.dstip ip.dstip = ppacket.srcip ip.protocol = ipv4.ICMP_PROTOCOL ip.payload = icmp_echo_reply_packet # make the new packet to send newPacket = ethernet() # set it's fields newPacket.type = ethernet.IP_TYPE newPacket.src = ethernet_frame.dst newPacket.dst = ethernet_frame.src newPacket.payload = ip self.resend_packet(newPacket, packet_in.in_port) def isRoutable (dst_ip): """ Check if the destination ip address wanted in packet is in our routing table or not. """ for r in self.routing_table: dst_network = r if IPAddress(dst_ip) in IPNetwork(dst_network): log.debug("packet is routable!") return True, dst_network log.debug("packet is not routable!") return False, null
def handle_ipPacket(self,event): # handle broad cast ip also # print "IP packet Received at R"+str(event.dpid) packet=event.parsed if(packet is None): print "error" print event src_mac = packet.src dst_mac = packet.dst ipv4_packet = event.parsed.next if(ipv4_packet is None): print "error" print event # Do more processing of the IPv4 packet src_ip = ipv4_packet.srcip dst_ip = ipv4_packet.dstip global _hello_tos, _lsu_tos if ipv4_packet.tos == _hello_tos: print "HELLO at R"+str(event.dpid)+" from "+src_ip.toStr() self.neighbours[event.port]=src_ip self.times[event.port]=time.time() self.G.add_edge(self.IPAddr,src_ip) self.send_lsu() return if ipv4_packet.tos == _lsu_tos: if src_ip==self.IPAddr: return print "LSU at R"+str(event.dpid)+" from "+src_ip.toStr() self.times2[src_ip]=time.time() pl=ipv4_packet.next lst=pl.split(':')[:-1] if src_ip in self.seqnum.keys() and self.seqnum[src_ip]>=int(pl[0]): return self.seqnum[src_ip]=int(pl[0]) ed=[i for i in self.G.edges() if i[0]==src_ip] try: self.G.remove_edges_from(ed) except: pass for i in lst[1:]: self.G.add_edge(src_ip,IPAddr(i)) eth = ethernet() eth.src = self.EthAddr eth.set_payload(ipv4_packet) eth.type = ethernet.IP_TYPE msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_ALL)) self.connection.send(msg) return if dst_mac!=self.EthAddr and dst_mac!=EthAddr('ff:ff:ff:ff:ff:ff'): return if(not self.isValidIpPacket(event)): return if(dst_ip==self.IPAddr or dst_ip.toStr()=='255.255.255.255'): if(packet.payload.protocol==packet.payload.ICMP_PROTOCOL): self.handle_icmp(event) else: nxt=self.FindNextHopInterface(dst_ip.toStr()) if(nxt[0]==-1): # need to send an icmp packet # print "No Route to Host" # Create ARP reply icmp_rep = icmp() icmp_rep.type = 3 icmp_rep.code= nxt[2] icmp_rep.next=unreach() # icmp_rep.next.seq=packet.payload.next.next.seq # icmp_rep.next.id=packet.payload.next.next.id # icmp_rep.next.raw=packet.payload.next.next.raw # Show the client that it's actually the me rep=ipv4() rep.srcip=self.IPAddr rep.dstip=src_ip rep.next=icmp_rep rep.protocol=packet.payload.ICMP_PROTOCOL eth = ethernet() eth.dst = packet.src eth.src = self.EthAddr eth.set_payload(rep) eth.type = ethernet.IP_TYPE msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = event.port self.connection.send(msg) print "icmp reply DONE" else: NextHopIP=nxt[0] Interface=nxt[1][-1] payload=packet.payload.payload # payload of IP packet # create a empty IP packet ipv4_packet_out=ipv4_packet ipv4_packet_out.ttl=ipv4_packet_out.ttl-1 # Create the Ethernet packet eth = ethernet() eth.type = ethernet.IP_TYPE if IPAddr(NextHopIP) in self.arp_table: eth.dst = self.arp_table[IPAddr(NextHopIP)] eth.src = self.EthAddr eth.set_payload(ipv4_packet_out) # msg is the "packet out" message. Now giving this packet special properties msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = int(Interface))) msg.in_port = event.port self.connection.send(msg) else: arp_rep = arp() arp_rep.opcode = arp.REQUEST # Show the client that it's actually the me arp_rep.hwsrc = self.EthAddr arp_rep.hwdst = EthAddr('ff:ff:ff:ff:ff:ff') #arp_rep.hwdst = 'ff:ff:ff:ff:ff:ff' arp_rep.protosrc = self.IPAddr arp_rep.protodst = IPAddr(NextHopIP) # Create the Ethernet packet eth1 = ethernet() eth1.type = ethernet.ARP_TYPE eth1.dst = EthAddr('ff:ff:ff:ff:ff:ff') eth1.src = self.EthAddr eth1.set_payload(arp_rep) # Send the ARP reply to client # msg is the "packet out" message. Now giving this packet special properties msg = of.ofp_packet_out() msg.data = eth1.pack() msg.actions.append(of.ofp_action_output(port = int(Interface))) msg.in_port = event.port self.connection.send(msg) eth.src = self.EthAddr eth.set_payload(ipv4_packet_out) self.que.append((eth,int(Interface),event.port))
def handle_ipPacket(self,event): # handle broad cast ip also print "IP packet Received at R"+str(event.dpid) packet=event.parsed src_mac = packet.src dst_mac = packet.dst if dst_mac!=self.EthAddr and dst_mac!=EthAddr('ff:ff:ff:ff:ff:ff'): return if(not self.isValidIpPacket(event)): return ipv4_packet = event.parsed.find("ipv4") # Do more processing of the IPv4 packet src_ip = ipv4_packet.srcip dst_ip = ipv4_packet.dstip if(dst_ip==self.IPAddr or dst_ip.toStr()=='255.255.255.255'): print "My Packet accept at ",self.IPAddr print ipv4_packet if(packet.payload.protocol==packet.payload.ICMP_PROTOCOL): self.handle_icmp(event) else: nxt=self.FindNextHopInterface(dst_ip.toStr()) if(nxt[0]==-1): # need to send an icmp packet # print "No Route to Host" # Create ARP reply icmp_rep = icmp() icmp_rep.type = 3 icmp_rep.code= nxt[2] icmp_rep.next=unreach() # icmp_rep.next.seq=packet.payload.next.next.seq # icmp_rep.next.id=packet.payload.next.next.id # icmp_rep.next.raw=packet.payload.next.next.raw # Show the client that it's actually the me rep=ipv4() rep.srcip=self.IPAddr rep.dstip=src_ip rep.next=icmp_rep rep.protocol=packet.payload.ICMP_PROTOCOL eth = ethernet() eth.dst = packet.src eth.src = self.EthAddr eth.set_payload(rep) eth.type = ethernet.IP_TYPE msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = event.port self.connection.send(msg) print "icmp reply DONE" else: NextHopIP=nxt[0] Interface=nxt[1][-1] # payload=packet.payload.pa/yload # payload of IP packet # create a empty IP packet # ipv4_packet_out=ipv4_packet ipv4_packet.ttl=ipv4_packet.ttl-1 # Create the Ethernet packet eth = ethernet() eth.type = ethernet.IP_TYPE if IPAddr(NextHopIP) in self.arp_table: eth.dst = self.arp_table[IPAddr(NextHopIP)] eth.src = self.EthAddr eth.set_payload(ipv4_packet) # msg is the "packet out" message. Now giving this packet special properties msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = int(Interface))) msg.in_port = event.port self.connection.send(msg) else: arp_rep = arp() arp_rep.opcode = arp.REQUEST # Show the client that it's actually the me arp_rep.hwsrc = self.EthAddr arp_rep.hwdst = EthAddr('ff:ff:ff:ff:ff:ff') #arp_rep.hwdst = 'ff:ff:ff:ff:ff:ff' arp_rep.protosrc = self.IPAddr arp_rep.protodst = IPAddr(NextHopIP) # Create the Ethernet packet eth1 = ethernet() eth1.type = ethernet.ARP_TYPE eth1.dst = EthAddr('ff:ff:ff:ff:ff:ff') eth1.src = self.EthAddr eth1.set_payload(arp_rep) # Send the ARP reply to client # msg is the "packet out" message. Now giving this packet special properties msg = of.ofp_packet_out() msg.data = eth1.pack() msg.actions.append(of.ofp_action_output(port = int(Interface))) msg.in_port = event.port self.connection.send(msg) eth.src = self.EthAddr eth.set_payload(ipv4_packet_out) self.que.append((eth,int(Interface),event.port))