From 92e7b975a9caffb97484bb8bf7fda8306d18f8be Mon Sep 17 00:00:00 2001 From: zhangzujian Date: Wed, 26 Jan 2022 13:45:07 +0800 Subject: [PATCH] check static route conflict --- pkg/controller/pod.go | 44 ++++++++++++++++++++++--------------------- pkg/daemon/handler.go | 21 ++++++++++++++------- pkg/ovs/ovn-nbctl.go | 28 +++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/pkg/controller/pod.go b/pkg/controller/pod.go index 990e0dec8e3..a8fd819fdeb 100644 --- a/pkg/controller/pod.go +++ b/pkg/controller/pod.go @@ -574,33 +574,35 @@ func (c *Controller) handleDeletePod(pod *v1.Pod) error { return nil } - addresses := c.ipam.GetPodAddress(key) - for _, address := range addresses { - if strings.TrimSpace(address.Ip) == "" { - continue - } - subnet, err := c.subnetsLister.Get(address.Subnet.Name) - if err != nil { - return err - } - vpc, err := c.vpcsLister.Get(subnet.Spec.Vpc) - if err != nil { - return err - } - if err := c.ovnClient.DeleteStaticRoute(address.Ip, vpc.Status.Router); err != nil { - return err - } - if err := c.ovnClient.DeleteNatRule(address.Ip, vpc.Status.Router); err != nil { - return err - } - } - ports, err := c.ovnClient.ListPodLogicalSwitchPorts(pod.Name, pod.Namespace) if err != nil { klog.Errorf("failed to list lsps of pod '%s', %v", pod.Name, err) return err } + if len(ports) != 0 { + addresses := c.ipam.GetPodAddress(key) + for _, address := range addresses { + if strings.TrimSpace(address.Ip) == "" { + continue + } + subnet, err := c.subnetsLister.Get(address.Subnet.Name) + if err != nil { + return err + } + vpc, err := c.vpcsLister.Get(subnet.Spec.Vpc) + if err != nil { + return err + } + if err := c.ovnClient.DeleteStaticRoute(address.Ip, vpc.Status.Router); err != nil { + return err + } + if err := c.ovnClient.DeleteNatRule(address.Ip, vpc.Status.Router); err != nil { + return err + } + } + } + var keepIpCR bool if ok, sts := isStatefulSetPod(pod); ok { delete, err := appendCheckStatefulSetPodToDel(c, pod) diff --git a/pkg/daemon/handler.go b/pkg/daemon/handler.go index bf83762c65e..27fab31769b 100644 --- a/pkg/daemon/handler.go +++ b/pkg/daemon/handler.go @@ -114,7 +114,9 @@ func (csh cniServerHandler) handleAdd(req *restful.Request, resp *restful.Respon priority = pod.Annotations[fmt.Sprintf(util.PriorityAnnotationTemplate, podRequest.Provider)] providerNetwork = pod.Annotations[fmt.Sprintf(util.ProviderNetworkTemplate, podRequest.Provider)] ipAddr = util.GetIpAddrWithMask(ip, cidr) - ifName = podRequest.IfName + if ifName = podRequest.IfName; ifName == "" { + ifName = "eth0" + } if podRequest.DeviceID != "" { nicType = util.OffloadType } else { @@ -127,16 +129,12 @@ func (csh cniServerHandler) handleAdd(req *restful.Request, resp *restful.Respon case "false": isDefaultRoute = false default: - if ifName == "" || ifName == "eth0" { - isDefaultRoute = true - } + isDefaultRoute = ifName == "eth0" } + break } - if ifName == "" { - ifName = "eth0" - } if pod.Annotations[fmt.Sprintf(util.AllocatedAnnotationTemplate, podRequest.Provider)] != "true" { err := fmt.Errorf("no address allocated to pod %s/%s provider %s, please see kube-ovn-controller logs to find errors", pod.Namespace, pod.Name, podRequest.Provider) klog.Error(err) @@ -153,6 +151,15 @@ func (csh cniServerHandler) handleAdd(req *restful.Request, resp *restful.Respon return } + if isDefaultRoute && pod.Annotations[fmt.Sprintf(util.RoutedAnnotationTemplate, podRequest.Provider)] != "true" { + err := fmt.Errorf("route is not ready for pod %s/%s provider %s, please see kube-ovn-controller logs to find errors", pod.Namespace, pod.Name, podRequest.Provider) + klog.Error(err) + if err := resp.WriteHeaderAndEntity(http.StatusInternalServerError, request.CniResponse{Err: err.Error()}); err != nil { + klog.Errorf("failed to write response, %v", err) + } + return + } + if strings.HasSuffix(podRequest.Provider, util.OvnProvider) && subnet != "" { podSubnet, err := csh.Controller.subnetsLister.Get(subnet) if err != nil { diff --git a/pkg/ovs/ovn-nbctl.go b/pkg/ovs/ovn-nbctl.go index f8d3c9f57b3..2c55980d87d 100644 --- a/pkg/ovs/ovn-nbctl.go +++ b/pkg/ovs/ovn-nbctl.go @@ -751,6 +751,20 @@ func (c Client) AddStaticRoute(policy, cidr, nextHop, router string, routeType s policy = PolicyDstIP } + var existingRoutes []string + if routeType != util.EcmpRouteType { + result, err := c.CustomFindEntity("Logical_Router", []string{"static_routes"}, fmt.Sprintf("name=%s", router)) + if err != nil { + return err + } + if len(result) > 1 { + return fmt.Errorf("unexpected error: found %d logical router with name %s", len(result), router) + } + if len(result) != 0 { + existingRoutes = result[0]["static_routes"] + } + } + for _, cidrBlock := range strings.Split(cidr, ",") { for _, gw := range strings.Split(nextHop, ",") { if util.CheckProtocol(cidrBlock) != util.CheckProtocol(gw) { @@ -761,6 +775,20 @@ func (c Client) AddStaticRoute(policy, cidr, nextHop, router string, routeType s return err } } else { + if !strings.ContainsRune(cidrBlock, '/') { + filter := []string{fmt.Sprintf("policy=%s", policy), fmt.Sprintf(`ip_prefix="%s"`, cidrBlock), fmt.Sprintf(`nexthop!="%s"`, gw)} + result, err := c.CustomFindEntity("Logical_Router_Static_Route", []string{"_uuid"}, filter...) + if err != nil { + return err + } + + for _, route := range result { + if util.ContainsString(existingRoutes, route["_uuid"][0]) { + return fmt.Errorf(`static route "policy=%s ip_prefix=%s" with different nexthop already exists on logical router %s`, policy, cidrBlock, router) + } + } + } + if _, err := c.ovnNbCommand(MayExist, fmt.Sprintf("%s=%s", Policy, policy), "lr-route-add", router, cidrBlock, gw); err != nil { return err }