From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 7B643A04B7; Wed, 14 Oct 2020 10:45:56 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id D56EE1DD42; Wed, 14 Oct 2020 10:43:34 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id A78D51DD36 for ; Wed, 14 Oct 2020 10:43:32 +0200 (CEST) IronPort-SDR: G5OL/qqbNXIY8AOG7kY8b8qzyfnVuiDF/okFPWjNDi5LUM1pzBNL+Gae5yOoLaRncHz3CAyYMP AUia6YLmUyyg== X-IronPort-AV: E=McAfee;i="6000,8403,9773"; a="163432247" X-IronPort-AV: E=Sophos;i="5.77,374,1596524400"; d="scan'208";a="163432247" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Oct 2020 01:43:32 -0700 IronPort-SDR: B6VxOPdiElcQRhWpA7mecaBIb62LAiucV2qEuTVBSj+U9BQDNlYSUrv0vSdzQ4cweU5BtD6OMq Hem5XQ4WOJbQ== X-IronPort-AV: E=Sophos;i="5.77,374,1596524400"; d="scan'208";a="299864596" Received: from intel-npg-odc-srv01.cd.intel.com ([10.240.178.136]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Oct 2020 01:43:29 -0700 From: SimonX Lu 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 Date: Wed, 14 Oct 2020 08:41:31 +0000 Message-Id: <20201014084131.72035-9-simonx.lu@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201014084131.72035-1-simonx.lu@intel.com> References: <20201014084131.72035-1-simonx.lu@intel.com> Subject: [dpdk-dev] [PATCH v1 8/8] net/i40e: use generic flow command to re-realize mirror rule X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Simon Lu 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 --- 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