1
2
3
4#include <net/devlink.h>
5
6#include "prestera_devlink.h"
7#include "prestera_hw.h"
8
9
10
11
12enum {
13 DEVLINK_PRESTERA_TRAP_ID_BASE = DEVLINK_TRAP_GENERIC_ID_MAX,
14 DEVLINK_PRESTERA_TRAP_ID_ARP_BC,
15 DEVLINK_PRESTERA_TRAP_ID_IS_IS,
16 DEVLINK_PRESTERA_TRAP_ID_OSPF,
17 DEVLINK_PRESTERA_TRAP_ID_IP_BC_MAC,
18 DEVLINK_PRESTERA_TRAP_ID_ROUTER_MC,
19 DEVLINK_PRESTERA_TRAP_ID_VRRP,
20 DEVLINK_PRESTERA_TRAP_ID_DHCP,
21 DEVLINK_PRESTERA_TRAP_ID_MAC_TO_ME,
22 DEVLINK_PRESTERA_TRAP_ID_IPV4_OPTIONS,
23 DEVLINK_PRESTERA_TRAP_ID_IP_DEFAULT_ROUTE,
24 DEVLINK_PRESTERA_TRAP_ID_IP_TO_ME,
25 DEVLINK_PRESTERA_TRAP_ID_IPV4_ICMP_REDIRECT,
26 DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_0,
27 DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_1,
28 DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_2,
29 DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_3,
30 DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_4,
31 DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_5,
32 DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_6,
33 DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_7,
34 DEVLINK_PRESTERA_TRAP_ID_BGP,
35 DEVLINK_PRESTERA_TRAP_ID_SSH,
36 DEVLINK_PRESTERA_TRAP_ID_TELNET,
37 DEVLINK_PRESTERA_TRAP_ID_ICMP,
38 DEVLINK_PRESTERA_TRAP_ID_MET_RED,
39 DEVLINK_PRESTERA_TRAP_ID_IP_SIP_IS_ZERO,
40 DEVLINK_PRESTERA_TRAP_ID_IP_UC_DIP_DA_MISMATCH,
41 DEVLINK_PRESTERA_TRAP_ID_ILLEGAL_IPV4_HDR,
42 DEVLINK_PRESTERA_TRAP_ID_ILLEGAL_IP_ADDR,
43 DEVLINK_PRESTERA_TRAP_ID_INVALID_SA,
44 DEVLINK_PRESTERA_TRAP_ID_LOCAL_PORT,
45 DEVLINK_PRESTERA_TRAP_ID_PORT_NO_VLAN,
46 DEVLINK_PRESTERA_TRAP_ID_RXDMA_DROP,
47};
48
49#define DEVLINK_PRESTERA_TRAP_NAME_ARP_BC \
50 "arp_bc"
51#define DEVLINK_PRESTERA_TRAP_NAME_IS_IS \
52 "is_is"
53#define DEVLINK_PRESTERA_TRAP_NAME_OSPF \
54 "ospf"
55#define DEVLINK_PRESTERA_TRAP_NAME_IP_BC_MAC \
56 "ip_bc_mac"
57#define DEVLINK_PRESTERA_TRAP_NAME_ROUTER_MC \
58 "router_mc"
59#define DEVLINK_PRESTERA_TRAP_NAME_VRRP \
60 "vrrp"
61#define DEVLINK_PRESTERA_TRAP_NAME_DHCP \
62 "dhcp"
63#define DEVLINK_PRESTERA_TRAP_NAME_MAC_TO_ME \
64 "mac_to_me"
65#define DEVLINK_PRESTERA_TRAP_NAME_IPV4_OPTIONS \
66 "ipv4_options"
67#define DEVLINK_PRESTERA_TRAP_NAME_IP_DEFAULT_ROUTE \
68 "ip_default_route"
69#define DEVLINK_PRESTERA_TRAP_NAME_IP_TO_ME \
70 "ip_to_me"
71#define DEVLINK_PRESTERA_TRAP_NAME_IPV4_ICMP_REDIRECT \
72 "ipv4_icmp_redirect"
73#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_0 \
74 "acl_code_0"
75#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_1 \
76 "acl_code_1"
77#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_2 \
78 "acl_code_2"
79#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_3 \
80 "acl_code_3"
81#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_4 \
82 "acl_code_4"
83#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_5 \
84 "acl_code_5"
85#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_6 \
86 "acl_code_6"
87#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_7 \
88 "acl_code_7"
89#define DEVLINK_PRESTERA_TRAP_NAME_BGP \
90 "bgp"
91#define DEVLINK_PRESTERA_TRAP_NAME_SSH \
92 "ssh"
93#define DEVLINK_PRESTERA_TRAP_NAME_TELNET \
94 "telnet"
95#define DEVLINK_PRESTERA_TRAP_NAME_ICMP \
96 "icmp"
97#define DEVLINK_PRESTERA_TRAP_NAME_RXDMA_DROP \
98 "rxdma_drop"
99#define DEVLINK_PRESTERA_TRAP_NAME_PORT_NO_VLAN \
100 "port_no_vlan"
101#define DEVLINK_PRESTERA_TRAP_NAME_LOCAL_PORT \
102 "local_port"
103#define DEVLINK_PRESTERA_TRAP_NAME_INVALID_SA \
104 "invalid_sa"
105#define DEVLINK_PRESTERA_TRAP_NAME_ILLEGAL_IP_ADDR \
106 "illegal_ip_addr"
107#define DEVLINK_PRESTERA_TRAP_NAME_ILLEGAL_IPV4_HDR \
108 "illegal_ipv4_hdr"
109#define DEVLINK_PRESTERA_TRAP_NAME_IP_UC_DIP_DA_MISMATCH \
110 "ip_uc_dip_da_mismatch"
111#define DEVLINK_PRESTERA_TRAP_NAME_IP_SIP_IS_ZERO \
112 "ip_sip_is_zero"
113#define DEVLINK_PRESTERA_TRAP_NAME_MET_RED \
114 "met_red"
115
116struct prestera_trap {
117 struct devlink_trap trap;
118 u8 cpu_code;
119};
120
121struct prestera_trap_item {
122 enum devlink_trap_action action;
123 void *trap_ctx;
124};
125
126struct prestera_trap_data {
127 struct prestera_switch *sw;
128 struct prestera_trap_item *trap_items_arr;
129 u32 traps_count;
130};
131
132#define PRESTERA_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT
133
134#define PRESTERA_TRAP_CONTROL(_id, _group_id, _action) \
135 DEVLINK_TRAP_GENERIC(CONTROL, _action, _id, \
136 DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
137 PRESTERA_TRAP_METADATA)
138
139#define PRESTERA_TRAP_DRIVER_CONTROL(_id, _group_id) \
140 DEVLINK_TRAP_DRIVER(CONTROL, TRAP, DEVLINK_PRESTERA_TRAP_ID_##_id, \
141 DEVLINK_PRESTERA_TRAP_NAME_##_id, \
142 DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
143 PRESTERA_TRAP_METADATA)
144
145#define PRESTERA_TRAP_EXCEPTION(_id, _group_id) \
146 DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id, \
147 DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
148 PRESTERA_TRAP_METADATA)
149
150#define PRESTERA_TRAP_DRIVER_EXCEPTION(_id, _group_id) \
151 DEVLINK_TRAP_DRIVER(EXCEPTION, TRAP, DEVLINK_PRESTERA_TRAP_ID_##_id, \
152 DEVLINK_PRESTERA_TRAP_NAME_##_id, \
153 DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
154 PRESTERA_TRAP_METADATA)
155
156#define PRESTERA_TRAP_DRIVER_DROP(_id, _group_id) \
157 DEVLINK_TRAP_DRIVER(DROP, DROP, DEVLINK_PRESTERA_TRAP_ID_##_id, \
158 DEVLINK_PRESTERA_TRAP_NAME_##_id, \
159 DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
160 PRESTERA_TRAP_METADATA)
161
162static const struct devlink_trap_group prestera_trap_groups_arr[] = {
163
164 DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0),
165 DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS, 0),
166 DEVLINK_TRAP_GROUP_GENERIC(L3_EXCEPTIONS, 0),
167 DEVLINK_TRAP_GROUP_GENERIC(NEIGH_DISCOVERY, 0),
168 DEVLINK_TRAP_GROUP_GENERIC(ACL_TRAP, 0),
169 DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS, 0),
170 DEVLINK_TRAP_GROUP_GENERIC(ACL_SAMPLE, 0),
171 DEVLINK_TRAP_GROUP_GENERIC(OSPF, 0),
172 DEVLINK_TRAP_GROUP_GENERIC(STP, 0),
173 DEVLINK_TRAP_GROUP_GENERIC(LACP, 0),
174 DEVLINK_TRAP_GROUP_GENERIC(LLDP, 0),
175 DEVLINK_TRAP_GROUP_GENERIC(VRRP, 0),
176 DEVLINK_TRAP_GROUP_GENERIC(DHCP, 0),
177 DEVLINK_TRAP_GROUP_GENERIC(BGP, 0),
178 DEVLINK_TRAP_GROUP_GENERIC(LOCAL_DELIVERY, 0),
179 DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS, 0),
180};
181
182
183static struct prestera_trap prestera_trap_items_arr[] = {
184 {
185 .trap = PRESTERA_TRAP_DRIVER_CONTROL(ARP_BC, NEIGH_DISCOVERY),
186 .cpu_code = 5,
187 },
188 {
189 .trap = PRESTERA_TRAP_DRIVER_CONTROL(IS_IS, LOCAL_DELIVERY),
190 .cpu_code = 13,
191 },
192 {
193 .trap = PRESTERA_TRAP_DRIVER_CONTROL(OSPF, OSPF),
194 .cpu_code = 16,
195 },
196 {
197 .trap = PRESTERA_TRAP_DRIVER_CONTROL(IP_BC_MAC, LOCAL_DELIVERY),
198 .cpu_code = 19,
199 },
200 {
201 .trap = PRESTERA_TRAP_CONTROL(STP, STP, TRAP),
202 .cpu_code = 26,
203 },
204 {
205 .trap = PRESTERA_TRAP_CONTROL(LACP, LACP, TRAP),
206 .cpu_code = 27,
207 },
208 {
209 .trap = PRESTERA_TRAP_CONTROL(LLDP, LLDP, TRAP),
210 .cpu_code = 28,
211 },
212 {
213 .trap = PRESTERA_TRAP_DRIVER_CONTROL(ROUTER_MC, LOCAL_DELIVERY),
214 .cpu_code = 29,
215 },
216 {
217 .trap = PRESTERA_TRAP_DRIVER_CONTROL(VRRP, VRRP),
218 .cpu_code = 30,
219 },
220 {
221 .trap = PRESTERA_TRAP_DRIVER_CONTROL(DHCP, DHCP),
222 .cpu_code = 33,
223 },
224 {
225 .trap = PRESTERA_TRAP_EXCEPTION(MTU_ERROR, L3_EXCEPTIONS),
226 .cpu_code = 63,
227 },
228 {
229 .trap = PRESTERA_TRAP_DRIVER_CONTROL(MAC_TO_ME, LOCAL_DELIVERY),
230 .cpu_code = 65,
231 },
232 {
233 .trap = PRESTERA_TRAP_EXCEPTION(TTL_ERROR, L3_EXCEPTIONS),
234 .cpu_code = 133,
235 },
236 {
237 .trap = PRESTERA_TRAP_DRIVER_EXCEPTION(IPV4_OPTIONS,
238 L3_EXCEPTIONS),
239 .cpu_code = 141,
240 },
241 {
242 .trap = PRESTERA_TRAP_DRIVER_CONTROL(IP_DEFAULT_ROUTE,
243 LOCAL_DELIVERY),
244 .cpu_code = 160,
245 },
246 {
247 .trap = PRESTERA_TRAP_CONTROL(LOCAL_ROUTE, LOCAL_DELIVERY,
248 TRAP),
249 .cpu_code = 161,
250 },
251 {
252 .trap = PRESTERA_TRAP_DRIVER_EXCEPTION(IPV4_ICMP_REDIRECT,
253 L3_EXCEPTIONS),
254 .cpu_code = 180,
255 },
256 {
257 .trap = PRESTERA_TRAP_CONTROL(ARP_RESPONSE, NEIGH_DISCOVERY,
258 TRAP),
259 .cpu_code = 188,
260 },
261 {
262 .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_0, ACL_TRAP),
263 .cpu_code = 192,
264 },
265 {
266 .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_1, ACL_TRAP),
267 .cpu_code = 193,
268 },
269 {
270 .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_2, ACL_TRAP),
271 .cpu_code = 194,
272 },
273 {
274 .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_3, ACL_TRAP),
275 .cpu_code = 195,
276 },
277 {
278 .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_4, ACL_TRAP),
279 .cpu_code = 196,
280 },
281 {
282 .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_5, ACL_TRAP),
283 .cpu_code = 197,
284 },
285 {
286 .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_6, ACL_TRAP),
287 .cpu_code = 198,
288 },
289 {
290 .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_7, ACL_TRAP),
291 .cpu_code = 199,
292 },
293 {
294 .trap = PRESTERA_TRAP_DRIVER_CONTROL(BGP, BGP),
295 .cpu_code = 206,
296 },
297 {
298 .trap = PRESTERA_TRAP_DRIVER_CONTROL(SSH, LOCAL_DELIVERY),
299 .cpu_code = 207,
300 },
301 {
302 .trap = PRESTERA_TRAP_DRIVER_CONTROL(TELNET, LOCAL_DELIVERY),
303 .cpu_code = 208,
304 },
305 {
306 .trap = PRESTERA_TRAP_DRIVER_CONTROL(ICMP, LOCAL_DELIVERY),
307 .cpu_code = 209,
308 },
309 {
310 .trap = PRESTERA_TRAP_DRIVER_DROP(RXDMA_DROP, BUFFER_DROPS),
311 .cpu_code = 37,
312 },
313 {
314 .trap = PRESTERA_TRAP_DRIVER_DROP(PORT_NO_VLAN, L2_DROPS),
315 .cpu_code = 39,
316 },
317 {
318 .trap = PRESTERA_TRAP_DRIVER_DROP(LOCAL_PORT, L2_DROPS),
319 .cpu_code = 56,
320 },
321 {
322 .trap = PRESTERA_TRAP_DRIVER_DROP(INVALID_SA, L2_DROPS),
323 .cpu_code = 60,
324 },
325 {
326 .trap = PRESTERA_TRAP_DRIVER_DROP(ILLEGAL_IP_ADDR, L3_DROPS),
327 .cpu_code = 136,
328 },
329 {
330 .trap = PRESTERA_TRAP_DRIVER_DROP(ILLEGAL_IPV4_HDR, L3_DROPS),
331 .cpu_code = 137,
332 },
333 {
334 .trap = PRESTERA_TRAP_DRIVER_DROP(IP_UC_DIP_DA_MISMATCH,
335 L3_DROPS),
336 .cpu_code = 138,
337 },
338 {
339 .trap = PRESTERA_TRAP_DRIVER_DROP(IP_SIP_IS_ZERO, L3_DROPS),
340 .cpu_code = 145,
341 },
342 {
343 .trap = PRESTERA_TRAP_DRIVER_DROP(MET_RED, BUFFER_DROPS),
344 .cpu_code = 185,
345 },
346};
347
348static void prestera_devlink_traps_fini(struct prestera_switch *sw);
349
350static int prestera_drop_counter_get(struct devlink *devlink,
351 const struct devlink_trap *trap,
352 u64 *p_drops);
353
354static int prestera_dl_info_get(struct devlink *dl,
355 struct devlink_info_req *req,
356 struct netlink_ext_ack *extack)
357{
358 struct prestera_switch *sw = devlink_priv(dl);
359 char buf[16];
360 int err;
361
362 err = devlink_info_driver_name_put(req, PRESTERA_DRV_NAME);
363 if (err)
364 return err;
365
366 snprintf(buf, sizeof(buf), "%d.%d.%d",
367 sw->dev->fw_rev.maj,
368 sw->dev->fw_rev.min,
369 sw->dev->fw_rev.sub);
370
371 return devlink_info_version_running_put(req,
372 DEVLINK_INFO_VERSION_GENERIC_FW,
373 buf);
374}
375
376static int prestera_trap_init(struct devlink *devlink,
377 const struct devlink_trap *trap, void *trap_ctx);
378
379static int prestera_trap_action_set(struct devlink *devlink,
380 const struct devlink_trap *trap,
381 enum devlink_trap_action action,
382 struct netlink_ext_ack *extack);
383
384static int prestera_devlink_traps_register(struct prestera_switch *sw);
385
386static const struct devlink_ops prestera_dl_ops = {
387 .info_get = prestera_dl_info_get,
388 .trap_init = prestera_trap_init,
389 .trap_action_set = prestera_trap_action_set,
390 .trap_drop_counter_get = prestera_drop_counter_get,
391};
392
393struct prestera_switch *prestera_devlink_alloc(struct prestera_device *dev)
394{
395 struct devlink *dl;
396
397 dl = devlink_alloc(&prestera_dl_ops, sizeof(struct prestera_switch),
398 dev->dev);
399
400 return devlink_priv(dl);
401}
402
403void prestera_devlink_free(struct prestera_switch *sw)
404{
405 struct devlink *dl = priv_to_devlink(sw);
406
407 devlink_free(dl);
408}
409
410int prestera_devlink_register(struct prestera_switch *sw)
411{
412 struct devlink *dl = priv_to_devlink(sw);
413 int err;
414
415 err = devlink_register(dl);
416 if (err) {
417 dev_err(prestera_dev(sw), "devlink_register failed: %d\n", err);
418 return err;
419 }
420
421 err = prestera_devlink_traps_register(sw);
422 if (err) {
423 devlink_unregister(dl);
424 dev_err(sw->dev->dev, "devlink_traps_register failed: %d\n",
425 err);
426 return err;
427 }
428
429 return 0;
430}
431
432void prestera_devlink_unregister(struct prestera_switch *sw)
433{
434 struct prestera_trap_data *trap_data = sw->trap_data;
435 struct devlink *dl = priv_to_devlink(sw);
436
437 prestera_devlink_traps_fini(sw);
438 devlink_unregister(dl);
439
440 kfree(trap_data->trap_items_arr);
441 kfree(trap_data);
442}
443
444int prestera_devlink_port_register(struct prestera_port *port)
445{
446 struct prestera_switch *sw = port->sw;
447 struct devlink *dl = priv_to_devlink(sw);
448 struct devlink_port_attrs attrs = {};
449 int err;
450
451 attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
452 attrs.phys.port_number = port->fp_id;
453 attrs.switch_id.id_len = sizeof(sw->id);
454 memcpy(attrs.switch_id.id, &sw->id, attrs.switch_id.id_len);
455
456 devlink_port_attrs_set(&port->dl_port, &attrs);
457
458 err = devlink_port_register(dl, &port->dl_port, port->fp_id);
459 if (err) {
460 dev_err(prestera_dev(sw), "devlink_port_register failed: %d\n", err);
461 return err;
462 }
463
464 return 0;
465}
466
467void prestera_devlink_port_unregister(struct prestera_port *port)
468{
469 devlink_port_unregister(&port->dl_port);
470}
471
472void prestera_devlink_port_set(struct prestera_port *port)
473{
474 devlink_port_type_eth_set(&port->dl_port, port->dev);
475}
476
477void prestera_devlink_port_clear(struct prestera_port *port)
478{
479 devlink_port_type_clear(&port->dl_port);
480}
481
482struct devlink_port *prestera_devlink_get_port(struct net_device *dev)
483{
484 struct prestera_port *port = netdev_priv(dev);
485
486 return &port->dl_port;
487}
488
489static int prestera_devlink_traps_register(struct prestera_switch *sw)
490{
491 const u32 groups_count = ARRAY_SIZE(prestera_trap_groups_arr);
492 const u32 traps_count = ARRAY_SIZE(prestera_trap_items_arr);
493 struct devlink *devlink = priv_to_devlink(sw);
494 struct prestera_trap_data *trap_data;
495 struct prestera_trap *prestera_trap;
496 int err, i;
497
498 trap_data = kzalloc(sizeof(*trap_data), GFP_KERNEL);
499 if (!trap_data)
500 return -ENOMEM;
501
502 trap_data->trap_items_arr = kcalloc(traps_count,
503 sizeof(struct prestera_trap_item),
504 GFP_KERNEL);
505 if (!trap_data->trap_items_arr) {
506 err = -ENOMEM;
507 goto err_trap_items_alloc;
508 }
509
510 trap_data->sw = sw;
511 trap_data->traps_count = traps_count;
512 sw->trap_data = trap_data;
513
514 err = devlink_trap_groups_register(devlink, prestera_trap_groups_arr,
515 groups_count);
516 if (err)
517 goto err_groups_register;
518
519 for (i = 0; i < traps_count; i++) {
520 prestera_trap = &prestera_trap_items_arr[i];
521 err = devlink_traps_register(devlink, &prestera_trap->trap, 1,
522 sw);
523 if (err)
524 goto err_trap_register;
525 }
526
527 return 0;
528
529err_trap_register:
530 for (i--; i >= 0; i--) {
531 prestera_trap = &prestera_trap_items_arr[i];
532 devlink_traps_unregister(devlink, &prestera_trap->trap, 1);
533 }
534 devlink_trap_groups_unregister(devlink, prestera_trap_groups_arr,
535 groups_count);
536err_groups_register:
537 kfree(trap_data->trap_items_arr);
538err_trap_items_alloc:
539 kfree(trap_data);
540 return err;
541}
542
543static struct prestera_trap_item *
544prestera_get_trap_item_by_cpu_code(struct prestera_switch *sw, u8 cpu_code)
545{
546 struct prestera_trap_data *trap_data = sw->trap_data;
547 struct prestera_trap *prestera_trap;
548 int i;
549
550 for (i = 0; i < trap_data->traps_count; i++) {
551 prestera_trap = &prestera_trap_items_arr[i];
552 if (cpu_code == prestera_trap->cpu_code)
553 return &trap_data->trap_items_arr[i];
554 }
555
556 return NULL;
557}
558
559void prestera_devlink_trap_report(struct prestera_port *port,
560 struct sk_buff *skb, u8 cpu_code)
561{
562 struct prestera_trap_item *trap_item;
563 struct devlink *devlink;
564
565 devlink = port->dl_port.devlink;
566
567 trap_item = prestera_get_trap_item_by_cpu_code(port->sw, cpu_code);
568 if (unlikely(!trap_item))
569 return;
570
571 devlink_trap_report(devlink, skb, trap_item->trap_ctx,
572 &port->dl_port, NULL);
573}
574
575static struct prestera_trap_item *
576prestera_devlink_trap_item_lookup(struct prestera_switch *sw, u16 trap_id)
577{
578 struct prestera_trap_data *trap_data = sw->trap_data;
579 int i;
580
581 for (i = 0; i < ARRAY_SIZE(prestera_trap_items_arr); i++) {
582 if (prestera_trap_items_arr[i].trap.id == trap_id)
583 return &trap_data->trap_items_arr[i];
584 }
585
586 return NULL;
587}
588
589static int prestera_trap_init(struct devlink *devlink,
590 const struct devlink_trap *trap, void *trap_ctx)
591{
592 struct prestera_switch *sw = devlink_priv(devlink);
593 struct prestera_trap_item *trap_item;
594
595 trap_item = prestera_devlink_trap_item_lookup(sw, trap->id);
596 if (WARN_ON(!trap_item))
597 return -EINVAL;
598
599 trap_item->trap_ctx = trap_ctx;
600 trap_item->action = trap->init_action;
601
602 return 0;
603}
604
605static int prestera_trap_action_set(struct devlink *devlink,
606 const struct devlink_trap *trap,
607 enum devlink_trap_action action,
608 struct netlink_ext_ack *extack)
609{
610
611 return -EOPNOTSUPP;
612}
613
614static int prestera_drop_counter_get(struct devlink *devlink,
615 const struct devlink_trap *trap,
616 u64 *p_drops)
617{
618 struct prestera_switch *sw = devlink_priv(devlink);
619 enum prestera_hw_cpu_code_cnt_t cpu_code_type =
620 PRESTERA_HW_CPU_CODE_CNT_TYPE_DROP;
621 struct prestera_trap *prestera_trap =
622 container_of(trap, struct prestera_trap, trap);
623
624 return prestera_hw_cpu_code_counters_get(sw, prestera_trap->cpu_code,
625 cpu_code_type, p_drops);
626}
627
628static void prestera_devlink_traps_fini(struct prestera_switch *sw)
629{
630 struct devlink *dl = priv_to_devlink(sw);
631 const struct devlink_trap *trap;
632 int i;
633
634 for (i = 0; i < ARRAY_SIZE(prestera_trap_items_arr); ++i) {
635 trap = &prestera_trap_items_arr[i].trap;
636 devlink_traps_unregister(dl, trap, 1);
637 }
638
639 devlink_trap_groups_unregister(dl, prestera_trap_groups_arr,
640 ARRAY_SIZE(prestera_trap_groups_arr));
641}
642