1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35#include <linux/kernel.h>
36#include <linux/types.h>
37#include <linux/slab.h>
38#include <linux/errno.h>
39#include <linux/rhashtable.h>
40#include <linux/list.h>
41
42#include "item.h"
43#include "trap.h"
44#include "core_acl_flex_actions.h"
45
46enum mlxsw_afa_set_type {
47 MLXSW_AFA_SET_TYPE_NEXT,
48 MLXSW_AFA_SET_TYPE_GOTO,
49};
50
51
52
53
54MLXSW_ITEM32(afa, set, type, 0xA0, 28, 4);
55
56
57
58
59MLXSW_ITEM32(afa, set, next_action_set_ptr, 0xA4, 0, 24);
60
61
62
63
64
65
66MLXSW_ITEM32(afa, set, goto_g, 0xA4, 29, 1);
67
68enum mlxsw_afa_set_goto_binding_cmd {
69
70 MLXSW_AFA_SET_GOTO_BINDING_CMD_NONE,
71
72 MLXSW_AFA_SET_GOTO_BINDING_CMD_JUMP,
73
74 MLXSW_AFA_SET_GOTO_BINDING_CMD_TERM = 4,
75};
76
77
78MLXSW_ITEM32(afa, set, goto_binding_cmd, 0xA4, 24, 3);
79
80
81
82
83
84MLXSW_ITEM32(afa, set, goto_next_binding, 0xA4, 0, 16);
85
86
87
88
89MLXSW_ITEM32(afa, all, action_type, 0x00, 24, 6);
90
91struct mlxsw_afa {
92 unsigned int max_acts_per_set;
93 const struct mlxsw_afa_ops *ops;
94 void *ops_priv;
95 struct rhashtable set_ht;
96 struct rhashtable fwd_entry_ht;
97};
98
99#define MLXSW_AFA_SET_LEN 0xA8
100
101struct mlxsw_afa_set_ht_key {
102 char enc_actions[MLXSW_AFA_SET_LEN];
103 bool is_first;
104};
105
106
107
108
109
110
111
112
113struct mlxsw_afa_set {
114 struct rhash_head ht_node;
115 struct mlxsw_afa_set_ht_key ht_key;
116 u32 kvdl_index;
117 bool shared;
118
119
120 unsigned int ref_count;
121 struct mlxsw_afa_set *next;
122 struct mlxsw_afa_set *prev;
123
124
125
126
127
128};
129
130static const struct rhashtable_params mlxsw_afa_set_ht_params = {
131 .key_len = sizeof(struct mlxsw_afa_set_ht_key),
132 .key_offset = offsetof(struct mlxsw_afa_set, ht_key),
133 .head_offset = offsetof(struct mlxsw_afa_set, ht_node),
134 .automatic_shrinking = true,
135};
136
137struct mlxsw_afa_fwd_entry_ht_key {
138 u8 local_port;
139};
140
141struct mlxsw_afa_fwd_entry {
142 struct rhash_head ht_node;
143 struct mlxsw_afa_fwd_entry_ht_key ht_key;
144 u32 kvdl_index;
145 unsigned int ref_count;
146};
147
148static const struct rhashtable_params mlxsw_afa_fwd_entry_ht_params = {
149 .key_len = sizeof(struct mlxsw_afa_fwd_entry_ht_key),
150 .key_offset = offsetof(struct mlxsw_afa_fwd_entry, ht_key),
151 .head_offset = offsetof(struct mlxsw_afa_fwd_entry, ht_node),
152 .automatic_shrinking = true,
153};
154
155struct mlxsw_afa *mlxsw_afa_create(unsigned int max_acts_per_set,
156 const struct mlxsw_afa_ops *ops,
157 void *ops_priv)
158{
159 struct mlxsw_afa *mlxsw_afa;
160 int err;
161
162 mlxsw_afa = kzalloc(sizeof(*mlxsw_afa), GFP_KERNEL);
163 if (!mlxsw_afa)
164 return ERR_PTR(-ENOMEM);
165 err = rhashtable_init(&mlxsw_afa->set_ht, &mlxsw_afa_set_ht_params);
166 if (err)
167 goto err_set_rhashtable_init;
168 err = rhashtable_init(&mlxsw_afa->fwd_entry_ht,
169 &mlxsw_afa_fwd_entry_ht_params);
170 if (err)
171 goto err_fwd_entry_rhashtable_init;
172 mlxsw_afa->max_acts_per_set = max_acts_per_set;
173 mlxsw_afa->ops = ops;
174 mlxsw_afa->ops_priv = ops_priv;
175 return mlxsw_afa;
176
177err_fwd_entry_rhashtable_init:
178 rhashtable_destroy(&mlxsw_afa->set_ht);
179err_set_rhashtable_init:
180 kfree(mlxsw_afa);
181 return ERR_PTR(err);
182}
183EXPORT_SYMBOL(mlxsw_afa_create);
184
185void mlxsw_afa_destroy(struct mlxsw_afa *mlxsw_afa)
186{
187 rhashtable_destroy(&mlxsw_afa->fwd_entry_ht);
188 rhashtable_destroy(&mlxsw_afa->set_ht);
189 kfree(mlxsw_afa);
190}
191EXPORT_SYMBOL(mlxsw_afa_destroy);
192
193static void mlxsw_afa_set_goto_set(struct mlxsw_afa_set *set,
194 enum mlxsw_afa_set_goto_binding_cmd cmd,
195 u16 group_id)
196{
197 char *actions = set->ht_key.enc_actions;
198
199 mlxsw_afa_set_type_set(actions, MLXSW_AFA_SET_TYPE_GOTO);
200 mlxsw_afa_set_goto_g_set(actions, true);
201 mlxsw_afa_set_goto_binding_cmd_set(actions, cmd);
202 mlxsw_afa_set_goto_next_binding_set(actions, group_id);
203}
204
205static void mlxsw_afa_set_next_set(struct mlxsw_afa_set *set,
206 u32 next_set_kvdl_index)
207{
208 char *actions = set->ht_key.enc_actions;
209
210 mlxsw_afa_set_type_set(actions, MLXSW_AFA_SET_TYPE_NEXT);
211 mlxsw_afa_set_next_action_set_ptr_set(actions, next_set_kvdl_index);
212}
213
214static struct mlxsw_afa_set *mlxsw_afa_set_create(bool is_first)
215{
216 struct mlxsw_afa_set *set;
217
218 set = kzalloc(sizeof(*set), GFP_KERNEL);
219 if (!set)
220 return NULL;
221
222 mlxsw_afa_set_goto_set(set, MLXSW_AFA_SET_GOTO_BINDING_CMD_TERM, 0);
223 set->ht_key.is_first = is_first;
224 set->ref_count = 1;
225 return set;
226}
227
228static void mlxsw_afa_set_destroy(struct mlxsw_afa_set *set)
229{
230 kfree(set);
231}
232
233static int mlxsw_afa_set_share(struct mlxsw_afa *mlxsw_afa,
234 struct mlxsw_afa_set *set)
235{
236 int err;
237
238 err = rhashtable_insert_fast(&mlxsw_afa->set_ht, &set->ht_node,
239 mlxsw_afa_set_ht_params);
240 if (err)
241 return err;
242 err = mlxsw_afa->ops->kvdl_set_add(mlxsw_afa->ops_priv,
243 &set->kvdl_index,
244 set->ht_key.enc_actions,
245 set->ht_key.is_first);
246 if (err)
247 goto err_kvdl_set_add;
248 set->shared = true;
249 set->prev = NULL;
250 return 0;
251
252err_kvdl_set_add:
253 rhashtable_remove_fast(&mlxsw_afa->set_ht, &set->ht_node,
254 mlxsw_afa_set_ht_params);
255 return err;
256}
257
258static void mlxsw_afa_set_unshare(struct mlxsw_afa *mlxsw_afa,
259 struct mlxsw_afa_set *set)
260{
261 mlxsw_afa->ops->kvdl_set_del(mlxsw_afa->ops_priv,
262 set->kvdl_index,
263 set->ht_key.is_first);
264 rhashtable_remove_fast(&mlxsw_afa->set_ht, &set->ht_node,
265 mlxsw_afa_set_ht_params);
266 set->shared = false;
267}
268
269static void mlxsw_afa_set_put(struct mlxsw_afa *mlxsw_afa,
270 struct mlxsw_afa_set *set)
271{
272 if (--set->ref_count)
273 return;
274 if (set->shared)
275 mlxsw_afa_set_unshare(mlxsw_afa, set);
276 mlxsw_afa_set_destroy(set);
277}
278
279static struct mlxsw_afa_set *mlxsw_afa_set_get(struct mlxsw_afa *mlxsw_afa,
280 struct mlxsw_afa_set *orig_set)
281{
282 struct mlxsw_afa_set *set;
283 int err;
284
285
286
287
288
289 set = rhashtable_lookup_fast(&mlxsw_afa->set_ht, &orig_set->ht_key,
290 mlxsw_afa_set_ht_params);
291 if (set) {
292 set->ref_count++;
293 mlxsw_afa_set_put(mlxsw_afa, orig_set);
294 } else {
295 set = orig_set;
296 err = mlxsw_afa_set_share(mlxsw_afa, set);
297 if (err)
298 return ERR_PTR(err);
299 }
300 return set;
301}
302
303
304
305
306
307struct mlxsw_afa_block {
308 struct mlxsw_afa *afa;
309 bool finished;
310 struct mlxsw_afa_set *first_set;
311 struct mlxsw_afa_set *cur_set;
312 unsigned int cur_act_index;
313 struct list_head fwd_entry_ref_list;
314};
315
316struct mlxsw_afa_block *mlxsw_afa_block_create(struct mlxsw_afa *mlxsw_afa)
317{
318 struct mlxsw_afa_block *block;
319
320 block = kzalloc(sizeof(*block), GFP_KERNEL);
321 if (!block)
322 return NULL;
323 INIT_LIST_HEAD(&block->fwd_entry_ref_list);
324 block->afa = mlxsw_afa;
325
326
327 block->first_set = mlxsw_afa_set_create(true);
328 if (!block->first_set)
329 goto err_first_set_create;
330 block->cur_set = block->first_set;
331 return block;
332
333err_first_set_create:
334 kfree(block);
335 return NULL;
336}
337EXPORT_SYMBOL(mlxsw_afa_block_create);
338
339static void mlxsw_afa_fwd_entry_refs_destroy(struct mlxsw_afa_block *block);
340
341void mlxsw_afa_block_destroy(struct mlxsw_afa_block *block)
342{
343 struct mlxsw_afa_set *set = block->first_set;
344 struct mlxsw_afa_set *next_set;
345
346 do {
347 next_set = set->next;
348 mlxsw_afa_set_put(block->afa, set);
349 set = next_set;
350 } while (set);
351 mlxsw_afa_fwd_entry_refs_destroy(block);
352 kfree(block);
353}
354EXPORT_SYMBOL(mlxsw_afa_block_destroy);
355
356int mlxsw_afa_block_commit(struct mlxsw_afa_block *block)
357{
358 struct mlxsw_afa_set *set = block->cur_set;
359 struct mlxsw_afa_set *prev_set;
360
361 block->cur_set = NULL;
362 block->finished = true;
363
364
365
366
367
368
369 do {
370 prev_set = set->prev;
371 set = mlxsw_afa_set_get(block->afa, set);
372 if (IS_ERR(set))
373
374
375
376
377 return PTR_ERR(set);
378 if (prev_set) {
379 prev_set->next = set;
380 mlxsw_afa_set_next_set(prev_set, set->kvdl_index);
381 set = prev_set;
382 }
383 } while (prev_set);
384
385 block->first_set = set;
386 return 0;
387}
388EXPORT_SYMBOL(mlxsw_afa_block_commit);
389
390char *mlxsw_afa_block_first_set(struct mlxsw_afa_block *block)
391{
392 return block->first_set->ht_key.enc_actions;
393}
394EXPORT_SYMBOL(mlxsw_afa_block_first_set);
395
396u32 mlxsw_afa_block_first_set_kvdl_index(struct mlxsw_afa_block *block)
397{
398 return block->first_set->kvdl_index;
399}
400EXPORT_SYMBOL(mlxsw_afa_block_first_set_kvdl_index);
401
402void mlxsw_afa_block_continue(struct mlxsw_afa_block *block)
403{
404 if (WARN_ON(block->finished))
405 return;
406 mlxsw_afa_set_goto_set(block->cur_set,
407 MLXSW_AFA_SET_GOTO_BINDING_CMD_NONE, 0);
408 block->finished = true;
409}
410EXPORT_SYMBOL(mlxsw_afa_block_continue);
411
412void mlxsw_afa_block_jump(struct mlxsw_afa_block *block, u16 group_id)
413{
414 if (WARN_ON(block->finished))
415 return;
416 mlxsw_afa_set_goto_set(block->cur_set,
417 MLXSW_AFA_SET_GOTO_BINDING_CMD_JUMP, group_id);
418 block->finished = true;
419}
420EXPORT_SYMBOL(mlxsw_afa_block_jump);
421
422static struct mlxsw_afa_fwd_entry *
423mlxsw_afa_fwd_entry_create(struct mlxsw_afa *mlxsw_afa, u8 local_port)
424{
425 struct mlxsw_afa_fwd_entry *fwd_entry;
426 int err;
427
428 fwd_entry = kzalloc(sizeof(*fwd_entry), GFP_KERNEL);
429 if (!fwd_entry)
430 return ERR_PTR(-ENOMEM);
431 fwd_entry->ht_key.local_port = local_port;
432 fwd_entry->ref_count = 1;
433
434 err = rhashtable_insert_fast(&mlxsw_afa->fwd_entry_ht,
435 &fwd_entry->ht_node,
436 mlxsw_afa_fwd_entry_ht_params);
437 if (err)
438 goto err_rhashtable_insert;
439
440 err = mlxsw_afa->ops->kvdl_fwd_entry_add(mlxsw_afa->ops_priv,
441 &fwd_entry->kvdl_index,
442 local_port);
443 if (err)
444 goto err_kvdl_fwd_entry_add;
445 return fwd_entry;
446
447err_kvdl_fwd_entry_add:
448 rhashtable_remove_fast(&mlxsw_afa->fwd_entry_ht, &fwd_entry->ht_node,
449 mlxsw_afa_fwd_entry_ht_params);
450err_rhashtable_insert:
451 kfree(fwd_entry);
452 return ERR_PTR(err);
453}
454
455static void mlxsw_afa_fwd_entry_destroy(struct mlxsw_afa *mlxsw_afa,
456 struct mlxsw_afa_fwd_entry *fwd_entry)
457{
458 mlxsw_afa->ops->kvdl_fwd_entry_del(mlxsw_afa->ops_priv,
459 fwd_entry->kvdl_index);
460 rhashtable_remove_fast(&mlxsw_afa->fwd_entry_ht, &fwd_entry->ht_node,
461 mlxsw_afa_fwd_entry_ht_params);
462 kfree(fwd_entry);
463}
464
465static struct mlxsw_afa_fwd_entry *
466mlxsw_afa_fwd_entry_get(struct mlxsw_afa *mlxsw_afa, u8 local_port)
467{
468 struct mlxsw_afa_fwd_entry_ht_key ht_key = {0};
469 struct mlxsw_afa_fwd_entry *fwd_entry;
470
471 ht_key.local_port = local_port;
472 fwd_entry = rhashtable_lookup_fast(&mlxsw_afa->fwd_entry_ht, &ht_key,
473 mlxsw_afa_fwd_entry_ht_params);
474 if (fwd_entry) {
475 fwd_entry->ref_count++;
476 return fwd_entry;
477 }
478 return mlxsw_afa_fwd_entry_create(mlxsw_afa, local_port);
479}
480
481static void mlxsw_afa_fwd_entry_put(struct mlxsw_afa *mlxsw_afa,
482 struct mlxsw_afa_fwd_entry *fwd_entry)
483{
484 if (--fwd_entry->ref_count)
485 return;
486 mlxsw_afa_fwd_entry_destroy(mlxsw_afa, fwd_entry);
487}
488
489struct mlxsw_afa_fwd_entry_ref {
490 struct list_head list;
491 struct mlxsw_afa_fwd_entry *fwd_entry;
492};
493
494static struct mlxsw_afa_fwd_entry_ref *
495mlxsw_afa_fwd_entry_ref_create(struct mlxsw_afa_block *block, u8 local_port)
496{
497 struct mlxsw_afa_fwd_entry_ref *fwd_entry_ref;
498 struct mlxsw_afa_fwd_entry *fwd_entry;
499 int err;
500
501 fwd_entry_ref = kzalloc(sizeof(*fwd_entry_ref), GFP_KERNEL);
502 if (!fwd_entry_ref)
503 return ERR_PTR(-ENOMEM);
504 fwd_entry = mlxsw_afa_fwd_entry_get(block->afa, local_port);
505 if (IS_ERR(fwd_entry)) {
506 err = PTR_ERR(fwd_entry);
507 goto err_fwd_entry_get;
508 }
509 fwd_entry_ref->fwd_entry = fwd_entry;
510 list_add(&fwd_entry_ref->list, &block->fwd_entry_ref_list);
511 return fwd_entry_ref;
512
513err_fwd_entry_get:
514 kfree(fwd_entry_ref);
515 return ERR_PTR(err);
516}
517
518static void
519mlxsw_afa_fwd_entry_ref_destroy(struct mlxsw_afa_block *block,
520 struct mlxsw_afa_fwd_entry_ref *fwd_entry_ref)
521{
522 list_del(&fwd_entry_ref->list);
523 mlxsw_afa_fwd_entry_put(block->afa, fwd_entry_ref->fwd_entry);
524 kfree(fwd_entry_ref);
525}
526
527static void mlxsw_afa_fwd_entry_refs_destroy(struct mlxsw_afa_block *block)
528{
529 struct mlxsw_afa_fwd_entry_ref *fwd_entry_ref;
530 struct mlxsw_afa_fwd_entry_ref *tmp;
531
532 list_for_each_entry_safe(fwd_entry_ref, tmp,
533 &block->fwd_entry_ref_list, list)
534 mlxsw_afa_fwd_entry_ref_destroy(block, fwd_entry_ref);
535}
536
537#define MLXSW_AFA_ONE_ACTION_LEN 32
538#define MLXSW_AFA_PAYLOAD_OFFSET 4
539
540static char *mlxsw_afa_block_append_action(struct mlxsw_afa_block *block,
541 u8 action_code, u8 action_size)
542{
543 char *oneact;
544 char *actions;
545
546 if (WARN_ON(block->finished))
547 return NULL;
548 if (block->cur_act_index + action_size >
549 block->afa->max_acts_per_set) {
550 struct mlxsw_afa_set *set;
551
552
553
554
555 set = mlxsw_afa_set_create(false);
556 if (!set)
557 return NULL;
558 set->prev = block->cur_set;
559 block->cur_act_index = 0;
560 block->cur_set->next = set;
561 block->cur_set = set;
562 }
563
564 actions = block->cur_set->ht_key.enc_actions;
565 oneact = actions + block->cur_act_index * MLXSW_AFA_ONE_ACTION_LEN;
566 block->cur_act_index += action_size;
567 mlxsw_afa_all_action_type_set(oneact, action_code);
568 return oneact + MLXSW_AFA_PAYLOAD_OFFSET;
569}
570
571
572
573
574
575
576
577
578#define MLXSW_AFA_VLAN_CODE 0x02
579#define MLXSW_AFA_VLAN_SIZE 1
580
581enum mlxsw_afa_vlan_vlan_tag_cmd {
582 MLXSW_AFA_VLAN_VLAN_TAG_CMD_NOP,
583 MLXSW_AFA_VLAN_VLAN_TAG_CMD_PUSH_TAG,
584 MLXSW_AFA_VLAN_VLAN_TAG_CMD_POP_TAG,
585};
586
587enum mlxsw_afa_vlan_cmd {
588 MLXSW_AFA_VLAN_CMD_NOP,
589 MLXSW_AFA_VLAN_CMD_SET_OUTER,
590 MLXSW_AFA_VLAN_CMD_SET_INNER,
591 MLXSW_AFA_VLAN_CMD_COPY_OUTER_TO_INNER,
592 MLXSW_AFA_VLAN_CMD_COPY_INNER_TO_OUTER,
593 MLXSW_AFA_VLAN_CMD_SWAP,
594};
595
596
597
598
599MLXSW_ITEM32(afa, vlan, vlan_tag_cmd, 0x00, 29, 3);
600
601
602MLXSW_ITEM32(afa, vlan, vid_cmd, 0x04, 29, 3);
603
604
605MLXSW_ITEM32(afa, vlan, vid, 0x04, 0, 12);
606
607
608MLXSW_ITEM32(afa, vlan, ethertype_cmd, 0x08, 29, 3);
609
610
611
612
613MLXSW_ITEM32(afa, vlan, ethertype, 0x08, 24, 3);
614
615
616MLXSW_ITEM32(afa, vlan, pcp_cmd, 0x08, 13, 3);
617
618
619MLXSW_ITEM32(afa, vlan, pcp, 0x08, 8, 3);
620
621static inline void
622mlxsw_afa_vlan_pack(char *payload,
623 enum mlxsw_afa_vlan_vlan_tag_cmd vlan_tag_cmd,
624 enum mlxsw_afa_vlan_cmd vid_cmd, u16 vid,
625 enum mlxsw_afa_vlan_cmd pcp_cmd, u8 pcp,
626 enum mlxsw_afa_vlan_cmd ethertype_cmd, u8 ethertype)
627{
628 mlxsw_afa_vlan_vlan_tag_cmd_set(payload, vlan_tag_cmd);
629 mlxsw_afa_vlan_vid_cmd_set(payload, vid_cmd);
630 mlxsw_afa_vlan_vid_set(payload, vid);
631 mlxsw_afa_vlan_pcp_cmd_set(payload, pcp_cmd);
632 mlxsw_afa_vlan_pcp_set(payload, pcp);
633 mlxsw_afa_vlan_ethertype_cmd_set(payload, ethertype_cmd);
634 mlxsw_afa_vlan_ethertype_set(payload, ethertype);
635}
636
637int mlxsw_afa_block_append_vlan_modify(struct mlxsw_afa_block *block,
638 u16 vid, u8 pcp, u8 et)
639{
640 char *act = mlxsw_afa_block_append_action(block,
641 MLXSW_AFA_VLAN_CODE,
642 MLXSW_AFA_VLAN_SIZE);
643
644 if (!act)
645 return -ENOBUFS;
646 mlxsw_afa_vlan_pack(act, MLXSW_AFA_VLAN_VLAN_TAG_CMD_NOP,
647 MLXSW_AFA_VLAN_CMD_SET_OUTER, vid,
648 MLXSW_AFA_VLAN_CMD_SET_OUTER, pcp,
649 MLXSW_AFA_VLAN_CMD_SET_OUTER, et);
650 return 0;
651}
652EXPORT_SYMBOL(mlxsw_afa_block_append_vlan_modify);
653
654
655
656
657
658
659
660
661
662
663#define MLXSW_AFA_TRAPDISC_CODE 0x03
664#define MLXSW_AFA_TRAPDISC_SIZE 1
665
666enum mlxsw_afa_trapdisc_trap_action {
667 MLXSW_AFA_TRAPDISC_TRAP_ACTION_NOP = 0,
668 MLXSW_AFA_TRAPDISC_TRAP_ACTION_TRAP = 2,
669};
670
671
672
673
674MLXSW_ITEM32(afa, trapdisc, trap_action, 0x00, 24, 4);
675
676enum mlxsw_afa_trapdisc_forward_action {
677 MLXSW_AFA_TRAPDISC_FORWARD_ACTION_DISCARD = 3,
678};
679
680
681
682
683MLXSW_ITEM32(afa, trapdisc, forward_action, 0x00, 0, 4);
684
685
686
687
688MLXSW_ITEM32(afa, trapdisc, trap_id, 0x04, 0, 9);
689
690static inline void
691mlxsw_afa_trapdisc_pack(char *payload,
692 enum mlxsw_afa_trapdisc_trap_action trap_action,
693 enum mlxsw_afa_trapdisc_forward_action forward_action,
694 u16 trap_id)
695{
696 mlxsw_afa_trapdisc_trap_action_set(payload, trap_action);
697 mlxsw_afa_trapdisc_forward_action_set(payload, forward_action);
698 mlxsw_afa_trapdisc_trap_id_set(payload, trap_id);
699}
700
701int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block)
702{
703 char *act = mlxsw_afa_block_append_action(block,
704 MLXSW_AFA_TRAPDISC_CODE,
705 MLXSW_AFA_TRAPDISC_SIZE);
706
707 if (!act)
708 return -ENOBUFS;
709 mlxsw_afa_trapdisc_pack(act, MLXSW_AFA_TRAPDISC_TRAP_ACTION_NOP,
710 MLXSW_AFA_TRAPDISC_FORWARD_ACTION_DISCARD, 0);
711 return 0;
712}
713EXPORT_SYMBOL(mlxsw_afa_block_append_drop);
714
715int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block)
716{
717 char *act = mlxsw_afa_block_append_action(block,
718 MLXSW_AFA_TRAPDISC_CODE,
719 MLXSW_AFA_TRAPDISC_SIZE);
720
721 if (!act)
722 return -ENOBUFS;
723 mlxsw_afa_trapdisc_pack(act, MLXSW_AFA_TRAPDISC_TRAP_ACTION_TRAP,
724 MLXSW_AFA_TRAPDISC_FORWARD_ACTION_DISCARD,
725 MLXSW_TRAP_ID_ACL0);
726 return 0;
727}
728EXPORT_SYMBOL(mlxsw_afa_block_append_trap);
729
730
731
732
733
734
735
736#define MLXSW_AFA_FORWARD_CODE 0x07
737#define MLXSW_AFA_FORWARD_SIZE 1
738
739enum mlxsw_afa_forward_type {
740
741 MLXSW_AFA_FORWARD_TYPE_PBS,
742
743 MLXSW_AFA_FORWARD_TYPE_OUTPUT,
744};
745
746
747MLXSW_ITEM32(afa, forward, type, 0x00, 24, 2);
748
749
750
751
752
753MLXSW_ITEM32(afa, forward, pbs_ptr, 0x08, 0, 24);
754
755
756
757
758MLXSW_ITEM32(afa, forward, in_port, 0x0C, 0, 1);
759
760static inline void
761mlxsw_afa_forward_pack(char *payload, enum mlxsw_afa_forward_type type,
762 u32 pbs_ptr, bool in_port)
763{
764 mlxsw_afa_forward_type_set(payload, type);
765 mlxsw_afa_forward_pbs_ptr_set(payload, pbs_ptr);
766 mlxsw_afa_forward_in_port_set(payload, in_port);
767}
768
769int mlxsw_afa_block_append_fwd(struct mlxsw_afa_block *block,
770 u8 local_port, bool in_port)
771{
772 struct mlxsw_afa_fwd_entry_ref *fwd_entry_ref;
773 u32 kvdl_index;
774 char *act;
775 int err;
776
777 if (in_port)
778 return -EOPNOTSUPP;
779 fwd_entry_ref = mlxsw_afa_fwd_entry_ref_create(block, local_port);
780 if (IS_ERR(fwd_entry_ref))
781 return PTR_ERR(fwd_entry_ref);
782 kvdl_index = fwd_entry_ref->fwd_entry->kvdl_index;
783
784 act = mlxsw_afa_block_append_action(block, MLXSW_AFA_FORWARD_CODE,
785 MLXSW_AFA_FORWARD_SIZE);
786 if (!act) {
787 err = -ENOBUFS;
788 goto err_append_action;
789 }
790 mlxsw_afa_forward_pack(act, MLXSW_AFA_FORWARD_TYPE_PBS,
791 kvdl_index, in_port);
792 return 0;
793
794err_append_action:
795 mlxsw_afa_fwd_entry_ref_destroy(block, fwd_entry_ref);
796 return err;
797}
798EXPORT_SYMBOL(mlxsw_afa_block_append_fwd);
799
800
801
802
803
804
805
806#define MLXSW_AFA_POLCNT_CODE 0x08
807#define MLXSW_AFA_POLCNT_SIZE 1
808
809enum mlxsw_afa_polcnt_counter_set_type {
810
811 MLXSW_AFA_POLCNT_COUNTER_SET_TYPE_NO_COUNT = 0x00,
812
813 MLXSW_AFA_POLCNT_COUNTER_SET_TYPE_PACKETS_BYTES = 0x03,
814
815 MLXSW_AFA_POLCNT_COUNTER_SET_TYPE_PACKETS = 0x05,
816};
817
818
819
820
821MLXSW_ITEM32(afa, polcnt, counter_set_type, 0x04, 24, 8);
822
823
824
825
826MLXSW_ITEM32(afa, polcnt, counter_index, 0x04, 0, 24);
827
828static inline void
829mlxsw_afa_polcnt_pack(char *payload,
830 enum mlxsw_afa_polcnt_counter_set_type set_type,
831 u32 counter_index)
832{
833 mlxsw_afa_polcnt_counter_set_type_set(payload, set_type);
834 mlxsw_afa_polcnt_counter_index_set(payload, counter_index);
835}
836
837int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block,
838 u32 counter_index)
839{
840 char *act = mlxsw_afa_block_append_action(block,
841 MLXSW_AFA_POLCNT_CODE,
842 MLXSW_AFA_POLCNT_SIZE);
843 if (!act)
844 return -ENOBUFS;
845 mlxsw_afa_polcnt_pack(act, MLXSW_AFA_POLCNT_COUNTER_SET_TYPE_PACKETS_BYTES,
846 counter_index);
847 return 0;
848}
849EXPORT_SYMBOL(mlxsw_afa_block_append_counter);
850
851
852
853
854
855
856
857#define MLXSW_AFA_VIRFWD_CODE 0x0E
858#define MLXSW_AFA_VIRFWD_SIZE 1
859
860enum mlxsw_afa_virfwd_fid_cmd {
861
862 MLXSW_AFA_VIRFWD_FID_CMD_NOOP,
863
864 MLXSW_AFA_VIRFWD_FID_CMD_SET,
865};
866
867
868MLXSW_ITEM32(afa, virfwd, fid_cmd, 0x08, 29, 3);
869
870
871
872
873MLXSW_ITEM32(afa, virfwd, fid, 0x08, 0, 16);
874
875static inline void mlxsw_afa_virfwd_pack(char *payload,
876 enum mlxsw_afa_virfwd_fid_cmd fid_cmd,
877 u16 fid)
878{
879 mlxsw_afa_virfwd_fid_cmd_set(payload, fid_cmd);
880 mlxsw_afa_virfwd_fid_set(payload, fid);
881}
882
883int mlxsw_afa_block_append_fid_set(struct mlxsw_afa_block *block, u16 fid)
884{
885 char *act = mlxsw_afa_block_append_action(block,
886 MLXSW_AFA_VIRFWD_CODE,
887 MLXSW_AFA_VIRFWD_SIZE);
888 if (!act)
889 return -ENOBUFS;
890 mlxsw_afa_virfwd_pack(act, MLXSW_AFA_VIRFWD_FID_CMD_SET, fid);
891 return 0;
892}
893EXPORT_SYMBOL(mlxsw_afa_block_append_fid_set);
894