Example #1
0
 def arp_response(a):
     r = arp()
     r.hwtype = a.hwtype
     r.prototype = a.prototype
     r.hwlen = a.hwlen
     r.protolen = a.protolen
     r.opcode = arp.REPLY
     r.hwdst = a.hwsrc
     r.protodst = a.protosrc
     r.protosrc = a.protodst
     r.hwsrc = EthAddr('00:00:00:00:00:02')
     e = ethernet(type=packet.type,
                  src=EthAddr('00:00:00:00:00:02'),
                  dst=a.hwsrc)
     e.payload = r
     if packet.type == ethernet.VLAN_TYPE:
         v_rcv = packet.find('vlan')
         e.payload = vlan(eth_type=e.type,
                          payload=e.payload,
                          id=v_rcv.id,
                          pcp=v_rcv.pcp)
         e.type = ethernet.VLAN_TYPE
     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)
Example #2
0
    def forwardToAppropriateController(self, event):

        #        print "forwarding to controller : " + str(event)

        # Get list of controllers from VMOC Switch Controller MAP
        controller_conns = scmap.lookup_controllers_for_switch_connection(self)
        if not controller_conns:
            log.debug("No controller connection : dropping " + str(event))
            return

        if event.ofp.header_type == of.OFPT_PACKET_IN:
            # Send the event to the client controller associated with this slice
            # Based on VLAN
            ethernet_packet = ethernet(raw=event.ofp.data)
            dst = ethernet_packet.dst
            src = ethernet_packet.src
            vlan_id = None
            if ethernet_packet.type == ethernet.VLAN_TYPE:
                #                print "EVENT: " + str(event)
                vlan_data = event.ofp.data[ethernet.MIN_LEN:]
                vlan_packet = vlan(vlan_data)
                log.debug("VLAN PACKET : " + str(vlan_packet))
                vlan_id = vlan_packet.id

            # If the switch is a 'VLAN HYBRID',
            # we will not  get tagged packets but we can use the
            # VLAN asssociated with the port
            if not config.vmoc_set_vlan_on_untagged_flow_mod:
                port_info = config.vlan_port_map[str(self._port)]
                if not vlan_id and port_info and \
                        bool(port_info['handle_untagged']):
                    vlan_id = int(port_info['vlan'])

            matched_controller_conn = None
            for controller_conn in controller_conns:
                if controller_conn.belongsToSlice(vlan_id, src, dst):
                    matched_controller_conn = controller_conn
                    break
            if matched_controller_conn is not None:
                log.debug("Sending packet " + str(event) + " " +
                          str(ethernet_packet) + " " +
                          str(matched_controller_conn) + " " + str(vlan_id))
                try:
                    matched_controller_conn.send(event.ofp)
                except Exception as e:
                    log.debug(
                        "Error writing to controller connection: resetting %s"
                        % e)
                    matched_controller_conn.close()
            else:
                log.debug("Dropping packet : " + str(event) + " " +
                          str(ethernet_packet) + " " + str(vlan_id))
        else:
            # Send every non-packet message directly to each controller
            # And the controller connection will send back every response
            for controller_conn in controller_conns:
                #                log.debug("Sending to CC : " + str(event.ofp.header_type))
                controller_conn.send(event.ofp)
Example #3
0
    def forwardToAppropriateController(self, event):

#        print "forwarding to controller : " + str(event)
        

        # Get list of controllers from VMOC Switch Controller MAP
        controller_conns = scmap.lookup_controllers_for_switch_connection(self)
        if not controller_conns: 
            log.debug("No controller connection : dropping " + str(event))
            return

        if event.ofp.header_type == of.OFPT_PACKET_IN:
            # Send the event to the client controller associated with this slice
            # Based on VLAN
            ethernet_packet = ethernet(raw=event.ofp.data)
            dst=ethernet_packet.dst
            src=ethernet_packet.src
            vlan_id = None
            if ethernet_packet.type == ethernet.VLAN_TYPE:
