Beispiel #1
0
  def rx_packet (self, packet, in_port, packet_data = None):
    """
    process a dataplane packet

    packet: an instance of ethernet
    in_port: the integer port number
    packet_data: packed version of packet if available
    """
    assert assert_type("packet", packet, ethernet, none_ok=False)
    assert assert_type("in_port", in_port, int, none_ok=False)
    port = self.ports.get(in_port)
    if port is None:
      self.log.warn("Got packet on missing port %i", in_port)
      return

    is_stp = packet.dst == _STP_MAC

    if (port.config & OFPPC_NO_RECV) and not is_stp:
      # Drop all except STP
      return
    if (port.config & OFPPC_NO_RECV_STP) and is_stp:
      # Drop STP
      return

    if self.config_flags & OFPC_FRAG_MASK:
      ipp = packet.find(ipv4)
      if ipp:
        if (ipp.flags & ipv4.MF_FLAG) or ipp.frag != 0:
          frag_mode = self.config_flags & OFPC_FRAG_MASK
          if frag_mode == OFPC_FRAG_DROP:
            # Drop fragment
            return
          elif frag_mode == OFPC_FRAG_REASM:
            if self.features.cap_ip_reasm:
              #TODO: Implement fragment reassembly
              self.log.info("Can't reassemble fragment: not implemented")
          else:
            self.log.warn("Illegal fragment processing mode: %i", frag_mode)

    self.port_stats[in_port].rx_packets += 1
    if packet_data is not None:
      self.port_stats[in_port].rx_bytes += len(packet_data)
    else:
      self.port_stats[in_port].rx_bytes += len(packet.pack()) # Expensive

    self._lookup_count += 1
    entry = self.table.entry_for_packet(packet, in_port)
    if entry is not None:
      self._matched_count += 1
      entry.touch_packet(len(packet))
      self._process_actions_for_packet(entry.actions, packet, in_port)
    else:
      # no matching entry
      if port.config & OFPPC_NO_PACKET_IN:
        return
      buffer_id = self._buffer_packet(packet, in_port)
      if packet_data is None:
        packet_data = packet.pack()
      self.send_packet_in(in_port, buffer_id, packet_data,
                          reason=OFPR_NO_MATCH, data_length=self.miss_send_len)
 def __init__(self, host, interface, switch, switch_port):
   assert_type("interface", interface, HostInterface, none_ok=False)
   assert_type("switch_port", switch_port, ofp_phy_port, none_ok=False)
   self.host = host
   self.interface = interface
   self.switch = switch
   self.switch_port = switch_port
Beispiel #3
0
  def rx_packet (self, packet, in_port):
    """
    process a dataplane packet

    packet: an instance of ethernet
    in_port: the integer port number
    """
    assert assert_type("packet", packet, ethernet, none_ok=False)
    assert assert_type("in_port", in_port, int, none_ok=False)
    port = self.ports.get(in_port)
    if port is None:
      self.log.warn("Got packet on missing port %i", in_port)
      return
    if port.config & OFPPC_NO_RECV:
      return

    self._lookup_count += 1
    entry = self.table.entry_for_packet(packet, in_port)
    if entry is not None:
      self._matched_count += 1
      entry.touch_packet(len(packet))
      self._process_actions_for_packet(entry.actions, packet, in_port)
    else:
      # no matching entry
      if port.config & OFPPC_NO_PACKET_IN:
        return
      buffer_id = self._buffer_packet(packet, in_port)
      self.send_packet_in(in_port, buffer_id, packet,
                          reason=OFPR_NO_MATCH, data_length=self.miss_send_len)
  def _output_packet(self, packet, out_port, in_port):
    """ send a packet out some port.
        packet: instance of ethernet
        out_port, in_port: the integer port number """
    assert_type("packet", packet, ethernet, none_ok=False)
    def real_send(port_no):
      if type(port_no) == ofp_phy_port:
        port_no = port_no.port_no
      if port_no not in self.ports:
        raise RuntimeError("Invalid physical output port: %x" % port_no)
      if self.ports[port_no].state & OFPPS_LINK_DOWN:
        self.log.debug("Sending packet on a port which is down!")
      else:
        self.raiseEvent(DpPacketOut(self, packet, self.ports[port_no]))

    if out_port < OFPP_MAX:
      real_send(out_port)
    elif out_port == OFPP_IN_PORT:
      real_send(in_port)
    elif out_port == OFPP_FLOOD or out_port == OFPP_ALL:
      # no support for spanning tree yet -> flood=all
      for (no,port) in self.ports.iteritems():
        if no != in_port:
          real_send(port)
    elif out_port == OFPP_CONTROLLER:
      buffer_id = self._buffer_packet(packet, in_port)
      self.send_packet_in(in_port, buffer_id, packet, self.xid_count(), reason=OFPR_ACTION)
    else:
      raise("Unsupported virtual output port: %x" % out_port)
 def __init__(self, start_switch_impl, start_port, end_switch_impl, end_port):
   assert_type("start_port", start_port, ofp_phy_port, none_ok=False)
   assert_type("end_port", end_port, ofp_phy_port, none_ok=False)
   self.start_switch_impl = start_switch_impl
   self.start_port = start_port
   self.end_switch_impl = end_switch_impl
   self.end_port = end_port
