Skip to content

OCPBUGS-87249: on AWS, select associated IPv6 CIDR block for egress IP subnet - #228

Merged
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
jechen0648:egressipv6_assignment_on_aws
Aug 14, 2026
Merged

OCPBUGS-87249: on AWS, select associated IPv6 CIDR block for egress IP subnet#228
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
jechen0648:egressipv6_assignment_on_aws

Conversation

@jechen0648

@jechen0648 jechen0648 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

On dualstack IPv4-primary AWS clusters, egressIPv6 addresses are never assigned to egress nodes even though the nodes report non-zero IPv6 capacity in their cloud.network.openshift.io/egress-ipconfig annotation.

The root cause is in getSubnet (pkg/cloudprovider/aws.go). AWS represents an IPv6 CIDR block association on a subnet through Ipv6CidrBlockAssociationSet, and each entry carries a state (associating, associated, disassociated, etc.). A subnet can accumulate multiple entries over its lifetime — for example, after an IPv6 CIDR block is replaced, the old entry stays in the list as disassociated ahead of the new associated entry.

The previous code unconditionally picked Ipv6CidrBlockAssociationSet[0] without checking state, if the first entry is stale (disassociated), one of two things goes wrong:

  1. Wrong CIDR returned — the old, now-disassociated IPv6 CIDR is used as the node's IPv6 subnet in the annotation. OVN-Kubernetes stores this and then cannot find a node whose subnet contains the egress IPv6 address (which is from the current, correct CIDR), so it never assigns the EgressIP.
  2. No CIDR returned — if the first entry has an empty Ipv6CidrBlock, the condition fails and v6Subnet stays nil. The annotation lacks an IPv6 subnet entirely and OVN-Kubernetes concludes the node has no IPv6 egress capability.
    In both cases, no CloudPrivateIPConfig is ever created for the IPv6 EgressIP, so CNCC is never asked to assign it.

Fix
Iterate through all entries in Ipv6CidrBlockAssociationSet and select the first one whose state is associated.

Two minor cleanups are included in the same change:

The empty-subnet guard is tightened from len > 1 to len != 1 so that a DescribeSubnets response returning zero subnets is also caught.
The IPv4 parsing block is cleaned up to avoid shadowing the outer subnet variable (_, v4Net, err instead of _, subnet, err).

