]> git.droids-corp.org - dpdk.git/commitdiff
net/mlx5: check delay drop settings in kernel driver
authorBing Zhao <bingz@nvidia.com>
Fri, 5 Nov 2021 15:30:39 +0000 (17:30 +0200)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 5 Nov 2021 16:04:53 +0000 (17:04 +0100)
The delay drop is the common feature managed on per device basis
and the kernel driver is responsible one for the initialization and
rearming.

By default, the timeout value is set to activate the delay drop when
the driver is loaded.

A private flag "dropless_rq" is used to control the rearming. Only
when it is on, the rearming will be handled once received a timeout
event. Or else, the delay drop will be deactivated after the first
timeout occurs and all the Rx queues won't have this feature.

The PMD is trying to query this flag and warn the application when
some queues are created with delay drop but the flag is off.

Signed-off-by: Bing Zhao <bingz@nvidia.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
doc/guides/nics/mlx5.rst
drivers/net/mlx5/linux/mlx5_ethdev_os.c
drivers/net/mlx5/mlx5.h
drivers/net/mlx5/mlx5_trigger.c
drivers/net/mlx5/windows/mlx5_ethdev_os.c

index 7500c6c2bdfcae8a906dd48e7f203f75d9cf6bd7..d175c2061ef3618369e0ce45886318336a187c8a 100644 (file)
@@ -619,6 +619,22 @@ Driver options
   The packets being received will not be dropped immediately when the WQEs are
   exhausted in a Rx queue with delay drop enabled.
 
+  A timeout value is set in the driver to control the waiting time before
+  dropping a packet. Once the timer is expired, the delay drop will be
+  deactivated for all the Rx queues with this feature enable. To re-activeate
+  it, a rearming is needed and it is part of the kernel driver starting from
+  OFED 5.5.
+
+  To enable / disable the delay drop rearming, the private flag ``dropless_rq``
+  can be set and queried via ethtool:
+
+  - ethtool --set-priv-flags <netdev> dropless_rq on (/ off)
+  - ethtool --show-priv-flags <netdev>
+
+  The configuration flag is global per PF and can only be set on the PF, once
+  it is on, all the VFs', SFs' and representors' Rx queues will share the timer
+  and rearming.
+
 - ``mprq_en`` parameter [int]
 
   A nonzero value enables configuring Multi-Packet Rx queues. Rx queue is
index 9d0e491d0c61d5dad3fb65bfb53d54c0ffbba803..c19825ee52e0977aa9793a4c80bf16394c45d1b4 100644 (file)
@@ -1630,3 +1630,114 @@ mlx5_get_mac(struct rte_eth_dev *dev, uint8_t (*mac)[RTE_ETHER_ADDR_LEN])
        memcpy(mac, request.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN);
        return 0;
 }
