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

udn: Wire up multicast for primary networks. #4547

Closed
wants to merge 12 commits into from
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ jobs:
env:
JOB_NAME: "${{ matrix.target }}-${{ matrix.ha }}-${{ matrix.gateway-mode }}-${{ matrix.ipfamily }}-${{ matrix.disable-snat-multiple-gws }}-${{ matrix.second-bridge }}-${{ matrix.ic }}"
OVN_HYBRID_OVERLAY_ENABLE: "${{ matrix.target == 'control-plane' || matrix.target == 'control-plane-helm' }}"
OVN_MULTICAST_ENABLE: "${{ matrix.target == 'control-plane' || matrix.target == 'control-plane-helm' }}"
OVN_MULTICAST_ENABLE: "${{ matrix.target == 'control-plane' || matrix.target == 'control-plane-helm' || matrix.target == 'network-segmentation' }}"
OVN_EMPTY_LB_EVENTS: "${{ matrix.target == 'control-plane' || matrix.target == 'control-plane-helm' }}"
OVN_HA: "${{ matrix.ha == 'HA' }}"
OVN_DISABLE_SNAT_MULTIPLE_GWS: "${{ matrix.disable-snat-multiple-gws == 'noSnatGW' }}"
Expand Down
70 changes: 70 additions & 0 deletions go-controller/pkg/ovn/base_network_controller_multicast.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package ovn

import (
"errors"
"fmt"

libovsdbclient "github.com/ovn-org/libovsdb/client"
libovsdbops "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops"
libovsdbutil "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/util"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/nbdb"
Expand Down Expand Up @@ -322,3 +324,71 @@ func (bnc *BaseNetworkController) syncNsMulticast(k8sNamespaces map[string]bool)

return nil
}

func (bnc *BaseNetworkController) setupClusterPortGroups() error {
pgIDs := bnc.getClusterPortGroupDbIDs(types.ClusterPortGroupNameBase)
pg := &nbdb.PortGroup{
Name: libovsdbutil.GetPortGroupName(pgIDs),
}
pg, err := libovsdbops.GetPortGroup(bnc.nbClient, pg)
if err != nil && !errors.Is(err, libovsdbclient.ErrNotFound) {
return err
}
if pg == nil {
// we didn't find an existing clusterPG, let's create a new empty PG (fresh cluster install)
// Create a cluster-wide port group that all logical switch ports are part of
pg := libovsdbutil.BuildPortGroup(pgIDs, nil, nil)
err = libovsdbops.CreateOrUpdatePortGroups(bnc.nbClient, pg)
if err != nil {
klog.Errorf("Failed to create cluster port group: %v", err)
return err
}
}

pgIDs = bnc.getClusterPortGroupDbIDs(types.ClusterRtrPortGroupNameBase)
pg = &nbdb.PortGroup{
Name: libovsdbutil.GetPortGroupName(pgIDs),
}
pg, err = libovsdbops.GetPortGroup(bnc.nbClient, pg)
if err != nil && !errors.Is(err, libovsdbclient.ErrNotFound) {
return err
}
if pg == nil {
// we didn't find an existing clusterRtrPG, let's create a new empty PG (fresh cluster install)
// Create a cluster-wide port group with all node-to-cluster router
// logical switch ports. Currently the only user is multicast but it might
// be used for other features in the future.
pg = libovsdbutil.BuildPortGroup(pgIDs, nil, nil)
err = libovsdbops.CreateOrUpdatePortGroups(bnc.nbClient, pg)
if err != nil {
klog.Errorf("Failed to create cluster port group: %v", err)
return err
}
}
return nil
}

