github.com/cilium/cilium@v1.16.2/pkg/maps/srv6map/policy.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 policyMapName4 = "cilium_srv6_policy_v4" 23 policyMapName6 = "cilium_srv6_policy_v6" 24 maxPolicyEntries = 16384 25 26 // policyStaticPrefixBits represents the size in bits of the static 27 // prefix part of an policy key (i.e. the VRF ID). 28 policyStaticPrefixBits = uint32(unsafe.Sizeof(uint32(0)) * 8) 29 ) 30 31 // PolicyKey4 is a key for the PolicyMap4. Implements bpf.MapKey. 32 type PolicyKey4 struct { 33 // PrefixLen is full 32 bits of VRF ID + DestCIDR's mask bits 34 PrefixLen uint32 `align:"lpm"` 35 VRFID uint32 `align:"vrf_id"` 36 DestCIDR types.IPv4 `align:"dst_cidr"` 37 } 38 39 func (k *PolicyKey4) New() bpf.MapKey { 40 return &PolicyKey4{} 41 } 42 43 func (k *PolicyKey4) String() string { 44 return fmt.Sprintf("vrfid=%d, destCIDR=%s", k.VRFID, k.getDestCIDR()) 45 } 46 47 func (k *PolicyKey4) getDestCIDR() netip.Prefix { 48 return netip.PrefixFrom( 49 k.DestCIDR.Addr(), 50 int(k.PrefixLen-policyStaticPrefixBits), 51 ) 52 } 53 54 // PolicyKey6 is a key for the PolicyMap6. Implements bpf.MapKey. 55 type PolicyKey6 struct { 56 // PrefixLen is full 32 bits of VRF ID + DestCIDR's mask bits 57 PrefixLen uint32 `align:"lpm"` 58 VRFID uint32 `align:"vrf_id"` 59 DestCIDR types.IPv6 `align:"dst_cidr"` 60 } 61 62 func (k *PolicyKey6) New() bpf.MapKey { 63 return &PolicyKey6{} 64 } 65 66 func (k *PolicyKey6) String() string { 67 return fmt.Sprintf("vrfid=%d, destCIDR=%s", k.VRFID, k.getDestCIDR()) 68 } 69 70 func (k *PolicyKey6) getDestCIDR() netip.Prefix { 71 return netip.PrefixFrom( 72 k.DestCIDR.Addr(), 73 int(k.PrefixLen-policyStaticPrefixBits), 74 ) 75 } 76 77 // PolicyKey abstracts away the differences between PolicyKey4 and PolicyKey6. 78 type PolicyKey struct { 79 VRFID uint32 80 DestCIDR netip.Prefix 81 } 82 83 // PolicyValue is a value for the PolicyMap4/6. Implements bpf.MapValue. 84 type PolicyValue struct { 85 SID types.IPv6 86 } 87 88 func (k *PolicyValue) New() bpf.MapValue { 89 return &PolicyValue{} 90 } 91 92 func (v *PolicyValue) String() string { 93 return fmt.Sprintf("sid=%s", v.SID.String()) 94 } 95 96 // SRv6PolicyIterateCallback represents the signature of the callback function 97 // expected by the IterateWithCallback method, which in turn is used to iterate 98 // all the keys/values of an SRv6 policy map. 99 type SRv6PolicyIterateCallback func(*PolicyKey, *PolicyValue) 100 101 // Define different types for IPv4 and IPv6 maps for DI 102 type PolicyMap4 srv6PolicyMap 103 type PolicyMap6 srv6PolicyMap 104 105 // IterateWithCallback4 iterates through the IPv4 keys/values of an egress 106 // policy map, passing each key/value pair to the cb callback. 107 func (m *PolicyMap4) IterateWithCallback(cb SRv6PolicyIterateCallback) error { 108 return m.DumpWithCallback(func(k bpf.MapKey, v bpf.MapValue) { 109 k4 := k.(*PolicyKey4) 110 key := &PolicyKey{ 111 VRFID: k4.VRFID, 112 DestCIDR: k4.getDestCIDR(), 113 } 114 value := v.(*PolicyValue) 115 cb(key, value) 116 }) 117 } 118 119 // IterateWithCallback iterates through the IPv6 keys/values of an egress 120 // policy map, passing each key/value pair to the cb callback. 121 func (m *PolicyMap6) IterateWithCallback(cb SRv6PolicyIterateCallback) error { 122 return m.DumpWithCallback(func(k bpf.MapKey, v bpf.MapValue) { 123 k6 := k.(*PolicyKey6) 124 key := &PolicyKey{ 125 VRFID: k6.VRFID, 126 DestCIDR: k6.getDestCIDR(), 127 } 128 value := v.(*PolicyValue) 129 cb(key, value) 130 }) 131 } 132 133 // srv6PolicyMap is the internal representation of an SRv6 policy map. 134 type srv6PolicyMap struct { 135 *bpf.Map 136 } 137 138 func newPolicyMaps(dc *option.DaemonConfig, lc cell.Lifecycle) (bpf.MapOut[*PolicyMap4], bpf.MapOut[*PolicyMap6], defines.NodeOut) { 139 if !dc.EnableSRv6 { 140 return bpf.MapOut[*PolicyMap4]{}, bpf.MapOut[*PolicyMap6]{}, defines.NodeOut{} 141 } 142 143 m4 := bpf.NewMap( 144 policyMapName4, 145 ebpf.LPMTrie, 146 &PolicyKey4{}, 147 &PolicyValue{}, 148 maxPolicyEntries, 149 bpf.BPF_F_NO_PREALLOC, 150 ) 151 152 m6 := bpf.NewMap( 153 policyMapName6, 154 ebpf.LPMTrie, 155 &PolicyKey6{}, 156 &PolicyValue{}, 157 maxPolicyEntries, 158 bpf.BPF_F_NO_PREALLOC, 159 ) 160 161 lc.Append(cell.Hook{ 162 OnStart: func(ctx cell.HookContext) error { 163 if err := m4.OpenOrCreate(); err != nil { 164 return err 165 } 166 if err := m6.OpenOrCreate(); err != nil { 167 return err 168 } 169 return nil 170 }, 171 OnStop: func(ctx cell.HookContext) error { 172 m4.Close() 173 m6.Close() 174 return nil 175 }, 176 }) 177 178 nodeOut := defines.NodeOut{ 179 NodeDefines: defines.Map{ 180 "SRV6_POLICY_MAP4": policyMapName4, 181 "SRV6_POLICY_MAP6": policyMapName6, 182 "SRV6_POLICY_MAP_SIZE": strconv.FormatUint(maxPolicyEntries, 10), 183 }, 184 } 185 186 return bpf.NewMapOut(&PolicyMap4{m4}), bpf.NewMapOut(&PolicyMap6{m6}), nodeOut 187 } 188 189 // OpenPolicyMaps opens the SRv6 policy maps on bpffs 190 func OpenPolicyMaps() (*PolicyMap4, *PolicyMap6, error) { 191 m4, err := bpf.OpenMap(bpf.MapPath(policyMapName4), &PolicyKey4{}, &PolicyValue{}) 192 if err != nil { 193 return nil, nil, err 194 } 195 m6, err := bpf.OpenMap(bpf.MapPath(policyMapName6), &PolicyKey6{}, &PolicyValue{}) 196 if err != nil { 197 return nil, nil, err 198 } 199 return &PolicyMap4{m4}, &PolicyMap6{m6}, nil 200 }