@@ -36,9 +36,10 @@ import (
36
36
// RFC 2131 suggests using exponential backoff, starting with 4sec
37
37
// and randomized to +/- 1sec
38
38
const (
39
- resendDelay0 = 4 * time .Second
40
- resendDelayMax = 62 * time .Second
41
- defaultLeaseTime = 60 * time .Minute
39
+ resendDelay0 = 4 * time .Second
40
+ resendDelayMax = 62 * time .Second
41
+ defaultLeaseTime = 60 * time .Minute
42
+ defaultResendTimeout = 208 * time .Second // fast resend + backoff resend
42
43
)
43
44
44
45
// To speed up the retry for first few failures, we retry without
@@ -69,6 +70,7 @@ type DHCPLease struct {
69
70
expireTime time.Time
70
71
timeout time.Duration
71
72
resendMax time.Duration
73
+ resendTimeout time.Duration
72
74
broadcast bool
73
75
stopping uint32
74
76
stop chan struct {}
@@ -155,23 +157,24 @@ func prepareOptions(cniArgs string, provideOptions []ProvideOption, requestOptio
155
157
func AcquireLease (
156
158
clientID , netns , ifName string ,
157
159
opts []dhcp4.Option ,
158
- timeout , resendMax time.Duration , broadcast bool ,
160
+ timeout , resendMax time.Duration , resendTimeout time. Duration , broadcast bool ,
159
161
) (* DHCPLease , error ) {
160
162
errCh := make (chan error , 1 )
161
163
162
164
ctx := context .Background ()
163
165
ctx , cancel := context .WithCancel (ctx )
164
166
165
167
l := & DHCPLease {
166
- clientID : clientID ,
167
- stop : make (chan struct {}),
168
- check : make (chan struct {}),
169
- timeout : timeout ,
170
- resendMax : resendMax ,
171
- broadcast : broadcast ,
172
- opts : opts ,
173
- cancelFunc : cancel ,
174
- ctx : ctx ,
168
+ clientID : clientID ,
169
+ stop : make (chan struct {}),
170
+ check : make (chan struct {}),
171
+ timeout : timeout ,
172
+ resendMax : resendMax ,
173
+ resendTimeout : resendTimeout ,
174
+ broadcast : broadcast ,
175
+ opts : opts ,
176
+ cancelFunc : cancel ,
177
+ ctx : ctx ,
175
178
}
176
179
177
180
log .Printf ("%v: acquiring lease" , clientID )
@@ -213,6 +216,7 @@ func AcquireLease(
213
216
func (l * DHCPLease ) Stop () {
214
217
if atomic .CompareAndSwapUint32 (& l .stopping , 0 , 1 ) {
215
218
close (l .stop )
219
+ l .cancelFunc ()
216
220
}
217
221
l .wg .Wait ()
218
222
}
@@ -251,9 +255,11 @@ func (l *DHCPLease) acquire() error {
251
255
}
252
256
defer c .Close ()
253
257
254
- pkt , err := backoffRetry (l .resendMax , func () (* nclient4.Lease , error ) {
258
+ timeoutCtx , cancel := context .WithTimeoutCause (l .ctx , l .resendTimeout , errNoMoreTries )
259
+ defer cancel ()
260
+ pkt , err := backoffRetry (timeoutCtx , l .resendMax , func () (* nclient4.Lease , error ) {
255
261
return c .Request (
256
- l . ctx ,
262
+ timeoutCtx ,
257
263
withClientID (l .clientID ),
258
264
withAllOptions (l ),
259
265
)
@@ -351,9 +357,11 @@ func (l *DHCPLease) renew() error {
351
357
}
352
358
defer c .Close ()
353
359
354
- lease , err := backoffRetry (l .resendMax , func () (* nclient4.Lease , error ) {
360
+ timeoutCtx , cancel := context .WithTimeoutCause (l .ctx , l .resendTimeout , errNoMoreTries )
361
+ defer cancel ()
362
+ lease , err := backoffRetry (timeoutCtx , l .resendMax , func () (* nclient4.Lease , error ) {
355
363
return c .Renew (
356
- l . ctx ,
364
+ timeoutCtx ,
357
365
l .latestLease ,
358
366
withClientID (l .clientID ),
359
367
withAllOptions (l ),
@@ -441,7 +449,7 @@ func jitter(span time.Duration) time.Duration {
441
449
return time .Duration (float64 (span ) * (2.0 * rand .Float64 () - 1.0 ))
442
450
}
443
451
444
- func backoffRetry (resendMax time.Duration , f func () (* nclient4.Lease , error )) (* nclient4.Lease , error ) {
452
+ func backoffRetry (ctx context. Context , resendMax time.Duration , f func () (* nclient4.Lease , error )) (* nclient4.Lease , error ) {
445
453
baseDelay := resendDelay0
446
454
var sleepTime time.Duration
447
455
fastRetryLimit := resendFastMax
@@ -462,17 +470,16 @@ func backoffRetry(resendMax time.Duration, f func() (*nclient4.Lease, error)) (*
462
470
463
471
log .Printf ("retrying in %f seconds" , sleepTime .Seconds ())
464
472
465
- time .Sleep (sleepTime )
466
-
467
- // only adjust delay time if we are in normal backoff stage
468
- if baseDelay < resendMax && fastRetryLimit == 0 {
469
- baseDelay *= 2
470
- } else if fastRetryLimit == 0 { // only break if we are at normal delay
471
- break
473
+ select {
474
+ case <- ctx .Done ():
475
+ return nil , context .Cause (ctx )
476
+ case <- time .After (sleepTime ):
477
+ // only adjust delay time if we are in normal backoff stage
478
+ if baseDelay < resendMax && fastRetryLimit == 0 {
479
+ baseDelay *= 2
480
+ }
472
481
}
473
482
}
474
-
475
- return nil , errNoMoreTries
476
483
}
477
484
478
485
func newDHCPClient (
0 commit comments