#                print "EVENT: " + str(event)
                vlan_data = event.ofp.data[ethernet.MIN_LEN:]
                vlan_packet = vlan(vlan_data)
                log.debug("VLAN PACKET : " + str(vlan_packet))
                vlan_id = vlan_packet.id

            # If the switch is a 'VLAN HYBRID', 
            # we will not  get tagged packets but we can use the
            # VLAN asssociated with the port
            if not config.vmoc_set_vlan_on_untagged_flow_mod:
                port_info = config.vlan_port_map[str(self._port)]
                if not vlan_id and port_info and \
                        bool(port_info['handle_untagged']):
                    vlan_id = int(port_info['vlan'])

            matched_controller_conn = None
            for controller_conn in controller_conns:
                if controller_conn.belongsToSlice(vlan_id, src, dst):
                    matched_controller_conn = controller_conn
                    break
            if matched_controller_conn is not None:
                log.debug("Sending packet " + str(event) + " " + str(ethernet_packet) +  " " + str(matched_controller_conn) + " " + str(vlan_id))
                try:
                    matched_controller_conn.send(event.ofp)
                except Exception as e:
                    log.debug("Error writing to controller connection: resetting %s" % e)
                    matched_controller_conn.close()
            else:
                log.debug("Dropping packet : " + str(event) + " " + str(ethernet_packet) + " " + str(vlan_id))
        else:
            # Send every non-packet message directly to each controller
            # And the controller connection will send back every response
            for controller_conn in controller_conns:
#                log.debug("Sending to CC : " + str(event.ofp.header_type))
                controller_conn.send(event.ofp)
Example #4
0
def add_vlan_to_packet(ethernet_packet, vlan_id):
    # Grab the ethernet packet = E
    new_ethernet_packet = ethernet(ethernet_packet.raw)
    new_ethernet_packet.type = ethernet.VLAN_TYPE
    E = new_ethernet_packet.hdr('')
    # Create the vlan packet = V
    vlan_packet = vlan()
    vlan_packet.id = vlan_id
    vlan_packet.pcp = 0
    vlan_packet.eth_type = ethernet_packet.type
    V = vlan_packet.hdr('')
    # Grab the rest of the packet = R
    R = ethernet_packet.raw[ethernet.MIN_LEN:]
    # Construct E + V + R
    new_raw = E + V + R
    new_ethernet_packet = ethernet(new_raw)
    return new_ethernet_packet
Example #5
0
    def parsePacket(self, event):

        #
        data = event.ofp.data
        ethernet_packet = ethernet(raw=data)
        #        print str(ethernet_packet)
        if ethernet_packet.type != ethernet.VLAN_TYPE:
            log.debug("WEIRD: Got packet without VLAN")
            return data, ethernet_packet, None, None

        vlan_packet = vlan(raw=data[ethernet.MIN_LEN:])
        ethernet_packet.set_payload(vlan_packet)
        #        print str(vlan_packet)

        ip_packet = None
        if vlan_packet.eth_type == ethernet.ARP_TYPE:
            ip_packet = arp(raw=data[IP_START:])
            vlan_packet.set_payload(ip_packet)
        elif vlan_packet.eth_type == ethernet.IP_TYPE:
            ip_packet = ipv4(raw=data[IP_START:])
            vlan_packet.set_payload(ip_packet)
        elif vlan_packet.eth_type == ethernet.IPV6_TYPE:
            pass
        else:
            log.debug("GOT soemthing that wasn't expecting: " +
                      vlan_packet.eth_type)

        tcp_packet = None
        if ip_packet and vlan_packet.eth_type == ethernet.IP_TYPE:
            if ip_packet.protocol == ipv4.TCP_PROTOCOL:
                tcp_raw = ip_packet.raw[ipv4.MIN_LEN:]
                tcp_packet = tcp(raw=tcp_raw)
                ip_packet.set_payload(tcp_packet)
                payload = tcp_packet.payload


#                print "TCP = " + str(tcp_packet) + " PAYLOAD = " + payload
#            print str(ip_packet)
#            ip_packet.dump()
        return data, ethernet_packet, vlan_packet, ip_packet, tcp_packet
Example #6
0
    def parsePacket(self, event):

        # 
        data = event.ofp.data
        ethernet_packet = ethernet(raw=data)
#        print str(ethernet_packet)
        if ethernet_packet.type != ethernet.VLAN_TYPE:
            log.debug("WEIRD: Got packet without VLAN")
            return data, ethernet_packet, None, None

        vlan_packet = vlan(raw=data[ethernet.MIN_LEN:])
        ethernet_packet.set_payload(vlan_packet)
