| /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ |
| /* Copyright (c) 2019-2021 Marvell International Ltd. All rights reserved. */ |
| |
| #ifndef _PRESTERA_ROUTER_HW_H_ |
| #define _PRESTERA_ROUTER_HW_H_ |
| |
| struct prestera_vr { |
| struct list_head router_node; |
| refcount_t refcount; |
| u32 tb_id; /* key (kernel fib table id) */ |
| u16 hw_vr_id; /* virtual router ID */ |
| u8 __pad[2]; |
| }; |
| |
| struct prestera_rif_entry { |
| struct prestera_rif_entry_key { |
| struct prestera_iface iface; |
| } key; |
| struct prestera_vr *vr; |
| unsigned char addr[ETH_ALEN]; |
| u16 hw_id; /* rif_id */ |
| struct list_head router_node; /* ht */ |
| }; |
| |
| struct prestera_ip_addr { |
| union { |
| __be32 ipv4; |
| struct in6_addr ipv6; |
| } u; |
| enum { |
| PRESTERA_IPV4 = 0, |
| PRESTERA_IPV6 |
| } v; |
| #define PRESTERA_IP_ADDR_PLEN(V) ((V) == PRESTERA_IPV4 ? 32 : \ |
| /* (V) == PRESTERA_IPV6 ? */ 128 /* : 0 */) |
| }; |
| |
| struct prestera_nh_neigh_key { |
| struct prestera_ip_addr addr; |
| /* Seems like rif is obsolete, because there is iface in info ? |
| * Key can contain functional fields, or fields, which is used to |
| * filter duplicate objects on logical level (before you pass it to |
| * HW)... also key can be used to cover hardware restrictions. |
| * In our case rif - is logical interface (even can be VLAN), which |
| * is used in combination with IP address (which is also not related to |
| * hardware nexthop) to provide logical compression of created nexthops. |
| * You even can imagine, that rif+IPaddr is just cookie. |
| */ |
| /* struct prestera_rif *rif; */ |
| /* Use just as cookie, to divide ARP domains (in order with addr) */ |
| void *rif; |
| }; |
| |
| /* Used for hw call */ |
| struct prestera_neigh_info { |
| struct prestera_iface iface; |
| unsigned char ha[ETH_ALEN]; |
| u8 connected; /* bool. indicate, if mac/oif valid */ |
| u8 __pad[1]; |
| }; |
| |
| /* Used to notify nh about neigh change */ |
| struct prestera_nh_neigh { |
| struct prestera_nh_neigh_key key; |
| struct prestera_neigh_info info; |
| struct rhash_head ht_node; /* node of prestera_vr */ |
| struct list_head nexthop_group_list; |
| }; |
| |
| #define PRESTERA_NHGR_SIZE_MAX 4 |
| |
| struct prestera_nexthop_group { |
| struct prestera_nexthop_group_key { |
| struct prestera_nh_neigh_key neigh[PRESTERA_NHGR_SIZE_MAX]; |
| } key; |
| /* Store intermediate object here. |
| * This prevent overhead kzalloc call. |
| */ |
| /* nh_neigh is used only to notify nexthop_group */ |
| struct prestera_nh_neigh_head { |
| struct prestera_nexthop_group *this; |
| struct list_head head; |
| /* ptr to neigh is not necessary. |
| * It used to prevent lookup of nh_neigh by key (n) on destroy |
| */ |
| struct prestera_nh_neigh *neigh; |
| } nh_neigh_head[PRESTERA_NHGR_SIZE_MAX]; |
| struct rhash_head ht_node; /* node of prestera_vr */ |
| refcount_t refcount; |
| u32 grp_id; /* hw */ |
| }; |
| |
| struct prestera_fib_key { |
| struct prestera_ip_addr addr; |
| u32 prefix_len; |
| u32 tb_id; |
| }; |
| |
| struct prestera_fib_info { |
| struct prestera_vr *vr; |
| struct list_head vr_node; |
| enum prestera_fib_type { |
| PRESTERA_FIB_TYPE_INVALID = 0, |
| /* must be pointer to nh_grp id */ |
| PRESTERA_FIB_TYPE_UC_NH, |
| /* It can be connected route |
| * and will be overlapped with neighbours |
| */ |
| PRESTERA_FIB_TYPE_TRAP, |
| PRESTERA_FIB_TYPE_DROP |
| } type; |
| /* Valid only if type = UC_NH*/ |
| struct prestera_nexthop_group *nh_grp; |
| }; |
| |
| struct prestera_fib_node { |
| struct rhash_head ht_node; /* node of prestera_vr */ |
| struct prestera_fib_key key; |
| struct prestera_fib_info info; /* action related info */ |
| }; |
| |
| struct prestera_rif_entry * |
| prestera_rif_entry_find(const struct prestera_switch *sw, |
| const struct prestera_rif_entry_key *k); |
| void prestera_rif_entry_destroy(struct prestera_switch *sw, |
| struct prestera_rif_entry *e); |
| struct prestera_rif_entry * |
| prestera_rif_entry_create(struct prestera_switch *sw, |
| struct prestera_rif_entry_key *k, |
| u32 tb_id, const unsigned char *addr); |
| struct prestera_nh_neigh * |
| prestera_nh_neigh_find(struct prestera_switch *sw, |
| struct prestera_nh_neigh_key *key); |
| struct prestera_nh_neigh * |
| prestera_nh_neigh_get(struct prestera_switch *sw, |
| struct prestera_nh_neigh_key *key); |
| void prestera_nh_neigh_put(struct prestera_switch *sw, |
| struct prestera_nh_neigh *neigh); |
| int prestera_nh_neigh_set(struct prestera_switch *sw, |
| struct prestera_nh_neigh *neigh); |
| bool prestera_nh_neigh_util_hw_state(struct prestera_switch *sw, |
| struct prestera_nh_neigh *nh_neigh); |
| struct prestera_fib_node *prestera_fib_node_find(struct prestera_switch *sw, |
| struct prestera_fib_key *key); |
| void prestera_fib_node_destroy(struct prestera_switch *sw, |
| struct prestera_fib_node *fib_node); |
| struct prestera_fib_node * |
| prestera_fib_node_create(struct prestera_switch *sw, |
| struct prestera_fib_key *key, |
| enum prestera_fib_type fib_type, |
| struct prestera_nexthop_group_key *nh_grp_key); |
| int prestera_router_hw_init(struct prestera_switch *sw); |
| void prestera_router_hw_fini(struct prestera_switch *sw); |
| |
| #endif /* _PRESTERA_ROUTER_HW_H_ */ |