routetable

package
v0.0.0-...-d216c5d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2024 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// Use this for targets with no outbound interface.
	InterfaceNone = "*NoOIF*"
)

Variables

View Source
var (
	ConnectFailed   = errors.New("connect to netlink failed")
	ListFailed      = errors.New("netlink list operation failed")
	UpdateFailed    = errors.New("netlink update operation failed")
	IfaceNotPresent = errors.New("interface not present")
	IfaceDown       = errors.New("interface down")
)

Functions

This section is empty.

Types

type ClassView

type ClassView struct {
	// contains filtered or unexported fields
}

ClassView wraps a RouteTable with a simplified API that removes the need to pass the RouteClass to each method.

func NewClassView

func NewClassView(class RouteClass, routeTable Interface) *ClassView

func (*ClassView) Apply

func (cv *ClassView) Apply() error

func (*ClassView) Index

func (cv *ClassView) Index() int

func (*ClassView) OnIfaceStateChanged

func (cv *ClassView) OnIfaceStateChanged(name string, ifIndex int, state ifacemonitor.State)

func (*ClassView) QueueResync

func (cv *ClassView) QueueResync()

func (*ClassView) QueueResyncIface

func (cv *ClassView) QueueResyncIface(ifaceName string)

func (*ClassView) ReadRoutesFromKernel

func (cv *ClassView) ReadRoutesFromKernel(ifaceName string) ([]Target, error)

func (*ClassView) RouteRemove

func (cv *ClassView) RouteRemove(ifaceName string, cidr ip.CIDR)

func (*ClassView) RouteUpdate

func (cv *ClassView) RouteUpdate(ifaceName string, target Target)

func (*ClassView) SetRoutes

func (cv *ClassView) SetRoutes(ifaceName string, targets []Target)

type ConntrackCleanupManager

type ConntrackCleanupManager struct {
	// contains filtered or unexported fields
}

ConntrackCleanupManager handles cleaning up conntrack entries on behalf of a RouteTable when routes are moved or deleted . It:

  • Uses a DeltaTracker to track which interfaces the RouteTable has told us own which IP addresses. We assume that the RouteTable only allows one route per CIDR (even though it understands how to clean up routes for other ToS and priority values).

  • Expects a callback from the RouteTable when a route is deleted.

  • Uses the interface index and route class on that callback to decide if the route being deleted needs a conntrack cleanup.

  • Provides a lookup function to check if an updated route needs a cleanup.

  • Updates that don't change the interface index don't need cleanup.

  • Updates from remote to remote don't need cleanup. For example, a route moving from VXLAN to VXLAN-same-subnet.

  • Updates where there was no previous route don't need cleanup.

A complicating factor is that the kernel keys routes using CIDR, ToS and priority whereas conntrack entries are keyed on 5-tuple only. We sidestep that by assuming the RouteTable only allows one route per CIDR in its final state. [Shaun] I tried to handle multiple routes per CIDR, but the complexity spiralled, and it wasn't clear what should be done in a lot of the corner cases. I'm hoping that, should we add function that uses multiple ToSes or priorities, the right way to handle conflicts will be clear at that time!

func NewConntrackCleanupManager

func NewConntrackCleanupManager(ipVersion uint8, conntrack conntrackIface) *ConntrackCleanupManager

func (*ConntrackCleanupManager) CIDRNeedsEarlyCleanup

func (c *ConntrackCleanupManager) CIDRNeedsEarlyCleanup(cidr ip.CIDR, oldIface int) bool

CIDRNeedsEarlyCleanup is called by the RouteTable to check if a route should be deleted early, to allow for conntrack cleanup to be properly sequenced.

func (*ConntrackCleanupManager) OnDataplaneRouteDeleted

func (c *ConntrackCleanupManager) OnDataplaneRouteDeleted(cidr ip.CIDR, ifindex int)

OnDataplaneRouteDeleted is called when the RouteTable tells us that a route has been removed from the dataplane on the given interface. In most cases, this will queue the CIDR for conntrack cleanup at the next call to StartConntrackCleanupAndReset.

No cleanup is triggered if there is a desired route for the given CIDR and that desired route is staying on this interface.

func (*ConntrackCleanupManager) RemoveCIDROwner

