]> Git Repo - linux.git/blob - net/devlink/trap.c
Linux 6.14-rc3
[linux.git] / net / devlink / trap.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
4  * Copyright (c) 2016 Jiri Pirko <[email protected]>
5  */
6
7 #include <trace/events/devlink.h>
8
9 #include "devl_internal.h"
10
11 struct devlink_stats {
12         u64_stats_t rx_bytes;
13         u64_stats_t rx_packets;
14         struct u64_stats_sync syncp;
15 };
16
17 /**
18  * struct devlink_trap_policer_item - Packet trap policer attributes.
19  * @policer: Immutable packet trap policer attributes.
20  * @rate: Rate in packets / sec.
21  * @burst: Burst size in packets.
22  * @list: trap_policer_list member.
23  *
24  * Describes packet trap policer attributes. Created by devlink during trap
25  * policer registration.
26  */
27 struct devlink_trap_policer_item {
28         const struct devlink_trap_policer *policer;
29         u64 rate;
30         u64 burst;
31         struct list_head list;
32 };
33
34 /**
35  * struct devlink_trap_group_item - Packet trap group attributes.
36  * @group: Immutable packet trap group attributes.
37  * @policer_item: Associated policer item. Can be NULL.
38  * @list: trap_group_list member.
39  * @stats: Trap group statistics.
40  *
41  * Describes packet trap group attributes. Created by devlink during trap
42  * group registration.
43  */
44 struct devlink_trap_group_item {
45         const struct devlink_trap_group *group;
46         struct devlink_trap_policer_item *policer_item;
47         struct list_head list;
48         struct devlink_stats __percpu *stats;
49 };
50
51 /**
52  * struct devlink_trap_item - Packet trap attributes.
53  * @trap: Immutable packet trap attributes.
54  * @group_item: Associated group item.
55  * @list: trap_list member.
56  * @action: Trap action.
57  * @stats: Trap statistics.
58  * @priv: Driver private information.
59  *
60  * Describes both mutable and immutable packet trap attributes. Created by
61  * devlink during trap registration and used for all trap related operations.
62  */
63 struct devlink_trap_item {
64         const struct devlink_trap *trap;
65         struct devlink_trap_group_item *group_item;
66         struct list_head list;
67         enum devlink_trap_action action;
68         struct devlink_stats __percpu *stats;
69         void *priv;
70 };
71
72 static struct devlink_trap_policer_item *
73 devlink_trap_policer_item_lookup(struct devlink *devlink, u32 id)
74 {
75         struct devlink_trap_policer_item *policer_item;
76
77         list_for_each_entry(policer_item, &devlink->trap_policer_list, list) {
78                 if (policer_item->policer->id == id)
79                         return policer_item;
80         }
81
82         return NULL;
83 }
84
85 static struct devlink_trap_item *
86 devlink_trap_item_lookup(struct devlink *devlink, const char *name)
87 {
88         struct devlink_trap_item *trap_item;
89
90         list_for_each_entry(trap_item, &devlink->trap_list, list) {
91                 if (!strcmp(trap_item->trap->name, name))
92                         return trap_item;
93         }
94
95         return NULL;
96 }
97
98 static struct devlink_trap_item *
99 devlink_trap_item_get_from_info(struct devlink *devlink,
100                                 struct genl_info *info)
101 {
102         struct nlattr *attr;
103
104         if (!info->attrs[DEVLINK_ATTR_TRAP_NAME])
105                 return NULL;
106         attr = info->attrs[DEVLINK_ATTR_TRAP_NAME];
107
108         return devlink_trap_item_lookup(devlink, nla_data(attr));
109 }
110
111 static int
112 devlink_trap_action_get_from_info(struct genl_info *info,
113                                   enum devlink_trap_action *p_trap_action)
114 {
115         u8 val;
116
117         val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]);
118         switch (val) {
119         case DEVLINK_TRAP_ACTION_DROP:
120         case DEVLINK_TRAP_ACTION_TRAP:
121         case DEVLINK_TRAP_ACTION_MIRROR:
122                 *p_trap_action = val;
123                 break;
124         default:
125                 return -EINVAL;
126         }
127
128         return 0;
129 }
130
131 static int devlink_trap_metadata_put(struct sk_buff *msg,
132                                      const struct devlink_trap *trap)
133 {
134         struct nlattr *attr;
135
136         attr = nla_nest_start(msg, DEVLINK_ATTR_TRAP_METADATA);
137         if (!attr)
138                 return -EMSGSIZE;
139
140         if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) &&
141             nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT))
142                 goto nla_put_failure;
143         if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE) &&
144             nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_FA_COOKIE))
145                 goto nla_put_failure;
146
147         nla_nest_end(msg, attr);
148
149         return 0;
150
151 nla_put_failure:
152         nla_nest_cancel(msg, attr);
153         return -EMSGSIZE;
154 }
155
156 static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats,
157                                     struct devlink_stats *stats)
158 {
159         int i;
160
161         memset(stats, 0, sizeof(*stats));
162         for_each_possible_cpu(i) {
163                 struct devlink_stats *cpu_stats;
164                 u64 rx_packets, rx_bytes;
165                 unsigned int start;
166
167                 cpu_stats = per_cpu_ptr(trap_stats, i);
168                 do {
169                         start = u64_stats_fetch_begin(&cpu_stats->syncp);
170                         rx_packets = u64_stats_read(&cpu_stats->rx_packets);
171                         rx_bytes = u64_stats_read(&cpu_stats->rx_bytes);
172                 } while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
173
174                 u64_stats_add(&stats->rx_packets, rx_packets);
175                 u64_stats_add(&stats->rx_bytes, rx_bytes);
176         }
177 }
178
179 static int
180 devlink_trap_group_stats_put(struct sk_buff *msg,
181                              struct devlink_stats __percpu *trap_stats)
182 {
183         struct devlink_stats stats;
184         struct nlattr *attr;
185
186         devlink_trap_stats_read(trap_stats, &stats);
187
188         attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
189         if (!attr)
190                 return -EMSGSIZE;
191
192         if (devlink_nl_put_u64(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
193                                u64_stats_read(&stats.rx_packets)))
194                 goto nla_put_failure;
195
196         if (devlink_nl_put_u64(msg, DEVLINK_ATTR_STATS_RX_BYTES,
197                                u64_stats_read(&stats.rx_bytes)))
198                 goto nla_put_failure;
199
200         nla_nest_end(msg, attr);
201
202         return 0;
203
204 nla_put_failure:
205         nla_nest_cancel(msg, attr);
206         return -EMSGSIZE;
207 }
208
209 static int devlink_trap_stats_put(struct sk_buff *msg, struct devlink *devlink,
210                                   const struct devlink_trap_item *trap_item)
211 {
212         struct devlink_stats stats;
213         struct nlattr *attr;
214         u64 drops = 0;
215         int err;
216
217         if (devlink->ops->trap_drop_counter_get) {
218                 err = devlink->ops->trap_drop_counter_get(devlink,
219                                                           trap_item->trap,
220                                                           &drops);
221                 if (err)
222                         return err;
223         }
224
225         devlink_trap_stats_read(trap_item->stats, &stats);
226
227         attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
228         if (!attr)
229                 return -EMSGSIZE;
230
231         if (devlink->ops->trap_drop_counter_get &&
232             devlink_nl_put_u64(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops))
233                 goto nla_put_failure;
234
235         if (devlink_nl_put_u64(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
236                                u64_stats_read(&stats.rx_packets)))
237                 goto nla_put_failure;
238
239         if (devlink_nl_put_u64(msg, DEVLINK_ATTR_STATS_RX_BYTES,
240                                u64_stats_read(&stats.rx_bytes)))
241                 goto nla_put_failure;
242
243         nla_nest_end(msg, attr);
244
245         return 0;
246
247 nla_put_failure:
248         nla_nest_cancel(msg, attr);
249         return -EMSGSIZE;
250 }
251
252 static int devlink_nl_trap_fill(struct sk_buff *msg, struct devlink *devlink,
253                                 const struct devlink_trap_item *trap_item,
254                                 enum devlink_command cmd, u32 portid, u32 seq,
255                                 int flags)
256 {
257         struct devlink_trap_group_item *group_item = trap_item->group_item;
258         void *hdr;
259         int err;
260
261         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
262         if (!hdr)
263                 return -EMSGSIZE;
264
265         if (devlink_nl_put_handle(msg, devlink))
266                 goto nla_put_failure;
267
268         if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
269                            group_item->group->name))
270                 goto nla_put_failure;
271
272         if (nla_put_string(msg, DEVLINK_ATTR_TRAP_NAME, trap_item->trap->name))
273                 goto nla_put_failure;
274
275         if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_TYPE, trap_item->trap->type))
276                 goto nla_put_failure;
277
278         if (trap_item->trap->generic &&
279             nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
280                 goto nla_put_failure;
281
282         if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_ACTION, trap_item->action))
283                 goto nla_put_failure;
284
285         err = devlink_trap_metadata_put(msg, trap_item->trap);
286         if (err)
287                 goto nla_put_failure;
288
289         err = devlink_trap_stats_put(msg, devlink, trap_item);
290         if (err)
291                 goto nla_put_failure;
292
293         genlmsg_end(msg, hdr);
294
295         return 0;
296
297 nla_put_failure:
298         genlmsg_cancel(msg, hdr);
299         return -EMSGSIZE;
300 }
301
302 int devlink_nl_trap_get_doit(struct sk_buff *skb, struct genl_info *info)
303 {
304         struct netlink_ext_ack *extack = info->extack;
305         struct devlink *devlink = info->user_ptr[0];
306         struct devlink_trap_item *trap_item;
307         struct sk_buff *msg;
308         int err;
309
310         if (list_empty(&devlink->trap_list))
311                 return -EOPNOTSUPP;
312
313         trap_item = devlink_trap_item_get_from_info(devlink, info);
314         if (!trap_item) {
315                 NL_SET_ERR_MSG(extack, "Device did not register this trap");
316                 return -ENOENT;
317         }
318
319         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
320         if (!msg)
321                 return -ENOMEM;
322
323         err = devlink_nl_trap_fill(msg, devlink, trap_item,
324                                    DEVLINK_CMD_TRAP_NEW, info->snd_portid,
325                                    info->snd_seq, 0);
326         if (err)
327                 goto err_trap_fill;
328
329         return genlmsg_reply(msg, info);
330
331 err_trap_fill:
332         nlmsg_free(msg);
333         return err;
334 }
335
336 static int devlink_nl_trap_get_dump_one(struct sk_buff *msg,
337                                         struct devlink *devlink,
338                                         struct netlink_callback *cb, int flags)
339 {
340         struct devlink_nl_dump_state *state = devlink_dump_state(cb);
341         struct devlink_trap_item *trap_item;
342         int idx = 0;
343         int err = 0;
344
345         list_for_each_entry(trap_item, &devlink->trap_list, list) {
346                 if (idx < state->idx) {
347                         idx++;
348                         continue;
349                 }
350                 err = devlink_nl_trap_fill(msg, devlink, trap_item,
351                                            DEVLINK_CMD_TRAP_NEW,
352                                            NETLINK_CB(cb->skb).portid,
353                                            cb->nlh->nlmsg_seq, flags);
354                 if (err) {
355                         state->idx = idx;
356                         break;
357                 }
358                 idx++;
359         }
360
361         return err;
362 }
363
364 int devlink_nl_trap_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
365 {
366         return devlink_nl_dumpit(skb, cb, devlink_nl_trap_get_dump_one);
367 }
368
369 static int __devlink_trap_action_set(struct devlink *devlink,
370                                      struct devlink_trap_item *trap_item,
371                                      enum devlink_trap_action trap_action,
372                                      struct netlink_ext_ack *extack)
373 {
374         int err;
375
376         if (trap_item->action != trap_action &&
377             trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) {
378                 NL_SET_ERR_MSG(extack, "Cannot change action of non-drop traps. Skipping");
379                 return 0;
380         }
381
382         err = devlink->ops->trap_action_set(devlink, trap_item->trap,
383                                             trap_action, extack);
384         if (err)
385                 return err;
386
387         trap_item->action = trap_action;
388
389         return 0;
390 }
391
392 static int devlink_trap_action_set(struct devlink *devlink,
393                                    struct devlink_trap_item *trap_item,
394                                    struct genl_info *info)
395 {
396         enum devlink_trap_action trap_action;
397         int err;
398
399         if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
400                 return 0;
401
402         err = devlink_trap_action_get_from_info(info, &trap_action);
403         if (err) {
404                 NL_SET_ERR_MSG(info->extack, "Invalid trap action");
405                 return -EINVAL;
406         }
407
408         return __devlink_trap_action_set(devlink, trap_item, trap_action,
409                                          info->extack);
410 }
411
412 int devlink_nl_trap_set_doit(struct sk_buff *skb, struct genl_info *info)
413 {
414         struct netlink_ext_ack *extack = info->extack;
415         struct devlink *devlink = info->user_ptr[0];
416         struct devlink_trap_item *trap_item;
417
418         if (list_empty(&devlink->trap_list))
419                 return -EOPNOTSUPP;
420
421         trap_item = devlink_trap_item_get_from_info(devlink, info);
422         if (!trap_item) {
423                 NL_SET_ERR_MSG(extack, "Device did not register this trap");
424                 return -ENOENT;
425         }
426
427         return devlink_trap_action_set(devlink, trap_item, info);
428 }
429
430 static struct devlink_trap_group_item *
431 devlink_trap_group_item_lookup(struct devlink *devlink, const char *name)
432 {
433         struct devlink_trap_group_item *group_item;
434
435         list_for_each_entry(group_item, &devlink->trap_group_list, list) {
436                 if (!strcmp(group_item->group->name, name))
437                         return group_item;
438         }
439
440         return NULL;
441 }
442
443 static struct devlink_trap_group_item *
444 devlink_trap_group_item_lookup_by_id(struct devlink *devlink, u16 id)
445 {
446         struct devlink_trap_group_item *group_item;
447
448         list_for_each_entry(group_item, &devlink->trap_group_list, list) {
449                 if (group_item->group->id == id)
450                         return group_item;
451         }
452
453         return NULL;
454 }
455
456 static struct devlink_trap_group_item *
457 devlink_trap_group_item_get_from_info(struct devlink *devlink,
458                                       struct genl_info *info)
459 {
460         char *name;
461
462         if (!info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME])
463                 return NULL;
464         name = nla_data(info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]);
465
466         return devlink_trap_group_item_lookup(devlink, name);
467 }
468
469 static int
470 devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink,
471                            const struct devlink_trap_group_item *group_item,
472                            enum devlink_command cmd, u32 portid, u32 seq,
473                            int flags)
474 {
475         void *hdr;
476         int err;
477
478         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
479         if (!hdr)
480                 return -EMSGSIZE;
481
482         if (devlink_nl_put_handle(msg, devlink))
483                 goto nla_put_failure;
484
485         if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
486                            group_item->group->name))
487                 goto nla_put_failure;
488
489         if (group_item->group->generic &&
490             nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
491                 goto nla_put_failure;
492
493         if (group_item->policer_item &&
494             nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
495                         group_item->policer_item->policer->id))
496                 goto nla_put_failure;
497
498         err = devlink_trap_group_stats_put(msg, group_item->stats);
499         if (err)
500                 goto nla_put_failure;
501
502         genlmsg_end(msg, hdr);
503
504         return 0;
505
506 nla_put_failure:
507         genlmsg_cancel(msg, hdr);
508         return -EMSGSIZE;
509 }
510
511 int devlink_nl_trap_group_get_doit(struct sk_buff *skb, struct genl_info *info)
512 {
513         struct netlink_ext_ack *extack = info->extack;
514         struct devlink *devlink = info->user_ptr[0];
515         struct devlink_trap_group_item *group_item;
516         struct sk_buff *msg;
517         int err;
518
519         if (list_empty(&devlink->trap_group_list))
520                 return -EOPNOTSUPP;
521
522         group_item = devlink_trap_group_item_get_from_info(devlink, info);
523         if (!group_item) {
524                 NL_SET_ERR_MSG(extack, "Device did not register this trap group");
525                 return -ENOENT;
526         }
527
528         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
529         if (!msg)
530                 return -ENOMEM;
531
532         err = devlink_nl_trap_group_fill(msg, devlink, group_item,
533                                          DEVLINK_CMD_TRAP_GROUP_NEW,
534                                          info->snd_portid, info->snd_seq, 0);
535         if (err)
536                 goto err_trap_group_fill;
537
538         return genlmsg_reply(msg, info);
539
540 err_trap_group_fill:
541         nlmsg_free(msg);
542         return err;
543 }
544
545 static int devlink_nl_trap_group_get_dump_one(struct sk_buff *msg,
546                                               struct devlink *devlink,
547                                               struct netlink_callback *cb,
548                                               int flags)
549 {
550         struct devlink_nl_dump_state *state = devlink_dump_state(cb);
551         struct devlink_trap_group_item *group_item;
552         int idx = 0;
553         int err = 0;
554
555         list_for_each_entry(group_item, &devlink->trap_group_list, list) {
556                 if (idx < state->idx) {
557                         idx++;
558                         continue;
559                 }
560                 err = devlink_nl_trap_group_fill(msg, devlink, group_item,
561                                                  DEVLINK_CMD_TRAP_GROUP_NEW,
562                                                  NETLINK_CB(cb->skb).portid,
563                                                  cb->nlh->nlmsg_seq, flags);
564                 if (err) {
565                         state->idx = idx;
566                         break;
567                 }
568                 idx++;
569         }
570
571         return err;
572 }
573
574 int devlink_nl_trap_group_get_dumpit(struct sk_buff *skb,
575                                      struct netlink_callback *cb)
576 {
577         return devlink_nl_dumpit(skb, cb, devlink_nl_trap_group_get_dump_one);
578 }
579
580 static int
581 __devlink_trap_group_action_set(struct devlink *devlink,
582                                 struct devlink_trap_group_item *group_item,
583                                 enum devlink_trap_action trap_action,
584                                 struct netlink_ext_ack *extack)
585 {
586         const char *group_name = group_item->group->name;
587         struct devlink_trap_item *trap_item;
588         int err;
589
590         if (devlink->ops->trap_group_action_set) {
591                 err = devlink->ops->trap_group_action_set(devlink, group_item->group,
592                                                           trap_action, extack);
593                 if (err)
594                         return err;
595
596                 list_for_each_entry(trap_item, &devlink->trap_list, list) {
597                         if (strcmp(trap_item->group_item->group->name, group_name))
598                                 continue;
599                         if (trap_item->action != trap_action &&
600                             trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP)
601                                 continue;
602                         trap_item->action = trap_action;
603                 }
604
605                 return 0;
606         }
607
608         list_for_each_entry(trap_item, &devlink->trap_list, list) {
609                 if (strcmp(trap_item->group_item->group->name, group_name))
610                         continue;
611                 err = __devlink_trap_action_set(devlink, trap_item,
612                                                 trap_action, extack);
613                 if (err)
614                         return err;
615         }
616
617         return 0;
618 }
619
620 static int
621 devlink_trap_group_action_set(struct devlink *devlink,
622                               struct devlink_trap_group_item *group_item,
623                               struct genl_info *info, bool *p_modified)
624 {
625         enum devlink_trap_action trap_action;
626         int err;
627
628         if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
629                 return 0;
630
631         err = devlink_trap_action_get_from_info(info, &trap_action);
632         if (err) {
633                 NL_SET_ERR_MSG(info->extack, "Invalid trap action");
634                 return -EINVAL;
635         }
636
637         err = __devlink_trap_group_action_set(devlink, group_item, trap_action,
638                                               info->extack);
639         if (err)
640                 return err;
641
642         *p_modified = true;
643
644         return 0;
645 }
646
647 static int devlink_trap_group_set(struct devlink *devlink,
648                                   struct devlink_trap_group_item *group_item,
649                                   struct genl_info *info)
650 {
651         struct devlink_trap_policer_item *policer_item;
652         struct netlink_ext_ack *extack = info->extack;
653         const struct devlink_trap_policer *policer;
654         struct nlattr **attrs = info->attrs;
655         u32 policer_id;
656         int err;
657
658         if (!attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
659                 return 0;
660
661         if (!devlink->ops->trap_group_set)
662                 return -EOPNOTSUPP;
663
664         policer_id = nla_get_u32(attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
665         policer_item = devlink_trap_policer_item_lookup(devlink, policer_id);
666         if (policer_id && !policer_item) {
667                 NL_SET_ERR_MSG(extack, "Device did not register this trap policer");
668                 return -ENOENT;
669         }
670         policer = policer_item ? policer_item->policer : NULL;
671
672         err = devlink->ops->trap_group_set(devlink, group_item->group, policer,
673                                            extack);
674         if (err)
675                 return err;
676
677         group_item->policer_item = policer_item;
678
679         return 0;
680 }
681
682 int devlink_nl_trap_group_set_doit(struct sk_buff *skb, struct genl_info *info)
683 {
684         struct netlink_ext_ack *extack = info->extack;
685         struct devlink *devlink = info->user_ptr[0];
686         struct devlink_trap_group_item *group_item;
687         bool modified = false;
688         int err;
689
690         if (list_empty(&devlink->trap_group_list))
691                 return -EOPNOTSUPP;
692
693         group_item = devlink_trap_group_item_get_from_info(devlink, info);
694         if (!group_item) {
695                 NL_SET_ERR_MSG(extack, "Device did not register this trap group");
696                 return -ENOENT;
697         }
698
699         err = devlink_trap_group_action_set(devlink, group_item, info,
700                                             &modified);
701         if (err)
702                 return err;
703
704         err = devlink_trap_group_set(devlink, group_item, info);
705         if (err)
706                 goto err_trap_group_set;
707
708         return 0;
709
710 err_trap_group_set:
711         if (modified)
712                 NL_SET_ERR_MSG(extack, "Trap group set failed, but some changes were committed already");
713         return err;
714 }
715
716 static struct devlink_trap_policer_item *
717 devlink_trap_policer_item_get_from_info(struct devlink *devlink,
718                                         struct genl_info *info)
719 {
720         u32 id;
721
722         if (!info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
723                 return NULL;
724         id = nla_get_u32(info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
725
726         return devlink_trap_policer_item_lookup(devlink, id);
727 }
728
729 static int
730 devlink_trap_policer_stats_put(struct sk_buff *msg, struct devlink *devlink,
731                                const struct devlink_trap_policer *policer)
732 {
733         struct nlattr *attr;
734         u64 drops;
735         int err;
736
737         if (!devlink->ops->trap_policer_counter_get)
738                 return 0;
739
740         err = devlink->ops->trap_policer_counter_get(devlink, policer, &drops);
741         if (err)
742                 return err;
743
744         attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
745         if (!attr)
746                 return -EMSGSIZE;
747
748         if (devlink_nl_put_u64(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops))
749                 goto nla_put_failure;
750
751         nla_nest_end(msg, attr);
752
753         return 0;
754
755 nla_put_failure:
756         nla_nest_cancel(msg, attr);
757         return -EMSGSIZE;
758 }
759
760 static int
761 devlink_nl_trap_policer_fill(struct sk_buff *msg, struct devlink *devlink,
762                              const struct devlink_trap_policer_item *policer_item,
763                              enum devlink_command cmd, u32 portid, u32 seq,
764                              int flags)
765 {
766         void *hdr;
767         int err;
768
769         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
770         if (!hdr)
771                 return -EMSGSIZE;
772
773         if (devlink_nl_put_handle(msg, devlink))
774                 goto nla_put_failure;
775
776         if (nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
777                         policer_item->policer->id))
778                 goto nla_put_failure;
779
780         if (devlink_nl_put_u64(msg, DEVLINK_ATTR_TRAP_POLICER_RATE,
781                                policer_item->rate))
782                 goto nla_put_failure;
783
784         if (devlink_nl_put_u64(msg, DEVLINK_ATTR_TRAP_POLICER_BURST,
785                                policer_item->burst))
786                 goto nla_put_failure;
787
788         err = devlink_trap_policer_stats_put(msg, devlink,
789                                              policer_item->policer);
790         if (err)
791                 goto nla_put_failure;
792
793         genlmsg_end(msg, hdr);
794
795         return 0;
796
797 nla_put_failure:
798         genlmsg_cancel(msg, hdr);
799         return -EMSGSIZE;
800 }
801
802 int devlink_nl_trap_policer_get_doit(struct sk_buff *skb,
803                                      struct genl_info *info)
804 {
805         struct devlink_trap_policer_item *policer_item;
806         struct netlink_ext_ack *extack = info->extack;
807         struct devlink *devlink = info->user_ptr[0];
808         struct sk_buff *msg;
809         int err;
810
811         if (list_empty(&devlink->trap_policer_list))
812                 return -EOPNOTSUPP;
813
814         policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
815         if (!policer_item) {
816                 NL_SET_ERR_MSG(extack, "Device did not register this trap policer");
817                 return -ENOENT;
818         }
819
820         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
821         if (!msg)
822                 return -ENOMEM;
823
824         err = devlink_nl_trap_policer_fill(msg, devlink, policer_item,
825                                            DEVLINK_CMD_TRAP_POLICER_NEW,
826                                            info->snd_portid, info->snd_seq, 0);
827         if (err)
828                 goto err_trap_policer_fill;
829
830         return genlmsg_reply(msg, info);
831
832 err_trap_policer_fill:
833         nlmsg_free(msg);
834         return err;
835 }
836
837 static int devlink_nl_trap_policer_get_dump_one(struct sk_buff *msg,
838                                                 struct devlink *devlink,
839                                                 struct netlink_callback *cb,
840                                                 int flags)
841 {
842         struct devlink_nl_dump_state *state = devlink_dump_state(cb);
843         struct devlink_trap_policer_item *policer_item;
844         int idx = 0;
845         int err = 0;
846
847         list_for_each_entry(policer_item, &devlink->trap_policer_list, list) {
848                 if (idx < state->idx) {
849                         idx++;
850                         continue;
851                 }
852                 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item,
853                                                    DEVLINK_CMD_TRAP_POLICER_NEW,
854                                                    NETLINK_CB(cb->skb).portid,
855                                                    cb->nlh->nlmsg_seq, flags);
856                 if (err) {
857                         state->idx = idx;
858                         break;
859                 }
860                 idx++;
861         }
862
863         return err;
864 }
865
866 int devlink_nl_trap_policer_get_dumpit(struct sk_buff *skb,
867                                        struct netlink_callback *cb)
868 {
869         return devlink_nl_dumpit(skb, cb, devlink_nl_trap_policer_get_dump_one);
870 }
871
872 static int
873 devlink_trap_policer_set(struct devlink *devlink,
874                          struct devlink_trap_policer_item *policer_item,
875                          struct genl_info *info)
876 {
877         struct netlink_ext_ack *extack = info->extack;
878         struct nlattr **attrs = info->attrs;
879         u64 rate, burst;
880         int err;
881
882         rate = policer_item->rate;
883         burst = policer_item->burst;
884
885         if (attrs[DEVLINK_ATTR_TRAP_POLICER_RATE])
886                 rate = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]);
887
888         if (attrs[DEVLINK_ATTR_TRAP_POLICER_BURST])
889                 burst = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]);
890
891         if (rate < policer_item->policer->min_rate) {
892                 NL_SET_ERR_MSG(extack, "Policer rate lower than limit");
893                 return -EINVAL;
894         }
895
896         if (rate > policer_item->policer->max_rate) {
897                 NL_SET_ERR_MSG(extack, "Policer rate higher than limit");
898                 return -EINVAL;
899         }
900
901         if (burst < policer_item->policer->min_burst) {
902                 NL_SET_ERR_MSG(extack, "Policer burst size lower than limit");
903                 return -EINVAL;
904         }
905
906         if (burst > policer_item->policer->max_burst) {
907                 NL_SET_ERR_MSG(extack, "Policer burst size higher than limit");
908                 return -EINVAL;
909         }
910
911         err = devlink->ops->trap_policer_set(devlink, policer_item->policer,
912                                              rate, burst, info->extack);
913         if (err)
914                 return err;
915
916         policer_item->rate = rate;
917         policer_item->burst = burst;
918
919         return 0;
920 }
921
922 int devlink_nl_trap_policer_set_doit(struct sk_buff *skb,
923                                      struct genl_info *info)
924 {
925         struct devlink_trap_policer_item *policer_item;
926         struct netlink_ext_ack *extack = info->extack;
927         struct devlink *devlink = info->user_ptr[0];
928
929         if (list_empty(&devlink->trap_policer_list))
930                 return -EOPNOTSUPP;
931
932         if (!devlink->ops->trap_policer_set)
933                 return -EOPNOTSUPP;
934
935         policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
936         if (!policer_item) {
937                 NL_SET_ERR_MSG(extack, "Device did not register this trap policer");
938                 return -ENOENT;
939         }
940
941         return devlink_trap_policer_set(devlink, policer_item, info);
942 }
943
944 #define DEVLINK_TRAP(_id, _type)                                              \
945         {                                                                     \
946                 .type = DEVLINK_TRAP_TYPE_##_type,                            \
947                 .id = DEVLINK_TRAP_GENERIC_ID_##_id,                          \
948                 .name = DEVLINK_TRAP_GENERIC_NAME_##_id,                      \
949         }
950
951 static const struct devlink_trap devlink_trap_generic[] = {
952         DEVLINK_TRAP(SMAC_MC, DROP),
953         DEVLINK_TRAP(VLAN_TAG_MISMATCH, DROP),
954         DEVLINK_TRAP(INGRESS_VLAN_FILTER, DROP),
955         DEVLINK_TRAP(INGRESS_STP_FILTER, DROP),
956         DEVLINK_TRAP(EMPTY_TX_LIST, DROP),
957         DEVLINK_TRAP(PORT_LOOPBACK_FILTER, DROP),
958         DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP),
959         DEVLINK_TRAP(TTL_ERROR, EXCEPTION),
960         DEVLINK_TRAP(TAIL_DROP, DROP),
961         DEVLINK_TRAP(NON_IP_PACKET, DROP),
962         DEVLINK_TRAP(UC_DIP_MC_DMAC, DROP),
963         DEVLINK_TRAP(DIP_LB, DROP),
964         DEVLINK_TRAP(SIP_MC, DROP),
965         DEVLINK_TRAP(SIP_LB, DROP),
966         DEVLINK_TRAP(CORRUPTED_IP_HDR, DROP),
967         DEVLINK_TRAP(IPV4_SIP_BC, DROP),
968         DEVLINK_TRAP(IPV6_MC_DIP_RESERVED_SCOPE, DROP),
969         DEVLINK_TRAP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, DROP),
970         DEVLINK_TRAP(MTU_ERROR, EXCEPTION),
971         DEVLINK_TRAP(UNRESOLVED_NEIGH, EXCEPTION),
972         DEVLINK_TRAP(RPF, EXCEPTION),
973         DEVLINK_TRAP(REJECT_ROUTE, EXCEPTION),
974         DEVLINK_TRAP(IPV4_LPM_UNICAST_MISS, EXCEPTION),
975         DEVLINK_TRAP(IPV6_LPM_UNICAST_MISS, EXCEPTION),
976         DEVLINK_TRAP(NON_ROUTABLE, DROP),
977         DEVLINK_TRAP(DECAP_ERROR, EXCEPTION),
978         DEVLINK_TRAP(OVERLAY_SMAC_MC, DROP),
979         DEVLINK_TRAP(INGRESS_FLOW_ACTION_DROP, DROP),
980         DEVLINK_TRAP(EGRESS_FLOW_ACTION_DROP, DROP),
981         DEVLINK_TRAP(STP, CONTROL),
982         DEVLINK_TRAP(LACP, CONTROL),
983         DEVLINK_TRAP(LLDP, CONTROL),
984         DEVLINK_TRAP(IGMP_QUERY, CONTROL),
985         DEVLINK_TRAP(IGMP_V1_REPORT, CONTROL),
986         DEVLINK_TRAP(IGMP_V2_REPORT, CONTROL),
987         DEVLINK_TRAP(IGMP_V3_REPORT, CONTROL),
988         DEVLINK_TRAP(IGMP_V2_LEAVE, CONTROL),
989         DEVLINK_TRAP(MLD_QUERY, CONTROL),
990         DEVLINK_TRAP(MLD_V1_REPORT, CONTROL),
991         DEVLINK_TRAP(MLD_V2_REPORT, CONTROL),
992         DEVLINK_TRAP(MLD_V1_DONE, CONTROL),
993         DEVLINK_TRAP(IPV4_DHCP, CONTROL),
994         DEVLINK_TRAP(IPV6_DHCP, CONTROL),
995         DEVLINK_TRAP(ARP_REQUEST, CONTROL),
996         DEVLINK_TRAP(ARP_RESPONSE, CONTROL),
997         DEVLINK_TRAP(ARP_OVERLAY, CONTROL),
998         DEVLINK_TRAP(IPV6_NEIGH_SOLICIT, CONTROL),
999         DEVLINK_TRAP(IPV6_NEIGH_ADVERT, CONTROL),
1000         DEVLINK_TRAP(IPV4_BFD, CONTROL),
1001         DEVLINK_TRAP(IPV6_BFD, CONTROL),
1002         DEVLINK_TRAP(IPV4_OSPF, CONTROL),
1003         DEVLINK_TRAP(IPV6_OSPF, CONTROL),
1004         DEVLINK_TRAP(IPV4_BGP, CONTROL),
1005         DEVLINK_TRAP(IPV6_BGP, CONTROL),
1006         DEVLINK_TRAP(IPV4_VRRP, CONTROL),
1007         DEVLINK_TRAP(IPV6_VRRP, CONTROL),
1008         DEVLINK_TRAP(IPV4_PIM, CONTROL),
1009         DEVLINK_TRAP(IPV6_PIM, CONTROL),
1010         DEVLINK_TRAP(UC_LB, CONTROL),
1011         DEVLINK_TRAP(LOCAL_ROUTE, CONTROL),
1012         DEVLINK_TRAP(EXTERNAL_ROUTE, CONTROL),
1013         DEVLINK_TRAP(IPV6_UC_DIP_LINK_LOCAL_SCOPE, CONTROL),
1014         DEVLINK_TRAP(IPV6_DIP_ALL_NODES, CONTROL),
1015         DEVLINK_TRAP(IPV6_DIP_ALL_ROUTERS, CONTROL),
1016         DEVLINK_TRAP(IPV6_ROUTER_SOLICIT, CONTROL),
1017         DEVLINK_TRAP(IPV6_ROUTER_ADVERT, CONTROL),
1018         DEVLINK_TRAP(IPV6_REDIRECT, CONTROL),
1019         DEVLINK_TRAP(IPV4_ROUTER_ALERT, CONTROL),
1020         DEVLINK_TRAP(IPV6_ROUTER_ALERT, CONTROL),
1021         DEVLINK_TRAP(PTP_EVENT, CONTROL),
1022         DEVLINK_TRAP(PTP_GENERAL, CONTROL),
1023         DEVLINK_TRAP(FLOW_ACTION_SAMPLE, CONTROL),
1024         DEVLINK_TRAP(FLOW_ACTION_TRAP, CONTROL),
1025         DEVLINK_TRAP(EARLY_DROP, DROP),
1026         DEVLINK_TRAP(VXLAN_PARSING, DROP),
1027         DEVLINK_TRAP(LLC_SNAP_PARSING, DROP),
1028         DEVLINK_TRAP(VLAN_PARSING, DROP),
1029         DEVLINK_TRAP(PPPOE_PPP_PARSING, DROP),
1030         DEVLINK_TRAP(MPLS_PARSING, DROP),
1031         DEVLINK_TRAP(ARP_PARSING, DROP),
1032         DEVLINK_TRAP(IP_1_PARSING, DROP),
1033         DEVLINK_TRAP(IP_N_PARSING, DROP),
1034         DEVLINK_TRAP(GRE_PARSING, DROP),
1035         DEVLINK_TRAP(UDP_PARSING, DROP),
1036         DEVLINK_TRAP(TCP_PARSING, DROP),
1037         DEVLINK_TRAP(IPSEC_PARSING, DROP),
1038         DEVLINK_TRAP(SCTP_PARSING, DROP),
1039         DEVLINK_TRAP(DCCP_PARSING, DROP),
1040         DEVLINK_TRAP(GTP_PARSING, DROP),
1041         DEVLINK_TRAP(ESP_PARSING, DROP),
1042         DEVLINK_TRAP(BLACKHOLE_NEXTHOP, DROP),
1043         DEVLINK_TRAP(DMAC_FILTER, DROP),
1044         DEVLINK_TRAP(EAPOL, CONTROL),
1045         DEVLINK_TRAP(LOCKED_PORT, DROP),
1046 };
1047
1048 #define DEVLINK_TRAP_GROUP(_id)                                               \
1049         {                                                                     \
1050                 .id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id,                    \
1051                 .name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id,                \
1052         }
1053
1054 static const struct devlink_trap_group devlink_trap_group_generic[] = {
1055         DEVLINK_TRAP_GROUP(L2_DROPS),
1056         DEVLINK_TRAP_GROUP(L3_DROPS),
1057         DEVLINK_TRAP_GROUP(L3_EXCEPTIONS),
1058         DEVLINK_TRAP_GROUP(BUFFER_DROPS),
1059         DEVLINK_TRAP_GROUP(TUNNEL_DROPS),
1060         DEVLINK_TRAP_GROUP(ACL_DROPS),
1061         DEVLINK_TRAP_GROUP(STP),
1062         DEVLINK_TRAP_GROUP(LACP),
1063         DEVLINK_TRAP_GROUP(LLDP),
1064         DEVLINK_TRAP_GROUP(MC_SNOOPING),
1065         DEVLINK_TRAP_GROUP(DHCP),
1066         DEVLINK_TRAP_GROUP(NEIGH_DISCOVERY),
1067         DEVLINK_TRAP_GROUP(BFD),
1068         DEVLINK_TRAP_GROUP(OSPF),
1069         DEVLINK_TRAP_GROUP(BGP),
1070         DEVLINK_TRAP_GROUP(VRRP),
1071         DEVLINK_TRAP_GROUP(PIM),
1072         DEVLINK_TRAP_GROUP(UC_LB),
1073         DEVLINK_TRAP_GROUP(LOCAL_DELIVERY),
1074         DEVLINK_TRAP_GROUP(EXTERNAL_DELIVERY),
1075         DEVLINK_TRAP_GROUP(IPV6),
1076         DEVLINK_TRAP_GROUP(PTP_EVENT),
1077         DEVLINK_TRAP_GROUP(PTP_GENERAL),
1078         DEVLINK_TRAP_GROUP(ACL_SAMPLE),
1079         DEVLINK_TRAP_GROUP(ACL_TRAP),
1080         DEVLINK_TRAP_GROUP(PARSER_ERROR_DROPS),
1081         DEVLINK_TRAP_GROUP(EAPOL),
1082 };
1083
1084 static int devlink_trap_generic_verify(const struct devlink_trap *trap)
1085 {
1086         if (trap->id > DEVLINK_TRAP_GENERIC_ID_MAX)
1087                 return -EINVAL;
1088
1089         if (strcmp(trap->name, devlink_trap_generic[trap->id].name))
1090                 return -EINVAL;
1091
1092         if (trap->type != devlink_trap_generic[trap->id].type)
1093                 return -EINVAL;
1094
1095         return 0;
1096 }
1097
1098 static int devlink_trap_driver_verify(const struct devlink_trap *trap)
1099 {
1100         int i;
1101
1102         if (trap->id <= DEVLINK_TRAP_GENERIC_ID_MAX)
1103                 return -EINVAL;
1104
1105         for (i = 0; i < ARRAY_SIZE(devlink_trap_generic); i++) {
1106                 if (!strcmp(trap->name, devlink_trap_generic[i].name))
1107                         return -EEXIST;
1108         }
1109
1110         return 0;
1111 }
1112
1113 static int devlink_trap_verify(const struct devlink_trap *trap)
1114 {
1115         if (!trap || !trap->name)
1116                 return -EINVAL;
1117
1118         if (trap->generic)
1119                 return devlink_trap_generic_verify(trap);
1120         else
1121                 return devlink_trap_driver_verify(trap);
1122 }
1123
1124 static int
1125 devlink_trap_group_generic_verify(const struct devlink_trap_group *group)
1126 {
1127         if (group->id > DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
1128                 return -EINVAL;
1129
1130         if (strcmp(group->name, devlink_trap_group_generic[group->id].name))
1131                 return -EINVAL;
1132
1133         return 0;
1134 }
1135
1136 static int
1137 devlink_trap_group_driver_verify(const struct devlink_trap_group *group)
1138 {
1139         int i;
1140
1141         if (group->id <= DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
1142                 return -EINVAL;
1143
1144         for (i = 0; i < ARRAY_SIZE(devlink_trap_group_generic); i++) {
1145                 if (!strcmp(group->name, devlink_trap_group_generic[i].name))
1146                         return -EEXIST;
1147         }
1148
1149         return 0;
1150 }
1151
1152 static int devlink_trap_group_verify(const struct devlink_trap_group *group)
1153 {
1154         if (group->generic)
1155                 return devlink_trap_group_generic_verify(group);
1156         else
1157                 return devlink_trap_group_driver_verify(group);
1158 }
1159
1160 static void
1161 devlink_trap_group_notify(struct devlink *devlink,
1162                           const struct devlink_trap_group_item *group_item,
1163                           enum devlink_command cmd)
1164 {
1165         struct sk_buff *msg;
1166         int err;
1167
1168         WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW &&
1169                      cmd != DEVLINK_CMD_TRAP_GROUP_DEL);
1170
1171         if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
1172                 return;
1173
1174         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1175         if (!msg)
1176                 return;
1177
1178         err = devlink_nl_trap_group_fill(msg, devlink, group_item, cmd, 0, 0,
1179                                          0);
1180         if (err) {
1181                 nlmsg_free(msg);
1182                 return;
1183         }
1184
1185         devlink_nl_notify_send(devlink, msg);
1186 }
1187
1188 void devlink_trap_groups_notify_register(struct devlink *devlink)
1189 {
1190         struct devlink_trap_group_item *group_item;
1191
1192         list_for_each_entry(group_item, &devlink->trap_group_list, list)
1193                 devlink_trap_group_notify(devlink, group_item,
1194                                           DEVLINK_CMD_TRAP_GROUP_NEW);
1195 }
1196
1197 void devlink_trap_groups_notify_unregister(struct devlink *devlink)
1198 {
1199         struct devlink_trap_group_item *group_item;
1200
1201         list_for_each_entry_reverse(group_item, &devlink->trap_group_list, list)
1202                 devlink_trap_group_notify(devlink, group_item,
1203                                           DEVLINK_CMD_TRAP_GROUP_DEL);
1204 }
1205
1206 static int
1207 devlink_trap_item_group_link(struct devlink *devlink,
1208                              struct devlink_trap_item *trap_item)
1209 {
1210         u16 group_id = trap_item->trap->init_group_id;
1211         struct devlink_trap_group_item *group_item;
1212
1213         group_item = devlink_trap_group_item_lookup_by_id(devlink, group_id);
1214         if (WARN_ON_ONCE(!group_item))
1215                 return -EINVAL;
1216
1217         trap_item->group_item = group_item;
1218
1219         return 0;
1220 }
1221
1222 static void devlink_trap_notify(struct devlink *devlink,
1223                                 const struct devlink_trap_item *trap_item,
1224                                 enum devlink_command cmd)
1225 {
1226         struct sk_buff *msg;
1227         int err;
1228
1229         WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_NEW &&
1230                      cmd != DEVLINK_CMD_TRAP_DEL);
1231
1232         if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
1233                 return;
1234
1235         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1236         if (!msg)
1237                 return;
1238
1239         err = devlink_nl_trap_fill(msg, devlink, trap_item, cmd, 0, 0, 0);
1240         if (err) {
1241                 nlmsg_free(msg);
1242                 return;
1243         }
1244
1245         devlink_nl_notify_send(devlink, msg);
1246 }
1247
1248 void devlink_traps_notify_register(struct devlink *devlink)
1249 {
1250         struct devlink_trap_item *trap_item;
1251
1252         list_for_each_entry(trap_item, &devlink->trap_list, list)
1253                 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW);
1254 }
1255
1256 void devlink_traps_notify_unregister(struct devlink *devlink)
1257 {
1258         struct devlink_trap_item *trap_item;
1259
1260         list_for_each_entry_reverse(trap_item, &devlink->trap_list, list)
1261                 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL);
1262 }
1263
1264 static int
1265 devlink_trap_register(struct devlink *devlink,
1266                       const struct devlink_trap *trap, void *priv)
1267 {
1268         struct devlink_trap_item *trap_item;
1269         int err;
1270
1271         if (devlink_trap_item_lookup(devlink, trap->name))
1272                 return -EEXIST;
1273
1274         trap_item = kzalloc(sizeof(*trap_item), GFP_KERNEL);
1275         if (!trap_item)
1276                 return -ENOMEM;
1277
1278         trap_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
1279         if (!trap_item->stats) {
1280                 err = -ENOMEM;
1281                 goto err_stats_alloc;
1282         }
1283
1284         trap_item->trap = trap;
1285         trap_item->action = trap->init_action;
1286         trap_item->priv = priv;
1287
1288         err = devlink_trap_item_group_link(devlink, trap_item);
1289         if (err)
1290                 goto err_group_link;
1291
1292         err = devlink->ops->trap_init(devlink, trap, trap_item);
1293         if (err)
1294                 goto err_trap_init;
1295
1296         list_add_tail(&trap_item->list, &devlink->trap_list);
1297         devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW);
1298
1299         return 0;
1300
1301 err_trap_init:
1302 err_group_link:
1303         free_percpu(trap_item->stats);
1304 err_stats_alloc:
1305         kfree(trap_item);
1306         return err;
1307 }
1308
1309 static void devlink_trap_unregister(struct devlink *devlink,
1310                                     const struct devlink_trap *trap)
1311 {
1312         struct devlink_trap_item *trap_item;
1313
1314         trap_item = devlink_trap_item_lookup(devlink, trap->name);
1315         if (WARN_ON_ONCE(!trap_item))
1316                 return;
1317
1318         devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL);
1319         list_del(&trap_item->list);
1320         if (devlink->ops->trap_fini)
1321                 devlink->ops->trap_fini(devlink, trap, trap_item);
1322         free_percpu(trap_item->stats);
1323         kfree(trap_item);
1324 }
1325
1326 static void devlink_trap_disable(struct devlink *devlink,
1327                                  const struct devlink_trap *trap)
1328 {
1329         struct devlink_trap_item *trap_item;
1330
1331         trap_item = devlink_trap_item_lookup(devlink, trap->name);
1332         if (WARN_ON_ONCE(!trap_item))
1333                 return;
1334
1335         devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP,
1336                                       NULL);
1337         trap_item->action = DEVLINK_TRAP_ACTION_DROP;
1338 }
1339
1340 /**
1341  * devl_traps_register - Register packet traps with devlink.
1342  * @devlink: devlink.
1343  * @traps: Packet traps.
1344  * @traps_count: Count of provided packet traps.
1345  * @priv: Driver private information.
1346  *
1347  * Return: Non-zero value on failure.
1348  */
1349 int devl_traps_register(struct devlink *devlink,
1350                         const struct devlink_trap *traps,
1351                         size_t traps_count, void *priv)
1352 {
1353         int i, err;
1354
1355         if (!devlink->ops->trap_init || !devlink->ops->trap_action_set)
1356                 return -EINVAL;
1357
1358         devl_assert_locked(devlink);
1359         for (i = 0; i < traps_count; i++) {
1360                 const struct devlink_trap *trap = &traps[i];
1361
1362                 err = devlink_trap_verify(trap);
1363                 if (err)
1364                         goto err_trap_verify;
1365
1366                 err = devlink_trap_register(devlink, trap, priv);
1367                 if (err)
1368                         goto err_trap_register;
1369         }
1370
1371         return 0;
1372
1373 err_trap_register:
1374 err_trap_verify:
1375         for (i--; i >= 0; i--)
1376                 devlink_trap_unregister(devlink, &traps[i]);
1377         return err;
1378 }
1379 EXPORT_SYMBOL_GPL(devl_traps_register);
1380
1381 /**
1382  * devlink_traps_register - Register packet traps with devlink.
1383  * @devlink: devlink.
1384  * @traps: Packet traps.
1385  * @traps_count: Count of provided packet traps.
1386  * @priv: Driver private information.
1387  *
1388  * Context: Takes and release devlink->lock <mutex>.
1389  *
1390  * Return: Non-zero value on failure.
1391  */
1392 int devlink_traps_register(struct devlink *devlink,
1393                            const struct devlink_trap *traps,
1394                            size_t traps_count, void *priv)
1395 {
1396         int err;
1397
1398         devl_lock(devlink);
1399         err = devl_traps_register(devlink, traps, traps_count, priv);
1400         devl_unlock(devlink);
1401         return err;
1402 }
1403 EXPORT_SYMBOL_GPL(devlink_traps_register);
1404
1405 /**
1406  * devl_traps_unregister - Unregister packet traps from devlink.
1407  * @devlink: devlink.
1408  * @traps: Packet traps.
1409  * @traps_count: Count of provided packet traps.
1410  */
1411 void devl_traps_unregister(struct devlink *devlink,
1412                            const struct devlink_trap *traps,
1413                            size_t traps_count)
1414 {
1415         int i;
1416
1417         devl_assert_locked(devlink);
1418         /* Make sure we do not have any packets in-flight while unregistering
1419          * traps by disabling all of them and waiting for a grace period.
1420          */
1421         for (i = traps_count - 1; i >= 0; i--)
1422                 devlink_trap_disable(devlink, &traps[i]);
1423         synchronize_rcu();
1424         for (i = traps_count - 1; i >= 0; i--)
1425                 devlink_trap_unregister(devlink, &traps[i]);
1426 }
1427 EXPORT_SYMBOL_GPL(devl_traps_unregister);
1428
1429 /**
1430  * devlink_traps_unregister - Unregister packet traps from devlink.
1431  * @devlink: devlink.
1432  * @traps: Packet traps.
1433  * @traps_count: Count of provided packet traps.
1434  *
1435  * Context: Takes and release devlink->lock <mutex>.
1436  */
1437 void devlink_traps_unregister(struct devlink *devlink,
1438                               const struct devlink_trap *traps,
1439                               size_t traps_count)
1440 {
1441         devl_lock(devlink);
1442         devl_traps_unregister(devlink, traps, traps_count);
1443         devl_unlock(devlink);
1444 }
1445 EXPORT_SYMBOL_GPL(devlink_traps_unregister);
1446
1447 static void
1448 devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats,
1449                           size_t skb_len)
1450 {
1451         struct devlink_stats *stats;
1452
1453         stats = this_cpu_ptr(trap_stats);
1454         u64_stats_update_begin(&stats->syncp);
1455         u64_stats_add(&stats->rx_bytes, skb_len);
1456         u64_stats_inc(&stats->rx_packets);
1457         u64_stats_update_end(&stats->syncp);
1458 }
1459
1460 static void
1461 devlink_trap_report_metadata_set(struct devlink_trap_metadata *metadata,
1462                                  const struct devlink_trap_item *trap_item,
1463                                  struct devlink_port *in_devlink_port,
1464                                  const struct flow_action_cookie *fa_cookie)
1465 {
1466         metadata->trap_name = trap_item->trap->name;
1467         metadata->trap_group_name = trap_item->group_item->group->name;
1468         metadata->fa_cookie = fa_cookie;
1469         metadata->trap_type = trap_item->trap->type;
1470
1471         spin_lock(&in_devlink_port->type_lock);
1472         if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH)
1473                 metadata->input_dev = in_devlink_port->type_eth.netdev;
1474         spin_unlock(&in_devlink_port->type_lock);
1475 }
1476
1477 /**
1478  * devlink_trap_report - Report trapped packet to drop monitor.
1479  * @devlink: devlink.
1480  * @skb: Trapped packet.
1481  * @trap_ctx: Trap context.
1482  * @in_devlink_port: Input devlink port.
1483  * @fa_cookie: Flow action cookie. Could be NULL.
1484  */
1485 void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb,
1486                          void *trap_ctx, struct devlink_port *in_devlink_port,
1487                          const struct flow_action_cookie *fa_cookie)
1488
1489 {
1490         struct devlink_trap_item *trap_item = trap_ctx;
1491
1492         devlink_trap_stats_update(trap_item->stats, skb->len);
1493         devlink_trap_stats_update(trap_item->group_item->stats, skb->len);
1494
1495         if (tracepoint_enabled(devlink_trap_report)) {
1496                 struct devlink_trap_metadata metadata = {};
1497
1498                 devlink_trap_report_metadata_set(&metadata, trap_item,
1499                                                  in_devlink_port, fa_cookie);
1500                 trace_devlink_trap_report(devlink, skb, &metadata);
1501         }
1502 }
1503 EXPORT_SYMBOL_GPL(devlink_trap_report);
1504
1505 /**
1506  * devlink_trap_ctx_priv - Trap context to driver private information.
1507  * @trap_ctx: Trap context.
1508  *
1509  * Return: Driver private information passed during registration.
1510  */
1511 void *devlink_trap_ctx_priv(void *trap_ctx)
1512 {
1513         struct devlink_trap_item *trap_item = trap_ctx;
1514
1515         return trap_item->priv;
1516 }
1517 EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv);
1518
1519 static int
1520 devlink_trap_group_item_policer_link(struct devlink *devlink,
1521                                      struct devlink_trap_group_item *group_item)
1522 {
1523         u32 policer_id = group_item->group->init_policer_id;
1524         struct devlink_trap_policer_item *policer_item;
1525
1526         if (policer_id == 0)
1527                 return 0;
1528
1529         policer_item = devlink_trap_policer_item_lookup(devlink, policer_id);
1530         if (WARN_ON_ONCE(!policer_item))
1531                 return -EINVAL;
1532
1533         group_item->policer_item = policer_item;
1534
1535         return 0;
1536 }
1537
1538 static int
1539 devlink_trap_group_register(struct devlink *devlink,
1540                             const struct devlink_trap_group *group)
1541 {
1542         struct devlink_trap_group_item *group_item;
1543         int err;
1544
1545         if (devlink_trap_group_item_lookup(devlink, group->name))
1546                 return -EEXIST;
1547
1548         group_item = kzalloc(sizeof(*group_item), GFP_KERNEL);
1549         if (!group_item)
1550                 return -ENOMEM;
1551
1552         group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
1553         if (!group_item->stats) {
1554                 err = -ENOMEM;
1555                 goto err_stats_alloc;
1556         }
1557
1558         group_item->group = group;
1559
1560         err = devlink_trap_group_item_policer_link(devlink, group_item);
1561         if (err)
1562                 goto err_policer_link;
1563
1564         if (devlink->ops->trap_group_init) {
1565                 err = devlink->ops->trap_group_init(devlink, group);
1566                 if (err)
1567                         goto err_group_init;
1568         }
1569
1570         list_add_tail(&group_item->list, &devlink->trap_group_list);
1571         devlink_trap_group_notify(devlink, group_item,
1572                                   DEVLINK_CMD_TRAP_GROUP_NEW);
1573
1574         return 0;
1575
1576 err_group_init:
1577 err_policer_link:
1578         free_percpu(group_item->stats);
1579 err_stats_alloc:
1580         kfree(group_item);
1581         return err;
1582 }
1583
1584 static void
1585 devlink_trap_group_unregister(struct devlink *devlink,
1586                               const struct devlink_trap_group *group)
1587 {
1588         struct devlink_trap_group_item *group_item;
1589
1590         group_item = devlink_trap_group_item_lookup(devlink, group->name);
1591         if (WARN_ON_ONCE(!group_item))
1592                 return;
1593
1594         devlink_trap_group_notify(devlink, group_item,
1595                                   DEVLINK_CMD_TRAP_GROUP_DEL);
1596         list_del(&group_item->list);
1597         free_percpu(group_item->stats);
1598         kfree(group_item);
1599 }
1600
1601 /**
1602  * devl_trap_groups_register - Register packet trap groups with devlink.
1603  * @devlink: devlink.
1604  * @groups: Packet trap groups.
1605  * @groups_count: Count of provided packet trap groups.
1606  *
1607  * Return: Non-zero value on failure.
1608  */
1609 int devl_trap_groups_register(struct devlink *devlink,
1610                               const struct devlink_trap_group *groups,
1611                               size_t groups_count)
1612 {
1613         int i, err;
1614
1615         devl_assert_locked(devlink);
1616         for (i = 0; i < groups_count; i++) {
1617                 const struct devlink_trap_group *group = &groups[i];
1618
1619                 err = devlink_trap_group_verify(group);
1620                 if (err)
1621                         goto err_trap_group_verify;
1622
1623                 err = devlink_trap_group_register(devlink, group);
1624                 if (err)
1625                         goto err_trap_group_register;
1626         }
1627
1628         return 0;
1629
1630 err_trap_group_register:
1631 err_trap_group_verify:
1632         for (i--; i >= 0; i--)
1633                 devlink_trap_group_unregister(devlink, &groups[i]);
1634         return err;
1635 }
1636 EXPORT_SYMBOL_GPL(devl_trap_groups_register);
1637
1638 /**
1639  * devlink_trap_groups_register - Register packet trap groups with devlink.
1640  * @devlink: devlink.
1641  * @groups: Packet trap groups.
1642  * @groups_count: Count of provided packet trap groups.
1643  *
1644  * Context: Takes and release devlink->lock <mutex>.
1645  *
1646  * Return: Non-zero value on failure.
1647  */
1648 int devlink_trap_groups_register(struct devlink *devlink,
1649                                  const struct devlink_trap_group *groups,
1650                                  size_t groups_count)
1651 {
1652         int err;
1653
1654         devl_lock(devlink);
1655         err = devl_trap_groups_register(devlink, groups, groups_count);
1656         devl_unlock(devlink);
1657         return err;
1658 }
1659 EXPORT_SYMBOL_GPL(devlink_trap_groups_register);
1660
1661 /**
1662  * devl_trap_groups_unregister - Unregister packet trap groups from devlink.
1663  * @devlink: devlink.
1664  * @groups: Packet trap groups.
1665  * @groups_count: Count of provided packet trap groups.
1666  */
1667 void devl_trap_groups_unregister(struct devlink *devlink,
1668                                  const struct devlink_trap_group *groups,
1669                                  size_t groups_count)
1670 {
1671         int i;
1672
1673         devl_assert_locked(devlink);
1674         for (i = groups_count - 1; i >= 0; i--)
1675                 devlink_trap_group_unregister(devlink, &groups[i]);
1676 }
1677 EXPORT_SYMBOL_GPL(devl_trap_groups_unregister);
1678
1679 /**
1680  * devlink_trap_groups_unregister - Unregister packet trap groups from devlink.
1681  * @devlink: devlink.
1682  * @groups: Packet trap groups.
1683  * @groups_count: Count of provided packet trap groups.
1684  *
1685  * Context: Takes and release devlink->lock <mutex>.
1686  */
1687 void devlink_trap_groups_unregister(struct devlink *devlink,
1688                                     const struct devlink_trap_group *groups,
1689                                     size_t groups_count)
1690 {
1691         devl_lock(devlink);
1692         devl_trap_groups_unregister(devlink, groups, groups_count);
1693         devl_unlock(devlink);
1694 }
1695 EXPORT_SYMBOL_GPL(devlink_trap_groups_unregister);
1696
1697 static void
1698 devlink_trap_policer_notify(struct devlink *devlink,
1699                             const struct devlink_trap_policer_item *policer_item,
1700                             enum devlink_command cmd)
1701 {
1702         struct sk_buff *msg;
1703         int err;
1704
1705         WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_POLICER_NEW &&
1706                      cmd != DEVLINK_CMD_TRAP_POLICER_DEL);
1707
1708         if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
1709                 return;
1710
1711         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1712         if (!msg)
1713                 return;
1714
1715         err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, cmd, 0,
1716                                            0, 0);
1717         if (err) {
1718                 nlmsg_free(msg);
1719                 return;
1720         }
1721
1722         devlink_nl_notify_send(devlink, msg);
1723 }
1724
1725 void devlink_trap_policers_notify_register(struct devlink *devlink)
1726 {
1727         struct devlink_trap_policer_item *policer_item;
1728
1729         list_for_each_entry(policer_item, &devlink->trap_policer_list, list)
1730                 devlink_trap_policer_notify(devlink, policer_item,
1731                                             DEVLINK_CMD_TRAP_POLICER_NEW);
1732 }
1733
1734 void devlink_trap_policers_notify_unregister(struct devlink *devlink)
1735 {
1736         struct devlink_trap_policer_item *policer_item;
1737
1738         list_for_each_entry_reverse(policer_item, &devlink->trap_policer_list,
1739                                     list)
1740                 devlink_trap_policer_notify(devlink, policer_item,
1741                                             DEVLINK_CMD_TRAP_POLICER_DEL);
1742 }
1743
1744 static int
1745 devlink_trap_policer_register(struct devlink *devlink,
1746                               const struct devlink_trap_policer *policer)
1747 {
1748         struct devlink_trap_policer_item *policer_item;
1749         int err;
1750
1751         if (devlink_trap_policer_item_lookup(devlink, policer->id))
1752                 return -EEXIST;
1753
1754         policer_item = kzalloc(sizeof(*policer_item), GFP_KERNEL);
1755         if (!policer_item)
1756                 return -ENOMEM;
1757
1758         policer_item->policer = policer;
1759         policer_item->rate = policer->init_rate;
1760         policer_item->burst = policer->init_burst;
1761
1762         if (devlink->ops->trap_policer_init) {
1763                 err = devlink->ops->trap_policer_init(devlink, policer);
1764                 if (err)
1765                         goto err_policer_init;
1766         }
1767
1768         list_add_tail(&policer_item->list, &devlink->trap_policer_list);
1769         devlink_trap_policer_notify(devlink, policer_item,
1770                                     DEVLINK_CMD_TRAP_POLICER_NEW);
1771
1772         return 0;
1773
1774 err_policer_init:
1775         kfree(policer_item);
1776         return err;
1777 }
1778
1779 static void
1780 devlink_trap_policer_unregister(struct devlink *devlink,
1781                                 const struct devlink_trap_policer *policer)
1782 {
1783         struct devlink_trap_policer_item *policer_item;
1784
1785         policer_item = devlink_trap_policer_item_lookup(devlink, policer->id);
1786         if (WARN_ON_ONCE(!policer_item))
1787                 return;
1788
1789         devlink_trap_policer_notify(devlink, policer_item,
1790                                     DEVLINK_CMD_TRAP_POLICER_DEL);
1791         list_del(&policer_item->list);
1792         if (devlink->ops->trap_policer_fini)
1793                 devlink->ops->trap_policer_fini(devlink, policer);
1794         kfree(policer_item);
1795 }
1796
1797 /**
1798  * devl_trap_policers_register - Register packet trap policers with devlink.
1799  * @devlink: devlink.
1800  * @policers: Packet trap policers.
1801  * @policers_count: Count of provided packet trap policers.
1802  *
1803  * Return: Non-zero value on failure.
1804  */
1805 int
1806 devl_trap_policers_register(struct devlink *devlink,
1807                             const struct devlink_trap_policer *policers,
1808                             size_t policers_count)
1809 {
1810         int i, err;
1811
1812         devl_assert_locked(devlink);
1813         for (i = 0; i < policers_count; i++) {
1814                 const struct devlink_trap_policer *policer = &policers[i];
1815
1816                 if (WARN_ON(policer->id == 0 ||
1817                             policer->max_rate < policer->min_rate ||
1818                             policer->max_burst < policer->min_burst)) {
1819                         err = -EINVAL;
1820                         goto err_trap_policer_verify;
1821                 }
1822
1823                 err = devlink_trap_policer_register(devlink, policer);
1824                 if (err)
1825                         goto err_trap_policer_register;
1826         }
1827         return 0;
1828
1829 err_trap_policer_register:
1830 err_trap_policer_verify:
1831         for (i--; i >= 0; i--)
1832                 devlink_trap_policer_unregister(devlink, &policers[i]);
1833         return err;
1834 }
1835 EXPORT_SYMBOL_GPL(devl_trap_policers_register);
1836
1837 /**
1838  * devl_trap_policers_unregister - Unregister packet trap policers from devlink.
1839  * @devlink: devlink.
1840  * @policers: Packet trap policers.
1841  * @policers_count: Count of provided packet trap policers.
1842  */
1843 void
1844 devl_trap_policers_unregister(struct devlink *devlink,
1845                               const struct devlink_trap_policer *policers,
1846                               size_t policers_count)
1847 {
1848         int i;
1849
1850         devl_assert_locked(devlink);
1851         for (i = policers_count - 1; i >= 0; i--)
1852                 devlink_trap_policer_unregister(devlink, &policers[i]);
1853 }
1854 EXPORT_SYMBOL_GPL(devl_trap_policers_unregister);
This page took 0.131832 seconds and 4 git commands to generate.