github.com/castai/kvisor@v1.7.1-0.20240516114728-b3572a2607b5/cmd/agent/daemon/conntrack/conntrack_cilium_linux.go (about) 1 //go:build linux 2 3 package conntrack 4 5 import ( 6 "net/netip" 7 "path/filepath" 8 9 "github.com/castai/kvisor/pkg/logging" 10 "github.com/castai/kvisor/pkg/proc" 11 "github.com/cilium/cilium/pkg/bpf" 12 "github.com/cilium/cilium/pkg/defaults" 13 "github.com/cilium/cilium/pkg/loadbalancer" 14 "github.com/cilium/cilium/pkg/maps/ctmap" 15 "github.com/cilium/cilium/pkg/maps/lbmap" 16 "github.com/cilium/cilium/pkg/tuple" 17 "github.com/cilium/cilium/pkg/u8proto" 18 ) 19 20 var ( 21 ciliumCt4 *bpf.Map 22 ciliumCt6 *bpf.Map 23 backends4Map *bpf.Map 24 backends6Map *bpf.Map 25 ) 26 27 // TODO(anjmao): Rewrite this with simple cilium/ebpf map lookups to not depend on cilium packages. 28 func iniCiliumMaps(log *logging.Logger) bool { 29 var err error 30 31 ciliumCt4, err = bpf.OpenMap(proc.HostPath(filepath.Join(defaults.BPFFSRoot, defaults.TCGlobalsPath, ctmap.MapNameTCP4Global)), &ctmap.CtKey4Global{}, &ctmap.CtEntry{}) 32 if err != nil { 33 log.Info(err.Error()) 34 // We always expect v4 map. If it doesn't exist assume that cilium is not used. 35 return false 36 } else { 37 log.Infof("found cilium ebpf-map %s", ctmap.MapNameTCP4Global) 38 } 39 40 ciliumCt6, err = bpf.OpenMap(proc.HostPath(filepath.Join(defaults.BPFFSRoot, defaults.TCGlobalsPath, ctmap.MapNameTCP6Global)), &ctmap.CtKey6Global{}, &ctmap.CtEntry{}) 41 if err != nil { 42 log.Warn(err.Error()) 43 } else { 44 log.Infof("found cilium ebpf-map %s", ctmap.MapNameTCP6Global) 45 } 46 backends4Map, err = bpf.OpenMap(proc.HostPath(filepath.Join(defaults.BPFFSRoot, defaults.TCGlobalsPath, lbmap.Backend4MapV3Name)), &lbmap.Backend4KeyV3{}, &lbmap.Backend4ValueV3{}) 47 if err != nil { 48 log.Warn(err.Error()) 49 } else { 50 log.Infof("found cilium ebpf-map %s", lbmap.Backend4MapV3Name) 51 } 52 53 backends6Map, err = bpf.OpenMap(proc.HostPath(filepath.Join(defaults.BPFFSRoot, defaults.TCGlobalsPath, lbmap.Backend6MapV3Name)), &lbmap.Backend6KeyV3{}, &lbmap.Backend6ValueV3{}) 54 if err != nil { 55 log.Warn(err.Error()) 56 } else { 57 log.Infof("found cilium ebpf-map %s", lbmap.Backend6MapV3Name) 58 } 59 60 return true 61 } 62 63 func closeCilium() { 64 if ciliumCt4 != nil { 65 _ = ciliumCt4.Close() 66 } 67 if ciliumCt6 != nil { 68 _ = ciliumCt6.Close() 69 } 70 if backends4Map != nil { 71 _ = backends4Map.Close() 72 } 73 if backends6Map != nil { 74 _ = backends6Map.Close() 75 } 76 } 77 78 func lookupCiliumConntrackTable(src, dst netip.AddrPort) *netip.AddrPort { 79 if src.Addr().Is4() { 80 return lookupCilium4(src, dst) 81 } 82 if src.Addr().Is6() { 83 return lookupCilium6(src, dst) 84 } 85 return nil 86 } 87 88 func lookupCilium4(src, dst netip.AddrPort) *netip.AddrPort { 89 if ciliumCt4 == nil || backends4Map == nil { 90 return nil 91 } 92 key := &ctmap.CtKey4Global{ 93 TupleKey4Global: tuple.TupleKey4Global{ 94 TupleKey4: tuple.TupleKey4{ 95 SourcePort: dst.Port(), 96 SourceAddr: src.Addr().As4(), 97 DestPort: src.Port(), 98 DestAddr: dst.Addr().As4(), 99 NextHeader: u8proto.TCP, 100 Flags: ctmap.TUPLE_F_SERVICE, 101 }, 102 }, 103 } 104 v, err := ciliumCt4.Lookup(key.ToNetwork()) 105 if err != nil || v == nil { 106 return nil 107 } 108 e := v.(*ctmap.CtEntry) 109 110 // https://github.com/cilium/cilium/blob/v1.13.0/bpf/lib/common.h#L819 111 // CtEntity.RxBytes stores `backend_id` if `e.Flags & TUPLE_F_SERVICE` 112 backendId := e.RxBytes 113 backendKey := lbmap.NewBackend4KeyV3(loadbalancer.BackendID(backendId)) 114 b, err := backends4Map.Lookup(backendKey) 115 if err != nil || b == nil { 116 return nil 117 } 118 var backend lbmap.BackendValue 119 switch bv := b.(type) { 120 case *lbmap.Backend4Value: 121 backend = bv.ToHost() 122 case *lbmap.Backend4ValueV3: 123 backend = bv.ToHost() 124 default: 125 return nil 126 } 127 backendIP, _ := netip.AddrFromSlice(backend.GetAddress()) 128 res := netip.AddrPortFrom(backendIP, backend.GetPort()) 129 return &res 130 } 131 132 func lookupCilium6(src, dst netip.AddrPort) *netip.AddrPort { 133 if ciliumCt6 == nil || backends6Map == nil { 134 return nil 135 } 136 key := &ctmap.CtKey6Global{ 137 TupleKey6Global: tuple.TupleKey6Global{ 138 TupleKey6: tuple.TupleKey6{ 139 SourcePort: dst.Port(), 140 SourceAddr: src.Addr().As16(), 141 DestPort: src.Port(), 142 DestAddr: dst.Addr().As16(), 143 NextHeader: u8proto.TCP, 144 Flags: ctmap.TUPLE_F_SERVICE, 145 }, 146 }, 147 } 148 v, err := ciliumCt6.Lookup(key.ToNetwork()) 149 if err != nil || v == nil { 150 return nil 151 } 152 e := v.(*ctmap.CtEntry) 153 backendId := e.RxBytes 154 backendKey := lbmap.NewBackend6KeyV3(loadbalancer.BackendID(backendId)) 155 b, err := backends6Map.Lookup(backendKey) 156 if err != nil || b == nil { 157 return nil 158 } 159 var backend lbmap.BackendValue 160 switch bv := b.(type) { 161 case *lbmap.Backend6Value: 162 backend = bv.ToHost() 163 case *lbmap.Backend6ValueV3: 164 backend = bv.ToHost() 165 default: 166 return nil 167 } 168 backendIP, _ := netip.AddrFromSlice(backend.GetAddress()) 169 res := netip.AddrPortFrom(backendIP, backend.GetPort()) 170 return &res 171 }