func (c *ConntrackCleanupManager) RemoveCIDROwner(cidr ip.CIDR)

RemoveCIDROwner is called when there is no longer an owner for the given CIDR. Like UpdateCIDROwner, it updates the "desired" next state so a call to UpdateCIDROwner for the same CIDR before the cleanup is triggered will undo the removal.

func (*ConntrackCleanupManager) StartConntrackCleanupAndReset

func (c *ConntrackCleanupManager) StartConntrackCleanupAndReset()

StartConntrackCleanupAndReset starts all pending conntrack cleanups and resets the tracker to prepare for the next round of updates.

func (*ConntrackCleanupManager) UpdateCIDROwner

func (c *ConntrackCleanupManager) UpdateCIDROwner(cidr ip.CIDR, ifaceIdx int, routeClass RouteClass)

UpdateCIDROwner is called when the new owner of a CIDR is calculated. It updates the "desired" next state, so multiple calls for the same CIDR are effectively coalesced; only the most recent update is remembered. the actual cleanup is triggered later by calls to OnDataplaneRouteDeleted and StartConntrackCleanupAndReset.

func (*ConntrackCleanupManager) WaitForPendingDeletion

func (c *ConntrackCleanupManager) WaitForPendingDeletion(cidr ip.CIDR)

WaitForPendingDeletion waits for any pending conntrack deletions (if any) for the given IP to complete. Returns immediately if there's no pending deletion.

type DummyTable

type DummyTable struct {
}

func (*DummyTable) Apply

func (_ *DummyTable) Apply() error

func (*DummyTable) Index

func (_ *DummyTable) Index() int

func (*DummyTable) OnIfaceStateChanged

func (_ *DummyTable) OnIfaceStateChanged(_ string, _ int, _ ifacemonitor.State)

func (*DummyTable) QueueResync

func (_ *DummyTable) QueueResync()

func (*DummyTable) QueueResyncIface

func (_ *DummyTable) QueueResyncIface(string)

func (*DummyTable) ReadRoutesFromKernel

func (_ *DummyTable) ReadRoutesFromKernel(ifaceName string) ([]Target, error)

func (*DummyTable) RouteRemove

func (_ *DummyTable) RouteRemove(routeClass RouteClass, ifaceName string, cidr ip.CIDR)

func (*DummyTable) RouteUpdate

func (_ *DummyTable) RouteUpdate(routeClass RouteClass, ifaceName string, target Target)

func (*DummyTable) SetRemoveExternalRoutes

func (_ *DummyTable) SetRemoveExternalRoutes(b bool)

func (*DummyTable) SetRoutes

func (_ *DummyTable) SetRoutes(routeClass RouteClass, ifaceName string, targets []Target)

type Interface

type Interface interface {
	SyncerInterface
	SetRoutes(routeClass RouteClass, ifaceName string, targets []Target)
	RouteRemove(routeClass RouteClass, ifaceName string, cidr ip.CIDR)
	RouteUpdate(routeClass RouteClass, ifaceName string, target Target)
	Index() int
	QueueResyncIface(ifaceName string)
	ReadRoutesFromKernel(ifaceName string) ([]Target, error)
}

Interface is the interface provided by the standard routetable module used to program the RIB.

type NextHop

type NextHop struct {
	Gw        ip.Addr
	IfaceName string
}

type NoOpRouteTracker

type NoOpRouteTracker struct {
}

NoOpRouteTracker is a dummy implementation of RouteOwnershipTracker that does nothing.

func NewNoOpRouteTracker

func NewNoOpRouteTracker() NoOpRouteTracker

func (NoOpRouteTracker) CIDRNeedsEarlyCleanup

func (n NoOpRouteTracker) CIDRNeedsEarlyCleanup(cidr ip.CIDR, ifindex int) bool

func (NoOpRouteTracker) OnDataplaneRouteDeleted

func (n NoOpRouteTracker) OnDataplaneRouteDeleted(cidr ip.CIDR, ifindex int)

func (NoOpRouteTracker) RemoveCIDROwner

func (n NoOpRouteTracker) RemoveCIDROwner(addr ip.CIDR)

func (NoOpRouteTracker) StartConntrackCleanupAndReset

func (n NoOpRouteTracker) StartConntrackCleanupAndReset()

func (NoOpRouteTracker) UpdateCIDROwner

