Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FelixConfiguration option for FloatingIPs (#5861) #3102

Merged
merged 1 commit into from
Apr 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions config/config_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,9 @@ type Config struct {
IpInIpMtu int `config:"int;0"`
IpInIpTunnelAddr net.IP `config:"ipv4;"`

// Feature enablement. Can be either "Enabled" or "Disabled".
FloatingIPs string `config:"oneof(Enabled,Disabled);Disabled"`

// Knobs provided to explicitly control whether we add rules to drop encap traffic
// from workloads. We always add them unless explicitly requested not to add them.
AllowVXLANPacketsFromWorkloads bool `config:"bool;false"`
Expand Down
6 changes: 4 additions & 2 deletions dataplane/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"os/exec"
"runtime/debug"
"strconv"
"strings"
"time"

log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -174,7 +175,7 @@ func StartDataplaneDriver(configParams *config.Config,
failsafeInboundHostPorts := configParams.FailsafeInboundHostPorts
failsafeOutboundHostPorts := configParams.FailsafeOutboundHostPorts
if configParams.WireguardEnabled {
var found = false
found := false
for _, i := range failsafeInboundHostPorts {
if i.Port == uint16(configParams.WireguardListeningPort) && i.Protocol == "udp" {
log.WithFields(log.Fields{
Expand Down Expand Up @@ -220,7 +221,8 @@ func StartDataplaneDriver(configParams *config.Config,
}

dpConfig := intdataplane.Config{
Hostname: configParams.FelixHostname,
Hostname: configParams.FelixHostname,
FloatingIPsEnabled: strings.EqualFold(configParams.FloatingIPs, string(apiv3.FloatingIPsEnabled)),
IfaceMonitorConfig: ifacemonitor.Config{
InterfaceExcludes: configParams.InterfaceExclude,
ResyncInterval: configParams.InterfaceRefreshInterval,
Expand Down
11 changes: 7 additions & 4 deletions dataplane/linux/endpoint_mgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ type endpointManager struct {
ipVersion uint8
wlIfacesRegexp *regexp.Regexp
kubeIPVSSupportEnabled bool
floatingIPsEnabled bool

// Our dependencies.
rawTable iptablesTable
Expand Down Expand Up @@ -221,6 +222,7 @@ func newEndpointManager(
bpfEnabled bool,
bpfEndpointManager hepListener,
callbacks *callbacks,
floatingIPsEnabled bool,
) *endpointManager {
return newEndpointManagerWithShims(
rawTable,
Expand All @@ -238,6 +240,7 @@ func newEndpointManager(
bpfEnabled,
bpfEndpointManager,
callbacks,
floatingIPsEnabled,
)
}

Expand All @@ -257,6 +260,7 @@ func newEndpointManagerWithShims(
bpfEnabled bool,
bpfEndpointManager hepListener,
callbacks *callbacks,
floatingIPsEnabled bool,
) *endpointManager {
wlIfacesPattern := "^(" + strings.Join(wlInterfacePrefixes, "|") + ").*"
wlIfacesRegexp := regexp.MustCompile(wlIfacesPattern)
Expand All @@ -267,6 +271,7 @@ func newEndpointManagerWithShims(
kubeIPVSSupportEnabled: kubeIPVSSupportEnabled,
bpfEnabled: bpfEnabled,
bpfEndpointManager: bpfEndpointManager,
floatingIPsEnabled: floatingIPsEnabled,

rawTable: rawTable,
mangleTable: mangleTable,
Expand Down Expand Up @@ -387,7 +392,6 @@ func (m *endpointManager) ResolveUpdateBatch() error {
}

func (m *endpointManager) CompleteDeferredWork() error {

m.resolveWorkloadEndpoints()

if m.hostEndpointsDirty {
Expand Down Expand Up @@ -626,7 +630,8 @@ func (m *endpointManager) resolveWorkloadEndpoints() {
natInfos = workload.Ipv6Nat
addrSuffix = "/128"
}
if len(natInfos) != 0 {
if m.floatingIPsEnabled && len(natInfos) != 0 {
// Include any floating IP NATs if the feature is enabled.
old := ipStrings
ipStrings = make([]string, len(old)+len(natInfos))
copy(ipStrings, old)
Expand Down Expand Up @@ -743,7 +748,6 @@ func (m *endpointManager) resolveEndpointMarks() {
}

func (m *endpointManager) resolveHostEndpoints() map[string]proto.HostEndpointID {

// Host endpoint resolution
// ------------------------
//
Expand Down Expand Up @@ -866,7 +870,6 @@ func (m *endpointManager) resolveHostEndpoints() map[string]proto.HostEndpointID
}

func (m *endpointManager) updateHostEndpoints() {

// Calculate filtered name/id maps for untracked and pre-DNAT policy, and a reverse map from
// each active host endpoint to the interfaces it is in use for.
newIfaceNameToHostEpID := m.newIfaceNameToHostEpID
Expand Down
66 changes: 55 additions & 11 deletions dataplane/linux/endpoint_mgr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@ func endpointManagerTests(ipVersion uint8) func() {
false,
hepListener,
newCallbacks(),
true,
)
})

Expand Down Expand Up @@ -1416,7 +1417,6 @@ func endpointManagerTests(ipVersion uint8) func() {
}))
})
})

})

Context("with host endpoint configured before interface signaled", func() {
Expand Down Expand Up @@ -1470,7 +1470,6 @@ func endpointManagerTests(ipVersion uint8) func() {
}

Describe("workload endpoints", func() {

Context("with a workload endpoint", func() {
wlEPID1 := proto.WorkloadEndpointID{
OrchestratorId: "k8s",
Expand Down Expand Up @@ -1514,7 +1513,6 @@ func endpointManagerTests(ipVersion uint8) func() {
It("should have expected chains", expectWlChainsFor("cali12345-ab_policy1"))

Context("with another endpoint with the same interface name and earlier workload ID, and no policy", func() {

JustBeforeEach(func() {
epMgr.OnUpdate(&proto.WorkloadEndpointUpdate{
Id: &proto.WorkloadEndpointID{
Expand All @@ -1541,7 +1539,6 @@ func endpointManagerTests(ipVersion uint8) func() {
It("should have expected chains with no policy", expectWlChainsFor("cali12345-ab"))

Context("with the first endpoint removed", func() {

JustBeforeEach(func() {
epMgr.OnUpdate(&proto.WorkloadEndpointRemove{
Id: &wlEPID1,
Expand All @@ -1555,7 +1552,6 @@ func endpointManagerTests(ipVersion uint8) func() {
It("should have expected chains with no policy", expectWlChainsFor("cali12345-ab"))

Context("with the second endpoint removed", func() {

JustBeforeEach(func() {
epMgr.OnUpdate(&proto.WorkloadEndpointRemove{
Id: &proto.WorkloadEndpointID{
Expand All @@ -1576,7 +1572,6 @@ func endpointManagerTests(ipVersion uint8) func() {
})

Context("with another endpoint with the same interface name and later workload ID, and no policy", func() {

JustBeforeEach(func() {
epMgr.OnUpdate(&proto.WorkloadEndpointUpdate{
Id: &proto.WorkloadEndpointID{
Expand All @@ -1603,7 +1598,6 @@ func endpointManagerTests(ipVersion uint8) func() {
It("should have expected chains", expectWlChainsFor("cali12345-ab_policy1"))

Context("with the first endpoint removed", func() {

JustBeforeEach(func() {
epMgr.OnUpdate(&proto.WorkloadEndpointRemove{
Id: &wlEPID1,
Expand All @@ -1617,7 +1611,6 @@ func endpointManagerTests(ipVersion uint8) func() {
It("should have expected chains with no policy", expectWlChainsFor("cali12345-ab"))

Context("with the second endpoint removed", func() {

JustBeforeEach(func() {
epMgr.OnUpdate(&proto.WorkloadEndpointRemove{
Id: &proto.WorkloadEndpointID{
Expand Down Expand Up @@ -1810,6 +1803,59 @@ func endpointManagerTests(ipVersion uint8) func() {
})
})

// Test that by disabling floatingIPs on the endpoint manager, even workload endpoints
// that have floating IP NAT addresses specified will not result in those routes being
// programmed.
Context("with floating IPs disasbled, but added to the endpoint", func() {
JustBeforeEach(func() {
epMgr.floatingIPsEnabled = false
epMgr.OnUpdate(&proto.WorkloadEndpointUpdate{
Id: &wlEPID1,
Endpoint: &proto.WorkloadEndpoint{
State: "active",
Mac: "01:02:03:04:05:06",
Name: "cali12345-ab",
ProfileIds: []string{},
Tiers: []*proto.TierInfo{},
Ipv4Nets: []string{"10.0.240.2/24"},
Ipv6Nets: []string{"2001:db8:2::2/128"},
Ipv4Nat: []*proto.NatInfo{
{ExtIp: "172.16.1.3", IntIp: "10.0.240.2"},
{ExtIp: "172.18.1.4", IntIp: "10.0.240.2"},
},
Ipv6Nat: []*proto.NatInfo{
{ExtIp: "2001:db8:3::2", IntIp: "2001:db8:2::2"},
{ExtIp: "2001:db8:4::2", IntIp: "2001:db8:4::2"},
},
},
})
err := epMgr.ResolveUpdateBatch()
Expect(err).ToNot(HaveOccurred())
err = epMgr.CompleteDeferredWork()
Expect(err).ToNot(HaveOccurred())
})

It("should have expected chains", expectWlChainsFor("cali12345-ab"))

It("should set routes with no floating IPs", func() {
if ipVersion == 6 {
routeTable.checkRoutes("cali12345-ab", []routetable.Target{
{
CIDR: ip.MustParseCIDROrIP("2001:db8:2::2/128"),
DestMAC: testutils.MustParseMAC("01:02:03:04:05:06"),
},
})
} else {
routeTable.checkRoutes("cali12345-ab", []routetable.Target{
{
CIDR: ip.MustParseCIDROrIP("10.0.240.0/24"),
DestMAC: testutils.MustParseMAC("01:02:03:04:05:06"),
},
})
}
})
})

Context("with the endpoint removed", func() {
JustBeforeEach(func() {
epMgr.OnUpdate(&proto.WorkloadEndpointRemove{
Expand Down Expand Up @@ -1961,9 +2007,7 @@ type testProcSys struct {
Fail bool
}

var (
procSysFail = errors.New("mock proc sys failure")
)
var procSysFail = errors.New("mock proc sys failure")

func (t *testProcSys) write(path, value string) error {
log.WithFields(log.Fields{
Expand Down
34 changes: 21 additions & 13 deletions dataplane/linux/floating_ip_mgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,14 @@ type floatingIPManager struct {
activeSNATChains []*iptables.Chain
natInfo map[proto.WorkloadEndpointID][]*proto.NatInfo
dirtyNATInfo bool
enabled bool
}

func newFloatingIPManager(
natTable iptablesTable,
ruleRenderer rules.RuleRenderer,
ipVersion uint8,
enabled bool,
) *floatingIPManager {
return &floatingIPManager{
natTable: natTable,
Expand All @@ -92,6 +94,7 @@ func newFloatingIPManager(
activeSNATChains: []*iptables.Chain{},
natInfo: map[proto.WorkloadEndpointID][]*proto.NatInfo{},
dirtyNATInfo: true,
enabled: enabled,
}
}

Expand All @@ -114,23 +117,28 @@ func (m *floatingIPManager) CompleteDeferredWork() error {
if m.dirtyNATInfo {
// Collate required DNATs as a map from external IP to internal IP.
dnats := map[string]string{}
for _, natInfos := range m.natInfo {
for _, natInfo := range natInfos {
log.WithFields(log.Fields{
"ExtIP": natInfo.ExtIp,
"IntIP": natInfo.IntIp,
}).Debug("NAT mapping")
if m.enabled {
// We only perform nat if the feature is explicitly enabled, otherwise
// we will simply remove any programmed floating IP NAT fules.
for _, natInfos := range m.natInfo {
for _, natInfo := range natInfos {
log.WithFields(log.Fields{
"ExtIP": natInfo.ExtIp,
"IntIP": natInfo.IntIp,
}).Debug("NAT mapping")

// We shouldn't ever have the same floating IP mapping to multiple
// workload IPs, but if we do we'll program the mapping to the
// alphabetically earlier one.
existingIntIP := dnats[natInfo.ExtIp]
if existingIntIP == "" || natInfo.IntIp < existingIntIP {
log.Debug("Wanted NAT mapping")
dnats[natInfo.ExtIp] = natInfo.IntIp
// We shouldn't ever have the same floating IP mapping to multiple
// workload IPs, but if we do we'll program the mapping to the
// alphabetically earlier one.
existingIntIP := dnats[natInfo.ExtIp]
if existingIntIP == "" || natInfo.IntIp < existingIntIP {
log.Debug("Wanted NAT mapping")
dnats[natInfo.ExtIp] = natInfo.IntIp
}
}
}
}

// Collate required SNATs as a map from internal IP to external IP.
snats := map[string]string{}
for extIP, intIP := range dnats {
Expand Down
Loading