From 098a8212dae2c3698c77b249f8e279cb90955e51 Mon Sep 17 00:00:00 2001 From: changluyi <47097611+changluyi@users.noreply.github.com> Date: Fri, 30 Dec 2022 17:17:55 +0800 Subject: [PATCH] u2o feature (#2189) * u2o feature * controller ipam initialize add u2oip * add crd ips for u2o interconnection ip * no need enqueue update subnet status, when u2o ip add/del --- Makefile | 10 + dist/images/install.sh | 9 + kubeovn-helm/templates/kube-ovn-crd.yaml | 7 + pkg/apis/kubeovn/v1/types.go | 17 +- pkg/controller/config.go | 16 +- pkg/controller/init.go | 14 ++ pkg/controller/ip.go | 5 + pkg/controller/node.go | 3 + pkg/controller/subnet.go | 269 ++++++++++++++++++++++- pkg/controller/vpc.go | 12 +- pkg/daemon/handler.go | 16 +- pkg/daemon/ovs_linux.go | 33 ++- pkg/daemon/ovs_windows.go | 6 +- pkg/ovs/ovn-nbctl-legacy.go | 49 ++++- pkg/util/const.go | 3 + yamls/crd.yaml | 7 + 16 files changed, 439 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index d2190d46d3a..cc9d13e0723 100644 --- a/Makefile +++ b/Makefile @@ -353,6 +353,16 @@ kind-install-underlay-ipv4: kind-disable-hairpin kind-load-image kind-untaint-co ENABLE_VLAN=true VLAN_NIC=eth0 bash kubectl describe no +.PHONY: kind-install-underlay-u2o-interconnection-dual +kind-install-underlay-u2o-interconnection-dual: kind-disable-hairpin kind-load-image kind-untaint-control-plane + $(call docker_network_info,kind) + @sed -e 's@^[[:space:]]*POD_CIDR=.*@POD_CIDR="$(KIND_IPV4_SUBNET),$(KIND_IPV6_SUBNET)"@' \ + -e 's@^[[:space:]]*POD_GATEWAY=.*@POD_GATEWAY="$(KIND_IPV4_GATEWAY),$(KIND_IPV6_GATEWAY)"@' \ + -e 's@^[[:space:]]*EXCLUDE_IPS=.*@EXCLUDE_IPS="$(KIND_IPV4_EXCLUDE_IPS),$(KIND_IPV6_EXCLUDE_IPS)"@' \ + -e 's@^VLAN_ID=.*@VLAN_ID="0"@' \ + dist/images/install.sh | \ + ENABLE_SSL=true DUAL_STACK=true ENABLE_VLAN=true VLAN_NIC=eth0 U2O_INTERCONNECTION=true bash + .PHONY: kind-install-underlay-hairpin-ipv4 kind-install-underlay-hairpin-ipv4: kind-enable-hairpin kind-load-image kind-untaint-control-plane $(call docker_network_info,kind) diff --git a/dist/images/install.sh b/dist/images/install.sh index 6abb9cb267b..d2eab8151c1 100755 --- a/dist/images/install.sh +++ b/dist/images/install.sh @@ -7,6 +7,7 @@ ENABLE_SSL=${ENABLE_SSL:-false} ENABLE_VLAN=${ENABLE_VLAN:-false} CHECK_GATEWAY=${CHECK_GATEWAY:-true} LOGICAL_GATEWAY=${LOGICAL_GATEWAY:-false} +U2O_INTERCONNECTION=${U2O_INTERCONNECTION:-false} ENABLE_MIRROR=${ENABLE_MIRROR:-false} VLAN_NIC=${VLAN_NIC:-} HW_OFFLOAD=${HW_OFFLOAD:-false} @@ -1327,6 +1328,9 @@ spec: - name: ExcludeIPs type: string jsonPath: .spec.excludeIps + - name: U2OInterconnectionIP + type: string + jsonPath: .status.u2oInterconnectionIP schema: openAPIV3Schema: type: object @@ -1348,6 +1352,8 @@ spec: type: string dhcpV6OptionsUUID: type: string + u2oInterconnectionIP: + type: string conditions: type: array items: @@ -1470,6 +1476,8 @@ spec: - allow - drop - reject + u2oInterconnection: + type: boolean scope: Cluster names: plural: subnets @@ -2978,6 +2986,7 @@ spec: - --default-gateway=$POD_GATEWAY - --default-gateway-check=$CHECK_GATEWAY - --default-logical-gateway=$LOGICAL_GATEWAY + - --default-u2o-interconnection=$U2O_INTERCONNECTION - --default-exclude-ips=$EXCLUDE_IPS - --node-switch-cidr=$JOIN_CIDR - --service-cluster-ip-range=$SVC_CIDR diff --git a/kubeovn-helm/templates/kube-ovn-crd.yaml b/kubeovn-helm/templates/kube-ovn-crd.yaml index f30f22b00c3..2723330d562 100644 --- a/kubeovn-helm/templates/kube-ovn-crd.yaml +++ b/kubeovn-helm/templates/kube-ovn-crd.yaml @@ -1112,6 +1112,9 @@ spec: - name: ExcludeIPs type: string jsonPath: .spec.excludeIps + - name: U2OInterconnectionIP + type: string + jsonPath: .status.u2oInterconnectionIP schema: openAPIV3Schema: type: object @@ -1133,6 +1136,8 @@ spec: type: string dhcpV6OptionsUUID: type: string + u2oInterconnectionIP: + type: string conditions: type: array items: @@ -1255,6 +1260,8 @@ spec: - allow - drop - reject + u2oInterconnection: + type: boolean scope: Cluster names: plural: subnets diff --git a/pkg/apis/kubeovn/v1/types.go b/pkg/apis/kubeovn/v1/types.go index 30de978874c..7185fc68706 100644 --- a/pkg/apis/kubeovn/v1/types.go +++ b/pkg/apis/kubeovn/v1/types.go @@ -139,6 +139,8 @@ type SubnetSpec struct { IPv6RAConfigs string `json:"ipv6RAConfigs,omitempty"` Acls []Acl `json:"acls,omitempty"` + + U2OInterconnection bool `json:"u2oInterconnection,omitempty"` } type Acl struct { @@ -179,13 +181,14 @@ type SubnetStatus struct { // +patchStrategy=merge Conditions []SubnetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` - V4AvailableIPs float64 `json:"v4availableIPs"` - V4UsingIPs float64 `json:"v4usingIPs"` - V6AvailableIPs float64 `json:"v6availableIPs"` - V6UsingIPs float64 `json:"v6usingIPs"` - ActivateGateway string `json:"activateGateway"` - DHCPv4OptionsUUID string `json:"dhcpV4OptionsUUID"` - DHCPv6OptionsUUID string `json:"dhcpV6OptionsUUID"` + V4AvailableIPs float64 `json:"v4availableIPs"` + V4UsingIPs float64 `json:"v4usingIPs"` + V6AvailableIPs float64 `json:"v6availableIPs"` + V6UsingIPs float64 `json:"v6usingIPs"` + ActivateGateway string `json:"activateGateway"` + DHCPv4OptionsUUID string `json:"dhcpV4OptionsUUID"` + DHCPv6OptionsUUID string `json:"dhcpV6OptionsUUID"` + U2OInterconnectionIP string `json:"u2oInterconnectionIP"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/controller/config.go b/pkg/controller/config.go index eb6c3742ede..a0b9881f4f4 100644 --- a/pkg/controller/config.go +++ b/pkg/controller/config.go @@ -38,12 +38,13 @@ type Configuration struct { KubeFactoryClient kubernetes.Interface KubeOvnFactoryClient clientset.Interface - DefaultLogicalSwitch string - DefaultCIDR string - DefaultGateway string - DefaultExcludeIps string - DefaultGatewayCheck bool - DefaultLogicalGateway bool + DefaultLogicalSwitch string + DefaultCIDR string + DefaultGateway string + DefaultExcludeIps string + DefaultGatewayCheck bool + DefaultLogicalGateway bool + DefaultU2OInterconnection bool ClusterRouter string NodeSwitch string @@ -111,6 +112,8 @@ func ParseFlags() (*Configuration, error) { argDefaultLogicalGateway = pflag.Bool("default-logical-gateway", false, "Create a logical gateway for the default subnet instead of using underlay gateway. Take effect only when the default subnet is in underlay mode. (default false)") argDefaultExcludeIps = pflag.String("default-exclude-ips", "", "Exclude ips in default switch (default gateway address)") + argDefaultU2OInterconnection = pflag.Bool("default-u2o-interconnection", false, "usage for underlay to overlay interconnection") + argClusterRouter = pflag.String("cluster-router", util.DefaultVpc, "The router name for cluster router") argNodeSwitch = pflag.String("node-switch", "join", "The name of node gateway switch which help node to access pod network") argNodeSwitchCIDR = pflag.String("node-switch-cidr", "100.64.0.0/16", "The cidr for node switch") @@ -184,6 +187,7 @@ func ParseFlags() (*Configuration, error) { DefaultGateway: *argDefaultGateway, DefaultGatewayCheck: *argDefaultGatewayCheck, DefaultLogicalGateway: *argDefaultLogicalGateway, + DefaultU2OInterconnection: *argDefaultU2OInterconnection, DefaultExcludeIps: *argDefaultExcludeIps, ClusterRouter: *argClusterRouter, NodeSwitch: *argNodeSwitch, diff --git a/pkg/controller/init.go b/pkg/controller/init.go index a06f091d501..b16eb3900d1 100644 --- a/pkg/controller/init.go +++ b/pkg/controller/init.go @@ -137,7 +137,13 @@ func (c *Controller) initDefaultLogicalSwitch() error { } if c.config.NetworkType == util.NetworkTypeVlan { defaultSubnet.Spec.Vlan = c.config.DefaultVlanName + if c.config.DefaultLogicalGateway && c.config.DefaultU2OInterconnection { + err = fmt.Errorf("logicalGateway and u2oInterconnection can't be opened at the same time") + klog.Error(err) + return err + } defaultSubnet.Spec.LogicalGateway = c.config.DefaultLogicalGateway + defaultSubnet.Spec.U2OInterconnection = c.config.DefaultU2OInterconnection } _, err = c.config.KubeOvnClient.KubeovnV1().Subnets().Create(context.Background(), &defaultSubnet, metav1.CreateOptions{}) @@ -304,6 +310,14 @@ func (c *Controller) InitIPAM() error { if err := c.ipam.AddOrUpdateSubnet(subnet.Name, subnet.Spec.CIDRBlock, subnet.Spec.Gateway, subnet.Spec.ExcludeIps); err != nil { klog.Errorf("failed to init subnet %s: %v", subnet.Name, err) } + + u2oInterconnName := fmt.Sprintf(util.U2OInterconnName, subnet.Spec.Vpc, subnet.Name) + u2oInterconnLrpName := fmt.Sprintf("%s-%s", subnet.Spec.Vpc, subnet.Name) + if subnet.Status.U2OInterconnectionIP != "" { + if _, _, _, err = c.ipam.GetStaticAddress(u2oInterconnName, u2oInterconnLrpName, subnet.Status.U2OInterconnectionIP, "", subnet.Name, true); err != nil { + klog.Errorf("failed to init subnet u2o interonnection ip to ipam %v", subnet.Name, err) + } + } } result, err := c.ovnLegacyClient.CustomFindEntity("logical_switch_port", []string{"name"}, `external-ids:vendor{<}""`) diff --git a/pkg/controller/ip.go b/pkg/controller/ip.go index 1d17d408c52..616f463d473 100644 --- a/pkg/controller/ip.go +++ b/pkg/controller/ip.go @@ -1,7 +1,9 @@ package controller import ( + "github.com/kubeovn/kube-ovn/pkg/util" "k8s.io/klog/v2" + "strings" kubeovnv1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1" ) @@ -10,6 +12,9 @@ func (c *Controller) enqueueAddOrDelIP(obj interface{}) { ipObj := obj.(*kubeovnv1.IP) klog.V(3).Infof("enqueue update status subnet %s", ipObj.Spec.Subnet) + if strings.HasPrefix(ipObj.Name, util.U2OInterconnName[0:19]) { + return + } c.updateSubnetStatusQueue.Add(ipObj.Spec.Subnet) for _, as := range ipObj.Spec.AttachSubnets { klog.V(3).Infof("enqueue update status subnet %s", as) diff --git a/pkg/controller/node.go b/pkg/controller/node.go index 6b71db050d8..73fcaf8ed05 100644 --- a/pkg/controller/node.go +++ b/pkg/controller/node.go @@ -603,6 +603,9 @@ func (c *Controller) createOrUpdateCrdIPs(podName, ip, mac, subnetName, ns, node if subnetName == c.config.NodeSwitch { key = nodeName ipName = fmt.Sprintf("node-%s", nodeName) + } else if strings.HasPrefix(podName, util.U2OInterconnName[0:19]) { + key = podName + ipName = podName } else { key = podName ipName = ovs.PodNameToPortName(podName, ns, providerName) diff --git a/pkg/controller/subnet.go b/pkg/controller/subnet.go index f06488b10b8..88d50e4f96f 100644 --- a/pkg/controller/subnet.go +++ b/pkg/controller/subnet.go @@ -70,7 +70,8 @@ func (c *Controller) enqueueUpdateSubnet(old, new interface{}) { } else { usingIPs = newSubnet.Status.V4UsingIPs } - if !newSubnet.DeletionTimestamp.IsZero() && usingIPs == 0 { + u2oInterconnIP := newSubnet.Status.U2OInterconnectionIP + if !newSubnet.DeletionTimestamp.IsZero() && usingIPs == 0 || (usingIPs == 1 && u2oInterconnIP != "") { c.addOrUpdateSubnetQueue.Add(key) return } @@ -92,7 +93,8 @@ func (c *Controller) enqueueUpdateSubnet(old, new interface{}) { oldSubnet.Spec.EnableIPv6RA != newSubnet.Spec.EnableIPv6RA || oldSubnet.Spec.IPv6RAConfigs != newSubnet.Spec.IPv6RAConfigs || oldSubnet.Spec.Protocol != newSubnet.Spec.Protocol || - !reflect.DeepEqual(oldSubnet.Spec.Acls, newSubnet.Spec.Acls) { + !reflect.DeepEqual(oldSubnet.Spec.Acls, newSubnet.Spec.Acls) || + oldSubnet.Spec.U2OInterconnection != newSubnet.Spec.U2OInterconnection { klog.V(3).Infof("enqueue update subnet %s", key) c.addOrUpdateSubnetQueue.Add(key) } @@ -433,7 +435,8 @@ func (c *Controller) handleSubnetFinalizer(subnet *kubeovnv1.Subnet) (bool, erro usingIps = subnet.Status.V6UsingIPs } - if !subnet.DeletionTimestamp.IsZero() && usingIps == 0 { + u2oInterconnIP := subnet.Status.U2OInterconnectionIP + if !subnet.DeletionTimestamp.IsZero() && usingIps == 0 || (usingIps == 1 && u2oInterconnIP != "") { subnet.Finalizers = util.RemoveString(subnet.Finalizers, util.ControllerName) if _, err := c.config.KubeOvnClient.KubeovnV1().Subnets().Update(context.Background(), subnet, metav1.UpdateOptions{}); err != nil { klog.Errorf("failed to remove finalizer from subnet %s, %v", subnet.Name, err) @@ -502,6 +505,12 @@ func (c *Controller) handleAddOrUpdateSubnet(key string) error { return nil } + if subnet.Spec.LogicalGateway && subnet.Spec.U2OInterconnection { + err = fmt.Errorf("logicalGateway and u2oInterconnection can't be opened at the same time") + klog.Error(err) + return err + } + vpc, err := c.vpcsLister.Get(subnet.Spec.Vpc) if err != nil { klog.Errorf("failed to get subnet's vpc '%s', %v", subnet.Spec.Vpc, err) @@ -550,6 +559,11 @@ func (c *Controller) handleAddOrUpdateSubnet(key string) error { return err } + if err := c.reconcileU2OInterconnectionIP(subnet); err != nil { + klog.Errorf("failed to reconcile underlay subnet %s to overlay interconnection %v", subnet.Name, err) + return err + } + if !isOvnSubnet(subnet) { return nil } @@ -613,7 +627,8 @@ func (c *Controller) handleAddOrUpdateSubnet(key string) error { c.patchSubnetStatus(subnet, "ListLogicalSwitchFailed", err.Error()) return err } - needRouter := subnet.Spec.Vlan == "" || subnet.Spec.LogicalGateway + needRouter := subnet.Spec.Vlan == "" || subnet.Spec.LogicalGateway || + (subnet.Status.U2OInterconnectionIP != "" && subnet.Spec.U2OInterconnection) // 1. overlay subnet, should add lrp, lrp ip is subnet gw // 2. underlay subnet use logical gw, should add lrp, lrp ip is subnet gw randomAllocateGW := !subnet.Spec.LogicalGateway && vpc.Spec.EnableExternal && subnet.Name == c.config.ExternalGatewaySwitch @@ -635,7 +650,11 @@ func (c *Controller) handleAddOrUpdateSubnet(key string) error { } else { // logical switch exists, only update other_config if !randomAllocateGW { - if err := c.ovnLegacyClient.SetLogicalSwitchConfig(subnet.Name, vpc.Status.Router, subnet.Spec.Protocol, subnet.Spec.CIDRBlock, subnet.Spec.Gateway, subnet.Spec.ExcludeIps, needRouter); err != nil { + gateway := subnet.Spec.Gateway + if subnet.Status.U2OInterconnectionIP != "" && subnet.Spec.U2OInterconnection { + gateway = subnet.Status.U2OInterconnectionIP + } + if err := c.ovnLegacyClient.SetLogicalSwitchConfig(subnet.Name, vpc.Status.Router, subnet.Spec.Protocol, subnet.Spec.CIDRBlock, gateway, subnet.Spec.ExcludeIps, needRouter); err != nil { c.patchSubnetStatus(subnet, "SetLogicalSwitchConfigFailed", err.Error()) return err } @@ -793,6 +812,19 @@ func (c *Controller) handleDeleteLogicalSwitch(key string) (err error) { func (c *Controller) handleDeleteSubnet(subnet *kubeovnv1.Subnet) error { c.updateVpcStatusQueue.Add(subnet.Spec.Vpc) + klog.Infof("delete u2o interconnection policy route for subnet %s", subnet.Name) + if err := c.deletePolicyRouteForU2OInterconn(subnet); err != nil { + klog.Errorf("failed to delete policy route for underlay to overlay subnet interconnection %s, %v", subnet.Name, err) + return err + } + + u2oInterconnName := fmt.Sprintf(util.U2OInterconnName, subnet.Spec.Vpc, subnet.Name) + if err := c.config.KubeOvnClient.KubeovnV1().IPs().Delete(context.Background(), u2oInterconnName, metav1.DeleteOptions{}); err != nil { + if !k8serrors.IsNotFound(err) { + klog.Errorf("failed to delete ip %s, %v", u2oInterconnName, err) + return err + } + } klog.Infof("delete policy route for %s subnet %s", subnet.Spec.GatewayType, subnet.Name) if err := c.deletePolicyRouteByGatewayType(subnet, subnet.Spec.GatewayType, true); err != nil { @@ -1033,7 +1065,7 @@ func (c *Controller) reconcileOvnRoute(subnet *kubeovnv1.Subnet) error { return err } - if !subnet.Spec.LogicalGateway && subnet.Name != c.config.ExternalGatewaySwitch { + if !subnet.Spec.LogicalGateway && subnet.Name != c.config.ExternalGatewaySwitch && !subnet.Spec.U2OInterconnection { lspName := fmt.Sprintf("%s-%s", subnet.Name, c.config.ClusterRouter) klog.Infof("delete logical switch port %s", lspName) if err := c.ovnLegacyClient.DeleteLogicalSwitchPort(lspName); err != nil { @@ -1047,6 +1079,18 @@ func (c *Controller) reconcileOvnRoute(subnet *kubeovnv1.Subnet) error { return err } } + + if subnet.Spec.U2OInterconnection && subnet.Status.U2OInterconnectionIP != "" { + if err := c.addPolicyRouteForU2OInterconn(subnet); err != nil { + klog.Errorf("failed to add policy route for underlay to overlay subnet interconnection %s %v", subnet.Name, err) + return err + } + } else { + if err := c.deletePolicyRouteForU2OInterconn(subnet); err != nil { + klog.Errorf("failed to delete policy route for underlay to overlay subnet interconnection %s, %v", subnet.Name, err) + return err + } + } } else { if err = c.addCommonRoutesForSubnet(subnet); err != nil { klog.Error(err) @@ -1411,6 +1455,66 @@ func (c *Controller) reconcileVlan(subnet *kubeovnv1.Subnet) error { return nil } +func (c *Controller) reconcileU2OInterconnectionIP(subnet *kubeovnv1.Subnet) error { + + needCalcIP := false + klog.Infof("reconcile underlay subnet %s to overlay interconnection with U2OInterconnection %v U2OInterconnectionIP %s ", + subnet.Name, subnet.Spec.U2OInterconnection, subnet.Status.U2OInterconnectionIP) + if subnet.Spec.U2OInterconnection { + if subnet.Status.U2OInterconnectionIP == "" { + u2oInterconnName := fmt.Sprintf(util.U2OInterconnName, subnet.Spec.Vpc, subnet.Name) + u2oInterconnLrpName := fmt.Sprintf("%s-%s", subnet.Spec.Vpc, subnet.Name) + v4ip, v6ip, _, err := c.acquireIpAddress(subnet.Name, u2oInterconnName, u2oInterconnLrpName) + if err != nil { + klog.Errorf("failed to acquire underlay to overlay interconnection ip address for subnet %s, %v", subnet.Name, err) + return err + } + switch subnet.Spec.Protocol { + case kubeovnv1.ProtocolIPv4: + subnet.Status.U2OInterconnectionIP = v4ip + case kubeovnv1.ProtocolIPv6: + subnet.Status.U2OInterconnectionIP = v6ip + case kubeovnv1.ProtocolDual: + subnet.Status.U2OInterconnectionIP = fmt.Sprintf("%s,%s", v4ip, v6ip) + } + if err := c.createOrUpdateCrdIPs(u2oInterconnName, subnet.Status.U2OInterconnectionIP, "", subnet.Name, "default", "", "", "", nil); err != nil { + klog.Errorf("failed to create or update IPs of %s : %v", u2oInterconnLrpName, err) + return err + } + + needCalcIP = true + } + } else { + if subnet.Status.U2OInterconnectionIP != "" { + u2oInterconnName := fmt.Sprintf(util.U2OInterconnName, subnet.Spec.Vpc, subnet.Name) + c.ipam.ReleaseAddressByPod(u2oInterconnName) + subnet.Status.U2OInterconnectionIP = "" + + if err := c.config.KubeOvnClient.KubeovnV1().IPs().Delete(context.Background(), u2oInterconnName, metav1.DeleteOptions{}); err != nil { + if !k8serrors.IsNotFound(err) { + klog.Errorf("failed to delete ip %s, %v", u2oInterconnName, err) + return err + } + } + + needCalcIP = true + } + } + + if needCalcIP { + if subnet.Spec.Protocol == kubeovnv1.ProtocolDual { + if err := calcDualSubnetStatusIP(subnet, c); err != nil { + return err + } + } else { + if err := calcSubnetStatusIP(subnet, c); err != nil { + return err + } + } + } + return nil +} + func calcDualSubnetStatusIP(subnet *kubeovnv1.Subnet, c *Controller) error { if err := util.CheckCidrs(subnet.Spec.CIDRBlock); err != nil { return err @@ -1933,3 +2037,156 @@ func (c *Controller) deletePolicyRouteByGatewayType(subnet *kubeovnv1.Subnet, ga return nil } + +func (c *Controller) addPolicyRouteForU2OInterconn(subnet *kubeovnv1.Subnet) error { + + var v4Gw, v6Gw string + for _, gw := range strings.Split(subnet.Spec.Gateway, ",") { + switch util.CheckProtocol(gw) { + case kubeovnv1.ProtocolIPv4: + v4Gw = gw + case kubeovnv1.ProtocolIPv6: + v6Gw = gw + } + } + + externalIDs := map[string]string{ + "vendor": util.CniTypeName, + "subnet": subnet.Name, + "isU2ORoutePolicy": "true", + } + + nodes, err := c.nodesLister.List(labels.Everything()) + if err != nil { + klog.Errorf("failed to list nodes: %v", err) + return err + } + + var nodesIPv4, nodesIPv6 []string + for _, node := range nodes { + nodeIPv4, nodeIPv6 := util.GetNodeInternalIP(*node) + + if nodeIPv4 != "" { + nodesIPv4 = append(nodesIPv4, nodeIPv4) + } + if nodeIPv6 != "" { + nodesIPv6 = append(nodesIPv6, nodeIPv6) + } + } + + u2oExcludeIp4Ag := strings.Replace(fmt.Sprintf(util.U2OExcludeIPAg, subnet.Name, "ip4"), "-", ".", -1) + u2oExcludeIp6Ag := strings.Replace(fmt.Sprintf(util.U2OExcludeIPAg, subnet.Name, "ip6"), "-", ".", -1) + if err := c.ovnLegacyClient.CreateAddressSet(u2oExcludeIp4Ag); err != nil { + klog.Errorf("failed to create address set %s %v", u2oExcludeIp4Ag, err) + return err + } + + if err := c.ovnLegacyClient.CreateAddressSet(u2oExcludeIp6Ag); err != nil { + klog.Errorf("failed to create address set %s %v", u2oExcludeIp6Ag, err) + return err + } + + if len(nodesIPv4) > 0 { + if err := c.ovnLegacyClient.SetAddressesToAddressSet(nodesIPv4, u2oExcludeIp4Ag); err != nil { + klog.Errorf("failed to set v4 address set %s with address %v err %v", u2oExcludeIp4Ag, nodesIPv4, err) + return err + } + } + + if len(nodesIPv6) > 0 { + if err := c.ovnLegacyClient.SetAddressesToAddressSet(nodesIPv6, u2oExcludeIp6Ag); err != nil { + klog.Errorf("failed to set v6 address set %s with address %v err %v", u2oExcludeIp6Ag, nodesIPv6, err) + return err + } + } + + for _, cidrBlock := range strings.Split(subnet.Spec.CIDRBlock, ",") { + ipSuffix := "ip4" + nextHop := v4Gw + U2OexcludeIPAs := u2oExcludeIp4Ag + if util.CheckProtocol(cidrBlock) == kubeovnv1.ProtocolIPv6 { + ipSuffix = "ip6" + nextHop = v6Gw + U2OexcludeIPAs = u2oExcludeIp6Ag + } + + match1 := fmt.Sprintf("%s.dst == %s && %s.dst != $%s", ipSuffix, cidrBlock, ipSuffix, U2OexcludeIPAs) + match2 := fmt.Sprintf("%s.dst == $%s && %s.src == %s", ipSuffix, U2OexcludeIPAs, ipSuffix, cidrBlock) + match3 := fmt.Sprintf("%s.src == %s", ipSuffix, cidrBlock) + + /* + policy1: + prio 31000 match: "ip4.dst == underlay subnet cidr && ip4.dst != node ips" action: allow + + policy2: + prio 31000 match: "ip4.dst == node ips && ip4.src == underlay subnet cidr" action: allow + + policy3: + prio 29000 match: "ip4.src == underlay subnet cidr" action: reroute physical gw + + comment: + policy1 and policy2 allow overlay pod access underlay but when overlay pod access node ip, it should go join subnet, + policy3: underlay pod first access u2o interconnection lrp and then reoute to physical gw + */ + klog.Infof("add u2o interconnection policy for router: %s, match %s, action %s", subnet.Spec.Vpc, match1, "allow") + if err := c.ovnLegacyClient.AddPolicyRoute(subnet.Spec.Vpc, util.SubnetRouterPolicyPriority, match1, "allow", "", externalIDs); err != nil { + klog.Errorf("failed to add u2o interconnection policy1 for subnet %s %v", subnet.Name, err) + return err + } + + klog.Infof("add u2o interconnection policy for router: %s, match %s, action %s", subnet.Spec.Vpc, match2, "allow") + if err := c.ovnLegacyClient.AddPolicyRoute(subnet.Spec.Vpc, util.SubnetRouterPolicyPriority, match2, "allow", "", externalIDs); err != nil { + klog.Errorf("failed to add u2o interconnection policy2 for subnet %s %v", subnet.Name, err) + return err + } + + klog.Infof("add u2o interconnection policy for router: %s, match %s, action %s, nexthop %s", subnet.Spec.Vpc, match3, "reroute", nextHop) + if err := c.ovnLegacyClient.AddPolicyRoute(subnet.Spec.Vpc, util.GatewayRouterPolicyPriority, match3, "reroute", nextHop, externalIDs); err != nil { + klog.Errorf("failed to add u2o interconnection policy3 for subnet %s %v", subnet.Name, err) + return err + } + } + return nil +} + +func (c *Controller) deletePolicyRouteForU2OInterconn(subnet *kubeovnv1.Subnet) error { + + results, err := c.ovnLegacyClient.CustomFindEntity("Logical_Router_Policy", []string{"_uuid", "match", "priority"}, + "external_ids:isU2ORoutePolicy=\"true\"", + fmt.Sprintf("external_ids:vendor=\"%s\"", util.CniTypeName), + fmt.Sprintf("external_ids:subnet=\"%s\"", subnet.Name)) + if err != nil { + klog.Errorf("customFindEntity failed, %v", err) + return err + } + + if len(results) == 0 { + return nil + } + + var uuids []string + for _, result := range results { + uuids = append(uuids, result["_uuid"][0]) + klog.Infof("delete u2o interconnection policy for router %s with match %s priority %s ", subnet.Spec.Vpc, result["match"], result["priority"]) + } + + if err := c.ovnLegacyClient.DeletePolicyRouteByUUID(subnet.Spec.Vpc, uuids); err != nil { + klog.Errorf("failed to delete u2o interconnection policy for subnet %s: %v", subnet.Name, err) + return err + } + + u2oExcludeIp4Ag := strings.Replace(fmt.Sprintf(util.U2OExcludeIPAg, subnet.Name, "ip4"), "-", ".", -1) + u2oExcludeIp6Ag := strings.Replace(fmt.Sprintf(util.U2OExcludeIPAg, subnet.Name, "ip6"), "-", ".", -1) + + if err := c.ovnLegacyClient.DeleteAddressSet(u2oExcludeIp4Ag); err != nil { + klog.Errorf("failed to delete address set %s %v", u2oExcludeIp4Ag, err) + return err + } + + if err := c.ovnLegacyClient.DeleteAddressSet(u2oExcludeIp6Ag); err != nil { + klog.Errorf("failed to delete address set %s %v", u2oExcludeIp6Ag, err) + return err + } + + return nil +} diff --git a/pkg/controller/vpc.go b/pkg/controller/vpc.go index c451b3eb2c8..a8d6beee723 100644 --- a/pkg/controller/vpc.go +++ b/pkg/controller/vpc.go @@ -191,7 +191,11 @@ func (c *Controller) reconcileRouterPorts(vpc *kubeovnv1.Vpc) error { return nil } - networks := util.GetIpAddrWithMask(subnet.Spec.Gateway, subnet.Spec.CIDRBlock) + gateway := subnet.Spec.Gateway + if subnet.Spec.U2OInterconnection && subnet.Status.U2OInterconnectionIP != "" { + gateway = subnet.Status.U2OInterconnectionIP + } + networks := util.GetIpAddrWithMask(gateway, subnet.Spec.CIDRBlock) klog.Infof("add vpc lrp %s, networks %s", routerPortName, networks) if err := c.ovnClient.AddLogicalRouterPort(router, routerPortName, "", networks); err != nil { klog.ErrorS(err, "unable to create router port", "vpc", vpc.Name, "subnet", subnetName) @@ -220,7 +224,11 @@ func (c *Controller) reconcileRouterPortBySubnet(vpc *kubeovnv1.Vpc, subnet *kub return err } - networks := util.GetIpAddrWithMask(subnet.Spec.Gateway, subnet.Spec.CIDRBlock) + gateway := subnet.Spec.Gateway + if subnet.Spec.U2OInterconnection && subnet.Status.U2OInterconnectionIP != "" { + gateway = subnet.Status.U2OInterconnectionIP + } + networks := util.GetIpAddrWithMask(gateway, subnet.Spec.CIDRBlock) klog.Infof("router port does not exist, trying to create %s with ip %s", routerPortName, networks) if err := c.ovnClient.AddLogicalRouterPort(router, routerPortName, "", networks); err != nil { diff --git a/pkg/daemon/handler.go b/pkg/daemon/handler.go index 2eb3d0665b3..cd2e8e4a709 100644 --- a/pkg/daemon/handler.go +++ b/pkg/daemon/handler.go @@ -83,7 +83,7 @@ func (csh cniServerHandler) handleAdd(req *restful.Request, resp *restful.Respon } var gatewayCheckMode int - var macAddr, ip, ipAddr, cidr, gw, subnet, ingress, egress, providerNetwork, ifName, nicType, podNicName, priority, vmName, latency, limit, loss string + var macAddr, ip, ipAddr, cidr, gw, subnet, ingress, egress, providerNetwork, ifName, nicType, podNicName, priority, vmName, latency, limit, loss, u2oInterconnectionIP string var isDefaultRoute bool var pod *v1.Pod var err error @@ -202,11 +202,21 @@ func (csh cniServerHandler) handleAdd(req *restful.Request, resp *restful.Respon return } + if podSubnet.Status.U2OInterconnectionIP == "" && podSubnet.Spec.U2OInterconnection { + errMsg := fmt.Errorf("failed to generate u2o ip on subnet %s ", podSubnet.Name) + klog.Error(errMsg) + return + } + subnetPriority := csh.Controller.getSubnetQosPriority(subnet) if priority == "" && subnetPriority != "" { priority = subnetPriority } + if podSubnet.Status.U2OInterconnectionIP != "" && podSubnet.Spec.U2OInterconnection { + u2oInterconnectionIP = podSubnet.Status.U2OInterconnectionIP + } + //skip ping check gateway for pods during live migration if pod.Annotations[fmt.Sprintf(util.LiveMigrationAnnotationTemplate, podRequest.Provider)] != "true" { if !podSubnet.Spec.DisableGatewayCheck { @@ -294,12 +304,12 @@ func (csh cniServerHandler) handleAdd(req *restful.Request, resp *restful.Respon klog.Infof("create container interface %s mac %s, ip %s, cidr %s, gw %s, u2o routes %v, custom routes %v", ifName, macAddr, ipAddr, cidr, gw, u2oRoutes, podRequest.Routes) allRoutes := append(u2oRoutes, podRequest.Routes...) if nicType == util.InternalType { - podNicName, err = csh.configureNicWithInternalPort(podRequest.PodName, podRequest.PodNamespace, podRequest.Provider, podRequest.NetNs, podRequest.ContainerID, ifName, macAddr, mtu, ipAddr, gw, isDefaultRoute, allRoutes, podRequest.DNS.Nameservers, podRequest.DNS.Search, ingress, egress, priority, podRequest.DeviceID, nicType, latency, limit, loss, gatewayCheckMode) + podNicName, err = csh.configureNicWithInternalPort(podRequest.PodName, podRequest.PodNamespace, podRequest.Provider, podRequest.NetNs, podRequest.ContainerID, ifName, macAddr, mtu, ipAddr, gw, isDefaultRoute, allRoutes, podRequest.DNS.Nameservers, podRequest.DNS.Search, ingress, egress, priority, podRequest.DeviceID, nicType, latency, limit, loss, gatewayCheckMode, u2oInterconnectionIP) } else if nicType == util.DpdkType { err = csh.configureDpdkNic(podRequest.PodName, podRequest.PodNamespace, podRequest.Provider, podRequest.NetNs, podRequest.ContainerID, ifName, macAddr, mtu, ipAddr, gw, ingress, egress, priority, getShortSharedDir(pod.UID, podRequest.VhostUserSocketVolumeName), podRequest.VhostUserSocketName) } else { podNicName = ifName - err = csh.configureNic(podRequest.PodName, podRequest.PodNamespace, podRequest.Provider, podRequest.NetNs, podRequest.ContainerID, podRequest.VfDriver, ifName, macAddr, mtu, ipAddr, gw, isDefaultRoute, allRoutes, podRequest.DNS.Nameservers, podRequest.DNS.Search, ingress, egress, priority, podRequest.DeviceID, nicType, latency, limit, loss, gatewayCheckMode) + err = csh.configureNic(podRequest.PodName, podRequest.PodNamespace, podRequest.Provider, podRequest.NetNs, podRequest.ContainerID, podRequest.VfDriver, ifName, macAddr, mtu, ipAddr, gw, isDefaultRoute, allRoutes, podRequest.DNS.Nameservers, podRequest.DNS.Search, ingress, egress, priority, podRequest.DeviceID, nicType, latency, limit, loss, gatewayCheckMode, u2oInterconnectionIP) } if err != nil { errMsg := fmt.Errorf("configure nic failed %v", err) diff --git a/pkg/daemon/ovs_linux.go b/pkg/daemon/ovs_linux.go index 5fa9a7682a6..58a63591c7d 100644 --- a/pkg/daemon/ovs_linux.go +++ b/pkg/daemon/ovs_linux.go @@ -55,7 +55,7 @@ func (csh cniServerHandler) configureDpdkNic(podName, podNamespace, provider, ne return nil } -func (csh cniServerHandler) configureNic(podName, podNamespace, provider, netns, containerID, vfDriver, ifName, mac string, mtu int, ip, gateway string, isDefaultRoute bool, routes []request.Route, dnsServer, dnsSuffix []string, ingress, egress, priority, DeviceID, nicType, latency, limit, loss string, gwCheckMode int) error { +func (csh cniServerHandler) configureNic(podName, podNamespace, provider, netns, containerID, vfDriver, ifName, mac string, mtu int, ip, gateway string, isDefaultRoute bool, routes []request.Route, dnsServer, dnsSuffix []string, ingress, egress, priority, DeviceID, nicType, latency, limit, loss string, gwCheckMode int, u2oInterconnectionIP string) error { var err error var hostNicName, containerNicName string if DeviceID == "" { @@ -120,7 +120,7 @@ func (csh cniServerHandler) configureNic(podName, podNamespace, provider, netns, if err != nil { return fmt.Errorf("failed to open netns %q: %v", netns, err) } - if err = configureContainerNic(containerNicName, ifName, ip, gateway, isDefaultRoute, routes, macAddr, podNS, mtu, nicType, gwCheckMode); err != nil { + if err = configureContainerNic(containerNicName, ifName, ip, gateway, isDefaultRoute, routes, macAddr, podNS, mtu, nicType, gwCheckMode, u2oInterconnectionIP); err != nil { return err } return nil @@ -206,7 +206,7 @@ func configureHostNic(nicName string) error { return nil } -func configureContainerNic(nicName, ifName string, ipAddr, gateway string, isDefaultRoute bool, routes []request.Route, macAddr net.HardwareAddr, netns ns.NetNS, mtu int, nicType string, gwCheckMode int) error { +func configureContainerNic(nicName, ifName string, ipAddr, gateway string, isDefaultRoute bool, routes []request.Route, macAddr net.HardwareAddr, netns ns.NetNS, mtu int, nicType string, gwCheckMode int, u2oInterconnectionIP string) error { containerLink, err := netlink.LinkByName(nicName) if err != nil { return fmt.Errorf("can not find container nic %s: %v", nicName, err) @@ -263,6 +263,11 @@ func configureContainerNic(nicName, ifName string, ipAddr, gateway string, isDef if isDefaultRoute { // Only eth0 requires the default route and gateway + containerGw := gateway + if u2oInterconnectionIP != "" { + containerGw = u2oInterconnectionIP + } + switch util.CheckProtocol(ipAddr) { case kubeovnv1.ProtocolIPv4: _, defaultNet, _ := net.ParseCIDR("0.0.0.0/0") @@ -270,7 +275,7 @@ func configureContainerNic(nicName, ifName string, ipAddr, gateway string, isDef LinkIndex: containerLink.Attrs().Index, Scope: netlink.SCOPE_UNIVERSE, Dst: defaultNet, - Gw: net.ParseIP(gateway), + Gw: net.ParseIP(containerGw), }) case kubeovnv1.ProtocolIPv6: _, defaultNet, _ := net.ParseCIDR("::/0") @@ -278,10 +283,10 @@ func configureContainerNic(nicName, ifName string, ipAddr, gateway string, isDef LinkIndex: containerLink.Attrs().Index, Scope: netlink.SCOPE_UNIVERSE, Dst: defaultNet, - Gw: net.ParseIP(gateway), + Gw: net.ParseIP(containerGw), }) case kubeovnv1.ProtocolDual: - gws := strings.Split(gateway, ",") + gws := strings.Split(containerGw, ",") _, defaultNet, _ := net.ParseCIDR("0.0.0.0/0") err = netlink.RouteReplace(&netlink.Route{ LinkIndex: containerLink.Attrs().Index, @@ -334,6 +339,18 @@ func configureContainerNic(nicName, ifName string, ipAddr, gateway string, isDef if gwCheckMode != gatewayModeDisabled { underlayGateway := gwCheckMode == gatewayCheckModeArping + + if u2oInterconnectionIP != "" { + if nicType != util.InternalType { + if err := waitNetworkReady(ifName, ipAddr, u2oInterconnectionIP, false, true); err != nil { + return err + } + } + if err := waitNetworkReady(ifName, ipAddr, u2oInterconnectionIP, false, true); err != nil { + return err + } + } + if nicType != util.InternalType { return waitNetworkReady(ifName, ipAddr, gateway, underlayGateway, true) } @@ -843,7 +860,7 @@ func renameLink(curName, newName string) error { return nil } -func (csh cniServerHandler) configureNicWithInternalPort(podName, podNamespace, provider, netns, containerID, ifName, mac string, mtu int, ip, gateway string, isDefaultRoute bool, routes []request.Route, dnsServer, dnsSuffix []string, ingress, egress, priority, DeviceID, nicType, latency, limit, loss string, gwCheckMode int) (string, error) { +func (csh cniServerHandler) configureNicWithInternalPort(podName, podNamespace, provider, netns, containerID, ifName, mac string, mtu int, ip, gateway string, isDefaultRoute bool, routes []request.Route, dnsServer, dnsSuffix []string, ingress, egress, priority, DeviceID, nicType, latency, limit, loss string, gwCheckMode int, u2oInterconnectionIP string) (string, error) { _, containerNicName := generateNicName(containerID, ifName) ipStr := util.GetIpWithoutMask(ip) ifaceID := ovs.PodNameToPortName(podName, podNamespace, provider) @@ -879,7 +896,7 @@ func (csh cniServerHandler) configureNicWithInternalPort(podName, podNamespace, if err != nil { return containerNicName, fmt.Errorf("failed to open netns %q: %v", netns, err) } - if err = configureContainerNic(containerNicName, ifName, ip, gateway, isDefaultRoute, routes, macAddr, podNS, mtu, nicType, gwCheckMode); err != nil { + if err = configureContainerNic(containerNicName, ifName, ip, gateway, isDefaultRoute, routes, macAddr, podNS, mtu, nicType, gwCheckMode, u2oInterconnectionIP); err != nil { return containerNicName, err } return containerNicName, nil diff --git a/pkg/daemon/ovs_windows.go b/pkg/daemon/ovs_windows.go index 2d6cf5b2f5f..1276fad41b1 100644 --- a/pkg/daemon/ovs_windows.go +++ b/pkg/daemon/ovs_windows.go @@ -22,11 +22,11 @@ func (csh cniServerHandler) configureDpdkNic(podName, podNamespace, provider, ne return errors.New("DPDK is not supported on Windows") } -func (csh cniServerHandler) configureNicWithInternalPort(podName, podNamespace, provider, netns, containerID, ifName, mac string, mtu int, ip, gateway string, isDefaultRoute bool, routes []request.Route, dnsServer, dnsSuffix []string, ingress, egress, priority, DeviceID, nicType, latency, limit, loss string, gwCheckMode int) (string, error) { - return ifName, csh.configureNic(podName, podNamespace, provider, netns, containerID, "", ifName, mac, mtu, ip, gateway, isDefaultRoute, routes, dnsServer, dnsSuffix, ingress, egress, priority, DeviceID, nicType, latency, limit, loss, gwCheckMode) +func (csh cniServerHandler) configureNicWithInternalPort(podName, podNamespace, provider, netns, containerID, ifName, mac string, mtu int, ip, gateway string, isDefaultRoute bool, routes []request.Route, dnsServer, dnsSuffix []string, ingress, egress, priority, DeviceID, nicType, latency, limit, loss string, gwCheckMode int, u2oInterconnectionIP string) (string, error) { + return ifName, csh.configureNic(podName, podNamespace, provider, netns, containerID, "", ifName, mac, mtu, ip, gateway, isDefaultRoute, routes, dnsServer, dnsSuffix, ingress, egress, priority, DeviceID, nicType, latency, limit, loss, gwCheckMode, u2oInterconnectionIP) } -func (csh cniServerHandler) configureNic(podName, podNamespace, provider, netns, containerID, vfDriver, ifName, mac string, mtu int, ip, gateway string, isDefaultRoute bool, routes []request.Route, dnsServer, dnsSuffix []string, ingress, egress, priority, DeviceID, nicType, latency, limit, loss string, gwCheckMode int) error { +func (csh cniServerHandler) configureNic(podName, podNamespace, provider, netns, containerID, vfDriver, ifName, mac string, mtu int, ip, gateway string, isDefaultRoute bool, routes []request.Route, dnsServer, dnsSuffix []string, ingress, egress, priority, DeviceID, nicType, latency, limit, loss string, gwCheckMode int, u2oInterconnectionIP string) error { if DeviceID != "" { return errors.New("SR-IOV is not supported on Windows") } diff --git a/pkg/ovs/ovn-nbctl-legacy.go b/pkg/ovs/ovn-nbctl-legacy.go index dd221b170bc..3181290706e 100644 --- a/pkg/ovs/ovn-nbctl-legacy.go +++ b/pkg/ovs/ovn-nbctl-legacy.go @@ -439,8 +439,38 @@ func (c LegacyClient) SetLogicalSwitchConfig(ls, lr, protocol, subnet, gateway s cmd = []string{MayExist, "ls-add", ls} } if needRouter { - cmd = append(cmd, []string{"--", - "set", "logical_router_port", fmt.Sprintf("%s-%s", lr, ls), fmt.Sprintf("networks=%s", networks)}...) + lsTolr := fmt.Sprintf("%s-%s", ls, lr) + lrTols := fmt.Sprintf("%s-%s", lr, ls) + + exist, err := c.LogicalSwitchPortExists(lsTolr) + if err != nil { + klog.Errorf("failed to get logical switch port %s to router, %v", lsTolr, err) + return err + } + if !exist { + cmd = append(cmd, []string{"--", MayExist, "lsp-add", ls, lsTolr, "--", + "set", "logical_switch_port", lsTolr, "type=router", "--", + "lsp-set-addresses", lsTolr, "router", "--", + "set", "logical_switch_port", lsTolr, fmt.Sprintf("options:router-port=%s", lrTols), "--", + "set", "logical_switch_port", lsTolr, fmt.Sprintf("external_ids:vendor=%s", util.CniTypeName)}...) + } + + // check router port exist + results, err := c.ListLogicalEntity("logical_router_port", fmt.Sprintf("name=%s", lrTols)) + if err != nil { + klog.Errorf("failed to list router port %s, %v", lrTols, err) + return err + } + if len(results) == 0 { + // v6address no need add \ when use lrp-add + networks = strings.ReplaceAll(networks, "\\:", ":") + networkList := strings.Split(networks, " ") + cmd = append(cmd, []string{"--", MayExist, "lrp-add", lr, lrTols, util.GenerateMac()}...) + cmd = append(cmd, networkList...) + } else { + cmd = append(cmd, []string{"--", + "set", "logical_router_port", fmt.Sprintf("%s-%s", lr, ls), fmt.Sprintf("networks=%s", networks)}...) + } } cmd = append(cmd, []string{"--", "set", "logical_switch", ls, fmt.Sprintf("external_ids:vendor=%s", util.CniTypeName)}...) @@ -2513,6 +2543,21 @@ func (c *LegacyClient) PolicyRouteExists(priority int32, match string) (bool, er return true, nil } +func (c *LegacyClient) DeletePolicyRouteByUUID(router string, uuids []string) error { + if len(uuids) == 0 { + return nil + } + for _, uuid := range uuids { + var args []string + args = append(args, []string{"lr-policy-del", router, uuid}...) + if _, err := c.ovnNbCommand(args...); err != nil { + klog.Errorf("failed to delete router %s policy route: %v", router, err) + return err + } + } + return nil +} + func (c *LegacyClient) GetPolicyRouteParas(priority int32, match string) ([]string, map[string]string, error) { result, err := c.CustomFindEntity("Logical_Router_Policy", []string{"nexthops", "external_ids"}, fmt.Sprintf("priority=%d", priority), fmt.Sprintf(`match="%s"`, match)) if err != nil { diff --git a/pkg/util/const.go b/pkg/util/const.go index d98568182d1..6bab1051b8d 100644 --- a/pkg/util/const.go +++ b/pkg/util/const.go @@ -202,4 +202,7 @@ const ( MatchV4Src = "ip4.src" MatchV4Dst = "ip4.dst" + + U2OInterconnName = "u2o-interconnection.%s.%s" + U2OExcludeIPAg = "%s.u2o_exclude_ip.%s" ) diff --git a/yamls/crd.yaml b/yamls/crd.yaml index 326c56bddd1..f5284b35a2b 100644 --- a/yamls/crd.yaml +++ b/yamls/crd.yaml @@ -705,6 +705,9 @@ spec: - name: ExcludeIPs type: string jsonPath: .spec.excludeIps + - name: U2OInterconnectionIP + type: string + jsonPath: .status.u2oInterconnectionIP schema: openAPIV3Schema: type: object @@ -726,6 +729,8 @@ spec: type: string dhcpV6OptionsUUID: type: string + u2oInterconnectionIP: + type: string conditions: type: array items: @@ -848,6 +853,8 @@ spec: - allow - drop - reject + u2oInterconnection: + type: boolean scope: Cluster names: plural: subnets