func (n NoOpRouteTracker) UpdateCIDROwner(addr ip.CIDR, ifaceIdx int, routeClass RouteClass)

func (NoOpRouteTracker) WaitForPendingDeletion

func (n NoOpRouteTracker) WaitForPendingDeletion(cidr ip.CIDR)

type Opt

type Opt func(table *RouteTable)

func WithConntrackCleanup

func WithConntrackCleanup(enabled bool) Opt

func WithConntrackShim

func WithConntrackShim(shim conntrackIface) Opt

func WithLivenessCB

func WithLivenessCB(cb func()) Opt

func WithNetlinkHandleShim

func WithNetlinkHandleShim(newNetlinkHandle func() (netlinkshim.Interface, error)) Opt

func WithRouteCleanupGracePeriod

func WithRouteCleanupGracePeriod(routeCleanupGracePeriod time.Duration) Opt

func WithStaticARPEntries

func WithStaticARPEntries(b bool) Opt

func WithTimeShim

func WithTimeShim(shim timeshim.Interface) Opt

type OwnershipPolicy

type OwnershipPolicy interface {
	RouteIsOurs(ifaceName string, route *netlink.Route) bool

	IfaceIsOurs(ifaceName string) bool
	IfaceShouldHaveARPEntries(ifaceName string) bool
	IfaceShouldHaveGracePeriod(ifaceName string) bool
}

OwnershipPolicy is used to determine whether a given interface or route belongs to Calico. Routes that are loaded from the kernel are checked against this policy to determine if they should be tracked. The RouteTable cleans up tracked routes that don't match the current datastore state.

The policy is also used to determine whether an interface should be tracked or not. If an interface is not tracked then the RouteTable will not be able to program routes for it, and it will not respond to interface state updates. This is mainly a performance optimisation for our non-main routing tables which tend to be used to manage routes for a single device.

type RouteClass

type RouteClass int

RouteClass is a type used to identify the different groups of routes that we program. It is used as a tie-breaker when there are conflicting routes for the same CIDR (lowest numeric value wins).

const (
	RouteClassLocalWorkload RouteClass = iota
	RouteClassBPFSpecial
	RouteClassWireguard
	RouteClassVXLANSameSubnet
	RouteClassVXLANTunnel
	RouteClassIPAMBlockDrop

	RouteClassMax
)

func (RouteClass) IsRemote

func (c RouteClass) IsRemote() bool

func (RouteClass) String

func (i RouteClass) String() string

type RouteOwnershipTracker

type RouteOwnershipTracker interface {
	UpdateCIDROwner(addr ip.CIDR, ifaceIdx int, routeClass RouteClass)
	RemoveCIDROwner(addr ip.CIDR)

	CIDRNeedsEarlyCleanup(cidr ip.CIDR, oldIface int) bool
	OnDataplaneRouteDeleted(cidr ip.CIDR, ifindex int)
	StartConntrackCleanupAndReset()

	WaitForPendingDeletion(cidr ip.CIDR)
}

type RouteTable

type RouteTable struct {
	// contains filtered or unexported fields
}

RouteTable manages the Calico routes for a specific kernel routing table.

There are several complicating factors to managing the routes and all of these have caused real problems in the past:

  • There is more than one Felix subcomponent that needs to program routes, often into the same table. It is possible for different components to try to program conflicting routes for the same CIDR (for example, if a local and remote endpoint share the same IP address). To deal with this we assign a RouteClass to each potential source of routes and break ties on that value.

  • Most Calico components only deal with CIDRs and interfaces, but the kernel routing table is indexed by CIDR, metric and ToS field. To handle this difference in indexing, we use a DeltaTracker indexed in a way that matches the kernel's indexing. That allows us to correctly clean up any kernel routes that would alias if we only considered CIDR.

  • We need to translate interface name to interface index and that mapping can change over time. Interfaces can be renamed, keeping the same index. Interfaces can be recreated, keeping the same name but getting a new index. We handle this by indexing the routes we've been told to create on interface name and by listening for interface state changes. When an interface is updated, we re-calculate the routes that we want to program for it and re-do conflict resolution.

  • We can race with the interface monitor goroutine, being asked to program a route before we've heard about the interface, or spotting a new interface index when we do a read back of routes from the kernel.

  • The CNI plugin also programs the same routes that we do, so we can race with it as well. We may see an interface pop up with a route before we hear about the corresponding WorkloadEndpoint. To deal with that, we implement a grace period before deleting routes that belong to us but that we don't know about yet.

  • When IP addresses move from one interface to another (for example because a workload has been terminated and a new workload now has the IP) we need to clean up the conntrack entries from the old workload. We delegate this cleanup to the RouteOwnershipTracker; giving it callbacks when routes move. We do that cleanup in the background to avoid holding up other route programming.