Beispiel #6
0
  def rx_packet (self, packet, in_port):
    """
    process a dataplane packet

    packet: an instance of ethernet
    in_port: the integer port number
    """
    assert assert_type("packet", packet, ethernet, none_ok=False)
    assert assert_type("in_port", in_port, int, none_ok=False)
    port = self.ports.get(in_port)
    if port is None:
      self.log.warn("Got packet on missing port %i", in_port)
      return
    if port.config & OFPPC_NO_RECV:
      return

    self._lookup_count += 1
    entry = self.table.entry_for_packet(packet, in_port)
    if entry is not None:
      self._matched_count += 1
      entry.touch_packet(len(packet))
      self._process_actions_for_packet(entry.actions, packet, in_port)
    else:
      # no matching entry
      if port.config & OFPPC_NO_PACKET_IN:
        return
      buffer_id = self._buffer_packet(packet, in_port)
      self.send_packet_in(in_port, buffer_id, packet,
                          reason=OFPR_NO_MATCH, data_length=self.miss_send_len)
Beispiel #7
0
  def rx_packet (self, packet, in_port, packet_data = None):
    """
    process a dataplane packet

    packet: an instance of ethernet
    in_port: the integer port number
    packet_data: packed version of packet if available
    """
    assert assert_type("packet", packet, ethernet, none_ok=False)
    assert assert_type("in_port", in_port, int, none_ok=False)
    port = self.ports.get(in_port)
    if port is None:
      self.log.warn("Got packet on missing port %i", in_port)
      return

    is_stp = packet.dst == _STP_MAC

    if (port.config & OFPPC_NO_RECV) and not is_stp:
      # Drop all except STP
      return
    if (port.config & OFPPC_NO_RECV_STP) and is_stp:
      # Drop STP
      return

    if self.config_flags & OFPC_FRAG_MASK:
      ipp = packet.find(ipv4)
      if ipp:
        if (ipp.flags & ipv4.MF_FLAG) or ipp.frag != 0:
          frag_mode = self.config_flags & OFPC_FRAG_MASK
          if frag_mode == OFPC_FRAG_DROP:
            # Drop fragment
            return
          elif frag_mode == OFPC_FRAG_REASM:
            if self.features.cap_ip_reasm:
              #TODO: Implement fragment reassembly
              self.log.info("Can't reassemble fragment: not implemented")
          else:
            self.log.warn("Illegal fragment processing mode: %i", frag_mode)

    self.port_stats[in_port].rx_packets += 1
    if packet_data is not None:
      self.port_stats[in_port].rx_bytes += len(packet_data)
    else:
      self.port_stats[in_port].rx_bytes += len(packet.pack()) # Expensive

    self._lookup_count += 1
    entry = self.table.entry_for_packet(packet, in_port)
    if entry is not None:
      self._matched_count += 1
      entry.touch_packet(len(packet))
      self._process_actions_for_packet(entry.actions, packet, in_port)
    else:
      # no matching entry
      if port.config & OFPPC_NO_PACKET_IN:
        return
      buffer_id = self._buffer_packet(packet, in_port)
      if packet_data is None:
        packet_data = packet.pack()
      self.send_packet_in(in_port, buffer_id, packet_data,
                          reason=OFPR_NO_MATCH, data_length=self.miss_send_len)
 def __init__ (self, node, packet, port):
   assert_type("packet", packet, ethernet, none_ok=False)
   Event.__init__(self)
   self.node = node
   self.packet = packet
   self.port = port
   # For backwards compatability:
   self.switch = node