+
+/*
+ * Query dropless_rq private flag value provided by ETHTOOL.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ *
+ * @return
+ *   - 0 on success, flag is not set.
+ *   - 1 on success, flag is set.
+ *   - negative errno value otherwise and rte_errno is set.
+ */
+int mlx5_get_flag_dropless_rq(struct rte_eth_dev *dev)
+{
+       struct {
+               struct ethtool_sset_info hdr;
+               uint32_t buf[1];
+       } sset_info;
+       struct ethtool_drvinfo drvinfo;
+       struct ifreq ifr;
+       struct ethtool_gstrings *strings = NULL;
+       struct ethtool_value flags;
+       const int32_t flag_len = sizeof(flags.data) * CHAR_BIT;
+       int32_t str_sz;
+       int32_t len;
+       int32_t i;
+       int ret;
+
+       sset_info.hdr.cmd = ETHTOOL_GSSET_INFO;
+       sset_info.hdr.reserved = 0;
+       sset_info.hdr.sset_mask = 1ULL << ETH_SS_PRIV_FLAGS;
+       ifr.ifr_data = (caddr_t)&sset_info;
+       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
+       if (!ret) {
+               const uint32_t *sset_lengths = sset_info.hdr.data;
+
+               len = sset_info.hdr.sset_mask ? sset_lengths[0] : 0;
+       } else if (ret == -EOPNOTSUPP) {
+               drvinfo.cmd = ETHTOOL_GDRVINFO;
+               ifr.ifr_data = (caddr_t)&drvinfo;
+               ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
+               if (ret) {
+                       DRV_LOG(WARNING, "port %u cannot get the driver info",
+                               dev->data->port_id);
+                       goto exit;
+               }
+               len = *(uint32_t *)((char *)&drvinfo +
+                       offsetof(struct ethtool_drvinfo, n_priv_flags));
+       } else {
+               DRV_LOG(WARNING, "port %u cannot get the sset info",
+                       dev->data->port_id);
+               goto exit;
+       }
+       if (!len) {
+               DRV_LOG(WARNING, "port %u does not have private flag",
+                       dev->data->port_id);
+               rte_errno = EOPNOTSUPP;
+               ret = -rte_errno;
+               goto exit;
+       } else if (len > flag_len) {
+               DRV_LOG(WARNING, "port %u maximal private flags number is %d",
+                       dev->data->port_id, flag_len);
+               len = flag_len;
+       }
+       str_sz = ETH_GSTRING_LEN * len;
+       strings = (struct ethtool_gstrings *)
+                 mlx5_malloc(0, str_sz + sizeof(struct ethtool_gstrings), 0,
+                             SOCKET_ID_ANY);
+       if (!strings) {
+               DRV_LOG(WARNING, "port %u unable to allocate memory for"
+                       " private flags", dev->data->port_id);
+               rte_errno = ENOMEM;
+               ret = -rte_errno;
+               goto exit;
+       }
+       strings->cmd = ETHTOOL_GSTRINGS;
+       strings->string_set = ETH_SS_PRIV_FLAGS;
+       strings->len = len;
+       ifr.ifr_data = (caddr_t)strings;
+       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
+       if (ret) {
+               DRV_LOG(WARNING, "port %u unable to get private flags strings",
+                       dev->data->port_id);
+               goto exit;
+       }
+       for (i = 0; i < len; i++) {
+               strings->data[(i + 1) * ETH_GSTRING_LEN - 1] = 0;
+               if (!strcmp((const char *)strings->data + i * ETH_GSTRING_LEN,
+                            "dropless_rq"))
+                       break;
+       }
+       if (i == len) {
+               DRV_LOG(WARNING, "port %u does not support dropless_rq",
+                       dev->data->port_id);
+               rte_errno = EOPNOTSUPP;
+               ret = -rte_errno;
+               goto exit;
+       }
+       flags.cmd = ETHTOOL_GPFLAGS;
+       ifr.ifr_data = (caddr_t)&flags;
+       ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
+       if (ret) {
+               DRV_LOG(WARNING, "port %u unable to get private flags status",
+                       dev->data->port_id);
+               goto exit;
+       }
+       ret = !!(flags.data & (1U << i));
+exit:
+       mlx5_free(strings);
+       return ret;
+}
index b2022f3300691ffc564329f9f7fa33d8cd9ce594..9307a4f95bf09f7f84a82525cf44e4437cc39635 100644 (file)
@@ -1602,6 +1602,7 @@ int mlx5_os_read_dev_stat(struct mlx5_priv *priv,
 int mlx5_os_read_dev_counters(struct rte_eth_dev *dev, uint64_t *stats);
 int mlx5_os_get_stats_n(struct rte_eth_dev *dev);
 void mlx5_os_stats_init(struct rte_eth_dev *dev);
+int mlx5_get_flag_dropless_rq(struct rte_eth_dev *dev);
 
 /* mlx5_mac.c */
 
index a3e62e95335fd2faa32a1bb9c9ed78fd0323a14e..0ecc530043f300dfc0e13a3619463c8c4df98db1 100644 (file)
@@ -1129,6 +1129,24 @@ mlx5_dev_start(struct rte_eth_dev *dev)
                        dev->data->port_id, strerror(rte_errno));
                goto error;
        }
+       if (priv->config.std_delay_drop || priv->config.hp_delay_drop) {
+               if (!priv->config.vf && !priv->config.sf &&
+                   !priv->representor) {
+                       ret = mlx5_get_flag_dropless_rq(dev);
+                       if (ret < 0)
+                               DRV_LOG(WARNING,
+                                       "port %u cannot query dropless flag",
+                                       dev->data->port_id);
+                       else if (!ret)
+                               DRV_LOG(WARNING,
+                                       "port %u dropless_rq OFF, no rearming",
+                                       dev->data->port_id);
+               } else {
+                       DRV_LOG(DEBUG,
+                               "port %u doesn't support dropless_rq flag",
+                               dev->data->port_id);
+               }
+       }
        ret = mlx5_rxq_start(dev);
        if (ret) {
                DRV_LOG(ERR, "port %u Rx queue allocation failed: %s",
index fddc7a6b121bb4300368bbc519165c071bb0d8a4..359f73df7ce171634590724f01a4edcda85b46a5 100644 (file)
@@ -389,3 +389,20 @@ mlx5_is_removed(struct rte_eth_dev *dev)
                return 1;
        return 0;
 }
+
+/*
+ * Query dropless_rq private flag value provided by ETHTOOL.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ *
+ * @return
+ *   - 0 on success, flag is not set.
+ *   - 1 on success, flag is set.
+ *   - negative errno value otherwise and rte_errno is set.
+ */
+int mlx5_get_flag_dropless_rq(struct rte_eth_dev *dev)
+{
+       RTE_SET_USED(dev);
+       return -ENOTSUP;
+}