func New

func New(
	ownershipPolicy OwnershipPolicy,
	ipVersion uint8,
	netlinkTimeout time.Duration,
	deviceRouteSourceAddress net.IP,
	defaultRouteProtocol netlink.RouteProtocol,
	removeExternalRoutes bool,
	tableIndex int,
	opReporter logutils.OpRecorder,
	featureDetector environment.FeatureDetectorIface,
	opts ...Opt,
) *RouteTable

func (*RouteTable) Apply

func (r *RouteTable) Apply() (err error)

func (*RouteTable) Index

func (r *RouteTable) Index() int

func (*RouteTable) OnIfaceStateChanged

func (r *RouteTable) OnIfaceStateChanged(ifaceName string, ifIndex int, state ifacemonitor.State)

func (*RouteTable) QueueResync

func (r *RouteTable) QueueResync()

func (*RouteTable) QueueResyncIface

func (r *RouteTable) QueueResyncIface(ifaceName string)

func (*RouteTable) ReadRoutesFromKernel

func (r *RouteTable) ReadRoutesFromKernel(ifaceName string) ([]Target, error)

ReadRoutesFromKernel offers partial support for reading back routes from the kernel. In particular, it assumes that "onlink" routes are VXLAN routes, which is lossy. Currently, this is only used in Enterprise, where the routes it needs to read are VXLAN routes.

func (*RouteTable) RouteRemove

func (r *RouteTable) RouteRemove(routeClass RouteClass, ifaceName string, cidr ip.CIDR)

RouteRemove removes the route with the specified CIDR. These deltas will be applied to any routes set using SetRoute.

func (*RouteTable) RouteUpdate

func (r *RouteTable) RouteUpdate(routeClass RouteClass, ifaceName string, target Target)

RouteUpdate updates the route keyed off the target CIDR. These deltas will be applied to any routes set using SetRoute.

func (*RouteTable) SetRemoveExternalRoutes

func (r *RouteTable) SetRemoveExternalRoutes(b bool)

func (*RouteTable) SetRoutes

func (r *RouteTable) SetRoutes(routeClass RouteClass, ifaceName string, targets []Target)

SetRoutes replaces the full set of targets for the specified interface.

type SyncerInterface

type SyncerInterface interface {
	OnIfaceStateChanged(name string, ifIndex int, state ifacemonitor.State)
	QueueResync()
	Apply() error
}

SyncerInterface is the interface used to manage data-sync of route table managers. This includes notification of interface state changes, hooks to queue a full resync and apply routing updates.

type Target

type Target struct {
	Type      TargetType
	CIDR      ip.CIDR
	GW        ip.Addr
	Src       ip.Addr
	DestMAC   net.HardwareAddr
	Protocol  netlink.RouteProtocol
	MultiPath []NextHop
}

func (Target) Equal

func (t Target) Equal(t2 Target) bool

func (Target) Flags

func (t Target) Flags() netlink.NextHopFlag

func (Target) RouteScope

func (t Target) RouteScope() netlink.Scope

func (Target) RouteType

func (t Target) RouteType() int

type TargetType

type TargetType string
const (
	TargetTypeLocal            TargetType = "local"
	TargetTypeVXLAN            TargetType = "vxlan"
	TargetTypeNoEncap          TargetType = "noencap"
	TargetTypeOnLink           TargetType = "onlink"
	TargetTypeGlobalUnicast    TargetType = "global-unicast"
	TargetTypeLinkLocalUnicast TargetType = "local-unicast"

	TargetTypeBlackhole   TargetType = "blackhole"
	TargetTypeProhibit    TargetType = "prohibit"
	TargetTypeThrow       TargetType = "throw"
	TargetTypeUnreachable TargetType = "unreachable"
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL