Skip to content

Commit 8e404fe

Browse files
w1ldptrSaeed Mahameed
authored and
Saeed Mahameed
committed
net/mlx5e: Match recirculated packet miss in slow table using reg_c1
Previous patch in series that implements stack devices RX path implements indirect table rules that match on tunnel VNI. After such rule is created all tunnel traffic is recirculated to root table. However, recirculated packet might not match on any rules installed in the table (for example, when IP traffic follows ARP traffic). In that case packets appear on representor of tunnel endpoint VF instead being redirected to the VF itself. Extend slow table with additional flow group that matches on reg_c0 (source port value set by indirect tables implemented by previous patch in series) and reg_c1 (special 0xFFF mark). When creating offloads fdb tables, install one rule per VF vport to match on recirculated miss packets and redirect them to appropriate VF vport. Modify indirect tables code to also rewrite reg_c1 with special 0xFFF mark. Implementation reuses reg_c1 tunnel id bits. This is safe to do because recirculated packets are always matched before decapsulation. Signed-off-by: Vlad Buslov <[email protected]> Signed-off-by: Dmytro Linkin <[email protected]> Reviewed-by: Roi Dayan <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent 48d216e commit 8e404fe

File tree

5 files changed

+143
-8
lines changed

5 files changed

+143
-8
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en_tc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5515,7 +5515,8 @@ int mlx5e_tc_esw_init(struct rhashtable *tc_ht)
55155515
}
55165516
uplink_priv->tunnel_mapping = mapping;
55175517

5518-
mapping = mapping_create(sz_enc_opts, ENC_OPTS_BITS_MASK, true);
5518+
/* 0xFFF is reserved for stack devices slow path table mark */
5519+
mapping = mapping_create(sz_enc_opts, ENC_OPTS_BITS_MASK - 1, true);
55195520
if (IS_ERR(mapping)) {
55205521
err = PTR_ERR(mapping);
55215522
goto err_enc_opts_mapping;

drivers/net/ethernet/mellanox/mlx5/core/esw/indir_table.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ static int mlx5_esw_indir_table_rule_get(struct mlx5_eswitch *esw,
162162
(attr->ip_version == 4 ? ETH_P_IP : ETH_P_IPV6));
163163
} else {
164164
err = -EOPNOTSUPP;
165-
goto err_mod_hdr;
165+
goto err_ethertype;
166166
}
167167

168168
if (attr->ip_version == 4) {
@@ -198,13 +198,18 @@ static int mlx5_esw_indir_table_rule_get(struct mlx5_eswitch *esw,
198198
err = mlx5e_tc_match_to_reg_set(esw->dev, &mod_acts, MLX5_FLOW_NAMESPACE_FDB,
199199
VPORT_TO_REG, data);
200200
if (err)
201-
goto err_mod_hdr;
201+
goto err_mod_hdr_regc0;
202+
203+
err = mlx5e_tc_match_to_reg_set(esw->dev, &mod_acts, MLX5_FLOW_NAMESPACE_FDB,
204+
TUNNEL_TO_REG, ESW_TUN_SLOW_TABLE_GOTO_VPORT);
205+
if (err)
206+
goto err_mod_hdr_regc1;
202207

203208
flow_act.modify_hdr = mlx5_modify_header_alloc(esw->dev, MLX5_FLOW_NAMESPACE_FDB,
204209
mod_acts.num_actions, mod_acts.actions);
205210
if (IS_ERR(flow_act.modify_hdr)) {
206211
err = PTR_ERR(flow_act.modify_hdr);
207-
goto err_mod_hdr;
212+
goto err_mod_hdr_alloc;
208213
}
209214

210215
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
@@ -236,7 +241,11 @@ static int mlx5_esw_indir_table_rule_get(struct mlx5_eswitch *esw,
236241
mlx5_chains_put_table(chains, 0, 1, 0);
237242
err_table:
238243
mlx5_modify_header_dealloc(esw->dev, flow_act.modify_hdr);
239-
err_mod_hdr:
244+
err_mod_hdr_alloc:
245+
err_mod_hdr_regc1:
246+
dealloc_mod_hdr_actions(&mod_acts);
247+
err_mod_hdr_regc0:
248+
err_ethertype:
240249
kfree(rule);
241250
out:
242251
kfree(rule_spec);

drivers/net/ethernet/mellanox/mlx5/core/eswitch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,11 @@ struct mlx5_eswitch_fdb {
179179
struct mlx5_flow_namespace *ns;
180180
struct mlx5_flow_table *slow_fdb;
181181
struct mlx5_flow_group *send_to_vport_grp;
182+
struct mlx5_flow_group *send_to_vport_meta_grp;
182183
struct mlx5_flow_group *peer_miss_grp;
183184
struct mlx5_flow_handle **peer_miss_rules;
184185
struct mlx5_flow_group *miss_grp;
186+
struct mlx5_flow_handle **send_to_vport_meta_rules;
185187
struct mlx5_flow_handle *miss_rule_uni;
186188
struct mlx5_flow_handle *miss_rule_multi;
187189
int vlan_push_pop_refcount;

drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c

Lines changed: 117 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,81 @@ void mlx5_eswitch_del_send_to_vport_rule(struct mlx5_flow_handle *rule)
10801080
mlx5_del_flow_rules(rule);
10811081
}
10821082

1083+
static void mlx5_eswitch_del_send_to_vport_meta_rules(struct mlx5_eswitch *esw)
1084+
{
1085+
struct mlx5_flow_handle **flows = esw->fdb_table.offloads.send_to_vport_meta_rules;
1086+
int i = 0, num_vfs = esw->esw_funcs.num_vfs, vport_num;
1087+
1088+
if (!num_vfs || !flows)
1089+
return;
1090+
1091+
mlx5_esw_for_each_vf_vport_num(esw, vport_num, num_vfs)
1092+
mlx5_del_flow_rules(flows[i++]);
1093+
1094+
kvfree(flows);
1095+
}
1096+
1097+
static int
1098+
mlx5_eswitch_add_send_to_vport_meta_rules(struct mlx5_eswitch *esw)
1099+
{
1100+
int num_vfs, vport_num, rule_idx = 0, err = 0;
1101+
struct mlx5_flow_destination dest = {};
1102+
struct mlx5_flow_act flow_act = {0};
1103+
struct mlx5_flow_handle *flow_rule;
1104+
struct mlx5_flow_handle **flows;
1105+
struct mlx5_flow_spec *spec;
1106+
1107+
num_vfs = esw->esw_funcs.num_vfs;
1108+
flows = kvzalloc(num_vfs * sizeof(*flows), GFP_KERNEL);
1109+
if (!flows)
1110+
return -ENOMEM;
1111+
1112+
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1113+
if (!spec) {
1114+
err = -ENOMEM;
1115+
goto alloc_err;
1116+
}
1117+
1118+
MLX5_SET(fte_match_param, spec->match_criteria,
1119+
misc_parameters_2.metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask());
1120+
MLX5_SET(fte_match_param, spec->match_criteria,
1121+
misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK);
1122+
MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_1,
1123+
ESW_TUN_SLOW_TABLE_GOTO_VPORT_MARK);
1124+
1125+
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
1126+
dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
1127+
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1128+
1129+
mlx5_esw_for_each_vf_vport_num(esw, vport_num, num_vfs) {
1130+
MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_0,
1131+
mlx5_eswitch_get_vport_metadata_for_match(esw, vport_num));
1132+
dest.vport.num = vport_num;
1133+
1134+
flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
1135+
spec, &flow_act, &dest, 1);
1136+
if (IS_ERR(flow_rule)) {
1137+
err = PTR_ERR(flow_rule);
1138+
esw_warn(esw->dev, "FDB: Failed to add send to vport meta rule idx %d, err %ld\n",
1139+
rule_idx, PTR_ERR(flow_rule));
1140+
goto rule_err;
1141+
}
1142+
flows[rule_idx++] = flow_rule;
1143+
}
1144+
1145+
esw->fdb_table.offloads.send_to_vport_meta_rules = flows;
1146+
kvfree(spec);
1147+
return 0;
1148+
1149+
rule_err:
1150+
while (--rule_idx >= 0)
1151+
mlx5_del_flow_rules(flows[rule_idx]);
1152+
kvfree(spec);
1153+
alloc_err:
1154+
kvfree(flows);
1155+
return err;
1156+
}
1157+
10831158
static bool mlx5_eswitch_reg_c1_loopback_supported(struct mlx5_eswitch *esw)
10841159
{
10851160
return MLX5_CAP_ESW_FLOWTABLE(esw->dev, fdb_to_vport_reg_c_id) &
@@ -1562,11 +1637,11 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
15621637
{
15631638
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
15641639
struct mlx5_flow_table_attr ft_attr = {};
1640+
int num_vfs, table_size, ix, err = 0;
15651641
struct mlx5_core_dev *dev = esw->dev;
15661642
struct mlx5_flow_namespace *root_ns;
15671643
struct mlx5_flow_table *fdb = NULL;
15681644
u32 flags = 0, *flow_group_in;
1569-
int table_size, ix, err = 0;
15701645
struct mlx5_flow_group *g;
15711646
void *match_criteria;
15721647
u8 *dmac;
@@ -1592,7 +1667,7 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
15921667
}
15931668

15941669
table_size = esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ +
1595-
MLX5_ESW_MISS_FLOWS + esw->total_vports;
1670+
MLX5_ESW_MISS_FLOWS + esw->total_vports + esw->esw_funcs.num_vfs;
15961671

15971672
/* create the slow path fdb with encap set, so further table instances
15981673
* can be created at run time while VFs are probed if the FW allows that.
@@ -1640,6 +1715,38 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
16401715
}
16411716
esw->fdb_table.offloads.send_to_vport_grp = g;
16421717

1718+
/* meta send to vport */
1719+
memset(flow_group_in, 0, inlen);
1720+
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
1721+
MLX5_MATCH_MISC_PARAMETERS_2);
1722+
1723+
match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
1724+
1725+
MLX5_SET(fte_match_param, match_criteria,
1726+
misc_parameters_2.metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask());
1727+
MLX5_SET(fte_match_param, match_criteria,
1728+
misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK);
1729+
1730+
num_vfs = esw->esw_funcs.num_vfs;
1731+
if (num_vfs) {
1732+
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix);
1733+
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ix + num_vfs - 1);
1734+
ix += num_vfs;
1735+
1736+
g = mlx5_create_flow_group(fdb, flow_group_in);
1737+
if (IS_ERR(g)) {
1738+
err = PTR_ERR(g);
1739+
esw_warn(dev, "Failed to create send-to-vport meta flow group err(%d)\n",
1740+
err);
1741+
goto send_vport_meta_err;
1742+
}
1743+
esw->fdb_table.offloads.send_to_vport_meta_grp = g;
1744+
1745+
err = mlx5_eswitch_add_send_to_vport_meta_rules(esw);
1746+
if (err)
1747+
goto meta_rule_err;
1748+
}
1749+
16431750
if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
16441751
/* create peer esw miss group */
16451752
memset(flow_group_in, 0, inlen);
@@ -1707,6 +1814,11 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
17071814
if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
17081815
mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
17091816
peer_miss_err:
1817+
mlx5_eswitch_del_send_to_vport_meta_rules(esw);
1818+
meta_rule_err:
1819+
if (esw->fdb_table.offloads.send_to_vport_meta_grp)
1820+
mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_meta_grp);
1821+
send_vport_meta_err:
17101822
mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
17111823
send_vport_err:
17121824
esw_chains_destroy(esw, esw_chains(esw));
@@ -1728,7 +1840,10 @@ static void esw_destroy_offloads_fdb_tables(struct mlx5_eswitch *esw)
17281840
esw_debug(esw->dev, "Destroy offloads FDB Tables\n");
17291841
mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_multi);
17301842
mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_uni);
1843+
mlx5_eswitch_del_send_to_vport_meta_rules(esw);
17311844
mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
1845+
if (esw->fdb_table.offloads.send_to_vport_meta_grp)
1846+
mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_meta_grp);
17321847
if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
17331848
mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
17341849
mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);