#        print str(vlan_packet)

        ip_packet = None
        if vlan_packet.eth_type == ethernet.ARP_TYPE:
            ip_packet = arp(raw=data[IP_START:])
            vlan_packet.set_payload(ip_packet)
        elif vlan_packet.eth_type == ethernet.IP_TYPE:
            ip_packet = ipv4(raw=data[IP_START:])
            vlan_packet.set_payload(ip_packet)
        elif vlan_packet.eth_type == ethernet.IPV6_TYPE:
            pass
        else:
            log.debug("GOT soemthing that wasn't expecting: " + vlan_packet.eth_type)

        tcp_packet = None
        if ip_packet and vlan_packet.eth_type == ethernet.IP_TYPE:
            if ip_packet.protocol == ipv4.TCP_PROTOCOL:
                tcp_raw = ip_packet.raw[ipv4.MIN_LEN:]
                tcp_packet = tcp(raw=tcp_raw)
                ip_packet.set_payload(tcp_packet)
                payload = tcp_packet.payload
#                print "TCP = " + str(tcp_packet) + " PAYLOAD = " + payload
#            print str(ip_packet)
#            ip_packet.dump()
        return data, ethernet_packet, vlan_packet, ip_packet, tcp_packet
Example #7
0
    def _handle_PacketIn(self, event):
        # Note: arp.hwsrc is not necessarily equal to ethernet.src
        # (one such example are arp replies generated by this module itself
        # as ethernet mac is set to switch dpid) so we should be careful
        # to use only arp addresses in the learning code!
        squelch = False

        dpid = event.connection.dpid
        inport = event.port
        packet = event.parsed
        if not packet.parsed:
            log.warning("%s: ignoring unparsed packet", dpid_to_str(dpid))
            return

        a = packet.find('arp')
        if not a: return

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

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

                    if _learn:
                        # Learn or update port/MAC info
                        if a.protosrc in _arp_table:
                            if _arp_table[a.protosrc] != a.hwsrc:
                                log.warn("%s RE-learned %s: %s->%s",
                                         dpid_to_str(dpid), a.protosrc,
                                         _arp_table[a.protosrc].mac, a.hwsrc)
                        else:
                            log.info("%s learned %s", dpid_to_str(dpid),
                                     a.protosrc)
                        _arp_table[a.protosrc] = Entry(a.hwsrc)

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

                        if a.protodst in _arp_table:
                            # We have an answer...

                            r = arp()
                            r.hwtype = a.hwtype
                            r.prototype = a.prototype
                            r.hwlen = a.hwlen
                            r.protolen = a.protolen
                            r.opcode = arp.REPLY
                            r.hwdst = a.hwsrc
                            r.protodst = a.protosrc
                            r.protosrc = a.protodst
                            mac = _arp_table[a.protodst].mac
                            if mac is True:
                                # Special case -- use ourself
                                mac = _dpid_to_mac(dpid)
                            r.hwsrc = mac
                            e = ethernet(type=packet.type,
                                         src=_dpid_to_mac(dpid),
                                         dst=a.hwsrc)
                            e.payload = r
                            if packet.type == ethernet.VLAN_TYPE:
                                v_rcv = packet.find('vlan')
                                e.payload = vlan(eth_type=e.type,
                                                 payload=e.payload,
                                                 id=v_rcv.id,
                                                 pcp=v_rcv.pcp)
                                e.type = ethernet.VLAN_TYPE
                            log.info("%s answering ARP for %s" %
                                     (dpid_to_str(dpid), str(r.protosrc)))
                            msg = of.ofp_packet_out()
                            msg.data = e.pack()
                            msg.actions.append(
                                of.ofp_action_output(port=of.OFPP_IN_PORT))
                            msg.in_port = inport
                            event.connection.send(msg)
                            return EventHalt if _eat_packets else None
                        else:
                            # Keep track of failed queries
                            squelch = a.protodst in _failed_queries
                            _failed_queries[a.protodst] = time.time()

        if self._check_for_flood(dpid, a):
            # Didn't know how to handle this ARP, so just flood it
            msg = "%s flooding ARP %s %s => %s" % (dpid_to_str(dpid), {
                arp.REQUEST: "request",
                arp.REPLY: "reply"
            }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, a.protodst)

            if squelch:
                log.debug(msg)
            else:
                log.info(msg)

            msg = of.ofp_packet_out()
            msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
            msg.data = event.ofp
            event.connection.send(msg.pack())

        return EventHalt if _eat_packets else None