Related
A companion fix in [openshift/ovn-kubernetes](openshift/ovn-kubernetes#3269) ensures OVN-Kubernetes re-evaluates unassigned EgressIPs when the cloud.network.openshift.io/egress-ipconfig annotation changes, so that any cluster where the annotation was previously incorrect (e.g., missing IPv6 subnet) gets healed automatically once CNCC updates it.

Testing
Pre-merge testing was performed with openshift/ovn-kubernetes#3269 on dualstack AWS IPv4 primary and dualstack AWS IPv6 primary cluster
Regression testing with openshift/ovn-kubernetes#3269 was performed on dualstack BM cluster

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jun 26, 2026
@openshift-ci-robot openshift-ci-robot added jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Jun 26, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@jechen0648: This pull request references Jira Issue OCPBUGS-87249, which is invalid:

  • expected the bug to target the "5.0.0" version, but no target version was set

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

On dualstack IPv4-primary AWS clusters, egressIPv6 addresses are never assigned to egress nodes even though the nodes report non-zero IPv6 capacity in their cloud.network.openshift.io/egress-ipconfig annotation.

The root cause is in getSubnet (pkg/cloudprovider/aws.go). AWS represents an IPv6 CIDR block association on a subnet through Ipv6CidrBlockAssociationSet, and each entry carries a state (associating, associated, disassociated, etc.). A subnet can accumulate multiple entries over its lifetime — for example, after an IPv6 CIDR block is replaced, the old entry stays in the list as disassociated ahead of the new associated entry.

The previous code unconditionally picked Ipv6CidrBlockAssociationSet[0] without checking state, if the first entry is stale (disassociated), one of two things goes wrong:

Wrong CIDR returned — the old, now-disassociated IPv6 CIDR is used as the node's IPv6 subnet in the annotation. OVN-Kubernetes stores this and then cannot find a node whose subnet contains the egress IPv6 address (which is from the current, correct CIDR), so it never assigns the EgressIP.
No CIDR returned — if the first entry has an empty Ipv6CidrBlock, the condition fails and v6Subnet stays nil. The annotation lacks an IPv6 subnet entirely and OVN-Kubernetes concludes the node has no IPv6 egress capability.
In both cases, no CloudPrivateIPConfig is ever created for the IPv6 EgressIP, so CNCC is never asked to assign it.

Fix
Iterate through all entries in Ipv6CidrBlockAssociationSet and select the first one whose state is associated.

Two minor cleanups are included in the same change:

The empty-subnet guard is tightened from len > 1 to len != 1 so that a DescribeSubnets response returning zero subnets is also caught.
The IPv4 parsing block is cleaned up to avoid shadowing the outer subnet variable (_, v4Net, err instead of _, subnet, err).

Testing

Related
A companion fix in openshift/ovn-kubernetes ensures OVN-Kubernetes re-evaluates unassigned EgressIPs when the cloud.network.openshift.io/egress-ipconfig annotation changes, so that any cluster where the annotation was previously incorrect (e.g., missing IPv6 subnet) gets healed automatically once CNCC updates it.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 6efd75a3-2f57-49a1-a3fd-b6196cb0398d

📥 Commits

Reviewing files that changed from the base of the PR and between dada754 and 67353ad.

📒 Files selected for processing (1)
  • pkg/cloudprovider/aws.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/cloudprovider/aws.go

Summary by CodeRabbit

  • Bug Fixes
    • Improved network address detection for IPv4 and IPv6 subnets.
    • IPv6 subnet selection now ignores associations that are not active.
    • Added clearer error reporting when subnet address parsing fails.

Walkthrough

The AWS getSubnet function now parses IPv4 CIDRs directly from CidrBlock and selects the first non-empty IPv6 association in Associated state. Parsing failures return version-specific errors.

Changes

AWS subnet CIDR parsing

Layer / File(s) Summary
Parse IPv4 and IPv6 CIDRs
pkg/cloudprovider/aws.go
IPv4 parsing uses subnet.CidrBlock. IPv6 parsing skips empty, nil, and non-Associated entries. Invalid values return version-specific errors.

Estimated code review effort: 2 (Simple) | ~10 minutes

Mergeability Score: ⚪ Minimal · up to 67353

This localized change selects the active AWS IPv6 subnet association and tightens subnet handling; no actionable merge-blocking risk remains beyond normal checks and review.

Suggested reviewers: martinkennelly

🚥 Pre-merge checks | ✅ 15
✅ Passed checks (15 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed The diff changes only pkg/cloudprovider/aws.go. It adds no Ginkgo test constructs or test titles, so no unstable or overly specific test name was introduced.
Test Structure And Quality ✅ Passed The PR changes only pkg/cloudprovider/aws.go; no Ginkgo test file or It block was added or modified, so these test-structure criteria are not applicable.
Microshift Test Compatibility ✅ Passed The patch changes only pkg/cloudprovider/aws.go and adds no Ginkgo e2e tests, so MicroShift test compatibility requirements do not apply.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The diff changes only pkg/cloudprovider/aws.go and adds no Ginkgo e2e tests, so no SNO multi-node test assumptions were introduced.
Topology-Aware Scheduling Compatibility ✅ Passed The diff changes only AWS subnet CIDR parsing in pkg/cloudprovider/aws.go. It adds no manifests, replicas, affinity, topology spread, selectors, tolerations, or PDBs.
Ote Binary Stdout Contract ✅ Passed The commit changes only AWS subnet CIDR parsing in getSubnet; it adds no stdout writes, logging setup changes, or process-level suite code.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The PR changes only pkg/cloudprovider/aws.go; it adds no Ginkgo e2e tests or test connectivity, so this compatibility check is not applicable.
No-Weak-Crypto ✅ Passed The commit changes only AWS subnet parsing. Added lines use net.ParseCIDR and compare AWS association state; no weak crypto, custom crypto, or secret/token comparison is introduced.
Container-Privileges ✅ Passed The diff changes only pkg/cloudprovider/aws.go; it adds no container or Kubernetes manifest privilege settings, capabilities, host namespaces, or privilege escalation options.
No-Sensitive-Data-In-Logs ✅ Passed The PR changes only CIDR parsing and association selection in getSubnet; it adds no logging and exposes no passwords, tokens, API keys, PII, hostnames, or customer data.
Title check ✅ Passed The title clearly identifies the AWS IPv6 CIDR selection fix for EgressIP subnet handling.
Description check ✅ Passed The description explains the AWS dual-stack EgressIP issue, root cause, fix, related work, and testing.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jechen0648

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@jechen0648

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@jechen0648 jechen0648 changed the title [WIP]OCPBUGS-87249: on AWS, select associated IPv6 CIDR block for egress IP subnet OCPBUGS-87249: on AWS, select associated IPv6 CIDR block for egress IP subnet Jul 6, 2026
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 6, 2026
@jechen0648
jechen0648 force-pushed the egressipv6_assignment_on_aws branch from 1568129 to b71c43e Compare July 6, 2026 20:38

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/cloudprovider/aws.go (1)

268-277: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Handle zero subnet results before indexing.

Line 268 only rejects multiple results, so Line 277 can panic when DescribeSubnets returns zero subnets. This also conflicts with the PR objective to tighten the guard to exactly one subnet.

Proposed fix
-	if len(describeOutput.Subnets) > 1 {
+	if len(describeOutput.Subnets) != 1 {
 		subnetId := "<nil>"
 		if networkInterface.SubnetId != nil {
 			subnetId = *networkInterface.SubnetId
 		}
-		return nil, nil, fmt.Errorf("error: multiple subnets found for the subnet ID: %s", subnetId)
+		return nil, nil, fmt.Errorf("error: expected exactly one subnet for subnet ID %s, got %d", subnetId, len(describeOutput.Subnets))
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/cloudprovider/aws.go` around lines 268 - 277, The subnet lookup in aws.go
only checks for multiple results in the DescribeSubnets flow, so it can still
panic when zero subnets are returned before using subnet :=
describeOutput.Subnets[0]. Update the guard around the DescribeSubnets result in
the same block to require exactly one subnet, handling the zero-subnet case with
an error before indexing and keeping the existing error path for multiple
results. Use the existing networkInterface.SubnetId, describeOutput.Subnets, and
subnet variables to locate and adjust the logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@pkg/cloudprovider/aws.go`:
- Around line 268-277: The subnet lookup in aws.go only checks for multiple
results in the DescribeSubnets flow, so it can still panic when zero subnets are
returned before using subnet := describeOutput.Subnets[0]. Update the guard
around the DescribeSubnets result in the same block to require exactly one
subnet, handling the zero-subnet case with an error before indexing and keeping
the existing error path for multiple results. Use the existing
networkInterface.SubnetId, describeOutput.Subnets, and subnet variables to
locate and adjust the logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 85fa1e5c-85d3-4b26-9ac5-1f81e3d4ad6b

📥 Commits

Reviewing files that changed from the base of the PR and between 0b49df2 and b71c43e.

📒 Files selected for processing (1)
  • pkg/cloudprovider/aws.go

@tssurya

tssurya commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

/assign @arghosh93 and @pperiyasamy

@openshift-ci

openshift-ci Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

@tssurya: GitHub didn't allow me to assign the following users: and.

Note that only openshift members with read permissions, repo collaborators and people who have commented on this issue/PR can be assigned. Additionally, issues/PRs can only have 10 assignees at the same time.
For more information please see the contributor guide

Details

In response to this:

/assign @arghosh93 and @pperiyasamy

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@jechen0648

Copy link
Copy Markdown
Contributor Author

@arghosh93 I pre-merge tested by fix by building pre-merged image using this PR + openshift/ovn-kubernetes#3269 which is same as u/s PR: ovn-kubernetes/ovn-kubernetes#6648, tests were performed on dualstack AWS for both IPv4 primary and IPv6 primary flavors.

@arghosh93 arghosh93 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only one NIT cmment and mostly looks god to me. I will approve based on your answer.

Comment thread pkg/cloudprovider/aws.go
subnet := describeOutput.Subnets[0]
if subnet.CidrBlock != nil && *subnet.CidrBlock != "" {
_, subnet, err := net.ParseCIDR(*subnet.CidrBlock)
_, v4Net, err := net.ParseCIDR(*subnet.CidrBlock)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you have to change the variable name here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this subnet variable is used for v4 and v6 below, it's like one variable used for two different ipstack types, it is easy to get confused , that is why I changed the variable name. But I can revert if you prefer minimal change

@arghosh93 arghosh93 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jul 15, 2026
@sadasu

sadasu commented Jul 15, 2026

Copy link
Copy Markdown

/payload-job-with-prs periodic-ci-openshift-release-main-nightly-5.0-e2e-aws-ovn-installer-dualstack-ipv6-primary-techpreview openshift/ovn-kubernetes#3269

@openshift-ci

openshift-ci Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@sadasu: it appears that you have attempted to use some version of the payload command, but your comment was incorrectly formatted and cannot be acted upon. See the docs for usage info.

@sadasu

sadasu commented Jul 15, 2026

Copy link
Copy Markdown

/payload-job-with-prs periodic-ci-openshift-release-main-nightly-5.0-e2e-aws-ovn-installer-dualstack-ipv6-primary-techpreview openshift/ovn-kubernetes#3269

@openshift-ci

openshift-ci Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@sadasu: trigger 1 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-5.0-e2e-aws-ovn-installer-dualstack-ipv6-primary-techpreview

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/91d917a0-8087-11f1-886f-7fdbe052f05d-0

@jechen0648

Copy link
Copy Markdown
Contributor Author

@jechen0648 Thanks for this fix. I also see the conformance test [sig-network][Feature:Router][apigroup:route.openshift.io] The HAProxy router should add replicas beyond the number of empty slots per backend [Suite:openshift/conformance/parallel] failing on AWS dualstack IPv4 primary and IPv6 primary jobs. I opened https://redhat.atlassian.net/browse/OCPBUGS-98795 for that issue. Would this fix also take care of that issue?

I do not think so, [sig-network][Feature:Router][apigroup:route.openshift.io] The HAProxy router should add replicas beyond the number of empty slots per backend [Suite:openshift/conformance/parallel] is a test from network edge team, I do not cover this area. My fix is specifically for egressIP feature that is a core networking feature

@pperiyasamy

Copy link
Copy Markdown
Member

The root cause is in getSubnet (pkg/cloudprovider/aws.go). AWS represents an IPv6 CIDR block association on a subnet through Ipv6CidrBlockAssociationSet, and each entry carries a state (associating, associated, disassociated, etc.). A subnet can accumulate multiple entries over its lifetime — for example, after an IPv6 CIDR block is replaced, the old entry stays in the list as disassociated ahead of the new associated entry.

you mentions a subnet can accumulate multiple entries over lifetime, do you mean lifetime of the node ? I assume associated ipv6 cidr never changes. right ? because cncc needs to populate cloud.network.openshift.io/egress-ipconfig annotation at the time of first node add event and EIPs can be assigned to it or is associated ipv6 cidr itself subject to change ?

@sadasu

sadasu commented Aug 4, 2026

Copy link
Copy Markdown

/payload-job-with-prs periodic-ci-openshift-release-main-nightly-5.0-e2e-aws-ovn-installer-dualstack-ipv6-primary-techpreview openshift/ovn-kubernetes#3269

@openshift-ci

openshift-ci Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

@sadasu: it appears that you have attempted to use some version of the payload command, but your comment was incorrectly formatted and cannot be acted upon. See the docs for usage info.

@sadasu

sadasu commented Aug 5, 2026

Copy link
Copy Markdown

/payload-job-with-prs periodic-ci-openshift-release-main-nightly-5.0-e2e-aws-ovn-installer-dualstack-ipv6-primary-techpreview openshift/ovn-kubernetes#3269

@openshift-ci

openshift-ci Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

@sadasu: trigger 1 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-5.0-e2e-aws-ovn-installer-dualstack-ipv6-primary-techpreview

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/aaa99e80-90d6-11f1-9bba-3026d0a99078-0

Comment thread pkg/cloudprovider/aws.go
}
v6Subnet = subnet
v6Subnet = v6Net
break

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this method is called only for dualstack installations, we should warn when we don't find any IPv6 subnet that is associated. For DualStack IPv6 primary, that would be an error and IPv4Primary that would be a warning. Is that captured anywhere?

@jechen0648 jechen0648 Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getSubnet() will be called for any IP stack type AWS, if Ipv6CidrBlockAssociationSet is not empty, it just processes and finds the first associated IPv6 CidrBlock

You're right that on dual-stack clusters, a missing associated IPv6 subnet may warrant a warning or error depending on Infrastructure.status.platformStatus.aws.ipFamily (DualStackIPv6Primary vs DualStackIPv4Primary). That logic is not implemented today — CNCC does not read cluster IP family config.

I think that's out of scope for this PR, which only fixes selecting the correct associated IPv6 CIDR when multiple associations exist. How about to open a follow-up for IP-stack-aware validation?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. Thanks!

@sadasu

sadasu commented Aug 12, 2026

Copy link
Copy Markdown

/jira refresh

@openshift-ci-robot openshift-ci-robot added jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. and removed jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Aug 12, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@sadasu: This pull request references Jira Issue OCPBUGS-87249, which is valid.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (5.0.0) matches configured target version for branch (5.0.0)
  • bug is in the state POST, which is one of the valid states (NEW, ASSIGNED, POST)

No GitHub users were found matching the public email listed for the QA contact in Jira (jechen+ocp-jechen@redhat.com), skipping review request.

Details

In response to this:

/jira refresh

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@sadasu

sadasu commented Aug 12, 2026

Copy link
Copy Markdown

I agree that the bug is hard to reproduce. The results from https://pr-payload-tests.ci.openshift.org/runs/ci/aaa99e80-90d6-11f1-9bba-3026d0a99078-0 show there are no regressions from this.

…P subnet

On dualstack AWS clusters, a subnet's Ipv6CidrBlockAssociationSet can
contain multiple entries when an IPv6 CIDR block has been replaced
(e.g., a stale 'disassociated' entry followed by the current
'associated' one). The previous code unconditionally picked [0],
which could return the wrong CIDR or no CIDR at all, causing the
egress-ipconfig annotation to lack the IPv6 subnet. OVN-Kubernetes
would then have no node eligible to host the IPv6 egress IP.

Fix by iterating through all associations and selecting the first one
in 'associated' state.

Signed-off-by: Jean Chen <jechen@redhat.com>
@jechen0648
jechen0648 force-pushed the egressipv6_assignment_on_aws branch from b71c43e to 67353ad Compare August 12, 2026 21:37
@openshift-ci openshift-ci Bot removed the lgtm Indicates that a PR is ready to be merged. label Aug 12, 2026
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@sadasu

sadasu commented Aug 13, 2026

Copy link
Copy Markdown

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Aug 13, 2026
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling required tests:
/test e2e-aws-ovn
/test e2e-azure-ovn
/test e2e-azure-serial-1of2
/test e2e-azure-serial-2of2
/test e2e-gcp-ovn
/test hypershift-e2e-aks

@jechen0648

Copy link
Copy Markdown
Contributor Author

/verified by pre-merge testing by @jechen0648

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label Aug 13, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@jechen0648: This PR has been marked as verified by pre-merge testing by @jechen0648.

Details

In response to this:

/verified by pre-merge testing by @jechen0648

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@sadasu

sadasu commented Aug 13, 2026

Copy link
Copy Markdown

@pperiyasamy @kyrtapz, @tssurya This seems ready for approval.

@sadasu

sadasu commented Aug 13, 2026

Copy link
Copy Markdown

/pipeline required

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling required tests:
/test e2e-aws-ovn
/test e2e-azure-ovn
/test e2e-azure-serial-1of2
/test e2e-azure-serial-2of2
/test e2e-gcp-ovn
/test hypershift-e2e-aks

@openshift-ci

openshift-ci Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

@jechen0648: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@pperiyasamy

Copy link
Copy Markdown
Member

/lgtm
/approve

@openshift-ci

openshift-ci Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: arghosh93, jechen0648, pperiyasamy, sadasu

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 14, 2026
@openshift-merge-bot
openshift-merge-bot Bot merged commit 7afccf2 into openshift:main Aug 14, 2026
14 checks passed
@openshift-ci-robot

Copy link
Copy Markdown

@jechen0648: Jira Issue OCPBUGS-87249: Some pull requests linked via external trackers have merged:

The following pull request, linked via external tracker, has not merged:

All associated pull requests must be merged or unlinked from the Jira bug in order for it to move to the next state. Once unlinked, request a bug refresh with /jira refresh.

Jira Issue OCPBUGS-87249 has not been moved to the MODIFIED state.

This PR is marked as verified. If the remaining PRs listed above are marked as verified before merging, the issue will automatically be moved to VERIFIED after all of the changes from the PRs are available in an accepted nightly payload.

Details

In response to this:

On dualstack IPv4-primary AWS clusters, egressIPv6 addresses are never assigned to egress nodes even though the nodes report non-zero IPv6 capacity in their cloud.network.openshift.io/egress-ipconfig annotation.

The root cause is in getSubnet (pkg/cloudprovider/aws.go). AWS represents an IPv6 CIDR block association on a subnet through Ipv6CidrBlockAssociationSet, and each entry carries a state (associating, associated, disassociated, etc.). A subnet can accumulate multiple entries over its lifetime — for example, after an IPv6 CIDR block is replaced, the old entry stays in the list as disassociated ahead of the new associated entry.

The previous code unconditionally picked Ipv6CidrBlockAssociationSet[0] without checking state, if the first entry is stale (disassociated), one of two things goes wrong:

  1. Wrong CIDR returned — the old, now-disassociated IPv6 CIDR is used as the node's IPv6 subnet in the annotation. OVN-Kubernetes stores this and then cannot find a node whose subnet contains the egress IPv6 address (which is from the current, correct CIDR), so it never assigns the EgressIP.
  2. No CIDR returned — if the first entry has an empty Ipv6CidrBlock, the condition fails and v6Subnet stays nil. The annotation lacks an IPv6 subnet entirely and OVN-Kubernetes concludes the node has no IPv6 egress capability.
    In both cases, no CloudPrivateIPConfig is ever created for the IPv6 EgressIP, so CNCC is never asked to assign it.

Fix
Iterate through all entries in Ipv6CidrBlockAssociationSet and select the first one whose state is associated.

Two minor cleanups are included in the same change:

The empty-subnet guard is tightened from len > 1 to len != 1 so that a DescribeSubnets response returning zero subnets is also caught.
The IPv4 parsing block is cleaned up to avoid shadowing the outer subnet variable (_, v4Net, err instead of _, subnet, err).

Related
A companion fix in [openshift/ovn-kubernetes](openshift/ovn-kubernetes#3269) ensures OVN-Kubernetes re-evaluates unassigned EgressIPs when the cloud.network.openshift.io/egress-ipconfig annotation changes, so that any cluster where the annotation was previously incorrect (e.g., missing IPv6 subnet) gets healed automatically once CNCC updates it.

Testing
Pre-merge testing was performed with openshift/ovn-kubernetes#3269 on dualstack AWS IPv4 primary and dualstack AWS IPv6 primary cluster
Regression testing with openshift/ovn-kubernetes#3269 was performed on dualstack BM cluster

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. verified Signifies that the PR passed pre-merge verification criteria

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants