Skip to content

Commit 49d37d0

Browse files
Chris Mikuba-moo
authored andcommitted
net/mlx5: CT: Separate CT and CT-NAT tuple entries
Currently a ct entry is stored in both ct and ct-nat tables. ct action is directed to the ct table, while ct nat action is directed to the nat table. ct-nat entries perform the nat header rewrites, if required. The current design assures that a ct action will match in hardware even if the tuple has nat configured, it will just not execute it. However, storing each connection in two tables increases the system's memory consumption while reducing its insertion rate. Offload a connection to either ct or the ct-nat table. Add a miss fall-through rule from ct-nat table to the ct table allowing ct(nat) action on non-natted connections. ct action on natted connections, by default, will be handled by the software miss path. Signed-off-by: Paul Blakey <[email protected]> Signed-off-by: Chris Mi <[email protected]> Signed-off-by: Tariq Toukan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent e575d3a commit 49d37d0

File tree

1 file changed

+143
-44
lines changed
  • drivers/net/ethernet/mellanox/mlx5/core/en

1 file changed

+143
-44
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c

Lines changed: 143 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ struct mlx5_tc_ct_priv {
6969
struct rhashtable ct_tuples_nat_ht;
7070
struct mlx5_flow_table *ct;
7171
struct mlx5_flow_table *ct_nat;
72+
struct mlx5_flow_group *ct_nat_miss_group;
73+
struct mlx5_flow_handle *ct_nat_miss_rule;
7274
struct mlx5e_post_act *post_act;
7375
struct mutex control_lock; /* guards parallel adds/dels */
7476
struct mapping_ctx *zone_mapping;
@@ -141,6 +143,8 @@ struct mlx5_ct_counter {
141143

142144
enum {
143145
MLX5_CT_ENTRY_FLAG_VALID,
146+
MLX5_CT_ENTRY_IN_CT_TABLE,
147+
MLX5_CT_ENTRY_IN_CT_NAT_TABLE,
144148
};
145149

146150
struct mlx5_ct_entry {
@@ -198,9 +202,15 @@ static const struct rhashtable_params tuples_nat_ht_params = {
198202
};
199203

200204
static bool
201-
mlx5_tc_ct_entry_has_nat(struct mlx5_ct_entry *entry)
205+
mlx5_tc_ct_entry_in_ct_table(struct mlx5_ct_entry *entry)
202206
{
203-
return !!(entry->tuple_nat_node.next);
207+
return test_bit(MLX5_CT_ENTRY_IN_CT_TABLE, &entry->flags);
208+
}
209+
210+
static bool
211+
mlx5_tc_ct_entry_in_ct_nat_table(struct mlx5_ct_entry *entry)
212+
{
213+
return test_bit(MLX5_CT_ENTRY_IN_CT_NAT_TABLE, &entry->flags);
204214
}
205215

206216
static int
@@ -526,8 +536,10 @@ static void
526536
mlx5_tc_ct_entry_del_rules(struct mlx5_tc_ct_priv *ct_priv,
527537
struct mlx5_ct_entry *entry)
528538
{
529-
mlx5_tc_ct_entry_del_rule(ct_priv, entry, true);
530-
mlx5_tc_ct_entry_del_rule(ct_priv, entry, false);
539+
if (mlx5_tc_ct_entry_in_ct_nat_table(entry))
540+
mlx5_tc_ct_entry_del_rule(ct_priv, entry, true);
541+
if (mlx5_tc_ct_entry_in_ct_table(entry))
542+
mlx5_tc_ct_entry_del_rule(ct_priv, entry, false);
531543

532544
atomic_dec(&ct_priv->debugfs.stats.offloaded);
533545
}
@@ -814,7 +826,7 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv,
814826
&zone_rule->mh,
815827
zone_restore_id,
816828
nat,
817-
mlx5_tc_ct_entry_has_nat(entry));
829+
mlx5_tc_ct_entry_in_ct_nat_table(entry));
818830
if (err) {
819831
ct_dbg("Failed to create ct entry mod hdr");
820832
goto err_mod_hdr;
@@ -888,7 +900,7 @@ mlx5_tc_ct_entry_replace_rule(struct mlx5_tc_ct_priv *ct_priv,
888900
*old_attr = *attr;
889901

890902
err = mlx5_tc_ct_entry_create_mod_hdr(ct_priv, attr, flow_rule, &mh, zone_restore_id,
891-
nat, mlx5_tc_ct_entry_has_nat(entry));
903+
nat, mlx5_tc_ct_entry_in_ct_nat_table(entry));
892904
if (err) {
893905
ct_dbg("Failed to create ct entry mod hdr");
894906
goto err_mod_hdr;
@@ -957,11 +969,13 @@ static void mlx5_tc_ct_entry_remove_from_tuples(struct mlx5_ct_entry *entry)
957969
{
958970
struct mlx5_tc_ct_priv *ct_priv = entry->ct_priv;
959971

960-
rhashtable_remove_fast(&ct_priv->ct_tuples_nat_ht,
961-
&entry->tuple_nat_node,
962-
tuples_nat_ht_params);
963-
rhashtable_remove_fast(&ct_priv->ct_tuples_ht, &entry->tuple_node,
964-
tuples_ht_params);
972+
if (mlx5_tc_ct_entry_in_ct_nat_table(entry))
973+
rhashtable_remove_fast(&ct_priv->ct_tuples_nat_ht,
974+
&entry->tuple_nat_node,
975+
tuples_nat_ht_params);
976+
if (mlx5_tc_ct_entry_in_ct_table(entry))
977+
rhashtable_remove_fast(&ct_priv->ct_tuples_ht, &entry->tuple_node,
978+
tuples_ht_params);
965979
}
966980

967981
static void mlx5_tc_ct_entry_del(struct mlx5_ct_entry *entry)
@@ -1100,21 +1114,26 @@ mlx5_tc_ct_entry_add_rules(struct mlx5_tc_ct_priv *ct_priv,
11001114
return err;
11011115
}
11021116

1103-
err = mlx5_tc_ct_entry_add_rule(ct_priv, flow_rule, entry, false,
1104-
zone_restore_id);
1105-
if (err)
1106-
goto err_orig;
1117+
if (mlx5_tc_ct_entry_in_ct_table(entry)) {
1118+
err = mlx5_tc_ct_entry_add_rule(ct_priv, flow_rule, entry, false,
1119+
zone_restore_id);
1120+
if (err)
1121+
goto err_orig;
1122+
}
11071123

1108-
err = mlx5_tc_ct_entry_add_rule(ct_priv, flow_rule, entry, true,
1109-
zone_restore_id);
1110-
if (err)
1111-
goto err_nat;
1124+
if (mlx5_tc_ct_entry_in_ct_nat_table(entry)) {
1125+
err = mlx5_tc_ct_entry_add_rule(ct_priv, flow_rule, entry, true,
1126+
zone_restore_id);
1127+
if (err)
1128+
goto err_nat;
1129+
}
11121130

11131131
atomic_inc(&ct_priv->debugfs.stats.offloaded);
11141132
return 0;
11151133

11161134
err_nat:
1117-
mlx5_tc_ct_entry_del_rule(ct_priv, entry, false);
1135+
if (mlx5_tc_ct_entry_in_ct_table(entry))
1136+
mlx5_tc_ct_entry_del_rule(ct_priv, entry, false);
11181137
err_orig:
11191138
mlx5_tc_ct_counter_put(ct_priv, entry);
11201139
return err;
@@ -1128,15 +1147,19 @@ mlx5_tc_ct_entry_replace_rules(struct mlx5_tc_ct_priv *ct_priv,
11281147
{
11291148
int err;
11301149

1131-
err = mlx5_tc_ct_entry_replace_rule(ct_priv, flow_rule, entry, false,
1132-
zone_restore_id);
1133-
if (err)
1134-
return err;
1150+
if (mlx5_tc_ct_entry_in_ct_table(entry)) {
1151+
err = mlx5_tc_ct_entry_replace_rule(ct_priv, flow_rule, entry, false,
1152+
zone_restore_id);
1153+
if (err)
1154+
return err;
1155+
}
11351156

1136-
err = mlx5_tc_ct_entry_replace_rule(ct_priv, flow_rule, entry, true,
1137-
zone_restore_id);
1138-
if (err)
1139-
mlx5_tc_ct_entry_del_rule(ct_priv, entry, false);
1157+
if (mlx5_tc_ct_entry_in_ct_nat_table(entry)) {
1158+
err = mlx5_tc_ct_entry_replace_rule(ct_priv, flow_rule, entry, true,
1159+
zone_restore_id);
1160+
if (err && mlx5_tc_ct_entry_in_ct_table(entry))
1161+
mlx5_tc_ct_entry_del_rule(ct_priv, entry, false);
1162+
}
11401163
return err;
11411164
}
11421165

@@ -1224,18 +1247,24 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft,
12241247
if (err)
12251248
goto err_entries;
12261249

1227-
err = rhashtable_lookup_insert_fast(&ct_priv->ct_tuples_ht,
1228-
&entry->tuple_node,
1229-
tuples_ht_params);
1230-
if (err)
1231-
goto err_tuple;
1232-
12331250
if (memcmp(&entry->tuple, &entry->tuple_nat, sizeof(entry->tuple))) {
12341251
err = rhashtable_lookup_insert_fast(&ct_priv->ct_tuples_nat_ht,
12351252
&entry->tuple_nat_node,
12361253
tuples_nat_ht_params);
12371254
if (err)
12381255
goto err_tuple_nat;
1256+
1257+
set_bit(MLX5_CT_ENTRY_IN_CT_NAT_TABLE, &entry->flags);
1258+
}
1259+
1260+
if (!mlx5_tc_ct_entry_in_ct_nat_table(entry)) {
1261+
err = rhashtable_lookup_insert_fast(&ct_priv->ct_tuples_ht,
1262+
&entry->tuple_node,
1263+
tuples_ht_params);
1264+
if (err)
1265+
goto err_tuple;
1266+
1267+
set_bit(MLX5_CT_ENTRY_IN_CT_TABLE, &entry->flags);
12391268
}
12401269
spin_unlock_bh(&ct_priv->ht_lock);
12411270

@@ -1251,17 +1280,10 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft,
12511280

12521281
err_rules:
12531282
spin_lock_bh(&ct_priv->ht_lock);
1254-
if (mlx5_tc_ct_entry_has_nat(entry))
1255-
rhashtable_remove_fast(&ct_priv->ct_tuples_nat_ht,
1256-
&entry->tuple_nat_node, tuples_nat_ht_params);
1257-
err_tuple_nat:
1258-
rhashtable_remove_fast(&ct_priv->ct_tuples_ht,
1259-
&entry->tuple_node,
1260-
tuples_ht_params);
12611283
err_tuple:
1262-
rhashtable_remove_fast(&ft->ct_entries_ht,
1263-
&entry->node,
1264-
cts_ht_params);
1284+
mlx5_tc_ct_entry_remove_from_tuples(entry);
1285+
err_tuple_nat:
1286+
rhashtable_remove_fast(&ft->ct_entries_ht, &entry->node, cts_ht_params);
12651287
err_entries:
12661288
spin_unlock_bh(&ct_priv->ht_lock);
12671289
err_set:
@@ -2149,6 +2171,76 @@ mlx5_ct_tc_remove_dbgfs(struct mlx5_tc_ct_priv *ct_priv)
21492171
debugfs_remove_recursive(ct_priv->debugfs.root);
21502172
}
21512173

2174+
static struct mlx5_flow_handle *
2175+
tc_ct_add_miss_rule(struct mlx5_flow_table *ft,
2176+
struct mlx5_flow_table *next_ft)
2177+
{
2178+
struct mlx5_flow_destination dest = {};
2179+
struct mlx5_flow_act act = {};
2180+
2181+
act.flags = FLOW_ACT_IGNORE_FLOW_LEVEL | FLOW_ACT_NO_APPEND;
2182+
act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2183+
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
2184+
dest.ft = next_ft;
2185+
2186+
return mlx5_add_flow_rules(ft, NULL, &act, &dest, 1);
2187+
}
2188+
2189+
static int
2190+
tc_ct_add_ct_table_miss_rule(struct mlx5_flow_table *from,
2191+
struct mlx5_flow_table *to,
2192+
struct mlx5_flow_group **miss_group,
2193+
struct mlx5_flow_handle **miss_rule)
2194+
{
2195+
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
2196+
struct mlx5_flow_group *group;
2197+
struct mlx5_flow_handle *rule;
2198+
unsigned int max_fte = from->max_fte;
2199+
u32 *flow_group_in;
2200+
int err = 0;
2201+
2202+
flow_group_in = kvzalloc(inlen, GFP_KERNEL);
2203+
if (!flow_group_in)
2204+
return -ENOMEM;
2205+
2206+
/* create miss group */
2207+
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index,
2208+
max_fte - 2);
2209+
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
2210+
max_fte - 1);
2211+
group = mlx5_create_flow_group(from, flow_group_in);
2212+
if (IS_ERR(group)) {
2213+
err = PTR_ERR(group);
2214+
goto err_miss_grp;
2215+
}
2216+
2217+
/* add miss rule to next fdb */
2218+
rule = tc_ct_add_miss_rule(from, to);
2219+
if (IS_ERR(rule)) {
2220+
err = PTR_ERR(rule);
2221+
goto err_miss_rule;
2222+
}
2223+
2224+
*miss_group = group;
2225+
*miss_rule = rule;
2226+
kvfree(flow_group_in);
2227+
return 0;
2228+
2229+
err_miss_rule:
2230+
mlx5_destroy_flow_group(group);
2231+
err_miss_grp:
2232+
kvfree(flow_group_in);
2233+
return err;
2234+
}
2235+
2236+
static void
2237+
tc_ct_del_ct_table_miss_rule(struct mlx5_flow_group *miss_group,
2238+
struct mlx5_flow_handle *miss_rule)
2239+
{
2240+
mlx5_del_flow_rules(miss_rule);
2241+
mlx5_destroy_flow_group(miss_group);
2242+
}
2243+
21522244
#define INIT_ERR_PREFIX "tc ct offload init failed"
21532245

21542246
struct mlx5_tc_ct_priv *
@@ -2212,6 +2304,12 @@ mlx5_tc_ct_init(struct mlx5e_priv *priv, struct mlx5_fs_chains *chains,
22122304
goto err_ct_nat_tbl;
22132305
}
22142306

2307+
err = tc_ct_add_ct_table_miss_rule(ct_priv->ct_nat, ct_priv->ct,
2308+
&ct_priv->ct_nat_miss_group,
2309+
&ct_priv->ct_nat_miss_rule);
2310+
if (err)
2311+
goto err_ct_zone_ht;
2312+
22152313
ct_priv->post_act = post_act;
22162314
mutex_init(&ct_priv->control_lock);
22172315
if (rhashtable_init(&ct_priv->zone_ht, &zone_params))
@@ -2273,6 +2371,7 @@ mlx5_tc_ct_clean(struct mlx5_tc_ct_priv *ct_priv)
22732371
ct_priv->fs_ops->destroy(ct_priv->fs);
22742372
kfree(ct_priv->fs);
22752373

2374+
tc_ct_del_ct_table_miss_rule(ct_priv->ct_nat_miss_group, ct_priv->ct_nat_miss_rule);
22762375
mlx5_chains_destroy_global_table(chains, ct_priv->ct_nat);
22772376
mlx5_chains_destroy_global_table(chains, ct_priv->ct);
22782377
mapping_destroy(ct_priv->zone_mapping);

0 commit comments

Comments
 (0)