return ret;
}
+/**
+ * Validate GRE optional item.
+ *
+ * @param[in] dev
+ * Pointer to the Ethernet device structure.
+ * @param[in] item
+ * Item specification.
+ * @param[in] item_flags
+ * Bit flags to mark detected items.
+ * @param[in] attr
+ * Flow rule attributes.
+ * @param[in] gre_item
+ * Pointer to gre_item
+ * @param[out] error
+ * Pointer to error structure.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_flow_validate_item_gre_option(struct rte_eth_dev *dev,
+ const struct rte_flow_item *item,
+ uint64_t item_flags,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item *gre_item,
+ struct rte_flow_error *error)
+{
+ const struct rte_flow_item_gre *gre_spec = gre_item->spec;
+ const struct rte_flow_item_gre *gre_mask = gre_item->mask;
+ const struct rte_flow_item_gre_opt *spec = item->spec;
+ const struct rte_flow_item_gre_opt *mask = item->mask;
+ struct mlx5_priv *priv = dev->data->dev_private;
+ int ret = 0;
+ struct rte_flow_item_gre_opt nic_mask = {
+ .checksum_rsvd = {
+ .checksum = RTE_BE16(UINT16_MAX),
+ .reserved1 = 0x0,
+ },
+ .key = {
+ .key = RTE_BE32(UINT32_MAX),
+ },
+ .sequence = {
+ .sequence = RTE_BE32(UINT32_MAX),
+ },
+ };
+
+ if (!(item_flags & MLX5_FLOW_LAYER_GRE))
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "No preceding GRE header");
+ if (item_flags & MLX5_FLOW_LAYER_INNER)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "GRE option following a wrong item");
+ if (!spec || !mask)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "At least one field gre_option(checksum/key/sequence) must be specified");
+ if (!gre_mask)
+ gre_mask = &rte_flow_item_gre_mask;
+ if (mask->checksum_rsvd.checksum)
+ if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x8000)) &&
+ !(gre_spec->c_rsvd0_ver & RTE_BE16(0x8000)))
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Checksum bit must be on");
+ if (mask->key.key)
+ if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x2000)) &&
+ !(gre_spec->c_rsvd0_ver & RTE_BE16(0x2000)))
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item, "Key bit must be on");
+ if (mask->sequence.sequence)
+ if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x1000)) &&
+ !(gre_spec->c_rsvd0_ver & RTE_BE16(0x1000)))
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Sequence bit must be on");
+ if (mask->checksum_rsvd.checksum || mask->sequence.sequence) {
+ if (priv->sh->steering_format_version ==
+ MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 ||
+ ((attr->group || attr->transfer) &&
+ !priv->sh->misc5_cap) ||
+ (!(priv->sh->tunnel_header_0_1 &&
+ priv->sh->tunnel_header_2_3) &&
+ !attr->group && !attr->transfer))
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Checksum/Sequence not supported");
+ }
+ ret = mlx5_flow_item_acceptable
+ (item, (const uint8_t *)mask,
+ (const uint8_t *)&nic_mask,
+ sizeof(struct rte_flow_item_gre_opt),
+ MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
+ return ret;
+}
+
/**
* Validate GRE item.
*
gre_item = items;
last_item = MLX5_FLOW_LAYER_GRE;
break;
+ case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
+ ret = mlx5_flow_validate_item_gre_option(dev, items, item_flags,
+ attr, gre_item, error);
+ if (ret < 0)
+ return ret;
+ last_item = MLX5_FLOW_LAYER_GRE;
+ break;
case RTE_FLOW_ITEM_TYPE_NVGRE:
ret = mlx5_flow_validate_item_nvgre(items, item_flags,
next_protocol,
protocol_m & protocol_v);
}
+/**
+ * Add GRE optional items 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] gre_item
+ * Pointer to gre_item.
+ * @param[in] pattern_flags
+ * Accumulated pattern flags.
+ */
+static void
+flow_dv_translate_item_gre_option(void *matcher, void *key,
+ const struct rte_flow_item *item,
+ const struct rte_flow_item *gre_item,
+ uint64_t pattern_flags)
+{
+ const struct rte_flow_item_gre_opt *option_m = item->mask;
+ const struct rte_flow_item_gre_opt *option_v = item->spec;
+ const struct rte_flow_item_gre *gre_m = gre_item->mask;
+ const struct rte_flow_item_gre *gre_v = gre_item->spec;
+ static const struct rte_flow_item_gre empty_gre = {0};
+ struct rte_flow_item gre_key_item;
+ uint16_t c_rsvd0_ver_m, c_rsvd0_ver_v;
+ uint16_t protocol_m, protocol_v;
+ void *misc5_m;
+ void *misc5_v;
+
+ /*
+ * If only match key field, keep using misc for matching.
+ * If need to match checksum or sequence, using misc5 and do
+ * not need using misc.
+ */
+ if (!(option_m->sequence.sequence ||
+ option_m->checksum_rsvd.checksum)) {
+ flow_dv_translate_item_gre(matcher, key, gre_item,
+ pattern_flags);
+ gre_key_item.spec = &option_v->key.key;
+ gre_key_item.mask = &option_m->key.key;
+ flow_dv_translate_item_gre_key(matcher, key, &gre_key_item);
+ return;
+ }
+ if (!gre_v) {
+ gre_v = &empty_gre;
+ gre_m = &empty_gre;
+ } else {
+ if (!gre_m)
+ gre_m = &rte_flow_item_gre_mask;
+ }
+ protocol_v = gre_v->protocol;
+ protocol_m = gre_m->protocol;
+ if (!protocol_m) {
+ /* Force next protocol to prevent matchers duplication */
+ uint16_t ether_type =
+ mlx5_translate_tunnel_etypes(pattern_flags);
+ if (ether_type) {
+ protocol_v = rte_be_to_cpu_16(ether_type);
+ protocol_m = UINT16_MAX;
+ }
+ }
+ c_rsvd0_ver_v = gre_v->c_rsvd0_ver;
+ c_rsvd0_ver_m = gre_m->c_rsvd0_ver;
+ if (option_m->sequence.sequence) {
+ c_rsvd0_ver_v |= RTE_BE16(0x1000);
+ c_rsvd0_ver_m |= RTE_BE16(0x1000);
+ }
+ if (option_m->key.key) {
+ c_rsvd0_ver_v |= RTE_BE16(0x2000);
+ c_rsvd0_ver_m |= RTE_BE16(0x2000);
+ }
+ if (option_m->checksum_rsvd.checksum) {
+ c_rsvd0_ver_v |= RTE_BE16(0x8000);
+ c_rsvd0_ver_m |= RTE_BE16(0x8000);
+ }
+ /*
+ * Hardware parses GRE optional field into the fixed location,
+ * do not need to adjust the tunnel dword indices.
+ */
+ misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
+ misc5_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters_5);
+ MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_0,
+ rte_be_to_cpu_32((c_rsvd0_ver_v | protocol_v << 16) &
+ (c_rsvd0_ver_m | protocol_m << 16)));
+ MLX5_SET(fte_match_set_misc5, misc5_m, tunnel_header_0,
+ rte_be_to_cpu_32(c_rsvd0_ver_m | protocol_m << 16));
+ MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1,
+ rte_be_to_cpu_32(option_v->checksum_rsvd.checksum &
+ option_m->checksum_rsvd.checksum));
+ MLX5_SET(fte_match_set_misc5, misc5_m, tunnel_header_1,
+ rte_be_to_cpu_32(option_m->checksum_rsvd.checksum));
+ MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_2,
+ rte_be_to_cpu_32(option_v->key.key & option_m->key.key));
+ MLX5_SET(fte_match_set_misc5, misc5_m, tunnel_header_2,
+ rte_be_to_cpu_32(option_m->key.key));
+ MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_3,
+ rte_be_to_cpu_32(option_v->sequence.sequence &
+ option_m->sequence.sequence));
+ MLX5_SET(fte_match_set_misc5, misc5_m, tunnel_header_3,
+ rte_be_to_cpu_32(option_m->sequence.sequence));
+}
+
/**
* Add NVGRE item to matcher and to the value.
*
};
const struct rte_flow_item *integrity_items[2] = {NULL, NULL};
const struct rte_flow_item *tunnel_item = NULL;
+ const struct rte_flow_item *gre_item = NULL;
if (!wks)
return rte_flow_error_set(error, ENOMEM,
matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
last_item = MLX5_FLOW_LAYER_GRE;
tunnel_item = items;
+ gre_item = items;
break;
case RTE_FLOW_ITEM_TYPE_GRE_KEY:
flow_dv_translate_item_gre_key(match_mask,
match_value, items);
last_item = MLX5_FLOW_LAYER_GRE_KEY;
break;
+ case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
+ matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
+ last_item = MLX5_FLOW_LAYER_GRE;
+ tunnel_item = items;
+ break;
case RTE_FLOW_ITEM_TYPE_NVGRE:
matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
last_item = MLX5_FLOW_LAYER_GRE;
else if (tunnel_item->type == RTE_FLOW_ITEM_TYPE_NVGRE)
flow_dv_translate_item_nvgre(match_mask, match_value,
tunnel_item, item_flags);
+ else if (tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE_OPTION)
+ flow_dv_translate_item_gre_option(match_mask, match_value,
+ tunnel_item, gre_item, item_flags);
else
MLX5_ASSERT(false);
}