@@ -1129,6 +1129,27 @@ Driver options
By default, the PMD will set this value to 1.
+- ``delay_drop_en`` parameter [int]
+
+ Bitmask value for the Rx queue delay drop attribute. Bit 0 is used for standard
+ Rx queue and bit 1 is used for hairpin Rx queue.
+ By default, the delay drop will be enabled for all hairpin Rx queues (if any)
+ and disabled for all standard Rx queues. It will be ignored if the NIC does
+ not support the attribute.
+ A timeout value is set in the driver to control the waiting time before dropping
+ a packet when there is no WQE available on a delay drop Rx queue. Once the timer
+ is expired, the delay drop will be deactivated for all queues. To re-activeate it,
+ a rearming is needed and now it is part of the kernel driver.
+
+ 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.
+
.. _mlx5_firmware_config:
Firmware configuration
@@ -1803,6 +1824,11 @@ Supported hardware offloads
| | | | | rdma-core 35 |
| | | | | ConnectX-6 Dx |
+-----------------------+-----------------+-----------------+
+ | Rxq Delay drop | | DPDK 21.11 | | DPDK 21.11 |
+ | | | OFED 5.5 | | OFED 5.5 |
+ | | | N/A | | N/A |
+ | | | ConnectX-5 | | ConnectX-5 |
+ +-----------------------+-----------------+-----------------+
.. table:: Minimal SW/HW versions for shared action offload
:name: sact
@@ -191,6 +191,7 @@ New Features
* Added implicit mempool registration to avoid data path hiccups (opt-out).
* Added NIC offloads for the PMD on Windows (TSO, VLAN strip, CRC keep).
* Added socket direct mode bonding support.
+ * Added delay drop support for Rx queue.
* **Updated Solarflare network PMD.**
@@ -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;
+}
@@ -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 */
@@ -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",
@@ -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;
+}