@@ -45,6 +45,10 @@ type controlPlaneCore struct {
45
45
isReload bool
46
46
bpfEjected bool
47
47
48
+ domainBumpMap map [netip.Addr ][]uint32
49
+ domainRoutingMap map [netip.Addr ][]uint32
50
+ bumpMapMu sync.Mutex
51
+
48
52
closed context.Context
49
53
close context.CancelFunc
50
54
ifmgr * component.InterfaceManager
@@ -67,17 +71,19 @@ func newControlPlaneCore(log *logrus.Logger,
67
71
ifmgr := component .NewInterfaceManager (log )
68
72
deferFuncs = append (deferFuncs , ifmgr .Close )
69
73
return & controlPlaneCore {
70
- log : log ,
71
- deferFuncs : deferFuncs ,
72
- bpf : bpf ,
73
- outboundId2Name : outboundId2Name ,
74
- kernelVersion : kernelVersion ,
75
- flip : coreFlip ,
76
- isReload : isReload ,
77
- bpfEjected : false ,
78
- ifmgr : ifmgr ,
79
- closed : closed ,
80
- close : toClose ,
74
+ log : log ,
75
+ deferFuncs : deferFuncs ,
76
+ bpf : bpf ,
77
+ outboundId2Name : outboundId2Name ,
78
+ kernelVersion : kernelVersion ,
79
+ flip : coreFlip ,
80
+ isReload : isReload ,
81
+ bpfEjected : false ,
82
+ ifmgr : ifmgr ,
83
+ domainBumpMap : make (map [netip.Addr ][]uint32 ),
84
+ domainRoutingMap : make (map [netip.Addr ][]uint32 ),
85
+ closed : closed ,
86
+ close : toClose ,
81
87
}
82
88
}
83
89
@@ -603,9 +609,8 @@ func (c *controlPlaneCore) bindDaens() (err error) {
603
609
return
604
610
}
605
611
606
- // BatchUpdateDomainRouting update bpf map domain_routing. Since one IP may have multiple domains, this function should
607
- // be invoked every A/AAAA-record lookup.
608
- func (c * controlPlaneCore ) BatchUpdateDomainRouting (cache * DnsCache ) error {
612
+ // BatchNewDomain update bpf map domain_bump and domain_routing. This function should be invoked every new cache.
613
+ func (c * controlPlaneCore ) BatchNewDomain (cache * DnsCache ) error {
609
614
// Parse ips from DNS resp answers.
610
615
var ips []netip.Addr
611
616
for _ , ans := range cache .Answer {
@@ -631,27 +636,70 @@ func (c *controlPlaneCore) BatchUpdateDomainRouting(cache *DnsCache) error {
631
636
// Update bpf map.
632
637
// Construct keys and vals, and BpfMapBatchUpdate.
633
638
var keys [][4 ]uint32
634
- var vals []bpfDomainRouting
639
+ var vals_bump []bpfDomainRouting
640
+ var vals_routing []bpfDomainRouting
641
+
642
+ c .bumpMapMu .Lock ()
643
+ defer c .bumpMapMu .Unlock ()
644
+
635
645
for _ , ip := range ips {
636
646
ip6 := ip .As16 ()
637
647
keys = append (keys , common .Ipv6ByteSliceToUint32Array (ip6 [:]))
648
+
638
649
r := bpfDomainRouting {}
639
- if len (cache .DomainBitmap ) != len (r .Bitmap ) {
650
+
651
+ if consts .MaxMatchSetLen / 32 != len (r .Bitmap ) || len (cache .DomainBitmap ) != len (r .Bitmap ) {
640
652
return fmt .Errorf ("domain bitmap length not sync with kern program" )
641
653
}
642
- copy (r .Bitmap [:], cache .DomainBitmap )
643
- vals = append (vals , r )
654
+
655
+ newBumpMap , exists := c .domainBumpMap [ip ]
656
+ if ! exists {
657
+ newBumpMap = make ([]uint32 , consts .MaxMatchSetLen )
658
+ }
659
+ for index := 0 ; index < consts .MaxMatchSetLen ; index ++ {
660
+ newBumpMap [index ] += cache .DomainBitmap [index / 32 ] >> (index % 32 ) & 1
661
+ }
662
+ for index , val := range newBumpMap {
663
+ if val > 0 {
664
+ r .Bitmap [index / 32 ] |= 1 << (index % 32 )
665
+ }
666
+ }
667
+ c .domainBumpMap [ip ] = newBumpMap
668
+ vals_bump = append (vals_bump , r )
669
+
670
+ if ! exists {
671
+ // New IP, init routingMap
672
+ c .domainRoutingMap [ip ] = cache .DomainBitmap
673
+ } else {
674
+ // Old IP, Update routingMap
675
+ for index := 0 ; index < consts .MaxMatchSetLen ; index ++ {
676
+ if (cache .DomainBitmap [index / 32 ]>> (index % 32 )& 1 ) == 1 && (c .domainRoutingMap [ip ][index / 32 ]>> (index % 32 )& 1 ) == 1 {
677
+ // If this domain matches the current rule, all previous domains also match the current rule, then it still matches
678
+ c .domainRoutingMap [ip ][index / 32 ] |= 1 << (index % 32 )
679
+ } else {
680
+ // Otherwise, it does not match
681
+ c .domainRoutingMap [ip ][index / 32 ] &^= 1 << (index % 32 )
682
+ }
683
+ }
684
+ }
685
+ copy (r .Bitmap [:], c .domainRoutingMap [ip ])
686
+ vals_routing = append (vals_routing , r )
687
+ }
688
+ if _ , err := BpfMapBatchUpdate (c .bpf .DomainBumpMap , keys , vals_bump , & ebpf.BatchOptions {
689
+ ElemFlags : uint64 (ebpf .UpdateAny ),
690
+ }); err != nil {
691
+ return err
644
692
}
645
- if _ , err := BpfMapBatchUpdate (c .bpf .DomainRoutingMap , keys , vals , & ebpf.BatchOptions {
693
+ if _ , err := BpfMapBatchUpdate (c .bpf .DomainRoutingMap , keys , vals_routing , & ebpf.BatchOptions {
646
694
ElemFlags : uint64 (ebpf .UpdateAny ),
647
695
}); err != nil {
648
696
return err
649
697
}
650
698
return nil
651
699
}
652
700
653
- // BatchRemoveDomainRouting remove bpf map domain_routing.
654
- func (c * controlPlaneCore ) BatchRemoveDomainRouting (cache * DnsCache ) error {
701
+ // BatchRemoveDomainBump update or remove bpf map domain_bump and domain_routing.
702
+ func (c * controlPlaneCore ) BatchRemoveDomain (cache * DnsCache ) error {
655
703
// Parse ips from DNS resp answers.
656
704
var ips []netip.Addr
657
705
for _ , ans := range cache .Answer {
@@ -675,15 +723,64 @@ func (c *controlPlaneCore) BatchRemoveDomainRouting(cache *DnsCache) error {
675
723
}
676
724
677
725
// Update bpf map.
678
- // Construct keys and vals, and BpfMapBatchUpdate.
679
- var keys [][4 ]uint32
726
+ // Update and determine whether to delete
727
+ var keys_del [][4 ]uint32
728
+ var keys_modify [][4 ]uint32
729
+ var vals_modify_bump []bpfDomainRouting
730
+ var vals_modify_routing []bpfDomainRouting
731
+
732
+ c .bumpMapMu .Lock ()
733
+ defer c .bumpMapMu .Unlock ()
734
+
680
735
for _ , ip := range ips {
681
736
ip6 := ip .As16 ()
682
- keys = append (keys , common .Ipv6ByteSliceToUint32Array (ip6 [:]))
737
+ newBumpMapVal := c .domainBumpMap [ip ]
738
+ for index := 0 ; index < consts .MaxMatchSetLen ; index ++ {
739
+ newBumpMapVal [index ] -= cache .DomainBitmap [index / 32 ] >> (index % 32 ) & 1
740
+ }
741
+
742
+ bumpMap := bpfDomainRouting {}
743
+ routingMap := bpfDomainRouting {}
744
+ copy (routingMap .Bitmap [:], c .domainRoutingMap [ip ])
745
+
746
+ del := true
747
+ for index , val := range newBumpMapVal {
748
+ if val > 0 {
749
+ del = false // This IP refers to some domain name that matches the domain_set, so there is no need to delete
750
+ bumpMap .Bitmap [index / 32 ] |= 1 << (index % 32 )
751
+ } else {
752
+ // This IP no longer refers to any domain name that matches the domain_set
753
+ routingMap .Bitmap [index / 32 ] &^= 1 << (index % 32 )
754
+ }
755
+ }
756
+ if del {
757
+ delete (c .domainBumpMap , ip )
758
+ delete (c .domainRoutingMap , ip )
759
+ keys_del = append (keys_del , common .Ipv6ByteSliceToUint32Array (ip6 [:]))
760
+ } else {
761
+ c .domainBumpMap [ip ] = newBumpMapVal
762
+ keys_modify = append (keys_modify , common .Ipv6ByteSliceToUint32Array (ip6 [:]))
763
+ vals_modify_bump = append (vals_modify_bump , bumpMap )
764
+ vals_modify_routing = append (vals_modify_routing , routingMap )
765
+ }
766
+ }
767
+ if _ , err := BpfMapBatchDelete (c .bpf .DomainBumpMap , keys_del ); err != nil {
768
+ return err
683
769
}
684
- if _ , err := BpfMapBatchDelete (c .bpf .DomainRoutingMap , keys ); err != nil {
770
+ if _ , err := BpfMapBatchDelete (c .bpf .DomainRoutingMap , keys_del ); err != nil {
685
771
return err
686
772
}
773
+ if _ , err := BpfMapBatchUpdate (c .bpf .DomainBumpMap , keys_modify , vals_modify_bump , & ebpf.BatchOptions {
774
+ ElemFlags : uint64 (ebpf .UpdateAny ),
775
+ }); err != nil {
776
+ return err
777
+ }
778
+ if _ , err := BpfMapBatchUpdate (c .bpf .DomainRoutingMap , keys_modify , vals_modify_routing , & ebpf.BatchOptions {
779
+ ElemFlags : uint64 (ebpf .UpdateAny ),
780
+ }); err != nil {
781
+ return err
782
+ }
783
+
687
784
return nil
688
785
}
689
786
0 commit comments