Beispiel #9
0
  def _process_actions_for_packet(self, actions, packet, in_port):
    """ process the output actions for a packet """
    assert_type("packet", packet, [ethernet, str], none_ok=False)
    if not isinstance(packet, ethernet):
      packet = ethernet.unpack(packet)

    def output_packet(action, packet):
      self._output_packet(packet, action.port, in_port)
    def set_vlan_id(action, packet):
      if not isinstance(packet, vlan): packet = vlan(packet)
      packet.id = action.vlan_id
    def set_vlan_pcp(action, packet):
      if not isinstance(packet, vlan): packet = vlan(packet)
      packet.pcp = action.vlan_pcp
    def strip_vlan(action, packet):
      if not isinstance(packet, vlan): packet = vlan(packet)
      packet.pcp = action.vlan_pcp
    def set_dl_src(action, packet):
      packet.src = action.dl_addr
    def set_dl_dst(action, packet):
      packet.dst = action.dl_addr
    def set_nw_src(action, packet):
      if(isinstance(packet, ipv4)):
        packet.nw_src = action.nw_addr
    def set_nw_dst(action, packet):
      if(isinstance(packet, ipv4)):
        packet.nw_dst = action.nw_addr
    def set_nw_tos(action, packet):
      if(isinstance(packet, ipv4)):
        packet.tos = action.nw_tos
    def set_tp_src(action, packet):
      if(isinstance(packet, udp) or isinstance(packet, tcp)):
        packet.srcport = action.tp_port
    def set_tp_dst(action, packet):
      if(isinstance(packet, udp) or isinstance(packet, tcp)):
        packet.dstport = action.tp_port
    def enqueue(action, packet):
      self.log.warn("output_enqueue not supported yet. Performing regular output")
      output_packet(action.tp_port, packet)

    handler_map = {
        OFPAT_OUTPUT: output_packet,
        OFPAT_SET_VLAN_VID: set_vlan_id,
        OFPAT_SET_VLAN_PCP: set_vlan_pcp,
        OFPAT_STRIP_VLAN: strip_vlan,
        OFPAT_SET_DL_SRC: set_dl_src,
        OFPAT_SET_DL_DST: set_dl_dst,
        OFPAT_SET_NW_SRC: set_nw_src,
        OFPAT_SET_NW_DST: set_nw_dst,
        OFPAT_SET_NW_TOS: set_nw_tos,
        OFPAT_SET_TP_SRC: set_tp_src,
        OFPAT_SET_TP_DST: set_tp_dst,
        OFPAT_ENQUEUE: enqueue
    }
    for action in actions:
      if(action.type not in handler_map):
        raise NotImplementedError("Unknown action type: %x " % type)
      handler_map[action.type](action, packet)
 def send_port_status(self, port, reason):
   '''
   port is an ofp_phy_port
   reason is one of 'OFPPR_ADD', 'OFPPR_DELETE', 'OFPPR_MODIFY'
   '''
   assert_type("port", port, ofp_phy_port, none_ok=False)
   assert(reason in ofp_port_reason_rev_map.values())
   msg = ofp_port_status(desc=port, reason=reason)
   self.send(msg)
Beispiel #11
0
 def __init__(self, start_software_switch, start_port,
              end_software_switch, end_port):
   if type(start_port) == int:
     assert(start_port in start_software_switch.ports)
     start_port = start_software_switch.ports[start_port]
   if type(end_port) == int:
     assert(end_port in start_software_switch.ports)
     end_port = end_software_switch.ports[end_port]
   super(Link, self).__init__(start_software_switch, start_port,
                              end_software_switch, end_port)
   assert_type("start_port", start_port, ofp_phy_port, none_ok=False)
   assert_type("end_port", end_port, ofp_phy_port, none_ok=False)
   self.start_software_switch = start_software_switch
   self.end_software_switch = end_software_switch
    def rx_packet(self, packet, in_port, packet_data=None):
        """
    process a dataplane packet

    packet: an instance of ethernet
    in_port: the integer port number
    packet_data: packed version of packet if available
    """
        assert assert_type("packet", packet, ethernet, none_ok=False)
        assert assert_type("in_port", in_port, int, none_ok=False)
        port = self.ports.get(in_port)
        if port is None:
            self.log.warn("Got packet on missing port %i", in_port)
            return

        is_stp = packet.dst == _STP_MAC

        if (port.config & OFPPC_NO_RECV) and not is_stp:
            # Drop all except STP
            return
        if (port.config & OFPPC_NO_RECV_STP) and is_stp:
            # Drop STP
            return

        self.port_stats[in_port].rx_packets += 1
        if packet_data is not None:
            self.port_stats[in_port].rx_bytes += len(packet_data)
        else:
            self.port_stats[in_port].rx_bytes += len(
                packet.pack())  # Expensive

        self._lookup_count += 1
        entry = self.table.entry_for_packet(packet, in_port)
        if entry is not None:
            self._matched_count += 1
            entry.touch_packet(len(packet))
            self._process_actions_for_packet(entry.actions, packet, in_port)
        else:
            # no matching entry
            if port.config & OFPPC_NO_PACKET_IN:
                return
            buffer_id = self._buffer_packet(packet, in_port)
            if packet_data is None:
                packet_data = packet.pack()
            self.send_packet_in(in_port,
                                buffer_id,
                                packet_data,
                                reason=OFPR_NO_MATCH,
                                data_length=self.miss_send_len)
