forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
....@@ -8,6 +8,7 @@
88 #include <linux/string.h>
99 #include <linux/rhashtable.h>
1010 #include <linux/netdevice.h>
11
+#include <linux/mutex.h>
1112 #include <net/net_namespace.h>
1213 #include <net/tc_act/tc_vlan.h>
1314
....@@ -25,6 +26,7 @@
2526 struct mlxsw_sp_fid *dummy_fid;
2627 struct rhashtable ruleset_ht;
2728 struct list_head rules;
29
+ struct mutex rules_lock; /* Protects rules list */
2830 struct {
2931 struct delayed_work dw;
3032 unsigned long interval; /* ms */
....@@ -38,23 +40,8 @@
3840 return acl->afk;
3941 }
4042
41
-struct mlxsw_sp_acl_block_binding {
42
- struct list_head list;
43
- struct net_device *dev;
44
- struct mlxsw_sp_port *mlxsw_sp_port;
45
- bool ingress;
46
-};
47
-
48
-struct mlxsw_sp_acl_block {
49
- struct list_head binding_list;
50
- struct mlxsw_sp_acl_ruleset *ruleset_zero;
51
- struct mlxsw_sp *mlxsw_sp;
52
- unsigned int rule_count;
53
- unsigned int disable_count;
54
-};
55
-
5643 struct mlxsw_sp_acl_ruleset_ht_key {
57
- struct mlxsw_sp_acl_block *block;
44
+ struct mlxsw_sp_flow_block *block;
5845 u32 chain_index;
5946 const struct mlxsw_sp_acl_profile_ops *ops;
6047 };
....@@ -64,7 +51,9 @@
6451 struct mlxsw_sp_acl_ruleset_ht_key ht_key;
6552 struct rhashtable rule_ht;
6653 unsigned int ref_count;
67
- unsigned long priv[0];
54
+ unsigned int min_prio;
55
+ unsigned int max_prio;
56
+ unsigned long priv[];
6857 /* priv has to be always the last item */
6958 };
7059
....@@ -77,7 +66,8 @@
7766 u64 last_used;
7867 u64 last_packets;
7968 u64 last_bytes;
80
- unsigned long priv[0];
69
+ u64 last_drops;
70
+ unsigned long priv[];
8171 /* priv has to be always the last item */
8272 };
8373
....@@ -100,44 +90,6 @@
10090 return mlxsw_sp->acl->dummy_fid;
10191 }
10292
103
-struct mlxsw_sp *mlxsw_sp_acl_block_mlxsw_sp(struct mlxsw_sp_acl_block *block)
104
-{
105
- return block->mlxsw_sp;
106
-}
107
-
108
-unsigned int mlxsw_sp_acl_block_rule_count(struct mlxsw_sp_acl_block *block)
109
-{
110
- return block ? block->rule_count : 0;
111
-}
112
-
113
-void mlxsw_sp_acl_block_disable_inc(struct mlxsw_sp_acl_block *block)
114
-{
115
- if (block)
116
- block->disable_count++;
117
-}
118
-
119
-void mlxsw_sp_acl_block_disable_dec(struct mlxsw_sp_acl_block *block)
120
-{
121
- if (block)
122
- block->disable_count--;
123
-}
124
-
125
-bool mlxsw_sp_acl_block_disabled(struct mlxsw_sp_acl_block *block)
126
-{
127
- return block->disable_count;
128
-}
129
-
130
-bool mlxsw_sp_acl_block_is_egress_bound(struct mlxsw_sp_acl_block *block)
131
-{
132
- struct mlxsw_sp_acl_block_binding *binding;
133
-
134
- list_for_each_entry(binding, &block->binding_list, list) {
135
- if (!binding->ingress)
136
- return true;
137
- }
138
- return false;
139
-}
140
-
14193 static bool
14294 mlxsw_sp_acl_ruleset_is_singular(const struct mlxsw_sp_acl_ruleset *ruleset)
14395 {
....@@ -145,10 +97,9 @@
14597 return ruleset->ref_count == 2;
14698 }
14799
148
-static int
149
-mlxsw_sp_acl_ruleset_bind(struct mlxsw_sp *mlxsw_sp,
150
- struct mlxsw_sp_acl_block *block,
151
- struct mlxsw_sp_acl_block_binding *binding)
100
+int mlxsw_sp_acl_ruleset_bind(struct mlxsw_sp *mlxsw_sp,
101
+ struct mlxsw_sp_flow_block *block,
102
+ struct mlxsw_sp_flow_block_binding *binding)
152103 {
153104 struct mlxsw_sp_acl_ruleset *ruleset = block->ruleset_zero;
154105 const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops;
....@@ -157,10 +108,9 @@
157108 binding->mlxsw_sp_port, binding->ingress);
158109 }
159110
160
-static void
161
-mlxsw_sp_acl_ruleset_unbind(struct mlxsw_sp *mlxsw_sp,
162
- struct mlxsw_sp_acl_block *block,
163
- struct mlxsw_sp_acl_block_binding *binding)
111
+void mlxsw_sp_acl_ruleset_unbind(struct mlxsw_sp *mlxsw_sp,
112
+ struct mlxsw_sp_flow_block *block,
113
+ struct mlxsw_sp_flow_block_binding *binding)
164114 {
165115 struct mlxsw_sp_acl_ruleset *ruleset = block->ruleset_zero;
166116 const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops;
....@@ -169,17 +119,12 @@
169119 binding->mlxsw_sp_port, binding->ingress);
170120 }
171121
172
-static bool mlxsw_sp_acl_ruleset_block_bound(struct mlxsw_sp_acl_block *block)
173
-{
174
- return block->ruleset_zero;
175
-}
176
-
177122 static int
178123 mlxsw_sp_acl_ruleset_block_bind(struct mlxsw_sp *mlxsw_sp,
179124 struct mlxsw_sp_acl_ruleset *ruleset,
180
- struct mlxsw_sp_acl_block *block)
125
+ struct mlxsw_sp_flow_block *block)
181126 {
182
- struct mlxsw_sp_acl_block_binding *binding;
127
+ struct mlxsw_sp_flow_block_binding *binding;
183128 int err;
184129
185130 block->ruleset_zero = ruleset;
....@@ -202,101 +147,18 @@
202147 static void
203148 mlxsw_sp_acl_ruleset_block_unbind(struct mlxsw_sp *mlxsw_sp,
204149 struct mlxsw_sp_acl_ruleset *ruleset,
205
- struct mlxsw_sp_acl_block *block)
150
+ struct mlxsw_sp_flow_block *block)
206151 {
207
- struct mlxsw_sp_acl_block_binding *binding;
152
+ struct mlxsw_sp_flow_block_binding *binding;
208153
209154 list_for_each_entry(binding, &block->binding_list, list)
210155 mlxsw_sp_acl_ruleset_unbind(mlxsw_sp, block, binding);
211156 block->ruleset_zero = NULL;
212157 }
213158
214
-struct mlxsw_sp_acl_block *mlxsw_sp_acl_block_create(struct mlxsw_sp *mlxsw_sp,
215
- struct net *net)
216
-{
217
- struct mlxsw_sp_acl_block *block;
218
-
219
- block = kzalloc(sizeof(*block), GFP_KERNEL);
220
- if (!block)
221
- return NULL;
222
- INIT_LIST_HEAD(&block->binding_list);
223
- block->mlxsw_sp = mlxsw_sp;
224
- return block;
225
-}
226
-
227
-void mlxsw_sp_acl_block_destroy(struct mlxsw_sp_acl_block *block)
228
-{
229
- WARN_ON(!list_empty(&block->binding_list));
230
- kfree(block);
231
-}
232
-
233
-static struct mlxsw_sp_acl_block_binding *
234
-mlxsw_sp_acl_block_lookup(struct mlxsw_sp_acl_block *block,
235
- struct mlxsw_sp_port *mlxsw_sp_port, bool ingress)
236
-{
237
- struct mlxsw_sp_acl_block_binding *binding;
238
-
239
- list_for_each_entry(binding, &block->binding_list, list)
240
- if (binding->mlxsw_sp_port == mlxsw_sp_port &&
241
- binding->ingress == ingress)
242
- return binding;
243
- return NULL;
244
-}
245
-
246
-int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp,
247
- struct mlxsw_sp_acl_block *block,
248
- struct mlxsw_sp_port *mlxsw_sp_port,
249
- bool ingress)
250
-{
251
- struct mlxsw_sp_acl_block_binding *binding;
252
- int err;
253
-
254
- if (WARN_ON(mlxsw_sp_acl_block_lookup(block, mlxsw_sp_port, ingress)))
255
- return -EEXIST;
256
-
257
- binding = kzalloc(sizeof(*binding), GFP_KERNEL);
258
- if (!binding)
259
- return -ENOMEM;
260
- binding->mlxsw_sp_port = mlxsw_sp_port;
261
- binding->ingress = ingress;
262
-
263
- if (mlxsw_sp_acl_ruleset_block_bound(block)) {
264
- err = mlxsw_sp_acl_ruleset_bind(mlxsw_sp, block, binding);
265
- if (err)
266
- goto err_ruleset_bind;
267
- }
268
-
269
- list_add(&binding->list, &block->binding_list);
270
- return 0;
271
-
272
-err_ruleset_bind:
273
- kfree(binding);
274
- return err;
275
-}
276
-
277
-int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp,
278
- struct mlxsw_sp_acl_block *block,
279
- struct mlxsw_sp_port *mlxsw_sp_port,
280
- bool ingress)
281
-{
282
- struct mlxsw_sp_acl_block_binding *binding;
283
-
284
- binding = mlxsw_sp_acl_block_lookup(block, mlxsw_sp_port, ingress);
285
- if (!binding)
286
- return -ENOENT;
287
-
288
- list_del(&binding->list);
289
-
290
- if (mlxsw_sp_acl_ruleset_block_bound(block))
291
- mlxsw_sp_acl_ruleset_unbind(mlxsw_sp, block, binding);
292
-
293
- kfree(binding);
294
- return 0;
295
-}
296
-
297159 static struct mlxsw_sp_acl_ruleset *
298160 mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp,
299
- struct mlxsw_sp_acl_block *block, u32 chain_index,
161
+ struct mlxsw_sp_flow_block *block, u32 chain_index,
300162 const struct mlxsw_sp_acl_profile_ops *ops,
301163 struct mlxsw_afk_element_usage *tmplt_elusage)
302164 {
....@@ -319,7 +181,8 @@
319181 goto err_rhashtable_init;
320182
321183 err = ops->ruleset_add(mlxsw_sp, &acl->tcam, ruleset->priv,
322
- tmplt_elusage);
184
+ tmplt_elusage, &ruleset->min_prio,
185
+ &ruleset->max_prio);
323186 if (err)
324187 goto err_ops_ruleset_add;
325188
....@@ -367,7 +230,7 @@
367230
368231 static struct mlxsw_sp_acl_ruleset *
369232 __mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp_acl *acl,
370
- struct mlxsw_sp_acl_block *block, u32 chain_index,
233
+ struct mlxsw_sp_flow_block *block, u32 chain_index,
371234 const struct mlxsw_sp_acl_profile_ops *ops)
372235 {
373236 struct mlxsw_sp_acl_ruleset_ht_key ht_key;
....@@ -382,7 +245,7 @@
382245
383246 struct mlxsw_sp_acl_ruleset *
384247 mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp,
385
- struct mlxsw_sp_acl_block *block, u32 chain_index,
248
+ struct mlxsw_sp_flow_block *block, u32 chain_index,
386249 enum mlxsw_sp_acl_profile profile)
387250 {
388251 const struct mlxsw_sp_acl_profile_ops *ops;
....@@ -400,7 +263,7 @@
400263
401264 struct mlxsw_sp_acl_ruleset *
402265 mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp,
403
- struct mlxsw_sp_acl_block *block, u32 chain_index,
266
+ struct mlxsw_sp_flow_block *block, u32 chain_index,
404267 enum mlxsw_sp_acl_profile profile,
405268 struct mlxsw_afk_element_usage *tmplt_elusage)
406269 {
....@@ -434,8 +297,17 @@
434297 return ops->ruleset_group_id(ruleset->priv);
435298 }
436299
300
+void mlxsw_sp_acl_ruleset_prio_get(struct mlxsw_sp_acl_ruleset *ruleset,
301
+ unsigned int *p_min_prio,
302
+ unsigned int *p_max_prio)
303
+{
304
+ *p_min_prio = ruleset->min_prio;
305
+ *p_max_prio = ruleset->max_prio;
306
+}
307
+
437308 struct mlxsw_sp_acl_rule_info *
438
-mlxsw_sp_acl_rulei_create(struct mlxsw_sp_acl *acl)
309
+mlxsw_sp_acl_rulei_create(struct mlxsw_sp_acl *acl,
310
+ struct mlxsw_afa_block *afa_block)
439311 {
440312 struct mlxsw_sp_acl_rule_info *rulei;
441313 int err;
....@@ -444,11 +316,17 @@
444316 if (!rulei)
445317 return ERR_PTR(-ENOMEM);
446318
319
+ if (afa_block) {
320
+ rulei->act_block = afa_block;
321
+ return rulei;
322
+ }
323
+
447324 rulei->act_block = mlxsw_afa_block_create(acl->mlxsw_sp->afa);
448325 if (IS_ERR(rulei->act_block)) {
449326 err = PTR_ERR(rulei->act_block);
450327 goto err_afa_block_create;
451328 }
329
+ rulei->action_created = 1;
452330 return rulei;
453331
454332 err_afa_block_create:
....@@ -458,7 +336,8 @@
458336
459337 void mlxsw_sp_acl_rulei_destroy(struct mlxsw_sp_acl_rule_info *rulei)
460338 {
461
- mlxsw_afa_block_destroy(rulei->act_block);
339
+ if (rulei->action_created)
340
+ mlxsw_afa_block_destroy(rulei->act_block);
462341 kfree(rulei);
463342 }
464343
....@@ -470,7 +349,7 @@
470349 void mlxsw_sp_acl_rulei_priority(struct mlxsw_sp_acl_rule_info *rulei,
471350 unsigned int priority)
472351 {
473
- rulei->priority = priority >> 16;
352
+ rulei->priority = priority;
474353 }
475354
476355 void mlxsw_sp_acl_rulei_keymask_u32(struct mlxsw_sp_acl_rule_info *rulei,
....@@ -506,9 +385,13 @@
506385 return mlxsw_afa_block_terminate(rulei->act_block);
507386 }
508387
509
-int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei)
388
+int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei,
389
+ bool ingress,
390
+ const struct flow_action_cookie *fa_cookie,
391
+ struct netlink_ext_ack *extack)
510392 {
511
- return mlxsw_afa_block_append_drop(rulei->act_block);
393
+ return mlxsw_afa_block_append_drop(rulei->act_block, ingress,
394
+ fa_cookie, extack);
512395 }
513396
514397 int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei)
....@@ -551,11 +434,11 @@
551434
552435 int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp,
553436 struct mlxsw_sp_acl_rule_info *rulei,
554
- struct mlxsw_sp_acl_block *block,
437
+ struct mlxsw_sp_flow_block *block,
555438 struct net_device *out_dev,
556439 struct netlink_ext_ack *extack)
557440 {
558
- struct mlxsw_sp_acl_block_binding *binding;
441
+ struct mlxsw_sp_flow_block_binding *binding;
559442 struct mlxsw_sp_port *in_port;
560443
561444 if (!list_is_singular(&block->binding_list)) {
....@@ -563,7 +446,7 @@
563446 return -EOPNOTSUPP;
564447 }
565448 binding = list_first_entry(&block->binding_list,
566
- struct mlxsw_sp_acl_block_binding, list);
449
+ struct mlxsw_sp_flow_block_binding, list);
567450 in_port = binding->mlxsw_sp_port;
568451
569452 return mlxsw_afa_block_append_mirror(rulei->act_block,
....@@ -580,7 +463,7 @@
580463 {
581464 u8 ethertype;
582465
583
- if (action == TCA_VLAN_ACT_MODIFY) {
466
+ if (action == FLOW_ACTION_VLAN_MANGLE) {
584467 switch (proto) {
585468 case ETH_P_8021Q:
586469 ethertype = 0;
....@@ -605,12 +488,197 @@
605488 }
606489 }
607490
491
+int mlxsw_sp_acl_rulei_act_priority(struct mlxsw_sp *mlxsw_sp,
492
+ struct mlxsw_sp_acl_rule_info *rulei,
493
+ u32 prio, struct netlink_ext_ack *extack)
494
+{
495
+ /* Even though both Linux and Spectrum switches support 16 priorities,
496
+ * spectrum_qdisc only processes the first eight priomap elements, and
497
+ * the DCB and PFC features are tied to 8 priorities as well. Therefore
498
+ * bounce attempts to prioritize packets to higher priorities.
499
+ */
500
+ if (prio >= IEEE_8021QAZ_MAX_TCS) {
501
+ NL_SET_ERR_MSG_MOD(extack, "Only priorities 0..7 are supported");
502
+ return -EINVAL;
503
+ }
504
+ return mlxsw_afa_block_append_qos_switch_prio(rulei->act_block, prio,
505
+ extack);
506
+}
507
+
508
+enum mlxsw_sp_acl_mangle_field {
509
+ MLXSW_SP_ACL_MANGLE_FIELD_IP_DSFIELD,
510
+ MLXSW_SP_ACL_MANGLE_FIELD_IP_DSCP,
511
+ MLXSW_SP_ACL_MANGLE_FIELD_IP_ECN,
512
+ MLXSW_SP_ACL_MANGLE_FIELD_IP_SPORT,
513
+ MLXSW_SP_ACL_MANGLE_FIELD_IP_DPORT,
514
+};
515
+
516
+struct mlxsw_sp_acl_mangle_action {
517
+ enum flow_action_mangle_base htype;
518
+ /* Offset is u32-aligned. */
519
+ u32 offset;
520
+ /* Mask bits are unset for the modified field. */
521
+ u32 mask;
522
+ /* Shift required to extract the set value. */
523
+ u32 shift;
524
+ enum mlxsw_sp_acl_mangle_field field;
525
+};
526
+
527
+#define MLXSW_SP_ACL_MANGLE_ACTION(_htype, _offset, _mask, _shift, _field) \
528
+ { \
529
+ .htype = _htype, \
530
+ .offset = _offset, \
531
+ .mask = _mask, \
532
+ .shift = _shift, \
533
+ .field = MLXSW_SP_ACL_MANGLE_FIELD_##_field, \
534
+ }
535
+
536
+#define MLXSW_SP_ACL_MANGLE_ACTION_IP4(_offset, _mask, _shift, _field) \
537
+ MLXSW_SP_ACL_MANGLE_ACTION(FLOW_ACT_MANGLE_HDR_TYPE_IP4, \
538
+ _offset, _mask, _shift, _field)
539
+
540
+#define MLXSW_SP_ACL_MANGLE_ACTION_IP6(_offset, _mask, _shift, _field) \
541
+ MLXSW_SP_ACL_MANGLE_ACTION(FLOW_ACT_MANGLE_HDR_TYPE_IP6, \
542
+ _offset, _mask, _shift, _field)
543
+
544
+#define MLXSW_SP_ACL_MANGLE_ACTION_TCP(_offset, _mask, _shift, _field) \
545
+ MLXSW_SP_ACL_MANGLE_ACTION(FLOW_ACT_MANGLE_HDR_TYPE_TCP, _offset, _mask, _shift, _field)
546
+
547
+#define MLXSW_SP_ACL_MANGLE_ACTION_UDP(_offset, _mask, _shift, _field) \
548
+ MLXSW_SP_ACL_MANGLE_ACTION(FLOW_ACT_MANGLE_HDR_TYPE_UDP, _offset, _mask, _shift, _field)
549
+
550
+static struct mlxsw_sp_acl_mangle_action mlxsw_sp_acl_mangle_actions[] = {
551
+ MLXSW_SP_ACL_MANGLE_ACTION_IP4(0, 0xff00ffff, 16, IP_DSFIELD),
552
+ MLXSW_SP_ACL_MANGLE_ACTION_IP4(0, 0xff03ffff, 18, IP_DSCP),
553
+ MLXSW_SP_ACL_MANGLE_ACTION_IP4(0, 0xfffcffff, 16, IP_ECN),
554
+
555
+ MLXSW_SP_ACL_MANGLE_ACTION_IP6(0, 0xf00fffff, 20, IP_DSFIELD),
556
+ MLXSW_SP_ACL_MANGLE_ACTION_IP6(0, 0xf03fffff, 22, IP_DSCP),
557
+ MLXSW_SP_ACL_MANGLE_ACTION_IP6(0, 0xffcfffff, 20, IP_ECN),
558
+
559
+ MLXSW_SP_ACL_MANGLE_ACTION_TCP(0, 0x0000ffff, 16, IP_SPORT),
560
+ MLXSW_SP_ACL_MANGLE_ACTION_TCP(0, 0xffff0000, 0, IP_DPORT),
561
+
562
+ MLXSW_SP_ACL_MANGLE_ACTION_UDP(0, 0x0000ffff, 16, IP_SPORT),
563
+ MLXSW_SP_ACL_MANGLE_ACTION_UDP(0, 0xffff0000, 0, IP_DPORT),
564
+};
565
+
566
+static int
567
+mlxsw_sp_acl_rulei_act_mangle_field(struct mlxsw_sp *mlxsw_sp,
568
+ struct mlxsw_sp_acl_rule_info *rulei,
569
+ struct mlxsw_sp_acl_mangle_action *mact,
570
+ u32 val, struct netlink_ext_ack *extack)
571
+{
572
+ switch (mact->field) {
573
+ case MLXSW_SP_ACL_MANGLE_FIELD_IP_DSFIELD:
574
+ return mlxsw_afa_block_append_qos_dsfield(rulei->act_block,
575
+ val, extack);
576
+ case MLXSW_SP_ACL_MANGLE_FIELD_IP_DSCP:
577
+ return mlxsw_afa_block_append_qos_dscp(rulei->act_block,
578
+ val, extack);
579
+ case MLXSW_SP_ACL_MANGLE_FIELD_IP_ECN:
580
+ return mlxsw_afa_block_append_qos_ecn(rulei->act_block,
581
+ val, extack);
582
+ default:
583
+ return -EOPNOTSUPP;
584
+ }
585
+}
586
+
587
+static int mlxsw_sp1_acl_rulei_act_mangle_field(struct mlxsw_sp *mlxsw_sp,
588
+ struct mlxsw_sp_acl_rule_info *rulei,
589
+ struct mlxsw_sp_acl_mangle_action *mact,
590
+ u32 val, struct netlink_ext_ack *extack)
591
+{
592
+ int err;
593
+
594
+ err = mlxsw_sp_acl_rulei_act_mangle_field(mlxsw_sp, rulei, mact, val, extack);
595
+ if (err != -EOPNOTSUPP)
596
+ return err;
597
+
598
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported mangle field");
599
+ return err;
600
+}
601
+
602
+static int mlxsw_sp2_acl_rulei_act_mangle_field(struct mlxsw_sp *mlxsw_sp,
603
+ struct mlxsw_sp_acl_rule_info *rulei,
604
+ struct mlxsw_sp_acl_mangle_action *mact,
605
+ u32 val, struct netlink_ext_ack *extack)
606
+{
607
+ int err;
608
+
609
+ err = mlxsw_sp_acl_rulei_act_mangle_field(mlxsw_sp, rulei, mact, val, extack);
610
+ if (err != -EOPNOTSUPP)
611
+ return err;
612
+
613
+ switch (mact->field) {
614
+ case MLXSW_SP_ACL_MANGLE_FIELD_IP_SPORT:
615
+ return mlxsw_afa_block_append_l4port(rulei->act_block, false, val, extack);
616
+ case MLXSW_SP_ACL_MANGLE_FIELD_IP_DPORT:
617
+ return mlxsw_afa_block_append_l4port(rulei->act_block, true, val, extack);
618
+ default:
619
+ break;
620
+ }
621
+
622
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported mangle field");
623
+ return err;
624
+}
625
+
626
+int mlxsw_sp_acl_rulei_act_mangle(struct mlxsw_sp *mlxsw_sp,
627
+ struct mlxsw_sp_acl_rule_info *rulei,
628
+ enum flow_action_mangle_base htype,
629
+ u32 offset, u32 mask, u32 val,
630
+ struct netlink_ext_ack *extack)
631
+{
632
+ const struct mlxsw_sp_acl_rulei_ops *acl_rulei_ops = mlxsw_sp->acl_rulei_ops;
633
+ struct mlxsw_sp_acl_mangle_action *mact;
634
+ size_t i;
635
+
636
+ for (i = 0; i < ARRAY_SIZE(mlxsw_sp_acl_mangle_actions); ++i) {
637
+ mact = &mlxsw_sp_acl_mangle_actions[i];
638
+ if (mact->htype == htype &&
639
+ mact->offset == offset &&
640
+ mact->mask == mask) {
641
+ val >>= mact->shift;
642
+ return acl_rulei_ops->act_mangle_field(mlxsw_sp,
643
+ rulei, mact,
644
+ val, extack);
645
+ }
646
+ }
647
+
648
+ NL_SET_ERR_MSG_MOD(extack, "Unknown mangle field");
649
+ return -EINVAL;
650
+}
651
+
652
+int mlxsw_sp_acl_rulei_act_police(struct mlxsw_sp *mlxsw_sp,
653
+ struct mlxsw_sp_acl_rule_info *rulei,
654
+ u32 index, u64 rate_bytes_ps,
655
+ u32 burst, struct netlink_ext_ack *extack)
656
+{
657
+ int err;
658
+
659
+ err = mlxsw_afa_block_append_police(rulei->act_block, index,
660
+ rate_bytes_ps, burst,
661
+ &rulei->policer_index, extack);
662
+ if (err)
663
+ return err;
664
+
665
+ rulei->policer_index_valid = true;
666
+
667
+ return 0;
668
+}
669
+
608670 int mlxsw_sp_acl_rulei_act_count(struct mlxsw_sp *mlxsw_sp,
609671 struct mlxsw_sp_acl_rule_info *rulei,
610672 struct netlink_ext_ack *extack)
611673 {
612
- return mlxsw_afa_block_append_counter(rulei->act_block,
613
- &rulei->counter_index, extack);
674
+ int err;
675
+
676
+ err = mlxsw_afa_block_append_counter(rulei->act_block,
677
+ &rulei->counter_index, extack);
678
+ if (err)
679
+ return err;
680
+ rulei->counter_valid = true;
681
+ return 0;
614682 }
615683
616684 int mlxsw_sp_acl_rulei_act_fid_set(struct mlxsw_sp *mlxsw_sp,
....@@ -624,6 +692,7 @@
624692 mlxsw_sp_acl_rule_create(struct mlxsw_sp *mlxsw_sp,
625693 struct mlxsw_sp_acl_ruleset *ruleset,
626694 unsigned long cookie,
695
+ struct mlxsw_afa_block *afa_block,
627696 struct netlink_ext_ack *extack)
628697 {
629698 const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops;
....@@ -631,7 +700,7 @@
631700 int err;
632701
633702 mlxsw_sp_acl_ruleset_ref_inc(ruleset);
634
- rule = kzalloc(sizeof(*rule) + ops->rule_priv_size(mlxsw_sp),
703
+ rule = kzalloc(sizeof(*rule) + ops->rule_priv_size,
635704 GFP_KERNEL);
636705 if (!rule) {
637706 err = -ENOMEM;
....@@ -640,7 +709,7 @@
640709 rule->cookie = cookie;
641710 rule->ruleset = ruleset;
642711
643
- rule->rulei = mlxsw_sp_acl_rulei_create(mlxsw_sp->acl);
712
+ rule->rulei = mlxsw_sp_acl_rulei_create(mlxsw_sp->acl, afa_block);
644713 if (IS_ERR(rule->rulei)) {
645714 err = PTR_ERR(rule->rulei);
646715 goto err_rulei_create;
....@@ -670,6 +739,7 @@
670739 {
671740 struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
672741 const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops;
742
+ struct mlxsw_sp_flow_block *block = ruleset->ht_key.block;
673743 int err;
674744
675745 err = ops->rule_add(mlxsw_sp, ruleset->priv, rule->priv, rule->rulei);
....@@ -687,14 +757,17 @@
687757 * one, to be directly bound to device. The rest of the
688758 * rulesets are bound by "Goto action set".
689759 */
690
- err = mlxsw_sp_acl_ruleset_block_bind(mlxsw_sp, ruleset,
691
- ruleset->ht_key.block);
760
+ err = mlxsw_sp_acl_ruleset_block_bind(mlxsw_sp, ruleset, block);
692761 if (err)
693762 goto err_ruleset_block_bind;
694763 }
695764
765
+ mutex_lock(&mlxsw_sp->acl->rules_lock);
696766 list_add_tail(&rule->list, &mlxsw_sp->acl->rules);
697
- ruleset->ht_key.block->rule_count++;
767
+ mutex_unlock(&mlxsw_sp->acl->rules_lock);
768
+ block->rule_count++;
769
+ block->ingress_blocker_rule_count += rule->rulei->ingress_bind_blocker;
770
+ block->egress_blocker_rule_count += rule->rulei->egress_bind_blocker;
698771 return 0;
699772
700773 err_ruleset_block_bind:
....@@ -710,16 +783,34 @@
710783 {
711784 struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
712785 const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops;
786
+ struct mlxsw_sp_flow_block *block = ruleset->ht_key.block;
713787
714
- ruleset->ht_key.block->rule_count--;
788
+ block->egress_blocker_rule_count -= rule->rulei->egress_bind_blocker;
789
+ block->ingress_blocker_rule_count -= rule->rulei->ingress_bind_blocker;
790
+ block->rule_count--;
791
+ mutex_lock(&mlxsw_sp->acl->rules_lock);
715792 list_del(&rule->list);
793
+ mutex_unlock(&mlxsw_sp->acl->rules_lock);
716794 if (!ruleset->ht_key.chain_index &&
717795 mlxsw_sp_acl_ruleset_is_singular(ruleset))
718
- mlxsw_sp_acl_ruleset_block_unbind(mlxsw_sp, ruleset,
719
- ruleset->ht_key.block);
796
+ mlxsw_sp_acl_ruleset_block_unbind(mlxsw_sp, ruleset, block);
720797 rhashtable_remove_fast(&ruleset->rule_ht, &rule->ht_node,
721798 mlxsw_sp_acl_rule_ht_params);
722799 ops->rule_del(mlxsw_sp, rule->priv);
800
+}
801
+
802
+int mlxsw_sp_acl_rule_action_replace(struct mlxsw_sp *mlxsw_sp,
803
+ struct mlxsw_sp_acl_rule *rule,
804
+ struct mlxsw_afa_block *afa_block)
805
+{
806
+ struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
807
+ const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops;
808
+ struct mlxsw_sp_acl_rule_info *rulei;
809
+
810
+ rulei = mlxsw_sp_acl_rule_rulei(rule);
811
+ rulei->act_block = afa_block;
812
+
813
+ return ops->rule_action_replace(mlxsw_sp, rule->priv, rule->rulei);
723814 }
724815
725816 struct mlxsw_sp_acl_rule *
....@@ -758,19 +849,18 @@
758849 struct mlxsw_sp_acl_rule *rule;
759850 int err;
760851
761
- /* Protect internal structures from changes */
762
- rtnl_lock();
852
+ mutex_lock(&acl->rules_lock);
763853 list_for_each_entry(rule, &acl->rules, list) {
764854 err = mlxsw_sp_acl_rule_activity_update(acl->mlxsw_sp,
765855 rule);
766856 if (err)
767857 goto err_rule_update;
768858 }
769
- rtnl_unlock();
859
+ mutex_unlock(&acl->rules_lock);
770860 return 0;
771861
772862 err_rule_update:
773
- rtnl_unlock();
863
+ mutex_unlock(&acl->rules_lock);
774864 return err;
775865 }
776866
....@@ -782,7 +872,7 @@
782872 msecs_to_jiffies(interval));
783873 }
784874
785
-static void mlxsw_sp_acl_rul_activity_update_work(struct work_struct *work)
875
+static void mlxsw_sp_acl_rule_activity_update_work(struct work_struct *work)
786876 {
787877 struct mlxsw_sp_acl *acl = container_of(work, struct mlxsw_sp_acl,
788878 rule_activity_update.dw.work);
....@@ -797,26 +887,42 @@
797887
798888 int mlxsw_sp_acl_rule_get_stats(struct mlxsw_sp *mlxsw_sp,
799889 struct mlxsw_sp_acl_rule *rule,
800
- u64 *packets, u64 *bytes, u64 *last_use)
890
+ u64 *packets, u64 *bytes, u64 *drops,
891
+ u64 *last_use,
892
+ enum flow_action_hw_stats *used_hw_stats)
801893
802894 {
895
+ enum mlxsw_sp_policer_type type = MLXSW_SP_POLICER_TYPE_SINGLE_RATE;
803896 struct mlxsw_sp_acl_rule_info *rulei;
804
- u64 current_packets;
805
- u64 current_bytes;
897
+ u64 current_packets = 0;
898
+ u64 current_bytes = 0;
899
+ u64 current_drops = 0;
806900 int err;
807901
808902 rulei = mlxsw_sp_acl_rule_rulei(rule);
809
- err = mlxsw_sp_flow_counter_get(mlxsw_sp, rulei->counter_index,
810
- &current_packets, &current_bytes);
811
- if (err)
812
- return err;
813
-
903
+ if (rulei->counter_valid) {
904
+ err = mlxsw_sp_flow_counter_get(mlxsw_sp, rulei->counter_index,
905
+ &current_packets,
906
+ &current_bytes);
907
+ if (err)
908
+ return err;
909
+ *used_hw_stats = FLOW_ACTION_HW_STATS_IMMEDIATE;
910
+ }
911
+ if (rulei->policer_index_valid) {
912
+ err = mlxsw_sp_policer_drops_counter_get(mlxsw_sp, type,
913
+ rulei->policer_index,
914
+ &current_drops);
915
+ if (err)
916
+ return err;
917
+ }
814918 *packets = current_packets - rule->last_packets;
815919 *bytes = current_bytes - rule->last_bytes;
920
+ *drops = current_drops - rule->last_drops;
816921 *last_use = rule->last_used;
817922
818923 rule->last_bytes = current_bytes;
819924 rule->last_packets = current_packets;
925
+ rule->last_drops = current_drops;
820926
821927 return 0;
822928 }
....@@ -855,18 +961,20 @@
855961 acl->dummy_fid = fid;
856962
857963 INIT_LIST_HEAD(&acl->rules);
964
+ mutex_init(&acl->rules_lock);
858965 err = mlxsw_sp_acl_tcam_init(mlxsw_sp, &acl->tcam);
859966 if (err)
860967 goto err_acl_ops_init;
861968
862969 /* Create the delayed work for the rule activity_update */
863970 INIT_DELAYED_WORK(&acl->rule_activity_update.dw,
864
- mlxsw_sp_acl_rul_activity_update_work);
971
+ mlxsw_sp_acl_rule_activity_update_work);
865972 acl->rule_activity_update.interval = MLXSW_SP_ACL_RULE_ACTIVITY_UPDATE_PERIOD_MS;
866973 mlxsw_core_schedule_dw(&acl->rule_activity_update.dw, 0);
867974 return 0;
868975
869976 err_acl_ops_init:
977
+ mutex_destroy(&acl->rules_lock);
870978 mlxsw_sp_fid_put(fid);
871979 err_fid_get:
872980 rhashtable_destroy(&acl->ruleset_ht);
....@@ -883,9 +991,34 @@
883991
884992 cancel_delayed_work_sync(&mlxsw_sp->acl->rule_activity_update.dw);
885993 mlxsw_sp_acl_tcam_fini(mlxsw_sp, &acl->tcam);
994
+ mutex_destroy(&acl->rules_lock);
886995 WARN_ON(!list_empty(&acl->rules));
887996 mlxsw_sp_fid_put(acl->dummy_fid);
888997 rhashtable_destroy(&acl->ruleset_ht);
889998 mlxsw_afk_destroy(acl->afk);
890999 kfree(acl);
8911000 }
1001
+
1002
+u32 mlxsw_sp_acl_region_rehash_intrvl_get(struct mlxsw_sp *mlxsw_sp)
1003
+{
1004
+ struct mlxsw_sp_acl *acl = mlxsw_sp->acl;
1005
+
1006
+ return mlxsw_sp_acl_tcam_vregion_rehash_intrvl_get(mlxsw_sp,
1007
+ &acl->tcam);
1008
+}
1009
+
1010
+int mlxsw_sp_acl_region_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp, u32 val)
1011
+{
1012
+ struct mlxsw_sp_acl *acl = mlxsw_sp->acl;
1013
+
1014
+ return mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(mlxsw_sp,
1015
+ &acl->tcam, val);
1016
+}
1017
+
1018
+struct mlxsw_sp_acl_rulei_ops mlxsw_sp1_acl_rulei_ops = {
1019
+ .act_mangle_field = mlxsw_sp1_acl_rulei_act_mangle_field,
1020
+};
1021
+
1022
+struct mlxsw_sp_acl_rulei_ops mlxsw_sp2_acl_rulei_ops = {
1023
+ .act_mangle_field = mlxsw_sp2_acl_rulei_act_mangle_field,
1024
+};