Skip to content

Commit 82850ed

Browse files
committed
Enable Layer2 route advertisements on LGW
Configure use_ct_inv_match=false on nbdb when route advertisements are enabled in LGW to support assymetric traffic on Layer2 advertised networks. Signed-off-by: Patryk Diak <[email protected]>
1 parent afd53ab commit 82850ed

File tree

4 files changed

+39
-26
lines changed

4 files changed

+39
-26
lines changed

dist/images/ovnkube.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,11 @@ local-nb-ovsdb() {
989989
wait_for_event attempts=3 process_ready ovnnb_db
990990
echo "=============== nb-ovsdb (unix sockets only) ========== RUNNING"
991991

992+
[[ "local" == "${OVN_GATEWAY_MODE}" && "true" == "${OVN_ROUTE_ADVERTISEMENTS_ENABLE}" ]] && {
993+
ovn-nbctl set NB_Global . options:use_ct_inv_match=false
994+
echo "=============== nb-ovsdb ========== reconfigured for route advertisements"
995+
}
996+
992997
# Let ovn-northd sleep and not use so much CPU
993998
ovn-nbctl set NB_Global . options:northd-backoff-interval-ms=${ovn_northd_backoff_interval}
994999
echo "=============== nb-ovsdb ========== reconfigured for northd backoff"

dist/templates/ovnkube-single-node-zone.yaml.j2

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ spec:
7979
value: "{{ ovn_loglevel_nb }}"
8080
- name: OVN_NORTHD_BACKOFF_INTERVAL
8181
value: "{{ ovn_northd_backoff_interval }}"
82+
- name: OVN_GATEWAY_MODE
83+
value: "{{ ovn_gateway_mode }}"
84+
- name: OVN_ROUTE_ADVERTISEMENTS_ENABLE
85+
value: "{{ ovn_route_advertisements_enable }}"
8286
- name: K8S_APISERVER
8387
valueFrom:
8488
configMapKeyRef:

go-controller/pkg/clustermanager/routeadvertisements/controller.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -373,10 +373,6 @@ func (c *Controller) generateFRRConfigurations(ra *ratypes.RouteAdvertisements)
373373
return nil, nil, fmt.Errorf("%w: selected network %q has unsupported topology %q", errConfig, networkName, network.TopologyType())
374374
}
375375

376-
if config.Gateway.Mode == config.GatewayModeLocal && network.TopologyType() == types.Layer2Topology {
377-
return nil, nil, fmt.Errorf("%w: BGP is currently not supported for Layer2 networks in local gateway mode, network: %s", errConfig, network.GetNetworkName())
378-
}
379-
380376
if advertisements.Has(ratypes.EgressIP) && network.TopologyType() == types.Layer2Topology {
381377
return nil, nil, fmt.Errorf("%w: EgressIP advertisement is currently not supported for Layer2 networks, network: %s", errConfig, network.GetNetworkName())
382378
}

test/e2e/route_advertisements.go

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -299,11 +299,6 @@ var _ = ginkgo.Describe("BGP: Pod to external server when CUDN network is advert
299299
Values: []string{f.Namespace.Name},
300300
}}}
301301

