X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_flow_dv.c;h=9a0102abb574d6fb8ada495f7caf6576fc1199dd;hb=18ca4a4ec73a2e28df45a10543b7cdd45f2801dd;hp=7a7591144a516ca1aa559ea261abb4c71a2813c9;hpb=dfb8c448daaf29a10d6249fc045bd2eef9655684;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index 7a7591144a..9a0102abb5 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -162,6 +162,7 @@ flow_dv_attr_init(const struct rte_flow_item *item, union flow_dv_attr *attr, case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: case RTE_FLOW_ITEM_TYPE_GENEVE: case RTE_FLOW_ITEM_TYPE_MPLS: + case RTE_FLOW_ITEM_TYPE_GTP: if (tunnel_decap) attr->attr = 0; break; @@ -2873,8 +2874,6 @@ flow_dv_validate_action_push_vlan(struct rte_eth_dev *dev, { const struct rte_flow_action_of_push_vlan *push_vlan = action->conf; const struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_dev_ctx_shared *sh = priv->sh; - bool direction_error = false; if (push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_VLAN) && push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_QINQ)) @@ -2886,22 +2885,6 @@ flow_dv_validate_action_push_vlan(struct rte_eth_dev *dev, RTE_FLOW_ERROR_TYPE_ACTION, action, "wrong action order, port_id should " "be after push VLAN"); - /* Push VLAN is not supported in ingress except for CX6 FDB mode. */ - if (attr->transfer) { - bool fdb_tx = priv->representor_id != UINT16_MAX; - bool is_cx5 = sh->steering_format_version == - MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5; - - if (!fdb_tx && is_cx5) - direction_error = true; - } else if (attr->ingress) { - direction_error = true; - } - if (direction_error) - return rte_flow_error_set(error, ENOTSUP, - RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, - NULL, - "push vlan action not supported for ingress"); if (!attr->transfer && priv->representor) return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, @@ -6862,7 +6845,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, bool external, int hairpin, struct rte_flow_error *error) { int ret; - uint64_t action_flags = 0; + uint64_t aso_mask, action_flags = 0; uint64_t item_flags = 0; uint64_t last_item = 0; uint8_t next_protocol = 0xff; @@ -6931,6 +6914,9 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, bool def_policy = false; bool shared_count = false; uint16_t udp_dport = 0; + uint32_t tag_id = 0; + const struct rte_flow_action_age *non_shared_age = NULL; + const struct rte_flow_action_count *count = NULL; if (items == NULL) return -1; @@ -6970,6 +6956,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, switch (type) { case RTE_FLOW_ITEM_TYPE_VOID: break; + case RTE_FLOW_ITEM_TYPE_ESP: + ret = mlx5_flow_validate_item_esp(items, item_flags, + next_protocol, + error); + if (ret < 0) + return ret; + last_item = MLX5_FLOW_ITEM_ESP; + break; case RTE_FLOW_ITEM_TYPE_PORT_ID: ret = flow_dv_validate_item_port_id (dev, items, attr, item_flags, error); @@ -7235,8 +7229,10 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, return ret; last_item = MLX5_FLOW_ITEM_TAG; break; - case MLX5_RTE_FLOW_ITEM_TYPE_TAG: case MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE: + last_item = MLX5_FLOW_ITEM_TX_QUEUE; + break; + case MLX5_RTE_FLOW_ITEM_TYPE_TAG: break; case RTE_FLOW_ITEM_TYPE_GTP: ret = flow_dv_validate_item_gtp(dev, items, item_flags, @@ -7405,6 +7401,8 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, ++actions_n; if (action_flags & MLX5_FLOW_ACTION_SAMPLE) modify_after_mirror = 1; + tag_id = ((const struct rte_flow_action_set_tag *) + actions->conf)->index; action_flags |= MLX5_FLOW_ACTION_SET_TAG; rw_act_num += MLX5_ACT_NUM_SET_TAG; break; @@ -7466,6 +7464,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, attr, error); if (ret < 0) return ret; + count = actions->conf; action_flags |= MLX5_FLOW_ACTION_COUNT; ++actions_n; break; @@ -7771,6 +7770,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, ++actions_n; break; case RTE_FLOW_ACTION_TYPE_AGE: + non_shared_age = actions->conf; ret = flow_dv_validate_action_age(action_flags, actions, dev, error); @@ -7839,6 +7839,11 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, error); if (ret < 0) return ret; + if ((action_flags & MLX5_FLOW_ACTION_SET_TAG) && + tag_id == 0 && priv->mtr_color_reg == REG_NON) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "sample after tag action causes metadata tag index 0 corruption"); action_flags |= MLX5_FLOW_ACTION_SAMPLE; ++actions_n; break; @@ -7994,6 +7999,28 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, RTE_FLOW_ERROR_TYPE_ACTION, NULL, "encap and decap " "combination aren't supported"); + /* Push VLAN is not supported in ingress except for NICs newer than CX5. */ + if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) { + struct mlx5_dev_ctx_shared *sh = priv->sh; + bool direction_error = false; + + if (attr->transfer) { + bool fdb_tx = priv->representor_id != UINT16_MAX; + bool is_cx5 = sh->steering_format_version == + MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5; + + if (!fdb_tx && is_cx5) + direction_error = true; + } else if (attr->ingress) { + direction_error = true; + } + if (direction_error) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, + NULL, + "push VLAN action not supported " + "for ingress"); + } if (!attr->transfer && attr->ingress) { if (action_flags & MLX5_FLOW_ACTION_ENCAP) return rte_flow_error_set @@ -8001,12 +8028,6 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, RTE_FLOW_ERROR_TYPE_ACTION, NULL, "encap is not supported" " for ingress traffic"); - else if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) - return rte_flow_error_set - (error, ENOTSUP, - RTE_FLOW_ERROR_TYPE_ACTION, - NULL, "push VLAN action not " - "supported for ingress"); else if ((action_flags & MLX5_FLOW_VLAN_ACTIONS) == MLX5_FLOW_VLAN_ACTIONS) return rte_flow_error_set @@ -8046,6 +8067,20 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, "cannot be done before meter action"); } } + /* + * Only support one ASO action in a single flow rule. + * non-shared AGE + counter will fallback to use HW counter, no ASO hit object. + * Group 0 uses HW counter for AGE too even if no counter action. + */ + aso_mask = (action_flags & MLX5_FLOW_ACTION_METER && priv->sh->meter_aso_en) << 2 | + (action_flags & MLX5_FLOW_ACTION_CT && priv->sh->ct_aso_en) << 1 | + (action_flags & MLX5_FLOW_ACTION_AGE && + !(non_shared_age && count) && + (attr->group || (attr->transfer && priv->fdb_def_rule)) && + priv->sh->flow_hit_aso_en); + if (__builtin_popcountl(aso_mask) > 1) + return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, + NULL, "unsupported combining AGE, METER, CT ASO actions in a single rule"); /* * Hairpin flow will add one more TAG action in TX implicit mode. * In TX explicit mode, there will be no hairpin flow ID. @@ -8069,6 +8104,18 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, NULL, "sample before modify action is not supported"); + /* + * Validation the NIC Egress flow on representor, except implicit + * hairpin default egress flow with TX_QUEUE item, other flows not + * work due to metadata regC0 mismatch. + */ + if ((!attr->transfer && attr->egress) && priv->representor && + !(item_flags & MLX5_FLOW_ITEM_TX_QUEUE)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + NULL, + "NIC egress rules on representors" + " is not supported"); return 0; } @@ -8691,6 +8738,58 @@ flow_dv_translate_item_tcp(void *matcher, void *key, (tcp_v->hdr.tcp_flags & tcp_m->hdr.tcp_flags)); } +/** + * Add ESP item to matcher and to the value. + * + * @param[in, out] matcher + * Flow matcher. + * @param[in, out] key + * Flow matcher value. + * @param[in] item + * Flow pattern to translate. + * @param[in] inner + * Item is inner pattern. + */ +static void +flow_dv_translate_item_esp(void *matcher, void *key, + const struct rte_flow_item *item, + int inner) +{ + const struct rte_flow_item_esp *esp_m = item->mask; + const struct rte_flow_item_esp *esp_v = item->spec; + void *headers_m; + void *headers_v; + char *spi_m; + char *spi_v; + + if (inner) { + headers_m = MLX5_ADDR_OF(fte_match_param, matcher, + inner_headers); + headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); + } else { + headers_m = MLX5_ADDR_OF(fte_match_param, matcher, + outer_headers); + headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); + } + MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_ESP); + if (!esp_v) + return; + if (!esp_m) + esp_m = &rte_flow_item_esp_mask; + headers_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters); + headers_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters); + if (inner) { + spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, inner_esp_spi); + spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, inner_esp_spi); + } else { + spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, outer_esp_spi); + spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, outer_esp_spi); + } + *(uint32_t *)spi_m = esp_m->hdr.spi; + *(uint32_t *)spi_v = esp_m->hdr.spi & esp_v->hdr.spi; +} + /** * Add UDP item to matcher and to the value. * @@ -11150,12 +11249,18 @@ flow_dv_hashfields_set(uint64_t item_flags, fields |= MLX5_IPV6_IBV_RX_HASH; } } - if (fields == 0) + if (items & MLX5_FLOW_ITEM_ESP) { + if (rss_types & RTE_ETH_RSS_ESP) + fields |= IBV_RX_HASH_IPSEC_SPI; + } + if ((fields & ~IBV_RX_HASH_IPSEC_SPI) == 0) { + *hash_fields = fields; /* * There is no match between the RSS types and the * L3 protocol (IPv4/IPv6) defined in the flow rule. */ return; + } if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_UDP)) || (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_UDP)) || !items) { @@ -11206,6 +11311,7 @@ flow_dv_hrxq_prepare(struct rte_eth_dev *dev, uint32_t *hrxq_idx) { struct mlx5_flow_handle *dh = dev_flow->handle; + uint32_t shared_rss = rss_desc->shared_rss; struct mlx5_hrxq *hrxq; MLX5_ASSERT(rss_desc->queue_num); @@ -11217,6 +11323,7 @@ flow_dv_hrxq_prepare(struct rte_eth_dev *dev, rss_desc->queue_num = 1; hrxq = mlx5_hrxq_get(dev, rss_desc); *hrxq_idx = hrxq ? hrxq->idx : 0; + rss_desc->shared_rss = shared_rss; return hrxq; } @@ -13498,6 +13605,11 @@ flow_dv_translate(struct rte_eth_dev *dev, RTE_FLOW_ERROR_TYPE_ITEM, NULL, "item not supported"); switch (item_type) { + case RTE_FLOW_ITEM_TYPE_ESP: + flow_dv_translate_item_esp(match_mask, match_value, + items, tunnel); + last_item = MLX5_FLOW_ITEM_ESP; + break; case RTE_FLOW_ITEM_TYPE_PORT_ID: flow_dv_translate_item_port_id (dev, match_mask, match_value, items, attr); @@ -13756,11 +13868,13 @@ flow_dv_translate(struct rte_eth_dev *dev, /* * When E-Switch mode is enabled, we have two cases where we need to * set the source port manually. - * The first one, is in case of Nic steering rule, and the second is - * E-Switch rule where no port_id item was found. In both cases - * the source port is set according the current port in use. + * The first one, is in case of NIC ingress steering rule, and the + * second is E-Switch rule where no port_id item was found. + * In both cases the source port is set according the current port + * in use. */ - if (!(item_flags & MLX5_FLOW_ITEM_PORT_ID) && priv->sh->esw_mode) { + if (!(item_flags & MLX5_FLOW_ITEM_PORT_ID) && priv->sh->esw_mode && + !(attr->egress && !attr->transfer)) { if (flow_dv_translate_item_port_id(dev, match_mask, match_value, NULL, attr)) return -rte_errno; @@ -13965,6 +14079,15 @@ __flow_dv_action_rss_hrxq_set(struct mlx5_shared_action_rss *action, case MLX5_RSS_HASH_NONE: hrxqs[6] = hrxq_idx; return 0; + case MLX5_RSS_HASH_IPV4_ESP: + hrxqs[7] = hrxq_idx; + return 0; + case MLX5_RSS_HASH_IPV6_ESP: + hrxqs[8] = hrxq_idx; + return 0; + case MLX5_RSS_HASH_ESP_SPI: + hrxqs[9] = hrxq_idx; + return 0; default: return -1; } @@ -14034,6 +14157,12 @@ flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx, return hrxqs[5]; case MLX5_RSS_HASH_NONE: return hrxqs[6]; + case MLX5_RSS_HASH_IPV4_ESP: + return hrxqs[7]; + case MLX5_RSS_HASH_IPV6_ESP: + return hrxqs[8]; + case MLX5_RSS_HASH_ESP_SPI: + return hrxqs[9]; default: return 0; } @@ -14750,8 +14879,8 @@ __flow_dv_action_rss_hrxqs_release(struct rte_eth_dev *dev, * MLX5_RSS_HASH_IPV4_DST_ONLY are mutually exclusive so they can share * same slot in mlx5_rss_hash_fields. * - * @param[in] rss_types - * RSS type. + * @param[in] orig_rss_types + * RSS type as provided in shared RSS action. * @param[in, out] hash_field * hash_field variable needed to be adjusted. * @@ -14759,9 +14888,11 @@ __flow_dv_action_rss_hrxqs_release(struct rte_eth_dev *dev, * void */ void -flow_dv_action_rss_l34_hash_adjust(uint64_t rss_types, +flow_dv_action_rss_l34_hash_adjust(uint64_t orig_rss_types, uint64_t *hash_field) { + uint64_t rss_types = rte_eth_rss_hf_refine(orig_rss_types); + switch (*hash_field & ~IBV_RX_HASH_INNER) { case MLX5_RSS_HASH_IPV4: if (rss_types & MLX5_IPV4_LAYER_TYPES) { @@ -15548,9 +15679,7 @@ __flow_dv_create_domain_policy_acts(struct rte_eth_dev *dev, (MLX5_MAX_MODIFY_NUM + 1)]; } mhdr_dummy; struct mlx5_flow_dv_modify_hdr_resource *mhdr_res = &mhdr_dummy.res; - struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); - MLX5_ASSERT(wks); egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0; transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0; memset(&dh, 0, sizeof(struct mlx5_flow_handle)); @@ -15588,7 +15717,6 @@ __flow_dv_create_domain_policy_acts(struct rte_eth_dev *dev, NULL, "cannot create policy " "mark action for this color"); - wks->mark = 1; if (flow_dv_tag_resource_register(dev, tag_be, &dev_flow, &flow_err)) return -rte_mtr_error_set(error, @@ -15600,6 +15728,7 @@ __flow_dv_create_domain_policy_acts(struct rte_eth_dev *dev, act_cnt->rix_mark = dev_flow.handle->dvh.rix_tag; action_flags |= MLX5_FLOW_ACTION_MARK; + mtr_policy->mark = 1; break; } case RTE_FLOW_ACTION_TYPE_SET_TAG: @@ -15883,6 +16012,8 @@ __flow_dv_create_domain_policy_acts(struct rte_eth_dev *dev, act_cnt->next_sub_policy = NULL; mtr_policy->is_hierarchy = 1; mtr_policy->dev = next_policy->dev; + if (next_policy->mark) + mtr_policy->mark = 1; action_flags |= MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY; break; @@ -17009,7 +17140,8 @@ __flow_dv_meter_get_rss_sub_policy(struct rte_eth_dev *dev, } } /* Create sub policy. */ - if (!mtr_policy->sub_policys[domain][0]->rix_hrxq[0]) { + if (!mtr_policy->sub_policys[domain][0]->rix_hrxq[RTE_COLOR_GREEN] && + !mtr_policy->sub_policys[domain][0]->rix_hrxq[RTE_COLOR_YELLOW]) { /* Reuse the first pre-allocated sub_policy. */ sub_policy = mtr_policy->sub_policys[domain][0]; sub_policy_idx = sub_policy->idx;