From patchwork Tue Nov 3 10:08:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 83545 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 2F835A0521; Tue, 3 Nov 2020 11:16:00 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 8082CCA4D; Tue, 3 Nov 2020 11:07:42 +0100 (CET) Received: from smtpproxy21.qq.com (smtpbg702.qq.com [203.205.195.102]) by dpdk.org (Postfix) with ESMTP id ADEC8C9BC for ; Tue, 3 Nov 2020 11:07:25 +0100 (CET) X-QQ-mid: bizesmtp26t1604398040tw2w1nm7 Received: from localhost.localdomain.com (unknown [183.129.236.74]) by esmtp10.qq.com (ESMTP) with id ; Tue, 03 Nov 2020 18:07:20 +0800 (CST) X-QQ-SSF: 01400000002000C0C000B00A0000000 X-QQ-FEAT: mr9Nfp8Iec2jr//d21tWsWAGUlSt4e7Es7qbSsmZ4S8y93EYSWjwgIzVLMew2 ZDfh/HhaDiSRoWbc7L+47EmFRpIBZ6TdRZ43kZMhnM6FL2QirDmwKMHuv7/8QZNKegStqc3 ZvLfcrWaG9BV5HAETQ3EJm6IwLZt+aTXEad2CWe9nKZ73ezHi5Kq5JA393+RIP32ghQcU1B 27HGy0H91wo5CV/W45nv8+NB140SoqNkjKQd2EveY5K0rAOiZFEBjky7/EGng3t3XeFQFww LPWs2+fyE29dwfZW4RGU/huQNSHrbl0MqwbIHiIbwA56Eh3xZ6MaIbqW7C2F4yMZUExz+Mn GISDZKtRaNxCdRNUHf7ffksfLVOzw== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Tue, 3 Nov 2020 18:08:04 +0800 Message-Id: <20201103100818.311881-24-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.18.4 In-Reply-To: <20201103100818.311881-1-jiawenwu@trustnetic.com> References: <20201103100818.311881-1-jiawenwu@trustnetic.com> X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign5 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH 23/37] net/txgbe: add flow API create function 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" Add support to create operation for flow API. Signed-off-by: Jiawen Wu --- drivers/net/txgbe/txgbe_ethdev.h | 2 + drivers/net/txgbe/txgbe_fdir.c | 27 ++++ drivers/net/txgbe/txgbe_flow.c | 257 +++++++++++++++++++++++++++++++ 3 files changed, 286 insertions(+) diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index 2b5c0e35d..f439a201b 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -464,6 +464,8 @@ void txgbe_set_ivar_map(struct txgbe_hw *hw, int8_t direction, */ int txgbe_fdir_configure(struct rte_eth_dev *dev); int txgbe_fdir_set_input_mask(struct rte_eth_dev *dev); +int txgbe_fdir_set_flexbytes_offset(struct rte_eth_dev *dev, + uint16_t offset); int txgbe_fdir_filter_program(struct rte_eth_dev *dev, struct txgbe_fdir_rule *rule, bool del, bool update); diff --git a/drivers/net/txgbe/txgbe_fdir.c b/drivers/net/txgbe/txgbe_fdir.c index 2faf7fd84..2342cf681 100644 --- a/drivers/net/txgbe/txgbe_fdir.c +++ b/drivers/net/txgbe/txgbe_fdir.c @@ -270,6 +270,33 @@ txgbe_fdir_store_input_mask(struct rte_eth_dev *dev) return 0; } +int +txgbe_fdir_set_flexbytes_offset(struct rte_eth_dev *dev, + uint16_t offset) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + int i; + + for (i = 0; i < 64; i++) { + uint32_t flexreg, flex; + flexreg = rd32(hw, TXGBE_FDIRFLEXCFG(i / 4)); + flex = TXGBE_FDIRFLEXCFG_BASE_MAC; + flex |= TXGBE_FDIRFLEXCFG_OFST(offset / 2); + flexreg &= ~(TXGBE_FDIRFLEXCFG_ALL(~0UL, i % 4)); + flexreg |= TXGBE_FDIRFLEXCFG_ALL(flex, i % 4); + wr32(hw, TXGBE_FDIRFLEXCFG(i / 4), flexreg); + } + + txgbe_flush(hw); + for (i = 0; i < TXGBE_FDIR_INIT_DONE_POLL; i++) { + if (rd32(hw, TXGBE_FDIRCTL) & + TXGBE_FDIRCTL_INITDONE) + break; + msec_delay(1); + } + return 0; +} + /* * txgbe_check_fdir_flex_conf -check if the flex payload and mask configuration * arguments are valid diff --git a/drivers/net/txgbe/txgbe_flow.c b/drivers/net/txgbe/txgbe_flow.c index 884a8545f..4141352bf 100644 --- a/drivers/net/txgbe/txgbe_flow.c +++ b/drivers/net/txgbe/txgbe_flow.c @@ -2629,6 +2629,262 @@ txgbe_filterlist_flush(void) } } +/** + * Create or destroy a flow rule. + * Theorically one rule can match more than one filters. + * We will let it use the filter which it hitt first. + * So, the sequence matters. + */ +static struct rte_flow * +txgbe_flow_create(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + int ret; + struct rte_eth_ntuple_filter ntuple_filter; + struct rte_eth_ethertype_filter ethertype_filter; + struct rte_eth_syn_filter syn_filter; + struct txgbe_fdir_rule fdir_rule; + struct txgbe_l2_tunnel_conf l2_tn_filter; + struct txgbe_hw_fdir_info *fdir_info = TXGBE_DEV_FDIR(dev); + struct txgbe_rte_flow_rss_conf rss_conf; + struct rte_flow *flow = NULL; + struct txgbe_ntuple_filter_ele *ntuple_filter_ptr; + struct txgbe_ethertype_filter_ele *ethertype_filter_ptr; + struct txgbe_eth_syn_filter_ele *syn_filter_ptr; + struct txgbe_eth_l2_tunnel_conf_ele *l2_tn_filter_ptr; + struct txgbe_fdir_rule_ele *fdir_rule_ptr; + struct txgbe_rss_conf_ele *rss_filter_ptr; + struct txgbe_flow_mem *txgbe_flow_mem_ptr; + uint8_t first_mask = FALSE; + + flow = rte_zmalloc("txgbe_rte_flow", sizeof(struct rte_flow), 0); + if (!flow) { + PMD_DRV_LOG(ERR, "failed to allocate memory"); + return (struct rte_flow *)flow; + } + txgbe_flow_mem_ptr = rte_zmalloc("txgbe_flow_mem", + sizeof(struct txgbe_flow_mem), 0); + if (!txgbe_flow_mem_ptr) { + PMD_DRV_LOG(ERR, "failed to allocate memory"); + rte_free(flow); + return NULL; + } + txgbe_flow_mem_ptr->flow = flow; + TAILQ_INSERT_TAIL(&txgbe_flow_list, + txgbe_flow_mem_ptr, entries); + + memset(&ntuple_filter, 0, sizeof(struct rte_eth_ntuple_filter)); + ret = txgbe_parse_ntuple_filter(dev, attr, pattern, + actions, &ntuple_filter, error); + + if (!ret) { + ret = txgbe_add_del_ntuple_filter(dev, &ntuple_filter, TRUE); + if (!ret) { + ntuple_filter_ptr = rte_zmalloc("txgbe_ntuple_filter", + sizeof(struct txgbe_ntuple_filter_ele), 0); + if (!ntuple_filter_ptr) { + PMD_DRV_LOG(ERR, "failed to allocate memory"); + goto out; + } + rte_memcpy(&ntuple_filter_ptr->filter_info, + &ntuple_filter, + sizeof(struct rte_eth_ntuple_filter)); + TAILQ_INSERT_TAIL(&filter_ntuple_list, + ntuple_filter_ptr, entries); + flow->rule = ntuple_filter_ptr; + flow->filter_type = RTE_ETH_FILTER_NTUPLE; + return flow; + } + goto out; + } + + memset(ðertype_filter, 0, sizeof(struct rte_eth_ethertype_filter)); + ret = txgbe_parse_ethertype_filter(dev, attr, pattern, + actions, ðertype_filter, error); + if (!ret) { + ret = txgbe_add_del_ethertype_filter(dev, + ðertype_filter, TRUE); + if (!ret) { + ethertype_filter_ptr = + rte_zmalloc("txgbe_ethertype_filter", + sizeof(struct txgbe_ethertype_filter_ele), 0); + if (!ethertype_filter_ptr) { + PMD_DRV_LOG(ERR, "failed to allocate memory"); + goto out; + } + rte_memcpy(ðertype_filter_ptr->filter_info, + ðertype_filter, + sizeof(struct rte_eth_ethertype_filter)); + TAILQ_INSERT_TAIL(&filter_ethertype_list, + ethertype_filter_ptr, entries); + flow->rule = ethertype_filter_ptr; + flow->filter_type = RTE_ETH_FILTER_ETHERTYPE; + return flow; + } + goto out; + } + + memset(&syn_filter, 0, sizeof(struct rte_eth_syn_filter)); + ret = txgbe_parse_syn_filter(dev, attr, pattern, + actions, &syn_filter, error); + if (!ret) { + ret = txgbe_syn_filter_set(dev, &syn_filter, TRUE); + if (!ret) { + syn_filter_ptr = rte_zmalloc("txgbe_syn_filter", + sizeof(struct txgbe_eth_syn_filter_ele), 0); + if (!syn_filter_ptr) { + PMD_DRV_LOG(ERR, "failed to allocate memory"); + goto out; + } + rte_memcpy(&syn_filter_ptr->filter_info, + &syn_filter, + sizeof(struct rte_eth_syn_filter)); + TAILQ_INSERT_TAIL(&filter_syn_list, + syn_filter_ptr, + entries); + flow->rule = syn_filter_ptr; + flow->filter_type = RTE_ETH_FILTER_SYN; + return flow; + } + goto out; + } + + memset(&fdir_rule, 0, sizeof(struct txgbe_fdir_rule)); + ret = txgbe_parse_fdir_filter(dev, attr, pattern, + actions, &fdir_rule, error); + if (!ret) { + /* A mask cannot be deleted. */ + if (fdir_rule.b_mask) { + if (!fdir_info->mask_added) { + /* It's the first time the mask is set. */ + rte_memcpy(&fdir_info->mask, + &fdir_rule.mask, + sizeof(struct txgbe_hw_fdir_mask)); + fdir_info->flex_bytes_offset = + fdir_rule.flex_bytes_offset; + + if (fdir_rule.mask.flex_bytes_mask) + txgbe_fdir_set_flexbytes_offset(dev, + fdir_rule.flex_bytes_offset); + + ret = txgbe_fdir_set_input_mask(dev); + if (ret) + goto out; + + fdir_info->mask_added = TRUE; + first_mask = TRUE; + } else { + /** + * Only support one global mask, + * all the masks should be the same. + */ + ret = memcmp(&fdir_info->mask, + &fdir_rule.mask, + sizeof(struct txgbe_hw_fdir_mask)); + if (ret) + goto out; + + if (fdir_info->flex_bytes_offset != + fdir_rule.flex_bytes_offset) + goto out; + } + } + + if (fdir_rule.b_spec) { + ret = txgbe_fdir_filter_program(dev, &fdir_rule, + FALSE, FALSE); + if (!ret) { + fdir_rule_ptr = rte_zmalloc("txgbe_fdir_filter", + sizeof(struct txgbe_fdir_rule_ele), 0); + if (!fdir_rule_ptr) { + PMD_DRV_LOG(ERR, + "failed to allocate memory"); + goto out; + } + rte_memcpy(&fdir_rule_ptr->filter_info, + &fdir_rule, + sizeof(struct txgbe_fdir_rule)); + TAILQ_INSERT_TAIL(&filter_fdir_list, + fdir_rule_ptr, entries); + flow->rule = fdir_rule_ptr; + flow->filter_type = RTE_ETH_FILTER_FDIR; + + return flow; + } + + if (ret) { + /** + * clean the mask_added flag if fail to + * program + **/ + if (first_mask) + fdir_info->mask_added = FALSE; + goto out; + } + } + + goto out; + } + + memset(&l2_tn_filter, 0, sizeof(struct txgbe_l2_tunnel_conf)); + ret = txgbe_parse_l2_tn_filter(dev, attr, pattern, + actions, &l2_tn_filter, error); + if (!ret) { + ret = txgbe_dev_l2_tunnel_filter_add(dev, &l2_tn_filter, FALSE); + if (!ret) { + l2_tn_filter_ptr = rte_zmalloc("txgbe_l2_tn_filter", + sizeof(struct txgbe_eth_l2_tunnel_conf_ele), 0); + if (!l2_tn_filter_ptr) { + PMD_DRV_LOG(ERR, "failed to allocate memory"); + goto out; + } + rte_memcpy(&l2_tn_filter_ptr->filter_info, + &l2_tn_filter, + sizeof(struct txgbe_l2_tunnel_conf)); + TAILQ_INSERT_TAIL(&filter_l2_tunnel_list, + l2_tn_filter_ptr, entries); + flow->rule = l2_tn_filter_ptr; + flow->filter_type = RTE_ETH_FILTER_L2_TUNNEL; + return flow; + } + } + + memset(&rss_conf, 0, sizeof(struct txgbe_rte_flow_rss_conf)); + ret = txgbe_parse_rss_filter(dev, attr, + actions, &rss_conf, error); + if (!ret) { + ret = txgbe_config_rss_filter(dev, &rss_conf, TRUE); + if (!ret) { + rss_filter_ptr = rte_zmalloc("txgbe_rss_filter", + sizeof(struct txgbe_rss_conf_ele), 0); + if (!rss_filter_ptr) { + PMD_DRV_LOG(ERR, "failed to allocate memory"); + goto out; + } + txgbe_rss_conf_init(&rss_filter_ptr->filter_info, + &rss_conf.conf); + TAILQ_INSERT_TAIL(&filter_rss_list, + rss_filter_ptr, entries); + flow->rule = rss_filter_ptr; + flow->filter_type = RTE_ETH_FILTER_HASH; + return flow; + } + } + +out: + TAILQ_REMOVE(&txgbe_flow_list, + txgbe_flow_mem_ptr, entries); + rte_flow_error_set(error, -ret, + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "Failed to create flow."); + rte_free(txgbe_flow_mem_ptr); + rte_free(flow); + return NULL; +} + /** * Check if the flow rule is supported by txgbe. * It only checkes the format. Don't guarantee the rule can be programmed into @@ -2688,5 +2944,6 @@ txgbe_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_ops txgbe_flow_ops = { .validate = txgbe_flow_validate, + .create = txgbe_flow_create, };