DPDK patches and discussions
 help / color / mirror / Atom feed
From: SimonX Lu <simonx.lu@intel.com>
To: dev@dpdk.org
Cc: jia.guo@intel.com, haiyue.wang@intel.com, qiming.yang@intel.com,
	beilei.xing@intel.com, orika@nvidia.com,
	Simon Lu <simonx.lu@intel.com>
Subject: [dpdk-dev] [PATCH v1 8/8] net/i40e: use generic flow command to re-realize mirror rule
Date: Wed, 14 Oct 2020 08:41:31 +0000	[thread overview]
Message-ID: <20201014084131.72035-9-simonx.lu@intel.com> (raw)
In-Reply-To: <20201014084131.72035-1-simonx.lu@intel.com>

From: Simon Lu <simonx.lu@intel.com>

follow mirror rule to add new action called mirror in flow management,
so we can use "flow create * pattern * action mirror *"  to replace
old "set port * mirror-rule *" command now

the example of mirror rule command mapping to flow management command:
(in below command, port 0 is PF and port 1-3 is VF):

1) ingress: pf => pf
   set port 0 mirror-rule 0 uplink-mirror dst-pool 4 on
   or
   flow create 0 ingress pattern pf / end actions mirror pf / end
2) egress: pf => pf
   set port 0 mirror-rule 0 downlink-mirror dst-pool 4 on
   or
   flow create 0 egress pattern pf / end actions mirror pf / end
3) ingress: pf => vf 3
   set port 0 mirror-rule 0 uplink-mirror dst-pool 3 on
   or
   flow create 0 ingress pattern pf / end actions mirror vf id 3 / end
4) egress: pf => vf 3
   set port 0 mirror-rule 0 downlink-mirror dst-pool 3 on
   or
   flow create 0 egress pattern pf / end actions mirror vf id 3 / end
5) ingress: vf 0,1 => pf
   set port 0 mirror-rule 0 pool-mirror-up 0x3 dst-pool 4 on
   or
   flow create 0 ingress pattern vf id is 0 / end \
                         actions mirror pf / end

   flow create 0 ingress pattern vf id is 1 / end \
                         actions mirror pf / end
   or
   flow create 0 ingress pattern vf id last 1 / end \
                         actions mirror pf / end
   or
   flow create 0 ingress pattern vf id mask 0x3 / end \
                         actions mirror pf / end
6) egress: vf 0,1 => pf
   set port 0 mirror-rule 0 pool-mirror-down 0x3 dst-pool 4 on
   or
   flow create 0 egress pattern vf id is 0 / end actions mirror pf / end
   flow create 0 egress pattern vf id is 1 / end actions mirror pf / end
   or
   flow create 0 egress pattern vf id last 1 / end actions mirror pf / end
   or
   flow create 0 egress pattern vf id mask 0x3 / end \
                        actions mirror pf / end
7) ingress: vf 1,2 => vf 3
   set port 0 mirror-rule 0 pool-mirror-up 0x6 dst-pool 3 on
   or
   flow create 0 ingress pattern vf id is 1 / end \
                         actions mirror vf id 3 / end

   flow create 0 ingress pattern vf id is 2 / end \
                         actions mirror vf id 3 / end
   or
   flow create 0 ingress pattern vf id is 1 id last 2 / end \
                         actions mirror vf id 3 / end
   or
   flow create 0 ingress pattern vf id mask 0x6 / end \
                         actions mirror vf id 3 / end
8) egress: vf 1,2 => vf 3
   set port 0 mirror-rule 0 pool-mirror-down 0x6 dst-pool 3 on
   or
   flow create 0 egress pattern vf id is 1 / end \
                        actions mirror vf id 3 / end

   flow create 0 egress pattern vf id is 2 / end \
                        actions mirror vf id 3 / end
   or
   flow create 0 egress pattern vf id is 1 id last 2 / end \
                        actions mirror vf id 3 / end
   or
   flow create 0 egress pattern vf id mask 0x6 / end \
                        actions mirror vf id 3 / end
9) ingress: vlan 4,6 => vf 3
   set port 0 mirror-rule 0 vlan-mirror 4,6 dst-pool 4 on
   or
   flow create 0 ingress pattern vlan vid is 4 / end \
                         actions mirror vf id 3 / end

   flow create 0 ingress pattern vlan vid is 6 / end \
                         actions mirror vf id 3 end
   or
   flow create 0 ingress pattern vlan vid mask 0x28 / end \
                         actions mirror vf id 3 / end
   or
   flow create 0 ingress pattern vlan vid is 4 vid last 6 \
        vid mask 0x5 / end actions mirror vf id 3 / end

Signed-off-by: Simon Lu <simonx.lu@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 153 +++++++++++++++++++++++++++++++++++
 1 file changed, 153 insertions(+)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 578a68773..8164903a2 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -116,6 +116,7 @@ static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_rss_filter(struct rte_eth_dev *dev);
