github.com/cilium/cilium@v1.16.2/pkg/bgpv1/types/utils.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package types
     5  
     6  import (
     7  	"net/netip"
     8  	"slices"
     9  
    10  	"github.com/osrg/gobgp/v3/pkg/packet/bgp"
    11  
    12  	ipamOption "github.com/cilium/cilium/pkg/ipam/option"
    13  )
    14  
    15  // CanAdvertisePodCIDR returns true if the provided IPAM mode is supported for
    16  // advertising PodCIDR
    17  func CanAdvertisePodCIDR(ipam string) bool {
    18  	supportedIPAMs := []string{
    19  		ipamOption.IPAMKubernetes,
    20  		ipamOption.IPAMClusterPool,
    21  	}
    22  	return slices.Contains(supportedIPAMs, ipam)
    23  }
    24  
    25  // NewPathForPrefix returns a Path that can be used to advertise the provided
    26  // IP prefix by the underlying BGP implementation.
    27  //
    28  // The prefix can be either IPv4 or IPv6 and this function will handle the differences
    29  // between MP BGP and BGP.
    30  //
    31  // The next hop of the path will always be set to "0.0.0.0" for IPv4 and "::" for IPv6,
    32  // so the underlying BGP implementation selects appropriate actual nexthop address when advertising it.
    33  func NewPathForPrefix(prefix netip.Prefix) (path *Path) {
    34  	originAttr := bgp.NewPathAttributeOrigin(0)
    35  
    36  	// Currently, we only support advertising locally originated paths (the paths generated in Cilium
    37  	// node itself, not the paths received from another BGP Peer or redistributed from another routing
    38  	// protocol. In this case, the nexthop address should be the address used for peering. That means
    39  	// the nexthop address can be changed depending on the neighbor.
    40  	//
    41  	// For example, when the Cilium node is connected to two subnets 10.0.0.0/24 and 10.0.1.0/24 with
    42  	// local address 10.0.0.1 and 10.0.1.1 respectively, the nexthop should be advertised for 10.0.0.0/24
    43  	// peers is 10.0.0.1. On the other hand, we should advertise 10.0.1.1 as a nexthop for 10.0.1.0/24.
    44  	//
    45  	// Fortunately, GoBGP takes care of resolving appropriate nexthop address for each peers when we
    46  	// specify an zero IP address (0.0.0.0 for IPv4 and :: for IPv6). So, we can just rely on that.
    47  	//
    48  	// References:
    49  	// - RFC4271 Section 5.1.3 (NEXT_HOP)
    50  	// - RFC4760 Section 3 (Multiprotocol Reachable NLRI - MP_REACH_NLRI (Type Code 14))
    51  
    52  	switch {
    53  	case prefix.Addr().Is4():
    54  		nlri := bgp.NewIPAddrPrefix(uint8(prefix.Bits()), prefix.Addr().String())
    55  		nextHopAttr := bgp.NewPathAttributeNextHop("0.0.0.0")
    56  		path = &Path{
    57  			NLRI: nlri,
    58  			PathAttributes: []bgp.PathAttributeInterface{
    59  				originAttr,
    60  				nextHopAttr,
    61  			},
    62  		}
    63  	case prefix.Addr().Is6():
    64  		nlri := bgp.NewIPv6AddrPrefix(uint8(prefix.Bits()), prefix.Addr().String())
    65  		mpReachNLRIAttr := bgp.NewPathAttributeMpReachNLRI("::", []bgp.AddrPrefixInterface{nlri})
    66  		path = &Path{
    67  			NLRI: nlri,
    68  			PathAttributes: []bgp.PathAttributeInterface{
    69  				originAttr,
    70  				mpReachNLRIAttr,
    71  			},
    72  		}
    73  	}
    74  
    75  	return
    76  }
    77  
    78  // DeepEqual is a manually created deepequal function, deeply comparing the receiver with another.
    79  // It compares fields with types that do not implement the `DeepEqual` method
    80  // and calls the generated private `deepEqual` method which compares the rest of the fields.
    81  func (m *RoutePolicyPrefixMatch) DeepEqual(other *RoutePolicyPrefixMatch) bool {
    82  	// Compare netip.Prefix field (does not implement the `DeepEqual` method)
    83  	if m.CIDR != other.CIDR {
    84  		return false
    85  	}
    86  	// Call generated `deepEqual` method which compares all fields except 'CIDR'
    87  	return m.deepEqual(other)
    88  }
    89  
    90  type PolicyPrefixMatchList []*RoutePolicyPrefixMatch
    91  
    92  // Less is a comparator of two RoutePolicyPrefixMatch rules to be used for sorting purposes
    93  func (l PolicyPrefixMatchList) Less(i, j int) bool {
    94  	return l[i].CIDR.Bits() < l[j].CIDR.Bits() || l[i].CIDR.Addr().Less(l[j].CIDR.Addr()) ||
    95  		l[i].PrefixLenMin < l[j].PrefixLenMin || l[i].PrefixLenMax < l[j].PrefixLenMax
    96  }