diff --git a/go-controller/pkg/node/bridgeconfig/bridgeconfig_testutil.go b/go-controller/pkg/node/bridgeconfig/bridgeconfig_testutil.go index 8395baf06d..d13568a529 100644 --- a/go-controller/pkg/node/bridgeconfig/bridgeconfig_testutil.go +++ b/go-controller/pkg/node/bridgeconfig/bridgeconfig_testutil.go @@ -47,10 +47,10 @@ func CheckUDNSvcIsolationOVSFlows(flows []string, netConfig *BridgeUDNConfigurat var protoPrefix string if net2.IsIPv4CIDR(svcCIDR) { mgmtMasqIP = netConfig.V4MasqIPs.ManagementPort.IP.String() - protoPrefix = "ip" + protoPrefix = protoPrefixV4 } else { mgmtMasqIP = netConfig.V6MasqIPs.ManagementPort.IP.String() - protoPrefix = "ip6" + protoPrefix = protoPrefixV6 } var nFlows int @@ -78,11 +78,11 @@ func CheckAdvertisedUDNSvcIsolationOVSFlows(flows []string, netConfig *BridgeUDN if net2.IsIPv4CIDR(svcCIDR) { matchingIPFamilySubnet, err = util.MatchFirstIPNetFamily(false, udnAdvertisedSubnets) Expect(err).ToNot(HaveOccurred()) - protoPrefix = "ip" + protoPrefix = protoPrefixV4 } else { matchingIPFamilySubnet, err = util.MatchFirstIPNetFamily(true, udnAdvertisedSubnets) Expect(err).ToNot(HaveOccurred()) - protoPrefix = "ip6" + protoPrefix = protoPrefixV6 } var nFlows int @@ -107,11 +107,11 @@ func CheckDefaultSvcIsolationOVSFlows(flows []string, defaultConfig *BridgeUDNCo var masqSubnet string var protoPrefix string if net2.IsIPv4CIDR(svcCIDR) { - protoPrefix = "ip" + protoPrefix = protoPrefixV4 masqIP = config.Gateway.MasqueradeIPs.V4HostMasqueradeIP.String() masqSubnet = config.Gateway.V4MasqueradeSubnet } else { - protoPrefix = "ip6" + protoPrefix = protoPrefixV6 masqIP = config.Gateway.MasqueradeIPs.V6HostMasqueradeIP.String() masqSubnet = config.Gateway.V6MasqueradeSubnet } diff --git a/go-controller/pkg/node/bridgeconfig/bridgeflows.go b/go-controller/pkg/node/bridgeconfig/bridgeflows.go index 8a858c30e9..0b85310efb 100644 --- a/go-controller/pkg/node/bridgeconfig/bridgeflows.go +++ b/go-controller/pkg/node/bridgeconfig/bridgeflows.go @@ -14,6 +14,11 @@ import ( "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/util" ) +const ( + protoPrefixV4 = "ip" + protoPrefixV6 = "ipv6" +) + func (b *BridgeConfiguration) DefaultBridgeFlows(hostSubnets []*net.IPNet, extraIPs []net.IP) ([]string, error) { b.mutex.Lock() defer b.mutex.Unlock() @@ -82,9 +87,10 @@ func (b *BridgeConfiguration) flowsForDefaultBridge(extraIPs []net.IP) ([]string for _, netConfig := range b.patchedNetConfigs() { // table 0, SVC Hairpin from OVN destined to local host, DNAT and go to table 4 dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=500, in_port=%s, ip, ip_dst=%s, ip_src=%s,"+ + fmt.Sprintf("cookie=%s, priority=500, in_port=%s, %s, %s_dst=%s, %s_src=%s,"+ "actions=ct(commit,zone=%d,nat(dst=%s),table=4)", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, config.Gateway.MasqueradeIPs.V4HostMasqueradeIP.String(), physicalIP.IP, + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, protoPrefixV4, protoPrefixV4, + config.Gateway.MasqueradeIPs.V4HostMasqueradeIP.String(), protoPrefixV4, physicalIP.IP, config.Default.HostMasqConntrackZone, physicalIP.IP)) } @@ -105,18 +111,20 @@ func (b *BridgeConfiguration) flowsForDefaultBridge(extraIPs []net.IP) ([]string for _, netConfig := range b.patchedNetConfigs() { dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=500, in_port=%s, ip, ip_dst=%s, ip_src=%s,"+ + fmt.Sprintf("cookie=%s, priority=500, in_port=%s, %s, %s_dst=%s, %s_src=%s,"+ "actions=ct(commit,zone=%d,table=4)", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, ip.String(), physicalIP.IP, + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, protoPrefixV4, + protoPrefixV4, ip.String(), protoPrefixV4, physicalIP.IP, config.Default.HostMasqConntrackZone)) } } // table 0, Reply SVC traffic from Host -> OVN, unSNAT and goto table 5 dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=500, in_port=%s, ip, ip_dst=%s,"+ + fmt.Sprintf("cookie=%s, priority=500, in_port=%s, %s, %s_dst=%s,"+ "actions=ct(zone=%d,nat,table=5)", - nodetypes.DefaultOpenFlowCookie, ofPortHost, config.Gateway.MasqueradeIPs.V4OVNMasqueradeIP.String(), config.Default.OVNMasqConntrackZone)) + nodetypes.DefaultOpenFlowCookie, ofPortHost, protoPrefixV4, protoPrefixV4, + config.Gateway.MasqueradeIPs.V4OVNMasqueradeIP.String(), config.Default.OVNMasqConntrackZone)) } if config.IPv6Mode { if ofPortPhys != "" { @@ -144,9 +152,10 @@ func (b *BridgeConfiguration) flowsForDefaultBridge(extraIPs []net.IP) ([]string // table 0, SVC Hairpin from OVN destined to local host, DNAT to host, send to table 4 for _, netConfig := range b.patchedNetConfigs() { dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=500, in_port=%s, ipv6, ipv6_dst=%s, ipv6_src=%s,"+ + fmt.Sprintf("cookie=%s, priority=500, in_port=%s, %s, %s_dst=%s, %s_src=%s,"+ "actions=ct(commit,zone=%d,nat(dst=%s),table=4)", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, config.Gateway.MasqueradeIPs.V6HostMasqueradeIP.String(), physicalIP.IP, + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, protoPrefixV6, protoPrefixV6, + config.Gateway.MasqueradeIPs.V6HostMasqueradeIP.String(), protoPrefixV6, physicalIP.IP, config.Default.HostMasqConntrackZone, physicalIP.IP)) } @@ -167,18 +176,20 @@ func (b *BridgeConfiguration) flowsForDefaultBridge(extraIPs []net.IP) ([]string for _, netConfig := range b.patchedNetConfigs() { dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=500, in_port=%s, ipv6, ipv6_dst=%s, ipv6_src=%s,"+ + fmt.Sprintf("cookie=%s, priority=500, in_port=%s, %s, %s_dst=%s, %s_src=%s,"+ "actions=ct(commit,zone=%d,table=4)", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, ip.String(), physicalIP.IP, + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, protoPrefixV6, protoPrefixV6, + ip.String(), protoPrefixV6, physicalIP.IP, config.Default.HostMasqConntrackZone)) } } // table 0, Reply SVC traffic from Host -> OVN, unSNAT and goto table 5 dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=500, in_port=%s, ipv6, ipv6_dst=%s,"+ + fmt.Sprintf("cookie=%s, priority=500, in_port=%s, %s, %s_dst=%s,"+ "actions=ct(zone=%d,nat,table=5)", - nodetypes.DefaultOpenFlowCookie, ofPortHost, config.Gateway.MasqueradeIPs.V6OVNMasqueradeIP.String(), config.Default.OVNMasqConntrackZone)) + nodetypes.DefaultOpenFlowCookie, ofPortHost, protoPrefixV6, protoPrefixV6, + config.Gateway.MasqueradeIPs.V6OVNMasqueradeIP.String(), config.Default.OVNMasqConntrackZone)) } var protoPrefix, masqIP, masqSubnet string @@ -186,11 +197,11 @@ func (b *BridgeConfiguration) flowsForDefaultBridge(extraIPs []net.IP) ([]string // table 0, packets coming from Host -> Service for _, svcCIDR := range config.Kubernetes.ServiceCIDRs { if utilnet.IsIPv4CIDR(svcCIDR) { - protoPrefix = "ip" + protoPrefix = protoPrefixV4 masqIP = config.Gateway.MasqueradeIPs.V4HostMasqueradeIP.String() masqSubnet = config.Gateway.V4MasqueradeSubnet } else { - protoPrefix = "ipv6" + protoPrefix = protoPrefixV6 masqIP = config.Gateway.MasqueradeIPs.V6HostMasqueradeIP.String() masqSubnet = config.Gateway.V6MasqueradeSubnet } @@ -287,50 +298,50 @@ func (b *BridgeConfiguration) flowsForDefaultBridge(extraIPs []net.IP) ([]string if config.IPv4Mode { // table 1, established and related connections in zone 64000 with ct_mark CtMarkOVN go to OVN dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, table=1, ip, ct_state=+trk+est, ct_mark=%s, "+ - "actions=%s", nodetypes.DefaultOpenFlowCookie, netConfig.MasqCTMark, actions)) + fmt.Sprintf("cookie=%s, priority=100, table=1, %s, ct_state=+trk+est, ct_mark=%s, "+ + "actions=%s", nodetypes.DefaultOpenFlowCookie, protoPrefixV4, netConfig.MasqCTMark, actions)) dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, table=1, ip, ct_state=+trk+rel, ct_mark=%s, "+ - "actions=%s", nodetypes.DefaultOpenFlowCookie, netConfig.MasqCTMark, actions)) + fmt.Sprintf("cookie=%s, priority=100, table=1, %s, ct_state=+trk+rel, ct_mark=%s, "+ + "actions=%s", nodetypes.DefaultOpenFlowCookie, protoPrefixV4, netConfig.MasqCTMark, actions)) } if config.IPv6Mode { // table 1, established and related connections in zone 64000 with ct_mark CtMarkOVN go to OVN dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, table=1, ipv6, ct_state=+trk+est, ct_mark=%s, "+ - "actions=%s", nodetypes.DefaultOpenFlowCookie, netConfig.MasqCTMark, actions)) + fmt.Sprintf("cookie=%s, priority=100, table=1, %s, ct_state=+trk+est, ct_mark=%s, "+ + "actions=%s", nodetypes.DefaultOpenFlowCookie, protoPrefixV6, netConfig.MasqCTMark, actions)) dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, table=1, ipv6, ct_state=+trk+rel, ct_mark=%s, "+ - "actions=%s", nodetypes.DefaultOpenFlowCookie, netConfig.MasqCTMark, actions)) + fmt.Sprintf("cookie=%s, priority=100, table=1, %s, ct_state=+trk+rel, ct_mark=%s, "+ + "actions=%s", nodetypes.DefaultOpenFlowCookie, protoPrefixV6, netConfig.MasqCTMark, actions)) } } if config.IPv4Mode { // table 1, established and related connections in zone 64000 with ct_mark CtMarkHost go to host dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, table=1, %s ip, ct_state=+trk+est, ct_mark=%s, "+ + fmt.Sprintf("cookie=%s, priority=100, table=1, %s %s, ct_state=+trk+est, ct_mark=%s, "+ "actions=%soutput:%s", - nodetypes.DefaultOpenFlowCookie, match_vlan, nodetypes.CtMarkHost, strip_vlan, ofPortHost)) + nodetypes.DefaultOpenFlowCookie, match_vlan, protoPrefixV4, nodetypes.CtMarkHost, strip_vlan, ofPortHost)) dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, table=1, %s ip, ct_state=+trk+rel, ct_mark=%s, "+ + fmt.Sprintf("cookie=%s, priority=100, table=1, %s %s, ct_state=+trk+rel, ct_mark=%s, "+ "actions=%soutput:%s", - nodetypes.DefaultOpenFlowCookie, match_vlan, nodetypes.CtMarkHost, strip_vlan, ofPortHost)) + nodetypes.DefaultOpenFlowCookie, match_vlan, protoPrefixV4, nodetypes.CtMarkHost, strip_vlan, ofPortHost)) } if config.IPv6Mode { // table 1, established and related connections in zone 64000 with ct_mark CtMarkHost go to host dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, table=1, %s ip6, ct_state=+trk+est, ct_mark=%s, "+ + fmt.Sprintf("cookie=%s, priority=100, table=1, %s %s, ct_state=+trk+est, ct_mark=%s, "+ "actions=%soutput:%s", - nodetypes.DefaultOpenFlowCookie, match_vlan, nodetypes.CtMarkHost, strip_vlan, ofPortHost)) + nodetypes.DefaultOpenFlowCookie, match_vlan, protoPrefixV6, nodetypes.CtMarkHost, strip_vlan, ofPortHost)) dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, table=1, %s ip6, ct_state=+trk+rel, ct_mark=%s, "+ + fmt.Sprintf("cookie=%s, priority=100, table=1, %s %s, ct_state=+trk+rel, ct_mark=%s, "+ "actions=%soutput:%s", - nodetypes.DefaultOpenFlowCookie, match_vlan, nodetypes.CtMarkHost, strip_vlan, ofPortHost)) + nodetypes.DefaultOpenFlowCookie, match_vlan, protoPrefixV6, nodetypes.CtMarkHost, strip_vlan, ofPortHost)) } @@ -372,22 +383,23 @@ func (b *BridgeConfiguration) flowsForDefaultBridge(extraIPs []net.IP) ([]string // the correct patch port of it's own network where it's a deadend if the clusterIP is not part of // that UDN network and works if it is part of the UDN network. dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=200, table=2, ip, ip_src=%s, "+ + fmt.Sprintf("cookie=%s, priority=200, table=2, %s, %s_src=%s, "+ "actions=drop", - nodetypes.DefaultOpenFlowCookie, matchingIPFamilySubnet.String())) + nodetypes.DefaultOpenFlowCookie, protoPrefixV4, protoPrefixV4, matchingIPFamilySubnet.String())) } // Drop traffic coming from the masquerade IP or the UDN subnet(for advertised UDNs) to ensure that // isolation between networks is enforced. This handles the case where a pod on the UDN subnet is sending traffic to // a service in another UDN. dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=200, table=2, ip, ip_src=%s, "+ + fmt.Sprintf("cookie=%s, priority=200, table=2, %s, %s_src=%s, "+ "actions=drop", - nodetypes.DefaultOpenFlowCookie, netConfig.V4MasqIPs.ManagementPort.IP.String())) + nodetypes.DefaultOpenFlowCookie, protoPrefixV4, protoPrefixV4, + netConfig.V4MasqIPs.ManagementPort.IP.String())) dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=250, table=2, ip, pkt_mark=%s, "+ + fmt.Sprintf("cookie=%s, priority=250, table=2, %s, pkt_mark=%s, "+ "actions=set_field:%s->eth_dst,output:%s", - nodetypes.DefaultOpenFlowCookie, netConfig.PktMark, + nodetypes.DefaultOpenFlowCookie, protoPrefixV4, netConfig.PktMark, bridgeMacAddress, netConfig.OfPortPatch)) } } @@ -411,18 +423,20 @@ func (b *BridgeConfiguration) flowsForDefaultBridge(extraIPs []net.IP) ([]string } dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=200, table=2, ip6, ipv6_src=%s, "+ + fmt.Sprintf("cookie=%s, priority=200, table=2, %s, %s_src=%s, "+ "actions=drop", - nodetypes.DefaultOpenFlowCookie, matchingIPFamilySubnet.String())) + nodetypes.DefaultOpenFlowCookie, protoPrefixV6, protoPrefixV6, + matchingIPFamilySubnet.String())) } dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=200, table=2, ip6, ipv6_src=%s, "+ + fmt.Sprintf("cookie=%s, priority=200, table=2, %s, %s_src=%s, "+ "actions=drop", - nodetypes.DefaultOpenFlowCookie, netConfig.V6MasqIPs.ManagementPort.IP.String())) + nodetypes.DefaultOpenFlowCookie, protoPrefixV6, protoPrefixV6, + netConfig.V6MasqIPs.ManagementPort.IP.String())) dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=250, table=2, ip6, pkt_mark=%s, "+ + fmt.Sprintf("cookie=%s, priority=250, table=2, %s, pkt_mark=%s, "+ "actions=set_field:%s->eth_dst,output:%s", - nodetypes.DefaultOpenFlowCookie, netConfig.PktMark, + nodetypes.DefaultOpenFlowCookie, protoPrefixV6, netConfig.PktMark, bridgeMacAddress, netConfig.OfPortPatch)) } } @@ -437,28 +451,28 @@ func (b *BridgeConfiguration) flowsForDefaultBridge(extraIPs []net.IP) ([]string // We need to SNAT and masquerade OVN GR IP, send to table 3 for dispatch to Host if config.IPv4Mode { dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, table=4,ip,"+ + fmt.Sprintf("cookie=%s, table=4,%s,"+ "actions=ct(commit,zone=%d,nat(src=%s),table=3)", - nodetypes.DefaultOpenFlowCookie, config.Default.OVNMasqConntrackZone, config.Gateway.MasqueradeIPs.V4OVNMasqueradeIP.String())) + nodetypes.DefaultOpenFlowCookie, protoPrefixV4, config.Default.OVNMasqConntrackZone, config.Gateway.MasqueradeIPs.V4OVNMasqueradeIP.String())) } if config.IPv6Mode { dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, table=4,ipv6, "+ + fmt.Sprintf("cookie=%s, table=4,%s, "+ "actions=ct(commit,zone=%d,nat(src=%s),table=3)", - nodetypes.DefaultOpenFlowCookie, config.Default.OVNMasqConntrackZone, config.Gateway.MasqueradeIPs.V6OVNMasqueradeIP.String())) + nodetypes.DefaultOpenFlowCookie, protoPrefixV6, config.Default.OVNMasqConntrackZone, config.Gateway.MasqueradeIPs.V6OVNMasqueradeIP.String())) } // table 5, Host Reply traffic to hairpinned svc, need to unDNAT, send to table 2 if config.IPv4Mode { dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, table=5, ip, "+ + fmt.Sprintf("cookie=%s, table=5, %s, "+ "actions=ct(commit,zone=%d,nat,table=2)", - nodetypes.DefaultOpenFlowCookie, config.Default.HostMasqConntrackZone)) + nodetypes.DefaultOpenFlowCookie, protoPrefixV4, config.Default.HostMasqConntrackZone)) } if config.IPv6Mode { dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, table=5, ipv6, "+ + fmt.Sprintf("cookie=%s, table=5, %s, "+ "actions=ct(commit,zone=%d,nat,table=2)", - nodetypes.DefaultOpenFlowCookie, config.Default.HostMasqConntrackZone)) + nodetypes.DefaultOpenFlowCookie, protoPrefixV6, config.Default.HostMasqConntrackZone)) } return dftFlows, nil } @@ -478,18 +492,20 @@ func generateIPFragmentReassemblyFlow(ofPortPhys string) []string { flows := make([]string, 0, 2) if config.IPv4Mode { flows = append(flows, - fmt.Sprintf("cookie=%s, priority=110, table=0, in_port=%s, ip, nw_frag=yes, actions=ct(table=0,zone=%d)", + fmt.Sprintf("cookie=%s, priority=110, table=0, in_port=%s, %s, nw_frag=yes, actions=ct(table=0,zone=%d)", nodetypes.DefaultOpenFlowCookie, ofPortPhys, + protoPrefixV4, config.Default.ReassemblyConntrackZone, ), ) } if config.IPv6Mode { flows = append(flows, - fmt.Sprintf("cookie=%s, priority=110, table=0, in_port=%s, ipv6, nw_frag=yes, actions=ct(table=0,zone=%d)", + fmt.Sprintf("cookie=%s, priority=110, table=0, in_port=%s, %s, nw_frag=yes, actions=ct(table=0,zone=%d)", nodetypes.DefaultOpenFlowCookie, ofPortPhys, + protoPrefixV6, config.Default.ReassemblyConntrackZone, ), ) @@ -555,10 +571,10 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e // egressService pods will also undergo this SNAT to nodeIP since these features are tied // together at the OVN policy level on the distributed router. dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=105, in_port=%s, dl_src=%s, ip, pkt_mark=%s "+ + fmt.Sprintf("cookie=%s, priority=105, in_port=%s, dl_src=%s, %s, pkt_mark=%s "+ "actions=ct(commit, zone=%d, nat(src=%s), exec(set_field:%s->ct_mark)),output:%s", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, nodetypes.OvnKubeNodeSNATMark, - config.Default.ConntrackZone, physicalIP.IP, netConfig.MasqCTMark, ofPortPhys)) + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, protoPrefixV4, + nodetypes.OvnKubeNodeSNATMark, config.Default.ConntrackZone, physicalIP.IP, netConfig.MasqCTMark, ofPortPhys)) // table 0, packets coming from egressIP pods only from user defined networks. If an egressIP is assigned to // this node, then all networks get a flow even if no pods on that network were selected for by this egressIP. @@ -567,9 +583,9 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e if netConfig.MasqCTMark != nodetypes.CtMarkOVN { for mark, eip := range b.eipMarkIPs.GetIPv4() { dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=105, in_port=%s, dl_src=%s, ip, pkt_mark=%d, "+ + fmt.Sprintf("cookie=%s, priority=105, in_port=%s, dl_src=%s, %s, pkt_mark=%d, "+ "actions=ct(commit, zone=%d, nat(src=%s), exec(set_field:%s->ct_mark)), output:%s", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, mark, + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, protoPrefixV4, mark, config.Default.ConntrackZone, eip, netConfig.MasqCTMark, ofPortPhys)) } } @@ -579,10 +595,10 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e // so that reverse direction goes back to the pods. if netConfig.IsDefaultNetwork() { dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, in_port=%s, dl_src=%s, ip, "+ + fmt.Sprintf("cookie=%s, priority=100, in_port=%s, dl_src=%s, %s, "+ "actions=ct(commit, zone=%d, exec(set_field:%s->ct_mark)), output:%s", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, config.Default.ConntrackZone, - netConfig.MasqCTMark, ofPortPhys)) + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, protoPrefixV4, + config.Default.ConntrackZone, netConfig.MasqCTMark, ofPortPhys)) // Allow (a) OVN->host traffic on the same node // (b) host->host traffic on the same node @@ -592,9 +608,10 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e } else { // for UDN we additionally SNAT the packet from masquerade IP -> node IP dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, in_port=%s, dl_src=%s, ip, ip_src=%s, "+ + fmt.Sprintf("cookie=%s, priority=100, in_port=%s, dl_src=%s, %s, %s_src=%s, "+ "actions=ct(commit, zone=%d, nat(src=%s), exec(set_field:%s->ct_mark)), output:%s", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, netConfig.V4MasqIPs.GatewayRouter.IP, config.Default.ConntrackZone, + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, protoPrefixV4, protoPrefixV4, + netConfig.V4MasqIPs.GatewayRouter.IP, config.Default.ConntrackZone, physicalIP.IP, netConfig.MasqCTMark, ofPortPhys)) } } @@ -602,9 +619,10 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e // table 0, packets coming from host Commit connections with ct_mark CtMarkHost // so that reverse direction goes back to the host. dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, in_port=%s, ip, "+ + fmt.Sprintf("cookie=%s, priority=100, in_port=%s, %s, "+ "actions=ct(commit, zone=%d, exec(set_field:%s->ct_mark)), %soutput:%s", - nodetypes.DefaultOpenFlowCookie, ofPortHost, config.Default.ConntrackZone, nodetypes.CtMarkHost, mod_vlan_id, ofPortPhys)) + nodetypes.DefaultOpenFlowCookie, ofPortHost, protoPrefixV4, config.Default.ConntrackZone, + nodetypes.CtMarkHost, mod_vlan_id, ofPortPhys)) } if config.Gateway.Mode == config.GatewayModeLocal { for _, netConfig := range b.patchedNetConfigs() { @@ -636,8 +654,8 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e // resubmit to table 1 to know the state and mark of the connection. // Note, there are higher priority rules that take care of traffic coming from LOCAL and OVN ports. dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=50, ip, actions=ct(zone=%d, nat, table=1)", - nodetypes.DefaultOpenFlowCookie, config.Default.ConntrackZone)) + fmt.Sprintf("cookie=%s, priority=50, %s, actions=ct(zone=%d, nat, table=1)", + nodetypes.DefaultOpenFlowCookie, protoPrefixV4, config.Default.ConntrackZone)) } } @@ -654,9 +672,9 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e // egressService pods will also undergo this SNAT to nodeIP since these features are tied // together at the OVN policy level on the distributed router. dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=105, in_port=%s, dl_src=%s, ipv6, pkt_mark=%s "+ + fmt.Sprintf("cookie=%s, priority=105, in_port=%s, dl_src=%s, %s, pkt_mark=%s "+ "actions=ct(commit, zone=%d, nat(src=%s), exec(set_field:%s->ct_mark)),output:%s", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, nodetypes.OvnKubeNodeSNATMark, + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, protoPrefixV6, nodetypes.OvnKubeNodeSNATMark, config.Default.ConntrackZone, physicalIP.IP, netConfig.MasqCTMark, ofPortPhys)) // table 0, packets coming from egressIP pods only from user defined networks. If an egressIP is assigned to @@ -666,9 +684,9 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e if netConfig.MasqCTMark != nodetypes.CtMarkOVN { for mark, eip := range b.eipMarkIPs.GetIPv6() { dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=105, in_port=%s, dl_src=%s, ipv6, pkt_mark=%d, "+ + fmt.Sprintf("cookie=%s, priority=105, in_port=%s, dl_src=%s, %s, pkt_mark=%d, "+ "actions=ct(commit, zone=%d, nat(src=%s), exec(set_field:%s->ct_mark)), output:%s", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, mark, + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, protoPrefixV6, mark, config.Default.ConntrackZone, eip, netConfig.MasqCTMark, ofPortPhys)) } } @@ -678,9 +696,10 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e // so that reverse direction goes back to the pods. if netConfig.IsDefaultNetwork() { dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, in_port=%s, dl_src=%s, ipv6, "+ + fmt.Sprintf("cookie=%s, priority=100, in_port=%s, dl_src=%s, %s, "+ "actions=ct(commit, zone=%d, exec(set_field:%s->ct_mark)), output:%s", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, config.Default.ConntrackZone, netConfig.MasqCTMark, ofPortPhys)) + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, protoPrefixV6, + config.Default.ConntrackZone, netConfig.MasqCTMark, ofPortPhys)) // Allow (a) OVN->host traffic on the same node // (b) host->host traffic on the same node @@ -690,9 +709,10 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e } else { // for UDN we additionally SNAT the packet from masquerade IP -> node IP dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, in_port=%s, dl_src=%s, ipv6, ipv6_src=%s, "+ + fmt.Sprintf("cookie=%s, priority=100, in_port=%s, dl_src=%s, %s, %s_src=%s, "+ "actions=ct(commit, zone=%d, nat(src=%s), exec(set_field:%s->ct_mark)), output:%s", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, netConfig.V6MasqIPs.GatewayRouter.IP, config.Default.ConntrackZone, + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, bridgeMacAddress, protoPrefixV6, protoPrefixV6, + netConfig.V6MasqIPs.GatewayRouter.IP, config.Default.ConntrackZone, physicalIP.IP, netConfig.MasqCTMark, ofPortPhys)) } } @@ -700,9 +720,10 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e // table 0, packets coming from host. Commit connections with ct_mark CtMarkHost // so that reverse direction goes back to the host. dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=100, in_port=%s, ipv6, "+ + fmt.Sprintf("cookie=%s, priority=100, in_port=%s, %s, "+ "actions=ct(commit, zone=%d, exec(set_field:%s->ct_mark)), %soutput:%s", - nodetypes.DefaultOpenFlowCookie, ofPortHost, config.Default.ConntrackZone, nodetypes.CtMarkHost, mod_vlan_id, ofPortPhys)) + nodetypes.DefaultOpenFlowCookie, ofPortHost, protoPrefixV6, + config.Default.ConntrackZone, nodetypes.CtMarkHost, mod_vlan_id, ofPortPhys)) } if config.Gateway.Mode == config.GatewayModeLocal { @@ -710,17 +731,17 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e // table 0, any packet coming from OVN send to host in LGW mode, host will take care of sending it outside if needed. // exceptions are traffic for egressIP and egressGW features and ICMP related traffic which will hit the priority 100 flow instead of this. dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=175, in_port=%s, tcp6, ipv6_src=%s, "+ + fmt.Sprintf("cookie=%s, priority=175, in_port=%s, tcp6, %s_src=%s, "+ "actions=ct(table=4,zone=%d)", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, physicalIP.IP, config.Default.HostMasqConntrackZone)) + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, protoPrefixV6, physicalIP.IP, config.Default.HostMasqConntrackZone)) dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=175, in_port=%s, udp6, ipv6_src=%s, "+ + fmt.Sprintf("cookie=%s, priority=175, in_port=%s, udp6, %s_src=%s, "+ "actions=ct(table=4,zone=%d)", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, physicalIP.IP, config.Default.HostMasqConntrackZone)) + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, protoPrefixV6, physicalIP.IP, config.Default.HostMasqConntrackZone)) dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=175, in_port=%s, sctp6, ipv6_src=%s, "+ + fmt.Sprintf("cookie=%s, priority=175, in_port=%s, sctp6, %s_src=%s, "+ "actions=ct(table=4,zone=%d)", - nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, physicalIP.IP, config.Default.HostMasqConntrackZone)) + nodetypes.DefaultOpenFlowCookie, netConfig.OfPortPatch, protoPrefixV6, physicalIP.IP, config.Default.HostMasqConntrackZone)) if ofPortPhys != "" { // We send BFD traffic coming from OVN to outside directly using a higher priority flow dftFlows = append(dftFlows, @@ -733,8 +754,8 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e // table 0, packets coming from external. Send it through conntrack and // resubmit to table 1 to know the state and mark of the connection. dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=50, in_port=%s, ipv6, "+ - "actions=ct(zone=%d, nat, table=1)", nodetypes.DefaultOpenFlowCookie, ofPortPhys, config.Default.ConntrackZone)) + fmt.Sprintf("cookie=%s, priority=50, in_port=%s, %s, "+ + "actions=ct(zone=%d, nat, table=1)", nodetypes.DefaultOpenFlowCookie, ofPortPhys, protoPrefixV6, config.Default.ConntrackZone)) } } if ofPortPhys != "" { @@ -911,9 +932,9 @@ func (b *BridgeConfiguration) PMTUDDropFlows(ipAddrs []string) []string { } func getIPv(ipnet *net.IPNet) string { - prefix := "ip" + prefix := protoPrefixV4 if utilnet.IsIPv6CIDR(ipnet) { - prefix = "ipv6" + prefix = protoPrefixV6 } return prefix } @@ -929,10 +950,10 @@ func hostNetworkNormalActionFlows(netConfig *BridgeUDNConfiguration, srcMAC stri var ipFamily, ipFamilyDest string if isV6 { - ipFamily = "ipv6" - ipFamilyDest = "ipv6_dst" + ipFamily = protoPrefixV6 + ipFamilyDest = protoPrefixV6 + "_dst" } else { - ipFamily = "ip" + ipFamily = protoPrefixV4 ipFamilyDest = "nw_dst" } diff --git a/go-controller/pkg/node/gateway_shared_intf.go b/go-controller/pkg/node/gateway_shared_intf.go index 35e409618b..5d1d94cba6 100644 --- a/go-controller/pkg/node/gateway_shared_intf.go +++ b/go-controller/pkg/node/gateway_shared_intf.go @@ -41,6 +41,8 @@ import ( ) const ( + protoPrefixV4 = "ip" + protoPrefixV6 = "ipv6" // etpSvcOpenFlowCookie identifies constant open flow rules added to the host OVS // bridge to move packets between host and external for etp=local traffic. // The hex number 0xe745ecf105, represents etp(e74)-service(5ec)-flows which makes it easier for debugging. @@ -400,32 +402,37 @@ func (npw *nodePortWatcher) updateServiceFlowCache(service *corev1.Service, netI return utilerrors.Join(errors...) } - ipPrefix := "ip" - if !utilnet.IsIPv4String(service.Spec.ClusterIP) { - ipPrefix = "ipv6" - } - // table 2, user-defined network host -> OVN towards default cluster network services defaultNetConfig := npw.ofm.defaultBridge.GetActiveNetworkBridgeConfigCopy(types.DefaultNetworkName) - // sample flow: cookie=0xdeff105, duration=2319.685s, table=2, n_packets=496, n_bytes=67111, priority=300, - // ip,nw_dst=10.96.0.1 actions=mod_dl_dst:02:42:ac:12:00:03,output:"patch-breth0_ov" - // This flow is used for UDNs and advertised UDNs to be able to reach kapi and dns services alone on default network - flows := []string{fmt.Sprintf("cookie=%s, priority=300, table=2, %s, %s_dst=%s, "+ - "actions=set_field:%s->eth_dst,output:%s", - nodetypes.DefaultOpenFlowCookie, ipPrefix, ipPrefix, service.Spec.ClusterIP, - npw.ofm.getDefaultBridgeMAC().String(), defaultNetConfig.OfPortPatch)} - if util.IsRouteAdvertisementsEnabled() { - // if the network is advertised, then for the reply from kapi and dns services to go back - // into the UDN's VRF we need flows that statically send this to the local port - // sample flow: cookie=0xdeff105, duration=264.196s, table=0, n_packets=0, n_bytes=0, priority=490,ip, - // in_port="patch-breth0_ov",nw_src=10.96.0.10,actions=ct(table=3,zone=64001,nat) - // this flow is meant to match all advertised UDNs and then the ip rules on the host will take - // this packet into the corresponding UDNs - // NOTE: We chose priority 490 to differentiate this flow from the flow at priority 500 added for the - // non-advertised UDNs reponse for debugging purposes: - // sample flow for non-advertised UDNs: cookie=0xdeff105, duration=684.087s, table=0, n_packets=0, n_bytes=0, - // idle_age=684, priority=500,ip,in_port=2,nw_src=10.96.0.0/16,nw_dst=169.254.0.0/17 actions=ct(table=3,zone=64001,nat) - flows = append(flows, fmt.Sprintf("cookie=%s, priority=490, in_port=%s, ip, ip_src=%s,actions=ct(zone=%d,nat,table=3)", - nodetypes.DefaultOpenFlowCookie, defaultNetConfig.OfPortPatch, service.Spec.ClusterIP, config.Default.HostMasqConntrackZone)) + var flows []string + clusterIPs := util.GetClusterIPs(service) + for _, clusterIP := range clusterIPs { + ipPrefix := protoPrefixV4 + if utilnet.IsIPv6String(clusterIP) { + ipPrefix = protoPrefixV6 + } + // table 2, user-defined network host -> OVN towards default cluster network services + // sample flow: cookie=0xdeff105, duration=2319.685s, table=2, n_packets=496, n_bytes=67111, priority=300, + // ip,nw_dst=10.96.0.1 actions=mod_dl_dst:02:42:ac:12:00:03,output:"patch-breth0_ov" + // This flow is used for UDNs and advertised UDNs to be able to reach kapi and dns services alone on default network + flows = append(flows, fmt.Sprintf("cookie=%s, priority=300, table=2, %s, %s_dst=%s, "+ + "actions=set_field:%s->eth_dst,output:%s", + nodetypes.DefaultOpenFlowCookie, ipPrefix, ipPrefix, clusterIP, + npw.ofm.getDefaultBridgeMAC().String(), defaultNetConfig.OfPortPatch)) + + if util.IsRouteAdvertisementsEnabled() { + // if the network is advertised, then for the reply from kapi and dns services to go back + // into the UDN's VRF we need flows that statically send this to the local port + // sample flow: cookie=0xdeff105, duration=264.196s, table=0, n_packets=0, n_bytes=0, priority=490,ip, + // in_port="patch-breth0_ov",nw_src=10.96.0.10,actions=ct(table=3,zone=64001,nat) + // this flow is meant to match all advertised UDNs and then the ip rules on the host will take + // this packet into the corresponding UDNs + // NOTE: We chose priority 490 to differentiate this flow from the flow at priority 500 added for the + // non-advertised UDNs reponse for debugging purposes: + // sample flow for non-advertised UDNs: cookie=0xdeff105, duration=684.087s, table=0, n_packets=0, n_bytes=0, + // idle_age=684, priority=500,ip,in_port=2,nw_src=10.96.0.0/16,nw_dst=169.254.0.0/17 actions=ct(table=3,zone=64001,nat) + flows = append(flows, fmt.Sprintf("cookie=%s, priority=490, in_port=%s, %s, %s_src=%s,actions=ct(zone=%d,nat,table=3)", + nodetypes.DefaultOpenFlowCookie, defaultNetConfig.OfPortPatch, ipPrefix, ipPrefix, clusterIP, config.Default.HostMasqConntrackZone)) + } } npw.ofm.updateFlowCacheEntry(key, flows) } diff --git a/go-controller/pkg/node/gateway_udn_test.go b/go-controller/pkg/node/gateway_udn_test.go index 4611ea97ed..984a666195 100644 --- a/go-controller/pkg/node/gateway_udn_test.go +++ b/go-controller/pkg/node/gateway_udn_test.go @@ -101,6 +101,12 @@ func setManagementPortFakeCommands(fexec *ovntest.FakeExec, nodeName string) { Cmd: "ip route replace table 7 172.16.1.0/24 via 100.128.0.1 dev ovn-k8s-mp0", Output: "0", }) + if config.IPv6Mode { + fexec.AddFakeCmd(&ovntest.ExpectedCmd{ + Cmd: "ip route replace table 7 fd02::/112 via ae70::1 dev ovn-k8s-mp0", + Output: "0", + }) + } fexec.AddFakeCmd(&ovntest.ExpectedCmd{ Cmd: "ip -4 rule", Output: "0", @@ -276,6 +282,10 @@ var _ = Describe("UserDefinedNetworkGateway", func() { // Restore global default values before each testcase err := config.PrepareTestConfig() Expect(err).NotTo(HaveOccurred()) + + // Set dual-stack service CIDRs directly after PrepareTestConfig + config.Kubernetes.ServiceCIDRs = ovntest.MustParseIPNets("172.16.1.0/24", "fd02::/112") + config.OVNKubernetesFeature.EnableMultiNetwork = true config.OVNKubernetesFeature.EnableNetworkSegmentation = true // Use a larger masq subnet to allow OF manager to allocate IPs for UDNs. @@ -653,7 +663,7 @@ var _ = Describe("UserDefinedNetworkGateway", func() { &kubeMock, vrf, ipRulesManager, localGw) Expect(err).NotTo(HaveOccurred()) flowMap := udnGateway.gateway.openflowManager.flowCache - Expect(flowMap["DEFAULT"]).To(HaveLen(46)) + Expect(flowMap["DEFAULT"]).To(HaveLen(50)) Expect(udnGateway.masqCTMark).To(Equal(udnGateway.masqCTMark)) var udnFlows int @@ -671,7 +681,7 @@ var _ = Describe("UserDefinedNetworkGateway", func() { Expect(udnGateway.AddNetwork()).To(Succeed()) flowMap = udnGateway.gateway.openflowManager.flowCache - Expect(flowMap["DEFAULT"]).To(HaveLen(64)) // 18 UDN Flows are added by default + Expect(flowMap["DEFAULT"]).To(HaveLen(70)) // 18 UDN Flows are added by default Expect(udnGateway.openflowManager.defaultBridge.GetNetConfigLen()).To(Equal(2)) // default network + UDN network defaultUdnConfig := udnGateway.openflowManager.defaultBridge.GetNetworkConfig("default") bridgeUdnConfig := udnGateway.openflowManager.defaultBridge.GetNetworkConfig("bluenet") @@ -687,7 +697,7 @@ var _ = Describe("UserDefinedNetworkGateway", func() { } } } - Expect(udnFlows).To(Equal(14)) + Expect(udnFlows).To(Equal(16)) openflowManagerCheckPorts(udnGateway.openflowManager) for _, svcCIDR := range config.Kubernetes.ServiceCIDRs { @@ -707,7 +717,7 @@ var _ = Describe("UserDefinedNetworkGateway", func() { kubeMock.On("UpdateNodeStatus", cnode).Return(nil) // check if network key gets deleted from annotation Expect(udnGateway.DelNetwork()).To(Succeed()) flowMap = udnGateway.gateway.openflowManager.flowCache - Expect(flowMap["DEFAULT"]).To(HaveLen(46)) // only default network flows are present + Expect(flowMap["DEFAULT"]).To(HaveLen(50)) // only default network flows are present Expect(udnGateway.openflowManager.defaultBridge.GetNetConfigLen()).To(Equal(1)) // default network only udnFlows = 0 for _, flows := range flowMap { @@ -885,7 +895,7 @@ var _ = Describe("UserDefinedNetworkGateway", func() { &kubeMock, vrf, ipRulesManager, localGw) Expect(err).NotTo(HaveOccurred()) flowMap := udnGateway.gateway.openflowManager.flowCache - Expect(flowMap["DEFAULT"]).To(HaveLen(46)) + Expect(flowMap["DEFAULT"]).To(HaveLen(50)) Expect(udnGateway.masqCTMark).To(Equal(udnGateway.masqCTMark)) var udnFlows int for _, flows := range flowMap { @@ -902,7 +912,7 @@ var _ = Describe("UserDefinedNetworkGateway", func() { Expect(udnGateway.AddNetwork()).To(Succeed()) flowMap = udnGateway.gateway.openflowManager.flowCache - Expect(flowMap["DEFAULT"]).To(HaveLen(64)) // 18 UDN Flows are added by default + Expect(flowMap["DEFAULT"]).To(HaveLen(70)) // 18 UDN Flows are added by default Expect(udnGateway.openflowManager.defaultBridge.GetNetConfigLen()).To(Equal(2)) // default network + UDN network defaultUdnConfig := udnGateway.openflowManager.defaultBridge.GetNetworkConfig("default") bridgeUdnConfig := udnGateway.openflowManager.defaultBridge.GetNetworkConfig("bluenet") @@ -918,7 +928,7 @@ var _ = Describe("UserDefinedNetworkGateway", func() { } } } - Expect(udnFlows).To(Equal(14)) + Expect(udnFlows).To(Equal(16)) openflowManagerCheckPorts(udnGateway.openflowManager) for _, svcCIDR := range config.Kubernetes.ServiceCIDRs { @@ -938,7 +948,7 @@ var _ = Describe("UserDefinedNetworkGateway", func() { kubeMock.On("UpdateNodeStatus", cnode).Return(nil) // check if network key gets deleted from annotation Expect(udnGateway.DelNetwork()).To(Succeed()) flowMap = udnGateway.gateway.openflowManager.flowCache - Expect(flowMap["DEFAULT"]).To(HaveLen(46)) // only default network flows are present + Expect(flowMap["DEFAULT"]).To(HaveLen(50)) // only default network flows are present Expect(udnGateway.openflowManager.defaultBridge.GetNetConfigLen()).To(Equal(1)) // default network only udnFlows = 0 for _, flows := range flowMap { @@ -1125,7 +1135,7 @@ var _ = Describe("UserDefinedNetworkGateway", func() { &kubeMock, vrf, ipRulesManager, localGw) Expect(err).NotTo(HaveOccurred()) flowMap := udnGateway.gateway.openflowManager.flowCache - Expect(flowMap["DEFAULT"]).To(HaveLen(46)) + Expect(flowMap["DEFAULT"]).To(HaveLen(50)) Expect(udnGateway.masqCTMark).To(Equal(udnGateway.masqCTMark)) var udnFlows int @@ -1143,7 +1153,7 @@ var _ = Describe("UserDefinedNetworkGateway", func() { Expect(udnGateway.AddNetwork()).To(Succeed()) flowMap = udnGateway.gateway.openflowManager.flowCache - Expect(flowMap["DEFAULT"]).To(HaveLen(73)) // 18 UDN Flows, 5 advertisedUDN flows, and 2 packet mark flows (IPv4+IPv6) are added by default + Expect(flowMap["DEFAULT"]).To(HaveLen(80)) // 18 UDN Flows, 5 advertisedUDN flows, and 2 packet mark flows (IPv4+IPv6) are added by default Expect(udnGateway.openflowManager.defaultBridge.GetNetConfigLen()).To(Equal(2)) // default network + UDN network defaultUdnConfig := udnGateway.openflowManager.defaultBridge.GetNetworkConfig("default") bridgeUdnConfig := udnGateway.openflowManager.defaultBridge.GetNetworkConfig("bluenet") @@ -1159,7 +1169,7 @@ var _ = Describe("UserDefinedNetworkGateway", func() { } } } - Expect(udnFlows).To(Equal(16)) + Expect(udnFlows).To(Equal(18)) openflowManagerCheckPorts(udnGateway.openflowManager) for _, svcCIDR := range config.Kubernetes.ServiceCIDRs { @@ -1181,7 +1191,7 @@ var _ = Describe("UserDefinedNetworkGateway", func() { kubeMock.On("UpdateNodeStatus", cnode).Return(nil) // check if network key gets deleted from annotation Expect(udnGateway.DelNetwork()).To(Succeed()) flowMap = udnGateway.gateway.openflowManager.flowCache - Expect(flowMap["DEFAULT"]).To(HaveLen(46)) // only default network flows are present + Expect(flowMap["DEFAULT"]).To(HaveLen(50)) // only default network flows are present Expect(udnGateway.openflowManager.defaultBridge.GetNetConfigLen()).To(Equal(1)) // default network only udnFlows = 0 for _, flows := range flowMap { @@ -1237,39 +1247,44 @@ var _ = Describe("UserDefinedNetworkGateway", func() { routes, err := udnGateway.computeRoutesForUDN(mplink) Expect(err).NotTo(HaveOccurred()) - Expect(routes).To(HaveLen(9)) - Expect(err).NotTo(HaveOccurred()) + Expect(routes).To(HaveLen(10)) + Expect(*routes[0].Dst).To(Equal(*ovntest.MustParseIPNet("172.16.1.0/24"))) // default service subnet Expect(routes[0].LinkIndex).To(Equal(bridgelink.Attrs().Index)) Expect(routes[0].Gw).To(Equal(config.Gateway.MasqueradeIPs.V4DummyNextHopMasqueradeIP)) + + Expect(*routes[1].Dst).To(Equal(*ovntest.MustParseIPNet("fd02::/112"))) // default service subnet + Expect(routes[1].LinkIndex).To(Equal(bridgelink.Attrs().Index)) + Expect(routes[1].Gw).To(Equal(config.Gateway.MasqueradeIPs.V6DummyNextHopMasqueradeIP)) + cidr, err := util.GetIPNetFullMask("169.254.0.16") Expect(err).NotTo(HaveOccurred()) - Expect(*routes[1].Dst).To(Equal(*cidr)) - Expect(routes[1].LinkIndex).To(Equal(mplink.Attrs().Index)) - cidr, err = util.GetIPNetFullMask("fd69::10") - Expect(err).NotTo(HaveOccurred()) Expect(*routes[2].Dst).To(Equal(*cidr)) Expect(routes[2].LinkIndex).To(Equal(mplink.Attrs().Index)) - - // IPv4 ETP=Local service masquerade IP route - Expect(*routes[3].Dst).To(Equal(*ovntest.MustParseIPNet("169.254.169.3/32"))) // ETP=Local svc masq IP + cidr, err = util.GetIPNetFullMask("fd69::10") + Expect(err).NotTo(HaveOccurred()) + Expect(*routes[3].Dst).To(Equal(*cidr)) Expect(routes[3].LinkIndex).To(Equal(mplink.Attrs().Index)) - Expect(routes[3].Gw.Equal(ovntest.MustParseIP("100.128.0.1"))).To(BeTrue()) - // IPv4 cluster subnet route - Expect(*routes[4].Dst).To(Equal(*ovntest.MustParseIPNet("100.128.0.0/16"))) // cluster subnet route + // IPv4 ETP=Local service masquerade IP route + Expect(*routes[4].Dst).To(Equal(*ovntest.MustParseIPNet("169.254.169.3/32"))) // ETP=Local svc masq IP Expect(routes[4].LinkIndex).To(Equal(mplink.Attrs().Index)) Expect(routes[4].Gw.Equal(ovntest.MustParseIP("100.128.0.1"))).To(BeTrue()) - // IPv6 ETP=Local service masquerade IP route - Expect(*routes[5].Dst).To(Equal(*ovntest.MustParseIPNet("fd69::3/128"))) // ETP=Local svc masq IP + // IPv4 cluster subnet route + Expect(*routes[5].Dst).To(Equal(*ovntest.MustParseIPNet("100.128.0.0/16"))) // cluster subnet route Expect(routes[5].LinkIndex).To(Equal(mplink.Attrs().Index)) - Expect(routes[5].Gw.Equal(ovntest.MustParseIP("ae70::1"))).To(BeTrue()) + Expect(routes[5].Gw.Equal(ovntest.MustParseIP("100.128.0.1"))).To(BeTrue()) - // IPv6 cluster subnet route - Expect(*routes[6].Dst).To(Equal(*ovntest.MustParseIPNet("ae70::/60"))) // cluster subnet route + // IPv6 ETP=Local service masquerade IP route + Expect(*routes[6].Dst).To(Equal(*ovntest.MustParseIPNet("fd69::3/128"))) // ETP=Local svc masq IP Expect(routes[6].LinkIndex).To(Equal(mplink.Attrs().Index)) Expect(routes[6].Gw.Equal(ovntest.MustParseIP("ae70::1"))).To(BeTrue()) + + // IPv6 cluster subnet route + Expect(*routes[7].Dst).To(Equal(*ovntest.MustParseIPNet("ae70::/60"))) // cluster subnet route + Expect(routes[7].LinkIndex).To(Equal(mplink.Attrs().Index)) + Expect(routes[7].Gw.Equal(ovntest.MustParseIP("ae70::1"))).To(BeTrue()) return nil }) Expect(err).NotTo(HaveOccurred()) @@ -1394,11 +1409,11 @@ var _ = Describe("UserDefinedNetworkGateway", func() { routes, err := udnGateway.computeRoutesForUDN(mplink) Expect(err).NotTo(HaveOccurred()) - Expect(routes).To(HaveLen(10)) + Expect(routes).To(HaveLen(11)) Expect(err).NotTo(HaveOccurred()) - Expect(*routes[1].Dst).To(Equal(*ovntest.MustParseIPNet("0.0.0.0/0"))) - Expect(routes[1].LinkIndex).To(Equal(bridgelink.Attrs().Index)) - Expect(routes[1].Gw.Equal(ovntest.MustParseIP(config.Gateway.NextHop))).To(BeTrue()) + Expect(*routes[2].Dst).To(Equal(*ovntest.MustParseIPNet("0.0.0.0/0"))) + Expect(routes[2].LinkIndex).To(Equal(bridgelink.Attrs().Index)) + Expect(routes[2].Gw.Equal(ovntest.MustParseIP(config.Gateway.NextHop))).To(BeTrue()) return nil }) Expect(err).NotTo(HaveOccurred()) @@ -1437,7 +1452,7 @@ var _ = Describe("UserDefinedNetworkGateway", func() { routes, err := udnGateway.computeRoutesForUDN(mplink) Expect(err).NotTo(HaveOccurred()) - Expect(routes).To(HaveLen(9)) + Expect(routes).To(HaveLen(10)) Expect(err).NotTo(HaveOccurred()) Expect(*routes[1].Dst).To(Not(Equal(*ovntest.MustParseIPNet("0.0.0.0/0")))) Expect(routes[1].Gw.Equal(ovntest.MustParseIP(config.Gateway.NextHop))).To(BeFalse()) diff --git a/go-controller/pkg/node/secondary_node_network_controller_test.go b/go-controller/pkg/node/secondary_node_network_controller_test.go index bd0fbaab09..6966e31a58 100644 --- a/go-controller/pkg/node/secondary_node_network_controller_test.go +++ b/go-controller/pkg/node/secondary_node_network_controller_test.go @@ -166,7 +166,7 @@ var _ = Describe("SecondaryNodeNetworkController: UserDefinedPrimaryNetwork Gate routeManager *routemanager.Controller ipRulesManager *iprulemanager.Controller v4NodeSubnet = "100.128.0.0/24" - v6NodeSubnet = "ae70::66/112" + v6NodeSubnet = "ae70::/112" mgtPort = fmt.Sprintf("%s%d", types.K8sMgmtIntfNamePrefix, netID) gatewayInterface = "eth0" gatewayBridge = "breth0" @@ -270,6 +270,7 @@ var _ = Describe("SecondaryNodeNetworkController: UserDefinedPrimaryNetwork Gate config.IPv6Mode = true config.IPv4Mode = true config.Gateway.NodeportEnable = true + config.Kubernetes.ServiceCIDRs = ovntest.MustParseIPNets("172.16.1.0/24", "fd02::/112") ifAddrs := ovntest.MustParseIPNets(v4NodeIP, v6NodeIP) By("creating necessary mocks")