| 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 | |