Skip to content

Commit a6c90dd

Browse files
committed
Merge branch 'sched-introduce-chain-templates-support-with-offloading-to-mlxsw'
Jiri Pirko says: ==================== sched: introduce chain templates support with offloading to mlxsw For the TC clsact offload these days, some of HW drivers need to hold a magic ball. The reason is, with the first inserted rule inside HW they need to guess what fields will be used for the matching. If later on this guess proves to be wrong and user adds a filter with a different field to match, there's a problem. Mlxsw resolves it now with couple of patterns. Those try to cover as many match fields as possible. This aproach is far from optimal, both performance-wise and scale-wise. Also, there is a combination of filters that in certain order won't succeed. Most of the time, when user inserts filters in chain, he knows right away how the filters are going to look like - what type and option will they have. For example, he knows that he will only insert filters of type flower matching destination IP address. He can specify a template that would cover all the filters in the chain. This patchset is providing the possibility to user to provide such template to kernel and propagate it all the way down to device drivers. See the examples below. Create dummy device with clsact first: There is no chain present by by default: Add chain number 11 by explicit command: chain parent ffff: chain 11 Add filter to chain number 12 which does not exist. That will create implicit chain 12: chain parent ffff: chain 11 chain parent ffff: chain 12 Delete both chains: Add a chain with template of type flower allowing to insert rules matching on last 2 bytes of destination mac address: The chain with template is now showed in the list: chain parent ffff: flower chain 0 dst_mac 00:00:00:00:00:00/00:00:00:00:ff:ff eth_type ipv4 Add another chain (number 22) with template: chain parent ffff: flower chain 0 dst_mac 00:00:00:00:00:00/00:00:00:00:ff:ff eth_type ipv4 chain parent ffff: flower chain 22 eth_type ipv4 dst_ip 0.0.0.0/16 Add a filter that fits the template: Addition of filters that does not fit the template would fail: Error: cls_flower: Mask does not fit the template. We have an error talking to the kernel, -1 Error: cls_flower: Mask does not fit the template. We have an error talking to the kernel, -1 Additions of filters to chain 22: Error: cls_flower: Mask does not fit the template. We have an error talking to the kernel, -1 Error: cls_flower: Mask does not fit the template. We have an error talking to the kernel, -1 --- v3->v4: - patch 2: - new patch - patch 3: - new patch, derived from the previous v3 chaintemplate obj patch - patch 4: - only templates part as chains creation/deletion is now a separate patch - don't pass template priv as arg of "change" op - patch 6: - rebased on top of flower cvlan patch and ip tos/ttl patch - patch 7: - templave priv is no longer passed as an arg to "change" op - patch 11: - split from the originally single patch - patch 12: - split from the originally single patch v2->v3: - patch 7: - rebase on top of the reoffload patchset - patch 8: - rebase on top of the reoffload patchset v1->v2: - patch 8: - remove leftover extack arg in fl_hw_create_tmplt() ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents d3585ed + d159b38 commit a6c90dd

File tree

15 files changed

+829
-139
lines changed

15 files changed

+829
-139
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,6 +1455,11 @@ mlxsw_sp_setup_tc_cls_flower(struct mlxsw_sp_acl_block *acl_block,
14551455
return 0;
14561456
case TC_CLSFLOWER_STATS:
14571457
return mlxsw_sp_flower_stats(mlxsw_sp, acl_block, f);
1458+
case TC_CLSFLOWER_TMPLT_CREATE:
1459+
return mlxsw_sp_flower_tmplt_create(mlxsw_sp, acl_block, f);
1460+
case TC_CLSFLOWER_TMPLT_DESTROY:
1461+
mlxsw_sp_flower_tmplt_destroy(mlxsw_sp, acl_block, f);
1462+
return 0;
14581463
default:
14591464
return -EOPNOTSUPP;
14601465
}

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,8 @@ mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp,
543543
struct mlxsw_sp_acl_ruleset *
544544
mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp,
545545
struct mlxsw_sp_acl_block *block, u32 chain_index,
546-
enum mlxsw_sp_acl_profile profile);
546+
enum mlxsw_sp_acl_profile profile,
547+
struct mlxsw_afk_element_usage *tmplt_elusage);
547548
void mlxsw_sp_acl_ruleset_put(struct mlxsw_sp *mlxsw_sp,
548549
struct mlxsw_sp_acl_ruleset *ruleset);
549550
u16 mlxsw_sp_acl_ruleset_group_id(struct mlxsw_sp_acl_ruleset *ruleset);
@@ -667,6 +668,12 @@ void mlxsw_sp_flower_destroy(struct mlxsw_sp *mlxsw_sp,
667668
int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp,
668669
struct mlxsw_sp_acl_block *block,
669670
struct tc_cls_flower_offload *f);
671+
int mlxsw_sp_flower_tmplt_create(struct mlxsw_sp *mlxsw_sp,
672+
struct mlxsw_sp_acl_block *block,
673+
struct tc_cls_flower_offload *f);
674+
void mlxsw_sp_flower_tmplt_destroy(struct mlxsw_sp *mlxsw_sp,
675+
struct mlxsw_sp_acl_block *block,
676+
struct tc_cls_flower_offload *f);
670677

