aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/marvell/prestera/prestera_router_hw.h
blob: 9ca97919c863893ed5f5cd82fd8960a4a7246405 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* 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_ */