コード例 #1
0
ファイル: psik_ctrl.py プロジェクト: ups100/PSIK
    def _do_dns_packet(self, packet, event):
        dnsp = packet.find('dns')

        if len(dnsp.questions) > 1:
            self._drop(packet, event.ofp.buffer_id, event.port)
            return

        question = dnsp.questions[0]
        response = None
        log.debug("Question: %s" % (question.name))
        if question.qtype == dns.rr.A_TYPE and question.name == self.service_name:
            # Some one is asking about our service so let's
            # choose one of data centers and answer him
            dc_ip = self._choose_server()
            response = dns.rr(question.name, question.qtype, question.qclass,
                              0, 4, dc_ip)
        elif question.qtype == dns.rr.PTR_TYPE:
            # for now we assume that only our dns is resolvable
            response = dns.rr(question.name, question.qtype, question.qclass,
                                  0, len(self.service_name), self.service_name)
        else:
            self._drop(packet, event.ofp.buffer_id, event.port)
            return

        self._send_dns_response_packet(packet, dnsp, question, response, event.port)
コード例 #2
0
ファイル: dns_responder.py プロジェクト: twzhu/sigcomm2013
 def _answer_A (self, q):
   if not q.name.endswith('.local'):
     log.info('ignoring question: %s' % q)
     return None, None
   name = q.name[:-len('.local')]
   for node in core.Outband.t.nodes:
     if (node.name.lower() == name.lower()):
       # TODO multiple addresses in the response?
       port = node.ports[max(node.ports)]
       log.info('answering: %s %s' % (q.name, port.ip))
       ttl = 120 # 2 minutes
       addr = IPAddr(port.ip).toRaw() # byte-order ???
       r = pkt_dns.rr(q.name, q.qtype, q.qclass, ttl, 4, addr)
       return port, r
   return None, None
コード例 #3
0
ファイル: dns_responder.py プロジェクト: nemethf/sigcomm2013
 def _answer_A (self, q):
   if not q.name.endswith('.local'):
     log.info('ignoring question: %s' % q)
     return None, None
   name = q.name[:-len('.local')]
   for node in core.Outband.t.nodes:
     if (node.name.lower() == name.lower()):
       # TODO multiple addresses in the response?
       port = node.ports[max(node.ports)]
       log.info('answering: %s %s' % (q.name, port.ip))
       ttl = 120 # 2 minutes
       addr = IPAddr(port.ip).toRaw() # byte-order ???
       r = pkt_dns.rr(q.name, q.qtype, q.qclass, ttl, 4, addr)
       return port, r
   return None, None
コード例 #4
0
ファイル: dns_responder.py プロジェクト: twzhu/sigcomm2013
 def _answer_PTR (self, q):
   if not q.name.endswith('.in-addr.arpa'):
     log.info('ignoring question: %s' % q)
     return None, None
   name = q.name[:-len('.in-addr.arpa')]
   ip = name.split('.')
   ip.reverse()
   ip = '.'.join(ip)
   node, port = core.Outband.t.ip_and_port(ip)
   if not node:
     return None, None
   log.info('answering: %s %s' % (q.name, node.name))
   ttl = 120 # 2 minutes
   domain = putName('', node.name + '.local')
   domain = domain.encode('ascii', 'ignore')
   r = pkt_dns.rr(q.name, q.qtype, q.qclass, ttl, len(domain), domain)
   return port, r
コード例 #5
0
ファイル: dns_responder.py プロジェクト: nemethf/sigcomm2013
 def _answer_PTR (self, q):
   if not q.name.endswith('.in-addr.arpa'):
     log.info('ignoring question: %s' % q)
     return None, None
   name = q.name[:-len('.in-addr.arpa')]
   ip = name.split('.')
   ip.reverse()
   ip = '.'.join(ip)
   node, port = core.Outband.t.ip_and_port(ip)
   if not node:
     return None, None
   log.info('answering: %s %s' % (q.name, node.name))
   ttl = 120 # 2 minutes
   domain = putName('', node.name + '.local')
   domain = domain.encode('ascii', 'ignore')
   r = pkt_dns.rr(q.name, q.qtype, q.qclass, ttl, len(domain), domain)
   return port, r
