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

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package nodemap
     5  
     6  import (
     7  	"fmt"
     8  	"net"
     9  	"unsafe"
    10  
    11  	"golang.org/x/sys/unix"
    12  
    13  	"github.com/cilium/cilium/pkg/bpf"
    14  	"github.com/cilium/cilium/pkg/ebpf"
    15  	"github.com/cilium/cilium/pkg/types"
    16  )
    17  
    18  const (
    19  	MapName           = "cilium_node_map"
    20  	DefaultMaxEntries = 16384
    21  )
    22  
    23  // Map provides access to the eBPF map node.
    24  type Map interface {
    25  	// Update inserts or updates the node map object associated with the provided
    26  	// IP and node id.
    27  	Update(ip net.IP, nodeID uint16) error
    28  
    29  	// Delete deletes the node map object associated with the provided
    30  	// IP.
    31  	Delete(ip net.IP) error
    32  
    33  	// IterateWithCallback iterates through all the keys/values of a node map,
    34  	// passing each key/value pair to the cb callback.
    35  	IterateWithCallback(cb NodeIterateCallback) error
    36  
    37  	// Size returns what how many entries the node map is configured to hold.
    38  	Size() uint32
    39  }
    40  
    41  type nodeMap struct {
    42  	conf   Config
    43  	bpfMap *ebpf.Map
    44  }
    45  
    46  func newMap(mapName string, conf Config) *nodeMap {
    47  	return &nodeMap{
    48  		conf: conf,
    49  		bpfMap: ebpf.NewMap(&ebpf.MapSpec{
    50  			Name:       mapName,
    51  			Type:       ebpf.Hash,
    52  			KeySize:    uint32(unsafe.Sizeof(NodeKey{})),
    53  			ValueSize:  uint32(unsafe.Sizeof(NodeValue{})),
    54  			MaxEntries: conf.NodeMapMax,
    55  			Flags:      unix.BPF_F_NO_PREALLOC,
    56  			Pinning:    ebpf.PinByName,
    57  		}),
    58  	}
    59  }
    60  
    61  type NodeKey struct {
    62  	Pad1   uint16 `align:"pad1"`
    63  	Pad2   uint8  `align:"pad2"`
    64  	Family uint8  `align:"family"`
    65  	// represents both IPv6 and IPv4 (in the lowest four bytes)
    66  	IP types.IPv6 `align:"$union0"`
    67  }
    68  
    69  func (k *NodeKey) String() string {
    70  	switch k.Family {
    71  	case bpf.EndpointKeyIPv4:
    72  		return net.IP(k.IP[:net.IPv4len]).String()
    73  	case bpf.EndpointKeyIPv6:
    74  		return k.IP.String()
    75  	}
    76  	return "<unknown>"
    77  }
    78  
    79  func newNodeKey(ip net.IP) NodeKey {
    80  	result := NodeKey{}
    81  	if ip4 := ip.To4(); ip4 != nil {
    82  		result.Family = bpf.EndpointKeyIPv4
    83  		copy(result.IP[:], ip4)
    84  	} else {
    85  		result.Family = bpf.EndpointKeyIPv6
    86  		copy(result.IP[:], ip)
    87  	}
    88  	return result
    89  }
    90  
    91  type NodeValue struct {
    92  	NodeID uint16
    93  }
    94  
    95  func (m *nodeMap) Update(ip net.IP, nodeID uint16) error {
    96  	key := newNodeKey(ip)
    97  	val := NodeValue{NodeID: nodeID}
    98  	return m.bpfMap.Update(key, val, 0)
    99  }
   100  
   101  func (m *nodeMap) Size() uint32 {
   102  	return m.conf.NodeMapMax
   103  }
   104  
   105  func (m *nodeMap) Delete(ip net.IP) error {
   106  	key := newNodeKey(ip)
   107  	return m.bpfMap.Map.Delete(key)
   108  }
   109  
   110  // NodeIterateCallback represents the signature of the callback function
   111  // expected by the IterateWithCallback method, which in turn is used to iterate
   112  // all the keys/values of a node map.
   113  type NodeIterateCallback func(*NodeKey, *NodeValue)
   114  
   115  func (m *nodeMap) IterateWithCallback(cb NodeIterateCallback) error {
   116  	return m.bpfMap.IterateWithCallback(&NodeKey{}, &NodeValue{},
   117  		func(k, v interface{}) {
   118  			key := k.(*NodeKey)
   119  			value := v.(*NodeValue)
   120  
   121  			cb(key, value)
   122  		})
   123  }
   124  
   125  // LoadNodeMap loads the pre-initialized node map for access.
   126  // This should only be used from components which aren't capable of using hive - mainly the Cilium CLI.
   127  // It needs to initialized beforehand via the Cilium Agent.
   128  func LoadNodeMap() (Map, error) {
   129  	bpfMap, err := ebpf.LoadRegisterMap(MapName)
   130  	if err != nil {
   131  		return nil, fmt.Errorf("failed to load bpf map: %w", err)
   132  	}
   133  
   134  	return &nodeMap{bpfMap: bpfMap}, nil
   135  }
   136  
   137  func (m *nodeMap) init() error {
   138  	if err := m.bpfMap.OpenOrCreate(); err != nil {
   139  		return fmt.Errorf("failed to init bpf map: %w", err)
   140  	}
   141  
   142  	return nil
   143  }