671678
/* spectrum_qdisc.c */
672679
int mlxsw_sp_tc_qdisc_init(struct mlxsw_sp_port *mlxsw_sp_port);

drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,8 @@ int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp,
317317
static struct mlxsw_sp_acl_ruleset *
318318
mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp,
319319
struct mlxsw_sp_acl_block *block, u32 chain_index,
320-
const struct mlxsw_sp_acl_profile_ops *ops)
320+
const struct mlxsw_sp_acl_profile_ops *ops,
321+
struct mlxsw_afk_element_usage *tmplt_elusage)
321322
{
322323
struct mlxsw_sp_acl *acl = mlxsw_sp->acl;
323324
struct mlxsw_sp_acl_ruleset *ruleset;
@@ -337,7 +338,8 @@ mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp,
337338
if (err)
338339
goto err_rhashtable_init;
339340

340-
err = ops->ruleset_add(mlxsw_sp, &acl->tcam, ruleset->priv);
341+
err = ops->ruleset_add(mlxsw_sp, &acl->tcam, ruleset->priv,
342+
tmplt_elusage);
341343
if (err)
342344
goto err_ops_ruleset_add;
343345

@@ -419,7 +421,8 @@ mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp,
419421
struct mlxsw_sp_acl_ruleset *
420422
mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp,
421423
struct mlxsw_sp_acl_block *block, u32 chain_index,
422-
enum mlxsw_sp_acl_profile profile)
424+
enum mlxsw_sp_acl_profile profile,
425+
struct mlxsw_afk_element_usage *tmplt_elusage)
423426
{
424427
const struct mlxsw_sp_acl_profile_ops *ops;
425428
struct mlxsw_sp_acl *acl = mlxsw_sp->acl;
@@ -434,7 +437,8 @@ mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp,
434437
mlxsw_sp_acl_ruleset_ref_inc(ruleset);
435438
return ruleset;
436439
}
437-
return mlxsw_sp_acl_ruleset_create(mlxsw_sp, block, chain_index, ops);
440+
return mlxsw_sp_acl_ruleset_create(mlxsw_sp, block, chain_index, ops,
441+
tmplt_elusage);
438442
}
439443

440444
void mlxsw_sp_acl_ruleset_put(struct mlxsw_sp *mlxsw_sp,

drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ struct mlxsw_sp_acl_tcam_group {
189189
struct mlxsw_sp_acl_tcam_group_ops *ops;
190190
const struct mlxsw_sp_acl_tcam_pattern *patterns;
191191
unsigned int patterns_count;
192+
bool tmplt_elusage_set;
193+
struct mlxsw_afk_element_usage tmplt_elusage;
192194
};
193195

194196
struct mlxsw_sp_acl_tcam_chunk {
@@ -234,13 +236,19 @@ mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp *mlxsw_sp,
234236
struct mlxsw_sp_acl_tcam *tcam,
235237
struct mlxsw_sp_acl_tcam_group *group,
236238
const struct mlxsw_sp_acl_tcam_pattern *patterns,
237-
unsigned int patterns_count)
239+
unsigned int patterns_count,
240+
struct mlxsw_afk_element_usage *tmplt_elusage)
238241
{
239242
int err;
240243

241244
group->tcam = tcam;
242245
group->patterns = patterns;
243246
group->patterns_count = patterns_count;
247+
if (tmplt_elusage) {
248+
group->tmplt_elusage_set = true;
249+
memcpy(&group->tmplt_elusage, tmplt_elusage,
250+
sizeof(group->tmplt_elusage));
251+
}
244252
INIT_LIST_HEAD(&group->region_list);
245253
err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id);
246254
if (err)
@@ -449,6 +457,15 @@ mlxsw_sp_acl_tcam_group_use_patterns(struct mlxsw_sp_acl_tcam_group *group,
449457
const struct mlxsw_sp_acl_tcam_pattern *pattern;
450458
int i;
451459

460+
/* In case the template is set, we don't have to look up the pattern
461+
* and just use the template.
462+
*/
463+
if (group->tmplt_elusage_set) {
464+
memcpy(out, &group->tmplt_elusage, sizeof(*out));
465+
WARN_ON(!mlxsw_afk_element_usage_subset(elusage, out));
466+
return;
467+
}
468+
452469
for (i = 0; i < group->patterns_count; i++) {
453470
pattern = &group->patterns[i];
454471
mlxsw_afk_element_usage_fill(out, pattern->elements,
@@ -865,13 +882,15 @@ struct mlxsw_sp_acl_tcam_flower_rule {
865882
static int
866883
mlxsw_sp_acl_tcam_flower_ruleset_add(struct mlxsw_sp *mlxsw_sp,
867884
struct mlxsw_sp_acl_tcam *tcam,
868-
void *ruleset_priv)
885+
void *ruleset_priv,
886+
struct mlxsw_afk_element_usage *tmplt_elusage)
869887
{
870888
struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
871889

872890
return mlxsw_sp_acl_tcam_group_add(mlxsw_sp, tcam, &ruleset->group,
873891
mlxsw_sp_acl_tcam_patterns,
874-
MLXSW_SP_ACL_TCAM_PATTERNS_COUNT);
892+
MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
893+
tmplt_elusage);
875894
}
876895

877896
static void

drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
6464
struct mlxsw_sp_acl_profile_ops {
6565
size_t ruleset_priv_size;
6666
int (*ruleset_add)(struct mlxsw_sp *mlxsw_sp,
67-
struct mlxsw_sp_acl_tcam *tcam, void *ruleset_priv);
67+
struct mlxsw_sp_acl_tcam *tcam, void *ruleset_priv,
68+
struct mlxsw_afk_element_usage *tmplt_elusage);
6869
void (*ruleset_del)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv);
6970
int (*ruleset_bind)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv,
7071
struct mlxsw_sp_port *mlxsw_sp_port,

drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ int mlxsw_sp_flower_replace(struct mlxsw_sp *mlxsw_sp,
414414

415415
ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
416416
f->common.chain_index,
417-
MLXSW_SP_ACL_PROFILE_FLOWER);
417+
MLXSW_SP_ACL_PROFILE_FLOWER, NULL);
418418
if (IS_ERR(ruleset))
419419
return PTR_ERR(ruleset);
420420

@@ -458,7 +458,7 @@ void mlxsw_sp_flower_destroy(struct mlxsw_sp *mlxsw_sp,
458458

459459
ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
460460
f->common.chain_index,
461-
MLXSW_SP_ACL_PROFILE_FLOWER);
461+
MLXSW_SP_ACL_PROFILE_FLOWER, NULL);
462462
if (IS_ERR(ruleset))
463463
return;
464464

@@ -484,7 +484,7 @@ int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp,
484484

485485
ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
486486
f->common.chain_index,
487-
MLXSW_SP_ACL_PROFILE_FLOWER);
487+
MLXSW_SP_ACL_PROFILE_FLOWER, NULL);
488488
if (WARN_ON(IS_ERR(ruleset)))
489489
return -EINVAL;
490490

