hs-test: temp skip some tests
[vpp.git] / src / vnet / interface.h
index 174e534..f0cb540 100644 (file)
 #include <vlib/vlib.h>
 #include <vppinfra/pcap.h>
 #include <vnet/l3_types.h>
+#include <vppinfra/lock.h>
+#include <vnet/hash/hash.h>
 
 struct vnet_main_t;
 struct vnet_hw_interface_t;
 struct vnet_sw_interface_t;
-struct ip46_address_t;
+union ip46_address_t_;
 
 typedef enum
 {
-  VNET_HW_INTERFACE_RX_MODE_UNKNOWN,
-  VNET_HW_INTERFACE_RX_MODE_POLLING,
-  VNET_HW_INTERFACE_RX_MODE_INTERRUPT,
-  VNET_HW_INTERFACE_RX_MODE_ADAPTIVE,
-  VNET_HW_INTERFACE_RX_MODE_DEFAULT,
-  VNET_HW_INTERFACE_NUM_RX_MODES,
-} vnet_hw_interface_rx_mode;
+  VNET_HW_IF_RX_MODE_UNKNOWN,
+  VNET_HW_IF_RX_MODE_POLLING,
+  VNET_HW_IF_RX_MODE_INTERRUPT,
+  VNET_HW_IF_RX_MODE_ADAPTIVE,
+  VNET_HW_IF_RX_MODE_DEFAULT,
+  VNET_HW_IF_NUM_RX_MODES,
+} vnet_hw_if_rx_mode;
 
 /* Interface up/down callback. */
 typedef clib_error_t *(vnet_interface_function_t)
@@ -68,21 +70,34 @@ typedef clib_error_t *(vnet_subif_add_del_function_t)
   (struct vnet_main_t * vnm, u32 if_index,
    struct vnet_sw_interface_t * template, int is_add);
 
+/* Interface set mtu callback. */
+typedef clib_error_t *(vnet_interface_set_max_frame_size_function_t) (
+  struct vnet_main_t *vnm, struct vnet_hw_interface_t *hi, u32 mtu);
+
 /* Interface set mac address callback. */
 typedef clib_error_t *(vnet_interface_set_mac_address_function_t)
   (struct vnet_hw_interface_t * hi,
    const u8 * old_address, const u8 * new_address);
 
+/* Interface add/del additional mac address callback */
+typedef clib_error_t *(vnet_interface_add_del_mac_address_function_t)
+  (struct vnet_hw_interface_t * hi, const u8 * address, u8 is_add);
+
 /* Interface set rx mode callback. */
 typedef clib_error_t *(vnet_interface_set_rx_mode_function_t)
   (struct vnet_main_t * vnm, u32 if_index, u32 queue_id,
-   vnet_hw_interface_rx_mode mode);
+   vnet_hw_if_rx_mode mode);
 
 /* Interface set l2 mode callback. */
 typedef clib_error_t *(vnet_interface_set_l2_mode_function_t)
   (struct vnet_main_t * vnm, struct vnet_hw_interface_t * hi,
    i32 l2_if_adjust);
 
