All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wei Zhao <wei.zhao1@intel.com>
To: dev@dpdk.org
Cc: wei.dai@intel.com, Wei Zhao <wei.zhao1@intel.com>
Subject: [PATCH v4 1/2] net/e1000: move RSS to flow API
Date: Thu,  4 Jan 2018 15:46:28 +0800	[thread overview]
Message-ID: <20180104074629.126767-2-wei.zhao1@intel.com> (raw)
In-Reply-To: <20180104074629.126767-1-wei.zhao1@intel.com>

Rte_flow actually defined to include RSS,
but till now, RSS is out of rte_flow.
This patch is to move igb existing RSS to rte_flow.
The old RSS configuration is still reserved.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 doc/guides/rel_notes/release_18_02.rst |   6 ++
 drivers/net/e1000/e1000_ethdev.h       |  20 +++++
 drivers/net/e1000/igb_ethdev.c         |  17 ++++
 drivers/net/e1000/igb_flow.c           | 160 +++++++++++++++++++++++++++++++++
 drivers/net/e1000/igb_rxtx.c           |  61 +++++++++++++
 5 files changed, 264 insertions(+)

diff --git a/doc/guides/rel_notes/release_18_02.rst b/doc/guides/rel_notes/release_18_02.rst
index 24b67bb..1b91508 100644
--- a/doc/guides/rel_notes/release_18_02.rst
+++ b/doc/guides/rel_notes/release_18_02.rst
@@ -41,6 +41,12 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **Added the igb ethernet driver to support RSS with flow API.**
+
+  Rte_flow actually defined to include RSS, but till now, RSS is out of
+  rte_flow. This patch is to support igb NIC with existing RSS configuration
+  using rte_flow API.
+
 
 API Changes
 -----------
diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h
index 5668910..0731766 100644
--- a/drivers/net/e1000/e1000_ethdev.h
+++ b/drivers/net/e1000/e1000_ethdev.h
@@ -257,6 +257,12 @@ struct igb_ethertype_filter {
 	uint32_t etqf;
 };
 
+struct igb_rte_flow_rss_conf {
+	struct rte_eth_rss_conf rss_conf; /**< RSS parameters. */
+	uint16_t num; /**< Number of entries in queue[]. */
+	uint16_t queue[IGB_MAX_RX_QUEUE_NUM]; /**< Queues indices to use. */
+};
+
 /*
  * Structure to store filters'info.
  */
@@ -274,6 +280,8 @@ struct e1000_filter_info {
 	struct e1000_2tuple_filter_list twotuple_list;
 	/* store the SYN filter info */
 	uint32_t syn_info;
+	/* store the rss filter info */
+	struct igb_rte_flow_rss_conf rss_info;
 };
 
 /*
@@ -342,6 +350,12 @@ struct igb_flex_filter_ele {
 	struct rte_eth_flex_filter filter_info;
 };
 
+/* rss filter  list structure */
+struct igb_rss_conf_ele {
+	TAILQ_ENTRY(igb_rss_conf_ele) entries;
+	struct igb_rte_flow_rss_conf filter_info;
+};
+
 /* igb_flow memory list structure */
 struct igb_flow_mem {
 	TAILQ_ENTRY(igb_flow_mem) entries;
@@ -357,6 +371,8 @@ TAILQ_HEAD(igb_syn_filter_list, igb_eth_syn_filter_ele);
 struct igb_syn_filter_list igb_filter_syn_list;
 TAILQ_HEAD(igb_flex_filter_list, igb_flex_filter_ele);
 struct igb_flex_filter_list igb_filter_flex_list;
+TAILQ_HEAD(igb_rss_filter_list, igb_rss_conf_ele);
+struct igb_rss_filter_list igb_filter_rss_list;
 TAILQ_HEAD(igb_flow_mem_list, igb_flow_mem);
 struct igb_flow_mem_list igb_flow_list;
 
@@ -500,4 +516,8 @@ int eth_igb_syn_filter_set(struct rte_eth_dev *dev,
 int eth_igb_add_del_flex_filter(struct rte_eth_dev *dev,
 			struct rte_eth_flex_filter *filter,
 			bool add);
+int igb_config_rss_filter(struct rte_eth_dev *dev,
+			struct igb_rte_flow_rss_conf *conf,
+			bool add);
+
 #endif /* _E1000_ETHDEV_H_ */
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index fdc139f..275fa02 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -948,6 +948,7 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
 	TAILQ_INIT(&igb_filter_ethertype_list);
 	TAILQ_INIT(&igb_filter_syn_list);
 	TAILQ_INIT(&igb_filter_flex_list);
+	TAILQ_INIT(&igb_filter_rss_list);
 	TAILQ_INIT(&igb_flow_list);
 
 	return 0;
@@ -1007,6 +1008,10 @@ eth_igb_dev_uninit(struct rte_eth_dev *eth_dev)
 	memset(filter_info->ethertype_filters, 0,
 		E1000_MAX_ETQF_FILTERS * sizeof(struct igb_ethertype_filter));
 
+	/* clear the rss filter info */
+	memset(&filter_info->rss_info, 0,
+		sizeof(struct igb_rte_flow_rss_conf));
+
 	/* remove all ntuple filters of the device */
 	igb_ntuple_filter_uninit(eth_dev);
 
@@ -5628,6 +5633,17 @@ igb_flex_filter_restore(struct rte_eth_dev *dev)
 	}
 }
 
