diff --git a/charts/templates/kube-ovn-crd.yaml b/charts/templates/kube-ovn-crd.yaml index fae15ed101d..399b4a88d76 100644 --- a/charts/templates/kube-ovn-crd.yaml +++ b/charts/templates/kube-ovn-crd.yaml @@ -1760,6 +1760,8 @@ spec: type: boolean enableEcmp: type: boolean + enableMulticastSnoop: + type: boolean routeTable: type: string scope: Cluster diff --git a/dist/images/install.sh b/dist/images/install.sh index 0b7abed236c..0b0ca80df3a 100755 --- a/dist/images/install.sh +++ b/dist/images/install.sh @@ -2299,6 +2299,8 @@ spec: type: boolean enableEcmp: type: boolean + enableMulticastSnoop: + type: boolean routeTable: type: string scope: Cluster diff --git a/pkg/apis/kubeovn/v1/types.go b/pkg/apis/kubeovn/v1/types.go index 151f41f2255..be9b19e68ef 100644 --- a/pkg/apis/kubeovn/v1/types.go +++ b/pkg/apis/kubeovn/v1/types.go @@ -166,6 +166,7 @@ type SubnetSpec struct { U2OInterconnection bool `json:"u2oInterconnection,omitempty"` EnableLb *bool `json:"enableLb,omitempty"` EnableEcmp bool `json:"enableEcmp,omitempty"` + EnableMulicastSnoop bool `json:"enableMulticastSnoop,omitempty"` RouteTable string `json:"routeTable,omitempty"` } diff --git a/pkg/controller/subnet.go b/pkg/controller/subnet.go index 837c84f1b5a..a1f65bcf7e9 100644 --- a/pkg/controller/subnet.go +++ b/pkg/controller/subnet.go @@ -104,6 +104,7 @@ func (c *Controller) enqueueUpdateSubnet(old, new interface{}) { oldSubnet.Spec.RouteTable != newSubnet.Spec.RouteTable || oldSubnet.Spec.Vpc != newSubnet.Spec.Vpc || oldSubnet.Spec.NatOutgoing != newSubnet.Spec.NatOutgoing || + oldSubnet.Spec.EnableMulicastSnoop != newSubnet.Spec.EnableMulicastSnoop || !reflect.DeepEqual(oldSubnet.Spec.NatOutgoingPolicyRules, newSubnet.Spec.NatOutgoingPolicyRules) || (newSubnet.Spec.U2OInterconnection && newSubnet.Spec.U2OInterconnectionIP != "" && oldSubnet.Spec.U2OInterconnectionIP != newSubnet.Spec.U2OInterconnectionIP) { @@ -758,6 +759,19 @@ func (c *Controller) handleAddOrUpdateSubnet(key string) error { return err } + multicastSnoopFlag := map[string]string{"mcast_snoop": "true", "mcast_querier": "false"} + if subnet.Spec.EnableMulicastSnoop { + if err := c.ovnClient.LogicalSwitchUpdateOtherConfig(subnet.Name, ovsdb.MutateOperationInsert, multicastSnoopFlag); err != nil { + klog.Errorf("enable logical switch multicast snoop %s: %v", subnet.Name, err) + return err + } + } else { + if err := c.ovnClient.LogicalSwitchUpdateOtherConfig(subnet.Name, ovsdb.MutateOperationDelete, multicastSnoopFlag); err != nil { + klog.Errorf("disable logical switch multicast snoop %s: %v", subnet.Name, err) + return err + } + } + subnet.Status.EnsureStandardConditions() if err := c.updateSubnetDHCPOption(subnet, needRouter); err != nil { diff --git a/pkg/ovs/interface.go b/pkg/ovs/interface.go index d0d948227ac..d861aea6216 100644 --- a/pkg/ovs/interface.go +++ b/pkg/ovs/interface.go @@ -51,6 +51,7 @@ type LogicalSwitch interface { CreateLogicalSwitch(lsName, lrName, cidrBlock, gateway string, needRouter, randomAllocateGW bool) error CreateBareLogicalSwitch(lsName string) error LogicalSwitchUpdateLoadBalancers(lsName string, op ovsdb.Mutator, lbNames ...string) error + LogicalSwitchUpdateOtherConfig(lsName string, op ovsdb.Mutator, otherConfig map[string]string) error DeleteLogicalSwitch(lsName string) error ListLogicalSwitch(needVendorFilter bool, filter func(ls *ovnnb.LogicalSwitch) bool) ([]ovnnb.LogicalSwitch, error) LogicalSwitchExists(lsName string) (bool, error) diff --git a/pkg/ovs/ovn-nb-logical_switch.go b/pkg/ovs/ovn-nb-logical_switch.go index 0a69c56a158..7024de8720d 100644 --- a/pkg/ovs/ovn-nb-logical_switch.go +++ b/pkg/ovs/ovn-nb-logical_switch.go @@ -170,6 +170,25 @@ func (c *ovnClient) LogicalSwitchUpdateLoadBalancers(lsName string, op ovsdb.Mut return nil } +// LogicalSwitchUpdateOtherConfig add other config to or from logical switch once +func (c *ovnClient) LogicalSwitchUpdateOtherConfig(lsName string, op ovsdb.Mutator, otherConfig map[string]string) error { + if len(otherConfig) == 0 { + return nil + } + + ops, err := c.LogicalSwitchUpdateOtherConfigOp(lsName, otherConfig, op) + if err != nil { + klog.Error(err) + return fmt.Errorf("generate operations for logical switch %s update other config %v: %v", lsName, otherConfig, err) + } + + if err := c.Transact("ls-other-config-update", ops); err != nil { + return fmt.Errorf("logical switch %s update other config %v: %v", lsName, otherConfig, err) + } + + return nil +} + // DeleteLogicalSwitch delete logical switch func (c *ovnClient) DeleteLogicalSwitch(lsName string) error { op, err := c.DeleteLogicalSwitchOp(lsName) @@ -286,6 +305,25 @@ func (c *ovnClient) LogicalSwitchUpdatePortOp(lsName string, lspUUID string, op return c.LogicalSwitchOp(lsName, mutation) } +// LogicalSwitchUpdateOtherConfigOp create operations add otherConfig to or delete otherConfig from logical switch +func (c *ovnClient) LogicalSwitchUpdateOtherConfigOp(lsName string, otherConfig map[string]string, op ovsdb.Mutator) ([]ovsdb.Operation, error) { + if len(otherConfig) == 0 { + return nil, nil + } + + mutation := func(ls *ovnnb.LogicalSwitch) *model.Mutation { + mutation := &model.Mutation{ + Field: &ls.OtherConfig, + Value: otherConfig, + Mutator: op, + } + + return mutation + } + + return c.LogicalSwitchOp(lsName, mutation) +} + // LogicalSwitchUpdateLoadBalancerOp create operations add lb to or delete lb from logical switch func (c *ovnClient) LogicalSwitchUpdateLoadBalancerOp(lsName string, lbUUIDs []string, op ovsdb.Mutator) ([]ovsdb.Operation, error) { if len(lbUUIDs) == 0 { diff --git a/yamls/crd.yaml b/yamls/crd.yaml index 3b7b14e16e7..c7be4c63754 100644 --- a/yamls/crd.yaml +++ b/yamls/crd.yaml @@ -2071,6 +2071,8 @@ spec: type: boolean enableEcmp: type: boolean + enableMulticastSnoop: + type: boolean scope: Cluster names: plural: subnets