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

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package lbmap
     5  
     6  import (
     7  	"fmt"
     8  	"net"
     9  	"unsafe"
    10  
    11  	"github.com/cilium/ebpf"
    12  
    13  	"github.com/cilium/cilium/pkg/bpf"
    14  	"github.com/cilium/cilium/pkg/byteorder"
    15  	cmtypes "github.com/cilium/cilium/pkg/clustermesh/types"
    16  	"github.com/cilium/cilium/pkg/loadbalancer"
    17  	"github.com/cilium/cilium/pkg/option"
    18  	"github.com/cilium/cilium/pkg/types"
    19  	"github.com/cilium/cilium/pkg/u8proto"
    20  )
    21  
    22  const (
    23  	// HealthProbe6MapName is the health datapath map name
    24  	HealthProbe6MapName = "cilium_lb6_health"
    25  
    26  	// SockRevNat6MapName is the BPF map name.
    27  	SockRevNat6MapName = "cilium_lb6_reverse_sk"
    28  
    29  	// SockRevNat6MapSize is the maximum number of entries in the BPF map.
    30  	SockRevNat6MapSize = 256 * 1024
    31  
    32  	// Service6MapV2Name is the name of the IPv6 LB Services v2 BPF map.
    33  	Service6MapV2Name = "cilium_lb6_services_v2"
    34  	// Backend6MapName is the name of the IPv6 LB backends BPF map.
    35  	Backend6MapName = "cilium_lb6_backends"
    36  	// Backend6MapV2Name is the name of the IPv6 LB backends v2 BPF map.
    37  	Backend6MapV2Name = "cilium_lb6_backends_v2"
    38  	// Backend6MapV3Name is the name of the IPv6 LB backends v3 BPF map.
    39  	Backend6MapV3Name = "cilium_lb6_backends_v3"
    40  	// RevNat6MapName is the name of the IPv6 LB reverse NAT BPF map.
    41  	RevNat6MapName = "cilium_lb6_reverse_nat"
    42  )
    43  
    44  var (
    45  	// MaxSockRevNat6MapEntries is the maximum number of entries in the BPF
    46  	// map. It is set by Init(), but unit tests use the initial value below.
    47  	MaxSockRevNat6MapEntries = SockRevNat6MapSize
    48  
    49  	// The following BPF maps are initialized in initSVC().
    50  
    51  	// Service6MapV2 is the IPv6 LB Services v2 BPF map.
    52  	Service6MapV2 *bpf.Map
    53  	// Backend6Map is the IPv6 LB backends BPF map.
    54  	Backend6Map *bpf.Map
    55  	// Backend6MapV2 is the IPv6 LB backends v2 BPF map.
    56  	Backend6MapV2 *bpf.Map
    57  	// Backend6MapV3 is the IPv6 LB backends v3 BPF map.
    58  	Backend6MapV3 *bpf.Map
    59  	// RevNat6Map is the IPv6 LB reverse NAT BPF map.
    60  	RevNat6Map *bpf.Map
    61  	// SockRevNat6Map is the IPv6 LB sock reverse NAT BPF map.
    62  	SockRevNat6Map *bpf.Map
    63  )
    64  
    65  // The compile-time check for whether the structs implement the interfaces
    66  var _ RevNatKey = (*RevNat6Key)(nil)
    67  var _ RevNatValue = (*RevNat6Value)(nil)
    68  var _ ServiceKey = (*Service6Key)(nil)
    69  var _ ServiceValue = (*Service6Value)(nil)
    70  var _ BackendKey = (*Backend6Key)(nil)
    71  var _ BackendValue = (*Backend6Value)(nil)
    72  var _ Backend = (*Backend6)(nil)
    73  
    74  type RevNat6Key struct {
    75  	Key uint16
    76  }
    77  
    78  func NewRevNat6Key(value uint16) *RevNat6Key {
    79  	return &RevNat6Key{value}
    80  }
    81  
    82  func (v *RevNat6Key) Map() *bpf.Map   { return RevNat6Map }
    83  func (v *RevNat6Key) String() string  { return fmt.Sprintf("%d", v.ToHost().(*RevNat6Key).Key) }
    84  func (v *RevNat6Key) New() bpf.MapKey { return &RevNat6Key{} }
    85  func (v *RevNat6Key) GetKey() uint16  { return v.Key }
    86  
    87  // ToNetwork converts RevNat6Key to network byte order.
    88  func (v *RevNat6Key) ToNetwork() RevNatKey {
    89  	n := *v
    90  	n.Key = byteorder.HostToNetwork16(n.Key)
    91  	return &n
    92  }
    93  
    94  // ToNetwork converts RevNat6Key to host byte order.
    95  func (v *RevNat6Key) ToHost() RevNatKey {
    96  	h := *v
    97  	h.Key = byteorder.NetworkToHost16(h.Key)
    98  	return &h
    99  }
   100  
   101  type RevNat6Value struct {
   102  	Address types.IPv6 `align:"address"`
   103  	Port    uint16     `align:"port"`
   104  }
   105  
   106  func (v *RevNat6Value) String() string {
   107  	vHost := v.ToHost().(*RevNat6Value)
   108  	return net.JoinHostPort(vHost.Address.String(), fmt.Sprintf("%d", vHost.Port))
   109  }
   110  
   111  func (v *RevNat6Value) New() bpf.MapValue { return &RevNat6Value{} }
   112  
   113  // ToNetwork converts RevNat6Value to network byte order.
   114  func (v *RevNat6Value) ToNetwork() RevNatValue {
   115  	n := *v
   116  	n.Port = byteorder.HostToNetwork16(n.Port)
   117  	return &n
   118  }
   119  
   120  // ToNetwork converts RevNat6Value to Host byte order.
   121  func (v *RevNat6Value) ToHost() RevNatValue {
   122  	h := *v
   123  	h.Port = byteorder.NetworkToHost16(h.Port)
   124  	return &h
   125  }
   126  
   127  // Service6Key must match 'struct lb6_key' in "bpf/lib/common.h".
   128  type Service6Key struct {
   129  	Address     types.IPv6 `align:"address"`
   130  	Port        uint16     `align:"dport"`
   131  	BackendSlot uint16     `align:"backend_slot"`
   132  	Proto       uint8      `align:"proto"`
   133  	Scope       uint8      `align:"scope"`
   134  	Pad         pad2uint8  `align:"pad"`
   135  }
   136  
   137  func NewService6Key(ip net.IP, port uint16, proto u8proto.U8proto, scope uint8, slot uint16) *Service6Key {
   138  	key := Service6Key{
   139  		Port:        port,
   140  		Proto:       uint8(proto),
   141  		Scope:       scope,
   142  		BackendSlot: slot,
   143  	}
   144  
   145  	copy(key.Address[:], ip.To16())
   146  
   147  	return &key
   148  }
   149  
   150  func (k *Service6Key) String() string {
   151  	kHost := k.ToHost().(*Service6Key)
   152  	if kHost.Scope == loadbalancer.ScopeInternal {
   153  		return fmt.Sprintf("[%s]:%d/i (%d)", kHost.Address, kHost.Port, kHost.BackendSlot)
   154  	} else {
   155  		return fmt.Sprintf("[%s]:%d (%d)", kHost.Address, kHost.Port, kHost.BackendSlot)
   156  	}
   157  }
   158  
   159  func (k *Service6Key) New() bpf.MapKey { return &Service6Key{} }
   160  
   161  func (k *Service6Key) IsIPv6() bool            { return true }
   162  func (k *Service6Key) IsSurrogate() bool       { return k.GetAddress().IsUnspecified() }
   163  func (k *Service6Key) Map() *bpf.Map           { return Service6MapV2 }
   164  func (k *Service6Key) SetBackendSlot(slot int) { k.BackendSlot = uint16(slot) }
   165  func (k *Service6Key) GetBackendSlot() int     { return int(k.BackendSlot) }
   166  func (k *Service6Key) SetScope(scope uint8)    { k.Scope = scope }
   167  func (k *Service6Key) GetScope() uint8         { return k.Scope }
   168  func (k *Service6Key) GetAddress() net.IP      { return k.Address.IP() }
   169  func (k *Service6Key) GetPort() uint16         { return k.Port }
   170  func (k *Service6Key) MapDelete() error        { return k.Map().Delete(k.ToNetwork()) }
   171  
   172  func (k *Service6Key) RevNatValue() RevNatValue {
   173  	return &RevNat6Value{
   174  		Address: k.Address,
   175  		Port:    k.Port,
   176  	}
   177  }
   178  
   179  func (k *Service6Key) ToNetwork() ServiceKey {
   180  	n := *k
   181  	n.Port = byteorder.HostToNetwork16(n.Port)
   182  	return &n
   183  }
   184  
   185  // ToHost converts Service6Key to host byte order.
   186  func (k *Service6Key) ToHost() ServiceKey {
   187  	h := *k
   188  	h.Port = byteorder.NetworkToHost16(h.Port)
   189  	return &h
   190  }
   191  
   192  // Service6Value must match 'struct lb6_service' in "bpf/lib/common.h".
   193  type Service6Value struct {
   194  	BackendID uint32    `align:"$union0"`
   195  	Count     uint16    `align:"count"`
   196  	RevNat    uint16    `align:"rev_nat_index"`
   197  	Flags     uint8     `align:"flags"`
   198  	Flags2    uint8     `align:"flags2"`
   199  	Pad       pad2uint8 `align:"pad"`
   200  }
   201  
   202  func (s *Service6Value) New() bpf.MapValue { return &Service6Value{} }
   203  
   204  func (s *Service6Value) String() string {
   205  	sHost := s.ToHost().(*Service6Value)
   206  	return fmt.Sprintf("%d %d (%d) [0x%x 0x%x]", sHost.BackendID, sHost.Count, sHost.RevNat, sHost.Flags, sHost.Flags2)
   207  }
   208  
   209  func (s *Service6Value) SetCount(count int)   { s.Count = uint16(count) }
   210  func (s *Service6Value) GetCount() int        { return int(s.Count) }
   211  func (s *Service6Value) SetRevNat(id int)     { s.RevNat = uint16(id) }
   212  func (s *Service6Value) GetRevNat() int       { return int(s.RevNat) }
   213  func (s *Service6Value) RevNatKey() RevNatKey { return &RevNat6Key{s.RevNat} }
   214  func (s *Service6Value) SetFlags(flags uint16) {
   215  	s.Flags = uint8(flags & 0xff)
   216  	s.Flags2 = uint8(flags >> 8)
   217  }
   218  
   219  func (s *Service6Value) GetFlags() uint16 {
   220  	return (uint16(s.Flags2) << 8) | uint16(s.Flags)
   221  }
   222  
   223  func (s *Service6Value) SetSessionAffinityTimeoutSec(t uint32) {
   224  	// See (* Service4Value).SetSessionAffinityTimeoutSec() for comment
   225  	s.BackendID = t
   226  }
   227  
   228  func (s *Service6Value) SetL7LBProxyPort(port uint16) {
   229  	// Go doesn't support union types, so we use BackendID to access the
   230  	// lb6_service.l7_lb_proxy_port field
   231  	s.BackendID = uint32(byteorder.HostToNetwork16(port))
   232  }
   233  
   234  func (s *Service6Value) SetBackendID(id loadbalancer.BackendID) {
   235  	s.BackendID = uint32(id)
   236  }
   237  func (s *Service6Value) GetBackendID() loadbalancer.BackendID {
   238  	return loadbalancer.BackendID(s.BackendID)
   239  }
   240  
   241  func (s *Service6Value) ToNetwork() ServiceValue {
   242  	n := *s
   243  	n.RevNat = byteorder.HostToNetwork16(n.RevNat)
   244  	return &n
   245  }
   246  
   247  // ToHost converts Service6Value to host byte order.
   248  func (s *Service6Value) ToHost() ServiceValue {
   249  	h := *s
   250  	h.RevNat = byteorder.NetworkToHost16(h.RevNat)
   251  	return &h
   252  }
   253  
   254  type Backend6KeyV3 struct {
   255  	ID loadbalancer.BackendID
   256  }
   257  
   258  func NewBackend6KeyV3(id loadbalancer.BackendID) *Backend6KeyV3 {
   259  	return &Backend6KeyV3{ID: id}
   260  }
   261  
   262  func (k *Backend6KeyV3) String() string                  { return fmt.Sprintf("%d", k.ID) }
   263  func (k *Backend6KeyV3) New() bpf.MapKey                 { return &Backend6KeyV3{} }
   264  func (k *Backend6KeyV3) Map() *bpf.Map                   { return Backend6MapV3 }
   265  func (k *Backend6KeyV3) SetID(id loadbalancer.BackendID) { k.ID = id }
   266  func (k *Backend6KeyV3) GetID() loadbalancer.BackendID   { return k.ID }
   267  
   268  type Backend6Key struct {
   269  	ID uint16
   270  }
   271  
   272  func (k *Backend6Key) String() string                  { return fmt.Sprintf("%d", k.ID) }
   273  func (k *Backend6Key) New() bpf.MapKey                 { return &Backend6Key{} }
   274  func (k *Backend6Key) Map() *bpf.Map                   { return Backend6Map }
   275  func (k *Backend6Key) SetID(id loadbalancer.BackendID) { k.ID = uint16(id) }
   276  func (k *Backend6Key) GetID() loadbalancer.BackendID   { return loadbalancer.BackendID(k.ID) }
   277  
   278  // Backend6Value must match 'struct lb6_backend' in "bpf/lib/common.h".
   279  type Backend6Value struct {
   280  	Address types.IPv6      `align:"address"`
   281  	Port    uint16          `align:"port"`
   282  	Proto   u8proto.U8proto `align:"proto"`
   283  	Flags   uint8           `align:"flags"`
   284  }
   285  
   286  func NewBackend6Value(ip net.IP, port uint16, proto u8proto.U8proto, state loadbalancer.BackendState) (*Backend6Value, error) {
   287  	ip6 := ip.To16()
   288  	if ip6 == nil {
   289  		return nil, fmt.Errorf("Not an IPv6 address")
   290  	}
   291  	flags := loadbalancer.NewBackendFlags(state)
   292  
   293  	val := Backend6Value{
   294  		Port:  port,
   295  		Proto: proto,
   296  		Flags: flags,
   297  	}
   298  	copy(val.Address[:], ip.To16())
   299  
   300  	return &val, nil
   301  }
   302  
   303  func (v *Backend6Value) String() string {
   304  	vHost := v.ToHost().(*Backend6Value)
   305  	return fmt.Sprintf("%s://[%s]:%d", vHost.Proto, vHost.Address, vHost.Port)
   306  }
   307  func (v *Backend6Value) New() bpf.MapValue { return &Backend6Value{} }
   308  
   309  func (b *Backend6Value) GetAddress() net.IP { return b.Address.IP() }
   310  func (b *Backend6Value) GetIPCluster() cmtypes.AddrCluster {
   311  	return cmtypes.AddrClusterFrom(b.Address.Addr(), 0)
   312  }
   313  func (b *Backend6Value) GetPort() uint16 { return b.Port }
   314  func (b *Backend6Value) GetFlags() uint8 { return b.Flags }
   315  func (b *Backend6Value) GetZone() uint8  { return 0 }
   316  
   317  func (v *Backend6Value) ToNetwork() BackendValue {
   318  	n := *v
   319  	n.Port = byteorder.HostToNetwork16(n.Port)
   320  	return &n
   321  }
   322  
   323  // ToHost converts Backend6Value to host byte order.
   324  func (v *Backend6Value) ToHost() BackendValue {
   325  	h := *v
   326  	h.Port = byteorder.NetworkToHost16(h.Port)
   327  	return &h
   328  }
   329  
   330  type Backend6ValueV3 struct {
   331  	Address   types.IPv6      `align:"address"`
   332  	Port      uint16          `align:"port"`
   333  	Proto     u8proto.U8proto `align:"proto"`
   334  	Flags     uint8           `align:"flags"`
   335  	ClusterID uint16          `align:"cluster_id"`
   336  	Zone      uint8           `align:"zone"`
   337  	Pad       uint8           `align:"pad"`
   338  }
   339  
   340  func NewBackend6ValueV3(addrCluster cmtypes.AddrCluster, port uint16, proto u8proto.U8proto, state loadbalancer.BackendState, zone uint8) (*Backend6ValueV3, error) {
   341  	addr := addrCluster.Addr()
   342  
   343  	// It is possible to have IPv4 backend in IPv6. We have NAT46/64.
   344  	if !addr.Is4() && !addr.Is6() {
   345  		return nil, fmt.Errorf("Not a valid IP address")
   346  	}
   347  
   348  	if addrCluster.ClusterID() > cmtypes.ClusterIDMax {
   349  		return nil, fmt.Errorf("ClusterID %d is too large. ClusterID > %d is not supported with Backend6ValueV3", addrCluster.ClusterID(), cmtypes.ClusterIDMax)
   350  	}
   351  
   352  	flags := loadbalancer.NewBackendFlags(state)
   353  
   354  	val := Backend6ValueV3{
   355  		Port:  port,
   356  		Proto: proto,
   357  		Flags: flags,
   358  		Zone:  zone,
   359  	}
   360  
   361  	ipv6Array := addr.As16()
   362  	copy(val.Address[:], ipv6Array[:])
   363  
   364  	return &val, nil
   365  }
   366  
   367  func (v *Backend6ValueV3) String() string {
   368  	vHost := v.ToHost().(*Backend6ValueV3)
   369  	if v.Zone != 0 {
   370  		return fmt.Sprintf("%s://%s[%s]", vHost.Proto, cmtypes.AddrClusterFrom(vHost.Address.Addr(), uint32(vHost.ClusterID)), option.Config.GetZone(v.Zone))
   371  	}
   372  	return fmt.Sprintf("%s://%s", vHost.Proto, cmtypes.AddrClusterFrom(vHost.Address.Addr(), uint32(vHost.ClusterID)))
   373  }
   374  
   375  func (v *Backend6ValueV3) New() bpf.MapValue { return &Backend6ValueV3{} }
   376  
   377  func (b *Backend6ValueV3) GetAddress() net.IP { return b.Address.IP() }
   378  func (b *Backend6ValueV3) GetIPCluster() cmtypes.AddrCluster {
   379  	return cmtypes.AddrClusterFrom(b.Address.Addr(), uint32(b.ClusterID))
   380  }
   381  func (b *Backend6ValueV3) GetPort() uint16 { return b.Port }
   382  func (b *Backend6ValueV3) GetFlags() uint8 { return b.Flags }
   383  func (b *Backend6ValueV3) GetZone() uint8  { return b.Zone }
   384  
   385  func (v *Backend6ValueV3) ToNetwork() BackendValue {
   386  	n := *v
   387  	n.Port = byteorder.HostToNetwork16(n.Port)
   388  	return &n
   389  }
   390  
   391  // ToHost converts Backend6ValueV3 to host byte order.
   392  func (v *Backend6ValueV3) ToHost() BackendValue {
   393  	h := *v
   394  	h.Port = byteorder.NetworkToHost16(h.Port)
   395  	return &h
   396  }
   397  
   398  type Backend6V3 struct {
   399  	Key   *Backend6KeyV3
   400  	Value *Backend6ValueV3
   401  }
   402  
   403  func NewBackend6V3(id loadbalancer.BackendID, addrCluster cmtypes.AddrCluster, port uint16,
   404  	proto u8proto.U8proto, state loadbalancer.BackendState, zone uint8) (*Backend6V3, error) {
   405  	val, err := NewBackend6ValueV3(addrCluster, port, proto, state, zone)
   406  	if err != nil {
   407  		return nil, err
   408  	}
   409  
   410  	return &Backend6V3{
   411  		Key:   NewBackend6KeyV3(id),
   412  		Value: val,
   413  	}, nil
   414  }
   415  
   416  func (b *Backend6V3) Map() *bpf.Map          { return Backend6MapV3 }
   417  func (b *Backend6V3) GetKey() BackendKey     { return b.Key }
   418  func (b *Backend6V3) GetValue() BackendValue { return b.Value }
   419  
   420  type Backend6V2 struct {
   421  	Key   *Backend6KeyV3
   422  	Value *Backend6Value
   423  }
   424  
   425  func NewBackend6V2(id loadbalancer.BackendID, ip net.IP, port uint16, proto u8proto.U8proto,
   426  	state loadbalancer.BackendState) (*Backend6V2, error) {
   427  	val, err := NewBackend6Value(ip, port, proto, state)
   428  	if err != nil {
   429  		return nil, err
   430  	}
   431  
   432  	return &Backend6V2{
   433  		Key:   NewBackend6KeyV3(id),
   434  		Value: val,
   435  	}, nil
   436  }
   437  
   438  func (b *Backend6V2) Map() *bpf.Map          { return Backend6MapV2 }
   439  func (b *Backend6V2) GetKey() BackendKey     { return b.Key }
   440  func (b *Backend6V2) GetValue() BackendValue { return b.Value }
   441  
   442  type Backend6 struct {
   443  	Key   *Backend6Key
   444  	Value *Backend6Value
   445  }
   446  
   447  func (b *Backend6) Map() *bpf.Map          { return Backend6Map }
   448  func (b *Backend6) GetKey() BackendKey     { return b.Key }
   449  func (b *Backend6) GetValue() BackendValue { return b.Value }
   450  
   451  // SockRevNat6Key is the tuple with address, port and cookie used as key in
   452  // the reverse NAT sock map.
   453  type SockRevNat6Key struct {
   454  	Cookie  uint64     `align:"cookie"`
   455  	Address types.IPv6 `align:"address"`
   456  	Port    int16      `align:"port"`
   457  	_       [6]byte
   458  }
   459  
   460  // SizeofSockRevNat6Key is the size of type SockRevNat6Key.
   461  const SizeofSockRevNat6Key = int(unsafe.Sizeof(SockRevNat6Key{}))
   462  
   463  // SockRevNat6Value is an entry in the reverse NAT sock map.
   464  type SockRevNat6Value struct {
   465  	address     types.IPv6 `align:"address"`
   466  	port        int16      `align:"port"`
   467  	revNatIndex uint16     `align:"rev_nat_index"`
   468  }
   469  
   470  // SizeofSockRevNat6Value is the size of type SockRevNat6Value.
   471  const SizeofSockRevNat6Value = int(unsafe.Sizeof(SockRevNat6Value{}))
   472  
   473  func (k *SockRevNat6Key) Map() *bpf.Map { return SockRevNat6Map }
   474  
   475  func NewSockRevNat6Key(cookie uint64, addr net.IP, port uint16) *SockRevNat6Key {
   476  	var key SockRevNat6Key
   477  
   478  	key.Cookie = cookie
   479  	key.Port = int16(byteorder.NetworkToHost16(port))
   480  	ipv6Array := addr.To16()
   481  	copy(key.Address[:], ipv6Array[:])
   482  
   483  	return &key
   484  }
   485  
   486  // String converts the key into a human readable string format.
   487  func (k *SockRevNat6Key) String() string {
   488  	return fmt.Sprintf("[%s]:%d, %d", k.Address, k.Port, k.Cookie)
   489  }
   490  
   491  func (k *SockRevNat6Key) New() bpf.MapKey { return &SockRevNat6Key{} }
   492  
   493  // String converts the value into a human readable string format.
   494  func (v *SockRevNat6Value) String() string {
   495  	return fmt.Sprintf("[%s]:%d, %d", v.address, v.port, v.revNatIndex)
   496  }
   497  
   498  func (v *SockRevNat6Value) New() bpf.MapValue { return &SockRevNat6Value{} }
   499  
   500  // CreateSockRevNat6Map creates the reverse NAT sock map.
   501  func CreateSockRevNat6Map() error {
   502  	SockRevNat6Map = bpf.NewMap(SockRevNat6MapName,
   503  		ebpf.LRUHash,
   504  		&SockRevNat6Key{},
   505  		&SockRevNat6Value{},
   506  		MaxSockRevNat6MapEntries,
   507  		0,
   508  	).WithPressureMetric()
   509  	return SockRevNat6Map.OpenOrCreate()
   510  }