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 _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 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 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 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, 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 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 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 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 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 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 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 _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, 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 _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 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 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 _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 _send_arp_response_packet(self, arpp, out_port): r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.opcode = r.REPLY r.hwdst = arpp.hwsrc r.protodst = arpp.protosrc r.hwsrc = self.my_mac r.protosrc = self.my_ip self._send_ethernet_packet(ethernet.ARP_TYPE, self.my_mac, arpp.hwsrc, r, out_port)
def buildArpReply (self, arp_request): arp_packet = arp() arp_packet.hwsrc = EthAddr('00:00:0:01:01:01') arp_packet.hwdst = arp_request.hwsrc arp_packet.opcode = arp.REPLY arp_packet.protosrc = IPAddr('10.1.1.1') arp_packet.protodst = arp_request.protosrc eth = pkt.ethernet(type=pkt.ethernet.ARP_TYPE) eth.src = arp_packet.hwsrc eth.dst = arp_packet.hwdst eth.payload = arp_packet return eth
def handle_arp(self, event, packet): ''' Handle the arp request if we can Note - this code was derived/inspired from the l3_learning.py switch in POX ''' log.debug("we got an ARP packet!!!" + str(event.connection.dpid)) arp_req = packet.next if arp_req.prototype == arp.PROTO_TYPE_IP and arp_req.hwtype == arp.HW_TYPE_ETHERNET and arp_req.protosrc != 0: log.debug("ARP proto source..." + str(arp_req.protosrc) + str(arp_req.protodst)) # update the arp table self.arptable[arp_req.protosrc] = (event.port, packet.src, time.time() * ARP_TIMEOUT) # see if we can handle the arp request (we know the dst and it hasn't expired) if arp_req.opcode == arp.REQUEST and arp_req.protodst in self.arptable and self.arptable[arp_req.protodst][2] > time.time(): # we can respond to the ARP request log.debug("responding to ARP request...") # 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 = self.arptable[arp_req.protodst][1] # create an ethernet package that contains the arp response we created above e = ethernet(type=packet.type, src=dpid_to_mac(event.connection.dpid), 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) return # we don't know where this mac is, flood the packet log.debug("flooding ARP packet!" + str(self.arptable)) self.flood_packet(event) return
def handle_arp (self, packet, in_port): print "ARP Packet Arrived at Router R"+str(self.connection.dpid)+" at Interface"+str(in_port) if packet.payload.opcode == arp.REQUEST: arp_req = packet.next # Create ARP reply arp_rep = arp() arp_rep.opcode = arp.REPLY # Show the client that it's actually the me arp_rep.hwsrc = self.EthAddr arp_rep.hwdst = arp_req.hwsrc arp_rep.protosrc = self.IPAddr arp_rep.protodst = arp_req.protosrc # Create the Ethernet packet eth = ethernet() eth.type = ethernet.ARP_TYPE eth.dst = packet.src eth.src = self.EthAddr 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) print "arp reply DONE" if packet.payload.opcode == arp.REPLY: self.arp_table[packet.next.protosrc]=packet.src que1=[] for tpl in self.que: eth=tpl[0] Interface=tpl[1] prt=tpl[2] if eth.payload.dstip==packet.next.protosrc: eth.dst=packet.src msg = of.ofp_packet_out() msg.data = eth.pack() # print "inport",of.OFPP_IN_PORT # print "outport",int(Interface) msg.actions.append(of.ofp_action_output(port = int(Interface))) msg.in_port = prt self.connection.send(msg) else: que1.append(tpl) self.que=que1
def send_arp_reply(self, connection, src_mac, src_ip, dst_mac, dst_ip, port_out): r = arp() r.opcode = r.REPLY r.hwsrc = EthAddr(src_mac) r.protosrc = IPAddr(src_ip) r.hwdst = EthAddr(dst_mac) r.protodst = IPAddr(dst_ip) e = ethernet(type=ethernet.ARP_TYPE, src=EthAddr(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=port_out)) msg.in_port = of.OFPP_NONE connection.send(msg)
def send_arp_request(self, req_ip, port): my_arp = arp() my_arp.opcode = arp.REQUEST my_arp.protosrc = IPAddr(port.ip) my_arp.protodst = IPAddr(req_ip) my_arp.hwdst = EthAddr('FF:FF:FF:FF:FF:FF') my_arp.hwsrc = EthAddr(port.mac) my_ether = ethernet() my_ether.type = ethernet.ARP_TYPE my_ether.dst = EthAddr('FF:FF:FF:FF:FF:FF') my_ether.src = EthAddr(port.mac) my_ether.payload = my_arp self.send_packet(None, my_ether, port.id, of.OFPP_NONE)
def _sendArpReq(self, destIp, outPort): r = arp() r.opcode = arp.REQUEST r.hwsrc = self.getPort(outPort).mac r.hwdst = ETHER_BROADCAST r.protodst = IPAddr(destIp) r.protosrc = self.getPort(outPort).ip e = ethernet(type = ethernet.ARP_TYPE, src = r.hwsrc, dst = r.hwdst) e.set_payload(r) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = outPort)) self.connection.send(msg)
def _handle_PacketIn(self, event): inport = event.port eth_packet = event.parsed # If packet is not parsed properly, alert if not eth_packet.parsed: log.warning("Unparsed packet") return # The ethernet packet carries an ARP packet if isinstance(eth_packet.next, arp): log.info("ARP packet has been received") arp_packet = eth_packet.next # Do src learning if possible if not self.icp_arp_table.Exists(arp_packet.protosrc): self.icp_arp_table.Insert(arp_packet.protosrc, arp_packet.hwsrc) log.info("Source learning: %s -> %s", arp_packet.protosrc, arp_packet.hwsrc) if arp_packet.opcode == arp.REQUEST: log.info("This is an ARP request") log.info("Entry found for %s? %s", arp_packet.protodst, self.icp_arp_table.Exists(arp_packet.protodst)) if self.icp_arp_table.Exists(arp_packet.protodst): log.info("The mapping is stored in the table") arp_reply = arp() arp_reply.hwtype = arp_packet.hwtype arp_reply.prototype = arp_packet.prototype arp_reply.hwlen = arp_packet.hwlen arp_reply.protolen = arp_packet.protolen arp_reply.opcode = arp.REPLY arp_reply.hwdst = arp_packet.hwsrc arp_reply.protodst = arp_packet.protosrc arp_reply.protosrc = arp_packet.protodst arp_reply.hwsrc = self.icp_arp_table.Find(arp_packet.protodst) # Currently the src addres is set to the destination of query # I doubt whether it should be the MAC of controller eth_reply = ethernet(type=ethernet.ARP_TYPE, src=arp_reply.hwsrc, dst=arp_reply.hwdst) eth_reply.set_payload(arp_reply) msg = of.ofp_packet_out() msg.data = eth_reply.pack() # I doubt whether the pack is needed here msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) return
def send_arp_request(self, connection, src_mac, src_ip, dst_ip, port_out): r = arp() r.opcode = r.REQUEST r.hwsrc = EthAddr(src_mac) r.protosrc = IPAddr(src_ip) r.hwdst = ETHER_BROADCAST r.protodst = IPAddr(dst_ip) e = ethernet(type=ethernet.ARP_TYPE, src=EthAddr(src_mac), dst=r.hwdst) e.payload = r msg = of.ofp_packet_out() msg.data = e.pack() if port_out is None: port_out = of.OFPP_FLOOD msg.actions.append(of.ofp_action_output(port=port_out)) msg.in_port = of.OFPP_NONE connection.send(msg)
def _hanle_arp_request(self, event): """ Process ARP request packet """ eth_packet = event.parsed arp_packet = eth_packet.payload LOGGER.info("ARP request: ip=%s query ip=%s", arp_packet.protosrc, arp_packet.protodst) # If entry not found, store the event and broadcast request if arp_packet.protodst not in self.ip_to_mac: LOGGER.info("Entry for %s not found, buffer and broadcast request", arp_packet.protodst) for conn in core.openflow.connections: conn_ports = conn.features.ports # Sift out ports connecting to hosts but vxlan peers host_ports = [port.port_no for port in conn_ports if port.port_no not in self.inception.dpid_ip_to_port.values()] actions_out_ports = [of.ofp_action_output(port=port) for port in host_ports] core.openflow.sendToDPID(conn.dpid, of.ofp_packet_out( data=eth_packet.pack(), action=actions_out_ports)) # Entry exists else: # setup data forwrading flows dst_mac = self.ip_to_mac[arp_packet.protodst] switch_id = event.dpid self._setup_data_fwd_flows(switch_id, dst_mac) # construct ARP reply packet and send it to the host LOGGER.info("Hit: dst_ip=%s, dst_mac=%s", arp_packet.protodst, dst_mac) arp_reply = arp(opcode=arp.REPLY, hwdst=arp_packet.hwsrc, hwsrc=dst_mac, protodst=arp_packet.protosrc, protosrc=arp_packet.protodst) eth_reply = ethernet(type=ethernet.ARP_TYPE, src=arp_reply.hwsrc, dst=arp_reply.hwdst) eth_reply.payload = arp_reply event.connection.send(of.ofp_packet_out( data=eth_reply.pack(), action=of.ofp_action_output(port=event.port))) LOGGER.info("Send ARP reply to host=%s on port=%s on behalf of " "ip=%s", arp_reply.protodst, event.port, arp_reply.protosrc)
def _handle_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed # Ignore LLDP packets if packet.type == ethernet.LLDP_TYPE: return if isinstance(packet.next, arp): # ARP packet a = packet.next inport = event.port 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)) print packet.next 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.mac_to_ip: log.debug("IP present in mac to ip table") else: # print a.hwsrc self.mac_to_ip[a.protosrc] = a.hwsrc # print self.mac_to_ip # 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.mac_to_ip or a.hwdst == EthAddr( "00:00:00:00:00:00"): # We have an answer... # print "..........." # Creating new ARP packet 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 for entry in event.connection.ports.values(): port = entry.port_no if port == inport: mac = entry.hw_addr r.hwsrc = 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))) # Creating new message 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 "Ipv4" log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip, packet.next.dstip) inport = event.port # Send any waiting packets... self._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport) # Learn or update port/MAC info print packet.next.srcip print packet.src if packet.next.srcip in self.mac_to_ip: log.debug("IP present in mac to ip table") else: self.mac_to_ip[packet.next.srcip] = packet.src # Try to forward dstaddr = packet.next.dstip if dstaddr in self.mac_to_ip: # We have info about what port to send it out on... # print "Checking dstaddr..." prt = int(routing_table[dpid][str(dstaddr)][1]) mac = self.mac_to_ip[dstaddr] print inport, prt, mac # Creating new Message 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 match.dl_dst = 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=match) # print "Message: " event.connection.send(msg) else: # 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 = (event.ofp.buffer_id, inport) bucket.append(entry) # print "Flood..." 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)
def _handle_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = copy.deepcopy(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)) # store the mac, ip info of the DNS SERVER into arpTable self.arpTable[dpid][IPAddr(IP_OF_DNS_SERVER)] = Entry( 6633, EthAddr(MAC_OF_DNS_SERVER)) if packet.type == ethernet.LLDP_TYPE: # Ignore LLDP packets return p = packet.find('dns') if p is not None and p.parsed: # Get dstName of the DNS Query dstname = '' for question in p.questions: dstname = question.name log.debug("DNS Query msg from %s: asking ip address for %s", packet.next.srcip, dstname) # 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) # generate random virtual ip for internal node n = random.randint(128, 254) vip = "10.0.0." + str(n) #add the srcip and virtual destination ip pair into srcip_dstip_map self.srcip_dstvip_map[str(packet.next.srcip)] = vip # forming answer answer = dns.rr(dstname, 1, 1, 5, len(vip), IPAddr(vip)) # write dns reply msg d = dns() d.questions = p.questions d.answers.append(answer) d.authorities = [] d.additional = [] d.id = p.id d.qr = True # dns reply d.opcode = 0 # standard d.aa = False d.tc = False d.rd = False d.ra = False d.z = False d.ad = False d.cd = False d.rcode = 0 e = ethernet(type=ethernet.IP_TYPE, src=MAC_OF_DNS_SERVER, dst=str(packet.src)) ip = ipv4(srcip=IPAddr(IP_OF_DNS_SERVER)) ip.dstip = packet.next.srcip ip.protocol = ip.UDP_PROTOCOL u = udp() u.srcport = dns.SERVER_PORT # get srcport from the packet and set it to the udp's dstport m = packet.find("udp") m.parsed u.dstport = m.srcport u.payload = d ip.payload = u e.payload = ip msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_nw_addr.set_dst( packet.next.srcip)) msg.actions.append(of.ofp_action_dl_addr.set_dst(packet.src)) msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) log.debug( " DNS reply msg has been sent to %s: %s's ip address is %s" % (str(packet.next.srcip), dstname, vip)) elif isinstance(packet.next, ipv4): log.debug("IPv4 msg: %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) print "Have sent lost buffers" # 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) srcaddr = packet.next.srcip dstaddr = packet.next.dstip if (dstaddr in self.vipList): self.srcip_dstvip_map[srcaddr] = dstaddr dstaddr = IPAddr(REAL_IP_OF_INTERNAL_HOST) 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 # Try to forward icmpmsg = packet.find("icmp") icmpmsg.parsed # icmp echo reply from internal host if icmpmsg.type == 0 and srcaddr == IPAddr( REAL_IP_OF_INTERNAL_HOST): log.info("ICMP echo reply msg from %s to %s", srcaddr, packet.next.dstip) 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)) # add flow entry msg = of.ofp_flow_mod(command=of.OFPFC_ADD) msg.match.dl_type = 0x0800 #ipv4 msg.match.nw_src = REAL_IP_OF_INTERNAL_HOST msg.match.nw_dst = dstaddr # change the srcip to virtual ip msg.actions.append( of.ofp_action_nw_addr.set_src( IPAddr(self.srcip_dstvip_map[dstaddr]))) msg.actions.append(of.ofp_action_dl_addr.set_dst(mac)) msg.actions.append(of.ofp_action_output(port=prt)) event.connection.send(msg) log.info( "ICMP echo reply flow entry for internal node to %s has been installed", packet.next.dstip) # icmp echo reply for internal host elif icmpmsg.type == 8 and dstaddr == IPAddr( REAL_IP_OF_INTERNAL_HOST): log.info("ICMP echo request msg from %s to %s", packet.next.srcip, packet.next.dstip) 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)) msg = of.ofp_flow_mod(command=of.OFPFC_ADD) msg.match.dl_type = 0x0800 #ipv4 msg msg.match.in_port = inport msg.match.nw_dst = "10.0.0.128/255.255.255.128" msg.actions.append(of.ofp_action_nw_addr.set_dst(dstaddr)) msg.actions.append(of.ofp_action_output(port=prt)) msg.actions.append(of.ofp_action_dl_addr.set_dst(mac)) event.connection.send(msg) log.info( "ICMP echo request flow entry for %s to internal host has been instaled", packet.next.srcip) else: log.warning("Uninvolved icmp msg type") return 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 if dstaddr in self.vipList: r.protodst = IPAddr(REAL_IP_OF_INTERNAL_HOST) else: 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 for Ipv4" % (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 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.protodst in self.vipList: self.srcip_dstvip_map[a.protosrc] = str(a.protodst) a.protodst = REAL_IP_OF_INTERNAL_HOST log.info("%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.REPLY: r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwsrc = a.hwsrc if a.protosrc == IPAddr(REAL_IP_OF_INTERNAL_HOST): if a.protodst in self.srcip_dstvip_map: r.protosrc = IPAddr( self.srcip_dstvip_map[a.protodst]) else: r.protosrc = a.protosrc r.protodst = a.protodst r.hwdst = self.arpTable[dpid][a.protodst].mac e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwdst) e.set_payload(r) log.debug("%i %i answering ARP for %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=self.arpTable[dpid][a.protodst].port)) msg.in_port = inport event.connection.send(msg) return if a.opcode == arp.REQUEST: # Maybe we can answer if a.protodst in self.vipList: self.srcip_dstvip_map[a.protosrc] = str( a.protodst) a.protodst = IPAddr(REAL_IP_OF_INTERNAL_HOST) 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.hwsrc = self.arpTable[dpid][ a.protodst].mac r.protodst = a.protosrc if a.protodst == IPAddr( REAL_IP_OF_INTERNAL_HOST): r.protosrc = IPAddr( self.srcip_dstvip_map[a.protosrc]) else: r.protosrc = a.protodst 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))) r1 = arp() r1.hwtype = a.HW_TYPE_ETHERNET r1.prototype = a.PROTO_TYPE_IP r1.hwlen = 6 r1.protolen = a.protolen r1.opcode = arp.REQUEST r1.hwdst = ETHER_BROADCAST r1.protodst = IPAddr(a.protodst) r1.hwsrc = a.hwsrc r1.protosrc = a.protosrc e1 = ethernet(type=ethernet.ARP_TYPE, src=a.hwsrc, dst=ETHER_BROADCAST) e1.set_payload(r1) log.debug("%i %i ARPing for %s on behalf of %s" % (dpid, inport, str( r1.protodst), str(r1.protosrc))) msg1 = of.ofp_packet_out() msg1.data = e1.pack() msg1.actions.append( of.ofp_action_output(port=of.OFPP_FLOOD)) msg1.in_port = inport event.connection.send(msg1)
def _handle_PacketIn(self, event): self.packetin = self.packetin + 1 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 print "new switch" 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 flag = 0 # This part of code handles packet in and write to file.py count variable that informs # us how many malicious packets Arrived to Virtual IPs ################################################################################################### if isinstance(packet.next, ipv4): if (self.isVirtualIPAddress(str(packet.next.dstip))): flag = 1 elif (self.isRealIPAddress(str(packet.next.dstip))): flag = 1 if (flag == 0): print "Unknown IP: %s,Dropping packet" % str(packet.next.dstip) if isinstance(packet.next, arp): print "after if arp: %s " % str(packet.next.protodst) if (self.isVirtualIPAddress(str(packet.next.protodst))): flag = 1 self.count = self.count + 1 print "$$$$$$$$$$ count = %i $$$$$$$$$$" % self.count if (flag == 0): print "Unknown IP: %s,Dropping packet" % str( packet.next.protodst) f = open('file.py', 'w') f.write('count = ' + str(self.count) + ' ' + 'num of packts in:' + ' ' + str(self.packetin) + '\n') f.close() ######################################################################################## # handling IPV4 packets if isinstance(packet.next, ipv4): log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip, packet.next.dstip) srcaddr = packet.next.srcip srcaddr_old = packet.next.srcip dstaddr = packet.next.dstip dstaddr_old = packet.next.dstip # if source is virtual we change it to real if self.isVirtualIPAddress(str(srcaddr)): srcaddr = IPAddr(self.V2R_Map[str(srcaddr)]) print("Changing SRC VIRTUAL IP " + self.R2V_Map[str(srcaddr)] + "---> REAL SRC IP " + str(srcaddr)) # if destination is virtual we change it to real if self.isVirtualIPAddress(str(dstaddr)): dstaddr = IPAddr(self.V2R_Map[str(dstaddr)]) print("Changing DST VIRTUAL IP " + self.R2V_Map[str(dstaddr)] + "---> REAL SRC IP " + str(dstaddr)) # if the IP was real we update HostMem (ip---dpid) mapping if self.isRealIPAddress( str(srcaddr_old)) and srcaddr not in self.HostMem.keys(): self.HostMem[srcaddr] = dpid dpid = self.HostMem[srcaddr] if self.isRealIPAddress( str(dstaddr_old)) and dstaddr not in self.HostMem.keys(): self.HostMem[dstaddr] = dpid dpid = self.HostMem[dstaddr] #update the correct macaddr if self.isVirtualIPAddress(str(srcaddr_old)): macaddr = dpid_to_mac(dpid) else: macaddr = packet.src self._send_lost_buffers(dpid, srcaddr, macaddr, inport) # Learn or update the correct port/MAC fron arpTable if srcaddr in self.arpTable[dpid]: if self.arpTable[dpid][srcaddr] != (inport, macaddr): log.info("%i %i RE-learned %s", dpid, inport, srcaddr) else: log.debug("%i %i learned %s", dpid, inport, str(srcaddr)) # if source was real update arpTable if (self.isRealIPAddress(str(srcaddr_old))): self.arpTable[dpid][srcaddr] = Entry(inport, macaddr) # if source was virtual take the correct values from arpTable # mininet give us wrong values when we use virtual IP if self.isVirtualIPAddress(str(srcaddr_old)): inport = self.arpTable[dpid][srcaddr].port macaddr = self.arpTable[dpid][srcaddr].mac # if we have a destination forward the packet 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, str(dstaddr))) else: log.debug( "%i %i installing flow for %s => %s out port %i" % (dpid, inport, srcaddr, 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()) # if we don't have a destination drop the packet. elif not (self.isRealIPAddress( str(dstaddr))) or not (self.isRealIPAddress(str(srcaddr))): po = of.ofp_packet_out(buffer_id=buffer_id, in_port=in_port) core.openflow.sendToDPID(dpid, po) log.warning( "Moving Targed Defense has blocked a packet from unknown source" ) # handles arp packet 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)) dstaddr2 = a.protodst dstaddr2_old = a.protodst srcaddr2 = a.protosrc srcaddr2_old = srcaddr2 if self.isVirtualIPAddress(str(srcaddr2)): srcaddr2 = IPAddr(self.V2R_Map[str(srcaddr2)]) print("arp: Changing SRC VIRTUAL IP " + self.R2V_Map[str(srcaddr2)] + "---> REAL SRC IP " + str(srcaddr2)) if self.isVirtualIPAddress(str(dstaddr2)): dstaddr2 = IPAddr(self.V2R_Map[str(dstaddr2)]) print("arp: Changing DST VIRTUAL IP " + self.R2V_Map[str(dstaddr2)] + "---> REAL DST IP " + str(dstaddr2)) if self.isRealIPAddress( str(srcaddr2_old)) and srcaddr2 not in self.HostMem.keys(): self.HostMem[srcaddr2] = dpid if self.isRealIPAddress( str(dstaddr2_old)) and dstaddr2 not in self.HostMem.keys(): self.HostMem[dstaddr2] = dpid dpid = self.HostMem[srcaddr2] if self.isVirtualIPAddress(str(srcaddr2_old)): macaddr = dpid_to_mac(dpid) else: macaddr = packet.src #macaddr = self.arpTable[dpid][srcaddr2].mac a.prototype = arp.PROTO_TYPE_IP a.hwtype = arp.HW_TYPE_ETHERNET if srcaddr2 != 0: # Learn or update port/MAC info if srcaddr2 in self.arpTable[dpid]: if self.arpTable[dpid][srcaddr2] != (inport, macaddr): log.info("%i %i RE-learned %s", dpid, inport, str(srcaddr2)) else: log.debug("%i %i learned %s", dpid, inport, str(srcaddr2)) if (self.isRealIPAddress(str(srcaddr2_old))): self.arpTable[dpid][srcaddr2] = Entry(inport, macaddr) if self.isVirtualIPAddress(str(srcaddr2_old)): #for keys,values in self.HostMem : # print (keys) #print (values) inport = self.arpTable[dpid][srcaddr2].port # Send any waiting packets... self._send_lost_buffers(dpid, str(srcaddr2), macaddr, inport) if a.opcode == arp.REQUEST: # Check if we can answer dstaddr2 = a.protodst if dstaddr2 in self.arpTable[dpid]: # destination exists if not self.arpTable[dpid][dstaddr2].isExpired(): # We will 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 = IPAddr(self.ReturnRealIP(srcaddr2)) r.protosrc = IPAddr(self.ReturnRealIP(dstaddr2)) r.hwsrc = self.arpTable[dpid][dstaddr2].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 # if source and dest were not virtual or real we dropp the packet elif not (self.isRealIPAddress(str(dstaddr2))) or not ( self.isRealIPAddress(str(srcaddr2))): po = of.ofp_packet_out(buffer_id=buffer_id, in_port=in_port) core.openflow.sendToDPID(dpid, po) log.warning( "Moving Targed Defense has blocked a packet from unknown source" ) srcaddr2_old = srcaddr2 # unrecognized arp: if source is recognized av Virtual or Real than # we flood the packet throgh the network if self.isVirtualIPAddress(str(srcaddr2)): srcaddr2 = IPAddr(self.V2R_Map[str(srcaddr2)]) print("arp flood: Changing SRC VIRTUAL IP " + self.R2V_Map[str(srcaddr2)] + "---> REAL SRC IP " + str(srcaddr2)) if self.isVirtualIPAddress(str(dstaddr2)): dstaddr2 = IPAddr(self.V2R_Map[str(dstaddr2)]) print("arp flood: Changing DST VIRTUAL IP " + self.R2V_Map[str(dstaddr2)] + "---> REAL DST IP " + str(dstaddr2)) if self.isRealIPAddress( str(srcaddr2_old)) and srcaddr2 not in self.HostMem.keys(): self.HostMem[srcaddr2] = dpid dpid = self.HostMem[srcaddr2] macaddr = self.arpTable[dpid][srcaddr2].mac macaddr = dpid_to_mac(dpid) if self.isVirtualIPAddress(str(srcaddr2_old)): inport = self.arpTable[dpid][srcaddr2].port # 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(srcaddr2), str(dstaddr2))) msg = of.ofp_packet_out( in_port=inport, data=event.ofp, action=of.ofp_action_output(port=of.OFPP_FLOOD)) event.connection.send(msg)
class l3_switch (EventMixin): def __init__ (self, fakeways = [], arp_for_unknowns = False): # These are "fake gateways" -- we'll answer ARPs for them with MAC # of the switch they're connected to. self.fakeways = set(fakeways) # If this is true and we see a packet for an unknown # host, we'll ARP for it. self.arp_for_unknowns = arp_for_unknowns # (dpid,IP) -> expire_time # We use this to keep from spamming ARPs self.outstanding_arps = {} # (dpid,IP) -> [(expire_time,buffer_id,in_port), ...] # These are buffers we've gotten at this datapath for this IP which # we can't deliver because we don't know where they go. self.lost_buffers = {} # For each switch, we map IP addresses to Entries self.arpTable = {} # This timer handles expiring stuff self._expire_timer = Timer(5, self._handle_expiration, recurring=True) self.listenTo(core) def _handle_expiration (self): # Called by a timer so that we can remove old items. empty = [] for k,v in self.lost_buffers.iteritems(): dpid,ip = k for item in list(v): expires_at,buffer_id,in_port = item if expires_at < time.time(): # This packet is old. Tell this switch to drop it. v.remove(item) po = of.ofp_packet_out(buffer_id = buffer_id, in_port = in_port) core.openflow.sendToDPID(dpid, po) if len(v) == 0: empty.append(k) # Remove empty buffer bins for k in empty: del self.lost_buffers[k] def _send_lost_buffers (self, dpid, ipaddr, macaddr, port): """ We may have "lost" buffers -- packets we got but didn't know where to send at the time. We may know now. Try and see. """ if (dpid,ipaddr) in self.lost_buffers: # Yup! bucket = self.lost_buffers[(dpid,ipaddr)] del self.lost_buffers[(dpid,ipaddr)] log.debug("Sending %i buffered packets to %s from %s" % (len(bucket),ipaddr,dpid_to_str(dpid))) for _,buffer_id,in_port in bucket: po = of.ofp_packet_out(buffer_id=buffer_id,in_port=in_port) po.actions.append(of.ofp_action_dl_addr.set_dst(macaddr)) po.actions.append(of.ofp_action_output(port = port)) core.openflow.sendToDPID(dpid, po) def _handle_GoingUpEvent (self, event): self.listenTo(core.openflow) log.debug("Up...") def _handle_PacketIn (self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed #print "------------------------------------------------------------------------" #print "IPv4: ", event.parsed.find('ipv4') #print "ARP: ", event.parsed.find('arp') #print "Packet Type: " , packet.type #print datetime.datetime.now(), ":", packet #print "\n", packet.parsed #print "\n", event.ofp global call_Timer global set_Timer global diction timerSet =False def preventing(): global diction global set_Timer if not set_Timer: set_Timer =True if len(diction) == 0: 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 else: diction[event.connection.dpid][event.port] = 1 print "\n",datetime.datetime.now(), ": printing diction ",str(diction),"\n" def _timer_func (): global diction #print "Dictionary:", diction global set_Timer if not set_Timer: set_Timer =True if set_Timer==True: for k,v in diction.iteritems(): for i,j in v.iteritems(): if j >=20: print "\n",datetime.datetime.now(),"DDOS DETECTED" print "\n",str(diction) print "\n",datetime.datetime.now(),": BLOCKED PORT NUMBER : ", str(i), " OF SWITCH ID: ", str(k) #appending no actions to the out_msg the packets will be dropped from the current DPID-PORT pair 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: # 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)) #print "Arp table: ", str(self.arpTable) 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) #print "\n" chi_obj.stats(packet.next.srcip) #edit chi_obj.baseLine() #edit if chi_obj.y < 0.05 : print "DDoS might be there" preventing() Timer(10, _timer_func) # Send any waiting packets... self._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport) #print "LOST BUFFERS: " , str(self.lost_buffers) #edited # Learn or update port/MAC info if packet.next.srcip in self.arpTable[dpid]: #print packet.next.srcip , "#editing" 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) #print "Arp table: ", str(self.arpTable) # 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=of.OFP_FLOW_PERMANENT, buffer_id=event.ofp.buffer_id, actions=actions, match=of.ofp_match.from_packet(packet, inport)) event.connection.send(msg.pack()) elif self.arp_for_unknowns: # 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)
def _handle_PacketIn (event): global l1_dpid,l2_dpid,l3_dpid,s4_dpid,s5_dpid,status packet = event.parsed arp_table = {"10.0.0.1": "00:00:00:00:00:01", "10.0.0.2": "00:00:00:00:00:02", "10.0.0.3": "000000000003", "10.0.0.4": "000000000004", "10.0.0.5": "000000000005", "10.0.0.6": "000000000006"} if packet.type == packet.ARP_TYPE: a = packet.find("arp") if a.opcode == a.REQUEST: #obtain ARP request from packet and create ARP reply r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwsrc = EthAddr(arp_table[str(packet.payload.protodst)])# request MAC address r.hwdst = packet.src r.opcode = arp.REPLY r.protosrc = packet.payload.protodst r.protodst = packet.payload.protosrc #make ethernet packet eth = ethernet() eth.type = ethernet.ARP_TYPE eth.dst = packet.src eth.src = r.hwsrc eth.payload = r #send ARP 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 = event.port event.connection.send(msg) if event.connection.dpid==l1_dpid: #print("Hello") sw = 0 for i in range(1,3): for j in range(1,7): if i != j : msg = of.ofp_flow_mod() msg.match.dl_type = 0x0800 src = "10.0.0." + str(i) dst = "10.0.0." + str(j) msg.match.nw_src = src msg.match.nw_dst = dst # print(msg) # print(msg.match) # print(status) # print(sw) # print(Table[status][sw]) # print((i,j)) # print(Table[status][sw][(i,j)][0]) # print(Table[status][sw][(i,j)][1]) outPort = Table[status][sw][(i,j)][0] msg.actions.append(of.ofp_action_output(port = outPort)) msg.priority = Table[status][sw][(i,j)][1] event.connection.send(msg) # exchange i j msg = of.ofp_flow_mod() msg.match.dl_type = 0x0800 src = "10.0.0." + str(j) dst = "10.0.0." + str(i) msg.match.nw_src = src msg.match.nw_dst = dst # print(status) # print(sw) # print(Table[status][sw]) # print((j,i)) # print(Table[status][sw][(j,i)][0]) # print(Table[status][sw][(j,i)][1]) outPort = Table[status][sw][(j,i)][0] msg.actions.append(of.ofp_action_output(port = outPort)) msg.priority = Table[status][sw][(j,i)][1] event.connection.send(msg) for i in range(1,7): for j in range(1,7): if i != j : src = EthAddr("00:00:00:00:00:0"+ str(i)) dst = EthAddr("00:00:00:00:00:0"+ str(j)) if src == packet.src: if dst == packet.dst: outPort = Table[status][sw][(i,j)][0] msg1 = of.ofp_packet_out(data = event.ofp) msg1.actions.append(of.ofp_action_output(port = outPort)) event.connection.send(msg1) log.debug("Sent a message for %s -> %s" % (src, dst, )) elif event.connection.dpid==l2_dpid: sw = 1 for i in range(3,5): for j in range(1,7): if i != j : msg = of.ofp_flow_mod() msg.match.dl_type = 0x0800 src = "10.0.0." + str(i) dst = "10.0.0." + str(j) msg.match.nw_src = src msg.match.nw_dst = dst # print(status) # print(sw) # print(Table[status][sw]) # print((i,j)) # print(Table[status][sw][(i,j)][0]) # print(Table[status][sw][(i,j)][1]) outPort = Table[status][sw][(i,j)][0] msg.actions.append(of.ofp_action_output(port = outPort)) msg.priority = Table[status][sw][(i,j)][1] event.connection.send(msg) # exchange i j msg = of.ofp_flow_mod() msg.match.dl_type = 0x0800 src = "10.0.0." + str(j) dst = "10.0.0." + str(i) msg.match.nw_src = src msg.match.nw_dst = dst # print(status) # print(sw) # print(Table[status][sw]) # print((j,i)) # print(Table[status][sw][(j,i)][0]) # print(Table[status][sw][(j,i)][1]) outPort = Table[status][sw][(j,i)][0] msg.actions.append(of.ofp_action_output(port = outPort)) msg.priority = Table[status][sw][(j,i)][1] event.connection.send(msg) for i in range(1,7): for j in range(1,7): if i != j : src = EthAddr("00:00:00:00:00:0"+ str(i)) dst = EthAddr("00:00:00:00:00:0"+ str(j)) if src == packet.src: if dst == packet.dst: outPort = Table[status][sw][(i,j)][0] msg1 = of.ofp_packet_out(data = event.ofp) msg1.actions.append(of.ofp_action_output(port = outPort)) event.connection.send(msg1) elif event.connection.dpid==l3_dpid: sw = 2 for i in range(5,7): for j in range(1,7): if i != j : msg = of.ofp_flow_mod() msg.match.dl_type = 0x0800 src = "10.0.0." + str(i) dst = "10.0.0." + str(j) msg.match.nw_src = src msg.match.nw_dst = dst # print(status) # print(sw) # print(Table[status][sw]) # print((i,j)) # print(Table[status][sw][(i,j)][0]) # print(Table[status][sw][(i,j)][1]) outPort = Table[status][sw][(i,j)][0] msg.actions.append(of.ofp_action_output(port = outPort)) msg.priority = Table[status][sw][(i,j)][1] event.connection.send(msg) # exchange i j msg = of.ofp_flow_mod() msg.match.dl_type = 0x0800 src = "10.0.0." + str(j) dst = "10.0.0." + str(i) msg.match.nw_src = src msg.match.nw_dst = dst # print(status) # print(sw) # print(Table[status][sw]) # print((j,i)) # print(Table[status][sw][(j,i)][0]) # print(Table[status][sw][(j,i)][1]) outPort = Table[status][sw][(j,i)][0] msg.actions.append(of.ofp_action_output(port = outPort)) msg.priority = Table[status][sw][(j,i)][1] event.connection.send(msg) for i in range(1,7): for j in range(1,7): if i != j : src = EthAddr("00:00:00:00:00:0"+ str(i)) dst = EthAddr("00:00:00:00:00:0"+ str(j)) if src == packet.src: if dst == packet.dst: outPort = Table[status][sw][(i,j)][0] msg1 = of.ofp_packet_out(data = event.ofp) msg1.actions.append(of.ofp_action_output(port = outPort)) event.connection.send(msg1) elif event.connection.dpid==s4_dpid: sw = 3 if status == 0: for i in range(1,7,2): for j in range(1,7): if i != j and i+1 != j: msg = of.ofp_flow_mod() msg.match.dl_type = 0x0800 src = "10.0.0." + str(i) dst = "10.0.0." + str(j) msg.match.nw_src = src msg.match.nw_dst = dst # print(status) # print(sw) # print(Table[status][sw]) # print((i,j)) # print(Table[status][sw][(i,j)][0]) # print(Table[status][sw][(i,j)][1]) outPort = Table[status][sw][(i,j)][0] msg.actions.append(of.ofp_action_output(port = outPort)) msg.priority = Table[status][sw][(i,j)][1] event.connection.send(msg) for i in range(1,7): for j in range(1,7): if i != j : src = EthAddr("00:00:00:00:00:0"+ str(i)) dst = EthAddr("00:00:00:00:00:0"+ str(j)) if src == packet.src: if dst == packet.dst: outPort = Table[status][sw][(i,j)][0] msg1 = of.ofp_packet_out(data = event.ofp) msg1.actions.append(of.ofp_action_output(port = outPort)) event.connection.send(msg1) elif status == 1: for i in range(1,7): for j in range(1,7): if i != j and (i,j) != (1,2) and (i,j) != (2,1) and (i,j) != (3,4) and (i,j) != (4,3) and (i,j) != (5,6) and (i,j) != (6,5) : msg = of.ofp_flow_mod() msg.match.dl_type = 0x0800 src = "10.0.0." + str(i) dst = "10.0.0." + str(j) msg.match.nw_src = src msg.match.nw_dst = dst # print(status) # print(sw) # print(Table[status][sw]) # print((i,j)) # print(Table[status][sw][(i,j)][0]) # print(Table[status][sw][(i,j)][1]) outPort = Table[status][sw][(i,j)][0] msg.actions.append(of.ofp_action_output(port = outPort)) msg.priority = Table[status][sw][(i,j)][1] event.connection.send(msg) for i in range(1,7): for j in range(1,7): if i != j : src = EthAddr("00:00:00:00:00:0"+ str(i)) dst = EthAddr("00:00:00:00:00:0"+ str(j)) if src == packet.src: if dst == packet.dst: outPort = Table[status][sw][(i,j)][0] msg1 = of.ofp_packet_out(data = event.ofp) msg1.actions.append(of.ofp_action_output(port = outPort)) event.connection.send(msg1) elif event.connection.dpid==s5_dpid: sw = 4 if status == 0: for i in range(2,8,2): for j in range(1,7): if i != j and i-1 != j: msg = of.ofp_flow_mod() msg.match.dl_type = 0x0800 src = "10.0.0." + str(i) dst = "10.0.0." + str(j) msg.match.nw_src = src msg.match.nw_dst = dst # print(status) # print(sw) # print(Table[status][sw]) # print((i,j)) # print(Table[status][sw][(i,j)][0]) # print(Table[status][sw][(i,j)][1]) outPort = Table[status][sw][(i,j)][0] msg.actions.append(of.ofp_action_output(port = outPort)) msg.priority = Table[status][sw][(i,j)][1] event.connection.send(msg) for i in range(1,7): for j in range(1,7): if i != j : src = EthAddr("00:00:00:00:00:0"+ str(i)) dst = EthAddr("00:00:00:00:00:0"+ str(j)) if src == packet.src: if dst == packet.dst: outPort = Table[status][sw][(i,j)][0] msg1 = of.ofp_packet_out(data = event.ofp) msg1.actions.append(of.ofp_action_output(port = outPort)) event.connection.send(msg1) elif status == 2: for i in range(1,7): for j in range(1,7): if i != j and (i,j) != (1,2) and (i,j) != (2,1) and (i,j) != (3,4) and (i,j) != (4,3) and (i,j) != (5,6) and (i,j) != (6,5) : msg = of.ofp_flow_mod() msg.match.dl_type = 0x0800 src = "10.0.0." + str(i) dst = "10.0.0." + str(j) msg.match.nw_src = src msg.match.nw_dst = dst # print(status) # print(sw) # print(Table[status][sw]) # print((i,j)) # print(Table[status][sw][(i,j)][0]) # print(Table[status][sw][(i,j)][1]) outPort = Table[status][sw][(i,j)][0] msg.actions.append(of.ofp_action_output(port = outPort)) msg.priority = Table[status][sw][(i,j)][1] event.connection.send(msg) for i in range(1,7): for j in range(1,7): if i != j : src = EthAddr("00:00:00:00:00:0"+ str(i)) dst = EthAddr("00:00:00:00:00:0"+ str(j)) if src == packet.src: if dst == packet.dst: outPort = Table[status][sw][(i,j)][0] msg1 = of.ofp_packet_out(data = event.ofp) msg1.actions.append(of.ofp_action_output(port = outPort)) event.connection.send(msg1)
def client_handler(address, fd, events): global ip_type sock = tables.fd_map[fd] if events & io_loop.READ: data = sock.recv(16384) if data == '': print "connection dropped" #when switch is dropped, the outdated information should be deleted io_loop.remove_handler(fd) if fd in tables.fd_map.iterkeys() and fd in tables.sock_dpid.iterkeys(): dpid = tables.sock_dpid[fd][1] tables.sock_dpid.pop(fd) tables.fd_map.pop(fd) for link in tables.topo_map.iterkeys(): if tables.topo_map[link]['status'] != -1 and (link[0] == dpid or link[2] == dpid): tables.topo_map[link]['status'] = -1#the link will not be re-counted dc.topo_flag += 2#when topo_flag>0, controller will stop dealing with packet tables.switch_map.pop(dpid) if dpid in tables.info_map.iterkeys(): tables.info_map.pop(dpid) if dpid in tables.flow_map.iterkeys(): tables.flow_map.pop(dpid) create_topo._connection_down(dpid)#renew the topo in discovery.py create_topo._sender._connection_down(dpid) if len(data)<8: print "not a openflow message" else: if len(data)>8: rmsg = of.ofp_header(data[0:8]) body = data[8:] else: rmsg = of.ofp_header(data) if rmsg.type == 0: print "OFPT_HELLO" msg = of.ofp_header(type = 5)#we send the features_request here. print "OFPT_FEATURES_REQUEST" io_loop.update_handler(fd, io_loop.WRITE) message_queue_map[sock].put(data) message_queue_map[sock].put(str(msg)) elif rmsg.type == 1: print "OFPT_ERROR" of.ofp_error_msg(body).show() elif rmsg.type == 2: #since the ECHO is too frequent, the print is canceled #print "OFPT_ECHO_REQUEST" msg = of.ofp_header(type=3, xid=rmsg.xid) message_queue_map[sock].put(str(msg)) io_loop.update_handler(fd, io_loop.WRITE) elif rmsg.type == 3: print "OFPT_ECHO_REPLY" elif rmsg.type == 4: print "OFPT_VENDOR" elif rmsg.type == 5: print "OFPT_FEATURES_REQUEST" elif rmsg.type == 6: print "OFPT_FEATURES_REPLY" msg = of.ofp_features_reply(body[0:24]) #length of reply msg tables.sock_dpid[fd]=[0, msg.datapath_id] #sock_dpid[fd] comes from here. port_info_raw = str(body[24:]) #we change it into str so we can manipulate it. port_info = {} print "port number:",len(port_info_raw)/48, "total length:", len(port_info_raw) for i in range(len(port_info_raw)/48): port_info[i] = of.ofp_phy_port(port_info_raw[0+i*48:48+i*48]) print port_info[i].port_no elif rmsg.type == 10: #print "OFPT_PACKET_IN" pkt_in_msg = of.ofp_packet_in(body)#buffer_id+in_port raw = pkt_in_msg.load pkt_ = ethernet(raw)#this method can be located in pox pkt_parsed = of.Ether(raw) dpid = tables.sock_dpid[fd][1] if pkt_.effective_ethertype == 0x88cc:#deal with the LLDP for topo create_topo._handle_openflow_PacketIn(pkt_in_msg, pkt_, dpid) if dc.topo_flag:#when the topo is not completed, do nothing pass else: if pkt_.effective_ethertype == 0x0806: #the ARP table is maintained for hosts' MAC in tables.py print "\n\nARP\n\n" request = pkt_parsed.next if request.opcode == arp.REQUEST: reply = arp() reply.hwtype = request.hwtype reply.prototype = request.prototype reply.hwlen = request.hwlen reply.protolen = request.protolen reply.opcode = arp.REPLY reply.hwdst = request.hwsrc reply.protodst = request.protosrc reply.protosrc = request.protodst reply.hwsrc = tables.get_mac(request.protodst.toStr()) #reply.hwsrc = tables.ip_mac[request.protodst] e_dpid = tables.sock_dpid[fd][1] for p,v in tables.switch_map[e_dpid]['port'].items(): if v.port_no == pkt_in_msg.in_port: e_src = v.hw_addr e = ethernet(type = pkt_parsed.type, src = e_src, dst = pkt_parsed.src) e.set_payload(reply) msg = off.ofp_packet_out() msg.data = e.pack() msg.actions.append(off.ofp_action_output(port = off.OFPP_IN_PORT))#port problem msg.in_port = pkt_in_msg.in_port msg = msg.pack() io_loop.update_handler(fd, io_loop.WRITE) message_queue_map[sock].put(str(msg)) elif pkt_.effective_ethertype == 0x8100: #to detect VLAN packets print "VLAN:\n" packet = pkt_.next print packet.__dict__ elif pkt_.effective_ethertype == 0x0800: #print "\n\nIP\n\n" #use the packet to produce flow_mod packet = pkt_.next if isinstance(packet, ipv4): src = packet.srcip.toStr() dst = packet.dstip.toStr() dpid = tables.sock_dpid[fd][1] #the routing type of the link(src,dst) is based on s_type if (src, dst) in ip_type.iterkeys(): s_type = ip_type[(src,dst)] elif stype != '0': s_type = stype else: s_type = '0' #src_mac = tables.switch_map[dpid]['port'][src_port].hw_addr #dst_mac = tables.switch_map[dpid]['port'][dst_port].hw_addr road, rlink, route_type = route.add_link(src, dst, s_type) #establish info for barrier if (src,dst) not in tables.road_map.iterkeys(): tables.road_map[(src,dst)] = road if (src,dst) not in tables.barrier_map.iterkeys(): tables.barrier_map[(src,dst)] = {} if dpid not in tables.barrier_map[(src,dst)].iterkeys(): tables.barrier_map[(src,dst)][dpid] = rmsg.xid if route_type == 0:#ip link, send flow ip_type[(src,dst)] = '1' if dpid in rlink.iterkeys(): src_port, dst_port = rlink[dpid][0], rlink[dpid][1] print "flow from ", src, " to ", dst, "\n" print "dpid:",dpid," inport:",src_port," outport:",dst_port, "\n" print "-------------------------" header = of.ofp_header(type=14, length = 88, xid=rmsg.xid) wildcards = of.ofp_flow_wildcards(OFPFW_NW_TOS=1, OFPFW_DL_VLAN_PCP=1, OFPFW_NW_DST_MASK=63, OFPFW_NW_SRC_MASK=63, OFPFW_TP_DST=1, OFPFW_TP_SRC=1, OFPFW_NW_PROTO=1, OFPFW_DL_TYPE=1, OFPFW_DL_DST=0, OFPFW_DL_SRC=0, OFPFW_DL_VLAN=1, OFPFW_IN_PORT=0) match = of.ofp_match(in_port=pkt_in_msg.in_port, dl_src = pkt_parsed.src, dl_dst = pkt_parsed.dst, dl_type = pkt_parsed.type, nw_tos = pkt_parsed.payload.tos, nw_proto = pkt_parsed.payload.proto, nw_src=src, nw_dst=dst) flow_mod = of.ofp_flow_mod(buffer_id = pkt_in_msg.buffer_id, idle_timeout = 0, hard_timeout = 30, flags = 1, cookie = rmsg.xid, out_port = dst_port) action_header = oof.ofp_action_header(type = 0) action_output = of.ofp_action_output(type = 0, port = dst_port, len = 8) msg = header/wildcards/match/flow_mod/action_header/action_output #here is to renew the flow_map if dpid not in tables.flow_map.iterkeys(): tables.flow_map[dpid] = [] tables.flow_map[dpid].append(msg) else: for flow in tables.flow_map[dpid]: flow_match = of.ofp_match((str(flow))[12:48]) if match == flow_match: tables.flow_map[dpid].remove(flow) break tables.flow_map[dpid].append(msg) message_queue_map[sock].put(str(msg)) io_loop.update_handler(fd, io_loop.WRITE) elif route_type == 1:#otn or wavelenth ip_type[(src,dst)] = '2' if dpid in rlink.iterkeys(): src = packet.srcip.toStr() dst = packet.dstip.toStr() src_port, dst_port = rlink[dpid][0], rlink[dpid][1] if (src,dst) not in tables.source_map.iterkeys(): tables.source_map[(src,dst)] = {} if dpid not in tables.source_map[(src,dst)].iterkeys(): tables.source_map[(src,dst)][dpid] = {} if src_port not in tables.source_map[(src,dst)][dpid].iterkeys(): tables.source_map[(src,dst)][dpid][src_port] = [] if dst_port not in tables.source_map[(src,dst)][dpid].iterkeys(): tables.source_map[(src,dst)][dpid][dst_port] = [] if dpid == road[-1]:#src host port has no slot src_slot = -1 else: for i in xrange(0,80): if tables.info_map[dpid][src_port][i]['status'] == 0: tables.info_map[dpid][src_port][i]['status'] = 1 src_slot = i tables.source_map[(src,dst)][dpid][src_port].append(i) break if dpid == road[0]:#dst host port has no slot: dst_slot = -1 else: for i in xrange(0,80): if tables.info_map[dpid][dst_port][i]['status'] == 0: tables.info_map[dpid][dst_port][i]['status'] = 1 dst_slot = i tables.source_map[(src,dst)][dpid][dst_port].append(i) break cflow_mod = of.ofp_header(type=0xff, xid=rmsg.xid)\ /of.ofp_cflow_mod(command=0)\ /of.ofp_connect_wildcards()\ /of.ofp_connect(in_port = pkt_in_msg.in_port)\ /of.ofp_action_output(type=0, port=dst_port, len=8) type = switch_info[tables.sock_dpid[fd][0]] if route_type == 1:#for OTN if src_slot == -1: cflow_mod.payload.payload.payload.nport_in = 81 else: cflow_mod.payload.payload.payload.nport_in = src_slot if dst_slot == -1: cflow_mod.payload.payload.payload.nport_out = 81 else: cflow_mod.payload.payload.payload.nport_out = dst_slot cflow_mod.payload.payload.payload.supp_sw_otn_gran_out = tables.switch_map[dpid]['port'][dst_port].SUPP_SW_GRAN cflow_mod.payload.payload.payload.sup_otn_port_bandwidth_out = tables.switch_map[dpid]['port'][dst_port].sup_otn_port_bandwidth elif route_type == 2:#for wavelength cflow_mod.payload.payload.payload.wport_in = src_slot cflow_mod.payload.payload.payload.wport_out = dst_slot #this field is used to record cflow, but I have no ideal about how to delete the outdate flow--------------------- if dpid not in tables.cflow_map.iterkeys():#cflow_map,12.19 tables.cflow_map[dpid] = {} tables.cflow_map[dpid][(src,dst)] = cflow_mod print "cflow from ", src, " to ", dst, "\n" print "dpid:", dpid, " in_port:", cflow_mod.payload.payload.payload.in_port, " out_port:", cflow_mod.payload.payload.payload.payload.port, "\n" print "------------------------" message_queue_map[sock].put(str(cflow_mod)) io_loop.update_handler(fd, io_loop.WRITE) #send barrier msg = of.ofp_header(type = 18,xid = rmsg.xid) message_queue_map[sock].put(str(msg)) io_loop.update_handler(fd, io_loop.WRITE) elif rmsg.type == 11: print "OFPT_FLOW_REMOVED" elif rmsg.type == 12: print "OFPT_PORT_STATUS" elif rmsg.type == 13: print "OFPT_PACKET_OUT" elif rmsg.type == 14: print "OFPT_FLOW_MOD" elif rmsg.type == 15: print "OFPT_PORT_MOD" elif rmsg.type == 16: print "OFPT_STATS_REQUEST" elif rmsg.type == 17 and len(data)> 12: print "OFPT_STATS_REPLY" # 1. parsing ofp_stats_reply reply_header = of.ofp_stats_reply(body[:4]) # 2.parsing ofp_flow_stats msg if reply_header.type == 0: reply_desc = of.ofp_desc_stats(body[4:]) reply.show() elif reply_header.type == 1 and len(data)>92: #here informatioin is used for flow stats reply_body_data1 = of.ofp_flow_stats(body[4:8]) # match field in ofp_flow_stats reply_body_wildcards = of.ofp_flow_wildcards(body[8:12]) reply_body_match = of.ofp_match(body[12:48]) # second part in ofp_flow_stats reply_body_data2 = of.ofp_flow_stats_data(body[48:92]) # 3.parsing actions reply_body_action = [] if len(body[92:])>8: #it is very important! num = len(body[92:])/8 for x in xrange(num): reply_body_action.append(of.ofp_action_output(body[92+x*8:100+x*8])) msg = reply_header/reply_body_data1/reply_body_wildcards/reply_body_match/reply_body_data2 #the followings are about Load Balancing if fd in tables.fd_map.iterkeys() and fd in tables.sock_dpid.iterkeys(): dpid = tables.sock_dpid[fd][1] if dpid in tables.flow_map.iterkeys(): src_mac = reply_body_match.dl_src dst_mac = reply_body_match.dl_dst for flow in tables.flow_map[dpid]: if flow.payload.payload.dl_src == src_mac and flow.payload.payload.dl_dst == dst_mac: src_ip = flow.payload.payload.nw_src dst_ip = flow.payload.payload.nw_dst pair = (src_ip,dst_ip) flow_time = float(reply_body_data2.duration_sec) + float(reply_body_data2.duration_nsec/1000000000) flow_data = float(reply_body_data2.byte_count) if pair not in ip_stats.iterkeys(): ip_stats[pair] = {} ip_stats[pair][0] = {} ip_stats[pair][0]['flow_time'] = flow_time ip_stats[pair][0]['flow_data'] = flow_data else: if 1 in ip_stats[pair].iterkeys():#have a pair ip_stats[pair][0]['flow_time'] = ip_stats[pair][1]['flow_time'] ip_stats[pair][0]['flow_data'] = ip_stats[pair][1]['flow_data'] else: ip_stats[pair][1] = {} ip_stats[pair][1]['flow_time'] = flow_time ip_stats[pair][1]['flow_data'] = flow_data if flow_time != ip_stats[pair][0]['flow_time']: load = (flow_data - ip_stats[pair][0]['flow_data']) / (flow_time - ip_stats[pair][0]['flow_time']) print "now the link ", pair, " load is ", load, "(byte/s)\n" global switch_load if load > switch_load:#change to cflow ip_type[pair] = '2' #todo:flow_mod(delete) elif reply_header.type == 2: reply_aggregate = of.ofp_aggregate_stats_reply(body[4:]) reply_aggregate.show() elif reply_header.type == 3: #table_stats length = rmsg.length - 12 num = length/64 for i in xrange(num): table_body = body[4+i*64:i*64+68] reply_table_stats = of.ofp_table_stats(table_body[:36]) table_wildcards = of.ofp_flow_wildcards(table_body[36:40]) reply_table_stats_data = of.ofp_table_stats_data(table_body[40:64]) msg_tmp = reply_header/reply_table_stats/table_wildcards/reply_table_stats_data msg = rmsg/msg_tmp msg.show() elif reply_header.type == 4: #port stats reply length = rmsg.length - 12 num = length/104 for i in xrange(num): offset = 4+i*104 reply_port_stats = of.ofp_port_stats_reply(body[offset:(offset+104)]) msg_tmp = reply_header/reply_port_stats msg = rmsg/msg_tmp msg.show() elif reply_header.type == 5: #queue reply length = rmsg.length - 12 num = length/32 if num: #if the queue is empty ,you need to check it ! for i in xrange(num): offset = 4+i*32 queue_reply = of.ofp_queue_stats(body[offset:offset+32]) msg_tmp = reply_header/queue_reply msg = rmsg/msg_tmp msg.show() elif reply_header.type == 0xffff: #vendor reply msg = rmsg/reply_header/of.ofp_vendor(body[4:]) elif rmsg.type == 18: print "OFPT_BARRIER_REQUEST" #no message body, the xid is the previous barrier request xid elif rmsg.type == 19: barrier = 0 dpid = tables.sock_dpid[fd][1] for a,b in tables.barrier_map.items(): for k,v in b.items(): if k == dpid and v == rmsg.xid: if dpid == tables.road_map[a][0]:#if the barrier is from the dst switch, then the road is completed barrier = 1 print "road ", a, " is completed!\n" tables.barrier_map.pop(a) if barrier: break #print "OFPT_BARRIER_REPLY: ", rmsg.xid, "Successful" elif rmsg.type == 20: print "OFPT_QUEUE_GET_CONFIG_REQUEST" elif rmsg.type == 21: print "OFPT_QUEUE_GET_CONFIG_REPLY" elif rmsg.type == 24: print "OFPT_CFEATURES_REPLY" msg = of.ofp_cfeatures_reply(body[0:24])#length of reply msg #bind the bpid and type (type, dpid) #OTN:WAVE:IP b'000' TYPE = msg.OFPC_IP_SWITCH + msg.OFPC_WAVE_SWITCH * 2 + msg.OFPC_OTN_SWITCH * 4 tables.sock_dpid[fd] = [TYPE, msg.datapath_id]#IP only port_info_raw = body[24:] port_info = {} port_i = {} print "port number:",len(port_info_raw)/72, "total length:", len(port_info_raw) for i in range(len(port_info_raw)/72): port_info[i] = of.ofp_phy_cport(port_info_raw[i*72:72+i*72]) port_i[port_info[i].port_no] = port_info[i] switch_type = tables.sock_dpid[fd][0]#features recorded in switch_map tables.switch_map[msg.datapath_id] = {'features':msg, 'type':switch_type, 'port':port_i} tables.info_map[msg.datapath_id] = {} #start to discovery lldp_flow = create_topo._connection_up(msg.datapath_id) message_queue_map[sock].put(str(lldp_flow)) io_loop.update_handler(fd, io_loop.WRITE)#discovery-handle create_topo._sender._connection_up(msg.datapath_id, port_info)
def _handle_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed if not packet.parsed: log.warning("DPID %i PORT %i ignoring unparsed packet", dpid, inport) return if dpid not in self.arpTable: # New switch -- create an empty table self.arpTable[dpid] = {} for fake in self.fakeways: self.arpTable[dpid][IPAddr(fake)] = Entry( of.OFPP_NONE, dpid_to_mac(dpid)) if packet.type == ethernet.LLDP_TYPE: # Ignore LLDP packets return if isinstance(packet.next, ipv4): log.debug("DPID %i PORT %i IP %s => %s", dpid, inport, packet.next.srcip, packet.next.dstip) # Send any waiting packets... self._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport) # Learn or update port/MAC info if packet.next.srcip in self.arpTable[dpid]: if self.arpTable[dpid][packet.next.srcip] != (inport, packet.src): log.info("DPID %i PORT %i RE-learned %s", dpid, inport, packet.next.srcip) else: log.debug("DPID %i PORT %i learned %s", dpid, inport, str(packet.next.srcip)) self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src) # Try to forward dstaddr = packet.next.dstip if (packet.find("icmp") and (dstaddr in switch)): # Reply to pings # Make the ping reply icmp = pkt.icmp() icmp.type = pkt.TYPE_ECHO_REPLY icmp.payload = packet.find("icmp").payload # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = packet.find("ipv4").dstip ipp.dstip = packet.find("ipv4").srcip # Ethernet around that... e = pkt.ethernet() e.src = packet.dst e.dst = packet.src e.type = e.IP_TYPE # Hook them up... ipp.payload = icmp e.payload = ipp # Send it back to the input port msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = event.port event.connection.send(msg) log.debug("%s pinged %s", ipp.dstip, ipp.srcip) if dstaddr in self.arpTable[dpid]: # We have info about what port to send it out on... prt = self.arpTable[dpid][dstaddr].port mac = self.arpTable[dpid][dstaddr].mac if prt == inport: log.warning( "DPID %i PORT %i not sending packet for %s back out of the " + "input port" % (dpid, inport, str(dstaddr))) else: log.debug( "DPID %i PORT %i installing flow for %s => %s out port %i" % (dpid, inport, packet.next.srcip, dstaddr, prt)) actions = [] actions.append(of.ofp_action_dl_addr.set_dst(mac)) actions.append(of.ofp_action_output(port=prt)) match = of.ofp_match.from_packet(packet, inport) match.dl_src = None # Wildcard source MAC msg = of.ofp_flow_mod(command=of.OFPFC_ADD, idle_timeout=FLOW_IDLE_TIMEOUT, hard_timeout=of.OFP_FLOW_PERMANENT, buffer_id=event.ofp.buffer_id, actions=actions, match=of.ofp_match.from_packet( packet, inport)) event.connection.send(msg.pack()) elif (dstaddr not in self.arpTable[dpid]) and (dstaddr not in switch): # We don't know this destination. # First, we track this buffer so that we can try to resend it later # if we learn the destination, second we ARP for the destination, # which should ultimately result in it responding and us learning # where it is # Add to tracked buffers if (dpid, dstaddr) not in self.lost_buffers: self.lost_buffers[(dpid, dstaddr)] = [] bucket = self.lost_buffers[(dpid, dstaddr)] entry = (time.time() + MAX_BUFFER_TIME, event.ofp.buffer_id, inport) bucket.append(entry) while len(bucket) > MAX_BUFFERED_PER_IP: del bucket[0] # Expire things from our outstanding ARP list... self.outstanding_arps = { k: v for k, v in self.outstanding_arps.iteritems() if v > time.time() } # Check if we've already ARPed recently if (dpid, dstaddr) in self.outstanding_arps: # Oop, we've already done this one recently. return # And ARP... self.outstanding_arps[(dpid, dstaddr)] = time.time() r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REQUEST r.hwdst = ETHER_BROADCAST r.protodst = dstaddr r.hwsrc = packet.src r.protosrc = packet.next.srcip e = ethernet(type=ethernet.ARP_TYPE, src=packet.src, dst=ETHER_BROADCAST) e.set_payload(r) log.debug("DPID %i PORT %i ARPing for %s on behalf of %s" % (dpid, inport, str(r.protodst), str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) msg.in_port = inport event.connection.send(msg) if (packet.find("ipv4").dstip not in node): icmp = pkt.icmp() icmp.type = pkt.TYPE_DEST_UNREACH icmp.code = pkt.CODE_UNREACH_HOST orig_ip = event.parsed.find('ipv4') pay = orig_ip.pack() pay = pay[:orig_ip.hl * 4 + 8] import struct pay = struct.pack("!HH", 0, 0) + pay icmp.payload = pay # Make the IP packet around it ipp = pkt.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = packet.find("ipv4").dstip ipp.dstip = packet.find("ipv4").srcip # Ethernet around that... e = pkt.ethernet() e.src = packet.dst e.dst = packet.src e.type = e.IP_TYPE # Hook them up... ipp.payload = icmp e.payload = ipp # Send it back to the input port msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = event.port event.connection.send(msg) log.debug("%s pinged %s", ipp.dstip, ipp.srcip) elif isinstance(packet.next, arp): a = packet.next log.debug("DPID %i PORT %i ARP %s %s => %s", dpid, inport, { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc), str(a.protodst)) if a.prototype == arp.PROTO_TYPE_IP: if a.hwtype == arp.HW_TYPE_ETHERNET: if a.protosrc != 0: # Learn or update port/MAC info if a.protosrc in self.arpTable[dpid]: if self.arpTable[dpid][a.protosrc] != (inport, packet.src): log.info("DPID %i PORT %i RE-learned %s", dpid, inport, str(a.protosrc)) else: log.debug("DPID %i PORT %i learned %s", dpid, inport, str(a.protosrc)) self.arpTable[dpid][a.protosrc] = Entry( inport, packet.src) # Send any waiting packets... self._send_lost_buffers(dpid, a.protosrc, packet.src, inport) if a.opcode == arp.REQUEST: # Maybe we can answer if a.protodst != None: #if a.protodst in self.arpTable[dpid]: # We have an answer... #if not self.arpTable[dpid][a.protodst].isExpired(): # .. and it's relatively current, so we'll reply ourselves r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwdst = a.hwsrc r.protodst = a.protosrc r.protosrc = a.protodst r.hwsrc = dpid_to_mac(dpid) e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwsrc) e.payload = r #e.set_payload(r) log.debug( "DPID %i PORT %i answering ARP for %s" % (dpid, inport, str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) return # Didn't know how to answer or otherwise handle this ARP, so just flood it log.debug("DPID %i PORT %i flooding ARP %s %s => %s" % (dpid, inport, { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc), str(a.protodst))) msg = of.ofp_packet_out( in_port=inport, data=event.ofp, action=of.ofp_action_output(port=of.OFPP_FLOOD)) event.connection.send(msg)
class l3_switch (EventMixin): def __init__ (self, fakeways = [], arp_for_unknowns = False): # These are "fake gateways" -- we'll answer ARPs for them with MAC # of the switch they're connected to. self.fakeways = set(fakeways) # If this is true and we see a packet for an unknown # host, we'll ARP for it. self.arp_for_unknowns = arp_for_unknowns # (dpid,IP) -> expire_time # We use this to keep from spamming ARPs self.outstanding_arps = {} # (dpid,IP) -> [(expire_time,buffer_id,in_port), ...] # These are buffers we've gotten at this datapath for this IP which # we can't deliver because we don't know where they go. self.lost_buffers = {} # For each switch, we map IP addresses to Entries self.arpTable = {} # This timer handles expiring stuff self._expire_timer = Timer(5, self._handle_expiration, recurring=True) self.listenTo(core) def _handle_expiration (self): # Called by a timer so that we can remove old items. empty = [] for k,v in self.lost_buffers.iteritems(): dpid,ip = k for item in list(v): expires_at,buffer_id,in_port = item if expires_at < time.time(): # This packet is old. Tell this switch to drop it. v.remove(item) po = of.ofp_packet_out(buffer_id = buffer_id, in_port = in_port) core.openflow.sendToDPID(dpid, po) print dpid, po if len(v) == 0: empty.append(k) # Remove empty buffer bins for k in empty: del self.lost_buffers[k] def _send_lost_buffers (self, dpid, ipaddr, macaddr, port): """ We may have "lost" buffers -- packets we got but didn't know where to send at the time. We may know now. Try and see. """ if (dpid,ipaddr) in self.lost_buffers: # Yup! bucket = self.lost_buffers[(dpid,ipaddr)] del self.lost_buffers[(dpid,ipaddr)] log.info("Sending %i buffered packets to %s from %s and port %s" % (len(bucket),ipaddr,dpid_to_str(dpid), port)) for _,buffer_id,in_port in bucket: po = of.ofp_packet_out(buffer_id=buffer_id,in_port=in_port) po.actions.append(of.ofp_action_dl_addr.set_dst(macaddr)) po.actions.append(of.ofp_action_output(port = port)) core.openflow.sendToDPID(dpid, po) print po def _handle_GoingUpEvent (self, event): self.listenTo(core.openflow) log.debug("Up...") def _handle_PacketIn (self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed #know = packet.next.next.srcport if not packet.parsed: log.info("%i %i ignoring unparsed packet", dpid, inport, packet) 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 ## -- gilnei - Cap Flows if isinstance(packet.next.next,tcp): sport = 0 dport = 0 sport = packet.next.next.srcport dport = packet.next.next.dstport log.info (" DPID %i src_port %i dst_port %i" , dpid, sport, dport) switchs = Switchs.objects.get(name_switch = dpid) fl = TemporaryFlows(id_switch=switchs, switchport = inport, ip_src = packet.next.srcip, ip_dst = packet.next.dstip, src_port = sport, dst_port = dport, timestamp = datetime.datetime.now()) fl.save() #swt = Switchs(name_switch = dpid, temporary_flows_id_temporaryflow = fl) #swt.save() # reg = SwitchsHasTemporaryFlows(switchs_id_switch = switch.id_switch, temporary_flows_id_temporaryflow = fl.id_temporaryflow) #reg.save() 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.debug("%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 srcaddr = packet.next.srcip #dstport = packet.next.tos 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 self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src) sport = ("-") dport = ("-") srcmac = self.arpTable[dpid][srcaddr].mac #fl = TemporaryFlow(switchport = inport, ip_src = packet.next.srcip, ip_dst = packet.next.dstip, mac_src = srcmac, mac_dst = mac, s_port = sport, d_port = dport) #fl.save() # print srcmac # print mac # print sport # if isinstance (packet.next.next, tcp): # print packet.next.next.srcport # print packet.next.next.dstport # print mac # print "hi" # print ("%s ITS MAC --- %s ITS PORT " % (mac, prt)) if prt == inport: log.info("%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 WHATTHEFuck %i => %s out port %i" % (dpid, inport, packet.next.srcip, packet.next.tos, 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 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.info("%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.info("%i %i answering ARP for %s" % (dpid, inport, str(r.protosrc))) msg = of.ofp_packet_out() print msg 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)""" # When we get flow stats, print stuff out """ def handle_flow_stats (self, event):
def _handle_openflow_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: # 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) ip_flag_df = 0 ip_flag_mf = 0 tcp_flag_ack = 0 tcp_flag_push = 0 tcp_flag_reset = 0 tcp_flag_syn = 0 tcp_flag_fin = 0 if packet.next.flags == 1: ip_flag_df = 1 elif packet.next.flags == 2: ip_flag_mf = 1 if packet.next.next.flags == 1: tcp_flag_fin = 1 elif packet.next.next.flags == 2: tcp_flag_syn = 1 elif packet.next.next.flags == 4: tcp_flag_reset = 1 elif packet.next.next.flags == 8: tcp_flag_push = 1 elif packet.next.next.flags == 16: tcp_flag_ack = 1 input_packet = [len(packet), packet.next.hl, packet.next.iplen, ip_flag_df, ip_flag_mf, 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, tcp_flag_ack, tcp_flag_push, tcp_flag_reset, tcp_flag_syn, tcp_flag_fin, packet.next.next.win] global packets_arr packets_arr.append(input_packet) if len(packets_arr) > 18: packets_arr.pop(0) model = load_model("/home/ubuntu/pox/pox/forwarding/model_18_features.h5") scalar = pickle.load(open('/home/ubuntu/pox/pox/forwarding/myScalar2.pkl', 'rb')) data = np.array(packets_arr) data = scalar.transform(data) prediction = model.predict(np.array([data]), verbose=1) if prediction.round(): print "****************************************************" print " Normal Packet" print " try forwarding" print " prediction: ", prediction[0][0] print "****************************************************" else: print "****************************************************" print " !!DDos Detected!!" print " packet dropped" print " prediction: ", prediction[0][0] print "****************************************************" msg = of.ofp_packet_out(in_port=inport) core.openflow.sendToDPID(dpid, msg) return # 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 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): dpid = event.connection.dpid inport = event.port packet = event.parsed #know = packet.next.next.srcport if not packet.parsed: log.info("%i %i ignoring unparsed packet", dpid, inport, packet) 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 ## -- gilnei - Cap Flows if isinstance(packet.next.next,tcp): sport = 0 dport = 0 sport = packet.next.next.srcport dport = packet.next.next.dstport log.info (" DPID %i src_port %i dst_port %i" , dpid, sport, dport) switchs = Switchs.objects.get(name_switch = dpid) fl = TemporaryFlows(id_switch=switchs, switchport = inport, ip_src = packet.next.srcip, ip_dst = packet.next.dstip, src_port = sport, dst_port = dport, timestamp = datetime.datetime.now()) fl.save() #swt = Switchs(name_switch = dpid, temporary_flows_id_temporaryflow = fl) #swt.save() # reg = SwitchsHasTemporaryFlows(switchs_id_switch = switch.id_switch, temporary_flows_id_temporaryflow = fl.id_temporaryflow) #reg.save() 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.debug("%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 srcaddr = packet.next.srcip #dstport = packet.next.tos 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 self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src) sport = ("-") dport = ("-") srcmac = self.arpTable[dpid][srcaddr].mac #fl = TemporaryFlow(switchport = inport, ip_src = packet.next.srcip, ip_dst = packet.next.dstip, mac_src = srcmac, mac_dst = mac, s_port = sport, d_port = dport) #fl.save() # print srcmac # print mac # print sport # if isinstance (packet.next.next, tcp): # print packet.next.next.srcport # print packet.next.next.dstport # print mac # print "hi" # print ("%s ITS MAC --- %s ITS PORT " % (mac, prt)) if prt == inport: log.info("%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 WHATTHEFuck %i => %s out port %i" % (dpid, inport, packet.next.srcip, packet.next.tos, 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 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)
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 "\n", datetime.datetime.now(), ": printing diction ", str( diction), "\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 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) #editing print "\n***** Entropy Value = ", str(ent_obj.value), "*****\n" 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_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. dpid =self.connection.dpid """ if packet.type == packet.LLDP_TYPE or packet.type == packet.IPV6_TYPE: # 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) """ if packet.type ==packet.ARP_TYPE: """ packet.next.srcip is a source IP address packet.src is its source MAC address. """ srcip = packet.payload.protosrc #use next maybe dstip = packet.payload.protodst #use next maybe #scrip = packet.next.srcip #dstip = packet.next.dstip if packet.payload.opcode ==arp.REQUEST: print("dpid ",dpid) if dpid not in self.arpTable: self.arpTable[dpid] = {} if packet.src not in self.arpTable[dpid]: # store it in arpTable self.arpTable[dpid][srcip]=Entry(packet.src,event.port) #IP map to mac and port msg = of.ofp_flow_mod() msg.priority = 8 msg.match.dl_type =0x0800 msg.match.nw_dst = srcip msg.actions.append(of.ofp_action_dl_addr.set_dst(packet.src)) # dst mac msg.actions.append(of.ofp_action_dl_addr.set_src(dpid_to_mac(dpid))) # dst mac #msg.actions.append(of.ofp_action_nw_addr.set_dst(srcip)) #dst ip msg.actions.append(of.ofp_action_output(port = event.port)) self.connection.send(msg) #create arp based on self.Mac arp_reply = arp() arp_reply.hwsrc = dpid_to_mac(dpid) # switch mac arp_reply.hwdst = packet.src # host mac arp_reply.opcode = arp.REPLY arp_reply.protodst = srcip arp_reply.protosrc = dstip#GatewayIPaddr #ethernet ether = ethernet() ether.type = ethernet.ARP_TYPE ether.dst = packet.src ether.src = dpid_to_mac(dpid) ether.set_payload(arp_reply) # send out arp reply print("dpid ",dpid," mac ",dpid_to_mac(dpid),"srcip ",srcip," dstip ",dstip) print("My mac",self.arpTable[dpid][srcip].mac,self.arpTable[dpid][srcip].port) self.resend_packet(ether.pack(),self.arpTable[dpid][srcip].port) return elif packet.type ==packet.ARP_TYPE: print("get arp reply My IP",dstip," from ",srcip) #elif packet.type == packet.IP_TYPE: # Handle client's request # Only accept ARP request for load balancer # log.debug("Receive an IPv4 packet from %s" % packet.next.srcip) print ("Unhandled packet from " + str(self.connection.dpid) + ":" + packet.dump())
def _handle_PacketIn(self, event): packet = event.parsed if not packet.parsed: return port = event.port dpid = event.connection.dpid pnext = packet.next # A new switch has connected with no arp table # initialize table if dpid not in self._arp_table: self._arp_table[dpid] = {} log.info("Initiating ARP table for dpid: %i" % (dpid, )) if int(dpid) in [1, 2, 3]: #left node of the same leaf switch ipaddrL = "10.0.0.%s" % str(2 * int(dpid) - 1) macL = "00:00:00:00:00:0%s" % str(2 * int(dpid) - 1) #right node of the same leaf switch ipaddrR = "10.0.0.%s" % str(2 * int(dpid)) macR = "00:00:00:00:00:0%s" % str(2 * int(dpid)) self._arp_table[dpid] = {IPAddr(ipaddrL): (EthAddr(macL), 3)} self._arp_table[dpid] = {IPAddr(ipaddrR): (EthAddr(macR), 4)} log.info("Initiating ARP ipL: %s, macL: %s, ipR: %s, macR: %s" %\ (ipaddrL,macL,ipaddrR,macR)) # If it is an IPv4 packet if isinstance(pnext, ipv4): # Learn or update mac and port info for IP self._arp_table[dpid][pnext.srcip] = (packet.src, port) 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,)) dst_ip = pnext.dstip # Find the packet destination # number hosts for computing convenience odd_ips = { IPAddr('10.0.0.1'): 1, IPAddr('10.0.0.3'): 3, IPAddr('10.0.0.5'): 5 } even_ips = { IPAddr('10.0.0.2'): 2, IPAddr('10.0.0.4'): 4, IPAddr('10.0.0.6'): 6 } # create msg and append destination port message = of.ofp_flow_mod(buffer_id=event.ofp.buffer_id) # 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] message.actions.append(of.ofp_action_dl_addr.set_dst(dst_mac)) #log.info("arp ref available 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.actions.append(of.ofp_action_output(port=dst_port)) message.match = of.ofp_match.from_packet(packet, port) event.connection.send(message) # (topology specific) if leaf switches (dpid is 1 , 2 or 3 in out case) if int(dpid) in [1, 2, 3]: ''' if dpid indicates leaf switch and src and dst shade that node directly redirect to the destination''' if pnext.srcip in odd_ips and \ odd_ips[pnext.srcip]+1 == even_ips[dst_ip]: message.actions.append(of.ofp_action_output(port=4)) message.match = of.ofp_match.from_packet(packet, port) event.connection.send(message) elif pnext.srcip in even_ips and \ even_ips[pnext.srcip]-1 == odd_ips[dst_ip]: message.actions.append(of.ofp_action_output(port=3)) message.match = of.ofp_match.from_packet(packet, port) event.connection.send(message) else: # route requests from odd numbered hosts through s4 if pnext.srcip in odd_ips: #message.actions.append(of.ofp_action_output(port = dst_port)) #core.openflow.sendToDPID(self.S4, message) message.actions.append( of.ofp_action_output(port=1)) message.match = of.ofp_match.from_packet( packet, port) log.info("Odd IP: %s should be routed through S4" % (pnext.srcip, )) event.connection.send(message) # route requests from even numbered hosts through s5 elif pnext.srcip in even_ips: #message.actions.append(of.ofp_action_output(port = dst_port)) message.actions.append( of.ofp_action_output(port=2)) message.match = of.ofp_match.from_packet( packet, port) log.info( "Even IP: %s should be routed through S5" % (pnext.srcip, )) event.connection.send(message) #core.openflow.sendToDPID(self.S5, message) # If this is a spine switch send message to all other links except the port in came on elif int(dpid) in [4, 5]: lnk_ports = [1, 2, 3] # ports on spine connecting to links lnk_ports = lnk_ports.remove(event.port) for i in lnk_ports: message.actions.append(of.ofp_action_output(port=i)) #message.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) message.match = of.ofp_match.from_packet(packet, port) event.connection.send(message) #If it is none of the switches 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("ARP: 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 ARP_Handler(self, packet, packet_in): log.debug("ARP FRAME RECEIVED FROM %s" % packet_in.in_port) if packet.payload.opcode == arp.REQUEST: log.debug("IT'S AN ARP REQUEST!") arp_payload = packet.payload arp_request_ip = str(arp_payload.protodst) if arp_request_ip in self.arp_table: log.debug("I know the MAC of this ARp REQUEST's IP!") 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("ARP REPLY SENT!") elif packet.payload.opcode == arp.REPLY: log.debug("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("%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(): ##DEBUG FROM HERE log.debug("A packet is detected in buffer!") out_port = self.routing_table[self.buffer[srcip]['DestinationNetwork']]['Port'] ip_packet = self.buffer[srcip]['IP_Packet'] source_ip = str(ip_packet.srcip) 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 if srcip == "10.0.4.100": print "Matching Source Ip Address too in flow push ("+source_ip+")" msg.match.nw_src = IPAddr(source_ip) else: print "source_ip match constraint not added" 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]))) if srcip == "10.0.4.100": #NOTE: srcip denotes the ip of the node that REPLIED to the ARP (it's hence the dest IP of the current packet) if source_ip == "10.0.1.100": queueno=1 elif source_ip == "10.0.2.100": queueno=2 else: queueno=0 print "PUSHING QOS FLOW for source_ip "+source_ip+" @queue "+str(queueno) msg.actions.append(of.ofp_action_enqueue(port = 4, queue_id=queueno)) else: print "PUSHING REGULAR FLOW!" msg.actions.append(of.ofp_action_output(port=out_port)) self.connection.send(msg) log.debug("Flow mod for destination network %s sent!", self.buffer[srcip]['DestinationNetwork']) self.buffer.pop(srcip)
def act_like_switch(self, packet, packet_in): """ Implement switch-like behavior. """ def drop(): if event.ofp.buffer_id is not None: msg = of.ofp_packet_out() msg.buffer_id = event.ofp.buffer_id event.ofp.buffer_id = None msg.in_port = packet_in.in_port self.connection.send(msg) # Here's some psuedocode to start you off implementing a learning # switch. You'll need to rewrite it as real Python code. # Learn the port for the source MAC self.mac_to_port[packet.src] = packet_in.in_port import pox.lib.packet as pkt #Ignore unnecessary packets if packet.type == packet.LLDP_TYPE: drop() return if packet.type == pkt.ethernet.IPV6_TYPE: return if packet.type == pkt.ethernet.IP_TYPE: ipv4_packet = packet.find("ipv4") src_ip = ipv4_packet.srcip dst_ip = ipv4_packet.dstip (nothing, sN, iPt, nada) = str(packet.next.srcip).split(".") (nothing, dN, dP, nada) = str(packet.next.dstip).split(".") srcNode = int(sN) dstNode = int(dN) destPort = int(dP) #Get all strictly shortest paths (e.g. same length) and randomly #select one from the top 8. allPaths = nx.all_shortest_paths(netGraph, self.sid, int(dstNode)) listPaths = [] for p in allPaths: listPaths.append(p) paths = listPaths[randint(0, min(len(listPaths) - 1, 7))] #Add corresponding flow table entry msg = of.ofp_flow_mod() msg.match = of.ofp_match.from_packet(packet) msg.match.idle_timeout = 10000 if dstNode == self.sid: msg.actions.append(of.ofp_action_output(port=destPort)) self.resend_packet(packet_in, destPort) else: nextPort = adjacency[paths[0]][paths[1]] msg.actions.append(of.ofp_action_output(port=nextPort)) self.resend_packet(packet_in, nextPort) self.connection.send(msg) #Handle ARP reply elif packet.type == packet.ARP_TYPE: if packet.payload.opcode == arp.REQUEST: mac_reply = ip_to_mac(packet.payload.protodst) print mac_reply print packet.payload.protodst arp_reply = arp() arp_reply.hwsrc = mac_reply 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 = mac_reply 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 = packet_in.in_port self.connection.send(msg) #Handle worst case unknown packet via flooding elif packet.type != packet.LLDP_TYPE: if packet.dst in self.mac_to_port: #if the port associated with the destination MAC of the packet is known: # Send packet out the associated port self.resend_packet(packet_in, self.mac_to_port[packet.dst]) # Once you have the above working, try pushing a flow entry # instead of resending the packet (comment out the above and # uncomment and complete the below.) log.debug("Installing flow...") # Maybe the log statement should have source/destination/port? #msg = of.ofp_flow_mod() # ## Set fields to match received packet #msg.match = of.ofp_match.from_packet(packet) # #< Set other fields of flow_mod (timeouts? buffer_id?) > # #< Add an output action, and send -- similar to resend_packet() > else: # Flood the packet out everything but the input port # This part looks familiar, right? self.resend_packet(packet_in, of.OFPP_ALL)
def _handle_PacketIn(self, event): """ Handles packet in messages from the switch. """ etherFrame = event.parsed # This is the parsed packet data. if not etherFrame.parsed: log.warning("Ignoring incomplete packet") return packet_in = event.ofp # The actual ofp_packet_in message. # Add the new MAC into CAM table if str(etherFrame.src) not in self.mac_to_port: log.debug('Adding %s into CAM' % str(etherFrame.src)) self.mac_to_port[str(etherFrame.src)] = packet_in.in_port # ARP if etherFrame.type == ethernet.ARP_TYPE: log.debug('RECEIVED: EtherType -> ARP') self.ARP_Handler(etherFrame, packet_in) # IP elif etherFrame.type == ethernet.IP_TYPE: log.debug('RECEIVED: EtherType -> IP') # Extract IP Packet from Ethernet Frame ip_packet = etherFrame.payload # Routable? destination_ip = str(ip_packet.dstip) source_ip = str(ip_packet.srcip) log.debug('DESTIP of THE CURRENT PACKET: '+destination_ip) routable = False for netaddr in self.routing_table: destination_network = netaddr if IPAddress(destination_ip) in IPNetwork(destination_network): log.debug('PACKET IS ROUTABLE!') routable = True break if routable: # Destined for router if self.routing_table[str(destination_network)]['RouterInterface'] == destination_ip: if ip_packet.protocol == ipv4.ICMP_PROTOCOL: log.debug('ICMP ECHO -> ROUTER INTERFACE') self.ICMP_Handler(etherFrame, packet_in) # Check if any there's any routable networks for the destination IP elif routable: # Route the packet to it's respective ports output_port = self.routing_table[destination_network]['Port'] # ARP if host MAC Address is not present if destination_ip not in self.arp_table: # Push frame to buffer self.buffer[destination_ip] = {'IP_Packet': ip_packet, 'DestinationNetwork': destination_network} # Construct ARP Packet arp_request = arp() arp_request.opcode = arp.REQUEST arp_request.protosrc = IPAddr(self.routing_table[destination_network]['RouterInterface']) arp_request.protodst = IPAddr(destination_ip) arp_request.hwsrc = EthAddr(self.arp_table[self.routing_table[destination_network]['RouterInterface']]) arp_request.hwdst = EthAddr('00:00:00:00:00:00') ether = ethernet() ether.type = ether.ARP_TYPE ether.src = EthAddr(self.arp_table[self.routing_table[destination_network]['RouterInterface']]) ether.dst = EthAddr('FF:FF:FF:FF:FF:FF') ether.payload = arp_request self.resend_packet(ether, output_port) if destination_ip in self.arp_table: etherFrame.src = EthAddr(self.arp_table[self.routing_table[destination_network]['RouterInterface']]) etherFrame.dst = EthAddr(self.arp_table[destination_ip]) self.resend_packet(etherFrame, output_port) # ICMP Destination Unreachable for non-routable networks else: log.debug('PACKET IS NOT ROUTABLE!') ethernet_frame = etherFrame ip_packet = etherFrame.payload icmp_request_packet = ip_packet.payload icmp_echo_reply_packet = icmp() icmp_echo_reply_packet.code = 0 icmp_echo_reply_packet.type = 3 icmp_echo_reply_packet.payload = icmp_request_packet.payload ip = ipv4() ip.srcip = ip_packet.dstip ip.dstip = ip_packet.srcip ip.protocol = ipv4.ICMP_PROTOCOL ip.payload = icmp_echo_reply_packet ether = ethernet() ether.type = ethernet.IP_TYPE ether.src = ethernet_frame.dst ether.dst = ethernet_frame.src ether.payload = ip self.resend_packet(ether, packet_in.in_port) log.debug("ICMP DESTINATION UNREACHABLE SENT")
def _handle_PacketIn (self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed #print "------------------------------------------------------------------------" #print "IPv4: ", event.parsed.find('ipv4') #print "ARP: ", event.parsed.find('arp') #print "Packet Type: " , packet.type #print datetime.datetime.now(), ":", packet #print "\n", packet.parsed #print "\n", event.ofp global call_Timer global set_Timer global diction timerSet =False def preventing(): global diction global set_Timer if not set_Timer: set_Timer =True if len(diction) == 0: 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 else: diction[event.connection.dpid][event.port] = 1 print "\n",datetime.datetime.now(), ": printing diction ",str(diction),"\n" def _timer_func (): global diction #print "Dictionary:", diction global set_Timer if not set_Timer: set_Timer =True if set_Timer==True: for k,v in diction.iteritems(): for i,j in v.iteritems(): if j >=20: print "\n",datetime.datetime.now(),"DDOS DETECTED" print "\n",str(diction) print "\n",datetime.datetime.now(),": BLOCKED PORT NUMBER : ", str(i), " OF SWITCH ID: ", str(k) #appending no actions to the out_msg the packets will be dropped from the current DPID-PORT pair 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: # 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)) #print "Arp table: ", str(self.arpTable) 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) #print "\n" chi_obj.stats(packet.next.srcip) #edit chi_obj.baseLine() #edit if chi_obj.y < 0.05 : print "DDoS might be there" preventing() Timer(10, _timer_func) # Send any waiting packets... self._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport) #print "LOST BUFFERS: " , str(self.lost_buffers) #edited # Learn or update port/MAC info if packet.next.srcip in self.arpTable[dpid]: #print packet.next.srcip , "#editing" 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) #print "Arp table: ", str(self.arpTable) # 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=of.OFP_FLOW_PERMANENT, buffer_id=event.ofp.buffer_id, actions=actions, match=of.ofp_match.from_packet(packet, inport)) event.connection.send(msg.pack()) elif self.arp_for_unknowns: # 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)
def _handle_PacketIn(self, event): global arpRecieved print('#####################################################') packet = event.parsed if packet.type == packet.ARP_TYPE: print('arp msg') arpRecieved = True if packet.payload.opcode == arp.REQUEST: print('arp request') # arp request packet from h1 to h2 if packet.payload.protosrc == ip_addr[ 1] and packet.payload.protodst == ip_addr[2]: # sending arp reply to h3 by modifying source as h2 arp_reply = arp() arp_reply.hwsrc = mac_addr[3] arp_reply.hwdst = packet.payload.hwsrc arp_reply.opcode = arp.REPLY arp_reply.protosrc = ip_addr[2] arp_reply.protodst = packet.payload.protosrc ether = ethernet() ether.type = ethernet.ARP_TYPE ether.dst = packet.src ether.src = mac_addr[3] ether.payload = arp_reply msg = of.ofp_packet_out() msg.data = ether.pack() msg.actions.append(of.ofp_action_output(port=1)) event.connection.send(msg) # arp request coming from h3 for h1 if packet.payload.protosrc == ip_addr[ 3] and packet.payload.protodst == ip_addr[1]: # sending arp reply to h1 by sending the mac address of h3 arp_reply = arp() arp_reply.hwsrc = mac_addr[1] arp_reply.hwdst = packet.payload.hwsrc arp_reply.opcode = arp.REPLY arp_reply.protosrc = ip_addr[1] arp_reply.protodst = packet.payload.protosrc ether = ethernet() ether.type = ethernet.ARP_TYPE ether.dst = packet.src ether.src = mac_addr[1] ether.payload = arp_reply msg = of.ofp_packet_out() msg.data = ether.pack() msg.actions.append(of.ofp_action_output(port=3)) event.connection.send(msg) # handling icmp packets if packet.find('icmp'): print('icmp packet found') icmp_request_packet = packet.payload.payload if arpRecieved: # sometimes hosts are sending icmp packets before sending arp packets, dropping those icmp packets if icmp_request_packet.type == 8: # if icmp packet is for h2 sending it to h3 if packet.payload.dstip == ip_addr[2]: packet.payload.dstip = ip_addr[3] msg = of.ofp_packet_out() msg.data = packet msg.actions.append(of.ofp_action_output(port=3)) event.connection.send(msg) if icmp_request_packet.type == 0: # seding icmp reply coming from h3 to h1 by changing its src address to h2 if packet.payload.srcip == ip_addr[3]: packet.payload.dstip = ip_addr[1] packet.payload.srcip = ip_addr[2] msg = of.ofp_packet_out() msg.data = packet msg.actions.append(of.ofp_action_output(port=1)) event.connection.send(msg)
def act_like_router(self, frame, packet_in, dpid): if frame.type == 0x0806: # ARP type packet = frame.payload network = 0 # arp request and in /30 subnet if packet.opcode == 1 and str(packet.protodst) in self.exterior: arp_data = pocket.arp( hwtype=packet.hwtype, prototype=packet.prototype, hwlen=packet.hwlen, protolen=packet.protolen, opcode=2, hwdst=packet.hwsrc, protodst=packet.protosrc, protosrc=packet.protodst, hwsrc=addresses.EthAddr('FA:DE:DD:ED:AF:AA')) e_frame = ethernet(type=0x0806, src=addresses.EthAddr('FA:DE:DD:ED:AF:AA'), dst=packet.hwsrc) e_frame.payload = arp_data out_packet = of.ofp_packet_out() out_packet.data = e_frame.pack() action = of.ofp_action_output(port=packet_in.in_port) out_packet.actions.append(action) self.connection.send(out_packet) log.debug("arp...") # arp reply and in /30 subnet elif (packet.opcode == 2) and str( packet.protodst) in self.exterior: self.arp_cache[packet.protosrc] = packet.hwsrc to_send = self.store.payload """ for nw in self.routing_table[dpid]: nw1 = self.routing_table[dpid][nw] if str(to_send.dstip) in nw1: network = nw break """ message = of.ofp_packet_out() my_port = self.routing_table[dpid][str(to_send.dstip)][3] action = of.ofp_action_output(port=my_port) self.store.src = addresses.EthAddr('FA:DE:DD:ED:AF:AA') self.store.dst = self.arp_cache[to_send.dstip] message.data = self.store.pack() message.actions.append(action) self.connection.send(message) log.debug("ICMP: sent from router to host") """ message = of.ofp_flow_mod() message.match.nw_dst = to_send.dstip message.match.dl_type = 0x0800 message.actions.append(of.ofp_action_dl_addr.set_src(self.store.src)) message.actions.append(of.ofp_action_dl_addr.set_dst(self.store.dst)) message.actions.append(of.ofp_action_output(port = self.routing_table[dpid][network][3])) log.debug("Flow Mode install Successfully") self.connection.send(message) """ self.store = None elif packet.protodst in self.interior: """ msg = of.ofp_packet_out() msg.data = frame.pack() my_port = self.routing_table[dpid][str(packet.protodst)][3] action = of.ofp_action_output(port = my_port) msg.actions.append(action) self.connection.send(msg) """ msg = of.ofp_flow_mod() msg.match = of.ofp_match.from_packet(frame) msg.data = packet_in action = of.ofp_action_output( port=self.routing_table[dpid][str(packet.protodst)][3]) msg.actions.append(action) self.connection.send(msg) elif frame.type == 0x0800: # IP type """ network = 0 for nw in self.interior: nw1 = nw if str(frame.payload.dstip) in nw1: network = nw break """ packet = frame.payload if str(packet.dstip) not in self.interior: # dst unreachable log.debug("dst %s is unreachable" % (frame.payload.dstip)) unreachable_type = pocket.unreach() unreachable_type.payload = frame.payload icmp_type = pocket.icmp() icmp_type.type = 3 icmp_type.payload = unreachable_type ip_type = pocket.ipv4(srcip=frame.payload.dstip, dstip=frame.payload.srcip, protocol=1, payload=icmp_type) ethernet_type = pocket.ethernet(type=0x0800, src=frame.dst, dst=frame.src, payload=ip_type) message = of.ofp_packet_out() message.data = ethernet_type.pack() message.actions.append( of.ofp_action_output(port=packet_in.in_port)) self.connection.send(message) # if ICMP type elif packet.protocol == 1 and packet.payload.type == 8 and str( packet.dstip) == self.exterior[dpid - 1]: data_icmp = packet.payload # if data_icmp.type == 8 and str(packet.dstip) in self.exterior: #if echo_request and dstip is in exterior echo_type = pocket.echo(seq=data_icmp.payload.seq + 1, id=data_icmp.payload.id) icmp_type = pocket.icmp(type=0, payload=echo_type) ip_type = pocket.ipv4(srcip=packet.dstip, dstip=packet.srcip, protocol=1, payload=icmp_type) ethernet_type = pocket.ethernet(type=0x0800, src=frame.dst, dst=frame.src, payload=ip_type) message = of.ofp_packet_out() message.data = ethernet_type.pack() message.actions.append( of.ofp_action_output(port=packet_in.in_port)) self.connection.send(message) elif packet.dstip in self.dirconnex[dpid]: port_num = self.routing_table[dpid][str(packet.dstip)][3] if packet.dstip not in self.arp_cache: # mapping of dstip not present self.store = frame arp_type = arp( hwlen=6, hwdst=ETHER_BROADCAST, protodst=packet.dstip, hwsrc=addresses.EthAddr('FA:DE:DD:ED:AF:AA'), protosrc=addresses.IPAddr(self.routing_table[dpid][str( packet.dstip)][2])) arp_type.opcode = 1 ethernet_type = ethernet( type=0x0806, src=addresses.EthAddr('FA:DE:DD:ED:AF:AA'), dst=ETHER_BROADCAST) ethernet_type.set_payload(arp_type) message = of.ofp_packet_out() message.data = ethernet_type.pack() message.actions.append( of.ofp_action_output(port=self.routing_table[dpid][str( packet.dstip)][3])) message.in_port = packet_in.in_port self.connection.send(message) elif packet.dstip in self.arp_cache: # mapping present in arp cache message = of.ofp_packet_out() action = of.ofp_action_output( port=self.routing_table[dpid][str(packet.dstip)][3]) frame.src = addresses.EthAddr('FA:DE:DD:ED:AF:AA') frame.dst = self.arp_cache[packet.dstip] message.data = frame.pack() message.actions.append(action) self.connection.send(message) """ message = of.ofp_flow_mod() message.match.nw_dst = packet.dstip message.match.dl_type = 0x0800 message.actions.append(of.ofp_action_dl_addr.set_src(frame.src)) message.actions.append(of.ofp_action_dl_addr.set_dst(frame.dst)) message.actions.append(of.ofp_action_output(port = self.routing_table[network][3])) self.connection.send(message) """ else: # route to the next hop log.debug("the packet proceeds to the next hop") port_to_send = self.routing_table[dpid][str(packet.dstip)][3] next_ip = self.routing_table[dpid][str(packet.dstip)][0] msg = of.ofp_packet_out() action = of.ofp_action_output(port=port_to_send) frame.dst = ETHER_BROADCAST frame.src = addresses.EthAddr('FA:DE:DD:ED:AF:AA') msg.data = frame.pack() msg.actions.append(action) self.connection.send(msg) log.debug("IPv4 has been sent")
def _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 >= 32: 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): # 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 if a.protosrc in _arp_table: if _arp_table[a.protosrc] != Entry(a.hwsrc): log.warn("%s RE-learned %s: %s->%s", dpid_to_str(dpid), a.protosrc, _arp_table[a.protosrc].mac, a.hwsrc) else: log.info("%s learned %s", dpid_to_str(dpid), a.protosrc) _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 = _dpid_to_mac(dpid) r.hwsrc = mac e = ethernet(type=packet.type, src=_dpid_to_mac(dpid), 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): 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 log.debug("Add switch %s", str(dpid)) self.arpTable[dpid] = {} for fake in self.fakeways[dpid - 1]: self.arpTable[dpid][IPAddr(fake)] = Entry( of.OFPP_NONE, dpid_to_mac(dpid)) self.set_firewall(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) '''deal with ICMP''' # in case the host may ping router (not 127.0.0.1) if packet.payload.protocol == packet.payload.ICMP_PROTOCOL and str( packet.payload.dstip) in self.fakeways[dpid - 1]: print "ICMP" packet.payload.payload.type = 0 # ICMP reachable packet.payload.dstip, packet.payload.srcip = packet.payload.srcip, packet.payload.dstip packet.src, packet.dst = packet.dst, packet.src msg = of.ofp_packet_out() msg.data = packet action = of.ofp_action_output(port=inport) msg.actions.append(action) event.connection.send(msg) return # 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=of.OFP_FLOW_PERMANENT, buffer_id=event.ofp.buffer_id, actions=actions, match=of.ofp_match.from_packet( packet, inport)) event.connection.send(msg.pack()) elif self.arp_for_unknowns: # 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) entry = (time.time() + MAX_BUFFER_TIME, event.ofp.buffer_id, inport, packet) 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)
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_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 """ FIREWALL""" p = "54312, 12311, 21311" blocking_port.update(int(x) for x in p.replace(",", " ").split()) core.openflow.addListenerByName("PacketIn", firewall) 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 dpid not in self.routing: # New switch -- create an empty table self.routing[dpid] = {} if dpid == 1: self.routing[dpid][IPAddr('10.0.2.1')] = 1 self.routing[dpid][IPAddr('10.0.3.1')] = 2 if dpid == 2: self.routing[dpid][IPAddr('10.0.1.1')] = 1 self.routing[dpid][IPAddr('10.0.3.1')] = 2 if dpid == 3: self.routing[dpid][IPAddr('10.0.1.1')] = 1 self.routing[dpid][IPAddr('10.0.2.1')] = 2 if packet.type == ethernet.LLDP_TYPE: # Ignore LLDP packets return if isinstance(packet.next, ipv4): dstaddr = packet.next.dstip srcaddr = packet.next.srcip n = str(dstaddr).split('.') l = str(srcaddr).split('.') log.debug("%i %i IP %s => %s here", dpid, inport, packet.next.srcip, packet.next.dstip) if n[2] != str(dpid) and l[2] != str(dpid): log.debug("Not destined to this subnet: Packet Dropped") return # 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) if packet.next.srcip not in self.routing[dpid]: self.routing[dpid][packet.next.srcip] = inport if n[0] != '10': self.icmp_message(dpid, packet, packet.next.srcip, packet.next.dstip, pkt.TYPE_DEST_UNREACH, event) return if n[1] != '0': self.icmp_message(dpid, packet, packet.next.srcip, packet.next.dstip, pkt.TYPE_DEST_UNREACH, event) return if n[2] != '1' and n[2] != '2' and n[2] != '3': self.icmp_message(dpid, packet, packet.next.srcip, packet.next.dstip, pkt.TYPE_DEST_UNREACH, event) return if n[2] == '1': if n[3] != '2' and n[3] != '3' and n[3] != '1' and n[3] != '4': self.icmp_message(dpid, packet, packet.next.srcip, packet.next.dstip, pkt.TYPE_DEST_UNREACH, event) return if n[2] == '2': if n[3] != '2' and n[3] != '1' and n[3] != '3' and n[3] != '4': self.icmp_message(dpid, packet, packet.next.srcip, packet.next.dstip, pkt.TYPE_DEST_UNREACH, event) return if n[2] == '3': if n[3] != '2' and n[3] != '1' and n[3] != '3' and n[3] != '4': self.icmp_message(dpid, packet, packet.next.srcip, packet.next.dstip, pkt.TYPE_DEST_UNREACH, event) return # Try to forward if dstaddr in self.fakeways and int(n[2]) == dpid: if isinstance(packet.next.next, icmp): if packet.next.next.type == pkt.TYPE_ECHO_REQUEST: self.icmp_message(dpid, packet, packet.next.srcip, packet.next.dstip, pkt.TYPE_ECHO_REPLY, event) elif n[2] == l[2]: if dstaddr not in self.routing[ dpid] or dstaddr not in self.arpTable[dpid]: 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 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) 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 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=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()) else: if dstaddr in self.arpTable[dpid]: n_addr = IPAddr('10.0.%d.1' % int(n[2])) mac = self.arpTable[dpid][dstaddr].mac prt = self.routing[dpid][dstaddr] 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 self.arp_for_unknowns: if dstaddr not in self.routing[ dpid] or dstaddr not in self.arpTable[dpid]: 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 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 n = str(packet.next.protodst).split('.') l = str(packet.next.protosrc).split('.') 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 n[2] != str(dpid) and l[2] != str(dpid): log.debug("Not destined to this subnet: Packet Dropped") return flag = 0 q = str(a.protodst).split('.') 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 packet.next.protosrc not in self.routing[dpid]: self.routing[dpid][packet.next.protosrc] = inport # 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 self.arpTable[dpid][a.protodst] or ( self.fakeways and int(n[2]) == dpid): # .. 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 else: n_addr = IPAddr('10.0.%d.1' % int(n[2])) mac = self.arpTable[dpid][n_addr].mac prt = self.routing[dpid][a.protodst] r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwdst = mac 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.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=prt)) msg.in_port = inport event.connection.send(msg) return elif a.opcode == arp.REPLY and a.protodst != IPAddr( '10.0.%d.1' % (dpid)): if a.protodst in self.routing[dpid] and n[2] != l[ 2] and inport != 1 and inport != 2: flag = 1 n_addr = IPAddr('10.0.%d.1' % int(n[2])) prt = self.routing[dpid][a.protodst] msg = of.ofp_packet_out() msg.data = event.ofp action = of.ofp_action_output(port=prt) msg.actions.append(action) event.connection.send(msg) else: flag = 1 msg = of.ofp_packet_out( in_port=inport, data=event.ofp, action=of.ofp_action_output( port=of.OFPP_FLOOD)) event.connection.send(msg) if flag == 0: # 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): packet = event.parsed if not packet.parsed: return port = event.port dpid = event.connection.dpid pnext = packet.next # 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 self._arp_table[dpid][pnext.srcip] = (packet.src, port) 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 # number hosts for computing convenience odd_ips = {"10.0.0.1": 1, "10.0.0.3": 3, "10.0.0.5": 5} even_ips = {"10.0.0.2": 2, "10.0.0.4": 4, "10.0.0.6": 6} # create msg message = of.ofp_flow_mod(buffer_id=event.ofp.buffer_id) message.actions.append(of.ofp_action_dl_addr.set_dst(dst_mac)) # if dpid indicates leaf switch and src and dst shade that node # directly redirect to the destination if pnext.srcip in odd_ips and \ odd_ips[pnext.srcip]+1 == even_ips[dst_ip]: message.actions.append(of.ofp_action_output(port=4)) if pnext.srcip in even_ips and \ even_ips[pnext.srcip]-1 == odd_ips[dst_ip]: message.actions.append(of.ofp_action_output(port=3)) # 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) # route odd leaf switches through s4 and even ones through s5 else: # (topology specific)if leaf switches (dpid is 1 , 2 or 3 in out case) if pnext.srcip in odd_ips and int(dpid) in [1, 2, 3]: # route throgh s4 # (topology specific)port 1 on leaf nodes always connect to s4 message.actions.append(of.ofp_action_output(port=1)) log.info("Odd IP: %s should be routed through S4" % (pnext.srcip, )) elif pnext.srcip in even_ips: # (topology specific)port 2 on leaf nodes always connect to s5 message.actions.append(of.ofp_action_output(port=2)) log.info("Even IP: %s should be routed through S5" % (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): # check if the entry is in the table or not # if it's not in the table, add an entry to the table # We don't know where the destination is yet. So, we'll just # send the packet out all ports (except the one it came in on!) # and hope the destination is out there somewhere. :) # To send out all ports, we can use either of the special ports # OFPP_FLOOD or OFPP_ALL. # if the appropriate entry is in the table, just forward the packet to that port # parse the packet packet = event.parsed src_mac = packet.src dst_mac = packet.dst switch = event.connection port_in = event.port switch = event.connection match = of.ofp_match.from_packet(packet) arp_request = packet.find('arp') #identify switch dpid = event.connection.dpid if not arp_request: #part 2 if (dpid_to_str(dpid) == "00-00-00-00-00-01"): port_out = l1[str(dst_mac)] elif (dpid_to_str(dpid) == "00-00-00-00-00-02"): port_out = l2[str(dst_mac)] elif (dpid_to_str(dpid) == "00-00-00-00-00-03"): port_out = l3[str(dst_mac)] elif (dpid_to_str(dpid) == "00-00-00-00-00-04"): port_out = s4[str(dst_mac)] elif (dpid_to_str(dpid) == "00-00-00-00-00-05"): port_out = s5[str(dst_mac)] msg = of.ofp_packet_out() msg.data = event.ofp msg.actions.append(of.ofp_action_output(port=port_out)) switch.send(msg) else: if arp_request.prototype == arp.PROTO_TYPE_IP: if arp_request.hwtype == arp.HW_TYPE_ETHERNET: if arp_request.protosrc != 0: if arp_request.opcode == arp.REQUEST: dst_ip = arp_request.protodst src_ip = arp_request.protosrc res = arp() res.hwtype = arp_request.hwtype res.prototype = arp_request.prototype res.hwlen = arp_request.hwlen res.protolen = arp_request.protolen res.opcode = arp.REPLY res.hwdst = arp_request.hwsrc res.protodst = src_ip res.protosrc = dst_ip mac = EthAddr(arp_table[str(dst_ip)]) res.hwsrc = mac e = ethernet(type=packet.type, src=mac, dst=arp_request.hwsrc) e.payload = res msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = port_in switch.send(msg)
def _handle_PacketIn (self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed if not packet.parsed: log.warning("%i %i ignoring unparsed packet", dpid, inport) return if dpid not in self.arpTable: # New switch -- create an empty table self.arpTable[dpid] = {} ##### Cria uma tabela vazia para registro de disponibilidade de QoS self.hasQoS[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=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()) ########################################################################################################## ########################################### Instrucoes QoS ############################################### ########################################################################################################## net=packet.next transp=packet.next.next #Realiza o mapeamento inicial entre IP, porta e QoS (-1) if net.protocol==6 and transp.dstport==SERVER_PORT: if not self.portMap.has_key(net.srcip): self.portMap={net.srcip:(transp.srcport,-1)} #Testa se o pacote eh UDP (troca de mensagens RSVP) if net.protocol==17: #Testa se a mensagem eh RSVP originada pelo solicitador if transp.srcport==23231: #Testa se a mensagem eh RSVP RESV if net.tos!=0: #Atualiza a fila do mapeamento IP, porta e QoS port,queue=self.portMap[net.srcip] queue=(net.tos/10)-1 self.portMap[net.srcip]=(port,queue) #Consulta a disponibilidade de QoS na porta de saida do roteador if not self.hasQoS[dpid].has_key(inport): self.hasQoS[dpid][inport] = be if self.hasQoS[dpid][inport] + classlist[queue].pico <= TX_MAX: log.info("QoS disponivel em R%d - porta %d: %d",dpid,inport,TX_MAX-self.hasQoS[dpid][inport]) else: log.info("QoS nao disponivel - largura de banda insuficiente") #Testa se a mensagem eh RSVP FIN else: #Exclui o mapeamento IP, porta e QoS if self.portMap.has_key(net.srcip): del self.portMap[net.srcip] #Testa se a mensagem eh RSVP originada pelo prestador if transp.srcport==23232: #Testa se a mensagem eh RSVP RESV_CONF if net.tos!=0: port,queue=self.portMap[net.dstip] #Aplica QoS na porta de saida do roteador qos=os.popen("ovs-vsctl list qos | grep _uuid | awk '{print $3}'").read().strip('\n') os.system('ovs-vsctl set port r%d-eth%d qos=%s' %(dpid,prt,qos)) log.info("QoS %s aplicada em R%s - porta %d",qos,dpid,prt) #Acrescenta a banda alocada a tabela de disponibilidade de QoS self.hasQoS[dpid][prt]+=classlist[self.portMap[net.dstip][1]].pico #Copia os parametros de cabecalho do pacote UDP msg1=of.ofp_flow_mod(command=of.OFPFC_MODIFY) msg1.match = of.ofp_match.from_packet(packet,inport) #Altera os parametros de cabecalho para o futuro fluxo TCP msg1.priority=65535 msg1.idle_timeout=30 msg1.hard_timeout=120 msg1.match.nw_proto=6 msg1.match.nw_tos=0 msg1.match.tp_src=SERVER_PORT msg1.match.tp_dst=port msg1.actions.append(of.ofp_action_enqueue(port=prt,queue_id=queue)) #Instala a regra no roteador event.connection.send(msg1) log.info("Fila %d aplicada ao fluxo tp_dst %d",queue,port) ########################################################################################################## ########################################### Instrucoes QoS ############################################### ########################################################################################################## 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)
def _handle_openflow_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: # 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) """ stdout ipv4 header """ ################################## print 'l3 prototype packet received' currentTime = time.time() - self.startTime sourceIP = packet.next.srcip destinationIP = packet.next.dstip packetString = str(packet.next) protocol = 0 if 'UDP' in packetString: protocol = 17 elif 'ICMP' in packetString: protocol = 1 elif 'TCP' in packetString: protocol = 6 #trafficClass = 1 if '18' in str(packet.next.ttl) trafficClass = 0 if '18' in str(packet.next.ttl): trafficClass = '1' else: trafficClass = '0' self.svm.classify( [currentTime, sourceIP, destinationIP, protocol, trafficClass]) #################################### # 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 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 ARP_Handler(self, packet, packet_in): log.debug("ARP FRAME RECEIVED FROM %s" % packet_in.in_port) if packet.payload.opcode == arp.REQUEST: log.debug("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("ARP REPLY SENT!") elif packet.payload.opcode == arp.REPLY: log.debug("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("%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 'YES!' 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("Flow mod for destination network %s sent!", self.buffer[srcip]['DestinationNetwork']) self.buffer.pop(srcip)
def _handle_PacketIn(self, event): """ Handles packet in messages from the switch. """ etherFrame = event.parsed # This is the parsed packet data. packet_in = event.ofp # The actual ofp_packet_in message. # Incomplete frames if not etherFrame.parsed: log.warning("Ignoring incomplete packet") return # LLDP if etherFrame.type == ethernet.LLDP_TYPE: log.warning("Ignoring LLDP") return # Add the new MAC into CAM table 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 list(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 list(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 for the Next Hop 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)