7
7
package net
8
8
9
9
import (
10
+ "internal/syscall/unix"
10
11
"syscall"
11
12
"testing"
12
13
"time"
13
14
)
14
15
15
- var testConfigs = []KeepAliveConfig {
16
- {
17
- Enable : true ,
18
- Idle : 2 * time .Second ,
19
- Interval : - 1 ,
20
- Count : - 1 ,
21
- },
22
- {
23
- Enable : true ,
24
- Idle : 0 ,
25
- Interval : - 1 ,
26
- Count : - 1 ,
27
- },
28
- {
29
- Enable : true ,
30
- Idle : - 1 ,
31
- Interval : - 1 ,
32
- Count : - 1 ,
33
- },
34
- }
35
-
36
16
func getCurrentKeepAliveSettings (fd fdType ) (cfg KeepAliveConfig , err error ) {
37
17
tcpKeepAlive , err := syscall .GetsockoptInt (fd , syscall .SOL_SOCKET , syscall .SO_KEEPALIVE )
38
18
if err != nil {
39
19
return
40
20
}
41
- tcpKeepAliveIdle , err := syscall .GetsockoptInt (fd , syscall .IPPROTO_TCP , syscall .TCP_KEEPALIVE_THRESHOLD )
42
- if err != nil {
43
- return
21
+
22
+ var (
23
+ tcpKeepAliveIdle int
24
+ tcpKeepAliveInterval int
25
+ tcpKeepAliveIdleTime time.Duration
26
+ tcpKeepAliveIntervalTime time.Duration
27
+ tcpKeepAliveCount int
28
+ )
29
+ if unix .SupportTCPKeepAliveIdleIntvlCNT () {
30
+ tcpKeepAliveIdle , err = syscall .GetsockoptInt (fd , syscall .IPPROTO_TCP , syscall_TCP_KEEPIDLE )
31
+ if err != nil {
32
+ return
33
+ }
34
+ tcpKeepAliveIdleTime = time .Duration (tcpKeepAliveIdle ) * time .Second
35
+
36
+ tcpKeepAliveInterval , err = syscall .GetsockoptInt (fd , syscall .IPPROTO_TCP , syscall_TCP_KEEPINTVL )
37
+ if err != nil {
38
+ return
39
+ }
40
+ tcpKeepAliveIntervalTime = time .Duration (tcpKeepAliveInterval ) * time .Second
41
+
42
+ tcpKeepAliveCount , err = syscall .GetsockoptInt (fd , syscall .IPPROTO_TCP , syscall_TCP_KEEPCNT )
43
+ if err != nil {
44
+ return
45
+ }
46
+ } else {
47
+ tcpKeepAliveIdle , err = syscall .GetsockoptInt (fd , syscall .IPPROTO_TCP , syscall .TCP_KEEPALIVE_THRESHOLD )
48
+ if err != nil {
49
+ return
50
+ }
51
+ tcpKeepAliveIdleTime = time .Duration (tcpKeepAliveIdle ) * time .Millisecond
52
+
53
+ // TCP_KEEPINTVL and TCP_KEEPCNT are not available on Solaris prior to 11.4,
54
+ // so we have to use the value of TCP_KEEPALIVE_ABORT_THRESHOLD for Interval
55
+ // and 1 for Count to keep this test going.
56
+ tcpKeepAliveInterval , err = syscall .GetsockoptInt (fd , syscall .IPPROTO_TCP , syscall .TCP_KEEPALIVE_ABORT_THRESHOLD )
57
+ if err != nil {
58
+ return
59
+ }
60
+ tcpKeepAliveIntervalTime = time .Duration (tcpKeepAliveInterval ) * time .Millisecond
61
+ tcpKeepAliveCount = 1
44
62
}
45
63
cfg = KeepAliveConfig {
46
64
Enable : tcpKeepAlive != 0 ,
47
- Idle : time . Duration ( tcpKeepAliveIdle ) * time . Millisecond ,
48
- Interval : - 1 ,
49
- Count : - 1 ,
65
+ Idle : tcpKeepAliveIdleTime ,
66
+ Interval : tcpKeepAliveIntervalTime ,
67
+ Count : tcpKeepAliveCount ,
50
68
}
51
69
return
52
70
}
53
71
54
72
func verifyKeepAliveSettings (t * testing.T , fd fdType , oldCfg , cfg KeepAliveConfig ) {
73
+ const defaultTcpKeepAliveAbortThreshold = 8 * time .Minute // default value on Solaris
74
+
55
75
if cfg .Idle == 0 {
56
76
cfg .Idle = defaultTCPKeepAliveIdle
57
77
}
@@ -64,11 +84,32 @@ func verifyKeepAliveSettings(t *testing.T, fd fdType, oldCfg, cfg KeepAliveConfi
64
84
if cfg .Idle == - 1 {
65
85
cfg .Idle = oldCfg .Idle
66
86
}
67
- if cfg .Interval == - 1 {
68
- cfg .Interval = oldCfg .Interval
69
- }
70
- if cfg .Count == - 1 {
71
- cfg .Count = oldCfg .Count
87
+
88
+ tcpKeepAliveAbortThreshold := defaultTcpKeepAliveAbortThreshold
89
+ if unix .SupportTCPKeepAliveIdleIntvlCNT () {
90
+ // Check out the comment on KeepAliveConfig to understand the following logic.
91
+ switch {
92
+ case cfg .Interval == - 1 && cfg .Count == - 1 :
93
+ cfg .Interval = oldCfg .Interval
94
+ cfg .Count = oldCfg .Count
95
+ case cfg .Interval == - 1 && cfg .Count > 0 :
96
+ cfg .Interval = defaultTcpKeepAliveAbortThreshold / time .Duration (cfg .Count )
97
+ case cfg .Count == - 1 && cfg .Interval > 0 :
98
+ cfg .Count = int (defaultTcpKeepAliveAbortThreshold / cfg .Interval )
99
+ case cfg .Interval > 0 && cfg .Count > 0 :
100
+ // TCP_KEEPALIVE_ABORT_THRESHOLD will be recalculated only when both TCP_KEEPINTVL
101
+ // and TCP_KEEPCNT are set, otherwise it will remain the default value.
102
+ tcpKeepAliveAbortThreshold = cfg .Interval * time .Duration (cfg .Count )
103
+ }
104
+ } else {
105
+ cfg .Interval = cfg .Interval * time .Duration (cfg .Count )
106
+ // Either Interval or Count is set to a negative value, TCP_KEEPALIVE_ABORT_THRESHOLD
107
+ // will remain the default value, so use the old Interval for the subsequent test.
108
+ if cfg .Interval == - 1 || cfg .Count == - 1 {
109
+ cfg .Interval = oldCfg .Interval
110
+ }
111
+ cfg .Count = 1
112
+ tcpKeepAliveAbortThreshold = cfg .Interval
72
113
}
73
114
74
115
tcpKeepAlive , err := syscall .GetsockoptInt (fd , syscall .SOL_SOCKET , syscall .SO_KEEPALIVE )
@@ -79,11 +120,51 @@ func verifyKeepAliveSettings(t *testing.T, fd fdType, oldCfg, cfg KeepAliveConfi
79
120
t .Fatalf ("SO_KEEPALIVE: got %t; want %t" , tcpKeepAlive != 0 , cfg .Enable )
80
121
}
81
122
82
- tcpKeepAliveIdle , err := syscall .GetsockoptInt (fd , syscall .IPPROTO_TCP , syscall .TCP_KEEPALIVE_THRESHOLD )
123
+ // TCP_KEEPALIVE_THRESHOLD and TCP_KEEPALIVE_ABORT_THRESHOLD are both available on Solaris 11.4
124
+ // and previous versions, so we can verify these two options regardless of the kernel version.
125
+ tcpKeepAliveThreshold , err := syscall .GetsockoptInt (fd , syscall .IPPROTO_TCP , syscall .TCP_KEEPALIVE_THRESHOLD )
126
+ if err != nil {
127
+ t .Fatal (err )
128
+ }
129
+ if time .Duration (tcpKeepAliveThreshold )* time .Millisecond != cfg .Idle {
130
+ t .Fatalf ("TCP_KEEPIDLE: got %dms; want %v" , tcpKeepAliveThreshold , cfg .Idle )
131
+ }
132
+
133
+ tcpKeepAliveAbortInterval , err := syscall .GetsockoptInt (fd , syscall .IPPROTO_TCP , syscall .TCP_KEEPALIVE_ABORT_THRESHOLD )
83
134
if err != nil {
84
135
t .Fatal (err )
85
136
}
86
- if time .Duration (tcpKeepAliveIdle )* time .Millisecond != cfg .Idle {
87
- t .Fatalf ("TCP_KEEPIDLE: got %dms; want %v" , tcpKeepAliveIdle , cfg .Idle )
137
+ if time .Duration (tcpKeepAliveAbortInterval )* time .Millisecond != tcpKeepAliveAbortThreshold {
138
+ t .Fatalf ("TCP_KEEPALIVE_ABORT_THRESHOLD: got %dms; want %v" , tcpKeepAliveAbortInterval , tcpKeepAliveAbortThreshold )
139
+ }
140
+
141
+ if unix .SupportTCPKeepAliveIdleIntvlCNT () {
142
+ tcpKeepAliveIdle , err := syscall .GetsockoptInt (fd , syscall .IPPROTO_TCP , syscall_TCP_KEEPIDLE )
143
+ if err != nil {
144
+ t .Fatal (err )
145
+ }
146
+ if time .Duration (tcpKeepAliveIdle )* time .Second != cfg .Idle {
147
+ t .Fatalf ("TCP_KEEPIDLE: got %ds; want %v" , tcpKeepAliveIdle , cfg .Idle )
148
+ }
149
+
150
+ tcpKeepAliveInterval , err := syscall .GetsockoptInt (fd , syscall .IPPROTO_TCP , syscall_TCP_KEEPINTVL )
151
+ if err != nil {
152
+ t .Fatal (err )
153
+ }
154
+ if time .Duration (tcpKeepAliveInterval )* time .Second != cfg .Interval {
155
+ t .Fatalf ("TCP_KEEPINTVL: got %ds; want %v" , tcpKeepAliveInterval , cfg .Interval )
156
+ }
157
+
158
+ tcpKeepAliveCount , err := syscall .GetsockoptInt (fd , syscall .IPPROTO_TCP , syscall_TCP_KEEPCNT )
159
+ if err != nil {
160
+ t .Fatal (err )
161
+ }
162
+ if tcpKeepAliveCount != cfg .Count {
163
+ t .Fatalf ("TCP_KEEPCNT: got %d; want %d" , tcpKeepAliveCount , cfg .Count )
164
+ }
165
+ } else {
166
+ if cfg .Count != 1 {
167
+ t .Fatalf ("TCP_KEEPCNT: got %d; want 1" , cfg .Count )
168
+ }
88
169
}
89
170
}
0 commit comments