302-
if IsGatewayModeLocal(f.ClientSet) && cudnTemplate.Spec.Network.Topology == udnv1.NetworkTopologyLayer2 {
303-
e2eskipper.Skipf(
304-
"BGP for L2 networks on LGW is currently unsupported",
305-
)
306-
}
307302
// Create CUDN
308303
ginkgo.By("create ClusterUserDefinedNetwork")
309304
udnClient, err := udnclientset.NewForConfig(f.ClientConfig())
@@ -521,6 +516,10 @@ var _ = ginkgo.Describe("BGP: Pod to external server when CUDN network is advert
521516
var _ = ginkgo.DescribeTableSubtree("BGP: isolation between advertised networks",
522517
func(cudnATemplate, cudnBTemplate *udnv1.ClusterUserDefinedNetwork) {
523518
const curlConnectionTimeoutCode = "28"
519+
const (
520+
ipFamilyV4 = iota
521+
ipFamilyV6
522+
)
524523

525524
f := wrappedTestFramework("bpp-network-isolation")
526525
f.SkipNamespaceCreation = true
@@ -536,9 +535,6 @@ var _ = ginkgo.DescribeTableSubtree("BGP: isolation between advertised networks"
536535
var ra *rav1.RouteAdvertisements
537536
var hostNetworkPort int
538537
ginkgo.BeforeEach(func() {
539-
if cudnATemplate.Spec.Network.Topology == udnv1.NetworkTopologyLayer2 && isLocalGWModeEnabled() {
540-
e2eskipper.Skipf("Advertising Layer2 UDNs is not currently supported in LGW")
541-
}
542538
ginkgo.By("Configuring primary UDN namespaces")
543539
var err error
544540
udnNamespaceA, err = f.CreateNamespace(context.TODO(), f.BaseName, map[string]string{
@@ -700,9 +696,6 @@ var _ = ginkgo.DescribeTableSubtree("BGP: isolation between advertised networks"
700696
})
701697

702698
ginkgo.AfterEach(func() {
703-
if cudnATemplate.Spec.Network.Topology == udnv1.NetworkTopologyLayer2 && isLocalGWModeEnabled() {
704-
return
705-
}
706699
gomega.Expect(f.ClientSet.CoreV1().Pods(udnNamespaceA.Name).DeleteCollection(context.Background(), metav1.DeleteOptions{}, metav1.ListOptions{})).To(gomega.Succeed())
707700
gomega.Expect(f.ClientSet.CoreV1().Pods(udnNamespaceB.Name).DeleteCollection(context.Background(), metav1.DeleteOptions{}, metav1.ListOptions{})).To(gomega.Succeed())
708701

@@ -779,7 +772,7 @@ var _ = ginkgo.DescribeTableSubtree("BGP: isolation between advertised networks"
779772
framework.Logf("Connectivity check successful:'%s' -> %s", client, targetAddress)
780773
return out, nil
781774
}
782-
clientName, clientNamespace, dst, expectedOutput, expectErr := connInfo(0)
775+
clientName, clientNamespace, dst, expectedOutput, expectErr := connInfo(ipFamilyV4)
783776

784777
asyncAssertion := gomega.Eventually
785778
timeout := time.Second * 30
@@ -800,7 +793,7 @@ var _ = ginkgo.DescribeTableSubtree("BGP: isolation between advertised networks"
800793
}
801794
if isIPv6Supported() && isIPv4Supported() {
802795
// use ipFamilyIndex of 1 to pick the IPv6 addresses
803-
clientName, clientNamespace, dst, expectedOutput, expectErr := connInfo(1)
796+
clientName, clientNamespace, dst, expectedOutput, expectErr := connInfo(ipFamilyV6)
804797
out, err := checkConnectivity(clientName, clientNamespace, dst)
805798
if expectErr != (err != nil) {
806799
return fmt.Errorf("expected connectivity check to return error(%t), got %v, output %v", expectErr, err, out)
@@ -906,7 +899,16 @@ var _ = ginkgo.DescribeTableSubtree("BGP: isolation between advertised networks"
906899
}),
907900
ginkgo.Entry("pod in the UDN should not be able to access a service in a different UDN",
908901
func(ipFamilyIndex int) (clientName string, clientNamespace string, dst string, expectedOutput string, expectErr bool) {
909-
return podsNetA[0].Name, podsNetA[0].Namespace, net.JoinHostPort(svcNetB.Spec.ClusterIPs[ipFamilyIndex], "8080") + "/clientip", curlConnectionTimeoutCode, true
902+
err := true
903+
out := curlConnectionTimeoutCode
904+
if cudnATemplate.Spec.Network.Topology == udnv1.NetworkTopologyLayer2 && isLocalGWModeEnabled() {
905+
// FIXME: prevent looping of traffic in L2 UDNs
906+
// bad behaviour: packet is looping from management port -> breth0 -> GR -> management port -> breth0 and so on
907+
// which is a never ending loop
908+
// this causes curl timeout with code 7 host unreachable instead of code 28
909+
out = ""
910+
}
911+
return podsNetA[0].Name, podsNetA[0].Namespace, net.JoinHostPort(svcNetB.Spec.ClusterIPs[ipFamilyIndex], "8080") + "/clientip", out, err
910912
}),
911913
ginkgo.Entry("host to a local UDN pod should not work",
912914
func(ipFamilyIndex int) (clientName string, clientNamespace string, dst string, expectedOutput string, expectErr bool) {
@@ -963,14 +965,20 @@ var _ = ginkgo.DescribeTableSubtree("BGP: isolation between advertised networks"
963965
errBool := false
964966
out := ""
965967
if cudnATemplate.Spec.Network.Topology == udnv1.NetworkTopologyLayer2 {
966-
// FIXME: fix assymmetry in L2 UDNs
967-
// bad behaviour: packet is coming from other node -> entering eth0 -> bretho and here kernel drops the packet since
968-
// rp_filter is set to 1 in breth0 and there is an iprule that sends the packet to mpX interface so kernel sees the packet
969-
// having return path different from the incoming interface.
970-
// The SNAT to nodeIP should fix this.
971-
// this causes curl timeout with code 28
972-
errBool = true
973-
out = curlConnectionTimeoutCode
968+
// FIXME: this should be removed once we add the SNAT for pod->node traffic
969+
// We now permit asymmetric traffic on LGW. This prevents the issue from occurring with IPv6.
970+
// However, for IPv4 LGW rp_filter is still blocking the replies.
971+
// The situation is different on SGW as we don't allow asymmetric traffic at all, which is why IPv6 traffic fails there too.
972+
if ipFamilyIndex == ipFamilyV4 || !isLocalGWModeEnabled() {
973+
// FIXME: fix assymmetry in L2 UDNs
974+
// bad behaviour: packet is coming from other node -> entering eth0 -> bretho and here kernel drops the packet since
975+
// rp_filter is set to 1 in breth0 and there is an iprule that sends the packet to mpX interface so kernel sees the packet
976+
// having return path different from the incoming interface.
977+
// The SNAT to nodeIP should fix this.
978+
// this causes curl timeout with code 28
979+
errBool = true
980+
out = curlConnectionTimeoutCode
981+
}
974982
}
975983
return clientPod.Name, clientPod.Namespace, net.JoinHostPort(nodeIP, fmt.Sprint(hostNetworkPort)) + "/hostname", out, errBool
976984
}),

0 commit comments

Comments
 (0)