History

net/mlx5: E-Switch, Increase number of chains and priorities

Increase the number of chains and priorities to support the whole range available in tc. We use unmanaged tables and ignore flow level to create more tables than what we declared to fs_core steering, and we manage the connections between the tables themselves. To support that we need FW with ignore_flow_level capability. Otherwise the old behaviour will be used, where we are limited by the number of levels we declared (4 chains, 16 prios).

Paul Blakey committed 6 years ago

Commit 278d51f1 parent 39ac2373 files · +232 −12Browse files

Unified · Split

3 files
  1. drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +2 −1
  2. drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c +227 −11
  3. drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.h +3 −0
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c+2−1
@@ -151,7 +151,7 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, · 150 unmodified lines
151 if (attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH) {151 if (attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH) {
152 flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;152 flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
153 dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;153 dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
154 dest[i].ft = esw->fdb_table.offloads.slow_fdb;154 dest[i].ft = mlx5_esw_chains_get_tc_end_ft(esw);
155 i++;155 i++;
156 } else if (attr->dest_chain) {156 } else if (attr->dest_chain) {
157 flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;157 flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
@@ -275,6 +275,7 @@ mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw, · 117 unmodified lines
275 if (attr->outer_match_level != MLX5_MATCH_NONE)275 if (attr->outer_match_level != MLX5_MATCH_NONE)
276 spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;276 spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
277 277
278 flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
278 rule = mlx5_add_flow_rules(fast_fdb, spec, &flow_act, dest, i);279 rule = mlx5_add_flow_rules(fast_fdb, spec, &flow_act, dest, i);
279 280
280 if (IS_ERR(rule))281 if (IS_ERR(rule))
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c+227−11
@@ -16,6 +16,10 @@ · 15 unmodified lines
16#define esw_chains_ht(esw) (esw_chains_priv(esw)->chains_ht)16#define esw_chains_ht(esw) (esw_chains_priv(esw)->chains_ht)
17#define esw_prios_ht(esw) (esw_chains_priv(esw)->prios_ht)17#define esw_prios_ht(esw) (esw_chains_priv(esw)->prios_ht)
18#define fdb_pool_left(esw) (esw_chains_priv(esw)->fdb_left)18#define fdb_pool_left(esw) (esw_chains_priv(esw)->fdb_left)
19#define tc_slow_fdb(esw) ((esw)->fdb_table.offloads.slow_fdb)
20#define tc_end_fdb(esw) (esw_chains_priv(esw)->tc_end_fdb)
21#define fdb_ignore_flow_level_supported(esw) \
22 (MLX5_CAP_ESW_FLOWTABLE_FDB((esw)->dev, ignore_flow_level))
19 23
20#define ESW_OFFLOADS_NUM_GROUPS 424#define ESW_OFFLOADS_NUM_GROUPS 4
21 25
@@ -39,6 +43,8 @@ struct mlx5_esw_chains_priv { · 17 unmodified lines
39 /* Protects above chains_ht and prios_ht */43 /* Protects above chains_ht and prios_ht */
40 struct mutex lock;44 struct mutex lock;
41 45
46 struct mlx5_flow_table *tc_end_fdb;
47
42 int fdb_left[ARRAY_SIZE(ESW_POOLS)];48 int fdb_left[ARRAY_SIZE(ESW_POOLS)];
43};49};
44 50
@@ -50,6 +56,7 @@ struct fdb_chain { · 5 unmodified lines
50 int ref;56 int ref;
51 57
52 struct mlx5_eswitch *esw;58 struct mlx5_eswitch *esw;
59 struct list_head prios_list;
53};60};
54 61
55struct fdb_prio_key {62struct fdb_prio_key {
@@ -60,6 +67,7 @@ struct fdb_prio_key { · 4 unmodified lines
60 67
61struct fdb_prio {68struct fdb_prio {
62 struct rhash_head node;69 struct rhash_head node;
70 struct list_head list;
63 71
64 struct fdb_prio_key key;72 struct fdb_prio_key key;
65 73
@@ -67,6 +75,9 @@ struct fdb_prio { · 1 unmodified line
67 75
68 struct fdb_chain *fdb_chain;76 struct fdb_chain *fdb_chain;
69 struct mlx5_flow_table *fdb;77 struct mlx5_flow_table *fdb;
78 struct mlx5_flow_table *next_fdb;
79 struct mlx5_flow_group *miss_group;
80 struct mlx5_flow_handle *miss_rule;
70};81};
71 82
72static const struct rhashtable_params chain_params = {83static const struct rhashtable_params chain_params = {
@@ -93,6 +104,9 @@ u32 mlx5_esw_chains_get_chain_range(struct mlx5_eswitch *esw) · 20 unmodified lines
93 if (!mlx5_esw_chains_prios_supported(esw))104 if (!mlx5_esw_chains_prios_supported(esw))
94 return 1;105 return 1;
95 106
107 if (fdb_ignore_flow_level_supported(esw))
108 return UINT_MAX - 1;
109
96 return FDB_TC_MAX_CHAIN;110 return FDB_TC_MAX_CHAIN;
97}111}
98 112
@@ -106,11 +120,17 @@ u32 mlx5_esw_chains_get_prio_range(struct mlx5_eswitch *esw) · 7 unmodified lines
106 if (!mlx5_esw_chains_prios_supported(esw))120 if (!mlx5_esw_chains_prios_supported(esw))
107 return 1;121 return 1;
108 122
123 if (fdb_ignore_flow_level_supported(esw))
124 return UINT_MAX;
125
109 return FDB_TC_MAX_PRIO;126 return FDB_TC_MAX_PRIO;
110}127}
111 128
112static unsigned int mlx5_esw_chains_get_level_range(struct mlx5_eswitch *esw)129static unsigned int mlx5_esw_chains_get_level_range(struct mlx5_eswitch *esw)
113{130{
131 if (fdb_ignore_flow_level_supported(esw))
132 return UINT_MAX;
133
114 return FDB_TC_LEVELS_PER_PRIO;134 return FDB_TC_LEVELS_PER_PRIO;
115}135}
116 136
@@ -181,13 +201,40 @@ mlx5_esw_chains_create_fdb_table(struct mlx5_eswitch *esw, · 64 unmodified lines
181 sz = mlx5_esw_chains_get_avail_sz_from_pool(esw, POOL_NEXT_SIZE);201 sz = mlx5_esw_chains_get_avail_sz_from_pool(esw, POOL_NEXT_SIZE);
182 if (!sz)202 if (!sz)
183 return ERR_PTR(-ENOSPC);203 return ERR_PTR(-ENOSPC);
184
185 ft_attr.max_fte = sz;204 ft_attr.max_fte = sz;
186 ft_attr.level = level;
187 ft_attr.prio = prio - 1;
188 ft_attr.autogroup.max_num_groups = ESW_OFFLOADS_NUM_GROUPS;
189 ns = mlx5_get_fdb_sub_ns(esw->dev, chain);
190 205
206 /* We use tc_slow_fdb(esw) as the table's next_ft till
207 * ignore_flow_level is allowed on FT creation and not just for FTEs.
208 * Instead caller should add an explicit miss rule if needed.
209 */
210 ft_attr.next_ft = tc_slow_fdb(esw);
211
212 /* The root table(chain 0, prio 1, level 0) is required to be
213 * connected to the previous prio (FDB_BYPASS_PATH if exists).
214 * We always create it, as a managed table, in order to align with
215 * fs_core logic.
216 */
217 if (!fdb_ignore_flow_level_supported(esw) ||
218 (chain == 0 && prio == 1 && level == 0)) {
219 ft_attr.level = level;
220 ft_attr.prio = prio - 1;
221 ns = mlx5_get_fdb_sub_ns(esw->dev, chain);
222 } else {
223 ft_attr.flags |= MLX5_FLOW_TABLE_UNMANAGED;
224 ft_attr.prio = FDB_TC_OFFLOAD;
225 /* Firmware doesn't allow us to create another level 0 table,
226 * so we create all unmanaged tables as level 1.
227 *
228 * To connect them, we use explicit miss rules with
229 * ignore_flow_level. Caller is responsible to create
230 * these rules (if needed).
231 */
232 ft_attr.level = 1;
233 ns = mlx5_get_flow_namespace(esw->dev, MLX5_FLOW_NAMESPACE_FDB);
234 }
235
236 ft_attr.autogroup.num_reserved_entries = 2;
237 ft_attr.autogroup.max_num_groups = ESW_OFFLOADS_NUM_GROUPS;
191 fdb = mlx5_create_auto_grouped_flow_table(ns, &ft_attr);238 fdb = mlx5_create_auto_grouped_flow_table(ns, &ft_attr);
192 if (IS_ERR(fdb)) {239 if (IS_ERR(fdb)) {
193 esw_warn(esw->dev,240 esw_warn(esw->dev,
@@ -220,6 +267,7 @@ mlx5_esw_chains_create_fdb_chain(struct mlx5_eswitch *esw, u32 chain) · 26 unmodified lines
220 267
221 fdb_chain->esw = esw;268 fdb_chain->esw = esw;
222 fdb_chain->chain = chain;269 fdb_chain->chain = chain;
270 INIT_LIST_HEAD(&fdb_chain->prios_list);
223 271
224 err = rhashtable_insert_fast(&esw_chains_ht(esw), &fdb_chain->node,272 err = rhashtable_insert_fast(&esw_chains_ht(esw), &fdb_chain->node,
225 chain_params);273 chain_params);
@@ -261,6 +309,79 @@ mlx5_esw_chains_get_fdb_chain(struct mlx5_eswitch *esw, u32 chain) · 35 unmodified lines
261 return fdb_chain;309 return fdb_chain;
262}310}
263 311
312static struct mlx5_flow_handle *
313mlx5_esw_chains_add_miss_rule(struct mlx5_flow_table *fdb,
314 struct mlx5_flow_table *next_fdb)
315{
316 static const struct mlx5_flow_spec spec = {};
317 struct mlx5_flow_destination dest = {};
318 struct mlx5_flow_act act = {};
319
320 act.flags = FLOW_ACT_IGNORE_FLOW_LEVEL | FLOW_ACT_NO_APPEND;
321 act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
322 dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
323 dest.ft = next_fdb;
324
325 return mlx5_add_flow_rules(fdb, &spec, &act, &dest, 1);
326}
327
328static int
329mlx5_esw_chains_update_prio_prevs(struct fdb_prio *fdb_prio,
330 struct mlx5_flow_table *next_fdb)
331{
332 struct mlx5_flow_handle *miss_rules[FDB_TC_LEVELS_PER_PRIO + 1] = {};
333 struct fdb_chain *fdb_chain = fdb_prio->fdb_chain;
334 struct fdb_prio *pos;
335 int n = 0, err;
336
337 if (fdb_prio->key.level)
338 return 0;
339
340 /* Iterate in reverse order until reaching the level 0 rule of
341 * the previous priority, adding all the miss rules first, so we can
342 * revert them if any of them fails.
343 */
344 pos = fdb_prio;
345 list_for_each_entry_continue_reverse(pos,
346 &fdb_chain->prios_list,
347 list) {
348 miss_rules[n] = mlx5_esw_chains_add_miss_rule(pos->fdb,
349 next_fdb);
350 if (IS_ERR(miss_rules[n])) {
351 err = PTR_ERR(miss_rules[n]);
352 goto err_prev_rule;
353 }
354
355 n++;
356 if (!pos->key.level)
357 break;
358 }
359
360 /* Success, delete old miss rules, and update the pointers. */
361 n = 0;
362 pos = fdb_prio;
363 list_for_each_entry_continue_reverse(pos,
364 &fdb_chain->prios_list,
365 list) {
366 mlx5_del_flow_rules(pos->miss_rule);
367
368 pos->miss_rule = miss_rules[n];
369 pos->next_fdb = next_fdb;
370
371 n++;
372 if (!pos->key.level)
373 break;
374 }
375
376 return 0;
377
378err_prev_rule:
379 while (--n >= 0)
380 mlx5_del_flow_rules(miss_rules[n]);
381
382 return err;
383}
384
264static void385static void
265mlx5_esw_chains_put_fdb_chain(struct fdb_chain *fdb_chain)386mlx5_esw_chains_put_fdb_chain(struct fdb_chain *fdb_chain)
266{387{
@@ -272,9 +393,15 @@ static struct fdb_prio * · 5 unmodified lines
272mlx5_esw_chains_create_fdb_prio(struct mlx5_eswitch *esw,393mlx5_esw_chains_create_fdb_prio(struct mlx5_eswitch *esw,
273 u32 chain, u32 prio, u32 level)394 u32 chain, u32 prio, u32 level)
274{395{
396 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
397 struct mlx5_flow_handle *miss_rule = NULL;
398 struct mlx5_flow_group *miss_group;
275 struct fdb_prio *fdb_prio = NULL;399 struct fdb_prio *fdb_prio = NULL;
400 struct mlx5_flow_table *next_fdb;
276 struct fdb_chain *fdb_chain;401 struct fdb_chain *fdb_chain;
277 struct mlx5_flow_table *fdb;402 struct mlx5_flow_table *fdb;
403 struct list_head *pos;
404 u32 *flow_group_in;
278 int err;405 int err;
279 406
280 fdb_chain = mlx5_esw_chains_get_fdb_chain(esw, chain);407 fdb_chain = mlx5_esw_chains_get_fdb_chain(esw, chain);
@@ -282,18 +409,65 @@ mlx5_esw_chains_create_fdb_prio(struct mlx5_eswitch *esw, · 1 unmodified line
282 return ERR_CAST(fdb_chain);409 return ERR_CAST(fdb_chain);
283 410
284 fdb_prio = kvzalloc(sizeof(*fdb_prio), GFP_KERNEL);411 fdb_prio = kvzalloc(sizeof(*fdb_prio), GFP_KERNEL);
285 if (!fdb_prio) {412 flow_group_in = kvzalloc(inlen, GFP_KERNEL);
413 if (!fdb_prio || !flow_group_in) {
286 err = -ENOMEM;414 err = -ENOMEM;
287 goto err_alloc;415 goto err_alloc;
288 }416 }
289 417
290 fdb = mlx5_esw_chains_create_fdb_table(esw, fdb_chain->chain, prio,418 /* Chain's prio list is sorted by prio and level.
291 level);419 * And all levels of some prio point to the next prio's level 0.
420 * Example list (prio, level):
421 * (3,0)->(3,1)->(5,0)->(5,1)->(6,1)->(7,0)
422 * In hardware, we will we have the following pointers:
423 * (3,0) -> (5,0) -> (7,0) -> Slow path
424 * (3,1) -> (5,0)
425 * (5,1) -> (7,0)
426 * (6,1) -> (7,0)
427 */
428
429 /* Default miss for each chain: */
430 next_fdb = (chain == mlx5_esw_chains_get_ft_chain(esw)) ?
431 tc_slow_fdb(esw) :
432 tc_end_fdb(esw);
433 list_for_each(pos, &fdb_chain->prios_list) {
434 struct fdb_prio *p = list_entry(pos, struct fdb_prio, list);
435
436 /* exit on first pos that is larger */
437 if (prio < p->key.prio || (prio == p->key.prio &&
438 level < p->key.level)) {
439 /* Get next level 0 table */
440 next_fdb = p->key.level == 0 ? p->fdb : p->next_fdb;
441 break;
442 }
443 }
444
445 fdb = mlx5_esw_chains_create_fdb_table(esw, chain, prio, level);
292 if (IS_ERR(fdb)) {446 if (IS_ERR(fdb)) {
293 err = PTR_ERR(fdb);447 err = PTR_ERR(fdb);
294 goto err_create;448 goto err_create;
295 }449 }
296 450
451 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index,
452 fdb->max_fte - 2);
453 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
454 fdb->max_fte - 1);
455 miss_group = mlx5_create_flow_group(fdb, flow_group_in);
456 if (IS_ERR(miss_group)) {
457 err = PTR_ERR(miss_group);
458 goto err_group;
459 }
460
461 /* Add miss rule to next_fdb */
462 miss_rule = mlx5_esw_chains_add_miss_rule(fdb, next_fdb);
463 if (IS_ERR(miss_rule)) {
464 err = PTR_ERR(miss_rule);
465 goto err_miss_rule;
466 }
467
468 fdb_prio->miss_group = miss_group;
469 fdb_prio->miss_rule = miss_rule;
470 fdb_prio->next_fdb = next_fdb;
297 fdb_prio->fdb_chain = fdb_chain;471 fdb_prio->fdb_chain = fdb_chain;
298 fdb_prio->key.chain = chain;472 fdb_prio->key.chain = chain;
299 fdb_prio->key.prio = prio;473 fdb_prio->key.prio = prio;
@@ -305,13 +479,30 @@ mlx5_esw_chains_create_fdb_prio(struct mlx5_eswitch *esw, · 5 unmodified lines
305 if (err)479 if (err)
306 goto err_insert;480 goto err_insert;
307 481
482 list_add(&fdb_prio->list, pos->prev);
483
484 /* Table is ready, connect it */
485 err = mlx5_esw_chains_update_prio_prevs(fdb_prio, fdb);
486 if (err)
487 goto err_update;
488
489 kvfree(flow_group_in);
308 return fdb_prio;490 return fdb_prio;
309 491
492err_update:
493 list_del(&fdb_prio->list);
494 rhashtable_remove_fast(&esw_prios_ht(esw), &fdb_prio->node,
495 prio_params);
310err_insert:496err_insert:
497 mlx5_del_flow_rules(miss_rule);
498err_miss_rule:
499 mlx5_destroy_flow_group(miss_group);
500err_group:
311 mlx5_esw_chains_destroy_fdb_table(esw, fdb);501 mlx5_esw_chains_destroy_fdb_table(esw, fdb);
312err_create:502err_create:
313 kvfree(fdb_prio);
314err_alloc:503err_alloc:
504 kvfree(fdb_prio);
505 kvfree(flow_group_in);
315 mlx5_esw_chains_put_fdb_chain(fdb_chain);506 mlx5_esw_chains_put_fdb_chain(fdb_chain);
316 return ERR_PTR(err);507 return ERR_PTR(err);
317}508}
@@ -322,8 +513,14 @@ mlx5_esw_chains_destroy_fdb_prio(struct mlx5_eswitch *esw, · 4 unmodified lines
322{513{
323 struct fdb_chain *fdb_chain = fdb_prio->fdb_chain;514 struct fdb_chain *fdb_chain = fdb_prio->fdb_chain;
324 515
516 WARN_ON(mlx5_esw_chains_update_prio_prevs(fdb_prio,
517 fdb_prio->next_fdb));
518
519 list_del(&fdb_prio->list);
325 rhashtable_remove_fast(&esw_prios_ht(esw), &fdb_prio->node,520 rhashtable_remove_fast(&esw_prios_ht(esw), &fdb_prio->node,
326 prio_params);521 prio_params);
522 mlx5_del_flow_rules(fdb_prio->miss_rule);
523 mlx5_destroy_flow_group(fdb_prio->miss_group);
327 mlx5_esw_chains_destroy_fdb_table(esw, fdb_prio->fdb);524 mlx5_esw_chains_destroy_fdb_table(esw, fdb_prio->fdb);
328 mlx5_esw_chains_put_fdb_chain(fdb_chain);525 mlx5_esw_chains_put_fdb_chain(fdb_chain);
329 kvfree(fdb_prio);526 kvfree(fdb_prio);
@@ -415,6 +612,12 @@ err_get_prio: · 85 unmodified lines
415 chain, prio, level);612 chain, prio, level);
416}613}
417 614
615struct mlx5_flow_table *
616mlx5_esw_chains_get_tc_end_ft(struct mlx5_eswitch *esw)
617{
618 return tc_end_fdb(esw);
619}
620
418static int621static int
419mlx5_esw_chains_init(struct mlx5_eswitch *esw)622mlx5_esw_chains_init(struct mlx5_eswitch *esw)
420{623{
@@ -484,11 +687,21 @@ mlx5_esw_chains_open(struct mlx5_eswitch *esw) · 63 unmodified lines
484 struct mlx5_flow_table *ft;687 struct mlx5_flow_table *ft;
485 int err;688 int err;
486 689
487 /* Always open the root for fast path */690 /* Create tc_end_fdb(esw) which is the always created ft chain */
488 ft = mlx5_esw_chains_get_table(esw, 0, 1, 0);691 ft = mlx5_esw_chains_get_table(esw, mlx5_esw_chains_get_ft_chain(esw),
692 1, 0);
489 if (IS_ERR(ft))693 if (IS_ERR(ft))
490 return PTR_ERR(ft);694 return PTR_ERR(ft);
491 695
696 tc_end_fdb(esw) = ft;
697
698 /* Always open the root for fast path */
699 ft = mlx5_esw_chains_get_table(esw, 0, 1, 0);
700 if (IS_ERR(ft)) {
701 err = PTR_ERR(ft);
702 goto level_0_err;
703 }
704
492 /* Open level 1 for split rules now if prios isn't supported */705 /* Open level 1 for split rules now if prios isn't supported */
493 if (!mlx5_esw_chains_prios_supported(esw)) {706 if (!mlx5_esw_chains_prios_supported(esw)) {
494 ft = mlx5_esw_chains_get_table(esw, 0, 1, 1);707 ft = mlx5_esw_chains_get_table(esw, 0, 1, 1);
@@ -503,6 +716,8 @@ mlx5_esw_chains_open(struct mlx5_eswitch *esw) · 8 unmodified lines
503 716
504level_1_err:717level_1_err:
505 mlx5_esw_chains_put_table(esw, 0, 1, 0);718 mlx5_esw_chains_put_table(esw, 0, 1, 0);
719level_0_err:
720 mlx5_esw_chains_put_table(esw, mlx5_esw_chains_get_ft_chain(esw), 1, 0);
506 return err;721 return err;
507}722}
508 723
@@ -512,6 +727,7 @@ mlx5_esw_chains_close(struct mlx5_eswitch *esw) · 3 unmodified lines
512 if (!mlx5_esw_chains_prios_supported(esw))727 if (!mlx5_esw_chains_prios_supported(esw))
513 mlx5_esw_chains_put_table(esw, 0, 1, 1);728 mlx5_esw_chains_put_table(esw, 0, 1, 1);
514 mlx5_esw_chains_put_table(esw, 0, 1, 0);729 mlx5_esw_chains_put_table(esw, 0, 1, 0);
730 mlx5_esw_chains_put_table(esw, mlx5_esw_chains_get_ft_chain(esw), 1, 0);
515}731}
516 732
517int733int
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.h+3−0
@@ -20,6 +20,9 @@ void · 19 unmodified lines
20mlx5_esw_chains_put_table(struct mlx5_eswitch *esw, u32 chain, u32 prio,20mlx5_esw_chains_put_table(struct mlx5_eswitch *esw, u32 chain, u32 prio,
21 u32 level);21 u32 level);
22 22
23struct mlx5_flow_table *
24mlx5_esw_chains_get_tc_end_ft(struct mlx5_eswitch *esw);
25
23int mlx5_esw_chains_create(struct mlx5_eswitch *esw);26int mlx5_esw_chains_create(struct mlx5_eswitch *esw);
24void mlx5_esw_chains_destroy(struct mlx5_eswitch *esw);27void mlx5_esw_chains_destroy(struct mlx5_eswitch *esw);
25 28

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t