+static int i40e_flow_flush_mirror_filter(struct rte_eth_dev *dev);
 static int
 i40e_flow_parse_qinq_filter(struct rte_eth_dev *dev,
 			      const struct rte_flow_attr *attr,
@@ -5508,6 +5509,104 @@ i40e_parse_mirror_filter(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int
+i40e_config_mirror_filter_set(struct rte_eth_dev *dev,
+			      struct i40e_mirror_rule_conf *conf)
+{
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct i40e_mirror_filter *it;
+	struct i40e_mirror_filter *mirror_filter;
+	uint16_t rule_id;
+	int ret;
+
+	if (pf->main_vsi->veb == NULL || pf->vfs == NULL) {
+		PMD_DRV_LOG(ERR,
+			"mirror rule can not be configured without veb or vfs.");
+		return -ENOSYS;
+	}
+	if (pf->nb_mirror_rule > I40E_MAX_MIRROR_RULES) {
+		PMD_DRV_LOG(ERR, "mirror table is full.");
+		return -ENOSPC;
+	}
+
+	TAILQ_FOREACH(it, &pf->mirror_filter_list, next) {
+		if (it->conf.dst_vsi_seid == conf->dst_vsi_seid &&
+		    it->conf.rule_type == conf->rule_type &&
+		    it->conf.num_entries == conf->num_entries &&
+		    !memcmp(it->conf.entries, conf->entries,
+			    conf->num_entries * sizeof(conf->entries[0]))) {
+			PMD_DRV_LOG(ERR, "mirror rule exists.");
+			return -EEXIST;
+		}
+	}
+
+	mirror_filter = rte_zmalloc("i40e_mirror_filter",
+				    sizeof(*mirror_filter), 0);
+	if (mirror_filter == NULL) {
+		PMD_DRV_LOG(ERR, "Failed to alloc memory.");
+		return -ENOMEM;
+	}
+	mirror_filter->conf = *conf;
+
+	ret = i40e_aq_add_mirror_rule(hw,
+				      pf->main_vsi->veb->seid,
+				      mirror_filter->conf.dst_vsi_seid,
+				      mirror_filter->conf.rule_type,
+				      mirror_filter->conf.entries,
+				      mirror_filter->conf.num_entries,
+				      &rule_id);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR,
+			"failed to add mirror rule: ret = %d, aq_err = %d.",
+			ret, hw->aq.asq_last_status);
+		rte_free(mirror_filter);
+		return -ENOSYS;
+	}
+
+	mirror_filter->conf.rule_id = rule_id;
+
+	pf->nb_mirror_rule++;
+
+	TAILQ_INSERT_TAIL(&pf->mirror_filter_list, mirror_filter, next);
+
+	return 0;
+}
+
+static int
+i40e_config_mirror_filter_del(struct rte_eth_dev *dev,
+			      struct i40e_mirror_rule_conf *conf)
+{
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct i40e_mirror_filter *mirror_filter;
+	void *temp;
+	int ret;
+
+	ret = i40e_aq_del_mirror_rule(hw,
+				      pf->main_vsi->veb->seid,
+				      conf->rule_type,
+				      conf->entries,
+				      conf->num_entries,
+				      conf->rule_id);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR,
+			    "failed to remove mirror rule: ret = %d, aq_err = %d.",
+			    ret, hw->aq.asq_last_status);
+		return -ENOSYS;
+	}
+
+	TAILQ_FOREACH_SAFE(mirror_filter, &pf->mirror_filter_list, next, temp) {
+		if (!memcmp(&mirror_filter->conf, conf,
+			    sizeof(struct i40e_mirror_rule_conf))) {
+			TAILQ_REMOVE(&pf->mirror_filter_list,
+				     mirror_filter, next);
+			rte_free(mirror_filter);
+		}
+	}
+	return 0;
+}
+
 static int
 i40e_flow_validate(struct rte_eth_dev *dev,
 		   const struct rte_flow_attr *attr,
@@ -5553,6 +5652,12 @@ i40e_flow_validate(struct rte_eth_dev *dev,
 		return ret;
 	}
 
+	if ((actions + i)->type == RTE_FLOW_ACTION_TYPE_MIRROR) {
+		ret = i40e_parse_mirror_filter(dev, attr, pattern,
+					    actions, &cons_filter, error);
+		return ret;
+	}
+
 	i = 0;
 	/* Get the non-void item number of pattern */
 	while ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_END) {
@@ -5672,6 +5777,14 @@ i40e_flow_create(struct rte_eth_dev *dev,
 		flow->rule = TAILQ_LAST(&pf->rss_config_list,
 				i40e_rss_conf_list);
 		break;
+	case RTE_ETH_FILTER_MIRROR:
+		ret = i40e_config_mirror_filter_set(dev,
+						    &cons_filter.mirror_conf);
+		if (ret)
+			goto free_flow;
+		flow->rule = TAILQ_LAST(&pf->mirror_filter_list,
+					i40e_mirror_filter_list);
+		break;
 	default:
 		goto free_flow;
 	}
@@ -5726,6 +5839,10 @@ i40e_flow_destroy(struct rte_eth_dev *dev,
 		ret = i40e_config_rss_filter_del(dev,
 			&((struct i40e_rss_filter *)flow->rule)->rss_filter_info);
 		break;
+	case RTE_ETH_FILTER_MIRROR:
+		ret = i40e_config_mirror_filter_del(dev,
+			&((struct i40e_mirror_filter *)flow->rule)->conf);
+		break;
 	default:
 		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
 			    filter_type);
@@ -5880,6 +5997,14 @@ i40e_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
 		return -rte_errno;
 	}
 