Example #8
0
  def _handle_PacketIn (self, event):
    # Note: arp.hwsrc is not necessarily equal to ethernet.src
    # (one such example are arp replies generated by this module itself
    # as ethernet mac is set to switch dpid) so we should be careful
    # to use only arp addresses in the learning code!
    squelch = False
    # print _arp_table
    # core.openflow.addListeners(self, priority=3)
    dpid = event.connection.dpid
    inport = event.port
    packet = event.parsed
    if not packet.parsed:
      log.warning("%s: ignoring unparsed packet", dpid_to_str(dpid))
      return
    a = packet.find('arp')

    if not a: return

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

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

#           if _learn:
#             # Learn or update port/MAC info
#             if a.protosrc in _arp_table:
#               if _arp_table[a.protosrc] != a.hwsrc:
#                 log.warn("%s RE-learned %s: %s->%s", dpid_to_str(dpid),
#                     a.protosrc, _arp_table[a.protosrc].mac, a.hwsrc)
#             else:
#               log.info("%s learned %s", dpid_to_str(dpid), a.protosrc)
#             _arp_table[a.protosrc] = Entry(a.hwsrc)
#           print "PacketIn"
#           print _arp_table


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

            if a.protodst in _arp_table:
              # We have an answer...

              r = arp()
              r.hwtype = a.hwtype
              r.prototype = a.prototype
              r.hwlen = a.hwlen
              r.protolen = a.protolen
              r.opcode = arp.REPLY
              r.hwdst = a.hwsrc
              r.protodst = a.protosrc
              r.protosrc = a.protodst
              mac = _arp_table[a.protodst].mac
              if mac is True:
                # Special case -- use ourself
                mac = _dpid_to_mac(dpid)
              r.hwsrc = mac
              e = ethernet(type=packet.type, src=_dpid_to_mac(dpid),
                            dst=a.hwsrc)
              e.payload = r
              if packet.type == ethernet.VLAN_TYPE:
                v_rcv = packet.find('vlan')
                e.payload = vlan(eth_type = e.type,
                                 payload = e.payload,
                                 id = v_rcv.id,
                                 pcp = v_rcv.pcp)
                e.type = ethernet.VLAN_TYPE
              log.info("%s answering ARP for %s" % (dpid_to_str(dpid),
                str(r.protosrc)))
              msg = of.ofp_packet_out()
              msg.data = e.pack()
              msg.actions.append(of.ofp_action_output(port =
                                                      of.OFPP_IN_PORT))
              msg.in_port = inport
              event.connection.send(msg)
#               print "SUCCESS"
              return EventHalt if _eat_packets else None
            else:
              # Keep track of failed queries
              squelch = a.protodst in _failed_queries
              _failed_queries[a.protodst] = time.time()
    def validateMessage(self, ofp, switch):

        ofp_revised = None
        if ofp.header_type == of.OFPT_FLOW_MOD:

            # Need to narrow down between the sub-cases for FLOW MOD below
            # Check that the match is okay
            match = ofp.match
            
#           print "COMMAND = " + str(ofp.command) + " " + str(of.OFPFC_DELETE)
#            print "WC = " + str(match.wildcards) + " " + str(OFPFW_ALL)
            if ofp.command == of.OFPFC_DELETE and not match.dl_vlan:
                if not config.vmoc_accept_clear_all_flows_on_startup:
                    return None
                # Weird case of getting a 'clear all entries' at startup
#                print "OFP = " + str(ofp)
#                print "*** CASE 0 ***"
                return ofp
            elif match.dl_vlan == of.OFP_VLAN_NONE or not match.dl_vlan:
                if not config.vmoc_set_vlan_on_untagged_flow_mod:
                    return ofp
                # add in the tag to the match if not set
#                print "OFP = " + str(ofp)
#                print "MATCH = " + str(match)
                match.dl_vlan = self._vlan