Beispiel #13
0
  def process_packet(self, packet, in_port):
    """ process a dataplane packet the way a real OpenFlow switch would.
        packet: an instance of ethernet
        in_port: the integer port number
    """
    assert_type("packet", packet, ethernet, none_ok=False)

    entry = self.table.entry_for_packet(packet, in_port)
    if(entry != None):
      entry.touch_packet(len(packet))
      self._process_actions_for_packet(entry.actions, packet, in_port)
    else:
      # no matching entry
      buffer_id = self._buffer_packet(packet, in_port)
      self.send_packet_in(in_port, buffer_id, packet, self.xid_count.next(), reason=OFPR_NO_MATCH)
Beispiel #14
0
  def _process_actions_for_packet (self, actions, packet, in_port, ofp=None):
    """
    process the output actions for a packet

    ofp is the message which triggered this processing, if any (used for error
    generation)
    """
    assert assert_type("packet", packet, (ethernet, bytes), none_ok=False)
    if not isinstance(packet, ethernet):
      packet = ethernet.unpack(packet)

    for action in actions:
      #if action.type is ofp_action_resubmit:
      #  self.rx_packet(packet, in_port)
      #  return
      h = self.action_handlers.get(action.type)
      if h is None:
        self.log.warn("Unknown action type: %x " % (action.type,))
        err = ofp_error(type=OFPET_BAD_ACTION, code=OFPBAC_BAD_TYPE)
        if ofp:
          err.xid = ofp.xid
          err.data = ofp.pack()
        else:
          err.xid = 0
        self.send(err)
        return
      packet = h(action, packet, in_port)
Beispiel #15
0
  def _output_packet (self, packet, out_port, in_port, max_len=None):
    """
    send a packet out some port

    This handles virtual ports and does validation.

    packet: instance of ethernet
    out_port, in_port: the integer port number
    max_len: maximum packet payload length to send to controller
    """
    assert assert_type("packet", packet, ethernet, none_ok=False)

    def real_send (port_no, allow_in_port=False):
      if type(port_no) == ofp_phy_port:
        port_no = port_no.port_no
      if port_no == in_port and not allow_in_port:
        self.log.warn("Dropping packet sent on port %i: Input port", port_no)
        return
      if port_no not in self.ports:
        self.log.warn("Dropping packet sent on port %i: Invalid port", port_no)
        return
      if self.ports[port_no].config & OFPPC_NO_FWD:
        self.log.warn("Dropping packet sent on port %i: Forwarding disabled",
                      port_no)
        return
      if self.ports[port_no].config & OFPPC_PORT_DOWN:
        self.log.warn("Dropping packet sent on port %i: Port down", port_no)
        return
      if self.ports[port_no].state & OFPPS_LINK_DOWN:
        self.log.debug("Dropping packet sent on port %i: Link down", port_no)
        return
      self.port_stats[port_no].tx_packets += 1
      self.port_stats[port_no].tx_bytes += len(packet.pack()) #FIXME: Expensive
      self._output_packet_physical(packet, port_no)

    if out_port < OFPP_MAX:
      real_send(out_port)
    elif out_port == OFPP_IN_PORT:
      real_send(in_port, allow_in_port=True)
    elif out_port == OFPP_FLOOD:
      for no,port in self.ports.iteritems():
        if no == in_port: continue
        if port.config & OFPPC_NO_FLOOD: continue
        real_send(port)
    elif out_port == OFPP_ALL:
      for no,port in self.ports.iteritems():
        if no == in_port: continue
        real_send(port)
    elif out_port == OFPP_CONTROLLER:
      buffer_id = self._buffer_packet(packet, in_port)
      # Should we honor OFPPC_NO_PACKET_IN here?
      self.send_packet_in(in_port, buffer_id, packet, reason=OFPR_ACTION,
                          data_length=max_len)
    elif out_port == OFPP_TABLE:
      # Do we disable send-to-controller when performing this?
      # (Currently, there's the possibility that a table miss from this
      # will result in a send-to-controller which may send back to table...)
      self.rx_packet(packet, in_port)
    else:
      self.log.warn("Unsupported virtual output port: %d", out_port)
