Loading drivers/infiniband/hw/mlx5/main.c +2 −1 Original line number Diff line number Diff line Loading @@ -3570,7 +3570,8 @@ static void mlx5_ib_set_rule_source_port(struct mlx5_ib_dev *dev, misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2); MLX5_SET_TO_ONES(fte_match_set_misc2, misc, metadata_reg_c_0); MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask()); } else { misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); Loading drivers/net/ethernet/mellanox/mlx5/core/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ mlx5_core-$(CONFIG_MLX5_EN_ARFS) += en_arfs.o mlx5_core-$(CONFIG_MLX5_EN_RXNFC) += en_fs_ethtool.o mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o en/port_buffer.o mlx5_core-$(CONFIG_MLX5_ESWITCH) += en_rep.o en_tc.o en/tc_tun.o lib/port_tun.o lag_mp.o \ lib/geneve.o en/tc_tun_vxlan.o en/tc_tun_gre.o \ lib/geneve.o en/mapping.o en/tc_tun_vxlan.o en/tc_tun_gre.o \ en/tc_tun_geneve.o diag/en_tc_tracepoint.o mlx5_core-$(CONFIG_PCI_HYPERV_INTERFACE) += en/hv_vhca_stats.o Loading drivers/net/ethernet/mellanox/mlx5/core/en/mapping.c 0 → 100644 +218 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB /* Copyright (c) 2018 Mellanox Technologies */ #include <linux/jhash.h> #include <linux/slab.h> #include <linux/xarray.h> #include <linux/hashtable.h> #include "mapping.h" #define MAPPING_GRACE_PERIOD 2000 struct mapping_ctx { struct xarray xarray; DECLARE_HASHTABLE(ht, 8); struct mutex lock; /* Guards hashtable and xarray */ unsigned long max_id; size_t data_size; bool delayed_removal; struct delayed_work dwork; struct list_head pending_list; spinlock_t pending_list_lock; /* Guards pending list */ }; struct mapping_item { struct rcu_head rcu; struct list_head list; unsigned long timeout; struct hlist_node node; int cnt; u32 id; char data[]; }; int mapping_add(struct mapping_ctx *ctx, void *data, u32 *id) { struct mapping_item *mi; int err = -ENOMEM; u32 hash_key; mutex_lock(&ctx->lock); hash_key = jhash(data, ctx->data_size, 0); hash_for_each_possible(ctx->ht, mi, node, hash_key) { if (!memcmp(data, mi->data, ctx->data_size)) goto attach; } mi = kzalloc(sizeof(*mi) + ctx->data_size, GFP_KERNEL); if (!mi) goto err_alloc; memcpy(mi->data, data, ctx->data_size); hash_add(ctx->ht, &mi->node, hash_key); err = xa_alloc(&ctx->xarray, &mi->id, mi, XA_LIMIT(1, ctx->max_id), GFP_KERNEL); if (err) goto err_assign; attach: ++mi->cnt; *id = mi->id; mutex_unlock(&ctx->lock); return 0; err_assign: hash_del(&mi->node); kfree(mi); err_alloc: mutex_unlock(&ctx->lock); return err; } static void mapping_remove_and_free(struct mapping_ctx *ctx, struct mapping_item *mi) { xa_erase(&ctx->xarray, mi->id); kfree_rcu(mi, rcu); } static void mapping_free_item(struct mapping_ctx *ctx, struct mapping_item *mi) { if (!ctx->delayed_removal) { mapping_remove_and_free(ctx, mi); return; } mi->timeout = jiffies + msecs_to_jiffies(MAPPING_GRACE_PERIOD); spin_lock(&ctx->pending_list_lock); list_add_tail(&mi->list, &ctx->pending_list); spin_unlock(&ctx->pending_list_lock); schedule_delayed_work(&ctx->dwork, MAPPING_GRACE_PERIOD); } int mapping_remove(struct mapping_ctx *ctx, u32 id) { unsigned long index = id; struct mapping_item *mi; int err = -ENOENT; mutex_lock(&ctx->lock); mi = xa_load(&ctx->xarray, index); if (!mi) goto out; err = 0; if (--mi->cnt > 0) goto out; hash_del(&mi->node); mapping_free_item(ctx, mi); out: mutex_unlock(&ctx->lock); return err; } int mapping_find(struct mapping_ctx *ctx, u32 id, void *data) { unsigned long index = id; struct mapping_item *mi; int err = -ENOENT; rcu_read_lock(); mi = xa_load(&ctx->xarray, index); if (!mi) goto err_find; memcpy(data, mi->data, ctx->data_size); err = 0; err_find: rcu_read_unlock(); return err; } static void mapping_remove_and_free_list(struct mapping_ctx *ctx, struct list_head *list) { struct mapping_item *mi; list_for_each_entry(mi, list, list) mapping_remove_and_free(ctx, mi); } static void mapping_work_handler(struct work_struct *work) { unsigned long min_timeout = 0, now = jiffies; struct mapping_item *mi, *next; LIST_HEAD(pending_items); struct mapping_ctx *ctx; ctx = container_of(work, struct mapping_ctx, dwork.work); spin_lock(&ctx->pending_list_lock); list_for_each_entry_safe(mi, next, &ctx->pending_list, list) { if (time_after(now, mi->timeout)) list_move(&mi->list, &pending_items); else if (!min_timeout || time_before(mi->timeout, min_timeout)) min_timeout = mi->timeout; } spin_unlock(&ctx->pending_list_lock); mapping_remove_and_free_list(ctx, &pending_items); if (min_timeout) schedule_delayed_work(&ctx->dwork, abs(min_timeout - now)); } static void mapping_flush_work(struct mapping_ctx *ctx) { if (!ctx->delayed_removal) return; cancel_delayed_work_sync(&ctx->dwork); mapping_remove_and_free_list(ctx, &ctx->pending_list); } struct mapping_ctx * mapping_create(size_t data_size, u32 max_id, bool delayed_removal) { struct mapping_ctx *ctx; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return ERR_PTR(-ENOMEM); ctx->max_id = max_id ? max_id : UINT_MAX; ctx->data_size = data_size; if (delayed_removal) { INIT_DELAYED_WORK(&ctx->dwork, mapping_work_handler); INIT_LIST_HEAD(&ctx->pending_list); spin_lock_init(&ctx->pending_list_lock); ctx->delayed_removal = true; } mutex_init(&ctx->lock); xa_init_flags(&ctx->xarray, XA_FLAGS_ALLOC1); return ctx; } void mapping_destroy(struct mapping_ctx *ctx) { mapping_flush_work(ctx); xa_destroy(&ctx->xarray); mutex_destroy(&ctx->lock); kfree(ctx); } drivers/net/ethernet/mellanox/mlx5/core/en/mapping.h 0 → 100644 +27 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* Copyright (c) 2019 Mellanox Technologies */ #ifndef __MLX5_MAPPING_H__ #define __MLX5_MAPPING_H__ struct mapping_ctx; int mapping_add(struct mapping_ctx *ctx, void *data, u32 *id); int mapping_remove(struct mapping_ctx *ctx, u32 id); int mapping_find(struct mapping_ctx *ctx, u32 id, void *data); /* mapping uses an xarray to map data to ids in add(), and for find(). * For locking, it uses a internal xarray spin lock for add()/remove(), * find() uses rcu_read_lock(). * Choosing delayed_removal postpones the removal of a previously mapped * id by MAPPING_GRACE_PERIOD milliseconds. * This is to avoid races against hardware, where we mark the packet in * hardware with a previous id, and quick remove() and add() reusing the same * previous id. Then find() will get the new mapping instead of the old * which was used to mark the packet. */ struct mapping_ctx *mapping_create(size_t data_size, u32 max_id, bool delayed_removal); void mapping_destroy(struct mapping_ctx *ctx); #endif /* __MLX5_MAPPING_H__ */ drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +110 −2 Original line number Diff line number Diff line Loading @@ -469,10 +469,15 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev, struct mlx5e_priv *priv, struct mlx5_flow_spec *spec, struct flow_cls_offload *f, void *headers_c, void *headers_v, u8 *match_level) u8 *match_level) { struct mlx5e_tc_tunnel *tunnel = mlx5e_get_tc_tun(filter_dev); struct flow_rule *rule = flow_cls_offload_flow_rule(f); void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, outer_headers); void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers); struct netlink_ext_ack *extack = f->common.extack; int err = 0; if (!tunnel) { Loading @@ -499,6 +504,109 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev, goto out; } if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_CONTROL)) { struct flow_match_control match; u16 addr_type; flow_rule_match_enc_control(rule, &match); addr_type = match.key->addr_type; /* For tunnel addr_type used same key id`s as for non-tunnel */ if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { struct flow_match_ipv4_addrs match; flow_rule_match_enc_ipv4_addrs(rule, &match); MLX5_SET(fte_match_set_lyr_2_4, headers_c, src_ipv4_src_ipv6.ipv4_layout.ipv4, ntohl(match.mask->src)); MLX5_SET(fte_match_set_lyr_2_4, headers_v, src_ipv4_src_ipv6.ipv4_layout.ipv4, ntohl(match.key->src)); MLX5_SET(fte_match_set_lyr_2_4, headers_c, dst_ipv4_dst_ipv6.ipv4_layout.ipv4, ntohl(match.mask->dst)); MLX5_SET(fte_match_set_lyr_2_4, headers_v, dst_ipv4_dst_ipv6.ipv4_layout.ipv4, ntohl(match.key->dst)); MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IP); } else if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { struct flow_match_ipv6_addrs match; flow_rule_match_enc_ipv6_addrs(rule, &match); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, src_ipv4_src_ipv6.ipv6_layout.ipv6), &match.mask->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, src_ipv4_src_ipv6.ipv6_layout.ipv6), &match.key->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, dst_ipv4_dst_ipv6.ipv6_layout.ipv6), &match.mask->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, dst_ipv4_dst_ipv6.ipv6_layout.ipv6), &match.key->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IPV6); } } if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) { struct flow_match_ip match; flow_rule_match_enc_ip(rule, &match); MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn, match.mask->tos & 0x3); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, match.key->tos & 0x3); MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp, match.mask->tos >> 2); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, match.key->tos >> 2); MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit, match.mask->ttl); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit, match.key->ttl); if (match.mask->ttl && !MLX5_CAP_ESW_FLOWTABLE_FDB (priv->mdev, ft_field_support.outer_ipv4_ttl)) { NL_SET_ERR_MSG_MOD(extack, "Matching on TTL is not supported"); err = -EOPNOTSUPP; goto out; } } /* Enforce DMAC when offloading incoming tunneled flows. * Flow counters require a match on the DMAC. */ MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_47_16); MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_15_0); ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, dmac_47_16), priv->netdev->dev_addr); /* let software handle IP fragments */ MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1); MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 0); return 0; out: return err; } Loading Loading
drivers/infiniband/hw/mlx5/main.c +2 −1 Original line number Diff line number Diff line Loading @@ -3570,7 +3570,8 @@ static void mlx5_ib_set_rule_source_port(struct mlx5_ib_dev *dev, misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2); MLX5_SET_TO_ONES(fte_match_set_misc2, misc, metadata_reg_c_0); MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask()); } else { misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); Loading
drivers/net/ethernet/mellanox/mlx5/core/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ mlx5_core-$(CONFIG_MLX5_EN_ARFS) += en_arfs.o mlx5_core-$(CONFIG_MLX5_EN_RXNFC) += en_fs_ethtool.o mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o en/port_buffer.o mlx5_core-$(CONFIG_MLX5_ESWITCH) += en_rep.o en_tc.o en/tc_tun.o lib/port_tun.o lag_mp.o \ lib/geneve.o en/tc_tun_vxlan.o en/tc_tun_gre.o \ lib/geneve.o en/mapping.o en/tc_tun_vxlan.o en/tc_tun_gre.o \ en/tc_tun_geneve.o diag/en_tc_tracepoint.o mlx5_core-$(CONFIG_PCI_HYPERV_INTERFACE) += en/hv_vhca_stats.o Loading
drivers/net/ethernet/mellanox/mlx5/core/en/mapping.c 0 → 100644 +218 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB /* Copyright (c) 2018 Mellanox Technologies */ #include <linux/jhash.h> #include <linux/slab.h> #include <linux/xarray.h> #include <linux/hashtable.h> #include "mapping.h" #define MAPPING_GRACE_PERIOD 2000 struct mapping_ctx { struct xarray xarray; DECLARE_HASHTABLE(ht, 8); struct mutex lock; /* Guards hashtable and xarray */ unsigned long max_id; size_t data_size; bool delayed_removal; struct delayed_work dwork; struct list_head pending_list; spinlock_t pending_list_lock; /* Guards pending list */ }; struct mapping_item { struct rcu_head rcu; struct list_head list; unsigned long timeout; struct hlist_node node; int cnt; u32 id; char data[]; }; int mapping_add(struct mapping_ctx *ctx, void *data, u32 *id) { struct mapping_item *mi; int err = -ENOMEM; u32 hash_key; mutex_lock(&ctx->lock); hash_key = jhash(data, ctx->data_size, 0); hash_for_each_possible(ctx->ht, mi, node, hash_key) { if (!memcmp(data, mi->data, ctx->data_size)) goto attach; } mi = kzalloc(sizeof(*mi) + ctx->data_size, GFP_KERNEL); if (!mi) goto err_alloc; memcpy(mi->data, data, ctx->data_size); hash_add(ctx->ht, &mi->node, hash_key); err = xa_alloc(&ctx->xarray, &mi->id, mi, XA_LIMIT(1, ctx->max_id), GFP_KERNEL); if (err) goto err_assign; attach: ++mi->cnt; *id = mi->id; mutex_unlock(&ctx->lock); return 0; err_assign: hash_del(&mi->node); kfree(mi); err_alloc: mutex_unlock(&ctx->lock); return err; } static void mapping_remove_and_free(struct mapping_ctx *ctx, struct mapping_item *mi) { xa_erase(&ctx->xarray, mi->id); kfree_rcu(mi, rcu); } static void mapping_free_item(struct mapping_ctx *ctx, struct mapping_item *mi) { if (!ctx->delayed_removal) { mapping_remove_and_free(ctx, mi); return; } mi->timeout = jiffies + msecs_to_jiffies(MAPPING_GRACE_PERIOD); spin_lock(&ctx->pending_list_lock); list_add_tail(&mi->list, &ctx->pending_list); spin_unlock(&ctx->pending_list_lock); schedule_delayed_work(&ctx->dwork, MAPPING_GRACE_PERIOD); } int mapping_remove(struct mapping_ctx *ctx, u32 id) { unsigned long index = id; struct mapping_item *mi; int err = -ENOENT; mutex_lock(&ctx->lock); mi = xa_load(&ctx->xarray, index); if (!mi) goto out; err = 0; if (--mi->cnt > 0) goto out; hash_del(&mi->node); mapping_free_item(ctx, mi); out: mutex_unlock(&ctx->lock); return err; } int mapping_find(struct mapping_ctx *ctx, u32 id, void *data) { unsigned long index = id; struct mapping_item *mi; int err = -ENOENT; rcu_read_lock(); mi = xa_load(&ctx->xarray, index); if (!mi) goto err_find; memcpy(data, mi->data, ctx->data_size); err = 0; err_find: rcu_read_unlock(); return err; } static void mapping_remove_and_free_list(struct mapping_ctx *ctx, struct list_head *list) { struct mapping_item *mi; list_for_each_entry(mi, list, list) mapping_remove_and_free(ctx, mi); } static void mapping_work_handler(struct work_struct *work) { unsigned long min_timeout = 0, now = jiffies; struct mapping_item *mi, *next; LIST_HEAD(pending_items); struct mapping_ctx *ctx; ctx = container_of(work, struct mapping_ctx, dwork.work); spin_lock(&ctx->pending_list_lock); list_for_each_entry_safe(mi, next, &ctx->pending_list, list) { if (time_after(now, mi->timeout)) list_move(&mi->list, &pending_items); else if (!min_timeout || time_before(mi->timeout, min_timeout)) min_timeout = mi->timeout; } spin_unlock(&ctx->pending_list_lock); mapping_remove_and_free_list(ctx, &pending_items); if (min_timeout) schedule_delayed_work(&ctx->dwork, abs(min_timeout - now)); } static void mapping_flush_work(struct mapping_ctx *ctx) { if (!ctx->delayed_removal) return; cancel_delayed_work_sync(&ctx->dwork); mapping_remove_and_free_list(ctx, &ctx->pending_list); } struct mapping_ctx * mapping_create(size_t data_size, u32 max_id, bool delayed_removal) { struct mapping_ctx *ctx; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return ERR_PTR(-ENOMEM); ctx->max_id = max_id ? max_id : UINT_MAX; ctx->data_size = data_size; if (delayed_removal) { INIT_DELAYED_WORK(&ctx->dwork, mapping_work_handler); INIT_LIST_HEAD(&ctx->pending_list); spin_lock_init(&ctx->pending_list_lock); ctx->delayed_removal = true; } mutex_init(&ctx->lock); xa_init_flags(&ctx->xarray, XA_FLAGS_ALLOC1); return ctx; } void mapping_destroy(struct mapping_ctx *ctx) { mapping_flush_work(ctx); xa_destroy(&ctx->xarray); mutex_destroy(&ctx->lock); kfree(ctx); }
drivers/net/ethernet/mellanox/mlx5/core/en/mapping.h 0 → 100644 +27 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* Copyright (c) 2019 Mellanox Technologies */ #ifndef __MLX5_MAPPING_H__ #define __MLX5_MAPPING_H__ struct mapping_ctx; int mapping_add(struct mapping_ctx *ctx, void *data, u32 *id); int mapping_remove(struct mapping_ctx *ctx, u32 id); int mapping_find(struct mapping_ctx *ctx, u32 id, void *data); /* mapping uses an xarray to map data to ids in add(), and for find(). * For locking, it uses a internal xarray spin lock for add()/remove(), * find() uses rcu_read_lock(). * Choosing delayed_removal postpones the removal of a previously mapped * id by MAPPING_GRACE_PERIOD milliseconds. * This is to avoid races against hardware, where we mark the packet in * hardware with a previous id, and quick remove() and add() reusing the same * previous id. Then find() will get the new mapping instead of the old * which was used to mark the packet. */ struct mapping_ctx *mapping_create(size_t data_size, u32 max_id, bool delayed_removal); void mapping_destroy(struct mapping_ctx *ctx); #endif /* __MLX5_MAPPING_H__ */
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +110 −2 Original line number Diff line number Diff line Loading @@ -469,10 +469,15 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev, struct mlx5e_priv *priv, struct mlx5_flow_spec *spec, struct flow_cls_offload *f, void *headers_c, void *headers_v, u8 *match_level) u8 *match_level) { struct mlx5e_tc_tunnel *tunnel = mlx5e_get_tc_tun(filter_dev); struct flow_rule *rule = flow_cls_offload_flow_rule(f); void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, outer_headers); void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers); struct netlink_ext_ack *extack = f->common.extack; int err = 0; if (!tunnel) { Loading @@ -499,6 +504,109 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev, goto out; } if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_CONTROL)) { struct flow_match_control match; u16 addr_type; flow_rule_match_enc_control(rule, &match); addr_type = match.key->addr_type; /* For tunnel addr_type used same key id`s as for non-tunnel */ if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { struct flow_match_ipv4_addrs match; flow_rule_match_enc_ipv4_addrs(rule, &match); MLX5_SET(fte_match_set_lyr_2_4, headers_c, src_ipv4_src_ipv6.ipv4_layout.ipv4, ntohl(match.mask->src)); MLX5_SET(fte_match_set_lyr_2_4, headers_v, src_ipv4_src_ipv6.ipv4_layout.ipv4, ntohl(match.key->src)); MLX5_SET(fte_match_set_lyr_2_4, headers_c, dst_ipv4_dst_ipv6.ipv4_layout.ipv4, ntohl(match.mask->dst)); MLX5_SET(fte_match_set_lyr_2_4, headers_v, dst_ipv4_dst_ipv6.ipv4_layout.ipv4, ntohl(match.key->dst)); MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IP); } else if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { struct flow_match_ipv6_addrs match; flow_rule_match_enc_ipv6_addrs(rule, &match); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, src_ipv4_src_ipv6.ipv6_layout.ipv6), &match.mask->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, src_ipv4_src_ipv6.ipv6_layout.ipv6), &match.key->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, dst_ipv4_dst_ipv6.ipv6_layout.ipv6), &match.mask->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, dst_ipv4_dst_ipv6.ipv6_layout.ipv6), &match.key->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IPV6); } } if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) { struct flow_match_ip match; flow_rule_match_enc_ip(rule, &match); MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn, match.mask->tos & 0x3); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, match.key->tos & 0x3); MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp, match.mask->tos >> 2); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, match.key->tos >> 2); MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit, match.mask->ttl); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit, match.key->ttl); if (match.mask->ttl && !MLX5_CAP_ESW_FLOWTABLE_FDB (priv->mdev, ft_field_support.outer_ipv4_ttl)) { NL_SET_ERR_MSG_MOD(extack, "Matching on TTL is not supported"); err = -EOPNOTSUPP; goto out; } } /* Enforce DMAC when offloading incoming tunneled flows. * Flow counters require a match on the DMAC. */ MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_47_16); MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_15_0); ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, dmac_47_16), priv->netdev->dev_addr); /* let software handle IP fragments */ MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1); MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 0); return 0; out: return err; } Loading