#                print "MATCH = " + str(match)
#                print "MATCH.DL_VLAN = " + str(match.dl_vlan) + " " + str(of.OFP_VLAN_NONE)
#               print "*** CASE 1 ***"
#               
#               pdb.set_trace()
                return ofp 

            elif match.dl_vlan != self._vlan:
                return ofp # ***
                log.debug("Dropping FLOW MOD: match tagged with wrong VLAN : " + \
                              str(ofp) + " " + str(self))
#                print "*** CASE 2 ***"
#               pdb.set_trace()
                return None

            # Check that the actions are okay
            actions = ofp.actions
            for action in actions:
                if isinstance(action, ofp_action_vlan_vid) and action.vlan_vid != self._vlan:
                    log.debug("Dropping FLOW MOD: action to set wrong VLAN : " + \
                              str(ofp) + " " + str(self))
#                    print "*** CASE 3 ***"
#                    pdb.set_trace()
                    return None

            return ofp

        elif ofp.header_type == of.OFPT_PACKET_OUT:

            data = ofp.data
            ethernet_packet = ethernet(raw=data)
            # if packet has a VLAN, make sure it fits this connection
            if ethernet_packet.type == ethernet.VLAN_TYPE:
                vlan_packet = vlan(data[ethernet.MIN_LEN:])
                if  vlan_packet.id != self._vlan:
                    log.debug("Dropping PACKET OUT: wrong VLAN set : "  + 
                              str(vlan_packet) + " " + str(ofp) + " " + str(self))
#                    print "*** CASE 4 ***"
#                   pdb.set_trace()
                    return None
                else:
                    return ofp
            else: 
                if not config.vmoc_set_vlan_on_untagged_packet_out:
                    return ofp 
                # If not, set it
                orig_in_port = ofp.in_port
                new_ethernet_packet = add_vlan_to_packet(ethernet_packet, self._vlan)
                # Create a new ofp from the new data
                ofp_orig = ofp
                ofp = of.ofp_packet_out(data=new_ethernet_packet.raw)
                ofp.buffer_id = None
                ofp.in_port = orig_in_port
                ofp.actions = ofp_orig.actions
                ofp.xid = ofp_orig.xid
                log.debug("Adding vlan to PACKET_OUT : " +  \
                              str(ethernet_packet) + " " + str(new_ethernet_packet) + " " + \
                              str(ofp) + " " + str(self))