Beispiel #16
0
  def _process_actions_for_packet (self, actions, packet, in_port, ofp=None):
    """
    process the output actions for a packet

    ofp is the message which triggered this processing, if any (used for error
    generation)
    """
    assert assert_type("packet", packet, (ethernet, bytes), none_ok=False)
    if not isinstance(packet, ethernet):
      packet = ethernet.unpack(packet)

    for action in actions:
      #if action.type is ofp_action_resubmit:
      #  self.rx_packet(packet, in_port)
      #  return
      h = self.action_handlers.get(action.type)
      if h is None:
        self.log.warn("Unknown action type: %x " % (action.type,))
        err = ofp_error(type=OFPET_BAD_ACTION, code=OFPBAC_BAD_TYPE)
        if ofp:
          err.xid = ofp.xid
          err.data = ofp.pack()
        else:
          err.xid = 0
        self.send(err)
        return
      packet = h(action, packet, in_port)
    def send_packet_in(self,
                       in_port,
                       buffer_id=None,
                       packet=b'',
                       reason=None,
                       data_length=None):
        """
    Send PacketIn
    """
        if hasattr(packet, 'pack'):
            packet = packet.pack()
        assert assert_type("packet", packet, bytes)
        self.log.debug("Send PacketIn")
        if reason is None:
            reason = OFPR_NO_MATCH
        if data_length is not None and len(packet) > data_length:
            if buffer_id is not None:
                packet = packet[:data_length]

        msg = ofp_packet_in(xid=0,
                            in_port=in_port,
                            buffer_id=buffer_id,
                            reason=reason,
                            data=packet)

        self.send(msg)
 def __init__(self, node, packet, port):
     assert assert_type("packet", packet, ethernet, none_ok=False)
     Event.__init__(self)
     self.node = node
     self.packet = packet
     self.port = port
     self.switch = node  # For backwards compatability
Beispiel #19
0
  def _output_packet (self, packet, out_port, in_port, max_len=None):
    """
    send a packet out some port

    This handles virtual ports and does validation.

    packet: instance of ethernet
    out_port, in_port: the integer port number
    max_len: maximum packet payload length to send to controller
    """
    assert assert_type("packet", packet, ethernet, none_ok=False)

    def real_send (port_no, allow_in_port=False):
      if type(port_no) == ofp_phy_port:
        port_no = port_no.port_no
      if port_no == in_port and not allow_in_port:
        self.log.warn("Dropping packet sent on port %i: Input port", port_no)
        return
      if port_no not in self.ports:
        self.log.warn("Dropping packet sent on port %i: Invalid port", port_no)
        return
      if self.ports[port_no].config & OFPPC_NO_FWD:
        self.log.warn("Dropping packet sent on port %i: Forwarding disabled",
                      port_no)
        return
      if self.ports[port_no].config & OFPPC_PORT_DOWN:
        self.log.warn("Dropping packet sent on port %i: Port down", port_no)
        return
      if self.ports[port_no].state & OFPPS_LINK_DOWN:
        self.log.debug("Dropping packet sent on port %i: Link down", port_no)
        return
      self.port_stats[port_no].tx_packets += 1
      self.port_stats[port_no].tx_bytes += len(packet.pack()) #FIXME: Expensive
      self._output_packet_physical(packet, port_no)

    if out_port < OFPP_MAX:
      real_send(out_port)
    elif out_port == OFPP_IN_PORT:
      real_send(in_port, allow_in_port=True)
    elif out_port == OFPP_FLOOD:
      for no,port in self.ports.iteritems():
        if no == in_port: continue
        if port.config & OFPPC_NO_FLOOD: continue
        real_send(port)
    elif out_port == OFPP_ALL:
      for no,port in self.ports.iteritems():
        if no == in_port: continue
        real_send(port)
    elif out_port == OFPP_CONTROLLER:
      buffer_id = self._buffer_packet(packet, in_port)
      # Should we honor OFPPC_NO_PACKET_IN here?
      self.send_packet_in(in_port, buffer_id, packet, reason=OFPR_ACTION,
                          data_length=max_len)
    elif out_port == OFPP_TABLE:
      # Do we disable send-to-controller when performing this?
      # (Currently, there's the possibility that a table miss from this
      # will result in a send-to-controller which may send back to table...)
      self.rx_packet(packet, in_port)
    else:
      self.log.warn("Unsupported virtual output port: %d", out_port)
Beispiel #20
0
  def _output_packet (self, packet, out_port, in_port, max_len=None):
    """
    send a packet out some port

    This handles virtual ports and does validation.

    packet: instance of ethernet
    out_port, in_port: the integer port number
    max_len: maximum packet payload length to send to controller
    """
    assert assert_type("packet", packet, ethernet, none_ok=False)

    def real_send (port_no, allow_in_port=False):
      if type(port_no) == ofp_phy_port:
        port_no = port_no.port_no
      if port_no == in_port and not allow_in_port:
        self.log.warn("Dropping packet sent on port %i: Input port", port_no)
        return
      if port_no not in self.ports:
        self.log.warn("Dropping packet sent on port %i: Invalid port", port_no)
        return
      if self.ports[port_no].config & OFPPC_NO_FWD:
        self.log.warn("Dropping packet sent on port %i: Forwarding disabled",
                      port_no)
        return
      if self.ports[port_no].config & OFPPC_PORT_DOWN:
        self.log.warn("Dropping packet sent on port %i: Port down", port_no)
        return
      if self.ports[port_no].state & OFPPS_LINK_DOWN:
        self.log.debug("Dropping packet sent on port %i: Link down", port_no)
        return
      self._output_packet_physical(packet, port_no)

    if out_port < OFPP_MAX:
      real_send(out_port)
    elif out_port == OFPP_IN_PORT:
      real_send(in_port, allow_in_port=True)
    elif out_port == OFPP_FLOOD:
      for no,port in self.ports.iteritems():
        if no == in_port: continue
        if port.config & OFPPC_NO_FLOOD: continue
        real_send(port)
    elif out_port == OFPP_ALL:
      for no,port in self.ports.iteritems():
        if no == in_port: continue
        real_send(port)
    elif out_port == OFPP_CONTROLLER:
      buffer_id = self._buffer_packet(packet, in_port)
      # Should we honor OFPPC_NO_PACKET_IN here?
      self.send_packet_in(in_port, buffer_id, packet, reason=OFPR_ACTION,
                          data_length=max_len)
    elif out_port == OFPP_TABLE:
      # There better be a table entry there, else we get infinite recurision
      # between switch<->controller
      # Note that this isn't infinite recursion, since the table entry's
      # out_port will not be OFPP_TABLE
      self.rx_packet(packet, in_port)
    else:
      raise("Unsupported virtual output port: %d" % (out_port,))
