Skip to content

Commit f0dd327

Browse files
committed
[podannotation] Move AddRoutesGatewayIP to the allocator/pod.
This helps to avoid circular dependency with generator/udn Signed-off-by: Nadia Pinaeva <[email protected]>
1 parent 6cbf833 commit f0dd327

File tree

3 files changed

+190
-189
lines changed

3 files changed

+190
-189
lines changed

go-controller/pkg/allocator/pod/pod_annotation.go

Lines changed: 188 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ import (
1010
corev1 "k8s.io/api/core/v1"
1111
listers "k8s.io/client-go/listers/core/v1"
1212
"k8s.io/klog/v2"
13+
utilnet "k8s.io/utils/net"
1314

1415
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/allocator/id"
1516
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/allocator/ip"
1617
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/allocator/ip/subnet"
18+
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config"
19+
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/generator/udn"
1720
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/kube"
1821
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/persistentips"
1922
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types"
@@ -434,7 +437,7 @@ func allocatePodAnnotationWithRollback(
434437
}
435438

436439
// handle routes & gateways
437-
err = util.AddRoutesGatewayIP(netInfo, node, pod, tentative, network)
440+
err = AddRoutesGatewayIP(netInfo, node, pod, tentative, network)
438441
if err != nil {
439442
return
440443
}
@@ -456,3 +459,187 @@ func allocatePodAnnotationWithRollback(
456459

457460
return
458461
}
462+
463+
func joinSubnetToRoute(netinfo util.NetInfo, isIPv6 bool, gatewayIP net.IP) util.PodRoute {
464+
joinSubnet := netinfo.JoinSubnetV4()
465+
if isIPv6 {
466+
joinSubnet = netinfo.JoinSubnetV6()
467+
}
468+
return util.PodRoute{
469+
Dest: joinSubnet,
470+
NextHop: gatewayIP,
471+
}
472+
}
473+
474+
func serviceCIDRToRoute(isIPv6 bool, gatewayIP net.IP) []util.PodRoute {
475+
var podRoutes []util.PodRoute
476+
for _, serviceSubnet := range config.Kubernetes.ServiceCIDRs {
477+
if isIPv6 == utilnet.IsIPv6CIDR(serviceSubnet) {
478+
podRoutes = append(podRoutes, util.PodRoute{
479+
Dest: serviceSubnet,
480+
NextHop: gatewayIP,
481+
})
482+
}
483+
}
484+
return podRoutes
485+
}
486+
487+
func hairpinMasqueradeIPToRoute(isIPv6 bool, gatewayIP net.IP) util.PodRoute {
488+
ip := config.Gateway.MasqueradeIPs.V4OVNServiceHairpinMasqueradeIP
489+
if isIPv6 {
490+
ip = config.Gateway.MasqueradeIPs.V6OVNServiceHairpinMasqueradeIP
491+
}
492+
return util.PodRoute{
493+
Dest: &net.IPNet{
494+
IP: ip,
495+
Mask: util.GetIPFullMask(ip),
496+
},
497+
NextHop: gatewayIP,
498+
}
499+
}
500+
501+
// addRoutesGatewayIP updates the provided pod annotation for the provided pod
502+
// with the gateways derived from the allocated IPs
503+
func AddRoutesGatewayIP(
504+
netinfo util.NetInfo,
505+
node *corev1.Node,
506+
pod *corev1.Pod,
507+
podAnnotation *util.PodAnnotation,
508+
network *nadapi.NetworkSelectionElement) error {
509+
510+
// generate the nodeSubnets from the allocated IPs
511+
nodeSubnets := util.IPsToNetworkIPs(podAnnotation.IPs...)
512+
513+
if netinfo.IsSecondary() {
514+
// for secondary network, see if its network-attachment's annotation has default-route key.
515+
// If present, then we need to add default route for it
516+
podAnnotation.Gateways = append(podAnnotation.Gateways, network.GatewayRequest...)
517+
topoType := netinfo.TopologyType()
518+
switch topoType {
519+
case types.LocalnetTopology:
520+
// no route needed for directly connected subnets
521+
return nil
522+
case types.Layer2Topology:
523+
if !util.IsNetworkSegmentationSupportEnabled() || !netinfo.IsPrimaryNetwork() {
524+
return nil
525+
}
526+
for _, podIfAddr := range podAnnotation.IPs {
527+
isIPv6 := utilnet.IsIPv6CIDR(podIfAddr)
528+
nodeSubnet, err := util.MatchFirstIPNetFamily(isIPv6, nodeSubnets)
529+
if err != nil {
530+
return err
531+
}
532+
gatewayIPnet := util.GetNodeGatewayIfAddr(nodeSubnet)
533+
// Ensure default service network traffic always goes to OVN
534+
podAnnotation.Routes = append(podAnnotation.Routes, serviceCIDRToRoute(isIPv6, gatewayIPnet.IP)...)
535+
// Ensure UDN join subnet traffic always goes to UDN LSP
536+
podAnnotation.Routes = append(podAnnotation.Routes, joinSubnetToRoute(netinfo, isIPv6, gatewayIPnet.IP))
537+
if network != nil && len(network.GatewayRequest) == 0 { // if specific default route for pod was not requested then add gatewayIP
538+
podAnnotation.Gateways = append(podAnnotation.Gateways, gatewayIPnet.IP)
539+
}
540+
}
541+
// Until https://github.com/ovn-kubernetes/ovn-kubernetes/issues/4876 is fixed, it is limited to IC only
542+
if config.OVNKubernetesFeature.EnableInterconnect {
543+
if _, isIPv6Mode := netinfo.IPMode(); isIPv6Mode {
544+
joinAddrs, err := udn.GetGWRouterIPs(node, netinfo.GetNetInfo())
545+
if err != nil {
546+
if util.IsAnnotationNotSetError(err) {
547+
return types.NewSuppressedError(err)
548+
}
549+
return fmt.Errorf("failed parsing node gateway router join addresses, network %q, %w", netinfo.GetNetworkName(), err)
550+
}
551+
podAnnotation.GatewayIPv6LLA = util.HWAddrToIPv6LLA(util.IPAddrToHWAddr(joinAddrs[0].IP))
552+
}
553+
}
554+
return nil
555+
case types.Layer3Topology:
556+
for _, podIfAddr := range podAnnotation.IPs {
557+
isIPv6 := utilnet.IsIPv6CIDR(podIfAddr)
558+
nodeSubnet, err := util.MatchFirstIPNetFamily(isIPv6, nodeSubnets)
559+
if err != nil {
560+
return err
561+
}
562+
gatewayIPnet := util.GetNodeGatewayIfAddr(nodeSubnet)
563+
for _, clusterSubnet := range netinfo.Subnets() {
564+
if isIPv6 == utilnet.IsIPv6CIDR(clusterSubnet.CIDR) {
565+
podAnnotation.Routes = append(podAnnotation.Routes, util.PodRoute{
566+
Dest: clusterSubnet.CIDR,
567+
NextHop: gatewayIPnet.IP,
568+
})
569+
}
570+
}
571+
if !util.IsNetworkSegmentationSupportEnabled() || !netinfo.IsPrimaryNetwork() {
572+
continue
573+
}
574+
// Ensure default service network traffic always goes to OVN
575+
podAnnotation.Routes = append(podAnnotation.Routes, serviceCIDRToRoute(isIPv6, gatewayIPnet.IP)...)
576+
// Ensure UDN join subnet traffic always goes to UDN LSP
577+
podAnnotation.Routes = append(podAnnotation.Routes, joinSubnetToRoute(netinfo, isIPv6, gatewayIPnet.IP))
578+
if network != nil && len(network.GatewayRequest) == 0 { // if specific default route for pod was not requested then add gatewayIP
579+
podAnnotation.Gateways = append(podAnnotation.Gateways, gatewayIPnet.IP)
580+
}
581+
}
582+
return nil
583+
}
584+
return fmt.Errorf("topology type %s not supported", topoType)
585+
}
586+
587+
// if there are other network attachments for the pod, then check if those network-attachment's
588+
// annotation has default-route key. If present, then we need to skip adding default route for
589+
// OVN interface
590+
networks, err := util.GetK8sPodAllNetworkSelections(pod)
591+
if err != nil {
592+
return fmt.Errorf("error while getting network attachment definition for [%s/%s]: %v",
593+
pod.Namespace, pod.Name, err)
594+
}
595+
otherDefaultRouteV4 := false
596+
otherDefaultRouteV6 := false
597+
for _, network := range networks {
598+
for _, gatewayRequest := range network.GatewayRequest {
599+
if utilnet.IsIPv6(gatewayRequest) {
600+
otherDefaultRouteV6 = true
601+
} else {
602+
otherDefaultRouteV4 = true
603+
}
604+
}
605+
}
606+
607+
for _, podIfAddr := range podAnnotation.IPs {
608+
isIPv6 := utilnet.IsIPv6CIDR(podIfAddr)
609+
nodeSubnet, err := util.MatchFirstIPNetFamily(isIPv6, nodeSubnets)
610+
if err != nil {
611+
return err
612+
}
613+
614+
gatewayIPnet := util.GetNodeGatewayIfAddr(nodeSubnet)
615+
616+
// Ensure default pod network traffic always goes to OVN
617+
for _, clusterSubnet := range config.Default.ClusterSubnets {
618+
if isIPv6 == utilnet.IsIPv6CIDR(clusterSubnet.CIDR) {
619+
podAnnotation.Routes = append(podAnnotation.Routes, util.PodRoute{
620+
Dest: clusterSubnet.CIDR,
621+
NextHop: gatewayIPnet.IP,
622+
})
623+
}
624+
}
625+
626+
if podAnnotation.Role == types.NetworkRolePrimary {
627+
// Ensure default service network traffic always goes to OVN
628+
podAnnotation.Routes = append(podAnnotation.Routes, serviceCIDRToRoute(isIPv6, gatewayIPnet.IP)...)
629+
// Ensure service hairpin masquerade traffic always goes to OVN
630+
podAnnotation.Routes = append(podAnnotation.Routes, hairpinMasqueradeIPToRoute(isIPv6, gatewayIPnet.IP))
631+
otherDefaultRoute := otherDefaultRouteV4
632+
if isIPv6 {
633+
otherDefaultRoute = otherDefaultRouteV6
634+
}
635+
if !otherDefaultRoute {
636+
podAnnotation.Gateways = append(podAnnotation.Gateways, gatewayIPnet.IP)
637+
}
638+
}
639+
640+
// Ensure default join subnet traffic always goes to OVN
641+
podAnnotation.Routes = append(podAnnotation.Routes, joinSubnetToRoute(netinfo, isIPv6, gatewayIPnet.IP))
642+
}
643+
644+
return nil
645+
}

go-controller/pkg/ovn/base_network_controller_pods.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
ipallocator "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/allocator/ip"
2525
subnetipallocator "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/allocator/ip/subnet"
26+
podallocator "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/allocator/pod"
2627
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config"
2728
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/factory"
2829
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/kubevirt"
@@ -915,7 +916,7 @@ func (bnc *BaseNetworkController) allocatePodAnnotation(pod *corev1.Pod, existin
915916
return nil, false, err
916917
}
917918

918-
err = util.AddRoutesGatewayIP(bnc.GetNetInfo(), node, pod, podAnnotation, network)
919+
err = podallocator.AddRoutesGatewayIP(bnc.GetNetInfo(), node, pod, podAnnotation, network)
919920
if err != nil {
920921
return nil, false, err
921922
}

0 commit comments

Comments
 (0)