prestera_devlink.c 16 KB

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