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  }