Beispiel #21
0
  def _output_packet (self, packet, out_port, in_port, max_len=None):
    """
    send a packet out some port

    This handles virtual ports and does validation.

    packet: instance of ethernet
    out_port, in_port: the integer port number
    max_len: maximum packet payload length to send to controller
    """
    assert assert_type("packet", packet, ethernet, none_ok=False)

    def real_send (port_no, allow_in_port=False):
      if type(port_no) == ofp_phy_port:
        port_no = port_no.port_no
      if port_no == in_port and not allow_in_port:
        self.log.warn("Dropping packet sent on port %i: Input port", port_no)
        return
      if port_no not in self.ports:
        self.log.warn("Dropping packet sent on port %i: Invalid port", port_no)
        return
      if self.ports[port_no].config & OFPPC_NO_FWD:
        self.log.warn("Dropping packet sent on port %i: Forwarding disabled",
                      port_no)
        return
      if self.ports[port_no].config & OFPPC_PORT_DOWN:
        self.log.warn("Dropping packet sent on port %i: Port down", port_no)
        return
      if self.ports[port_no].state & OFPPS_LINK_DOWN:
        self.log.debug("Dropping packet sent on port %i: Link down", port_no)
        return
      self._output_packet_physical(packet, port_no)

    if out_port < OFPP_MAX:
      real_send(out_port)
    elif out_port == OFPP_IN_PORT:
      real_send(in_port, allow_in_port=True)
    elif out_port == OFPP_FLOOD:
      for no,port in self.ports.iteritems():
        if no == in_port: continue
        if port.config & OFPPC_NO_FLOOD: continue
        real_send(port)
    elif out_port == OFPP_ALL:
      for no,port in self.ports.iteritems():
        if no == in_port: continue
        real_send(port)
    elif out_port == OFPP_CONTROLLER:
      buffer_id = self._buffer_packet(packet, in_port)
      # Should we honor OFPPC_NO_PACKET_IN here?
      self.send_packet_in(in_port, buffer_id, packet, reason=OFPR_ACTION,
                          data_length=max_len)
    elif out_port == OFPP_TABLE:
      # There better be a table entry there, else we get infinite recurision
      # between switch<->controller
      # Note that this isn't infinite recursion, since the table entry's
      # out_port will not be OFPP_TABLE
      self.rx_packet(packet, in_port)
    else:
      raise("Unsupported virtual output port: %d" % (out_port,))
