The patch adds a new option 'use-intr' to enable afxdp interrupt
mode.  At receive path, add a poll() syscall so that when there
is no packet arrived, the pmd thread will be blocked and this
saves some CPU time for other processes. This avoids burning the
CPU to always 100% when there is no traffic. Disabled by default.

Tested-at: https://travis-ci.org/williamtu/ovs-travis/builds/653613549
Signed-off-by: William Tu <[email protected]>
---
 NEWS                       |  3 +++
 lib/netdev-afxdp.c         | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 lib/netdev-linux-private.h |  2 ++
 vswitchd/vswitch.xml       | 12 ++++++++++++
 4 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/NEWS b/NEWS
index f62ef1f47ea8..d91002a76fff 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 option 'use-intr' for netdev-afxdp to save CPU cycles by enabling
+       interrupt mode. Disabled by default.
 
 
 v2.13.0 - 14 Feb 2020
diff --git a/lib/netdev-afxdp.c b/lib/netdev-afxdp.c
index 482400d8d135..7b60acde1b02 100644
--- a/lib/netdev-afxdp.c
+++ b/lib/netdev-afxdp.c
@@ -604,6 +604,7 @@ netdev_afxdp_set_config(struct netdev *netdev, const struct 
smap *args,
     enum afxdp_mode xdp_mode;
     bool need_wakeup;
     int new_n_rxq;
+    bool use_intr;
 
     ovs_mutex_lock(&dev->mutex);
     new_n_rxq = MAX(smap_get_int(args, "n_rxq", NR_QUEUE), 1);
@@ -637,12 +638,16 @@ netdev_afxdp_set_config(struct netdev *netdev, const 
struct smap *args,
     }
 #endif
 
+    use_intr = smap_get_bool(args, "use-intr", false);
+
     if (dev->requested_n_rxq != new_n_rxq
         || dev->requested_xdp_mode != xdp_mode
-        || dev->requested_need_wakeup != need_wakeup) {
+        || dev->requested_need_wakeup != need_wakeup
+        || dev->requested_use_intr != use_intr) {
         dev->requested_n_rxq = new_n_rxq;
         dev->requested_xdp_mode = xdp_mode;
         dev->requested_need_wakeup = need_wakeup;
+        dev->requested_use_intr = use_intr;
         netdev_request_reconfigure(netdev);
     }
     ovs_mutex_unlock(&dev->mutex);
@@ -661,6 +666,8 @@ netdev_afxdp_get_config(const struct netdev *netdev, struct 
smap *args)
                     xdp_modes[dev->xdp_mode_in_use].name);
     smap_add_format(args, "use-need-wakeup", "%s",
                     dev->use_need_wakeup ? "true" : "false");
+    smap_add_format(args, "use-intr", "%s",
+                    dev->use_intr ? "true" : "false");
     ovs_mutex_unlock(&dev->mutex);
     return 0;
 }
@@ -696,6 +703,7 @@ netdev_afxdp_reconfigure(struct netdev *netdev)
     if (netdev->n_rxq == dev->requested_n_rxq
         && dev->xdp_mode == dev->requested_xdp_mode
         && dev->use_need_wakeup == dev->requested_need_wakeup
+        && dev->use_intr == dev->requested_use_intr
         && dev->xsks) {
         goto out;
     }
@@ -713,6 +721,7 @@ netdev_afxdp_reconfigure(struct netdev *netdev)
         VLOG_ERR("setrlimit(RLIMIT_MEMLOCK) failed: %s", ovs_strerror(errno));
     }
     dev->use_need_wakeup = dev->requested_need_wakeup;
+    dev->use_intr = dev->requested_use_intr;
 
     err = xsk_configure_all(netdev);
     if (err) {
@@ -815,6 +824,32 @@ prepare_fill_queue(struct xsk_socket_info *xsk_info)
     xsk_info->available_rx += BATCH_SIZE;
 }
 
+static int
+enable_intr_mode(int fd, struct netdev *netdev)
+{
+    struct pollfd fds[1];
+    int ret;
+
+    memset(fds, 0, sizeof fds);
+    fds[0].fd = fd;
+    fds[0].events = POLLIN;
+
+    ret = poll(fds, 1, 1);
+    if (OVS_UNLIKELY(ret == 0)) {
+        /* Timeout. */
+        ovsrcu_quiesce_start();
+        return EAGAIN;
+    }
+    if (OVS_UNLIKELY(ret < 0)) {
+        VLOG_WARN_RL(&rl, "%s: error polling rx fd: %s.",
+                     netdev_get_name(netdev),
+                     ovs_strerror(errno));
+        return EAGAIN;
+    }
+
+    return 0;
+}
+
 int
 netdev_afxdp_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch,
                       int *qfill)
@@ -827,6 +862,7 @@ netdev_afxdp_rxq_recv(struct netdev_rxq *rxq_, struct 
dp_packet_batch *batch,
     uint32_t idx_rx = 0;
     int qid = rxq_->queue_id;
     unsigned int rcvd, i;
+    int ret;
 
     xsk_info = dev->xsks[qid];
     if (!xsk_info || !xsk_info->xsk) {
@@ -838,6 +874,13 @@ netdev_afxdp_rxq_recv(struct netdev_rxq *rxq_, struct 
dp_packet_batch *batch,
     umem = xsk_info->umem;
     rx->fd = xsk_socket__fd(xsk_info->xsk);
 
+    if (OVS_UNLIKELY(dev->use_intr)) {
+        ret = enable_intr_mode(rx->fd, netdev);
+        if (ret > 0) {
+            return ret;
+        }
+    }
+
     rcvd = xsk_ring_cons__peek(&xsk_info->rx, BATCH_SIZE, &idx_rx);
     if (!rcvd) {
         xsk_rx_wakeup_if_needed(umem, netdev, rx->fd);
diff --git a/lib/netdev-linux-private.h b/lib/netdev-linux-private.h
index c7c515f70700..a89eb36b5e3c 100644
--- a/lib/netdev-linux-private.h
+++ b/lib/netdev-linux-private.h
@@ -116,6 +116,8 @@ struct netdev_linux {
 
     bool use_need_wakeup;
     bool requested_need_wakeup;
+    bool use_intr;
+    bool requested_use_intr;
 
     struct netdev_afxdp_tx_lock *tx_locks;  /* Array of locks for TX queues. */
 #endif
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 4a74ed3ef24e..046018179578 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -3186,6 +3186,18 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch 
options:peer=p1 \
         </p>
       </column>
 
+      <column name="options" key="use-intr"
+              type='{"type": "boolean"}'>
+        <p>
+          Specifies whether to use interrupt mode feature in afxdp netdev.
+          If enabled, the pmd thread calls poll() syscall on the RX path.
+          If there is no packet at rx queue, the pmd is blocked at poll()
+          until it is timeout or new packets arrive. This saves CPU cycles
+          when packet arrival rate is low.
+          Defaults to false.
+        </p>
+      </column>
+
       <column name="options" key="vhost-server-path"
               type='{"type": "string"}'>
         <p>
-- 
2.7.4

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to