github.com/cilium/cilium@v1.16.2/pkg/maps/tunnel/tunnel.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package tunnel
     5  
     6  import (
     7  	"fmt"
     8  	"net"
     9  	"sync"
    10  
    11  	"github.com/sirupsen/logrus"
    12  
    13  	"github.com/cilium/cilium/pkg/bpf"
    14  	cmtypes "github.com/cilium/cilium/pkg/clustermesh/types"
    15  	"github.com/cilium/cilium/pkg/ebpf"
    16  	ippkg "github.com/cilium/cilium/pkg/ip"
    17  	"github.com/cilium/cilium/pkg/option"
    18  	"github.com/cilium/cilium/pkg/types"
    19  )
    20  
    21  const (
    22  	MapName = "cilium_tunnel_map"
    23  
    24  	// MaxEntries is the maximum entries in the tunnel endpoint map
    25  	MaxEntries = 65536
    26  )
    27  
    28  var (
    29  	// TunnelMap represents the BPF map for tunnels
    30  	tunnelMap     *Map
    31  	tunnelMapInit = &sync.Once{}
    32  )
    33  
    34  // SetTunnelMap sets the tunnel map. Only used for testing.
    35  func SetTunnelMap(m *Map) {
    36  	if tunnelMap != nil {
    37  		tunnelMap.UnpinIfExists()
    38  	}
    39  
    40  	tunnelMap = m
    41  }
    42  
    43  func TunnelMap() *Map {
    44  	tunnelMapInit.Do(func() {
    45  		if tunnelMap == nil {
    46  			tunnelMap = NewTunnelMap(MapName)
    47  		}
    48  	})
    49  	return tunnelMap
    50  }
    51  
    52  // Map implements tunnel connectivity configuration in the BPF datapath.
    53  type Map struct {
    54  	*bpf.Map
    55  }
    56  
    57  // NewTunnelMap returns a new tunnel map.
    58  func NewTunnelMap(mapName string) *Map {
    59  	return &Map{Map: bpf.NewMap(
    60  		mapName,
    61  		ebpf.Hash,
    62  		&TunnelKey{},
    63  		&TunnelValue{},
    64  		MaxEntries,
    65  		0,
    66  	).WithCache().WithPressureMetric().
    67  		WithEvents(option.Config.GetEventBufferConfig(MapName)),
    68  	}
    69  }
    70  
    71  // +k8s:deepcopy-gen=true
    72  type TunnelIP struct {
    73  	// represents both IPv6 and IPv4 (in the lowest four bytes)
    74  	IP     types.IPv6 `align:"$union0"`
    75  	Family uint8      `align:"family"`
    76  }
    77  
    78  type TunnelKey struct {
    79  	TunnelIP
    80  	Pad       uint8  `align:"pad"`
    81  	ClusterID uint16 `align:"cluster_id"`
    82  }
    83  
    84  // String provides a string representation of the TunnelKey.
    85  func (k TunnelKey) String() string {
    86  	if ip := k.toIP(); ip != nil {
    87  		addrCluster := cmtypes.AddrClusterFrom(
    88  			ippkg.MustAddrFromIP(ip),
    89  			uint32(k.ClusterID),
    90  		)
    91  		return addrCluster.String()
    92  	}
    93  	return "nil"
    94  }
    95  
    96  func (k *TunnelKey) New() bpf.MapKey { return &TunnelKey{} }
    97  
    98  type TunnelValue struct {
    99  	TunnelIP
   100  	Key uint8  `align:"key"`
   101  	Pad uint16 `align:"pad"`
   102  }
   103  
   104  // String provides a string representation of the TunnelValue.
   105  func (k TunnelValue) String() string {
   106  	if ip := k.toIP(); ip != nil {
   107  		return ip.String() + ":" + fmt.Sprintf("%d", k.Key)
   108  	}
   109  	return "nil"
   110  }
   111  
   112  func (k *TunnelValue) New() bpf.MapValue { return &TunnelValue{} }
   113  
   114  // ToIP converts the TunnelIP into a net.IP structure.
   115  func (v TunnelIP) toIP() net.IP {
   116  	switch v.Family {
   117  	case bpf.EndpointKeyIPv4:
   118  		return v.IP[:4]
   119  	case bpf.EndpointKeyIPv6:
   120  		return v.IP[:]
   121  	}
   122  	return nil
   123  }
   124  
   125  func newTunnelKey(ip net.IP, clusterID uint32) (*TunnelKey, error) {
   126  	if clusterID > cmtypes.ClusterIDMax {
   127  		return nil, fmt.Errorf("ClusterID %d is too large. ClusterID > %d is not supported in TunnelMap", clusterID, cmtypes.ClusterIDMax)
   128  	}
   129  
   130  	result := TunnelKey{}
   131  	result.TunnelIP = newTunnelIP(ip)
   132  	result.ClusterID = uint16(clusterID)
   133  	return &result, nil
   134  }
   135  
   136  func newTunnelValue(ip net.IP, key uint8) *TunnelValue {
   137  	result := TunnelValue{}
   138  	result.TunnelIP = newTunnelIP(ip)
   139  	result.Key = key
   140  	return &result
   141  }
   142  
   143  func newTunnelIP(ip net.IP) TunnelIP {
   144  	result := TunnelIP{}
   145  	if ip4 := ip.To4(); ip4 != nil {
   146  		result.Family = bpf.EndpointKeyIPv4
   147  		copy(result.IP[:], ip4)
   148  	} else {
   149  		result.Family = bpf.EndpointKeyIPv6
   150  		copy(result.IP[:], ip)
   151  	}
   152  	return result
   153  }
   154  
   155  // SetTunnelEndpoint adds/replaces a prefix => tunnel-endpoint mapping
   156  func (m *Map) SetTunnelEndpoint(encryptKey uint8, prefix cmtypes.AddrCluster, endpoint net.IP) error {
   157  	key, err := newTunnelKey(prefix.AsNetIP(), prefix.ClusterID())
   158  	if err != nil {
   159  		return err
   160  	}
   161  
   162  	val := newTunnelValue(endpoint, encryptKey)
   163  
   164  	log.WithFields(logrus.Fields{
   165  		fieldPrefix:   prefix,
   166  		fieldEndpoint: endpoint,
   167  		fieldKey:      encryptKey,
   168  	}).Debug("Updating tunnel map entry")
   169  
   170  	return m.Update(key, val)
   171  }
   172  
   173  // GetTunnelEndpoint retrieves a prefix => tunnel-endpoint mapping
   174  func (m *Map) GetTunnelEndpoint(prefix cmtypes.AddrCluster) (net.IP, error) {
   175  	key, err := newTunnelKey(prefix.AsNetIP(), prefix.ClusterID())
   176  	if err != nil {
   177  		return net.IP{}, err
   178  	}
   179  
   180  	val, err := m.Lookup(key)
   181  	if err != nil {
   182  		return net.IP{}, err
   183  	}
   184  
   185  	return val.(*TunnelValue).toIP(), nil
   186  }
   187  
   188  // DeleteTunnelEndpoint removes a prefix => tunnel-endpoint mapping
   189  func (m *Map) DeleteTunnelEndpoint(prefix cmtypes.AddrCluster) error {
   190  	key, err := newTunnelKey(prefix.AsNetIP(), prefix.ClusterID())
   191  	if err != nil {
   192  		return err
   193  	}
   194  	log.WithField(fieldPrefix, prefix).Debug("Deleting tunnel map entry")
   195  	return m.Delete(key)
   196  }
   197  
   198  // SilentDeleteTunnelEndpoint removes a prefix => tunnel-endpoint mapping.
   199  // If the prefix is not found no error is returned.
   200  func (m *Map) SilentDeleteTunnelEndpoint(prefix cmtypes.AddrCluster) error {
   201  	key, err := newTunnelKey(prefix.AsNetIP(), prefix.ClusterID())
   202  	if err != nil {
   203  		return err
   204  	}
   205  	log.WithField(fieldPrefix, prefix).Debug("Silently deleting tunnel map entry")
   206  	_, err = m.SilentDelete(key)
   207  	return err
   208  }