From c410e1d5627bd7ce41b5c74013407d6b40a5cdef Mon Sep 17 00:00:00 2001 From: Gregory Etelson Date: Mon, 5 Jul 2021 14:40:35 +0300 Subject: [PATCH] net/mlx5: support flow matchng on IPv4 IHL Query MLX5 port hardware if it is capable to offload IPv4 IHL field. Provide flow rules capability to match on IPv4 IHL field. Minimal HCA firmware version required to offload IPv4 IHL is xx_30_2000. Signed-off-by: Gregory Etelson Acked-by: Viacheslav Ovsiienko --- doc/guides/nics/mlx5.rst | 1 + doc/guides/rel_notes/release_21_08.rst | 1 + drivers/common/mlx5/mlx5_devx_cmds.c | 6 +++++ drivers/common/mlx5/mlx5_devx_cmds.h | 2 ++ drivers/net/mlx5/mlx5_flow_dv.c | 31 +++++++++++++++++++------- 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index 4d989686db..f5b727c1ee 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -99,6 +99,7 @@ Features - Hardware LRO. - Hairpin. - Multiple-thread flow insertion. +- Matching on IPv4 Internet Header Length (IHL). - Matching on GTP extension header with raw encap/decap action. - Matching on Geneve TLV option header with raw encap/decap action. - RSS support in sample action. diff --git a/doc/guides/rel_notes/release_21_08.rst b/doc/guides/rel_notes/release_21_08.rst index fadaa71087..1b38b1aa51 100644 --- a/doc/guides/rel_notes/release_21_08.rst +++ b/doc/guides/rel_notes/release_21_08.rst @@ -88,6 +88,7 @@ New Features * Added support for meter hierarchy. * Added devargs options ``allow_duplicate_pattern``. + * Added matching on IPv4 Internet Header Length (IHL). * Added support for matching on VXLAN header last 8-bits reserved field. * Optimized multi-thread flow rule insertion rate. diff --git a/drivers/common/mlx5/mlx5_devx_cmds.c b/drivers/common/mlx5/mlx5_devx_cmds.c index 63ae95832d..10a02d13ee 100644 --- a/drivers/common/mlx5/mlx5_devx_cmds.c +++ b/drivers/common/mlx5/mlx5_devx_cmds.c @@ -951,6 +951,12 @@ mlx5_devx_cmd_query_hca_attr(void *ctx, (flow_table_nic_cap, hcattr, ft_field_support_2_nic_receive.tunnel_header_0_1); attr->pkt_integrity_match = mlx5_devx_query_pkt_integrity_match(hcattr); + attr->inner_ipv4_ihl = MLX5_GET + (flow_table_nic_cap, hcattr, + ft_field_support_2_nic_receive.inner_ipv4_ihl); + attr->outer_ipv4_ihl = MLX5_GET + (flow_table_nic_cap, hcattr, + ft_field_support_2_nic_receive.outer_ipv4_ihl); /* Query HCA offloads for Ethernet protocol. */ memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); diff --git a/drivers/common/mlx5/mlx5_devx_cmds.h b/drivers/common/mlx5/mlx5_devx_cmds.h index 124f43e852..c11ca6586f 100644 --- a/drivers/common/mlx5/mlx5_devx_cmds.h +++ b/drivers/common/mlx5/mlx5_devx_cmds.h @@ -153,6 +153,8 @@ struct mlx5_hca_attr { uint32_t crypto_login:1; /* General obj type CRYPTO_LOGIN supported. */ uint32_t regexp_num_of_engines; uint32_t log_max_ft_sampler_num:8; + uint32_t inner_ipv4_ihl:1; + uint32_t outer_ipv4_ihl:1; uint32_t geneve_tlv_opt; uint32_t cqe_compression:1; uint32_t mini_cqe_resp_flow_tag:1; diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index eb0465a650..996106b051 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -2492,19 +2492,19 @@ flow_dv_validate_item_gtp_psc(const struct rte_flow_item *item, * 0 on success, a negative errno value otherwise and rte_errno is set. */ static int -flow_dv_validate_item_ipv4(const struct rte_flow_item *item, - uint64_t item_flags, - uint64_t last_item, - uint16_t ether_type, - struct rte_flow_error *error) +flow_dv_validate_item_ipv4(struct rte_eth_dev *dev, + const struct rte_flow_item *item, + uint64_t item_flags, uint64_t last_item, + uint16_t ether_type, struct rte_flow_error *error) { int ret; + struct mlx5_priv *priv = dev->data->dev_private; const struct rte_flow_item_ipv4 *spec = item->spec; const struct rte_flow_item_ipv4 *last = item->last; const struct rte_flow_item_ipv4 *mask = item->mask; rte_be16_t fragment_offset_spec = 0; rte_be16_t fragment_offset_last = 0; - const struct rte_flow_item_ipv4 nic_ipv4_mask = { + struct rte_flow_item_ipv4 nic_ipv4_mask = { .hdr = { .src_addr = RTE_BE32(0xffffffff), .dst_addr = RTE_BE32(0xffffffff), @@ -2515,6 +2515,17 @@ flow_dv_validate_item_ipv4(const struct rte_flow_item *item, }, }; + if (mask && (mask->hdr.version_ihl & RTE_IPV4_HDR_IHL_MASK)) { + int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); + bool ihl_cap = !tunnel ? priv->config.hca_attr.outer_ipv4_ihl : + priv->config.hca_attr.inner_ipv4_ihl; + if (!ihl_cap) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "IPV4 ihl offload not supported"); + nic_ipv4_mask.hdr.version_ihl = mask->hdr.version_ihl; + } ret = mlx5_flow_validate_item_ipv4(item, item_flags, last_item, ether_type, &nic_ipv4_mask, MLX5_ITEM_RANGE_ACCEPTED, error); @@ -6996,7 +7007,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, case RTE_FLOW_ITEM_TYPE_IPV4: mlx5_flow_tunnel_ip_check(items, next_protocol, &item_flags, &tunnel); - ret = flow_dv_validate_item_ipv4(items, item_flags, + ret = flow_dv_validate_item_ipv4(dev, items, item_flags, last_item, ether_type, error); if (ret < 0) @@ -8375,7 +8386,7 @@ flow_dv_translate_item_ipv4(void *matcher, void *key, void *headers_v; char *l24_m; char *l24_v; - uint8_t tos; + uint8_t tos, ihl_m, ihl_v; if (inner) { headers_m = MLX5_ADDR_OF(fte_match_param, matcher, @@ -8404,6 +8415,10 @@ flow_dv_translate_item_ipv4(void *matcher, void *key, *(uint32_t *)l24_m = ipv4_m->hdr.src_addr; *(uint32_t *)l24_v = ipv4_m->hdr.src_addr & ipv4_v->hdr.src_addr; tos = ipv4_m->hdr.type_of_service & ipv4_v->hdr.type_of_service; + ihl_m = ipv4_m->hdr.version_ihl & RTE_IPV4_HDR_IHL_MASK; + ihl_v = ipv4_v->hdr.version_ihl & RTE_IPV4_HDR_IHL_MASK; + MLX5_SET(fte_match_set_lyr_2_4, headers_m, ipv4_ihl, ihl_m); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, ipv4_ihl, ihl_m & ihl_v); MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_ecn, ipv4_m->hdr.type_of_service); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, tos); -- 2.20.1