@@ -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
}
@@ -64,16 +68,18 @@ func newControlPlaneCore(log *logrus.Logger,
64
68
}
65
69
closed , toClose := context .WithCancel (context .Background ())
66
70
return & controlPlaneCore {
67
- log : log ,
68
- deferFuncs : deferFuncs ,
69
- bpf : bpf ,
70
- outboundId2Name : outboundId2Name ,
71
- kernelVersion : kernelVersion ,
72
- flip : coreFlip ,
73
- isReload : isReload ,
74
- bpfEjected : false ,
75
- closed : closed ,
76
- close : toClose ,
71
+ log : log ,
72
+ deferFuncs : deferFuncs ,
73
+ bpf : bpf ,
74
+ outboundId2Name : outboundId2Name ,
75
+ kernelVersion : kernelVersion ,
76
+ flip : coreFlip ,
77
+ isReload : isReload ,
78
+ bpfEjected : false ,
79
+ domainBumpMap : make (map [netip.Addr ][]uint32 ),
80
+ domainRoutingMap : make (map [netip.Addr ][]uint32 ),
81
+ closed : closed ,
82
+ close : toClose ,
77
83
}
78
84
}
79
85
@@ -618,9 +624,8 @@ func (c *controlPlaneCore) bindDaens() (err error) {
618
624
return
619
625
}
620
626
621
- // BatchUpdateDomainRouting update bpf map domain_routing. Since one IP may have multiple domains, this function should
622
- // be invoked every A/AAAA-record lookup.
623
- func (c * controlPlaneCore ) BatchUpdateDomainRouting (cache * DnsCache ) error {
627
+ // BatchNewDomain update bpf map domain_bump and domain_routing. This function should be invoked every new cache.
628
+ func (c * controlPlaneCore ) BatchNewDomain (cache * DnsCache ) error {
624
629
// Parse ips from DNS resp answers.
625
630
var ips []netip.Addr
626
631
for _ , ans := range cache .Answer {
@@ -646,27 +651,70 @@ func (c *controlPlaneCore) BatchUpdateDomainRouting(cache *DnsCache) error {
646
651
// Update bpf map.
647
652
// Construct keys and vals, and BpfMapBatchUpdate.
648
653
var keys [][4 ]uint32
649
- var vals []bpfDomainRouting
654
+ var vals_bump []bpfDomainRouting
655
+ var vals_routing []bpfDomainRouting
656
+
657
+ c .bumpMapMu .Lock ()
658
+ defer c .bumpMapMu .Unlock ()
659
+
650
660
for _ , ip := range ips {
651
661
ip6 := ip .As16 ()
652
662
keys = append (keys , common .Ipv6ByteSliceToUint32Array (ip6 [:]))
663
+
653
664
r := bpfDomainRouting {}
654
- if len (cache .DomainBitmap ) != len (r .Bitmap ) {
665
+
666
+ if consts .MaxMatchSetLen / 32 != len (r .Bitmap ) || len (cache .DomainBitmap ) != len (r .Bitmap ) {
655
667
return fmt .Errorf ("domain bitmap length not sync with kern program" )
656
668
}
657
- copy (r .Bitmap [:], cache .DomainBitmap )
658
- vals = append (vals , r )
669
+
670
+ newBumpMap , exists := c .domainBumpMap [ip ]
671
+ if ! exists {
672
+ newBumpMap = make ([]uint32 , consts .MaxMatchSetLen )
673
+ }
674
+ for index := 0 ; index < consts .MaxMatchSetLen ; index ++ {
675
+ newBumpMap [index ] += cache .DomainBitmap [index / 32 ] >> (index % 32 ) & 1
676
+ }
677
+ for index , val := range newBumpMap {
678
+ if val > 0 {
679
+ r .Bitmap [index / 32 ] |= 1 << (index % 32 )
680
+ }
681
+ }
682
+ c .domainBumpMap [ip ] = newBumpMap
683
+ vals_bump = append (vals_bump , r )
684
+
685
+ if ! exists {
686
+ // New IP, init routingMap
687
+ c .domainRoutingMap [ip ] = cache .DomainBitmap
688
+ } else {
689
+ // Old IP, Update routingMap
690
+ for index := 0 ; index < consts .MaxMatchSetLen ; index ++ {
691
+ if (cache .DomainBitmap [index / 32 ]>> (index % 32 )& 1 ) == 1 && (c .domainRoutingMap [ip ][index / 32 ]>> (index % 32 )& 1 ) == 1 {
692
+ // If this domain matches the current rule, all previous domains also match the current rule, then it still matches
693
+ c .domainRoutingMap [ip ][index / 32 ] |= 1 << (index % 32 )
694
+ } else {
695
+ // Otherwise, it does not match
696
+ c .domainRoutingMap [ip ][index / 32 ] &^= 1 << (index % 32 )
697
+ }
698
+ }
699
+ }
700
+ copy (r .Bitmap [:], c .domainRoutingMap [ip ])
701
+ vals_routing = append (vals_routing , r )
702
+ }
703
+ if _ , err := BpfMapBatchUpdate (c .bpf .DomainBumpMap , keys , vals_bump , & ebpf.BatchOptions {
704
+ ElemFlags : uint64 (ebpf .UpdateAny ),
705
+ }); err != nil {
706
+ return err
659
707
}
660
- if _ , err := BpfMapBatchUpdate (c .bpf .DomainRoutingMap , keys , vals , & ebpf.BatchOptions {
708
+ if _ , err := BpfMapBatchUpdate (c .bpf .DomainRoutingMap , keys , vals_routing , & ebpf.BatchOptions {
661
709
ElemFlags : uint64 (ebpf .UpdateAny ),
662
710
}); err != nil {
663
711
return err
664
712
}
665
713
return nil
666
714
}
667
715
668
- // BatchRemoveDomainRouting remove bpf map domain_routing.
669
- func (c * controlPlaneCore ) BatchRemoveDomainRouting (cache * DnsCache ) error {
716
+ // BatchRemoveDomainBump update or remove bpf map domain_bump and domain_routing.
717
+ func (c * controlPlaneCore ) BatchRemoveDomain (cache * DnsCache ) error {
670
718
// Parse ips from DNS resp answers.
671
719
var ips []netip.Addr
672
720
for _ , ans := range cache .Answer {
@@ -690,15 +738,64 @@ func (c *controlPlaneCore) BatchRemoveDomainRouting(cache *DnsCache) error {
690
738
}
691
739
692
740
// Update bpf map.
693
- // Construct keys and vals, and BpfMapBatchUpdate.
694
- var keys [][4 ]uint32
741
+ // Update and determine whether to delete
742
+ var keys_del [][4 ]uint32
743
+ var keys_modify [][4 ]uint32
744
+ var vals_modify_bump []bpfDomainRouting
745
+ var vals_modify_routing []bpfDomainRouting
746
+
747
+ c .bumpMapMu .Lock ()
748
+ defer c .bumpMapMu .Unlock ()
749
+
695
750
for _ , ip := range ips {
696
751
ip6 := ip .As16 ()
697
- keys = append (keys , common .Ipv6ByteSliceToUint32Array (ip6 [:]))
752
+ newBumpMapVal := c .domainBumpMap [ip ]
753
+ for index := 0 ; index < consts .MaxMatchSetLen ; index ++ {
754
+ newBumpMapVal [index ] -= cache .DomainBitmap [index / 32 ] >> (index % 32 ) & 1
755
+ }
756
+
757
+ bumpMap := bpfDomainRouting {}
758
+ routingMap := bpfDomainRouting {}
759
+ copy (routingMap .Bitmap [:], c .domainRoutingMap [ip ])
760
+
761
+ del := true
762
+ for index , val := range newBumpMapVal {
763
+ if val > 0 {
764
+ del = false // This IP refers to some domain name that matches the domain_set, so there is no need to delete
765
+ bumpMap .Bitmap [index / 32 ] |= 1 << (index % 32 )
766
+ } else {
767
+ // This IP no longer refers to any domain name that matches the domain_set
768
+ routingMap .Bitmap [index / 32 ] &^= 1 << (index % 32 )
769
+ }
770
+ }
771
+ if del {
772
+ delete (c .domainBumpMap , ip )
773
+ delete (c .domainRoutingMap , ip )
774
+ keys_del = append (keys_del , common .Ipv6ByteSliceToUint32Array (ip6 [:]))
775
+ } else {
776
+ c .domainBumpMap [ip ] = newBumpMapVal
777
+ keys_modify = append (keys_modify , common .Ipv6ByteSliceToUint32Array (ip6 [:]))
778
+ vals_modify_bump = append (vals_modify_bump , bumpMap )
779
+ vals_modify_routing = append (vals_modify_routing , routingMap )
780
+ }
781
+ }
782
+ if _ , err := BpfMapBatchDelete (c .bpf .DomainBumpMap , keys_del ); err != nil {
783
+ return err
784
+ }
785
+ if _ , err := BpfMapBatchDelete (c .bpf .DomainRoutingMap , keys_del ); err != nil {
786
+ return err
787
+ }
788
+ if _ , err := BpfMapBatchUpdate (c .bpf .DomainBumpMap , keys_modify , vals_modify_bump , & ebpf.BatchOptions {
789
+ ElemFlags : uint64 (ebpf .UpdateAny ),
790
+ }); err != nil {
791
+ return err
698
792
}
699
- if _ , err := BpfMapBatchDelete (c .bpf .DomainRoutingMap , keys ); err != nil {
793
+ if _ , err := BpfMapBatchUpdate (c .bpf .DomainRoutingMap , keys_modify , vals_modify_routing , & ebpf.BatchOptions {
794
+ ElemFlags : uint64 (ebpf .UpdateAny ),
795
+ }); err != nil {
700
796
return err
701
797
}
798
+
702
799
return nil
703
800
}
704
801
0 commit comments