|
FD.io VPP
v21.06-3-gbb25fbf28
Vector Packet Processing
|
Go to the documentation of this file.
20 #include <linux/if_link.h>
21 #include <bpf/libbpf.h>
74 af_xdp_log (VLIB_LOG_LEVEL_ERR, ad,
"set unicast not supported yet");
78 "set promiscuous not supported yet");
81 af_xdp_log (VLIB_LOG_LEVEL_ERR, ad,
"set mtu not supported yet");
85 af_xdp_log (VLIB_LOG_LEVEL_ERR, ad,
"unknown flag %x requested",
flags);
94 struct xsk_socket **xsk;
95 struct xsk_umem **umem;
111 xsk_socket__delete (*xsk);
114 xsk_umem__delete (*umem);
119 bpf_object__unload (ad->
bpf_obj);
139 args->
rv = VNET_API_ERROR_INVALID_VALUE;
146 if (bpf_prog_load (args->
prog, BPF_PROG_TYPE_XDP, &ad->
bpf_obj, &fd))
148 args->
rv = VNET_API_ERROR_SYSCALL_ERROR_5;
154 #ifndef XDP_FLAGS_REPLACE
155 #define XDP_FLAGS_REPLACE 0
159 args->
rv = VNET_API_ERROR_SYSCALL_ERROR_6;
169 bpf_object__unload (ad->
bpf_obj);
180 struct xsk_umem **umem;
181 struct xsk_socket **xsk;
184 struct xsk_umem_config umem_config;
185 struct xsk_socket_config sock_config;
186 struct xdp_options opt;
188 const int is_rx = qid < ad->
rxq_num;
189 const int is_tx = qid < ad->
txq_num;
207 struct xsk_ring_cons *rx = is_rx ? &rxq->
rx : 0;
208 struct xsk_ring_prod *fq = &rxq->
fq;
209 struct xsk_ring_prod *tx = is_tx ? &txq->
tx : 0;
210 struct xsk_ring_cons *cq = &txq->
cq;
213 memset (&umem_config, 0,
sizeof (umem_config));
214 umem_config.fill_size = args->
rxq_size;
215 umem_config.comp_size = args->
txq_size;
216 umem_config.frame_size =
219 umem_config.flags = XDP_UMEM_UNALIGNED_CHUNK_FLAG;
224 args->
rv = VNET_API_ERROR_SYSCALL_ERROR_1;
229 memset (&sock_config, 0,
sizeof (sock_config));
230 sock_config.rx_size = args->
rxq_size;
231 sock_config.tx_size = args->
txq_size;
232 sock_config.bind_flags = XDP_USE_NEED_WAKEUP;
238 sock_config.bind_flags |= XDP_COPY;
241 sock_config.bind_flags |= XDP_ZEROCOPY;
244 if (xsk_socket__create
245 (xsk, ad->
linux_ifname, qid, *umem, rx, tx, &sock_config))
247 args->
rv = VNET_API_ERROR_SYSCALL_ERROR_2;
250 "xsk_socket__create() failed (is linux netdev %s up?)",
255 fd = xsk_socket__fd (*xsk);
256 optlen =
sizeof (opt);
257 if (getsockopt (fd, SOL_XDP, XDP_OPTIONS, &opt, &optlen))
259 args->
rv = VNET_API_ERROR_SYSCALL_ERROR_3;
264 if (opt.flags & XDP_OPTIONS_ZEROCOPY)
265 ad->
flags |= AF_XDP_DEVICE_F_ZEROCOPY;
267 rxq->
xsk_fd = is_rx ? fd : -1;
272 if (is_rx && (ad->
flags & AF_XDP_DEVICE_F_SYSCALL_LOCK))
297 xsk_socket__delete (*xsk);
299 xsk_umem__delete (*umem);
314 (
char *)
format (0,
"/sys/class/net/%s/device/numa_node%c", ifname, 0);
333 const af_xdp_rxq_mode_t
mode)
348 if (ad->
flags & AF_XDP_DEVICE_F_SYSCALL_LOCK)
350 "kernel workaround incompatible with interrupt mode");
359 fm->file_update (
f, update);
373 int rxq_num, txq_num, q_num;
383 args->
rv = VNET_API_ERROR_INVALID_VALUE;
392 args->
rv = VNET_API_ERROR_INVALID_VALUE;
395 "queue size must be a power of two between %i and 65535",
404 ad->
flags |= AF_XDP_DEVICE_F_SYSCALL_LOCK;
412 q_num =
clib_max (rxq_num, txq_num);
415 for (
i = 0;
i < q_num;
i++)
475 args->
rv = VNET_API_ERROR_INVALID_INTERFACE;
496 .file_descriptor = rxq->
xsk_fd,
534 if (ad->
flags & AF_XDP_DEVICE_F_ERROR)
541 ad->
flags |= AF_XDP_DEVICE_F_ADMIN_UP;
547 ad->
flags &= ~AF_XDP_DEVICE_F_ADMIN_UP;
575 ASSERT (0 &&
"unreachable");
615 .name =
"AF_XDP interface",
#define af_xdp_log(lvl, dev, f,...)
static int af_xdp_create_queue(vlib_main_t *vm, af_xdp_create_if_args_t *args, af_xdp_device_t *ad, int qid)
static void clib_spinlock_init(clib_spinlock_t *p)
#define VNET_HW_IF_RXQ_THREAD_ANY
u8 buffer_pool_index
index of buffer pool this buffer belongs.
clib_file_main_t file_main
af_xdp_create_flag_t flags
static clib_error_t * af_xdp_interface_rx_mode_change(vnet_main_t *vnm, u32 hw_if_index, u32 qid, vnet_hw_if_rx_mode mode)
@ VNET_HW_IF_RX_MODE_ADAPTIVE
vnet_hw_interface_capabilities_t caps
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
__clib_export errno_t memcpy_s(void *__restrict__ dest, rsize_t dmax, const void *__restrict__ src, rsize_t n)
copy src to dest, at most n bytes, up to dmax
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
format_function_t format_af_xdp_device_name
#define clib_error_return(e, args...)
VNET_DEVICE_CLASS(af_xdp_device_class)
af_xdp_device_t * devices
unsigned int if_nametoindex(const char *ifname)
vl_api_tunnel_mode_t mode
@ VNET_SW_INTERFACE_FLAG_ADMIN_UP
#define pool_put(P, E)
Free an object E in pool P.
@ VNET_HW_IF_RX_MODE_POLLING
vlib_buffer_main_t * buffer_main
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
@ VNET_HW_INTERFACE_FLAG_LINK_UP
vnet_device_class_t af_xdp_device_class
@ VNET_HW_IF_NUM_RX_MODES
static char * af_xdp_tx_func_error_strings[]
static int af_xdp_get_numa(const char *ifname)
@ VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT
clib_spinlock_t syscall_lock
#define vlib_log_err(...)
#define XDP_FLAGS_REPLACE
__clib_export u8 * format_clib_error(u8 *s, va_list *va)
void af_xdp_create_if(vlib_main_t *vm, af_xdp_create_if_args_t *args)
vlib_buffer_t * buffer_template
#define vec_elt(v, i)
Get vector value at index i.
__clib_export clib_error_t * clib_sysfs_read(char *file_name, char *fmt,...)
#define clib_error_return_code(e, code, flags, args...)
#define clib_error_create(args...)
clib_error_t * af_xdp_init(vlib_main_t *vm)
gdb_af_xdp_pair_t gdb_af_xdp_get_cons(const struct xsk_ring_cons *cons)
af_xdp_main_t af_xdp_main
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
vnet_main_t * vnet_get_main(void)
static clib_error_t * af_xdp_mac_change(vnet_hw_interface_t *hw, const u8 *old, const u8 *new)
clib_spinlock_t syscall_lock
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
void vnet_hw_if_update_runtime_data(vnet_main_t *vnm, u32 hw_if_index)
@ VNET_HW_IF_RX_MODE_INTERRUPT
sll srl srl sll sra u16x4 i
static void clib_spinlock_free(clib_spinlock_t *p)
#define ETHERNET_INTERFACE_FLAG_MTU
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment)
static_always_inline void vnet_hw_if_rx_queue_set_int_pending(vnet_main_t *vnm, u32 queue_index)
volatile u8 ref_count
Reference count for this buffer.
@ VNET_HW_IF_RX_MODE_DEFAULT
struct bpf_object * bpf_obj
#define CLIB_CACHE_LINE_BYTES
static int af_xdp_load_program(af_xdp_create_if_args_t *args, af_xdp_device_t *ad)
void vnet_hw_if_set_rx_queue_file_index(vnet_main_t *vnm, u32 queue_index, u32 file_index)
@ UNIX_FILE_UPDATE_DELETE
static clib_file_t * clib_file_get(clib_file_main_t *fm, u32 file_index)
gdb_af_xdp_pair_t gdb_af_xdp_get_prod(const struct xsk_ring_prod *prod)
@ AF_XDP_RXQ_MODE_INTERRUPT
#define vec_set_len(v, l)
Set vector length to a user-defined value.
static void af_xdp_clear(u32 dev_instance)
#define vec_free(V)
Free vector's memory (no header).
static void ethernet_mac_address_generate(u8 *mac)
void af_xdp_device_input_refill(af_xdp_device_t *ad)
static clib_error_t * af_xdp_device_rxq_read_ready(clib_file_t *f)
static clib_error_t * af_xdp_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
description fragment has unexpected format
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
static_always_inline u32 vlib_buffer_get_default_data_size(vlib_main_t *vm)
#define VLIB_INIT_FUNCTION(x)
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
format_function_t format_af_xdp_device
#define vec_foreach(var, vec)
Vector iterator.
#define clib_error_return_unix(e, args...)
static uword clib_file_add(clib_file_main_t *um, clib_file_t *template)
#define AF_XDP_NUM_RX_QUEUES_ALL
static u8 vlib_buffer_pool_get_default_for_numa(vlib_main_t *vm, u32 numa_node)
u32 vnet_hw_if_register_rx_queue(vnet_main_t *vnm, u32 hw_if_index, u32 queue_id, u32 thread_index)
static vlib_main_t * vlib_get_main(void)
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags)
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
#define ETHERNET_INTERFACE_FLAG_ACCEPT_ALL
#define uword_to_pointer(u, type)
void af_xdp_delete_if(vlib_main_t *vm, af_xdp_device_t *ad)
vlib_node_registration_t af_xdp_input_node
(constructor) VLIB_REGISTER_NODE (af_xdp_input_node)
static void clib_file_del_by_index(clib_file_main_t *um, uword index)
@ VNET_HW_INTERFACE_CAP_SUPPORTS_INT_MODE
#define clib_error_free(e)
static clib_error_t * af_xdp_device_set_rxq_mode(const af_xdp_device_t *ad, af_xdp_rxq_t *rxq, const af_xdp_rxq_mode_t mode)
static void af_xdp_set_interface_next_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
u32 per_interface_next_index
static vlib_thread_main_t * vlib_get_thread_main()
static uword is_pow2(uword x)
#define foreach_af_xdp_tx_func_error
@ AF_XDP_RXQ_MODE_POLLING
@ AF_XDP_CREATE_FLAGS_NO_SYSCALL_LOCK
static u32 af_xdp_flag_change(vnet_main_t *vnm, vnet_hw_interface_t *hw, u32 flags)
clib_error_t * ethernet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, const u8 *address, u32 *hw_if_index_return, ethernet_flag_change_function_t flag_change)
void vnet_hw_if_set_input_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
@ VNET_HW_IF_RX_MODE_UNKNOWN
VLIB buffer representation.
vl_api_wireguard_peer_flags_t flags