+/* restore rss filter */
+static inline void
+igb_rss_filter_restore(struct rte_eth_dev *dev)
+{
+	struct e1000_filter_info *filter_info =
+		E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+
+	if (filter_info->rss_info.num)
+		igb_config_rss_filter(dev, &filter_info->rss_info, TRUE);
+}
+
 /* restore all types filter */
 static int
 igb_filter_restore(struct rte_eth_dev *dev)
@@ -5636,6 +5652,7 @@ igb_filter_restore(struct rte_eth_dev *dev)
 	igb_ethertype_filter_restore(dev);
 	igb_syn_filter_restore(dev);
 	igb_flex_filter_restore(dev);
+	igb_rss_filter_restore(dev);
 
 	return 0;
 }
diff --git a/drivers/net/e1000/igb_flow.c b/drivers/net/e1000/igb_flow.c
index 22bad26..32ad8d2 100644
--- a/drivers/net/e1000/igb_flow.c
+++ b/drivers/net/e1000/igb_flow.c
@@ -1295,6 +1295,101 @@ igb_parse_flex_filter(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int
+igb_parse_rss_filter(struct rte_eth_dev *dev,
+			const struct rte_flow_attr *attr,
+			const struct rte_flow_action actions[],
+			struct igb_rte_flow_rss_conf *rss_conf,
+			struct rte_flow_error *error)
+{
+	const struct rte_flow_action *act;
+	const struct rte_flow_action_rss *rss;
+	uint16_t n, index;
+
+	/**
+	 * rss only supports forwarding,
+	 * check if the first not void action is RSS.
+	 */
+	index = 0;
+	NEXT_ITEM_OF_ACTION(act, actions, index);
+	if (act->type != RTE_FLOW_ACTION_TYPE_RSS) {
+		memset(rss_conf, 0, sizeof(struct igb_rte_flow_rss_conf));
+		rte_flow_error_set(error, EINVAL,
+			RTE_FLOW_ERROR_TYPE_ACTION,
+			act, "Not supported action.");
+		return -rte_errno;
+	}
+
+	rss = (const struct rte_flow_action_rss *)act->conf;
+
+	if (!rss || !rss->num) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ACTION,
+				act,
+			   "no valid queues");
+		return -rte_errno;
+	}
+
+	for (n = 0; n < rss->num; n++) {
+		if (rss->queue[n] >= dev->data->nb_rx_queues) {
+			rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ACTION,
+				   act,
+				   "queue id > max number of queues");
+			return -rte_errno;
+		}
+	}
+
+	if (rss->rss_conf)
+		rss_conf->rss_conf = *rss->rss_conf;
+	else
+		rss_conf->rss_conf.rss_hf = IGB_RSS_OFFLOAD_ALL;
+
+	for (n = 0; n < rss->num; ++n)
+		rss_conf->queue[n] = rss->queue[n];
+	rss_conf->num = rss->num;
+
+	/* check if the next not void item is END */
+	index++;
+	NEXT_ITEM_OF_ACTION(act, actions, index);
+	if (act->type != RTE_FLOW_ACTION_TYPE_END) {
+		memset(rss_conf, 0, sizeof(struct rte_eth_rss_conf));
+		rte_flow_error_set(error, EINVAL,
+			RTE_FLOW_ERROR_TYPE_ACTION,
+			act, "Not supported action.");
+		return -rte_errno;
+	}
+
+	/* parse attr */
+	/* must be input direction */
+	if (!attr->ingress) {
+		memset(rss_conf, 0, sizeof(struct igb_rte_flow_rss_conf));
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+				   attr, "Only support ingress.");
+		return -rte_errno;
+	}
+
+	/* not supported */
+	if (attr->egress) {
+		memset(rss_conf, 0, sizeof(struct igb_rte_flow_rss_conf));
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+				   attr, "Not support egress.");
+		return -rte_errno;
+	}
+
+	if (attr->priority > 0xFFFF) {
+		memset(rss_conf, 0, sizeof(struct igb_rte_flow_rss_conf));
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
+				   attr, "Error priority.");
+		return -rte_errno;
+	}
+
+	return 0;
+}
+
 /**
  * Create a flow rule.
  * Theorically one rule can match more than one filters.
@@ -1313,11 +1408,13 @@ igb_flow_create(struct rte_eth_dev *dev,
 	struct rte_eth_ethertype_filter ethertype_filter;
 	struct rte_eth_syn_filter syn_filter;
 	struct rte_eth_flex_filter flex_filter;
+	struct igb_rte_flow_rss_conf rss_conf;
 	struct rte_flow *flow = NULL;
 	struct igb_ntuple_filter_ele *ntuple_filter_ptr;
 	struct igb_ethertype_filter_ele *ethertype_filter_ptr;
 	struct igb_eth_syn_filter_ele *syn_filter_ptr;
 	struct igb_flex_filter_ele *flex_filter_ptr;
+	struct igb_rss_conf_ele *rss_filter_ptr;
 	struct igb_flow_mem *igb_flow_mem_ptr;
 
 	flow = rte_zmalloc("igb_rte_flow", sizeof(struct rte_flow), 0);
@@ -1419,6 +1516,29 @@ igb_flow_create(struct rte_eth_dev *dev,
 		}
 	}
 
+	memset(&rss_conf, 0, sizeof(struct igb_rte_flow_rss_conf));
+	ret = igb_parse_rss_filter(dev, attr,
+					actions, &rss_conf, error);
+	if (!ret) {
+		ret = igb_config_rss_filter(dev, &rss_conf, TRUE);
+		if (!ret) {
+			rss_filter_ptr = rte_zmalloc("igb_rss_filter",
+				sizeof(struct igb_rss_conf_ele), 0);
+			if (!rss_filter_ptr) {
+				PMD_DRV_LOG(ERR, "failed to allocate memory");
+				goto out;
+			}
+			rte_memcpy(&rss_filter_ptr->filter_info,
+				&rss_conf,
+				sizeof(struct igb_rte_flow_rss_conf));
+			TAILQ_INSERT_TAIL(&igb_filter_rss_list,
+				rss_filter_ptr, entries);
+			flow->rule = rss_filter_ptr;
+			flow->filter_type = RTE_ETH_FILTER_HASH;
+			return flow;
+		}
+	}
+
 out:
 	TAILQ_REMOVE(&igb_flow_list,
 		igb_flow_mem_ptr, entries);
@@ -1446,6 +1566,7 @@ igb_flow_validate(__rte_unused struct rte_eth_dev *dev,
 	struct rte_eth_ethertype_filter ethertype_filter;
 	struct rte_eth_syn_filter syn_filter;
 	struct rte_eth_flex_filter flex_filter;
+	struct igb_rte_flow_rss_conf rss_conf;
 	int ret;
 
 	memset(&ntuple_filter, 0, sizeof(struct rte_eth_ntuple_filter));
@@ -1469,6 +1590,12 @@ igb_flow_validate(__rte_unused struct rte_eth_dev *dev,
 	memset(&flex_filter, 0, sizeof(struct rte_eth_flex_filter));
 	ret = igb_parse_flex_filter(dev, attr, pattern,
 				actions, &flex_filter, error);
+	if (!ret)
+		return 0;
+
+	memset(&rss_conf, 0, sizeof(struct igb_rte_flow_rss_conf));
+	ret = igb_parse_rss_filter(dev, attr,
+					actions, &rss_conf, error);
 
 	return ret;
 }
@@ -1487,6 +1614,7 @@ igb_flow_destroy(struct rte_eth_dev *dev,
 	struct igb_eth_syn_filter_ele *syn_filter_ptr;
 	struct igb_flex_filter_ele *flex_filter_ptr;
 	struct igb_flow_mem *igb_flow_mem_ptr;
+	struct igb_rss_conf_ele *rss_filter_ptr;
 
 	switch (filter_type) {
 	case RTE_ETH_FILTER_NTUPLE:
@@ -1533,6 +1661,17 @@ igb_flow_destroy(struct rte_eth_dev *dev,
 			rte_free(flex_filter_ptr);
 		}
 		break;
+	case RTE_ETH_FILTER_HASH:
+		rss_filter_ptr = (struct igb_rss_conf_ele *)
+				pmd_flow->rule;
+		ret = igb_config_rss_filter(dev,
+					&rss_filter_ptr->filter_info, FALSE);
+		if (!ret) {
+			TAILQ_REMOVE(&igb_filter_rss_list,
+				rss_filter_ptr, entries);
+			rte_free(rss_filter_ptr);
+		}
+		break;
 	default:
 		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
 			    filter_type);
@@ -1621,6 +1760,17 @@ igb_clear_all_flex_filter(struct rte_eth_dev *dev)
 		igb_remove_flex_filter(dev, flex_filter);
 }
 
+/* remove the rss filter */
+static void
+igb_clear_rss_filter(struct rte_eth_dev *dev)
+{
+	struct e1000_filter_info *filter =
+		E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+
+	if (filter->rss_info.num)
+		igb_config_rss_filter(dev, &filter->rss_info, FALSE);
+}
+
 void
 igb_filterlist_flush(struct rte_eth_dev *dev)
 {
@@ -1628,6 +1778,7 @@ igb_filterlist_flush(struct rte_eth_dev *dev)
 	struct igb_ethertype_filter_ele *ethertype_filter_ptr;
 	struct igb_eth_syn_filter_ele *syn_filter_ptr;
 	struct igb_flex_filter_ele *flex_filter_ptr;
+	struct igb_rss_conf_ele  *rss_filter_ptr;
 	struct igb_flow_mem *igb_flow_mem_ptr;
 	enum rte_filter_type filter_type;
 	struct rte_flow *pmd_flow;
@@ -1670,6 +1821,14 @@ igb_filterlist_flush(struct rte_eth_dev *dev)
 						flex_filter_ptr, entries);
 				rte_free(flex_filter_ptr);
 				break;