#                print str(ethernet_packet)
#                ip_packet = ipv4(ethernet_packet.raw[ethernet.MIN_LEN:])
#                print str(ip_packet)
#                print str(ofp_orig)
#                print str(ofp)
#                print str(new_ethernet_packet)
#                vlan_packet = vlan(new_ethernet_packet.raw[ethernet.MIN_LEN:])
#                print str(vlan_packet)
#                ip_packet = ipv4(new_ethernet_packet.raw[ethernet.MIN_LEN+vlan.MIN_LEN:])
#                print str(ip_packet)
#                pdb.set_trace()
                return ofp

        else:  # Not a FLOW_MOD or PACKET_OUT
            return ofp
  def _handle_PacketIn (self, event):
    # Note: arp.hwsrc is not necessarily equal to ethernet.src
    # (one such example are arp replies generated by this module itself
    # as ethernet mac is set to switch dpid) so we should be careful
    # to use only arp addresses in the learning code!
    squelch = False

    dpid = event.connection.dpid
    inport = event.port
    packet = event.parsed
    if not packet.parsed:
      log.warning("%s: ignoring unparsed packet", dpid_to_str(dpid))
      return

    a = packet.find('arp')
    if not a: return

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

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

          if _learn:
            # Learn or update port/MAC info
            old_entry = _arp_table.get(a.protosrc)
            if old_entry is None:
              log.info("%s learned %s", dpid_to_str(dpid), a.protosrc)
              _arp_table[a.protosrc] = Entry(a.hwsrc)
            else:
              if old_entry.mac is True:
                # We never replace these special cases.
                # Might want to warn on conflict?
                pass
              elif old_entry.mac != a.hwsrc:
                if old_entry.static:
                  log.warn("%s static entry conflict %s: %s->%s",
                      dpid_to_str(dpid), a.protosrc, old_entry.mac, a.hwsrc)
                else:
                  log.warn("%s RE-learned %s: %s->%s", dpid_to_str(dpid),
                      a.protosrc, old.entry.mac, a.hwsrc)
                  _arp_table[a.protosrc] = Entry(a.hwsrc)
              else:
                # Update timestamp
                _arp_table[a.protosrc] = Entry(a.hwsrc)

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

            if a.protodst in _arp_table:
              # We have an answer...

              r = arp()
              r.hwtype = a.hwtype
              r.prototype = a.prototype
              r.hwlen = a.hwlen
              r.protolen = a.protolen
              r.opcode = arp.REPLY
              r.hwdst = a.hwsrc
              r.protodst = a.protosrc
              r.protosrc = a.protodst
              mac = _arp_table[a.protodst].mac
              if mac is True:
                # Special case -- use ourself
                mac = event.connection.eth_addr
              r.hwsrc = mac
              e = ethernet(type=packet.type, src=event.connection.eth_addr,
                           dst=a.hwsrc)
              e.payload = r
              if packet.type == ethernet.VLAN_TYPE:
                v_rcv = packet.find('vlan')
                e.payload = vlan(eth_type = e.type,
                                 payload = e.payload,
                                 id = v_rcv.id,
                                 pcp = v_rcv.pcp)
                e.type = ethernet.VLAN_TYPE
              log.info("%s answering ARP for %s" % (dpid_to_str(dpid),
                str(r.protosrc)))
              msg = of.ofp_packet_out()
              msg.data = e.pack()
              msg.actions.append(of.ofp_action_output(port =
                                                      of.OFPP_IN_PORT))
              msg.in_port = inport
              event.connection.send(msg)
              return EventHalt if _eat_packets else None
            else:
              # Keep track of failed queries
              squelch = a.protodst in _failed_queries
              _failed_queries[a.protodst] = time.time()

    if self._check_for_flood(dpid, a):
      # Didn't know how to handle this ARP, so just flood it
      msg = "%s flooding ARP %s %s => %s" % (dpid_to_str(dpid),
          {arp.REQUEST:"request",arp.REPLY:"reply"}.get(a.opcode,
          'op:%i' % (a.opcode,)), a.protosrc, a.protodst)

      if squelch:
        log.debug(msg)
      else:
        log.info(msg)

      msg = of.ofp_packet_out()
      msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
      msg.data = event.ofp
      event.connection.send(msg.pack())

    return EventHalt if _eat_packets else None
