diff options
author | Benoît Ganne <bganne@cisco.com> | 2021-08-25 16:53:22 +0200 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2021-08-26 14:44:39 +0000 |
commit | 4fe2f4c29e3672f38038d34f177a9ccbff18d9ad (patch) | |
tree | 6ba49d054ca502484db4f8f7cc1bc470df1bcd8d | |
parent | ad8b82d8394e7e711b2c1953b3c273aab4920355 (diff) |
af_xdp: fix stale rx/tx pointers in xsk objects
xsk objects keep pointers to the rx and tx objects. If we re-allocate
the rx and tx vectors after initializing the associated xsk object, the
pointers in the xsk object will be staled.
To avoid this, we allocate the vectors to the max expected size instead
of growing them.
Type: fix
Change-Id: If30433a28c186787d66c12dbab34bf210c95b519
Signed-off-by: Benoît Ganne <bganne@cisco.com>
-rw-r--r-- | src/plugins/af_xdp/device.c | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/src/plugins/af_xdp/device.c b/src/plugins/af_xdp/device.c index 2600170704b..c82b700bbea 100644 --- a/src/plugins/af_xdp/device.c +++ b/src/plugins/af_xdp/device.c @@ -17,7 +17,10 @@ #include <stdio.h> #include <net/if.h> +#include <sys/ioctl.h> +#include <linux/ethtool.h> #include <linux/if_link.h> +#include <linux/sockios.h> #include <bpf/libbpf.h> #include <vlib/vlib.h> #include <vlib/unix/unix.h> @@ -188,16 +191,9 @@ af_xdp_create_queue (vlib_main_t *vm, af_xdp_create_if_args_t *args, const int is_rx = qid < ad->rxq_num; const int is_tx = qid < ad->txq_num; - vec_validate_aligned (ad->umem, qid, CLIB_CACHE_LINE_BYTES); umem = vec_elt_at_index (ad->umem, qid); - - vec_validate_aligned (ad->xsk, qid, CLIB_CACHE_LINE_BYTES); xsk = vec_elt_at_index (ad->xsk, qid); - - vec_validate_aligned (ad->rxqs, qid, CLIB_CACHE_LINE_BYTES); rxq = vec_elt_at_index (ad->rxqs, qid); - - vec_validate_aligned (ad->txqs, qid, CLIB_CACHE_LINE_BYTES); txq = vec_elt_at_index (ad->txqs, qid); /* @@ -321,6 +317,31 @@ af_xdp_get_numa (const char *ifname) return numa; } +static void +af_xdp_get_q_count (const char *ifname, int *rxq_num, int *txq_num) +{ + struct ethtool_channels ec = { .cmd = ETHTOOL_GCHANNELS }; + struct ifreq ifr = { .ifr_data = (void *) &ec }; + int fd, err; + + *rxq_num = *txq_num = 1; + + fd = socket (AF_INET, SOCK_DGRAM, 0); + if (fd < 0) + return; + + snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", ifname); + err = ioctl (fd, SIOCETHTOOL, &ifr); + + close (fd); + + if (err) + return; + + *rxq_num = clib_max (ec.combined_count, ec.rx_count); + *txq_num = clib_max (ec.combined_count, ec.tx_count); +} + static clib_error_t * af_xdp_device_rxq_read_ready (clib_file_t * f) { @@ -375,8 +396,7 @@ af_xdp_create_if (vlib_main_t * vm, af_xdp_create_if_args_t * args) args->rxq_size = args->rxq_size ? args->rxq_size : 2 * VLIB_FRAME_SIZE; args->txq_size = args->txq_size ? args->txq_size : 2 * VLIB_FRAME_SIZE; - rxq_num = args->rxq_num ? args->rxq_num : 1; - txq_num = tm->n_vlib_mains; + args->rxq_num = args->rxq_num ? args->rxq_num : 1; if (!args->linux_ifname) { @@ -397,6 +417,17 @@ af_xdp_create_if (vlib_main_t * vm, af_xdp_create_if_args_t * args) goto err0; } + af_xdp_get_q_count (args->linux_ifname, &rxq_num, &txq_num); + if (args->rxq_num > rxq_num && AF_XDP_NUM_RX_QUEUES_ALL != args->rxq_num) + { + args->rv = VNET_API_ERROR_INVALID_VALUE; + args->error = clib_error_create ("too many rxq requested (%d > %d)", + args->rxq_num, rxq_num); + goto err0; + } + rxq_num = clib_min (rxq_num, args->rxq_num); + txq_num = clib_min (txq_num, tm->n_vlib_mains); + pool_get_zero (am->devices, ad); if (tm->n_vlib_mains > 1 && @@ -412,6 +443,12 @@ af_xdp_create_if (vlib_main_t * vm, af_xdp_create_if_args_t * args) q_num = clib_max (rxq_num, txq_num); ad->rxq_num = rxq_num; ad->txq_num = txq_num; + + vec_validate_aligned (ad->umem, q_num - 1, CLIB_CACHE_LINE_BYTES); + vec_validate_aligned (ad->xsk, q_num - 1, CLIB_CACHE_LINE_BYTES); + vec_validate_aligned (ad->rxqs, q_num - 1, CLIB_CACHE_LINE_BYTES); + vec_validate_aligned (ad->txqs, q_num - 1, CLIB_CACHE_LINE_BYTES); + for (i = 0; i < q_num; i++) { if (af_xdp_create_queue (vm, args, ad, i)) @@ -433,7 +470,7 @@ af_xdp_create_if (vlib_main_t * vm, af_xdp_create_if_args_t * args) ad->rxq_num = clib_min (i, rxq_num); ad->txq_num = clib_min (i, txq_num); - if (i < rxq_num && AF_XDP_NUM_RX_QUEUES_ALL != rxq_num) + if (i < rxq_num && AF_XDP_NUM_RX_QUEUES_ALL != args->rxq_num) { ad->rxq_num = ad->txq_num = 0; goto err1; /* failed creating requested rxq: fatal error, bailing |