134dd1710SVadym Kochan // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 234dd1710SVadym Kochan /* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */ 334dd1710SVadym Kochan 434dd1710SVadym Kochan #include <net/devlink.h> 534dd1710SVadym Kochan 634dd1710SVadym Kochan #include "prestera_devlink.h" 7a80cf955SOleksandr Mazur #include "prestera_hw.h" 834dd1710SVadym Kochan 90a9003f4SOleksandr Mazur /* All driver-specific traps must be documented in 100a9003f4SOleksandr Mazur * Documentation/networking/devlink/prestera.rst 110a9003f4SOleksandr Mazur */ 120a9003f4SOleksandr Mazur enum { 130a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_BASE = DEVLINK_TRAP_GENERIC_ID_MAX, 140a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ARP_BC, 150a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IS_IS, 160a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_OSPF, 170a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IP_BC_MAC, 180a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ROUTER_MC, 190a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_VRRP, 200a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_DHCP, 210a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_MAC_TO_ME, 220a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IPV4_OPTIONS, 230a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IP_DEFAULT_ROUTE, 240a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IP_TO_ME, 250a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IPV4_ICMP_REDIRECT, 260a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_0, 270a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_1, 280a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_2, 290a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_3, 300a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_4, 310a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_5, 320a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_6, 330a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_7, 340a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_BGP, 350a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_SSH, 360a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_TELNET, 370a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ICMP, 38a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_MET_RED, 39a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IP_SIP_IS_ZERO, 40a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IP_UC_DIP_DA_MISMATCH, 41a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ILLEGAL_IPV4_HDR, 42a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ILLEGAL_IP_ADDR, 43a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_INVALID_SA, 44a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_LOCAL_PORT, 45a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_PORT_NO_VLAN, 46a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_RXDMA_DROP, 470a9003f4SOleksandr Mazur }; 480a9003f4SOleksandr Mazur 490a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ARP_BC \ 500a9003f4SOleksandr Mazur "arp_bc" 510a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IS_IS \ 520a9003f4SOleksandr Mazur "is_is" 530a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_OSPF \ 540a9003f4SOleksandr Mazur "ospf" 550a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IP_BC_MAC \ 560a9003f4SOleksandr Mazur "ip_bc_mac" 570a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ROUTER_MC \ 580a9003f4SOleksandr Mazur "router_mc" 590a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_VRRP \ 600a9003f4SOleksandr Mazur "vrrp" 610a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_DHCP \ 620a9003f4SOleksandr Mazur "dhcp" 630a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_MAC_TO_ME \ 640a9003f4SOleksandr Mazur "mac_to_me" 650a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IPV4_OPTIONS \ 660a9003f4SOleksandr Mazur "ipv4_options" 670a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IP_DEFAULT_ROUTE \ 680a9003f4SOleksandr Mazur "ip_default_route" 690a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IP_TO_ME \ 700a9003f4SOleksandr Mazur "ip_to_me" 710a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IPV4_ICMP_REDIRECT \ 720a9003f4SOleksandr Mazur "ipv4_icmp_redirect" 730a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_0 \ 740a9003f4SOleksandr Mazur "acl_code_0" 750a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_1 \ 760a9003f4SOleksandr Mazur "acl_code_1" 770a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_2 \ 780a9003f4SOleksandr Mazur "acl_code_2" 790a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_3 \ 800a9003f4SOleksandr Mazur "acl_code_3" 810a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_4 \ 820a9003f4SOleksandr Mazur "acl_code_4" 830a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_5 \ 840a9003f4SOleksandr Mazur "acl_code_5" 850a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_6 \ 860a9003f4SOleksandr Mazur "acl_code_6" 870a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_7 \ 880a9003f4SOleksandr Mazur "acl_code_7" 890a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_BGP \ 900a9003f4SOleksandr Mazur "bgp" 910a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_SSH \ 920a9003f4SOleksandr Mazur "ssh" 930a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_TELNET \ 940a9003f4SOleksandr Mazur "telnet" 950a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ICMP \ 960a9003f4SOleksandr Mazur "icmp" 97a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_RXDMA_DROP \ 98a80cf955SOleksandr Mazur "rxdma_drop" 99a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_PORT_NO_VLAN \ 100a80cf955SOleksandr Mazur "port_no_vlan" 101a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_LOCAL_PORT \ 102a80cf955SOleksandr Mazur "local_port" 103a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_INVALID_SA \ 104a80cf955SOleksandr Mazur "invalid_sa" 105a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ILLEGAL_IP_ADDR \ 106a80cf955SOleksandr Mazur "illegal_ip_addr" 107a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ILLEGAL_IPV4_HDR \ 108a80cf955SOleksandr Mazur "illegal_ipv4_hdr" 109a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IP_UC_DIP_DA_MISMATCH \ 110a80cf955SOleksandr Mazur "ip_uc_dip_da_mismatch" 111a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IP_SIP_IS_ZERO \ 112a80cf955SOleksandr Mazur "ip_sip_is_zero" 113a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_MET_RED \ 114a80cf955SOleksandr Mazur "met_red" 1150a9003f4SOleksandr Mazur 1160a9003f4SOleksandr Mazur struct prestera_trap { 1170a9003f4SOleksandr Mazur struct devlink_trap trap; 1180a9003f4SOleksandr Mazur u8 cpu_code; 1190a9003f4SOleksandr Mazur }; 1200a9003f4SOleksandr Mazur 1210a9003f4SOleksandr Mazur struct prestera_trap_item { 1220a9003f4SOleksandr Mazur enum devlink_trap_action action; 1230a9003f4SOleksandr Mazur void *trap_ctx; 1240a9003f4SOleksandr Mazur }; 1250a9003f4SOleksandr Mazur 1260a9003f4SOleksandr Mazur struct prestera_trap_data { 1270a9003f4SOleksandr Mazur struct prestera_switch *sw; 1280a9003f4SOleksandr Mazur struct prestera_trap_item *trap_items_arr; 1290a9003f4SOleksandr Mazur u32 traps_count; 1300a9003f4SOleksandr Mazur }; 1310a9003f4SOleksandr Mazur 1320a9003f4SOleksandr Mazur #define PRESTERA_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT 1330a9003f4SOleksandr Mazur 1340a9003f4SOleksandr Mazur #define PRESTERA_TRAP_CONTROL(_id, _group_id, _action) \ 1350a9003f4SOleksandr Mazur DEVLINK_TRAP_GENERIC(CONTROL, _action, _id, \ 1360a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 1370a9003f4SOleksandr Mazur PRESTERA_TRAP_METADATA) 1380a9003f4SOleksandr Mazur 1390a9003f4SOleksandr Mazur #define PRESTERA_TRAP_DRIVER_CONTROL(_id, _group_id) \ 1400a9003f4SOleksandr Mazur DEVLINK_TRAP_DRIVER(CONTROL, TRAP, DEVLINK_PRESTERA_TRAP_ID_##_id, \ 1410a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_NAME_##_id, \ 1420a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 1430a9003f4SOleksandr Mazur PRESTERA_TRAP_METADATA) 1440a9003f4SOleksandr Mazur 1450a9003f4SOleksandr Mazur #define PRESTERA_TRAP_EXCEPTION(_id, _group_id) \ 1460a9003f4SOleksandr Mazur DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id, \ 1470a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 1480a9003f4SOleksandr Mazur PRESTERA_TRAP_METADATA) 1490a9003f4SOleksandr Mazur 1500a9003f4SOleksandr Mazur #define PRESTERA_TRAP_DRIVER_EXCEPTION(_id, _group_id) \ 1510a9003f4SOleksandr Mazur DEVLINK_TRAP_DRIVER(EXCEPTION, TRAP, DEVLINK_PRESTERA_TRAP_ID_##_id, \ 1520a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_NAME_##_id, \ 1530a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 1540a9003f4SOleksandr Mazur PRESTERA_TRAP_METADATA) 1550a9003f4SOleksandr Mazur 156a80cf955SOleksandr Mazur #define PRESTERA_TRAP_DRIVER_DROP(_id, _group_id) \ 157a80cf955SOleksandr Mazur DEVLINK_TRAP_DRIVER(DROP, DROP, DEVLINK_PRESTERA_TRAP_ID_##_id, \ 158a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_NAME_##_id, \ 159a80cf955SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 160a80cf955SOleksandr Mazur PRESTERA_TRAP_METADATA) 161a80cf955SOleksandr Mazur 1620a9003f4SOleksandr Mazur static const struct devlink_trap_group prestera_trap_groups_arr[] = { 1630a9003f4SOleksandr Mazur /* No policer is associated with following groups (policerid == 0)*/ 1640a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0), 1650a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS, 0), 1660a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(L3_EXCEPTIONS, 0), 1670a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(NEIGH_DISCOVERY, 0), 1680a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(ACL_TRAP, 0), 1690a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS, 0), 1700a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(ACL_SAMPLE, 0), 1710a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(OSPF, 0), 1720a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(STP, 0), 1730a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(LACP, 0), 1740a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(LLDP, 0), 1750a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(VRRP, 0), 1760a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(DHCP, 0), 1770a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(BGP, 0), 1780a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(LOCAL_DELIVERY, 0), 179a80cf955SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS, 0), 1800a9003f4SOleksandr Mazur }; 1810a9003f4SOleksandr Mazur 1820a9003f4SOleksandr Mazur /* Initialize trap list, as well as associate CPU code with them. */ 1830a9003f4SOleksandr Mazur static struct prestera_trap prestera_trap_items_arr[] = { 1840a9003f4SOleksandr Mazur { 1850a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ARP_BC, NEIGH_DISCOVERY), 1860a9003f4SOleksandr Mazur .cpu_code = 5, 1870a9003f4SOleksandr Mazur }, 1880a9003f4SOleksandr Mazur { 1890a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(IS_IS, LOCAL_DELIVERY), 1900a9003f4SOleksandr Mazur .cpu_code = 13, 1910a9003f4SOleksandr Mazur }, 1920a9003f4SOleksandr Mazur { 1930a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(OSPF, OSPF), 1940a9003f4SOleksandr Mazur .cpu_code = 16, 1950a9003f4SOleksandr Mazur }, 1960a9003f4SOleksandr Mazur { 1970a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(IP_BC_MAC, LOCAL_DELIVERY), 1980a9003f4SOleksandr Mazur .cpu_code = 19, 1990a9003f4SOleksandr Mazur }, 2000a9003f4SOleksandr Mazur { 2010a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_CONTROL(STP, STP, TRAP), 2020a9003f4SOleksandr Mazur .cpu_code = 26, 2030a9003f4SOleksandr Mazur }, 2040a9003f4SOleksandr Mazur { 2050a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_CONTROL(LACP, LACP, TRAP), 2060a9003f4SOleksandr Mazur .cpu_code = 27, 2070a9003f4SOleksandr Mazur }, 2080a9003f4SOleksandr Mazur { 2090a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_CONTROL(LLDP, LLDP, TRAP), 2100a9003f4SOleksandr Mazur .cpu_code = 28, 2110a9003f4SOleksandr Mazur }, 2120a9003f4SOleksandr Mazur { 2130a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ROUTER_MC, LOCAL_DELIVERY), 2140a9003f4SOleksandr Mazur .cpu_code = 29, 2150a9003f4SOleksandr Mazur }, 2160a9003f4SOleksandr Mazur { 2170a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(VRRP, VRRP), 2180a9003f4SOleksandr Mazur .cpu_code = 30, 2190a9003f4SOleksandr Mazur }, 2200a9003f4SOleksandr Mazur { 2210a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(DHCP, DHCP), 2220a9003f4SOleksandr Mazur .cpu_code = 33, 2230a9003f4SOleksandr Mazur }, 2240a9003f4SOleksandr Mazur { 2250a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_EXCEPTION(MTU_ERROR, L3_EXCEPTIONS), 2260a9003f4SOleksandr Mazur .cpu_code = 63, 2270a9003f4SOleksandr Mazur }, 2280a9003f4SOleksandr Mazur { 2290a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(MAC_TO_ME, LOCAL_DELIVERY), 2300a9003f4SOleksandr Mazur .cpu_code = 65, 2310a9003f4SOleksandr Mazur }, 2320a9003f4SOleksandr Mazur { 2330a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_EXCEPTION(TTL_ERROR, L3_EXCEPTIONS), 2340a9003f4SOleksandr Mazur .cpu_code = 133, 2350a9003f4SOleksandr Mazur }, 2360a9003f4SOleksandr Mazur { 2370a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_EXCEPTION(IPV4_OPTIONS, 2380a9003f4SOleksandr Mazur L3_EXCEPTIONS), 2390a9003f4SOleksandr Mazur .cpu_code = 141, 2400a9003f4SOleksandr Mazur }, 2410a9003f4SOleksandr Mazur { 2420a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(IP_DEFAULT_ROUTE, 2430a9003f4SOleksandr Mazur LOCAL_DELIVERY), 2440a9003f4SOleksandr Mazur .cpu_code = 160, 2450a9003f4SOleksandr Mazur }, 2460a9003f4SOleksandr Mazur { 2470a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_CONTROL(LOCAL_ROUTE, LOCAL_DELIVERY, 2480a9003f4SOleksandr Mazur TRAP), 2490a9003f4SOleksandr Mazur .cpu_code = 161, 2500a9003f4SOleksandr Mazur }, 2510a9003f4SOleksandr Mazur { 2520a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_EXCEPTION(IPV4_ICMP_REDIRECT, 2530a9003f4SOleksandr Mazur L3_EXCEPTIONS), 2540a9003f4SOleksandr Mazur .cpu_code = 180, 2550a9003f4SOleksandr Mazur }, 2560a9003f4SOleksandr Mazur { 2570a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_CONTROL(ARP_RESPONSE, NEIGH_DISCOVERY, 2580a9003f4SOleksandr Mazur TRAP), 2590a9003f4SOleksandr Mazur .cpu_code = 188, 2600a9003f4SOleksandr Mazur }, 2610a9003f4SOleksandr Mazur { 2620a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_0, ACL_TRAP), 2630a9003f4SOleksandr Mazur .cpu_code = 192, 2640a9003f4SOleksandr Mazur }, 2650a9003f4SOleksandr Mazur { 2660a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_1, ACL_TRAP), 2670a9003f4SOleksandr Mazur .cpu_code = 193, 2680a9003f4SOleksandr Mazur }, 2690a9003f4SOleksandr Mazur { 2700a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_2, ACL_TRAP), 2710a9003f4SOleksandr Mazur .cpu_code = 194, 2720a9003f4SOleksandr Mazur }, 2730a9003f4SOleksandr Mazur { 2740a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_3, ACL_TRAP), 2750a9003f4SOleksandr Mazur .cpu_code = 195, 2760a9003f4SOleksandr Mazur }, 2770a9003f4SOleksandr Mazur { 2780a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_4, ACL_TRAP), 2790a9003f4SOleksandr Mazur .cpu_code = 196, 2800a9003f4SOleksandr Mazur }, 2810a9003f4SOleksandr Mazur { 2820a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_5, ACL_TRAP), 2830a9003f4SOleksandr Mazur .cpu_code = 197, 2840a9003f4SOleksandr Mazur }, 2850a9003f4SOleksandr Mazur { 2860a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_6, ACL_TRAP), 2870a9003f4SOleksandr Mazur .cpu_code = 198, 2880a9003f4SOleksandr Mazur }, 2890a9003f4SOleksandr Mazur { 2900a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_7, ACL_TRAP), 2910a9003f4SOleksandr Mazur .cpu_code = 199, 2920a9003f4SOleksandr Mazur }, 2930a9003f4SOleksandr Mazur { 2940a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(BGP, BGP), 2950a9003f4SOleksandr Mazur .cpu_code = 206, 2960a9003f4SOleksandr Mazur }, 2970a9003f4SOleksandr Mazur { 2980a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(SSH, LOCAL_DELIVERY), 2990a9003f4SOleksandr Mazur .cpu_code = 207, 3000a9003f4SOleksandr Mazur }, 3010a9003f4SOleksandr Mazur { 3020a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(TELNET, LOCAL_DELIVERY), 3030a9003f4SOleksandr Mazur .cpu_code = 208, 3040a9003f4SOleksandr Mazur }, 3050a9003f4SOleksandr Mazur { 3060a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ICMP, LOCAL_DELIVERY), 3070a9003f4SOleksandr Mazur .cpu_code = 209, 3080a9003f4SOleksandr Mazur }, 309a80cf955SOleksandr Mazur { 310a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(RXDMA_DROP, BUFFER_DROPS), 311a80cf955SOleksandr Mazur .cpu_code = 37, 312a80cf955SOleksandr Mazur }, 313a80cf955SOleksandr Mazur { 314a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(PORT_NO_VLAN, L2_DROPS), 315a80cf955SOleksandr Mazur .cpu_code = 39, 316a80cf955SOleksandr Mazur }, 317a80cf955SOleksandr Mazur { 318a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(LOCAL_PORT, L2_DROPS), 319a80cf955SOleksandr Mazur .cpu_code = 56, 320a80cf955SOleksandr Mazur }, 321a80cf955SOleksandr Mazur { 322a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(INVALID_SA, L2_DROPS), 323a80cf955SOleksandr Mazur .cpu_code = 60, 324a80cf955SOleksandr Mazur }, 325a80cf955SOleksandr Mazur { 326a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(ILLEGAL_IP_ADDR, L3_DROPS), 327a80cf955SOleksandr Mazur .cpu_code = 136, 328a80cf955SOleksandr Mazur }, 329a80cf955SOleksandr Mazur { 330a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(ILLEGAL_IPV4_HDR, L3_DROPS), 331a80cf955SOleksandr Mazur .cpu_code = 137, 332a80cf955SOleksandr Mazur }, 333a80cf955SOleksandr Mazur { 334a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(IP_UC_DIP_DA_MISMATCH, 335a80cf955SOleksandr Mazur L3_DROPS), 336a80cf955SOleksandr Mazur .cpu_code = 138, 337a80cf955SOleksandr Mazur }, 338a80cf955SOleksandr Mazur { 339a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(IP_SIP_IS_ZERO, L3_DROPS), 340a80cf955SOleksandr Mazur .cpu_code = 145, 341a80cf955SOleksandr Mazur }, 342a80cf955SOleksandr Mazur { 343a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(MET_RED, BUFFER_DROPS), 344a80cf955SOleksandr Mazur .cpu_code = 185, 345a80cf955SOleksandr Mazur }, 3460a9003f4SOleksandr Mazur }; 3470a9003f4SOleksandr Mazur 348a80cf955SOleksandr Mazur static int prestera_drop_counter_get(struct devlink *devlink, 349a80cf955SOleksandr Mazur const struct devlink_trap *trap, 350a80cf955SOleksandr Mazur u64 *p_drops); 351a80cf955SOleksandr Mazur 35234dd1710SVadym Kochan static int prestera_dl_info_get(struct devlink *dl, 35334dd1710SVadym Kochan struct devlink_info_req *req, 35434dd1710SVadym Kochan struct netlink_ext_ack *extack) 35534dd1710SVadym Kochan { 35634dd1710SVadym Kochan struct prestera_switch *sw = devlink_priv(dl); 35734dd1710SVadym Kochan char buf[16]; 35834dd1710SVadym Kochan int err; 35934dd1710SVadym Kochan 36034dd1710SVadym Kochan err = devlink_info_driver_name_put(req, PRESTERA_DRV_NAME); 36134dd1710SVadym Kochan if (err) 36234dd1710SVadym Kochan return err; 36334dd1710SVadym Kochan 36434dd1710SVadym Kochan snprintf(buf, sizeof(buf), "%d.%d.%d", 36534dd1710SVadym Kochan sw->dev->fw_rev.maj, 36634dd1710SVadym Kochan sw->dev->fw_rev.min, 36734dd1710SVadym Kochan sw->dev->fw_rev.sub); 36834dd1710SVadym Kochan 36934dd1710SVadym Kochan return devlink_info_version_running_put(req, 37034dd1710SVadym Kochan DEVLINK_INFO_VERSION_GENERIC_FW, 37134dd1710SVadym Kochan buf); 37234dd1710SVadym Kochan } 37334dd1710SVadym Kochan 3740a9003f4SOleksandr Mazur static int prestera_trap_init(struct devlink *devlink, 3750a9003f4SOleksandr Mazur const struct devlink_trap *trap, void *trap_ctx); 3760a9003f4SOleksandr Mazur 3770a9003f4SOleksandr Mazur static int prestera_trap_action_set(struct devlink *devlink, 3780a9003f4SOleksandr Mazur const struct devlink_trap *trap, 3790a9003f4SOleksandr Mazur enum devlink_trap_action action, 3800a9003f4SOleksandr Mazur struct netlink_ext_ack *extack); 3810a9003f4SOleksandr Mazur 38234dd1710SVadym Kochan static const struct devlink_ops prestera_dl_ops = { 38334dd1710SVadym Kochan .info_get = prestera_dl_info_get, 3840a9003f4SOleksandr Mazur .trap_init = prestera_trap_init, 3850a9003f4SOleksandr Mazur .trap_action_set = prestera_trap_action_set, 386a80cf955SOleksandr Mazur .trap_drop_counter_get = prestera_drop_counter_get, 38734dd1710SVadym Kochan }; 38834dd1710SVadym Kochan 389919d13a7SLeon Romanovsky struct prestera_switch *prestera_devlink_alloc(struct prestera_device *dev) 39034dd1710SVadym Kochan { 39134dd1710SVadym Kochan struct devlink *dl; 39234dd1710SVadym Kochan 393919d13a7SLeon Romanovsky dl = devlink_alloc(&prestera_dl_ops, sizeof(struct prestera_switch), 394919d13a7SLeon Romanovsky dev->dev); 39534dd1710SVadym Kochan 39634dd1710SVadym Kochan return devlink_priv(dl); 39734dd1710SVadym Kochan } 39834dd1710SVadym Kochan 39934dd1710SVadym Kochan void prestera_devlink_free(struct prestera_switch *sw) 40034dd1710SVadym Kochan { 40134dd1710SVadym Kochan struct devlink *dl = priv_to_devlink(sw); 40234dd1710SVadym Kochan 40334dd1710SVadym Kochan devlink_free(dl); 40434dd1710SVadym Kochan } 40534dd1710SVadym Kochan 406*4beb0c24SLeon Romanovsky void prestera_devlink_register(struct prestera_switch *sw) 40734dd1710SVadym Kochan { 40834dd1710SVadym Kochan struct devlink *dl = priv_to_devlink(sw); 40934dd1710SVadym Kochan 410db4278c5SLeon Romanovsky devlink_register(dl); 4110a9003f4SOleksandr Mazur } 4120a9003f4SOleksandr Mazur 41334dd1710SVadym Kochan void prestera_devlink_unregister(struct prestera_switch *sw) 41434dd1710SVadym Kochan { 41534dd1710SVadym Kochan struct devlink *dl = priv_to_devlink(sw); 41634dd1710SVadym Kochan 41734dd1710SVadym Kochan devlink_unregister(dl); 41834dd1710SVadym Kochan } 41934dd1710SVadym Kochan 42034dd1710SVadym Kochan int prestera_devlink_port_register(struct prestera_port *port) 42134dd1710SVadym Kochan { 42234dd1710SVadym Kochan struct prestera_switch *sw = port->sw; 42334dd1710SVadym Kochan struct devlink *dl = priv_to_devlink(sw); 42434dd1710SVadym Kochan struct devlink_port_attrs attrs = {}; 42534dd1710SVadym Kochan int err; 42634dd1710SVadym Kochan 42734dd1710SVadym Kochan attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; 42834dd1710SVadym Kochan attrs.phys.port_number = port->fp_id; 42934dd1710SVadym Kochan attrs.switch_id.id_len = sizeof(sw->id); 43034dd1710SVadym Kochan memcpy(attrs.switch_id.id, &sw->id, attrs.switch_id.id_len); 43134dd1710SVadym Kochan 43234dd1710SVadym Kochan devlink_port_attrs_set(&port->dl_port, &attrs); 43334dd1710SVadym Kochan 43434dd1710SVadym Kochan err = devlink_port_register(dl, &port->dl_port, port->fp_id); 43534dd1710SVadym Kochan if (err) { 43634dd1710SVadym Kochan dev_err(prestera_dev(sw), "devlink_port_register failed: %d\n", err); 43734dd1710SVadym Kochan return err; 43834dd1710SVadym Kochan } 43934dd1710SVadym Kochan 44034dd1710SVadym Kochan return 0; 44134dd1710SVadym Kochan } 44234dd1710SVadym Kochan 44334dd1710SVadym Kochan void prestera_devlink_port_unregister(struct prestera_port *port) 44434dd1710SVadym Kochan { 44534dd1710SVadym Kochan devlink_port_unregister(&port->dl_port); 44634dd1710SVadym Kochan } 44734dd1710SVadym Kochan 44834dd1710SVadym Kochan void prestera_devlink_port_set(struct prestera_port *port) 44934dd1710SVadym Kochan { 45034dd1710SVadym Kochan devlink_port_type_eth_set(&port->dl_port, port->dev); 45134dd1710SVadym Kochan } 45234dd1710SVadym Kochan 45334dd1710SVadym Kochan void prestera_devlink_port_clear(struct prestera_port *port) 45434dd1710SVadym Kochan { 45534dd1710SVadym Kochan devlink_port_type_clear(&port->dl_port); 45634dd1710SVadym Kochan } 45734dd1710SVadym Kochan 45834dd1710SVadym Kochan struct devlink_port *prestera_devlink_get_port(struct net_device *dev) 45934dd1710SVadym Kochan { 46034dd1710SVadym Kochan struct prestera_port *port = netdev_priv(dev); 46134dd1710SVadym Kochan 46234dd1710SVadym Kochan return &port->dl_port; 46334dd1710SVadym Kochan } 4640a9003f4SOleksandr Mazur 465*4beb0c24SLeon Romanovsky int prestera_devlink_traps_register(struct prestera_switch *sw) 4660a9003f4SOleksandr Mazur { 4670a9003f4SOleksandr Mazur const u32 groups_count = ARRAY_SIZE(prestera_trap_groups_arr); 4680a9003f4SOleksandr Mazur const u32 traps_count = ARRAY_SIZE(prestera_trap_items_arr); 4690a9003f4SOleksandr Mazur struct devlink *devlink = priv_to_devlink(sw); 4700a9003f4SOleksandr Mazur struct prestera_trap_data *trap_data; 4710a9003f4SOleksandr Mazur struct prestera_trap *prestera_trap; 4720a9003f4SOleksandr Mazur int err, i; 4730a9003f4SOleksandr Mazur 4740a9003f4SOleksandr Mazur trap_data = kzalloc(sizeof(*trap_data), GFP_KERNEL); 4750a9003f4SOleksandr Mazur if (!trap_data) 4760a9003f4SOleksandr Mazur return -ENOMEM; 4770a9003f4SOleksandr Mazur 4780a9003f4SOleksandr Mazur trap_data->trap_items_arr = kcalloc(traps_count, 4790a9003f4SOleksandr Mazur sizeof(struct prestera_trap_item), 4800a9003f4SOleksandr Mazur GFP_KERNEL); 4810a9003f4SOleksandr Mazur if (!trap_data->trap_items_arr) { 4820a9003f4SOleksandr Mazur err = -ENOMEM; 4830a9003f4SOleksandr Mazur goto err_trap_items_alloc; 4840a9003f4SOleksandr Mazur } 4850a9003f4SOleksandr Mazur 4860a9003f4SOleksandr Mazur trap_data->sw = sw; 4870a9003f4SOleksandr Mazur trap_data->traps_count = traps_count; 4880a9003f4SOleksandr Mazur sw->trap_data = trap_data; 4890a9003f4SOleksandr Mazur 4900a9003f4SOleksandr Mazur err = devlink_trap_groups_register(devlink, prestera_trap_groups_arr, 4910a9003f4SOleksandr Mazur groups_count); 4920a9003f4SOleksandr Mazur if (err) 4930a9003f4SOleksandr Mazur goto err_groups_register; 4940a9003f4SOleksandr Mazur 4950a9003f4SOleksandr Mazur for (i = 0; i < traps_count; i++) { 4960a9003f4SOleksandr Mazur prestera_trap = &prestera_trap_items_arr[i]; 4970a9003f4SOleksandr Mazur err = devlink_traps_register(devlink, &prestera_trap->trap, 1, 4980a9003f4SOleksandr Mazur sw); 4990a9003f4SOleksandr Mazur if (err) 5000a9003f4SOleksandr Mazur goto err_trap_register; 5010a9003f4SOleksandr Mazur } 5020a9003f4SOleksandr Mazur 5030a9003f4SOleksandr Mazur return 0; 5040a9003f4SOleksandr Mazur 5050a9003f4SOleksandr Mazur err_trap_register: 5060a9003f4SOleksandr Mazur for (i--; i >= 0; i--) { 5070a9003f4SOleksandr Mazur prestera_trap = &prestera_trap_items_arr[i]; 5080a9003f4SOleksandr Mazur devlink_traps_unregister(devlink, &prestera_trap->trap, 1); 5090a9003f4SOleksandr Mazur } 51013a9c4acSLeon Romanovsky devlink_trap_groups_unregister(devlink, prestera_trap_groups_arr, 51113a9c4acSLeon Romanovsky groups_count); 5120a9003f4SOleksandr Mazur err_groups_register: 5130a9003f4SOleksandr Mazur kfree(trap_data->trap_items_arr); 5140a9003f4SOleksandr Mazur err_trap_items_alloc: 5150a9003f4SOleksandr Mazur kfree(trap_data); 5160a9003f4SOleksandr Mazur return err; 5170a9003f4SOleksandr Mazur } 5180a9003f4SOleksandr Mazur 5190a9003f4SOleksandr Mazur static struct prestera_trap_item * 5200a9003f4SOleksandr Mazur prestera_get_trap_item_by_cpu_code(struct prestera_switch *sw, u8 cpu_code) 5210a9003f4SOleksandr Mazur { 5220a9003f4SOleksandr Mazur struct prestera_trap_data *trap_data = sw->trap_data; 5230a9003f4SOleksandr Mazur struct prestera_trap *prestera_trap; 5240a9003f4SOleksandr Mazur int i; 5250a9003f4SOleksandr Mazur 5260a9003f4SOleksandr Mazur for (i = 0; i < trap_data->traps_count; i++) { 5270a9003f4SOleksandr Mazur prestera_trap = &prestera_trap_items_arr[i]; 5280a9003f4SOleksandr Mazur if (cpu_code == prestera_trap->cpu_code) 5290a9003f4SOleksandr Mazur return &trap_data->trap_items_arr[i]; 5300a9003f4SOleksandr Mazur } 5310a9003f4SOleksandr Mazur 5320a9003f4SOleksandr Mazur return NULL; 5330a9003f4SOleksandr Mazur } 5340a9003f4SOleksandr Mazur 5350a9003f4SOleksandr Mazur void prestera_devlink_trap_report(struct prestera_port *port, 5360a9003f4SOleksandr Mazur struct sk_buff *skb, u8 cpu_code) 5370a9003f4SOleksandr Mazur { 5380a9003f4SOleksandr Mazur struct prestera_trap_item *trap_item; 5390a9003f4SOleksandr Mazur struct devlink *devlink; 5400a9003f4SOleksandr Mazur 5410a9003f4SOleksandr Mazur devlink = port->dl_port.devlink; 5420a9003f4SOleksandr Mazur 5430a9003f4SOleksandr Mazur trap_item = prestera_get_trap_item_by_cpu_code(port->sw, cpu_code); 5440a9003f4SOleksandr Mazur if (unlikely(!trap_item)) 5450a9003f4SOleksandr Mazur return; 5460a9003f4SOleksandr Mazur 5470a9003f4SOleksandr Mazur devlink_trap_report(devlink, skb, trap_item->trap_ctx, 5480a9003f4SOleksandr Mazur &port->dl_port, NULL); 5490a9003f4SOleksandr Mazur } 5500a9003f4SOleksandr Mazur 5510a9003f4SOleksandr Mazur static struct prestera_trap_item * 5520a9003f4SOleksandr Mazur prestera_devlink_trap_item_lookup(struct prestera_switch *sw, u16 trap_id) 5530a9003f4SOleksandr Mazur { 5540a9003f4SOleksandr Mazur struct prestera_trap_data *trap_data = sw->trap_data; 5550a9003f4SOleksandr Mazur int i; 5560a9003f4SOleksandr Mazur 5570a9003f4SOleksandr Mazur for (i = 0; i < ARRAY_SIZE(prestera_trap_items_arr); i++) { 5580a9003f4SOleksandr Mazur if (prestera_trap_items_arr[i].trap.id == trap_id) 5590a9003f4SOleksandr Mazur return &trap_data->trap_items_arr[i]; 5600a9003f4SOleksandr Mazur } 5610a9003f4SOleksandr Mazur 5620a9003f4SOleksandr Mazur return NULL; 5630a9003f4SOleksandr Mazur } 5640a9003f4SOleksandr Mazur 5650a9003f4SOleksandr Mazur static int prestera_trap_init(struct devlink *devlink, 5660a9003f4SOleksandr Mazur const struct devlink_trap *trap, void *trap_ctx) 5670a9003f4SOleksandr Mazur { 5680a9003f4SOleksandr Mazur struct prestera_switch *sw = devlink_priv(devlink); 5690a9003f4SOleksandr Mazur struct prestera_trap_item *trap_item; 5700a9003f4SOleksandr Mazur 5710a9003f4SOleksandr Mazur trap_item = prestera_devlink_trap_item_lookup(sw, trap->id); 5720a9003f4SOleksandr Mazur if (WARN_ON(!trap_item)) 5730a9003f4SOleksandr Mazur return -EINVAL; 5740a9003f4SOleksandr Mazur 5750a9003f4SOleksandr Mazur trap_item->trap_ctx = trap_ctx; 5760a9003f4SOleksandr Mazur trap_item->action = trap->init_action; 5770a9003f4SOleksandr Mazur 5780a9003f4SOleksandr Mazur return 0; 5790a9003f4SOleksandr Mazur } 5800a9003f4SOleksandr Mazur 5810a9003f4SOleksandr Mazur static int prestera_trap_action_set(struct devlink *devlink, 5820a9003f4SOleksandr Mazur const struct devlink_trap *trap, 5830a9003f4SOleksandr Mazur enum devlink_trap_action action, 5840a9003f4SOleksandr Mazur struct netlink_ext_ack *extack) 5850a9003f4SOleksandr Mazur { 5860a9003f4SOleksandr Mazur /* Currently, driver does not support trap action altering */ 5870a9003f4SOleksandr Mazur return -EOPNOTSUPP; 5880a9003f4SOleksandr Mazur } 5890a9003f4SOleksandr Mazur 590a80cf955SOleksandr Mazur static int prestera_drop_counter_get(struct devlink *devlink, 591a80cf955SOleksandr Mazur const struct devlink_trap *trap, 592a80cf955SOleksandr Mazur u64 *p_drops) 593a80cf955SOleksandr Mazur { 594a80cf955SOleksandr Mazur struct prestera_switch *sw = devlink_priv(devlink); 595a80cf955SOleksandr Mazur enum prestera_hw_cpu_code_cnt_t cpu_code_type = 596a80cf955SOleksandr Mazur PRESTERA_HW_CPU_CODE_CNT_TYPE_DROP; 597a80cf955SOleksandr Mazur struct prestera_trap *prestera_trap = 598a80cf955SOleksandr Mazur container_of(trap, struct prestera_trap, trap); 599a80cf955SOleksandr Mazur 600a80cf955SOleksandr Mazur return prestera_hw_cpu_code_counters_get(sw, prestera_trap->cpu_code, 601a80cf955SOleksandr Mazur cpu_code_type, p_drops); 602a80cf955SOleksandr Mazur } 603a80cf955SOleksandr Mazur 604*4beb0c24SLeon Romanovsky void prestera_devlink_traps_unregister(struct prestera_switch *sw) 6050a9003f4SOleksandr Mazur { 606*4beb0c24SLeon Romanovsky struct prestera_trap_data *trap_data = sw->trap_data; 6070a9003f4SOleksandr Mazur struct devlink *dl = priv_to_devlink(sw); 6080a9003f4SOleksandr Mazur const struct devlink_trap *trap; 6090a9003f4SOleksandr Mazur int i; 6100a9003f4SOleksandr Mazur 6110a9003f4SOleksandr Mazur for (i = 0; i < ARRAY_SIZE(prestera_trap_items_arr); ++i) { 6120a9003f4SOleksandr Mazur trap = &prestera_trap_items_arr[i].trap; 6130a9003f4SOleksandr Mazur devlink_traps_unregister(dl, trap, 1); 6140a9003f4SOleksandr Mazur } 6150a9003f4SOleksandr Mazur 6160a9003f4SOleksandr Mazur devlink_trap_groups_unregister(dl, prestera_trap_groups_arr, 6170a9003f4SOleksandr Mazur ARRAY_SIZE(prestera_trap_groups_arr)); 618*4beb0c24SLeon Romanovsky kfree(trap_data->trap_items_arr); 619*4beb0c24SLeon Romanovsky kfree(trap_data); 6200a9003f4SOleksandr Mazur } 621