Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d2127e4
Openflow: lookup conntrack & table=1 only when breth0 is next hop
trozet Aug 27, 2025
79ef291
Openflow: drop in_port from IPv6 dispatch OF rule at prio=50
ricky-rav Aug 28, 2025
a7476f2
Openflow: lookup conntrack & table=1 when breth0 is next hop (IPv6)
ricky-rav Aug 28, 2025
1bf08b9
E2E localnet: remove double import of ginkgo
ricky-rav Aug 14, 2025
d50d504
E2E: add test host -> localnet with IP in host subnet
ricky-rav Aug 7, 2025
ca0c713
Configure existing multihoming CI lane as IC-enabled and shared gw
ricky-rav Sep 2, 2025
c317be2
E2E localnet: remove references to downstream bugs and stories
ricky-rav Sep 1, 2025
878d540
E2E localnet: specify that the localnet uses IPs from host subnet
ricky-rav Aug 19, 2025
35faf85
E2E localnet: make IP request for localnet pod extensible
ricky-rav Aug 14, 2025
2118ba6
E2E localnet: Fix requirement on number of schedulable nodes
ricky-rav Aug 19, 2025
51f5fde
E2E localnet: default network->localnet on VLAN with external router
ricky-rav Aug 18, 2025
164d9f8
E2E localnet: host network -> localnet on VLAN with external router
ricky-rav Aug 20, 2025
63bb48f
E2E localnet: localnet -> host network on VLAN with external router
ricky-rav Aug 25, 2025
5611e7b
E2E localnet: send three pings instead of just one
ricky-rav Aug 14, 2025
d65ec5c
Fix ovnkube-controller-with-node shutdown sequence
martinkennelly Jul 15, 2025
50a94e1
ovn-controller: block GARP during startup
martinkennelly Jul 15, 2025
a7869b2
Node controller shutdown: do not ref gateway if not set
martinkennelly Sep 9, 2025
a4776fb
[IC][EIP] OCPBUGS-42303: Fix race between SB DB and OVN-Controller
martinkennelly Oct 6, 2025
92bb5ee
Merge pull request #2751 from ricky-rav/OCPBUGS-59657_420
openshift-merge-bot[bot] Oct 8, 2025
0e9f3c7
Configure sec nic EIPv6 address with NODAD and maximum lifetime
jcaamano Sep 16, 2025
84cdb99
Merge pull request #2767 from martinkennelly/420-garp
openshift-merge-bot[bot] Oct 10, 2025
050ed2c
Merge pull request #2797 from jcaamano/ocpbugs-56783-4.20
openshift-merge-bot[bot] Oct 16, 2025
a20ecf4
Merge remote-tracking branch 'upstream/release-4.20' into 4.19-sync-f…
jluhrsen Oct 16, 2025
f573d53
Merge pull request #2810 from jluhrsen/4.19-sync-from-4.20-10-16-2025
openshift-merge-bot[bot] Oct 22, 2025
1551a11
Merge remote-tracking branch 'origin/release-4.19' into sync-release-…
Oct 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 13 additions & 20 deletions go-controller/pkg/node/controllers/egressip/egressip.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/syncmap"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/util"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/util/egressip"
utilerrors "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/util/errors"
)

