github.com/looshlee/beatles@v0.0.0-20220727174639-742810ab631c/pkg/maps/lbmap/ipv6.go (about)

     1  // Copyright 2016-2019 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package lbmap
    16  
    17  import (
    18  	"fmt"
    19  	"net"
    20  	"unsafe"
    21  
    22  	"github.com/cilium/cilium/common/types"
    23  	"github.com/cilium/cilium/pkg/bpf"
    24  	"github.com/cilium/cilium/pkg/byteorder"
    25  	"github.com/cilium/cilium/pkg/loadbalancer"
    26  	"github.com/cilium/cilium/pkg/u8proto"
    27  )
    28  
    29  var (
    30  	// Service6Map represents the BPF map for services in IPv6 load balancer
    31  	Service6Map = bpf.NewMap("cilium_lb6_services",
    32  		bpf.MapTypeHash,
    33  		&Service6Key{},
    34  		int(unsafe.Sizeof(Service6Key{})),
    35  		&Service6Value{},
    36  		int(unsafe.Sizeof(Service6Value{})),
    37  		MaxEntries,
    38  		0, 0,
    39  		func(key []byte, value []byte, mapKey bpf.MapKey, mapValue bpf.MapValue) (bpf.MapKey, bpf.MapValue, error) {
    40  			svcKey, svcVal := mapKey.(*Service6Key), mapValue.(*Service6Value)
    41  
    42  			if _, _, err := bpf.ConvertKeyValue(key, value, svcKey, svcVal); err != nil {
    43  				return nil, nil, err
    44  			}
    45  
    46  			return svcKey.ToNetwork(), svcVal.ToNetwork(), nil
    47  		}).WithCache()
    48  	Service6MapV2 = bpf.NewMap("cilium_lb6_services_v2",
    49  		bpf.MapTypeHash,
    50  		&Service6KeyV2{},
    51  		int(unsafe.Sizeof(Service6KeyV2{})),
    52  		&Service6ValueV2{},
    53  		int(unsafe.Sizeof(Service6ValueV2{})),
    54  		MaxEntries,
    55  		0, 0,
    56  		func(key []byte, value []byte, mapKey bpf.MapKey, mapValue bpf.MapValue) (bpf.MapKey, bpf.MapValue, error) {
    57  			svcKey, svcVal := mapKey.(*Service6KeyV2), mapValue.(*Service6ValueV2)
    58  
    59  			if _, _, err := bpf.ConvertKeyValue(key, value, svcKey, svcVal); err != nil {
    60  				return nil, nil, err
    61  			}
    62  
    63  			return svcKey.ToNetwork(), svcVal.ToNetwork(), nil
    64  		}).WithCache()
    65  	Backend6Map = bpf.NewMap("cilium_lb6_backends",
    66  		bpf.MapTypeHash,
    67  		&Backend6Key{},
    68  		int(unsafe.Sizeof(Backend6Key{})),
    69  		&Backend6Value{},
    70  		int(unsafe.Sizeof(Backend6Value{})),
    71  		MaxEntries,
    72  		0, 0,
    73  		func(key []byte, value []byte, mapKey bpf.MapKey, mapValue bpf.MapValue) (bpf.MapKey, bpf.MapValue, error) {
    74  			backendVal := mapValue.(*Backend6Value)
    75  
    76  			if _, _, err := bpf.ConvertKeyValue(key, value, mapKey, backendVal); err != nil {
    77  				return nil, nil, err
    78  			}
    79  
    80  			return mapKey, backendVal.ToNetwork(), nil
    81  		}).WithCache()
    82  	// RevNat6Map represents the BPF map for reverse NAT in IPv6 load balancer
    83  	RevNat6Map = bpf.NewMap("cilium_lb6_reverse_nat",
    84  		bpf.MapTypeHash,
    85  		&RevNat6Key{},
    86  		int(unsafe.Sizeof(RevNat6Key{})),
    87  		&RevNat6Value{},
    88  		int(unsafe.Sizeof(RevNat6Value{})),
    89  		MaxEntries,
    90  		0, 0,
    91  		func(key []byte, value []byte, mapKey bpf.MapKey, mapValue bpf.MapValue) (bpf.MapKey, bpf.MapValue, error) {
    92  			revKey, revNat := mapKey.(*RevNat6Key), mapValue.(*RevNat6Value)
    93  
    94  			if _, _, err := bpf.ConvertKeyValue(key, value, revKey, revNat); err != nil {
    95  				return nil, nil, err
    96  			}
    97  
    98  			return revKey.ToNetwork(), revNat.ToNetwork(), nil
    99  		}).WithCache()
   100  	// RRSeq6Map represents the BPF map for wrr sequences in IPv6 load balancer
   101  	RRSeq6Map = bpf.NewMap("cilium_lb6_rr_seq",
   102  		bpf.MapTypeHash,
   103  		&Service6Key{},
   104  		int(unsafe.Sizeof(Service6Key{})),
   105  		&RRSeqValue{},
   106  		int(unsafe.Sizeof(RRSeqValue{})),
   107  		maxFrontEnds,
   108  		0, 0,
   109  		func(key []byte, value []byte, mapKey bpf.MapKey, mapValue bpf.MapValue) (bpf.MapKey, bpf.MapValue, error) {
   110  			svcKey := mapKey.(*Service6Key)
   111  
   112  			if _, _, err := bpf.ConvertKeyValue(key, value, svcKey, mapValue); err != nil {
   113  				return nil, nil, err
   114  			}
   115  
   116  			return svcKey.ToNetwork(), mapValue, nil
   117  		}).WithCache()
   118  	// RRSeq6MapV2 represents the BPF map for wrr sequences in IPv6 load balancer
   119  	RRSeq6MapV2 = bpf.NewMap("cilium_lb6_rr_seq_v2",
   120  		bpf.MapTypeHash,
   121  		&Service6KeyV2{},
   122  		int(unsafe.Sizeof(Service6KeyV2{})),
   123  		&RRSeqValue{},
   124  		int(unsafe.Sizeof(RRSeqValue{})),
   125  		maxFrontEnds,
   126  		0, 0,
   127  		func(key []byte, value []byte, mapKey bpf.MapKey, mapValue bpf.MapValue) (bpf.MapKey, bpf.MapValue, error) {
   128  			svcKey := mapKey.(*Service6KeyV2)
   129  
   130  			if _, _, err := bpf.ConvertKeyValue(key, value, svcKey, mapValue); err != nil {
   131  				return nil, nil, err
   132  			}
   133  
   134  			return svcKey.ToNetwork(), mapValue, nil
   135  		}).WithCache()
   136  )
   137  
   138  // Service6Key must match 'struct lb6_key' in "bpf/lib/common.h".
   139  // +k8s:deepcopy-gen=true
   140  // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey
   141  type Service6Key struct {
   142  	Address types.IPv6 `align:"address"`
   143  	Port    uint16     `align:"dport"`
   144  	Slave   uint16     `align:"slave"`
   145  }
   146  
   147  func NewService6Key(ip net.IP, port uint16, slave uint16) *Service6Key {
   148  	key := Service6Key{
   149  		Port:  port,
   150  		Slave: slave,
   151  	}
   152  
   153  	copy(key.Address[:], ip.To16())
   154  
   155  	return &key
   156  }
   157  
   158  func (k Service6Key) IsIPv6() bool               { return true }
   159  func (k Service6Key) Map() *bpf.Map              { return Service6Map }
   160  func (k Service6Key) RRMap() *bpf.Map            { return RRSeq6Map }
   161  func (k Service6Key) NewValue() bpf.MapValue     { return &Service6Value{} }
   162  func (k *Service6Key) GetKeyPtr() unsafe.Pointer { return unsafe.Pointer(k) }
   163  func (k *Service6Key) GetPort() uint16           { return k.Port }
   164  func (k *Service6Key) SetPort(port uint16)       { k.Port = port }
   165  func (k *Service6Key) SetBackend(backend int)    { k.Slave = uint16(backend) }
   166  func (k *Service6Key) GetBackend() int           { return int(k.Slave) }
   167  
   168  // ToNetwork converts Service6Key to network byte order.
   169  func (k *Service6Key) ToNetwork() ServiceKey {
   170  	n := *k
   171  	n.Port = byteorder.HostToNetwork(n.Port).(uint16)
   172  	return &n
   173  }
   174  
   175  // ToHost converts Service6Key to host byte order.
   176  func (k *Service6Key) ToHost() ServiceKey {
   177  	n := *k
   178  	n.Port = byteorder.NetworkToHost(n.Port).(uint16)
   179  	return &n
   180  }
   181  
   182  func (k *Service6Key) String() string {
   183  	return fmt.Sprintf("[%s]:%d", k.Address, k.Port)
   184  }
   185  
   186  func (k *Service6Key) RevNatValue() RevNatValue {
   187  	return &RevNat6Value{
   188  		Address: k.Address,
   189  		Port:    k.Port,
   190  	}
   191  }
   192  
   193  // Service6Value must match 'struct lb6_service' in "bpf/lib/common.h".
   194  // +k8s:deepcopy-gen=true
   195  // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapValue
   196  type Service6Value struct {
   197  	Address types.IPv6 `align:"target"`
   198  	Port    uint16     `align:"port"`
   199  	Count   uint16     `align:"count"`
   200  	RevNat  uint16     `align:"rev_nat_index"`
   201  	Weight  uint16     `align:"weight"`
   202  }
   203  
   204  func NewService6Value(count uint16, target net.IP, port uint16, revNat uint16, weight uint16) *Service6Value {
   205  	svc := Service6Value{
   206  		Count:  count,
   207  		Port:   port,
   208  		RevNat: revNat,
   209  		Weight: weight,
   210  	}
   211  
   212  	copy(svc.Address[:], target.To16())
   213  
   214  	return &svc
   215  }
   216  
   217  func (s *Service6Value) GetValuePtr() unsafe.Pointer { return unsafe.Pointer(s) }
   218  func (s *Service6Value) SetPort(port uint16)         { s.Port = port }
   219  func (s *Service6Value) GetPort() uint16             { return s.Port }
   220  func (s *Service6Value) SetCount(count int)          { s.Count = uint16(count) }
   221  func (s *Service6Value) GetCount() int               { return int(s.Count) }
   222  func (s *Service6Value) SetRevNat(id int)            { s.RevNat = uint16(id) }
   223  func (s *Service6Value) RevNatKey() RevNatKey        { return &RevNat6Key{s.RevNat} }
   224  func (s *Service6Value) SetWeight(weight uint16)     { s.Weight = weight }
   225  func (s *Service6Value) GetWeight() uint16           { return s.Weight }
   226  func (s *Service6Value) IsIPv6() bool                { return true }
   227  
   228  func (s *Service6Value) SetAddress(ip net.IP) error {
   229  	if ip.To4() != nil {
   230  		return fmt.Errorf("Not an IPv6 address")
   231  	}
   232  
   233  	copy(s.Address[:], ip.To16())
   234  	return nil
   235  }
   236  
   237  func (s *Service6Value) GetAddress() net.IP {
   238  	return s.Address.IP()
   239  }
   240  
   241  // ToNetwork converts Service6Value ports to network byte order.
   242  func (s *Service6Value) ToNetwork() ServiceValue {
   243  	n := *s
   244  	n.RevNat = byteorder.HostToNetwork(n.RevNat).(uint16)
   245  	n.Port = byteorder.HostToNetwork(n.Port).(uint16)
   246  	n.Weight = byteorder.HostToNetwork(n.Weight).(uint16)
   247  	return &n
   248  }
   249  
   250  // ToHost converts Service6Value ports to host byte order.
   251  func (s *Service6Value) ToHost() ServiceValue {
   252  	n := *s
   253  	n.RevNat = byteorder.NetworkToHost(n.RevNat).(uint16)
   254  	n.Port = byteorder.NetworkToHost(n.Port).(uint16)
   255  	n.Weight = byteorder.NetworkToHost(n.Weight).(uint16)
   256  	return &n
   257  }
   258  
   259  func (s *Service6Value) String() string {
   260  	return fmt.Sprintf("[%s]:%d (%d)", s.Address, s.Port, s.RevNat)
   261  }
   262  
   263  func (s *Service6Value) BackendAddrID() BackendAddrID {
   264  	return BackendAddrID(fmt.Sprintf("[%s]:%d", s.Address, s.Port))
   265  }
   266  
   267  // +k8s:deepcopy-gen=true
   268  // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey
   269  type RevNat6Key struct {
   270  	Key uint16
   271  }
   272  
   273  func NewRevNat6Key(value uint16) *RevNat6Key {
   274  	return &RevNat6Key{value}
   275  }
   276  
   277  func (v *RevNat6Key) IsIPv6() bool              { return true }
   278  func (v *RevNat6Key) Map() *bpf.Map             { return RevNat6Map }
   279  func (v *RevNat6Key) NewValue() bpf.MapValue    { return &RevNat6Value{} }
   280  func (v *RevNat6Key) GetKeyPtr() unsafe.Pointer { return unsafe.Pointer(v) }
   281  func (v *RevNat6Key) String() string            { return fmt.Sprintf("%d", v.Key) }
   282  func (v *RevNat6Key) GetKey() uint16            { return v.Key }
   283  
   284  // ToNetwork converts RevNat6Key to network byte order.
   285  func (v *RevNat6Key) ToNetwork() RevNatKey {
   286  	n := *v
   287  	n.Key = byteorder.HostToNetwork(n.Key).(uint16)
   288  	return &n
   289  }
   290  
   291  // +k8s:deepcopy-gen=true
   292  // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapValue
   293  type RevNat6Value struct {
   294  	Address types.IPv6
   295  	Port    uint16
   296  }
   297  
   298  func NewRevNat6Value(ip net.IP, port uint16) *RevNat6Value {
   299  	revNat := RevNat6Value{
   300  		Port: port,
   301  	}
   302  
   303  	copy(revNat.Address[:], ip.To16())
   304  
   305  	return &revNat
   306  }
   307  
   308  func (v *RevNat6Value) GetValuePtr() unsafe.Pointer { return unsafe.Pointer(v) }
   309  func (v *RevNat6Value) String() string              { return fmt.Sprintf("%s:%d", v.Address, v.Port) }
   310  
   311  // ToNetwork converts RevNat6Value to network byte order.
   312  func (v *RevNat6Value) ToNetwork() RevNatValue {
   313  	n := *v
   314  	n.Port = byteorder.HostToNetwork(n.Port).(uint16)
   315  	return &n
   316  }
   317  
   318  // Service6KeyV2 must match 'struct lb6_key_v2' in "bpf/lib/common.h".
   319  // +k8s:deepcopy-gen=true
   320  // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey
   321  type Service6KeyV2 struct {
   322  	Address types.IPv6 `align:"address"`
   323  	Port    uint16     `align:"dport"`
   324  	Slave   uint16     `align:"slave"`
   325  	Proto   uint8      `align:"proto"`
   326  	Pad     pad3uint8
   327  }
   328  
   329  func NewService6KeyV2(ip net.IP, port uint16, proto u8proto.U8proto, slave uint16) *Service6KeyV2 {
   330  	key := Service6KeyV2{
   331  		Port:  port,
   332  		Proto: uint8(proto),
   333  		Slave: slave,
   334  	}
   335  
   336  	copy(key.Address[:], ip.To16())
   337  
   338  	return &key
   339  }
   340  
   341  func (k *Service6KeyV2) String() string {
   342  	return fmt.Sprintf("[%s]:%d", k.Address, k.Port)
   343  }
   344  
   345  func (k *Service6KeyV2) GetKeyPtr() unsafe.Pointer { return unsafe.Pointer(k) }
   346  func (k *Service6KeyV2) NewValue() bpf.MapValue    { return &Service6ValueV2{} }
   347  func (k *Service6KeyV2) IsIPv6() bool              { return true }
   348  func (k *Service6KeyV2) Map() *bpf.Map             { return Service6MapV2 }
   349  func (k *Service6KeyV2) RRMap() *bpf.Map           { return RRSeq6MapV2 }
   350  func (k *Service6KeyV2) SetSlave(slave int)        { k.Slave = uint16(slave) }
   351  func (k *Service6KeyV2) GetSlave() int             { return int(k.Slave) }
   352  func (k *Service6KeyV2) GetAddress() net.IP        { return k.Address.IP() }
   353  func (k *Service6KeyV2) GetPort() uint16           { return k.Port }
   354  func (k *Service6KeyV2) MapDelete() error          { return k.Map().Delete(k.ToNetwork()) }
   355  
   356  func (k *Service6KeyV2) ToNetwork() ServiceKeyV2 {
   357  	n := *k
   358  	n.Port = byteorder.HostToNetwork(n.Port).(uint16)
   359  	return &n
   360  }
   361  
   362  // Service6ValueV2 must match 'struct lb6_service_v2' in "bpf/lib/common.h".
   363  // +k8s:deepcopy-gen=true
   364  // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapValue
   365  type Service6ValueV2 struct {
   366  	BackendID uint32 `align:"backend_id"`
   367  	Count     uint16 `align:"count"`
   368  	RevNat    uint16 `align:"rev_nat_index"`
   369  	Weight    uint16 `align:"weight"`
   370  	Pad       uint16
   371  }
   372  
   373  func NewService6ValueV2(count uint16, backendID loadbalancer.BackendID, revNat uint16, weight uint16) *Service6ValueV2 {
   374  	svc := Service6ValueV2{
   375  		Count:     count,
   376  		BackendID: uint32(backendID),
   377  		RevNat:    revNat,
   378  		Weight:    weight,
   379  	}
   380  
   381  	return &svc
   382  }
   383  
   384  func (s *Service6ValueV2) String() string {
   385  	return fmt.Sprintf("%d (%d)", s.BackendID, s.RevNat)
   386  }
   387  
   388  func (s *Service6ValueV2) GetValuePtr() unsafe.Pointer { return unsafe.Pointer(s) }
   389  
   390  func (s *Service6ValueV2) SetCount(count int)      { s.Count = uint16(count) }
   391  func (s *Service6ValueV2) GetCount() int           { return int(s.Count) }
   392  func (s *Service6ValueV2) SetRevNat(id int)        { s.RevNat = uint16(id) }
   393  func (s *Service6ValueV2) GetRevNat() int          { return int(s.RevNat) }
   394  func (s *Service6ValueV2) SetWeight(weight uint16) { s.Weight = weight }
   395  func (s *Service6ValueV2) GetWeight() uint16       { return s.Weight }
   396  func (s *Service6ValueV2) RevNatKey() RevNatKey    { return &RevNat6Key{s.RevNat} }
   397  
   398  func (s *Service6ValueV2) SetBackendID(id loadbalancer.BackendID) {
   399  	s.BackendID = uint32(id)
   400  }
   401  func (s *Service6ValueV2) GetBackendID() loadbalancer.BackendID {
   402  	return loadbalancer.BackendID(s.BackendID)
   403  }
   404  
   405  func (s *Service6ValueV2) ToNetwork() ServiceValueV2 {
   406  	n := *s
   407  	n.RevNat = byteorder.HostToNetwork(n.RevNat).(uint16)
   408  	n.Weight = byteorder.HostToNetwork(n.Weight).(uint16)
   409  	return &n
   410  }
   411  
   412  // +k8s:deepcopy-gen=true
   413  // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey
   414  type Backend6Key struct {
   415  	ID loadbalancer.BackendID
   416  }
   417  
   418  func NewBackend6Key(id loadbalancer.BackendID) *Backend6Key {
   419  	return &Backend6Key{ID: id}
   420  }
   421  
   422  func (k *Backend6Key) String() string                  { return fmt.Sprintf("%d", k.ID) }
   423  func (k *Backend6Key) GetKeyPtr() unsafe.Pointer       { return unsafe.Pointer(k) }
   424  func (k *Backend6Key) NewValue() bpf.MapValue          { return &Backend6Value{} }
   425  func (k *Backend6Key) Map() *bpf.Map                   { return Backend6Map }
   426  func (k *Backend6Key) SetID(id loadbalancer.BackendID) { k.ID = id }
   427  func (k *Backend6Key) GetID() loadbalancer.BackendID   { return k.ID }
   428  
   429  // Backend6Value must match 'struct lb6_backend' in "bpf/lib/common.h".
   430  // +k8s:deepcopy-gen=true
   431  // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapValue
   432  type Backend6Value struct {
   433  	Address types.IPv6      `align:"address"`
   434  	Port    uint16          `align:"port"`
   435  	Proto   u8proto.U8proto `align:"proto"`
   436  	Pad     uint8
   437  }
   438  
   439  func NewBackend6Value(ip net.IP, port uint16, proto u8proto.U8proto) (*Backend6Value, error) {
   440  	ip6 := ip.To16()
   441  	if ip6 == nil {
   442  		return nil, fmt.Errorf("Not an IPv6 address")
   443  	}
   444  
   445  	val := Backend6Value{
   446  		Port:  port,
   447  		Proto: proto,
   448  	}
   449  	copy(val.Address[:], ip.To16())
   450  
   451  	return &val, nil
   452  }
   453  
   454  func (v *Backend6Value) String() string {
   455  	return fmt.Sprintf("%s://[%s]:%d", v.Proto, v.Address, v.Port)
   456  }
   457  
   458  func (v *Backend6Value) GetValuePtr() unsafe.Pointer { return unsafe.Pointer(v) }
   459  
   460  func (b *Backend6Value) GetAddress() net.IP { return b.Address.IP() }
   461  func (b *Backend6Value) GetPort() uint16    { return b.Port }
   462  
   463  func (b *Backend6Value) BackendAddrID() BackendAddrID {
   464  	return BackendAddrID(fmt.Sprintf("[%s]:%d", b.Address, b.Port))
   465  }
   466  
   467  func (v *Backend6Value) ToNetwork() BackendValue {
   468  	n := *v
   469  	n.Port = byteorder.HostToNetwork(n.Port).(uint16)
   470  	return &n
   471  }
   472  
   473  type Backend6 struct {
   474  	Key   *Backend6Key
   475  	Value *Backend6Value
   476  }
   477  
   478  func NewBackend6(id loadbalancer.BackendID, ip net.IP, port uint16, proto u8proto.U8proto) (*Backend6, error) {
   479  	val, err := NewBackend6Value(ip, port, proto)
   480  	if err != nil {
   481  		return nil, err
   482  	}
   483  
   484  	return &Backend6{
   485  		Key:   NewBackend6Key(id),
   486  		Value: val,
   487  	}, nil
   488  }
   489  
   490  func (b *Backend6) IsIPv6() bool                  { return true }
   491  func (b *Backend6) Map() *bpf.Map                 { return Backend6Map }
   492  func (b *Backend6) GetID() loadbalancer.BackendID { return b.Key.GetID() }
   493  func (b *Backend6) GetKey() BackendKey            { return b.Key }
   494  func (b *Backend6) GetValue() BackendValue        { return b.Value }