Example #11
0
    def _handle_PacketIn(self, event):
        # Note: arp.hwsrc is not necessarily equal to ethernet.src
        # (one such example are arp replies generated by this module itself
        # as ethernet mac is set to switch dpid) so we should be careful
        # to use only arp addresses in the learning code!
        squelch = False

        dpid = event.connection.dpid
        inport = event.port
        packet = event.parsed
        if not packet.parsed:
            log.warning("%s: ignoring unparsed packet", dpid_to_str(dpid))
            return

        #UPDATE ARP TABLE BASED ON DHCP
        checkD = packet.find('ipv4')
        if checkD:
            cD = checkD.payload
            if cD.srcport == pkt.dhcp.CLIENT_PORT or cD.srcport == pkt.dhcp.SERVER_PORT:
                bootPk = cD.payload
                dhcpOpt = bootPk.options.get(bootPk.MSG_TYPE_OPT)
                print "FOUND A DHCP PACKET; LOOKIE THERE, with option: " + str(
                    dhcpOpt)
                if dhcpOpt.type == 5:
                    _arp_table[bootPk.yiaddr] = Entry(packet.dst, static=False)
                elif dhcpOpt.type == 7:
                    print "Looking to release" + str(bootPk.ciaddr)
                    for k, v in _arp_table.iteritems():
                        print k, v

                    if bootPk.ciaddr in _arp_table:
                        print "Let's get rid of the IP-MAC binding for " + str(
                            bootPk.ciaddr)
                        del _arp_table[bootPk.ciaddr]

        a = packet.find('arp')
        if not a: return

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

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

                    if _learn:
                        # Learn or update port/MAC info
                        old_entry = _arp_table.get(a.protosrc)
                        if old_entry is None:
                            log.info("%s learned %s", dpid_to_str(dpid),
                                     a.protosrc)
                            _arp_table[a.protosrc] = Entry(a.hwsrc)
                        else:
                            if old_entry.mac is True:
                                # We never replace these special cases.
                                # Might want to warn on conflict?
                                pass
                            elif old_entry.mac != a.hwsrc:
                                if old_entry.static:
                                    log.warn(
                                        "%s static entry conflict %s: %s->%s",
                                        dpid_to_str(dpid), a.protosrc,
                                        old_entry.mac, a.hwsrc)
                                else:
                                    log.warn("%s RE-learned %s: %s->%s",
                                             dpid_to_str(dpid), a.protosrc,
                                             old_entry.mac, a.hwsrc)
                                    _arp_table[a.protosrc] = Entry(a.hwsrc)
                            else:
                                # Update timestamp
                                _arp_table[a.protosrc] = Entry(a.hwsrc)

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

                        if a.protodst in _arp_table:
                            # We have an answer...

                            r = arp()
                            r.hwtype = a.hwtype
                            r.prototype = a.prototype
                            r.hwlen = a.hwlen
                            r.protolen = a.protolen
                            r.opcode = arp.REPLY
                            r.hwdst = a.hwsrc
                            r.protodst = a.protosrc
                            r.protosrc = a.protodst
                            mac = _arp_table[a.protodst].mac
                            if mac is True:
                                # Special case -- use ourself
                                mac = event.connection.eth_addr
                            r.hwsrc = mac
                            e = ethernet(type=packet.type,
                                         src=event.connection.eth_addr,
                                         dst=a.hwsrc)
                            e.payload = r
                            if packet.type == ethernet.VLAN_TYPE:
                                v_rcv = packet.find('vlan')
                                e.payload = vlan(eth_type=e.type,
                                                 payload=e.payload,
                                                 id=v_rcv.id,
                                                 pcp=v_rcv.pcp)
                                e.type = ethernet.VLAN_TYPE
                            log.info("%s answering ARP for %s" %
                                     (dpid_to_str(dpid), str(r.protosrc)))
                            log.info("The corresponding MAC is %s" %
                                     str(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 EventHalt if _eat_packets else None
                        else:
                            # Keep track of failed queries
                            squelch = a.protodst in _failed_queries
                            _failed_queries[a.protodst] = time.time()

        if self._check_for_flood(dpid, a):
            # Didn't know how to handle this ARP, so just flood it
            msg = "%s flooding ARP %s %s => %s" % (dpid_to_str(dpid), {
                arp.REQUEST: "request",
                arp.REPLY: "reply"
            }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, a.protodst)

            if squelch:
                log.debug(msg)
            else:
                log.info(msg)

            msg = of.ofp_packet_out()
            msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
            msg.data = event.ofp
            event.connection.send(msg.pack())

        return EventHalt if _eat_packets else None
Example #12
0
    vlan_packet.id = vlan_id
    vlan_packet.pcp = 0
    vlan_packet.eth_type = ethernet_packet.type
    V = vlan_packet.hdr('')
    # Grab the rest of the packet = R
    R = ethernet_packet.raw[ethernet.MIN_LEN:]
    # Construct E + V + R
    new_raw = E + V + R
    new_ethernet_packet = ethernet(new_raw)
    return new_ethernet_packet

                  
if __name__ == "__main__":
    eth = ethernet()
    eth.dst = EthAddr("01:02:03:04:05:06")
    eth.src = EthAddr("11:12:13:14:15:16")
    eth.type = ethernet.IP_TYPE
    ip = ipv4()
    ip.srcip = IPAddr("128.99.98.97")
    ip.dstip = IPAddr("128.89.8.87")

    joint_eth = ethernet(eth.hdr('') + ip.hdr(''))
    print "JOINT = " + str(joint_eth)
    print "IP = " + str(ipv4(joint_eth.raw[ethernet.MIN_LEN:]))
    joint_eth_vlan = add_vlan_to_packet(joint_eth, 1000)
    print "JOINT_V = " + str(joint_eth_vlan)
    print "V = " + str(vlan(joint_eth_vlan.raw[ethernet.MIN_LEN:]))
    print "IP = " + str(ipv4(joint_eth_vlan.raw[ethernet.MIN_LEN+vlan.MIN_LEN:]))