Skip to content

Commit bfd593c

Browse files
Merge pull request #2551 from tssurya/release-4.19-blocker-bug-ovs-cpu-backport
OCPBUGS-55825: Release 4.19 blocker bug ovs cpu backport: special cherry-pick
2 parents f7dd74f + def2909 commit bfd593c

File tree

3 files changed

+58
-161
lines changed

3 files changed

+58
-161
lines changed

go-controller/pkg/node/gateway_shared_intf.go

Lines changed: 41 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,10 +1937,9 @@ func commonFlows(hostSubnets []*net.IPNet, bridge *bridgeConfiguration) ([]strin
19371937
defaultOpenFlowCookie, netConfig.ofPortPatch, bridgeMacAddress, config.Default.ConntrackZone,
19381938
netConfig.masqCTMark, ofPortPhys))
19391939

1940-
// Allow (a) OVN->host traffic on the same node
1941-
// (b) host->host traffic on the same node
1940+
// Allow OVN->Host traffic on the same node
19421941
if config.Gateway.Mode == config.GatewayModeShared || config.Gateway.Mode == config.GatewayModeLocal {
1943-
dftFlows = append(dftFlows, hostNetworkNormalActionFlows(netConfig, bridgeMacAddress, hostSubnets, false)...)
1942+
dftFlows = append(dftFlows, ovnToHostNetworkNormalActionFlows(netConfig, bridgeMacAddress, hostSubnets, false)...)
19441943
}
19451944
} else {
19461945
// for UDN we additionally SNAT the packet from masquerade IP -> node IP
@@ -2034,10 +2033,9 @@ func commonFlows(hostSubnets []*net.IPNet, bridge *bridgeConfiguration) ([]strin
20342033
"actions=ct(commit, zone=%d, exec(set_field:%s->ct_mark)), output:%s",
20352034
defaultOpenFlowCookie, netConfig.ofPortPatch, bridgeMacAddress, config.Default.ConntrackZone, netConfig.masqCTMark, ofPortPhys))
20362035

