From patchwork Tue Dec 25 05:44:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhao1, Wei" X-Patchwork-Id: 49261 X-Patchwork-Delegate: qi.z.zhang@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id AE3451B44E; Tue, 25 Dec 2018 07:10:13 +0100 (CET) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id 1EE8B1B436; Tue, 25 Dec 2018 07:10:10 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 24 Dec 2018 22:10:10 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,395,1539673200"; d="scan'208";a="121503673" Received: from dpdk6.bj.intel.com ([172.16.182.192]) by orsmga001.jf.intel.com with ESMTP; 24 Dec 2018 22:10:08 -0800 From: Wei Zhao To: dev@dpdk.org Cc: stable@dpdk.org, wenzhuo.lu@intel.com, qi.z.zhang@intel.com, yuan.peng@intel.com, Wei Zhao Date: Tue, 25 Dec 2018 13:44:47 +0800 Message-Id: <1545716688-34608-2-git-send-email-wei.zhao1@intel.com> X-Mailer: git-send-email 2.7.5 In-Reply-To: <1545716688-34608-1-git-send-email-wei.zhao1@intel.com> References: <1545025982-2065-1-git-send-email-wei.zhao1@intel.com> <1545716688-34608-1-git-send-email-wei.zhao1@intel.com> Subject: [dpdk-dev] [PATCH v2 1/2] net/ixgbe: enable x550 flexible byte filter 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" There is need for users to use flexible byte filter on x550. x550 support IP mode and tunnel mode flexible byte filter. tunnel mode flexible byte filter is used for vxlan packets and so on. It can be used combined with FDIR tunnel filter. By now, ixgbe PMD flow parer code do not support tunnel mode flexible byte filter for x550, So I have to enable it in function ixgbe_parse_fdir_filter_tunnel(). Although IP mode flexible byte filter parser is support in function ixgbe_parse_fdir_filter_normal(), but some flow like "flow create 0 ingress pattern raw pattern is 0xab / end actions queue index 3 / end" need to be support, so parser code also need change a little. This patch enable all of these feature. Fixes: 82fb702077f6 ("ixgbe: support new flow director modes for X550") Fixes: 11777435c727 ("net/ixgbe: parse flow director filter") Signed-off-by: Wei Zhao --- drivers/net/ixgbe/ixgbe_fdir.c | 9 +- drivers/net/ixgbe/ixgbe_flow.c | 274 ++++++++++++++++++++++++++++------------- 2 files changed, 195 insertions(+), 88 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_fdir.c b/drivers/net/ixgbe/ixgbe_fdir.c index e559f0f..deb9a21 100644 --- a/drivers/net/ixgbe/ixgbe_fdir.c +++ b/drivers/net/ixgbe/ixgbe_fdir.c @@ -307,6 +307,8 @@ fdir_set_input_mask_82599(struct rte_eth_dev *dev) /* flex byte mask */ if (info->mask.flex_bytes_mask == 0) fdirm |= IXGBE_FDIRM_FLEX; + if (info->mask.src_ipv4_mask == 0 && info->mask.dst_ipv4_mask == 0) + fdirm |= IXGBE_FDIRM_L3P; IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm); @@ -356,8 +358,7 @@ fdir_set_input_mask_x550(struct rte_eth_dev *dev) /* mask VM pool and DIPv6 since there are currently not supported * mask FLEX byte, it will be set in flex_conf */ - uint32_t fdirm = IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6 | - IXGBE_FDIRM_FLEX; + uint32_t fdirm = IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6; uint32_t fdiripv6m; enum rte_fdir_mode mode = dev->data->dev_conf.fdir_conf.mode; uint16_t mac_mask; @@ -385,6 +386,10 @@ fdir_set_input_mask_x550(struct rte_eth_dev *dev) return -EINVAL; } + /* flex byte mask */ + if (info->mask.flex_bytes_mask == 0) + fdirm |= IXGBE_FDIRM_FLEX; + IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm); fdiripv6m = ((u32)0xFFFFU << IXGBE_FDIRIP6M_DIPM_SHIFT); diff --git a/drivers/net/ixgbe/ixgbe_flow.c b/drivers/net/ixgbe/ixgbe_flow.c index f0fafeb..dc210c5 100644 --- a/drivers/net/ixgbe/ixgbe_flow.c +++ b/drivers/net/ixgbe/ixgbe_flow.c @@ -1622,9 +1622,9 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev, const struct rte_flow_item_raw *raw_mask; const struct rte_flow_item_raw *raw_spec; uint8_t j; - struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + if (!pattern) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM, @@ -1651,9 +1651,7 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev, * value. So, we need not do anything for the not provided fields later. */ memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - memset(&rule->mask, 0xFF, sizeof(struct ixgbe_hw_fdir_mask)); - rule->mask.vlan_tci_mask = 0; - rule->mask.flex_bytes_mask = 0; + memset(&rule->mask, 0, sizeof(struct ixgbe_hw_fdir_mask)); /** * The first not void item should be @@ -1665,7 +1663,8 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev, item->type != RTE_FLOW_ITEM_TYPE_IPV6 && item->type != RTE_FLOW_ITEM_TYPE_TCP && item->type != RTE_FLOW_ITEM_TYPE_UDP && - item->type != RTE_FLOW_ITEM_TYPE_SCTP) { + item->type != RTE_FLOW_ITEM_TYPE_SCTP && + item->type != RTE_FLOW_ITEM_TYPE_RAW) { memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2201,6 +2200,7 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev, } raw_mask = item->mask; + rule->b_mask = TRUE; /* check mask */ if (raw_mask->relative != 0x1 || @@ -2217,6 +2217,7 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev, } raw_spec = item->spec; + rule->b_spec = TRUE; /* check spec */ if (raw_spec->relative != 0 || @@ -2323,6 +2324,8 @@ ixgbe_parse_fdir_filter_tunnel(const struct rte_flow_attr *attr, const struct rte_flow_item_eth *eth_mask; const struct rte_flow_item_vlan *vlan_spec; const struct rte_flow_item_vlan *vlan_mask; + const struct rte_flow_item_raw *raw_mask; + const struct rte_flow_item_raw *raw_spec; uint32_t j; if (!pattern) { @@ -2351,8 +2354,7 @@ ixgbe_parse_fdir_filter_tunnel(const struct rte_flow_attr *attr, * value. So, we need not do anything for the not provided fields later. */ memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - memset(&rule->mask, 0xFF, sizeof(struct ixgbe_hw_fdir_mask)); - rule->mask.vlan_tci_mask = 0; + memset(&rule->mask, 0, sizeof(struct ixgbe_hw_fdir_mask)); /** * The first not void item should be @@ -2364,7 +2366,8 @@ ixgbe_parse_fdir_filter_tunnel(const struct rte_flow_attr *attr, item->type != RTE_FLOW_ITEM_TYPE_IPV6 && item->type != RTE_FLOW_ITEM_TYPE_UDP && item->type != RTE_FLOW_ITEM_TYPE_VXLAN && - item->type != RTE_FLOW_ITEM_TYPE_NVGRE) { + item->type != RTE_FLOW_ITEM_TYPE_NVGRE && + item->type != RTE_FLOW_ITEM_TYPE_RAW) { memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2520,6 +2523,18 @@ ixgbe_parse_fdir_filter_tunnel(const struct rte_flow_attr *attr, &rule->ixgbe_fdir.formatted.tni_vni), vxlan_spec->vni, RTE_DIM(vxlan_spec->vni)); } + /* check if the next not void item is MAC VLAN RAW or END*/ + item = next_no_void_pattern(pattern, item); + if (item->type != RTE_FLOW_ITEM_TYPE_ETH && + item->type != RTE_FLOW_ITEM_TYPE_VLAN && + item->type != RTE_FLOW_ITEM_TYPE_RAW && + item->type != RTE_FLOW_ITEM_TYPE_END){ + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; + } } /* Get the NVGRE info */ @@ -2616,16 +2631,19 @@ ixgbe_parse_fdir_filter_tunnel(const struct rte_flow_attr *attr, rte_memcpy(&rule->ixgbe_fdir.formatted.tni_vni, nvgre_spec->tni, RTE_DIM(nvgre_spec->tni)); } - } - /* check if the next not void item is MAC */ - item = next_no_void_pattern(pattern, item); - if (item->type != RTE_FLOW_ITEM_TYPE_ETH) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, - item, "Not supported by fdir filter"); - return -rte_errno; + /* check if the next not void item is MAC VLAN RAW or END*/ + item = next_no_void_pattern(pattern, item); + if (item->type != RTE_FLOW_ITEM_TYPE_ETH && + item->type != RTE_FLOW_ITEM_TYPE_VLAN && + item->type != RTE_FLOW_ITEM_TYPE_RAW && + item->type != RTE_FLOW_ITEM_TYPE_END){ + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; + } } /** @@ -2633,92 +2651,91 @@ ixgbe_parse_fdir_filter_tunnel(const struct rte_flow_attr *attr, * others should be masked. */ - if (!item->mask) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, - item, "Not supported by fdir filter"); - return -rte_errno; - } - /*Not supported last point for range*/ - if (item->last) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - item, "Not supported last point for range"); - return -rte_errno; - } - rule->b_mask = TRUE; - eth_mask = item->mask; - - /* Ether type should be masked. */ - if (eth_mask->type) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, - item, "Not supported by fdir filter"); - return -rte_errno; - } - - /* src MAC address should be masked. */ - for (j = 0; j < ETHER_ADDR_LEN; j++) { - if (eth_mask->src.addr_bytes[j]) { - memset(rule, 0, - sizeof(struct ixgbe_fdir_rule)); + if (item->type == RTE_FLOW_ITEM_TYPE_ETH) { + if (!item->mask) { + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, "Not supported by fdir filter"); return -rte_errno; } - } - rule->mask.mac_addr_byte_mask = 0; - for (j = 0; j < ETHER_ADDR_LEN; j++) { - /* It's a per byte mask. */ - if (eth_mask->dst.addr_bytes[j] == 0xFF) { - rule->mask.mac_addr_byte_mask |= 0x1 << j; - } else if (eth_mask->dst.addr_bytes[j]) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + /*Not supported last point for range*/ + if (item->last) { rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + item, "Not supported last point for range"); + return -rte_errno; + } + rule->b_mask = TRUE; + eth_mask = item->mask; + + /* Ether type should be masked. */ + if (eth_mask->type) { + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, "Not supported by fdir filter"); return -rte_errno; } - } - /* When no vlan, considered as full mask. */ - rule->mask.vlan_tci_mask = rte_cpu_to_be_16(0xEFFF); - - if (item->spec) { - rule->b_spec = TRUE; - eth_spec = item->spec; - - /* Get the dst MAC. */ + /* src MAC address should be masked. */ for (j = 0; j < ETHER_ADDR_LEN; j++) { - rule->ixgbe_fdir.formatted.inner_mac[j] = - eth_spec->dst.addr_bytes[j]; + if (eth_mask->src.addr_bytes[j]) { + memset(rule, 0, + sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; + } + } + for (j = 0; j < ETHER_ADDR_LEN; j++) { + /* It's a per byte mask. */ + if (eth_mask->dst.addr_bytes[j] == 0xFF) { + rule->mask.mac_addr_byte_mask |= 0x1 << j; + } else if (eth_mask->dst.addr_bytes[j]) { + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; + } } - } - /** - * Check if the next not void item is vlan or ipv4. - * IPv6 is not supported. - */ - item = next_no_void_pattern(pattern, item); - if ((item->type != RTE_FLOW_ITEM_TYPE_VLAN) && - (item->type != RTE_FLOW_ITEM_TYPE_IPV4)) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, - item, "Not supported by fdir filter"); - return -rte_errno; - } - /*Not supported last point for range*/ - if (item->last) { - rte_flow_error_set(error, EINVAL, + if (item->spec) { + rule->b_spec = TRUE; + eth_spec = item->spec; + + /* Get the dst MAC. */ + for (j = 0; j < ETHER_ADDR_LEN; j++) { + rule->ixgbe_fdir.formatted.inner_mac[j] = + eth_spec->dst.addr_bytes[j]; + } + } + /** + * Check if the next not void item is vlan or ipv4. + * IPv6 is not supported. + */ + item = next_no_void_pattern(pattern, item); + if (item->type != RTE_FLOW_ITEM_TYPE_VLAN && + item->type != RTE_FLOW_ITEM_TYPE_RAW && + item->type != RTE_FLOW_ITEM_TYPE_END) { + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; + } + /*Not supported last point for range*/ + if (item->last) { + rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, item, "Not supported last point for range"); - return -rte_errno; + return -rte_errno; + } } + if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) { if (!(item->spec && item->mask)) { memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); @@ -2736,10 +2753,90 @@ ixgbe_parse_fdir_filter_tunnel(const struct rte_flow_attr *attr, rule->mask.vlan_tci_mask = vlan_mask->tci; rule->mask.vlan_tci_mask &= rte_cpu_to_be_16(0xEFFF); /* More than one tags are not supported. */ + item = next_no_void_pattern(pattern, item); + if (item->type != RTE_FLOW_ITEM_TYPE_RAW && + item->type != RTE_FLOW_ITEM_TYPE_END) { + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; + } + } + + /* Get the flex byte info */ + if (item->type == RTE_FLOW_ITEM_TYPE_RAW) { + /* Not supported last point for range*/ + if (item->last) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + item, "Not supported last point for range"); + return -rte_errno; + } + /* mask should not be null */ + if (!item->mask || !item->spec) { + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; + } + + raw_mask = item->mask; + rule->b_mask = TRUE; + /* check mask */ + if (raw_mask->relative != 0x1 || + raw_mask->search != 0x1 || + raw_mask->reserved != 0x0 || + (uint32_t)raw_mask->offset != 0xffffffff || + raw_mask->limit != 0xffff || + raw_mask->length != 0xffff) { + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; + } + + raw_spec = item->spec; + rule->b_spec = TRUE; + + /* check spec */ + if (raw_spec->relative != 0 || + raw_spec->search != 0 || + raw_spec->reserved != 0 || + raw_spec->offset > IXGBE_MAX_FLX_SOURCE_OFF || + raw_spec->offset % 2 || + raw_spec->limit != 0 || + raw_spec->length != 2 || + /* pattern can't be 0xffff */ + (raw_spec->pattern[0] == 0xff && + raw_spec->pattern[1] == 0xff)) { + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; + } + + /* check pattern mask */ + if (raw_mask->pattern[0] != 0xff || + raw_mask->pattern[1] != 0xff) { + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; + } + + rule->mask.flex_bytes_mask = 0xffff; + rule->ixgbe_fdir.formatted.flex_bytes = + (((uint16_t)raw_spec->pattern[1]) << 8) | + raw_spec->pattern[0]; + rule->flex_bytes_offset = raw_spec->offset; /* check if the next not void item is END */ item = next_no_void_pattern(pattern, item); - if (item->type != RTE_FLOW_ITEM_TYPE_END) { memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); rte_flow_error_set(error, EINVAL, @@ -2776,12 +2873,17 @@ ixgbe_parse_fdir_filter(struct rte_eth_dev *dev, hw->mac.type != ixgbe_mac_X550EM_a) return -ENOTSUP; + if (fdir_mode == RTE_FDIR_MODE_PERFECT_TUNNEL) + goto tunnel_filter; + ret = ixgbe_parse_fdir_filter_normal(dev, attr, pattern, actions, rule, error); if (!ret) goto step_next; +tunnel_filter: + ret = ixgbe_parse_fdir_filter_tunnel(attr, pattern, actions, rule, error); From patchwork Tue Dec 25 05:44:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhao1, Wei" X-Patchwork-Id: 49262 X-Patchwork-Delegate: qi.z.zhang@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 10D5D1B459; Tue, 25 Dec 2018 07:10:16 +0100 (CET) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id 9AA081B44B; Tue, 25 Dec 2018 07:10:13 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 24 Dec 2018 22:10:13 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,395,1539673200"; d="scan'208";a="121503689" Received: from dpdk6.bj.intel.com ([172.16.182.192]) by orsmga001.jf.intel.com with ESMTP; 24 Dec 2018 22:10:11 -0800 From: Wei Zhao To: dev@dpdk.org Cc: stable@dpdk.org, wenzhuo.lu@intel.com, qi.z.zhang@intel.com, yuan.peng@intel.com, Wei Zhao Date: Tue, 25 Dec 2018 13:44:48 +0800 Message-Id: <1545716688-34608-3-git-send-email-wei.zhao1@intel.com> X-Mailer: git-send-email 2.7.5 In-Reply-To: <1545716688-34608-1-git-send-email-wei.zhao1@intel.com> References: <1545025982-2065-1-git-send-email-wei.zhao1@intel.com> <1545716688-34608-1-git-send-email-wei.zhao1@intel.com> Subject: [dpdk-dev] [PATCH v2 2/2] app/testpmd: add support of hex string parser for flow API 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" There is need for users to use flexible byte filter on ixgbe. The flexible byte should be pass down as hex number not char string. This patch enable users to make configuration using hex number for flexible byte filter. cmdline flow parse HEX number, in order to not using string which pass ASIC number. Fixes: abc3d81aca1b ("app/testpmd: add item raw to flow command") Signed-off-by: Wei Zhao --- app/test-pmd/cmdline_flow.c | 141 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 140 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 8b7a5c0..ba9b692 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -35,6 +35,7 @@ enum index { PREFIX, BOOLEAN, STRING, + HEX, MAC_ADDR, IPV4_ADDR, IPV6_ADDR, @@ -1122,6 +1123,9 @@ static int parse_boolean(struct context *, const struct token *, static int parse_string(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_hex(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size); static int parse_mac_addr(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -1198,6 +1202,13 @@ static const struct token token_list[] = { .call = parse_string, .comp = comp_none, }, + [HEX] = { + .name = "{hex}", + .type = "HEX", + .help = "fixed string", + .call = parse_hex, + .comp = comp_none, + }, [MAC_ADDR] = { .name = "{MAC address}", .type = "MAC-48", @@ -1544,7 +1555,7 @@ static const struct token token_list[] = { .name = "pattern", .help = "byte string to look for", .next = NEXT(item_raw, - NEXT_ENTRY(STRING), + NEXT_ENTRY(HEX), NEXT_ENTRY(ITEM_PARAM_IS, ITEM_PARAM_SPEC, ITEM_PARAM_MASK)), @@ -4441,6 +4452,134 @@ parse_string(struct context *ctx, const struct token *token, return -1; } +static uint32_t +get_hex_val(char c) +{ + switch (c) { + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + return c - '0'; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + return c - 'A' + 10; + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return c - 'a' + 10; + default: + return 0; + } +} + +static int +parse_hex_string(const char *src, uint8_t *dst, uint32_t *size) +{ + const char *c; + uint32_t i; + + /* Check input parameters */ + if ((src == NULL) || + (dst == NULL) || + (size == NULL) || + (*size == 0)) + return -1; + if ((*size & 1) != 0) + return -1; + + for (c = src, i = 0; i < *size; c++, i++) { + if ((((*c) >= '0') && ((*c) <= '9')) || + (((*c) >= 'A') && ((*c) <= 'F')) || + (((*c) >= 'a') && ((*c) <= 'f'))) + continue; + + return -1; + } + *size = *size / 2; + + /* Convert chars to bytes */ + for (i = 0; i < *size; i++) + dst[i] = get_hex_val(src[2 * i]) * 16 + + get_hex_val(src[2 * i + 1]); + + return 0; +} + +static int +parse_hex(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + const struct arg *arg_data = pop_args(ctx); + const struct arg *arg_len = pop_args(ctx); + const struct arg *arg_addr = pop_args(ctx); + char tmp[16]; /* Ought to be enough. */ + int ret; + unsigned int hexlen = len; + uint8_t hex_tmp[16]; + + /* Arguments are expected. */ + if (!arg_data) + return -1; + if (!arg_len) { + push_args(ctx, arg_data); + return -1; + } + if (!arg_addr) { + push_args(ctx, arg_len); + push_args(ctx, arg_data); + return -1; + } + size = arg_data->size; + /* Bit-mask fill is not supported. */ + if (arg_data->mask || size < len) + goto error; + if (!ctx->object) + return len; + + /* translate bytes string to array. */ + if (str[0] == '0' && ((str[1] == 'x') || + (str[1] == 'X'))) { + str += 2; + hexlen -= 2; + } + parse_hex_string(str, hex_tmp, &hexlen); + /* Let parse_int() fill length information first. */ + ret = snprintf(tmp, sizeof(tmp), "%u", hexlen); + if (ret < 0) + goto error; + push_args(ctx, arg_len); + ret = parse_int(ctx, token, tmp, ret, NULL, 0); + if (ret < 0) { + pop_args(ctx); + goto error; + } + buf = (uint8_t *)ctx->object + arg_data->offset; + /* Output buffer is not necessarily NUL-terminated. */ + memcpy(buf, hex_tmp, hexlen); + memset((uint8_t *)buf + len, 0x00, size - hexlen); + if (ctx->objmask) + memset((uint8_t *)ctx->objmask + arg_data->offset, + 0xff, hexlen); + /* Save address if requested. */ + if (arg_addr->size) { + memcpy((uint8_t *)ctx->object + arg_addr->offset, + (void *[]){ + (uint8_t *)ctx->object + arg_data->offset + }, + arg_addr->size); + if (ctx->objmask) + memcpy((uint8_t *)ctx->objmask + arg_addr->offset, + (void *[]){ + (uint8_t *)ctx->objmask + arg_data->offset + }, + arg_addr->size); + } + return len; +error: + push_args(ctx, arg_addr); + push_args(ctx, arg_len); + push_args(ctx, arg_data); + return -1; + +} + /** * Parse a MAC address. *