Merge branch 'for-v5.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/ebieder...
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlxsw / core_acl_flex_actions.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
3
4 #include <linux/kernel.h>
5 #include <linux/types.h>
6 #include <linux/slab.h>
7 #include <linux/errno.h>
8 #include <linux/rhashtable.h>
9 #include <linux/list.h>
10 #include <linux/idr.h>
11 #include <linux/refcount.h>
12 #include <net/flow_offload.h>
13
14 #include "item.h"
15 #include "trap.h"
16 #include "core_acl_flex_actions.h"
17
18 enum mlxsw_afa_set_type {
19         MLXSW_AFA_SET_TYPE_NEXT,
20         MLXSW_AFA_SET_TYPE_GOTO,
21 };
22
23 /* afa_set_type
24  * Type of the record at the end of the action set.
25  */
26 MLXSW_ITEM32(afa, set, type, 0xA0, 28, 4);
27
28 /* afa_set_next_action_set_ptr
29  * A pointer to the next action set in the KVD Centralized database.
30  */
31 MLXSW_ITEM32(afa, set, next_action_set_ptr, 0xA4, 0, 24);
32
33 /* afa_set_goto_g
34  * group - When set, the binding is of an ACL group. When cleared,
35  * the binding is of an ACL.
36  * Must be set to 1 for Spectrum.
37  */
38 MLXSW_ITEM32(afa, set, goto_g, 0xA4, 29, 1);
39
40 enum mlxsw_afa_set_goto_binding_cmd {
41         /* continue go the next binding point */
42         MLXSW_AFA_SET_GOTO_BINDING_CMD_NONE,
43         /* jump to the next binding point no return */
44         MLXSW_AFA_SET_GOTO_BINDING_CMD_JUMP,
45         /* terminate the acl binding */
46         MLXSW_AFA_SET_GOTO_BINDING_CMD_TERM = 4,
47 };
48
49 /* afa_set_goto_binding_cmd */
50 MLXSW_ITEM32(afa, set, goto_binding_cmd, 0xA4, 24, 3);
51
52 /* afa_set_goto_next_binding
53  * ACL/ACL group identifier. If the g bit is set, this field should hold
54  * the acl_group_id, else it should hold the acl_id.
55  */
56 MLXSW_ITEM32(afa, set, goto_next_binding, 0xA4, 0, 16);
57
58 /* afa_all_action_type
59  * Action Type.
60  */
61 MLXSW_ITEM32(afa, all, action_type, 0x00, 24, 6);
62
63 struct mlxsw_afa {
64         unsigned int max_acts_per_set;
65         const struct mlxsw_afa_ops *ops;
66         void *ops_priv;
67         struct rhashtable set_ht;
68         struct rhashtable fwd_entry_ht;
69         struct rhashtable cookie_ht;
70         struct rhashtable policer_ht;
71         struct idr cookie_idr;
72         struct list_head policer_list;
73 };
74
75 #define MLXSW_AFA_SET_LEN 0xA8
76
77 struct mlxsw_afa_set_ht_key {
78         char enc_actions[MLXSW_AFA_SET_LEN]; /* Encoded set */
79         bool is_first;
80 };
81
82 /* Set structure holds one action set record. It contains up to three
83  * actions (depends on size of particular actions). The set is either
84  * put directly to a rule, or it is stored in KVD linear area.
85  * To prevent duplicate entries in KVD linear area, a hashtable is
86  * used to track sets that were previously inserted and may be shared.
87  */
88
89 struct mlxsw_afa_set {
90         struct rhash_head ht_node;
91         struct mlxsw_afa_set_ht_key ht_key;
92         u32 kvdl_index;
93         u8 shared:1, /* Inserted in hashtable (doesn't mean that
94                       * kvdl_index is valid).
95                       */
96            has_trap:1,
97            has_police:1;
98         unsigned int ref_count;
99         struct mlxsw_afa_set *next; /* Pointer to the next set. */
100         struct mlxsw_afa_set *prev; /* Pointer to the previous set,
101                                      * note that set may have multiple
102                                      * sets from multiple blocks
103                                      * pointing at it. This is only
104                                      * usable until commit.
105                                      */
106 };
107
108 static const struct rhashtable_params mlxsw_afa_set_ht_params = {
109         .key_len = sizeof(struct mlxsw_afa_set_ht_key),
110         .key_offset = offsetof(struct mlxsw_afa_set, ht_key),
111         .head_offset = offsetof(struct mlxsw_afa_set, ht_node),
112         .automatic_shrinking = true,
113 };
114
115 struct mlxsw_afa_fwd_entry_ht_key {
116         u8 local_port;
117 };
118
119 struct mlxsw_afa_fwd_entry {
120         struct rhash_head ht_node;
121         struct mlxsw_afa_fwd_entry_ht_key ht_key;
122         u32 kvdl_index;
123         unsigned int ref_count;
124 };
125
126 static const struct rhashtable_params mlxsw_afa_fwd_entry_ht_params = {
127         .key_len = sizeof(struct mlxsw_afa_fwd_entry_ht_key),
128         .key_offset = offsetof(struct mlxsw_afa_fwd_entry, ht_key),
129         .head_offset = offsetof(struct mlxsw_afa_fwd_entry, ht_node),
130         .automatic_shrinking = true,
131 };
132
133 struct mlxsw_afa_cookie {
134         struct rhash_head ht_node;
135         refcount_t ref_count;
136         struct rcu_head rcu;
137         u32 cookie_index;
138         struct flow_action_cookie fa_cookie;
139 };
140
141 static u32 mlxsw_afa_cookie_hash(const struct flow_action_cookie *fa_cookie,
142                                  u32 seed)
143 {
144         return jhash2((u32 *) fa_cookie->cookie,
145                       fa_cookie->cookie_len / sizeof(u32), seed);
146 }
147
148 static u32 mlxsw_afa_cookie_key_hashfn(const void *data, u32 len, u32 seed)
149 {
150         const struct flow_action_cookie *fa_cookie = data;
151
152         return mlxsw_afa_cookie_hash(fa_cookie, seed);
153 }
154
155 static u32 mlxsw_afa_cookie_obj_hashfn(const void *data, u32 len, u32 seed)
156 {
157         const struct mlxsw_afa_cookie *cookie = data;
158
159         return mlxsw_afa_cookie_hash(&cookie->fa_cookie, seed);
160 }
161
162 static int mlxsw_afa_cookie_obj_cmpfn(struct rhashtable_compare_arg *arg,
163                                       const void *obj)
164 {
165         const struct flow_action_cookie *fa_cookie = arg->key;
166         const struct mlxsw_afa_cookie *cookie = obj;
167
168         if (cookie->fa_cookie.cookie_len == fa_cookie->cookie_len)
169                 return memcmp(cookie->fa_cookie.cookie, fa_cookie->cookie,
170                               fa_cookie->cookie_len);
171         return 1;
172 }
173
174 static const struct rhashtable_params mlxsw_afa_cookie_ht_params = {
175         .head_offset = offsetof(struct mlxsw_afa_cookie, ht_node),
176         .hashfn = mlxsw_afa_cookie_key_hashfn,
177         .obj_hashfn = mlxsw_afa_cookie_obj_hashfn,
178         .obj_cmpfn = mlxsw_afa_cookie_obj_cmpfn,
179         .automatic_shrinking = true,
180 };
181
182 struct mlxsw_afa_policer {
183         struct rhash_head ht_node;
184         struct list_head list; /* Member of policer_list */
185         refcount_t ref_count;
186         u32 fa_index;
187         u16 policer_index;
188 };
189
190 static const struct rhashtable_params mlxsw_afa_policer_ht_params = {
191         .key_len = sizeof(u32),
192         .key_offset = offsetof(struct mlxsw_afa_policer, fa_index),
193         .head_offset = offsetof(struct mlxsw_afa_policer, ht_node),
194         .automatic_shrinking = true,
195 };
196
197 struct mlxsw_afa *mlxsw_afa_create(unsigned int max_acts_per_set,
198                                    const struct mlxsw_afa_ops *ops,
199                                    void *ops_priv)
200 {
201         struct mlxsw_afa *mlxsw_afa;
202         int err;
203
204         mlxsw_afa = kzalloc(sizeof(*mlxsw_afa), GFP_KERNEL);
205         if (!mlxsw_afa)
206                 return ERR_PTR(-ENOMEM);
207         err = rhashtable_init(&mlxsw_afa->set_ht, &mlxsw_afa_set_ht_params);
208         if (err)
209                 goto err_set_rhashtable_init;
210         err = rhashtable_init(&mlxsw_afa->fwd_entry_ht,
211                               &mlxsw_afa_fwd_entry_ht_params);
212         if (err)
213                 goto err_fwd_entry_rhashtable_init;
214         err = rhashtable_init(&mlxsw_afa->cookie_ht,
215                               &mlxsw_afa_cookie_ht_params);
216         if (err)
217                 goto err_cookie_rhashtable_init;
218         err = rhashtable_init(&mlxsw_afa->policer_ht,
219                               &mlxsw_afa_policer_ht_params);
220         if (err)
221                 goto err_policer_rhashtable_init;
222         idr_init(&mlxsw_afa->cookie_idr);
223         INIT_LIST_HEAD(&mlxsw_afa->policer_list);
224         mlxsw_afa->max_acts_per_set = max_acts_per_set;
225         mlxsw_afa->ops = ops;
226         mlxsw_afa->ops_priv = ops_priv;
227         return mlxsw_afa;
228
229 err_policer_rhashtable_init:
230         rhashtable_destroy(&mlxsw_afa->cookie_ht);
231 err_cookie_rhashtable_init:
232         rhashtable_destroy(&mlxsw_afa->fwd_entry_ht);
233 err_fwd_entry_rhashtable_init:
234         rhashtable_destroy(&mlxsw_afa->set_ht);
235 err_set_rhashtable_init:
236         kfree(mlxsw_afa);
237         return ERR_PTR(err);
238 }
239 EXPORT_SYMBOL(mlxsw_afa_create);
240
241 void mlxsw_afa_destroy(struct mlxsw_afa *mlxsw_afa)
242 {
243         WARN_ON(!list_empty(&mlxsw_afa->policer_list));
244         WARN_ON(!idr_is_empty(&mlxsw_afa->cookie_idr));
245         idr_destroy(&mlxsw_afa->cookie_idr);
246         rhashtable_destroy(&mlxsw_afa->policer_ht);
247         rhashtable_destroy(&mlxsw_afa->cookie_ht);
248         rhashtable_destroy(&mlxsw_afa->fwd_entry_ht);
249         rhashtable_destroy(&mlxsw_afa->set_ht);
250         kfree(mlxsw_afa);
251 }
252 EXPORT_SYMBOL(mlxsw_afa_destroy);
253
254 static void mlxsw_afa_set_goto_set(struct mlxsw_afa_set *set,
255                                    enum mlxsw_afa_set_goto_binding_cmd cmd,
256                                    u16 group_id)
257 {
258         char *actions = set->ht_key.enc_actions;
259
260         mlxsw_afa_set_type_set(actions, MLXSW_AFA_SET_TYPE_GOTO);
261         mlxsw_afa_set_goto_g_set(actions, true);
262         mlxsw_afa_set_goto_binding_cmd_set(actions, cmd);
263         mlxsw_afa_set_goto_next_binding_set(actions, group_id);
264 }
265
266 static void mlxsw_afa_set_next_set(struct mlxsw_afa_set *set,
267                                    u32 next_set_kvdl_index)
268 {
269         char *actions = set->ht_key.enc_actions;
270
271         mlxsw_afa_set_type_set(actions, MLXSW_AFA_SET_TYPE_NEXT);
272         mlxsw_afa_set_next_action_set_ptr_set(actions, next_set_kvdl_index);
273 }
274
275 static struct mlxsw_afa_set *mlxsw_afa_set_create(bool is_first)
276 {
277         struct mlxsw_afa_set *set;
278
279         set = kzalloc(sizeof(*set), GFP_KERNEL);
280         if (!set)
281                 return NULL;
282         /* Need to initialize the set to pass by default */
283         mlxsw_afa_set_goto_set(set, MLXSW_AFA_SET_GOTO_BINDING_CMD_TERM, 0);
284         set->ht_key.is_first = is_first;
285         set->ref_count = 1;
286         return set;
287 }
288
289 static void mlxsw_afa_set_destroy(struct mlxsw_afa_set *set)
290 {
291         kfree(set);
292 }
293
294 static int mlxsw_afa_set_share(struct mlxsw_afa *mlxsw_afa,
295                                struct mlxsw_afa_set *set)
296 {
297         int err;
298
299         err = rhashtable_insert_fast(&mlxsw_afa->set_ht, &set->ht_node,
300                                      mlxsw_afa_set_ht_params);
301         if (err)
302                 return err;
303         err = mlxsw_afa->ops->kvdl_set_add(mlxsw_afa->ops_priv,
304                                            &set->kvdl_index,
305                                            set->ht_key.enc_actions,
306                                            set->ht_key.is_first);
307         if (err)
308                 goto err_kvdl_set_add;
309         set->shared = true;
310         set->prev = NULL;
311         return 0;
312
313 err_kvdl_set_add:
314         rhashtable_remove_fast(&mlxsw_afa->set_ht, &set->ht_node,
315                                mlxsw_afa_set_ht_params);
316         return err;
317 }
318
319 static void mlxsw_afa_set_unshare(struct mlxsw_afa *mlxsw_afa,
320                                   struct mlxsw_afa_set *set)
321 {
322         mlxsw_afa->ops->kvdl_set_del(mlxsw_afa->ops_priv,
323                                      set->kvdl_index,
324                                      set->ht_key.is_first);
325         rhashtable_remove_fast(&mlxsw_afa->set_ht, &set->ht_node,
326                                mlxsw_afa_set_ht_params);
327         set->shared = false;
328 }
329
330 static void mlxsw_afa_set_put(struct mlxsw_afa *mlxsw_afa,
331                               struct mlxsw_afa_set *set)
332 {
333         if (--set->ref_count)
334                 return;
335         if (set->shared)
336                 mlxsw_afa_set_unshare(mlxsw_afa, set);
337         mlxsw_afa_set_destroy(set);
338 }
339
340 static struct mlxsw_afa_set *mlxsw_afa_set_get(struct mlxsw_afa *mlxsw_afa,
341                                                struct mlxsw_afa_set *orig_set)
342 {
343         struct mlxsw_afa_set *set;
344         int err;
345
346         /* There is a hashtable of sets maintained. If a set with the exact
347          * same encoding exists, we reuse it. Otherwise, the current set
348          * is shared by making it available to others using the hash table.
349          */
350         set = rhashtable_lookup_fast(&mlxsw_afa->set_ht, &orig_set->ht_key,
351                                      mlxsw_afa_set_ht_params);
352         if (set) {
353                 set->ref_count++;
354                 mlxsw_afa_set_put(mlxsw_afa, orig_set);
355         } else {
356                 set = orig_set;
357                 err = mlxsw_afa_set_share(mlxsw_afa, set);
358                 if (err)
359                         return ERR_PTR(err);
360         }
361         return set;
362 }
363
364 /* Block structure holds a list of action sets. One action block
365  * represents one chain of actions executed upon match of a rule.
366  */
367
368 struct mlxsw_afa_block {
369         struct mlxsw_afa *afa;
370         bool finished;
371         struct mlxsw_afa_set *first_set;
372         struct mlxsw_afa_set *cur_set;
373         unsigned int cur_act_index; /* In current set. */
374         struct list_head resource_list; /* List of resources held by actions
375                                          * in this block.
376                                          */
377 };
378
379 struct mlxsw_afa_resource {
380         struct list_head list;
381         void (*destructor)(struct mlxsw_afa_block *block,
382                            struct mlxsw_afa_resource *resource);
383 };
384
385 static void mlxsw_afa_resource_add(struct mlxsw_afa_block *block,
386                                    struct mlxsw_afa_resource *resource)
387 {
388         list_add(&resource->list, &block->resource_list);
389 }
390
391 static void mlxsw_afa_resource_del(struct mlxsw_afa_resource *resource)
392 {
393         list_del(&resource->list);
394 }
395
396 static void mlxsw_afa_resources_destroy(struct mlxsw_afa_block *block)
397 {
398         struct mlxsw_afa_resource *resource, *tmp;
399
400         list_for_each_entry_safe(resource, tmp, &block->resource_list, list) {
401                 resource->destructor(block, resource);
402         }
403 }
404
405 struct mlxsw_afa_block *mlxsw_afa_block_create(struct mlxsw_afa *mlxsw_afa)
406 {
407         struct mlxsw_afa_block *block;
408
409         block = kzalloc(sizeof(*block), GFP_KERNEL);
410         if (!block)
411                 return ERR_PTR(-ENOMEM);
412         INIT_LIST_HEAD(&block->resource_list);
413         block->afa = mlxsw_afa;
414
415         /* At least one action set is always present, so just create it here */
416         block->first_set = mlxsw_afa_set_create(true);
417         if (!block->first_set)
418                 goto err_first_set_create;
419
420         /* In case user instructs to have dummy first set, we leave it
421          * empty here and create another, real, set right away.
422          */
423         if (mlxsw_afa->ops->dummy_first_set) {
424                 block->cur_set = mlxsw_afa_set_create(false);
425                 if (!block->cur_set)
426                         goto err_second_set_create;
427                 block->cur_set->prev = block->first_set;
428                 block->first_set->next = block->cur_set;
429         } else {
430                 block->cur_set = block->first_set;
431         }
432
433         return block;
434
435 err_second_set_create:
436         mlxsw_afa_set_destroy(block->first_set);
437 err_first_set_create:
438         kfree(block);
439         return ERR_PTR(-ENOMEM);
440 }
441 EXPORT_SYMBOL(mlxsw_afa_block_create);
442
443 void mlxsw_afa_block_destroy(struct mlxsw_afa_block *block)
444 {
445         struct mlxsw_afa_set *set = block->first_set;
446         struct mlxsw_afa_set *next_set;
447
448         do {
449                 next_set = set->next;
450                 mlxsw_afa_set_put(block->afa, set);
451                 set = next_set;
452         } while (set);
453         mlxsw_afa_resources_destroy(block);
454         kfree(block);
455 }
456 EXPORT_SYMBOL(mlxsw_afa_block_destroy);
457
458 int mlxsw_afa_block_commit(struct mlxsw_afa_block *block)
459 {
460         struct mlxsw_afa_set *set = block->cur_set;
461         struct mlxsw_afa_set *prev_set;
462
463         block->cur_set = NULL;
464         block->finished = true;
465
466         /* Go over all linked sets starting from last
467          * and try to find existing set in the hash table.
468          * In case it is not there, assign a KVD linear index
469          * and insert it.
470          */
471         do {
472                 prev_set = set->prev;
473                 set = mlxsw_afa_set_get(block->afa, set);
474                 if (IS_ERR(set))
475                         /* No rollback is needed since the chain is
476                          * in consistent state and mlxsw_afa_block_destroy
477                          * will take care of putting it away.
478                          */
479                         return PTR_ERR(set);
480                 if (prev_set) {
481                         prev_set->next = set;
482                         mlxsw_afa_set_next_set(prev_set, set->kvdl_index);
483                         set = prev_set;
484                 }
485         } while (prev_set);
486
487         block->first_set = set;
488         return 0;
489 }
490 EXPORT_SYMBOL(mlxsw_afa_block_commit);
491
492 char *mlxsw_afa_block_first_set(struct mlxsw_afa_block *block)
493 {
494         return block->first_set->ht_key.enc_actions;
495 }
496 EXPORT_SYMBOL(mlxsw_afa_block_first_set);
497
498 char *mlxsw_afa_block_cur_set(struct mlxsw_afa_block *block)
499 {
500         return block->cur_set->ht_key.enc_actions;
501 }
502 EXPORT_SYMBOL(mlxsw_afa_block_cur_set);
503
504 u32 mlxsw_afa_block_first_kvdl_index(struct mlxsw_afa_block *block)
505 {
506         /* First set is never in KVD linear. So the first set
507          * with valid KVD linear index is always the second one.
508          */
509         if (WARN_ON(!block->first_set->next))
510                 return 0;
511         return block->first_set->next->kvdl_index;
512 }
513 EXPORT_SYMBOL(mlxsw_afa_block_first_kvdl_index);
514
515 int mlxsw_afa_block_activity_get(struct mlxsw_afa_block *block, bool *activity)
516 {
517         u32 kvdl_index = mlxsw_afa_block_first_kvdl_index(block);
518
519         return block->afa->ops->kvdl_set_activity_get(block->afa->ops_priv,
520                                                       kvdl_index, activity);
521 }
522 EXPORT_SYMBOL(mlxsw_afa_block_activity_get);
523
524 int mlxsw_afa_block_continue(struct mlxsw_afa_block *block)
525 {
526         if (block->finished)
527                 return -EINVAL;
528         mlxsw_afa_set_goto_set(block->cur_set,
529                                MLXSW_AFA_SET_GOTO_BINDING_CMD_NONE, 0);
530         block->finished = true;
531         return 0;
532 }
533 EXPORT_SYMBOL(mlxsw_afa_block_continue);
534
535 int mlxsw_afa_block_jump(struct mlxsw_afa_block *block, u16 group_id)
536 {
537         if (block->finished)
538                 return -EINVAL;
539         mlxsw_afa_set_goto_set(block->cur_set,
540                                MLXSW_AFA_SET_GOTO_BINDING_CMD_JUMP, group_id);
541         block->finished = true;
542         return 0;
543 }
544 EXPORT_SYMBOL(mlxsw_afa_block_jump);
545
546 int mlxsw_afa_block_terminate(struct mlxsw_afa_block *block)
547 {
548         if (block->finished)
549                 return -EINVAL;
550         mlxsw_afa_set_goto_set(block->cur_set,
551                                MLXSW_AFA_SET_GOTO_BINDING_CMD_TERM, 0);
552         block->finished = true;
553         return 0;
554 }
555 EXPORT_SYMBOL(mlxsw_afa_block_terminate);
556
557 static struct mlxsw_afa_fwd_entry *
558 mlxsw_afa_fwd_entry_create(struct mlxsw_afa *mlxsw_afa, u8 local_port)
559 {
560         struct mlxsw_afa_fwd_entry *fwd_entry;
561         int err;
562
563         fwd_entry = kzalloc(sizeof(*fwd_entry), GFP_KERNEL);
564         if (!fwd_entry)
565                 return ERR_PTR(-ENOMEM);
566         fwd_entry->ht_key.local_port = local_port;
567         fwd_entry->ref_count = 1;
568
569         err = rhashtable_insert_fast(&mlxsw_afa->fwd_entry_ht,
570                                      &fwd_entry->ht_node,
571                                      mlxsw_afa_fwd_entry_ht_params);
572         if (err)
573                 goto err_rhashtable_insert;
574
575         err = mlxsw_afa->ops->kvdl_fwd_entry_add(mlxsw_afa->ops_priv,
576                                                  &fwd_entry->kvdl_index,
577                                                  local_port);
578         if (err)
579                 goto err_kvdl_fwd_entry_add;
580         return fwd_entry;
581
582 err_kvdl_fwd_entry_add:
583         rhashtable_remove_fast(&mlxsw_afa->fwd_entry_ht, &fwd_entry->ht_node,
584                                mlxsw_afa_fwd_entry_ht_params);
585 err_rhashtable_insert:
586         kfree(fwd_entry);
587         return ERR_PTR(err);
588 }
589
590 static void mlxsw_afa_fwd_entry_destroy(struct mlxsw_afa *mlxsw_afa,
591                                         struct mlxsw_afa_fwd_entry *fwd_entry)
592 {
593         mlxsw_afa->ops->kvdl_fwd_entry_del(mlxsw_afa->ops_priv,
594                                            fwd_entry->kvdl_index);
595         rhashtable_remove_fast(&mlxsw_afa->fwd_entry_ht, &fwd_entry->ht_node,
596                                mlxsw_afa_fwd_entry_ht_params);
597         kfree(fwd_entry);
598 }
599
600 static struct mlxsw_afa_fwd_entry *
601 mlxsw_afa_fwd_entry_get(struct mlxsw_afa *mlxsw_afa, u8 local_port)
602 {
603         struct mlxsw_afa_fwd_entry_ht_key ht_key = {0};
604         struct mlxsw_afa_fwd_entry *fwd_entry;
605
606         ht_key.local_port = local_port;
607         fwd_entry = rhashtable_lookup_fast(&mlxsw_afa->fwd_entry_ht, &ht_key,
608                                            mlxsw_afa_fwd_entry_ht_params);
609         if (fwd_entry) {
610                 fwd_entry->ref_count++;
611                 return fwd_entry;
612         }
613         return mlxsw_afa_fwd_entry_create(mlxsw_afa, local_port);
614 }
615
616 static void mlxsw_afa_fwd_entry_put(struct mlxsw_afa *mlxsw_afa,
617                                     struct mlxsw_afa_fwd_entry *fwd_entry)
618 {
619         if (--fwd_entry->ref_count)
620                 return;
621         mlxsw_afa_fwd_entry_destroy(mlxsw_afa, fwd_entry);
622 }
623
624 struct mlxsw_afa_fwd_entry_ref {
625         struct mlxsw_afa_resource resource;
626         struct mlxsw_afa_fwd_entry *fwd_entry;
627 };
628
629 static void
630 mlxsw_afa_fwd_entry_ref_destroy(struct mlxsw_afa_block *block,
631                                 struct mlxsw_afa_fwd_entry_ref *fwd_entry_ref)
632 {
633         mlxsw_afa_resource_del(&fwd_entry_ref->resource);
634         mlxsw_afa_fwd_entry_put(block->afa, fwd_entry_ref->fwd_entry);
635         kfree(fwd_entry_ref);
636 }
637
638 static void
639 mlxsw_afa_fwd_entry_ref_destructor(struct mlxsw_afa_block *block,
640                                    struct mlxsw_afa_resource *resource)
641 {
642         struct mlxsw_afa_fwd_entry_ref *fwd_entry_ref;
643
644         fwd_entry_ref = container_of(resource, struct mlxsw_afa_fwd_entry_ref,
645                                      resource);
646         mlxsw_afa_fwd_entry_ref_destroy(block, fwd_entry_ref);
647 }
648
649 static struct mlxsw_afa_fwd_entry_ref *
650 mlxsw_afa_fwd_entry_ref_create(struct mlxsw_afa_block *block, u8 local_port)
651 {
652         struct mlxsw_afa_fwd_entry_ref *fwd_entry_ref;
653         struct mlxsw_afa_fwd_entry *fwd_entry;
654         int err;
655
656         fwd_entry_ref = kzalloc(sizeof(*fwd_entry_ref), GFP_KERNEL);
657         if (!fwd_entry_ref)
658                 return ERR_PTR(-ENOMEM);
659         fwd_entry = mlxsw_afa_fwd_entry_get(block->afa, local_port);
660         if (IS_ERR(fwd_entry)) {
661                 err = PTR_ERR(fwd_entry);
662                 goto err_fwd_entry_get;
663         }
664         fwd_entry_ref->fwd_entry = fwd_entry;
665         fwd_entry_ref->resource.destructor = mlxsw_afa_fwd_entry_ref_destructor;
666         mlxsw_afa_resource_add(block, &fwd_entry_ref->resource);
667         return fwd_entry_ref;
668
669 err_fwd_entry_get:
670         kfree(fwd_entry_ref);
671         return ERR_PTR(err);
672 }
673
674 struct mlxsw_afa_counter {
675         struct mlxsw_afa_resource resource;
676         u32 counter_index;
677 };
678
679 static void
680 mlxsw_afa_counter_destroy(struct mlxsw_afa_block *block,
681                           struct mlxsw_afa_counter *counter)
682 {
683         mlxsw_afa_resource_del(&counter->resource);
684         block->afa->ops->counter_index_put(block->afa->ops_priv,
685                                            counter->counter_index);
686         kfree(counter);
687 }
688
689 static void
690 mlxsw_afa_counter_destructor(struct mlxsw_afa_block *block,
691                              struct mlxsw_afa_resource *resource)
692 {
693         struct mlxsw_afa_counter *counter;
694
695         counter = container_of(resource, struct mlxsw_afa_counter, resource);
696         mlxsw_afa_counter_destroy(block, counter);
697 }
698
699 static struct mlxsw_afa_counter *
700 mlxsw_afa_counter_create(struct mlxsw_afa_block *block)
701 {
702         struct mlxsw_afa_counter *counter;
703         int err;
704
705         counter = kzalloc(sizeof(*counter), GFP_KERNEL);
706         if (!counter)
707                 return ERR_PTR(-ENOMEM);
708
709         err = block->afa->ops->counter_index_get(block->afa->ops_priv,
710                                                  &counter->counter_index);
711         if (err)
712                 goto err_counter_index_get;
713         counter->resource.destructor = mlxsw_afa_counter_destructor;
714         mlxsw_afa_resource_add(block, &counter->resource);
715         return counter;
716
717 err_counter_index_get:
718         kfree(counter);
719         return ERR_PTR(err);
720 }
721
722 /* 20 bits is a maximum that hardware can handle in trap with userdef action
723  * and carry along with the trapped packet.
724  */
725 #define MLXSW_AFA_COOKIE_INDEX_BITS 20
726 #define MLXSW_AFA_COOKIE_INDEX_MAX ((1 << MLXSW_AFA_COOKIE_INDEX_BITS) - 1)
727
728 static struct mlxsw_afa_cookie *
729 mlxsw_afa_cookie_create(struct mlxsw_afa *mlxsw_afa,
730                         const struct flow_action_cookie *fa_cookie)
731 {
732         struct mlxsw_afa_cookie *cookie;
733         u32 cookie_index;
734         int err;
735
736         cookie = kzalloc(sizeof(*cookie) + fa_cookie->cookie_len, GFP_KERNEL);
737         if (!cookie)
738                 return ERR_PTR(-ENOMEM);
739         refcount_set(&cookie->ref_count, 1);
740         memcpy(&cookie->fa_cookie, fa_cookie,
741                sizeof(*fa_cookie) + fa_cookie->cookie_len);
742
743         err = rhashtable_insert_fast(&mlxsw_afa->cookie_ht, &cookie->ht_node,
744                                      mlxsw_afa_cookie_ht_params);
745         if (err)
746                 goto err_rhashtable_insert;
747
748         /* Start cookie indexes with 1. Leave the 0 index unused. Packets
749          * that come from the HW which are not dropped by drop-with-cookie
750          * action are going to pass cookie_index 0 to lookup.
751          */
752         cookie_index = 1;
753         err = idr_alloc_u32(&mlxsw_afa->cookie_idr, cookie, &cookie_index,
754                             MLXSW_AFA_COOKIE_INDEX_MAX, GFP_KERNEL);
755         if (err)
756                 goto err_idr_alloc;
757         cookie->cookie_index = cookie_index;
758         return cookie;
759
760 err_idr_alloc:
761         rhashtable_remove_fast(&mlxsw_afa->cookie_ht, &cookie->ht_node,
762                                mlxsw_afa_cookie_ht_params);
763 err_rhashtable_insert:
764         kfree(cookie);
765         return ERR_PTR(err);
766 }
767
768 static void mlxsw_afa_cookie_destroy(struct mlxsw_afa *mlxsw_afa,
769                                      struct mlxsw_afa_cookie *cookie)
770 {
771         idr_remove(&mlxsw_afa->cookie_idr, cookie->cookie_index);
772         rhashtable_remove_fast(&mlxsw_afa->cookie_ht, &cookie->ht_node,
773                                mlxsw_afa_cookie_ht_params);
774         kfree_rcu(cookie, rcu);
775 }
776
777 static struct mlxsw_afa_cookie *
778 mlxsw_afa_cookie_get(struct mlxsw_afa *mlxsw_afa,
779                      const struct flow_action_cookie *fa_cookie)
780 {
781         struct mlxsw_afa_cookie *cookie;
782
783         cookie = rhashtable_lookup_fast(&mlxsw_afa->cookie_ht, fa_cookie,
784                                         mlxsw_afa_cookie_ht_params);
785         if (cookie) {
786                 refcount_inc(&cookie->ref_count);
787                 return cookie;
788         }
789         return mlxsw_afa_cookie_create(mlxsw_afa, fa_cookie);
790 }
791
792 static void mlxsw_afa_cookie_put(struct mlxsw_afa *mlxsw_afa,
793                                  struct mlxsw_afa_cookie *cookie)
794 {
795         if (!refcount_dec_and_test(&cookie->ref_count))
796                 return;
797         mlxsw_afa_cookie_destroy(mlxsw_afa, cookie);
798 }
799
800 /* RCU read lock must be held */
801 const struct flow_action_cookie *
802 mlxsw_afa_cookie_lookup(struct mlxsw_afa *mlxsw_afa, u32 cookie_index)
803 {
804         struct mlxsw_afa_cookie *cookie;
805
806         /* 0 index means no cookie */
807         if (!cookie_index)
808                 return NULL;
809         cookie = idr_find(&mlxsw_afa->cookie_idr, cookie_index);
810         if (!cookie)
811                 return NULL;
812         return &cookie->fa_cookie;
813 }
814 EXPORT_SYMBOL(mlxsw_afa_cookie_lookup);
815
816 struct mlxsw_afa_cookie_ref {
817         struct mlxsw_afa_resource resource;
818         struct mlxsw_afa_cookie *cookie;
819 };
820
821 static void
822 mlxsw_afa_cookie_ref_destroy(struct mlxsw_afa_block *block,
823                              struct mlxsw_afa_cookie_ref *cookie_ref)
824 {
825         mlxsw_afa_resource_del(&cookie_ref->resource);
826         mlxsw_afa_cookie_put(block->afa, cookie_ref->cookie);
827         kfree(cookie_ref);
828 }
829
830 static void
831 mlxsw_afa_cookie_ref_destructor(struct mlxsw_afa_block *block,
832                                 struct mlxsw_afa_resource *resource)
833 {
834         struct mlxsw_afa_cookie_ref *cookie_ref;
835
836         cookie_ref = container_of(resource, struct mlxsw_afa_cookie_ref,
837                                   resource);
838         mlxsw_afa_cookie_ref_destroy(block, cookie_ref);
839 }
840
841 static struct mlxsw_afa_cookie_ref *
842 mlxsw_afa_cookie_ref_create(struct mlxsw_afa_block *block,
843                             const struct flow_action_cookie *fa_cookie)
844 {
845         struct mlxsw_afa_cookie_ref *cookie_ref;
846         struct mlxsw_afa_cookie *cookie;
847         int err;
848
849         cookie_ref = kzalloc(sizeof(*cookie_ref), GFP_KERNEL);
850         if (!cookie_ref)
851                 return ERR_PTR(-ENOMEM);
852         cookie = mlxsw_afa_cookie_get(block->afa, fa_cookie);
853         if (IS_ERR(cookie)) {
854                 err = PTR_ERR(cookie);
855                 goto err_cookie_get;
856         }
857         cookie_ref->cookie = cookie;
858         cookie_ref->resource.destructor = mlxsw_afa_cookie_ref_destructor;
859         mlxsw_afa_resource_add(block, &cookie_ref->resource);
860         return cookie_ref;
861
862 err_cookie_get:
863         kfree(cookie_ref);
864         return ERR_PTR(err);
865 }
866
867 static struct mlxsw_afa_policer *
868 mlxsw_afa_policer_create(struct mlxsw_afa *mlxsw_afa, u32 fa_index,
869                          u64 rate_bytes_ps, u32 burst,
870                          struct netlink_ext_ack *extack)
871 {
872         struct mlxsw_afa_policer *policer;
873         int err;
874
875         policer = kzalloc(sizeof(*policer), GFP_KERNEL);
876         if (!policer)
877                 return ERR_PTR(-ENOMEM);
878
879         err = mlxsw_afa->ops->policer_add(mlxsw_afa->ops_priv, rate_bytes_ps,
880                                           burst, &policer->policer_index,
881                                           extack);
882         if (err)
883                 goto err_policer_add;
884
885         refcount_set(&policer->ref_count, 1);
886         policer->fa_index = fa_index;
887
888         err = rhashtable_insert_fast(&mlxsw_afa->policer_ht, &policer->ht_node,
889                                      mlxsw_afa_policer_ht_params);
890         if (err)
891                 goto err_rhashtable_insert;
892
893         list_add_tail(&policer->list, &mlxsw_afa->policer_list);
894
895         return policer;
896
897 err_rhashtable_insert:
898         mlxsw_afa->ops->policer_del(mlxsw_afa->ops_priv,
899                                     policer->policer_index);
900 err_policer_add:
901         kfree(policer);
902         return ERR_PTR(err);
903 }
904
905 static void mlxsw_afa_policer_destroy(struct mlxsw_afa *mlxsw_afa,
906                                       struct mlxsw_afa_policer *policer)
907 {
908         list_del(&policer->list);
909         rhashtable_remove_fast(&mlxsw_afa->policer_ht, &policer->ht_node,
910                                mlxsw_afa_policer_ht_params);
911         mlxsw_afa->ops->policer_del(mlxsw_afa->ops_priv,
912                                     policer->policer_index);
913         kfree(policer);
914 }
915
916 static struct mlxsw_afa_policer *
917 mlxsw_afa_policer_get(struct mlxsw_afa *mlxsw_afa, u32 fa_index,
918                       u64 rate_bytes_ps, u32 burst,
919                       struct netlink_ext_ack *extack)
920 {
921         struct mlxsw_afa_policer *policer;
922
923         policer = rhashtable_lookup_fast(&mlxsw_afa->policer_ht, &fa_index,
924                                          mlxsw_afa_policer_ht_params);
925         if (policer) {
926                 refcount_inc(&policer->ref_count);
927                 return policer;
928         }
929
930         return mlxsw_afa_policer_create(mlxsw_afa, fa_index, rate_bytes_ps,
931                                         burst, extack);
932 }
933
934 static void mlxsw_afa_policer_put(struct mlxsw_afa *mlxsw_afa,
935                                   struct mlxsw_afa_policer *policer)
936 {
937         if (!refcount_dec_and_test(&policer->ref_count))
938                 return;
939         mlxsw_afa_policer_destroy(mlxsw_afa, policer);
940 }
941
942 struct mlxsw_afa_policer_ref {
943         struct mlxsw_afa_resource resource;
944         struct mlxsw_afa_policer *policer;
945 };
946
947 static void
948 mlxsw_afa_policer_ref_destroy(struct mlxsw_afa_block *block,
949                               struct mlxsw_afa_policer_ref *policer_ref)
950 {
951         mlxsw_afa_resource_del(&policer_ref->resource);
952         mlxsw_afa_policer_put(block->afa, policer_ref->policer);
953         kfree(policer_ref);
954 }
955
956 static void
957 mlxsw_afa_policer_ref_destructor(struct mlxsw_afa_block *block,
958                                  struct mlxsw_afa_resource *resource)
959 {
960         struct mlxsw_afa_policer_ref *policer_ref;
961
962         policer_ref = container_of(resource, struct mlxsw_afa_policer_ref,
963                                    resource);
964         mlxsw_afa_policer_ref_destroy(block, policer_ref);
965 }
966
967 static struct mlxsw_afa_policer_ref *
968 mlxsw_afa_policer_ref_create(struct mlxsw_afa_block *block, u32 fa_index,
969                              u64 rate_bytes_ps, u32 burst,
970                              struct netlink_ext_ack *extack)
971 {
972         struct mlxsw_afa_policer_ref *policer_ref;
973         struct mlxsw_afa_policer *policer;
974         int err;
975
976         policer_ref = kzalloc(sizeof(*policer_ref), GFP_KERNEL);
977         if (!policer_ref)
978                 return ERR_PTR(-ENOMEM);
979
980         policer = mlxsw_afa_policer_get(block->afa, fa_index, rate_bytes_ps,
981                                         burst, extack);
982         if (IS_ERR(policer)) {
983                 err = PTR_ERR(policer);
984                 goto err_policer_get;
985         }
986
987         policer_ref->policer = policer;
988         policer_ref->resource.destructor = mlxsw_afa_policer_ref_destructor;
989         mlxsw_afa_resource_add(block, &policer_ref->resource);
990
991         return policer_ref;
992
993 err_policer_get:
994         kfree(policer_ref);
995         return ERR_PTR(err);
996 }
997
998 #define MLXSW_AFA_ONE_ACTION_LEN 32
999 #define MLXSW_AFA_PAYLOAD_OFFSET 4
1000
1001 enum mlxsw_afa_action_type {
1002         MLXSW_AFA_ACTION_TYPE_TRAP,
1003         MLXSW_AFA_ACTION_TYPE_POLICE,
1004         MLXSW_AFA_ACTION_TYPE_OTHER,
1005 };
1006
1007 static bool
1008 mlxsw_afa_block_need_split(const struct mlxsw_afa_block *block,
1009                            enum mlxsw_afa_action_type type)
1010 {
1011         struct mlxsw_afa_set *cur_set = block->cur_set;
1012
1013         /* Due to a hardware limitation, police action cannot be in the same
1014          * action set with MLXSW_AFA_TRAP_CODE or MLXSW_AFA_TRAPWU_CODE
1015          * actions. Work around this limitation by creating a new action set
1016          * and place the new action there.
1017          */
1018         return (cur_set->has_trap && type == MLXSW_AFA_ACTION_TYPE_POLICE) ||
1019                (cur_set->has_police && type == MLXSW_AFA_ACTION_TYPE_TRAP);
1020 }
1021
1022 static char *mlxsw_afa_block_append_action_ext(struct mlxsw_afa_block *block,
1023                                                u8 action_code, u8 action_size,
1024                                                enum mlxsw_afa_action_type type)
1025 {
1026         char *oneact;
1027         char *actions;
1028
1029         if (block->finished)
1030                 return ERR_PTR(-EINVAL);
1031         if (block->cur_act_index + action_size > block->afa->max_acts_per_set ||
1032             mlxsw_afa_block_need_split(block, type)) {
1033                 struct mlxsw_afa_set *set;
1034
1035                 /* The appended action won't fit into the current action set,
1036                  * so create a new set.
1037                  */
1038                 set = mlxsw_afa_set_create(false);
1039                 if (!set)
1040                         return ERR_PTR(-ENOBUFS);
1041                 set->prev = block->cur_set;
1042                 block->cur_act_index = 0;
1043                 block->cur_set->next = set;
1044                 block->cur_set = set;
1045         }
1046
1047         switch (type) {
1048         case MLXSW_AFA_ACTION_TYPE_TRAP:
1049                 block->cur_set->has_trap = true;
1050                 break;
1051         case MLXSW_AFA_ACTION_TYPE_POLICE:
1052                 block->cur_set->has_police = true;
1053                 break;
1054         default:
1055                 break;
1056         }
1057
1058         actions = block->cur_set->ht_key.enc_actions;
1059         oneact = actions + block->cur_act_index * MLXSW_AFA_ONE_ACTION_LEN;
1060         block->cur_act_index += action_size;
1061         mlxsw_afa_all_action_type_set(oneact, action_code);
1062         return oneact + MLXSW_AFA_PAYLOAD_OFFSET;
1063 }
1064
1065 static char *mlxsw_afa_block_append_action(struct mlxsw_afa_block *block,
1066                                            u8 action_code, u8 action_size)
1067 {
1068         return mlxsw_afa_block_append_action_ext(block, action_code,
1069                                                  action_size,
1070                                                  MLXSW_AFA_ACTION_TYPE_OTHER);
1071 }
1072
1073 /* VLAN Action
1074  * -----------
1075  * VLAN action is used for manipulating VLANs. It can be used to implement QinQ,
1076  * VLAN translation, change of PCP bits of the VLAN tag, push, pop as swap VLANs
1077  * and more.
1078  */
1079
1080 #define MLXSW_AFA_VLAN_CODE 0x02
1081 #define MLXSW_AFA_VLAN_SIZE 1
1082
1083 enum mlxsw_afa_vlan_vlan_tag_cmd {
1084         MLXSW_AFA_VLAN_VLAN_TAG_CMD_NOP,
1085         MLXSW_AFA_VLAN_VLAN_TAG_CMD_PUSH_TAG,
1086         MLXSW_AFA_VLAN_VLAN_TAG_CMD_POP_TAG,
1087 };
1088
1089 enum mlxsw_afa_vlan_cmd {
1090         MLXSW_AFA_VLAN_CMD_NOP,
1091         MLXSW_AFA_VLAN_CMD_SET_OUTER,
1092         MLXSW_AFA_VLAN_CMD_SET_INNER,
1093         MLXSW_AFA_VLAN_CMD_COPY_OUTER_TO_INNER,
1094         MLXSW_AFA_VLAN_CMD_COPY_INNER_TO_OUTER,
1095         MLXSW_AFA_VLAN_CMD_SWAP,
1096 };
1097
1098 /* afa_vlan_vlan_tag_cmd
1099  * Tag command: push, pop, nop VLAN header.
1100  */
1101 MLXSW_ITEM32(afa, vlan, vlan_tag_cmd, 0x00, 29, 3);
1102
1103 /* afa_vlan_vid_cmd */
1104 MLXSW_ITEM32(afa, vlan, vid_cmd, 0x04, 29, 3);
1105
1106 /* afa_vlan_vid */
1107 MLXSW_ITEM32(afa, vlan, vid, 0x04, 0, 12);
1108
1109 /* afa_vlan_ethertype_cmd */
1110 MLXSW_ITEM32(afa, vlan, ethertype_cmd, 0x08, 29, 3);
1111
1112 /* afa_vlan_ethertype
1113  * Index to EtherTypes in Switch VLAN EtherType Register (SVER).
1114  */
1115 MLXSW_ITEM32(afa, vlan, ethertype, 0x08, 24, 3);
1116
1117 /* afa_vlan_pcp_cmd */
1118 MLXSW_ITEM32(afa, vlan, pcp_cmd, 0x08, 13, 3);
1119
1120 /* afa_vlan_pcp */
1121 MLXSW_ITEM32(afa, vlan, pcp, 0x08, 8, 3);
1122
1123 static inline void
1124 mlxsw_afa_vlan_pack(char *payload,
1125                     enum mlxsw_afa_vlan_vlan_tag_cmd vlan_tag_cmd,
1126                     enum mlxsw_afa_vlan_cmd vid_cmd, u16 vid,
1127                     enum mlxsw_afa_vlan_cmd pcp_cmd, u8 pcp,
1128                     enum mlxsw_afa_vlan_cmd ethertype_cmd, u8 ethertype)
1129 {
1130         mlxsw_afa_vlan_vlan_tag_cmd_set(payload, vlan_tag_cmd);
1131         mlxsw_afa_vlan_vid_cmd_set(payload, vid_cmd);
1132         mlxsw_afa_vlan_vid_set(payload, vid);
1133         mlxsw_afa_vlan_pcp_cmd_set(payload, pcp_cmd);
1134         mlxsw_afa_vlan_pcp_set(payload, pcp);
1135         mlxsw_afa_vlan_ethertype_cmd_set(payload, ethertype_cmd);
1136         mlxsw_afa_vlan_ethertype_set(payload, ethertype);
1137 }
1138
1139 int mlxsw_afa_block_append_vlan_modify(struct mlxsw_afa_block *block,
1140                                        u16 vid, u8 pcp, u8 et,
1141                                        struct netlink_ext_ack *extack)
1142 {
1143         char *act = mlxsw_afa_block_append_action(block,
1144                                                   MLXSW_AFA_VLAN_CODE,
1145                                                   MLXSW_AFA_VLAN_SIZE);
1146
1147         if (IS_ERR(act)) {
1148                 NL_SET_ERR_MSG_MOD(extack, "Cannot append vlan_modify action");
1149                 return PTR_ERR(act);
1150         }
1151         mlxsw_afa_vlan_pack(act, MLXSW_AFA_VLAN_VLAN_TAG_CMD_NOP,
1152                             MLXSW_AFA_VLAN_CMD_SET_OUTER, vid,
1153                             MLXSW_AFA_VLAN_CMD_SET_OUTER, pcp,
1154                             MLXSW_AFA_VLAN_CMD_SET_OUTER, et);
1155         return 0;
1156 }
1157 EXPORT_SYMBOL(mlxsw_afa_block_append_vlan_modify);
1158
1159 /* Trap Action / Trap With Userdef Action
1160  * --------------------------------------
1161  * The Trap action enables trapping / mirroring packets to the CPU
1162  * as well as discarding packets.
1163  * The ACL Trap / Discard separates the forward/discard control from CPU
1164  * trap control. In addition, the Trap / Discard action enables activating
1165  * SPAN (port mirroring).
1166  *
1167  * The Trap with userdef action action has the same functionality as
1168  * the Trap action with addition of user defined value that can be set
1169  * and used by higher layer applications.
1170  */
1171
1172 #define MLXSW_AFA_TRAP_CODE 0x03
1173 #define MLXSW_AFA_TRAP_SIZE 1
1174
1175 #define MLXSW_AFA_TRAPWU_CODE 0x04
1176 #define MLXSW_AFA_TRAPWU_SIZE 2
1177
1178 enum mlxsw_afa_trap_trap_action {
1179         MLXSW_AFA_TRAP_TRAP_ACTION_NOP = 0,
1180         MLXSW_AFA_TRAP_TRAP_ACTION_TRAP = 2,
1181 };
1182
1183 /* afa_trap_trap_action
1184  * Trap Action.
1185  */
1186 MLXSW_ITEM32(afa, trap, trap_action, 0x00, 24, 4);
1187
1188 enum mlxsw_afa_trap_forward_action {
1189         MLXSW_AFA_TRAP_FORWARD_ACTION_FORWARD = 1,
1190         MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD = 3,
1191 };
1192
1193 /* afa_trap_forward_action
1194  * Forward Action.
1195  */
1196 MLXSW_ITEM32(afa, trap, forward_action, 0x00, 0, 4);
1197
1198 /* afa_trap_trap_id
1199  * Trap ID to configure.
1200  */
1201 MLXSW_ITEM32(afa, trap, trap_id, 0x04, 0, 9);
1202
1203 /* afa_trap_mirror_agent
1204  * Mirror agent.
1205  */
1206 MLXSW_ITEM32(afa, trap, mirror_agent, 0x08, 29, 3);
1207
1208 /* afa_trap_mirror_enable
1209  * Mirror enable.
1210  */
1211 MLXSW_ITEM32(afa, trap, mirror_enable, 0x08, 24, 1);
1212
1213 /* user_def_val
1214  * Value for the SW usage. Can be used to pass information of which
1215  * rule has caused a trap. This may be overwritten by later traps.
1216  * This field does a set on the packet's user_def_val only if this
1217  * is the first trap_id or if the trap_id has replaced the previous
1218  * packet's trap_id.
1219  */
1220 MLXSW_ITEM32(afa, trap, user_def_val, 0x0C, 0, 20);
1221
1222 static inline void
1223 mlxsw_afa_trap_pack(char *payload,
1224                     enum mlxsw_afa_trap_trap_action trap_action,
1225                     enum mlxsw_afa_trap_forward_action forward_action,
1226                     u16 trap_id)
1227 {
1228         mlxsw_afa_trap_trap_action_set(payload, trap_action);
1229         mlxsw_afa_trap_forward_action_set(payload, forward_action);
1230         mlxsw_afa_trap_trap_id_set(payload, trap_id);
1231 }
1232
1233 static inline void
1234 mlxsw_afa_trapwu_pack(char *payload,
1235                       enum mlxsw_afa_trap_trap_action trap_action,
1236                       enum mlxsw_afa_trap_forward_action forward_action,
1237                       u16 trap_id, u32 user_def_val)
1238 {
1239         mlxsw_afa_trap_pack(payload, trap_action, forward_action, trap_id);
1240         mlxsw_afa_trap_user_def_val_set(payload, user_def_val);
1241 }
1242
1243 static inline void
1244 mlxsw_afa_trap_mirror_pack(char *payload, bool mirror_enable,
1245                            u8 mirror_agent)
1246 {
1247         mlxsw_afa_trap_mirror_enable_set(payload, mirror_enable);
1248         mlxsw_afa_trap_mirror_agent_set(payload, mirror_agent);
1249 }
1250
1251 static char *mlxsw_afa_block_append_action_trap(struct mlxsw_afa_block *block,
1252                                                 u8 action_code, u8 action_size)
1253 {
1254         return mlxsw_afa_block_append_action_ext(block, action_code,
1255                                                  action_size,
1256                                                  MLXSW_AFA_ACTION_TYPE_TRAP);
1257 }
1258
1259 static int mlxsw_afa_block_append_drop_plain(struct mlxsw_afa_block *block,
1260                                              bool ingress)
1261 {
1262         char *act = mlxsw_afa_block_append_action_trap(block,
1263                                                        MLXSW_AFA_TRAP_CODE,
1264                                                        MLXSW_AFA_TRAP_SIZE);
1265
1266         if (IS_ERR(act))
1267                 return PTR_ERR(act);
1268         mlxsw_afa_trap_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_TRAP,
1269                             MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD,
1270                             ingress ? MLXSW_TRAP_ID_DISCARD_INGRESS_ACL :
1271                                       MLXSW_TRAP_ID_DISCARD_EGRESS_ACL);
1272         return 0;
1273 }
1274
1275 static int
1276 mlxsw_afa_block_append_drop_with_cookie(struct mlxsw_afa_block *block,
1277                                         bool ingress,
1278                                         const struct flow_action_cookie *fa_cookie,
1279                                         struct netlink_ext_ack *extack)
1280 {
1281         struct mlxsw_afa_cookie_ref *cookie_ref;
1282         u32 cookie_index;
1283         char *act;
1284         int err;
1285
1286         cookie_ref = mlxsw_afa_cookie_ref_create(block, fa_cookie);
1287         if (IS_ERR(cookie_ref)) {
1288                 NL_SET_ERR_MSG_MOD(extack, "Cannot create cookie for drop action");
1289                 return PTR_ERR(cookie_ref);
1290         }
1291         cookie_index = cookie_ref->cookie->cookie_index;
1292
1293         act = mlxsw_afa_block_append_action_trap(block, MLXSW_AFA_TRAPWU_CODE,
1294                                                  MLXSW_AFA_TRAPWU_SIZE);
1295         if (IS_ERR(act)) {
1296                 NL_SET_ERR_MSG_MOD(extack, "Cannot append drop with cookie action");
1297                 err = PTR_ERR(act);
1298                 goto err_append_action;
1299         }
1300         mlxsw_afa_trapwu_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_TRAP,
1301                               MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD,
1302                               ingress ? MLXSW_TRAP_ID_DISCARD_INGRESS_ACL :
1303                                         MLXSW_TRAP_ID_DISCARD_EGRESS_ACL,
1304                               cookie_index);
1305         return 0;
1306
1307 err_append_action:
1308         mlxsw_afa_cookie_ref_destroy(block, cookie_ref);
1309         return err;
1310 }
1311
1312 int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress,
1313                                 const struct flow_action_cookie *fa_cookie,
1314                                 struct netlink_ext_ack *extack)
1315 {
1316         return fa_cookie ?
1317                mlxsw_afa_block_append_drop_with_cookie(block, ingress,
1318                                                        fa_cookie, extack) :
1319                mlxsw_afa_block_append_drop_plain(block, ingress);
1320 }
1321 EXPORT_SYMBOL(mlxsw_afa_block_append_drop);
1322
1323 int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id)
1324 {
1325         char *act = mlxsw_afa_block_append_action_trap(block,
1326                                                        MLXSW_AFA_TRAP_CODE,
1327                                                        MLXSW_AFA_TRAP_SIZE);
1328
1329         if (IS_ERR(act))
1330                 return PTR_ERR(act);
1331         mlxsw_afa_trap_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_TRAP,
1332                             MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD, trap_id);
1333         return 0;
1334 }
1335 EXPORT_SYMBOL(mlxsw_afa_block_append_trap);
1336
1337 int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
1338                                             u16 trap_id)
1339 {
1340         char *act = mlxsw_afa_block_append_action_trap(block,
1341                                                        MLXSW_AFA_TRAP_CODE,
1342                                                        MLXSW_AFA_TRAP_SIZE);
1343
1344         if (IS_ERR(act))
1345                 return PTR_ERR(act);
1346         mlxsw_afa_trap_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_TRAP,
1347                             MLXSW_AFA_TRAP_FORWARD_ACTION_FORWARD, trap_id);
1348         return 0;
1349 }
1350 EXPORT_SYMBOL(mlxsw_afa_block_append_trap_and_forward);
1351
1352 struct mlxsw_afa_mirror {
1353         struct mlxsw_afa_resource resource;
1354         int span_id;
1355         u8 local_in_port;
1356         bool ingress;
1357 };
1358
1359 static void
1360 mlxsw_afa_mirror_destroy(struct mlxsw_afa_block *block,
1361                          struct mlxsw_afa_mirror *mirror)
1362 {
1363         mlxsw_afa_resource_del(&mirror->resource);
1364         block->afa->ops->mirror_del(block->afa->ops_priv,
1365                                     mirror->local_in_port,
1366                                     mirror->span_id,
1367                                     mirror->ingress);
1368         kfree(mirror);
1369 }
1370
1371 static void
1372 mlxsw_afa_mirror_destructor(struct mlxsw_afa_block *block,
1373                             struct mlxsw_afa_resource *resource)
1374 {
1375         struct mlxsw_afa_mirror *mirror;
1376
1377         mirror = container_of(resource, struct mlxsw_afa_mirror, resource);
1378         mlxsw_afa_mirror_destroy(block, mirror);
1379 }
1380
1381 static struct mlxsw_afa_mirror *
1382 mlxsw_afa_mirror_create(struct mlxsw_afa_block *block, u8 local_in_port,
1383                         const struct net_device *out_dev, bool ingress)
1384 {
1385         struct mlxsw_afa_mirror *mirror;
1386         int err;
1387
1388         mirror = kzalloc(sizeof(*mirror), GFP_KERNEL);
1389         if (!mirror)
1390                 return ERR_PTR(-ENOMEM);
1391
1392         err = block->afa->ops->mirror_add(block->afa->ops_priv,
1393                                           local_in_port, out_dev,
1394                                           ingress, &mirror->span_id);
1395         if (err)
1396                 goto err_mirror_add;
1397
1398         mirror->ingress = ingress;
1399         mirror->local_in_port = local_in_port;
1400         mirror->resource.destructor = mlxsw_afa_mirror_destructor;
1401         mlxsw_afa_resource_add(block, &mirror->resource);
1402         return mirror;
1403
1404 err_mirror_add:
1405         kfree(mirror);
1406         return ERR_PTR(err);
1407 }
1408
1409 static int
1410 mlxsw_afa_block_append_allocated_mirror(struct mlxsw_afa_block *block,
1411                                         u8 mirror_agent)
1412 {
1413         char *act = mlxsw_afa_block_append_action_trap(block,
1414                                                        MLXSW_AFA_TRAP_CODE,
1415                                                        MLXSW_AFA_TRAP_SIZE);
1416
1417         if (IS_ERR(act))
1418                 return PTR_ERR(act);
1419         mlxsw_afa_trap_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_NOP,
1420                             MLXSW_AFA_TRAP_FORWARD_ACTION_FORWARD, 0);
1421         mlxsw_afa_trap_mirror_pack(act, true, mirror_agent);
1422         return 0;
1423 }
1424
1425 int
1426 mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block, u8 local_in_port,
1427                               const struct net_device *out_dev, bool ingress,
1428                               struct netlink_ext_ack *extack)
1429 {
1430         struct mlxsw_afa_mirror *mirror;
1431         int err;
1432
1433         mirror = mlxsw_afa_mirror_create(block, local_in_port, out_dev,
1434                                          ingress);
1435         if (IS_ERR(mirror)) {
1436                 NL_SET_ERR_MSG_MOD(extack, "Cannot create mirror action");
1437                 return PTR_ERR(mirror);
1438         }
1439         err = mlxsw_afa_block_append_allocated_mirror(block, mirror->span_id);
1440         if (err) {
1441                 NL_SET_ERR_MSG_MOD(extack, "Cannot append mirror action");
1442                 goto err_append_allocated_mirror;
1443         }
1444
1445         return 0;
1446
1447 err_append_allocated_mirror:
1448         mlxsw_afa_mirror_destroy(block, mirror);
1449         return err;
1450 }
1451 EXPORT_SYMBOL(mlxsw_afa_block_append_mirror);
1452
1453 /* QoS Action
1454  * ----------
1455  * The QOS_ACTION is used for manipulating the QoS attributes of a packet. It
1456  * can be used to change the DCSP, ECN, Color and Switch Priority of the packet.
1457  * Note that PCP field can be changed using the VLAN action.
1458  */
1459
1460 #define MLXSW_AFA_QOS_CODE 0x06
1461 #define MLXSW_AFA_QOS_SIZE 1
1462
1463 enum mlxsw_afa_qos_ecn_cmd {
1464         /* Do nothing */
1465         MLXSW_AFA_QOS_ECN_CMD_NOP,
1466         /* Set ECN to afa_qos_ecn */
1467         MLXSW_AFA_QOS_ECN_CMD_SET,
1468 };
1469
1470 /* afa_qos_ecn_cmd
1471  */
1472 MLXSW_ITEM32(afa, qos, ecn_cmd, 0x04, 29, 3);
1473
1474 /* afa_qos_ecn
1475  * ECN value.
1476  */
1477 MLXSW_ITEM32(afa, qos, ecn, 0x04, 24, 2);
1478
1479 enum mlxsw_afa_qos_dscp_cmd {
1480         /* Do nothing */
1481         MLXSW_AFA_QOS_DSCP_CMD_NOP,
1482         /* Set DSCP 3 LSB bits according to dscp[2:0] */
1483         MLXSW_AFA_QOS_DSCP_CMD_SET_3LSB,
1484         /* Set DSCP 3 MSB bits according to dscp[5:3] */
1485         MLXSW_AFA_QOS_DSCP_CMD_SET_3MSB,
1486         /* Set DSCP 6 bits according to dscp[5:0] */
1487         MLXSW_AFA_QOS_DSCP_CMD_SET_ALL,
1488 };
1489
1490 /* afa_qos_dscp_cmd
1491  * DSCP command.
1492  */
1493 MLXSW_ITEM32(afa, qos, dscp_cmd, 0x04, 14, 2);
1494
1495 /* afa_qos_dscp
1496  * DSCP value.
1497  */
1498 MLXSW_ITEM32(afa, qos, dscp, 0x04, 0, 6);
1499
1500 enum mlxsw_afa_qos_switch_prio_cmd {
1501         /* Do nothing */
1502         MLXSW_AFA_QOS_SWITCH_PRIO_CMD_NOP,
1503         /* Set Switch Priority to afa_qos_switch_prio */
1504         MLXSW_AFA_QOS_SWITCH_PRIO_CMD_SET,
1505 };
1506
1507 /* afa_qos_switch_prio_cmd
1508  */
1509 MLXSW_ITEM32(afa, qos, switch_prio_cmd, 0x08, 14, 2);
1510
1511 /* afa_qos_switch_prio
1512  * Switch Priority.
1513  */
1514 MLXSW_ITEM32(afa, qos, switch_prio, 0x08, 0, 4);
1515
1516 enum mlxsw_afa_qos_dscp_rw {
1517         MLXSW_AFA_QOS_DSCP_RW_PRESERVE,
1518         MLXSW_AFA_QOS_DSCP_RW_SET,
1519         MLXSW_AFA_QOS_DSCP_RW_CLEAR,
1520 };
1521
1522 /* afa_qos_dscp_rw
1523  * DSCP Re-write Enable. Controlling the rewrite_enable for DSCP.
1524  */
1525 MLXSW_ITEM32(afa, qos, dscp_rw, 0x0C, 30, 2);
1526
1527 static inline void
1528 mlxsw_afa_qos_ecn_pack(char *payload,
1529                        enum mlxsw_afa_qos_ecn_cmd ecn_cmd, u8 ecn)
1530 {
1531         mlxsw_afa_qos_ecn_cmd_set(payload, ecn_cmd);
1532         mlxsw_afa_qos_ecn_set(payload, ecn);
1533 }
1534
1535 static inline void
1536 mlxsw_afa_qos_dscp_pack(char *payload,
1537                         enum mlxsw_afa_qos_dscp_cmd dscp_cmd, u8 dscp)
1538 {
1539         mlxsw_afa_qos_dscp_cmd_set(payload, dscp_cmd);
1540         mlxsw_afa_qos_dscp_set(payload, dscp);
1541 }
1542
1543 static inline void
1544 mlxsw_afa_qos_switch_prio_pack(char *payload,
1545                                enum mlxsw_afa_qos_switch_prio_cmd prio_cmd,
1546                                u8 prio)
1547 {
1548         mlxsw_afa_qos_switch_prio_cmd_set(payload, prio_cmd);
1549         mlxsw_afa_qos_switch_prio_set(payload, prio);
1550 }
1551
1552 static int __mlxsw_afa_block_append_qos_dsfield(struct mlxsw_afa_block *block,
1553                                                 bool set_dscp, u8 dscp,
1554                                                 bool set_ecn, u8 ecn,
1555                                                 struct netlink_ext_ack *extack)
1556 {
1557         char *act = mlxsw_afa_block_append_action(block,
1558                                                   MLXSW_AFA_QOS_CODE,
1559                                                   MLXSW_AFA_QOS_SIZE);
1560
1561         if (IS_ERR(act)) {
1562                 NL_SET_ERR_MSG_MOD(extack, "Cannot append QOS action");
1563                 return PTR_ERR(act);
1564         }
1565
1566         if (set_ecn)
1567                 mlxsw_afa_qos_ecn_pack(act, MLXSW_AFA_QOS_ECN_CMD_SET, ecn);
1568         if (set_dscp) {
1569                 mlxsw_afa_qos_dscp_pack(act, MLXSW_AFA_QOS_DSCP_CMD_SET_ALL,
1570                                         dscp);
1571                 mlxsw_afa_qos_dscp_rw_set(act, MLXSW_AFA_QOS_DSCP_RW_CLEAR);
1572         }
1573
1574         return 0;
1575 }
1576
1577 int mlxsw_afa_block_append_qos_dsfield(struct mlxsw_afa_block *block,
1578                                        u8 dsfield,
1579                                        struct netlink_ext_ack *extack)
1580 {
1581         return __mlxsw_afa_block_append_qos_dsfield(block,
1582                                                     true, dsfield >> 2,
1583                                                     true, dsfield & 0x03,
1584                                                     extack);
1585 }
1586 EXPORT_SYMBOL(mlxsw_afa_block_append_qos_dsfield);
1587
1588 int mlxsw_afa_block_append_qos_dscp(struct mlxsw_afa_block *block,
1589                                     u8 dscp, struct netlink_ext_ack *extack)
1590 {
1591         return __mlxsw_afa_block_append_qos_dsfield(block,
1592                                                     true, dscp,
1593                                                     false, 0,
1594                                                     extack);
1595 }
1596 EXPORT_SYMBOL(mlxsw_afa_block_append_qos_dscp);
1597
1598 int mlxsw_afa_block_append_qos_ecn(struct mlxsw_afa_block *block,
1599                                    u8 ecn, struct netlink_ext_ack *extack)
1600 {
1601         return __mlxsw_afa_block_append_qos_dsfield(block,
1602                                                     false, 0,
1603                                                     true, ecn,
1604                                                     extack);
1605 }
1606 EXPORT_SYMBOL(mlxsw_afa_block_append_qos_ecn);
1607
1608 int mlxsw_afa_block_append_qos_switch_prio(struct mlxsw_afa_block *block,
1609                                            u8 prio,
1610                                            struct netlink_ext_ack *extack)
1611 {
1612         char *act = mlxsw_afa_block_append_action(block,
1613                                                   MLXSW_AFA_QOS_CODE,
1614                                                   MLXSW_AFA_QOS_SIZE);
1615
1616         if (IS_ERR(act)) {
1617                 NL_SET_ERR_MSG_MOD(extack, "Cannot append QOS action");
1618                 return PTR_ERR(act);
1619         }
1620         mlxsw_afa_qos_switch_prio_pack(act, MLXSW_AFA_QOS_SWITCH_PRIO_CMD_SET,
1621                                        prio);
1622         return 0;
1623 }
1624 EXPORT_SYMBOL(mlxsw_afa_block_append_qos_switch_prio);
1625
1626 /* Forwarding Action
1627  * -----------------
1628  * Forwarding Action can be used to implement Policy Based Switching (PBS)
1629  * as well as OpenFlow related "Output" action.
1630  */
1631
1632 #define MLXSW_AFA_FORWARD_CODE 0x07
1633 #define MLXSW_AFA_FORWARD_SIZE 1
1634
1635 enum mlxsw_afa_forward_type {
1636         /* PBS, Policy Based Switching */
1637         MLXSW_AFA_FORWARD_TYPE_PBS,
1638         /* Output, OpenFlow output type */
1639         MLXSW_AFA_FORWARD_TYPE_OUTPUT,
1640 };
1641
1642 /* afa_forward_type */
1643 MLXSW_ITEM32(afa, forward, type, 0x00, 24, 2);
1644
1645 /* afa_forward_pbs_ptr
1646  * A pointer to the PBS entry configured by PPBS register.
1647  * Reserved when in_port is set.
1648  */
1649 MLXSW_ITEM32(afa, forward, pbs_ptr, 0x08, 0, 24);
1650
1651 /* afa_forward_in_port
1652  * Packet is forwarded back to the ingress port.
1653  */
1654 MLXSW_ITEM32(afa, forward, in_port, 0x0C, 0, 1);
1655
1656 static inline void
1657 mlxsw_afa_forward_pack(char *payload, enum mlxsw_afa_forward_type type,
1658                        u32 pbs_ptr, bool in_port)
1659 {
1660         mlxsw_afa_forward_type_set(payload, type);
1661         mlxsw_afa_forward_pbs_ptr_set(payload, pbs_ptr);
1662         mlxsw_afa_forward_in_port_set(payload, in_port);
1663 }
1664
1665 int mlxsw_afa_block_append_fwd(struct mlxsw_afa_block *block,
1666                                u8 local_port, bool in_port,
1667                                struct netlink_ext_ack *extack)
1668 {
1669         struct mlxsw_afa_fwd_entry_ref *fwd_entry_ref;
1670         u32 kvdl_index;
1671         char *act;
1672         int err;
1673
1674         if (in_port) {
1675                 NL_SET_ERR_MSG_MOD(extack, "Forwarding to ingress port is not supported");
1676                 return -EOPNOTSUPP;
1677         }
1678         fwd_entry_ref = mlxsw_afa_fwd_entry_ref_create(block, local_port);
1679         if (IS_ERR(fwd_entry_ref)) {
1680                 NL_SET_ERR_MSG_MOD(extack, "Cannot create forward action");
1681                 return PTR_ERR(fwd_entry_ref);
1682         }
1683         kvdl_index = fwd_entry_ref->fwd_entry->kvdl_index;
1684
1685         act = mlxsw_afa_block_append_action(block, MLXSW_AFA_FORWARD_CODE,
1686                                             MLXSW_AFA_FORWARD_SIZE);
1687         if (IS_ERR(act)) {
1688                 NL_SET_ERR_MSG_MOD(extack, "Cannot append forward action");
1689                 err = PTR_ERR(act);
1690                 goto err_append_action;
1691         }
1692         mlxsw_afa_forward_pack(act, MLXSW_AFA_FORWARD_TYPE_PBS,
1693                                kvdl_index, in_port);
1694         return 0;
1695
1696 err_append_action:
1697         mlxsw_afa_fwd_entry_ref_destroy(block, fwd_entry_ref);
1698         return err;
1699 }
1700 EXPORT_SYMBOL(mlxsw_afa_block_append_fwd);
1701
1702 /* Policing and Counting Action
1703  * ----------------------------
1704  * Policing and Counting action is used for binding policer and counter
1705  * to ACL rules.
1706  */
1707
1708 #define MLXSW_AFA_POLCNT_CODE 0x08
1709 #define MLXSW_AFA_POLCNT_SIZE 1
1710
1711 enum {
1712         MLXSW_AFA_POLCNT_COUNTER,
1713         MLXSW_AFA_POLCNT_POLICER,
1714 };
1715
1716 /* afa_polcnt_c_p
1717  * Counter or policer.
1718  * Indicates whether the action binds a policer or a counter to the flow.
1719  * 0: Counter
1720  * 1: Policer
1721  */
1722 MLXSW_ITEM32(afa, polcnt, c_p, 0x00, 31, 1);
1723
1724 enum mlxsw_afa_polcnt_counter_set_type {
1725         /* No count */
1726         MLXSW_AFA_POLCNT_COUNTER_SET_TYPE_NO_COUNT = 0x00,
1727         /* Count packets and bytes */
1728         MLXSW_AFA_POLCNT_COUNTER_SET_TYPE_PACKETS_BYTES = 0x03,
1729         /* Count only packets */
1730         MLXSW_AFA_POLCNT_COUNTER_SET_TYPE_PACKETS = 0x05,
1731 };
1732
1733 /* afa_polcnt_counter_set_type
1734  * Counter set type for flow counters.
1735  */
1736 MLXSW_ITEM32(afa, polcnt, counter_set_type, 0x04, 24, 8);
1737
1738 /* afa_polcnt_counter_index
1739  * Counter index for flow counters.
1740  */
1741 MLXSW_ITEM32(afa, polcnt, counter_index, 0x04, 0, 24);
1742
1743 /* afa_polcnt_pid
1744  * Policer ID.
1745  * Reserved when c_p = 0
1746  */
1747 MLXSW_ITEM32(afa, polcnt, pid, 0x08, 0, 14);
1748
1749 static inline void
1750 mlxsw_afa_polcnt_pack(char *payload,
1751                       enum mlxsw_afa_polcnt_counter_set_type set_type,
1752                       u32 counter_index)
1753 {
1754         mlxsw_afa_polcnt_c_p_set(payload, MLXSW_AFA_POLCNT_COUNTER);
1755         mlxsw_afa_polcnt_counter_set_type_set(payload, set_type);
1756         mlxsw_afa_polcnt_counter_index_set(payload, counter_index);
1757 }
1758
1759 static void mlxsw_afa_polcnt_policer_pack(char *payload, u16 policer_index)
1760 {
1761         mlxsw_afa_polcnt_c_p_set(payload, MLXSW_AFA_POLCNT_POLICER);
1762         mlxsw_afa_polcnt_pid_set(payload, policer_index);
1763 }
1764
1765 int mlxsw_afa_block_append_allocated_counter(struct mlxsw_afa_block *block,
1766                                              u32 counter_index)
1767 {
1768         char *act = mlxsw_afa_block_append_action(block, MLXSW_AFA_POLCNT_CODE,
1769                                                   MLXSW_AFA_POLCNT_SIZE);
1770         if (IS_ERR(act))
1771                 return PTR_ERR(act);
1772         mlxsw_afa_polcnt_pack(act, MLXSW_AFA_POLCNT_COUNTER_SET_TYPE_PACKETS_BYTES,
1773                               counter_index);
1774         return 0;
1775 }
1776 EXPORT_SYMBOL(mlxsw_afa_block_append_allocated_counter);
1777
1778 int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block,
1779                                    u32 *p_counter_index,
1780                                    struct netlink_ext_ack *extack)
1781 {
1782         struct mlxsw_afa_counter *counter;
1783         u32 counter_index;
1784         int err;
1785
1786         counter = mlxsw_afa_counter_create(block);
1787         if (IS_ERR(counter)) {
1788                 NL_SET_ERR_MSG_MOD(extack, "Cannot create count action");
1789                 return PTR_ERR(counter);
1790         }
1791         counter_index = counter->counter_index;
1792
1793         err = mlxsw_afa_block_append_allocated_counter(block, counter_index);
1794         if (err) {
1795                 NL_SET_ERR_MSG_MOD(extack, "Cannot append count action");
1796                 goto err_append_allocated_counter;
1797         }
1798         if (p_counter_index)
1799                 *p_counter_index = counter_index;
1800         return 0;
1801
1802 err_append_allocated_counter:
1803         mlxsw_afa_counter_destroy(block, counter);
1804         return err;
1805 }
1806 EXPORT_SYMBOL(mlxsw_afa_block_append_counter);
1807
1808 int mlxsw_afa_block_append_police(struct mlxsw_afa_block *block,
1809                                   u32 fa_index, u64 rate_bytes_ps, u32 burst,
1810                                   u16 *p_policer_index,
1811                                   struct netlink_ext_ack *extack)
1812 {
1813         struct mlxsw_afa_policer_ref *policer_ref;
1814         char *act;
1815         int err;
1816
1817         policer_ref = mlxsw_afa_policer_ref_create(block, fa_index,
1818                                                    rate_bytes_ps,
1819                                                    burst, extack);
1820         if (IS_ERR(policer_ref))
1821                 return PTR_ERR(policer_ref);
1822         *p_policer_index = policer_ref->policer->policer_index;
1823
1824         act = mlxsw_afa_block_append_action_ext(block, MLXSW_AFA_POLCNT_CODE,
1825                                                 MLXSW_AFA_POLCNT_SIZE,
1826                                                 MLXSW_AFA_ACTION_TYPE_POLICE);
1827         if (IS_ERR(act)) {
1828                 NL_SET_ERR_MSG_MOD(extack, "Cannot append police action");
1829                 err = PTR_ERR(act);
1830                 goto err_append_action;
1831         }
1832         mlxsw_afa_polcnt_policer_pack(act, *p_policer_index);
1833
1834         return 0;
1835
1836 err_append_action:
1837         mlxsw_afa_policer_ref_destroy(block, policer_ref);
1838         return err;
1839 }
1840 EXPORT_SYMBOL(mlxsw_afa_block_append_police);
1841
1842 /* Virtual Router and Forwarding Domain Action
1843  * -------------------------------------------
1844  * Virtual Switch action is used for manipulate the Virtual Router (VR),
1845  * MPLS label space and the Forwarding Identifier (FID).
1846  */
1847
1848 #define MLXSW_AFA_VIRFWD_CODE 0x0E
1849 #define MLXSW_AFA_VIRFWD_SIZE 1
1850
1851 enum mlxsw_afa_virfwd_fid_cmd {
1852         /* Do nothing */
1853         MLXSW_AFA_VIRFWD_FID_CMD_NOOP,
1854         /* Set the Forwarding Identifier (FID) to fid */
1855         MLXSW_AFA_VIRFWD_FID_CMD_SET,
1856 };
1857
1858 /* afa_virfwd_fid_cmd */
1859 MLXSW_ITEM32(afa, virfwd, fid_cmd, 0x08, 29, 3);
1860
1861 /* afa_virfwd_fid
1862  * The FID value.
1863  */
1864 MLXSW_ITEM32(afa, virfwd, fid, 0x08, 0, 16);
1865
1866 static inline void mlxsw_afa_virfwd_pack(char *payload,
1867                                          enum mlxsw_afa_virfwd_fid_cmd fid_cmd,
1868                                          u16 fid)
1869 {
1870         mlxsw_afa_virfwd_fid_cmd_set(payload, fid_cmd);
1871         mlxsw_afa_virfwd_fid_set(payload, fid);
1872 }
1873
1874 int mlxsw_afa_block_append_fid_set(struct mlxsw_afa_block *block, u16 fid,
1875                                    struct netlink_ext_ack *extack)
1876 {
1877         char *act = mlxsw_afa_block_append_action(block,
1878                                                   MLXSW_AFA_VIRFWD_CODE,
1879                                                   MLXSW_AFA_VIRFWD_SIZE);
1880         if (IS_ERR(act)) {
1881                 NL_SET_ERR_MSG_MOD(extack, "Cannot append fid_set action");
1882                 return PTR_ERR(act);
1883         }
1884         mlxsw_afa_virfwd_pack(act, MLXSW_AFA_VIRFWD_FID_CMD_SET, fid);
1885         return 0;
1886 }
1887 EXPORT_SYMBOL(mlxsw_afa_block_append_fid_set);
1888
1889 /* MC Routing Action
1890  * -----------------
1891  * The Multicast router action. Can be used by RMFT_V2 - Router Multicast
1892  * Forwarding Table Version 2 Register.
1893  */
1894
1895 #define MLXSW_AFA_MCROUTER_CODE 0x10
1896 #define MLXSW_AFA_MCROUTER_SIZE 2
1897
1898 enum mlxsw_afa_mcrouter_rpf_action {
1899         MLXSW_AFA_MCROUTER_RPF_ACTION_NOP,
1900         MLXSW_AFA_MCROUTER_RPF_ACTION_TRAP,
1901         MLXSW_AFA_MCROUTER_RPF_ACTION_DISCARD_ERROR,
1902 };
1903
1904 /* afa_mcrouter_rpf_action */
1905 MLXSW_ITEM32(afa, mcrouter, rpf_action, 0x00, 28, 3);
1906
1907 /* afa_mcrouter_expected_irif */
1908 MLXSW_ITEM32(afa, mcrouter, expected_irif, 0x00, 0, 16);
1909
1910 /* afa_mcrouter_min_mtu */
1911 MLXSW_ITEM32(afa, mcrouter, min_mtu, 0x08, 0, 16);
1912
1913 enum mlxsw_afa_mrouter_vrmid {
1914         MLXSW_AFA_MCROUTER_VRMID_INVALID,
1915         MLXSW_AFA_MCROUTER_VRMID_VALID
1916 };
1917
1918 /* afa_mcrouter_vrmid
1919  * Valid RMID: rigr_rmid_index is used as RMID
1920  */
1921 MLXSW_ITEM32(afa, mcrouter, vrmid, 0x0C, 31, 1);
1922
1923 /* afa_mcrouter_rigr_rmid_index
1924  * When the vrmid field is set to invalid, the field is used as pointer to
1925  * Router Interface Group (RIGR) Table in the KVD linear.
1926  * When the vrmid is set to valid, the field is used as RMID index, ranged
1927  * from 0 to max_mid - 1. The index is to the Port Group Table.
1928  */
1929 MLXSW_ITEM32(afa, mcrouter, rigr_rmid_index, 0x0C, 0, 24);
1930
1931 static inline void
1932 mlxsw_afa_mcrouter_pack(char *payload,
1933                         enum mlxsw_afa_mcrouter_rpf_action rpf_action,
1934                         u16 expected_irif, u16 min_mtu,
1935                         enum mlxsw_afa_mrouter_vrmid vrmid, u32 rigr_rmid_index)
1936
1937 {
1938         mlxsw_afa_mcrouter_rpf_action_set(payload, rpf_action);
1939         mlxsw_afa_mcrouter_expected_irif_set(payload, expected_irif);
1940         mlxsw_afa_mcrouter_min_mtu_set(payload, min_mtu);
1941         mlxsw_afa_mcrouter_vrmid_set(payload, vrmid);
1942         mlxsw_afa_mcrouter_rigr_rmid_index_set(payload, rigr_rmid_index);
1943 }
1944
1945 int mlxsw_afa_block_append_mcrouter(struct mlxsw_afa_block *block,
1946                                     u16 expected_irif, u16 min_mtu,
1947                                     bool rmid_valid, u32 kvdl_index)
1948 {
1949         char *act = mlxsw_afa_block_append_action(block,
1950                                                   MLXSW_AFA_MCROUTER_CODE,
1951                                                   MLXSW_AFA_MCROUTER_SIZE);
1952         if (IS_ERR(act))
1953                 return PTR_ERR(act);
1954         mlxsw_afa_mcrouter_pack(act, MLXSW_AFA_MCROUTER_RPF_ACTION_TRAP,
1955                                 expected_irif, min_mtu, rmid_valid, kvdl_index);
1956         return 0;
1957 }
1958 EXPORT_SYMBOL(mlxsw_afa_block_append_mcrouter);
1959
1960 /* L4 Port Action
1961  * --------------
1962  * The L4_PORT_ACTION is used for modifying the sport and dport fields of the packet, e.g. for NAT.
1963  * If (the L4 is TCP) or if (the L4 is UDP and checksum field!=0) then the L4 checksum is updated.
1964  */
1965
1966 #define MLXSW_AFA_L4PORT_CODE 0x12
1967 #define MLXSW_AFA_L4PORT_SIZE 1
1968
1969 enum mlxsw_afa_l4port_s_d {
1970         /* configure src_l4_port */
1971         MLXSW_AFA_L4PORT_S_D_SRC,
1972         /* configure dst_l4_port */
1973         MLXSW_AFA_L4PORT_S_D_DST,
1974 };
1975
1976 /* afa_l4port_s_d
1977  * Source or destination.
1978  */
1979 MLXSW_ITEM32(afa, l4port, s_d, 0x00, 31, 1);
1980
1981 /* afa_l4port_l4_port
1982  * Number of port to change to.
1983  */
1984 MLXSW_ITEM32(afa, l4port, l4_port, 0x08, 0, 16);
1985
1986 static void mlxsw_afa_l4port_pack(char *payload, enum mlxsw_afa_l4port_s_d s_d, u16 l4_port)
1987 {
1988         mlxsw_afa_l4port_s_d_set(payload, s_d);
1989         mlxsw_afa_l4port_l4_port_set(payload, l4_port);
1990 }
1991
1992 int mlxsw_afa_block_append_l4port(struct mlxsw_afa_block *block, bool is_dport, u16 l4_port,
1993                                   struct netlink_ext_ack *extack)
1994 {
1995         enum mlxsw_afa_l4port_s_d s_d = is_dport ? MLXSW_AFA_L4PORT_S_D_DST :
1996                                                    MLXSW_AFA_L4PORT_S_D_SRC;
1997         char *act = mlxsw_afa_block_append_action(block,
1998                                                   MLXSW_AFA_L4PORT_CODE,
1999                                                   MLXSW_AFA_L4PORT_SIZE);
2000
2001         if (IS_ERR(act)) {
2002                 NL_SET_ERR_MSG_MOD(extack, "Cannot append L4_PORT action");
2003                 return PTR_ERR(act);
2004         }
2005
2006         mlxsw_afa_l4port_pack(act, s_d, l4_port);
2007         return 0;
2008 }
2009 EXPORT_SYMBOL(mlxsw_afa_block_append_l4port);
2010
2011 /* Mirror Sampler Action
2012  * ---------------------
2013  * The SAMPLER_ACTION is used to mirror packets with a probability (sampling).
2014  */
2015
2016 #define MLXSW_AFA_SAMPLER_CODE 0x13
2017 #define MLXSW_AFA_SAMPLER_SIZE 1
2018
2019 /* afa_sampler_mirror_agent
2020  * Mirror (SPAN) agent.
2021  */
2022 MLXSW_ITEM32(afa, sampler, mirror_agent, 0x04, 0, 3);
2023
2024 #define MLXSW_AFA_SAMPLER_RATE_MAX (BIT(24) - 1)
2025
2026 /* afa_sampler_mirror_probability_rate
2027  * Mirroring probability.
2028  * Valid values are 1 to 2^24 - 1
2029  */
2030 MLXSW_ITEM32(afa, sampler, mirror_probability_rate, 0x08, 0, 24);
2031
2032 static void mlxsw_afa_sampler_pack(char *payload, u8 mirror_agent, u32 rate)
2033 {
2034         mlxsw_afa_sampler_mirror_agent_set(payload, mirror_agent);
2035         mlxsw_afa_sampler_mirror_probability_rate_set(payload, rate);
2036 }
2037
2038 struct mlxsw_afa_sampler {
2039         struct mlxsw_afa_resource resource;
2040         int span_id;
2041         u8 local_port;
2042         bool ingress;
2043 };
2044
2045 static void mlxsw_afa_sampler_destroy(struct mlxsw_afa_block *block,
2046                                       struct mlxsw_afa_sampler *sampler)
2047 {
2048         mlxsw_afa_resource_del(&sampler->resource);
2049         block->afa->ops->sampler_del(block->afa->ops_priv, sampler->local_port,
2050                                      sampler->span_id, sampler->ingress);
2051         kfree(sampler);
2052 }
2053
2054 static void mlxsw_afa_sampler_destructor(struct mlxsw_afa_block *block,
2055                                          struct mlxsw_afa_resource *resource)
2056 {
2057         struct mlxsw_afa_sampler *sampler;
2058
2059         sampler = container_of(resource, struct mlxsw_afa_sampler, resource);
2060         mlxsw_afa_sampler_destroy(block, sampler);
2061 }
2062
2063 static struct mlxsw_afa_sampler *
2064 mlxsw_afa_sampler_create(struct mlxsw_afa_block *block, u8 local_port,
2065                          struct psample_group *psample_group, u32 rate,
2066                          u32 trunc_size, bool truncate, bool ingress,
2067                          struct netlink_ext_ack *extack)
2068 {
2069         struct mlxsw_afa_sampler *sampler;
2070         int err;
2071
2072         sampler = kzalloc(sizeof(*sampler), GFP_KERNEL);
2073         if (!sampler)
2074                 return ERR_PTR(-ENOMEM);
2075
2076         err = block->afa->ops->sampler_add(block->afa->ops_priv, local_port,
2077                                            psample_group, rate, trunc_size,
2078                                            truncate, ingress, &sampler->span_id,
2079                                            extack);
2080         if (err)
2081                 goto err_sampler_add;
2082
2083         sampler->ingress = ingress;
2084         sampler->local_port = local_port;
2085         sampler->resource.destructor = mlxsw_afa_sampler_destructor;
2086         mlxsw_afa_resource_add(block, &sampler->resource);
2087         return sampler;
2088
2089 err_sampler_add:
2090         kfree(sampler);
2091         return ERR_PTR(err);
2092 }
2093
2094 static int
2095 mlxsw_afa_block_append_allocated_sampler(struct mlxsw_afa_block *block,
2096                                          u8 mirror_agent, u32 rate)
2097 {
2098         char *act = mlxsw_afa_block_append_action(block, MLXSW_AFA_SAMPLER_CODE,
2099                                                   MLXSW_AFA_SAMPLER_SIZE);
2100
2101         if (IS_ERR(act))
2102                 return PTR_ERR(act);
2103         mlxsw_afa_sampler_pack(act, mirror_agent, rate);
2104         return 0;
2105 }
2106
2107 int mlxsw_afa_block_append_sampler(struct mlxsw_afa_block *block, u8 local_port,
2108                                    struct psample_group *psample_group,
2109                                    u32 rate, u32 trunc_size, bool truncate,
2110                                    bool ingress,
2111                                    struct netlink_ext_ack *extack)
2112 {
2113         struct mlxsw_afa_sampler *sampler;
2114         int err;
2115
2116         if (rate > MLXSW_AFA_SAMPLER_RATE_MAX) {
2117                 NL_SET_ERR_MSG_MOD(extack, "Sampling rate is too high");
2118                 return -EINVAL;
2119         }
2120
2121         sampler = mlxsw_afa_sampler_create(block, local_port, psample_group,
2122                                            rate, trunc_size, truncate, ingress,
2123                                            extack);
2124         if (IS_ERR(sampler))
2125                 return PTR_ERR(sampler);
2126
2127         err = mlxsw_afa_block_append_allocated_sampler(block, sampler->span_id,
2128                                                        rate);
2129         if (err) {
2130                 NL_SET_ERR_MSG_MOD(extack, "Cannot append sampler action");
2131                 goto err_append_allocated_sampler;
2132         }
2133
2134         return 0;
2135
2136 err_append_allocated_sampler:
2137         mlxsw_afa_sampler_destroy(block, sampler);
2138         return err;
2139 }
2140 EXPORT_SYMBOL(mlxsw_afa_block_append_sampler);