summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/af_xdp/af_xdp.h14
-rw-r--r--src/plugins/af_xdp/device.c75
-rw-r--r--src/plugins/af_xdp/input.c33
3 files changed, 86 insertions, 36 deletions
diff --git a/src/plugins/af_xdp/af_xdp.h b/src/plugins/af_xdp/af_xdp.h
index 3bd53ad768d..568380baa56 100644
--- a/src/plugins/af_xdp/af_xdp.h
+++ b/src/plugins/af_xdp/af_xdp.h
@@ -27,12 +27,12 @@
#define af_xdp_log(lvl, dev, f, ...) \
vlib_log(lvl, af_xdp_main.log_class, "%v: " f, (dev)->name, ##__VA_ARGS__)
-#define foreach_af_xdp_device_flags \
- _(0, INITIALIZED, "initialized") \
- _(1, ERROR, "error") \
- _(2, ADMIN_UP, "admin-up") \
- _(4, LINK_UP, "link-up") \
- _(8, ZEROCOPY, "zero-copy") \
+#define foreach_af_xdp_device_flags \
+ _ (0, INITIALIZED, "initialized") \
+ _ (1, ERROR, "error") \
+ _ (2, ADMIN_UP, "admin-up") \
+ _ (3, LINK_UP, "link-up") \
+ _ (4, ZEROCOPY, "zero-copy")
enum
{
@@ -62,6 +62,8 @@ typedef struct
/* fields below are accessed in control-plane only (cold) */
uword file_index;
+ u32 queue_index;
+ u8 is_polling;
} af_xdp_rxq_t;
typedef struct
diff --git a/src/plugins/af_xdp/device.c b/src/plugins/af_xdp/device.c
index 5090d3a649a..632f1608c1e 100644
--- a/src/plugins/af_xdp/device.c
+++ b/src/plugins/af_xdp/device.c
@@ -25,6 +25,7 @@
#include <vppinfra/linux/sysfs.h>
#include <vppinfra/unix.h>
#include <vnet/ethernet/ethernet.h>
+#include <vnet/interface/rx_queue_funcs.h>
#include "af_xdp.h"
af_xdp_main_t af_xdp_main;
@@ -98,7 +99,6 @@ af_xdp_delete_if (vlib_main_t * vm, af_xdp_device_t * ad)
if (ad->hw_if_index)
{
vnet_hw_interface_set_flags (vnm, ad->hw_if_index, 0);
- vnet_hw_interface_unassign_rx_thread (vnm, ad->hw_if_index, 0);
ethernet_delete_interface (vnm, ad->hw_if_index);
}
@@ -292,15 +292,25 @@ af_xdp_get_numa (const char *ifname)
static clib_error_t *
af_xdp_device_rxq_read_ready (clib_file_t * f)
{
- vnet_main_t *vnm = vnet_get_main ();
- const af_xdp_main_t *am = &af_xdp_main;
- const u32 dev_instance = f->private_data >> 16;
- const u16 qid = f->private_data & 0xffff;
- const af_xdp_device_t *ad = vec_elt_at_index (am->devices, dev_instance);
- vnet_device_input_set_interrupt_pending (vnm, ad->hw_if_index, qid);
+ vnet_hw_if_rx_queue_set_int_pending (vnet_get_main (), f->private_data);
return 0;
}
+static void
+af_xdp_device_set_rxq_mode (af_xdp_rxq_t *rxq, int is_polling)
+{
+ clib_file_main_t *fm = &file_main;
+ clib_file_t *f;
+
+ if (rxq->is_polling == is_polling)
+ return;
+
+ f = clib_file_get (fm, rxq->file_index);
+ fm->file_update (f, is_polling ? UNIX_FILE_UPDATE_DELETE :
+ UNIX_FILE_UPDATE_ADD);
+ rxq->is_polling = !!is_polling;
+}
+
void
af_xdp_create_if (vlib_main_t * vm, af_xdp_create_if_args_t * args)
{
@@ -418,19 +428,25 @@ af_xdp_create_if (vlib_main_t * vm, af_xdp_create_if_args_t * args)
for (i = 0; i < vec_len (ad->rxqs); i++)
{
af_xdp_rxq_t *rxq = vec_elt_at_index (ad->rxqs, i);
+ rxq->queue_index = vnet_hw_if_register_rx_queue (
+ vnm, ad->hw_if_index, i, VNET_HW_IF_RXQ_THREAD_ANY);
+ u8 *desc = format (0, "%U rxq %d", format_af_xdp_device_name,
+ ad->dev_instance, i);
clib_file_t f = {
.file_descriptor = rxq->xsk_fd,
.flags = UNIX_FILE_EVENT_EDGE_TRIGGERED,
- .private_data = (uword) ad->dev_instance << 16 | (uword) i,
+ .private_data = rxq->queue_index,
.read_function = af_xdp_device_rxq_read_ready,
- .description =
- format (0, "%U rxq %d", format_af_xdp_device_name, ad->dev_instance,
- i),
+ .description = desc,
};
rxq->file_index = clib_file_add (&file_main, &f);
- vnet_hw_interface_assign_rx_thread (vnm, ad->hw_if_index, i, ~0);
+ vnet_hw_if_set_rx_queue_file_index (vnm, rxq->queue_index,
+ rxq->file_index);
+ af_xdp_device_set_rxq_mode (rxq, 1 /* polling */);
}
+ vnet_hw_if_update_runtime_data (vnm, ad->hw_if_index);
+
/* buffer template */
vec_validate_aligned (ad->buffer_template, 1, CLIB_CACHE_LINE_BYTES);
ad->buffer_template->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID;
@@ -472,6 +488,37 @@ af_xdp_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
return 0;
}
+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)
+{
+ af_xdp_main_t *am = &af_xdp_main;
+ vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
+ af_xdp_device_t *ad = pool_elt_at_index (am->devices, hw->dev_instance);
+ af_xdp_rxq_t *rxq = vec_elt_at_index (ad->rxqs, qid);
+
+ switch (mode)
+ {
+ case VNET_HW_IF_RX_MODE_UNKNOWN:
+ case VNET_HW_IF_NUM_RX_MODES: /* fallthrough */
+ return clib_error_create ("uknown rx mode - doing nothing");
+ case VNET_HW_IF_RX_MODE_DEFAULT:
+ case VNET_HW_IF_RX_MODE_POLLING: /* fallthrough */
+ if (rxq->is_polling)
+ break;
+ af_xdp_device_set_rxq_mode (rxq, 1 /* polling */);
+ break;
+ case VNET_HW_IF_RX_MODE_INTERRUPT:
+ case VNET_HW_IF_RX_MODE_ADAPTIVE: /* fallthrough */
+ if (0 == rxq->is_polling)
+ break;
+ af_xdp_device_set_rxq_mode (rxq, 0 /* interrupt */);
+ break;
+ }
+
+ return 0;
+}
+
static void
af_xdp_set_interface_next_node (vnet_main_t * vnm, u32 hw_if_index,
u32 node_index)
@@ -507,12 +554,12 @@ af_xdp_clear (u32 dev_instance)
}
/* *INDENT-OFF* */
-VNET_DEVICE_CLASS (af_xdp_device_class) =
-{
+VNET_DEVICE_CLASS (af_xdp_device_class) = {
.name = "AF_XDP interface",
.format_device = format_af_xdp_device,
.format_device_name = format_af_xdp_device_name,
.admin_up_down_function = af_xdp_interface_admin_up_down,
+ .rx_mode_change_function = af_xdp_interface_rx_mode_change,
.rx_redirect_to_node = af_xdp_set_interface_next_node,
.tx_function_n_errors = AF_XDP_TX_N_ERROR,
.tx_function_error_strings = af_xdp_tx_func_error_strings,
diff --git a/src/plugins/af_xdp/input.c b/src/plugins/af_xdp/input.c
index 2cf121fb69d..65eee75cb92 100644
--- a/src/plugins/af_xdp/input.c
+++ b/src/plugins/af_xdp/input.c
@@ -21,6 +21,7 @@
#include <vlib/pci/pci.h>
#include <vnet/ethernet/ethernet.h>
#include <vnet/devices/devices.h>
+#include <vnet/interface/rx_queue_funcs.h>
#include "af_xdp.h"
#define foreach_af_xdp_input_error \
@@ -326,22 +327,22 @@ VLIB_NODE_FN (af_xdp_input_node) (vlib_main_t * vm,
{
u32 n_rx = 0;
af_xdp_main_t *am = &af_xdp_main;
- vnet_device_input_runtime_t *rt = (void *) node->runtime_data;
- vnet_device_and_queue_t *dq;
-
- foreach_device_and_queue (dq, rt->devices_and_queues)
- {
- af_xdp_device_t *ad;
- ad = vec_elt_at_index (am->devices, dq->dev_instance);
- if ((ad->flags & AF_XDP_DEVICE_F_ADMIN_UP) == 0)
- continue;
- if (PREDICT_TRUE (ad->flags & AF_XDP_DEVICE_F_ZEROCOPY))
- n_rx += af_xdp_device_input_inline (vm, node, frame, ad, dq->queue_id,
- /* copy */ 0);
- else
- n_rx += af_xdp_device_input_inline (vm, node, frame, ad, dq->queue_id,
- /* copy */ 1);
- }
+ vnet_hw_if_rxq_poll_vector_t *p,
+ *pv = vnet_hw_if_get_rxq_poll_vector (vm, node);
+
+ vec_foreach (p, pv)
+ {
+ af_xdp_device_t *ad = vec_elt_at_index (am->devices, p->dev_instance);
+ if ((ad->flags & AF_XDP_DEVICE_F_ADMIN_UP) == 0)
+ continue;
+ if (PREDICT_TRUE (ad->flags & AF_XDP_DEVICE_F_ZEROCOPY))
+ n_rx += af_xdp_device_input_inline (vm, node, frame, ad, p->queue_id,
+ /* copy */ 0);
+ else
+ n_rx += af_xdp_device_input_inline (vm, node, frame, ad, p->queue_id,
+ /* copy */ 1);
+ }
+
return n_rx;
}