On 2/27/20 6:30 PM, William Tu wrote:
> The patch adds a new netdev class 'afxdp-nonpmd' to enable afxdp
> interrupt mode. This is similar to 'type=afxdp', except that the
> is_pmd field is set to false. As a result, the packet processing
> is handled by main thread, not pmd thread. This avoids burning
> the CPU to always 100% when there is no traffic.
>
> Tested-at: https://travis-ci.org/williamtu/ovs-travis/builds/655885506
> Signed-off-by: William Tu <[email protected]>
> ---
> NEWS | 3 +++
> lib/netdev-afxdp.c | 20 +++++++++++++++++++-
> lib/netdev-linux.c | 20 ++++++++++++++++++++
> lib/netdev-provider.h | 1 +
> lib/netdev.c | 1 +
> tests/system-afxdp.at | 23 +++++++++++++++++++++++
> 6 files changed, 67 insertions(+), 1 deletion(-)
>
> diff --git a/NEWS b/NEWS
> index f62ef1f47ea8..594c55dc11d6 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -4,6 +4,9 @@ Post-v2.13.0
> - OpenFlow:
> * The OpenFlow ofp_desc/serial_num may now be configured by setting the
> value of other-config:dp-sn in the Bridge table.
> + - AF_XDP:
> + * New netdev class 'afxdp-nonpmd' for netdev-afxdp to save CPU cycles
> + by enabling interrupt mode.
>
>
> v2.13.0 - 14 Feb 2020
> diff --git a/lib/netdev-afxdp.c b/lib/netdev-afxdp.c
> index 482400d8d135..cd2c7c381139 100644
> --- a/lib/netdev-afxdp.c
> +++ b/lib/netdev-afxdp.c
> @@ -169,6 +169,12 @@ struct netdev_afxdp_tx_lock {
> );
> };
>
> +static int nonpmd_cnt; /* Number of afxdp netdevs in non-pmd mode. */
> +static bool
> +netdev_is_afxdp_nonpmd(struct netdev *netdev) {
> + return netdev_get_class(netdev) == &netdev_afxdp_nonpmd_class;
> +}
> +
> #ifdef HAVE_XDP_NEED_WAKEUP
> static inline void
> xsk_rx_wakeup_if_needed(struct xsk_umem_info *umem,
> @@ -1115,7 +1121,10 @@ netdev_afxdp_batch_send(struct netdev *netdev, int qid,
> struct netdev_linux *dev;
> int ret;
>
> - if (concurrent_txq) {
> + /* Lock is required when mixing afxdp pmd and nonpmd mode.
> + * ex: one device is created 'afxdp', the other is 'afxdp-nonpmd'.
> + */
> + if (concurrent_txq || (nonpmd_cnt != 0)) {
I'm confused about this change. Are you expecting same device being
opened twice with different netdev type? Database should not allow this.
> dev = netdev_linux_cast(netdev);
> qid = qid % netdev_n_txq(netdev);
>
> @@ -1159,6 +1168,7 @@ libbpf_print(enum libbpf_print_level level,
> int netdev_afxdp_init(void)
> {
> libbpf_set_print(libbpf_print);
> + nonpmd_cnt = 0;
> return 0;
> }
>
> @@ -1188,6 +1198,10 @@ netdev_afxdp_construct(struct netdev *netdev)
> dev->tx_locks = NULL;
>
> netdev_request_reconfigure(netdev);
> +
> + if (netdev_is_afxdp_nonpmd(netdev)) {
> + nonpmd_cnt++;
> + }
> return 0;
> }
>
> @@ -1208,6 +1222,10 @@ netdev_afxdp_destruct(struct netdev *netdev)
>
> xsk_destroy_all(netdev);
> ovs_mutex_destroy(&dev->mutex);
> +
> + if (netdev_is_afxdp_nonpmd(netdev)) {
> + nonpmd_cnt--;
> + }
> }
>
> int
> diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
> index c6f3d27409b6..75b3b55d3cad 100644
> --- a/lib/netdev-linux.c
> +++ b/lib/netdev-linux.c
> @@ -3605,6 +3605,26 @@ const struct netdev_class netdev_afxdp_class = {
> .rxq_destruct = netdev_afxdp_rxq_destruct,
> .rxq_recv = netdev_afxdp_rxq_recv,
> };
> +
> +const struct netdev_class netdev_afxdp_nonpmd_class = {
> + NETDEV_LINUX_CLASS_COMMON,
> + .type = "afxdp-nonpmd",
> + .is_pmd = false,
> + .init = netdev_afxdp_init,
> + .construct = netdev_afxdp_construct,
> + .destruct = netdev_afxdp_destruct,
> + .get_stats = netdev_afxdp_get_stats,
> + .get_custom_stats = netdev_afxdp_get_custom_stats,
> + .get_status = netdev_linux_get_status,
> + .set_config = netdev_afxdp_set_config,
> + .get_config = netdev_afxdp_get_config,
> + .reconfigure = netdev_afxdp_reconfigure,
> + .get_numa_id = netdev_linux_get_numa_id,
> + .send = netdev_afxdp_batch_send,
> + .rxq_construct = netdev_afxdp_rxq_construct,
> + .rxq_destruct = netdev_afxdp_rxq_destruct,
> + .rxq_recv = netdev_afxdp_rxq_recv,
> +};
> #endif
>
>
> diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
> index 22f4cde3337a..06c1d98a0b07 100644
> --- a/lib/netdev-provider.h
> +++ b/lib/netdev-provider.h
> @@ -848,6 +848,7 @@ extern const struct netdev_class netdev_tap_class;
>
> #ifdef HAVE_AF_XDP
> extern const struct netdev_class netdev_afxdp_class;
> +extern const struct netdev_class netdev_afxdp_nonpmd_class;
> #endif
> #ifdef __cplusplus
> }
> diff --git a/lib/netdev.c b/lib/netdev.c
> index f95b19af4da0..6d9723ebc3c1 100644
> --- a/lib/netdev.c
> +++ b/lib/netdev.c
> @@ -154,6 +154,7 @@ netdev_initialize(void)
> netdev_register_flow_api_provider(&netdev_offload_tc);
> #ifdef HAVE_AF_XDP
> netdev_register_provider(&netdev_afxdp_class);
> + netdev_register_provider(&netdev_afxdp_nonpmd_class);
> #endif
> #endif
> #if defined(__FreeBSD__) || defined(__NetBSD__)
> diff --git a/tests/system-afxdp.at b/tests/system-afxdp.at
> index e4451624f882..0d09906fb6c8 100644
> --- a/tests/system-afxdp.at
> +++ b/tests/system-afxdp.at
> @@ -22,3 +22,26 @@ AT_CHECK([grep "ovs-p0: could not set configuration"
> ovs-vswitchd.log | wc -l],
> OVS_TRAFFIC_VSWITCHD_STOP(["/ovs-p0: Too big 'n_rxq'/d
> /ovs-p0: could not set configuration/d"])
> AT_CLEANUP
> +
> +
> +AT_SETUP([AF_XDP - ping between pmd and non-pmd ports])
> +AT_KEYWORDS([afxdp nonpmd])
> +OVS_TRAFFIC_VSWITCHD_START()
> +
> +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
> +
> +ADD_NAMESPACES(at_ns0, at_ns1)
> +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
> +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
> +
> +AT_CHECK([ovs-vsctl del-port ovs-p0])
> +AT_CHECK([ovs-vsctl add-port br0 ovs-p0 -- \
> + set interface ovs-p0 type=afxdp-nonpmd options:n_rxq=1],
> + [0], [], [stderr])
> +
> +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.2 | FORMAT_PING],
> [0], [dnl
> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
> +])
> +
> +OVS_TRAFFIC_VSWITCHD_STOP
> +AT_CLEANUP
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev