@@ -400,19 +400,19 @@ func (l *Local) Allocate(ctx context.Context, cni *daemon.CNI, request ResourceR
400
400
}
401
401
402
402
log := logr .FromContextOrDiscard (ctx )
403
- log .Info (fmt .Sprintf ("local request %v" , localIPRequest ))
404
403
405
404
expectV4 := 0
406
405
expectV6 := 0
407
406
407
+ var ipv4 , ipv6 * IP
408
408
if l .enableIPv4 {
409
409
if localIPRequest .NoCache {
410
410
if len (l .ipv4 )+ l .allocatingV4 .Len () >= l .cap {
411
411
return nil , []Trace {{Condition : Full }}
412
412
}
413
413
expectV4 = 1
414
414
} else {
415
- ipv4 : = l .ipv4 .PeekAvailable (cni .PodID )
415
+ ipv4 = l .ipv4 .PeekAvailable (cni .PodID )
416
416
if ipv4 == nil && len (l .ipv4 )+ l .allocatingV4 .Len () >= l .cap {
417
417
return nil , []Trace {{Condition : Full }}
418
418
} else if ipv4 == nil {
@@ -428,7 +428,7 @@ func (l *Local) Allocate(ctx context.Context, cni *daemon.CNI, request ResourceR
428
428
}
429
429
expectV6 = 1
430
430
} else {
431
- ipv6 : = l .ipv6 .PeekAvailable (cni .PodID )
431
+ ipv6 = l .ipv6 .PeekAvailable (cni .PodID )
432
432
if ipv6 == nil && len (l .ipv6 )+ l .allocatingV6 .Len () >= l .cap {
433
433
return nil , []Trace {{Condition : Full }}
434
434
} else if ipv6 == nil {
@@ -442,6 +442,30 @@ func (l *Local) Allocate(ctx context.Context, cni *daemon.CNI, request ResourceR
442
442
return nil , []Trace {{Condition : InsufficientVSwitchIP , Reason : fmt .Sprintf ("alloc inhibit, expire at %s" , l .ipAllocInhibitExpireAt .String ())}}
443
443
}
444
444
445
+ ok1 := l .enableIPv4 && ipv4 != nil || ! l .enableIPv4
446
+ ok2 := l .enableIPv6 && ipv6 != nil || ! l .enableIPv6
447
+
448
+ if ok1 && ok2 {
449
+ // direct return
450
+ respCh := make (chan * AllocResp )
451
+ // assign ip to pod , as we are ready
452
+ // this must be protected by lock
453
+ if ipv4 != nil {
454
+ ipv4 .Allocate (cni .PodID )
455
+ }
456
+ if ipv6 != nil {
457
+ ipv6 .Allocate (cni .PodID )
458
+ }
459
+
460
+ go func () {
461
+ l .cond .L .Lock ()
462
+ defer l .cond .L .Unlock ()
463
+
464
+ l .commit (ctx , respCh , ipv4 , ipv6 , cni .PodID )
465
+ }()
466
+ return respCh , nil
467
+ }
468
+
445
469
for i := 0 ; i < expectV4 ; i ++ {
446
470
l .allocatingV4 = append (l .allocatingV4 , localIPRequest )
447
471
}
@@ -455,6 +479,11 @@ func (l *Local) Allocate(ctx context.Context, cni *daemon.CNI, request ResourceR
455
479
456
480
go l .allocWorker (ctx , cni , localIPRequest , respCh )
457
481
482
+ if l .eni == nil {
483
+ log .Info ("local request" , "eni" , "" , "req" , localIPRequest )
484
+ } else {
485
+ log .Info ("local request" , "eni" , l .eni .ID , "req" , localIPRequest )
486
+ }
458
487
return respCh , nil
459
488
}
460
489
@@ -528,6 +557,8 @@ func (l *Local) allocWorker(ctx context.Context, cni *daemon.CNI, request *Local
528
557
l .cond .L .Lock ()
529
558
defer l .cond .L .Unlock ()
530
559
560
+ defer l .cond .Broadcast ()
561
+
531
562
defer func () {
532
563
if request == nil {
533
564
return
@@ -550,6 +581,32 @@ func (l *Local) allocWorker(ctx context.Context, cni *daemon.CNI, request *Local
550
581
}()
551
582
552
583
log := logr .FromContextOrDiscard (ctx )
584
+ if request != nil && request .NoCache {
585
+ // as we want to do preheat, so this ip will not be consumed
586
+ // so just hang there , let this ctx done
587
+
588
+ for {
589
+ select {
590
+ case <- request .workerCtx .Done ():
591
+ // work ctx finished (factory cancel it)
592
+
593
+ select {
594
+ case <- ctx .Done ():
595
+ close (respCh )
596
+ case respCh <- & AllocResp {}:
597
+ }
598
+
599
+ return
600
+ case <- ctx .Done ():
601
+ // parent cancel the context, so close the ch
602
+ close (respCh )
603
+ return
604
+ default :
605
+ }
606
+ l .cond .Wait ()
607
+ }
608
+ }
609
+
553
610
for {
554
611
select {
555
612
case <- ctx .Done ():
@@ -559,52 +616,24 @@ func (l *Local) allocWorker(ctx context.Context, cni *daemon.CNI, request *Local
559
616
default :
560
617
}
561
618
562
- resp := & AllocResp {}
563
-
564
- var ip types.IPSet2
565
619
var ipv4 , ipv6 * IP
566
620
if l .enableIPv4 {
567
621
ipv4 = l .ipv4 .PeekAvailable (cni .PodID )
568
622
if ipv4 == nil {
623
+ log .Info ("waiting ipv4" )
569
624
l .cond .Wait ()
570
625
continue
571
626
}
572
- ip .IPv4 = ipv4 .ip
573
627
}
574
628
if l .enableIPv6 {
575
629
ipv6 = l .ipv6 .PeekAvailable (cni .PodID )
576
630
if ipv6 == nil {
577
631
l .cond .Wait ()
578
632
continue
579
633
}
580
- ip .IPv6 = ipv6 .ip
581
634
}
582
635
583
- resp .NetworkConfigs = append (resp .NetworkConfigs , & LocalIPResource {
584
- ENI : * l .eni ,
585
- IP : ip ,
586
- })
587
-
588
- log .Info ("allocWorker got ip" , "eni" , l .eni .ID , "ipv4" , ip .IPv4 .String (), "ipv6" , ip .IPv6 .String ())
589
-
590
- select {
591
- case <- ctx .Done ():
592
- continue
593
- case respCh <- resp :
594
- // mark the ip as allocated
595
- if ipv4 != nil {
596
- ipv4 .Allocate (cni .PodID )
597
- if cni .PodID != "" {
598
- metric .ResourcePoolIdle .WithLabelValues (metric .ResourcePoolTypeLocal , string (types .IPStackIPv4 )).Dec ()
599
- }
600
- }
601
- if ipv6 != nil {
602
- ipv6 .Allocate (cni .PodID )
603
- if cni .PodID != "" {
604
- metric .ResourcePoolIdle .WithLabelValues (metric .ResourcePoolTypeLocal , string (types .IPStackIPv6 )).Dec ()
605
- }
606
- }
607
- }
636
+ l .commit (ctx , respCh , ipv4 , ipv6 , cni .PodID )
608
637
609
638
return
610
639
}
@@ -1012,6 +1041,47 @@ func (l *Local) Status() Status {
1012
1041
return s
1013
1042
}
1014
1043
1044
+ // commit send the allocated ip result to respCh
1045
+ // if ctx canceled, the respCh will be closed
1046
+ func (l * Local ) commit (ctx context.Context , respCh chan * AllocResp , ipv4 , ipv6 * IP , podID string ) {
1047
+ var ip types.IPSet2
1048
+ if ipv4 != nil {
1049
+ ip .IPv4 = ipv4 .ip
1050
+ ipv4 .Allocate (podID )
1051
+ if podID != "" {
1052
+ metric .ResourcePoolIdle .WithLabelValues (metric .ResourcePoolTypeLocal , string (types .IPStackIPv4 )).Dec ()
1053
+ }
1054
+ }
1055
+ if ipv6 != nil {
1056
+ ip .IPv6 = ipv6 .ip
1057
+ ipv6 .Allocate (podID )
1058
+ if podID != "" {
1059
+ metric .ResourcePoolIdle .WithLabelValues (metric .ResourcePoolTypeLocal , string (types .IPStackIPv6 )).Dec ()
1060
+ }
1061
+ }
1062
+ resp := & AllocResp {}
1063
+ resp .NetworkConfigs = append (resp .NetworkConfigs , & LocalIPResource {
1064
+ ENI : * l .eni ,
1065
+ IP : ip ,
1066
+ })
1067
+ select {
1068
+ case <- ctx .Done ():
1069
+ if ipv4 != nil {
1070
+ ipv4 .Release (podID )
1071
+ }
1072
+ if ipv6 != nil {
1073
+ ipv6 .Release (podID )
1074
+ }
1075
+
1076
+ // parent cancel the context, so close the ch
1077
+ close (respCh )
1078
+
1079
+ return
1080
+ case respCh <- resp :
1081
+ logr .FromContextOrDiscard (ctx ).Info ("allocWorker got ip" , "eni" , l .eni .ID , "ipv4" , ip .IPv4 .String (), "ipv6" , ip .IPv6 .String ())
1082
+ }
1083
+ }
1084
+
1015
1085
// syncIPLocked will mark ip as invalid , if not found in remote
1016
1086
func syncIPLocked (lo Set , remote []netip.Addr ) {
1017
1087
s := sets .New [netip.Addr ](remote ... )
@@ -1128,12 +1198,24 @@ func (l *Local) popNIPv4Jobs(count int) {
1128
1198
firstPart , secondPart := Split (l .allocatingV4 , count )
1129
1199
l .dangingV4 = append (l .dangingV4 , firstPart ... )
1130
1200
l .allocatingV4 = secondPart
1201
+
1202
+ lo .ForEach (l .dangingV4 , func (item * LocalIPRequest , index int ) {
1203
+ if item .NoCache {
1204
+ item .cancel ()
1205
+ }
1206
+ })
1131
1207
}
1132
1208
1133
1209
func (l * Local ) popNIPv6Jobs (count int ) {
1134
1210
firstPart , secondPart := Split (l .allocatingV6 , count )
1135
1211
l .dangingV6 = append (l .dangingV6 , firstPart ... )
1136
1212
l .allocatingV6 = secondPart
1213
+
1214
+ lo .ForEach (l .dangingV6 , func (item * LocalIPRequest , index int ) {
1215
+ if item .NoCache {
1216
+ item .cancel ()
1217
+ }
1218
+ })
1137
1219
}
1138
1220
1139
1221
func Split [T any ](arr []T , index int ) ([]T , []T ) {
0 commit comments