#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_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,
/* 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;
} 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; \
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->name = CLIB_MARCH_VARIANT_STR; \
- r->next_registration = devclass.tx_fn_registrations; \
- devclass.tx_fn_registrations = r; \
-} \
-uword CLIB_CPU_OPTIMIZED CLIB_MARCH_SFX (devclass##_tx_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.
_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
/* 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;
/* 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;
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),
+ /* 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 _
- /* tx checksum offload */
- VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD = (1 << 17),
+} vnet_hw_if_caps_t;
- /* gso */
- VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO = (1 << 18),
+#define VNET_HW_IF_CAP_L4_TX_CKSUM \
+ (VNET_HW_IF_CAP_TX_TCP_CKSUM | VNET_HW_IF_CAP_TX_UDP_CKSUM)
- /* non-broadcast multiple access */
- VNET_HW_INTERFACE_FLAG_NBMA = (1 << 19),
+#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)
- /* hw/driver can switch between l2-promisc and l3-dmac-filter modes */
- VNET_HW_INTERFACE_FLAG_SUPPORTS_MAC_FILTER = (1 << 20),
-} vnet_hw_interface_flags_t;
+#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_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
{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
- /* Interface name. */
- u8 *name;
-
/* 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). */
/* 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;
/* 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 packet size for this interface. */
- u32 max_packet_bytes;
+ /* Largest frame size for this interface. */
+ u32 max_frame_size;
+
+ /* Layer 2 overhead */
+ u16 frame_overhead;
/* Hash table mapping sub interface id to sw_if_index. */
uword *sub_interface_sw_if_index_by_id;
/* 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;
+ /* tx queues */
+ u32 *tx_queue_indices;
+
/* numa node that hardware device connects to */
u8 numa_node;
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;
typedef struct
{
- vnet_hw_if_rxq_poll_vector_t *rxq_poll_vector;
+ 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;
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;
/* 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
int vnet_interface_name_renumber (u32 sw_if_index, u32 new_show_dev_instance);
-vlib_node_function_t *vnet_interface_output_node_get (vlib_main_t * vm);
-
void vnet_register_format_buffer_opaque_helper
(vnet_buffer_opquae_formatter_t fn);
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 */
/*