[dpdk-dev] [PATCH] net/enic: support UDP RSS on 1400 series adapters

John Daley johndale at cisco.com
Thu Apr 5 01:54:52 CEST 2018


Recent models support IPv4/IPv6 UDP RSS. There is no control bit to
enable UDP RSS alone. Instead, the NIC enables/disables TCP and UDP
RSS together.

Signed-off-by: John Daley <johndale at cisco.com>
Reviewed-by: Hyong Youb Kim <hyonkim at cisco.com>
---
 doc/guides/nics/enic.rst         |  2 +-
 drivers/net/enic/base/vnic_dev.c | 18 ++++++++++++++++++
 drivers/net/enic/base/vnic_dev.h |  1 +
 drivers/net/enic/base/vnic_nic.h |  1 +
 drivers/net/enic/enic_main.c     | 12 ++++++++++++
 drivers/net/enic/enic_res.c      |  5 +++++
 6 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/enic.rst b/doc/guides/nics/enic.rst
index 133b1e682..d02a69829 100644
--- a/doc/guides/nics/enic.rst
+++ b/doc/guides/nics/enic.rst
@@ -416,6 +416,7 @@ Supported features
 - VLAN filtering (supported via UCSM/CIMC only)
 - Execution of application by unprivileged system users
 - IPV4, IPV6 and TCP RSS hashing
+- UDP hashing (1400 series and later adapters)
 - Scattered Rx
 - MTU update
 - SR-IOV on UCS managed servers connected to Fabric Interconnects
@@ -434,7 +435,6 @@ Known bugs and unsupported features in this release
 - VLAN based flow direction
 - Non-IPV4 flow direction
 - Setting of extended VLAN
-- UDP RSS hashing
 - MTU update only works if Scattered Rx mode is disabled
 - Maximum receive packet length is ignored if Scattered Rx mode is used
 
diff --git a/drivers/net/enic/base/vnic_dev.c b/drivers/net/enic/base/vnic_dev.c
index 386db6411..1d6734dc1 100644
--- a/drivers/net/enic/base/vnic_dev.c
+++ b/drivers/net/enic/base/vnic_dev.c
@@ -10,6 +10,7 @@
 #include "vnic_dev.h"
 #include "vnic_resource.h"
 #include "vnic_devcmd.h"
+#include "vnic_nic.h"
 #include "vnic_stats.h"
 
 
@@ -531,6 +532,23 @@ int vnic_dev_capable_filter_mode(struct vnic_dev *vdev, u32 *mode,
 	return 0;
 }
 
+int vnic_dev_capable_udp_rss(struct vnic_dev *vdev)
+{
+	u64 a0 = CMD_NIC_CFG, a1 = 0;
+	u64 rss_hash_type;
+	int wait = 1000;
+	int err;
+
+	err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait);
+	if (err)
+		return 0;
+	if (a0 == 0)
+		return 0;
+	rss_hash_type = (a1 >> NIC_CFG_RSS_HASH_TYPE_SHIFT) &
+		NIC_CFG_RSS_HASH_TYPE_MASK_FIELD;
+	return ((rss_hash_type & NIC_CFG_RSS_HASH_TYPE_UDP) ? 1 : 0);
+}
+
 int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd)
 {
 	u64 a0 = (u32)cmd, a1 = 0;
diff --git a/drivers/net/enic/base/vnic_dev.h b/drivers/net/enic/base/vnic_dev.h
index b3ce26032..62c09fa86 100644
--- a/drivers/net/enic/base/vnic_dev.h
+++ b/drivers/net/enic/base/vnic_dev.h
@@ -109,6 +109,7 @@ int vnic_dev_capable_adv_filters(struct vnic_dev *vdev);
 int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd);
 int vnic_dev_capable_filter_mode(struct vnic_dev *vdev, u32 *mode,
 				 u8 *filter_tags);
+int vnic_dev_capable_udp_rss(struct vnic_dev *vdev);
 int vnic_dev_asic_info(struct vnic_dev *vdev, u16 *asic_type, u16 *asic_rev);
 int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, size_t size,
 	void *value);
diff --git a/drivers/net/enic/base/vnic_nic.h b/drivers/net/enic/base/vnic_nic.h
index a753b3a5a..b20915e76 100644
--- a/drivers/net/enic/base/vnic_nic.h
+++ b/drivers/net/enic/base/vnic_nic.h
@@ -33,6 +33,7 @@
 #define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6		(1 << 4)
 #define NIC_CFG_RSS_HASH_TYPE_IPV6_EX		(1 << 5)
 #define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6_EX	(1 << 6)
+#define NIC_CFG_RSS_HASH_TYPE_UDP		(1 << 7)
 
 static inline void vnic_set_nic_cfg(u32 *nic_cfg,
 	u8 rss_default_cpu, u8 rss_hash_type,
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 9b254d98e..f01a77c0a 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -1178,10 +1178,22 @@ int enic_set_rss_conf(struct enic *enic, struct rte_eth_rss_conf *rss_conf)
 			rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_IPV4;
 		if (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP)
 			rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_TCP_IPV4;
+		if (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) {
+			/*
+			 * 'TCP' is not a typo. HW does not have a separate
+			 * enable bit for UDP RSS. The TCP bit enables both TCP
+			 * and UDP RSS..
+			 */
+			rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_TCP_IPV4;
+		}
 		if (rss_hf & ETH_RSS_IPV6)
 			rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_IPV6;
 		if (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP)
 			rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_TCP_IPV6;
+		if (rss_hf & ETH_RSS_NONFRAG_IPV6_UDP) {
+			/* Again, 'TCP' is not a typo. */
+			rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_TCP_IPV6;
+		}
 		if (rss_hf & ETH_RSS_IPV6_EX)
 			rss_hash_type |= NIC_CFG_RSS_HASH_TYPE_IPV6_EX;
 		if (rss_hf & ETH_RSS_IPV6_TCP_EX)
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c
index 47f825e51..34532720c 100644
--- a/drivers/net/enic/enic_res.c
+++ b/drivers/net/enic/enic_res.c
@@ -144,6 +144,11 @@ int enic_get_vnic_config(struct enic *enic)
 		enic->flow_type_rss_offloads |= ETH_RSS_IPV6_EX;
 	if (ENIC_SETTING(enic, RSSHASH_TCPIPV6_EX))
 		enic->flow_type_rss_offloads |= ETH_RSS_IPV6_TCP_EX;
+	if (vnic_dev_capable_udp_rss(enic->vdev)) {
+		enic->flow_type_rss_offloads |=
+			ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_NONFRAG_IPV6_UDP;
+	}
+
 	/* Zero offloads if RSS is not enabled */
 	if (!ENIC_SETTING(enic, RSS))
 		enic->flow_type_rss_offloads = 0;
-- 
2.16.2



More information about the dev mailing list