include/linux/mlx5/eswitch.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,16 @@ u32 mlx5_eswitch_get_vport_metadata_for_set(struct mlx5_eswitch *esw,
114114
#define ESW_ZONE_ID_BITS 8
115115
#define ESW_TUN_OPTS_BITS 12
116116
#define ESW_TUN_ID_BITS 12
117-
#define ESW_TUN_OFFSET ESW_ZONE_ID_BITS
117+
#define ESW_TUN_OPTS_OFFSET ESW_ZONE_ID_BITS
118+
#define ESW_TUN_OFFSET ESW_TUN_OPTS_OFFSET
118119
#define ESW_ZONE_ID_MASK GENMASK(ESW_ZONE_ID_BITS - 1, 0)
120+
#define ESW_TUN_OPTS_MASK GENMASK(32 - ESW_TUN_ID_BITS - 1, ESW_TUN_OPTS_OFFSET)
121+
#define ESW_TUN_MASK GENMASK(31, ESW_TUN_OFFSET)
122+
#define ESW_TUN_ID_SLOW_TABLE_GOTO_VPORT 0 /* 0 is not a valid tunnel id */
123+
#define ESW_TUN_OPTS_SLOW_TABLE_GOTO_VPORT 0xFFF /* 0xFFF is a reserved mapping */
124+
#define ESW_TUN_SLOW_TABLE_GOTO_VPORT ((ESW_TUN_ID_SLOW_TABLE_GOTO_VPORT << ESW_TUN_OPTS_BITS) | \
125+
ESW_TUN_OPTS_SLOW_TABLE_GOTO_VPORT)
126+
#define ESW_TUN_SLOW_TABLE_GOTO_VPORT_MARK ESW_TUN_OPTS_MASK
119127

120128
u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev);
121129
#else /* CONFIG_MLX5_ESWITCH */

0 commit comments

Comments
 (0)