def convert(h,val): if h in ['srcmac','dstmac']: return packetaddr.EthAddr(val) elif h in ['srcip','dstip']: try: return packetaddr.IPAddr(val) except: return val elif h in ['vlan_id','vlan_pcp'] and val == 'None': return None else: return val
def broadcast_routing_table(self): rip_msg = pkt.rip() rip_msg.version = 2 rip_msg.command = pkt.RIP_RESPONSE for entry in self.routing_table: rip_entry = pkt.RIPEntry() rip_entry.ip = adr.IPAddr(entry.split("/")[0]) rip_entry.netmask = int(entry.split("/")[1]) rip_entry.metric = self.routing_table[entry][-1] rip_msg.entries.append(rip_entry) if entry[1] != forever_ttl: --self.routing_table[entry][1] if self.routing_table[entry][1] == 0: del self.routing_table[entry] udp = pkt.udp() udp.srcport = 520 udp.dstport = 520 # log.debug( "Created rip msg of len: %d", len(rip_msg) ) udp.len = len(rip_msg) udp.payload = rip_msg ipv4 = pkt.ipv4() ipv4.protocol = pkt.ipv4.UDP_PROTOCOL ipv4.srcip = pkt.IP_ANY ipv4.dstip = pkt.rip.RIP2_ADDRESS ipv4.payload = udp ether = pkt.ethernet() ether.type = pkt.ethernet.IP_TYPE ether.dst = adr.EthAddr('ff:ff:ff:ff:ff:ff') ether.payload = ipv4 for port in self.port_to_hwaddr.keys()[0:-1]: ether.src = self.port_to_hwaddr[port] # log.debug( "Broadcasting routing table" ) msg = of.ofp_packet_out() msg.data = ether.pack() # Add an action to send to the specified port action = of.ofp_action_output(port=port) msg.actions.append(action) self.connection.send(msg)
def addNode(self, ip, mac, port=None): """ Construct a new Node from the given argument, keep it in self.nodes, and perform active OVS port discovery. If there is already a node with the same IP and MAC, no new node will be created """ ipaddr = libaddr.IPAddr(ip) macaddr = libaddr.EthAddr(mac) node = self.nodes.get(ipaddr, None) if node and node.mac == macaddr: return node newNode = Node(ipaddr, macaddr, port=port) self.nodes[ipaddr] = newNode self.sendArpRequest(newNode) log.debug('New Node object created with IP %s' % ipaddr) return newNode
def __init__(self, conn, ipaddr=None): self.conn = conn # Reserved IP address for the SDN controller. if ipaddr: self._ip = libaddr.IPAddr(ipaddr) else: self._ip = IP_ANY # we can update this later self._macAddress = _randomMacAddress() # relevant network nodes connected to this OVS self.nodes = {} # available service chains reachable by the OVS self.availableChains = {} # full SFC path between 2 endpoints. Each path is identified by an ordered # pair of the endpoints. Service chains can be reused by different pairs. # This table will be filled after active discovery by the SDN controller self.servicePaths = {}
f = logging.Formatter(logging.BASIC_FORMAT) h.setFormatter(f) l.addHandler(h) addRemoteLogger(fw_log, 9999) addRemoteLogger(logging.getLogger(), 9998) MAX_CONNECTIONS = 7000 PRIORITY_NORMAL = 10 #of.OFP_DEFAULT_PRIORITY PRIORITY_ALL_TCP = PRIORITY_NORMAL - 1 PRIORITY_FLOOD_REST = PRIORITY_ALL_TCP - 1 LOCAL_NETWORK = addresses.parseCIDR("10.1.1.0/24") INTERNAL_ADDRESS = addresses.IPAddr("10.1.1.1") MAX_BUFFERED_PACKETS = 15000 MAX_BUFFERED_PER_CONNECTION = 500 current_buffered_packets = 0 UNKNOWN_PORT = object() INSIDE_PORT = ["uap0", "eth0"] OUTSIDE_PORT = "veth1" INTERNAL_PORT = "veth1" class ACTION_FORWARD: pass
def send_arp_request(self, port_num, packet, packet_in, dpid): arp_data = arp(hwdst = ETHER_BROADCAST, hwlen = 6, protodst = packet.payload.dstip, hwsrc = adr.EthAddr('EF:EF:EF:EF:EF:EF'), protosrc = adr.IPAddr(self.routing_table[dpid][str(packet.payload.dstip)][2])) arp_data.hwtype = arp_data.HW_TYPE_ETHERNET arp_data.prototype = arp_data.PROTO_TYPE_IP arp_data.protolen = arp_data.protolen arp_data.opcode = arp_data.REQUEST e = ethernet(type=ethernet.ARP_TYPE, src=adr.EthAddr('EF:EF:EF:EF:EF:EF'), dst=ETHER_BROADCAST) e.set_payload(arp_data) message = of.ofp_packet_out() message.data = e.pack() message.actions.append(of.ofp_action_output(port = port_num)) message.in_port = packet_in.in_port self.connection.send(message) log.debug("ARP: request sent")
def setIP(self, ipstring): """ Set an IP address for the SDN controller between this connection """ ipaddr = libaddr.IPAddr(ipstring) self._ip = ipaddr
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_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed flag = 1 packet_in = event.ofp self.connection = event.connection if not packet.parsed: log.warning("Router %i, input port = %i: ignoring unparsed packet", dpid, inport) return icmp_packet = packet.find('icmp') if icmp_packet is not None: if icmp_packet.type == pkt.TYPE_ECHO_REQUEST: log.debug("Received ICMP request message") found = 0 #To check if destination is reachable by ping for node in self.node_list: if packet.payload.dstip.inNetwork( node): #If the destination IP is in the network found = node break if found == 0: log.debug("Destination Unreachable") icmp_reply = pkt.icmp() icmp_reply.type = pkt.TYPE_DEST_UNREACH icmp_reply.code = pkt.ICMP.CODE_UNREACH_HOST icmp_reply_payload = packet.find('ipv4').pack() icmp_reply_payload = icmp_reply_payload[:packet.find('ipv4' ).hl * 4 + 8] import struct icmp_reply_payload = struct.pack("!HH", 0, 0) + icmp_reply_payload icmp_reply.payload = icmp_reply_payload #Making the IPv4 packet around it icmp_reply_packet = pkt.ipv4() icmp_reply_packet.protocol = icmp_reply_packet.ICMP_PROTOCOL icmp_reply_packet.srcip = packet.find("ipv4").dstip icmp_reply_packet.dstip = packet.find("ipv4").srcip #Putting this packet in an ethernet frame icmp_ethernet_frame = pkt.ethernet() icmp_ethernet_frame.type = pkt.ethernet.IP_TYPE icmp_ethernet_frame.dst = packet.src icmp_ethernet_frame.src = packet.dst #Encapsulating... icmp_reply_packet.payload = icmp_reply icmp_ethernet_frame.payload = icmp_reply_packet #Sending the ping reply back through the port it came in at msg = of.ofp_packet_out() msg.data = icmp_ethernet_frame.pack() msg.actions.append( of.ofp_action_output(port=packet_in.in_port)) self.connection.send(msg) log.debug("Sent 'Dest Unreachable' message") else: if found == "10.0.1.1" or "10.0.2.1": log.debug("Trying to reach router = %s" % found) #Making the ping reply icmp_reply = pkt.icmp() icmp_reply.type = pkt.TYPE_ECHO_REPLY icmp_reply.payload = icmp_packet.payload #Making the IPv4 packet around it icmp_reply_packet = pkt.ipv4() icmp_reply_packet.protocol = icmp_reply_packet.ICMP_PROTOCOL icmp_reply_packet.srcip = packet.find("ipv4").dstip icmp_reply_packet.dstip = packet.find("ipv4").srcip #Putting this packet in an ethernet frame icmp_ethernet_frame = pkt.ethernet() icmp_ethernet_frame.type = pkt.ethernet.IP_TYPE icmp_ethernet_frame.dst = packet.src icmp_ethernet_frame.src = packet.dst #Encapsulating... icmp_reply_packet.payload = icmp_reply icmp_ethernet_frame.payload = icmp_reply_packet #Sending the ping reply back through the port it came in at msg = of.ofp_packet_out() msg.data = icmp_ethernet_frame.pack() msg.actions.append( of.ofp_action_output(port=packet_in.in_port)) self.connection.send(msg) log.debug("Sent ICMP reply") flag = 0 if dpid not in self.mac_table: # New switch -- create an empty table self.mac_table[dpid] = {} for subnet in self.subnets: self.mac_table[dpid][addr.IPAddr(subnet)] = Entry( of.OFPP_NONE, dpid_to_mac(dpid)) if isinstance(packet.next, pkt.ipv4): log.debug( "Router %i, input port = %i: Received an IP packet from %s to %s", dpid, inport, packet.next.srcip, packet.next.dstip) # Learn or update port/MAC info self.mac_table[dpid][packet.next.srcip] = Entry(inport, packet.src) # Try to forward dstaddr = packet.next.dstip if dstaddr in self.mac_table[dpid]: # We know where to send it prt = self.mac_table[dpid][dstaddr].port mac = self.mac_table[dpid][dstaddr].mac log.debug( "Router %i:Forwarding the packet to dst_MAC address = %s through port = %i", dpid, mac, prt) if flag == 1: actions = [] actions.append(of.ofp_action_dl_addr.set_dst(mac)) actions.append(of.ofp_action_output(port=prt)) match = of.ofp_match.from_packet(packet, inport) match.dl_src = None msg = of.ofp_flow_mod(command=of.OFPFC_ADD, idle_timeout=FLOW_IDLE_TIMEOUT, hard_timeout=of.OFP_FLOW_PERMANENT, buffer_id=event.ofp.buffer_id, actions=actions, match=of.ofp_match.from_packet( packet, inport)) event.connection.send(msg.pack()) elif self.arp_for_unknowns: r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REQUEST r.hwdst = ETHER_BROADCAST r.protodst = dstaddr r.hwsrc = packet.src r.protosrc = packet.next.srcip e = pkt.ethernet(type=pkt.ethernet.ARP_TYPE, src=packet.src, dst=ETHER_BROADCAST) e.set_payload(r) log.debug("Router %i: ARPing for %s on behalf of %s" % (dpid, str(r.protodst), str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) msg.in_port = inport event.connection.send(msg) elif isinstance(packet.next, arp): a = packet.next log.debug("Router %i, received an ARP packet at port = %i", dpid, inport) if a.prototype == arp.PROTO_TYPE_IP: if a.hwtype == arp.HW_TYPE_ETHERNET: if a.protosrc != 0: #Update MAC table self.mac_table[dpid][a.protosrc] = Entry( inport, packet.src) if a.opcode == arp.REQUEST: if a.protodst in self.mac_table[dpid]: #We know how to answer the ARP ourselves r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwdst = a.hwsrc r.protodst = a.protosrc r.protosrc = a.protodst r.hwsrc = self.mac_table[dpid][a.protodst].mac e = pkt.ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwsrc) e.set_payload(r) log.debug( "Router %i, input port %i answering ARP for %s" % (dpid, inport, str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) return else: # Didn't know how to answer or otherwise handle this ARP, so just flood it log.debug( "Flooding to all ports since we don't have the MAC address in mac_table" ) msg = of.ofp_packet_out( in_port=inport, data=event.ofp, action=of.ofp_action_output( port=of.OFPP_FLOOD)) event.connection.send(msg)
def launch(): subnets = "10.0.1.1 10.0.2.1" subnets = subnets.split() subnets = [addr.IPAddr(x) for x in subnets] arp_for_unknowns = len(subnets) > 0 core.registerNew(router, subnets, arp_for_unknowns)
def packet_handler (self, frame, packet_in): "process every packet\n" # disposal of different kinds of packet, including a default drop # generates prompt text for non-data packets and all invalid packets isHandled = False if frame.type == Packet.ethernet.ARP_TYPE: arpPkt = frame.payload if arpPkt.opcode == Packet.arp.REQUEST: # check if the arp request has a valid target arp_req = arpPkt srcIPStr = str(arp_req.protosrc) prefix = srcIPStr[0:srcIPStr.rfind(".")] expectedIPdest = prefix + ".1" if expectedIPdest == str(arp_req.protodst): # a valid arp req log.info("a valid arp request is got") arpReply = Packet.arp() macInterface = Addr.EthAddr("00:00:00:00:00:" + prefix[-1]*2) arpReply.hwsrc = macInterface arpReply.hwdst = arp_req.hwsrc arpReply.opcode = Packet.arp.REPLY arpReply.protosrc = Addr.IPAddr(expectedIPdest) arpReply.protodst = arp_req.protosrc ether = Packet.ethernet() ether.type = Packet.ethernet.ARP_TYPE ether.dst = frame.src ether.src = macInterface ether.payload = arpReply msg = of.ofp_packet_out() msg.data = ether action = of.ofp_action_output(port = packet_in.in_port) msg.actions.append(action) self.connection.send(msg) isHandled = True elif frame.type == frame.IP_TYPE: datagram = frame.payload # if it's a valid icmp echo request, reply to it if datagram.protocol == datagram.ICMP_PROTOCOL: segment = datagram.payload if segment.type == Packet.TYPE_ECHO_REQUEST: # check if the destination IP is correct dstIPStr = str(datagram.dstip) if dstIPStr in self.interface_IPs: log.info("an icmp request to router interfaces is got") # generate a reply and send it icmpReply = Packet.icmp() icmpReply.type = Packet.TYPE_ECHO_REPLY icmpReply.payload = segment.payload ipp = Packet.ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = datagram.dstip ipp.dstip = datagram.srcip e = Packet.ethernet() e.src = frame.dst e.dst = frame.src e.type = e.IP_TYPE ipp.payload = icmpReply e.payload = ipp msg = of.ofp_packet_out() msg.data = e msg.actions.append( of.ofp_action_output(port = packet_in.in_port)) self.connection.send(msg) isHandled = True # if it's a packet sent to one of the other two hosts dstIPStr = str(datagram.dstip) if dstIPStr in self.routing_table: log.info("a packet between hosts is got") tableEntry = self.routing_table[dstIPStr] # # # flow mod # msg = of.ofp_flow_mod(match = of.ofp_match.from_packet(frame)) # msg.actions.append( # of.ofp_action_dl_addr.set_src(Addr.EthAddr(tableEntry["intMAC"]))) # msg.actions.append( # of.ofp_action_dl_addr.set_dst(Addr.EthAddr(tableEntry["hostMAC"]))) # msg.actions.append(of.ofp_action_output(port = tableEntry["port"])) # self.connection.send(msg) # log.info("a flow entry is installed") # modify data link src and dst frame.src = Addr.EthAddr(tableEntry["intMAC"]) frame.dst = Addr.EthAddr(tableEntry["hostMAC"]) # resend it out self.resend_packet(frame, tableEntry["port"]) isHandled = True if not isHandled: # drop it log.info("an invalid frame is got")