This patches detects the number of combined channels on a AF_XDP port
via using ethtool interface.  If the number of combined channels
is different from the n_rxq, netdev_afxdp will not be able to get
all the packets from that port.  Thus, abort the port setup when
the case is detected.

Signed-off-by: Yi-Hung Wei <[email protected]>
---
Travis CI: https://travis-ci.org/YiHungWei/ovs/builds/627972465

---
 lib/netdev-afxdp.c | 15 +++++++++++++++
 lib/netdev-linux.c | 27 +++++++++++++++++++++++++++
 lib/netdev-linux.h |  2 ++
 3 files changed, 44 insertions(+)

diff --git a/lib/netdev-afxdp.c b/lib/netdev-afxdp.c
index 58365ed483e3..6d002882d355 100644
--- a/lib/netdev-afxdp.c
+++ b/lib/netdev-afxdp.c
@@ -601,6 +601,14 @@ netdev_afxdp_set_config(struct netdev *netdev, const 
struct smap *args,
     enum afxdp_mode xdp_mode;
     bool need_wakeup;
     int new_n_rxq;
+    int combined_channels;
+
+    if (netdev_linux_ethtool_get_combined_channels(netdev,
+                                                   &combined_channels)) {
+        VLOG_INFO("Cannot get the number of combined channels of %s. "
+                  "Defaults it to 1.", netdev_get_name(netdev));
+        combined_channels = 1;
+    }
 
     ovs_mutex_lock(&dev->mutex);
     new_n_rxq = MAX(smap_get_int(args, "n_rxq", NR_QUEUE), 1);
@@ -611,6 +619,13 @@ netdev_afxdp_set_config(struct netdev *netdev, const 
struct smap *args,
         return EINVAL;
     }
 
+    if (new_n_rxq != combined_channels) {
+        ovs_mutex_unlock(&dev->mutex);
+        VLOG_ERR("%s: n_rxq: %d != combined channels: %d.",
+                 netdev_get_name(netdev), new_n_rxq, combined_channels);
+        return EINVAL;
+    }
+
     str_xdp_mode = smap_get_def(args, "xdp-mode", "best-effort");
     for (xdp_mode = OVS_AF_XDP_MODE_BEST_EFFORT;
          xdp_mode < OVS_AF_XDP_MODE_MAX;
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index f8e59bacfb13..e3086fc1cbb6 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -2166,6 +2166,33 @@ out:
     netdev->get_features_error = error;
 }
 
+int
+netdev_linux_ethtool_get_combined_channels(struct netdev *netdev_,
+                                           int *combined_channels)
+{
+    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
+    struct ethtool_channels echannels;
+    int err;
+
+    ovs_mutex_lock(&netdev->mutex);
+
+    COVERAGE_INC(netdev_get_ethtool);
+
+    memset(&echannels, 0, sizeof echannels);
+    err = netdev_linux_do_ethtool(netdev_get_name(netdev_),
+                                  (struct ethtool_cmd *) &echannels,
+                                  ETHTOOL_GCHANNELS, "ETHTOOL_GCHANNELS");
+    if (err) {
+        goto exit;
+    }
+
+    *combined_channels = echannels.combined_count;
+
+exit:
+    ovs_mutex_unlock(&netdev->mutex);
+    return err;
+}
+
 /* Stores the features supported by 'netdev' into of '*current', '*advertised',
  * '*supported', and '*peer'.  Each value is a bitmap of NETDEV_* bits.
  * Returns 0 if successful, otherwise a positive errno value. */
diff --git a/lib/netdev-linux.h b/lib/netdev-linux.h
index e1e30f806557..55cade4bb356 100644
--- a/lib/netdev-linux.h
+++ b/lib/netdev-linux.h
@@ -27,6 +27,8 @@ struct netdev;
 
 int netdev_linux_ethtool_set_flag(struct netdev *netdev, uint32_t flag,
                                   const char *flag_name, bool enable);
+int netdev_linux_ethtool_get_combined_channels(struct netdev *netdev,
+                                               int *combined_channels);
 int linux_get_ifindex(const char *netdev_name);
 
 #endif /* netdev-linux.h */
-- 
2.17.1

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

Reply via email to