Commit | Line | Data |
---|---|---|
b9022b53 TY |
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> | |
949d6b40 JK |
10 | #include <linux/netdevice.h> |
11 | #include <net/gro_cells.h> | |
12 | #include <net/rtnetlink.h> | |
b9022b53 TY |
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, | |
4934609d | 21 | AMT_MSG_TEARDOWN, |
b9022b53 TY |
22 | __AMT_MSG_MAX, |
23 | }; | |
24 | ||
25 | #define AMT_MSG_MAX (__AMT_MSG_MAX - 1) | |
26 | ||
bc54e49c TY |
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 | ||
b9022b53 TY |
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 | ||
30e22a6e TY |
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 | ||
cbc21dc1 TY |
93 | struct amt_header { |
94 | #if defined(__LITTLE_ENDIAN_BITFIELD) | |
95 | u8 type:4, | |
96 | version: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 | ||
b9022b53 TY |
105 | struct amt_header_discovery { |
106 | #if defined(__LITTLE_ENDIAN_BITFIELD) | |
107 | u32 type:4, | |
108 | version:4, | |
109 | reserved: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 nonce; | |
118 | } __packed; | |
119 | ||
120 | struct amt_header_advertisement { | |
121 | #if defined(__LITTLE_ENDIAN_BITFIELD) | |
122 | u32 type:4, | |
123 | version:4, | |
124 | reserved: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 nonce; | |
133 | __be32 ip4; | |
134 | } __packed; | |
135 | ||
136 | struct amt_header_request { | |
137 | #if defined(__LITTLE_ENDIAN_BITFIELD) | |
138 | u32 type:4, | |
139 | version:4, | |
140 | reserved1:7, | |
141 | p:1, | |
142 | reserved2: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 nonce; | |
153 | } __packed; | |
154 | ||
155 | struct amt_header_membership_query { | |
156 | #if defined(__LITTLE_ENDIAN_BITFIELD) | |
157 | u64 type:4, | |
158 | version:4, | |
159 | reserved:6, | |
160 | l:1, | |
161 | g:1, | |
162 | response_mac: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 nonce; | |
174 | } __packed; | |
175 | ||
176 | struct amt_header_membership_update { | |
177 | #if defined(__LITTLE_ENDIAN_BITFIELD) | |
178 | u64 type:4, | |
179 | version:4, | |
180 | reserved:8, | |
181 | response_mac: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 nonce; | |
191 | } __packed; | |
192 | ||
193 | struct amt_header_mcast_data { | |
194 | #if defined(__LITTLE_ENDIAN_BITFIELD) | |
195 | u16 type:4, | |
196 | version:4, | |
197 | reserved: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 | ||
bc54e49c TY |
207 | struct amt_headers { |
208 | union { | |
209 | struct amt_header_discovery discovery; | |
210 | struct amt_header_advertisement advertisement; | |
211 | struct amt_header_request request; | |
212 | struct amt_header_membership_query query; | |
213 | struct amt_header_membership_update update; | |
214 | struct amt_header_mcast_data data; | |
215 | }; | |
216 | } __packed; | |
217 | ||
b9022b53 TY |
218 | struct amt_gw_headers { |
219 | union { | |
220 | struct amt_header_discovery discovery; | |
221 | struct amt_header_request request; | |
222 | struct amt_header_membership_update update; | |
223 | }; | |
224 | } __packed; | |
225 | ||
226 | struct amt_relay_headers { | |
227 | union { | |
228 | struct amt_header_advertisement advertisement; | |
229 | struct amt_header_membership_query query; | |
230 | struct amt_header_mcast_data data; | |
231 | }; | |
232 | } __packed; | |
233 | ||
cbc21dc1 TY |
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 | ||
bc54e49c TY |
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 | ||
30e22a6e TY |
307 | #define AMT_MAX_EVENTS 16 |
308 | struct amt_events { | |
309 | enum amt_event event; | |
310 | struct sk_buff *skb; | |
311 | }; | |
312 | ||
b9022b53 TY |
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; | |
30e22a6e | 329 | struct work_struct event_wq; |
b9022b53 TY |
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; | |
30e22a6e TY |
367 | /* AMT gateway side message handler queue */ |
368 | struct amt_events events[AMT_MAX_EVENTS]; | |
369 | u8 event_idx; | |
370 | u8 nr_events; | |
b9022b53 TY |
371 | }; |
372 | ||
bc54e49c | 373 | #define AMT_TOS 0xc0 |
cbc21dc1 | 374 | #define AMT_IPHDR_OPTS 4 |
b75f7095 | 375 | #define AMT_IP6HDR_OPTS 8 |
bc54e49c | 376 | #define AMT_GC_INTERVAL (30 * 1000) |
b9022b53 TY |
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 | ||
cbc21dc1 TY |
382 | #define AMT_DISCOVERY_TIMEOUT 5000 |
383 | #define AMT_INIT_REQ_TIMEOUT 1 | |
b9022b53 | 384 | #define AMT_INIT_QUERY_INTERVAL 125 |
cbc21dc1 TY |
385 | #define AMT_MAX_REQ_TIMEOUT 120 |
386 | #define AMT_MAX_REQ_COUNT 3 | |
387 | #define AMT_SECRET_TIMEOUT 60000 | |
b9022b53 TY |
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 | ||
cbc21dc1 TY |
403 | static inline u64 amt_gmi(const struct amt_dev *amt) |
404 | { | |
405 | return ((amt->qrv * amt->qi) + amt->qri) * 1000; | |
406 | } | |
407 | ||
b9022b53 | 408 | #endif /* _NET_AMT_H_ */ |