func (bnc *BaseNetworkController) syncDefaultMulticastPolicies() error {
// If supported, enable IGMP relay on the router to forward multicast
// traffic between nodes.
if bnc.multicastSupport {
// Drop IP multicast globally. Multicast is allowed only if explicitly
// enabled in a namespace.
if err := bnc.createDefaultDenyMulticastPolicy(); err != nil {
klog.Errorf("Failed to create default deny multicast policy, error: %v", err)
return err
}

// Allow IP multicast from node switch to cluster router and from
// cluster router to node switch.
if err := bnc.createDefaultAllowMulticastPolicy(); err != nil {
klog.Errorf("Failed to create default deny multicast policy, error: %v", err)
return err
}
} else {
if err := bnc.disableMulticast(); err != nil {
return fmt.Errorf("failed to delete default multicast policy, error: %v", err)
}
}
return nil
}
17 changes: 13 additions & 4 deletions go-controller/pkg/ovn/base_network_controller_secondary.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,10 +328,13 @@ func (bsnc *BaseSecondaryNetworkController) addLogicalPortToNetworkForNAD(pod *k
return err
}
}

if bsnc.doesNetworkRequireIPAM() && util.IsMultiNetworkPoliciesSupportEnabled() {
if bsnc.doesNetworkRequireIPAM() && (util.IsMultiNetworkPoliciesSupportEnabled() || bsnc.multicastSupport) {
// Ensure the namespace/nsInfo exists
addOps, err := bsnc.addPodToNamespaceForSecondaryNetwork(pod.Namespace, podAnnotation.IPs)
portUUID := ""
if lsp != nil {
portUUID = lsp.UUID
}
addOps, err := bsnc.addPodToNamespaceForSecondaryNetwork(pod.Namespace, podAnnotation.IPs, portUUID)
if err != nil {
return err
}
Expand Down Expand Up @@ -559,7 +562,7 @@ func (bsnc *BaseSecondaryNetworkController) syncPodsForSecondaryNetwork(pods []i
}

// addPodToNamespaceForSecondaryNetwork returns the ops needed to add pod's IP to the namespace's address set.
func (bsnc *BaseSecondaryNetworkController) addPodToNamespaceForSecondaryNetwork(ns string, ips []*net.IPNet) ([]ovsdb.Operation, error) {
func (bsnc *BaseSecondaryNetworkController) addPodToNamespaceForSecondaryNetwork(ns string, ips []*net.IPNet, portUUID string) ([]ovsdb.Operation, error) {
var ops []ovsdb.Operation
var err error
nsInfo, nsUnlock, err := bsnc.ensureNamespaceLockedForSecondaryNetwork(ns, true, nil)
Expand All @@ -573,6 +576,12 @@ func (bsnc *BaseSecondaryNetworkController) addPodToNamespaceForSecondaryNetwork
return nil, err
}

if portUUID != "" && nsInfo.portGroupName != "" {
if ops, err = libovsdbops.AddPortsToPortGroupOps(bsnc.nbClient, ops, nsInfo.portGroupName, portUUID); err != nil {
return nil, err
}
}

return ops, nil
}

Expand Down
6 changes: 3 additions & 3 deletions go-controller/pkg/ovn/egressfirewall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ var _ = ginkgo.Describe("OVN EgressFirewall Operations", func() {
config.Gateway.Mode = gwMode
app.Action = func(ctx *cli.Context) error {
// owned by non-existing namespace
fakeController := getFakeController(DefaultNetworkControllerName)
fakeController := getFakeController()
purgeIDs := fakeController.getEgressFirewallACLDbIDs("none", 0)
purgeACL := libovsdbops.BuildACL(
"purgeACL1",
Expand Down Expand Up @@ -489,7 +489,7 @@ var _ = ginkgo.Describe("OVN EgressFirewall Operations", func() {
config.Gateway.Mode = gwMode
app.Action = func(ctx *cli.Context) error {

fakeController := getFakeController(DefaultNetworkControllerName)
fakeController := getFakeController()
fakeOVN.controller = fakeController

namespace1 := *newNamespace("namespace1")
Expand Down Expand Up @@ -522,7 +522,7 @@ var _ = ginkgo.Describe("OVN EgressFirewall Operations", func() {
namespace1 := *newNamespace("namespace1")
dnsName := util.LowerCaseFQDN("www.example.com")

fakeController := getFakeController(DefaultNetworkControllerName)
fakeController := getFakeController()
fakeOVN.controller = fakeController

// add dns address set along with the acl and pg to the initial db.
Expand Down
59 changes: 2 additions & 57 deletions go-controller/pkg/ovn/master.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/kube"
libovsdbops "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops"
libovsdbutil "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/util"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/nbdb"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/sbdb"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types"
Expand All @@ -43,67 +42,13 @@ func (oc *DefaultNetworkController) SetupMaster(existingNodeNames []string) erro
}
oc.defaultCOPPUUID = *(logicalRouter.Copp)

pgIDs := oc.getClusterPortGroupDbIDs(types.ClusterPortGroupNameBase)
pg := &nbdb.PortGroup{
Name: libovsdbutil.GetPortGroupName(pgIDs),
}
pg, err = libovsdbops.GetPortGroup(oc.nbClient, pg)
if err != nil && !errors.Is(err, libovsdbclient.ErrNotFound) {
if err := oc.setupClusterPortGroups(); err != nil {
return err
}
if pg == nil {
// we didn't find an existing clusterPG, let's create a new empty PG (fresh cluster install)
// Create a cluster-wide port group that all logical switch ports are part of
pg := libovsdbutil.BuildPortGroup(pgIDs, nil, nil)
err = libovsdbops.CreateOrUpdatePortGroups(oc.nbClient, pg)
if err != nil {
klog.Errorf("Failed to create cluster port group: %v", err)
return err
}
}

pgIDs = oc.getClusterPortGroupDbIDs(types.ClusterRtrPortGroupNameBase)
pg = &nbdb.PortGroup{
Name: libovsdbutil.GetPortGroupName(pgIDs),
}
pg, err = libovsdbops.GetPortGroup(oc.nbClient, pg)
if err != nil && !errors.Is(err, libovsdbclient.ErrNotFound) {
if err := oc.syncDefaultMulticastPolicies(); err != nil {
return err
}
if pg == nil {
// we didn't find an existing clusterRtrPG, let's create a new empty PG (fresh cluster install)
// Create a cluster-wide port group with all node-to-cluster router
// logical switch ports. Currently the only user is multicast but it might
// be used for other features in the future.
pg = libovsdbutil.BuildPortGroup(pgIDs, nil, nil)
err = libovsdbops.CreateOrUpdatePortGroups(oc.nbClient, pg)
if err != nil {
klog.Errorf("Failed to create cluster port group: %v", err)
return err
}
}

// If supported, enable IGMP relay on the router to forward multicast
// traffic between nodes.
if oc.multicastSupport {
// Drop IP multicast globally. Multicast is allowed only if explicitly
// enabled in a namespace.
if err := oc.createDefaultDenyMulticastPolicy(); err != nil {
klog.Errorf("Failed to create default deny multicast policy, error: %v", err)
return err
}

// Allow IP multicast from node switch to cluster router and from
// cluster router to node switch.
if err := oc.createDefaultAllowMulticastPolicy(); err != nil {
klog.Errorf("Failed to create default deny multicast policy, error: %v", err)
return err
}
} else {
if err = oc.disableMulticast(); err != nil {
return fmt.Errorf("failed to delete default multicast policy, error: %v", err)
}
}

// Create OVNJoinSwitch that will be used to connect gateway routers to the distributed router.
logicalSwitch := nbdb.LogicalSwitch{
Expand Down
12 changes: 10 additions & 2 deletions go-controller/pkg/ovn/master_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1834,15 +1834,23 @@ func newClusterJoinSwitch() *nbdb.LogicalSwitch {
}

func newClusterPortGroup() *nbdb.PortGroup {
fakeController := getFakeController(DefaultNetworkControllerName)
return newClusterPortGroupForNetwork(&util.DefaultNetInfo{})
}

func newClusterPortGroupForNetwork(netInfo util.NetInfo) *nbdb.PortGroup {
fakeController := getFakeControllerForNetwork(netInfo)
pgIDs := fakeController.getClusterPortGroupDbIDs(types.ClusterPortGroupNameBase)
pg := libovsdbutil.BuildPortGroup(pgIDs, nil, nil)
pg.UUID = pgIDs.String()
return pg
}

func newRouterPortGroup() *nbdb.PortGroup {
fakeController := getFakeController(DefaultNetworkControllerName)
return newRouterPortGroupForNetwork(&util.DefaultNetInfo{})
}

func newRouterPortGroupForNetwork(netInfo util.NetInfo) *nbdb.PortGroup {
fakeController := getFakeControllerForNetwork(netInfo)
pgIDs := fakeController.getClusterPortGroupDbIDs(types.ClusterRtrPortGroupNameBase)
pg := libovsdbutil.BuildPortGroup(pgIDs, nil, nil)
pg.UUID = pgIDs.String()
Expand Down
27 changes: 19 additions & 8 deletions go-controller/pkg/ovn/multicast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,12 @@ func setIpMode(m ipMode) {
}

func getMulticastDefaultExpectedData(clusterPortGroup, clusterRtrPortGroup *nbdb.PortGroup) []libovsdb.TestData {
return getMulticastDefaultExpectedDataForNetwork(&util.DefaultNetInfo{}, clusterPortGroup, clusterRtrPortGroup)
}
func getMulticastDefaultExpectedDataForNetwork(netInfo util.NetInfo, clusterPortGroup, clusterRtrPortGroup *nbdb.PortGroup) []libovsdb.TestData {
controllerName := getNetworkControllerName(netInfo.GetNetworkName())
match := getMulticastACLMatch()
aclIDs := getDefaultMcastACLDbIDs(mcastDefaultDenyID, libovsdbutil.ACLEgress, DefaultNetworkControllerName)
aclIDs := getDefaultMcastACLDbIDs(mcastDefaultDenyID, libovsdbutil.ACLEgress, controllerName)
aclName := libovsdbutil.GetACLName(aclIDs)
defaultDenyEgressACL := libovsdbops.BuildACL(
aclName,
Expand All @@ -74,7 +78,7 @@ func getMulticastDefaultExpectedData(clusterPortGroup, clusterRtrPortGroup *nbdb
)
defaultDenyEgressACL.UUID = "defaultDenyEgressACL_UUID"

aclIDs = getDefaultMcastACLDbIDs(mcastDefaultDenyID, libovsdbutil.ACLIngress, DefaultNetworkControllerName)
aclIDs = getDefaultMcastACLDbIDs(mcastDefaultDenyID, libovsdbutil.ACLIngress, controllerName)
aclName = libovsdbutil.GetACLName(aclIDs)
defaultDenyIngressACL := libovsdbops.BuildACL(
aclName,
Expand All @@ -92,7 +96,7 @@ func getMulticastDefaultExpectedData(clusterPortGroup, clusterRtrPortGroup *nbdb
defaultDenyIngressACL.UUID = "defaultDenyIngressACL_UUID"
clusterPortGroup.ACLs = []string{defaultDenyEgressACL.UUID, defaultDenyIngressACL.UUID}

aclIDs = getDefaultMcastACLDbIDs(mcastAllowInterNodeID, libovsdbutil.ACLEgress, DefaultNetworkControllerName)
aclIDs = getDefaultMcastACLDbIDs(mcastAllowInterNodeID, libovsdbutil.ACLEgress, controllerName)
aclName = libovsdbutil.GetACLName(aclIDs)
egressMatch := libovsdbutil.GetACLMatch(clusterRtrPortGroup.Name, match, libovsdbutil.ACLEgress)
defaultAllowEgressACL := libovsdbops.BuildACL(
Expand All @@ -112,7 +116,7 @@ func getMulticastDefaultExpectedData(clusterPortGroup, clusterRtrPortGroup *nbdb
)
defaultAllowEgressACL.UUID = "defaultAllowEgressACL_UUID"

aclIDs = getDefaultMcastACLDbIDs(mcastAllowInterNodeID, libovsdbutil.ACLIngress, DefaultNetworkControllerName)
aclIDs = getDefaultMcastACLDbIDs(mcastAllowInterNodeID, libovsdbutil.ACLIngress, controllerName)
aclName = libovsdbutil.GetACLName(aclIDs)
ingressMatch := libovsdbutil.GetACLMatch(clusterRtrPortGroup.Name, match, libovsdbutil.ACLIngress)
defaultAllowIngressACL := libovsdbops.BuildACL(
Expand Down Expand Up @@ -141,7 +145,11 @@ func getMulticastDefaultExpectedData(clusterPortGroup, clusterRtrPortGroup *nbdb
}

func getMulticastDefaultStaleData(clusterPortGroup, clusterRtrPortGroup *nbdb.PortGroup) []libovsdb.TestData {
testData := getMulticastDefaultExpectedData(clusterPortGroup, clusterRtrPortGroup)
return getMulticastDefaultStaleDataForNetwork(&util.DefaultNetInfo{}, clusterPortGroup, clusterRtrPortGroup)
}

func getMulticastDefaultStaleDataForNetwork(netInfo util.NetInfo, clusterPortGroup, clusterRtrPortGroup *nbdb.PortGroup) []libovsdb.TestData {
testData := getMulticastDefaultExpectedDataForNetwork(netInfo, clusterPortGroup, clusterRtrPortGroup)
defaultDenyIngressACL := testData[0].(*nbdb.ACL)
newName := libovsdbutil.JoinACLName(types.ClusterPortGroupNameBase, "DefaultDenyMulticastIngress")
defaultDenyIngressACL.Name = &newName
Expand Down Expand Up @@ -179,15 +187,18 @@ func getDefaultPortGroups() (clusterPortGroup, clusterRtrPortGroup *nbdb.PortGro
}

func getMulticastPolicyExpectedData(ns string, ports []string) []libovsdb.TestData {
fakeController := getFakeController(DefaultNetworkControllerName)
return getMulticastPolicyExpectedDataForNetwork(&util.DefaultNetInfo{}, ns, ports)
}
func getMulticastPolicyExpectedDataForNetwork(netInfo util.NetInfo, ns string, ports []string) []libovsdb.TestData {
fakeController := getFakeControllerForNetwork(netInfo)
pg_hash := fakeController.getNamespacePortGroupName(ns)
egressMatch := libovsdbutil.GetACLMatch(pg_hash, fakeController.getMulticastACLEgrMatch(), libovsdbutil.ACLEgress)

ip4AddressSet, ip6AddressSet := getNsAddrSetHashNames(ns)
mcastMatch := getACLMatchAF(getMulticastACLIgrMatchV4(ip4AddressSet), getMulticastACLIgrMatchV6(ip6AddressSet), config.IPv4Mode, config.IPv6Mode)
ingressMatch := libovsdbutil.GetACLMatch(pg_hash, mcastMatch, libovsdbutil.ACLIngress)

aclIDs := getNamespaceMcastACLDbIDs(ns, libovsdbutil.ACLEgress, DefaultNetworkControllerName)
aclIDs := getNamespaceMcastACLDbIDs(ns, libovsdbutil.ACLEgress, getNetworkControllerName(netInfo.GetNetworkName()))
aclName := libovsdbutil.GetACLName(aclIDs)
egressACL := libovsdbops.BuildACL(
aclName,
Expand All @@ -206,7 +217,7 @@ func getMulticastPolicyExpectedData(ns string, ports []string) []libovsdb.TestDa
)
egressACL.UUID = ns + "mc-egress-UUID"

aclIDs = getNamespaceMcastACLDbIDs(ns, libovsdbutil.ACLIngress, DefaultNetworkControllerName)
aclIDs = getNamespaceMcastACLDbIDs(ns, libovsdbutil.ACLIngress, getNetworkControllerName(netInfo.GetNetworkName()))
aclName = libovsdbutil.GetACLName(aclIDs)
ingressACL := libovsdbops.BuildACL(
aclName,
Expand Down
Loading
Loading