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

[WIP] UDN: L2: Add missing remote LRPs: One step closer towards making external->services work on L2! #4777

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
85 changes: 78 additions & 7 deletions go-controller/pkg/ovn/secondary_layer2_network_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"net"
"reflect"
"strconv"
"sync"
"time"

Expand Down Expand Up @@ -113,7 +114,7 @@ func (h *secondaryLayer2NetworkControllerEventHandler) AddResource(obj interface
}
return h.oc.addUpdateLocalNodeEvent(node, nodeParams)
}
return h.oc.addUpdateRemoteNodeEvent(node)
return h.oc.addUpdateRemoteNodeEvent(node, config.OVNKubernetesFeature.EnableInterconnect)
default:
return h.oc.AddSecondaryNetworkResourceCommon(h.objType, obj)
}
Expand Down Expand Up @@ -176,7 +177,8 @@ func (h *secondaryLayer2NetworkControllerEventHandler) UpdateResource(oldObj, ne

return h.oc.addUpdateLocalNodeEvent(newNode, nodeSyncsParam)
} else {
return h.oc.addUpdateRemoteNodeEvent(newNode)
_, syncZoneIC := h.oc.syncZoneICFailed.Load(newNode.Name)
return h.oc.addUpdateRemoteNodeEvent(newNode, syncZoneIC)
}
default:
return h.oc.UpdateSecondaryNetworkResourceCommon(h.objType, oldObj, newObj, inRetryCache)
Expand Down Expand Up @@ -231,8 +233,9 @@ type SecondaryLayer2NetworkController struct {
BaseSecondaryLayer2NetworkController

// Node-specific syncMaps used by node event handler
mgmtPortFailed sync.Map
gatewaysFailed sync.Map
mgmtPortFailed sync.Map
gatewaysFailed sync.Map
syncZoneICFailed sync.Map

// Cluster-wide router default Control Plane Protection (COPP) UUID
defaultCOPPUUID string
Expand Down Expand Up @@ -309,9 +312,10 @@ func NewSecondaryLayer2NetworkController(cnci *CommonNetworkControllerInfo, netI
},
},
},
mgmtPortFailed: sync.Map{},
gatewayManagers: sync.Map{},
svcController: svcController,
mgmtPortFailed: sync.Map{},
syncZoneICFailed: sync.Map{},
gatewayManagers: sync.Map{},
svcController: svcController,
}

