github.com/cilium/cilium@v1.16.2/pkg/maps/srv6map/vrf.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package srv6map 5 6 import ( 7 "fmt" 8 "net/netip" 9 "strconv" 10 "unsafe" 11 12 "github.com/cilium/ebpf" 13 "github.com/cilium/hive/cell" 14 15 "github.com/cilium/cilium/pkg/bpf" 16 "github.com/cilium/cilium/pkg/datapath/linux/config/defines" 17 "github.com/cilium/cilium/pkg/option" 18 "github.com/cilium/cilium/pkg/types" 19 ) 20 21 const ( 22 vrfMapName4 = "cilium_srv6_vrf_v4" 23 vrfMapName6 = "cilium_srv6_vrf_v6" 24 maxVRFEntries = 16384 25 26 // vrf4StaticPrefixBits represents the size in bits of the static 27 // prefix part of an vrf key (i.e. the VRF ID). 28 vrf4StaticPrefixBits = uint32(unsafe.Sizeof(types.IPv4{}) * 8) 29 30 // vrf6StaticPrefixBits represents the size in bits of the static 31 // prefix part of an vrf key (i.e. the VRF ID). 32 vrf6StaticPrefixBits = uint32(unsafe.Sizeof(types.IPv6{}) * 8) 33 ) 34 35 // VRFKey4 is a key for the VRFMap4. Implements bpf.MapKey. 36 type VRFKey4 struct { 37 // PrefixLen is full 32 bits of VRF ID + DestCIDR's mask bits 38 PrefixLen uint32 `align:"lpm"` 39 SourceIP types.IPv4 `align:"src_ip"` 40 DestCIDR types.IPv4 `align:"dst_cidr"` 41 } 42 43 func (v *VRFKey4) New() bpf.MapKey { 44 return &VRFKey4{} 45 } 46 47 func (v *VRFKey4) String() string { 48 return fmt.Sprintf("srcip=%s, destCIDR=%s", v.SourceIP, v.getDestCIDR()) 49 } 50 51 func (k *VRFKey4) getDestCIDR() netip.Prefix { 52 return netip.PrefixFrom( 53 k.DestCIDR.Addr(), 54 int(k.PrefixLen-vrf4StaticPrefixBits), 55 ) 56 } 57 58 // VRFKey6 is a key for the VRFMap6. Implements bpf.MapKey. 59 type VRFKey6 struct { 60 // PrefixLen is full 32 bits of VRF ID + DestCIDR's mask bits 61 PrefixLen uint32 `align:"lpm"` 62 SourceIP types.IPv6 `align:"src_ip"` 63 DestCIDR types.IPv6 `align:"dst_cidr"` 64 } 65 66 func (v *VRFKey6) New() bpf.MapKey { 67 return &VRFKey6{} 68 } 69 70 func (v *VRFKey6) String() string { 71 return fmt.Sprintf("srcip=%s, destCIDR=%s", v.SourceIP, v.getDestCIDR()) 72 } 73 74 func (k *VRFKey6) getDestCIDR() netip.Prefix { 75 return netip.PrefixFrom( 76 k.DestCIDR.Addr(), 77 int(k.PrefixLen-vrf6StaticPrefixBits), 78 ) 79 } 80 81 // VRFKey abstracts away the differences between VRFKey4 and VRFKey6. 82 type VRFKey struct { 83 SourceIP netip.Addr 84 DestCIDR netip.Prefix 85 } 86 87 // VRFValue is a value for the VRFMap4/6. Implements bpf.MapValue. 88 type VRFValue struct { 89 ID uint32 90 } 91 92 func (v *VRFValue) New() bpf.MapValue { 93 return &VRFValue{} 94 } 95 96 func (v *VRFValue) String() string { 97 return fmt.Sprintf("vrfid=%d", v.ID) 98 } 99 100 // SRv6VRFIterateCallback represents the signature of the callback function 101 // expected by the IterateWithCallback method, which in turn is used to iterate 102 // all the keys/values of policy maps. 103 type SRv6VRFIterateCallback func(*VRFKey, *VRFValue) 104 105 // Define different types for IPv4 and IPv6 maps for DI 106 type VRFMap4 srv6VRFMap 107 type VRFMap6 srv6VRFMap 108 109 // IterateWithCallback iterates through the IPv4 keys/values of a VRF mapping 110 // map, passing each key/value pair to the cb callback. 111 func (m *VRFMap4) IterateWithCallback(cb SRv6VRFIterateCallback) error { 112 return m.DumpWithCallback(func(k bpf.MapKey, v bpf.MapValue) { 113 k4 := k.(*VRFKey4) 114 key := &VRFKey{ 115 SourceIP: k4.SourceIP.Addr(), 116 DestCIDR: k4.getDestCIDR(), 117 } 118 value := v.(*VRFValue) 119 cb(key, value) 120 }) 121 } 122 123 // IterateWithCallback iterates through the IPv6 keys/values of a VRF mapping 124 // map, passing each key/value pair to the cb callback. 125 func (m *VRFMap6) IterateWithCallback(cb SRv6VRFIterateCallback) error { 126 return m.DumpWithCallback(func(k bpf.MapKey, v bpf.MapValue) { 127 k6 := k.(*VRFKey6) 128 key := &VRFKey{ 129 SourceIP: k6.SourceIP.Addr(), 130 DestCIDR: k6.getDestCIDR(), 131 } 132 value := v.(*VRFValue) 133 cb(key, value) 134 }) 135 } 136 137 // srv6VRFMap is the internal representation of an SRv6 VRF mapping map. 138 type srv6VRFMap struct { 139 *bpf.Map 140 } 141 142 func newVRFMaps(dc *option.DaemonConfig, lc cell.Lifecycle) (bpf.MapOut[*VRFMap4], bpf.MapOut[*VRFMap6], defines.NodeOut) { 143 if !dc.EnableSRv6 { 144 return bpf.MapOut[*VRFMap4]{}, bpf.MapOut[*VRFMap6]{}, defines.NodeOut{} 145 } 146 147 m4 := bpf.NewMap( 148 vrfMapName4, 149 ebpf.LPMTrie, 150 &VRFKey4{}, 151 &VRFValue{}, 152 maxVRFEntries, 153 bpf.BPF_F_NO_PREALLOC, 154 ) 155 156 m6 := bpf.NewMap( 157 vrfMapName6, 158 ebpf.LPMTrie, 159 &VRFKey6{}, 160 &VRFValue{}, 161 maxVRFEntries, 162 bpf.BPF_F_NO_PREALLOC, 163 ) 164 165 lc.Append(cell.Hook{ 166 OnStart: func(ctx cell.HookContext) error { 167 if err := m4.OpenOrCreate(); err != nil { 168 return err 169 } 170 if err := m6.OpenOrCreate(); err != nil { 171 return err 172 } 173 return nil 174 }, 175 OnStop: func(ctx cell.HookContext) error { 176 m4.Close() 177 m6.Close() 178 return nil 179 }, 180 }) 181 182 nodeOut := defines.NodeOut{ 183 NodeDefines: defines.Map{ 184 "SRV6_VRF_MAP4": vrfMapName4, 185 "SRV6_VRF_MAP6": vrfMapName6, 186 "SRV6_VRF_MAP_SIZE": strconv.FormatUint(maxVRFEntries, 10), 187 }, 188 } 189 190 return bpf.NewMapOut(&VRFMap4{m4}), bpf.NewMapOut(&VRFMap6{m6}), nodeOut 191 } 192 193 // OpenVRFMaps opens the SRv6 VRF maps on bpffs 194 func OpenVRFMaps() (*VRFMap4, *VRFMap6, error) { 195 m4, err := bpf.OpenMap(bpf.MapPath(vrfMapName4), &VRFKey4{}, &VRFValue{}) 196 if err != nil { 197 return nil, nil, err 198 } 199 200 m6, err := bpf.OpenMap(bpf.MapPath(vrfMapName6), &VRFKey6{}, &VRFValue{}) 201 if err != nil { 202 return nil, nil, err 203 } 204 205 return &VRFMap4{m4}, &VRFMap6{m6}, nil 206 }