-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtcp.h
executable file
·1969 lines (1680 loc) · 66.4 KB
/
tcp.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
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for the TCP module.
*
* Version: @(#)tcp.h 1.0.5 05/23/93
*
* Authors: Ross Biro
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* 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 _TCP_H
#define _TCP_H
#define TCP_DEBUG 1
#define FASTRETRANS_DEBUG 1
#include <linux/list.h>
#include <linux/tcp.h>
#include <linux/slab.h>
#include <linux/cache.h>
#include <linux/percpu.h>
#include <linux/skbuff.h>
#include <linux/dmaengine.h>
#include <linux/crypto.h>
#include <linux/cryptohash.h>
#include <linux/kref.h>
#include <net/inet_connection_sock.h>
#include <net/inet_timewait_sock.h>
#include <net/inet_hashtables.h>
#include <net/checksum.h>
#include <net/request_sock.h>
#include <net/sock.h>
#include <net/snmp.h>
#include <net/ip.h>
#include <net/tcp_states.h>
#include <net/inet_ecn.h>
#include <net/dst.h>
#include <linux/seq_file.h>
extern struct inet_hashinfo tcp_hashinfo;
extern struct percpu_counter tcp_orphan_count;
extern void tcp_time_wait(struct sock *sk, int state, int timeo);
#define MAX_TCP_HEADER (128 + MAX_HEADER)
#define MAX_TCP_OPTION_SPACE 40
/*
* Never offer a window over 32767 without using window scaling. Some
* poor stacks do signed 16bit maths!
*/
#define MAX_TCP_WINDOW 32767U
/* Minimal accepted MSS. It is (60+60+8) - (20+20). */
#define TCP_MIN_MSS 88U
/* The least MTU to use for probing */
#define TCP_BASE_MSS 512
/* After receiving this amount of duplicate ACKs fast retransmit starts. */
#define TCP_FASTRETRANS_THRESH 3
/* Maximal reordering. */
#define TCP_MAX_REORDERING 127
/* Maximal number of ACKs sent quickly to accelerate slow-start. */
#define TCP_MAX_QUICKACKS 16U
/* urg_data states */
/* 标识紧急数据时有效的,用户可以读取*/
#define TCP_URG_VALID 0x0100
/* 标识接收到的段中存在紧急数据*/
#define TCP_URG_NOTYET 0x0200
/* 标识紧急数据已全部被读取*/
#define TCP_URG_READ 0x0400
#define TCP_RETR1 3 /*
* This is how many retries it does before it
* tries to figure out if the gateway is
* down. Minimal RFC value is 3; it corresponds
* to ~3sec-8min depending on RTO.
*/
#define TCP_RETR2 15 /*
* This should take at least
* 90 minutes to time out.
* RFC1122 says that the limit is 100 sec.
* 15 is ~13-30min depending on RTO.
*/
#define TCP_SYN_RETRIES 5 /* number of times to retry active opening a
* connection: ~180sec is RFC minimum */
#define TCP_SYNACK_RETRIES 5 /* number of times to retry passive opening a
* connection: ~180sec is RFC minimum */
#define TCP_ORPHAN_RETRIES 7 /* number of times to retry on an orphaned
* socket. 7 is ~50sec-16min.
*/
#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT
* state, about 60 seconds */
#define TCP_FIN_TIMEOUT TCP_TIMEWAIT_LEN
/* BSD style FIN_WAIT2 deadlock breaker.
* It used to be 3min, new value is 60sec,
* to combine FIN-WAIT-2 timeout with
* TIME-WAIT timer.
*/
#define TCP_DELACK_MAX ((unsigned)(HZ/5)) /* maximal time to delay before sending an ACK */
#if HZ >= 100
#define TCP_DELACK_MIN ((unsigned)(HZ/25)) /* minimal time to delay before sending an ACK */
#define TCP_ATO_MIN ((unsigned)(HZ/25))
#else
#define TCP_DELACK_MIN 4U
#define TCP_ATO_MIN 4U
#endif
#define TCP_RTO_MAX ((unsigned)(120*HZ))
#define TCP_RTO_MIN ((unsigned)(HZ/5))
#define TCP_TIMEOUT_INIT ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value */
#define TCP_RESOURCE_PROBE_INTERVAL ((unsigned)(HZ/2U)) /* Maximal interval between probes
* for local resources.
*/
#define TCP_KEEPALIVE_TIME (120*60*HZ) /* two hours */
#define TCP_KEEPALIVE_PROBES 9 /* Max of 9 keepalive probes */
#define TCP_KEEPALIVE_INTVL (75*HZ)
#define MAX_TCP_KEEPIDLE 32767
#define MAX_TCP_KEEPINTVL 32767
#define MAX_TCP_KEEPCNT 127
#define MAX_TCP_SYNCNT 127
#define TCP_SYNQ_INTERVAL (HZ/5) /* Period of SYNACK timer */
#define TCP_PAWS_24DAYS (60 * 60 * 24 * 24)
#define TCP_PAWS_MSL 60 /* Per-host timestamps are invalidated
* after this time. It should be equal
* (or greater than) TCP_TIMEWAIT_LEN
* to provide reliability equal to one
* provided by timewait state.
*/
#define TCP_PAWS_WINDOW 1 /* Replay window for per-host
* timestamps. It must be less than
* minimal timewait lifetime.
*/
/*
* TCP option
*/
//这些一般在SYN段中,参考tcp_parse_options
#define TCPOPT_NOP 1 /* Padding */
#define TCPOPT_EOL 0 /* End of options */
#define TCPOPT_MSS 2 /* Segment size negotiating */
#define TCPOPT_WINDOW 3 /* Window scaling */
#define TCPOPT_SACK_PERM 4 /* SACK Permitted */
#define TCPOPT_SACK 5 /* SACK Block */
#define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
#define TCPOPT_MD5SIG 19 /* MD5 Signature (RFC2385) */
#define TCPOPT_COOKIE 253 /* Cookie extension (experimental) */
/*
* TCP option lengths
*/
#define TCPOLEN_MSS 4 //只能出现在SYN段中
#define TCPOLEN_WINDOW 3
#define TCPOLEN_SACK_PERM 2
#define TCPOLEN_TIMESTAMP 10
#define TCPOLEN_MD5SIG 18
#define TCPOLEN_COOKIE_BASE 2 /* Cookie-less header extension */
#define TCPOLEN_COOKIE_PAIR 3 /* Cookie pair header extension */
#define TCPOLEN_COOKIE_MIN (TCPOLEN_COOKIE_BASE+TCP_COOKIE_MIN)
#define TCPOLEN_COOKIE_MAX (TCPOLEN_COOKIE_BASE+TCP_COOKIE_MAX)
/* But this is what stacks really send out. */
#define TCPOLEN_TSTAMP_ALIGNED 12
#define TCPOLEN_WSCALE_ALIGNED 4
#define TCPOLEN_SACKPERM_ALIGNED 4
#define TCPOLEN_SACK_BASE 2
#define TCPOLEN_SACK_BASE_ALIGNED 4
#define TCPOLEN_SACK_PERBLOCK 8
#define TCPOLEN_MD5SIG_ALIGNED 20
#define TCPOLEN_MSS_ALIGNED 4
/* Flags in tp->nonagle */
#define TCP_NAGLE_OFF 1 /* Nagle's algo is disabled */
#define TCP_NAGLE_CORK 2 /* Socket is corked */
#define TCP_NAGLE_PUSH 4 /* Cork is overridden for already queued data */
/* TCP thin-stream limits */
#define TCP_THIN_LINEAR_RETRIES 6 /* After 6 linear retries, do exp. backoff */
/*
/proc/sys/net/ipv4/icmp_timeexceed_rate
这个在traceroute时导致著名的“Solaris middle star”。这个文件控制发送ICMP Time Exceeded消息的比率。
/proc/sys/net/ipv4/igmp_max_memberships
主机上最多有多少个igmp (多播)套接字进行监听。
/proc/sys/net/ipv4/inet_peer_gc_maxtime
求 助: Add a little explanation about the inet peer storage? Minimum interval between garbage collection passes. This interval is in effect under low (or absent) memory pressure on the pool. Measured in jiffies.
/proc/sys/net/ipv4/inet_peer_gc_mintime
每一遍碎片收集之间的最小时间间隔。当内存压力比较大的时候,调整这个间隔很有效。以jiffies计。
/proc/sys/net/ipv4/inet_peer_maxttl
entries的最大生存期。在pool没有内存压力的情况下(比如,pool中entries的数量很少的时候),未使用的entries经过一段时间就会过期。以jiffies计。
/proc/sys/net/ipv4/inet_peer_minttl
entries的最小生存期。应该不小于汇聚端分片的生存期。当pool的大小不大于inet_peer_threshold时,这个最小生存期必须予以保证。以jiffies计。
/proc/sys/net/ipv4/inet_peer_threshold
The approximate size of the INET peer storage. Starting from this threshold entries will be thrown aggressively. This threshold also determines entries' time-to-live and time intervals between garbage collection passes. More entries, less time-to-live, less GC interval.
/proc/sys/net/ipv4/ip_autoconfig
这个文件里面写着一个数字,表示主机是否通过RARP、BOOTP、DHCP或者其它机制取得其IP配置。否则就是0。
/proc/sys/net/ipv4/ip_default_ttl
数据包的生存期。设置为64是安全的。如果你的网络规模巨大就提高这个值。不要因为好玩而这么做——那样会产生有害的路由环路。实际上,在很多情况下你要考虑能否减小这个值。
/proc/sys/net/ipv4/ip_dynaddr/proc/sys/net/ipv4/icmp_destunreach_rate
如果你有一个动态地址的自动拨号接口,就得设置它。当你的自动拨号接口激活的时候,本地所有没有收到答复的TCP套接字会重新绑定到正确的地址上。这可以解决引发拨号的套接字本身无法工作,重试一次却可以的问题。
/proc/sys/net/ipv4/ip_forward
内核是否转发数据包。缺省禁止。
/proc/sys/net/ipv4/ip_local_port_range
用于向外连接的端口范围。缺省情况下其实很小:1024到4999。
/proc/sys/net/ipv4/ip_no_pmtu_disc
如果你想禁止“沿途MTU发现”就设置它。“沿途MTU发现”是一种技术,可以在传输路径上检测出最大可能的MTU值。参见Cookbook一章中关于“沿途MTU发现”的内容。
/proc/sys/net/ipv4/ipfrag_high_thresh
用 于IP分片汇聚的最大内存用量。分配了这么多字节的内存后,一旦用尽,分片处理程序就会丢弃分片。When ipfrag_high_thresh bytes of memory is allocated for this purpose, the fragment handler will toss packets until ipfrag_low_thresh is reached.
/proc/sys/net/ipv4/ip_nonlocal_bind
如果你希望你的应用程序能够绑定到不属于本地网卡的地址上时,设置这个选项。如果你的机器没有专线连接(甚至是动态连接)时非常有用,即使你的连接断开,你的服务也可以启动并绑定在一个指定的地址上。
/proc/sys/net/ipv4/ipfrag_low_thresh
用于IP分片汇聚的最小内存用量。
/proc/sys/net/ipv4/ipfrag_time
IP分片在内存中的保留时间(秒数)。
/proc/sys/net/ipv4/tcp_abort_on_overflow
一个布尔类型的标志,控制着当有很多的连接请求时内核的行为。启用的话,如果服务超载,内核将主动地发送RST包。
/proc/sys/net/ipv4/tcp_fin_timeout
如 果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60秒。2.2 内核的通常值是180秒,你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB服务器,也有因为大量的死套接字而内存溢出的风险,FIN- WAIT-2的危险性比FIN-WAIT-1要小,因为它最多只能吃掉1.5K内存,但是它们的生存期长些。参见tcp_max_orphans。
/proc/sys/net/ipv4/tcp_keepalive_time
当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时。
/proc/sys/net/ipv4/tcp_keepalive_intvl
当探测没有确认时,重新发送探测的频度。缺省是75秒。
/proc/sys/net/ipv4/tcp_keepalive_probes
在认定连接失效之前,发送多少个TCP的keepalive探测包。缺省值是9。这个值乘以tcp_keepalive_intvl之后决定了,一个连接发送了keepalive之后可以有多少时间没有回应。
/proc/sys/net/ipv4/tcp_max_orphans
系 统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打印出警告信息。这个限制仅仅是为了防止简单的DoS攻击,你绝对不能过分依靠它或者人为地减小这个值,更应该增加这个值(如果增加了内存之后)。This limit exists only to prevent simple DoS attacks, you _must_ not rely on this or lower the limit artificially, but rather increase it (probably, after increasing installed memory), if network conditions require more than default value, and tune network services to linger and kill such states more aggressively. 让我再次提醒你:每个孤儿套接字最多能够吃掉你64K不可交换的内存。
/proc/sys/net/ipv4/tcp_orphan_retries
本端试图关闭TCP连接之前重试多少次。缺省值是7,相当于50秒~16分钟(取决于RTO)。如果你的机器是一个重载的WEB服务器,你应该考虑减低这个值,因为这样的套接字会消耗很多重要的资源。参见tcp_max_orphans。
/proc/sys/net/ipv4/tcp_max_syn_backlog
记 录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M内存的系统而言,缺省值是1024,小内存的系统则是128。如果服务器不堪重负,试 试提高这个值。注意!如果你设置这个值大于1024,最好同时调整include/net/tcp.h中的TCP_SYNQ_HSIZE,以保证 TCP_SYNQ_HSIZE*16 ≤tcp_max_syn_backlo,然后重新编译内核。
/proc/sys/net/ipv4/tcp_max_tw_buckets
系 统同时保持timewait套接字的最大数量。如果超过这个数字,time-wait套接字将立刻被清除并打印警告信息。这个限制仅仅是为了防止简单的 DoS攻击,你绝对不能过分依靠它或者人为地减小这个值,如果网络实际需要大于缺省值,更应该增加这个值(如果增加了内存之后)。
/proc/sys/net/ipv4/tcp_retrans_collapse
为兼容某些糟糕的打印机设置的“将错就错”选项。再次发送时,把数据包增大一些,来避免某些TCP协议栈的BUG。
/proc/sys/net/ipv4/tcp_retries1
在认定出错并向网络层提交错误报告之前,重试多少次。缺省设置为RFC规定的最小值:3,相当于3秒~8分钟(取决于RIO)。
/proc/sys/net/ipv4/tcp_retries2
在杀死一个活动的TCP连接之前重试多少次。RFC 1122规定这个限制应该长于100秒。这个值太小了。缺省值是15,相当于13~30分钟(取决于RIO)。
/proc/sys/net/ipv4/tcp_rfc1337
这个开关可以启动对于在RFC1337中描述的“tcp的time-wait暗杀危机”问题的修复。启用后,内核将丢弃那些发往time-wait状态TCP套接字的RST包。却省为0。
/proc/sys/net/ipv4/tcp_sack
特别针对丢失的数据包使用选择性ACK,这样有助于快速恢复。
/proc/sys/net/ipv4/tcp_stdurg
使用TCP紧急指针的主机需求解释。因为绝大多数主机采用BSD解释,所以如果你在Linux上打开它,可能会影响它与其它机器的正常通讯。缺省是FALSE。
/proc/sys/net/ipv4/tcp_syn_retries
在内核放弃建立连接之前发送SYN包的数量。
/proc/sys/net/ipv4/tcp_synack_retries
为了打开对端的连接,内核需要发送一个SYN并附带一个回应前面一个SYN的ACK。也就是所谓三次握手中的第二次握手。这个设置决定了内核放弃连接之前发送SYN+ACK包的数量。
/proc/sys/net/ipv4/tcp_timestamps
时间戳可以避免序列号的卷绕。一个1Gbps的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。
/proc/sys/net/ipv4/tcp_tw_recycle
能够更快地回收TIME-WAIT套接字。缺省值是1。除非有技术专家的建议和要求,否则不应修改。
/proc/sys/net/ipv4/tcp_window_scaling
一般来说TCP/IP允许窗口尺寸达到65535字节。对于速度确实很高的网络而言这个值可能还是太小。这个选项允许设置上G字节的窗口大小,有利于在带宽*延迟很大的环境中使用。
一旦内核认为它无法发包,就会丢弃这个包,并向发包的主机发送ICMP通知。
/proc/sys/net/ipv4/icmp_echo_ignore_all
根本不要响应echo包。请不要设置为缺省,它可能在你正被利用成为DoS攻击的跳板时可能有用。
/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts [Useful]
如果你ping子网的子网地址,所有的机器都应该予以回应。这可能成为非常好用的拒绝服务攻击工具。设置为1来忽略这些子网广播消息。
/proc/sys/net/ipv4/icmp_echoreply_rate
设置了向任意主机回应echo请求的比率。
/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
设置它之后,可以忽略由网络中的那些声称回应地址是广播地址的主机生成的ICMP错误。
/proc/sys/net/ipv4/icmp_paramprob_rate
一个相对不很明确的ICMP消息,用来回应IP头或TCP头损坏的异常数据包。你可以通过这个文件控制消息的发送比率。
*/
//这些值对应的proc文件名,见ipv4_table,应用层设置下面这些值是在ipv4_table中的data生效
extern struct inet_timewait_death_row tcp_death_row;
/* sysctl variables for tcp */
//见tcp_syn_options
//tcp_timestamps参数用来设置是否启用时间戳选项,tcp_tw_recycle参数用来启用快速回收TIME_WAIT套接字。tcp_timestamps参数会影响到tcp_tw_recycle参数的效果。如果没有时间戳选项的话,tcp_tw_recycle参数无效
extern int sysctl_tcp_timestamps;// tcp_timestamps参数用来设置是否启用时间戳选项,如果启用了,则发送报文的时候TCP首部长度会多出这部分长度
extern int sysctl_tcp_window_scaling;
extern int sysctl_tcp_sack;
//对于本端断开的socket连接,TCP保持在FIN_WAIT_2状态的时间。对方可能会断开连接或一直不结束连接或不可预料的进程死亡,可以通过这个超市时间让wait2退出到CLOSE状态
extern int sysctl_tcp_fin_timeout;
//tcpkeepalivetime的单位是秒,表示TCP链接在多少秒之后没有数据报文传输启动探测报文;
//tcpkeepaliveintvl单位是也秒,表示前一个探测报文和后一个探测报文之间的时间间隔,
//tcpkeepaliveprobes表示探测的次数。
extern int sysctl_tcp_keepalive_time;
extern int sysctl_tcp_keepalive_probes;
extern int sysctl_tcp_keepalive_intvl;
extern int sysctl_tcp_syn_retries;
/*
* 这个设置的值,只是重传次数的默认值。如果
* 半连接队列中半连接数超过半连接队列长度的一半,
* 会递减重传次数。
* 这个参数还有一个作用,就是
* 控制最大的重传次数,就是即使启用了TCP_DEFER_ACCEPT
* 选项,总的重传次数也不能超过这个变量的值。
* 参见inet_csk_reqsk_queue_prune()。
*/
extern int sysctl_tcp_synack_retries;
extern int sysctl_tcp_retries1; //它表示的是最大的重试次数,当超过了这个值,我们就需要检测路由表了。
/*
* 获取确定断开连接前持续定时器周期性发送
* TCP段的数目上限,用于持续定时器发出段数
* 量的检测。
*/ //这个值也是表示重试最大次数,只不过这个值一般要比上面的值大。和上面那个不同的是,当重试次数超过这个值,我们就必须放弃重试了。
extern int sysctl_tcp_retries2;
//主要是针对孤立的socket(也就是已经从进程上下文中删除了,可是还有一些清理工作没有完成).对于这种socket,我们重试的最大的次数就是它。
extern int sysctl_tcp_orphan_retries;
extern int sysctl_tcp_syncookies;
extern int sysctl_tcp_retrans_collapse;
extern int sysctl_tcp_stdurg;
extern int sysctl_tcp_rfc1337;
extern int sysctl_tcp_abort_on_overflow;
extern int sysctl_tcp_max_orphans;//在tcp_close的时候,在关闭过程中会增加,表示还未四次挥手超过的套接字数。见tcp_too_many_orphans如果这次关闭close的时候,已经达到这个阀值,则不走正常挥手流程,而是直接发送rst
extern int sysctl_tcp_fack;
extern int sysctl_tcp_reordering;
extern int sysctl_tcp_ecn;
extern int sysctl_tcp_dsack;
//当tcp_memory_allocated大于sysctl_tcp_mem[1]时,TCP缓存管理进入警告状态,tcp_memory_pressure置为1。 这几个变量存到proto中的对应变量中。如果进入警告状态,则在接收数据的时候会tcp_should_expand_sndbuf
//当tcp_memory_allocated小于sysctl_tcp_mem[0]时,TCP缓存管理退出警告状态,tcp_memory_pressure置为0。
extern int sysctl_tcp_mem[3];///proc/sys/net/ipv4/tcp_mem中查看 tcp_init更加内存情况赋值初始化
extern int sysctl_tcp_wmem[3];
/*
* 3个整数,默认值为: 4096,87380,174760,分别对应于min,
* default,max。
* min:接收队列中报文数据总长度(sock结构的sk_rmem_alloc)的上限
* default: 接收缓冲区长度上限的初始值,用来初始化sock结构
* 的成员sk_rcvbuf
* max: 接收缓冲区长度上限的最大值,用来调整sock
* 结构的成员sk_rcvbuf
*/
extern int sysctl_tcp_rmem[3];
extern int sysctl_tcp_app_win;
extern int sysctl_tcp_adv_win_scale;
// 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;注意和这个的区别SO_REUSEADDR
extern int sysctl_tcp_tw_reuse;
extern int sysctl_tcp_frto;
extern int sysctl_tcp_frto_response;
extern int sysctl_tcp_low_latency;
extern int sysctl_tcp_dma_copybreak;
extern int sysctl_tcp_nometrics_save;
/*那么,设置好最大缓存限制后就高枕无忧了吗?对于一个TCP连接来说,可能已经充分利用网络资源,使用大窗口、大缓存来保持高速传输了。比如在长肥网络中,缓存上限可能会被设置为几十兆字节,但系统的总内存却是有限的,当每一个连接都全速飞奔使用到最大窗口时,1万个连接就会占用内存到几百G了,这就限制了高并发场景的使用,公平性也得不到保证。我们希望的场景是,在并发连接比较少时,把缓存限制放大一些,让每一个TCP连接开足马力工作;当并发连接很多时,此时系统内存资源不足,那么就把缓存限制缩小一些,使每一个TCP连接的缓存尽量的小一些,以容纳更多的连接。
linux为了实现这种场景,引入了自动调整内存分配的功能,由tcp_moderate_rcvbuf配置决定,如下:
net.ipv4.tcp_moderate_rcvbuf = 1
默认tcp_moderate_rcvbuf配置为1,表示打开了TCP内存自动调整功能。若配置为0,这个功能将不会生效(慎用)。
另外请注意:当我们在编程中对连接设置了SO_SNDBUF、SO_RCVBUF,将会使linux内核不再对这样的连接执行自动调整功能!*/
extern int sysctl_tcp_moderate_rcvbuf;
extern int sysctl_tcp_tso_win_divisor;
extern int sysctl_tcp_abc;
extern int sysctl_tcp_mtu_probing;
extern int sysctl_tcp_base_mss; //见tcp_mtup_init
extern int sysctl_tcp_workaround_signed_windows;
extern int sysctl_tcp_slow_start_after_idle;
extern int sysctl_tcp_max_ssthresh;
extern int sysctl_tcp_cookie_size;
extern int sysctl_tcp_thin_linear_timeouts;
extern int sysctl_tcp_thin_dupack;
extern atomic_t tcp_memory_allocated;
extern struct percpu_counter tcp_sockets_allocated;
//当tcp_memory_allocated大于sysctl_tcp_mem[1]时,TCP缓存管理进入警告状态,tcp_memory_pressure置为1。 这几个变量存到proto中的对应变量中。如果进入警告状态,则在接收数据的时候会tcp_should_expand_sndbuf
//当tcp_memory_allocated小于sysctl_tcp_mem[0]时,TCP缓存管理退出警告状态,tcp_memory_pressure置为0。
extern int tcp_memory_pressure;
/*
* 无论是为发送而分配SKB,还是将报文接收到TCP传输层,都需要对新进入传输控制块的缓存进行确认。确认时如果套接字缓存中的数据长度大于
* 预分配量,则需进行全面的确认,这个过程由__sk_mem_schedule()实现。
* @size:要确认的缓存长度
* @kind:类型,0为发送缓存,1为接收缓存。
*/
/*
* The next routines deal with comparing 32 bit unsigned ints
* and worry about wraparound (automatic with unsigned arithmetic).
*/
static inline int before(__u32 seq1, __u32 seq2)
{
return (__s32)(seq1-seq2) < 0;
}
#define after(seq2, seq1) before(seq1, seq2)
/* is s2<=s1<=s3 ? */
static inline int between(__u32 seq1, __u32 seq2, __u32 seq3)
{
return seq3 - seq2 >= seq1 - seq2;
}
/*
* 在以下情况下返回1:
* a. 待销毁的sock结构的数目超过sysctl_tcp_max_orphans的值
* 即系统最大限制
* b. sock的发送队列中数据的总长度大于SOCK_MIN_SNDBUF
* 并且当前TCP层为缓冲区分配的内存大于TCP层进入pressure状态的
* 内存限制
*/
static inline bool tcp_too_many_orphans(struct sock *sk, int shift)
{
struct percpu_counter *ocp = sk->sk_prot->orphan_count;
int orphans = percpu_counter_read_positive(ocp);
if (orphans << shift > sysctl_tcp_max_orphans) {
orphans = percpu_counter_sum_positive(ocp);
if (orphans << shift > sysctl_tcp_max_orphans)
return true;
}
if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])
return true;
return false;
}
/* syncookies: remember time of last synqueue overflow */
static inline void tcp_synq_overflow(struct sock *sk)
{
tcp_sk(sk)->rx_opt.ts_recent_stamp = jiffies;
}
/* syncookies: no recent synqueue overflow on this listening socket? */
static inline int tcp_synq_no_recent_overflow(const struct sock *sk)
{
unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp;
return time_after(jiffies, last_overflow + TCP_TIMEOUT_INIT);
}
extern struct proto tcp_prot;
#define TCP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.tcp_statistics, field)
#define TCP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.tcp_statistics, field)
#define TCP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->mib.tcp_statistics, field)
#define TCP_ADD_STATS_USER(net, field, val) SNMP_ADD_STATS_USER((net)->mib.tcp_statistics, field, val)
#define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val)
extern void tcp_v4_err(struct sk_buff *skb, u32);
extern void tcp_shutdown (struct sock *sk, int how);
extern int tcp_v4_rcv(struct sk_buff *skb);
extern int tcp_v4_remember_stamp(struct sock *sk);
extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
extern int tcp_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size);
extern ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags);
extern int tcp_ioctl(struct sock *sk,
int cmd,
unsigned long arg);
extern int tcp_rcv_state_process(struct sock *sk,
struct sk_buff *skb,
struct tcphdr *th,
unsigned len);
extern int tcp_rcv_established(struct sock *sk,
struct sk_buff *skb,
struct tcphdr *th,
unsigned len);
extern void tcp_rcv_space_adjust(struct sock *sk);
extern void tcp_cleanup_rbuf(struct sock *sk, int copied);
extern int tcp_twsk_unique(struct sock *sk,
struct sock *sktw, void *twp);
extern void tcp_twsk_destructor(struct sock *sk);
extern ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len, unsigned int flags);
static inline void tcp_dec_quickack_mode(struct sock *sk,
const unsigned int pkts)
{
struct inet_connection_sock *icsk = inet_csk(sk);
if (icsk->icsk_ack.quick) {
if (pkts >= icsk->icsk_ack.quick) {
icsk->icsk_ack.quick = 0;
/* Leaving quickack mode we deflate ATO. */
icsk->icsk_ack.ato = TCP_ATO_MIN;
} else
icsk->icsk_ack.quick -= pkts;
}
}
extern void tcp_enter_quickack_mode(struct sock *sk);
#define TCP_ECN_OK 1
#define TCP_ECN_QUEUE_CWR 2
#define TCP_ECN_DEMAND_CWR 4
static __inline__ void
TCP_ECN_create_request(struct request_sock *req, struct tcphdr *th)
{
if (sysctl_tcp_ecn && th->ece && th->cwr)
inet_rsk(req)->ecn_ok = 1;
}
enum tcp_tw_status {
TCP_TW_SUCCESS = 0,
TCP_TW_RST = 1,
TCP_TW_ACK = 2,
TCP_TW_SYN = 3
};
extern enum tcp_tw_status tcp_timewait_state_process(struct inet_timewait_sock *tw,
struct sk_buff *skb,
const struct tcphdr *th);
extern struct sock * tcp_check_req(struct sock *sk,struct sk_buff *skb,
struct request_sock *req,
struct request_sock **prev);
extern int tcp_child_process(struct sock *parent,
struct sock *child,
struct sk_buff *skb);
extern int tcp_use_frto(struct sock *sk);
extern void tcp_enter_frto(struct sock *sk);
extern void tcp_enter_loss(struct sock *sk, int how);
extern void tcp_clear_retrans(struct tcp_sock *tp);
extern void tcp_update_metrics(struct sock *sk);
extern void tcp_close(struct sock *sk,
long timeout);
extern unsigned int tcp_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
extern int tcp_getsockopt(struct sock *sk, int level,
int optname,
char __user *optval,
int __user *optlen);
extern int tcp_setsockopt(struct sock *sk, int level,
int optname, char __user *optval,
unsigned int optlen);
extern int compat_tcp_getsockopt(struct sock *sk,
int level, int optname,
char __user *optval, int __user *optlen);
extern int compat_tcp_setsockopt(struct sock *sk,
int level, int optname,
char __user *optval, unsigned int optlen);
extern void tcp_set_keepalive(struct sock *sk, int val);
extern void tcp_syn_ack_timeout(struct sock *sk,
struct request_sock *req);
extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk,
struct msghdr *msg,
size_t len, int nonblock,
int flags, int *addr_len);
extern void tcp_parse_options(struct sk_buff *skb,
struct tcp_options_received *opt_rx,
u8 **hvpp,
int estab);
extern u8 *tcp_parse_md5sig_option(struct tcphdr *th);
/*
* TCP v4 functions exported for the inet6 API
*/
extern void tcp_v4_send_check(struct sock *sk,
struct sk_buff *skb);
extern int tcp_v4_conn_request(struct sock *sk,
struct sk_buff *skb);
extern struct sock * tcp_create_openreq_child(struct sock *sk,
struct request_sock *req,
struct sk_buff *skb);
extern struct sock * tcp_v4_syn_recv_sock(struct sock *sk,
struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst);
extern int tcp_v4_do_rcv(struct sock *sk,
struct sk_buff *skb);
extern int tcp_v4_connect(struct sock *sk,
struct sockaddr *uaddr,
int addr_len);
extern int tcp_connect(struct sock *sk);
extern struct sk_buff * tcp_make_synack(struct sock *sk,
struct dst_entry *dst,
struct request_sock *req,
struct request_values *rvp);
extern int tcp_disconnect(struct sock *sk, int flags);
/* From syncookies.c */
extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];
extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
struct ip_options *opt);
extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
__u16 *mss);
extern __u32 cookie_init_timestamp(struct request_sock *req);
extern void cookie_check_timestamp(struct tcp_options_received *tcp_opt);
/* From net/ipv6/syncookies.c */
extern struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb);
extern __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb,
__u16 *mss);
/* tcp_output.c */
extern void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
int nonagle);
extern int tcp_may_send_now(struct sock *sk);
extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
extern void tcp_retransmit_timer(struct sock *sk);
extern void tcp_xmit_retransmit_queue(struct sock *);
extern void tcp_simple_retransmit(struct sock *);
extern int tcp_trim_head(struct sock *, struct sk_buff *, u32);
extern int tcp_fragment(struct sock *, struct sk_buff *, u32, unsigned int);
extern void tcp_send_probe0(struct sock *);
extern void tcp_send_partial(struct sock *);
extern int tcp_write_wakeup(struct sock *);
extern void tcp_send_fin(struct sock *sk);
extern void tcp_send_active_reset(struct sock *sk, gfp_t priority);
extern int tcp_send_synack(struct sock *);
extern void tcp_push_one(struct sock *, unsigned int mss_now);
extern void tcp_send_ack(struct sock *sk);
extern void tcp_send_delayed_ack(struct sock *sk);
/* tcp_input.c */
extern void tcp_cwnd_application_limited(struct sock *sk);
/* tcp_timer.c */
extern void tcp_init_xmit_timers(struct sock *);
static inline void tcp_clear_xmit_timers(struct sock *sk)
{
inet_csk_clear_xmit_timers(sk);
}
extern unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu);
extern unsigned int tcp_current_mss(struct sock *sk);
/* Bound MSS / TSO packet size with the half of the window */
static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize)
{
int cutoff;
/* When peer uses tiny windows, there is no use in packetizing
* to sub-MSS pieces for the sake of SWS or making sure there
* are enough packets in the pipe for fast recovery.
*
* On the other hand, for extremely large MSS devices, handling
* smaller than MSS windows in this way does make sense.
*/
if (tp->max_window >= 512)
cutoff = (tp->max_window >> 1);
else
cutoff = tp->max_window;
if (cutoff && pktsize > cutoff)
return max_t(int, cutoff, 68U - tp->tcp_header_len);
else
return pktsize;
}
/* tcp.c */
extern void tcp_get_info(struct sock *, struct tcp_info *);
/* Read 'sendfile()'-style from a TCP socket */
typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *,
unsigned int, size_t);
extern int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
sk_read_actor_t recv_actor);
extern void tcp_initialize_rcv_mss(struct sock *sk);
extern int tcp_mtu_to_mss(struct sock *sk, int pmtu);
extern int tcp_mss_to_mtu(struct sock *sk, int mss);
extern void tcp_mtup_init(struct sock *sk);
static inline void tcp_bound_rto(const struct sock *sk)
{
if (inet_csk(sk)->icsk_rto > TCP_RTO_MAX)
inet_csk(sk)->icsk_rto = TCP_RTO_MAX;
}
static inline u32 __tcp_set_rto(const struct tcp_sock *tp)
{
return (tp->srtt >> 3) + tp->rttvar;
}
static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
{
tp->pred_flags = htonl((tp->tcp_header_len << 26) |
ntohl(TCP_FLAG_ACK) |
snd_wnd);
}
/*
* tcp_fast_path_on()是对__tcp_fast_path_on()的封装,提供发送
* 窗口大小,由snd_wnd和窗口扩大因子计算得到
*/
static inline void tcp_fast_path_on(struct tcp_sock *tp)
{
__tcp_fast_path_on(tp, tp->snd_wnd >> tp->rx_opt.snd_wscale);
}
/*
* 用于设置预测标志,当然必须满足设置
* 预测标志的条件
*/
static inline void tcp_fast_path_check(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
/*
* 设置预测标志的条件是:
* 1)缓存乱序队列为空,说明网络比较畅通。
* 2)接收窗口不为0,说明当前还能接收数据。
* 3)当前已使用的接收缓存未达到上限,也说明目前还能接收数据
* 4)没有收到紧急指针,快速路径不处理带外数据。
*/
if (skb_queue_empty(&tp->out_of_order_queue) &&
tp->rcv_wnd &&
atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf &&
!tp->urg_data)
tcp_fast_path_on(tp);
}
/* Compute the actual rto_min value */
static inline u32 tcp_rto_min(struct sock *sk)
{
struct dst_entry *dst = __sk_dst_get(sk);
u32 rto_min = TCP_RTO_MIN;
if (dst && dst_metric_locked(dst, RTAX_RTO_MIN))
rto_min = dst_metric_rtt(dst, RTAX_RTO_MIN);
return rto_min;
}
/* Compute the actual receive window we are currently advertising.
* Rcv_nxt can be after the window if our peer push more data
* than the offered window.
*/
static inline u32 tcp_receive_window(const struct tcp_sock *tp)
{
s32 win = tp->rcv_wup + tp->rcv_wnd - tp->rcv_nxt;
if (win < 0)
win = 0;
return (u32) win;
}
/* Choose a new window, without checks for shrinking, and without
* scaling applied to the result. The caller does these things
* if necessary. This is a "raw" window selection.
*/
extern u32 __tcp_select_window(struct sock *sk);
/* TCP timestamps are only 32-bits, this causes a slight
* complication on 64-bit systems since we store a snapshot
* of jiffies in the buffer control blocks below. We decided
* to use only the low 32-bits of jiffies and hide the ugly
* casts with the following macro.
*/
#define tcp_time_stamp ((__u32)(jiffies))
/* This is what the send packet queuing engine uses to pass
* TCP per-packet control information to the transmission
* code. We also store the host-order sequence numbers in
* here too. This is 36 bytes on 32-bit architectures,
* 40 bytes on 64-bit machines, if this grows please adjust
* skbuff.h:skbuff->cb[xxx] size appropriately.
*/
struct tcp_skb_cb {
union {
struct inet_skb_parm h4;
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
struct inet6_skb_parm h6;
#endif
} header; /* For incoming frames */
__u32 seq; /* Starting sequence number */
__u32 end_seq; /* SEQ + FIN + SYN + datalen */
__u32 when; /* used to compute rtt's */
__u8 flags; /* TCP header flags. */
/* NOTE: These must match up to the flags byte in a
* real TCP header.
*/
#define TCPCB_FLAG_FIN 0x01
#define TCPCB_FLAG_SYN 0x02
#define TCPCB_FLAG_RST 0x04
#define TCPCB_FLAG_PSH 0x08
#define TCPCB_FLAG_ACK 0x10
#define TCPCB_FLAG_URG 0x20
#define TCPCB_FLAG_ECE 0x40
#define TCPCB_FLAG_CWR 0x80
__u8 sacked; /* State flags for SACK/FACK. */
#define TCPCB_SACKED_ACKED 0x01 /* SKB ACK'd by a SACK block */
#define TCPCB_SACKED_RETRANS 0x02 /* SKB retransmitted */
#define TCPCB_LOST 0x04 /* SKB is lost */
#define TCPCB_TAGBITS 0x07 /* All tag bits */
#define TCPCB_EVER_RETRANS 0x80 /* Ever retransmitted frame */
#define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS)
__u32 ack_seq; /* Sequence number ACK'd */
};
/*
* TCP层在SKB区中的私有信息控制块,即skb_buff结构的cb成员,TCP利用
*
这个字段存储了一个tcp_skb_cb结构。在TCP层,用宏TCP_SKB_CB实现访
* 问该信息控制块,已增强代码的可读性。对这个私有信息控制块的赋值
* 一般在本层接收到段或发送段之前进行。例如:tcp_v4_rcv是TCP层接收入口函数,当收到TCP段并对其进行必要的校验后,就会对此段的tcp_skb_cb进行设置。而发送过程中,
大部分是在生成TCP段时,或是在对TCP段进行分段时设置,例如创建TCP分段函数tcp_fragment,在MAC层发送前进行tso分段的函数tso_fragment,进行路径MTU探测的函数tcp_mtu_probe,
发送FIN段的函数tcp_send_fin,这些函数都会创建一个TCP段。在发送TCP段前会根据tcp_skb_cb的值进行处理或从中取值,如发送TCP段的函数tcp_transmit_skb,从传TCP段的
函数tcp_retransmit_skb.
*/ //TCP接收过程中的TCP选项字段从接收的SKB中解析出来,见tcp_parse_options,最终TCP选项字段存放在inet_request_sock中,IP选项字段存储在skb->cb中
struct tcp_skb_cb { //这下面是TCP和IP首部选项字段,如果未0,表示没有携带对应的选项字段
// //在发送数据tcp_sendmsg中的skb_entail函数中赋值
/*
* 在TCP处理接收到的TCP段之前,下层协议(IPv4或IPv6)会先处理该段,且会
* 利用SKB中的控制块来记录每一个包中的信息,例如IPv4会记录从IP首部中
* 解析出的IP首部选项。为了不破坏三层协议私有数据,在SKB中TCP控制块
* 的前部定义了这个结构,这包括IPv4和IPv6。
*/
union {
struct inet_skb_parm h4;
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
struct inet6_skb_parm h6;
#endif
} header; /* For incoming frames 这是IP选项,后面的这些是TCP选项 */
/*
* seq为当前段开始序号,而end_seq为当前段开始序号加上当前段
* 数据长度,如果标志域中存在SYN或FIN标志,则还需要加1,因为
* SYN和FIN标志都会消耗一个序号。利用end_seq、seq和标志,很
* 容易得到数据长度
*/ //这几个序号是从TCP首部中提取出来的,见tcp_v4_rcv
//这里的seq end_seq应该是应用层接收来的数据直接存到SKB中,这时的数据长度应该没有分段的,可能大于1500
__u32 seq; /* Starting sequence number */
__u32 end_seq; /* SEQ + FIN + SYN + datalen */
/*
* 段发送时间及段发送时记录的当前jiffies值。必要时,此值也
* 用来计算RTT。
* 该值通常在向外发送SKB时使用tcp_time_stamp设置,例如tcp_write_xmit()。
*/
__u32 when; /* used to compute rtt's */
/*
* 记录原始TCP首部标志。发送过程中,tcp_transmit_skb()在发送TCP
* 段之前会根据此标志来填充发送段的TCP首部的标志域;接收过程中,
* 会提取接收段的TCP首部标志到该字段中 值为TCPCB_FLAG_SYN FEN PUSH等
*/ //在tcp_sendmsg中的TCP_SKB_CB会设置该标志, 见tcp_transmit_skb
__u8 flags; /* TCP header flags. */
/* NOTE: These must match up to the flags byte in a
* real TCP header.
*/
#define TCPCB_FLAG_FIN 0x01
#define TCPCB_FLAG_SYN 0x02
#define TCPCB_FLAG_RST 0x04
#define TCPCB_FLAG_PSH 0x08
#define TCPCB_FLAG_ACK 0x10
#define TCPCB_FLAG_URG 0x20
#define TCPCB_FLAG_ECE 0x40
#define TCPCB_FLAG_CWR 0x80
/*
* 主要用来描述段的重传状态,同时标识包是否包含紧急数据,可能的取值
* 为TCPCB_SACKED_ACKED等。检查接收到的SACK,根据需要更新TCPCB_TAGBITS
* 标志位,重传引擎会根据该标志位来确定是否需要重传。一旦重传超时发生,
* 所有的SACK状态标志将被清除,因为无需再关心其状态。无论通过哪种方式
* 重传了包,重传超时或快速重传,都会设置TCPCB_EVER_RETRANS标志位。
* tcp_retransmit_skb()中设置TCPCB_SACKED_RETRANS和TCPCB_EVER_RETRANS
* 标志位,tcp_enter_loss()中则清除TCPCB_SACKED_RETRANS标志位。
* 值得注意的是,在描述包的重传状态之前的sacked值并非段的重传标志,而是
* SACK选项在TCP首部中的偏移,此值在接收TCP段之后的tcp_parse_options()中
* 解析TCP选项时被赋值。而后在tcp_sacktag_write_queue()中才真正根据SACK
* 选项标记段的重传状态等
*/
__u8 sacked; /* State flags for SACK/FACK. */
/*
* 该段通过SACK被确认
*/
#define TCPCB_SACKED_ACKED 0x01 /* SKB ACK'd by a SACK block */
/*
* 该段已经重传
*/
#define TCPCB_SACKED_RETRANS 0x02 /* SKB retransmitted */
/*
* 该段在传输过程中已丢失
*/
#define TCPCB_LOST 0x04 /* SKB is lost */
#define TCPCB_TAGBITS 0x07 /* All tag bits */
#define TCPCB_EVER_RETRANS 0x80 /* Ever retransmitted frame */
#define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS)
/*
* 接收到的TCP段首部中的确认序号
*/
__u32 ack_seq; /* Sequence number ACK'd */
};
#define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0]))
/* Due to TSO, an SKB can be composed of multiple actual
* packets. To keep these tracked properly, we use this.
*/
static inline int tcp_skb_pcount(const struct sk_buff *skb)
{
return skb_shinfo(skb)->gso_segs;
}
/* This is valid iff tcp_skb_pcount() > 1. */
static inline int tcp_skb_mss(const struct sk_buff *skb)
{
return skb_shinfo(skb)->gso_size;
}
/* Events passed to congestion control interface */
enum tcp_ca_event {
CA_EVENT_TX_START, /* first transmit when no packets in flight */
CA_EVENT_CWND_RESTART, /* congestion window restart */
CA_EVENT_COMPLETE_CWR, /* end of congestion recovery */
CA_EVENT_FRTO, /* fast recovery timeout */
CA_EVENT_LOSS, /* loss timeout */
CA_EVENT_FAST_ACK, /* in sequence ack */
CA_EVENT_SLOW_ACK, /* other ack */
};
/*
* Interface for adding new TCP congestion control handlers
*/
#define TCP_CA_NAME_MAX 16
#define TCP_CA_MAX 128
#define TCP_CA_BUF_MAX (TCP_CA_NAME_MAX*TCP_CA_MAX)
#define TCP_CONG_NON_RESTRICTED 0x1
#define TCP_CONG_RTT_STAMP 0x2
/*
* tcp_congestion_ops结构提供了支持多种拥塞控制算法的机制。
* 拥塞控制算法只要为tcp_congestion_ops结构实现一个实例,
* 并且实现其中的一些接口。比如,必须实现接口
* ssthresh()和cong_avoid(),其他接口可选。
*/
struct tcp_congestion_ops {
/*
* 连接注册到系统中不同的各种拥塞算法。
*/
struct list_head list;
unsigned long flags; //取值TCP_CONG_RTT_STAMP等
/* initialize private data (optional) */
/*
* 拥塞算法的初始化函数,进行特定的
* 初始化过程,当传输控制块的某种
* 拥塞控制算法被选中时被调用。
*/
void (*init)(struct sock *sk);
/* cleanup private data (optional) */