@@ -506,3 +506,41 @@ int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp,
506506
mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset);
507507
return err;
508508
}
509+
510+
int mlxsw_sp_flower_tmplt_create(struct mlxsw_sp *mlxsw_sp,
511+
struct mlxsw_sp_acl_block *block,
512+
struct tc_cls_flower_offload *f)
513+
{
514+
struct mlxsw_sp_acl_ruleset *ruleset;
515+
struct mlxsw_sp_acl_rule_info rulei;
516+
int err;
517+
518+
memset(&rulei, 0, sizeof(rulei));
519+
err = mlxsw_sp_flower_parse(mlxsw_sp, block, &rulei, f);
520+
if (err)
521+
return err;
522+
ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
523+
f->common.chain_index,
524+
MLXSW_SP_ACL_PROFILE_FLOWER,
525+
&rulei.values.elusage);
526+
if (IS_ERR(ruleset))
527+
return PTR_ERR(ruleset);
528+
/* keep the reference to the ruleset */
529+
return 0;
530+
}
531+
532+
void mlxsw_sp_flower_tmplt_destroy(struct mlxsw_sp *mlxsw_sp,
533+
struct mlxsw_sp_acl_block *block,
534+
struct tc_cls_flower_offload *f)
535+
{
536+
struct mlxsw_sp_acl_ruleset *ruleset;
537+
538+
ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
539+
f->common.chain_index,
540+
MLXSW_SP_ACL_PROFILE_FLOWER, NULL);
541+
if (IS_ERR(ruleset))
542+
return;
543+
/* put the reference to the ruleset kept in create */
544+
mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset);
545+
mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset);
546+
}

include/net/pkt_cls.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,8 @@ enum tc_fl_command {
721721
TC_CLSFLOWER_REPLACE,
722722
TC_CLSFLOWER_DESTROY,
723723
TC_CLSFLOWER_STATS,
724+
TC_CLSFLOWER_TMPLT_CREATE,
725+
TC_CLSFLOWER_TMPLT_DESTROY,
724726
};
725727

726728
struct tc_cls_flower_offload {

include/net/sch_generic.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ struct tcf_result {
238238
};
239239
};
240240

241+
struct tcf_chain;
242+
241243
struct tcf_proto_ops {
242244
struct list_head head;
243245
char kind[IFNAMSIZ];
@@ -263,10 +265,18 @@ struct tcf_proto_ops {
263265
tc_setup_cb_t *cb, void *cb_priv,
264266
struct netlink_ext_ack *extack);
265267
void (*bind_class)(void *, u32, unsigned long);
268+
void * (*tmplt_create)(struct net *net,
269+
struct tcf_chain *chain,
270+
struct nlattr **tca,
271+
struct netlink_ext_ack *extack);
272+
void (*tmplt_destroy)(void *tmplt_priv);
266273

267274
/* rtnetlink specific */
268275
int (*dump)(struct net*, struct tcf_proto*, void *,
269276
struct sk_buff *skb, struct tcmsg*);
277+
int (*tmplt_dump)(struct sk_buff *skb,
278+
struct net *net,
279+
void *tmplt_priv);
270280

271281
struct module *owner;
272282
};
@@ -300,11 +310,13 @@ typedef void tcf_chain_head_change_t(struct tcf_proto *tp_head, void *priv);
300310

301311
struct tcf_chain {
302312
struct tcf_proto __rcu *filter_chain;
303-
struct list_head filter_chain_list;
304313
struct list_head list;
305314
struct tcf_block *block;
306315
u32 index; /* chain index */
307316
unsigned int refcnt;
317+
bool explicitly_created;
318+
const struct tcf_proto_ops *tmplt_ops;
319+
void *tmplt_priv;
308320
};
309321

310322
struct tcf_block {
@@ -318,6 +330,10 @@ struct tcf_block {
318330
bool keep_dst;
319331
unsigned int offloadcnt; /* Number of oddloaded filters */
320332
unsigned int nooffloaddevcnt; /* Number of devs unable to do offload */
333+
struct {
334+
struct tcf_chain *chain;
335+
struct list_head filter_chain_list;
336+
} chain0;
321337
};
322338

323339
static inline void tcf_block_offload_inc(struct tcf_block *block, u32 *flags)

include/uapi/linux/rtnetlink.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,13 @@ enum {
150150
RTM_NEWCACHEREPORT = 96,
151151
#define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT
152152

153+
RTM_NEWCHAIN = 100,
154+
#define RTM_NEWCHAIN RTM_NEWCHAIN
155+
RTM_DELCHAIN,
156+
#define RTM_DELCHAIN RTM_DELCHAIN
157+
RTM_GETCHAIN,
158+
#define RTM_GETCHAIN RTM_GETCHAIN
159+
153160
__RTM_MAX,
154161
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
155162
};

0 commit comments

Comments
 (0)