+			case RTE_ETH_FILTER_HASH:
+				rss_filter_ptr =
+					(struct igb_rss_conf_ele *)
+						pmd_flow->rule;
+				TAILQ_REMOVE(&igb_filter_rss_list,
+						rss_filter_ptr, entries);
+				rte_free(rss_filter_ptr);
+				break;
 			default:
 				PMD_DRV_LOG(WARNING, "Filter type"
 					"(%d) not supported", filter_type);
@@ -1693,6 +1852,7 @@ igb_flow_flush(struct rte_eth_dev *dev,
 	igb_clear_all_ethertype_filter(dev);
 	igb_clear_syn_filter(dev);
 	igb_clear_all_flex_filter(dev);
+	igb_clear_rss_filter(dev);
 	igb_filterlist_flush(dev);
 
 	return 0;
diff --git a/drivers/net/e1000/igb_rxtx.c b/drivers/net/e1000/igb_rxtx.c
index 4ee12e9..af86726 100644
--- a/drivers/net/e1000/igb_rxtx.c
+++ b/drivers/net/e1000/igb_rxtx.c
@@ -2786,3 +2786,64 @@ igb_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 	qinfo->conf.tx_thresh.hthresh = txq->hthresh;
 	qinfo->conf.tx_thresh.wthresh = txq->wthresh;
 }
