From fb0dca719c6949eebf01acba0a7531a6f503a37c Mon Sep 17 00:00:00 2001 From: zhangzujian Date: Tue, 16 Jul 2024 06:40:55 +0000 Subject: [PATCH] add support for interface activation strategy Signed-off-by: zhangzujian --- dist/images/Dockerfile.base | 4 +- mocks/pkg/ovs/interface.go | 28 +++++++++++ pkg/controller/pod.go | 11 +++-- pkg/daemon/handler.go | 5 +- pkg/daemon/ovs_linux.go | 2 +- pkg/ovs/interface.go | 1 + pkg/ovs/ovn-nb-logical_switch_port.go | 33 ++++++++++++- pkg/util/const.go | 67 ++++++++++++++------------- 8 files changed, 112 insertions(+), 39 deletions(-) diff --git a/dist/images/Dockerfile.base b/dist/images/Dockerfile.base index 7ef89bb21bc..ddeedc94885 100644 --- a/dist/images/Dockerfile.base +++ b/dist/images/Dockerfile.base @@ -53,7 +53,9 @@ RUN cd /usr/src/ && git clone -b branch-24.03 --depth=1 https://github.com/ovn-o # fix lr-lb dnat with multiple distributed gateway ports curl -s https://github.com/kubeovn/ovn/commit/c092b1f74ab2dfcc8d814e7a96d0ed99a1d4ec22.patch | git apply && \ # northd: skip arp/nd request for lrp addresses from localnet ports - curl -s https://github.com/kubeovn/ovn/commit/1aa952f2f1b348739d2585618a6f2afff2ed4501.patch | git apply + curl -s https://github.com/kubeovn/ovn/commit/1aa952f2f1b348739d2585618a6f2afff2ed4501.patch | git apply && \ + # ovn-controller: make activation strategy work for single chassis + curl -s https://github.com/kubeovn/ovn/commit/487cd1c6c0cc9def7cedaaaf3dd4bc99c23974c4.patch | git apply RUN apt install -y build-essential fakeroot \ autoconf automake bzip2 debhelper-compat dh-exec dh-python dh-sequence-python3 dh-sequence-sphinxdoc \ diff --git a/mocks/pkg/ovs/interface.go b/mocks/pkg/ovs/interface.go index 8506e89ee94..03a4d73c9e8 100644 --- a/mocks/pkg/ovs/interface.go +++ b/mocks/pkg/ovs/interface.go @@ -1002,6 +1002,20 @@ func (mr *MockLogicalSwitchPortMockRecorder) ResetLogicalSwitchPortMigrateOption return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetLogicalSwitchPortMigrateOptions", reflect.TypeOf((*MockLogicalSwitchPort)(nil).ResetLogicalSwitchPortMigrateOptions), lspName, srcNodeName, targetNodeName, migratedFail) } +// SetLogicalSwitchPortActivationStrategy mocks base method. +func (m *MockLogicalSwitchPort) SetLogicalSwitchPortActivationStrategy(lspName, chassis string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetLogicalSwitchPortActivationStrategy", lspName, chassis) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetLogicalSwitchPortActivationStrategy indicates an expected call of SetLogicalSwitchPortActivationStrategy. +func (mr *MockLogicalSwitchPortMockRecorder) SetLogicalSwitchPortActivationStrategy(lspName, chassis any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLogicalSwitchPortActivationStrategy", reflect.TypeOf((*MockLogicalSwitchPort)(nil).SetLogicalSwitchPortActivationStrategy), lspName, chassis) +} + // SetLogicalSwitchPortArpProxy mocks base method. func (m *MockLogicalSwitchPort) SetLogicalSwitchPortArpProxy(lspName string, enableArpProxy bool) error { m.ctrl.T.Helper() @@ -4174,6 +4188,20 @@ func (mr *MockNbClientMockRecorder) SetLoadBalancerAffinityTimeout(lbName, timeo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLoadBalancerAffinityTimeout", reflect.TypeOf((*MockNbClient)(nil).SetLoadBalancerAffinityTimeout), lbName, timeout) } +// SetLogicalSwitchPortActivationStrategy mocks base method. +func (m *MockNbClient) SetLogicalSwitchPortActivationStrategy(lspName, chassis string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetLogicalSwitchPortActivationStrategy", lspName, chassis) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetLogicalSwitchPortActivationStrategy indicates an expected call of SetLogicalSwitchPortActivationStrategy. +func (mr *MockNbClientMockRecorder) SetLogicalSwitchPortActivationStrategy(lspName, chassis any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLogicalSwitchPortActivationStrategy", reflect.TypeOf((*MockNbClient)(nil).SetLogicalSwitchPortActivationStrategy), lspName, chassis) +} + // SetLogicalSwitchPortArpProxy mocks base method. func (m *MockNbClient) SetLogicalSwitchPortArpProxy(lspName string, enableArpProxy bool) error { m.ctrl.T.Helper() diff --git a/pkg/controller/pod.go b/pkg/controller/pod.go index cdfd59add5e..da533cd39db 100644 --- a/pkg/controller/pod.go +++ b/pkg/controller/pod.go @@ -829,13 +829,13 @@ func (c *Controller) reconcileRouteSubnets(cachedPod, pod *v1.Pod, needRoutePodN return fmt.Errorf("NodeSwitch subnet %s is unavailable for pod", subnet.Name) } + portName := ovs.PodNameToPortName(podName, pod.Namespace, podNet.ProviderName) if (!c.config.EnableLb || !(subnet.Spec.EnableLb != nil && *subnet.Spec.EnableLb)) && subnet.Spec.Vpc == c.config.ClusterRouter && subnet.Spec.U2OInterconnection && subnet.Spec.Vlan != "" && !subnet.Spec.LogicalGateway { pgName := getOverlaySubnetsPortGroupName(subnet.Name, pod.Spec.NodeName) - portName := ovs.PodNameToPortName(podName, pod.Namespace, podNet.ProviderName) if err := c.OVNNbClient.PortGroupAddPorts(pgName, portName); err != nil { klog.Errorf("failed to add port to u2o port group %s: %v", pgName, err) return err @@ -887,7 +887,6 @@ func (c *Controller) reconcileRouteSubnets(cachedPod, pod *v1.Pod, needRoutePodN } // remove lsp from port group to make EIP/SNAT work - portName := ovs.PodNameToPortName(podName, pod.Namespace, podNet.ProviderName) if err = c.OVNNbClient.PortGroupRemovePorts(pgName, portName); err != nil { klog.Error(err) return err @@ -908,7 +907,6 @@ func (c *Controller) reconcileRouteSubnets(cachedPod, pod *v1.Pod, needRoutePodN continue } - portName := ovs.PodNameToPortName(podName, pod.Namespace, podNet.ProviderName) if err := c.OVNNbClient.PortGroupAddPorts(pgName, portName); err != nil { klog.Errorf("add port to port group %s: %v", pgName, err) return err @@ -990,6 +988,13 @@ func (c *Controller) reconcileRouteSubnets(cachedPod, pod *v1.Pod, needRoutePodN } } + if pod.Annotations[fmt.Sprintf(util.ActivationStrategyTemplate, podNet.ProviderName)] != "" { + if err := c.OVNNbClient.SetLogicalSwitchPortActivationStrategy(portName, pod.Spec.NodeName); err != nil { + klog.Errorf("failed to set activation strategy for lsp %s: %v", portName, err) + return err + } + } + pod.Annotations[fmt.Sprintf(util.RoutedAnnotationTemplate, podNet.ProviderName)] = "true" } patch, err := util.GenerateMergePatchPayload(cachedPod, pod) diff --git a/pkg/daemon/handler.go b/pkg/daemon/handler.go index 84e2d00fc13..1e3e399cc79 100644 --- a/pkg/daemon/handler.go +++ b/pkg/daemon/handler.go @@ -26,7 +26,7 @@ import ( ) const ( - gatewayModeDisabled = iota + gatewayCheckModeDisabled = iota gatewayCheckModePing gatewayCheckModeArping gatewayCheckModePingNotConcerned @@ -270,6 +270,9 @@ func (csh cniServerHandler) handleAdd(req *restful.Request, resp *restful.Respon // do not perform ipv4 conflict detection during VM live migration detectIPConflict = false } + if pod.Annotations[fmt.Sprintf(util.ActivationStrategyTemplate, podRequest.Provider)] != "" { + gatewayCheckMode = gatewayCheckModeDisabled + } if podSubnet.Spec.Mtu > 0 { mtu = int(podSubnet.Spec.Mtu) diff --git a/pkg/daemon/ovs_linux.go b/pkg/daemon/ovs_linux.go index 6df4dfbf3d6..d94b1e14218 100644 --- a/pkg/daemon/ovs_linux.go +++ b/pkg/daemon/ovs_linux.go @@ -474,7 +474,7 @@ func (csh cniServerHandler) configureContainerNic(podName, podNamespace, nicName finalRoutes = append(finalRoutes, route) } - if gwCheckMode != gatewayModeDisabled { + if gwCheckMode != gatewayCheckModeDisabled { var ( underlayGateway = gwCheckMode == gatewayCheckModeArping || gwCheckMode == gatewayCheckModeArpingNotConcerned interfaceName = nicName diff --git a/pkg/ovs/interface.go b/pkg/ovs/interface.go index 949f8fd2abd..801fdb37351 100644 --- a/pkg/ovs/interface.go +++ b/pkg/ovs/interface.go @@ -94,6 +94,7 @@ type LogicalSwitchPort interface { ListLogicalSwitchPortsWithLegacyExternalIDs() ([]ovnnb.LogicalSwitchPort, error) GetLogicalSwitchPort(lspName string, ignoreNotFound bool) (*ovnnb.LogicalSwitchPort, error) LogicalSwitchPortExists(name string) (bool, error) + SetLogicalSwitchPortActivationStrategy(lspName, chassis string) error // vm live migrate SetLogicalSwitchPortMigrateOptions(lspName, srcNodeName, targetNodeName string) error ResetLogicalSwitchPortMigrateOptions(lspName, srcNodeName, targetNodeName string, migratedFail bool) error diff --git a/pkg/ovs/ovn-nb-logical_switch_port.go b/pkg/ovs/ovn-nb-logical_switch_port.go index e949f8f0634..a85ef03ba09 100644 --- a/pkg/ovs/ovn-nb-logical_switch_port.go +++ b/pkg/ovs/ovn-nb-logical_switch_port.go @@ -840,6 +840,37 @@ func getLogicalSwitchPortSgs(lsp *ovnnb.LogicalSwitchPort) *strset.Set { return sgs } +// SetLogicalSwitchPortActivationStrategy sets activation-strategy to rarp for the logical switch port +func (c *OVNNbClient) SetLogicalSwitchPortActivationStrategy(lspName, chassis string) error { + lsp, err := c.GetLogicalSwitchPort(lspName, false) + if err != nil { + klog.Errorf("failed to get logical switch port %s: %v", lspName, err) + return err + } + + if lsp.Options != nil && lsp.Options["requested-chassis"] != "" { + delete(lsp.Options, "requested-chassis") + delete(lsp.Options, "activation-strategy") + if err = c.UpdateLogicalSwitchPort(lsp, &lsp.Options); err != nil { + klog.Errorf("failed to clear activation strategy for the logical switch port %s: %v", lspName, err) + return err + } + } + + requestedChassis := fmt.Sprintf("%s,%s", chassis, chassis) + if lsp.Options == nil { + lsp.Options = make(map[string]string, 2) + } + lsp.Options["requested-chassis"] = requestedChassis + lsp.Options["activation-strategy"] = "rarp" + if err = c.UpdateLogicalSwitchPort(lsp, &lsp.Options); err != nil { + klog.Errorf("failed to set activation strategy to rarp for the logical switch port %s: %v", lspName, err) + return err + } + + return nil +} + // SetLogicalSwitchPortMigrateOptions set logical switch port options of migrate func (c *OVNNbClient) SetLogicalSwitchPortMigrateOptions(lspName, srcNodeName, targetNodeName string) error { // to facilitate the migration of the VM: ovn-nbctl lsp-set-options migrator requested-chassis=src,target activation-strategy=rarp @@ -873,7 +904,7 @@ func (c *OVNNbClient) SetLogicalSwitchPortMigrateOptions(lspName, srcNodeName, t requestedChassis := fmt.Sprintf("%s,%s", srcNodeName, targetNodeName) if lsp.Options == nil { - lsp.Options = make(map[string]string) + lsp.Options = make(map[string]string, 2) } lsp.Options["requested-chassis"] = requestedChassis lsp.Options["activation-strategy"] = "rarp" diff --git a/pkg/util/const.go b/pkg/util/const.go index ee13636f32e..b0d7006b609 100644 --- a/pkg/util/const.go +++ b/pkg/util/const.go @@ -6,38 +6,40 @@ const ( DepreciatedFinalizerName = "kube-ovn-controller" KubeOVNControllerFinalizer = "kubeovn.io/kube-ovn-controller" - AllocatedAnnotation = "ovn.kubernetes.io/allocated" - RoutedAnnotation = "ovn.kubernetes.io/routed" - RoutesAnnotation = "ovn.kubernetes.io/routes" - MacAddressAnnotation = "ovn.kubernetes.io/mac_address" - IPAddressAnnotation = "ovn.kubernetes.io/ip_address" - CidrAnnotation = "ovn.kubernetes.io/cidr" - GatewayAnnotation = "ovn.kubernetes.io/gateway" - IPPoolAnnotation = "ovn.kubernetes.io/ip_pool" - BgpAnnotation = "ovn.kubernetes.io/bgp" - SnatAnnotation = "ovn.kubernetes.io/snat" - EipAnnotation = "ovn.kubernetes.io/eip" - FipFinalizer = "ovn.kubernetes.io/fip" - VipAnnotation = "ovn.kubernetes.io/vip" - AAPsAnnotation = "ovn.kubernetes.io/aaps" - ChassisAnnotation = "ovn.kubernetes.io/chassis" - VMAnnotation = "ovn.kubernetes.io/virtualmachine" - - VpcNatGatewayAnnotation = "ovn.kubernetes.io/vpc_nat_gw" - VpcNatGatewayInitAnnotation = "ovn.kubernetes.io/vpc_nat_gw_init" - VpcEipsAnnotation = "ovn.kubernetes.io/vpc_eips" - VpcFloatingIPMd5Annotation = "ovn.kubernetes.io/vpc_floating_ips" - VpcDnatMd5Annotation = "ovn.kubernetes.io/vpc_dnat_md5" - VpcSnatMd5Annotation = "ovn.kubernetes.io/vpc_snat_md5" - VpcCIDRsAnnotation = "ovn.kubernetes.io/vpc_cidrs" - VpcLbAnnotation = "ovn.kubernetes.io/vpc_lb" - VpcExternalLabel = "ovn.kubernetes.io/vpc_external" - VpcEipAnnotation = "ovn.kubernetes.io/vpc_eip" - VpcDnatEPortLabel = "ovn.kubernetes.io/vpc_dnat_eport" - VpcNatAnnotation = "ovn.kubernetes.io/vpc_nat" - OvnEipTypeLabel = "ovn.kubernetes.io/ovn_eip_type" - EipV4IpLabel = "ovn.kubernetes.io/eip_v4_ip" - EipV6IpLabel = "ovn.kubernetes.io/eip_v6_ip" + AllocatedAnnotation = "ovn.kubernetes.io/allocated" + RoutedAnnotation = "ovn.kubernetes.io/routed" + RoutesAnnotation = "ovn.kubernetes.io/routes" + MacAddressAnnotation = "ovn.kubernetes.io/mac_address" + IPAddressAnnotation = "ovn.kubernetes.io/ip_address" + CidrAnnotation = "ovn.kubernetes.io/cidr" + GatewayAnnotation = "ovn.kubernetes.io/gateway" + IPPoolAnnotation = "ovn.kubernetes.io/ip_pool" + BgpAnnotation = "ovn.kubernetes.io/bgp" + SnatAnnotation = "ovn.kubernetes.io/snat" + EipAnnotation = "ovn.kubernetes.io/eip" + FipFinalizer = "ovn.kubernetes.io/fip" + VipAnnotation = "ovn.kubernetes.io/vip" + AAPsAnnotation = "ovn.kubernetes.io/aaps" + ChassisAnnotation = "ovn.kubernetes.io/chassis" + VMAnnotation = "ovn.kubernetes.io/virtualmachine" + ActivationStrategyAnnotation = "ovn.kubernetes.io/activation_strategy" + + VpcNatGatewayAnnotation = "ovn.kubernetes.io/vpc_nat_gw" + VpcNatGatewayInitAnnotation = "ovn.kubernetes.io/vpc_nat_gw_init" + VpcNatGatewayActivatedAnnotation = "ovn.kubernetes.io/vpc_nat_gw_activated" + VpcEipsAnnotation = "ovn.kubernetes.io/vpc_eips" + VpcFloatingIPMd5Annotation = "ovn.kubernetes.io/vpc_floating_ips" + VpcDnatMd5Annotation = "ovn.kubernetes.io/vpc_dnat_md5" + VpcSnatMd5Annotation = "ovn.kubernetes.io/vpc_snat_md5" + VpcCIDRsAnnotation = "ovn.kubernetes.io/vpc_cidrs" + VpcLbAnnotation = "ovn.kubernetes.io/vpc_lb" + VpcExternalLabel = "ovn.kubernetes.io/vpc_external" + VpcEipAnnotation = "ovn.kubernetes.io/vpc_eip" + VpcDnatEPortLabel = "ovn.kubernetes.io/vpc_dnat_eport" + VpcNatAnnotation = "ovn.kubernetes.io/vpc_nat" + OvnEipTypeLabel = "ovn.kubernetes.io/ovn_eip_type" + EipV4IpLabel = "ovn.kubernetes.io/eip_v4_ip" + EipV6IpLabel = "ovn.kubernetes.io/eip_v6_ip" SwitchLBRuleVipsAnnotation = "ovn.kubernetes.io/switch_lb_vip" SwitchLBRuleVip = "switch_lb_vip" @@ -70,6 +72,7 @@ const ( DefaultRouteAnnotationTemplate = "%s.kubernetes.io/default_route" VfRepresentorNameTemplate = "%s.kubernetes.io/vf_representor" VfNameTemplate = "%s.kubernetes.io/vf" + ActivationStrategyTemplate = "%s.kubernetes.io/activation_strategy" ProviderNetworkTemplate = "%s.kubernetes.io/provider_network" ProviderNetworkErrMessageTemplate = "%s.provider-network.kubernetes.io/err_mesg"