xref: /openbmc/linux/include/net/amt.h (revision ccc319dc)
1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * Copyright (c) 2021 Taehee Yoo <ap420073@gmail.com>
4  */
5 #ifndef _NET_AMT_H_
6 #define _NET_AMT_H_
7 
8 #include <linux/siphash.h>
9 #include <linux/jhash.h>
10 
11 enum amt_msg_type {
12 	AMT_MSG_DISCOVERY = 1,
13 	AMT_MSG_ADVERTISEMENT,
14 	AMT_MSG_REQUEST,
15 	AMT_MSG_MEMBERSHIP_QUERY,
16 	AMT_MSG_MEMBERSHIP_UPDATE,
17 	AMT_MSG_MULTICAST_DATA,
18 	AMT_MSG_TEARDOWN,
19 	__AMT_MSG_MAX,
20 };
21 
22 #define AMT_MSG_MAX (__AMT_MSG_MAX - 1)
23 
24 enum amt_ops {
25 	/* A*B */
26 	AMT_OPS_INT,
27 	/* A+B */
28 	AMT_OPS_UNI,
29 	/* A-B */
30 	AMT_OPS_SUB,
31 	/* B-A */
32 	AMT_OPS_SUB_REV,
33 	__AMT_OPS_MAX,
34 };
35 
36 #define AMT_OPS_MAX (__AMT_OPS_MAX - 1)
37 
38 enum amt_filter {
39 	AMT_FILTER_FWD,
40 	AMT_FILTER_D_FWD,
41 	AMT_FILTER_FWD_NEW,
42 	AMT_FILTER_D_FWD_NEW,
43 	AMT_FILTER_ALL,
44 	AMT_FILTER_NONE_NEW,
45 	AMT_FILTER_BOTH,
46 	AMT_FILTER_BOTH_NEW,
47 	__AMT_FILTER_MAX,
48 };
49 
50 #define AMT_FILTER_MAX (__AMT_FILTER_MAX - 1)
51 
52 enum amt_act {
53 	AMT_ACT_GMI,
54 	AMT_ACT_GMI_ZERO,
55 	AMT_ACT_GT,
56 	AMT_ACT_STATUS_FWD_NEW,
57 	AMT_ACT_STATUS_D_FWD_NEW,
58 	AMT_ACT_STATUS_NONE_NEW,
59 	__AMT_ACT_MAX,
60 };
61 
62 #define AMT_ACT_MAX (__AMT_ACT_MAX - 1)
63 
64 enum amt_status {
65 	AMT_STATUS_INIT,
66 	AMT_STATUS_SENT_DISCOVERY,
67 	AMT_STATUS_RECEIVED_DISCOVERY,
68 	AMT_STATUS_SENT_ADVERTISEMENT,
69 	AMT_STATUS_RECEIVED_ADVERTISEMENT,
70 	AMT_STATUS_SENT_REQUEST,
71 	AMT_STATUS_RECEIVED_REQUEST,
72 	AMT_STATUS_SENT_QUERY,
73 	AMT_STATUS_RECEIVED_QUERY,
74 	AMT_STATUS_SENT_UPDATE,
75 	AMT_STATUS_RECEIVED_UPDATE,
76 	__AMT_STATUS_MAX,
77 };
78 
79 #define AMT_STATUS_MAX (__AMT_STATUS_MAX - 1)
80 
81 struct amt_header {
82 #if defined(__LITTLE_ENDIAN_BITFIELD)
83 	u8 type:4,
84 	   version:4;
85 #elif defined(__BIG_ENDIAN_BITFIELD)
86 	u8 version:4,
87 	   type:4;
88 #else
89 #error  "Please fix <asm/byteorder.h>"
90 #endif
91 } __packed;
92 
93 struct amt_header_discovery {
94 #if defined(__LITTLE_ENDIAN_BITFIELD)
95 	u32	type:4,
96 		version:4,
97 		reserved:24;
98 #elif defined(__BIG_ENDIAN_BITFIELD)
99 	u32	version:4,
100 		type:4,
101 		reserved:24;
102 #else
103 #error  "Please fix <asm/byteorder.h>"
104 #endif
105 	__be32	nonce;
106 } __packed;
107 
108 struct amt_header_advertisement {
109 #if defined(__LITTLE_ENDIAN_BITFIELD)
110 	u32	type:4,
111 		version:4,
112 		reserved:24;
113 #elif defined(__BIG_ENDIAN_BITFIELD)
114 	u32	version:4,
115 		type:4,
116 		reserved:24;
117 #else
118 #error  "Please fix <asm/byteorder.h>"
119 #endif
120 	__be32	nonce;
121 	__be32	ip4;
122 } __packed;
123 
124 struct amt_header_request {
125 #if defined(__LITTLE_ENDIAN_BITFIELD)
126 	u32	type:4,
127 		version:4,
128 		reserved1:7,
129 		p:1,
130 		reserved2:16;
131 #elif defined(__BIG_ENDIAN_BITFIELD)
132 	u32	version:4,
133 		type:4,
134 		p:1,
135 		reserved1:7,
136 		reserved2:16;
137 #else
138 #error  "Please fix <asm/byteorder.h>"
139 #endif
140 	__be32	nonce;
141 } __packed;
142 
143 struct amt_header_membership_query {
144 #if defined(__LITTLE_ENDIAN_BITFIELD)
145 	u64	type:4,
146 		version:4,
147 		reserved:6,
148 		l:1,
149 		g:1,
150 		response_mac:48;
151 #elif defined(__BIG_ENDIAN_BITFIELD)
152 	u64	version:4,
153 		type:4,
154 		g:1,
155 		l:1,
156 		reserved:6,
157 		response_mac:48;
158 #else
159 #error  "Please fix <asm/byteorder.h>"
160 #endif
161 	__be32	nonce;
162 } __packed;
163 
164 struct amt_header_membership_update {
165 #if defined(__LITTLE_ENDIAN_BITFIELD)
166 	u64	type:4,
167 		version:4,
168 		reserved:8,
169 		response_mac:48;
170 #elif defined(__BIG_ENDIAN_BITFIELD)
171 	u64	version:4,
172 		type:4,
173 		reserved:8,
174 		response_mac:48;
175 #else
176 #error  "Please fix <asm/byteorder.h>"
177 #endif
178 	__be32	nonce;
179 } __packed;
180 
181 struct amt_header_mcast_data {
182 #if defined(__LITTLE_ENDIAN_BITFIELD)
183 	u16	type:4,
184 		version:4,
185 		reserved:8;
186 #elif defined(__BIG_ENDIAN_BITFIELD)
187 	u16	version:4,
188 		type:4,
189 		reserved:8;
190 #else
191 #error  "Please fix <asm/byteorder.h>"
192 #endif
193 } __packed;
194 
195 struct amt_headers {
196 	union {
197 		struct amt_header_discovery discovery;
198 		struct amt_header_advertisement advertisement;
199 		struct amt_header_request request;
200 		struct amt_header_membership_query query;
201 		struct amt_header_membership_update update;
202 		struct amt_header_mcast_data data;
203 	};
204 } __packed;
205 
206 struct amt_gw_headers {
207 	union {
208 		struct amt_header_discovery discovery;
209 		struct amt_header_request request;
210 		struct amt_header_membership_update update;
211 	};
212 } __packed;
213 
214 struct amt_relay_headers {
215 	union {
216 		struct amt_header_advertisement advertisement;
217 		struct amt_header_membership_query query;
218 		struct amt_header_mcast_data data;
219 	};
220 } __packed;
221 
222 struct amt_skb_cb {
223 	struct amt_tunnel_list *tunnel;
224 };
225 
226 struct amt_tunnel_list {
227 	struct list_head	list;
228 	/* Protect All resources under an amt_tunne_list */
229 	spinlock_t		lock;
230 	struct amt_dev		*amt;
231 	u32			nr_groups;
232 	u32			nr_sources;
233 	enum amt_status		status;
234 	struct delayed_work	gc_wq;
235 	__be16			source_port;
236 	__be32			ip4;
237 	__be32			nonce;
238 	siphash_key_t		key;
239 	u64			mac:48,
240 				reserved:16;
241 	struct rcu_head		rcu;
242 	struct hlist_head	groups[];
243 };
244 
245 union amt_addr {
246 	__be32			ip4;
247 #if IS_ENABLED(CONFIG_IPV6)
248 	struct in6_addr		ip6;
249 #endif
250 };
251 
252 /* RFC 3810
253  *
254  * When the router is in EXCLUDE mode, the router state is represented
255  * by the notation EXCLUDE (X,Y), where X is called the "Requested List"
256  * and Y is called the "Exclude List".  All sources, except those from
257  * the Exclude List, will be forwarded by the router
258  */
259 enum amt_source_status {
260 	AMT_SOURCE_STATUS_NONE,
261 	/* Node of Requested List */
262 	AMT_SOURCE_STATUS_FWD,
263 	/* Node of Exclude List */
264 	AMT_SOURCE_STATUS_D_FWD,
265 };
266 
267 /* protected by gnode->lock */
268 struct amt_source_node {
269 	struct hlist_node	node;
270 	struct amt_group_node	*gnode;
271 	struct delayed_work     source_timer;
272 	union amt_addr		source_addr;
273 	enum amt_source_status	status;
274 #define AMT_SOURCE_OLD	0
275 #define AMT_SOURCE_NEW	1
276 	u8			flags;
277 	struct rcu_head		rcu;
278 };
279 
280 /* Protected by amt_tunnel_list->lock */
281 struct amt_group_node {
282 	struct amt_dev		*amt;
283 	union amt_addr		group_addr;
284 	union amt_addr		host_addr;
285 	bool			v6;
286 	u8			filter_mode;
287 	u32			nr_sources;
288 	struct amt_tunnel_list	*tunnel_list;
289 	struct hlist_node	node;
290 	struct delayed_work     group_timer;
291 	struct rcu_head		rcu;
292 	struct hlist_head	sources[];
293 };
294 
295 struct amt_dev {
296 	struct net_device       *dev;
297 	struct net_device       *stream_dev;
298 	struct net		*net;
299 	/* Global lock for amt device */
300 	spinlock_t		lock;
301 	/* Used only in relay mode */
302 	struct list_head        tunnel_list;
303 	struct gro_cells	gro_cells;
304 
305 	/* Protected by RTNL */
306 	struct delayed_work     discovery_wq;
307 	/* Protected by RTNL */
308 	struct delayed_work     req_wq;
309 	/* Protected by RTNL */
310 	struct delayed_work     secret_wq;
311 	/* AMT status */
312 	enum amt_status		status;
313 	/* Generated key */
314 	siphash_key_t		key;
315 	struct socket	  __rcu *sock;
316 	u32			max_groups;
317 	u32			max_sources;
318 	u32			hash_buckets;
319 	u32			hash_seed;
320 	/* Default 128 */
321 	u32                     max_tunnels;
322 	/* Default 128 */
323 	u32                     nr_tunnels;
324 	/* Gateway or Relay mode */
325 	u32                     mode;
326 	/* Default 2268 */
327 	__be16			relay_port;
328 	/* Default 2268 */
329 	__be16			gw_port;
330 	/* Outer local ip */
331 	__be32			local_ip;
332 	/* Outer remote ip */
333 	__be32			remote_ip;
334 	/* Outer discovery ip */
335 	__be32			discovery_ip;
336 	/* Only used in gateway mode */
337 	__be32			nonce;
338 	/* Gateway sent request and received query */
339 	bool			ready4;
340 	bool			ready6;
341 	u8			req_cnt;
342 	u8			qi;
343 	u64			qrv;
344 	u64			qri;
345 	/* Used only in gateway mode */
346 	u64			mac:48,
347 				reserved:16;
348 };
349 
350 #define AMT_TOS			0xc0
351 #define AMT_IPHDR_OPTS		4
352 #define AMT_IP6HDR_OPTS		8
353 #define AMT_GC_INTERVAL		(30 * 1000)
354 #define AMT_MAX_GROUP		32
355 #define AMT_MAX_SOURCE		128
356 #define AMT_HSIZE_SHIFT		8
357 #define AMT_HSIZE		(1 << AMT_HSIZE_SHIFT)
358 
359 #define AMT_DISCOVERY_TIMEOUT	5000
360 #define AMT_INIT_REQ_TIMEOUT	1
361 #define AMT_INIT_QUERY_INTERVAL	125
362 #define AMT_MAX_REQ_TIMEOUT	120
363 #define AMT_MAX_REQ_COUNT	3
364 #define AMT_SECRET_TIMEOUT	60000
365 #define IANA_AMT_UDP_PORT	2268
366 #define AMT_MAX_TUNNELS         128
367 #define AMT_MAX_REQS		128
368 #define AMT_GW_HLEN (sizeof(struct iphdr) + \
369 		     sizeof(struct udphdr) + \
370 		     sizeof(struct amt_gw_headers))
371 #define AMT_RELAY_HLEN (sizeof(struct iphdr) + \
372 		     sizeof(struct udphdr) + \
373 		     sizeof(struct amt_relay_headers))
374 
375 static inline bool netif_is_amt(const struct net_device *dev)
376 {
377 	return dev->rtnl_link_ops && !strcmp(dev->rtnl_link_ops->kind, "amt");
378 }
379 
380 static inline u64 amt_gmi(const struct amt_dev *amt)
381 {
382 	return ((amt->qrv * amt->qi) + amt->qri) * 1000;
383 }
384 
385 #endif /* _NET_AMT_H_ */
386