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