Expand Down Expand Up @@ -539,15 +540,15 @@ func (c *Controller) processEIP(eip *eipv1.EgressIP) (*eIPConfig, sets.Set[strin
if isValid := isEIPStatusItemValid(status, c.nodeName); !isValid {
continue
}
eIPNet, err := util.GetIPNetFullMask(status.EgressIP)
if err != nil {
ip := net.ParseIP(status.EgressIP)
if ip == nil {
return nil, selectedNamespaces, selectedPods, selectedNamespacesPodIPs,
fmt.Errorf("failed to generate mask for EgressIP %s IP %s: %v", eip.Name, status.EgressIP, err)
fmt.Errorf("failed to parse EgressIP %s IP %s", eip.Name, status.EgressIP)
}
if util.IsOVNNetwork(parsedNodeEIPConfig, eIPNet.IP) {
if util.IsOVNNetwork(parsedNodeEIPConfig, ip) {
continue
}
found, link, err := findLinkOnSameNetworkAsIP(eIPNet.IP, c.v4, c.v6)
found, link, err := findLinkOnSameNetworkAsIP(ip, c.v4, c.v6)
if err != nil {
return nil, selectedNamespaces, selectedPods, selectedNamespacesPodIPs,
fmt.Errorf("failed to find a network to host EgressIP %s IP %s: %v", eip.Name, status.EgressIP, err)
Expand All @@ -560,7 +561,7 @@ func (c *Controller) processEIP(eip *eipv1.EgressIP) (*eIPConfig, sets.Set[strin
if err != nil {
return nil, selectedNamespaces, selectedPods, selectedNamespacesPodIPs, fmt.Errorf("failed to list namespaces: %w", err)
}
isEIPV6 := utilnet.IsIPv6(eIPNet.IP)
isEIPV6 := utilnet.IsIPv6(ip)
for _, namespace := range namespaces {
netInfo, err := c.getActiveNetworkForNamespace(namespace.Name)
if err != nil {
Expand Down Expand Up @@ -593,13 +594,13 @@ func (c *Controller) processEIP(eip *eipv1.EgressIP) (*eIPConfig, sets.Set[strin
if selectedNamespacesPodIPs[namespace.Name] == nil {
selectedNamespacesPodIPs[namespace.Name] = make(map[ktypes.NamespacedName]*podIPConfigList)
}
selectedNamespacesPodIPs[namespace.Name][podNamespaceName] = generatePodConfig(ips, link, eIPNet, isEIPV6)
selectedNamespacesPodIPs[namespace.Name][podNamespaceName] = generatePodConfig(ips, link, ip, isEIPV6)
selectedPods.Insert(podNamespaceName)
}
}
// ensure at least one pod is selected before generating config
if len(selectedNamespacesPodIPs) > 0 {
eipSpecificConfig, err = generateEIPConfig(link, eIPNet, isEIPV6)
eipSpecificConfig, err = generateEIPConfig(link, ip, isEIPV6)
if err != nil {
return nil, selectedNamespaces, selectedPods, selectedNamespacesPodIPs,
fmt.Errorf("failed to generate EIP configuration for EgressIP %s IP %s: %v", eip.Name, status.EgressIP, err)
Expand All @@ -611,15 +612,15 @@ func (c *Controller) processEIP(eip *eipv1.EgressIP) (*eIPConfig, sets.Set[strin
return eipSpecificConfig, selectedNamespaces, selectedPods, selectedNamespacesPodIPs, nil
}

func generatePodConfig(podIPs []net.IP, link netlink.Link, eIPNet *net.IPNet, isEIPV6 bool) *podIPConfigList {
func generatePodConfig(podIPs []net.IP, link netlink.Link, eIP net.IP, isEIPV6 bool) *podIPConfigList {
newPodIPConfigs := newPodIPConfigList()
for _, podIP := range podIPs {
isPodIPv6 := utilnet.IsIPv6(podIP)
if isPodIPv6 != isEIPV6 {
continue
}
ipConfig := newPodIPConfig()
ipConfig.ipTableRule = generateIPTablesSNATRuleArg(podIP, isPodIPv6, link.Attrs().Name, eIPNet.IP.String())
ipConfig.ipTableRule = generateIPTablesSNATRuleArg(podIP, isPodIPv6, link.Attrs().Name, eIP.String())
ipConfig.ipRule = generateIPRule(podIP, isPodIPv6, link.Attrs().Index)
ipConfig.v6 = isPodIPv6
newPodIPConfigs.elems = append(newPodIPConfigs.elems, ipConfig)
Expand All @@ -628,14 +629,14 @@ func generatePodConfig(podIPs []net.IP, link netlink.Link, eIPNet *net.IPNet, is
}

// generateEIPConfig generates configuration that isn't related to any pod EIPs to support config of a single EIP
func generateEIPConfig(link netlink.Link, eIPNet *net.IPNet, isEIPV6 bool) (*eIPConfig, error) {
func generateEIPConfig(link netlink.Link, eIP net.IP, isEIPV6 bool) (*eIPConfig, error) {
eipConfig := newEIPConfig()
linkRoutes, err := generateRoutesForLink(link, isEIPV6)
if err != nil {
return nil, err
}
eipConfig.routes = linkRoutes
eipConfig.addr = getNetlinkAddress(eIPNet, link.Attrs().Index)
eipConfig.addr = egressip.GetNetlinkAddress(eIP, link.Attrs().Index)
return eipConfig, nil
}

Expand Down Expand Up @@ -1482,14 +1483,6 @@ func isLinkUp(flags string) bool {
return strings.Contains(flags, "up")
}

func getNetlinkAddress(addr *net.IPNet, ifindex int) *netlink.Addr {
return &netlink.Addr{
IPNet: addr,
Scope: int(netlink.SCOPE_UNIVERSE),
LinkIndex: ifindex,
}
}

// generateIPRules generates IP rules at a predefined priority for each pod IP with a custom routing table based
// from the links 'ifindex'
func generateIPRule(srcIP net.IP, isIPv6 bool, ifIndex int) netlink.Rule {
Expand Down
35 changes: 3 additions & 32 deletions go-controller/pkg/node/egressip/gateway_egressip.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@ package egressip
import (
"encoding/json"
"fmt"
"math"
"net"
"sync"

"github.com/vishvananda/netlink"
"golang.org/x/sys/unix"

"k8s.io/apimachinery/pkg/util/sets"
corev1informers "k8s.io/client-go/informers/core/v1"
corev1listers "k8s.io/client-go/listers/core/v1"
Expand All @@ -23,6 +19,7 @@ import (
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/kube"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/node/linkmanager"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/util"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/util/egressip"
)

// markIPs contains packet mark and associated EgressIP IP for IPv4 / IPv6. Key is packet mark, value egress IP
Expand Down Expand Up @@ -451,15 +448,15 @@ func (g *BridgeEIPAddrManager) addIPBridge(ip net.IP) error {
if err != nil {
return fmt.Errorf("failed to get link obj by name %s: %v", g.bridgeName, err)
}
return g.addrManager.AddAddress(getEIPBridgeNetlinkAddress(ip, link.Attrs().Index))
return g.addrManager.AddAddress(*egressip.GetNetlinkAddress(ip, link.Attrs().Index))
}

func (g *BridgeEIPAddrManager) deleteIPBridge(ip net.IP) error {
link, err := util.GetNetLinkOps().LinkByName(g.bridgeName)
if err != nil {
return fmt.Errorf("failed to get link obj by name %s: %v", g.bridgeName, err)
}
return g.addrManager.DelAddress(getEIPBridgeNetlinkAddress(ip, link.Attrs().Index))
return g.addrManager.DelAddress(*egressip.GetNetlinkAddress(ip, link.Attrs().Index))
}

// getAnnotationIPs retrieves the egress IP annotation from the current node Nodes object. If multiple users, callers must synchronise.
Expand Down Expand Up @@ -514,29 +511,3 @@ func getIPsStr(ips ...net.IP) []string {
}
return ipsStr
}

func getEIPBridgeNetlinkAddress(ip net.IP, ifindex int) netlink.Addr {
return netlink.Addr{
IPNet: &net.IPNet{IP: ip, Mask: util.GetIPFullMask(ip)},
Flags: getEIPNetlinkAddressFlag(ip),
Scope: int(netlink.SCOPE_UNIVERSE),
ValidLft: getEIPNetlinkAddressValidLft(ip),
LinkIndex: ifindex,
}
}

func getEIPNetlinkAddressFlag(ip net.IP) int {
// isV6?
if ip.To4() == nil && ip.To16() != nil {
return unix.IFA_F_NODAD
}
return 0
}

func getEIPNetlinkAddressValidLft(ip net.IP) int {
// isV6?
if ip.To4() == nil && ip.To16() != nil {
return math.MaxUint32
}
return 0
}
Loading