+/* Interface to set rss queues of the interface */
+typedef clib_error_t *(vnet_interface_rss_queues_set_t)
+  (struct vnet_main_t * vnm, struct vnet_hw_interface_t * hi,
+   clib_bitmap_t * bitmap);
+
 typedef enum
 {
   VNET_FLOW_DEV_OP_ADD_FLOW,
@@ -131,7 +146,7 @@ static void __vnet_interface_function_deinit_##tag##_##f (void)         \
 {                                                                       \
  vnet_main_t * vnm = vnet_get_main();                                   \
  _vnet_interface_function_list_elt_t *next;                             \
- if (vnm->tag##_functions[p]->fp == (void *) &f)                        \
+ if (vnm->tag##_functions[p]->fp == f)                                  \
     {                                                                   \
       vnm->tag##_functions[p] =                                         \
         vnm->tag##_functions[p]->next_interface_function;               \
@@ -140,7 +155,7 @@ static void __vnet_interface_function_deinit_##tag##_##f (void)         \
   next = vnm->tag##_functions[p];                                       \
   while (next->next_interface_function)                                 \
     {                                                                   \
-      if (next->next_interface_function->fp == (void *) &f)             \
+      if (next->next_interface_function->fp == f)                       \
         {                                                               \
           next->next_interface_function =                               \
             next->next_interface_function->next_interface_function;     \
@@ -169,11 +184,21 @@ static __clib_unused void * __clib_unused_##f = f;
   _VNET_INTERFACE_FUNCTION_DECL(f,sw_interface_mtu_change)
 #define VNET_SW_INTERFACE_ADD_DEL_FUNCTION(f)                  \
   _VNET_INTERFACE_FUNCTION_DECL(f,sw_interface_add_del)
+#define VNET_SW_INTERFACE_ADD_DEL_FUNCTION_PRIO(f,p)           \
+  _VNET_INTERFACE_FUNCTION_DECL_PRIO(f,sw_interface_add_del,p)
 #define VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(f)            \
   _VNET_INTERFACE_FUNCTION_DECL(f,sw_interface_admin_up_down)
 #define VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION_PRIO(f,p)             \
   _VNET_INTERFACE_FUNCTION_DECL_PRIO(f,sw_interface_admin_up_down, p)
 
+/**
+ * Tunnel description parameters
+ */
+typedef int (*vnet_dev_class_ip_tunnel_desc_t) (u32 sw_if_index,
+                                               union ip46_address_t_ * src,
+                                               union ip46_address_t_ * dst,
+                                               u8 * is_l2);
+
 /* A class of hardware interface devices. */
 typedef struct _vnet_device_class
 {
@@ -209,6 +234,7 @@ typedef struct _vnet_device_class
 
   /* Error strings indexed by error code for this node. */
   char **tx_function_error_strings;
+  vlib_error_desc_t *tx_function_error_counters;
 
   /* Number of error codes used by this node. */
   u32 tx_function_n_errors;
@@ -235,6 +261,8 @@ typedef struct _vnet_device_class
   /* Format flow offload entry */
   format_function_t *format_flow;
 
+  vnet_dev_class_ip_tunnel_desc_t ip_tun_desc;
+
   /* Function to clear hardware counters for device. */
   void (*clear_counters) (u32 dev_class_instance);
 
@@ -255,8 +283,17 @@ typedef struct _vnet_device_class
 
   /* Function to set mac address. */
   vnet_interface_set_mac_address_function_t *mac_addr_change_function;
+
+  /* Function to add/delete additional MAC addresses */
+  vnet_interface_add_del_mac_address_function_t *mac_addr_add_del_function;
+
+  /* Interface to set rss queues of the interface */
+  vnet_interface_rss_queues_set_t *set_rss_queues_function;
+
 } vnet_device_class_t;
 
+u32 vnet_register_device_class (vlib_main_t *, vnet_device_class_t *);
+
 #ifndef CLIB_MARCH_VARIANT
 #define VNET_DEVICE_CLASS(x,...)                                        \
   __VA_ARGS__ vnet_device_class_t x;                                    \
@@ -284,26 +321,25 @@ __VA_ARGS__ vnet_device_class_t x
 static __clib_unused vnet_device_class_t __clib_unused_##x
 #endif
 
-#define VNET_DEVICE_CLASS_TX_FN(devclass)                              \
-uword CLIB_MARCH_SFX (devclass##_tx_fn)();                             \
-static vlib_node_fn_registration_t                                     \
-  CLIB_MARCH_SFX(devclass##_tx_fn_registration) =                      \
-  { .function = &CLIB_MARCH_SFX (devclass##_tx_fn), };                 \
-                                                                       \
-static void __clib_constructor                                         \
-CLIB_MARCH_SFX (devclass##_tx_fn_multiarch_register) (void)            \
-{                                                                      \
-  extern vnet_device_class_t devclass;                                 \
-  vlib_node_fn_registration_t *r;                                      \
-  r = &CLIB_MARCH_SFX (devclass##_tx_fn_registration);                 \
-  r->priority = CLIB_MARCH_FN_PRIORITY();                              \
-  r->next_registration = devclass.tx_fn_registrations;                 \
-  devclass.tx_fn_registrations = r;                                    \
-}                                                                      \
-uword CLIB_CPU_OPTIMIZED CLIB_MARCH_SFX (devclass##_tx_fn)
-
-/* FIXME to be removed */
-#define VLIB_DEVICE_TX_FUNCTION_MULTIARCH(dev, fn)
+#define VNET_DEVICE_CLASS_TX_FN(devclass)                                     \
+  uword CLIB_MARCH_SFX (devclass##_tx_fn) (                                   \
+    vlib_main_t *, vlib_node_runtime_t *, vlib_frame_t *);                    \
+  static vlib_node_fn_registration_t CLIB_MARCH_SFX (                         \
+    devclass##_tx_fn_registration) = {                                        \
+    .function = &CLIB_MARCH_SFX (devclass##_tx_fn),                           \
+  };                                                                          \
+                                                                              \
+  static void __clib_constructor CLIB_MARCH_SFX (                             \
+    devclass##_tx_fn_multiarch_register) (void)                               \
+  {                                                                           \
+    extern vnet_device_class_t devclass;                                      \
+    vlib_node_fn_registration_t *r;                                           \
+    r = &CLIB_MARCH_SFX (devclass##_tx_fn_registration);                      \
+    r->march_variant = CLIB_MARCH_SFX (CLIB_MARCH_VARIANT_TYPE);              \
+    r->next_registration = devclass.tx_fn_registrations;                      \
+    devclass.tx_fn_registrations = r;                                         \
+  }                                                                           \
+  uword CLIB_MARCH_SFX (devclass##_tx_fn)
 
 /**
  * Link Type: A description of the protocol of packets on the link.
@@ -338,11 +374,17 @@ typedef enum vnet_link_t_
        _link <= VNET_LINK_NSH;       \
        _link++)
 
+#define FOR_EACH_VNET_IP_LINK(_link)    \
+  for (_link = VNET_LINK_IP4;           \
+       _link <= VNET_LINK_IP6;          \
+       _link++)
+
 /**
- * @brief Number of link types. Not part of the enum so it does not have to be included in
- * switch statements
+ * @brief Number of link types. Not part of the enum so it does not have to be
+ * included in switch statements
  */
 #define VNET_LINK_NUM (VNET_LINK_NSH+1)
+#define VNET_N_LINKS VNET_LINK_NUM
 
 /**
  * @brief Convert a link to to an Ethertype
@@ -358,6 +400,10 @@ typedef enum vnet_hw_interface_class_flags_t_
    * @brief a point 2 point interface
    */
   VNET_HW_INTERFACE_CLASS_FLAG_P2P = (1 << 0),
+  /**
+   * @brief a non-broadcast multiple access interface
+   */
+  VNET_HW_INTERFACE_CLASS_FLAG_NBMA = (1 << 1),
 } vnet_hw_interface_class_flags_t;
 
 /* Layer-2 (e.g. Ethernet) interface class. */
@@ -372,6 +418,9 @@ typedef struct _vnet_hw_interface_class
   /* Flags */
   vnet_hw_interface_class_flags_t flags;
 
+  /* tx hash type for interfaces of this hw class */
+  vnet_hash_fn_type_t tx_hash_fn_type;
+
   /* Function to call when hardware interface is added/deleted. */
   vnet_interface_function_t *interface_add_del_function;
 
@@ -384,6 +433,12 @@ typedef struct _vnet_hw_interface_class
   /* Function to call when link MAC changes. */
   vnet_interface_set_mac_address_function_t *mac_addr_change_function;
 
+  /* Function to add/delete additional MAC addresses */
+  vnet_interface_add_del_mac_address_function_t *mac_addr_add_del_function;
+
+  /* Function to set max frame size. */
+  vnet_interface_set_max_frame_size_function_t *set_max_frame_size;
+
   /* Format function to display interface name. */
   format_function_t *format_interface_name;
 
@@ -428,7 +483,7 @@ typedef struct _vnet_hw_interface_class
 } vnet_hw_interface_class_t;
 
 /**
- * @brief Return a complete, zero-length (aka dummy) rewrite
+ * @brief Return a complete, zero-length (aka placeholder) rewrite
  */
 extern u8 *default_build_rewrite (struct vnet_main_t *vnm,
                                  u32 sw_if_index,
@@ -470,32 +525,139 @@ typedef enum vnet_hw_interface_flags_t_
   VNET_HW_INTERFACE_FLAG_HALF_DUPLEX = (1 << 1),
   VNET_HW_INTERFACE_FLAG_FULL_DUPLEX = (1 << 2),
 
-  /* rx mode flags */
-  VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE = (1 << 16),
-
-  /* tx checksum offload */
-  VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD = (1 << 17),
+  /* non-broadcast multiple access */
+  VNET_HW_INTERFACE_FLAG_NBMA = (1 << 19),
 } vnet_hw_interface_flags_t;
 
+#define foreach_vnet_hw_if_caps                                               \
+  _ (0, TX_IP4_CKSUM, "ip4-csum-tx")                                          \
+  _ (1, TX_TCP_CKSUM, "tcp-csum-tx")                                          \
+  _ (2, TX_UDP_CKSUM, "udp-csum-tx")                                          \
+  _ (3, TX_IP4_OUTER_CKSUM, "outer-ip4-csum-tx")                              \
+  _ (4, TX_UDP_OUTER_CKSUM, "outer-udp-csum-tx")                              \
+  _ (5, RX_IP4_CKSUM, "ip4-csum-rx")                                          \
+  _ (6, RX_TCP_CKSUM, "tcp-csum-rx")                                          \
+  _ (7, RX_UDP_CKSUM, "udp-csum-rx")                                          \
+  _ (8, RX_IP4_OUTER_CKSUM, "outer-ip4-csum-rx")                              \
+  _ (9, RX_UDP_OUTER_CKSUM, "outer-udp-csum-rx")                              \
+  _ (10, TCP_GSO, "tcp-tso")                                                  \
+  _ (11, UDP_GSO, "udp-gso")                                                  \
+  _ (12, VXLAN_TNL_GSO, "vxlan-tnl-gso")                                      \
+  _ (13, IPIP_TNL_GSO, "ipip-tnl-gso")                                        \
+  _ (14, GENEVE_TNL_GSO, "geneve-tnl-gso")                                    \
+  _ (15, GRE_TNL_GSO, "gre-tnl-gso")                                          \
+  _ (16, UDP_TNL_GSO, "udp-tnl-gso")                                          \
+  _ (17, IP_TNL_GSO, "ip-tnl-gso")                                            \
+  _ (18, TCP_LRO, "tcp-lro")                                                  \
+  _ (30, INT_MODE, "int-mode")                                                \
+  _ (31, MAC_FILTER, "mac-filter")
+
+typedef enum vnet_hw_if_caps_t_
+{
+  VNET_HW_INTERFACE_CAP_NONE,
+#define _(bit, sfx, str) VNET_HW_IF_CAP_##sfx = (1 << (bit)),
+  foreach_vnet_hw_if_caps
+#undef _
+
+} vnet_hw_if_caps_t;
+
+#define VNET_HW_IF_CAP_L4_TX_CKSUM                                            \
+  (VNET_HW_IF_CAP_TX_TCP_CKSUM | VNET_HW_IF_CAP_TX_UDP_CKSUM)
+
+#define VNET_HW_IF_CAP_TX_CKSUM                                               \
+  (VNET_HW_IF_CAP_TX_IP4_CKSUM | VNET_HW_IF_CAP_TX_TCP_CKSUM |                \
+   VNET_HW_IF_CAP_TX_UDP_CKSUM)
+
+#define VNET_HW_IF_CAP_TX_OUTER_CKSUM                                         \
+  (VNET_HW_IF_CAP_TX_IP4_OUTER_CKSUM | VNET_HW_IF_CAP_TX_UDP_OUTER_CKSUM)
+
+#define VNET_HW_IF_CAP_TX_CKSUM_MASK                                          \
+  (VNET_HW_IF_CAP_TX_CKSUM | VNET_HW_IF_CAP_TX_OUTER_CKSUM)
+
+#define VNET_HW_IF_CAP_L4_RX_CKSUM                                            \
+  (VNET_HW_IF_CAP_RX_TCP_CKSUM | VNET_HW_IF_CAP_RX_UDP_CKSUM)
+
+#define VNET_HW_IF_CAP_RX_CKSUM                                               \
+  (VNET_HW_IF_CAP_RX_IP4_CKSUM | VNET_HW_IF_CAP_RX_TCP_CKSUM |                \
+   VNET_HW_IF_CAP_RX_UDP_CKSUM)
+
+#define VNET_HW_IF_CAP_TNL_GSO_MASK                                           \
+  VNET_HW_IF_CAP_VXLAN_TNL_GSO | VNET_HW_IF_CAP_IPIP_TNL_GSO
+
 #define VNET_HW_INTERFACE_FLAG_DUPLEX_SHIFT 1
 #define VNET_HW_INTERFACE_FLAG_SPEED_SHIFT  3
 #define VNET_HW_INTERFACE_FLAG_DUPLEX_MASK     \
   (VNET_HW_INTERFACE_FLAG_HALF_DUPLEX |                \
    VNET_HW_INTERFACE_FLAG_FULL_DUPLEX)
 
+typedef struct
+{
+  /* hw interface index */
+  u32 hw_if_index;
+
+  /* device instance */
+  u32 dev_instance;
+
+  /* index of thread pollling this queue */
+  u32 thread_index;
+
+  /* file index of queue interrupt line */
+  u32 file_index;
+
+  /* hardware queue identifier */
+  u32 queue_id;
+
+  /* mode */
+  vnet_hw_if_rx_mode mode : 8;
+#define VNET_HW_IF_RXQ_THREAD_ANY      ~0
+#define VNET_HW_IF_RXQ_NO_RX_INTERRUPT ~0
+} vnet_hw_if_rx_queue_t;
+
+typedef struct
+{
+  u8 shared_queue : 1;
+  /* hw interface index */
+  u32 hw_if_index;
+
+  /* hardware queue identifier */
+  u32 queue_id;
+
+  /* bitmap of threads which use this queue */
+  clib_bitmap_t *threads;
+} vnet_hw_if_tx_queue_t;
+
+typedef enum
+{
+  VNET_HW_IF_TX_FRAME_HINT_NOT_CHAINED = (1 << 0),
+  VNET_HW_IF_TX_FRAME_HINT_NO_GSO = (1 << 1),
+  VNET_HW_IF_TX_FRAME_HINT_NO_CKSUM_OFFLOAD = (1 << 2),
+} vnet_hw_if_tx_frame_hint_t;
+
+typedef struct
+{
+  u8 shared_queue : 1;
+  vnet_hw_if_tx_frame_hint_t hints : 16;
+  u32 queue_id;
+} vnet_hw_if_tx_frame_t;
+
+typedef struct
+{
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+  vnet_hw_if_tx_frame_t *frame;
+  u32 *lookup_table;
+  u32 n_queues;
+} vnet_hw_if_output_node_runtime_t;
+
 /* Hardware-interface.  This corresponds to a physical wire
    that packets flow over. */
 typedef struct vnet_hw_interface_t
 {
-  /* Interface name. */
-  u8 *name;
-
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
   /* flags */
   vnet_hw_interface_flags_t flags;
 
-
-  /* link speed in kbps */
-  u32 link_speed;
+  /* capabilities flags */
+  vnet_hw_if_caps_t caps;
 
   /* Hardware address as vector.  Zero (e.g. zero-length vector) if no
      address for this class (e.g. PPP). */
@@ -505,6 +667,9 @@ typedef struct vnet_hw_interface_t
   /* NAME.{output,tx} nodes for this interface. */
   u32 output_node_index, tx_node_index;
 
+  /* interface-output-arc-end node next index for tx node */
+  u32 if_out_arc_end_node_next_index;
+
   /* (dev_class, dev_instance) uniquely identifies hw interface. */
   u32 dev_class_index;
   u32 dev_instance;
@@ -519,30 +684,42 @@ typedef struct vnet_hw_interface_t
   /* Software index for this hardware interface. */
   u32 sw_if_index;
 
+  /* per thread output-node runtimes */
+  vnet_hw_if_output_node_runtime_t *output_node_thread_runtimes;
+
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
+
+  /* Interface name. */
+  u8 *name;
+
+  /* link speed in kbps */
+  u32 link_speed;
+
   /* Next index in interface-output node for this interface
      used by node function vnet_per_buffer_interface_output() */
   u32 output_node_next_index;
 
+  /* called when hw interface is using transmit side packet steering */
+  vnet_hash_fn_t hf;
+
   /* Maximum transmit rate for this interface in bits/sec. */
   f64 max_rate_bits_per_sec;
 
-  /* Smallest packet size supported by this interface. */
-  u32 min_supported_packet_bytes;
-
-  /* Largest packet size supported by this interface. */
-  u32 max_supported_packet_bytes;
-
   /* Smallest packet size for this interface. */
-  u32 min_packet_bytes;
+  u32 min_frame_size;
+
+  /* Largest frame size for this interface. */
+  u32 max_frame_size;
 
-  /* Largest packet size for this interface. */
-  u32 max_packet_bytes;
+  /* Layer 2 overhead */
+  u16 frame_overhead;
 
   /* Hash table mapping sub interface id to sw_if_index. */
   uword *sub_interface_sw_if_index_by_id;
 
-  /* Count of number of L2 subinterfaces */
+  /* Count of number of L2 and L3 subinterfaces */
   u32 l2_if_count;
+  u32 l3_if_count;
 
   /* Bonded interface info -
      0       - not a bonded interface nor a slave
@@ -555,18 +732,42 @@ typedef struct vnet_hw_interface_t
   /* Input node */
   u32 input_node_index;
 
-  /* input node cpu index by queue */
-  u32 *input_node_thread_index_by_queue;
+  vnet_hw_if_rx_mode default_rx_mode;
+
+  /* rx queues */
+  u32 *rx_queue_indices;
 
-  /* vnet_hw_interface_rx_mode by queue */
-  u8 *rx_mode_by_queue;
-  vnet_hw_interface_rx_mode default_rx_mode;
+  /* tx queues */
+  u32 *tx_queue_indices;
 
-  /* device input device_and_queue runtime index */
-  uword *dq_runtime_index_by_queue;
+  /* numa node that hardware device connects to */
+  u8 numa_node;
 
+  /* rss queues bitmap */
+  clib_bitmap_t *rss_queues;
+
+  /* trace */
+  i32 n_trace;
+
+  u32 trace_classify_table_index;
 } vnet_hw_interface_t;
 
+STATIC_ASSERT_OFFSET_OF (vnet_hw_interface_t, cacheline1,
+                        CLIB_CACHE_LINE_BYTES);
+
+typedef struct
+{
+  u32 dev_instance;
+  u32 queue_id;
+} vnet_hw_if_rxq_poll_vector_t;
+
+typedef struct
+{
+  vnet_hw_if_rxq_poll_vector_t *rxq_vector_int;
+  vnet_hw_if_rxq_poll_vector_t *rxq_vector_poll;
+  void *rxq_interrupts;
+} vnet_hw_if_rx_node_runtime_t;
+
 extern vnet_device_class_t vnet_local_interface_device_class;
 
 typedef enum
@@ -657,11 +858,11 @@ typedef enum vnet_sw_interface_flags_t_
   /* Interface is disabled for forwarding: punt all traffic to slow-path. */
   VNET_SW_INTERFACE_FLAG_PUNT = (1 << 1),
 
-  VNET_SW_INTERFACE_FLAG_PROXY_ARP = (1 << 2),
+  __VNET_SW_INTERFACE_FLAG_UNSUED = (1 << 2),
 
   VNET_SW_INTERFACE_FLAG_UNNUMBERED = (1 << 3),
 
-  VNET_SW_INTERFACE_FLAG_BOND_SLAVE = (1 << 4),
+  __VNET_SW_INTERFACE_FLAG_UNUSED2 = (1 << 4),
 
   /* Interface does not appear in CLI/API */
   VNET_SW_INTERFACE_FLAG_HIDDEN = (1 << 5),
@@ -761,7 +962,7 @@ typedef enum
   _(RX_MULTICAST, rx-multicast, if)            \
   _(RX_BROADCAST, rx-broadcast, if)            \
   _(TX, tx, if)                                        \
-  _(TX_UNICAST, tx-unicast-miss, if)           \
+  _(TX_UNICAST, tx-unicast, if)                        \
   _(TX_MULTICAST, tx-multicast, if)            \
   _(TX_BROADCAST, tx-broadcast, if)
 
@@ -789,11 +990,28 @@ typedef struct
   u32 tx_node_index;
 } vnet_hw_interface_nodes_t;
 
+typedef struct
+{
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+  u32 *split_buffers;
+} vnet_interface_per_thread_data_t;
+
+typedef u8 *(*vnet_buffer_opquae_formatter_t) (const vlib_buffer_t * b,
+                                              u8 * s);
+
 typedef struct
 {
   /* Hardware interfaces. */
   vnet_hw_interface_t *hw_interfaces;
 
+  /* Hardware interface RX queues */
+  vnet_hw_if_rx_queue_t *hw_if_rx_queues;
+  uword *rxq_index_by_hw_if_index_and_queue_id;
+
+  /* Hardware interface TX queues */
+  vnet_hw_if_tx_queue_t *hw_if_tx_queues;
+  uword *txq_index_by_hw_if_index_and_queue_id;
+
   /* Hash table mapping HW interface name to index. */
   uword *hw_interface_by_name;
 
@@ -813,46 +1031,79 @@ typedef struct
 
   /* Software interface counters both simple and combined
      packet and byte counters. */
-  volatile u32 *sw_if_counter_lock;
+  clib_spinlock_t sw_if_counter_lock;
   vlib_simple_counter_main_t *sw_if_counters;
   vlib_combined_counter_main_t *combined_sw_if_counters;
 
   vnet_hw_interface_nodes_t *deleted_hw_interface_nodes;
 
-  /* pcap drop tracing */
-  int drop_pcap_enable;
-  pcap_main_t pcap_main;
-  u8 *pcap_filename;
-  u32 pcap_sw_if_index;
-  u32 pcap_pkts_to_capture;
+  /*
+   * pcap drop tracing
+   * Only the drop filter hash lives here. See ../src/vlib/main.h for
+   * the rest of the variables.
+   */
   uword *pcap_drop_filter_hash;
 
+  /* Buffer metadata format helper functions */
+  vnet_buffer_opquae_formatter_t *buffer_opaque_format_helpers;
+  vnet_buffer_opquae_formatter_t *buffer_opaque2_format_helpers;
+
+  /* per-thread data */
+  vnet_interface_per_thread_data_t *per_thread_data;
+
   /* feature_arc_index */
   u8 output_feature_arc_index;
+
+  /* fast lookup tables */
+  u32 *hw_if_index_by_sw_if_index;
+  u16 *if_out_arc_end_next_index_by_sw_if_index;
 } vnet_interface_main_t;
 
 static inline void
 vnet_interface_counter_lock (vnet_interface_main_t * im)
 {
   if (im->sw_if_counter_lock)
-    while (clib_atomic_test_and_set (im->sw_if_counter_lock))
-      /* zzzz */ ;
+    clib_spinlock_lock (&im->sw_if_counter_lock);
 }
 
 static inline void
 vnet_interface_counter_unlock (vnet_interface_main_t * im)
 {
   if (im->sw_if_counter_lock)
-    clib_atomic_release (im->sw_if_counter_lock);
+    clib_spinlock_unlock (&im->sw_if_counter_lock);
 }
 
 void vnet_pcap_drop_trace_filter_add_del (u32 error_index, int is_add);
 
 int vnet_interface_name_renumber (u32 sw_if_index, u32 new_show_dev_instance);
 
-uword vnet_interface_output_node (vlib_main_t * vm,
-                                 vlib_node_runtime_t * node,
-                                 vlib_frame_t * frame);
+void vnet_register_format_buffer_opaque_helper
+  (vnet_buffer_opquae_formatter_t fn);
+
+void vnet_register_format_buffer_opaque2_helper
+  (vnet_buffer_opquae_formatter_t fn);
+
+typedef struct
+{
+  u8 *filename;
+  int enable;
+  int status;
+  u32 packets_to_capture;
+  u32 max_bytes_per_pkt;
+  u8 rx_enable;
+  u8 tx_enable;
+  u8 drop_enable;
+  u8 preallocate_data;
+  u8 free_data;
+  u32 sw_if_index;
+  int filter;
+  vlib_error_t drop_err;
+} vnet_pcap_dispatch_trace_args_t;
+
+int vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t *);
+
+extern vlib_node_registration_t vnet_interface_output_node;
+extern vlib_node_registration_t vnet_interface_output_arc_end_node;
 
 #endif /* included_vnet_interface_h */