if config.OVNKubernetesFeature.EnableInterconnect {
Expand Down Expand Up @@ -552,6 +556,73 @@ func (oc *SecondaryLayer2NetworkController) addUpdateLocalNodeEvent(node *corev1
return err
}

func (oc *SecondaryLayer2NetworkController) addUpdateRemoteNodeEvent(node *corev1.Node, syncZoneIC bool) error {
var errs []error

if util.IsNetworkSegmentationSupportEnabled() && oc.IsPrimaryNetwork() {
if syncZoneIC && config.OVNKubernetesFeature.EnableInterconnect {
if err := oc.addPortForRemoteNodeGR(node); err != nil {
err = fmt.Errorf("failed to add the remote zone node [%s] to the zone interconnect handler, err : %v", node.Name, err)
errs = append(errs, err)
oc.syncZoneICFailed.Store(node.Name, true)
} else {
oc.syncZoneICFailed.Delete(node.Name)
}
}
}

errs = append(errs, oc.BaseSecondaryLayer2NetworkController.addUpdateRemoteNodeEvent(node))

err := utilerrors.Join(errs...)
if err != nil {
oc.recordNodeErrorEvent(node, err)
}
return err
}

func (oc *SecondaryLayer2NetworkController) addPortForRemoteNodeGR(node *corev1.Node) error {
nodeJoinSubnetIPs, err := util.ParseNodeGatewayRouterJoinAddrs(node, oc.GetNetworkName())
if err != nil || len(nodeJoinSubnetIPs) == 0 {
return fmt.Errorf("failed to get the node %s join subnet IPs : %w", node.Name, err)
}

remoteGRPortMac := util.IPAddrToHWAddr(nodeJoinSubnetIPs[0].IP)
var remoteGRPortNetworks []string
for _, ip := range nodeJoinSubnetIPs {
remoteGRPortNetworks = append(remoteGRPortNetworks, ip.String())
}

remotePortAddr := remoteGRPortMac.String()
for _, tsNetwork := range remoteGRPortNetworks {
remotePortAddr = remotePortAddr + " " + tsNetwork
}
logicalSwitchPort := nbdb.LogicalSwitchPort{
Name: types.SwitchToRouterPrefix + oc.GetNetworkScopedSwitchName(types.OVNLayer2Switch) + "_" + node.Name,
Type: "remote",
Addresses: []string{remotePortAddr},
}
logicalSwitchPort.ExternalIDs = map[string]string{
types.NetworkExternalID: oc.GetNetworkName(),
types.TopologyExternalID: oc.TopologyType(),
"node": node.Name,
}
nodeID := util.GetNodeID(node)
if nodeID == -1 {
// Don't consider this node as cluster-manager has not allocated node id yet.
return fmt.Errorf("failed to get node id for node - %s", node.Name)
}
logicalSwitchPort.Options = map[string]string{
"requested-tnl-key": strconv.Itoa(types.MaxLogicalPortTunnelKey - nodeID),
"requested-chassis": node.Name,
}
sw := nbdb.LogicalSwitch{Name: oc.GetNetworkScopedSwitchName(types.OVNLayer2Switch)}
err = libovsdbops.CreateOrUpdateLogicalSwitchPortsOnSwitch(oc.nbClient, &sw, &logicalSwitchPort)
if err != nil {
return fmt.Errorf("failed to create port %v on logical switch %q: %v", logicalSwitchPort, sw.Name, err)
}
return nil
}

func (oc *SecondaryLayer2NetworkController) deleteNodeEvent(node *corev1.Node) error {
if err := oc.gatewayManagerForNode(node.Name).Cleanup(); err != nil {
return fmt.Errorf("failed to cleanup gateway on node %q: %w", node.Name, err)
Expand Down
25 changes: 8 additions & 17 deletions test/e2e/network_segmentation_services.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
nadclient "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types"
kapi "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -34,7 +33,7 @@ var _ = Describe("Network Segmentation: services", func() {
nadName = "tenant-red"
servicePort = 80
serviceTargetPort = 80
userDefinedNetworkIPv4Subnet = "10.128.0.0/16"
userDefinedNetworkIPv4Subnet = "203.203.0.0/16"
userDefinedNetworkIPv6Subnet = "2014:100:200::0/60"
)

Expand Down Expand Up @@ -159,14 +158,12 @@ var _ = Describe("Network Segmentation: services", func() {
// UDN -> UDN
By("Connect to the UDN service cluster IP from the UDN client pod on the same node")
checkConnectionToClusterIPs(f, udnClientPod, udnService, udnServerPod.Name)
By("Connect to the UDN service nodePort from the UDN client pod to all 3 nodes")
checkConnectionToNodePort(f, udnClientPod, udnService, &nodes.Items[0], "endpoint node", udnServerPod.Name)
// FIXME(dceara): Remove this check when Local Gateway external->service support is implemented.
if !IsGatewayModeLocal() {
// FIXME(kyrtapz): Remove once l2 external->svc is fixed. Client node is nodes.Items[0]
if netConfigParams.topology != types.Layer2Topology {
checkConnectionToNodePort(f, udnClientPod, udnService, &nodes.Items[1], "other node", udnServerPod.Name)
checkConnectionToNodePort(f, udnClientPod, udnService, &nodes.Items[2], "other node", udnServerPod.Name)
}
checkConnectionToNodePort(f, udnClientPod, udnService, &nodes.Items[1], "other node", udnServerPod.Name)
checkConnectionToNodePort(f, udnClientPod, udnService, &nodes.Items[2], "other node", udnServerPod.Name)
}

By(fmt.Sprintf("Creating a UDN client pod on a different node (%s)", clientNode))
Expand All @@ -179,11 +176,8 @@ var _ = Describe("Network Segmentation: services", func() {
checkConnectionToNodePort(f, udnClientPod2, udnService, &nodes.Items[1], "local node", udnServerPod.Name)
// FIXME(dceara): Remove this check when Local Gateway external->service support is implemented.
if !IsGatewayModeLocal() {
// FIXME(kyrtapz): Remove once l2 external->svc is fixed. Client node is nodes.Items[1]
if netConfigParams.topology != types.Layer2Topology {
checkConnectionToNodePort(f, udnClientPod2, udnService, &nodes.Items[0], "server node", udnServerPod.Name)
checkConnectionToNodePort(f, udnClientPod2, udnService, &nodes.Items[2], "other node", udnServerPod.Name)
}
checkConnectionToNodePort(f, udnClientPod2, udnService, &nodes.Items[0], "server node", udnServerPod.Name)
checkConnectionToNodePort(f, udnClientPod2, udnService, &nodes.Items[2], "other node", udnServerPod.Name)
}

// Default network -> UDN
Expand All @@ -207,11 +201,8 @@ var _ = Describe("Network Segmentation: services", func() {

// FIXME(dceara): Remove this check when Local Gateway external->service support is implemented.
if !IsGatewayModeLocal() {
// FIXME(kyrtapz): Remove once l2 external->svc is fixed
if netConfigParams.topology != types.Layer2Topology {
checkConnectionToNodePort(f, defaultClient, udnService, &nodes.Items[0], "server node", udnServerPod.Name)
checkConnectionToNodePort(f, defaultClient, udnService, &nodes.Items[2], "other node", udnServerPod.Name)
}
checkConnectionToNodePort(f, defaultClient, udnService, &nodes.Items[0], "server node", udnServerPod.Name)
checkConnectionToNodePort(f, defaultClient, udnService, &nodes.Items[2], "other node", udnServerPod.Name)
}

// UDN -> Default network
Expand Down
Loading