Beispiel #22
0
  def send_packet_in(self, in_port, buffer_id=None, packet="", xid=None, reason=None):
    """Send PacketIn
    Assume no match as reason, buffer_id = 0xFFFFFFFF,
    and empty packet by default
    """
    assert_type("packet", packet, ethernet)
    self.log.debug("Send PacketIn %s " % self.name)
    if (reason == None):
      reason = ofp_packet_in_reason_rev_map['OFPR_NO_MATCH']
    if (buffer_id == None):
      buffer_id = int("0xFFFFFFFF",16)

    if xid == None:
      xid = self.xid_count.next()
    msg = ofp_packet_in(xid=xid, in_port = in_port, buffer_id = buffer_id, reason = reason,
                        data = packet.pack())
    self.send(msg)
    def rx_packet(self, packet, in_port, packet_data=None):
        """
    process a dataplane packet

    packet: an instance of ethernet
    in_port: the integer port number
    packet_data: packed version of packet if available
    """
        assert assert_type("packet", packet, ethernet, none_ok=False)
        assert assert_type("in_port", in_port, int, none_ok=False)
        port = self.ports.get(in_port)
        if port is None:
            self.log.warn("Got packet on missing port %i", in_port)
            return

        is_stp = packet.dst == _STP_MAC

        if (port.config & OFPPC_NO_RECV) and not is_stp:
            # Drop all except STP
            return
        if (port.config & OFPPC_NO_RECV_STP) and is_stp:
            # Drop STP
            return

        self.port_stats[in_port].rx_packets += 1
        if packet_data is not None:
            self.port_stats[in_port].rx_bytes += len(packet_data)
        else:
            self.port_stats[in_port].rx_bytes += len(packet.pack())  # Expensive

        self._lookup_count += 1
        entry = self.table.entry_for_packet(packet, in_port)
        if entry is not None:
            self._matched_count += 1
            entry.touch_packet(len(packet))
            self._process_actions_for_packet(entry.actions, packet, in_port)
        else:
            # no matching entry
            if port.config & OFPPC_NO_PACKET_IN:
                return
            buffer_id = self._buffer_packet(packet, in_port)
            if packet_data is None:
                packet_data = packet.pack()
            self.send_packet_in(in_port, buffer_id, packet_data, reason=OFPR_NO_MATCH, data_length=self.miss_send_len)
    def send_port_status(self, port, reason):
        """
    Send port status

    port is an ofp_phy_port
    reason is one of OFPPR_xxx
    """
        assert assert_type("port", port, ofp_phy_port, none_ok=False)
        assert reason in ofp_port_reason_rev_map.values()
        msg = ofp_port_status(desc=port, reason=reason)
        self.send(msg)
Beispiel #25
0
  def send_port_status (self, port, reason):
    """
    Send port status

    port is an ofp_phy_port
    reason is one of OFPPR_xxx
    """
    assert assert_type("port", port, ofp_phy_port, none_ok=False)
    assert reason in ofp_port_reason_rev_map.values()
    msg = ofp_port_status(desc=port, reason=reason)
    self.send(msg)
    def send_packet_in(self, in_port, buffer_id=None, packet=b"", reason=None, data_length=None):
        """
    Send PacketIn
    """
        if hasattr(packet, "pack"):
            packet = packet.pack()
        assert assert_type("packet", packet, bytes)
        self.log.debug("Send PacketIn")
        if reason is None:
            reason = OFPR_NO_MATCH
        if data_length is not None and len(packet) > data_length:
            if buffer_id is not None:
                packet = packet[:data_length]

        msg = ofp_packet_in(xid=0, in_port=in_port, buffer_id=buffer_id, reason=reason, data=packet)

        self.send(msg)
  def _process_actions_for_packet(self, actions, packet, in_port):
    """ process the output actions for a packet """
    assert_type("packet", packet, [ethernet, str], none_ok=False)
    if not isinstance(packet, ethernet):
      packet = ethernet.unpack(packet)

    def output_packet(action, packet):
      self._output_packet(packet, action.port, in_port)
      return packet
    def set_vlan_id(action, packet):
      if not isinstance(packet.next, vlan): 
        packet.next = vlan(prev = packet.next)
        packet.next.eth_type = packet.type
        packet.type = ethernet.VLAN_TYPE
      packet.id = action.vlan_id
      return packet
    def set_vlan_pcp(action, packet):
      if not isinstance(packet.next, vlan):
        packet.next = vlan(prev = packet)
        packet.next.eth_type = packet.type
        packet.type = ethernet.VLAN_TYPE
      packet.pcp = action.vlan_pcp
      return packet
    def strip_vlan(action, packet):
      if isinstance(packet.next, vlan): 
        packet.type = packet.next.eth_type
        packet.next = packet.next.next
      return packet
    def set_dl_src(action, packet):
      packet.src = action.dl_addr
      return packet
    def set_dl_dst(action, packet):
      packet.dst = action.dl_addr
      return packet
    def set_nw_src(action, packet):
      if(isinstance(packet.next, ipv4)):
        packet.next.nw_src = action.nw_addr
      return packet
    def set_nw_dst(action, packet):
      if(isinstance(packet.next, ipv4)):
        packet.next.nw_dst = action.nw_addr
      return packet
    def set_nw_tos(action, packet):
      if(isinstance(packet.next, ipv4)):
        packet.next.tos = action.nw_tos
      return packet
    def set_tp_src(action, packet):
      if(isinstance(packet.next, udp) or isinstance(packet.next, tcp)):
        packet.next.srcport = action.tp_port
      return packet
    def set_tp_dst(action, packet):
      if(isinstance(packet.next, udp) or isinstance(packet.next, tcp)):
        packet.next.dstport = action.tp_port
      return packet
    def enqueue(action, packet):
      self.log.warn("output_enqueue not supported yet. Performing regular output")
      return output_packet(action.tp_port, packet)
