Exemplo n.º 1
0
def _handle_PacketIn (event):
  packet = event.parsed

  if packet.find("arp"):
    # Reply to ARP
    a = packet.find("arp")
    if a.opcode == a.REQUEST:
      r = pkt.arp()
      r.hwtype = a.hwtype
      r.prototype = a.prototype
      r.hwlen = a.hwlen
      r.protolen = a.protolen
      r.opcode = r.REPLY
      r.hwdst = a.hwsrc
      r.protodst = a.protosrc
      r.protosrc = a.protodst
      r.hwsrc = EthAddr("02:00:DE:AD:BE:EF")
      e = pkt.ethernet(type=packet.type, src=r.hwsrc, dst=a.hwsrc)
      e.payload = r

      msg = of.ofp_packet_out()
      msg.data = e.pack()
      msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
      msg.in_port = event.port
      event.connection.send(msg)

      log.info("%s ARPed for %s", r.protodst, r.protosrc)

  elif packet.find("icmp"):
    # Reply to pings

    # Make the ping reply
    icmp = pkt.icmp()
    icmp.type = pkt.TYPE_ECHO_REPLY
    icmp.payload = packet.find("icmp").payload

    # Make the IP packet around it
    ipp = pkt.ipv4()
    ipp.protocol = ipp.ICMP_PROTOCOL
    ipp.srcip = packet.find("ipv4").dstip
    ipp.dstip = packet.find("ipv4").srcip

    # Ethernet around that...
    e = pkt.ethernet()
    e.src = packet.dst
    e.dst = packet.src
    e.type = e.IP_TYPE

    # Hook them up...
    ipp.payload = icmp
    e.payload = ipp

    # Send it back to the input port
    msg = of.ofp_packet_out()
    msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
    msg.data = e.pack()
    msg.in_port = event.port
    event.connection.send(msg)

    log.debug("%s pinged %s", ipp.dstip, ipp.srcip)
Exemplo n.º 2
0
    def send_to_switch(self,packet):
        switch = packet["switch"]
        outport = packet["outport"]
        try:
            inport = packet["inport"]
            if inport == -1 or inport == outport:
                inport = inport_value_hack(outport)
        except KeyError:
            inport = inport_value_hack(outport)
        
        msg = of.ofp_packet_out()
        msg.in_port = inport
        msg.data = self.packet_to_network(packet)
        msg.actions.append(of.ofp_action_output(port = outport))
 
        if self.show_traces:
            print "========= POX/OF SEND ================"
            print msg
            print packetlib.ethernet(msg._get_data())
            print

        ## HANDLE PACKETS SEND ON LINKS THAT HAVE TIMED OUT
        try:
            self.switches[switch]['connection'].send(msg)
        except Runtimerror, e:
            print "ERROR:send_to_switch: %s to switch %d" % (str(e),switch)
Exemplo n.º 3
0
    def packet_to_network(self, packet):
        self.trace("packet_to_network: packet=%s\n" % packet, timeStamped=True)
        
        if len(packet["raw"]) == 0:
            if packet["ethtype"] == packetlib.ethernet.ARP_TYPE:
                p_begin = p = self.make_arp(packet)
            else:  # BLANK PACKET FOR NOW - MAY NEED TO SUPPORT OTHER PACKETS LATER
                p_begin = p = packetlib.ethernet()
        else:
            p_begin = p = packetlib.ethernet(packet["raw"])

        # ETHERNET PACKET IS OUTERMOST
        p.src = packet["srcmac"]
        p.dst = packet["dstmac"]

        if 'vlan_id' in packet:
            if isinstance(p.next, packetlib.vlan):
                p = p.next
            else:
                # Make a vlan header
                old_eth_type = p.type
                p.type = 0x8100
                p.next = packetlib.vlan(next=p.next)
                p = p.next
                p.eth_type = old_eth_type
            p.id = packet['vlan_id']
            p.pcp = packet['vlan_pcp']
        else:
            if isinstance(p.next, packetlib.vlan):
                p.type = p.next.eth_type # Restore encapsulated eth type
                p.next = p.next.next # Remove vlan from header

        # GET PACKET INSIDE ETHERNET/VLAN
        p = p.next
        if isinstance(p, packetlib.ipv4):
            p.srcip = packet["srcip"]
            p.dstip = packet["dstip"]
            p.protocol = packet["protocol"]
            p.tos = packet["tos"]

            p = p.next
            if isinstance(p, packetlib.udp) or isinstance(p, packetlib.tcp):
                p.srcport = packet["srcport"]
                p.dstport = packet["dstport"]
            elif isinstance(p, packetlib.icmp):
                p.type = packet["srcport"]
                p.code = packet["dstport"]

        elif isinstance(p, packetlib.arp):
            if 'vlan_id' in packet:
                p.opcode = packet["protocol"]
                p.protosrc = packet["srcip"]
                p.protodst = packet["dstip"]
            else:
                p_begin = self.make_arp(packet)
        
        return p_begin.pack()
Exemplo n.º 4
0
 def icmp_ping(self, interface, destination_interface):
   # randomly choose an in_port.
   e = ethernet()
   e.src = interface.hw_addr
   if destination_interface is not None:
     e.dst = destination_interface.hw_addr
   else:
     # TODO(cs): need a better way to create random MAC addresses
     e.dst = EthAddr(struct.pack("Q",self.random.randint(1,0xFF))[:6])
   e.type = ethernet.IP_TYPE
   ipp = ipv4()
   ipp.protocol = ipv4.ICMP_PROTOCOL
   if hasattr(interface, 'ips'):
     ipp.srcip = self.random.choice(interface.ips)
   else:
     ipp.srcip = IPAddr(self.random.randint(0,0xFFFFFFFF))
   if destination_interface is not None and hasattr(destination_interface, 'ips'):
     ipp.dstip = self.random.choice(destination_interface.ips)
   else:
     ipp.dstip = IPAddr(self.random.randint(0,0xFFFFFFFF))
   ping = icmp()
   ping.type = self.random.choice([TYPE_ECHO_REQUEST,TYPE_ECHO_REPLY])
   ping.payload = "PingPing" * 6
   ipp.payload = ping
   e.payload = ipp
   return e
Exemplo n.º 5
0
    def send_icmp_msg_large(self, event, src_ip = IP_ANY, dst_ip = IP_ANY, src_mac = ETHER_BROADCAST,
                            dst_mac = ETHER_BROADCAST, payload = None, icmp_type = pkt.TYPE_ECHO_REPLY):

        icmp = pkt.icmp()
        icmp.type = icmp_type
        icmp.payload = payload

        # Make the IP packet around it
        ipp = pkt.ipv4()
        ipp.protocol = ipp.ICMP_PROTOCOL
        ipp.srcip = src_ip
        ipp.dstip = dst_ip

        e = pkt.ethernet()
        e.src = src_mac
        e.dst = dst_mac
        e.type = e.IP_TYPE

        ipp.payload = icmp
        e.payload = ipp

        msg = of.ofp_packet_out()
        msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
        msg.data = e.pack()
        msg.in_port = event.port
        event.connection.send(msg)
Exemplo n.º 6
0
  def create_discovery_packet (self, dpid, port_num, port_addr):
    """
    Build discovery packet
    """

    chassis_id = pkt.chassis_id(subtype=pkt.chassis_id.SUB_LOCAL)
    chassis_id.id = bytes('dpid:' + hex(long(dpid))[2:-1])
    # Maybe this should be a MAC.  But a MAC of what?  Local port, maybe?

    port_id = pkt.port_id(subtype=pkt.port_id.SUB_PORT, id=str(port_num))

    ttl = pkt.ttl(ttl = self._ttl)

    sysdesc = pkt.system_description()
    sysdesc.payload = bytes('dpid:' + hex(long(dpid))[2:-1])

    discovery_packet = pkt.lldp()
    discovery_packet.tlvs.append(chassis_id)
    discovery_packet.tlvs.append(port_id)
    discovery_packet.tlvs.append(ttl)
    discovery_packet.tlvs.append(sysdesc)
    discovery_packet.tlvs.append(pkt.end_tlv())

    eth = pkt.ethernet(type=pkt.ethernet.LLDP_TYPE)
    eth.src = port_addr
    eth.dst = pkt.ETHERNET.NDP_MULTICAST
    eth.payload = discovery_packet

    po = of.ofp_packet_out(action = of.ofp_action_output(port=port_num))
    po.data = eth.pack()
    return po.pack()
Exemplo n.º 7
0
    def send_icmp_msg_small(self, packet, match, event, icmp_type = pkt.TYPE_ECHO_REPLY, payload = None):
        pload = payload if payload is not None or packet is None or packet.find("icmp") is None else packet.find("icmp").payload
        return self.send_icmp_msg_large(event, packet.find("ipv4").dstip, packet.find("ipv4").srcip, packet.dst, packet.src, pload, icmp_type)

        icmp = pkt.icmp()
        icmp.type = pkt.TYPE_ECHO_REPLY
        icmp.payload = packet.find("icmp").payload

        # Make the IP packet around it
        ipp = pkt.ipv4()
        ipp.protocol = ipp.ICMP_PROTOCOL
        ipp.srcip = packet.find("ipv4").dstip
        ipp.dstip = packet.find("ipv4").srcip

        e = pkt.ethernet()
        e.src = packet.dst
        e.dst = packet.src
        e.type = e.IP_TYPE

        ipp.payload = icmp
        e.payload = ipp

        msg = of.ofp_packet_out()
        msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
        msg.data = e.pack()
        msg.in_port = event.port
        event.connection.send(msg)

        log.debug("%s pinged %s", ipp.dstip, ipp.srcip)
Exemplo n.º 8
0
  def _handle_arp(self, event, ether_pkt, arp_pkt):
    # Update the ARP table with the info for the sender.
    self._packet_logger.action('Add ARP Entry', [
      ('IP Address', arp_pkt.protosrc), ('MAC Address', arp_pkt.hwsrc)
    ])
    self._arp_table.add(arp_pkt.protosrc, arp_pkt.hwsrc)
    if not is_special_mac(arp_pkt.hwdst):
      # If the hardware destination is a normal MAC address, add it to the ARP table.
      self._packet_logger.action('Add ARP Entry', [
        ('IP Address', arp_pkt.protodst), ('MAC Address', arp_pkt.hwdst)
      ])
      self._arp_table.add(arp_pkt.protodst, arp_pkt.hwdst)

    if arp_pkt.opcode == arp.REQUEST:
      # Try to find a known MAC address for the requested IP address and send a reply ourselves.
      requested_ip = arp_pkt.protodst
      requested_mac = self._arp_table.lookup(requested_ip)
      self._packet_logger.metric('ARP Target', [ ('IP', requested_ip), ('MAC', requested_mac) ])
      if requested_mac:
        self._packet_logger.action('ARP Reply', [
          ('Requested MAC', requested_mac),
          ('Out Port', event.ofp.in_port)
        ])
        arp_reply = arp(hwsrc = requested_mac, hwdst = arp_pkt.hwsrc, opcode = arp.REPLY, protosrc = requested_ip, protodst = arp_pkt.protosrc)
        ether = ethernet(type = ethernet.ARP_TYPE, dst = arp_pkt.hwsrc, src = requested_mac, payload = arp_reply)
        self._send_packet(ether, event.ofp.in_port)
        return True
Exemplo n.º 9
0
 def arpReply(self, e):
     '''
         This method builds and sends ARP reply in response to ARP Request.
         e = payload of original IP packet received
         '''
         #	Create ARP reply header (Ethernet)
     if (e.protodst in self.interface):
         dev = self.interface[e.protodst][1]
         ethpkt = pktlib.ethernet()
         ethpkt.src = self.interface[e.protodst][2]
         ethpkt.dst = e.hwsrc
         ethpkt.type = ethpkt.ARP_TYPE
         
         arp_rep = pktlib.arp()
         arp_rep.opcode = pktlib.arp.REPLY
         arp_rep.protosrc = e.protodst
         arp_rep.protodst = e.protosrc
         arp_rep.hwsrc = self.interface[e.protodst][2]
         arp_rep.hwdst = e.hwsrc
         
         #	Encapsulate eth packet
         ethpkt.set_payload(arp_rep)
         
         # 	Send it back to the src address
         self.net.send_packet(dev,ethpkt)
         return
def pi_cb (data, parser):
  global _pis, _pos
  packet = pkt.ethernet(data)
  if packet.find('tcp'):
    if packet.find('tcp').dstport == _of_port or \
       packet.find('tcp').srcport == _of_port:
      p = packet.find('tcp').payload
      assert p[0] == '\x01'
      t = ord(p[1])
      packet_length = ord(p[2]) << 8 | ord(p[3])
      if packet_length != len(p):
        log.error("%s != %s" % (packet_length, len(p)))
      if t == of.OFPT_PACKET_IN:
        if _out_only: return
        l,p = of.ofp_packet_in.unpack_new(p)
        _pis += 1
      elif t == of.OFPT_PACKET_OUT:
        if _in_only: return
        l,p = of.ofp_packet_out.unpack_new(p)
        _pos += 1
      else:
        return
      assert l == len(p)

      _writer.write(p.data, time=parser._time, wire_size=parser._wire_size)
Exemplo n.º 11
0
    def _rx_packet(self, rx_packet):
        """
        process a dataplane packet

        data: an instance of packet data
        in_port: the integer port number
        packet_data: packed version of packet if available

        :param in_packet:
        :param in_port:
        :param packet_data:
        :return:
        """

        in_port = rx_packet['inport']
        in_packet = rx_packet['raw']

        p = self.ports.get(in_port)
        if p is None:
            log.warn("Got packet on missing port %i", in_port)
            return

        _packet = ethernet(in_packet)
        log.debug(_packet.dump())

        if self.policy:
            in_concrete_packet = rx_packet
            in_pyretic_packet = concrete_to_pydatapath(in_concrete_packet)

            out_pyretic_packets = self.policy.eval(in_pyretic_packet)

            out_concrete_packets = map(pydatapath_to_concrete, out_pyretic_packets)
            map(self._tx_packet, out_concrete_packets)
        else:
            log.warn("Switch (%s) target.datapath policy not defined", self.name)
Exemplo n.º 12
0
 def create_eth_header(self, pkt, dstMAC, srcMAC):
     ether = ethernet()                                  #creates an ethernet packet
     ether.type  = ethernet.IP_TYPE                      #NECESSARY??
     ether.src = srcMAC                                  #SRC is own mac addr
     ether.dst = dstMAC                                  #MACaddress
     ether.set_payload(pkt.payload)                      #adds the payload which == None
     return ether    
Exemplo n.º 13
0
  def reply_to_ping(self, event):
    # Reply to pings
    packet=event.parsed
    # Make the ping reply
    icmp = pkt.icmp()
    icmp.type = pkt.TYPE_ECHO_REPLY
    icmp.payload = packet.find("icmp").payload

    # Make the IP packet around it
    ipp = pkt.ipv4()
    ipp.protocol = ipp.ICMP_PROTOCOL
    packet=event.parsed
    ipp.srcip = packet.find("ipv4").dstip
    ipp.dstip = packet.find("ipv4").srcip

    # Ethernet around that...
    e = pkt.ethernet()
    e.src = packet.dst
    e.dst = packet.src
    e.type = e.IP_TYPE

    # Hook them up...
    ipp.payload = icmp
    e.payload = ipp

    # Send it back to the input port
    msg = of.ofp_packet_out()
    msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
    msg.data = e.pack()
    msg.in_port = event.port
    event.connection.send(msg)

    log.debug("%s pinged %s", ipp.dstip, ipp.srcip)
Exemplo n.º 14
0
    def perform(self, event):
        packet = event.parse()
        n = packet.find("ipv4")
        i = packet.find("icmp")

        # Create echo reply icmp.
        icmp = pkt.icmp()
        icmp.type = pkt.TYPE_ECHO_REPLY
        icmp.payload = i.payload

        # Create ipv4 packet ipp.
        ipp = pkt.ipv4()
        ipp.protocol = ipp.ICMP_PROTOCOL
        ipp.srcip = n.dstip
        ipp.dstip = n.srcip

        # Create ethernet packet e.
        e = pkt.ethernet()
        e.src = packet.dst
        e.dst = packet.src
        e.type = e.IP_TYPE

        # Link the payloads.
        ipp.payload = icmp
        e.payload = ipp

        # Create PacketOut msg.
        msg = of.ofp_packet_out()
        msg.data = e.pack()
        msg.in_port = event.port
        msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT))
        event.connection.send(msg)
Exemplo n.º 15
0
    def perform(self, event):
        packet = event.parse()
        a = packet.find("arp")

        # Create arp reply r.
        r = pkt.arp()
        r.hwtype = a.hwtype
        r.prototype = a.prototype
        r.hwlen = a.hwlen
        r.protolen = a.protolen
        r.opcode = r.REPLY
        r.hwdst = a.hwsrc
        r.protodst = a.protosrc
        r.protosrc = a.protodst
        r.hwsrc = self.macAddr

        # Create ethernet packet e.
        e = pkt.ethernet(type=packet.type, src=self.macAddr, dst=packet.src)
        e.payload = r

        # Create PacketOut msg.
        msg = of.ofp_packet_out()
        msg.data = e.pack()
        msg.in_port = event.port
        msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT))
        event.connection.send(msg)
Exemplo n.º 16
0
 def gratuitousARP(self,vs):
     if vs is None:
         vswitches = self.net[0xaabbcc].vswitch
     else:
         vswitches = dict(only=vs)
     for k in vswitches.keys():
         v = vswitches[k]
         pkt_eth = pkt.ethernet(dst=pkt.ETHER_BROADCAST,src=v.hw_addr)
         pkt_eth.type = pkt.ethernet.VLAN_TYPE
         pkt_vlan = pkt.vlan(id=v.vstag)
         pkt_vlan.eth_type = pkt.ethernet.ARP_TYPE
         grat = pkt.arp()
         grat.opcode = pkt.arp.REQUEST
         grat.hwsrc = pkt_eth.src
         grat.hwdst = pkt_eth.dst
         grat.payload = b'\x0f' * 8
         pkt_eth.payload=pkt_vlan
         pkt_vlan.payload=grat
         dpid = self.net[0xaabbcc].getDPID(v)
         msg = of.ofp_packet_out(data=pkt_eth)
         msg.actions.append(of.ofp_action_output(port = v.uplink))
         try:
             conn = core.openflow.getConnection(dpid)
             self.log.debug("Sending gratuitousARP for %s" % v)
             conn.send(msg)
         except:
             raise RuntimeError("can't send msg to vSwitch %s" % v)
Exemplo n.º 17
0
  def reply (self, event, msg):
    orig = event.parsed.find('dhcp')
    broadcast = (orig.flags & orig.BROADCAST_FLAG) != 0
    msg.op = msg.BOOTREPLY
    msg.chaddr = event.parsed.src
    msg.htype = 1
    msg.hlen = 6
    msg.xid = orig.xid
    msg.add_option(pkt.DHCP.DHCPServerIdentifierOption(self.ip_addr))

    ethp = pkt.ethernet(src=ip_for_event(event),dst=event.parsed.src)
    ethp.type = pkt.ethernet.IP_TYPE
    ipp = pkt.ipv4(srcip = self.ip_addr)
    ipp.dstip = event.parsed.find('ipv4').srcip
    if broadcast:
      ipp.dstip = IP_BROADCAST
      ethp.dst = pkt.ETHERNET.ETHER_BROADCAST
    ipp.protocol = ipp.UDP_PROTOCOL
    udpp = pkt.udp()
    udpp.srcport = pkt.dhcp.SERVER_PORT
    udpp.dstport = pkt.dhcp.CLIENT_PORT
    udpp.payload = msg
    ipp.payload = udpp
    ethp.payload = ipp
    po = of.ofp_packet_out(data=ethp.pack())
    po.actions.append(of.ofp_action_output(port=event.port))
    event.connection.send(po)
Exemplo n.º 18
0
    def arpBuilder(self, dev, pkt, nexthop, retry):
        '''
            This method builds and sends ARP request
            
            '''
        if (pkt.type == pkt.IP_TYPE):
            e=pkt.payload

        if dev in self.devInterface:
            tempeth = self.devInterface[dev][0]
            tempip = self.devInterface[dev][1]
        
        ethpkt = pktlib.ethernet()
        ethpkt.src = tempeth
        ethpkt.dst = ETHER_BROADCAST
        ethpkt.type = ethpkt.ARP_TYPE
        
        #   arp header
        arp_req = pktlib.arp()
        arp_req.opcode = pktlib.arp.REQUEST
        arp_req.protosrc = tempip
        
        if (nexthop==IPAddr("0")):
            arp_req.protodst = e.dstip
        else:
            arp_req.protodst = nexthop
        
        arp_req.hwsrc = tempeth
        arp_req.hwdst = EthAddr('ff:ff:ff:ff:ff:ff')
        
        #	Encapsulate the packet and send it
        ethpkt.set_payload(arp_req)
        self.arpRequest(dev, pkt, ethpkt, retry)
Exemplo n.º 19
0
  def sendICMP(self,type_,code,ip,packet):
    icm = icmp()
    icm.type=type_
    icm.code=code
    d = packet.next.pack()
    d = d[:packet.next.hl * 4+8]
    d = struct.pack("!HH", 0,0) + d
    icm.payload = d
    # icmp.type = pkt.TYPE_DEST_UNREACH

    # Make the IP packet around it
    ipp = pkt.ipv4()
    ipp.protocol = ipp.ICMP_PROTOCOL
    ipp.srcip = self.ip
    ipp.dstip = ip.srcip

    # Ethernet around that...
    e = pkt.ethernet()
    e.src = self.mac
    e.dst = packet.src
    e.type = e.IP_TYPE

    # Hook them up...
    ipp.set_payload(icm)
    e.set_payload(ipp)

    # Send it back to the input port
    msg = of.ofp_packet_out()
    msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
    msg.data = e.pack()
    msg.in_port = self.event_port
    self.connection.send(msg)
Exemplo n.º 20
0
	def handle_icmp(self,event):
		print "Replying to Ping: ",event.dpid
		packet = event.parsed
		icmp_reply = icmp()
		icmp_reply.type = pkt.TYPE_ECHO_REPLY
		icmp_reply.payload = packet.find("icmp").payload

		# Make the IP packet around it
		ipp = pkt.ipv4()
		ipp.protocol = ipp.ICMP_PROTOCOL
		ipp.srcip = packet.find("ipv4").dstip
		ipp.dstip = packet.find("ipv4").srcip

		# Ethernet around that...
		e = pkt.ethernet()
		e.src = packet.dst
		e.dst = packet.src
		e.type = e.IP_TYPE

		# Hook them up...
		ipp.payload = icmp_reply
		e.payload = ipp

		# Send it back to the input port
		msg = of.ofp_packet_out()
		msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
		msg.data = e.pack()
		msg.in_port = event.port
		event.connection.send(msg)
Exemplo n.º 21
0
 def examineStalled(self):
     keys = self.arp_ip.keys() #Can/will lose keys during iteration
     for dst in keys:
         stalled = self.arp_ip.pop(dst)
         
         if dst in self.ip_to_ether: #We've since figured this one out
             dst_eth = self.ip_to_ether[dst]
             
             for ether_pkt in stalled.getList(): #Send out all the waiting packets
                 ether_pkt.dst = dst_eth
                 self.net.send_packet(stalled.intf_name, ether_pkt)
         else:
             difference = time.time() - stalled.start_time
         
             sentICMP = False
             if difference/stalled.tries > 1:
                 if stalled.tries >=5: #Timeout, send ICMP timeout
                     ether = stalled.packet_list[0] # one of the ethernet packets that are queued up is all we need to get IP info
                     icmp_error = self.makeICMP(pktlib.TYPE_DEST_UNREACH, pktlib.CODE_UNREACH_HOST, ether.payload)
                     ip_reply = self.makeIP(icmp_error, ether.payload.srcip, self.nameMap[stalled.dev][1])
                     ether = ethernet() #wrap ip in ether because forward_packet uses ethernet packets
                     ether.type = ether.IP_TYPE
                     ether.set_payload(ip_reply)
                     self.forward_packet(ether, stalled.intf_name) 
                     sentICMP = True
                 else:
                     self.net.send_packet(stalled.intf_name, stalled.arp_req) #Send ARP again
                     stalled.tries += 1
                 
             if not sentICMP:
                 self.arp_ip[dst] = stalled #Add stalled back to the dict
Exemplo n.º 22
0
 def send_udp_packet_out(self, conn, payload, tp_src, tp_dst,src_ip, dst_ip, 
                         src_mac, dst_mac, fw_port = of.OFPP_ALL):
   msg = of.ofp_packet_out(in_port=of.OFPP_NONE)
   msg.buffer_id = None
   #Make the udp packet
   udpp = pkt.udp()
   udpp.srcport = tp_src
   udpp.dstport = tp_dst
   udpp.payload = payload
   #Make the IP packet around it
   ipp = pkt.ipv4()
   ipp.protocol = ipp.UDP_PROTOCOL
   ipp.srcip = IPAddr(src_ip)
   ipp.dstip = IPAddr(dst_ip)
   # Ethernet around that...
   ethp = pkt.ethernet()
   ethp.src = EthAddr(src_mac)
   ethp.dst = EthAddr(dst_mac)
   ethp.type = ethp.IP_TYPE
   # Hook them up...
   ipp.payload = udpp
   ethp.payload = ipp
   # Send it to the sw
   msg.actions.append(of.ofp_action_output(port = fw_port))
   msg.data = ethp.pack()
   #show msg before sending
   """
   print '*******************'
   print 'msg.show(): ',msg.show()
   print '*******************'
   """
   #print "send_udp_packet_out; sw%s and fw_port:%s" %(conn.dpid, fw_port)
   conn.send(msg)
Exemplo n.º 23
0
	def reply_icmp_error(self, event, icmp_type, code):
		print "Replying Host Unreachable from ", event.dpid
		packet = event.parsed
		icmp_reply = icmp()
		icmp_reply.type = icmp_type
		icmp_reply.code = code
		# icmp_reply.payload = packet.find("icmp").payload
		d = packet.next.pack()
		d = d[:packet.next.hl*4+8]
		d = struct.pack("!HH", 0, 0) + d
		icmp_reply.payload = d

		# Make the IP packet around it
		ipp = pkt.ipv4()
		ipp.protocol = ipp.ICMP_PROTOCOL
		ipp.srcip = self.ip
		ipp.dstip = packet.find("ipv4").srcip

		# Ethernet around that...
		e = pkt.ethernet()
		e.src = self.mac
		e.dst = packet.src
		e.type = e.IP_TYPE

		# Hook them up...
		ipp.payload = icmp_reply
		e.payload = ipp

		# Send it back to the input port
		msg = of.ofp_packet_out()
		msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
		msg.data = e.pack()
		msg.in_port = event.port
		print "Sending to (fromIP, toIP, fromMAC, toMAC) : ", ipp.srcip, ipp.dstip, e.src, e.dst
		event.connection.send(msg)
Exemplo n.º 24
0
  def _send_arp_request(self, nw_dst):
    # If the ARP is for an IP on the internal network, use the internal gateway IP
    # address as the source and flood it.
    if IPAddr(nw_dst).in_network(self._network, netmask = self._netmask):
      proto_src = self._gateway_ip
      out_port = of.OFPP_FLOOD
    else:
      # Otherwise, use the external NAT IP address and send it out the uplink.
      proto_src = self._nat_ip
      out_port = self._uplink_port

    self._packet_logger.action('Send ARP Request', [
      ('Source MAC', self._gateway_mac),
      ('Dest MAC', SpecialMacs.ARP_REQUEST_DESTINATION),
      ('Source IP', proto_src),
      ('Dest IP', nw_dst)
    ])
    arp_request = arp(
        hwsrc = self._gateway_mac,
        hwdst = SpecialMacs.ARP_REQUEST_DESTINATION,
        opcode = arp.REQUEST,
        protosrc = proto_src,
        protodst = nw_dst)
    ether = ethernet(type = ethernet.ARP_TYPE, src = self._gateway_mac, dst = SpecialMacs.BROADCAST, payload = arp_request)
    self._send_packet(ether, out_port)
Exemplo n.º 25
0
def generate_example_trace_fat_tree(num_pods=4):
  # TODO(cs): highly redundant

  fat_tree = topo.FatTree(num_pods)
  (_, _, hosts, access_links) = (fat_tree.switches,
          fat_tree.network_links, fat_tree.hosts, fat_tree.access_links)

  host2pings = defaultdict(lambda: [])
  payload = "ping"
  for access_link in access_links:
    host = access_link.host
    other_hosts = list((set(hosts) - set([access_link.host])))
    for other_host in other_hosts:
      eth = ethernet(src=access_link.host.interfaces[0].hw_addr,dst=other_host.interfaces[0].hw_addr,type=ethernet.IP_TYPE)
      dst_ip_addr = other_host.interfaces[0].ips[0]
      ipp = ipv4(protocol=ipv4.ICMP_PROTOCOL, srcip=access_link.host.interfaces[0].ips[0], dstip=dst_ip_addr)
      ping = icmp(type=TYPE_ECHO_REQUEST, payload=payload)
      ipp.payload = ping
      eth.payload = ipp
      host2pings[host].append(DataplaneEvent(access_link.interface, eth))

  # ping pong (no responses) between fake hosts
  # (Some large number: TODO(cs): serialize a generator to disk)
  # Trace is [one ping from every host to a random other host] * 50000
  trace = []
  for _ in range(50000):
    for host, pings in host2pings.iteritems():
      trace.append(random.choice(pings))

  write_trace_log(trace, "dataplane_traces/ping_pong_fat_tree.trace")
Exemplo n.º 26
0
def generate_example_trace():
  trace = []

  mesh = topo.MeshTopology(num_switches=2)
  hosts = mesh.hosts
  access_links = mesh.access_links

  packet_events = []
  ping_or_pong = "ping"

  for access_link in access_links:
    other_host = (set(hosts) - set([access_link.host])).pop()
    eth = ethernet(src=access_link.host.interfaces[0].hw_addr,dst=access_link.switch_port.hw_addr,type=ethernet.IP_TYPE)
    dst_ip_addr = other_host.interfaces[0].ips[0]
    ipp = ipv4(protocol=ipv4.ICMP_PROTOCOL, srcip=access_link.host.interfaces[0].ips[0], dstip=dst_ip_addr)
    if ping_or_pong == "ping":
      ping = icmp(type=TYPE_ECHO_REQUEST, payload=ping_or_pong)
    else:
      ping = icmp(type=TYPE_ECHO_REPLY, payload=ping_or_pong)
    ipp.payload = ping
    eth.payload = ipp
    packet_events.append(DataplaneEvent(access_link.interface, eth))

  # ping ping (no responses) between fake hosts
  for _ in range(40):
    trace.append(packet_events[0])
    trace.append(packet_events[1])

  write_trace_log(trace, "dataplane_traces/ping_pong.trace")
Exemplo n.º 27
0
 def router_main(self):    
     while True:
         try:
             dev,ts,pkt = self.net.recv_packet(timeout=1.0)
         except SrpyNoPackets:
             # log_debug("Timeout waiting for packets")
             continue
         except SrpyShutdown:
             return
         if pkt.type == pkt.ARP_TYPE:
             arp_request = pkt.payload
             for intf in self.net.interfaces():
                 if (intf.ipaddr==arp_request.protodst):
                     arp_reply = pktlib.arp()
                     arp_reply.protodst = arp_request.protosrc
                     arp_reply.protosrc = intf.ipaddr
                     arp_reply.hwsrc = intf.ethaddr
                     arp_reply.hwdst = arp_request.hwsrc
                     arp_reply.opcode = pktlib.arp.REPLY
                     ether = pktlib.ethernet()
                     ether.type = ether.ARP_TYPE
                     ether.src = intf.ethaddr
                     ether.dst = arp_request.hwsrc
                     ether.set_payload(arp_reply)
                     self.net.send_packet(dev, ether)
                     #self.net.send_packet(dev, arp_reply)
                     break
Exemplo n.º 28
0
def generate_example_trace_same_subnet():
  # TODO: highly redundant
  trace = []
  
  (patch_panel, switches, network_links, hosts, access_links) = topo_gen.create_mesh(num_switches=2)
  
  packet_events = []
  ping_or_pong = "ping"
  for access_link in access_links:
    other_host = (set(hosts) - set([access_link.host])).pop()
    eth = ethernet(src=access_link.host.interfaces[0].mac,dst=other_host.interfaces[0].mac,type=ethernet.IP_TYPE)
    dst_ip_addr = other_host.interfaces[0].ips[0]
    ipp = ipv4(protocol=ipv4.ICMP_PROTOCOL, srcip=access_link.host.interfaces[0].ips[0], dstip=dst_ip_addr)
    if ping_or_pong == "ping":
      ping = icmp(type=TYPE_ECHO_REQUEST, payload=ping_or_pong)
    else:
      ping = icmp(type=TYPE_ECHO_REPLY, payload=ping_or_pong)
    ipp.payload = ping 
    eth.payload = ipp
    packet_events.append(DataplaneEvent(access_link.interface, eth))
    
  # ping ping (no responses) between fake hosts
  for _ in range(40):
    trace.append(packet_events[0])
    trace.append(packet_events[1])
    
  write_trace_log(trace, "traces/ping_pong_same_subnet.trace")
Exemplo n.º 29
0
  def _create_broadcast_discovery_packet (dpid, port_num, port_addr, ttl):

    chassis_id = pkt.chassis_id(subtype=pkt.chassis_id.SUB_LOCAL)
    chassis_id.id = bytes('dpid:' + hex(long(dpid))[2:-1])
    # Maybe this should be a MAC.  But a MAC of what?  Local port, maybe?

    port_id = pkt.port_id(subtype=pkt.port_id.SUB_PORT, id=str(port_num))

    ttl = pkt.ttl(ttl = ttl)

    sysdesc = pkt.system_description()
    sysdesc.payload = bytes('dpid:' + hex(long(dpid))[2:-1])

    discovery_packet = pkt.lldp()
    discovery_packet.tlvs.append(chassis_id)
    discovery_packet.tlvs.append(port_id)
    discovery_packet.tlvs.append(ttl)
    discovery_packet.tlvs.append(sysdesc)
    discovery_packet.tlvs.append(pkt.end_tlv())

    eth = pkt.ethernet(type=pkt.ethernet.LLDP_TYPE)
    eth.src = port_addr
    eth.dst = pkt.ETHERNET.ETHER_BROADCAST
    eth.payload = discovery_packet

    return eth
Exemplo n.º 30
0
def send_discovery_packet(event):
	""" Sends the discovery packet used to identity the links present between the switches"""
	for p in event.ofp.ports:
		chass_id = event.dpid
		src = str(p.hw_addr)

		portno = p.port_no
		chassis_id = pktt.chassis_id(subtype=pktt.chassis_id.SUB_LOCAL, id = str(chass_id))
		
		port_id = pktt.port_id(subtype = pktt.port_id.SUB_PORT, id = str(portno))
		ttl = pktt.ttl(ttl = lldp_ttl)


		discovery_packet = pktt.lldp()
		discovery_packet.tlvs.append(chassis_id)
		discovery_packet.tlvs.append(port_id)
		discovery_packet.tlvs.append(ttl)
		discovery_packet.tlvs.append(pktt.end_tlv())

		eth = pktt.ethernet(type = pktt.ethernet.LLDP_TYPE)
		eth.src = src
		eth.dst = pktt.ETHERNET.NDP_MULTICAST
		eth.payload = discovery_packet

		pkt = of.ofp_packet_out(action = of.ofp_action_output(port = portno))
                pkt.data = eth.pack()
                event.connection.send(pkt.pack())
Exemplo n.º 31
0
    def act_like_router(self, packet, packet_in):
        #handle ARP Requests and replies
        etherPayload = packet.payload  #the stripped ethFrame, contains ipv4 or arp packet
        src_mac = packet.src
        dst_mac = packet.dst

        if packet.type == pkt.ethernet.ARP_TYPE:
            src_ip = etherPayload.protosrc
            dst_ip = etherPayload.protodst
            if etherPayload.opcode == pkt.arp.REQUEST:
                print(
                    "received ARP REQUEST checking if i have info on sender: "
                    + str(src_mac))

                if src_mac not in self.mac_to_port:
                    print("sender mac unknown, adding to mac table...")
                    self.mac_to_port[src_mac] = packet_in.in_port
                if src_ip not in self.arp_table:
                    print("sender ip unknown, adding to arp table...")
                    self.arp_table[src_ip] = src_mac
                if src_ip not in self.ip_to_port:
                    print("sender ip unknown, adding to ip table...")
                    self.ip_to_port[src_ip] = packet_in.in_port

                self.displayTables()

                #creating arp reply to send back
                arp_reply = pkt.arp()
                arp_reply.hwsrc = adr.EthAddr(
                    "11:12:13:14:15:16")  # fake mac in response
                arp_reply.hwdst = etherPayload.hwsrc
                arp_reply.opcode = pkt.arp.REPLY
                arp_reply.protosrc = etherPayload.protodst
                arp_reply.protodst = etherPayload.protosrc

                # encapsulate in ethernet frame now
                ether = pkt.ethernet()
                ether.type = pkt.ethernet.ARP_TYPE
                ether.dst = packet.src
                ether.src = packet.dst
                ether.payload = arp_reply

                #sending packet to switch
                self.resend_packet(ether, packet_in.in_port)

        elif packet.type == pkt.ethernet.IP_TYPE:
            if etherPayload.protocol == pkt.ipv4.ICMP_PROTOCOL:
                icmp_packet = etherPayload.payload
                src_ip = etherPayload.srcip
                dst_ip = etherPayload.dstip
                k = 0  #subnet holder
                if icmp_packet.type == pkt.TYPE_ECHO_REQUEST:

                    if src_mac not in self.mac_to_port:
                        print("sender mac unknown, adding to mac table...")
                        self.mac_to_port[src_mac] = packet_in.in_port
                    if src_ip not in self.arp_table:
                        print("sender ip unknown, adding to arp table...")
                        self.arp_table[src_ip] = src_mac
                    if src_ip not in self.ip_to_port:
                        print("sender ip unknown, adding to ip table...")
                        self.ip_to_port[src_ip] = packet_in.in_port

                    self.displayTables()

                    for subnet in self.routing_table:
                        if dst_ip.inNetwork(subnet):
                            k = subnet
                    if k != 0:
                        #create ping reply
                        # create echo fields
                        ech = pkt.echo()  # echo contained in pkt.icmp
                        ech.id = icmp_packet.payload.id
                        ech.seq = icmp_packet.payload.seq + 1

                        # encapsulates in icmp
                        icmp_reply = pkt.icmp()
                        icmp_reply.type = pkt.TYPE_ECHO_REPLY  # code 0
                        icmp_reply.payload = ech

                        # encapsulates in ipv4
                        ip_p = pkt.ipv4()
                        ip_p.protocol = pkt.ipv4.ICMP_PROTOCOL
                        ip_p.srcip = dst_ip
                        ip_p.dstip = src_ip
                        ip_p.payload = icmp_reply

                        # encapsulates in ethernet
                        eth_p = pkt.ethernet()
                        eth_p.type = pkt.ethernet.IP_TYPE
                        eth_p.src = packet.dst
                        eth_p.dst = packet.src
                        eth_p.payload = ip_p

                        msg = of.ofp_packet_out()
                        msg.data = eth_p.pack()
                        action = of.ofp_action_output(port=packet_in.in_port)
                        msg.actions.append(action)
                        self.connection.send(msg)

                        print("echo Reply sent!")
                        self.createflow(packet_in, eth_p, packet_in.in_port)

                    else:
                        print("ICMP destination unreachable")

                        unr = pkt.unreach()
                        unr.payload = etherPayload

                        icmp_reply = pkt.icmp()
                        icmp_reply.type = pkt.TYPE_DEST_UNREACH
                        icmp_reply.payload = unr

                        ip_p = pkt.ipv4()
                        ip_p.srcip = dst_ip
                        ip_p.dstip = src_ip
                        ip_p.protocol = pkt.ipv4.ICMP_PROTOCOL
                        ip_p.payload = icmp_reply

                        eth_p = pkt.ethernet()
                        eth_p.type = pkt.ethernet.IP_TYPE
                        eth_p.dst = packet.src
                        eth_p.src = packet.dst
                        eth_p.payload = ip_p

                        msg = of.ofp_packet_out()
                        msg.data = eth_p.pack()
                        action = of.ofp_action_output(port=packet_in.in_port)
                        msg.actions.append(action)
                        self.connection.send(msg)
                        print("echo Unreachable Reply sent!")
                        self.createflow(packet_in, eth_p, packet_in.in_port)

            #other type of ip packet maybe udp or tcp
            else:
                src_ip = etherPayload.srcip
                dst_ip = etherPayload.dstip

                if dst_ip in self.ip_to_port and dst_ip in self.arp_table:
                    print("received other type of packet sending reply...")
                    out_port = self.ip_to_port[dst_ip]
                    eth_dest = self.arp_table[dst_ip]

                    msg = of.ofp_packet_out()
                    packet.src = packet.dst  #since who received the packet is sending the reply set src = dst
                    packet.dst = adr.EthAddr(eth_dest)
                    msg.data = packet.pack()
                    action = of.ofp_action_output(port=out_port)
                    msg.actions.append(action)

                    self.connection.send(msg)
                    self.createflow(packet_in, packet, out_port)
                else:
                    print("who do i send this to I am switch: " +
                          str(self.connection.dpid))
                    print("packet src ip: " + str(src_ip) + " to: " +
                          str(dst_ip))
                    self.resend_packet(packet, of.OFPP_ALL)
                    self.createflow(packet_in, packet, of.OFPP_ALL)
'''
'''
This is a Client. Can be an IoT Device and use CoAP communication. 
We just send an IP packet without actually knowing IPv6 with 
just a tag in the IP packet payload.

'''

#Create an IP packet
ipv6_packet = ipv6()
ipv6_packet.srcip = IPAddr6("::0")

#Random IP destination address
ipv6_packet.dstip = IPAddr6("::7")
ipv6_packet.next_header_type = 0xFD

# Set a tag in IP payload. e.g color = red. Tag-Based Forwarding
ipv6_packet.payload = "[color='red']"
ether = ethernet()
ether.type = 0x86DD

# Because we don't know the destination mac address we set :00 as mac
ether.dst = EthAddr(b"\x00\x00\x00\x00\x00\x00")
ether.src = EthAddr(b"\x08\x00\x27\xc8\x18\xa5")
ether.payload = ipv6_packet

# Open a socket and send the packet through it
s = socket(AF_PACKET, SOCK_RAW)
s.bind(('h1-eth0', 0))
s.send(ether.pack())
Exemplo n.º 33
0
  def install_path (self, dst_sw, last_port, match, event):
    """
    Attempts to install a path between this switch and some destination
    """
    p = _get_path(self, dst_sw, event.port, last_port)
    if p is None:
      log.warning("Can't get from %s to %s", match.dl_src, match.dl_dst)

      import pox.lib.packet as pkt

      if (match.dl_type == pkt.ethernet.IP_TYPE and
          event.parsed.find('ipv4')):
        # It's IP -- let's send a destination unreachable
        log.debug("Dest unreachable (%s -> %s)",
                  match.dl_src, match.dl_dst)

        e = pkt.ethernet()
        e.src = EthAddr(dpid_to_str(self.dpid)) #FIXME: Hmm...
        e.dst = match.dl_src
        e.type = e.IP_TYPE
        ipp = pkt.ipv4()
        ipp.protocol = ipp.ICMP_PROTOCOL
        ipp.srcip = match.nw_dst #FIXME: Ridiculous
        ipp.dstip = match.nw_src
        icmp = pkt.icmp()
        icmp.type = pkt.ICMP.TYPE_DEST_UNREACH
        icmp.code = pkt.ICMP.CODE_UNREACH_HOST
        orig_ip = event.parsed.find('ipv4')

        d = orig_ip.pack()
        d = d[:orig_ip.hl * 4 + 8]
        import struct
        d = struct.pack("!HH", 0,0) + d #FIXME: MTU
        icmp.payload = d
        ipp.payload = icmp
        e.payload = ipp
        msg = of.ofp_packet_out()
        msg.actions.append(of.ofp_action_output(port = event.port))
        msg.data = e.pack()
        self.connection.send(msg)

      return

    if match.nw_dst in virtual_server:
      vs_ip = match.nw_dst
      rs_ip = real_servers.get(match.dl_dst)
      log.debug("Virtual server path %s -> %s(serving by %s, %i hops)",
                match.nw_src, match.nw_dst, rs_ip, len(p))
      self._install_path_mod_dst(p, match.clone(), rs_ip, event.ofp)

      # Now reverse it and install it backwards
      # Works well for IPv4 packets
      # The packet coming back is from the real server. Re-write header
      # on the last hop.
      p = [(sw,out_port,in_port) for sw,in_port,out_port in p]
      match.set_nw_dst(rs_ip)
      self._install_path_mod_src(p, match.flip(), vs_ip)

    else:
      log.debug("Installing path for %s -> %s %04x (%i hops)",
          match.dl_src, match.dl_dst, match.dl_type, len(p))

      # We have a path -- install it
      self._install_path(p, match, event.ofp)

      # Now reverse it and install it backwards
      # (we'll just assume that will work)
      p = [(sw,out_port,in_port) for sw,in_port,out_port in p]
      self._install_path(p, match.flip())
Exemplo n.º 34
0
    def install_path(self, dst_sw, last_port, match, event):
        """
    Attempts to install a path between this switch and some destination
    """
        #print "inside install_path and switches in sequence are self,dst_sw,event.port,last_port"
        #print str(self)+" "+str(dst_sw)+" "+str(event.port)+" "+str(last_port)
        print "printing mac_map again"
        #for key in mac_map:
        #print key
        #print mac_map[key]
        p = _get_path(self, dst_sw, event.port, last_port)
        print p
        if p is None:
            log.warning("Can't get from %s to %s", match.dl_src, match.dl_dst)

            import pox.lib.packet as pkt

            if (match.dl_type == pkt.ethernet.IP_TYPE
                    and event.parsed.find('ipv4')):
                # It's IP -- let's send a destination unreachable
                log.debug("Dest unreachable (%s -> %s)", match.dl_src,
                          match.dl_dst)

                from pox.lib.addresses import EthAddr
                e = pkt.ethernet()
                e.src = EthAddr(dpid_to_str(self.dpid))  #FIXME: Hmm...
                e.dst = match.dl_src
                e.type = e.IP_TYPE
                ipp = pkt.ipv4()
                ipp.protocol = ipp.ICMP_PROTOCOL
                ipp.srcip = match.nw_dst  #FIXME: Ridiculous
                ipp.dstip = match.nw_src
                icmp = pkt.icmp()
                icmp.type = pkt.ICMP.TYPE_DEST_UNREACH
                icmp.code = pkt.ICMP.CODE_UNREACH_HOST
                orig_ip = event.parsed.find('ipv4')

                d = orig_ip.pack()
                d = d[:orig_ip.hl * 4 + 8]
                import struct
                d = struct.pack("!HH", 0, 0) + d  #FIXME: MTU
                icmp.payload = d
                ipp.payload = icmp
                e.payload = ipp
                msg = of.ofp_packet_out()
                msg.actions.append(of.ofp_action_output(port=event.port))
                msg.data = e.pack()
                self.connection.send(msg)

            return

        log.debug("Installing path for %s -> %s %04x (%i hops)", match.dl_src,
                  match.dl_dst, match.dl_type, len(p))

        # We have a path -- install it
        self._install_path(p, match, event.ofp)

        # Now reverse it and install it backwards
        # (we'll just assume that will work)
        #Sumit : We  need a reverse path for getting the packets but the reverse path (host B to host A) shouldn't go via service VMs..that should go directly between switchs
        p = [(sw, out_port, in_port) for sw, in_port, out_port in p]
        self._install_path(p, match.flip())
Exemplo n.º 35
0
    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")
Exemplo n.º 36
0
    def ICMP_Request_handler(self, packet, packet_in):
        ip_packet = packet.payload
        icmp_segment = ip_packet.payload

        ipSrcAdd = self.route_table.get(str(ip_packet.srcip))
        ipDstAdd = self.route_table.get(str(ip_packet.dstip))

        if ipDstAdd != None:
            # router
            if str(packet.dst) == '00:00:00:00:00:11':
                if str(ip_packet.dstip) == '10.0.1.1':
                    echo_segment = pkt.echo()
                    echo_segment.seq = icmp_segment.payload.seq + 1
                    echo_segment.id = icmp_segment.payload.id
                    #icmp packt|echo
                    icmp_reply = pkt.icmp()
                    icmp_reply.type = pkt.TYPE_ECHO_REPLY
                    icmp_reply.payload = echo_segment
                    #ip packet|icmp|echo
                    ip_pack = pkt.ipv4()
                    ip_pack.srcip = ip_packet.dstip
                    ip_pack.dstip = ip_packet.srcip
                    ip_pack.protocol = pkt.ipv4.ICMP_PROTOCOL
                    ip_pack.payload = icmp_reply
                    #frame|ip|icmp|echo
                    ether_pack = pkt.ethernet()
                    ether_pack.dst = packet.src
                    ether_pack.src = packet.dst
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.payload = ip_pack
                    self.send_Packet(frame=ether_pack,
                                     out_port=packet_in.in_port)

                elif ipDstAdd[1] == '10.0.1.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr(ipDstAdd[0])
                    ether_pack.payload = packet.payload
                    self.send_Packet(frame=ether_pack, out_port=ipDstAdd[3])

                elif ipDstAdd[1] == '10.0.2.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr('00:00:00:00:00:22')
                    ether_pack.payload = packet.payload
                    self.send_Packet(frame=ether_pack, out_port=3)

            elif str(packet.dst) == '00:00:00:00:00:22':
                #echo rely to source Router -> H5
                if str(ip_packet.dstip) == '10.0.2.1':
                    echo_segment = pkt.echo()
                    echo_segment.seq = icmp_segment.payload.seq + 1
                    echo_segment.id = icmp_segment.payload.id
                    #icmp packt|echo
                    icmp_reply = pkt.icmp()
                    icmp_reply.type = pkt.TYPE_ECHO_REPLY
                    icmp_reply.payload = echo_segment
                    #ip packet|icmp|echo
                    ip_pack = pkt.ipv4()
                    ip_pack.srcip = ip_packet.dstip
                    ip_pack.dstip = ip_packet.srcip
                    ip_pack.protocol = pkt.ipv4.ICMP_PROTOCOL
                    ip_pack.payload = icmp_reply
                    #frame|ip|icmp|echo
                    ether_pack = pkt.ethernet()
                    ether_pack.dst = packet.src
                    ether_pack.src = packet.dst
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.payload = ip_pack
                    self.send_Packet(frame=ether_pack,
                                     out_port=packet_in.in_port)

                elif ipDstAdd[1] == '10.0.2.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr(ipDstAdd[0])
                    ether_pack.payload = packet.payload
                    self.send_Packet(frame=ether_pack, out_port=ipDstAdd[3])

                elif ipDstAdd[1] == '10.0.1.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr('00:00:00:00:00:11')
                    ether_pack.payload = packet.payload
                    self.send_Packet(frame=ether_pack, out_port=1)
            else:
                self.send_Packet(frame=packet, out_port=ipDstAdd[3])
        else:
            #unreach ICMP packet
            unreachPacket = pkt.unreach()
            unreachPacket.payload = packet.payload

            icmp_unreReply = pkt.icmp()
            icmp_unreReply.type = pkt.TYPE_DEST_UNREACH
            icmp_unreReply.payload = unreachPacket

            ip_unrePack = pkt.ipv4()
            ip_unrePack.srcip = ip_packet.dstip
            ip_unrePack.dstip = ip_packet.srcip
            ip_unrePack.protocol = pkt.ipv4.ICMP_PROTOCOL
            ip_unrePack.payload = icmp_unreReply

            ether_unrePack = pkt.ethernet()
            ether_unrePack.src = packet.dst
            ether_unrePack.dst = packet.src
            ether_unrePack.type = pkt.ethernet.IP_TYPE
            ether_unrePack.payload = ip_unrePack

            self.send_Packet(frame=ether_unrePack, out_port=packet_in.in_port)
Exemplo n.º 37
0
    def IP_handler(self, packet, packet_in):

        ip_packet = packet.payload
        ipSrcAdd = self.route_table.get(str(ip_packet.srcip))
        ipDstAdd = self.route_table.get(str(ip_packet.dstip))

        if ipDstAdd != None:
            if str(packet.dst) == '00:00:00:00:00:11':
                if ipDstAdd[1] == '10.0.1.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr(ipDstAdd[0])
                    ether_pack.payload = packet.payload
                    msg = of.ofp_flow_mod()
                    msg.match.in_port = packet_in.in_port
                    msg.match = of.ofp_match.from_packet(packet)
                    msg.actions.append(
                        of.ofp_action_dl_addr.set_dst(adr.EthAddr(
                            ipDstAdd[0])))
                    msg.actions.append(
                        of.ofp_action_dl_addr.set_src(packet.dst))
                    msg.actions.append(of.ofp_action_output(port=ipDstAdd[3]))
                    self.connection.send(msg)

                elif ipDstAdd[1] == '10.0.2.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr('00:00:00:00:00:22')
                    ether_pack.payload = packet.payload
                    msg = of.ofp_flow_mod()
                    msg.match.in_port = packet_in.in_port
                    msg.match = of.ofp_match.from_packet(packet)
                    msg.actions.append(
                        of.ofp_action_dl_addr.set_dst(adr.EthAddr(
                            ipDstAdd[0])))
                    msg.actions.append(
                        of.ofp_action_dl_addr.set_src(packet.dst))
                    msg.actions.append(of.ofp_action_output(port=3))
                    self.connection.send(msg)
            elif str(packet.dst) == '00:00:00:00:00:22':
                if ipDstAdd[1] == '10.0.2.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr(ipDstAdd[0])
                    ether_pack.payload = packet.payload
                    msg = of.ofp_flow_mod()
                    msg.match.in_port = packet_in.in_port
                    msg.match = of.ofp_match.from_packet(packet)
                    msg.actions.append(
                        of.ofp_action_dl_addr.set_dst(adr.EthAddr(
                            ipDstAdd[0])))
                    msg.actions.append(
                        of.ofp_action_dl_addr.set_src(packet.dst))
                    msg.actions.append(of.ofp_action_output(port=ipDstAdd[3]))
                    self.connection.send(msg)
                elif ipDstAdd[1] == '10.0.1.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr('00:00:00:00:00:11')
                    ether_pack.payload = packet.payload
                    msg = of.ofp_flow_mod()
                    msg.match.in_port = packet_in.in_port
                    msg.match = of.ofp_match.from_packet(packet)
                    msg.actions.append(
                        of.ofp_action_dl_addr.set_dst(adr.EthAddr(
                            ipDstAdd[0])))
                    msg.actions.append(
                        of.ofp_action_dl_addr.set_src(packet.dst))
                    msg.actions.append(of.ofp_action_output(port=1))
                    self.connection.send(msg)
            else:
                msg = of.ofp_flow_mod()
                msg.match.in_port = packet_in.in_port
                msg.match = of.ofp_match.from_packet(packet)
                msg.actions.append(
                    of.ofp_action_dl_addr.set_dst(adr.EthAddr(ipDstAdd[0])))
                msg.actions.append(of.ofp_action_dl_addr.set_src(packet.dst))
                msg.actions.append(of.ofp_action_output(port=ipDstAdd[3]))
                self.connection.send(msg)
Exemplo n.º 38
0
    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")
Exemplo n.º 39
0
    def act_like_router(self, packet, packet_in):
        #handle arp
        if packet.type == pkt.ethernet.ARP_TYPE:
            if packet.payload.opcode == pkt.arp.REQUEST:
                log.debug("ARP request received")
                arp_reply = pkt.arp()
                arp_reply.hwsrc = adr.EthAddr("40:10:40:10:40:10")  #fake MAC
                arp_reply.hwdst = packet.payload.hwsrc
                arp_reply.opcode = pkt.arp.REPLY
                arp_reply.protosrc = packet.payload.protodst
                arp_reply.protodst = packet.payload.protosrc
                ether = pkt.ethernet()
                ether.type = pkt.ethernet.ARP_TYPE
                ether.dst = packet.src
                ether.src = packet.dst
                ether.payload = arp_reply

                msg = of.ofp_packet_out()
                msg.data = ether.pack()

                # Add an action to send to the specified port
                action = of.ofp_action_output(port=packet_in.in_port)
                msg.actions.append(action)
                #msg.in_port = event.port

                # Send message to switch
                self.connection.send(msg)
                log.debug("ARP reply sent")
            elif packet.payload.opcode == pkt.arp.REPLY:
                log.debug("It's a reply!")
                self.mac_to_port[packet.src] = packet_in.in_port
            else:
                log.debug("Some other ARP opcode")

        elif packet.type == pkt.ethernet.IP_TYPE:
            ip_packet = packet.payload
            if ip_packet.protocol == pkt.ipv4.ICMP_PROTOCOL:
                icmp_packet = ip_packet.payload
                if icmp_packet.type == pkt.TYPE_ECHO_REQUEST:
                    log.debug("ICMP request received")
                    src_ip = ip_packet.srcip
                    dst_ip = ip_packet.dstip
                    k = 0
                    for key in self.routing_table.keys():
                        if dst_ip.inNetwork(key):
                            k = key
                            break
                    if k != 0:
                        log.debug("ICMP reply sent")
                        log.debug("network containing host: " + k)
                        ech = pkt.echo()
                        ech.seq = icmp_packet.payload.seq + 1
                        ech.id = icmp_packet.payload.id

                        icmp_reply = pkt.icmp()
                        icmp_reply.type = pkt.TYPE_ECHO_REPLY
                        icmp_reply.payload = ech

                        ip_p = pkt.ipv4()
                        ip_p.srcip = dst_ip
                        ip_p.dstip = src_ip
                        ip_p.protocol = pkt.ipv4.ICMP_PROTOCOL
                        ip_p.payload = icmp_reply

                        eth_p = pkt.ethernet()
                        eth_p.type = pkt.ethernet.IP_TYPE
                        eth_p.dst = packet.src
                        eth_p.src = packet.dst
                        eth_p.payload = ip_p

                        msg = of.ofp_packet_out()
                        msg.data = eth_p.pack()

                        # Add an action to send to the specified port
                        action = of.ofp_action_output(port=packet_in.in_port)
                        #fl2.actions.append(action)
                        msg.actions.append(action)
                        #msg.in_port = event.port

                        # Send message to switch
                        self.connection.send(msg)
                    else:
                        log.debug("ICMP destination unreachable")
                        unr = pkt.unreach()
                        unr.payload = ip_packet

                        icmp_reply = pkt.icmp()
                        icmp_reply.type = pkt.TYPE_DEST_UNREACH
                        icmp_reply.payload = unr

                        ip_p = pkt.ipv4()
                        ip_p.srcip = dst_ip
                        ip_p.dstip = src_ip
                        ip_p.protocol = pkt.ipv4.ICMP_PROTOCOL
                        ip_p.payload = icmp_reply

                        eth_p = pkt.ethernet()
                        eth_p.type = pkt.ethernet.IP_TYPE
                        eth_p.dst = packet.src
                        eth_p.src = packet.dst
                        eth_p.payload = ip_p

                        msg = of.ofp_packet_out()
                        msg.data = eth_p.pack()

                        # Add an action to send to the specified port
                        action = of.ofp_action_output(port=packet_in.in_port)
                        #fl2.actions.append(action)
                        msg.actions.append(action)
                        #msg.in_port = event.port

                        # Send message to switch
                        self.connection.send(msg)
            else:
                src_ip = ip_packet.srcip
                dst_ip = ip_packet.dstip

                k = 0
                for key in self.routing_table.keys():
                    if dst_ip.inNetwork(key):
                        k = key
                        break
                if k != 0:
                    port1 = self.routing_table[k][3]
                    dsteth = adr.EthAddr(self.routing_table[k][4])

                    msg = of.ofp_packet_out()

                    action = of.ofp_action_output(port=port1)

                    packet.src = packet.dst
                    packet.dst = dsteth
                    msg.data = packet.pack()
                    msg.actions.append(action)
                    self.connection.send(msg)
            self.FlowMode(packet_in, packet_in.in_port)
Exemplo n.º 40
0
    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)
Exemplo n.º 41
0
    def install_path(self, dst_sw, last_port, match, event):

        p = _get_path(self, dst_sw, event.port, last_port)

        if p is None:

            log.warning("Can't get from %s to %s", match.dl_src, match.dl_dst)

            import pox.lib.packet as pkt

            if (match.dl_type == pkt.ethernet.IP_TYPE
                    and event.parsed.find('ipv4')):

                log.debug("Dest unreachable (%s -> %s)", match.dl_src,
                          match.dl_dst)

                from pox.lib.addresses import EthAddr

                e = pkt.ethernet()

                e.src = EthAddr(dpid_to_str(self.dpid))

                e.dst = match.dl_src

                e.type = e.IP_TYPE

                ipp = pkt.ipv4()

                ipp.protocol = ipp.ICMP_PROTOCOL

                ipp.srcip = match.nw_dst

                ipp.dstip = match.nw_src

                icmp = pkt.icmp()

                icmp.type = pkt.ICMP.TYPE_DEST_UNREACH

                icmp.code = pkt.ICMP.CODE_UNREACH_HOST

                orig_ip = event.parsed.find('ipv4')

                d = orig_ip.pack()

                d = d[:orig_ip.hl * 4 + 8]

                import struct

                d = struct.pack("!HH", 0, 0) + d

                icmp.payload = d

                ipp.payload = icmp

                e.payload = ipp

                msg = of.ofp_packet_out()

                msg.actions.append(of.ofp_action_output(port=event.port))

                msg.data = e.pack()

                self.connection.send(msg)

            return

        log.debug("Installing path for %s -> %s %04x (%i hops)", match.dl_src,
                  match.dl_dst, match.dl_type, len(p))

        self._install_path(p, match, event.ofp)

        p = [(sw, out_port, in_port) for sw, in_port, out_port in p]

        self._install_path(p, match.flip())
Exemplo n.º 42
0
def ifReach(dstip, event, self):
    packet = event.parsed
    ipLoad = packet.payload
    dpid = self.connection.dpid
    #search the routeTable
    for subRouteTable in self.routeTable:
        #extract the network address
        dstnetwork = subRouteTable[DST_Network]
        if dstip == fireWall[dpid]:
            return False
        if ipLoad.srcip == fireWall[dpid]:
            return False
        #if destination IP in network address in the routetable
        if dstip.inNetwork(dstnetwork):
            log.debug('------ip dst %s is in the routeTable-----' % dstip)

            nextPort = subRouteTable[NEXTHOP_PORT]
            log.debug('------IP dst port %s is in the routeTable-----' %
                      nextPort)
            #if routeTable tells to send it back, do nothing and continue loop
            if nextPort == event.ofp.in_port:
                continue

            nextHopIp = IPAddr(subRouteTable[NETX_HOP_IP])
            nextPortIp = IPAddr(subRouteTable[NEXT_PORT_IP])
            srcMac = arpCache[dpid][nextPort][nextPortIp]

            #if router knows desIP's MAC address, forwarding the packet
            if nextHopIp in arpCache[dpid][nextPort]:
                log.debug('------I know the next dst %s mac-----' % nextHopIp)
                nextHopMac = arpCache[dpid][nextPort][nextHopIp]

                msg = of.ofp_flow_mod()
                msg.match = of.ofp_match()
                msg.match.dl_type = ethernet.IP_TYPE
                msg.match.nw_dst = dstip

                msg.command = 0
                msg.idle_timeout = 10
                msg.hard_timeout = 30
                msg.buffer_id = event.ofp.buffer_id
                msg.actions.append(of.ofp_action_dl_addr.set_src(srcMac))
                msg.actions.append(of.ofp_action_dl_addr.set_dst(nextHopMac))
                msg.actions.append(of.ofp_action_output(port=nextPort))
                self.connection.send(msg)

                log.debug('------install a flow-----')
            #else router does not knows detIP's MAC address, send ARP request.
            else:
                log.debug(
                    '------I do not know the next dst %s mac,make an arp request'
                    % IPAddr(subRouteTable[NETX_HOP_IP]))
                ARPrequest = arp()
                ARPrequest.opcode = arp.REQUEST
                ARPrequest.protosrc = nextPortIp
                ARPrequest.hwsrc = srcMac
                ARPrequest.protodst = nextHopIp
                arpPacket = ethernet(type=ethernet.ARP_TYPE,
                                     src=ARPrequest.hwsrc,
                                     dst=ETHER_BROADCAST)
                arpPacket.set_payload(ARPrequest)
                msg = of.ofp_packet_out()
                msg.data = arpPacket.pack()
                msg.actions.append(of.ofp_action_output(port=nextPort))
                msg.in_port = event.ofp.in_port
                event.connection.send(msg)
                log.debug('------Arp request has been snet-----')

                nextHopMac = ETHER_BROADCAST
                msg = of.ofp_packet_out()
                msg.in_port = event.port
                msg.buffer_id = event.ofp.buffer_id
                msg.actions.append(of.ofp_action_dl_addr.set_src(srcMac))
                msg.actions.append(of.ofp_action_dl_addr.set_dst(nextHopMac))
                msg.actions.append(of.ofp_action_output(port=nextPort))
                self.connection.send(msg)

            return True
    return False
Exemplo n.º 43
0
 def from_json(json_hash):
     interface = HostInterface.from_json(json_hash['interface'])
     raw = base64.b64decode(json_hash['packet'])
     packet = ethernet(raw=raw)
     return DataplaneEvent(interface, packet)
  def _handle_PacketIn (self, event):
    """
    Handle packet in messages from the switch to implement above algorithm.
    """
	
    packet = event.parsed
    
    if self.dpidToIP.get((event.dpid, event.port), None) is None:
	  self.dpidToIP[(event.dpid, event.port)] = "10.10.{:d}.{:d}".format((6-event.dpid%2), self.addr);
	  self.addr += 1;
    
    if (str(type(packet.next)) == "<class 'pox.lib.packet.ipv4.ipv4'>"):
      packet.next.ttl -= 1;
      
    if ((str(type(packet.next)) == "<class 'pox.lib.packet.ipv4.ipv4'>") and (packet.next.ttl == 0)):
      log.debug ("TTL expired!!!");
      
      # Create ICMP Time Exceeded Message
      icmp = pkt.icmp();
      icmp.type = pkt.TYPE_TIME_EXCEED;
      log.debug ("This is the ICMP error message {:s}".format(icmp.payload));
      
      # Create IP Payload
      ipp = pkt.ipv4();
      ipp.protocol = ipp.ICMP_PROTOCOL;
      ipp.srcip = IPAddr(self.dpidToIP[(event.dpid, event.port)]);
      ipp.dstip = packet.next.srcip;
      ipp.payload = icmp;
      log.debug ("This is the IP payload {:s}".format(ipp.payload));
      
      # Create Ethernet Payload
      e = pkt.ethernet();
      e.src = packet.dst;
      e.dst = packet.src;
      e.type = e.IP_TYPE;
      e.payload = ipp;
      log.debug ("This is the Ethernet payload {:s}".format(e.payload));
      
      # Send Packet Back through the Same Port
      msg = of.ofp_packet_out();
      msg.actions.append(of.ofp_action_output(port=event.port));
      msg.date = e.pack();
      msg.in_port = of.OFPP_NONE;event.connection.send(msg);
    else:
      def flood (message = None):
          """ Floods the packet """
          msg = of.ofp_packet_out()
          if time.time() - self.connection.connect_time >= _flood_delay:
            # Only flood if we've been connected for a little while...

            if self.hold_down_expired is False:
              # Oh yes it is!
              self.hold_down_expired = True
              log.info("%s: Flood hold-down expired -- flooding", dpid_to_str(event.dpid))

            if message is not None: log.debug(message)
            #log.debug("%i: flood %s -> %s", event.dpid,packet.src,packet.dst)
            # OFPP_FLOOD is optional; on some switches you may need to change
            # this to OFPP_ALL.
            msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
          else:
            pass
            #log.info("Holding down flood for %s", dpid_to_str(event.dpid))
          msg.data = event.ofp
          msg.in_port = event.port
          self.connection.send(msg)

      def drop (duration = None):
        """
        Drops this packet and optionally installs a flow to continue
        dropping similar ones for a while
        """
        if duration is not None:
          if not isinstance(duration, tuple):
            duration = (duration,duration)
          msg = of.ofp_flow_mod()
          msg.match = of.ofp_match.from_packet(packet)
          msg.idle_timeout = duration[0]
          msg.hard_timeout = duration[1]
          msg.buffer_id = event.ofp.buffer_id
          self.connection.send(msg)
        elif event.ofp.buffer_id is not None:
          msg = of.ofp_packet_out()
          msg.buffer_id = event.ofp.buffer_id
          msg.in_port = event.port
          self.connection.send(msg)

      self.macToPort[packet.src] = event.port # 1

      if not self.transparent: # 2
        if packet.type == packet.LLDP_TYPE or packet.dst.isBridgeFiltered():
          drop() # 2a
          return

      if packet.dst.is_multicast:
        flood() # 3a
      else:
        if packet.dst not in self.macToPort: # 4
          flood("Port for %s unknown -- flooding" % (packet.dst,)) # 4a
        else:
          port = self.macToPort[packet.dst]
          if port == event.port: # 5
            # 5a
            log.warning("Same port for packet from %s -> %s on %s.%s.  Drop." % (packet.src, packet.dst, dpid_to_str(event.dpid), port))
            drop(10)
            return
          # 6
          log.debug("installing flow for %s.%i -> %s.%i" % (packet.src, event.port, packet.dst, port))
          msg = of.ofp_flow_mod()
          msg.match = of.ofp_match.from_packet(packet, event.port)
          msg.idle_timeout = 10
          msg.hard_timeout = 30
          msg.actions.append(of.ofp_action_output(port = port))
          msg.data = event.ofp # 6a
          self.connection.send(msg)
    def _handle_PacketIn(self, event):
        dpid = event.connection.dpid
        inport = event.port
        packet = event.parsed
        if not packet.parsed:
            log.warning("%i %i ignoring unparsed packet", dpid, inport)
            return

        if dpid not in self.arpTable:
            self.arpTable[dpid] = {}

        if packet.type == ethernet.LLDP_TYPE:
            return

        if isinstance(packet.next, ipv4):
            log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip,
                      packet.next.dstip)
            self.sendWaitingPackets(dpid, packet.next.srcip, packet.src,
                                    inport)
            if packet.next.srcip in self.arpTable[dpid]:
                if self.arpTable[dpid][packet.next.srcip] != (inport,
                                                              packet.src):
                    log.info("%i %i RE-learned %s", dpid, inport,
                             packet.next.srcip)
            else:
                log.debug("%i %i learned %s", dpid, inport,
                          str(packet.next.srcip))
            self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src)

            prt = 0
            dstaddr = packet.next.dstip

            prt = self.ip_to_port.get(dstaddr)

            if prt != None:
                log.debug("Got port %i from dictionary", prt)
                mac = None
                if dstaddr in self.arpTable[dpid]:
                    mac = self.arpTable[dpid][dstaddr].mac
                if mac != None:
                    actions = []
                    actions.append(of.ofp_action_dl_addr.set_dst(mac))
                    actions.append(
                        of.ofp_action_dl_addr.set_src(dpid_to_mac(dpid)))
                    actions.append(of.ofp_action_output(port=prt))
                    match = of.ofp_match.from_packet(packet, inport)
                    match.dl_src = None

                    msg = of.ofp_flow_mod(command=of.OFPFC_ADD,
                                          buffer_id=event.ofp.buffer_id,
                                          actions=actions,
                                          match=of.ofp_match.from_packet(
                                              packet, inport))
                    event.connection.send(msg.pack())
                    return
                else:
                    # Add to tracked buffers
                    if (dpid, dstaddr) not in self.message_queue:
                        self.message_queue[(dpid, dstaddr)] = []
                    bucket = self.message_queue[(dpid, dstaddr)]
                    entry = (None, event.ofp.buffer_id, inport)
                    bucket.append(entry)

                    r = arp()
                    r.hwtype = r.HW_TYPE_ETHERNET
                    r.prototype = r.PROTO_TYPE_IP
                    r.hwlen = 6
                    r.protolen = r.protolen
                    r.opcode = r.REQUEST
                    r.hwdst = ETHER_BROADCAST
                    r.protodst = dstaddr
                    r.hwsrc = dpid_to_mac(dpid)
                    r.protosrc = packet.next.srcip
                    e = ethernet(type=ethernet.ARP_TYPE,
                                 src=packet.src,
                                 dst=ETHER_BROADCAST)
                    e.set_payload(r)
                    log.debug("%i %i ARPing for %s on behalf of %s" %
                              (dpid, inport, str(r.protodst), str(r.protosrc)))
                    msg = of.ofp_packet_out()
                    msg.data = e.pack()
                    msg.actions.append(
                        of.ofp_action_output(port=of.OFPP_FLOOD))
                    msg.in_port = inport
                    event.connection.send(msg)

            else:
                icmpflag = 0
                for list in self.routingTable:
                    if list[0] == str(dstaddr):
                        log.debug(
                            "Searching Routing Table for IP address: %s ",
                            str(dstaddr))
                        prt = list[4]
                    if list[3] == str(dstaddr):
                        prt = list[4]
                        icmpflag = 1
                        self.arpTable[dpid][dstaddr] = Entry(
                            prt, dpid_to_mac(dpid))

                if icmpflag == 1:
                    icmp = pkt.icmp()
                    icmp.type = pkt.TYPE_ECHO_REPLY
                    icmp.payload = packet.find("icmp").payload

                    # Make the IP packet around it
                    ipp = pkt.ipv4()
                    ipp.protocol = ipp.ICMP_PROTOCOL
                    ipp.srcip = packet.find("ipv4").dstip
                    ipp.dstip = packet.find("ipv4").srcip

                    # Ethernet around that...
                    e = pkt.ethernet()
                    e.src = packet.dst
                    e.dst = packet.src
                    e.type = e.IP_TYPE

                    # Hook them up...
                    ipp.payload = icmp
                    e.payload = ipp

                    # Send it back to the input port
                    msg = of.ofp_packet_out()
                    msg.actions.append(
                        of.ofp_action_output(port=of.OFPP_IN_PORT))
                    msg.data = e.pack()
                    msg.in_port = event.port
                    event.connection.send(msg)
                    return

                if prt == None:
                    log.debug("Unreachable IP Address : %s", str(dstaddr))
                    icmp = pkt.icmp()
                    icmp.type = 3
                    #icmp.payload = packet.find("icmp").payload

                    # Make the IP packet around it
                    ipp = pkt.ipv4()
                    ipp.protocol = ipp.ICMP_PROTOCOL
                    ipp.srcip = packet.find("ipv4").dstip
                    ipp.dstip = packet.find("ipv4").srcip

                    # Ethernet around that...
                    e = pkt.ethernet()
                    e.src = packet.dst
                    e.dst = packet.src
                    e.type = e.IP_TYPE

                    # Hook them up...
                    ipp.payload = icmp
                    e.payload = ipp

                    # Send it back to the input port
                    msg = of.ofp_packet_out()
                    msg.actions.append(
                        of.ofp_action_output(port=of.OFPP_IN_PORT))
                    msg.data = e.pack()
                    msg.in_port = event.port
                    event.connection.send(msg)
                    return

                log.debug("Got Port Number : %s from routing table", prt)
                self.ip_to_port[dstaddr] = prt
                mac = None
                if dstaddr in self.arpTable[dpid]:
                    mac = self.arpTable[dpid][dstaddr].mac
                if mac != None:
                    actions = []
                    actions.append(of.ofp_action_dl_addr.set_dst(mac))
                    actions.append(
                        of.ofp_action_dl_addr.set_src(dpid_to_mac(dpid)))
                    actions.append(of.ofp_action_output(port=prt))
                    match = of.ofp_match.from_packet(packet, inport)
                    match.dl_src = None  # Wildcard source MAC

                    msg = of.ofp_flow_mod(command=of.OFPFC_ADD,
                                          buffer_id=event.ofp.buffer_id,
                                          actions=actions,
                                          match=of.ofp_match.from_packet(
                                              packet, inport))
                    event.connection.send(msg.pack())
                    return
                else:
                    if (dpid, dstaddr) not in self.message_queue:
                        self.message_queue[(dpid, dstaddr)] = []
                    bucket = self.message_queue[(dpid, dstaddr)]
                    entry = (None, event.ofp.buffer_id, inport)
                    bucket.append(entry)

                    r = arp()
                    r.hwtype = r.HW_TYPE_ETHERNET
                    r.prototype = r.PROTO_TYPE_IP
                    r.hwlen = 6
                    r.protolen = r.protolen
                    r.opcode = r.REQUEST
                    r.hwdst = ETHER_BROADCAST
                    r.protodst = dstaddr
                    r.hwsrc = dpid_to_mac(dpid)
                    r.protosrc = packet.next.srcip
                    e = ethernet(type=ethernet.ARP_TYPE,
                                 src=packet.src,
                                 dst=ETHER_BROADCAST)
                    e.set_payload(r)
                    log.debug("%i %i ARPing for %s on behalf of %s" %
                              (dpid, inport, str(r.protodst), str(r.protosrc)))
                    msg = of.ofp_packet_out()
                    msg.data = e.pack()
                    msg.actions.append(
                        of.ofp_action_output(port=of.OFPP_FLOOD))
                    msg.in_port = inport
                    event.connection.send(msg)

        elif isinstance(packet.next, arp):
            a = packet.next
            log.debug("%i %i ARP %s %s => %s", dpid, inport, {
                arp.REQUEST: "request",
                arp.REPLY: "reply"
            }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc),
                      str(a.protodst))

            dstaddr = a.protodst
            prt = None
            for list in self.routingTable:
                if list[0] == str(dstaddr):
                    log.debug("Searching Routing Table for IP address: %s ",
                              str(dstaddr))
                    prt = list[4]
                if list[3] == str(dstaddr):
                    prt = list[4]
                    #icmpflag = 1
                    self.arpTable[dpid][dstaddr] = Entry(
                        prt, dpid_to_mac(dpid))

            if prt == None:
                log.debug("Unreachable IP Address : %s", str(dstaddr))
                return

            if a.prototype == arp.PROTO_TYPE_IP:
                if a.hwtype == arp.HW_TYPE_ETHERNET:
                    if a.protosrc != 0:

                        # Learn or update port/MAC info
                        if a.protosrc in self.arpTable[dpid]:
                            if self.arpTable[dpid][a.protosrc] != (inport,
                                                                   packet.src):
                                log.info("%i %i RE-learned %s", dpid, inport,
                                         str(a.protosrc))
                        else:
                            log.debug("%i %i learned %s", dpid, inport,
                                      str(a.protosrc))
                        self.arpTable[dpid][a.protosrc] = Entry(
                            inport, packet.src)

                        # Send any waiting packets...
                        self.sendWaitingPackets(dpid, a.protosrc, packet.src,
                                                inport)

                        if a.opcode == arp.REQUEST:
                            # Maybe we can answer

                            if a.protodst in self.arpTable[dpid]:
                                # We have an answer...
                                r = arp()
                                r.hwtype = a.hwtype
                                r.prototype = a.prototype
                                r.hwlen = a.hwlen
                                r.protolen = a.protolen
                                r.opcode = arp.REPLY
                                r.hwdst = a.hwsrc
                                r.protodst = a.protosrc
                                r.protosrc = a.protodst
                                r.hwsrc = self.arpTable[dpid][a.protodst].mac
                                e = ethernet(type=packet.type,
                                             src=dpid_to_mac(dpid),
                                             dst=a.hwsrc)
                                e.set_payload(r)
                                log.debug("%i %i answering ARP from %s to %s" %
                                          (dpid, inport, str(
                                              r.protosrc), str(r.protodst)))
                                msg = of.ofp_packet_out()
                                msg.data = e.pack()
                                msg.actions.append(
                                    of.ofp_action_output(port=of.OFPP_IN_PORT))
                                msg.in_port = inport
                                event.connection.send(msg)
                                return

                        if a.opcode == arp.REPLY:
                            for list in self.routingTable:
                                if list[0] == str(a.protodst):
                                    log.debug(
                                        "Searching Routing Table for IP address: %s ",
                                        str(a.protodst))
                                    prt = list[4]
                                    msg = of.ofp_packet_out(
                                        in_port=inport,
                                        action=of.ofp_action_output(port=prt))

            log.debug("%i %i flooding ARP %s %s => %s" % (dpid, inport, {
                arp.REQUEST: "request",
                arp.REPLY: "reply"
            }.get(a.opcode, 'op:%i' %
                  (a.opcode, )), str(a.protosrc), str(a.protodst)))

            msg = of.ofp_packet_out(
                in_port=inport,
                action=of.ofp_action_output(port=of.OFPP_FLOOD))
            if event.ofp.buffer_id is of.NO_BUFFER:
                # Try sending the (probably incomplete) raw data
                msg.data = event.data
            else:
                msg.buffer_id = event.ofp.buffer_id
            event.connection.send(msg.pack())
Exemplo n.º 46
0
def process_data(msg):
    if msg.data == b'':
        return ()
    else:
        dp_packet = ethernet(msg.data)
        return DPFingerprint.from_pkt(dp_packet)
Exemplo n.º 47
0
    def ICMP_Reply_handler(self, packet, packet_in):
        ip_packet = packet.payload
        ipSrcAdd = self.route_table.get(str(ip_packet.srcip))
        ipDstAdd = self.route_table.get(str(ip_packet.dstip))

        if ipDstAdd != None:
            if str(packet.dst) == '00:00:00:00:11:05':
                if ipDstAdd[1] == '10.0.1.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr(ipDstAdd[0])
                    ether_pack.payload = packet.payload
                    self.send_Packet(frame=ether_pack, out_port=ipDstAdd[3])
                elif ipDstAdd[1] == '10.0.2.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr('00:00:00:00:11:06')
                    ether_pack.payload = packet.payload
                    self.send_Packet(frame=ether_pack, out_port=3)
                elif ipDstAdd[1] == '10.0.3.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr('00:00:00:00:11:07')
                    ether_pack.payload = packet.payload
                    self.send_Packet(frame=ether_pack, out_port=4)
            elif str(packet.dst) == '00:00:00:00:11:06':
                if ipDstAdd[1] == '10.0.2.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr(ipDstAdd[0])
                    ether_pack.payload = packet.payload
                    self.send_Packet(frame=ether_pack, out_port=ipDstAdd[3])
                elif ipDstAdd[1] == '10.0.1.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr('00:00:00:00:11:05')
                    ether_pack.payload = packet.payload
                    self.send_Packet(frame=ether_pack, out_port=2)
                elif ipDstAdd[1] == '10.0.3.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr('00:00:00:00:11:07')
                    ether_pack.payload = packet.payload
                    self.send_Packet(frame=ether_pack, out_port=3)
            elif str(packet.dst) == '00:00:00:00:11:07':
                if ipDstAdd[1] == '10.0.3.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr(ipDstAdd[0])
                    ether_pack.payload = packet.payload
                    self.send_Packet(frame=ether_pack, out_port=ipDstAdd[3])
                elif ipDstAdd[1] == '10.0.1.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr('00:00:00:00:11:05')
                    ether_pack.payload = packet.payload
                    self.send_Packet(frame=ether_pack, out_port=3)
                elif ipDstAdd[1] == '10.0.2.0/24':
                    ether_pack = pkt.ethernet()
                    ether_pack.type = pkt.ethernet.IP_TYPE
                    ether_pack.src = packet.dst
                    ether_pack.dst = adr.EthAddr('00:00:00:00:11:06')
                    ether_pack.payload = packet.payload
                    self.send_Packet(frame=ether_pack, out_port=2)
            else:
                self.send_Packet(frame=packet, out_port=ipDstAdd[3])
Exemplo n.º 48
0
    def ICMP_Request_handler(self, packet, packet_in):
        ip_packet = packet.payload
        icmp_segment = ip_packet.payload
        ipDstAdd = self.route_table.get(str(ip_packet.dstip))

        #ICMP reach
        if ipDstAdd != None:
            #ICMP -> router
            if ipDstAdd[2] == 'R':
                log.debug("----------ICMP echo packet----------")
                #echo packet
                echo_segment = pkt.echo()
                echo_segment.seq = icmp_segment.payload.seq + 1
                echo_segment.id = icmp_segment.payload.id
                #icmp packt|echo
                icmp_reply = pkt.icmp()
                icmp_reply.type = pkt.TYPE_ECHO_REQUEST
                icmp_reply.payload = echo_segment
                #ip packet|icmp|echo
                ip_pack = pkt.ipv4()
                ip_pack.srcip = ip_packet.dstip
                ip_pack.dstip = ip_packet.srcip
                ip_pack.protocol = pkt.ipv4.ICMP_PROTOCOL
                ip_pack.payload = icmp_reply
                #frame|ip|icmp|echo
                ether_pack = pkt.ethernet()
                ether_pack.dst = packet.src
                ether_pack.src = packet.dst
                ether_pack.type = pkt.ethernet.IP_TYPE
                ether_pack.payload = ip_pack

                self.send_Packet(frame=ether_pack, out_port=packet_in.in_port)

            elif ipDstAdd[2] == 'H':
                #router -> can reache ipadd
                #frame|original packet send to dst
                ether_pack = pkt.ethernet()
                ether_pack.type = pkt.ethernet.IP_TYPE
                ether_pack.src = packet.dst
                ether_pack.dst = adr.EthAddr(ipDstAdd[0])
                ether_pack.payload = packet.payload

                self.send_Packet(frame=ether_pack, out_port=ipDstAdd[1])
        #ICMP unreach
        else:
            #log.debug("----------ICMP unreach----------")
            unreachPacket = pkt.unreach()
            unreachPacket.payload = packet.payload

            icmp_unreReply = pkt.icmp()
            icmp_unreReply.type = pkt.TYPE_DEST_UNREACH
            icmp_unreReply.payload = unreachPacket

            ip_unrePack = pkt.ipv4()
            ip_unrePack.srcip = ip_packet.dstip
            ip_unrePack.dstip = ip_packet.srcip
            ip_unrePack.protocol = pkt.ipv4.ICMP_PROTOCOL
            ip_unrePack.payload = icmp_unreReply

            ether_unrePack = pkt.ethernet()
            ether_unrePack.src = packet.dst
            ether_unrePack.dst = packet.src
            ether_unrePack.type = pkt.ethernet.IP_TYPE
            ether_unrePack.payload = ip_unrePack

            self.send_Packet(frame=ether_unrePack, out_port=packet_in.in_port)
Exemplo n.º 49
0
def _do_ctl2(event):
    def errf(msg, *args):
        raise RuntimeError(msg % args)

    args = event.args

    def ra(low, high=None):
        if high is None: high = low
        if len(args) < low or len(args) > high:
            raise RuntimeError("Wrong number of arguments")
        return False

    def get_sw(arg, fail=True):
        r = _switches.get(arg)
        if r is not None: return r
        try:
            dpid = str_to_dpid(arg)
        except Exception:
            raise RuntimeError("No such switch as %s" % (arg, ))
        r = core.datapaths.get(dpid)
        if r is None and fail:
            raise RuntimeError("No such switch as %s" % (dpid_to_str(dpid), ))
        return r

    try:
        if event.first == "add-port":
            ra(1, 2)
            if len(event.args) == 1 and len(_switches) == 1:
                sw = _switches[_switches.keys()[0]]
                p = args[0]
            else:
                ra(2)
                sw = get_sw(args[0])
                p = args[1]
            sw.add_interface(p, start=True, on_error=errf)
        elif event.first == "del-port":
            ra(1, 2)
            if len(event.args) == 1:
                for sw in _switches.values():
                    for p in sw.ports.values():
                        if p.name == event.args[0]:
                            sw.remove_interface(event.args[0])
                            return
                raise RuntimeError("No such interface")
            sw = _switches[event.args[0]]
            sw.remove_interface(args[1])
        elif event.first == "show":
            ra(0)
            s = []
            for sw in _switches.values():
                s.append("Switch %s" % (sw.name, ))
                for no, p in sw.ports.iteritems():
                    stats = sw.port_stats[no]
                    s.append(" %3s %-16s rx:%-20s tx:%-20s" %
                             (no, p.name, "%s (%s)" %
                              (stats.rx_packets, stats.rx_bytes), "%s (%s)" %
                              (stats.tx_packets, stats.tx_bytes)))
            return "\n".join(s)

        elif event.first == "show-table":
            ra(0, 1)
            sw = None
            if len(args) == 1:
                sw = get_sw(args[0])
            s = []
            for switch in _switches.values():
                if sw is None or switch is sw:
                    s.append("== " + switch.name + " ==")
                    for entry in switch.table.entries:
                        s.append(entry.show())
            return "\n".join(s)

        elif event.first == "wire-port":
            # Wire a virtual port to a channel: wire-port [sw] port channel
            ra(2, 3)
            if len(event.args) == 2 and len(_switches) == 1:
                sw = _switches[_switches.keys()[0]]
                p = args[0]
                c = args[1]
            else:
                ra(3)
                sw = get_sw(args[0])
                p = args[1]
                c = args[2]
            for port in sw.ports.values():
                if port.name == p:
                    px = sw.px.get(port.port_no)
                    if not isinstance(px, VirtualPort):
                        raise RuntimeError("Port is not a virtual port")
                    px.channel = c
                    return
            raise RuntimeError("No such interface")

        elif event.first == "unwire-port":
            # Unhook the virtual port: unwire-port [sw] port
            ra(1, 2)
            if len(event.args) == 1 and len(_switches) == 1:
                sw = _switches[_switches.keys()[0]]
                p = args[0]
            else:
                ra(2)
                sw = get_sw(args[0])
                p = args[1]
            for port in sw.ports.values():
                if port.name == p:
                    px = sw.px.get(port.port_no)
                    if not isinstance(px, VirtualPort):
                        raise RuntimeError("Port is not a virtual port")
                    px.channel = None
                    return
            raise RuntimeError("No such interface")

        elif event.first == "sendraw":
            # sendraw sw src-port <raw hex bytes>
            if len(args) < 3: ra(3)
            sw = get_sw(args[0])
            p = args[1]
            data = []
            for x in args[2:]:
                x = x.strip()
                #print "<",x,">"
                if len(x) < 2:
                    data.append(int(x, 16))
                else:
                    assert len(x) & 1 == 0
                    for y, z in zip(x[::2], x[1::2]):
                        data.append(int(y + z, 16))
            data = "".join(chr(x) for x in data)
            for port in sw.ports.values():
                if port.name == p:
                    px = sw.px.get(port.port_no)
                    sw._pcap_rx(px, data, 0, 0, len(data))
                    return
            raise RuntimeError("No such interface")

        elif event.first == "ping":
            # ping [sw] dst-mac dst-ip [-I src-ip] [--port src-port]
            #      [-s byte-count] [-p pad] [-t ttl]
            from pox.lib.addresses import EthAddr, IPAddr
            kvs = dict(s=(int, 56),
                       p=(str, chr(0x42)),
                       port=(str, ""),
                       I=(IPAddr, IPAddr("1.1.1.1")),
                       t=(int, 64))
            ai = list(event.args)
            ai.append(None)
            args[:] = []
            skip = False
            for k, v in zip(ai[:-1], ai[1:]):
                if skip:
                    skip = False
                    continue
                if not k.startswith("-"):
                    args.append(k)
                    continue
                k = k.lstrip("-").replace("-", "_")
                if "=" in k:
                    k, v = k.split("=", 1)
                else:
                    if v is None:
                        raise RuntimeError("Expected argument for '%s'" %
                                           (k, ))
                    skip = True
                if k not in kvs:
                    raise RuntimeError("Unknown option '%s'" % (k, ))
                kvs[k] = (kvs[k][0], kvs[k][0](v))
            kvs = {k: v[1] for k, v in kvs.items()}
            ra(2, 3)
            pad = (kvs['p'] * kvs['s'])[:kvs['s']]
            if len(args) == 2 and len(_switches) == 1:
                sw = _switches[_switches.keys()[0]]
                mac, ip = args
            else:
                ra(3)
                sw = get_sw(args[0])
                mac, ip = args[1:]
            mac = EthAddr(mac)
            ip = IPAddr(ip)
            srcport = kvs['port']

            for p in sw.ports.values():
                if srcport == "" or p.name == srcport:
                    echo = pkt.echo()
                    echo.payload = pad

                    icmp = pkt.icmp()
                    icmp.type = pkt.TYPE_ECHO_REQUEST
                    icmp.payload = echo

                    # Make the IP packet around it
                    ipp = pkt.ipv4()
                    ipp.protocol = ipp.ICMP_PROTOCOL
                    ipp.srcip = kvs['I']
                    ipp.dstip = ip
                    ipp.ttl = kvs['t']
                    ipp.payload = icmp

                    # Ethernet around that...
                    e = pkt.ethernet()
                    e.src = p.hw_addr
                    e.dst = mac
                    e.type = e.IP_TYPE
                    e.payload = ipp

                    data = e.pack()

                    px = sw.px.get(p.port_no)
                    sw._pcap_rx(px, data, 0, 0, len(data))
                    return
            raise RuntimeError("No such interface")

        else:
            raise RuntimeError("Unknown command")

    except Exception as e:
        log.exception("While processing command")
        return "Error: " + str(e)
Exemplo n.º 50
0
    def _handle_openflow_PacketIn(self, event):
        dpid = event.connection.dpid
        inport = event.port
        packet = event.parsed
        log.warning("Inho #5168 : %s %s ", type(dpid), dpid)
        if not packet.parsed:
            log.warning("%i %i ignoring unparsed packet", dpid, inport)
            return

        if dpid not in self.arpTable:
            # New switch -- create an empty table
            self.arpTable[dpid] = {}
            for fake in self.fakeways:
                self.arpTable[dpid][IPAddr(fake)] = Entry(
                    of.OFPP_NONE, dpid_to_mac(dpid))

        if packet.type == ethernet.LLDP_TYPE:
            # Ignore LLDP packets
            return

        if isinstance(packet.next, ipv4):
            log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip,
                      packet.next.dstip)

            # Send any waiting packets...
            self._send_lost_buffers(dpid, packet.next.srcip, packet.src,
                                    inport)

            # Learn or update port/MAC info
            if packet.next.srcip in self.arpTable[dpid]:
                if self.arpTable[dpid][packet.next.srcip] != (inport,
                                                              packet.src):
                    log.info("%i %i RE-learned %s", dpid, inport,
                             packet.next.srcip)
                    if self.wide:
                        # Make sure we don't have any entries with the old info...
                        msg = of.ofp_flow_mod(command=of.OFPFC_DELETE)
                        msg.match.nw_dst = packet.next.srcip
                        msg.match.dl_type = ethernet.IP_TYPE
                        event.connection.send(msg)
            else:
                log.debug("%i %i learned %s", dpid, inport, packet.next.srcip)
            self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src)

            # Try to forward
            dstaddr = packet.next.dstip
            if dstaddr not in self.arpTable[dpid]:
                if packet.next.srcip == IPAddr("10.0.0.1"):
                    self.arpTable[dpid][packet.next.dstip] = Entry(
                        inport, packet.src)
                    self.arpTable[dpid][packet.next.dstip].mac = EthAddr(
                        "32:d5:a3:be:19:77")
                else:
                    self.arpTable[dpid][packet.next.dstip] = Entry(
                        inport, packet.src)
                    self.arpTable[dpid][packet.next.dstip].mac = EthAddr(
                        "08:00:27:2a:87:c3")

            if packet.next.protocol == ipv4.TCP_PROTOCOL:
                if packet.next.dstip == "10.0.0.1":
                    e = pkt.ethernet()
                    e.src = EthAddr(packet.src)
                    e.dst = self.arpTable[dpid][dstaddr].mac
                    e.type = e.IP_TYPE
                    tcpp = pkt.tcp()
                    tcpp.srcport = packet.next.payload.srcport  #packet.next.payload = tcpp, packet.next = ip, packet = E
                    tcpp.dstport = packet.next.payload.dstport
                    tcpp.seq = packet.next.payload.seq
                    tcpp.ack = packet.next.payload.ack
                    tcpp.win = 29200
                    tcpp.SYN = True  #send SYN
                    tcpp.ACK = False

                    tcp = pkt.ipv4()
                    tcp.protocol = tcp.TCP_PROTOCOL
                    tcp.srcip = packet.next.srcip
                    tcp.dstip = packet.next.dstip
                    tcp.payload = tcpp

                    e.payload = tcp
                    msg = of.ofp_packet_out()
                    msg.data = e.pack()
                    msg.actions.append(
                        of.ofp_action_output(port=of.OFPP_IN_PORT))
                    msg.in_port = inport
                    event.connection.send(msg)

                    print(e.dst)
                    print(packet.next.dstip)

            if packet.next.protocol == ipv4.ICMP_PROTOCOL:
                e = pkt.ethernet()
                e.src = self.arpTable[dpid][dstaddr].mac
                e.dst = EthAddr(packet.src)
                e.type = e.IP_TYPE
                ipp = pkt.ipv4()
                ipp.protocol = ipp.ICMP_PROTOCOL
                ipp.srcip = packet.next.dstip
                print(ipp.srcip)
                ipp.dstip = packet.next.srcip
                icmp = pkt.icmp()
                icmp.type = pkt.ICMP.TYPE_ECHO_REPLY
                icmp.payload = packet.next.payload.payload  #copy the ping payload of the packet that they receive
                ipp.payload = icmp
                e.payload = ipp
                msg = of.ofp_packet_out()
                msg.data = e.pack()
                msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT))
                msg.in_port = inport
                event.connection.send(msg)
                return

            if packet.next.protocol == ipv4.TCP_PROTOCOL and packet.next.dstip != "10.0.0.1":

                if packet.next.payload.SYN and not packet.next.payload.ACK:  #this is to send SYN, ACK
                    print "SYN packet", packet.next.payload

                    e = pkt.ethernet()
                    e.src = self.arpTable[dpid][dstaddr].mac
                    e.dst = EthAddr(packet.src)
                    e.type = e.IP_TYPE
                    tcpp = pkt.tcp()
                    tcpp.srcport = packet.next.payload.dstport  #packet.next.payload = tcpp, packet.next = ip, packet = E
                    tcpp.dstport = packet.next.payload.srcport
                    tcpp.seq = 0
                    tcpp.ack = packet.next.payload.seq + 1
                    tcpp.win = 29200
                    tcpp.SYN = True  #send SYN
                    tcpp.ACK = True  #send ACK

                    tcp = pkt.ipv4()
                    tcp.protocol = tcp.TCP_PROTOCOL
                    tcp.srcip = packet.next.dstip
                    tcp.dstip = packet.next.srcip
                    tcp.payload = tcpp

                    e.payload = tcp
                    msg = of.ofp_packet_out()
                    msg.data = e.pack()
                    msg.actions.append(
                        of.ofp_action_output(port=of.OFPP_IN_PORT))
                    msg.in_port = inport
                    event.connection.send(msg)

                    time.sleep(0.15)

                    e = pkt2.ethernet()
                    e.src = self.arpTable[dpid][dstaddr].mac
                    e.dst = EthAddr(packet.src)
                    e.type = e.IP_TYPE
                    tcpp = pkt2.tcp()
                    tcpp.srcport = packet.next.payload.dstport
                    tcpp.dstport = packet.next.payload.srcport
                    #print(packet.next.payload.ack)
                    tcpp.seq = 1
                    tcpp.ack = packet.next.payload.seq + 127
                    tcpp.win = 29200
                    tcpp.PSH = True  #send PSH
                    tcpp.ACK = True  #send ACK
                    tcpp.payload = makeMessage(
                        magic, "version",
                        makeVersionPayload(str(packet.next.dstip),
                                           str(packet.next.srcip)))

                    tcp = pkt2.ipv4()
                    tcp.protocol = tcp.TCP_PROTOCOL
                    tcp.srcip = packet.next.dstip
                    tcp.dstip = packet.next.srcip
                    tcp.payload = tcpp
                    e.payload = tcp

                    print "*****"
                    msg = of.ofp_packet_out()
                    msg.data = e.pack()
                    msg.actions.append(
                        of.ofp_action_output(port=of.OFPP_IN_PORT))
                    msg.in_port = inport
                    event.connection.send(msg)
                    return

                # if not packet.next.payload.SYN and packet.next.payload.ACK:
                #   print "ACK packet", packet.next.payload
                #   e = pkt.ethernet()
                #   e.src = self.arpTable[dpid][dstaddr].mac
                #   e.dst = EthAddr(packet.src)
                #   e.type = e.IP_TYPE
                #   tcpp = pkt.tcp()
                #   tcpp.srcport = packet.next.payload.dstport
                #   tcpp.dstport = packet.next.payload.srcport
                #   # tcpp.seq = 1 # will be random
                #   tcpp.ack = packet.next.payload.ack+1
                #   # tcpp.SYN = True
                #   tcpp.ACK = True

                #   tcp = pkt.ipv4()
                #   tcp.protocol = tcp.TCP_PROTOCOL
                #   tcp.srcip = packet.next.dstip
                #   tcp.dstip = packet.next.srcip
                #   tcp.payload = tcpp

                #   e.payload = tcp
                #   msg = of.ofp_packet_out()
                #   msg.data = e.pack()
                #   msg.actions.append(of.ofp_action_output(port =
                #                                           of.OFPP_IN_PORT))
                #   msg.in_port = inport
                #   event.connection.send(msg)
                #   return
                else:
                    print "Not SYN", packet.next.payload
            elif self.arp_for_unknowns:
                # We don't know this destination.
                # First, we track this buffer so that we can try to resend it later
                # if we learn the destination, second we ARP for the destination,
                # which should ultimately result in it responding and us learning
                # where it is

                # Add to tracked buffers
                if (dpid, dstaddr) not in self.lost_buffers:
                    self.lost_buffers[(dpid, dstaddr)] = []
                bucket = self.lost_buffers[(dpid, dstaddr)]
                entry = (time.time() + MAX_BUFFER_TIME, event.ofp.buffer_id,
                         inport)
                bucket.append(entry)
                while len(bucket) > MAX_BUFFERED_PER_IP:
                    del bucket[0]

                # Expire things from our outstanding ARP list...
                self.outstanding_arps = {
                    k: v
                    for k, v in self.outstanding_arps.iteritems()
                    if v > time.time()
                }

                # Check if we've already ARPed recently
                if (dpid, dstaddr) in self.outstanding_arps:
                    # Oop, we've already done this one recently.
                    return

                # And ARP...
                self.outstanding_arps[(dpid, dstaddr)] = time.time() + 4

                r = arp()
                r.hwtype = r.HW_TYPE_ETHERNET
                r.prototype = r.PROTO_TYPE_IP
                r.hwlen = 6
                r.protolen = r.protolen
                r.opcode = r.REQUEST
                r.hwdst = ETHER_BROADCAST
                r.protodst = dstaddr
                r.hwsrc = packet.src
                r.protosrc = packet.next.srcip
                e = ethernet(type=ethernet.ARP_TYPE,
                             src=packet.src,
                             dst=ETHER_BROADCAST)
                e.set_payload(r)
                log.debug("%i %i ARPing for %s on behalf of %s" %
                          (dpid, inport, r.protodst, r.protosrc))
                msg = of.ofp_packet_out()
                msg.data = e.pack()
                msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
                msg.in_port = inport
                event.connection.send(msg)

        elif isinstance(packet.next, arp):
            a = packet.next
            log.debug("%i %i ARP %s %s => %s", dpid, inport, {
                arp.REQUEST: "request",
                arp.REPLY: "reply"
            }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, a.protodst)

            if a.protosrc == IPAddr("10.0.0.1"):
                if a.opcode == arp.REQUEST:

                    if a.protodst not in self.arpTable[dpid]:
                        self.arpTable[dpid][a.protodst] = Entry(
                            inport, packet.src)
                        self.arpTable[dpid][a.protodst].mac = EthAddr(
                            "32:d5:a3:be:19:77")

                    r = arp()
                    r.hwtype = a.hwtype
                    r.prototype = a.prototype
                    r.hwlen = a.hwlen
                    r.protolen = a.protolen
                    r.opcode = arp.REPLY
                    r.hwdst = a.hwsrc
                    r.protodst = a.protosrc
                    r.protosrc = a.protodst
                    r.hwsrc = self.arpTable[dpid][a.protodst].mac
                    e = ethernet(type=packet.type,
                                 src=dpid_to_mac(dpid),
                                 dst=a.hwsrc)
                    e.set_payload(r)
                    log.debug("%i %i answering ARP for %s: %s" %
                              (dpid, inport, r.protosrc, r.hwsrc))
                    msg = of.ofp_packet_out()
                    msg.data = e.pack()
                    msg.actions.append(
                        of.ofp_action_output(port=of.OFPP_IN_PORT))
                    msg.in_port = inport
                    event.connection.send(msg)
                    return

            # Didn't know how to answer or otherwise handle this ARP, so just flood it
            log.debug("%i %i flooding ARP %s %s => %s" % (dpid, inport, {
                arp.REQUEST: "request",
                arp.REPLY: "reply"
            }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, a.protodst))

            msg = of.ofp_packet_out(
                in_port=inport,
                data=event.ofp,
                action=of.ofp_action_output(port=of.OFPP_FLOOD))
            event.connection.send(msg)
Exemplo n.º 51
0
    def install_path(self, src, dst, match, event):
        """
    Attempts to install a path between this switch and some destination
    """
        global file
        p = _get_path(src, dst)
        if p is None:
            log.warning("Can't get from %s to %s", match.dl_src, match.dl_dst)
            file.write("Can't get from %s to %s \n" %
                       (match.dl_src, match.dl_dst))

            import pox.lib.packet as pkt

            if (match.dl_type == pkt.ethernet.IP_TYPE
                    and event.parsed.find('ipv4')):
                # It's IP -- let's send a destination unreachable
                log.debug("Dest unreachable (%s -> %s)", match.dl_src,
                          match.dl_dst)
                file.write("Dest unreachable (%s -> %s \n)" %
                           (match.dl_src, match.dl_dst))

                from pox.lib.addresses import EthAddr
                e = pkt.ethernet()
                e.src = EthAddr(dpid_to_str(self.dpid))  #FIXME: Hmm...
                e.dst = match.dl_src
                e.type = e.IP_TYPE
                ipp = pkt.ipv4()
                ipp.protocol = ipp.ICMP_PROTOCOL
                ipp.srcip = match.nw_dst  #FIXME: Ridiculous
                ipp.dstip = match.nw_src
                icmp = pkt.icmp()
                icmp.type = pkt.ICMP.TYPE_DEST_UNREACH
                icmp.code = pkt.ICMP.CODE_UNREACH_HOST
                orig_ip = event.parsed.find('ipv4')

                d = orig_ip.pack()
                d = d[:orig_ip.hl * 4 + 8]
                import struct
                d = struct.pack("!HH", 0, 0) + d  #FIXME: MTU
                icmp.payload = d
                ipp.payload = icmp
                e.payload = ipp
                msg = of.ofp_packet_out()
                msg.actions.append(of.ofp_action_output(port=event.port))
                msg.data = e.pack()
                self.connection.send(msg)

            return

        log.debug("Installing path for %s -> %s %04x (%i hops)", match.dl_src,
                  match.dl_dst, match.dl_type, len(p))
        file.write("Installing path for %s -> %s %04x (%i hops) \n" %
                   (match.dl_src, match.dl_dst, match.dl_type, len(p)))

        # We have a path -- install it
        self._install_path(p, match, event.ofp)

        # Now reverse it and install it backwards
        # (we'll just assume that will work)
        p = [(sw, out_port, in_port) for sw, in_port, out_port in p]
        ##############the path order is important,change it
        c = []
        for i in range(0, len(p)):
            c.append(p[len(p) - 1 - i])
        self._install_path(c, match.flip())
Exemplo n.º 52
0
    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)
Exemplo n.º 53
0
    def _handle_PacketIn(self, event):
        """
    Handle packet in messages from the switch to implement above algorithm.
    """
        global file
        packet = event.parsed

        def flood():
            """ Floods the packet """
            if self.is_holding_down:
                log.warning("Not flooding -- holddown active")
                file.write("Not flooding -- holddown active\n")
            msg = of.ofp_packet_out()
            # OFPP_FLOOD is optional; some switches may need OFPP_ALL
            msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
            #print '**************************************************************'
            #print 'THe packetIn is flooding!!!'
            #print '**************************************************************'
            file.write(
                '**************************************************************\n'
            )
            file.write('THe packetIn is flooding!!!\n')
            file.write(
                '**************************************************************\n'
            )
            msg.buffer_id = event.ofp.buffer_id
            msg.in_port = event.port
            self.connection.send(msg)

        def drop():
            # Kill the buffer
            if event.ofp.buffer_id is not None:
                msg = of.ofp_packet_out()
                msg.buffer_id = event.ofp.buffer_id
                event.ofp.buffer_id = None  # Mark is dead
                msg.in_port = event.port
                print '**************************************************************'
                print 'THe packetIn is drop!!!'
                print '**************************************************************'
                file.write(
                    '**************************************************************\n'
                )
                file.write('THe packetIn is drop!!!\n')
                file.write(
                    '**************************************************************\n'
                )
                self.connection.send(msg)

        self.macToPort[packet.src] = event.port  # 1

        match = of.ofp_match.from_packet(packet)

        iptomac[match.nw_src] = match.dl_src
        if match.dl_dst != EthAddr("ff:ff:ff:ff:ff:ff"):
            iptomac[match.nw_dst] = match.dl_dst

        global mac_map
        for key, value in self.macToPort.iteritems():
            if value != 6:
                mac_map[key] = (self, value
                                )  #note the sw which client is connected with

        #print '********************************************************************'
        #print 'switch dpid:'+str(self.dpid)
        #print 'nw_src:'+str(match.nw_src)
        #print 'inport:'+str(event.port)
        #print 'dl_dst:'+str(match.dl_dst)
        #file.write('********************************************************************\n')
        #file.write('switch dpid:'+str(self.dpid)+'\n')
        #file.write('nw_src:'+str(match.nw_src)+'\n')
        #file.write('inport:'+str(event.port)+'\n')
        #file.write('dl_dst:'+str(match.dl_dst)+'\n')

        if match.dl_type == 2054:  #0x0806
            print '********************************************************************'
            print 'switch dpid:' + str(self.dpid)
            print 'nw_src:' + str(match.nw_src)
            print 'inport:' + str(event.port)
            print 'dl_dst:' + str(match.dl_dst)
            file.write(
                '********************************************************************\n'
            )
            file.write('switch dpid:' + str(self.dpid) + '\n')
            file.write('nw_src:' + str(match.nw_src) + '\n')
            file.write('inport:' + str(event.port) + '\n')
            file.write('dl_dst:' + str(match.dl_dst) + '\n')
            if match.nw_proto == 1:
                print 'arp request'
                file.write('arp request\n')
            elif match.nw_proto == 2:
                print 'arp answer'
                file.write('arp answer\n')
            else:
                print 'arp unknown'
                file.write('arp unknown\n')
        elif match.dl_type == 2048:  #0x0800
            if match.nw_proto == 1:
                print '********************************************************************'
                print 'switch dpid:' + str(self.dpid)
                print 'nw_src:' + str(match.nw_src)
                print 'inport:' + str(event.port)
                print 'dl_dst:' + str(match.dl_dst)
                print 'icmp'
                file.write(
                    '********************************************************************\n'
                )
                file.write('switch dpid:' + str(self.dpid) + '\n')
                file.write('nw_src:' + str(match.nw_src) + '\n')
                file.write('inport:' + str(event.port) + '\n')
                file.write('dl_dst:' + str(match.dl_dst) + '\n')
                file.write('icmp\n')
                '''
      elif match.nw_proto == 6:
        print 'tcp'
        file.write('tcp\n')
      elif match.nw_proto == 17:
        print 'udp'
        file.write('udp\n')
      else:
        print 'ip unknown'
        file.write('ip unknown\n')
    elif match.dl_type == 34525:   #0x86DD
      print 'ipv6'
      file.write('ipv6\n')
    else:
      print 'unknown'
      file.write('unknown\n')
      '''
        #print '********************************************************************'
        file.write(
            '********************************************************************\n'
        )

        #print self.dpid
        #print match
        #print iptomac
        #print self.macToPort
        #print mac_map

        #loc = (self, event.port) # Place we saw this ethaddr
        #oldloc = mac_map.get(packet.src) # Place we last saw this ethaddr

        if packet.effective_ethertype == packet.LLDP_TYPE:
            drop()
            return

        if match.dl_type == 2054 and match.nw_proto == 1 and match.nw_dst in iptomac.keys(
        ):
            import pox.lib.packet as pkt
            if match.dl_type == pkt.ethernet.ARP_TYPE:
                e = pkt.ethernet()
                e.src = EthAddr(dpid_to_str(self.dpid))  #FIXME: Hmm...
                e.dst = match.dl_src
                e.type = e.ARP_TYPE
                arpp = pkt.arp()
                arpp.opcode = arpp.REPLY
                arpp.hwsrc = iptomac[match.nw_dst]
                arpp.hwdst = match.dl_src
                arpp.protosrc = match.nw_dst
                arpp.protodst = match.nw_src

                e.payload = arpp
                msg = of.ofp_packet_out()
                msg.actions.append(of.ofp_action_output(port=event.port))
                msg.data = e.pack()
                self.connection.send(msg)

                print '**********************************************************'
                print 'arp reply to ' + str(match.nw_src)
                print '**********************************************************'
                file.write(
                    '**********************************************************\n'
                )
                file.write('arp reply to ' + str(match.nw_src) + '\n')
                file.write(
                    '**********************************************************\n'
                )
                return

        if packet.dst.is_multicast:
            #if match.dl_dst == Ethaddr('ff:ff:ff:ff:ff:ff')
            if match.dl_type == 2054 and match.nw_proto == 1 and match.nw_dst in iptomac.keys(
            ):
                import pox.lib.packet as pkt
                if match.dl_type == pkt.ethernet.ARP_TYPE:
                    e = pkt.ethernet()
                    e.src = EthAddr(dpid_to_str(self.dpid))  #FIXME: Hmm...
                    e.dst = match.dl_src
                    e.type = e.ARP_TYPE
                    arpp = pkt.arp()
                    arpp.opcode = arpp.REPLY
                    arpp.hwsrc = iptomac[match.nw_dst]
                    arpp.hwdst = match.dl_src
                    arpp.protosrc = match.nw_dst
                    arpp.protodst = match.nw_src

                    e.payload = arpp
                    msg = of.ofp_packet_out()
                    msg.actions.append(of.ofp_action_output(port=event.port))
                    msg.data = e.pack()
                    self.connection.send(msg)

                    print '**********************************************************'
                    print 'arp reply to' + str(match.nw_src)
                    print '**********************************************************'
                    file.write(
                        '**********************************************************\n'
                    )
                    file.write('arp reply to' + str(match.nw_src) + '\n')
                    file.write(
                        '**********************************************************\n'
                    )

            else:
                flood()  # 3a
        else:
            if packet.dst not in mac_map:
                if packet.dst in mesh_bat0_mac.values():
                    drop()
                else:
                    flood()
            else:
                #dest = mac_map[packet.dst]                         ###ycj
                #match = of.ofp_match.from_packet(packet)           ###ycj
                #print match
                #print 'packet.src'
                #print packet.src
                #print packet.dst
                #print mac_map[packet.src][0].dpid
                print '********************************************'
                print 'install dl_type: ' + str(
                    match.dl_type) + '  install nw_proto: ' + str(
                        match.nw_proto)
                print '********************************************'
                file.write('*******************************************\n')
                file.write('install dl_type: ' + str(match.dl_type) +
                           '  install nw_proto: ' + str(match.nw_proto) + '\n')
                file.write('*******************************************\n')
                self.install_path(packet.src, packet.dst, match, event)
Exemplo n.º 54
0
 def cb(obj, data, sec, usec, length):
     p = pkt.ethernet(data)
     print p.dump()
Exemplo n.º 55
0
  def install_path (self, dst_sw, last_port, match, event):
    """
    Attempts to install a path between this switch and some destination
    """
    # p = _get_path(self.dpid, dst_sw.dpid, event.port, last_port)
    # log.info("their path: %s", str(p))
    our_p = _our_get_path(self.dpid, dst_sw.dpid, event.port, last_port)
    log.info("our path: %s", str(our_p))

    # if p is not None and our_p is None:
    #   pdb.set_trace()

    # for n1, n2 in zip(p, our_p):
    #   assert n1 == n2
    p = our_p
    if p is None:
      log.warning("Can't get from %s to %s", match.dl_src, match.dl_dst)

      import pox.lib.packet as pkt

      if (match.dl_type == pkt.ethernet.IP_TYPE and
          event.parsed.find('ipv4')):
        # It's IP -- let's send a destination unreachable
        log.info("Dest unreachable (%s -> %s)",
                  match.dl_src, match.dl_dst)

        from pox.lib.addresses import EthAddr
        e = pkt.ethernet()
        e.src = EthAddr(_dpid_to_str(self.dpid)) #FIXME: Hmm...
        e.dst = match.dl_src
        e.type = e.IP_TYPE
        ipp = pkt.ipv4()
        ipp.protocol = ipp.ICMP_PROTOCOL
        ipp.srcip = match.nw_dst #FIXME: Ridiculous
        ipp.dstip = match.nw_src
        icmp = pkt.icmp()
        icmp.type = pkt.ICMP.TYPE_DEST_UNREACH
        icmp.code = pkt.ICMP.CODE_UNREACH_HOST
        orig_ip = event.parsed.find('ipv4')

        d = orig_ip.pack()
        d = d[:orig_ip.hl * 4 + 8]
        import struct
        d = struct.pack("!HH", 0,0) + d #FIXME: MTU
        icmp.payload = d
        ipp.payload = icmp
        e.payload = ipp
        msg = of.ofp_packet_out()
        msg.actions.append(of.ofp_action_output(port = event.port))
        msg.data = e.pack()
        self.connection.send(msg)

      return

    log.info("Installing path for %s -> %s %04x (%i hops)",
        match.dl_src, match.dl_dst, match.dl_type, len(p))
    # log.info("path: %s", str(p))

    # We have a path -- install it
    self._install_path(p, match, event.ofp)

    # Now reverse it and install it backwards
    # (we'll just assume that will work)
    p = [(sw,out_port,in_port) for sw,in_port,out_port in p]
    self._install_path(p, match.flip())
Exemplo n.º 56
0
def ifReach(dstip, event, self):

    dpid = self.connection.dpid
    for subRouteTable in self.routeTable:

        dstnetwork = subRouteTable[DST_Network]
        if dstip.inNetwork(dstnetwork):
            log.debug('------ip dst %s is in the routeTable-----' % dstip)

            nextPort = subRouteTable[NEXTHOP_PORT]
            log.debug('------ip dst %s is in the routeTable-----' % nextPort)
            if nextPort == event.ofp.in_port:
                continue

            nextHopIp = IPAddr(subRouteTable[NETX_HOP_IP])
            nextPortIp = IPAddr(subRouteTable[NEXT_PORT_IP])
            srcMac = arpCache[dpid][nextPort][nextPortIp]

            if nextHopIp in arpCache[dpid][nextPort]:
                log.debug('------I know the next dst %s mac-----' % nextHopIp)
                nextHopMac = arpCache[dpid][nextPort][nextHopIp]

                msg = of.ofp_flow_mod()
                msg.match = of.ofp_match()
                msg.match.dl_type = ethernet.IP_TYPE
                msg.match.nw_dst = dstip

                msg.command = 0
                msg.idle_timeout = 10
                msg.hard_timeout = 30
                msg.buffer_id = event.ofp.buffer_id
                msg.actions.append(of.ofp_action_dl_addr.set_src(srcMac))
                msg.actions.append(of.ofp_action_dl_addr.set_dst(nextHopMac))
                msg.actions.append(of.ofp_action_output(port=nextPort))
                self.connection.send(msg)

                log.debug('-----install a flow-----')

            else:
                log.debug(
                    '------I don\'t know the next dst %s mac,make an arp request-----'
                    % IPAddr(subRouteTable[NETX_HOP_IP]))
                ARPrequest = arp()
                ARPrequest.opcode = arp.REQUEST
                ARPrequest.protosrc = nextPortIp
                ARPrequest.hwsrc = srcMac
                ARPrequest.protodst = nextHopIp
                arpPacket = ethernet(type=ethernet.ARP_TYPE,
                                     src=ARPrequest.hwsrc,
                                     dst=ETHER_BROADCAST)
                arpPacket.set_payload(ARPrequest)
                msg = of.ofp_packet_out()
                msg.data = arpPacket.pack()
                msg.actions.append(of.ofp_action_output(port=nextPort))
                msg.in_port = event.ofp.in_port
                event.connection.send(msg)
                log.debug('------Arp request has been snet-----')

                nextHopMac = ETHER_BROADCAST
                msg = of.ofp_packet_out()
                msg.in_port = event.port
                msg.buffer_id = event.ofp.buffer_id
                msg.actions.append(of.ofp_action_dl_addr.set_src(srcMac))
                msg.actions.append(of.ofp_action_dl_addr.set_dst(nextHopMac))
                msg.actions.append(of.ofp_action_output(port=nextPort))
                self.connection.send(msg)

            return True
    return False
Exemplo n.º 57
0
    def _handle_PacketIn(self, event):

        packet = event.parsed

        def drop(duration=None):

            if duration is not None:
                if not isinstance(duration, tuple):
                    duration = (duration, duration)
                msg = of.ofp_flow_mod()
                msg.match = of.ofp_match.from_packet(packet)
                msg.idle_timeout = duration[0]
                msg.hard_timeout = duration[1]
                msg.buffer_id = event.ofp.buffer_id
                self.connection.send(msg)
            elif event.ofp.buffer_id is not None:
                msg = of.ofp_packet_out()
                msg.buffer_id = event.ofp.buffer_id
                msg.in_port = event.port
                self.connection.send(msg)

        def flood(message=None):

            msg = of.ofp_packet_out()
            if time.time() - self.connection.connect_time >= _flood_delay:
                if self.hold_down_expired is False:
                    self.hold_down_expired = True
                    log.info("%s: Flood hold-down expired -- flooding",
                             dpid_to_str(event.dpid))
                if message is not None: log.debug(message)
                msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
            else:
                pass
            msg.data = event.ofp
            msg.in_port = event.port
            self.connection.send(msg)

        """Add MAC & IP to Tables"""
        self.macToPort[packet.src] = event.port
        if (self.macToIP.get(packet.src, None)) is None:
            self.macToIP[packet.src] = "10.10.{:d}.{:d}".format(
                (6 - event.dpid % 2), self.addr)
            self.addr += 1
        """Catch and Process IPv4 Packets"""
        ip = packet.find("ipv4")

        if ip is not None:
            ip.ttl -= 1
            """Handle ICMP Time Exceeded Event"""
            if (ip.ttl == 0):
                log.debug("TTL expired!!!")
                """Create ICMP Time Exceeded Message"""
                icmp = pkt.icmp()
                icmp.type = pkt.TYPE_TIME_EXCEED
                log.debug("This is the ICMP error message {:s}".format(
                    icmp.payload))
                """Create IP Payload"""
                ipp = pkt.ipv4()
                ipp.protocol = ipp.ICMP_PROTOCOL
                ipp.srcip = IPAddr(self.macToIP[packet.src])
                ipp.dstip = packet.next.srcip
                ipp.payload = icmp
                log.debug("This is the IP payload {:s}".format(ipp.payload))
                """Create Ethernet Payload"""
                e = pkt.ethernet()
                e.src = packet.dst
                e.dst = packet.src
                e.type = e.IP_TYPE
                e.payload = ipp
                log.debug("This is the Ethernet payload {:s}".format(
                    e.payload))
                """Send Packet the Original Source"""
                msg = of.ofp_packet_out()
                msg.actions.append(
                    of.ofp_action_output(port=self.macToPort[packet.src]))
                msg.date = e.pack()
                msg.in_port = of.OFPP_NONE
                event.connection.send(msg)
Exemplo n.º 58
0
def install_path (self, dst_sw, last_port, match, event):
"""
Attempts to install a path between this switch and some
destination
"""
p = _get_path(self, dst_sw, event.port, last_port)
if p is None:
log.warning("Can't get from %s to %s", match.dl_src, match.dl_dst)
import pox.lib.packet as pkt
if (match.dl_type == pkt.ethernet.IP_TYPE and event.parsed.find('ipv4')):
# It's IP -- let's send a destination unreachable
log.debug("Dest unreachable (%s -> %s)", match.dl_src, match.dl_dst)
from pox.lib.addresses import EthAddr
e = pkt.ethernet()
e.src = EthAddr(dpid_to_str(self.dpid)) #FIXME: Hmm...
e.dst = match.dl_src
e.type = e.IP_TYPE
ipp = pkt.ipv4()
ipp.protocol = ipp.ICMP_PROTOCOL
ipp.srcip = match.nw_dst #FIXME: Ridiculous
ipp.dstip = match.nw_src
icmp = pkt.icmp()
icmp.type = pkt.ICMP.TYPE_DEST_UNREACH
icmp.code = pkt.ICMP.CODE_UNREACH_HOST
orig_ip = event.parsed.find('ipv4')
d = orig_ip.pack()
d = d[:orig_ip.hl * 4 + 8]
import struct
d = struct.pack("!HH", 0,0) + d #FIXME: MTU
icmp.payload = d
ipp.payload = icmp
e.payload = ipp
msg = of.ofp_packet_out()
msg.actions.append(of.ofp_action_output(port =
event.port))
msg.data = e.pack()
self.connection.send(msg)
return
log.debug("Installing path for %s -> %s %04x (%i hops)",
match.dl_src, match.dl_dst, match.dl_type, len(p))
print "maryam dest ip is" , match.nw_dst
#calling the statcolect function when a new flow is to be installed. This function collects statisctics to monitor the network behavior to detect DDOS attacks.
send_path = p
tuple(send_path)
self.statcolect(send_path, match.nw_dst, match.nw_src)
# We have a path -- install it
self._install_path(p, match, event.ofp)
# Now reverse it and install it backwards
# (we'll just assume that will work)
p = [(sw,out_port,in_port) for sw,in_port,out_port in p]
self._install_path(p, match.flip())
def _handle_PacketIn (self, event):
def flood ():
""" Floods the packet """
if self.is_holding_down:
log.warning("Not flooding -- holddown active")
msg = of.ofp_packet_out()
# OFPP_FLOOD is optional; some switches may need OFPP_ALL
msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
msg.buffer_id = event.ofp.buffer_id
msg.in_port = event.port
self.connection.send(msg)
def drop ():
# Kill the buffer
if event.ofp.buffer_id is not None:
msg = of.ofp_packet_out()
msg.buffer_id = event.ofp.buffer_id
event.ofp.buffer_id = None # Mark is dead
msg.in_port = event.port
self.connection.send(msg)
packet = event.parsed
loc = (self, event.port) # Place we saw this ethaddr
oldloc = mac_map.get(packet.src) # Place we last saw this
ethaddr
if packet.effective_ethertype == packet.LLDP_TYPE:
drop()
return
if oldloc is None:
if packet.src.is_multicast == False:
mac_map[packet.src] = loc # Learn position for ethaddr
log.debug("Learned %s at %s.%i", packet.src, loc[0], loc[1])
elif oldloc != loc:
# ethaddr seen at different place!
if loc[1] not in adjacency[loc[0]].values():
# New place is another "plain" port (probably)
log.debug("%s moved from %s.%i to %s.%i?", packet.src, dpid_to_str(oldloc[0].connection.dpid), oldloc[1], dpid_to_str( loc[0].connection.dpid), loc[1])
if packet.src.is_multicast == False:
mac_map[packet.src] = loc # Learn position for ethaddr
log.debug("Learned %s at %s.%i", packet.src, loc[0], loc[1])
elif packet.dst.is_multicast == False:
# New place is a switch-to-switch port!
#TODO: This should be a flood. It'd be nice if we knew. We could
# check if the port is in the spanning tree if it's available.
# Or maybe we should flood more carefully?
log.warning("Packet from %s arrived at %s.%i without flow", packet.src, dpid_to_str(self.dpid), event.port)
#drop()
#return
if packet.dst.is_multicast:
log.debug("Flood multicast from %s", packet.src)
flood()
else:
if packet.dst not in mac_map:
log.debug("%s unknown -- flooding" % (packet.dst,))
flood()
else:
dest = mac_map[packet.dst]
match = of.ofp_match.from_packet(packet)
self.install_path(dest[0], dest[1], match, event)
def disconnect (self):
if self.connection is not None:
log.debug("Disconnect %s" % (self.connection,))
self.connection.removeListeners(self._listeners)
self.connection = None
self._listeners = None
def connect (self, connection):
if self.dpid is None:
self.dpid = connection.dpid
assert self.dpid == connection.dpid
if self.ports is None:
self.ports = connection.features.ports
self.disconnect()
log.debug("Connect %s" % (connection,))
self.connection = connection
self._listeners = self.listenTo(connection)
self._connected_at = time.time()
@property
def is_holding_down (self):
if self._connected_at is None: return True
if time.time() - self._connected_at > FLOOD_HOLDDOWN:
return False
return True
def _handle_ConnectionDown (self, event):
self.disconnect()
class l2_multi (EventMixin):
_eventMixin_events = set([
PathInstalled,
])
def __init__ (self):
# Listen to dependencies
def startup ():
core.openflow.addListeners(self, priority=0)
core.openflow_discovery.addListeners(self)
core.call_when_ready(startup,
('openflow','openflow_discovery'))
def _handle_LinkEvent (self, event):
def flip (link):
return Discovery.Link(link[2],link[3], link[0],link[1])
l = event.link
sw1 = switches[l.dpid1]
sw2 = switches[l.dpid2]
# Invalidate all flows and path info.
# For link adds, this makes sure that if a new link leads to an
# improved path, we use it.
# For link removals, this makes sure that we don't use a
# path that may have been broken.
#NOTE: This could be radically improved! (e.g., not *ALL* paths break)
clear = of.ofp_flow_mod(command=of.OFPFC_DELETE)
for sw in switches.itervalues():
if sw.connection is None: continue
sw.connection.send(clear)
path_map.clear()
if event.removed:
# This link no longer okay
if sw2 in adjacency[sw1]: del adjacency[sw1][sw2]
if sw1 in adjacency[sw2]: del adjacency[sw2][sw1]
# But maybe there's another way to connect these...
for ll in core.openflow_discovery.adjacency:
if ll.dpid1 == l.dpid1 and ll.dpid2 == l.dpid2:
if flip(ll) in core.openflow_discovery.adjacency:
# Yup, link goes both ways
adjacency[sw1][sw2] = ll.port1
adjacency[sw2][sw1] = ll.port2
# Fixed -- new link chosen to connect these
break
else:
# If we already consider these nodes connected, we can
# ignore this link up.
# Otherwise, we might be interested...
if adjacency[sw1][sw2] is None:
# These previously weren't connected. If the link
# exists in both directions, we consider them connected now.
if flip(l) in core.openflow_discovery.adjacency:
# Yup, link goes both ways -- connected!
adjacency[sw1][sw2] = l.port1
adjacency[sw2][sw1] = l.port2
# If we have learned a MAC on this port which we now know to
# be connected to a switch, unlearn it.
bad_macs = set()
for mac,(sw,port) in mac_map.iteritems():
#print sw,sw1,port,l.port1
if sw is sw1 and port == l.port1:
if mac not in bad_macs:
log.debug("Unlearned %s", mac)
bad_macs.add(mac)
if sw is sw2 and port == l.port2:
if mac not in bad_macs:
log.debug("Unlearned %s", mac)
bad_macs.add(mac)
for mac in bad_macs:
del mac_map[mac]
def _handle_ConnectionUp (self, event):
sw = switches.get(event.dpid)
if sw is None:
# New switch
sw = Switch()
switches[event.dpid] = sw
sw.connect(event.connection)
else:
sw.connect(event.connection)
def _handle_BarrierIn (self, event):
wp = waiting_paths.pop((event.dpid,event.xid), None)
if not wp:
#log.info("No waiting packet %s,%s", event.dpid, event.xid)
return
#log.debug("Notify waiting packet %s,%s", event.dpid,event.xid)
wp.notify(event)
def launch ():
core.registerNew(l2_multi)
core.registerNew(Cleanswitch)
core.Cleanswitch._do_sleep()
timeout = min(max(PATH_SETUP_TIME, 5) * 2, 15)
Timer(timeout, WaitingPath.expire_waiting_paths, recurring=True)
print "will go to execute the timer for sent_sw"
#we will call the cleaning_sent_sw function in the switch class to erase the list of the switches that have been already polled for statistics. As long as the switches are in the sent_sw list no statistics request will be sent to them.
Timer(10, Switch.cleaning_sent_sw, recurring=True)
core.openflow.addListenerByName("FlowStatsReceived",
Switch()._handle_flowstats_received)
Exemplo n.º 59
0
 def gestisciPacketIn(self, packet, packet_in, dpid, event):
     #eseguendo una gestione manuale delle ARP, bisogna salvane le info importanti
     if packet.type == packet.ARP_TYPE:
         self.registraHost(packet.src, event.connection.dpid, event.port,
                           packet.payload.protosrc)
         ipSource = str(packet.payload.protosrc)
         ipDest = str(packet.payload.protodst)
         macSource = str(packet.src)
         #se non e' presente il mittente in tabella, viene aggiunto
         if ipSource not in self.tabellaC.keys():
             self.tabellaC[ipSource] = (macSource, dpid)
         #se e' un arp request
         if packet.payload.opcode == pkt.arp.REQUEST:
             if ipDest in self.tabellaC.keys(
             ):  #trovato destinatario nella tabella, rispondi direttamente con arp reply
                 arp_reply = pkt.arp()
                 coppia = self.tabellaC[
                     ipDest]  #ottieni coppia (MAC, SWITCH) del destinatario
                 macDest = coppia[0]  #prendi MAC del destinatario
                 arp_reply.hwsrc = EthAddr(macDest)
                 arp_reply.hwdst = EthAddr(macSource)
                 arp_reply.opcode = pkt.arp.REPLY
                 arp_reply.protosrc = IPAddr(ipDest)
                 arp_reply.protodst = IPAddr(ipSource)
                 ether = pkt.ethernet()
                 ether.type = pkt.ethernet.ARP_TYPE
                 ether.src = EthAddr(macDest)
                 ether.dst = EthAddr(macSource)
                 ether.payload = arp_reply
                 self.sendPacketToDPID(ether, dpid)
             else:  #non c'e in tabella manda una arp request a tutti gli switch
                 arp_request = pkt.arp()
                 arp_request.hwsrc = EthAddr(macSource)
                 arp_request.opcode = pkt.arp.REQUEST
                 arp_request.protosrc = IPAddr(ipSource)
                 arp_request.protodst = IPAddr(ipDest)
                 ether = pkt.ethernet()
                 ether.type = pkt.ethernet.ARP_TYPE
                 ether.src = EthAddr(macSource)
                 ether.dst = pkt.ETHER_BROADCAST
                 ether.payload = arp_request
                 self.sendPacketAll(ether)
         else:  # e' una arp reply, viene inoltrata al destinatario
             arp_reply = pkt.arp()
             coppia = self.tabellaC[
                 ipDest]  #ottieni coppia (MAC, SWITCH) del destinatario
             macDest = coppia[0]  #prendi MAC del destinatario
             arp_reply.hwsrc = EthAddr(macDest)
             arp_reply.hwdst = EthAddr(macSource)
             arp_reply.opcode = pkt.arp.REPLY
             arp_reply.protosrc = IPAddr(ipDest)
             arp_reply.protodst = IPAddr(ipSource)
             ether = pkt.ethernet()
             ether.type = pkt.ethernet.ARP_TYPE
             ether.src = EthAddr(macDest)
             ether.dst = EthAddr(macSource)
             ether.payload = arp_reply
             self.sendPacketToDPID(ether, coppia[1])
     #il pacchetto non e' un ARP
     else:
         #prende le info dal pacchetto
         ipDest = str(packet.payload.dstip)
         ipSrc = str(packet.payload.srcip)
         coppia_dst = self.tabellaC[
             ipDest]  #ottieni lo coppia (MAC, DPID) del destinatario
         dpid_dst = coppia_dst[
             1]  #ottieni il dpid dello switch destinatario
         mac_dst = coppia_dst[0]
         coppia_src = self.tabellaC[ipSrc]
         mac_src = coppia_src[0]
         #calcola il percorso per la destinazione con dijkstra
         percorso = self.dijkstra(dpid, dpid_dst)
         #avvia l'installazione negli switch del percorso
         self.avvia_instal(percorso, ipDest, ipSrc)
         #riesegui il procedimento, ma sul percorso inverso
         percorso.reverse()
         self.avvia_instal(percorso, ipSrc, ipDest)
         print percorso
         #dato che si conosce il dpid destinatario, inoltra direttamente il pacchetto, senza passare per la rete
         self.sendPacketToDPID(packet, dpid_dst)
Exemplo n.º 60
0
    def _handle_PacketIn(self, event):
        dpid = self.connection.dpid
        log.debug('-' * 50 + "dpid=" + str(dpid) + '-' * 50)
        log.debug("A PacketIn Message Recieved")
        packet = event.parsed

        # arp
        if packet.type == ethernet.ARP_TYPE:
            log.debug('---It\'s an arp packet')
            arppacket = packet.payload
            # arp回应
            if arppacket.opcode == arp.REPLY:
                arpTable[self.connection.dpid][event.ofp.in_port][
                    arppacket.protosrc] = arppacket.hwsrc
                arpTable[self.connection.dpid][event.ofp.in_port][
                    arppacket.protodst] = arppacket.hwdst
                # 更新后的arp表
                log.debug('------arpTable learned form arp Reply srt and dst')
                log.debug('------' + str(arpTable))

            # arp请求
            if arppacket.opcode == arp.REQUEST:
                log.debug('------Arp request')
                log.debug('------' + arppacket._to_str())
                arpTable[self.connection.dpid][event.ofp.in_port][
                    arppacket.protosrc] = arppacket.hwsrc
                # 更新后的arp表
                log.debug('------arpTable learned form arp Request srt')
                log.debug('------' + str(arpTable))

                # 发送arp回应
                if arppacket.protodst in arpTable[self.connection.dpid][
                        event.ofp.in_port]:
                    log.debug('------I know that ip %s,send reply' %
                              arppacket.protodst)

                    #构造arp回应
                    a = arppacket
                    r = arp()
                    r.hwtype = a.hwtype
                    r.prototype = a.prototype
                    r.hwlen = a.hwlen
                    r.protolen = a.protolen
                    r.opcode = arp.REPLY
                    r.hwdst = a.hwsrc
                    r.protodst = a.protosrc
                    r.protosrc = a.protodst
                    r.hwsrc = arpTable[self.connection.dpid][
                        event.ofp.in_port][arppacket.protodst]
                    e = ethernet(type=packet.type, src=r.hwsrc, dst=a.hwsrc)
                    e.set_payload(r)
                    msg = of.ofp_packet_out()
                    msg.data = e.pack()
                    msg.actions.append(
                        of.ofp_action_output(port=event.ofp.in_port))
                    self.connection.send(msg)

        # ip包
        if packet.type == ethernet.IP_TYPE:
            log.debug('---It\'s an ip packet')
            ippacket = packet.payload
            # 目的ip
            dstip = ippacket.dstip

            # 查找端口映射表,判断目的ip是否为路由器本身,回应icmp echo reply
            for t in portTable[dpid]:
                selfip = t[pPORT_IP]
                # 如果目的ip地址为当前路由器拥有的地址
                if dstip == selfip:
                    #如果是icmp echo request报文
                    if ippacket.protocol == ipv4.ICMP_PROTOCOL:
                        log.debug('!!!!!!!!!!An icmp for me!!!!!!!!!!!')
                        icmppacket = ippacket.payload
                        #是否为icmp echo request
                        if icmppacket.type == TYPE_ECHO_REQUEST:
                            selfmac = t[pPORT_MAC]
                            log.debug(
                                '!!!!!!!!!!An icmp echo request for me!!!!!!!!!!!'
                            )

                            # 构造icmp包
                            r = icmppacket
                            r.type = TYPE_ECHO_REPLY

                            #构造ip包
                            s = ipv4()
                            s.protocol = ipv4.ICMP_PROTOCOL
                            s.srcip = selfip
                            s.dstip = ippacket.srcip
                            s.payload = r

                            #构造以太网帧
                            e = ethernet()
                            e.type = ethernet.IP_TYPE
                            e.src = selfmac
                            e.dst = packet.src
                            e.payload = s

                            # 构造PacketOut消息
                            # 回发icmp包
                            msg = of.ofp_packet_out()
                            msg.data = e.pack()
                            msg.actions.append(
                                of.ofp_action_output(port=event.port))
                            self.connection.send(msg)
                            log.debug('!!!!!!!!!!Reply it!!!!!!!!!!!')
                            return
                        else:
                            #对发往路由器的icmp包,除了icmp echo request之外,均不理会
                            return
                    #发往路由器的非icmp包
                    else:
                        #直接丢包,这里控制器暂时不做回应
                        return

            # 搜索路由表
            for t in self.routeTable:
                # 路由表项中的网络前缀
                dstnetwork = t[rDST_NETWORK]
                # 如果目的ip在路由表中
                if dstip.inNetwork(dstnetwork):
                    log.debug('------ip dst %s is in the routeTable' % dstip)

                    # 找到对应的下一跳信息
                    nh_port = t[rNEXTHOP_PORT]
                    if nh_port == event.ofp.in_port:
                        return  # 应该下达丢包动作
                    nh_ip = IPAddr(t[rNEXTHOP_IP])
                    # 直接交付
                    if nh_ip == IPAddr('0.0.0.0'):
                        nh_ip = dstip
                    nh_port_ip = IPAddr(t[rNEXTHOP_PORT_IP])

                    # 查找arp表
                    nh_mac_src = arpTable[dpid][nh_port][nh_port_ip]

                    # 若下一跳目的主机的mac已知,添加流表
                    if nh_ip in arpTable[dpid][nh_port]:
                        log.debug('------I know the next dst %s mac' % nh_ip)
                        nh_mac_dst = arpTable[dpid][nh_port][nh_ip]

                        # 下发流表
                        msg1 = of.ofp_flow_mod()
                        # 匹配
                        msg1.match = of.ofp_match()
                        msg1.match.dl_type = ethernet.IP_TYPE
                        msg1.match.nw_dst = dstip
                        # Flow actions
                        msg1.command = 0
                        msg1.idle_timeout = 10
                        msg1.hard_timeout = 30
                        msg1.buffer_id = event.ofp.buffer_id
                        msg1.flags = 3  # of.ofp_flow_mod_flags_rev_map('OFPFF_CHECK_OVERLAP') | of.ofp_flow_mod_flags_rev_map('OFPFF_CHECK_OVERLAP')
                        msg1.actions.append(
                            of.ofp_action_dl_addr.set_src(nh_mac_src))
                        msg1.actions.append(
                            of.ofp_action_dl_addr.set_dst(nh_mac_dst))
                        msg1.actions.append(of.ofp_action_output(port=nh_port))
                        self.connection.send(msg1)
                        log.debug('###Add a flow###')

                    # 若下一跳目的主机的mac未知,发送arp请求,并广播ip包
                    else:
                        log.debug(
                            '------I don\'t know the next dst %s mac,make an arp request'
                            % IPAddr(t[rNEXTHOP_IP]))
                        # 构造arp请求
                        r = arp()
                        r.opcode = arp.REQUEST
                        r.protosrc = nh_port_ip
                        r.hwsrc = nh_mac_src
                        r.protodst = nh_ip
                        e_arp = ethernet(type=ethernet.ARP_TYPE,
                                         src=r.hwsrc,
                                         dst=ETHER_BROADCAST)
                        e_arp.set_payload(r)
                        msg = of.ofp_packet_out()
                        msg.data = e_arp.pack()
                        msg.actions.append(of.ofp_action_output(port=nh_port))
                        msg.in_port = event.ofp.in_port
                        event.connection.send(msg)

                        # 广播ip包,不下发流表
                        nh_mac_dst = ETHER_BROADCAST
                        msg1 = of.ofp_packet_out()
                        msg1.in_port = event.port
                        msg1.buffer_id = event.ofp.buffer_id
                        msg1.actions.append(
                            of.ofp_action_dl_addr.set_src(nh_mac_src))
                        msg1.actions.append(
                            of.ofp_action_dl_addr.set_dst(nh_mac_dst))
                        msg1.actions.append(of.ofp_action_output(port=nh_port))
                        self.connection.send(msg1)

                    return

            # 在路由表中未找到匹配项,发送icmp网络不可达报文
            r = icmp()
            r.type = TYPE_DEST_UNREACH
            r.code = CODE_UNREACH_NET
            d = ippacket.pack()[:ippacket.iplen + 8]
            import struct
            d = struct.pack("!I", 0) + d  #不可达报文的unused字段,也包含在icmp的payload中
            #这里大写的I代表4字节无符号整形,0代表数值,
            # struct.pack("!I", 0)的返回值是4个字节的0,正好填在不可达报文未用字段
            r.payload = d
            s = ipv4()
            s.protocol = ipv4.ICMP_PROTOCOL
            for t in portTable[dpid]:
                selfip = t[pPORT_IP]
                if (event.port == t[pPORT]):
                    s.srcip = selfip
                    break
            s.dstip = ippacket.srcip
            s.payload = r
            e = ethernet()
            e.type = ethernet.IP_TYPE
            e.src = packet.dst
            e.dst = packet.src
            e.payload = s

            # 构造PacketOut消息
            # 回发icmp包
            msg = of.ofp_packet_out()
            msg.data = e.pack()
            msg.actions.append(of.ofp_action_output(port=event.port))
            self.connection.send(msg)