def sendPing (self, macEntry, ipAddr): """ Builds an ETH/IP any-to-any ARP packet (an "ARP ping") """ r = arp() r.opcode = arp.REQUEST r.hwdst = macEntry.macaddr r.hwsrc = self.ping_src_mac r.protodst = ipAddr # src is IP_ANY e = ethernet(type=ethernet.ARP_TYPE, src=r.hwsrc, dst=r.hwdst) e.payload = r log.debug("%i %i sending ARP REQ to %s %s", macEntry.dpid, macEntry.port, str(r.hwdst), str(r.protodst)) msg = of.ofp_packet_out(data = e.pack(), action = of.ofp_action_output(port=macEntry.port)) if core.openflow.sendToDPID(macEntry.dpid, msg.pack()): ipEntry = macEntry.ipAddrs[ipAddr] ipEntry.pings.sent() else: # macEntry is stale, remove it. log.debug("%i %i ERROR sending ARP REQ to %s %s", macEntry.dpid, macEntry.port, str(r.hwdst), str(r.protodst)) del macEntry.ipAddrs[ipAddr] return
def _do_probe (self): """ Send an ARP to a server to see if it's still up """ self._do_expire() server = self.servers.pop(0) self.servers.append(server) r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.opcode = r.REQUEST r.hwdst = ETHER_BROADCAST r.protodst = server r.hwsrc = self.mac r.protosrc = self.service_ip e = ethernet(type=ethernet.ARP_TYPE, src=self.mac, dst=ETHER_BROADCAST) e.set_payload(r) #self.log.debug("ARPing for %s", server) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) msg.in_port = of.OFPP_NONE self.con.send(msg) self.outstanding_probes[server] = time.time() + self.arp_timeout core.callDelayed(self._probe_wait_time, self._do_probe)
def create_discovery_packet(self, dpid, portNum, portAddr): """ Create LLDP packet """ discovery_packet = lldp() cid = chassis_id() # Maybe this should be a MAC. But a MAC of what? Local port, maybe? cid.fill(cid.SUB_LOCAL, bytes("dpid:" + hex(long(dpid))[2:-1])) discovery_packet.add_tlv(cid) pid = port_id() pid.fill(pid.SUB_PORT, str(portNum)) discovery_packet.add_tlv(pid) ttlv = ttl() ttlv.fill(LLDP_TTL) discovery_packet.add_tlv(ttlv) sysdesc = system_description() sysdesc.fill(bytes("dpid:" + hex(long(dpid))[2:-1])) discovery_packet.add_tlv(sysdesc) discovery_packet.add_tlv(end_tlv()) eth = ethernet() eth.src = portAddr eth.dst = NDP_MULTICAST eth.set_payload(discovery_packet) eth.type = ethernet.LLDP_TYPE po = of.ofp_packet_out(action=of.ofp_action_output(port=portNum), data=eth.pack()) return po.pack()
def _handle_PacketIn(self,event): eth_packetRecv = event.parsed if eth_packetRecv.type == ethernet.ARP_TYPE: #checking if the payload is ARP pkt msg = of.ofp_packet_out() msg.in_port = event.port arpreq = eth_packetRecv.payload # extract arp packet - arpreq # log.debug('%s arp table',ARPTable) if arpreq.protosrc not in ARPTable.keys(): #if no srcip entry in ARP table,add a new entry for scrip, srcmac ARPTable[arpreq.protosrc] = arpreq.hwsrc # print "in 1" if arpreq.protodst not in ARPTable.keys():#if no entry in the ARPtable , then flood the ARP packet as l2 bc eth_packetSent = eth_packetRecv msg.data = eth_packetSent.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) #flooding on all ports of the swtch elif arpreq.protodst in ARPTable.keys(): # if dstip in ARPTable,build appropriate ARP reply arpreply = self.buildReply(arpreq)#building the arp reply , eth_packetSent = ethernet(type = ethernet.ARP_TYPE,dst = arpreply.hwdst )#setting type of ethernet packet and src and dst mac addresses eth_packetSent.set_payload(arpreply) # the payload of the eth packet is the arp packet msg.data = eth_packetSent.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = event.port elif eth_packetRecv.type != ethernet.ARP_TYPE: # print "in switching..." msg = self.processPacket(event) # log.debug('mac addr table %s',self.macaddrtable) event.connection.send(msg)
def send_arpResponse(self, arp_req, event, packet, mac): ''' Send out an ARP response ''' # create the arp response packet arp_res = arp() arp_res.hwtype = arp_req.hwtype arp_res.prototype = arp_req.prototype arp_res.hwlen = arp_req.hwlen arp_res.protolen = arp_req.protolen arp_res.opcode = arp.REPLY arp_res.hwdst = arp_req.hwsrc arp_res.protodst = arp_req.protosrc arp_res.protosrc = arp_req.protodst arp_res.hwsrc = mac # create an ethernet package that contains the arp response we created above e = ethernet(type=packet.type, src=mac, dst=arp_req.hwsrc) e.set_payload(arp_res) log.debug("%i %i answering ARP for %s" % (event.connection.dpid, event.port, str(arp_res.protosrc))) # send the ARP response 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)
def f_arp_reply(self,arpp): #print "It's a arp request" ''' #print 'arpp.next=',arpp.next #print 'arpp.protosrc=',arpp.protosrc #print 'arpp.protodst=',arpp.protodst ''' dstIP = arpp.protodst.toStr() #print 'dstIP=',dstIP dstMac = self.f_get_arp_mac(dstIP) #print 'dstMac=', dstMac if dstMac != None: arp_reply = arp() arp_reply.opcode = arp.REPLY arp_reply.hwdst = arpp.hwsrc arp_reply.protodst = arpp.protosrc arp_reply.protosrc = arpp.protodst arp_reply.hwsrc = dstMac ether = ethernet() ether.type = ethernet.ARP_TYPE ether.src = dstMac ether.dst = arpp.hwsrc ether.payload = arp_reply #send this packet to the switch self.f_send_arp_reply_pkt(ether,self.packet_event.port) #''' else: '''Send Openflow arp flood via Openflow flood port NOT ethernet flood !!!!!!!!''' self.f_send_arp_openflow_flood()
def _handle_ConnectionUp(self, event): # fake mac id for service ip self.lb_mac = EthAddr("0A:00:00:00:00:01") self.connection = event.connection # pre emptively collecting the mac and port number of server IPs # by sending ARP request packets for ip in self.serverIp: # constructing ARP packet arpPacket = arp() arpPacket.opcode = arpPacket.REQUEST arpPacket.hwsrc = self.lb_mac arpPacket.hwdst = ETHER_BROADCAST arpPacket.protosrc = self.serviceIp arpPacket.protodst = ip # constructing ethernet packet with ARP as payload e = ethernet(type = ethernet.ARP_TYPE, src = self.connection.eth_addr, dst = ETHER_BROADCAST) e.set_payload(arpPacket) # constructing openflow out message msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) msg.in_port = of.OFPP_NONE # sending message self.connection.send(msg)
def arp_reply(arp_request): src_ip = arp_request.protosrc dst_ip = arp_request.protodst dst_mac = EthAddr(ip_mac[str(dst_ip)]) log.info("Faking ARP Reply") log.info('from ' + str(dst_ip) + ' to ' + str(src_ip)) reply = arp() reply.opcode = arp.REPLY reply.hwtype = arp_request.hwtype reply.prototype = arp_request.prototype reply.hwlen = arp_request.hwlen reply.protolen = arp_request.protolen reply.hwsrc = dst_mac reply.hwdst = arp_request.hwsrc reply.protosrc = dst_ip reply.protodst = src_ip ether = ethernet() ether.type = ethernet.ARP_TYPE ether.dst = packet.src ether.src = dst_mac ether.set_payload(reply) msg = of.ofp_packet_out() msg.data = ether.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = event.port event.connection.send(msg)
def sendPing (self, macEntry, ipAddr): """ Builds an ETH/IP any-to-any ARP packet (an "ARP ping") """ r = arp() r.opcode = arp.REQUEST r.hwdst = macEntry.macaddr r.hwsrc = self.ping_src_mac r.protodst = ipAddr # src is IP_ANY e = ethernet(type=ethernet.ARP_TYPE, src=r.hwsrc, dst=r.hwdst) e.payload = r #custom code start the_file.write("Time: " + time.asctime(time.localtime(time.time())) + "\n") the_file.write("ARP Request:\n") the_file.write("Src MAC:" + str(self.ping_src_mac)) the_file.write("Dest MAC:" + str(macEntry.macaddr)) the_file.write("Dest IP:" + str(ipAddr)) #custom code start log.debug("%i %i sending ARP REQ to %s %s", macEntry.dpid, macEntry.port, str(r.hwdst), str(r.protodst)) msg = of.ofp_packet_out(data = e.pack(), action = of.ofp_action_output(port=macEntry.port)) if core.openflow.sendToDPID(macEntry.dpid, msg.pack()): ipEntry = macEntry.ipAddrs[ipAddr] ipEntry.pings.sent() else: # macEntry is stale, remove it. log.debug("%i %i ERROR sending ARP REQ to %s %s", macEntry.dpid, macEntry.port, str(r.hwdst), str(r.protodst)) del macEntry.ipAddrs[ipAddr] return
def create_eth_packet(src, dst, payload): ether = ethernet() ether.type = pkt.ethernet.ARP_TYPE ether.dst = dst ether.src = src ether.payload = payload return ether
def _arp_for_real_servers (): for rs in [server for server in _real_servers if server not in _arp_table]: log.debug("ARPing in UpEvent for real server %s", str(rs)) q = arp() q.opcode = arp.REQUEST q.protodst = rs con = None for con in core.openflow.connections: if con is not None: break else: log.info("can't get any connection") return True e = ethernet(type=ethernet.ARP_TYPE, dst=ETHER_BROADCAST) e.payload = q log.debug("%s ARPing in UpEvent for real server %s", dpid_to_str(con.dpid), str(rs)) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) # FIXME assume port number starts from 1 # There will be a problem if port 1 is the # only port that will join flooding (spanning_tree) msg.in_port = 1 con.send(msg) res = False for server in _real_servers: if server not in _arp_table: res = True break return res
def _router_handle_arp(self, event): arpPacket = event.parsed.next ingressPort = self.getPort(event.port) if arpPacket.opcode == arp.REQUEST and \ arpPacket.protodst == ingressPort.ip: r = arp() r.opcode = arp.REPLY r.hwdst = arpPacket.hwsrc r.hwsrc = ingressPort.mac r.protodst = arpPacket.protosrc r.protosrc = arpPacket.protodst e = ethernet(type = ethernet.ARP_TYPE, src = ingressPort.mac, dst = arpPacket.hwsrc) e.set_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) elif arpPacket.opcode == arp.REPLY: ip = IPAddr(arpPacket.protosrc) mac = EthAddr(arpPacket.hwsrc) self.arp[ip] = EthAddr(mac) self._tryPurgeQueue() self.installRouteEntry(ip, event.port, mac) else: self._drop(event)
def handle_arp (self, packet, in_port): # function No.2 # Get the ARP request from packet arp_req = packet.next # Create ARP reply arp_rep = arp() arp_rep.opcode = arp.REPLY arp_rep.hwsrc = LOAD_BALANCER_MAC # hardware source arp_rep.hwdst = arp_req.hwsrc # hardware destination arp_rep.protosrc = LOAD_BALANCER_IP # software source arp_rep.protodst = arp_req.protosrc # software destination # Create the Ethernet packet eth = ethernet() eth.type = ethernet.ARP_TYPE eth.dst = packet.src eth.src = LOAD_BALANCER_MAC eth.set_payload(arp_rep) # Send the ARP reply to client msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = in_port self.connection.send(msg)
def send_arp_reply (reply_to, mac, src_mac = None, src_ip = None): """ Send an ARP reply. src_mac can be None to use the "DPID MAC" or True to use the port Mac. (or it can be an EthAddr) """ # reply_to should be a PacketIn event arpp = reply_to.parsed.find('arp') mac = EthAddr(mac) if src_mac is None: #src_mac = mac # Used to be this ??? src_mac = reply_to.connection.eth_addr elif src_mac is True: src_mac = reply_to.connection.ports[reply_to.port].hw_addr else: src_mac = EthAddr(src_mac) r = arp() r.opcode = r.REPLY r.hwdst = arpp.hwsrc r.protodst = arpp.protosrc r.hwsrc = EthAddr(src_mac) r.protosrc = IPAddr("0.0.0.0") if src_ip is None else IPAddr(src_ip) e = ethernet(type=ethernet.ARP_TYPE, src=src_mac, dst=r.hwdst) e.payload = r msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = reply_to.port)) msg.in_port = of.OFPP_NONE reply_to.connection.send(msg)
def reply_to_arp(self, event, match): dpid = event.connection.dpid inport = event.port packet = event.parsed #print "reply to ARP request", match.dl_dst r = arp() r.opcode = arp.REPLY r.hwdst = match.dl_src if (self.addr_is_gw(dpid, match.nw_dst.toStr())): r.protosrc = match.nw_dst mac_addr=self.find_mac_addr(dpid, inport) #print "mac_addr=", mac_addr r.hwsrc = addresses.EthAddr(mac_addr) r.protodst = match.nw_src e = ethernet(type=packet.ARP_TYPE, src=r.hwsrc, dst=r.hwdst) e.set_payload(r) log.debug("%i %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
def handleARPmessages (self, packet, event): in_port = event.port # Get the ARP request from packet arp_req = packet.next # Create ARP reply arp_rep = arp() arp_rep.opcode = arp.REPLY arp_rep.hwsrc = WEB_SERVER_MAC arp_rep.hwdst = arp_req.hwsrc arp_rep.protosrc = WEB_SERVER_IP arp_rep.protodst = arp_req.protosrc # Create the Ethernet packet eth = ethernet() eth.type = ethernet.ARP_TYPE eth.dst = packet.src eth.src = WEB_SERVER_MAC eth.set_payload(arp_rep) # Send the ARP reply to client msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = in_port self.connection.send(msg) pass
def cheat(self,event,dpid): inport = event.port packet = event.parsed a=packet.next print a.protodst if a.protodst == "10.10.1.0": print "pretend arp" 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 = EthAddr("BC:AE:C5:43:58:DC") e = ethernet(type=packet.type, src=r.hwsrc, dst=r.hwdst) e.set_payload(r) log.debug("%i %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
def sendHello(self,entry): inf = entry[0] srcip = entry[1] port = self.intf2Port[inf] mac = self.port2Mac[port] pwospf_hello = pwospf() pwospf_hello.rid = self.rid pwospf_hello.type = pwospf.TYPE_HELLO pwospf_hello.helloint = self.helloint << 16 pwospf_hello.netmask = IPAddr("255.255.255.0").toUnsigned() ipp = pkt.ipv4() ipp.protocol = ipv4.PWOSPF_PROTOCOL ipp.srcip = IPAddr(srcip) ipp.dstip = IPAddr(ALLSPFRouters) ipp.payload = pwospf_hello ether = ethernet() ether.type = ethernet.IP_TYPE ether.src = mac ether.dst = ETHER_BROADCAST ether.payload = ipp msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = port)) msg.data = ether.pack() self.connection.send(msg)
def arpReply(self, packet, event, additive = 0): if packet.payload.opcode == arp.REQUEST: arp_reply = arp() if additive == 0: arp_reply.hwsrc = EthAddr('fa-31-11-11-11-11') elif additive == 1: arp_reply.hwsrc = EthAddr('fa-31-11-11-11-12') arp_reply.hwdst = packet.src arp_reply.opcode = arp.REPLY arp_reply.protosrc = packet.payload.protodst arp_reply.protodst = packet.payload.protosrc ether = ethernet() ether.type = ethernet.ARP_TYPE ether.dst = packet.src ether.src = arp_reply.hwsrc ether.payload = arp_reply #send this packet to the switch #see section below on this topic msg = of.ofp_packet_out(in_port=event.port) msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.data = ether self.connection.send(msg) log.debug('Replying ARP request for %s.', str(arp_reply.protosrc))
def send_arp_request(self, event, route, packet, match, nextHopIp): if nextHopIp in self.outstandingarp and time.time() > self.outstandingarp[nextHopIp] + self.ARP_TIMEOUT: return self.outstandingarp[nextHopIp] = time.time() r = pkt.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 = nextHopIp r.hwsrc = self.port2Mac[self.intf2Port[route.intf]] r.protosrc = IPAddr(ROUTERS_IPS[route.intf]) #r.protodst = packet.next.dstip e = ethernet(type=ethernet.ARP_TYPE, src=r.hwsrc, dst=r.hwdst) e.set_payload(r) log.debug("%s ARPing for %s on behalf of %s" % (route.intf, 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.actions.append(of.ofp_action_output(port = self.intf2Port[route.intf])) msg.in_port = event.port event.connection.send(msg)
def sendLSU(self,seq,srcip,dstip): print "Sending LSU Packets: ",self.name pwospf_hello = pwospf() pwospf_hello.rid = self.rid pwospf_hello.type = pwospf.TYPE_LSU pwospf_hello.seq = seq pwospf_hello.nadv = len(self.adjList[self.rid].items()) for ne in self.adjList[self.rid].items(): print ne.subnet pwospf_hello.advList.append(IPAddr(ne.subnet).toUnsigned()) pwospf_hello.advList.append(IPAddr(ne.netmask).toUnsigned()) pwospf_hello.advList.append(ne.rid) ipp = pkt.ipv4() ipp.protocol = ipv4.PWOSPF_PROTOCOL ipp.srcip = IPAddr(srcip) ipp.dstip = IPAddr(dstip) ipp.payload = pwospf_hello ether = ethernet() ether.type = ethernet.IP_TYPE ether.payload = ipp self.send_ipv4_packet(ether)
def _handle_ConnectionUp(self, event): #new switch connection self.lb_mac = EthAddr("0A:00:00:00:00:01") #fake mac of load balancer self.connection = event.connection #write your code here!!! ##Send initial ARP request to the servers for i in self.server_ips: r = arp() r.hwtype=1 r.prototype=0x0800 r.hwlen=6 r.opcode = arp.REQUEST r.hwsrc = self.lb_mac r.protosrc=self.service_ip r.protodst=i r.hwdst = EthAddr("00:00:00:00:00:00") # print "APR Message: "+ str(r) e = ethernet(type=0x0806,src=self.lb_mac,dst=EthAddr("FF:FF:FF:FF:FF:FF")) e.set_payload(r) # print "Ethernet Frame: "+ str(e) #""" msg = of.ofp_packet_out() msg.data=e.pack() msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) msg.in_port=of.OFPP_NONE self.connection.send(msg)
def sendPing(cls, macEntry, ipAddr): """ send Ping msg to switch. """ req = arp() # Builds an "ETH/IP any-to-any ARP packet req.opcode = arp.REQUEST req.hwdst = macEntry.macaddr req.protodst = ipAddr # src is ETHER_ANY, IP_ANY eth = ethernet(type=ethernet.ARP_TYPE, src=req.hwsrc, dst=req.hwdst) eth.set_payload(req) log.debug("%i %i sending ARP REQ to %s %s", macEntry.dpid, macEntry.port, str(req.hwdst), str(req.protodst)) msg = of.ofp_packet_out(data = eth.pack(), action = of.ofp_action_output(port = macEntry.port)) if core.openflow.sendToDPID(macEntry.dpid, msg.pack()): ipEntry = macEntry.ipAddrs[ipAddr] ipEntry.pings.sent() else: # macEntry is stale, remove it. log.debug("%i %i ERROR sending ARP REQ to %s %s", macEntry.dpid, macEntry.port, str(req.hwdst), str(req.protodst)) del macEntry.ipAddrs[ipAddr] return
def handle_arp(self, packet, packet_in): self.network.lock.acquire() port = self.network.routers[self.connection.dpid].ports[packet_in.in_port] log.debug("GOT ARP packet at router {}, type: {}; in port_mac {}; from hwsrc {}; to hwdst: {};".format(self.connection.dpid, packet.payload.opcode, port.mac, str(packet.payload.hwsrc), str(packet.payload.hwdst))) if packet.payload.opcode == arp.REQUEST and port.ip == str(packet.payload.protodst): my_arp = arp() my_arp.opcode = arp.REPLY my_arp.protosrc = IPAddr(port.ip) my_arp.protodst = packet.payload.protosrc my_arp.hwdst = packet.payload.hwsrc my_arp.hwsrc = EthAddr(port.mac) my_ether = ethernet() my_ether.type = ethernet.ARP_TYPE my_ether.dst = packet.payload.hwsrc my_ether.src = EthAddr(port.mac) my_ether.payload = my_arp log.debug("Sending ARP REPLY at router {}, to dest_ip {}; to port {};".format(self.connection.dpid, str(packet.payload.protosrc), port.id)) self.send_packet(None, my_ether, packet_in.in_port, of.OFPP_NONE) elif packet.payload.opcode is arp.REPLY and port.mac == str(packet.payload.hwdst): log.debug("GOT ARP REPLY at router {}; from src_mac {}; src_ip {}; input_port {}".format(self.connection.dpid, str(packet.payload.hwsrc),packet.payload.protosrc, packet_in.in_port)) if str(packet.payload.protosrc) in self.waiting_arp_requests: self.arp_cache[str(packet.payload.protosrc)] = (packet.payload.hwsrc, time.time()) self.network.lock.release() self.handle_ip(self.waiting_arp_requests[str(packet.payload.protosrc)][0], self.waiting_arp_requests[str(packet.payload.protosrc)][1]) self.network.lock.acquire() del self.waiting_arp_requests[str(packet.payload.protosrc)] self.network.lock.release()
def sendRequestIdentity(self, macaddr_dst, port_switch_dst): """ Send EAP-REQUEST-IDENTITY to host Use to initialize EAP-session by switch Start EAP-SESSION after EAPOL-START """ macaddr_dst = checkMac(macaddr_dst) port_switch_dst = checkInt(port_switch_dst) #Requete EAPOL/EAP forgee eap_pckt = eap(code=1, type_name=1, id=1) eap_pckt.type = 1 eapol_pckt= eapol(version=2, type=0) eapol_pckt.next = eap_pckt self.host_progress[macaddr_dst]['eap-id']=eapol_pckt.next.getID() switch = self.host_progress[macaddr_dst]['switch'] e= ethernet(type= 0x888e, src = EthAddr(switch), dst = macaddr_dst) e.set_payload(eapol_pckt) #Envoie du paquet EAPOL/EAP msg= of.ofp_packet_out() msg.data = e.pack() action=of.ofp_action_output( port=of.OFPP_IN_PORT ) msg.actions.append(action) msg.in_port= port_switch_dst self.connection.send(msg) log.debug("envoi REQUEST IDENTITY a %s sur le port %s" %(macaddr_dst, port_switch_dst))
def handle_arp (self, packet, in_port): print "ARP Packet Arrived" # Get the ARP request from packet arp_req = packet.next # Create ARP reply arp_rep = arp() arp_rep.opcode = arp.REPLY # Show the client that it's actually the "main" server arp_rep.hwsrc = LOAD_BALANCER_MAC arp_rep.hwdst = arp_req.hwsrc arp_rep.protosrc = LOAD_BALANCER_IP arp_rep.protodst = arp_req.protosrc # Create the Ethernet packet eth = ethernet() eth.type = ethernet.ARP_TYPE eth.dst = packet.src eth.src = LOAD_BALANCER_MAC eth.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 = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = in_port self.connection.send(msg)
def _process_raw_socket_read(io_worker): # N.B. raw sockets return exactly one ethernet frame for every read(). data = io_worker.peek_receive_buf() packet = ethernet(bytes(data)) io_worker.consume_receive_buf(len(data)) if log.isEnabledFor(logging.DEBUG): log.debug("Dequeing packet %s, port %s" % (packet, port)) switch.process_packet(packet, port.port_no)
def _send_ethernet_packet(self, packet_type, _src, _dst, payload, out_port): e = ethernet(type=packet_type, src=_src, dst=_dst) e.set_payload(payload) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = out_port)) msg.in_port = of.OFPP_NONE self.connection.send(msg)
def _handle_PacketIn (self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed a = packet.find('arp') if not a: return if a.prototype != arp.PROTO_TYPE_IP: return if a.hwtype != arp.HW_TYPE_ETHERNET: return if a.opcode == arp.REQUEST: log.debug("%s ARP request %s => %s", dpid_to_str(dpid), a.protosrc, a.protodst) if self.use_port_mac: src_mac = event.connection.ports[inport].hw_addr else: src_mac = event.connection.eth_addr ev = ARPRequest(event.connection, a, src_mac, self.eat_packets, inport) self.raiseEvent(ev) if ev.reply is not None: 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 = EthAddr(ev.reply) e = ethernet(type=packet.type, src=ev.reply_from, dst=a.hwsrc) e.payload = r log.debug("%s answering ARP for %s" % (dpid_to_str(dpid), 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 EventHalt if ev.eat_packet else None elif a.opcode == arp.REPLY: log.debug("%s ARP reply %s => %s", dpid_to_str(dpid), a.protosrc, a.hwsrc) ev = ARPReply(event.connection,a,self.eat_packets,inport) self.raiseEvent(ev) return EventHalt if ev.eat_packet else None return EventHalt if self.eat_packets else None
def _handle_PacketIn(self,event): packet = event.parsed Switch_Output[event.dpid][packet.src]=event.port if packet.find("arp"): arp_packet=packet.find("arp") IP_To_MAC[arp_packet.protosrc]=packet.src if arp_packet.opcode==arp.REQUEST: if arp_packet.protodst in IP_To_MAC: #reply #construct arp reply packet arp_reply=arp() arp_reply.hwsrc=IP_To_MAC[arp_packet.protodst] arp_reply.hwdst=packet.src arp_reply.opcode=arp.REPLY arp_reply.protosrc=arp_packet.protodst arp_reply.protodst=arp_packet.protosrc ether=ethernet() ether.type=ethernet.ARP_TYPE ether.dst=packet.src ether.src=IP_To_MAC[arp_packet.protodst] ether.payload=arp_reply # send the created arp reply back to switch msg=of.ofp_packet_out() msg.data=ether.pack() msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port=event.port event.connection.send(msg) elif (arp_packet.protosrc,arp_packet.protodst) not in Switch_AntiFlood[event.dpid]: #flood msg=of.ofp_packet_out(data=event.data) msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) msg.in_port=event.port event.connection.send(msg) # Switch_AntiFlood[event.dpid].append((arp_reply.protosrc,arp_packet.protodst) ) # if packet.find('ipv4'): # ip_packet=packet.find('ipv4') # IP_To_MAC[ip_packet.dstip]=packet.dst # IP_To_MAC[ip_packet.srcip]=packet.src if packet.dst in Switch_Output[event.dpid] : msg=of.ofp_packet_out(data=event.ofp) msg.actions.append(of.ofp_action_output(port=Switch_Output[event.dpid][packet.dst])) msg.in_port=event.port event.connection.send(msg) Install_Flow(event,packet.src,packet.dst,Switch_Output[event.dpid][packet.dst]) Install_Flow(event,packet.dst,packet.src,Switch_Output[event.dpid][packet.src]) print event.dpid,'packet_in:',packet print 'out_put:',Switch_Output print 'IP_MAC',IP_To_MAC print 'Anti',Switch_AntiFlood print
def _handle_openflow_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed global set_Timer global defendDDOS global blockPort timerSet = False global diction def preventing(): global diction global set_Timer if not set_Timer: set_Timer = True #Timer(1, _timer_func(), recurring=True) #print"\n\n*********new packetIN************" if len(diction) == 0: print("Enpty diction ", str(event.connection.dpid), str(event.port)) diction[event.connection.dpid] = {} diction[event.connection.dpid][event.port] = 1 elif event.connection.dpid not in diction: diction[event.connection.dpid] = {} diction[event.connection.dpid][event.port] = 1 #print "ERROR" else: if event.connection.dpid in diction: # temp = diction[event.connection.dpid] #print(temp) #print "error check " , str(diction[event.connection.dpid][event.port]) if event.port in diction[event.connection.dpid]: temp_count = 0 temp_count = diction[event.connection.dpid][event.port] temp_count = temp_count + 1 diction[event.connection.dpid][event.port] = temp_count #print "printting dpid port number and its packet count: ", str(event.connection.dpid), str(diction[event.connection.dpid]), str(diction[event.connection.dpid][event.port]) else: diction[event.connection.dpid][event.port] = 1 print " switch id: ", str(event.connection.dpid) print " port number: ", str(event.port) print " packet count:", str( diction[event.connection.dpid][event.port]), "\n" def _timer_func(): global diction global set_Timer if set_Timer == True: #print datetime.datetime.now(),": calling timer fucntion now!!!!!" for k, v in diction.iteritems(): for i, j in v.iteritems(): if j >= 50: print "_____________________________________________________________________________________________" print "\n", datetime.datetime.now( ), "** DDOS ATTACK DETECTED **" print "\n", str(diction) print "\n", datetime.datetime.now( ), ": BLOCKED PORT NUMBER : ", str( i), " OF SWITCH ID: ", str(k) print "\n_____________________________________________________________________________________________" #self.dropDDOS () dpid = k msg = of.ofp_packet_out(in_port=i) #msg.priority=42 #msg.in_port = event.port #po = of.ofp_packet_out(buffer_id = buffer_id, in_port = in_port) core.openflow.sendToDPID(dpid, msg) diction = {} 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) ent_obj.statcolect(event.parsed.next.dstip) print "\n-Entropy = ", str(ent_obj.value), "" if ent_obj.value < 0.5: preventing() if timerSet is not True: Timer(2, _timer_func, recurring=True) timerSet = False else: timerSet = False # 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) #nandan: getting source ip address from the packetIn #myPacketInSrcIP= packet.next.srcip #myPacketInSrcEth= packet.src #myPacketInDstIP= packet.next.dstip #myPacketInDstEth= packet.dst #print "switcID: "+str(dpid)+" ,Port: "+str(event.port)+" ,MAC address: "+str(myPacketInSrcEth)+" ,SrcIP: "+ str(myPacketInSrcIP)+", Dst Mac: "+str(myPacketInDstEth)+", Dst IP: "+str(myPacketInDstEth) # Try to forward dstaddr = packet.next.dstip 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( "%i %i not sending packet for %s back out of the " "input port" % (dpid, inport, dstaddr)) else: log.debug( "%i %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)) if self.wide: match = of.ofp_match(dl_type=packet.type, nw_dst=dstaddr) else: match = of.ofp_match.from_packet(packet, inport) 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=match) event.connection.send(msg.pack()) 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.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, a.protosrc) 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.dl_type = ethernet.IP_TYPE msg.match.nw_dst = a.protosrc event.connection.send(msg) else: log.debug("%i %i learned %s", dpid, inport, 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 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 = 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" % (dpid, inport, 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("%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 handle_arp(self, event): packet = event.parsed if packet.payload.opcode == arp.REQUEST: print "Received ARP Request (for, from, at) ", packet.payload.protodst, packet.payload.protosrc, event.dpid if str(packet.payload.protosrc)[-1:] == '1': if self.ip != packet.payload.protodst: return # hop = self.forwardTable.findNextHop(packet.payload.protodst,event) # if hop is None: # return # if str(packet.payload.protosrc)==hop: # return # print "I am next hop (me,next hop from me)",self.ip,hop # print "REQCurrent Table", self.ipToPort # hop = self.forwardTable.findNextHop(packet.payload.protodst,event) # if hop == '': # print "Found Nothing Router",event.dpid # return # print "REQFound Next Hop ", hop # print "REQCreating Reply" arp_reply = arp() arp_reply.hwsrc = self.mac arp_reply.hwdst = packet.src arp_reply.opcode = arp.REPLY self.ipToPort[str(packet.payload.protosrc)] = event.port self.ipToMac[str(packet.payload.protosrc)] = packet.payload.hwsrc arp_reply.protosrc = packet.payload.protodst arp_reply.protodst = packet.payload.protosrc ether = ethernet() ether.type = ethernet.ARP_TYPE ether.dst = packet.src ether.src = self.mac ether.payload = arp_reply msg = of.ofp_packet_out() msg.data = ether.pack() msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = event.port event.connection.send(msg) elif packet.payload.opcode == arp.REPLY: print "Received ARP REPLY from (dest router) :", packet.payload.protosrc arp_reply = packet.payload self.ipToPort[str(arp_reply.protosrc)] = event.port self.ipToMac[str(arp_reply.protosrc)] = arp_reply.hwsrc print "Saving Mapping for (mappedIp, mappedPort, at ) :", arp_reply.protosrc, event.port, event.dpid print self.ipToPort print "Resending buffered packets ... at Router", event.dpid # print self.packetQueue[str(arp_reply.protosrc)] if str(arp_reply.protosrc) not in self.packetQueue.keys(): return for pac in self.packetQueue[str(arp_reply.protosrc)]: print "Packet - ", str(pac.find('icmp')), arp_reply.hwsrc msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=event.port)) pac.src = self.mac pac.dst = arp_reply.hwsrc msg.data = pac.pack() # msg.in_port = event.port event.connection.send(msg) self.packetQueue[str(arp_reply.protosrc)] = [] else: print "Some other ARP opcode, probably do something smart here"
def _handle_PacketIn(self, event): # Note: arp.hwsrc is not necessarily equal to ethernet.src # (one such example are arp replies generated by this module itself # as ethernet mac is set to switch dpid) so we should be careful # to use only arp addresses in the learning code! squelch = False dpid = event.connection.dpid inport = event.port packet = event.parsed if not packet.parsed: log.warning("%s: ignoring unparsed packet", dpid_to_str(dpid)) return a = packet.find('arp') if not a: return log.debug("%s ARP %s %s => %s", dpid_to_str(dpid), { 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: if _learn: # Learn or update port/MAC info old_entry = _arp_table.get(a.protosrc) if old_entry is None: log.info("%s learned %s", dpid_to_str(dpid), a.protosrc) _arp_table[a.protosrc] = Entry(a.hwsrc) else: if old_entry.mac is True: # We never replace these special cases. # Might want to warn on conflict? pass elif old_entry.mac != a.hwsrc: if old_entry.static: log.warn( "%s static entry conflict %s: %s->%s", dpid_to_str(dpid), a.protosrc, old_entry.mac, a.hwsrc) else: log.warn("%s RE-learned %s: %s->%s", dpid_to_str(dpid), a.protosrc, old_entry.mac, a.hwsrc) _arp_table[a.protosrc] = Entry(a.hwsrc) else: # Update timestamp _arp_table[a.protosrc] = Entry(a.hwsrc) if a.opcode == arp.REQUEST: # Maybe we can answer if a.protodst in _arp_table: # 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 mac = _arp_table[a.protodst].mac if mac is True: # Special case -- use ourself mac = event.connection.eth_addr r.hwsrc = mac e = ethernet(type=packet.type, src=event.connection.eth_addr, dst=a.hwsrc) e.payload = r if packet.type == ethernet.VLAN_TYPE: v_rcv = packet.find('vlan') e.payload = vlan(eth_type=e.type, payload=e.payload, id=v_rcv.id, pcp=v_rcv.pcp) e.type = ethernet.VLAN_TYPE log.info("%s answering ARP for %s" % (dpid_to_str(dpid), 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 EventHalt if _eat_packets else None else: # Keep track of failed queries squelch = a.protodst in _failed_queries _failed_queries[a.protodst] = time.time() if self._check_for_flood(dpid, a): # Didn't know how to handle this ARP, so just flood it msg = "%s flooding ARP %s %s => %s" % (dpid_to_str(dpid), { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, a.protodst) if squelch: log.debug(msg) else: log.info(msg) msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) msg.data = event.ofp event.connection.send(msg.pack()) return EventHalt if _eat_packets else None
def _handle_PacketIn(self, event): """ Packets not handled by the router rules will be forwarded to this method to be handled by the controller """ 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. # handle ip and arp down here #print "handling packet", packet match = of.ofp_match.from_packet(packet) matchip = of.ofp_match.from_packet(packet) if (packet.type == ethernet.IP_TYPE ): #and matchip.dl_src == EthAddr("00:00:00:00:00:07")) : #r = ipv4() #r.hwsrc = EthAddr("00:00:00:00:00:07") #r.hwdst = EthAddr(IPREST[str(packet.payload.dstip)][0]) #r.srcip = IPAddr(IPROUTER[str(packet.payload.dstip)]) #r.srcip = packet.payload.srcip #r.dstip = packet.payload.dstip #packet.src = EthAddr("00:00:00:00:00:07") #packet.dst = EthAddr(IPREST[str(packet.payload.dstip)][0])) #msg = of.ofp_packet_out() #msg.data = packet #msg.actions.append(of.ofp_action_output(port = IPREST[str(packet.payload.dstip)][1])) #self.connection.send(packet) #print "mac src", EthAddr("00:00:00:00:00:07") #print "mac dst", EthAddr(IPREST[str(packet.payload.dstip)][0]) #packet.payload.srcip = IPAddr(IPROUTER[str(packet.payload.srcip)]) #print "ip src", packet.payload.srcip #print "ip dst", packet.payload.dstip e = ethernet(type=packet.IP_TYPE, src=EthAddr("00:00:00:00:00:07"), dst=EthAddr(IPREST[str(packet.payload.dstip)][0])) e.set_payload(packet.payload) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output( port=IPREST[str(packet.payload.dstip)][1])) #print "port" , IPREST[str(packet.payload.dstip)][1] msg.in_port = event.port event.connection.send(msg) elif (match.dl_type == packet.ARP_TYPE and match.nw_proto == arp.REQUEST): #print "generating response" reply = arp() reply.opcode = arp.REPLY reply.hwdst = packet.src #match.dl_src #print "dl_dst", #match.dl_dst #print "protosrc" , packet.payload.protosrc #print "ip router", IPROUTER[str(packet.payload.protosrc)] reply.protosrc = IPAddr(IPROUTER[str( packet.payload.protosrc)]) #IPAddr("10.0.1.1") reply.protodst = packet.payload.protosrc #match.nw_src reply.hwsrc = EthAddr("00:00:00:00:00:07") e = ethernet(type=packet.ARP_TYPE, src=reply.hwsrc, dst=reply.hwdst) e.set_payload(reply) msg = of.ofp_packet_out() msg.data = e.pack() #print "msg", msg msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) #print "out port", msg.in_port = event.port event.connection.send(msg)
# Create the vlan packet = V vlan_packet = vlan() vlan_packet.id = vlan_id vlan_packet.pcp = 0 vlan_packet.eth_type = ethernet_packet.type V = vlan_packet.hdr('') # Grab the rest of the packet = R R = ethernet_packet.raw[ethernet.MIN_LEN:] # Construct E + V + R new_raw = E + V + R new_ethernet_packet = ethernet(new_raw) return new_ethernet_packet if __name__ == "__main__": eth = ethernet() eth.dst = EthAddr("01:02:03:04:05:06") eth.src = EthAddr("11:12:13:14:15:16") eth.type = ethernet.IP_TYPE ip = ipv4() ip.srcip = IPAddr("128.99.98.97") ip.dstip = IPAddr("128.89.8.87") joint_eth = ethernet(eth.hdr('') + ip.hdr('')) print "JOINT = " + str(joint_eth) print "IP = " + str(ipv4(joint_eth.raw[ethernet.MIN_LEN:])) joint_eth_vlan = add_vlan_to_packet(joint_eth, 1000) print "JOINT_V = " + str(joint_eth_vlan) print "V = " + str(vlan(joint_eth_vlan.raw[ethernet.MIN_LEN:])) print "IP = " + str(ipv4(joint_eth_vlan.raw[ethernet.MIN_LEN+vlan.MIN_LEN:]))
def _handle_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed a = packet.find('arp') if not a: return arp_type = { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )) log_str = "%s ARP %s %s => %s" % (dpid_to_str(dpid), arp_type, str(a.protosrc), str(a.protodst)) if arp_type == 'reply': log.debug(log_str) else: log.info(log_str) eat = False dst_mac = None dst_dpid = None dst_node, dst_port = core.Outband.t.ip_and_port(a.protodst) if dst_node is None: eat = True else: dst_dpid = dst_node.dpid if dst_dpid is None: eat = True else: dst_mac = dst_port.mac if dst_mac is None: eat = True if (not eat) and (a.prototype == arp.PROTO_TYPE_IP): if a.hwtype == arp.HW_TYPE_ETHERNET: if a.protosrc != 0: if a.opcode == arp.REQUEST: # we can answer everything 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 = ETHER_BROADCAST r.hwsrc = dst_mac e = ethernet(type=ethernet.ARP_TYPE, src=self._dpid_to_mac(dpid), dst=a.hwsrc) e.payload = r if packet.type == ethernet.VLAN_TYPE: v_rcv = packet.find('vlan') e.next = vlan(eth_type=e.type, next=e.payload, id=v_rcv.id, pcp=v_rcv.pcp) e.type = ethernet.VLAN_TYPE log.info("%s answering ARP for %s" % (dpid_to_str(dpid), 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 # EventHalt # Didn't know how to handle this ARP, so just ignoring it msg = "%s ignoring ARP %s %s => %s" % (dpid_to_str(dpid), { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, a.protodst) log.debug(msg) return # EventHalt
def _handle_PacketIn(self, event): """ Handles packet in messages from the switch. """ etherFrame = event.parsed packet_in = event.ofp # Incomplete frames if not etherFrame.parsed: log.warning("Ignoring incomplete packet") return # LLDP if etherFrame.type == ethernet.LLDP_TYPE: log.warning("Ignoring LLDP") return # ajouter la nouvelle adresse MAC à la table mac if str(etherFrame.src) not in self.mac_to_port: self.mac_to_port[str(etherFrame.src)] = packet_in.in_port log.debug('%s Adding %s into CAM' % (self.dpid, str(etherFrame.src))) # Switchable? if str(etherFrame.dst) in self.mac_to_port: self.resend_packet(etherFrame, self.mac_to_port[str(etherFrame.dst)]) log.debug("%s Frame can be switched!" % self.dpid) else: # 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('%s RECEIVED: EtherType -> IP' % self.dpid) # Extract IP Packet from Ethernet Frame ip_packet = etherFrame.payload destination_ip = str(ip_packet.dstip) # For Router? if destination_ip in self.interfaces: log.debug('%s ICMP ECHO -> ROUTER INTERFACE' % self.dpid) self.ICMP_Handler(etherFrame, packet_in) else: routable = False for netaddr in self.routing_table.keys(): destination_network = netaddr if IPAddress(destination_ip) in IPNetwork( destination_network): routable = True log.debug('%s Packet can be routed!' % self.dpid) break local = False if not routable: for netaddr in self.interfaces.keys(): destination_network = self.interfaces[netaddr][ 'Network'] if IPAddress(destination_ip) in IPNetwork( destination_network): local = True log.debug('%s Packet forwarded locally!' % self.dpid) break if local: if destination_ip not in self.arp_table: # ARP pour le prochain saut arp_request = arp() arp_request.opcode = arp.REQUEST arp_request.protosrc = IPAddr(netaddr) arp_request.protodst = IPAddr(destination_ip) arp_request.hwsrc = EthAddr( self.interfaces[netaddr]['MAC']) arp_request.hwdst = EthAddr('00:00:00:00:00:00') ether = ethernet() ether.type = ethernet.ARP_TYPE ether.src = EthAddr( self.interfaces[netaddr]['MAC']) ether.dst = EthAddr('FF:FF:FF:FF:FF:FF') ether.payload = arp_request msg = of.ofp_packet_out() msg.data = ether msg.actions.append( of.ofp_action_output(port=of.OFPP_FLOOD)) self.connection.send(msg) if destination_ip in self.arp_table: etherFrame.src = etherFrame.dst etherFrame.dst = EthAddr( self.arp_table[destination_ip]) self.resend_packet( etherFrame, self.mac_to_port[ self.arp_table[destination_ip]]) elif routable: next_hop = self.routing_table[destination_network][ 'Next Hop'] if next_hop not in self.arp_table: # ARP for the Next Hop arp_request = arp() arp_request.opcode = arp.REQUEST arp_request.protosrc = IPAddr( self.routing_table[destination_network] ['Connected']) arp_request.protodst = IPAddr(next_hop) arp_request.hwsrc = EthAddr(self.interfaces[ self.routing_table[destination_network] ['Connected']]['MAC']) arp_request.hwdst = EthAddr('00:00:00:00:00:00') ether = ethernet() ether.type = ethernet.ARP_TYPE ether.src = EthAddr(self.interfaces[ self.routing_table[destination_network] ['Connected']]['MAC']) ether.dst = EthAddr('FF:FF:FF:FF:FF:FF') ether.payload = arp_request msg = of.ofp_packet_out() msg.data = ether msg.actions.append( of.ofp_action_output(port=of.OFPP_FLOOD)) self.connection.send(msg) if next_hop in self.arp_table: etherFrame.src = EthAddr(self.interfaces[ self.routing_table[destination_network] ['Connected']]['MAC']) etherFrame.dst = EthAddr(self.arp_table[next_hop]) self.resend_packet( etherFrame, self.mac_to_port[self.arp_table[next_hop]]) log.debug('%s Packet forwarded to next hop!' % self.dpid)
def _handle_PacketIn(self, event): """ Handles packet in messages from the switch to implement above algorithm. """ pkt = event.parse() #code.interact(local=locals()) #log.debug("OFHandler: Got OF PacketIN!\n") if (event.port == 3 and pkt.type == ethernet.ARP_TYPE and pkt.next.opcode == arp.REQUEST): arp_req = pkt.next #log.debug("\nGot a packet request from port 3, flood it\n") arp_reply = arp() arp_reply.hwtype = arp_req.hwtype arp_reply.prototype = arp_req.prototype arp_reply.hwlen = arp_req.hwlen arp_reply.protolen = arp_req.protolen arp_reply.opcode = arp.REPLY arp_reply.protodst = arp_req.protosrc arp_reply.protosrc = arp_req.protodst arp_reply.hwsrc = EthAddr(self.sw_info["eth3"][1]) arp_reply.hwdst = arp_req.hwsrc e = ethernet(type=pkt.type, src=arp_reply.hwsrc, dst=arp_req.hwsrc) e.payload = arp_reply 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) elif (event.port == 3): #log.debug("OFHandler: raise SRPacketIn event\n") #log.debug("OFHandler: packet from outside, translate address\n") #implement an internal NAT here packet = event.parse() #print 'original packet: ', packet if (packet.type == ethernet.IP_TYPE): ip_pkt = packet.next #print INTERNAL_IP.keys() #print IP_SETTING.values() #print ip_pkt.dstip dst_ip = ip_pkt.dstip.toStr() src_ip = ip_pkt.srcip.toStr() if (dst_ip in INTERNAL_IP.keys()): #print "change IP destination\n" ip_pkt.dstip = IPAddr(IP_SETTING[INTERNAL_IP[dst_ip]]) ip_pkt.csum = ip_pkt.checksum() # ip_pkt.raw = ip_pkt.pack() ip_pkt.raw = None packet.next = ip_pkt elif (packet.type == ethernet.ARP_TYPE): if (packet.next.opcode == arp.REPLY): arp_reply = packet.next dst_ip = arp_reply.protodst.toStr() if (dst_ip in INTERNAL_IP.keys()): #print "change arp reply dst \n" arp_reply.protodst = IPAddr( IP_SETTING[INTERNAL_IP[dst_ip]]) #print arp_reply.protodst arp_reply.raw = None packet.next = arp_reply #print "modified packet: ", packet raw_packet = packet.pack() core.cs144_ofhandler.raiseEvent(SRPacketIn(raw_packet, event.port)) else: raw_packet = pkt.raw core.cs144_ofhandler.raiseEvent(SRPacketIn(raw_packet, event.port)) # Drop this packet as we won't reference it. Just trying to be # safe so that OVS's/vswitchd's buffer doesn't have stale packets. msg = of.ofp_packet_out() msg.buffer_id = event.ofp.buffer_id msg.in_port = event.port self.connection.send(msg)
def _handle_SRPacketOut(self, event): msg = of.ofp_packet_out() new_packet = event.pkt if (event.port == 1): #out going packet, need to go through NAT packet = ethernet(raw=event.pkt) if (packet.type == ethernet.IP_TYPE): #print "in SRPacketOut" #print packet ip_pkt = ipv4(raw=event.pkt[ethernet.MIN_LEN:]) if (ip_pkt.protocol == ipv4.UDP_PROTOCOL and ip_pkt.next.dstport == 53): src_ip = ip_pkt.srcip.toStr() if (src_ip in IP_SETTING.values()): ip_pkt.srcip = IPAddr( INTERNAL_NAME[NAME_SETTING[src_ip]]) ip_pkt.csum = ip_pkt.checksum() packet.next = ip_pkt #new_packet = packet.pack() #event.pkt[ethernet.MIN_LEN:ipv4.hl] = ip_pkt.tyhdr() #ipp = ip_pkt #event.pkt[ethernet.MIN_LEN:ip_pkt.hl] = struct.pack('!BBHHHBBHII', (ipp.v << 4) + ipp.hl, ipp.tos, ipp.iplen, ipp.id, (ipp.flags << 13) | ipp.frag, ipp.ttl, ipp.protocol, ipp.csum, ipp.srcip.toUnsigned(), ipp.dstip.toUnsigned()) #npkt = ipv4(raw=event.pkt[ethernet.MIN_LEN:]) #print npkt # udp_pkt= ip_pkt.next # dns_pkt = udp_pkt.next # print dns_pkt # d = dns() # u = udp() # ipp = ipv4() # ipp.protocol = ipp.UDP_PROTOCOL # ipp.srcip = IPAddr(INTERNAL_NAME[NAME_SETTING[src_ip]]) # ipp.dstip = ip_pkt.dstip # e = ethernet() # e.src = packet.src # e.dst = packet.dst # e.type = e.IP_TYPE # ipp.payload = udp_pkt # e.payload = ipp # new_packet = e.pack() else: src_ip = ip_pkt.srcip.toStr() #print ip_pkt.srcip if (src_ip in IP_SETTING.values()): # print "change IP src\n" ip_pkt.srcip = IPAddr( INTERNAL_NAME[NAME_SETTING[src_ip]]) # print ip_pkt.srcip ip_pkt.csum = ip_pkt.checksum() ip_pkt.raw = None packet.next = ip_pkt if (ip_pkt.protocol == ipv4.ICMP_PROTOCOL): icmp_pkt = ip_pkt.next icmp_pkt.raw = None if (icmp_pkt.type == 3): ip_hdr = icmp_pkt.next.next ip_hdr.dstip = IPAddr( INTERNAL_NAME[NAME_SETTING[src_ip]]) #print "Replace icmp MSG IP addr !!!!\n" #print icmp_pkt new_packet = packet.pack() elif (packet.type == ethernet.ARP_TYPE): if (packet.next.opcode == arp.REQUEST): # print "get a arp request" arp_req = packet.next src_ip = arp_req.protosrc.toStr() if (src_ip in IP_SETTING.values()): # print "change arp request src \n" arp_req.protosrc = IPAddr( INTERNAL_NAME[NAME_SETTING[src_ip]]) # print arp_req.protosrc arp_req.raw = None packet.next = arp_req new_packet = packet.pack() msg.actions.append(of.ofp_action_output(port=event.port)) msg.buffer_id = -1 msg.in_port = of.OFPP_NONE msg.data = new_packet #log.debug("SRServer catch SRPacketOut event, fwd_pkt=%r, port=%s\n" % (event.pkt, event.port)) 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("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) if (str(packet.next.srcip) == "10.0.1.3") and (firewall == 1): return # 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) if (str(packet.next.protosrc) == "10.0.1.3") and (firewall == 1): return # 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 _handle_PacketIn(self, event): dpid = event.dpid inport = event.port packet = event.parsed if not packet.parsed: log.warning("%s: ignoring unparsed packet", dpid_to_str(dpid)) return 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 event.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 event.connection.send(msg) a = packet.find('arp') if not a: return log.debug("%s ARP %s %s => %s", dpid_to_str(dpid), { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc), str(a.protodst)) if a.opcode == arp.REQUEST: if packet.payload.hwsrc != self.mac and packet.payload.protosrc != self.ip: if packet.payload.protodst in arpNat: arpNat[packet.payload.protodst].append([ packet.payload.hwsrc, packet.payload.protosrc, dpid, inport ]) else: arpNat[packet.payload.protodst] = [[ packet.payload.hwsrc, packet.payload.protosrc, dpid, inport ]] 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 = packet.payload.protodst r.protosrc = self.ip r.hwsrc = self.mac e = ethernet(type=ethernet.ARP_TYPE, src=self.mac, dst=ETHER_BROADCAST) e.payload = r 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) return EventHalt else: return elif a.opcode == arp.REPLY: if (packet.payload.protosrc in arpNat and arpNat[packet.payload.protosrc]) and ( packet.payload.protodst == self.ip) and (packet.payload.hwdst == self.mac): # flag = False # count = 0 # for e in arpNat[packet.payload.protosrc]: # if e[2] == dpid: # flag = True # i = count # count += 1 # if flag: r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REPLY # print arpNat[packet.payload.protosrc] r.hwdst, r.protodst, outpid, outport = arpNat[ packet.payload.protosrc].pop() r.hwsrc = packet.payload.hwsrc r.protosrc = packet.payload.protosrc e = ethernet(type=ethernet.ARP_TYPE, src=self.mac, dst=r.hwdst) e.set_payload(r) log.debug("ARPing for %s on behalf of %s" % (r.protodst, r.protosrc)) msg = of.ofp_packet_out( data=e.pack(), action=of.ofp_action_output(port=outport)) # msg.data = e.pack() # msg.actions.append(of.ofp_action_output(port=outport)) # msg.in_port = inport core.openflow.sendToDPID(outpid, msg) # event.connection.send(msg) # print "outport: "+str(outport) +" dpid:"+ str(dpid)+" outpid:"+str(outpid) arpttl.add( (packet.payload.protosrc, packet.payload.protodst), [ packet.payload.hwsrc, outport, outpid, r.protodst, r.hwdst ]) return EventHalt else: if (packet.payload.protosrc, packet.payload.protodst) in arpttl: if arpttl[(packet.payload.protosrc, packet.payload.protodst )][0] == packet.payload.hwsrc: print "multiple replies, but OK" return EventHalt else: # if dpid == arpttl[(packet.payload.protosrc, packet.payload.protodst)][2]: print "multiple replies for the same IP with different mac addresses" r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REPLY r.hwdst = arpttl[(packet.payload.protosrc, packet.payload.protodst)][4] r.protodst = arpttl[(packet.payload.protosrc, packet.payload.protodst)][3] outport = arpttl[(packet.payload.protosrc, packet.payload.protodst)][1] r.hwsrc = self.safe r.protosrc = packet.payload.protosrc e = ethernet(type=ethernet.ARP_TYPE, src=self.safe, dst=r.hwdst) e.set_payload(r) log.debug("ARPing for %s on behalf of %s" % (r.protodst, r.protosrc)) msg = of.ofp_packet_out( data=e.pack(), action=of.ofp_action_output(port=outport)) # msg = of.ofp_packet_out() # msg.data = e.pack() # msg.actions.append(of.ofp_action_output(port=outport)) # msg.in_port = inport time.sleep(1) core.openflow.sendToDPID( arpttl[(packet.payload.protosrc, packet.payload.protodst)][2], msg) # event.connection.send(msg) return EventHalt else: print "Dropping gratuitous reply" return EventHalt
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 _handle_PacketIn(self, event): """ Gerencia os pacotes de entrada. :param event: Evento relacionado à chamada da função. :return: Sem retorno. """ 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: # New switch -- create an empty table self.arpTable[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, str(packet.next.srcip), str(packet.next.dstip)) # 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, str(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) # Try to forward dstaddr = packet.next.dstip if dstaddr in self.arpTable[dpid]: # We have info about what port to send it out on... prt = self.arpTable[dpid][dstaddr].port if prt == inport: log.warning( "%i %i not sending packet for %s back out of the input port" % (dpid, inport, str(dstaddr))) else: log.debug( "%i %i installing flow for %s => %s out port %i" % (dpid, inport, str( packet.next.srcip), str(dstaddr), prt)) 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, action=of.ofp_action_output(port=prt), match=of.ofp_match.from_packet(packet, inport)) event.connection.send(msg.pack()) 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)) 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) if a.opcode == arp.REQUEST: # Maybe we can answer 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 = self.arpTable[dpid][ a.protodst].mac e = ethernet(type=packet.type, src=r.hwsrc, dst=a.hwsrc) e.set_payload(r) log.debug("%i %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("%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()) return
def _handle_openflow_PacketIn(self, event): global packets global dpids 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: # 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): print "dpid and port: (", event.connection.dpid, event.port, ")" log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip, packet.next.dstip) # ['frame.len', 'ip.hdr_len', # 'ip.len', 'ip.flags.rb', 'ip.flags.df', 'p.flags.mf', 'ip.frag_offset', # 'ip.ttl', 'ip.proto', 'tcp.srcport', 'tcp.dstport', # 'tcp.len', 'tcp.ack', 'tcp.flags.res', 'tcp.flags.ns', 'tcp.flags.cwr', # 'tcp.flags.ecn', 'tcp.flags.urg', 'tcp.flags.ack', 'tcp.flags.push', # 'tcp.flags.reset', 'tcp.flags.syn', 'tcp.flags.fin', 'tcp.window_size', # 'tcp.time_delta'] x_test = [ len(packet), packet.next.hl, packet.next.iplen, 0, packet.next.flags == 1, packet.next.flags == 2, packet.next.frag, packet.next.ttl, packet.next.protocol, packet.next.next.srcport, packet.next.next.dstport, len(packet.next.next), packet.next.next.ACK, 0, 0, 0, 0, 0, packet.next.next.flags == 16, packet.next.next.flags == 8, packet.next.next.flags == 4, packet.next.next.flags == 2, packet.next.next.flags == 1, packet.next.next.win, 0 ] defender = Detector() packets.append(x_test) dpids.append(event.connection.dpid) if len(packets) >= 25: normal = defender.predictResult(packets) print "value: ", normal if int(normal[0][0] + 0.5): print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~normal~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' packets.pop(0) dpids.pop(0) if not int(normal[0][0] + 0.5): print '--------------- -------------------Warning!! DDoS detected! -----------------------------------------------' print 'the prediction from LSTM DL model: ', normal[0][ 0], '(1: normal, 0: attack)' print 'blocking the malicious attack.......................................' print 'event.connection.dpid: ', event.connection.dpid print '---------------------------------------------------------------------------------------------------------' for i, dpid in enumerate(dpids): # print "inport, dstport: ", packets[i][9], packets[i][10] msg = of.ofp_packet_out(in_port=packets[i][9] + 25) core.openflow.sendToDPID(dpid, msg) packets.pop(0) dpids.pop(0) os._exit(0) # 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) print "forwarding" # Try to forward dstaddr = packet.next.dstip 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( "%i %i not sending packet for %s back out of the " "input port" % (dpid, inport, dstaddr)) else: log.debug( "%i %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)) if self.wide: match = of.ofp_match(dl_type=packet.type, nw_dst=dstaddr) else: match = of.ofp_match.from_packet(packet, inport) 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=match) event.connection.send(msg.pack()) 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.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, a.protosrc) 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.dl_type = ethernet.IP_TYPE msg.match.nw_dst = a.protosrc event.connection.send(msg) else: log.debug("%i %i learned %s", dpid, inport, 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 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 = 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" % (dpid, inport, 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("%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 _handle_PacketIn(self, event): packet = event.parsed if not packet.parsed: return port = event.port dpid = event.connection.dpid pnext = packet.next # If destination is known via other switches odd_ips = ["10.0.0.1", "10.0.0.3", "10.0.0.5"] even_ips = ["10.0.0.2", "10.0.0.4", "10.0.0.6"] log.info("current packet dpid: %i at port: %s " %\ (dpid, port)) # A new switch has connected if dpid not in self._arp_table: self._arp_table[dpid] = {} log.info("Initiating ARP table for dpid: %i" % (dpid, )) # If it is an IPv4 packet if isinstance(pnext, ipv4): # Learn or update mac and port info for IP #if it is the leaf switches if int(dpid) in [1, 2, 3]: log.info("leaf dpid") if pnext.srcip in odd_ips: log.info("odd src ip matched src ip %s" % (pnext.srcip, )) self._arp_table[dpid][pnext.srcip] = (packet.src, 1) else: self._arp_table[dpid][pnext.srcip] = (packet.src, 2) self._master_arp_table[pnext.srcip] = packet.src log.info("Updating ARP table for dpid: %i & IP: %s with (%s, %i)" %\ (dpid, pnext.srcip, packet.src, port,)) # Find the packet destination dst_ip = pnext.dstip # If destination is known then if dst_ip in self._arp_table[dpid]: # Obtain its mac and port dst_mac, dst_port = self._arp_table[dpid][dst_ip] log.info("Probed ARP table for dpid: %i & IP: %s to get (%s, %i)" %\ (dpid, dst_ip, dst_mac, dst_port,)) # Add the flow rule to switch if dst_port != port: message = of.ofp_flow_mod(buffer_id=event.ofp.buffer_id) message.actions.append( of.ofp_action_dl_addr.set_dst(dst_mac)) message.actions.append(of.ofp_action_output(port=dst_port)) message.match = of.ofp_match.from_packet(packet, port) event.connection.send(message) else: ''' # If destination is known via other switches odd_ips = ["10.0.0.1", "10.0.0.3", "10.0.0.5"] even_ips = ["10.0.0.2", "10.0.0.4", "10.0.0.6"] if pnext.srcip in odd_ips: # route throgh s4 log.info("Odd IP: %s should be routed through S4" % (pnext.srcip,)) elif pnext.srcip in even_ips: log.info("Even IP: %s should be routed through S4" % (pnext.srcip,)) else: # unknown dpid log.info("Encountered unknown IP: %s" % (pnext.srcip,)) ''' # Else if it is an ARP packet elif isinstance(pnext, arp): if pnext.prototype == arp.PROTO_TYPE_IP and pnext.hwtype == arp.HW_TYPE_ETHERNET \ and pnext.protosrc != 0: # Learn or update MAC & port info for IP self._arp_table[dpid][pnext.protosrc] = (packet.src, port) self._master_arp_table[pnext.protosrc] = packet.src log.info("Updating ARP table for dpid: %i & IP: %s with (%s, %i)" %\ (dpid, pnext.protosrc, packet.src, port,)) # If it is an ARP request and we know the destination # if pnext.opcode == arp.REQUEST and pnext.protodst in self._arp_table[dpid]: if pnext.opcode == arp.REQUEST and pnext.protodst in self._master_arp_table: # Send the ARP response res = arp() # res.hwsrc, _ = self._arp_table[dpid][pnext.protodst] res.hwsrc = self._master_arp_table[pnext.protodst] res.hwtype = arp.HW_TYPE_ETHERNET res.hwdst = pnext.hwsrc res.hwlen = pnext.hwlen res.prototype = arp.PROTO_TYPE_IP res.protodst = pnext.protosrc res.protosrc = pnext.protodst res.protolen = pnext.protolen res.opcode = arp.REPLY eth = ethernet() eth.type = packet.type eth.src = EthAddr("%012x" % (dpid & 0xFFFFFFFFFFFF)) eth.dst = res.hwdst eth.set_payload(res) message = of.ofp_packet_out() message.in_port = port message.data = eth.pack() message.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) event.connection.send(message) log.info("Responded to ARP request for dpid: %s and destination: %s" %\ (dpid, pnext.protodst,))
def _handle_PacketIn (event): #log.info("*** _handle_PacketIn... ***") dpid = event.connection.dpid inport = event.port packet = event.parsed if not packet.parsed: log.warning("%i %i ignoring unparsed packet", dpid, inport) return a = packet.find('arp') if not a: return log.info("%s ARP %s %s => %s", dpid_to_str(dpid), {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.opcode == arp.REQUEST: if str(a.protodst)=="192.168.1.1": 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 = EthAddr("00:00:00:00:00:03") e = ethernet(type=packet.type, src=r.hwsrc, dst=a.hwsrc) e.payload = r log.info("%s answering ARP for %s" % (dpid_to_str(dpid), 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) if str(a.protodst)=="10.0.0.2": 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 = EthAddr("00:00:00:00:00:04") e = ethernet(type=packet.type, src=r.hwsrc, dst=a.hwsrc) e.payload = r log.info("%s answering ARP for %s" % (dpid_to_str(dpid), 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)
def parse(self): if self._parsed is None: self._parsed = ethernet(self.data) return self._parsed
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("!LOG WARN! S1 : 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('!LOG! S1 : Adding %s into CAM, recv from %s' % (str(etherFrame.src), str(packet_in.in_port))) self.mac_to_port[str(etherFrame.src)] = packet_in.in_port # ARP if etherFrame.type == ethernet.ARP_TYPE: log.debug('!LOG! S1 : RECEIVED: EtherType -> ARP') self.ARP_Handler(etherFrame, packet_in) # IP elif etherFrame.type == ethernet.IP_TYPE: log.debug('!LOG! S1 : 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('!LOG! S1 : 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('!LOG! S1 : 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('!LOG! S1 : 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("!LOG! S1 : ICMP DESTINATION UNREACHABLE SENT")
def ARP_Handler(self, packet, packet_in): log.debug("!LOG! S1 : ARP FRAME RECEIVED FROM %s" % packet_in.in_port) if packet.payload.opcode == arp.REQUEST: log.debug("!LOG! S1 : IT'S AN ARP REQUEST!") arp_payload = packet.payload arp_request_ip = str(arp_payload.protodst) if arp_request_ip in self.arp_table: arp_reply = arp() arp_reply.opcode = arp.REPLY arp_reply.hwsrc = EthAddr(self.arp_table[arp_request_ip]) arp_reply.hwdst = arp_payload.hwsrc arp_reply.protosrc = arp_payload.protodst arp_reply.protodst = arp_payload.protosrc ether = ethernet() ether.type = ether.ARP_TYPE ether.src = EthAddr(self.arp_table[arp_request_ip]) ether.dst = arp_payload.hwsrc ether.payload = arp_reply self.resend_packet(ether, packet_in.in_port) log.debug("!LOG! S1 : ARP REPLY SENT!") elif packet.payload.opcode == arp.REPLY: log.debug("!LOG! S1 : IT'S AN ARP REPLY!") arp_payload = packet.payload hwsrc = str(arp_payload.hwsrc) srcip = str(arp_payload.protosrc) if srcip not in self.arp_table: self.arp_table[srcip] = hwsrc self.mac_to_port[hwsrc] = packet_in.in_port log.debug("!LOG! S1 : %s %s INSTALLED TO CAM TABLE" % (srcip, hwsrc)) # If there are packets in buffer waiting to be sent out if srcip in self.buffer.keys(): print 'Packet waiting in buffer!' out_port = self.routing_table[self.buffer[srcip] ['DestinationNetwork']]['Port'] ip_packet = self.buffer[srcip]['IP_Packet'] etherFrame = ethernet() etherFrame.type = etherFrame.IP_TYPE etherFrame.src = EthAddr(self.arp_table[self.routing_table[ self.buffer[srcip]['DestinationNetwork']] ['RouterInterface']]) etherFrame.dst = EthAddr(self.arp_table[srcip]) etherFrame.payload = ip_packet self.resend_packet(etherFrame, out_port) msg = of.ofp_flow_mod() print self.buffer[srcip]['DestinationNetwork'] msg.priority = 10 msg.match.dl_type = ethernet.IP_TYPE msg.match.nw_proto = ipv4.ICMP_PROTOCOL msg.match.set_nw_dst(self.buffer[srcip]['DestinationNetwork']) # msg.match.nw_dst = IPAddr(srcip) msg.actions.append( of.ofp_action_dl_addr.set_src( EthAddr(self.arp_table[self.routing_table[ self.buffer[srcip]['DestinationNetwork']] ['RouterInterface']]))) msg.actions.append( of.ofp_action_dl_addr.set_dst( EthAddr(self.arp_table[srcip]))) msg.actions.append(of.ofp_action_output(port=out_port)) self.connection.send(msg) log.debug( "!LOG! S1 : Flow mod for destination network %s sent!", self.buffer[srcip]['DestinationNetwork']) self.buffer.pop(srcip)
def _handle_PacketIn(self, event): dpid = event.dpid inport = event.port packet = event.parsed if not packet.parsed: log.warning("%s: ignoring unparsed packet", dpid_to_str(dpid)) return 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 event.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 event.connection.send(msg) a = packet.find('arp') if not a: return log.debug("%s ARP %s %s => %s", dpid_to_str(dpid), { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc), str(a.protodst)) if a.opcode == arp.REQUEST: if packet.payload.hwsrc != self.mac and packet.payload.protosrc != self.ip: if packet.payload.protodst in arpNat: arpNat[packet.payload.protodst].append([ packet.payload.hwsrc, packet.payload.protosrc, dpid, inport ]) else: arpNat[packet.payload.protodst] = [[ packet.payload.hwsrc, packet.payload.protosrc, dpid, inport ]] 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 = packet.payload.protodst r.protosrc = self.ip r.hwsrc = self.mac e = ethernet(type=ethernet.ARP_TYPE, src=self.mac, dst=ETHER_BROADCAST) e.payload = r 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) return EventHalt else: return elif a.opcode == arp.REPLY: if (arpNat[packet.payload.protosrc] and packet.payload.protodst == self.ip and packet.payload.hwdst == self.mac): drop() flag = False count = 0 for e in arpNat[packet.payload.protosrc]: if e[2] == dpid: flag = True i = count count += 1 if flag: r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REPLY r.hwdst, r.protodst, outpid, outport = arpNat[ packet.payload.protosrc].pop(i) r.hwsrc = packet.payload.hwsrc r.protosrc = packet.payload.protosrc e = ethernet(type=ethernet.ARP_TYPE, src=self.mac, dst=r.hwdst) e.set_payload(r) log.debug("ARPing for %s on behalf of %s" % (r.protodst, r.protosrc)) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port=outport)) msg.in_port = inport event.connection.send(msg) return EventHalt else: return
def _handle_openflow_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed global set_Timer global defendDDOS global blockPort timerSet = False global diction def preventing(): global diction global set_Timer if not set_Timer: set_Timer = True if len(diction) == 0: print("Empty diction ", str(event.connection.dpid), str(event.port)) diction[event.connection.dpid] = {} diction[event.connection.dpid][event.port] = 1 elif event.connection.dpid not in diction: diction[event.connection.dpid] = {} diction[event.connection.dpid][event.port] = 1 else: if event.connection.dpid in diction: if event.port in diction[event.connection.dpid]: temp_count = 0 temp_count = diction[event.connection.dpid][event.port] temp_count = temp_count + 1 diction[event.connection.dpid][event.port] = temp_count #print "*****************************************************************************************************************************************************************************" print "dpid port and its packet count: ", str( event.connection.dpid), str( diction[event.connection.dpid]), str( diction[event.connection.dpid][event.port]) #print "*****************************************************************************************************************************************************************************" else: diction[event.connection.dpid][event.port] = 1 def _timer_func(): global diction global set_Timer if set_Timer == True: for k, v in diction.iteritems(): for i, j in v.iteritems(): if j >= 5: print "_____________________________________________________________________________________________" print "\n DDOS DETECTED \n" print "\n", str(diction) print "\n", datetime.datetime.now( ), ": BLOCKED PORT NUMBER : ", str( i), " OF SWITCH ID: ", str(k) print "\n___________________________________________________________________________________________" os._exit(0) dpid = k msg = of.ofp_packet_out(in_port=i) core.openflow.sendToDPID(dpid, msg) diction = {} if not packet.parsed: log.warning("%i %i ignoring unparsed packet", dpid, inport) return if dpid not in self.arpTable: 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: return if isinstance(packet.next, ipv4): log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip, packet.next.dstip) ent_obj.collectStats(event.parsed.next.dstip) print "Entropy : ", str(ent_obj.value) if ent_obj.value < 1.0: preventing() if timerSet is not True: Timer(1, _timer_func, recurring=True) timerSet = False else: timerSet = False self._send_lost_buffers(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) if self.wide: 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) dstaddr = packet.next.dstip if dstaddr in self.arpTable[dpid]: prt = self.arpTable[dpid][dstaddr].port mac = self.arpTable[dpid][dstaddr].mac if prt == inport: log.warning( "%i %i not sending packet for %s back out of the " "input port" % (dpid, inport, dstaddr)) else: log.debug( "%i %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)) if self.wide: match = of.ofp_match(dl_type=packet.type, nw_dst=dstaddr) else: match = of.ofp_match.from_packet(packet, inport) 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=match) event.connection.send(msg.pack()) elif self.arp_for_unknowns: 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] self.outstanding_arps = { k: v for k, v in self.outstanding_arps.iteritems() if v > time.time() } if (dpid, dstaddr) in self.outstanding_arps: return 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.prototype == arp.PROTO_TYPE_IP: if a.hwtype == arp.HW_TYPE_ETHERNET: if a.protosrc != 0: 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, a.protosrc) if self.wide: msg = of.ofp_flow_mod( command=of.OFPFC_DELETE) msg.match.dl_type = ethernet.IP_TYPE msg.match.nw_dst = a.protosrc event.connection.send(msg) else: log.debug("%i %i learned %s", dpid, inport, a.protosrc) self.arpTable[dpid][a.protosrc] = Entry( inport, packet.src) self._send_lost_buffers(dpid, a.protosrc, packet.src, inport) if a.opcode == arp.REQUEST: if a.protodst in self.arpTable[dpid]: if not self.arpTable[dpid][ a.protodst].isExpired(): 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" % (dpid, inport, 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 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 _handle_PacketIn(self, event): log.info('Start main funciton') dpid = event.connection.dpid #log.info('dpid is %s ' %dpid) packet = event.parsed # This is the parsed packet data. inport = event.port if not packet.parsed: log.warning("%s: ignoring unparsed packet", dpid_to_str(dpid)) return packet_in = event.ofp # The actual ofp_packet_in message. #log.info("Installing flow...") # Maybe the log statement should have source/destination/port? #log.debug('the source MAC is %s' %packet.src) #log.debug('the dist MAC is %s' %packet.dst) #log.debug('the source port is %s' %packet_in.in_port) if dpid == 1: _route = _route1 else: _route = _route2 '***********************ARP**********************************' if packet.find("arp"): a = packet.find('arp') if not a: return log.debug("ARP %s %s => %s", { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc), str(a.protodst)) _ip_to_port[IPAddr(a.protosrc)] = inport #Deal with ARP REQUEST then ARP REPLY to hosts if a.prototype == arp.PROTO_TYPE_IP and a.hwtype == arp.HW_TYPE_ETHERNET and a.opcode == arp.REQUEST: _arp_cache[IPAddr(a.protosrc)] = EthAddr(a.hwsrc) #log.info('store to cache %s' %_arp_cache) #log.info('self._arp_cache[a.protosrc] = %s protosrc is %s' %(self._arp_cache[IPAddr(a.protosrc)],IPAddr(a.protosrc))) if dpid == 2 and inport == 1: p = arp() p.hwtype = arp.HW_TYPE_ETHERNET p.prototype = arp.PROTO_TYPE_IP p.hwlen = 6 p.protolen = 4 p.opcode = arp.REQUEST p.hwdst = EthAddr('ff:ff:ff:ff:ff:ff') p.hwsrc = EthAddr('00:00:00:00:00:07') p.protodst = _route[2][0] p.protosrc = _route[2][1] E = ethernet(type=ethernet.ARP_TYPE, src=p.hwsrc, dst=p.hwdst) E.payload = p self.resend_packet(E, 2) elif dpid == 1 and inport == 1: pp = arp() pp.hwtype = arp.HW_TYPE_ETHERNET pp.prototype = arp.PROTO_TYPE_IP pp.hwlen = 6 pp.protolen = 4 pp.opcode = arp.REQUEST pp.hwdst = EthAddr('ff:ff:ff:ff:ff:ff') pp.hwsrc = EthAddr('00:00:00:00:00:04') pp.protodst = a.protodst pp.protosrc = IPAddr('10.0.1.1') EE = ethernet(type=ethernet.ARP_TYPE, src=pp.hwsrc, dst=pp.hwdst) EE.payload = pp self.resend_packet(EE, 2) self.resend_packet(EE, 3) else: 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 if str(a.protodst) == '10.0.1.1': r.hwsrc = EthAddr('00:00:00:00:00:04') if str(a.protodst) == '10.0.2.1': r.hwsrc = EthAddr('00:00:00:00:00:07') e = ethernet(type=packet.type, src=r.hwsrc, dst=a.hwsrc) e.payload = r log.info("Answering ARP for %s" % (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) msg1 = of.ofp_flow_mod() msg1.match = of.ofp_match() msg1.match.dl_type = 0x800 msg1.match.nw_dst = a.protosrc msg1.actions.append(of.ofp_action_dl_addr.set_src(r.hwsrc)) msg1.actions.append(of.ofp_action_dl_addr.set_dst(r.hwdst)) msg1.actions.append(of.ofp_action_output(port=inport)) self.connection.send(msg1) #Deal with ARP REPLY and store ARP cache #Prepare to send buffered ICMP REQUEST packets with new MAC address if a.prototype == arp.PROTO_TYPE_IP and a.hwtype == arp.HW_TYPE_ETHERNET and a.opcode == arp.REPLY: _arp_cache[IPAddr(a.protosrc)] = EthAddr(a.hwsrc) msg2 = of.ofp_flow_mod() msg2.match = of.ofp_match() msg2.match.dl_type = 0x800 msg2.match.nw_dst = a.protosrc msg2.actions.append(of.ofp_action_dl_addr.set_src(a.hwdst)) msg2.actions.append(of.ofp_action_dl_addr.set_dst(a.hwsrc)) msg2.actions.append(of.ofp_action_output(port=inport)) self.connection.send(msg2) self.msg_send(_buff[IPAddr(a.protosrc)], a.hwdst, a.hwsrc, inport) #self.icmp_forward(_buff[IPAddr(a.protosrc)],TYPE_ECHO_REQUEST,_ip_bf[IPAddr(a.protosrc)].srcip,_ip_bf[IPAddr(a.protosrc)].dstip,a.hwdst,a.hwsrc,inport) log.info('forward dic %s' % _buff[IPAddr(a.protosrc)]) '****************************ICMP***********************' if packet.find("icmp"): log.info('ICMP occurs') _ip_to_port[IPAddr(packet.payload.srcip)] = inport #intall the packet and get information of the packet #rqt_src: router interface IP addr; rqt_port: router port; rqt_pfx: network prefix; rqt_hwsrc: router interface MAC addr. payload_bf = packet.payload.payload.payload icmp_bf = packet.payload.payload #log.info('icmp type =%s'%packet.payload.payload.type) global rqtsrc, rqtdst, rqtport, rqtpfx, rqthwsrc global rplsrc, rpldst, rplport, rplpfx, rplhwsrc #log.debug('before loop:') #log.info('icmp cache is %s' %_arp_cache) target = 0 for j in range(0, 5): for i in range(0, 3): if str(_route[i][j]) == str(packet.payload.dstip): if j == 0: rqtsrc = _route[i][1] rqtdst = _route[i][0] rqtport = _route[i][2] rqtpfx = _route[i][3] rqthwsrc = _route[i][4] #target = 1 means the icmp packet is to host target = 1 break elif j == 1: #router reply to host rplsrc = _route[i][1] rpldst = _route[i][0] rplport = _route[i][2] rplpfx = _route[i][3] rplhwsrc = _route[i][4] #target = 2 means the icmp packet is to router interface target = 2 flagd = i break for k in range(0, 3): if str(_route[k][0]) == str(packet.payload.srcip): interfaceip = _route[k][1] interfacedst = _route[k][0] flags = _route[k][2] break '*********ICMP REQUEST***' if target == 0: log.info('unknown') self.icmp_unknownhost(packet, interfaceip, inport) log.info('unknown from %s' % interfaceip) elif packet.payload.payload.type == 8 and target != 0: #If we do not have IP_MAC in routing table, create ARP Request if packet.payload.dstip not in _arp_cache: self.arp_request(packet, _arp_cache[rqthwsrc], rqthwsrc, rqtport) _buff[IPAddr(packet.payload.dstip)] = packet _ip_bf[IPAddr(packet.payload.dstip)] = packet.payload #log.info('buff %s' %_buff) #If we have IP_MAC in routing table, forward packet directly elif packet.payload.dstip in _arp_cache: if target == 1: if dpid == 1: if rqtport != 1: #h3 ICMP request forward to h4 self.icmp_forward( packet.payload.payload.payload, TYPE_ECHO_REQUEST, packet.payload.srcip, packet.payload.dstip, rqthwsrc, _arp_cache[IPAddr(packet.payload.dstip)], rqtport) else: #s1 ICMP request forward to s2 self.msg_send(packet, packet.src, packet.dst, 1) else: if inport == 1: #s2 have to forward it to h5 self.icmp_forward( packet.payload.payload.payload, TYPE_ECHO_REQUEST, packet.payload.srcip, packet.payload.dstip, _arp_cache[rqtsrc], _arp_cache[IPAddr(packet.payload.dstip)], rqtport) else: #s2 give it to s1 self.msg_send(packet, packet.src, packet.dst, 1) elif target == 2: #log.debug('icmp cache %s' %_arp_cache) #log.info('flags is %s' %flags) #log.info('dpid is %s, rplport is %s, dstinterface is %s' %(dpid, rplport,interfaceip)) if dpid == 1: if rplport != inport: #ping other gateway self.icmp_forward(payload_bf, TYPE_ECHO_REPLY, rplsrc, interfacedst, packet.dst, packet.src, inport) else: #ping default gateway self.icmp_forward(payload_bf, TYPE_ECHO_REPLY, rplsrc, rpldst, rplhwsrc, _arp_cache[IPAddr(rpldst)], rplport) else: if flags == flagd: #ping default gateway self.icmp_forward(payload_bf, TYPE_ECHO_REPLY, rplsrc, rpldst, rplhwsrc, _arp_cache[IPAddr(rpldst)], rplport) else: #ping other gateway self.icmp_forward(payload_bf, TYPE_ECHO_REPLY, interfaceip, interfacedst, packet.dst, packet.src, inport) ############ICMP REPLY############### #Receive ICPM Reply, we need forward the the reply elif packet.payload.payload.type == 0: if dpid == 2: #h5 reply to h3 if inport == 2: log.info('flow mod starts 1') msg0 = of.ofp_flow_mod() msg0.match = of.ofp_match() msg0.match.dl_type = 0x800 msg0.match.nw_dst = packet.payload.dstip msg0.actions.append( of.ofp_action_dl_addr.set_src(_port_to_mac_2['1'])) msg0.actions.append( of.ofp_action_dl_addr.set_dst(_port_to_mac_1['1'])) msg0.actions.append(of.ofp_action_output(port=1)) log.info('flow mod ends 1') self.connection.send(msg0) self.msg_send(packet, packet.src, packet.dst, 1) else: self.msg_send(packet, rqthwsrc, _arp_cache[packet.payload.dstip], rqtport) elif dpid == 1 and rqtport != 1: #h3 and h4 want to receive if inport != 1: self.icmp_forward( packet.payload.payload.payload, TYPE_ECHO_REPLY, packet.payload.srcip, packet.payload.dstip, rqthwsrc, _arp_cache[IPAddr(packet.payload.dstip)], rqtport) else: self.msg_send(packet, rqthwsrc, _arp_cache[packet.payload.dstip], rqtport) else: log.info('flow mod starts 2') msg3 = of.ofp_flow_mod() msg3.match = of.ofp_match() msg3.match.dl_type = 0x800 msg3.match.nw_dst = packet.payload.dstip msg3.actions.append( of.ofp_action_dl_addr.set_src(_port_to_mac_1['1'])) msg3.actions.append( of.ofp_action_dl_addr.set_dst(_port_to_mac_2['1'])) msg3.actions.append(of.ofp_action_output(port=1)) log.info('flow mod end 2') self.connection.send(msg3) self.msg_send(packet, packet.src, packet.dst, 1) #log.info('ICMP reply for h5 from s1 to s2') #########TCP+UDP############ elif packet.find("ipv4"): log.info('TCP occurs') for i in range(0, 3): if str(_route[i][0]) == str(packet.payload.dstip): tcpsrc = _route[i][1] tcpdst = _route[i][0] tcpport = _route[i][2] tcppfx = _route[i][3] tcphwsrc = _route[i][4] break if packet.payload.dstip in _arp_cache: if dpid == 1: if tcpport == 1: #s1 send the request to s2 self.msg_send(packet, _port_to_mac_1['1'], _port_to_mac_2['1'], 1) else: #s1 send the request to h4 self.msg_send(packet, tcphwsrc, _arp_cache[tcpdst], tcpport) else: #s2 received a request if inport == 1: #s2 send the request to h5 self.msg_send(packet, tcphwsrc, _arp_cache[tcpdst], tcpport) else: #s2 send to s1 self.msg_send(packet, _port_to_mac_2['1'], _port_to_mac_1['1'], 1) else: #not in cache _buff[IPAddr(packet.payload.dstip)] = packet if dpid == 1: if tcpport == 1: #s1 send the arp request to s2 self.arp_request(packet, _arp_cache[_port_to_mac_1['1']], _port_to_mac_1['1'], 1) else: #s1 broadcast arp request self.arp_request(packet, tcpsrc, tcphwsrc, 2) self.arp_request(packet, tcpsrc, tcphwsrc, 3) else: #s2 send the arp request to s1 self.arp_request(packet, _arp_cache[_port_to_mac_2['1']], _port_to_mac_2['1'], 1)
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.ip_mac_port: self.ip_mac_port[dpid] = {} for fake in self.fakeways: self.ip_mac_port[dpid][IPAddr(fake)] = Entry( of.OFPP_NONE, dpid_to_mac(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._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport) if packet.next.srcip in self.ip_mac_port[dpid]: if self.ip_mac_port[dpid][packet.next.srcip] != (inport, packet.src): log.debug("%i %i RE-learned %s", dpid, inport, packet.next.srcip) else: #log.info("%i %i learned %s", dpid,inport,str(packet.next.srcip)) log.info("switch %i learned %s from input port %i", dpid, str(packet.next.srcip), inport) self.ip_mac_port[dpid][packet.next.srcip] = Entry( inport, packet.src) dstaddr = packet.next.dstip if dstaddr in self.ip_mac_port[dpid]: prt = self.ip_mac_port[dpid][dstaddr].port mac = self.ip_mac_port[dpid][dstaddr].mac print dstaddr if prt == inport: log.warning( "%i %i not sending packet for %s back out of the " + "input port" % (dpid, inport, str(dstaddr))) else: log.debug( "%i %i installing flow for %s => %s out port %i" % (dpid, inport, packet.next.srcip, dstaddr, prt)) if event.ofp.buffer_id == None: bid = None else: bid = event.ofp.buffer_id ip_packet = packet.find("ipv4") if ip_packet != None: if ip_packet.protocol == 1: actions3 = [] actions3.append(of.ofp_action_dl_addr.set_dst(mac)) #actions3.append(of.ofp_action_output(port = prt)) actions3.append( of.ofp_action_enqueue(port=prt, queue_id=1)) match3 = of.ofp_match.from_packet(packet, inport) match3.dl_type = 0x800 match3.nw_proto = 1 match3.dl_src = None msg3 = of.ofp_flow_mod( command=of.OFPFC_ADD, idle_timeout=FLOW_IDLE_TIMEOUT, hard_timeout=of.OFP_FLOW_PERMANENT, buffer_id=bid, actions=actions3, priority=30, match=match3) event.connection.send(msg3.pack()) print "into queue 1" elif ip_packet.protocol == 17 or ip_packet.protocol == 6: udp_packet = packet.find("udp") if udp_packet == None: udp_packet = packet.find("tcp") if ip_packet.dstip == IPAddr( "172.16.0.3" ) and udp_packet.dstport == 5001: actions5 = [] actions5.append( of.ofp_action_dl_addr.set_dst(mac)) #actions5.append(of.ofp_action_output(port = prt)) actions5.append( of.ofp_action_enqueue(port=prt, queue_id=3)) match5 = of.ofp_match.from_packet( packet, inport) match5.dl_type = 0x800 match5.nw_proto = 17 match5.nw_dst = IPAddr("172.16.0.3") match5.tp_dst = 5001 match5.dl_src = None msg5 = of.ofp_flow_mod( command=of.OFPFC_ADD, idle_timeout=FLOW_IDLE_TIMEOUT, hard_timeout=of.OFP_FLOW_PERMANENT, buffer_id=bid, actions=actions5, priority=43, match=match5) event.connection.send(msg5.pack()) print "privillaged user into queue 3" elif ip_packet.tos == 0: actions2 = [] actions2.append( of.ofp_action_dl_addr.set_dst(mac)) #actions2.append(of.ofp_action_output(port = prt)) actions2.append(of.ofp_action_nw_tos(224)) actions2.append( of.ofp_action_enqueue(port=prt, queue_id=2)) match2 = of.ofp_match.from_packet( packet, inport) match2.dl_type = 0x800 if udp_packet != None: match2.nw_proto = 17 else: match2.nw_proto = 6 match2.dl_src = None msg2 = of.ofp_flow_mod( command=of.OFPFC_ADD, idle_timeout=FLOW_IDLE_TIMEOUT, hard_timeout=of.OFP_FLOW_PERMANENT, buffer_id=bid, actions=actions2, priority=42, match=match2) event.connection.send(msg2.pack()) print "into queue 2" else: actions1 = [] actions1.append( of.ofp_action_dl_addr.set_dst(mac)) #actions1.append(of.ofp_action_output(port = prt)) actions1.append( of.ofp_action_enqueue(port=prt, queue_id=2)) match1 = of.ofp_match.from_packet( packet, inport) match1.dl_type = 0x800 match1.nw_tos = 224 match1.dl_src = None msg1 = of.ofp_flow_mod( command=of.OFPFC_ADD, idle_timeout=FLOW_IDLE_TIMEOUT, hard_timeout=of.OFP_FLOW_PERMANENT, buffer_id=bid, actions=actions1, priority=42, match=match1) event.connection.send(msg1.pack()) print "into queue 2 dscp tagged" else: actions = [] actions.append(of.ofp_action_dl_addr.set_dst(mac)) actions.append(of.ofp_action_output(port=prt)) match4 = of.ofp_match.from_packet(packet, inport) match4.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=bid, actions=actions, priority=20, match=match4) event.connection.send(msg.pack()) elif self.arp_for_unknowns: 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] self.outstanding_arps = { k: v for k, v in self.outstanding_arps.iteritems() if v > time.time() } if (dpid, dstaddr) in self.outstanding_arps: return 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, 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)) 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.ip_mac_port[dpid]: if self.ip_mac_port[dpid][a.protosrc] != ( inport, packet.src): log.debug("%i %i RE-learned %s", dpid, inport, str(a.protosrc)) else: log.info("switch %i learned %s from input port %i", dpid, str(a.protosrc), inport) self.ip_mac_port[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 in self.ip_mac_port[dpid]: # We have an answer... if not self.ip_mac_port[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 = self.ip_mac_port[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" % (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("%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, data=event.ofp, action=of.ofp_action_output(port=of.OFPP_FLOOD)) event.connection.send(msg)
def _handle_PacketIn(self, event): # parsing the input packet packet = event.parse() # If no switch has ever seen this host before, then it must be directly # connected to us! Record that in our global list. if packet.src not in self.hostlocations or self.hostlocations[ packet.src]["lastseen"] < (datetime.now() - timedelta(0, IDLE_TIMEOUT)): #log.debug("s%s takes ownership of host %s" % (self.connection.ID, packet.src)) self.hostlocations[packet.src] = { "ID": self.connection.ID, "lastseen": datetime.now() } # Record which hosts exists on which of our ports ip = GetIPFromMAC(packet.src) if ip is not None: #log.debug(" on IP '%s'" % ip) self.hostports[event.port] = packet.src elif self.hostlocations[packet.src]["ID"] == self.connection.ID: #log.debug("s%s continues to own host %s" % (datetime.now(), self.connection.ID, packet.src)) self.hostlocations[packet.src]["lastseen"] = datetime.now() # Keep a list of which MAC addresses live on which port, so we can forward # packets as needed if packet.src not in self.mactable or self.mactable[ packet.src] != event.ofp.in_port: self.mactable[packet.src] = event.ofp.in_port #log.debug("Learned port %s connects to %s" % (event.ofp.in_port, packet.src)) if packet.type == packet.LLDP_TYPE or packet.type == 0x86DD: # Drop LLDP packets # Drop IPv6 packets # send of command without actions msg = of.ofp_packet_out() msg.buffer_id = event.ofp.buffer_id msg.in_port = event.port self.connection.send(msg) return # Watch for ARP packets trying to discover a load-balance target. packet_arp = packet.find('arp') if packet_arp is not None and str( packet_arp.protodst).startswith(LOADBALANCE_TARGET): # Found one! Respond with a special MAC address, which our switches will # be able to identify easily for load-balancing. #log.debug('ARP Packet!!!! Looking for %s' % packet_arp.protodst) mac = GetMACForLoadBalancing() reply_arp = arp() reply_arp.hwtype = packet_arp.hwtype reply_arp.prototype = packet_arp.prototype reply_arp.hwlen = packet_arp.hwlen reply_arp.protolen = packet_arp.protolen reply_arp.opcode = arp.REPLY reply_arp.hwdst = packet_arp.hwsrc reply_arp.hwsrc = mac reply_arp.protodst = packet_arp.protosrc reply_arp.protosrc = packet_arp.protodst reply_eth = ethernet(type=packet.type, src=mac, dst=packet_arp.hwsrc) reply_eth.payload = reply_arp reply = of.ofp_packet_out(in_port=of.OFPP_NONE) reply.actions.append(of.ofp_action_output(port=event.port)) reply.data = reply_eth.pack() event.connection.send(reply) return # If this packet is being delivered to a special MAC, set up some flows to # get the data to the right place. packet_ipv4 = packet.find('ipv4') if IsMACForLoadBalancing(packet.dst) and packet_ipv4 is not None: eligibleports = [] for port in self.connection.features.ports: if port.port_no != event.port and not port.config & OFPPC_PORT_DOWN: eligibleports.append(port.port_no) port_out = random.choice(eligibleports) # Establish bi-directional flows! log.debug("Establishing load-balancing flows for %s <--> %s" % (packet.src, packet.dst)) flow_in = of.ofp_flow_mod() flow_out = of.ofp_flow_mod() flow_in.idle_timeout = flow_out.idle_timeout = IDLE_TIMEOUT flow_in.hard_timeout = flow_out.hard_timeout = HARD_TIMEOUT flow_in.match = of.ofp_match(dl_dst=packet.src, dl_src=packet.dst) flow_out.match = of.ofp_match(dl_dst=packet.dst, dl_src=packet.src) if port_out in self.hostports: # If we're delivering to a host (instead of another switch), we need # to rewrite some of the packet data, so that things line up properly # on each end. The sender sends to the special IP, and the receiver # should see the packet addressed to itself (and vice versa). log.debug("...which will be handled by %s" % (self.hostports[port_out])) flow_in.actions.append( of.ofp_action_dl_addr(of.OFPAT_SET_DL_SRC, packet.dst)) flow_in.actions.append( of.ofp_action_nw_addr(of.OFPAT_SET_NW_SRC, packet_ipv4.dstip)) flow_out.actions.append( of.ofp_action_dl_addr(of.OFPAT_SET_DL_DST, self.hostports[port_out])) flow_out.actions.append( of.ofp_action_nw_addr( of.OFPAT_SET_NW_DST, GetIPFromMAC(self.hostports[port_out]))) # We also need to update one of our match rules, since the packet will # be sent with a non-special MAC address. flow_in.match.dl_src = self.hostports[port_out] flow_in.actions.append(of.ofp_action_output(port=event.port)) flow_out.actions.append(of.ofp_action_output(port=port_out)) flow_in.in_port = port_out flow_out.in_port = event.port flow_out.data = event.ofp self.connection.send(flow_in) self.connection.send(flow_out) return elif packet.dst in self.mactable: # If we know the destination, but are being told about it, recreate the # flow, since this is either the initial discovery, or the flow expired. log.debug( "Establishing flow to deliver packets for %s to port %s" % (packet.dst, self.mactable[packet.dst])) fm = of.ofp_flow_mod() fm.idle_timeout = IDLE_TIMEOUT fm.hard_timeout = HARD_TIMEOUT fm.actions.append( of.ofp_action_output(port=self.mactable[packet.dst])) # Defining the match via from_packet will cause us to establish a flow # for each unique packet type per destination, instead of just per dest. fm.match = of.ofp_match(dl_dst=packet.dst, dl_src=packet.src) #fm.match = of.ofp_match.from_packet(packet) fm.data = event.ofp # Deliver the packet along this flow self.connection.send(fm) return log.debug("Port for %s unknown -- flooding" % (packet.dst, )) msg = of.ofp_packet_out() 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 forward(message=None): # dpid => switch (i) dpid = event.connection.dpid # port of a switch inport = event.port packet = event.parsed log.debug("Add to forward table src=%s, port=%s" % (packet.src, event.port)) # self.macToPort[packet.src] = event.port if dpid not in self.forwardTable: self.forwardTable[dpid] = {} if packet.type == ethernet.LLDP_TYPE: # Ignore LLDP packets return if isinstance(packet.next, ipv4): log.debug("IPV4 packet s=%i, sp=%i src=%s => dst=%s", dpid, inport, packet.next.srcip, packet.next.dstip) if (packet.next.protocol == packet.next.TCP_PROTOCOL): # Get TCP payload in IPv4 tcpPacket = packet.next.payload log.debug("TCP payload srcport= %s dstport=%s", str(tcpPacket.srcport), str(tcpPacket.dstport)) # Check firewall if self.check_rule(packet.next.srcip, packet.next.dstip, tcpPacket.dstport) or self.check_rule( packet.next.dstip, packet.next.srcip, tcpPacket.dstport): log.warning( "Firewall DROP between %s <--> %s on port %s", str(packet.next.srcip), str(packet.next.dstip), str(tcpPacket.dstport)) drop(priorityFirewall) return # Send any waiting packets... self._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport) # Learn or update forwarding table log.debug("s=%i, sp=%i LEARN or UPDATE src=%s", dpid, inport, str(packet.next.srcip)) self.forwardTable[dpid][packet.next.srcip] = Entry( inport, packet.src) # Try to forward to destination by checking port dstip = packet.next.dstip if (dstip in self.forwardTable[dpid]): # Got the port info to send out dstport = self.forwardTable[dpid][dstip].port dstmac = self.forwardTable[dpid][dstip].mac if dstport == inport: # Same port for destination and switch.. log.warning( "s=%i, sp=%i NOT SEND PACKET for dst=%s with same port" % (dpid, inport, str(dstip))) else: log.debug( "s=%i, sp=%i INSTALL FLOW for src=%s => dst=%s out port=%i" % (dpid, inport, packet.next.srcip, dstip, dstport)) actions = [] if self.check_premium(packet.next.dstip): actions.append( of.ofp_action_enqueue(port=dstport, queue_id=1)) else: actions.append(of.ofp_action_output(port=dstport)) # actions.append(of.ofp_action_output(port = dstport)) actions.append(of.ofp_action_dl_addr.set_dst(dstmac)) 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)) msg.priority = priorityPremium # if self.check_premium(packet.next.dstip): # log.debug("PRIORITY dst ip=%s has priority of 100!!!!!" % packet.next.dstip) # msg.priority = 100 # else: # log.debug("PRIORITY dst ip=%s has priority of 1...." % packet.next.dstip) # msg.priority = 1 # event.connection.send(msg.pack()) event.connection.send(msg) elif isinstance(packet.next, arp): pktnext = packet.next if pktnext.prototype == arp.PROTO_TYPE_IP: if pktnext.hwtype == arp.HW_TYPE_ETHERNET: if pktnext.protosrc != 0: # Learn or update port, mac info self.forwardTable[dpid][pktnext.protosrc] = Entry( inport, packet.src) # Send any waiting packets... self._send_lost_buffers(dpid, pktnext.protosrc, packet.src, inport) if pktnext.opcode == arp.REQUEST: if pktnext.protodst in self.forwardTable[dpid]: # Reply ARP back r = arp() r.hwtype = pktnext.hwtype r.prototype = pktnext.prototype r.hwlen = pktnext.hwlen r.protolen = pktnext.protolen r.opcode = arp.REPLY r.hwdst = pktnext.hwsrc r.protodst = pktnext.protosrc r.protosrc = pktnext.protodst r.hwsrc = self.forwardTable[dpid][ pktnext.protodst].mac e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=pktnext.hwsrc) e.set_payload(r) log.debug("s=%i sp=%i answer 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 log.debug("s=%i sp=%i FLOOD ARP %s %s => %s" % (dpid, inport, { arp.REQUEST: "request", arp.REPLY: "reply" }.get(pktnext.opcode, 'op:%i' % (pktnext.opcode, )), str(pktnext.protosrc), str(pktnext.protodst))) msg = of.ofp_packet_out( in_port=inport, data=event.ofp, action=of.ofp_action_output(port=of.OFPP_FLOOD)) # msg.priority = priorityLearn event.connection.send(msg)
def _handle_addFlowEntry (self,event): FLOW_IDLE_TIMEOUT = event.idleTimeout FLOW_HARD_TIMEOUT = event.hardTimeout event = event.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: # 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) else: log.debug("%i %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 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("%i %i not sending packet for %s back out of the " + "input port" % (dpid, inport, str(dstaddr))) else: log.debug("%i %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=FLOW_HARD_TIMEOUT, buffer_id=event.ofp.buffer_id, actions=actions, flags=of.OFPFF_SEND_FLOW_REM, match=of.ofp_match.from_packet(packet, inport)) event.connection.send(msg.pack()) 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, 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)) 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._send_lost_buffers(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... 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 = 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" % (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("%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, data = event.ofp, action = of.ofp_action_output(port = of.OFPP_FLOOD)) event.connection.send(msg)
EthAddr('00:00:00:00:00:07'))]) _port_to_mac_1 = { '1': EthAddr('00:00:00:00:00:05'), '2': EthAddr('00:00:00:00:00:04'), '3': EthAddr('00:00:00:00:00:04') } _port_to_mac_2 = { '1': EthAddr('00:00:00:00:00:06'), '2': EthAddr('00:00:00:00:00:07') } _ip_to_port = {} rqtsrc, rqtdst, rqtport, rqtpfx, rqthwsrc = 0, 0, 0, 0, 0 rplsrc, rpldst, rplport, rplpfx, rplhwsrc = 0, 0, 0, 0, 0 icmpf = icmp() ip_pakt = ipv4() eth = ethernet() _buff = {} _ip_bf = {} class controller3(object): '**********begin***************************' def __init__(self, connection): # Keep track of the connection to the switch so that we can # send it messages! self.connection = connection # This binds our PacketIn event listener connection.addListeners(self)
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[dpid]: 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[dpid]: if list[0] == str(dstaddr): log.debug("Searching Routing Table for IP address: %s ",str(dstaddr)) prt = list[4] log.debug("The mac address is %s",dpid_to_mac(dpid)) if list[3] == str(dstaddr): prt = list[4] #icmpflag = 1 self.arpTable[dpid][dstaddr] = Entry(prt, dpid_to_mac(dpid)) log.debug("The mac address is %s",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) log.debug("The inport %i The input mac address is %s",inport,str(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... log.debug("This is a known path") 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: self.arpTable[dpid][dstaddr] = Entry(prt, a.hwsrc) for list in self.routingTable[dpid]: 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 _handle_openflow_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed if dpid not in self.arpTable: # We've come across a new switch self.arpTable[dpid] = {} # Add the 10.0.0.10 false address in order to pick up on DNS traffic self.arpTable[dpid][IPAddr('10.0.0.10')] = Entry( of.OFPP_NONE, dpid_to_mac(dpid)) # The two types of packets we care about are IPv4 and ARP packets, so that's all we will check for. if isinstance(packet.next, ipv4): # Check and see if the IPv4 packet is a DNS packet or not if packet.next.find('dns'): pac = packet.next.find('dns') # Loop through each of the questions, though in this assignment there should only be one for question in pac.questions: # If they are looking for the protected host, in this case h3, then resolve the DNS if question.name[:2] == 'h3': log.debug(" Received DNS request for %s", question.name) # Make a new IP address. Simple algorithm, starts at 10.0.0.11 and goes up from there each time. newIP = IPAddr('10.0.0.' + str(self.ipOffset)) self.ipOffset += 1 log.debug(" Sent bogus IP Address %s to %s", newIP, packet.next.srcip) self.ipMapping[packet.next.srcip] = newIP # Set up the reply DNS packet and send it out pac.answers.append( pac.rr(question.name, question.qtype, question.qclass, 100, str(len(newIP)), newIP)) pac.qr = True pac.ra = True udpp = udp() udpp.dstport = packet.next.find('udp').srcport udpp.srcport = packet.next.find('udp').dstport udpp.payload = pac ipp = ipv4() ipp.protocol = ipp.UDP_PROTOCOL ipp.srcip = packet.next.dstip ipp.dstip = packet.next.srcip ipp.payload = udpp e = ethernet(type=ethernet.IP_TYPE, src=packet.dst, dst=packet.src) 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) else: # Just a normal IPv4 packet log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip, packet.next.dstip) storesrc = packet.next.srcip if packet.next.srcip in self.ipMapping: packet.next.dstip = self.trueIP log.debug(" Translated %s to %s", self.ipMapping[packet.next.srcip], self.trueIP) elif packet.next.dstip in self.ipMapping: log.debug(" Translated %s to %s", self.trueIP, self.ipMapping[packet.next.dstip]) packet.next.srcip = self.ipMapping[packet.next.dstip] # Empty out the buffer of pending packets self._send_buffer(dpid, packet.next.srcip, packet.src, inport) # If we haven't seen the source IP before, add it to the ARP table if packet.next.srcip not in self.arpTable[dpid]: log.debug("%i %i learned %s", dpid, inport, packet.next.srcip) self.arpTable[dpid][packet.next.srcip] = Entry( inport, packet.src) # Rather than using flows, since each packet needs to have the protected IP modified # we need to see every packet. This forwards the packet with the modified IP address. if packet.next.dstip in self.arpTable[dpid]: packet.dst = self.arpTable[dpid][packet.next.dstip].mac msg = of.ofp_packet_out() msg.actions.append( of.ofp_action_output( port=self.arpTable[dpid][packet.next.dstip].port)) msg.data = packet.pack() msg.in_port = event.port event.connection.send(msg) elif isinstance(packet.next, arp): # Got an ARP packet ap = packet.next which = { arp.REQUEST: 1, arp.REPLY: 0 }.get(ap.opcode, 'op:%i' % (ap.opcode, )) # Save the old values to have the correct mappings to internal structures. storesrc = ap.protosrc storedst = ap.protodst # See if this is a request or a reply ARP in order to swap the right IP address. if ap.opcode == arp.REQUEST: if ap.protosrc in self.ipMapping: log.debug(" Translated %s to %s", self.ipMapping[ap.protosrc], self.trueIP) ap.protodst = self.trueIP elif ap.protosrc == self.trueIP: if ap.protodst in self.ipMapping: ap.protosrc = self.ipMapping[ap.protodst] log.debug("%i %i ARP %s %s => %s", dpid, inport, { arp.REQUEST: "request", arp.REPLY: "reply" }.get(ap.opcode, 'op:%i' % (ap.opcode, )), ap.protosrc, ap.protodst) if ap.prototype == arp.PROTO_TYPE_IP: if ap.hwtype == arp.HW_TYPE_ETHERNET: if ap.protosrc != 0: # If the source is new to us, add it to the ARP table if storesrc not in self.arpTable[dpid]: log.debug("%i %i learned %s", dpid, inport, storesrc) self.arpTable[dpid][storesrc] = Entry( inport, packet.src) # Send any waiting packets self._send_buffer(dpid, ap.protosrc, packet.src, inport) if ap.opcode == arp.REQUEST: if ap.protodst in self.arpTable[dpid]: # There is a matching entry in the ARP table if not self.arpTable[dpid][ ap.protodst].isExpired(): # .. and it's relatively current, so we'll reply ourselves r = arp() r.hwtype = ap.hwtype r.prototype = ap.prototype r.hwlen = ap.hwlen r.protolen = ap.protolen r.opcode = arp.REPLY r.hwdst = ap.hwsrc r.protodst = ap.protosrc r.protosrc = storedst r.hwsrc = self.arpTable[dpid][ ap.protodst].mac e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=ap.hwsrc) e.set_payload(r) log.debug("%i %i answering ARP for %s" % (dpid, inport, 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 # To prevent the hosts from knowing the protected IP, retransmit all ARPs from the controller if (dpid, ap.protodst) not in self.buffer: self.buffer[(dpid, ap.protodst)] = [] bucket = self.buffer[(dpid, ap.protodst)] entry = (time.time() + 5, event.ofp.buffer_id, inport) bucket.append(entry) while len(bucket) > 5: 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 to prevent spamming if (dpid, ap.protodst) in self.outstanding_arps: return self.outstanding_arps[(dpid, ap.protodst)] = time.time() + 4 # Send out the ARP 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 = ap.protodst r.hwsrc = packet.src r.protosrc = storesrc 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)