#    def push_mpls_tag(action, packet):
#      bottom_of_stack = isinstance(packet.next, mpls)
#      packet.next = mpls(prev = packet.pack())
#      if bottom_of_stack:
#        packet.next.s = 1
#      packet.type = action.ethertype
#      return packet
#    def pop_mpls_tag(action, packet):
#      if not isinstance(packet.next, mpls):
#        return packet
#      if not isinstance(packet.next.next, str):
#        packet.next.next = packet.next.next.pack()
#      if action.ethertype in ethernet.type_parsers:
#        packet.next = ethernet.type_parsers[action.ethertype](packet.next.next)
#      else:
#        packet.next = packet.next.next
#      packet.ethertype = action.ethertype
#      return packet
#    def set_mpls_label(action, packet):
#      if not isinstance(packet.next, mpls):
#        mock = ofp_action_push_mpls()
#        packet = push_mpls_tag(mock, packet)
#      packet.next.label = action.mpls_label
#      return packet
#    def set_mpls_tc(action, packet):
#      if not isinstance(packet.next, mpls):
#        mock = ofp_action_push_mpls()
#        packet = push_mpls_tag(mock, packet)
#      packet.next.tc = action.mpls_tc
#      return packet
#    def set_mpls_ttl(action, packet):
#      if not isinstance(packet.next, mpls):
#        mock = ofp_action_push_mpls()
#        packet = push_mpls_tag(mock, packet)
#      packet.next.ttl = action.mpls_ttl
#      return packet
#    def dec_mpls_ttl(action, packet):
#      if not isinstance(packet.next, mpls):
#        return packet
#      packet.next.ttl = packet.next.ttl - 1
#      return packet
    handler_map = {
        OFPAT_OUTPUT: output_packet,
        OFPAT_SET_VLAN_VID: set_vlan_id,
        OFPAT_SET_VLAN_PCP: set_vlan_pcp,
        OFPAT_STRIP_VLAN: strip_vlan,
        OFPAT_SET_DL_SRC: set_dl_src,
        OFPAT_SET_DL_DST: set_dl_dst,
        OFPAT_SET_NW_SRC: set_nw_src,
        OFPAT_SET_NW_DST: set_nw_dst,
        OFPAT_SET_NW_TOS: set_nw_tos,
        OFPAT_SET_TP_SRC: set_tp_src,
        OFPAT_SET_TP_DST: set_tp_dst,
        OFPAT_ENQUEUE: enqueue,
#        OFPAT_PUSH_MPLS: push_mpls_tag,
#        OFPAT_POP_MPLS: pop_mpls_tag,
#        OFPAT_SET_MPLS_LABEL: set_mpls_label,
#        OFPAT_SET_MPLS_TC: set_mpls_tc,
#        OFPAT_SET_MPLS_TTL: set_mpls_ttl,
#        OFPAT_DEC_MPLS_TTL: dec_mpls_ttl,
    }
    for action in actions:
#      if action.type is ofp_action_resubmit:
#        self.process_packet(packet, in_port)
#        return
      if(action.type not in handler_map):
        raise NotImplementedError("Unknown action type: %x " % type)
      packet = handler_map[action.type](action, packet)
Beispiel #28
0
 def send(self, data):
     """ send data from the client side. fire and forget. """
     assert_type("data", data, [bytes], none_ok=False)
     self.send_buf += data
Beispiel #29
0
 def send(self, data):
   """ send data from the client side. fire and forget. """
   assert_type("data", data, [bytes], none_ok=False)
   self.send_buf += data
Beispiel #30
0
 def __init__ (self, interface, packet):
   assert_type("interface", interface, HostInterface, none_ok=False)
   assert_type("packet", packet, ethernet, none_ok=False)
   self.interface = interface 
   self.packet = packet
Beispiel #31
0
 def __init__(self, host, interface, switch, switch_port):
   super(AccessLink, self).__init__(host, interface, switch, switch_port)
   assert_type("interface", interface, HostInterface, none_ok=False)
   assert_type("switch_port", switch_port, ofp_phy_port, none_ok=False)
Beispiel #32
0
 def __init__(self, interface, packet):
     assert_type("interface", interface, HostInterface, none_ok=False)
     assert_type("packet", packet, ethernet, none_ok=False)
     self.interface = interface
     self.packet = packet
Beispiel #33
0
 def send(self, data):
     """ Send data.  Fire and forget. """
     #print(" Send in IOWOrker")
     assert assert_type("data", data, [bytes], none_ok=False)
     self.send_buf += data
Beispiel #34
0
 def send(self, data):
     """ Send data.  Fire and forget. """
     assert assert_type("data", data, [bytes], none_ok=False)
     self.send_buf += data
Beispiel #35
0
 def send (self, data):
   """ Send data.  Fire and forget. """
   assert assert_type("data", data, [bytes], none_ok=False)
   self.send_buf += data