|
FD.io VPP
v21.10.1-2-g0a485f517
Vector Packet Processing
|
Go to the documentation of this file.
22 #include <sys/ioctl.h>
23 #include <sys/socket.h>
26 #include <sys/types.h>
28 #include <netinet/in.h>
31 #include <linux/if_arp.h>
32 #include <linux/if_tun.h>
57 #define VHOST_USER_TX_COPY_THRESHOLD (VHOST_USER_COPY_ARRAY_N - 200)
61 #define foreach_vhost_user_tx_func_error \
63 _(NOT_READY, "vhost vring not ready") \
64 _(DOWN, "vhost interface is down") \
65 _(PKT_DROP_NOBUF, "tx packet drops (no available descriptors)") \
66 _(PKT_DROP_NOMRG, "tx packet drops (cannot merge descriptors)") \
67 _(MMAP_FAIL, "mmap failure") \
68 _(INDIRECT_OVERFLOW, "indirect descriptor table overflow")
72 #define _(f,s) VHOST_USER_TX_FUNC_ERROR_##f,
84 static __clib_unused
u8 *
88 u32 show_dev_instance = ~0;
94 if (show_dev_instance != ~0)
95 i = show_dev_instance;
97 s =
format (s,
"VirtualEthernet0/0/%d",
i);
101 static __clib_unused
int
110 hi->dev_instance, ~0);
115 vu_log_debug (vui,
"renumbered vhost-user interface dev_instance %d to %d",
116 hi->dev_instance, new_dev_instance);
136 hdr_desc = &rxvq->
desc[desc_current];
158 u16 copy_len,
u32 * map_hint)
160 void *dst0, *dst1, *dst2, *dst3;
205 virtio_net_hdr_t * hdr)
208 int is_ip4 =
b->
flags & VNET_BUFFER_F_IS_IP4;
214 if (oflags & VNET_BUFFER_OFFLOAD_F_IP_CKSUM)
224 if (oflags & VNET_BUFFER_OFFLOAD_F_UDP_CKSUM)
230 else if (oflags & VNET_BUFFER_OFFLOAD_F_TCP_CKSUM)
238 if (
b->
flags & VNET_BUFFER_F_GSO)
240 if (oflags & VNET_BUFFER_OFFLOAD_F_TCP_CKSUM)
256 (oflags & VNET_BUFFER_OFFLOAD_F_UDP_CKSUM))
267 u16 * n_descs_processed,
u8 chained,
271 vring_packed_desc_t *desc_table = rxvq->
packed_desc;
286 for (desc_idx = 1; desc_idx < *n_descs_processed; desc_idx++)
299 *n_descs_processed = 0;
303 vring_packed_desc_t *desc_table = rxvq->
packed_desc;
315 (rxvq->
avail_event->flags != VRING_EVENT_F_DISABLE))
332 u32 desc_current = last_avail_idx & rxvq->
qsz_mask;
333 vring_packed_desc_t *hdr_desc = 0;
377 vring_packed_desc_t *desc_table;
379 u16 desc_head, desc_index, desc_len;
380 u16 n_descs_processed;
381 u8 indirect, chained;
384 error = VHOST_USER_TX_FUNC_ERROR_NONE;
387 n_descs_processed = 0;
392 uword buffer_map_addr;
395 u32 total_desc_len = 0;
416 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
427 sizeof (vring_packed_desc_t)))
429 error = VHOST_USER_TX_FUNC_ERROR_INDIRECT_OVERFLOW;
432 n_entries = desc_table[desc_head].len >> 4;
437 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
446 buffer_map_addr = desc_table[desc_index].addr;
447 buffer_len = desc_table[desc_index].len;
450 virtio_net_hdr_mrg_rxbuf_t *hdr = &cpu->
tx_headers[tx_headers_len];
454 hdr->num_buffers = 1;
456 or_flags = (b0->
flags & VNET_BUFFER_F_OFFLOAD);
468 cpy->
dst = buffer_map_addr;
495 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
501 buffer_map_addr = desc_table[desc_index].addr;
502 buffer_len = desc_table[desc_index].len;
503 total_desc_len += desc_len;
519 error = VHOST_USER_TX_FUNC_ERROR_INDIRECT_OVERFLOW;
522 total_desc_len += desc_len;
523 desc_index = (desc_index + 1) & rxvq->
qsz_mask;
524 buffer_map_addr = desc_table[desc_index].addr;
525 buffer_len = desc_table[desc_index].len;
534 virtio_net_hdr_mrg_rxbuf_t *hdr =
537 desc_table[desc_index].len = desc_len;
539 desc_head = desc_index =
551 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
555 buffer_map_addr = desc_table[desc_index].addr;
556 buffer_len = desc_table[desc_index].len;
560 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOMRG;
568 cpy->
len = bytes_left;
569 cpy->
len = (cpy->
len > buffer_len) ? buffer_len : cpy->
len;
570 cpy->
dst = buffer_map_addr;
574 bytes_left -= cpy->
len;
575 buffer_len -= cpy->
len;
576 buffer_map_addr += cpy->
len;
577 desc_len += cpy->
len;
585 (current_b0->
flags & VLIB_BUFFER_NEXT_PRESENT))
599 total_desc_len += desc_len;
619 VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL, 1);
636 VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL, 1);
654 if (
n_left && (
error == VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF) && retry)
671 return frame->n_vectors;
698 error = VHOST_USER_TX_FUNC_ERROR_DOWN;
704 error = VHOST_USER_TX_FUNC_ERROR_NOT_READY;
709 rxvq = &vui->vrings[qid];
714 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
724 error = VHOST_USER_TX_FUNC_ERROR_NONE;
730 u16 desc_head, desc_index, desc_len;
732 uword buffer_map_addr;
750 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
754 desc_table = rxvq->
desc;
755 desc_head = desc_index =
765 error = VHOST_USER_TX_FUNC_ERROR_INDIRECT_OVERFLOW;
773 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
779 desc_len = vui->virtio_net_hdr_sz;
780 buffer_map_addr = desc_table[desc_index].
addr;
781 buffer_len = desc_table[desc_index].
len;
785 virtio_net_hdr_mrg_rxbuf_t *hdr = &cpu->
tx_headers[tx_headers_len];
789 hdr->num_buffers = 1;
791 or_flags = (b0->
flags & VNET_BUFFER_F_OFFLOAD);
802 cpy->
len = vui->virtio_net_hdr_sz;
803 cpy->
dst = buffer_map_addr;
807 buffer_map_addr += vui->virtio_net_hdr_sz;
808 buffer_len -= vui->virtio_net_hdr_sz;
818 desc_index = desc_table[desc_index].
next;
819 buffer_map_addr = desc_table[desc_index].
addr;
820 buffer_len = desc_table[desc_index].
len;
822 else if (vui->virtio_net_hdr_sz == 12)
824 virtio_net_hdr_mrg_rxbuf_t *hdr =
847 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
851 desc_table = rxvq->
desc;
852 desc_head = desc_index =
862 error = VHOST_USER_TX_FUNC_ERROR_INDIRECT_OVERFLOW;
871 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
876 buffer_map_addr = desc_table[desc_index].
addr;
877 buffer_len = desc_table[desc_index].
len;
881 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOMRG;
890 cpy->
len = bytes_left;
891 cpy->
len = (cpy->
len > buffer_len) ? buffer_len : cpy->
len;
892 cpy->
dst = buffer_map_addr;
896 bytes_left -= cpy->
len;
897 buffer_len -= cpy->
len;
898 buffer_map_addr += cpy->
len;
899 desc_len += cpy->
len;
908 (current_b0->
flags & VLIB_BUFFER_NEXT_PRESENT))
946 VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL, 1);
964 VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL, 1);
983 if (
n_left && (
error == VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF) && retry)
1012 return frame->n_vectors;
1034 vu_log_err (vui,
"unhandled mode %d changed for if %d queue %d",
mode,
1095 u8 link_old, link_new;
1103 if (link_old != link_new)
1112 .name =
"vhost-user",
u32 next_buffer
Next buffer for this linked-list of buffers.
static_always_inline void vhost_user_send_call(vlib_main_t *vm, vhost_user_intf_t *vui, vhost_user_vring_t *vq)
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
#define VIRTIO_NET_HDR_GSO_NONE
static_always_inline u8 vui_is_link_up(vhost_user_intf_t *vui)
@ VNET_HW_IF_RX_MODE_ADAPTIVE
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
struct _vnet_device_class vnet_device_class_t
vnet_device_class_t vhost_user_device_class
static_always_inline void vhost_user_log_dirty_pages_2(vhost_user_intf_t *vui, u64 addr, u64 len, u8 is_host_address)
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
struct _tcp_header tcp_header_t
VNET_DEVICE_CLASS(vhost_user_device_class)
static __clib_unused clib_error_t * vhost_user_interface_rx_mode_change(vnet_main_t *vnm, u32 hw_if_index, u32 qid, vnet_hw_if_rx_mode mode)
vlib_main_t vlib_node_runtime_t * node
#define clib_error_return(e, args...)
static __clib_unused u8 * format_vhost_user_interface_name(u8 *s, va_list *args)
static_always_inline uword vhost_user_device_class_packed(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, vhost_user_intf_t *vui, vhost_user_vring_t *rxvq)
u16 device_index
The interface queue index (Not the virtio vring idx)
vl_api_tunnel_mode_t mode
#define VHOST_USER_TX_COPY_THRESHOLD
@ VNET_SW_INTERFACE_FLAG_ADMIN_UP
@ VNET_HW_IF_RX_MODE_POLLING
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
vhost_copy_t copy[VHOST_USER_COPY_ARRAY_N]
static_always_inline void vhost_user_advance_last_avail_table_idx(vhost_user_intf_t *vui, vhost_user_vring_t *vring, u8 chained)
#define VRING_DESC_F_USED
@ VNET_HW_INTERFACE_FLAG_LINK_UP
#define VIRTIO_FEATURE(X)
vlib_simple_counter_main_t * sw_if_counters
vring_desc_event_t * avail_event
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
#define vhost_user_log_dirty_ring(vui, vq, member)
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
static __clib_unused char * vhost_user_tx_func_error_strings[]
static_always_inline u8 vhost_user_packed_desc_available(vhost_user_vring_t *vring, u16 idx)
#define VNET_DEVICE_CLASS_TX_FN(devclass)
@ VHOST_USER_TX_FUNC_N_ERROR
#define VHOST_VRING_IDX_RX(qid)
static_always_inline u64 vhost_user_is_packed_ring_supported(vhost_user_intf_t *vui)
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
#define VIRTIO_NET_HDR_GSO_TCPV4
vhost_user_tx_func_error_t
static_always_inline void vhost_user_advance_last_used_idx(vhost_user_vring_t *vring)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static_always_inline void vhost_user_handle_tx_offload(vhost_user_intf_t *vui, vlib_buffer_t *b, virtio_net_hdr_t *hdr)
static_always_inline void vhost_user_tx_trace(vhost_trace_t *t, vhost_user_intf_t *vui, u16 qid, vlib_buffer_t *b, vhost_user_vring_t *rxvq)
#define VHOST_USER_EVENT_STOP_TIMER
#define VRING_DESC_F_AVAIL
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
u32 virtio_ring_flags
The device index.
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
virtio_net_hdr_mrg_rxbuf_t hdr
Length of the first data descriptor.
static __clib_unused clib_error_t * vhost_user_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
#define static_always_inline
#define VRING_DESC_F_INDIRECT
#define vlib_prefetch_buffer_with_index(vm, bi, type)
Prefetch buffer metadata by buffer index The first 64 bytes of buffer contains most header informatio...
#define vu_log_err(dev, f,...)
#define VIRTIO_NET_HDR_GSO_UDP
vhost_trace_t * current_trace
@ VNET_HW_IF_RX_MODE_INTERRUPT
#define VRING_DESC_F_NEXT
vring_packed_desc_t * packed_desc
vhost_user_vring_t * vrings
#define VRING_AVAIL_F_NO_INTERRUPT
#define CLIB_MEMORY_BARRIER()
#define VHOST_VRING_IDX_TX(qid)
static_always_inline u32 vhost_user_tx_copy(vhost_user_intf_t *vui, vhost_copy_t *cpy, u16 copy_len, u32 *map_hint)
vhost_cpu_t * cpus
Per-CPU data for vhost-user.
u16 current_length
Nbytes between current data and the end of this buffer.
static void * vlib_frame_scalar_args(vlib_frame_t *f)
Get pointer to frame scalar data.
static_always_inline void vhost_user_dequeue_descs(vhost_user_vring_t *rxvq, virtio_net_hdr_mrg_rxbuf_t *hdr, u16 *n_descs_processed)
static __clib_unused int vhost_user_name_renumber(vnet_hw_interface_t *hi, u32 new_dev_instance)
vnet_hw_if_tx_frame_t * tf
#define VHOST_USER_COPY_ARRAY_N
static_always_inline void vhost_user_dequeue_chained_descs(vhost_user_vring_t *rxvq, u16 *n_descs_processed)
#define VHOST_USER_EVENT_START_TIMER
description fragment has unexpected format
#define foreach_vhost_user_tx_func_error
u32 * show_dev_instance_by_real_dev_instance
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header,...
vhost_user_main_t vhost_user_main
#define VIRTIO_NET_HDR_GSO_TCPV6
static_always_inline void clib_prefetch_load(void *p)
static_always_inline void vhost_user_mark_desc_available(vlib_main_t *vm, vhost_user_intf_t *vui, vhost_user_vring_t *rxvq, u16 *n_descs_processed, u8 chained, vlib_frame_t *frame, u32 n_left)
#define VIRTIO_NET_HDR_F_NEEDS_CSUM
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
static_always_inline u8 * format_vhost_trace(u8 *s, va_list *va)
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags)
static_always_inline void vnet_generic_header_offset_parser(vlib_buffer_t *b0, generic_header_offset_t *gho, int is_l2, int is_ip4, int is_ip6)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
static u16 ip4_header_checksum(ip4_header_t *i)
vring_used_elem_t ring[0]
static_always_inline void * map_guest_mem(vhost_user_intf_t *vui, uword addr, u32 *hint)
clib_spinlock_t vring_lock
#define vu_log_debug(dev, f,...)
vhost_user_intf_t * vhost_user_interfaces
u16 first_desc_len
Runtime queue flags
void vhost_user_set_operation_mode(vhost_user_intf_t *vui, vhost_user_vring_t *txvq)
vlib_node_registration_t vhost_user_send_interrupt_node
(constructor) VLIB_REGISTER_NODE (vhost_user_send_interrupt_node)
@ VNET_INTERFACE_COUNTER_DROP
static_always_inline void vhost_user_advance_last_avail_idx(vhost_user_vring_t *vring)
vnet_interface_main_t interface_main
virtio_net_hdr_mrg_rxbuf_t tx_headers[VLIB_FRAME_SIZE]
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
VLIB buffer representation.
static_always_inline void vhost_user_tx_trace_packed(vhost_trace_t *t, vhost_user_intf_t *vui, u16 qid, vlib_buffer_t *b, vhost_user_vring_t *rxvq)
vl_api_wireguard_peer_flags_t flags