1bca5859bSYevhen Orlov /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ 2bca5859bSYevhen Orlov /* Copyright (c) 2019-2021 Marvell International Ltd. All rights reserved. */ 3bca5859bSYevhen Orlov 4bca5859bSYevhen Orlov #ifndef _PRESTERA_ROUTER_HW_H_ 5bca5859bSYevhen Orlov #define _PRESTERA_ROUTER_HW_H_ 6bca5859bSYevhen Orlov 7bca5859bSYevhen Orlov struct prestera_vr { 8bca5859bSYevhen Orlov struct list_head router_node; 96a1ba875SYevhen Orlov refcount_t refcount; 10bca5859bSYevhen Orlov u32 tb_id; /* key (kernel fib table id) */ 11bca5859bSYevhen Orlov u16 hw_vr_id; /* virtual router ID */ 12bca5859bSYevhen Orlov u8 __pad[2]; 13bca5859bSYevhen Orlov }; 14bca5859bSYevhen Orlov 15bca5859bSYevhen Orlov struct prestera_rif_entry { 16bca5859bSYevhen Orlov struct prestera_rif_entry_key { 17bca5859bSYevhen Orlov struct prestera_iface iface; 18bca5859bSYevhen Orlov } key; 19bca5859bSYevhen Orlov struct prestera_vr *vr; 20bca5859bSYevhen Orlov unsigned char addr[ETH_ALEN]; 21bca5859bSYevhen Orlov u16 hw_id; /* rif_id */ 22bca5859bSYevhen Orlov struct list_head router_node; /* ht */ 23bca5859bSYevhen Orlov }; 24bca5859bSYevhen Orlov 2516de3db1SYevhen Orlov struct prestera_ip_addr { 2616de3db1SYevhen Orlov union { 2716de3db1SYevhen Orlov __be32 ipv4; 2816de3db1SYevhen Orlov struct in6_addr ipv6; 2916de3db1SYevhen Orlov } u; 3016de3db1SYevhen Orlov enum { 3116de3db1SYevhen Orlov PRESTERA_IPV4 = 0, 3216de3db1SYevhen Orlov PRESTERA_IPV6 3316de3db1SYevhen Orlov } v; 34*59b44ea8SYevhen Orlov #define PRESTERA_IP_ADDR_PLEN(V) ((V) == PRESTERA_IPV4 ? 32 : \ 35*59b44ea8SYevhen Orlov /* (V) == PRESTERA_IPV6 ? */ 128 /* : 0 */) 3616de3db1SYevhen Orlov }; 3716de3db1SYevhen Orlov 380a23ae23SYevhen Orlov struct prestera_nh_neigh_key { 390a23ae23SYevhen Orlov struct prestera_ip_addr addr; 400a23ae23SYevhen Orlov /* Seems like rif is obsolete, because there is iface in info ? 410a23ae23SYevhen Orlov * Key can contain functional fields, or fields, which is used to 420a23ae23SYevhen Orlov * filter duplicate objects on logical level (before you pass it to 430a23ae23SYevhen Orlov * HW)... also key can be used to cover hardware restrictions. 440a23ae23SYevhen Orlov * In our case rif - is logical interface (even can be VLAN), which 450a23ae23SYevhen Orlov * is used in combination with IP address (which is also not related to 460a23ae23SYevhen Orlov * hardware nexthop) to provide logical compression of created nexthops. 470a23ae23SYevhen Orlov * You even can imagine, that rif+IPaddr is just cookie. 480a23ae23SYevhen Orlov */ 490a23ae23SYevhen Orlov /* struct prestera_rif *rif; */ 500a23ae23SYevhen Orlov /* Use just as cookie, to divide ARP domains (in order with addr) */ 510a23ae23SYevhen Orlov void *rif; 520a23ae23SYevhen Orlov }; 530a23ae23SYevhen Orlov 540a23ae23SYevhen Orlov /* Used for hw call */ 550a23ae23SYevhen Orlov struct prestera_neigh_info { 560a23ae23SYevhen Orlov struct prestera_iface iface; 570a23ae23SYevhen Orlov unsigned char ha[ETH_ALEN]; 580a23ae23SYevhen Orlov u8 connected; /* bool. indicate, if mac/oif valid */ 590a23ae23SYevhen Orlov u8 __pad[1]; 600a23ae23SYevhen Orlov }; 610a23ae23SYevhen Orlov 620a23ae23SYevhen Orlov /* Used to notify nh about neigh change */ 630a23ae23SYevhen Orlov struct prestera_nh_neigh { 640a23ae23SYevhen Orlov struct prestera_nh_neigh_key key; 650a23ae23SYevhen Orlov struct prestera_neigh_info info; 660a23ae23SYevhen Orlov struct rhash_head ht_node; /* node of prestera_vr */ 670a23ae23SYevhen Orlov struct list_head nexthop_group_list; 680a23ae23SYevhen Orlov }; 690a23ae23SYevhen Orlov 700a23ae23SYevhen Orlov #define PRESTERA_NHGR_SIZE_MAX 4 710a23ae23SYevhen Orlov 720a23ae23SYevhen Orlov struct prestera_nexthop_group { 730a23ae23SYevhen Orlov struct prestera_nexthop_group_key { 740a23ae23SYevhen Orlov struct prestera_nh_neigh_key neigh[PRESTERA_NHGR_SIZE_MAX]; 750a23ae23SYevhen Orlov } key; 760a23ae23SYevhen Orlov /* Store intermediate object here. 770a23ae23SYevhen Orlov * This prevent overhead kzalloc call. 780a23ae23SYevhen Orlov */ 790a23ae23SYevhen Orlov /* nh_neigh is used only to notify nexthop_group */ 800a23ae23SYevhen Orlov struct prestera_nh_neigh_head { 810a23ae23SYevhen Orlov struct prestera_nexthop_group *this; 820a23ae23SYevhen Orlov struct list_head head; 830a23ae23SYevhen Orlov /* ptr to neigh is not necessary. 840a23ae23SYevhen Orlov * It used to prevent lookup of nh_neigh by key (n) on destroy 850a23ae23SYevhen Orlov */ 860a23ae23SYevhen Orlov struct prestera_nh_neigh *neigh; 870a23ae23SYevhen Orlov } nh_neigh_head[PRESTERA_NHGR_SIZE_MAX]; 880a23ae23SYevhen Orlov struct rhash_head ht_node; /* node of prestera_vr */ 890a23ae23SYevhen Orlov refcount_t refcount; 900a23ae23SYevhen Orlov u32 grp_id; /* hw */ 910a23ae23SYevhen Orlov }; 920a23ae23SYevhen Orlov 9316de3db1SYevhen Orlov struct prestera_fib_key { 9416de3db1SYevhen Orlov struct prestera_ip_addr addr; 9516de3db1SYevhen Orlov u32 prefix_len; 9616de3db1SYevhen Orlov u32 tb_id; 9716de3db1SYevhen Orlov }; 9816de3db1SYevhen Orlov 9916de3db1SYevhen Orlov struct prestera_fib_info { 10016de3db1SYevhen Orlov struct prestera_vr *vr; 10116de3db1SYevhen Orlov struct list_head vr_node; 10216de3db1SYevhen Orlov enum prestera_fib_type { 10316de3db1SYevhen Orlov PRESTERA_FIB_TYPE_INVALID = 0, 1040a23ae23SYevhen Orlov /* must be pointer to nh_grp id */ 1050a23ae23SYevhen Orlov PRESTERA_FIB_TYPE_UC_NH, 10616de3db1SYevhen Orlov /* It can be connected route 10716de3db1SYevhen Orlov * and will be overlapped with neighbours 10816de3db1SYevhen Orlov */ 10916de3db1SYevhen Orlov PRESTERA_FIB_TYPE_TRAP, 11016de3db1SYevhen Orlov PRESTERA_FIB_TYPE_DROP 11116de3db1SYevhen Orlov } type; 1120a23ae23SYevhen Orlov /* Valid only if type = UC_NH*/ 1130a23ae23SYevhen Orlov struct prestera_nexthop_group *nh_grp; 11416de3db1SYevhen Orlov }; 11516de3db1SYevhen Orlov 11616de3db1SYevhen Orlov struct prestera_fib_node { 11716de3db1SYevhen Orlov struct rhash_head ht_node; /* node of prestera_vr */ 11816de3db1SYevhen Orlov struct prestera_fib_key key; 11916de3db1SYevhen Orlov struct prestera_fib_info info; /* action related info */ 12016de3db1SYevhen Orlov }; 12116de3db1SYevhen Orlov 122bca5859bSYevhen Orlov struct prestera_rif_entry * 123bca5859bSYevhen Orlov prestera_rif_entry_find(const struct prestera_switch *sw, 124bca5859bSYevhen Orlov const struct prestera_rif_entry_key *k); 125bca5859bSYevhen Orlov void prestera_rif_entry_destroy(struct prestera_switch *sw, 126bca5859bSYevhen Orlov struct prestera_rif_entry *e); 127bca5859bSYevhen Orlov struct prestera_rif_entry * 128bca5859bSYevhen Orlov prestera_rif_entry_create(struct prestera_switch *sw, 129bca5859bSYevhen Orlov struct prestera_rif_entry_key *k, 130bca5859bSYevhen Orlov u32 tb_id, const unsigned char *addr); 1310a23ae23SYevhen Orlov struct prestera_nh_neigh * 1320a23ae23SYevhen Orlov prestera_nh_neigh_find(struct prestera_switch *sw, 1330a23ae23SYevhen Orlov struct prestera_nh_neigh_key *key); 1340a23ae23SYevhen Orlov struct prestera_nh_neigh * 1350a23ae23SYevhen Orlov prestera_nh_neigh_get(struct prestera_switch *sw, 1360a23ae23SYevhen Orlov struct prestera_nh_neigh_key *key); 1370a23ae23SYevhen Orlov void prestera_nh_neigh_put(struct prestera_switch *sw, 1380a23ae23SYevhen Orlov struct prestera_nh_neigh *neigh); 1390a23ae23SYevhen Orlov int prestera_nh_neigh_set(struct prestera_switch *sw, 1400a23ae23SYevhen Orlov struct prestera_nh_neigh *neigh); 1410a23ae23SYevhen Orlov bool prestera_nh_neigh_util_hw_state(struct prestera_switch *sw, 1420a23ae23SYevhen Orlov struct prestera_nh_neigh *nh_neigh); 14316de3db1SYevhen Orlov struct prestera_fib_node *prestera_fib_node_find(struct prestera_switch *sw, 14416de3db1SYevhen Orlov struct prestera_fib_key *key); 14516de3db1SYevhen Orlov void prestera_fib_node_destroy(struct prestera_switch *sw, 14616de3db1SYevhen Orlov struct prestera_fib_node *fib_node); 14716de3db1SYevhen Orlov struct prestera_fib_node * 14816de3db1SYevhen Orlov prestera_fib_node_create(struct prestera_switch *sw, 14916de3db1SYevhen Orlov struct prestera_fib_key *key, 1500a23ae23SYevhen Orlov enum prestera_fib_type fib_type, 1510a23ae23SYevhen Orlov struct prestera_nexthop_group_key *nh_grp_key); 152bca5859bSYevhen Orlov int prestera_router_hw_init(struct prestera_switch *sw); 153e179f045SYevhen Orlov void prestera_router_hw_fini(struct prestera_switch *sw); 154bca5859bSYevhen Orlov 155bca5859bSYevhen Orlov #endif /* _PRESTERA_ROUTER_HW_H_ */ 156