+
+int
+igb_config_rss_filter(struct rte_eth_dev *dev,
+		struct igb_rte_flow_rss_conf *conf, bool add)
+{
+	uint32_t shift;
+	uint16_t i, j;
+	struct rte_eth_rss_conf rss_conf = conf->rss_conf;
+	struct e1000_filter_info *filter_info =
+		E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (!add) {
+		if (memcmp(conf, &filter_info->rss_info,
+			sizeof(struct igb_rte_flow_rss_conf)) == 0) {
+			igb_rss_disable(dev);
+			memset(&filter_info->rss_info, 0,
+				sizeof(struct igb_rte_flow_rss_conf));
+			return 0;
+		}
+		return -EINVAL;
+	}
+
+	if (filter_info->rss_info.num)
+		return -EINVAL;
+
+	/* Fill in redirection table. */
+	shift = (hw->mac.type == e1000_82575) ? 6 : 0;
+	for (i = 0, j = 0; i < 128; i++, j++) {
+		union e1000_reta {
+			uint32_t dword;
+			uint8_t  bytes[4];
+		} reta;
+		uint8_t q_idx;
+
+		q_idx = conf->queue[j];
+		if (j == conf->num)
+			j = 0;
+		reta.bytes[i & 3] = (uint8_t)(q_idx << shift);
+		if ((i & 3) == 3)
+			E1000_WRITE_REG(hw, E1000_RETA(i >> 2), reta.dword);
+	}
+
+	/* Configure the RSS key and the RSS protocols used to compute
+	 * the RSS hash of input packets.
+	 */
+	if ((rss_conf.rss_hf & IGB_RSS_OFFLOAD_ALL) == 0) {
+		igb_rss_disable(dev);
+		return 0;
+	}
+	if (rss_conf.rss_key == NULL)
+		rss_conf.rss_key = rss_intel_key; /* Default hash key */
+	igb_hw_rss_hash_set(hw, &rss_conf);
+
+	rte_memcpy(&filter_info->rss_info,
+		conf, sizeof(struct igb_rte_flow_rss_conf));
+
+	return 0;
+}
-- 
2.9.3

  reply	other threads:[~2018-01-04  7:54 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-23  9:03 [PATCH 1/2] net/e1000: move RSS to flow API Wei Zhao
2017-11-23  9:03 ` [PATCH 2/2] net/ixgbe: " Wei Zhao
2017-11-24  3:10 ` [PATCH v2 0/2] " Wei Zhao
2017-11-24  3:10   ` [PATCH v2 1/2] net/e1000: " Wei Zhao
2017-11-24  3:10   ` [PATCH v2 2/2] net/ixgbe: " Wei Zhao
2017-11-24  8:05   ` [PATCH v3 0/2] " Wei Zhao
2017-11-24  8:05     ` [PATCH v3 1/2] net/e1000: " Wei Zhao
2017-12-07  9:19       ` Dai, Wei
2017-12-08  2:28         ` Zhao1, Wei
2017-12-21  3:11           ` Zhang, Helin
2018-01-04  8:48             ` Zhao1, Wei
2017-11-24  8:05     ` [PATCH v3 2/2] net/ixgbe: " Wei Zhao
2017-12-07  9:19       ` Dai, Wei
2017-12-08  2:27         ` Zhao1, Wei
2017-12-21  3:11           ` Zhang, Helin
2018-01-04  8:51             ` Zhao1, Wei
2018-01-04  7:46     ` [PATCH v4 0/2] " Wei Zhao
2018-01-04  7:46       ` Wei Zhao [this message]
2018-01-05  6:05         ` [PATCH v4 1/2] net/e1000: " Dai, Wei
2018-01-04  7:46       ` [PATCH v4 2/2] net/ixgbe: " Wei Zhao
2018-01-05  6:01         ` Dai, Wei
2018-01-09  6:20       ` [PATCH v5 0/2] " Wei Zhao
2018-01-09  6:20         ` [PATCH v5 1/2] net/e1000: " Wei Zhao
2018-01-09  6:20         ` [PATCH v5 2/2] net/ixgbe: " Wei Zhao
2018-01-09  6:44         ` [PATCH v6 0/2] " Wei Zhao
2018-01-09  6:44           ` [PATCH v6 1/2] net/e1000: " Wei Zhao
2018-01-09  6:44           ` [PATCH v6 2/2] net/ixgbe: " Wei Zhao
2018-01-09  7:11           ` [PATCH v6 0/2] " Zhang, Helin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180104074629.126767-2-wei.zhao1@intel.com \
    --to=wei.zhao1@intel.com \
    --cc=dev@dpdk.org \
    --cc=wei.dai@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.