xref: /linux/drivers/net/ethernet/marvell/prestera/prestera_router_hw.h (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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