コード例 #6
0
    def _handle_PacketIn(self, event):
        dpid = event.connection.dpid

        inport = event.port
        packet = copy.deepcopy(event.parsed)
        if not packet.parsed:
            log.warning("%i %i ignoring unparsed packet", dpid, inport)
            return

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

        # store the mac, ip info of the DNS SERVER into arpTable
        self.arpTable[dpid][IPAddr(IP_OF_DNS_SERVER)] = Entry(
            6633, EthAddr(MAC_OF_DNS_SERVER))

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

        p = packet.find('dns')

        if p is not None and p.parsed:

            # Get dstName of the DNS Query
            dstname = ''
            for question in p.questions:
                dstname = question.name

            log.debug("DNS Query msg from %s: asking ip address for %s",
                      packet.next.srcip, dstname)

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

            # generate random virtual ip for internal node
            n = random.randint(128, 254)
            vip = "10.0.0." + str(n)
            #add the srcip and virtual destination ip pair into srcip_dstip_map
            self.srcip_dstvip_map[str(packet.next.srcip)] = vip
            # forming answer
            answer = dns.rr(dstname, 1, 1, 5, len(vip), IPAddr(vip))
            # write dns reply msg
            d = dns()
            d.questions = p.questions
            d.answers.append(answer)
            d.authorities = []
            d.additional = []

            d.id = p.id
            d.qr = True  # dns reply
            d.opcode = 0  # standard
            d.aa = False
            d.tc = False
            d.rd = False
            d.ra = False
            d.z = False
            d.ad = False
            d.cd = False
            d.rcode = 0

            e = ethernet(type=ethernet.IP_TYPE,
                         src=MAC_OF_DNS_SERVER,
                         dst=str(packet.src))
            ip = ipv4(srcip=IPAddr(IP_OF_DNS_SERVER))
            ip.dstip = packet.next.srcip
            ip.protocol = ip.UDP_PROTOCOL
            u = udp()
            u.srcport = dns.SERVER_PORT
            # get srcport from the packet and set it to the udp's dstport
            m = packet.find("udp")
            m.parsed
            u.dstport = m.srcport
            u.payload = d
            ip.payload = u
            e.payload = ip

            msg = of.ofp_packet_out()
            msg.data = e.pack()
            msg.actions.append(of.ofp_action_nw_addr.set_dst(
                packet.next.srcip))
            msg.actions.append(of.ofp_action_dl_addr.set_dst(packet.src))
            msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT))
            msg.in_port = inport
            event.connection.send(msg)
            log.debug(
                " DNS reply msg has been sent to %s: %s's ip address is %s" %
                (str(packet.next.srcip), dstname, vip))

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

            # Send any waiting packets...
            self._send_lost_buffers(dpid, packet.next.srcip, packet.src,
                                    inport)
            print "Have sent lost buffers"

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

            srcaddr = packet.next.srcip
            dstaddr = packet.next.dstip

            if (dstaddr in self.vipList):
                self.srcip_dstvip_map[srcaddr] = dstaddr
                dstaddr = IPAddr(REAL_IP_OF_INTERNAL_HOST)

            if dstaddr in self.arpTable[dpid]:
                # We have info about what port to send it out on...
                prt = self.arpTable[dpid][dstaddr].port
                mac = self.arpTable[dpid][dstaddr].mac

                # Try to forward
                icmpmsg = packet.find("icmp")
                icmpmsg.parsed

                # icmp echo reply from internal host
                if icmpmsg.type == 0 and srcaddr == IPAddr(
                        REAL_IP_OF_INTERNAL_HOST):
                    log.info("ICMP echo reply msg from %s to %s", srcaddr,
                             packet.next.dstip)

                    if prt == inport:
                        log.warning(
                            "%i %i not sending packet for %s back out of the "
                            + "input port" % (dpid, inport, str(dstaddr)))
                    else:
                        log.debug(
                            "%i %i installing flow for %s => %s out port %i" %
                            (dpid, inport, packet.next.srcip, dstaddr, prt))

                    # add flow entry
                    msg = of.ofp_flow_mod(command=of.OFPFC_ADD)
                    msg.match.dl_type = 0x0800  #ipv4
                    msg.match.nw_src = REAL_IP_OF_INTERNAL_HOST
                    msg.match.nw_dst = dstaddr

                    # change the srcip to virtual ip
                    msg.actions.append(
                        of.ofp_action_nw_addr.set_src(
                            IPAddr(self.srcip_dstvip_map[dstaddr])))
                    msg.actions.append(of.ofp_action_dl_addr.set_dst(mac))
                    msg.actions.append(of.ofp_action_output(port=prt))

                    event.connection.send(msg)
                    log.info(
                        "ICMP echo reply flow entry for internal node to %s has been installed",
                        packet.next.dstip)

                # icmp echo reply for internal host
                elif icmpmsg.type == 8 and dstaddr == IPAddr(
                        REAL_IP_OF_INTERNAL_HOST):
                    log.info("ICMP echo request msg from %s to %s",
                             packet.next.srcip, packet.next.dstip)

                    if prt == inport:
                        log.warning(
                            "%i %i not sending packet for %s back out of the "
                            + "input port" % (dpid, inport, str(dstaddr)))
                    else:
                        log.debug(
                            "%i %i installing flow for %s => %s out port %i" %
                            (dpid, inport, packet.next.srcip, dstaddr, prt))

                    msg = of.ofp_flow_mod(command=of.OFPFC_ADD)
                    msg.match.dl_type = 0x0800  #ipv4 msg
                    msg.match.in_port = inport
                    msg.match.nw_dst = "10.0.0.128/255.255.255.128"
                    msg.actions.append(of.ofp_action_nw_addr.set_dst(dstaddr))
                    msg.actions.append(of.ofp_action_output(port=prt))
                    msg.actions.append(of.ofp_action_dl_addr.set_dst(mac))
                    event.connection.send(msg)
                    log.info(
                        "ICMP echo request flow entry for %s to internal host has been instaled",
                        packet.next.srcip)

                else:
                    log.warning("Uninvolved icmp msg type")
                    return

            elif self.arp_for_unknowns:
                # We don't know this destination.
                # First, we track this buffer so that we can try to resend it later
                # if we learn the destination, second we ARP for the destination,
                # which should ultimately result in it responding and us learning
                # where it is

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

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

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

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

                r = arp()
                r.hwtype = r.HW_TYPE_ETHERNET
                r.prototype = r.PROTO_TYPE_IP
                r.hwlen = 6
                r.protolen = r.protolen
                r.opcode = r.REQUEST
                r.hwdst = ETHER_BROADCAST

                if dstaddr in self.vipList:
                    r.protodst = IPAddr(REAL_IP_OF_INTERNAL_HOST)
                else:
                    r.protodst = dstaddr

                r.hwsrc = packet.src
                r.protosrc = packet.next.srcip
                e = ethernet(type=ethernet.ARP_TYPE,
                             src=packet.src,
                             dst=ETHER_BROADCAST)
                e.set_payload(r)
                log.debug("%i %i ARPing for %s on behalf of %s for Ipv4" %
                          (dpid, inport, str(r.protodst), str(r.protosrc)))
                msg = of.ofp_packet_out()
                msg.data = e.pack()
                msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
                msg.in_port = inport
                event.connection.send(msg)

        elif isinstance(packet.next, arp):

            a = packet.next

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

            if a.protodst in self.vipList:
                self.srcip_dstvip_map[a.protosrc] = str(a.protodst)
                a.protodst = REAL_IP_OF_INTERNAL_HOST

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

            if a.prototype == arp.PROTO_TYPE_IP:

                if a.hwtype == arp.HW_TYPE_ETHERNET:

                    if a.protosrc != 0:

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

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

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

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

                            if a.protodst in self.vipList:
                                self.srcip_dstvip_map[a.protosrc] = str(
                                    a.protodst)
                                a.protodst = IPAddr(REAL_IP_OF_INTERNAL_HOST)

                            if a.protodst in self.arpTable[dpid]:
                                # We have an answer...

                                if not self.arpTable[dpid][
                                        a.protodst].isExpired():
                                    # .. and it's relatively current, so we'll reply ourselves

                                    r = arp()
                                    r.hwtype = a.hwtype
                                    r.prototype = a.prototype
                                    r.hwlen = a.hwlen
                                    r.protolen = a.protolen
                                    r.opcode = arp.REPLY
                                    r.hwdst = a.hwsrc
                                    r.hwsrc = self.arpTable[dpid][
                                        a.protodst].mac
                                    r.protodst = a.protosrc
                                    if a.protodst == IPAddr(
                                            REAL_IP_OF_INTERNAL_HOST):
                                        r.protosrc = IPAddr(
                                            self.srcip_dstvip_map[a.protosrc])
                                    else:
                                        r.protosrc = a.protodst

                                    e = ethernet(type=packet.type,
                                                 src=dpid_to_mac(dpid),
                                                 dst=a.hwsrc)
                                    e.set_payload(r)
                                    log.debug("%i %i answering ARP for %s" %
                                              (dpid, inport, str(r.protosrc)))
                                    msg = of.ofp_packet_out()
                                    msg.data = e.pack()
                                    msg.actions.append(
                                        of.ofp_action_output(
                                            port=of.OFPP_IN_PORT))
                                    msg.in_port = inport
                                    event.connection.send(msg)
                                    return

            # Didn't know how to answer or otherwise handle this ARP, so just flood it
                            log.debug("%i %i flooding ARP %s %s => %s" %
                                      (dpid, inport, {
                                          arp.REQUEST: "request",
                                          arp.REPLY: "reply"
                                      }.get(a.opcode, 'op:%i' % (a.opcode, )),
                                       str(a.protosrc), str(a.protodst)))
                            r1 = arp()
                            r1.hwtype = a.HW_TYPE_ETHERNET
                            r1.prototype = a.PROTO_TYPE_IP
                            r1.hwlen = 6
                            r1.protolen = a.protolen
                            r1.opcode = arp.REQUEST
                            r1.hwdst = ETHER_BROADCAST
                            r1.protodst = IPAddr(a.protodst)
                            r1.hwsrc = a.hwsrc
                            r1.protosrc = a.protosrc
                            e1 = ethernet(type=ethernet.ARP_TYPE,
                                          src=a.hwsrc,
                                          dst=ETHER_BROADCAST)
                            e1.set_payload(r1)
                            log.debug("%i %i ARPing for %s on behalf of %s" %
                                      (dpid, inport, str(
                                          r1.protodst), str(r1.protosrc)))
                            msg1 = of.ofp_packet_out()
                            msg1.data = e1.pack()
                            msg1.actions.append(
                                of.ofp_action_output(port=of.OFPP_FLOOD))
                            msg1.in_port = inport
                            event.connection.send(msg1)
