|
FD.io VPP
v21.10.1-2-g0a485f517
Vector Packet Processing
|
Go to the documentation of this file.
20 #include <sys/ioctl.h>
21 #include <linux/ethtool.h>
22 #include <linux/if_link.h>
23 #include <linux/sockios.h>
24 #include <bpf/libbpf.h>
77 af_xdp_log (VLIB_LOG_LEVEL_ERR, ad,
"set unicast not supported yet");
81 "set promiscuous not supported yet");
84 af_xdp_log (VLIB_LOG_LEVEL_ERR, ad,
"set mtu not supported yet");
88 af_xdp_log (VLIB_LOG_LEVEL_ERR, ad,
"unknown flag %x requested",
flags);
97 struct xsk_socket **xsk;
98 struct xsk_umem **umem;
111 xsk_socket__delete (*xsk);
114 xsk_umem__delete (*umem);
122 bpf_object__unload (ad->
bpf_obj);
142 args->
rv = VNET_API_ERROR_INVALID_VALUE;
149 if (bpf_prog_load (args->
prog, BPF_PROG_TYPE_XDP, &ad->
bpf_obj, &fd))
151 args->
rv = VNET_API_ERROR_SYSCALL_ERROR_5;
157 #ifndef XDP_FLAGS_REPLACE
158 #define XDP_FLAGS_REPLACE 0
162 args->
rv = VNET_API_ERROR_SYSCALL_ERROR_6;
172 bpf_object__unload (ad->
bpf_obj);
183 struct xsk_umem **umem;
184 struct xsk_socket **xsk;
187 struct xsk_umem_config umem_config;
188 struct xsk_socket_config sock_config;
189 struct xdp_options opt;
191 const int is_rx = qid < ad->
rxq_num;
192 const int is_tx = qid < ad->
txq_num;
203 struct xsk_ring_cons *rx = is_rx ? &rxq->
rx : 0;
204 struct xsk_ring_prod *fq = &rxq->
fq;
205 struct xsk_ring_prod *tx = is_tx ? &txq->
tx : 0;
206 struct xsk_ring_cons *cq = &txq->
cq;
209 memset (&umem_config, 0,
sizeof (umem_config));
210 umem_config.fill_size = args->
rxq_size;
211 umem_config.comp_size = args->
txq_size;
212 umem_config.frame_size =
215 umem_config.flags = XDP_UMEM_UNALIGNED_CHUNK_FLAG;
220 args->
rv = VNET_API_ERROR_SYSCALL_ERROR_1;
225 memset (&sock_config, 0,
sizeof (sock_config));
226 sock_config.rx_size = args->
rxq_size;
227 sock_config.tx_size = args->
txq_size;
228 sock_config.bind_flags = XDP_USE_NEED_WAKEUP;
234 sock_config.bind_flags |= XDP_COPY;
237 sock_config.bind_flags |= XDP_ZEROCOPY;
240 if (xsk_socket__create
241 (xsk, ad->
linux_ifname, qid, *umem, rx, tx, &sock_config))
243 args->
rv = VNET_API_ERROR_SYSCALL_ERROR_2;
246 "xsk_socket__create() failed (is linux netdev %s up?)",
251 fd = xsk_socket__fd (*xsk);
252 optlen =
sizeof (opt);
253 if (getsockopt (fd, SOL_XDP, XDP_OPTIONS, &opt, &optlen))
255 args->
rv = VNET_API_ERROR_SYSCALL_ERROR_3;
260 if (opt.flags & XDP_OPTIONS_ZEROCOPY)
261 ad->
flags |= AF_XDP_DEVICE_F_ZEROCOPY;
263 rxq->
xsk_fd = is_rx ? fd : -1;
268 if (is_rx && (ad->
flags & AF_XDP_DEVICE_F_SYSCALL_LOCK))
293 xsk_socket__delete (*xsk);
295 xsk_umem__delete (*umem);
310 (
char *)
format (0,
"/sys/class/net/%s/device/numa_node%c", ifname, 0);
323 struct ethtool_channels ec = { .cmd = ETHTOOL_GCHANNELS };
324 struct ifreq ifr = { .ifr_data = (
void *) &ec };
327 *rxq_num = *txq_num = 1;
329 fd = socket (AF_INET, SOCK_DGRAM, 0);
333 snprintf (ifr.ifr_name, sizeof (ifr.ifr_name),
"%s", ifname);
334 err = ioctl (fd, SIOCETHTOOL, &ifr);
341 *rxq_num =
clib_max (ec.combined_count, ec.rx_count);
342 *txq_num =
clib_max (ec.combined_count, ec.tx_count);
354 const af_xdp_rxq_mode_t
mode)
369 if (ad->
flags & AF_XDP_DEVICE_F_SYSCALL_LOCK)
371 "kernel workaround incompatible with interrupt mode");
380 fm->file_update (
f, update);
394 int rxq_num, txq_num, q_num;
403 args->
rv = VNET_API_ERROR_INVALID_VALUE;
412 args->
rv = VNET_API_ERROR_INVALID_VALUE;
415 "queue size must be a power of two between %i and 65535",
423 args->
rv = VNET_API_ERROR_INVALID_VALUE;
435 ad->
flags |= AF_XDP_DEVICE_F_SYSCALL_LOCK;
443 q_num =
clib_max (rxq_num, txq_num);
452 for (
i = 0;
i < q_num;
i++)
473 if (i < rxq_num && AF_XDP_NUM_RX_QUEUES_ALL != args->rxq_num)
512 args->
rv = VNET_API_ERROR_INVALID_INTERFACE;
533 .file_descriptor = rxq->
xsk_fd,
571 if (ad->
flags & AF_XDP_DEVICE_F_ERROR)
578 ad->
flags |= AF_XDP_DEVICE_F_ADMIN_UP;
584 ad->
flags &= ~AF_XDP_DEVICE_F_ADMIN_UP;
612 ASSERT (0 &&
"unreachable");
652 .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
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
static void af_xdp_get_q_count(const char *ifname, int *rxq_num, int *txq_num)
@ 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