-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmptcp.h
1500 lines (1305 loc) · 42.9 KB
/
mptcp.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* MPTCP implementation
*
* Initial Design & Implementation:
* Sébastien Barré <[email protected]>
*
* Current Maintainer & Author:
* Christoph Paasch <[email protected]>
*
* Additional authors:
* Jaakko Korkeaniemi <[email protected]>
* Gregory Detal <[email protected]>
* Fabien Duchêne <[email protected]>
* Andreas Seelinger <[email protected]>
* Lavkesh Lahngir <[email protected]>
* Andreas Ripke <[email protected]>
* Vlad Dogaru <[email protected]>
* Octavian Purdila <[email protected]>
* John Ronan <[email protected]>
* Catalin Nicutar <[email protected]>
* Brandon Heller <[email protected]>
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _MPTCP_H
#define _MPTCP_H
#include <linux/inetdevice.h>
#include <linux/ipv6.h>
#include <linux/list.h>
#include <linux/net.h>
#include <linux/netpoll.h>
#include <linux/siphash.h>
#include <linux/skbuff.h>
#include <linux/socket.h>
#include <linux/tcp.h>
#include <linux/kernel.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
#include <crypto/hash.h>
#include <net/tcp.h>
#if defined(__LITTLE_ENDIAN_BITFIELD)
#define ntohll(x) be64_to_cpu(x)
#define htonll(x) cpu_to_be64(x)
#elif defined(__BIG_ENDIAN_BITFIELD)
#define ntohll(x) (x)
#define htonll(x) (x)
#endif
struct mptcp_loc4 {
u8 loc4_id;
u8 low_prio:1;
int if_idx;
struct in_addr addr;
};
struct mptcp_rem4 {
u8 rem4_id;
__be16 port;
struct in_addr addr;
};
struct mptcp_loc6 {
u8 loc6_id;
u8 low_prio:1;
int if_idx;
struct in6_addr addr;
};
struct mptcp_rem6 {
u8 rem6_id;
__be16 port;
struct in6_addr addr;
};
struct mptcp_request_sock {
struct tcp_request_sock req;
struct hlist_nulls_node hash_entry;
union {
struct {
/* Only on initial subflows */
u64 mptcp_loc_key;
u64 mptcp_rem_key;
u32 mptcp_loc_token;
};
struct {
/* Only on additional subflows */
u32 mptcp_rem_nonce;
u32 mptcp_loc_nonce;
u64 mptcp_hash_tmac;
};
};
u8 loc_id;
u8 rem_id; /* Address-id in the MP_JOIN */
u8 dss_csum:1,
is_sub:1, /* Is this a new subflow? */
low_prio:1, /* Interface set to low-prio? */
rcv_low_prio:1,
mptcp_ver:4;
};
struct mptcp_options_received {
u16 saw_mpc:1,
dss_csum:1,
drop_me:1,
is_mp_join:1,
join_ack:1,
saw_low_prio:2, /* 0x1 - low-prio set for this subflow
* 0x2 - low-prio set for another subflow
*/
low_prio:1,
saw_add_addr:2, /* Saw at least one add_addr option:
* 0x1: IPv4 - 0x2: IPv6
*/
more_add_addr:1, /* Saw one more add-addr. */
saw_rem_addr:1, /* Saw at least one rem_addr option */
more_rem_addr:1, /* Saw one more rem-addr. */
mp_fail:1,
mp_fclose:1;
u8 rem_id; /* Address-id in the MP_JOIN */
u8 prio_addr_id; /* Address-id in the MP_PRIO */
const unsigned char *add_addr_ptr; /* Pointer to add-address option */
const unsigned char *rem_addr_ptr; /* Pointer to rem-address option */
u32 data_ack;
u32 data_seq;
u16 data_len;
u8 mptcp_ver; /* MPTCP version */
/* Key inside the option (from mp_capable or fast_close) */
u64 mptcp_sender_key;
u64 mptcp_receiver_key;
u32 mptcp_rem_token; /* Remote token */
u32 mptcp_recv_nonce;
u64 mptcp_recv_tmac;
u8 mptcp_recv_mac[20];
};
struct mptcp_tcp_sock {
struct hlist_node node;
struct hlist_node cb_list;
struct mptcp_options_received rx_opt;
/* Those three fields record the current mapping */
u64 map_data_seq;
u32 map_subseq;
u16 map_data_len;
u16 slave_sk:1,
fully_established:1,
second_packet:1,
attached:1,
send_mp_fail:1,
include_mpc:1,
mapping_present:1,
map_data_fin:1,
low_prio:1, /* use this socket as backup */
rcv_low_prio:1, /* Peer sent low-prio option to us */
send_mp_prio:1, /* Trigger to send mp_prio on this socket */
pre_established:1; /* State between sending 3rd ACK and
* receiving the fourth ack of new subflows.
*/
/* isn: needed to translate abs to relative subflow seqnums */
u32 snt_isn;
u32 rcv_isn;
u8 path_index;
u8 loc_id;
u8 rem_id;
u8 sk_err;
#define MPTCP_SCHED_SIZE 128
u8 mptcp_sched[MPTCP_SCHED_SIZE] __aligned(8);
int init_rcv_wnd;
u32 infinite_cutoff_seq;
struct delayed_work work;
u32 mptcp_loc_nonce;
struct tcp_sock *tp;
u32 last_end_data_seq;
/* MP_JOIN subflow: timer for retransmitting the 3rd ack */
struct timer_list mptcp_ack_timer;
/* HMAC of the third ack */
char sender_mac[20];
};
struct mptcp_tw {
struct list_head list;
u64 loc_key;
u64 rcv_nxt;
struct mptcp_cb __rcu *mpcb;
u8 meta_tw:1,
in_list:1;
};
#define MPTCP_PM_NAME_MAX 16
struct mptcp_pm_ops {
struct list_head list;
/* Signal the creation of a new MPTCP-session. */
void (*new_session)(const struct sock *meta_sk);
void (*release_sock)(struct sock *meta_sk);
void (*fully_established)(struct sock *meta_sk);
void (*close_session)(struct sock *meta_sk);
void (*new_remote_address)(struct sock *meta_sk);
int (*get_local_id)(const struct sock *meta_sk, sa_family_t family,
union inet_addr *addr, bool *low_prio);
void (*addr_signal)(struct sock *sk, unsigned *size,
struct tcp_out_options *opts, struct sk_buff *skb);
void (*add_raddr)(struct mptcp_cb *mpcb, const union inet_addr *addr,
sa_family_t family, __be16 port, u8 id);
void (*rem_raddr)(struct mptcp_cb *mpcb, u8 rem_id);
void (*init_subsocket_v4)(struct sock *sk, struct in_addr addr);
void (*init_subsocket_v6)(struct sock *sk, struct in6_addr addr);
void (*established_subflow)(struct sock *sk);
void (*delete_subflow)(struct sock *sk);
void (*prio_changed)(struct sock *sk, int low_prio);
char name[MPTCP_PM_NAME_MAX];
struct module *owner;
};
#define MPTCP_SCHED_NAME_MAX 16
struct mptcp_sched_ops {
struct list_head list;
struct sock * (*get_subflow)(struct sock *meta_sk,
struct sk_buff *skb,
bool zero_wnd_test);
struct sk_buff * (*next_segment)(struct sock *meta_sk,
int *reinject,
struct sock **subsk,
unsigned int *limit);
void (*init)(struct sock *sk);
void (*release)(struct sock *sk);
char name[MPTCP_SCHED_NAME_MAX];
struct module *owner;
};
struct mptcp_cb {
/* list of sockets in this multipath connection */
struct hlist_head conn_list;
/* list of sockets that need a call to release_cb */
struct hlist_head callback_list;
/* Lock used for protecting the different rcu-lists of mptcp_cb */
spinlock_t mpcb_list_lock;
/* High-order bits of 64-bit sequence numbers */
u32 snd_high_order[2];
u32 rcv_high_order[2];
u16 send_infinite_mapping:1,
in_time_wait:1,
list_rcvd:1, /* XXX TO REMOVE */
addr_signal:1, /* Path-manager wants us to call addr_signal */
dss_csum:1,
server_side:1,
infinite_mapping_rcv:1,
infinite_mapping_snd:1,
dfin_combined:1, /* Was the DFIN combined with subflow-fin? */
passive_close:1,
snd_hiseq_index:1, /* Index in snd_high_order of snd_nxt */
rcv_hiseq_index:1, /* Index in rcv_high_order of rcv_nxt */
tcp_ca_explicit_set:1; /* was meta CC set by app? */
#define MPTCP_SCHED_DATA_SIZE 128
u8 mptcp_sched[MPTCP_SCHED_DATA_SIZE] __aligned(8);
const struct mptcp_sched_ops *sched_ops;
struct sk_buff_head reinject_queue;
/* First cache-line boundary is here minus 8 bytes. But from the
* reinject-queue only the next and prev pointers are regularly
* accessed. Thus, the whole data-path is on a single cache-line.
*/
u64 csum_cutoff_seq;
u64 infinite_rcv_seq;
/***** Start of fields, used for connection closure */
unsigned char mptw_state;
u8 dfin_path_index;
struct list_head tw_list;
/***** Start of fields, used for subflow establishment and closure */
refcount_t mpcb_refcnt;
/* Mutex needed, because otherwise mptcp_close will complain that the
* socket is owned by the user.
* E.g., mptcp_sub_close_wq is taking the meta-lock.
*/
struct mutex mpcb_mutex;
/***** Start of fields, used for subflow establishment */
struct sock *meta_sk;
/* Master socket, also part of the conn_list, this
* socket is the one that the application sees.
*/
struct sock *master_sk;
__u64 mptcp_loc_key;
__u64 mptcp_rem_key;
__u32 mptcp_loc_token;
__u32 mptcp_rem_token;
#define MPTCP_PM_SIZE 608
u8 mptcp_pm[MPTCP_PM_SIZE] __aligned(8);
const struct mptcp_pm_ops *pm_ops;
unsigned long path_index_bits;
__u8 mptcp_ver;
/* Original snd/rcvbuf of the initial subflow.
* Used for the new subflows on the server-side to allow correct
* autotuning
*/
int orig_sk_rcvbuf;
int orig_sk_sndbuf;
u32 orig_window_clamp;
struct tcp_info *master_info;
};
#define MPTCP_VERSION_0 0
#define MPTCP_VERSION_1 1
#define MPTCP_SUB_CAPABLE 0
#define MPTCP_SUB_LEN_CAPABLE_SYN 12
#define MPTCP_SUB_LEN_CAPABLE_SYN_ALIGN 12
#define MPTCP_SUB_LEN_CAPABLE_ACK 20
#define MPTCP_SUB_LEN_CAPABLE_ACK_ALIGN 20
#define MPTCP_SUB_JOIN 1
#define MPTCP_SUB_LEN_JOIN_SYN 12
#define MPTCP_SUB_LEN_JOIN_SYN_ALIGN 12
#define MPTCP_SUB_LEN_JOIN_SYNACK 16
#define MPTCP_SUB_LEN_JOIN_SYNACK_ALIGN 16
#define MPTCP_SUB_LEN_JOIN_ACK 24
#define MPTCP_SUB_LEN_JOIN_ACK_ALIGN 24
#define MPTCP_SUB_DSS 2
#define MPTCP_SUB_LEN_DSS 4
#define MPTCP_SUB_LEN_DSS_ALIGN 4
/* Lengths for seq and ack are the ones without the generic MPTCP-option header,
* as they are part of the DSS-option.
* To get the total length, just add the different options together.
*/
#define MPTCP_SUB_LEN_SEQ 10
#define MPTCP_SUB_LEN_SEQ_CSUM 12
#define MPTCP_SUB_LEN_SEQ_ALIGN 12
#define MPTCP_SUB_LEN_SEQ_64 14
#define MPTCP_SUB_LEN_SEQ_CSUM_64 16
#define MPTCP_SUB_LEN_SEQ_64_ALIGN 16
#define MPTCP_SUB_LEN_ACK 4
#define MPTCP_SUB_LEN_ACK_ALIGN 4
#define MPTCP_SUB_LEN_ACK_64 8
#define MPTCP_SUB_LEN_ACK_64_ALIGN 8
/* This is the "default" option-length we will send out most often.
* MPTCP DSS-header
* 32-bit data sequence number
* 32-bit data ack
*
* It is necessary to calculate the effective MSS we will be using when
* sending data.
*/
#define MPTCP_SUB_LEN_DSM_ALIGN (MPTCP_SUB_LEN_DSS_ALIGN + \
MPTCP_SUB_LEN_SEQ_ALIGN + \
MPTCP_SUB_LEN_ACK_ALIGN)
#define MPTCP_SUB_ADD_ADDR 3
#define MPTCP_SUB_LEN_ADD_ADDR4 8
#define MPTCP_SUB_LEN_ADD_ADDR4_VER1 16
#define MPTCP_SUB_LEN_ADD_ADDR6 20
#define MPTCP_SUB_LEN_ADD_ADDR6_VER1 28
#define MPTCP_SUB_LEN_ADD_ADDR4_ALIGN 8
#define MPTCP_SUB_LEN_ADD_ADDR4_ALIGN_VER1 16
#define MPTCP_SUB_LEN_ADD_ADDR6_ALIGN 20
#define MPTCP_SUB_LEN_ADD_ADDR6_ALIGN_VER1 28
#define MPTCP_SUB_REMOVE_ADDR 4
#define MPTCP_SUB_LEN_REMOVE_ADDR 4
#define MPTCP_SUB_PRIO 5
#define MPTCP_SUB_LEN_PRIO 3
#define MPTCP_SUB_LEN_PRIO_ADDR 4
#define MPTCP_SUB_LEN_PRIO_ALIGN 4
#define MPTCP_SUB_FAIL 6
#define MPTCP_SUB_LEN_FAIL 12
#define MPTCP_SUB_LEN_FAIL_ALIGN 12
#define MPTCP_SUB_FCLOSE 7
#define MPTCP_SUB_LEN_FCLOSE 12
#define MPTCP_SUB_LEN_FCLOSE_ALIGN 12
#define OPTION_MPTCP (1 << 5)
/* Max number of fastclose retransmissions */
#define MPTCP_FASTCLOSE_RETRIES 3
#ifdef CONFIG_MPTCP
/* Used for checking if the mptcp initialization has been successful */
extern bool mptcp_init_failed;
/* MPTCP options */
#define OPTION_TYPE_SYN (1 << 0)
#define OPTION_TYPE_SYNACK (1 << 1)
#define OPTION_TYPE_ACK (1 << 2)
#define OPTION_MP_CAPABLE (1 << 3)
#define OPTION_DATA_ACK (1 << 4)
#define OPTION_ADD_ADDR (1 << 5)
#define OPTION_MP_JOIN (1 << 6)
#define OPTION_MP_FAIL (1 << 7)
#define OPTION_MP_FCLOSE (1 << 8)
#define OPTION_REMOVE_ADDR (1 << 9)
#define OPTION_MP_PRIO (1 << 10)
/* MPTCP flags: both TX and RX */
#define MPTCPHDR_SEQ 0x01 /* DSS.M option is present */
#define MPTCPHDR_FIN 0x02 /* DSS.F option is present */
#define MPTCPHDR_SEQ64_INDEX 0x04 /* index of seq in mpcb->snd_high_order */
/* MPTCP flags: RX only */
#define MPTCPHDR_ACK 0x08
#define MPTCPHDR_SEQ64_SET 0x10 /* Did we received a 64-bit seq number? */
#define MPTCPHDR_SEQ64_OFO 0x20 /* Is it not in our circular array? */
#define MPTCPHDR_DSS_CSUM 0x40
/* MPTCP flags: TX only */
#define MPTCPHDR_INF 0x08
#define MPTCP_REINJECT 0x10 /* Did we reinject this segment? */
struct mptcp_option {
__u8 kind;
__u8 len;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ver:4,
sub:4;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 sub:4,
ver:4;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
};
struct mp_capable {
__u8 kind;
__u8 len;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ver:4,
sub:4;
__u8 h:1,
rsv:5,
b:1,
a:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 sub:4,
ver:4;
__u8 a:1,
b:1,
rsv:5,
h:1;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__u64 sender_key;
__u64 receiver_key;
} __attribute__((__packed__));
struct mp_join {
__u8 kind;
__u8 len;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 b:1,
rsv:3,
sub:4;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 sub:4,
rsv:3,
b:1;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__u8 addr_id;
union {
struct {
u32 token;
u32 nonce;
} syn;
struct {
__u64 mac;
u32 nonce;
} synack;
struct {
__u8 mac[20];
} ack;
} u;
} __attribute__((__packed__));
struct mp_dss {
__u8 kind;
__u8 len;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 rsv1:4,
sub:4,
A:1,
a:1,
M:1,
m:1,
F:1,
rsv2:3;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 sub:4,
rsv1:4,
rsv2:3,
F:1,
m:1,
M:1,
a:1,
A:1;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
};
struct mp_add_addr {
__u8 kind;
__u8 len;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ipver:4,
sub:4;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 sub:4,
ipver:4;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__u8 addr_id;
union {
struct {
struct in_addr addr;
__be16 port;
__u8 mac[8];
} v4;
struct {
struct in6_addr addr;
__be16 port;
__u8 mac[8];
} v6;
} u;
} __attribute__((__packed__));
struct mp_remove_addr {
__u8 kind;
__u8 len;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 rsv:4,
sub:4;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 sub:4,
rsv:4;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
/* list of addr_id */
__u8 addrs_id;
};
struct mp_fail {
__u8 kind;
__u8 len;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 rsv1:4,
sub:4,
rsv2:8;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 sub:4,
rsv1:4,
rsv2:8;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__be64 data_seq;
} __attribute__((__packed__));
struct mp_fclose {
__u8 kind;
__u8 len;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 rsv1:4,
sub:4,
rsv2:8;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 sub:4,
rsv1:4,
rsv2:8;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__u64 key;
} __attribute__((__packed__));
struct mp_prio {
__u8 kind;
__u8 len;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 b:1,
rsv:3,
sub:4;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 sub:4,
rsv:3,
b:1;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__u8 addr_id;
} __attribute__((__packed__));
static inline int mptcp_sub_len_dss(const struct mp_dss *m, const int csum)
{
return 4 + m->A * (4 + m->a * 4) + m->M * (10 + m->m * 4 + csum * 2);
}
#define MPTCP_SYSCTL 1
extern int sysctl_mptcp_enabled;
extern int sysctl_mptcp_version;
extern int sysctl_mptcp_checksum;
extern int sysctl_mptcp_debug;
extern int sysctl_mptcp_syn_retries;
extern struct workqueue_struct *mptcp_wq;
#define mptcp_debug(fmt, args...) \
do { \
if (unlikely(sysctl_mptcp_debug)) \
pr_err(fmt, ##args); \
} while (0)
static inline struct sock *mptcp_to_sock(const struct mptcp_tcp_sock *mptcp)
{
return (struct sock *)mptcp->tp;
}
#define mptcp_for_each_sub(__mpcb, __mptcp) \
hlist_for_each_entry_rcu(__mptcp, &((__mpcb)->conn_list), node)
/* Must be called with the appropriate lock held */
#define mptcp_for_each_sub_safe(__mpcb, __mptcp, __tmp) \
hlist_for_each_entry_safe(__mptcp, __tmp, &((__mpcb)->conn_list), node)
/* Iterates over all bit set to 1 in a bitset */
#define mptcp_for_each_bit_set(b, i) \
for (i = ffs(b) - 1; i >= 0; i = ffs(b >> (i + 1) << (i + 1)) - 1)
#define mptcp_for_each_bit_unset(b, i) \
mptcp_for_each_bit_set(~b, i)
#define MPTCP_INC_STATS(net, field) SNMP_INC_STATS((net)->mptcp.mptcp_statistics, field)
#define MPTCP_INC_STATS_BH(net, field) __SNMP_INC_STATS((net)->mptcp.mptcp_statistics, field)
enum
{
MPTCP_MIB_NUM = 0,
MPTCP_MIB_MPCAPABLEPASSIVE, /* Received SYN with MP_CAPABLE */
MPTCP_MIB_MPCAPABLEACTIVE, /* Sent SYN with MP_CAPABLE */
MPTCP_MIB_MPCAPABLEACTIVEACK, /* Received SYN/ACK with MP_CAPABLE */
MPTCP_MIB_MPCAPABLEPASSIVEACK, /* Received third ACK with MP_CAPABLE */
MPTCP_MIB_MPCAPABLEPASSIVEFALLBACK,/* Server-side fallback during 3-way handshake */
MPTCP_MIB_MPCAPABLEACTIVEFALLBACK, /* Client-side fallback during 3-way handshake */
MPTCP_MIB_MPCAPABLERETRANSFALLBACK,/* Client-side stopped sending MP_CAPABLE after too many SYN-retransmissions */
MPTCP_MIB_CSUMENABLED, /* Created MPTCP-connection with DSS-checksum enabled */
MPTCP_MIB_RETRANSSEGS, /* Segments retransmitted at the MPTCP-level */
MPTCP_MIB_MPFAILRX, /* Received an MP_FAIL */
MPTCP_MIB_CSUMFAIL, /* Received segment with invalid checksum */
MPTCP_MIB_FASTCLOSERX, /* Recevied a FAST_CLOSE */
MPTCP_MIB_FASTCLOSETX, /* Sent a FAST_CLOSE */
MPTCP_MIB_FBACKSUB, /* Fallback upon ack without data-ack on new subflow */
MPTCP_MIB_FBACKINIT, /* Fallback upon ack without data-ack on initial subflow */
MPTCP_MIB_FBDATASUB, /* Fallback upon data without DSS at the beginning on new subflow */
MPTCP_MIB_FBDATAINIT, /* Fallback upon data without DSS at the beginning on initial subflow */
MPTCP_MIB_REMADDRSUB, /* Remove subflow due to REMOVE_ADDR */
MPTCP_MIB_JOINNOTOKEN, /* Received MP_JOIN but the token was not found */
MPTCP_MIB_JOINFALLBACK, /* Received MP_JOIN on session that has fallen back to reg. TCP */
MPTCP_MIB_JOINSYNTX, /* Sent a SYN + MP_JOIN */
MPTCP_MIB_JOINSYNRX, /* Received a SYN + MP_JOIN */
MPTCP_MIB_JOINSYNACKRX, /* Received a SYN/ACK + MP_JOIN */
MPTCP_MIB_JOINSYNACKMAC, /* HMAC was wrong on SYN/ACK + MP_JOIN */
MPTCP_MIB_JOINACKRX, /* Received an ACK + MP_JOIN */
MPTCP_MIB_JOINACKMAC, /* HMAC was wrong on ACK + MP_JOIN */
MPTCP_MIB_JOINACKFAIL, /* Third ACK on new subflow did not contain an MP_JOIN */
MPTCP_MIB_JOINACKRTO, /* Retransmission timer for third ACK + MP_JOIN timed out */
MPTCP_MIB_JOINACKRXMIT, /* Retransmitted an ACK + MP_JOIN */
MPTCP_MIB_NODSSWINDOW, /* Received too many packets without a DSS-option */
MPTCP_MIB_DSSNOMATCH, /* Received a new mapping that did not match the previous one */
MPTCP_MIB_INFINITEMAPRX, /* Received an infinite mapping */
MPTCP_MIB_DSSTCPMISMATCH, /* DSS-mapping did not map with TCP's sequence numbers */
MPTCP_MIB_DSSTRIMHEAD, /* Trimmed segment at the head (coalescing middlebox) */
MPTCP_MIB_DSSSPLITTAIL, /* Trimmed segment at the tail (coalescing middlebox) */
MPTCP_MIB_PURGEOLD, /* Removed old skb from the rcv-queue due to missing DSS-mapping */
MPTCP_MIB_ADDADDRRX, /* Received an ADD_ADDR */
MPTCP_MIB_ADDADDRTX, /* Sent an ADD_ADDR */
MPTCP_MIB_REMADDRRX, /* Received a REMOVE_ADDR */
MPTCP_MIB_REMADDRTX, /* Sent a REMOVE_ADDR */
__MPTCP_MIB_MAX
};
#define MPTCP_MIB_MAX __MPTCP_MIB_MAX
struct mptcp_mib {
unsigned long mibs[MPTCP_MIB_MAX];
};
extern struct lock_class_key meta_key;
extern char *meta_key_name;
extern struct lock_class_key meta_slock_key;
extern char *meta_slock_key_name;
extern siphash_key_t mptcp_secret;
/* This is needed to ensure that two subsequent key/nonce-generation result in
* different keys/nonces if the IPs and ports are the same.
*/
extern u32 mptcp_seed;
#define MPTCP_HASH_SIZE 1024
extern struct hlist_nulls_head tk_hashtable[MPTCP_HASH_SIZE];
/* Request-sockets can be hashed in the tk_htb for collision-detection or in
* the regular htb for join-connections. We need to define different NULLS
* values so that we can correctly detect a request-socket that has been
* recycled. See also c25eb3bfb9729.
*/
#define MPTCP_REQSK_NULLS_BASE (1U << 29)
void mptcp_data_ready(struct sock *sk);
void mptcp_write_space(struct sock *sk);
void mptcp_add_meta_ofo_queue(const struct sock *meta_sk, struct sk_buff *skb,
struct sock *sk);
void mptcp_cleanup_rbuf(struct sock *meta_sk, int copied);
int mptcp_add_sock(struct sock *meta_sk, struct sock *sk, u8 loc_id, u8 rem_id,
gfp_t flags);
void mptcp_del_sock(struct sock *sk);
void mptcp_update_metasocket(const struct sock *meta_sk);
void mptcp_reinject_data(struct sock *orig_sk, int clone_it);
void mptcp_update_sndbuf(const struct tcp_sock *tp);
void mptcp_send_fin(struct sock *meta_sk);
void mptcp_send_active_reset(struct sock *meta_sk, gfp_t priority);
bool mptcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
int push_one, gfp_t gfp);
void tcp_parse_mptcp_options(const struct sk_buff *skb,
struct mptcp_options_received *mopt);
void mptcp_parse_options(const uint8_t *ptr, int opsize,
struct mptcp_options_received *mopt,
const struct sk_buff *skb,
struct tcp_sock *tp);
void mptcp_syn_options(const struct sock *sk, struct tcp_out_options *opts,
unsigned *remaining);
void mptcp_synack_options(struct request_sock *req,
struct tcp_out_options *opts,
unsigned *remaining);
void mptcp_established_options(struct sock *sk, struct sk_buff *skb,
struct tcp_out_options *opts, unsigned *size);
void mptcp_options_write(__be32 *ptr, struct tcp_sock *tp,
const struct tcp_out_options *opts,
struct sk_buff *skb);
void mptcp_close(struct sock *meta_sk, long timeout);
bool mptcp_doit(struct sock *sk);
int mptcp_create_master_sk(struct sock *meta_sk, __u64 remote_key,
__u8 mptcp_ver, u32 window);
int mptcp_check_req_fastopen(struct sock *child, struct request_sock *req);
int mptcp_check_req_master(struct sock *sk, struct sock *child,
struct request_sock *req, const struct sk_buff *skb,
int drop, u32 tsoff);
struct sock *mptcp_check_req_child(struct sock *meta_sk,
struct sock *child,
struct request_sock *req,
struct sk_buff *skb,
const struct mptcp_options_received *mopt);
u32 __mptcp_select_window(struct sock *sk);
void mptcp_select_initial_window(const struct sock *sk, int __space, __u32 mss,
__u32 *rcv_wnd, __u32 *window_clamp,
int wscale_ok, __u8 *rcv_wscale,
__u32 init_rcv_wnd);
unsigned int mptcp_current_mss(struct sock *meta_sk);
int mptcp_select_size(const struct sock *meta_sk, bool first_skb, bool zc);
void mptcp_hmac_sha1(const u8 *key_1, const u8 *key_2, u32 *hash_out,
int arg_num, ...);
void mptcp_clean_rtx_infinite(const struct sk_buff *skb, struct sock *sk);
void mptcp_fin(struct sock *meta_sk);
void mptcp_meta_retransmit_timer(struct sock *meta_sk);
void mptcp_sub_retransmit_timer(struct sock *sk);
int mptcp_write_wakeup(struct sock *meta_sk, int mib);
void mptcp_sub_close_wq(struct work_struct *work);
void mptcp_sub_close(struct sock *sk, unsigned long delay);
struct sock *mptcp_select_ack_sock(const struct sock *meta_sk);
void mptcp_prepare_for_backlog(struct sock *sk, struct sk_buff *skb);
int mptcp_backlog_rcv(struct sock *meta_sk, struct sk_buff *skb);
void mptcp_ack_handler(struct timer_list *t);
bool mptcp_check_rtt(const struct tcp_sock *tp, int time);
int mptcp_check_snd_buf(const struct tcp_sock *tp);
bool mptcp_handle_options(struct sock *sk, const struct tcphdr *th,
const struct sk_buff *skb);
void __init mptcp_init(void);
void mptcp_destroy_sock(struct sock *sk);
int mptcp_rcv_synsent_state_process(struct sock *sk, struct sock **skptr,
const struct sk_buff *skb,
const struct mptcp_options_received *mopt);
unsigned int mptcp_xmit_size_goal(const struct sock *meta_sk, u32 mss_now,
int large_allowed);
int mptcp_init_tw_sock(struct sock *sk, struct tcp_timewait_sock *tw);
void mptcp_twsk_destructor(struct tcp_timewait_sock *tw);
void mptcp_time_wait(struct sock *sk, int state, int timeo);
void mptcp_disconnect(struct sock *meta_sk);
bool mptcp_should_expand_sndbuf(const struct sock *sk);
int mptcp_retransmit_skb(struct sock *meta_sk, struct sk_buff *skb);
void mptcp_tsq_flags(struct sock *sk);
void mptcp_tsq_sub_deferred(struct sock *meta_sk);
struct mp_join *mptcp_find_join(const struct sk_buff *skb);
void mptcp_hash_remove_bh(struct tcp_sock *meta_tp);
struct sock *mptcp_hash_find(const struct net *net, const u32 token);
int mptcp_lookup_join(struct sk_buff *skb, struct inet_timewait_sock *tw);
int mptcp_do_join_short(struct sk_buff *skb,
const struct mptcp_options_received *mopt,
struct net *net);
void mptcp_reqsk_destructor(struct request_sock *req);
void mptcp_connect_init(struct sock *sk);
void mptcp_sub_force_close(struct sock *sk);
int mptcp_sub_len_remove_addr_align(u16 bitfield);
void mptcp_join_reqsk_init(const struct mptcp_cb *mpcb,
const struct request_sock *req,
struct sk_buff *skb);
void mptcp_reqsk_init(struct request_sock *req, const struct sock *sk,
const struct sk_buff *skb, bool want_cookie);
int mptcp_conn_request(struct sock *sk, struct sk_buff *skb);
void mptcp_enable_sock(struct sock *sk);
void mptcp_disable_sock(struct sock *sk);
void mptcp_disable_static_key(void);
void mptcp_cookies_reqsk_init(struct request_sock *req,
struct mptcp_options_received *mopt,
struct sk_buff *skb);
void mptcp_mpcb_put(struct mptcp_cb *mpcb);
int mptcp_finish_handshake(struct sock *child, struct sk_buff *skb);
int mptcp_get_info(const struct sock *meta_sk, char __user *optval, int optlen);
void mptcp_clear_sk(struct sock *sk, int size);
/* MPTCP-path-manager registration/initialization functions */
int mptcp_register_path_manager(struct mptcp_pm_ops *pm);
void mptcp_unregister_path_manager(struct mptcp_pm_ops *pm);
void mptcp_init_path_manager(struct mptcp_cb *mpcb);
void mptcp_cleanup_path_manager(struct mptcp_cb *mpcb);
void mptcp_fallback_default(struct mptcp_cb *mpcb);
void mptcp_get_default_path_manager(char *name);
int mptcp_set_scheduler(struct sock *sk, const char *name);
int mptcp_set_path_manager(struct sock *sk, const char *name);
int mptcp_set_default_path_manager(const char *name);
int mptcp_set_split_ratio(struct sock *sk, char *ratio,int optlen);
int random_mptcp_set_weight(struct sock *sk, char *ratio,int optlen);
extern struct mptcp_pm_ops mptcp_pm_default;
/* MPTCP-scheduler registration/initialization functions */
int mptcp_register_scheduler(struct mptcp_sched_ops *sched);
void mptcp_unregister_scheduler(struct mptcp_sched_ops *sched);
void mptcp_init_scheduler(struct mptcp_cb *mpcb);
void mptcp_cleanup_scheduler(struct mptcp_cb *mpcb);
void mptcp_get_default_scheduler(char *name);
int mptcp_set_default_scheduler(const char *name);
bool mptcp_is_available(struct sock *sk, const struct sk_buff *skb,
bool zero_wnd_test);
bool mptcp_is_def_unavailable(struct sock *sk);
bool subflow_is_active(const struct tcp_sock *tp);
bool subflow_is_backup(const struct tcp_sock *tp);
struct sock *get_available_subflow(struct sock *meta_sk, struct sk_buff *skb,
bool zero_wnd_test);
extern struct mptcp_sched_ops mptcp_sched_default;
/* Initializes function-pointers and MPTCP-flags */
static inline void mptcp_init_tcp_sock(struct sock *sk)
{
if (!mptcp_init_failed && sysctl_mptcp_enabled == MPTCP_SYSCTL)
mptcp_enable_sock(sk);
}
static inline int mptcp_pi_to_flag(int pi)
{
return 1 << (pi - 1);
}
static inline
struct mptcp_request_sock *mptcp_rsk(const struct request_sock *req)
{
return (struct mptcp_request_sock *)req;
}
static inline
struct request_sock *rev_mptcp_rsk(const struct mptcp_request_sock *req)
{
return (struct request_sock *)req;
}
static inline bool mptcp_can_sendpage(struct sock *sk)
{
struct mptcp_tcp_sock *mptcp;
if (tcp_sk(sk)->mpcb->dss_csum)
return false;
mptcp_for_each_sub(tcp_sk(sk)->mpcb, mptcp) {
struct sock *sk_it = mptcp_to_sock(mptcp);
if (!(sk_it->sk_route_caps & NETIF_F_SG))
return false;
}
return true;
}
static inline void mptcp_push_pending_frames(struct sock *meta_sk)
{
/* We check packets out and send-head here. TCP only checks the
* send-head. But, MPTCP also checks packets_out, as this is an
* indication that we might want to do opportunistic reinjection.
*/
if (tcp_sk(meta_sk)->packets_out || tcp_send_head(meta_sk)) {
struct tcp_sock *tp = tcp_sk(meta_sk);
/* We don't care about the MSS, because it will be set in
* mptcp_write_xmit.
*/
__tcp_push_pending_frames(meta_sk, 0, tp->nonagle);
}
}
static inline void mptcp_send_reset(struct sock *sk)
{
if (tcp_need_reset(sk->sk_state))
tcp_sk(sk)->ops->send_active_reset(sk, GFP_ATOMIC);
mptcp_sub_force_close(sk);
}
static inline void mptcp_sub_force_close_all(struct mptcp_cb *mpcb,
struct sock *except)
{
struct mptcp_tcp_sock *mptcp;
struct hlist_node *tmp;
mptcp_for_each_sub_safe(mpcb, mptcp, tmp) {
struct sock *sk_it = mptcp_to_sock(mptcp);
if (sk_it != except)
mptcp_send_reset(sk_it);
}
}
static inline bool mptcp_is_data_seq(const struct sk_buff *skb)
{
return TCP_SKB_CB(skb)->mptcp_flags & MPTCPHDR_SEQ;
}
static inline bool mptcp_is_data_fin(const struct sk_buff *skb)
{
return TCP_SKB_CB(skb)->mptcp_flags & MPTCPHDR_FIN;
}
/* Is it a data-fin while in infinite mapping mode?
* In infinite mode, a subflow-fin is in fact a data-fin.
*/