calc

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: 37 Imported by: 0

Documentation

Overview

The calc package implements a calculation graph for Felix's dynamic state. The graph filters and transforms updates from the backend Syncer into a stream of host-specific updates to policies, profiles, endpoints and IP sets.

The graph is available either with a synchronous callback API or as a channel-based async API. The async version of the API is recommended because it includes and EventBuffer to efficiently batch IP set updates. In addition, it converts the callbacks into structs from the felix/proto package, which are ready to be marshaled directly to the felix front-end.

// Using the async API.
asyncCalcGraph := calc.NewAsyncCalcGraph("hostname", outputChannel, nil)
syncer := fc.datastore.Syncer(asyncCalcGraph)
syncer.Start()
asyncCalcGraph.Start()
for event := range outputChannel {
	switch event := event.(type) {
	case *proto.XYZ:
		...
	...
}

The best explanation of the wiring of the calculation graph nodes is in the code comments inside NewCalculationGraph.

Index

Constants

View Source
const (
	// Compromise: shorter is better for occupancy and readability. Longer is better for
	// collision-resistance.  16 chars gives us 96 bits of entropy, which is fairly collision
	// resistant.
	RuleIDLength = 16
)

Variables

View Source
var AllSelector selector.Selector

AllSelector is a pre-calculated copy of the "all()" selector.

View Source
var (
	DummyDropRules = model.ProfileRules{
		InboundRules:  []model.Rule{{Action: "deny"}},
		OutboundRules: []model.Rule{{Action: "deny"}},
	}
)

Functions

func ModelHostEndpointToProto

func ModelHostEndpointToProto(ep *model.HostEndpoint, tiers, untrackedTiers, preDNATTiers []*proto.TierInfo, forwardTiers []*proto.TierInfo) *proto.HostEndpoint

func ModelWorkloadEndpointToProto

func ModelWorkloadEndpointToProto(ep *model.WorkloadEndpoint, tiers []*proto.TierInfo) *proto.WorkloadEndpoint

func ParsedRulesToActivePolicyUpdate

func ParsedRulesToActivePolicyUpdate(key model.PolicyKey, rules *ParsedRules) *proto.ActivePolicyUpdate

func PolKVLess

func PolKVLess(i, j PolKV) bool

func TierLess

func TierLess(i, j tierInfoKey) bool

Types

type ActiveRulesCalculator

type ActiveRulesCalculator struct {

	// Callback objects.
	RuleScanner           ruleScanner
	PolicyMatchListener   PolicyMatchListener
	OnPolicyCountsChanged func(numTiers, numPolicies, numProfiles, numALPPolicies int)
	OnAlive               func()
	// contains filtered or unexported fields
}

ActiveRulesCalculator calculates the set of policies and profiles (i.e. the rules) that are active for the particular endpoints that it's been told about. It emits events when the set of active rules changes.

For example, if the ActiveRulesCalculator is fed *all* the policies/profiles along with the endpoints that are on the local host then its output (via the callback objects) will indicate exactly which policies/profiles are active on the local host.

When looking at policies, the ActiveRules calculator is only interested in the selector attached to the policy itself (which determines the set of endpoints that it applies to). The rules in a policy may also contain selectors; those are ignored here; they are mapped to IP sets by the RuleScanner.

func NewActiveRulesCalculator

func NewActiveRulesCalculator() *ActiveRulesCalculator

func (*ActiveRulesCalculator) OnStatusUpdate

func (arc *ActiveRulesCalculator) OnStatusUpdate(status api.SyncStatus)

func (*ActiveRulesCalculator) OnUpdate

func (arc *ActiveRulesCalculator) OnUpdate(update api.Update) (_ bool)

func (*ActiveRulesCalculator) RegisterWith

func (arc *ActiveRulesCalculator) RegisterWith(localEndpointDispatcher, allUpdDispatcher *dispatcher.Dispatcher)

type AsyncCalcGraph

type AsyncCalcGraph struct {
	CalcGraph *CalcGraph
	// contains filtered or unexported fields
}

func NewAsyncCalcGraph

func NewAsyncCalcGraph(
	conf *config.Config,
	outputChannels []chan<- interface{},
	healthAggregator *health.HealthAggregator,
) *AsyncCalcGraph

func (*AsyncCalcGraph) OnStatusUpdated

func (acg *AsyncCalcGraph) OnStatusUpdated(status api.SyncStatus)

func (*AsyncCalcGraph) OnUpdates

func (acg *AsyncCalcGraph) OnUpdates(updates []api.Update)

func (*AsyncCalcGraph) Start

func (acg *AsyncCalcGraph) Start()

type Block

type Block struct {
	NodeName string // Set for each route that comes from an IPAM block.
}

type CalcGraph

type CalcGraph struct {
	// AllUpdDispatcher is the input node to the calculation graph.
	AllUpdDispatcher *dispatcher.Dispatcher
	// contains filtered or unexported fields
}

func NewCalculationGraph

func NewCalculationGraph(callbacks PipelineCallbacks, conf *config.Config, liveCallback func()) *CalcGraph

func (*CalcGraph) Flush

func (g *CalcGraph) Flush()

func (*CalcGraph) OnStatusUpdated

func (g *CalcGraph) OnStatusUpdated(update api.SyncStatus)

func (*CalcGraph) OnUpdates

func (g *CalcGraph) OnUpdates(updates []api.Update)

type ConfigBatcher

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

func NewConfigBatcher

func NewConfigBatcher(hostname string, callbacks configCallbacks) *ConfigBatcher

func (*ConfigBatcher) OnDatamodelStatus

func (cb *ConfigBatcher) OnDatamodelStatus(status api.SyncStatus)

func (*ConfigBatcher) OnUpdate

func (cb *ConfigBatcher) OnUpdate(update api.Update) (filterOut bool)

func (*ConfigBatcher) RegisterWith

func (cb *ConfigBatcher) RegisterWith(allUpdDispatcher *dispatcher.Dispatcher)

type DataplanePassthru

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

DataplanePassthru passes through some datamodel updates to the dataplane layer, removing some duplicates along the way. It maps OnUpdate() calls to dedicated method calls for consistency with the rest of the dataplane API.

func NewDataplanePassthru

func NewDataplanePassthru(callbacks passthruCallbacks, ipv6Support bool) *DataplanePassthru

func (*DataplanePassthru) OnUpdate

func (h *DataplanePassthru) OnUpdate(update api.Update) (filterOut bool)

func (*DataplanePassthru) RegisterWith

func (h *DataplanePassthru) RegisterWith(dispatcher *dispatcher.Dispatcher)

type DatastoreNotReady

type DatastoreNotReady struct{}

type EncapsulationCalculator

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

EncapsulationCalculator is a helper struct to aid in calculating if IPIP and/or VXLAN encapsulation should be enabled based on the existing IP Pools and their configuration. It is used by EncapsulationResolver in this file, where it watches for encapsulation changes to restart Felix, and by Run() in daemon.go, where it calculates the encapsulation state that will be effectively used by Felix.

func NewEncapsulationCalculator

func NewEncapsulationCalculator(config *config.Config, ippoolKVPList *model.KVPairList) *EncapsulationCalculator

func (*EncapsulationCalculator) IPIPEnabled

func (c *EncapsulationCalculator) IPIPEnabled() bool

func (*EncapsulationCalculator) VXLANEnabled

func (c *EncapsulationCalculator) VXLANEnabled() bool

func (*EncapsulationCalculator) VXLANEnabledV6

func (c *EncapsulationCalculator) VXLANEnabledV6() bool

type EncapsulationResolver

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

EncapsulationResolver is a Calculation Graph component that watches IP pool updates and calculates if the IPIP or VXLAN encaps should be enabled or disabled. The new Encapsulation is sent to the dataplane, which restarts Felix if it changed.

func NewEncapsulationResolver

func NewEncapsulationResolver(config *config.Config, callbacks encapCallbacks) *EncapsulationResolver

func (*EncapsulationResolver) OnPoolUpdate

func (r *EncapsulationResolver) OnPoolUpdate(update api.Update) (filterOut bool)

func (*EncapsulationResolver) OnStatusUpdate

func (r *EncapsulationResolver) OnStatusUpdate(status api.SyncStatus)

func (*EncapsulationResolver) RegisterWith

func (r *EncapsulationResolver) RegisterWith(dispatcher *dispatcher.Dispatcher)

type EndpointKeyToProfileIDMap

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

EndpointKeyToProfileIDMap is a specialised map that calculates the deltas to the profile IDs when making an update.

func NewEndpointKeyToProfileIDMap

func NewEndpointKeyToProfileIDMap() *EndpointKeyToProfileIDMap

func (EndpointKeyToProfileIDMap) Update

func (idx EndpointKeyToProfileIDMap) Update(
	key model.Key,
	profileIDs []string,
) (
	removedIDs, addedIDs map[string]bool,
)

type EventHandler

type EventHandler func(message interface{})

type EventSequencer

type EventSequencer struct {
	Callback EventHandler
	// contains filtered or unexported fields
}

EventSequencer buffers and coalesces updates from the calculation graph then flushes them when Flush() is called. It flushed updates in a dependency-safe order.

func NewEventSequencer

func NewEventSequencer(conf configInterface) *EventSequencer

func (*EventSequencer) Flush

func (buf *EventSequencer) Flush()

func (*EventSequencer) OnConfigUpdate

func (buf *EventSequencer) OnConfigUpdate(globalConfig, hostConfig map[string]string)

func (*EventSequencer) OnDatastoreNotReady

func (buf *EventSequencer) OnDatastoreNotReady()

func (*EventSequencer) OnEncapUpdate

func (buf *EventSequencer) OnEncapUpdate(encap config.Encapsulation)

func (*EventSequencer) OnEndpointTierUpdate

func (buf *EventSequencer) OnEndpointTierUpdate(key model.Key,
	endpoint interface{},
	filteredTiers []TierInfo,
)

func (*EventSequencer) OnGlobalBGPConfigUpdate

func (buf *EventSequencer) OnGlobalBGPConfigUpdate(cfg *v3.BGPConfiguration)

func (*EventSequencer) OnHostIPRemove

func (buf *EventSequencer) OnHostIPRemove(hostname string)

func (*EventSequencer) OnHostIPUpdate

func (buf *EventSequencer) OnHostIPUpdate(hostname string, ip *net.IP)

func (*EventSequencer) OnHostIPv6Remove

func (buf *EventSequencer) OnHostIPv6Remove(hostname string)

func (*EventSequencer) OnHostIPv6Update

func (buf *EventSequencer) OnHostIPv6Update(hostname string, ip *net.IP)

func (*EventSequencer) OnHostMetadataRemove

func (buf *EventSequencer) OnHostMetadataRemove(hostname string)

func (*EventSequencer) OnHostMetadataUpdate

func (buf *EventSequencer) OnHostMetadataUpdate(hostname string, ip4 *net.IPNet, ip6 *net.IPNet, asnumber string, labels map[string]string)

func (*EventSequencer) OnIPPoolRemove

func (buf *EventSequencer) OnIPPoolRemove(key model.IPPoolKey)

func (*EventSequencer) OnIPPoolUpdate

func (buf *EventSequencer) OnIPPoolUpdate(key model.IPPoolKey, pool *model.IPPool)

func (*EventSequencer) OnIPSetAdded

func (buf *EventSequencer) OnIPSetAdded(setID string, ipSetType proto.IPSetUpdate_IPSetType)

func (*EventSequencer) OnIPSetMemberAdded

func (buf *EventSequencer) OnIPSetMemberAdded(setID string, member labelindex.IPSetMember)

func (*EventSequencer) OnIPSetMemberRemoved

func (buf *EventSequencer) OnIPSetMemberRemoved(setID string, member labelindex.IPSetMember)

func (*EventSequencer) OnIPSetRemoved

func (buf *EventSequencer) OnIPSetRemoved(setID string)

func (*EventSequencer) OnNamespaceRemove

func (buf *EventSequencer) OnNamespaceRemove(id proto.NamespaceID)

func (*EventSequencer) OnNamespaceUpdate

func (buf *EventSequencer) OnNamespaceUpdate(update *proto.NamespaceUpdate)

func (*EventSequencer) OnPolicyActive

func (buf *EventSequencer) OnPolicyActive(key model.PolicyKey, rules *ParsedRules)

func (*EventSequencer) OnPolicyInactive

func (buf *EventSequencer) OnPolicyInactive(key model.PolicyKey)

func (*EventSequencer) OnProfileActive

func (buf *EventSequencer) OnProfileActive(key model.ProfileRulesKey, rules *ParsedRules)

func (*EventSequencer) OnProfileInactive

func (buf *EventSequencer) OnProfileInactive(key model.ProfileRulesKey)

func (*EventSequencer) OnRouteRemove

func (buf *EventSequencer) OnRouteRemove(dst string)

func (*EventSequencer) OnRouteUpdate

func (buf *EventSequencer) OnRouteUpdate(update *proto.RouteUpdate)

func (*EventSequencer) OnServiceAccountRemove

func (buf *EventSequencer) OnServiceAccountRemove(id proto.ServiceAccountID)

func (*EventSequencer) OnServiceAccountUpdate

func (buf *EventSequencer) OnServiceAccountUpdate(update *proto.ServiceAccountUpdate)

func (*EventSequencer) OnServiceRemove

func (buf *EventSequencer) OnServiceRemove(update *proto.ServiceRemove)

func (*EventSequencer) OnServiceUpdate

func (buf *EventSequencer) OnServiceUpdate(update *proto.ServiceUpdate)

func (*EventSequencer) OnVTEPRemove

func (buf *EventSequencer) OnVTEPRemove(dst string)

func (*EventSequencer) OnVTEPUpdate

func (buf *EventSequencer) OnVTEPUpdate(update *proto.VXLANTunnelEndpointUpdate)

func (*EventSequencer) OnWireguardRemove

func (buf *EventSequencer) OnWireguardRemove(nodename string)

func (*EventSequencer) OnWireguardUpdate

func (buf *EventSequencer) OnWireguardUpdate(nodename string, wg *model.Wireguard)

type FelixSender

type FelixSender interface {
	SendUpdateToFelix(update model.KVPair)
}

type IPSetData

type IPSetData struct {
	// The selector and named port that this IP set represents.  To represent an unfiltered named
	// port, set selector to AllSelector.  If NamedPortProtocol == ProtocolNone then
	// this IP set represents a selector only, with no named port component.
	Selector selector.Selector

	// NamedPortProtocol identifies the protocol (TCP or UDP) for a named port IP set.  It is
	// set to ProtocolNone for a selector-only IP set.
	NamedPortProtocol labelindex.IPSetPortProtocol
	// NamedPort contains the name of the named port represented by this IP set or "" for a
	// selector-only IP set
	NamedPort string
	// The service that this IP set represents, in namespace/name format.
	Service string
	// Type of the ip set to represent for this service. This allows us to create service
	// IP sets with and without port information.
	ServiceIncludePorts bool
	// contains filtered or unexported fields
}

func (*IPSetData) DataplaneProtocolType

func (d *IPSetData) DataplaneProtocolType() proto.IPSetUpdate_IPSetType

DataplaneProtocolType returns the dataplane driver protocol type of this IP set. One of the proto.IPSetUpdate_IPSetType constants.

func (*IPSetData) String

func (d *IPSetData) String() string

func (*IPSetData) UniqueID

func (d *IPSetData) UniqueID() string

type L3RouteResolver

type L3RouteResolver struct {
	OnAlive func()
	// contains filtered or unexported fields
}

L3RouteResolver is responsible for indexing (currently only IPv4 versions of):

- IPAM blocks - IP pools - Node metadata (either from the Node resource, if available, or from HostIP)

and emitting a set of longest prefix match routes that include:

- The relevant destination CIDR. - The IP pool type that contains the CIDR (or none). - Other metadata about the containing IP pool. - Whether this (/32) CIDR is a host or not. - For workload CIDRs, the IP and name of the host that contains the workload.

The BPF dataplane use the above to form a map of IP space so it can look up whether a particular IP belongs to a workload/host/IP pool etc. and where to forward that IP to if it needs to. The VXLAN dataplane combines routes for remote workloads with VTEPs from the VXLANResolver to form VXLAN routes.

func NewL3RouteResolver

func NewL3RouteResolver(hostname string, callbacks PipelineCallbacks, useNodeResourceUpdates bool, routeSource string) *L3RouteResolver

func (*L3RouteResolver) OnBlockUpdate

func (c *L3RouteResolver) OnBlockUpdate(update api.Update) (_ bool)

func (*L3RouteResolver) OnHostIPUpdate

func (c *L3RouteResolver) OnHostIPUpdate(update api.Update) (_ bool)

OnHostIPUpdate gets called whenever a node IP address changes.

func (*L3RouteResolver) OnPoolUpdate

func (c *L3RouteResolver) OnPoolUpdate(update api.Update) (_ bool)

OnPoolUpdate gets called whenever an IP pool changes.

func (*L3RouteResolver) OnResourceUpdate

func (c *L3RouteResolver) OnResourceUpdate(update api.Update) (_ bool)

func (*L3RouteResolver) OnWorkloadUpdate

func (c *L3RouteResolver) OnWorkloadUpdate(update api.Update) (_ bool)

func (*L3RouteResolver) RegisterWith

func (c *L3RouteResolver) RegisterWith(allUpdDispatcher, localDispatcher *dispatcher.Dispatcher)

type ParsedRule

type ParsedRule struct {
	Action string

	IPVersion *int

	Protocol *numorstring.Protocol

	SrcNets              []*net.IPNet
	SrcPorts             []numorstring.Port
	SrcNamedPortIPSetIDs []string
	DstNets              []*net.IPNet
	DstPorts             []numorstring.Port
	DstNamedPortIPSetIDs []string
	ICMPType             *int
	ICMPCode             *int
	SrcIPSetIDs          []string
	DstIPSetIDs          []string
	DstIPPortSetIDs      []string

	NotProtocol             *numorstring.Protocol
	NotSrcNets              []*net.IPNet
	NotSrcPorts             []numorstring.Port
	NotSrcNamedPortIPSetIDs []string
	NotDstNets              []*net.IPNet
	NotDstPorts             []numorstring.Port
	NotDstNamedPortIPSetIDs []string
	NotICMPType             *int
	NotICMPCode             *int
	NotSrcIPSetIDs          []string
	NotDstIPSetIDs          []string

	// These fields allow us to pass through the raw match criteria from the V3 datamodel,
	// unmodified. The selectors above are formed in the update processor layer by combining the
	// original selectors, namespace selectors an service account matches into one.
	OriginalSrcSelector               string
	OriginalSrcNamespaceSelector      string
	OriginalDstSelector               string
	OriginalDstNamespaceSelector      string
	OriginalNotSrcSelector            string
	OriginalNotDstSelector            string
	OriginalSrcServiceAccountNames    []string
	OriginalSrcServiceAccountSelector string
	OriginalDstServiceAccountNames    []string
	OriginalDstServiceAccountSelector string
	OriginalSrcService                string
	OriginalSrcServiceNamespace       string
	OriginalDstService                string
	OriginalDstServiceNamespace       string

	// These fields allow us to pass through the HTTP match criteria from the V3 datamodel. The iptables dataplane
	// does not implement the match, but other dataplanes such as Dikastes do.
	HTTPMatch *model.HTTPMatch

	Metadata *model.RuleMetadata
}

ParsedRule is like a backend.model.Rule, except the selector matches and named ports are replaced with pre-calculated ipset IDs.

type ParsedRules

type ParsedRules struct {
	// For NetworkPolicies, Namespace is set to the original namespace of the NetworkPolicy.
	// For GlobalNetworkPolicies and Profiles, "".
	Namespace string

	InboundRules  []*ParsedRule
	OutboundRules []*ParsedRule

	// Untracked is true if these rules should not be "conntracked".
	Untracked bool

	// PreDNAT is true if these rules should be applied before any DNAT.
	PreDNAT bool

	OriginalSelector string
}

ParsedRules holds our intermediate representation of either a policy's rules or a profile's rules. As part of its processing, the RuleScanner converts backend rules into ParsedRules. Where backend rules contain selectors and named ports, ParsedRules only contain IPSet IDs. The RuleScanner calculates the relevant IDs as it processes the rules and diverts the details of the active selectors and named ports to the named port index, which figures out the members that should be in those IP sets.

type PipelineCallbacks

type PipelineCallbacks interface {
	// contains filtered or unexported methods
}

type PolKV

type PolKV struct {
	Key   model.PolicyKey
	Value *model.Policy
	// contains filtered or unexported fields
}

PolKV is really internal to the calc package. It is named with an initial capital so that the test package calc_test can also use it.

func (*PolKV) GovernsEgress

func (p *PolKV) GovernsEgress() bool

func (*PolKV) GovernsIngress

func (p *PolKV) GovernsIngress() bool

func (*PolKV) String

func (p *PolKV) String() string

type PolicyMatchListener

type PolicyMatchListener interface {
	OnPolicyMatch(policyKey model.PolicyKey, endpointKey model.Key)
	OnPolicyMatchStopped(policyKey model.PolicyKey, endpointKey model.Key)
}

type PolicyResolver

type PolicyResolver struct {
	Callbacks []PolicyResolverCallbacks
	InSync    bool
	// contains filtered or unexported fields
}

PolicyResolver marries up the active policies with local endpoints and calculates the complete, ordered set of policies that apply to each endpoint. As policies and endpoints are added/removed/updated, it emits events via the PolicyResolverCallbacks with the updated set of matching policies.

The PolicyResolver doesn't figure out which policies are currently active, it expects to be told via its OnPolicyMatch(Stopped) methods which policies match which endpoints. The ActiveRulesCalculator does that calculation.

func NewPolicyResolver

func NewPolicyResolver() *PolicyResolver

func (*PolicyResolver) Flush

func (pr *PolicyResolver) Flush()

func (*PolicyResolver) OnDatamodelStatus

func (pr *PolicyResolver) OnDatamodelStatus(status api.SyncStatus)

func (*PolicyResolver) OnPolicyMatch

func (pr *PolicyResolver) OnPolicyMatch(policyKey model.PolicyKey, endpointKey model.Key)

func (*PolicyResolver) OnPolicyMatchStopped

func (pr *PolicyResolver) OnPolicyMatchStopped(policyKey model.PolicyKey, endpointKey model.Key)

func (*PolicyResolver) OnUpdate

func (pr *PolicyResolver) OnUpdate(update api.Update) (filterOut bool)

func (*PolicyResolver) RegisterCallback

func (pr *PolicyResolver) RegisterCallback(cb PolicyResolverCallbacks)

func (*PolicyResolver) RegisterWith

func (pr *PolicyResolver) RegisterWith(allUpdDispatcher, localEndpointDispatcher *dispatcher.Dispatcher)

type PolicyResolverCallbacks

type PolicyResolverCallbacks interface {
	OnEndpointTierUpdate(endpointKey model.Key, endpoint interface{}, filteredTiers []TierInfo)
}

type PolicySorter

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

func NewPolicySorter

func NewPolicySorter() *PolicySorter

func (*PolicySorter) HasPolicy

func (poc *PolicySorter) HasPolicy(key model.PolicyKey) bool

func (*PolicySorter) OnUpdate

func (poc *PolicySorter) OnUpdate(update api.Update) (dirty bool)

func (*PolicySorter) Sorted

func (poc *PolicySorter) Sorted() []*TierInfo

func (*PolicySorter) UpdatePolicy

func (poc *PolicySorter) UpdatePolicy(key model.PolicyKey, newPolicy *model.Policy) (dirty bool)

type Pool

type Pool struct {
	Type        proto.IPPoolType // Only set if this CIDR represents an IP pool
	NATOutgoing bool
	CrossSubnet bool
}

type ProfileDecoder

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

ProfileDecoder takes updates from a dispatcher, determines if the profile is a Kubernetes Service Account or Kubernetes Namespace, and if it is, generates a dataplane update or remove for it.

func NewProfileDecoder

func NewProfileDecoder(callbacks passthruCallbacks) *ProfileDecoder

func (*ProfileDecoder) OnUpdate

func (p *ProfileDecoder) OnUpdate(update api.Update) (filterOut bool)

func (*ProfileDecoder) RegisterWith

func (p *ProfileDecoder) RegisterWith(d *dispatcher.Dispatcher)

type Ref

type Ref struct {
	// Count of Refs that have this CIDR.  Normally, for WEPs this will be 0 or 1 but Felix has to be tolerant
	// to bad data (two Refs with the same CIDR) so we do ref counting. For tunnel IPs, multiple tunnels may share the
	// same IP, so again ref counting is necessary here.
	RefCount int

	// The type of reference.
	RefType RefType

	// NodeName contains the nodename for this Ref / CIDR.
	NodeName string
}

type RefType

type RefType byte
const (
	RefTypeWEP RefType = iota
	RefTypeWireguard
	RefTypeIPIP
	RefTypeVXLAN
)

type RouteInfo

type RouteInfo struct {
	// Pools contains information extracted from the local and remote IP pools that have this CIDR.
	// Since the datastore guarantees that pools have unique CIDRs within the cluster, we only expect one entry.
	Pools []Pool

	// Blocks contains route information extracted from local and remote IPAM blocks.
	// Since the datastore guarantees that blocks have unique CIDRs within the cluster, we only expect one entry.
	Blocks []Block

	// Host contains information extracted from the node/host config updates.
	Host struct {
		NodeNames []string // set if this CIDR _is_ a node's own IP.
	}

	// Refs contains information extracted from workload endpoints, or tunnel addresses extracted from the node.
	Refs []Ref

	// WasSent is set to true when the route is sent downstream.
	WasSent bool
}

func (RouteInfo) Copy

func (r RouteInfo) Copy() RouteInfo

Copy returns a copy of the RouteInfo. Since some fields are pointers, we need to explicitly copy them so that they are not shared between the copies.

func (RouteInfo) Equals

func (r RouteInfo) Equals(other RouteInfo) bool

func (RouteInfo) IsValidRoute

func (r RouteInfo) IsValidRoute() bool

IsValidRoute returns true if the RouteInfo contains some information about a CIDR, i.e. if this route should be sent downstream. This _excludes_ the WasSent flag, which we use to track whether a route with this CIDR was previously sent. If IsValidRoute() returns false but WasSent is true then we need to withdraw the route.

func (RouteInfo) IsZero

func (r RouteInfo) IsZero() bool

IsZero() returns true if this node in the trie now contains no tracking information at all and is ready for deletion.

type RouteTrie

type RouteTrie struct {
	OnAlive func()
	// contains filtered or unexported fields
}

RouteTrie stores the information that we've gleaned from various resources in a way that allows us to

  • Look up a CIDR and find all the information that we know about the containing CIDRs. Example: if we look up a workload /32 CIDR then we'll also find the IP pool that contains it.
  • Deal with collisions where resources from different sources share the same CIDR. Example: an IP pool and an IPAM block can share the same CIDR. When we do a lookup, we want to know about both the pool and the block.

More examples of nesting and collisions to be aware of:

  • Disabled IPAM pools that contain no blocks, which are used for tagging "external" IPs as safe destinations that don't require SNAT and for adding IP ranges for BIRD to export.
  • IPAM blocks that are /32s so they overlap with the pod IP inside them (and potentially with a misconfigured host IP).
  • Transient misconfigurations during a resync where we may see things out of order (for example, two hosts sharing an IP).
  • In future, /32s that we've learned from workload endpoints that are not contained within IP pools.

Approach: for each CIDR in the trie, we store a RouteInfo struct, which has a disjoint nested struct for tracking data from each source. All updates are done via the updateCIDR method, which handles cleaning up RouteInfo structs that are empty.

The RouteTrie maintains a set of dirty CIDRs. When an IPAM pool is updated, all the CIDRs under it are marked dirty.

func NewRouteTrie

func NewRouteTrie() *RouteTrie

func (*RouteTrie) AddHost

func (r *RouteTrie) AddHost(cidr ip.CIDR, nodeName string)

func (*RouteTrie) AddRef

func (r *RouteTrie) AddRef(cidr ip.CIDR, nodename string, rt RefType)

func (*RouteTrie) Get

func (r *RouteTrie) Get(cidr ip.CIDR) RouteInfo

func (*RouteTrie) MarkCIDRDirty

func (r *RouteTrie) MarkCIDRDirty(cidr ip.CIDR)

func (*RouteTrie) RemoveBlockRoute

func (r *RouteTrie) RemoveBlockRoute(cidr ip.CIDR)

func (*RouteTrie) RemoveHost

func (r *RouteTrie) RemoveHost(cidr ip.CIDR, nodeName string)

func (*RouteTrie) RemovePool

func (r *RouteTrie) RemovePool(cidr ip.CIDR)

func (*RouteTrie) RemoveRef

func (r *RouteTrie) RemoveRef(cidr ip.CIDR, nodename string, rt RefType)

func (*RouteTrie) SetRouteSent

func (r *RouteTrie) SetRouteSent(cidr ip.CIDR, sent bool)

func (*RouteTrie) UpdateBlockRoute

func (r *RouteTrie) UpdateBlockRoute(cidr ip.CIDR, nodeName string)

func (*RouteTrie) UpdatePool

func (r *RouteTrie) UpdatePool(cidr ip.CIDR, poolType proto.IPPoolType, natOutgoing bool, crossSubnet bool)

type RuleScanner

type RuleScanner struct {
	OnIPSetActive   func(ipSet *IPSetData)
	OnIPSetInactive func(ipSet *IPSetData)

	RulesUpdateCallbacks rulesUpdateCallbacks
	// contains filtered or unexported fields
}

RuleScanner scans the rules sent to it by the ActiveRulesCalculator, looking for selectors. It calculates the set of active selectors and emits events when they become active/inactive.

Previously, Felix tracked tags and selectors separately, with a separate tag and label index. However, we found that had a high occupancy cost. The current code uses a shared index and maps tags onto labels, so a tag named tagName, becomes a label tagName="". The RuleScanner maps tags to label selectors of the form "has(tagName)", taking advantage of the mapping. Such a selector is almost equivalent to having the tag; the only case where the behaviour would differ is if the user was using the same name for a tag and a label and the label and tags of the same name were applied to different endpoints. Since tags are being deprecated, we can live with that potential aliasing issue in return for a significant occupancy improvement at high scale.

The RuleScanner also emits events when rules are updated: since the input rule structs contain tags and selectors but downstream, we only care about IP sets, the RuleScanner converts rules from model.Rule objects to calc.ParsedRule objects. The latter share most fields, but the tags and selector fields are replaced by lists of IP sets.

The RuleScanner only calculates which selectors and tags are active/inactive. It doesn't match endpoints against tags/selectors. (That is done downstream in a labelindex.InheritIndex created in NewCalculationGraph.)

func NewRuleScanner

func NewRuleScanner() *RuleScanner

func (*RuleScanner) OnPolicyActive

func (rs *RuleScanner) OnPolicyActive(key model.PolicyKey, policy *model.Policy)

func (*RuleScanner) OnPolicyInactive

func (rs *RuleScanner) OnPolicyInactive(key model.PolicyKey)

func (*RuleScanner) OnProfileActive

func (rs *RuleScanner) OnProfileActive(key model.ProfileRulesKey, profile *model.ProfileRules)

func (*RuleScanner) OnProfileInactive

func (rs *RuleScanner) OnProfileInactive(key model.ProfileRulesKey)

type StatsCollector

type StatsCollector struct {
	Callback func(StatsUpdate) error
	// contains filtered or unexported fields
}

func NewStatsCollector

func NewStatsCollector(callback func(StatsUpdate) error) *StatsCollector

func (*StatsCollector) OnStatusUpdate

func (s *StatsCollector) OnStatusUpdate(status api.SyncStatus)

func (*StatsCollector) OnUpdate

func (s *StatsCollector) OnUpdate(update api.Update) (filterOut bool)

func (*StatsCollector) RegisterWith

func (s *StatsCollector) RegisterWith(calcGraph *CalcGraph)

func (*StatsCollector) UpdatePolicyCounts

func (s *StatsCollector) UpdatePolicyCounts(numTiers, numPolicies, numProfiles, numALPPolicies int)

type StatsUpdate

type StatsUpdate struct {
	NumHosts             int
	NumWorkloadEndpoints int
	NumHostEndpoints     int
	NumTiers             int
	NumPolicies          int
	NumProfiles          int
	NumALPPolicies       int
}

func (StatsUpdate) String

func (s StatsUpdate) String() string

type SyncerCallbacksDecoupler

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

func NewSyncerCallbacksDecoupler

func NewSyncerCallbacksDecoupler() *SyncerCallbacksDecoupler

func (*SyncerCallbacksDecoupler) OnStatusUpdated

func (a *SyncerCallbacksDecoupler) OnStatusUpdated(status api.SyncStatus)

func (*SyncerCallbacksDecoupler) OnUpdates

func (a *SyncerCallbacksDecoupler) OnUpdates(updates []api.Update)

func (*SyncerCallbacksDecoupler) SendTo

type TierInfo

type TierInfo struct {
	Name            string
	Valid           bool
	Order           *float64
	DefaultAction   v3.Action
	Policies        map[model.PolicyKey]*model.Policy
	SortedPolicies  *btree.BTreeG[PolKV]
	OrderedPolicies []PolKV
}

func NewTierInfo

func NewTierInfo(name string) *TierInfo

func (TierInfo) String

func (t TierInfo) String() string

type VXLANResolver

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

VXLANResolver is responsible for resolving node IPs and node config to calculate the VTEP for each host. It registers for:

  • model.HostIPKey
  • model.HostConfigKey

VXLAN routes are calculated by the L3RouteResolver, and to be valid for the dataplane must target a VXLAN tunnel endpoint (VTEP) which comprises a node IP address, VXLAN tunnel address, and a deterministically calculated MAC address. The VXLAN resolver calculates the VTEPs. The dataplane is responsible for only programming routes once the VTEP is ready.

For each VTEP, this component will send a *proto.VXLANTunnelEndpointUpdate.

If a VTEP is no longer fully specified (e.g., due to a vxlan tunnel address removal), a *proto.VXLANTunnelEndpointRemove message is sent.

If a VTEP changes (e.g., due to a vxlan tunnel address changing), this component will treat it as a delete followed by an add.

func NewVXLANResolver

func NewVXLANResolver(hostname string, callbacks vxlanCallbacks, useNodeResourceUpdates bool) *VXLANResolver

func (*VXLANResolver) OnHostConfigUpdate

func (c *VXLANResolver) OnHostConfigUpdate(update api.Update) (_ bool)

OnHostConfigUpdate gets called whenever a node's host config changes. We only care about VXLAN tunnel IP/MAC address updates. On an add/update, we need to check if there are VTEPs which are now valid, and trigger programming of them to the data plane. On a delete, we need to withdraw any VTEPs associated with the node.

func (*VXLANResolver) OnHostIPUpdate

func (c *VXLANResolver) OnHostIPUpdate(update api.Update) (_ bool)

OnHostIPUpdate gets called whenever a node IP address changes. On an add/update, we need to check if there is a VTEP which is now valid, and trigger programming of them to the data plane. On a delete, we need to withdraw the VTEP associated with the node.

func (*VXLANResolver) OnResourceUpdate

func (c *VXLANResolver) OnResourceUpdate(update api.Update) (_ bool)

func (*VXLANResolver) RegisterWith

func (c *VXLANResolver) RegisterWith(allUpdDispatcher *dispatcher.Dispatcher)

type ValidationFilter

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

func NewValidationFilter

func NewValidationFilter(sink api.SyncerCallbacks, felixConfig *config.Config) *ValidationFilter

func (*ValidationFilter) OnStatusUpdated

func (v *ValidationFilter) OnStatusUpdated(status api.SyncStatus)

func (*ValidationFilter) OnUpdates

func (v *ValidationFilter) OnUpdates(updates []api.Update)

Jump to

Keyboard shortcuts

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