コード例 #7
0
  def _handle_PacketIn (self, event):
    dpid = event.connection.dpid

    inport = event.port
    packet = copy.deepcopy(event.parsed)
    if not packet.parsed:
      log.warning("%i %i ignoring unparsed packet", dpid, inport)
      return

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

    # store the mac, ip info of the DNS SERVER into arpTable
    self.arpTable[dpid][IPAddr(IP_OF_DNS_SERVER)]=Entry(6633, EthAddr(MAC_OF_DNS_SERVER))

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

    p = packet.find('dns')

    if p is not None and p.parsed:

      # Get dstName of the DNS Query
      dstname = '';
      for question in p.questions:
          dstname = question.name

      log.debug("DNS Query msg from %s: asking ip address for %s", packet.next.srcip, dstname)

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

      # generate random virtual ip for internal node
      n = random.randint(128, 254)
      vip = "10.0.0." + str(n)
      #add the srcip and virtual destination ip pair into srcip_dstip_map
      self.srcip_dstvip_map[str(packet.next.srcip)] = vip
      # forming answer
      answer = dns.rr(dstname, 1, 1, 5, len(vip), IPAddr(vip))
      # write dns reply msg
      d = dns()
      d.questions = p.questions
      d.answers.append(answer)
      d.authorities = []
      d.additional =[]

      d.id = p.id
      d.qr = True # dns reply
      d.opcode = 0 # standard
      d.aa = False
      d.tc = False
      d.rd = False
      d.ra = False
      d.z = False
      d.ad = False
      d.cd = False
      d.rcode = 0

      e = ethernet(type=ethernet.IP_TYPE, src=MAC_OF_DNS_SERVER, dst=str(packet.src))
      ip = ipv4(srcip = IPAddr(IP_OF_DNS_SERVER))
      ip.dstip = packet.next.srcip
      ip.protocol = ip.UDP_PROTOCOL
      u = udp()
      u.srcport = dns.SERVER_PORT
      # get srcport from the packet and set it to the udp's dstport
      m = packet.find("udp")
      m.parsed
      u.dstport = m.srcport
      u.payload = d
      ip.payload = u
      e.payload = ip

      msg = of.ofp_packet_out()
      msg.data = e.pack()
      msg.actions.append(of.ofp_action_nw_addr.set_dst(packet.next.srcip))
      msg.actions.append(of.ofp_action_dl_addr.set_dst(packet.src))
      msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
      msg.in_port = inport
      event.connection.send(msg)
      log.debug(" DNS reply msg has been sent to %s: %s's ip address is %s" % (str(packet.next.srcip), dstname, vip))

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

      # Send any waiting packets...
      self._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport)
      print "Have sent lost buffers"

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

      srcaddr = packet.next.srcip
      dstaddr = packet.next.dstip

      if(dstaddr in self.vipList):
         self.srcip_dstvip_map[srcaddr] = dstaddr
         dstaddr = IPAddr(REAL_IP_OF_INTERNAL_HOST)

      if dstaddr in self.arpTable[dpid]:
         # We have info about what port to send it out on...
         prt = self.arpTable[dpid][dstaddr].port
         mac = self.arpTable[dpid][dstaddr].mac

         # Try to forward
         icmpmsg = packet.find("icmp")
         icmpmsg.parsed

         # icmp echo reply from internal host
         if icmpmsg.type == 0 and srcaddr == IPAddr(REAL_IP_OF_INTERNAL_HOST):   
           log.info("ICMP echo reply msg from %s to %s", srcaddr, packet.next.dstip)

           if prt == inport:
               log.warning("%i %i not sending packet for %s back out of the " +
                         "input port" % (dpid, inport, str(dstaddr)))
           else:
               log.debug("%i %i installing flow for %s => %s out port %i"
                       % (dpid, inport, packet.next.srcip, dstaddr, prt))

           # add flow entry
           msg = of.ofp_flow_mod(command = of.OFPFC_ADD)
           msg.match.dl_type = 0x0800 #ipv4
           msg.match.nw_src = REAL_IP_OF_INTERNAL_HOST
           msg.match.nw_dst = dstaddr

           # change the srcip to virtual ip
           msg.actions.append(of.ofp_action_nw_addr.set_src(IPAddr(self.srcip_dstvip_map[dstaddr])))
           msg.actions.append(of.ofp_action_dl_addr.set_dst(mac))
           msg.actions.append(of.ofp_action_output(port = prt))

           event.connection.send(msg)
           log.info("ICMP echo reply flow entry for internal node to %s has been installed", packet.next.dstip)

         # icmp echo reply for internal host
         elif icmpmsg.type == 8 and dstaddr == IPAddr(REAL_IP_OF_INTERNAL_HOST):
           log.info("ICMP echo request msg from %s to %s", packet.next.srcip, packet.next.dstip)

           if prt == inport:
              log.warning("%i %i not sending packet for %s back out of the " +
                         "input port" % (dpid, inport, str(dstaddr)))
           else:
              log.debug("%i %i installing flow for %s => %s out port %i"
                      % (dpid, inport, packet.next.srcip, dstaddr, prt))

           msg = of.ofp_flow_mod(command = of.OFPFC_ADD)
           msg.match.dl_type = 0x0800 #ipv4 msg
           msg.match.in_port = inport
           msg.match.nw_dst = "10.0.0.128/255.255.255.128"
           msg.actions.append(of.ofp_action_nw_addr.set_dst(dstaddr))
           msg.actions.append(of.ofp_action_output(port = prt))
           msg.actions.append(of.ofp_action_dl_addr.set_dst(mac))
           event.connection.send(msg)
           log.info("ICMP echo request flow entry for %s to internal host has been instaled", packet.next.srcip)

         else:
           log.warning("Uninvolved icmp msg type")
           return

      elif self.arp_for_unknowns:
        # We don't know this destination.
        # First, we track this buffer so that we can try to resend it later
        # if we learn the destination, second we ARP for the destination,
        # which should ultimately result in it responding and us learning
        # where it is

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

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

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

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

        r = arp()
        r.hwtype = r.HW_TYPE_ETHERNET
        r.prototype = r.PROTO_TYPE_IP
        r.hwlen = 6
        r.protolen = r.protolen
        r.opcode = r.REQUEST
        r.hwdst = ETHER_BROADCAST

        if dstaddr in self.vipList:
             r.protodst = IPAddr(REAL_IP_OF_INTERNAL_HOST)
        else:
             r.protodst = dstaddr

        r.hwsrc = packet.src
        r.protosrc = packet.next.srcip
        e = ethernet(type=ethernet.ARP_TYPE, src=packet.src,
                     dst=ETHER_BROADCAST)
        e.set_payload(r)
        log.debug("%i %i ARPing for %s on behalf of %s for Ipv4" % (dpid, inport, str(r.protodst), str(r.protosrc)))
        msg = of.ofp_packet_out()
        msg.data = e.pack()
        msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
        msg.in_port = inport
        event.connection.send(msg)

    elif isinstance(packet.next, arp):

      a = packet.next

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

      if a.protodst in self.vipList:
         self.srcip_dstvip_map[a.protosrc] = str(a.protodst)
         a.protodst = REAL_IP_OF_INTERNAL_HOST

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

      if a.prototype == arp.PROTO_TYPE_IP:

        if a.hwtype == arp.HW_TYPE_ETHERNET:

          if a.protosrc != 0:

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

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

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

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

              if a.protodst in self.vipList:
                   self.srcip_dstvip_map[a.protosrc] = str(a.protodst)
                   a.protodst = IPAddr(REAL_IP_OF_INTERNAL_HOST)

              if a.protodst in self.arpTable[dpid]:
                # We have an answer...

                if not self.arpTable[dpid][a.protodst].isExpired():
                  # .. and it's relatively current, so we'll reply ourselves

                  r = arp()
                  r.hwtype = a.hwtype
                  r.prototype = a.prototype
                  r.hwlen = a.hwlen
                  r.protolen = a.protolen
                  r.opcode = arp.REPLY
                  r.hwdst = a.hwsrc
                  r.hwsrc = self.arpTable[dpid][a.protodst].mac
                  r.protodst = a.protosrc
                  if a.protodst == IPAddr(REAL_IP_OF_INTERNAL_HOST):
                     r.protosrc = IPAddr(self.srcip_dstvip_map[a.protosrc])
                  else:
                     r.protosrc = a.protodst

                  e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwsrc)
                  e.set_payload(r)
                  log.debug("%i %i answering ARP for %s" % (dpid, inport,
                   str(r.protosrc)))
                  msg = of.ofp_packet_out()
                  msg.data = e.pack()
                  msg.actions.append(of.ofp_action_output(port =
                                                          of.OFPP_IN_PORT))
                  msg.in_port = inport
                  event.connection.send(msg)
                  return

      # Didn't know how to answer or otherwise handle this ARP, so just flood it
              log.debug("%i %i flooding ARP %s %s => %s" % (dpid, inport,
       {arp.REQUEST:"request",arp.REPLY:"reply"}.get(a.opcode,
       'op:%i' % (a.opcode,)), str(a.protosrc), str(a.protodst)))
              r1 = arp()
              r1.hwtype = a.HW_TYPE_ETHERNET
              r1.prototype = a.PROTO_TYPE_IP
              r1.hwlen = 6
              r1.protolen = a.protolen
              r1.opcode = arp.REQUEST
              r1.hwdst = ETHER_BROADCAST
              r1.protodst = IPAddr(a.protodst)
              r1.hwsrc = a.hwsrc
              r1.protosrc = a.protosrc
              e1 = ethernet(type=ethernet.ARP_TYPE, src=a.hwsrc, dst=ETHER_BROADCAST)
              e1.set_payload(r1)
              log.debug("%i %i ARPing for %s on behalf of %s" % (dpid, inport, str(r1.protodst), str(r1.protosrc)))
              msg1 = of.ofp_packet_out()
              msg1.data = e1.pack()
              msg1.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
              msg1.in_port = inport
              event.connection.send(msg1)