2037-
// Allow (a) OVN->host traffic on the same node
2038-
// (b) host->host traffic on the same node
2036+
// Allow OVN->Host traffic on the same node
20392037
if config.Gateway.Mode == config.GatewayModeShared || config.Gateway.Mode == config.GatewayModeLocal {
2040-
dftFlows = append(dftFlows, hostNetworkNormalActionFlows(netConfig, bridgeMacAddress, hostSubnets, true)...)
2038+
dftFlows = append(dftFlows, ovnToHostNetworkNormalActionFlows(netConfig, bridgeMacAddress, hostSubnets, true)...)
20412039
}
20422040
} else {
20432041
// for UDN we additionally SNAT the packet from masquerade IP -> node IP
@@ -2217,15 +2215,23 @@ func commonFlows(hostSubnets []*net.IPNet, bridge *bridgeConfiguration) ([]strin
22172215
return dftFlows, nil
22182216
}
22192217

2220-
// hostNetworkNormalActionFlows returns the flows that allow IP{v4,v6} traffic:
2221-
// a. from pods in the OVN network to pods in a localnet network, on the same node
2222-
// b. from pods on the host to pods in a localnet network, on the same node
2223-
// when the localnet is mapped to breth0.
2224-
// The expected srcMAC is the MAC address of breth0 and the expected hostSubnets is the host subnets found on the node
2225-
// primary interface.
2226-
func hostNetworkNormalActionFlows(netConfig *bridgeUDNConfiguration, srcMAC string, hostSubnets []*net.IPNet, isV6 bool) []string {
2218+
// ovnToHostNetworkNormalActionFlows returns the flows that allow IP{v4,v6} traffic from the OVN network to the host network
2219+
// when the destination is on the same node as the sender. This is necessary for pods in the default network to reach
2220+
// localnet pods on the same node, when the localnet is mapped to breth0. The expected srcMAC is the MAC address of breth0
2221+
// and the expected hostSubnets is the host subnets found on the node primary interface.
2222+
func ovnToHostNetworkNormalActionFlows(netConfig *bridgeUDNConfiguration, srcMAC string, hostSubnets []*net.IPNet, isV6 bool) []string {
2223+
var inPort, ctMark, ipFamily, ipFamilyDest string
22272224
var flows []string
2228-
var ipFamily, ipFamilyDest string
2225+
2226+
if config.Gateway.Mode == config.GatewayModeShared {
2227+
inPort = netConfig.ofPortPatch
2228+
ctMark = netConfig.masqCTMark
2229+
} else if config.Gateway.Mode == config.GatewayModeLocal {
2230+
inPort = "LOCAL"
2231+
ctMark = ctMarkHost
2232+
} else {
2233+
return nil
2234+
}
22292235

22302236
if isV6 {
22312237
ipFamily = "ipv6"
@@ -2235,69 +2241,38 @@ func hostNetworkNormalActionFlows(netConfig *bridgeUDNConfiguration, srcMAC stri
22352241
ipFamilyDest = "nw_dst"
22362242
}
22372243

2238-
formatFlow := func(inPort, destIP, ctMark string) string {
2239-
// Matching IP traffic will be handled by the bridge instead of being output directly
2240-
// to the NIC by the existing flow at prio=100.
2241-
flowTemplate := "cookie=%s, priority=102, in_port=%s, dl_src=%s, %s, %s=%s, " +
2242-
"actions=ct(commit, zone=%d, exec(set_field:%s->ct_mark)), output:NORMAL"
2243-
return fmt.Sprintf(flowTemplate,
2244-
defaultOpenFlowCookie,
2245-
inPort,
2246-
srcMAC,
2247-
ipFamily,
2248-
ipFamilyDest,
2249-
destIP,
2250-
config.Default.ConntrackZone,
2251-
ctMark)
2252-
}
2253-
2254-
// Traffic path (a): OVN->localnet for shared gw mode
2255-
if config.Gateway.Mode == config.GatewayModeShared {
2256-
for _, hostSubnet := range hostSubnets {
2257-
if utilnet.IsIPv6(hostSubnet.IP) != isV6 {
2258-
continue
2259-
}
2260-
flows = append(flows, formatFlow(netConfig.ofPortPatch, hostSubnet.String(), netConfig.masqCTMark))
2261-
}
2262-
}
2263-
2264-
// Traffic path (a): OVN->localnet for local gw mode
2265-
// Traffic path (b): host->localnet for both gw modes
22662244
for _, hostSubnet := range hostSubnets {
2267-
if utilnet.IsIPv6(hostSubnet.IP) != isV6 {
2245+
if (hostSubnet.IP.To4() == nil) != isV6 {
22682246
continue
22692247
}
2270-
flows = append(flows, formatFlow("LOCAL", hostSubnet.String(), ctMarkHost))
2271-
}
2272-
2273-
if isV6 {
2274-
// IPv6 neighbor discovery uses ICMPv6 messages sent to a special destination (ff02::1:ff00:0/104)
2275-
// that is unrelated to the host subnets matched in the prio=102 flow above.
2276-
// Allow neighbor discovery by matching against ICMP type and ingress port.
2277-
formatICMPFlow := func(inPort, ctMark string, icmpType int) string {
2278-
icmpFlowTemplate := "cookie=%s, priority=102, in_port=%s, dl_src=%s, icmp6, icmpv6_type=%d, " +
2279-
"actions=ct(commit, zone=%d, exec(set_field:%s->ct_mark)), output:NORMAL"
2280-
return fmt.Sprintf(icmpFlowTemplate,
2248+
// IP traffic from the OVN network to the host network should be handled normally by the bridge instead of
2249+
// being output directly to the NIC by the existing flow at prio=100.
2250+
flows = append(flows,
2251+
fmt.Sprintf("cookie=%s, priority=102, in_port=%s, dl_src=%s, %s, %s=%s, "+
2252+
"actions=ct(commit, zone=%d, exec(set_field:%s->ct_mark)), output:NORMAL",
22812253
defaultOpenFlowCookie,
22822254
inPort,
22832255
srcMAC,
2284-
icmpType,
2256+
ipFamily,
2257+
ipFamilyDest,
2258+
hostSubnet.String(),
22852259
config.Default.ConntrackZone,
2286-
ctMark)
2287-
}
2260+
ctMark))
2261+
}
22882262

2263+
if isV6 {
2264+
// Neighbor discovery in IPv6 happens through ICMPv6 messages to a special destination (ff02::1:ff00:0/104),
2265+
// which has nothing to do with the host subnets we're matching against in the flow above at prio=102.
2266+
// Let's allow neighbor discovery by matching against icmp type and in_port.
22892267
for _, icmpType := range []int{types.NeighborSolicitationICMPType, types.NeighborAdvertisementICMPType} {
2290-
// Traffic path (a) for ICMP: OVN-> localnet for shared gw mode
2291-
if config.Gateway.Mode == config.GatewayModeShared {
2292-
flows = append(flows,
2293-
formatICMPFlow(netConfig.ofPortPatch, netConfig.masqCTMark, icmpType))
2294-
}
2295-
2296-
// Traffic path (a) for ICMP: OVN->localnet for local gw mode
2297-
// Traffic path (b) for ICMP: host->localnet for both gw modes
2298-
flows = append(flows, formatICMPFlow("LOCAL", ctMarkHost, icmpType))
2268+
flows = append(flows,
2269+
fmt.Sprintf("cookie=%s, priority=102, in_port=%s, dl_src=%s, icmp6, icmpv6_type=%d, "+
2270+
"actions=ct(commit, zone=%d, exec(set_field:%s->ct_mark)), output:NORMAL",
2271+
defaultOpenFlowCookie, inPort, srcMAC, icmpType,
2272+
config.Default.ConntrackZone, ctMark))
22992273
}
23002274
}
2275+
23012276
return flows
23022277
}
23032278

test/e2e/multihoming.go

Lines changed: 4 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -331,31 +331,17 @@ var _ = Describe("Multi Homing", func() {
331331
kickstartPod(cs, clientPodConfig)
332332

333333
// Check that the client pod can reach the server pod on the server localnet interface
334-
var serverIPs []string
335-
if serverPodConfig.hostNetwork {
336-
serverIPs, err = podIPsFromStatus(cs, serverPodConfig.namespace, serverPodConfig.name)
337-
} else {
338-
serverIPs, err = podIPsForAttachment(cs, serverPod.Namespace, serverPod.Name, netConfig.name)
339-
340-
}
334+
serverIPs, err := podIPsForAttachment(cs, f.Namespace.Name, serverPod.GetName(), netConfig.name)
341335
Expect(err).NotTo(HaveOccurred())
342-
343336
for _, serverIP := range serverIPs {
344337
By(fmt.Sprintf("asserting the *client* can contact the server pod exposed endpoint: %q on port %q", serverIP, port))
345-
curlArgs := []string{}
346-
pingArgs := []string{}
347-
if clientPodConfig.attachments != nil {
348-
// When the client is attached to a localnet, send probes from the localnet interface
349-
curlArgs = []string{"--interface", "net1"}
350-
pingArgs = []string{"-I", "net1"}
351-
}
352338
Eventually(func() error {
353-
return reachServerPodFromClient(cs, serverPodConfig, clientPodConfig, serverIP, port, curlArgs...)
339+
return reachServerPodFromClient(cs, serverPodConfig, clientPodConfig, serverIP, port)
354340
}, 2*time.Minute, 6*time.Second).Should(Succeed())
355341

356342
By(fmt.Sprintf("asserting the *client* can ping the server pod exposed endpoint: %q", serverIP))
357343
Eventually(func() error {
358-
return pingServerPodFromClient(cs, serverPodConfig, clientPodConfig, serverIP, pingArgs...)
344+
return pingServerPodFromClient(cs, serverPodConfig, clientPodConfig, serverIP)
359345
}, 2*time.Minute, 6*time.Second).Should(Succeed())
360346
}
361347
},
@@ -403,52 +389,6 @@ var _ = Describe("Multi Homing", func() {
403389
},
404390
Label("BUG", "OCPBUGS-43004"),
405391
),
406-
ginkgo.Entry(
407-
"can reach a host-networked pod on a different node",
408-
networkAttachmentConfigParams{
409-
name: secondaryNetworkName,
410-
topology: "localnet",
411-
},
412-
podConfiguration{ // client on localnet
413-
attachments: []nadapi.NetworkSelectionElement{{
414-
Name: secondaryNetworkName,
415-
}},
416-
name: clientPodName,
417-
nodeSelector: map[string]string{nodeHostnameKey: workerOneNodeName},
418-
isPrivileged: true,
419-
needsIPRequestFromHostSubnet: true,
420-
},
421-
podConfiguration{ // server on default network, pod is host-networked
422-
name: podName,
423-
containerCmd: httpServerContainerCmd(port),
424-
nodeSelector: map[string]string{nodeHostnameKey: workerTwoNodeName},
425-
hostNetwork: true,
426-
},
427-
Label("STORY", "SDN-5345"),
428-
),
429-
ginkgo.Entry(
430-
"can reach a host-networked pod on the same node",
431-
networkAttachmentConfigParams{
432-
name: secondaryNetworkName,
433-
topology: "localnet",
434-
},
435-
podConfiguration{ // client on localnet
436-
attachments: []nadapi.NetworkSelectionElement{{
437-
Name: secondaryNetworkName,
438-
}},
439-
name: clientPodName,
440-
nodeSelector: map[string]string{nodeHostnameKey: workerTwoNodeName},
441-
isPrivileged: true,
442-
needsIPRequestFromHostSubnet: true,
443-
},
444-
podConfiguration{ // server on default network, pod is host-networked
445-
name: podName,
446-
containerCmd: httpServerContainerCmd(port),
447-
nodeSelector: map[string]string{nodeHostnameKey: workerTwoNodeName},
448-
hostNetwork: true,
449-
},
450-
Label("STORY", "SDN-5345"),
451-
),
452392
)
453393
})
454394

@@ -908,6 +848,7 @@ var _ = Describe("Multi Homing", func() {
908848
Context("localnet OVN-K secondary network", func() {
909849
const (
910850
clientPodName = "client-pod"
851+
nodeHostnameKey = "kubernetes.io/hostname"
911852
servicePort = 9000
912853
dockerNetworkName = "underlay"
913854
underlayServiceIP = "60.128.0.1"

test/e2e/multihoming_utils.go

Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,6 @@ type podConfiguration struct {
161161
isPrivileged bool
162162
labels map[string]string
163163
requiresExtraNamespace bool
164-
hostNetwork bool
165164
needsIPRequestFromHostSubnet bool
166165
}
167166

@@ -172,7 +171,6 @@ func generatePodSpec(config podConfiguration) *v1.Pod {
172171
}
173172
podSpec.Spec.NodeSelector = config.nodeSelector
174173
podSpec.Labels = config.labels
175-
podSpec.Spec.HostNetwork = config.hostNetwork
176174
if config.isPrivileged {
177175
podSpec.Spec.Containers[0].SecurityContext.Privileged = ptr.To(true)
178176
} else {
@@ -255,19 +253,17 @@ func inRange(cidr string, ip string) error {
255253
return fmt.Errorf("ip [%s] is NOT in range %s", ip, cidr)
256254
}
257255

258-
func connectToServer(clientPodConfig podConfiguration, serverIP string, port int, args ...string) error {
259-
target := net.JoinHostPort(serverIP, fmt.Sprintf("%d", port))
260-
baseArgs := []string{
256+
func connectToServer(clientPodConfig podConfiguration, serverIP string, port int) error {
257+
_, err := e2ekubectl.RunKubectl(
258+
clientPodConfig.namespace,
261259
"exec",
262260
clientPodConfig.name,
263261
"--",
264262
"curl",
265263
"--connect-timeout",
266264
"2",
267-
}
268-
baseArgs = append(baseArgs, args...)
269-
270-
_, err := e2ekubectl.RunKubectl(clientPodConfig.namespace, append(baseArgs, target)...)
265+
net.JoinHostPort(serverIP, fmt.Sprintf("%d", port)),
266+
)
271267
return err
272268
}
273269

@@ -312,19 +308,16 @@ func getSecondaryInterfaceMTU(clientPodConfig podConfiguration) (int, error) {
312308
return mtu, nil
313309
}
314310

315-
func pingServer(clientPodConfig podConfiguration, serverIP string, args ...string) error {
316-
baseArgs := []string{
311+
func pingServer(clientPodConfig podConfiguration, serverIP string) error {
312+
_, err := e2ekubectl.RunKubectl(
313+
clientPodConfig.namespace,
317314
"exec",
318315
clientPodConfig.name,
319316
"--",
320317
"ping",
321318
"-c", "1", // send one ICMP echo request
322319
"-W", "2", // timeout after 2 seconds if no response
323-
}
324-
baseArgs = append(baseArgs, args...)
325-
326-
_, err := e2ekubectl.RunKubectl(clientPodConfig.namespace, append(baseArgs, serverIP)...)
327-
320+
serverIP)
328321
return err
329322
}
330323

@@ -388,18 +381,6 @@ func podIPForAttachment(k8sClient clientset.Interface, podNamespace string, podN
388381
return ips[ipIndex], nil
389382
}
390383

391-
func podIPsFromStatus(k8sClient clientset.Interface, podNamespace string, podName string) ([]string, error) {
392-
pod, err := k8sClient.CoreV1().Pods(podNamespace).Get(context.Background(), podName, metav1.GetOptions{})
393-
if err != nil {
394-
return nil, err
395-
}
396-
podIPs := make([]string, 0, len(pod.Status.PodIPs))
397-
for _, podIP := range pod.Status.PodIPs {
398-
podIPs = append(podIPs, podIP.IP)
399-
}
400-
return podIPs, nil
401-
}
402-
403384
func allowedClient(podName string) string {
404385
return "allowed-" + podName
405386
}
@@ -629,27 +610,27 @@ func allowedTCPPortsForPolicy(allowPorts ...int) []mnpapi.MultiNetworkPolicyPort
629610
return portAllowlist
630611
}
631612

632-
func reachServerPodFromClient(cs clientset.Interface, serverConfig podConfiguration, clientConfig podConfiguration, serverIP string, serverPort int, args ...string) error {
613+
func reachServerPodFromClient(cs clientset.Interface, serverConfig podConfiguration, clientConfig podConfiguration, serverIP string, serverPort int) error {
633614
updatedPod, err := cs.CoreV1().Pods(serverConfig.namespace).Get(context.Background(), serverConfig.name, metav1.GetOptions{})
634615
if err != nil {
635616
return err
636617
}
637618

638619
if updatedPod.Status.Phase == v1.PodRunning {
639-
return connectToServer(clientConfig, serverIP, serverPort, args...)
620+
return connectToServer(clientConfig, serverIP, serverPort)
640621
}
641622

642623
return fmt.Errorf("pod not running. /me is sad")
643624
}
644625

645-
func pingServerPodFromClient(cs clientset.Interface, serverConfig podConfiguration, clientConfig podConfiguration, serverIP string, args ...string) error {
626+
func pingServerPodFromClient(cs clientset.Interface, serverConfig podConfiguration, clientConfig podConfiguration, serverIP string) error {
646627
updatedPod, err := cs.CoreV1().Pods(serverConfig.namespace).Get(context.Background(), serverConfig.name, metav1.GetOptions{})
647628
if err != nil {
648629
return err
649630
}
650631

651632
if updatedPod.Status.Phase == v1.PodRunning {
652-
return pingServer(clientConfig, serverIP, args...)
633+
return pingServer(clientConfig, serverIP)
653634
}
654635

655636
return fmt.Errorf("pod not running. /me is sad")

0 commit comments

Comments
 (0)