+	ret = i40e_flow_flush_mirror_filter(dev);
+	if (ret) {
+		rte_flow_error_set(error, -ret,
+				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+				   "Failed to flush mirror flows.");
+		return -rte_errno;
+	}
+
 	return ret;
 }
 
@@ -6026,6 +6151,34 @@ i40e_flow_flush_rss_filter(struct rte_eth_dev *dev)
 	return ret;
 }
 
+/* remove the mirror filter */
+static int
+i40e_flow_flush_mirror_filter(struct rte_eth_dev *dev)
+{
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct rte_flow *flow;
+	void *temp;
+	int32_t ret = -EINVAL;
+
+	/* Delete mirror flows in flow list. */
+	TAILQ_FOREACH_SAFE(flow, &pf->flow_list, node, temp) {
+		struct i40e_mirror_filter *rule = flow->rule;
+
+		if (flow->filter_type != RTE_ETH_FILTER_MIRROR)
+			continue;
+
+		if (rule) {
+			ret = i40e_config_mirror_filter_del(dev, &rule->conf);
+			if (ret)
+				return ret;
+		}
+		TAILQ_REMOVE(&pf->flow_list, flow, node);
+		rte_free(flow);
+	}
+
+	return ret;
+}
+
 static int
 i40e_flow_query(struct rte_eth_dev *dev __rte_unused,
 		struct rte_flow *flow,
-- 
2.17.1


  parent reply	other threads:[~2020-10-14  8:45 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-14  8:41 [dpdk-dev] [PATCH v1 0/8] " SimonX Lu
2020-10-14  8:41 ` [dpdk-dev] [PATCH v1 1/8] ethdev: support the mirror action for flow SimonX Lu
2020-10-14 12:07   ` Ori Kam
2020-10-14  8:41 ` [dpdk-dev] [PATCH v1 2/8] app/testpmd: support action mirror for flow command SimonX Lu
2020-10-14  8:41 ` [dpdk-dev] [PATCH v1 3/8] net/ixgbe: add mirror rule config and extend flow filter type SimonX Lu
2020-10-14  8:41 ` [dpdk-dev] [PATCH v1 4/8] net/ixgbe: define the mirror filter paser SimonX Lu
2020-10-14  8:41 ` [dpdk-dev] [PATCH v1 5/8] net/ixgbe: use generic flow command to re-realize mirror rule SimonX Lu
2020-10-14  8:41 ` [dpdk-dev] [PATCH v1 6/8] net/i40e: add mirror rule config and export add/del rule APIs SimonX Lu
2020-10-14  8:41 ` [dpdk-dev] [PATCH v1 7/8] net/i40e: define the mirror filter paser SimonX Lu
2020-10-14  8:41 ` SimonX Lu [this message]
     [not found] ` <20201103082809.41149-1-stevex.yang@intel.com>
2020-11-03  8:28   ` [dpdk-dev] [RFC v2 1/6] net/i40e: add mirror rule config and add/del rule APIs Steve Yang
2020-11-03  8:28   ` [dpdk-dev] [RFC v2 2/6] net/i40e: define the mirror filter parser Steve Yang
2021-02-18 18:59     ` Thomas Monjalon
2021-02-19 12:56     ` Ferruh Yigit
2020-11-03  8:28   ` [dpdk-dev] [RFC v2 3/6] net/i40e: use generic flow command to re-realize mirror rule Steve Yang
2020-11-03  8:28   ` [dpdk-dev] [RFC v2 4/6] net/ixgbe: add mirror rule config and add/del rule APIs Steve Yang
2020-11-03  8:28   ` [dpdk-dev] [RFC v2 5/6] net/ixgbe: define the mirror filter parser Steve Yang
2021-02-19 12:57     ` Ferruh Yigit
2020-11-03  8:28   ` [dpdk-dev] [RFC v2 6/6] net/ixgbe: use flow sample to re-realize mirror rule Steve Yang
2021-02-19 12:59     ` Ferruh Yigit

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=20201014084131.72035-9-simonx.lu@intel.com \
    --to=simonx.lu@intel.com \
    --cc=beilei.xing@intel.com \
    --cc=dev@dpdk.org \
    --cc=haiyue.wang@intel.com \
    --cc=jia.guo@intel.com \
    --cc=orika@nvidia.com \
    --cc=qiming.yang@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).