| 1 |
|
| 2 | |
| 3 | * Copyright (c) 2021 Taehee Yoo <[email protected]>
|
| 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 |
|
| 29 | AMT_OPS_INT,
|
| 30 |
|
| 31 | AMT_OPS_UNI,
|
| 32 |
|
| 33 | AMT_OPS_SUB,
|
| 34 |
|
| 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 |
|
| 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 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 234 | struct amt_tunnel_list {
|
| 235 | struct list_head list;
|
| 236 |
|
| 237 | spinlock_t lock;
|
| 238 | struct amt_dev *amt;
|
| 239 | u32 nr_groups;
|
| 240 | u32 nr_sources;
|
| 241 | enum amt_status status;
|
| 242 | struct delayed_work gc_wq;
|
| 243 | __be16 source_port;
|
| 244 | __be32 ip4;
|
| 245 | __be32 nonce;
|
| 246 | siphash_key_t key;
|
| 247 | u64 mac:48,
|
| 248 | reserved:16;
|
| 249 | struct rcu_head rcu;
|
| 250 | struct hlist_head groups[];
|
| 251 | };
|
| 252 |
|
| 253 | union amt_addr {
|
| 254 | __be32 ip4;
|
| 255 | #if IS_ENABLED(CONFIG_IPV6)
|
| 256 | struct in6_addr ip6;
|
| 257 | #endif
|
| 258 | };
|
| 259 |
|
| 260 | |
| 261 | *
|
| 262 | * When the router is in EXCLUDE mode, the router state is represented
|
| 263 | * by the notation EXCLUDE (X,Y), where X is called the "Requested List"
|
| 264 | * and Y is called the "Exclude List". All sources, except those from
|
| 265 | * the Exclude List, will be forwarded by the router
|
| 266 |
|
| 267 | enum amt_source_status {
|
| 268 | AMT_SOURCE_STATUS_NONE,
|
| 269 |
|
| 270 | AMT_SOURCE_STATUS_FWD,
|
| 271 |
|
| 272 | AMT_SOURCE_STATUS_D_FWD,
|
| 273 | };
|
| 274 |
|
| 275 |
|
| 276 | struct amt_source_node {
|
| 277 | struct hlist_node node;
|
| 278 | struct amt_group_node *gnode;
|
| 279 | struct delayed_work source_timer;
|
| 280 | union amt_addr source_addr;
|
| 281 | enum amt_source_status status;
|
| 282 | #define AMT_SOURCE_OLD 0
|
| 283 | #define AMT_SOURCE_NEW 1
|
| 284 | u8 flags;
|
| 285 | struct rcu_head rcu;
|
| 286 | };
|
| 287 |
|
| 288 |
|
| 289 | struct amt_group_node {
|
| 290 | struct amt_dev *amt;
|
| 291 | union amt_addr group_addr;
|
| 292 | union amt_addr host_addr;
|
| 293 | bool v6;
|
| 294 | u8 filter_mode;
|
| 295 | u32 nr_sources;
|
| 296 | struct amt_tunnel_list *tunnel_list;
|
| 297 | struct hlist_node node;
|
| 298 | struct delayed_work group_timer;
|
| 299 | struct rcu_head rcu;
|
| 300 | struct hlist_head sources[];
|
| 301 | };
|
| 302 |
|
| 303 | #define AMT_MAX_EVENTS 16
|
| 304 | struct amt_events {
|
| 305 | enum amt_event event;
|
| 306 | struct sk_buff *skb;
|
| 307 | };
|
| 308 |
|
| 309 | struct amt_dev {
|
| 310 | struct net_device *dev;
|
| 311 | struct net_device *stream_dev;
|
| 312 | struct net *net;
|
| 313 |
|
| 314 | spinlock_t lock;
|
| 315 |
|
| 316 | struct list_head tunnel_list;
|
| 317 | struct gro_cells gro_cells;
|
| 318 |
|
| 319 |
|
| 320 | struct delayed_work discovery_wq;
|
| 321 |
|
| 322 | struct delayed_work req_wq;
|
| 323 |
|
| 324 | struct delayed_work secret_wq;
|
| 325 | struct work_struct event_wq;
|
| 326 |
|
| 327 | enum amt_status status;
|
| 328 |
|
| 329 | siphash_key_t key;
|
| 330 | struct sock __rcu *sk;
|
| 331 | u32 max_groups;
|
| 332 | u32 max_sources;
|
| 333 | u32 hash_buckets;
|
| 334 | u32 hash_seed;
|
| 335 |
|
| 336 | u32 max_tunnels;
|
| 337 |
|
| 338 | u32 nr_tunnels;
|
| 339 |
|
| 340 | u32 mode;
|
| 341 |
|
| 342 | __be16 relay_port;
|
| 343 |
|
| 344 | __be16 gw_port;
|
| 345 |
|
| 346 | __be32 local_ip;
|
| 347 |
|
| 348 | __be32 remote_ip;
|
| 349 |
|
| 350 | __be32 discovery_ip;
|
| 351 |
|
| 352 | __be32 nonce;
|
| 353 |
|
| 354 | bool ready4;
|
| 355 | bool ready6;
|
| 356 | u8 req_cnt;
|
| 357 | u8 qi;
|
| 358 | u64 qrv;
|
| 359 | u64 qri;
|
| 360 |
|
| 361 | u64 mac:48,
|
| 362 | reserved:16;
|
| 363 |
|
| 364 | struct amt_events events[AMT_MAX_EVENTS];
|
| 365 | u8 event_idx;
|
| 366 | u8 nr_events;
|
| 367 | };
|
| 368 |
|
| 369 | #define AMT_TOS 0xc0
|
| 370 | #define AMT_IPHDR_OPTS 4
|
| 371 | #define AMT_IP6HDR_OPTS 8
|
| 372 | #define AMT_GC_INTERVAL (30 * 1000)
|
| 373 | #define AMT_MAX_GROUP 32
|
| 374 | #define AMT_MAX_SOURCE 128
|
| 375 | #define AMT_HSIZE_SHIFT 8
|
| 376 | #define AMT_HSIZE (1 << AMT_HSIZE_SHIFT)
|
| 377 |
|
| 378 | #define AMT_DISCOVERY_TIMEOUT 5000
|
| 379 | #define AMT_INIT_REQ_TIMEOUT 1
|
| 380 | #define AMT_INIT_QUERY_INTERVAL 125
|
| 381 | #define AMT_MAX_REQ_TIMEOUT 120
|
| 382 | #define AMT_MAX_REQ_COUNT 3
|
| 383 | #define AMT_SECRET_TIMEOUT 60000
|
| 384 | #define IANA_AMT_UDP_PORT 2268
|
| 385 | #define AMT_MAX_TUNNELS 128
|
| 386 | #define AMT_MAX_REQS 128
|
| 387 | #define AMT_GW_HLEN (sizeof(struct iphdr) + \
|
| 388 | sizeof(struct udphdr) + \
|
| 389 | sizeof(struct amt_gw_headers))
|
| 390 | #define AMT_RELAY_HLEN (sizeof(struct iphdr) + \
|
| 391 | sizeof(struct udphdr) + \
|
| 392 | sizeof(struct amt_relay_headers))
|
| 393 |
|
| 394 | static inline bool netif_is_amt(const struct net_device *dev)
|
| 395 | {
|
| 396 | return dev->rtnl_link_ops && !strcmp(dev->rtnl_link_ops->kind, "amt");
|
| 397 | }
|
| 398 |
|
| 399 | static inline u64 amt_gmi(const struct amt_dev *amt)
|
| 400 | {
|
| 401 | return ((amt->qrv * amt->qi) + amt->qri) * 1000;
|
| 402 | }
|
| 403 |
|
| 404 | #endif
|