Skip to content

OCPBUGS-104452: frr-k8s: sync CRD - #3108

Open
oribon wants to merge 1 commit into
openshift:masterfrom
oribon:fixtlssync
Open

OCPBUGS-104452: frr-k8s: sync CRD#3108
oribon wants to merge 1 commit into
openshift:masterfrom
oribon:fixtlssync

Conversation

@oribon

@oribon oribon commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

sync with openshift/frr#135

Signed-off-by: Ori Braunshtein <obraunsh@redhat.com>
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Aug 5, 2026
@openshift-ci-robot

Copy link
Copy Markdown
Contributor

@oribon: This pull request references Jira Issue OCPBUGS-104452, 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)

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

Details

In response to this:

sync with openshift/frr#135

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.

@openshift-ci-robot openshift-ci-robot added the jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. label Aug 5, 2026
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Summary by CodeRabbit

  • New Features

    • Added EVPN configuration options for advertising SVIs and managing Layer 2 and Layer 3 VNIs.
    • Added support for route distinguishers and route targets in EVPN configurations.
    • Added neighbor address-family selection for unicast and EVPN.
    • Added configurable allowAsIn policies for BGP neighbors.
    • Added optional IPv4 and IPv6 next-hop settings for advertised routes.
  • Validation

    • Added validation for EVPN and neighbor settings.
    • Limited each router configuration to a maximum of 50 routers.

Walkthrough

The FRRConfiguration CRD adds router-level EVPN settings, neighbor address-family and allowAsIn options, per-neighbor next-hop fields, clarified unicast scope, and a maximum of 50 BGP routers.

Changes

FRR BGP schema

Layer / File(s) Summary
Router EVPN configuration
bindata/network/frr-k8s/001-crd.yaml
The router schema adds SVI and VNI advertisement, L2/L3 VNI settings, route targets, route distinguishers, CEL validation, and a 50-router limit.
Neighbor address-family controls
bindata/network/frr-k8s/001-crd.yaml
Neighbors support unicast and evpn address families, with unicast as the default, and add allowAsIn policy values.
Unicast advertisement fields
bindata/network/frr-k8s/001-crd.yaml
Descriptions define IPv4/IPv6 unicast scope. toAdvertise.nextHop adds separately validated IPv4 and IPv6 fields.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested reviewers: jcaamano


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (3 errors)

Check name Status Explanation Resolution
Pr Quality ❌ Error The authored description only says “sync with” a remote PR; it omits Why, What, automated CI testing, and user impact or rollback details, while the 389-line CRD patch adds EVPN behavior. Update the PR description with Why, What, automated CNO CI lanes and platforms, and user impact plus upgrade/rollback considerations.
Commit Message Quality ❌ Error The PR has one non-merge commit with a scoped subject, but its body contains only a Signed-off-by trailer and does not explain why the CRD sync is needed. Add a concise commit body that states the intent and reason for syncing the CRD with openshift/frr#135; keep the existing scoped subject.
Unit Tests For Go Changes ❌ Error The PR modifies bindata/network/frr-k8s/001-crd.yaml (+386/-3), but the commit contains no added or modified *_test.go files. Add corresponding Go tests, or document a valid testing justification under “How to verify it”; then use “@coderabbitai ignore pre-merge checks” after other checks pass.
✅ Passed checks (21 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.
E2e Tests For Feature Changes ✅ Passed The PR changes only bindata/network/frr-k8s/001-crd.yaml; no *.go files under pkg/ or cmd/ were added or modified, so this check does not apply.
Rbac Least Privilege ✅ Passed The pull request changes only bindata/network/frr-k8s/001-crd.yaml; no Role or ClusterRole rules are added or modified.
Docs For Feature And Behavior Changes ✅ Passed The commit changes only bindata/network/frr-k8s/001-crd.yaml and is titled “frr-k8s: sync CRD”; the check explicitly passes upstream CRD additions.
Stale Project Docs And Config ✅ Passed Only bindata/network/frr-k8s/001-crd.yaml changed; the FRRConfiguration identity is unchanged, no scoped docs/config paths changed, and no affected API names are documented there.
Go And Test Code Quality ✅ Passed The PR changes only bindata/network/frr-k8s/001-crd.yaml; no new or modified Go code exists to trigger any of the nine checks.
Ai-Generated Code Smell ✅ Passed The diff changes only the generated CRD YAML, with no tests, comments, AI references, or unrelated code; added descriptions and validations document the new schema.
Stable And Deterministic Test Names ✅ Passed The pull request changes only bindata/network/frr-k8s/001-crd.yaml, a declarative CRD; it adds no Ginkgo test declarations or test titles.
Test Structure And Quality ✅ Passed Not applicable: the commit changes only bindata/network/frr-k8s/001-crd.yaml and adds no Ginkgo test code, cluster operations, or assertions to review.
Microshift Test Compatibility ✅ Passed The pull request changes only bindata/network/frr-k8s/001-crd.yaml; it adds no Ginkgo e2e tests or test declarations requiring MicroShift compatibility review.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The pull request changes only bindata/network/frr-k8s/001-crd.yaml and adds no Ginkgo e2e tests, so SNO test compatibility does not apply.
Topology-Aware Scheduling Compatibility ✅ Passed The PR changes only a CustomResourceDefinition schema. It adds no deployment, controller, replica, affinity, topology spread, node targeting, or disruption scheduling logic.
Ote Binary Stdout Contract ✅ Passed The PR changes only bindata/network/frr-k8s/001-crd.yaml; it adds no OTE binary, main, suite setup, or process-level stdout code.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The pull request changes only bindata/network/frr-k8s/001-crd.yaml; it adds no Ginkgo e2e tests or test networking and therefore does not trigger this check.
No-Weak-Crypto ✅ Passed The PR changes only a CRD YAML file. Added lines contain no MD5, SHA-1, DES, RC4, Blowfish, ECB, custom crypto, or secret comparison logic.
Container-Privileges ✅ Passed The PR changes only a CRD schema; added lines contain no privileged, hostPID, hostNetwork, hostIPC, SYS_ADMIN, or allowPrivilegeEscalation settings.
No-Sensitive-Data-In-Logs ✅ Passed The commit changes only a CRD YAML schema; its additions contain no logging code or sensitive values, and the validation-message text does not log data.
Title check ✅ Passed The title uses an imperative verb, identifies the affected frr-k8s component, describes the CRD synchronization, and is under 72 characters.
Description check ✅ Passed The description identifies the upstream pull request that provides the CRD changes being synchronized.
✨ 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.

@openshift-ci
openshift-ci Bot requested review from bpickard22 and fedepaol August 5, 2026 10:52
@openshift-ci

openshift-ci Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: oribon

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 5, 2026

@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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
bindata/network/frr-k8s/001-crd.yaml (1)

139-152: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Report the duplicated enum and the description typo upstream.

advertiseVNIs declares the same enum twice inside allOf. This is a controller-gen artifact from duplicated kubebuilder markers on both the type alias and the field. It is functionally harmless but it duplicates validation work on every request.

Line 150 also contains a typo: "Avertise all VNIs". This text is user-visible through oc explain.

This file is synced from openshift/frr, so fix both in the upstream API types and re-sync.

🤖 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 `@bindata/network/frr-k8s/001-crd.yaml` around lines 139 - 152, Remove the
duplicated enum validation contributing to advertiseVNIs in the upstream API
type, retaining a single Disabled/All enum definition, and correct the
description text from “Avertise all VNIs” to “Advertise all VNIs”; then re-sync
bindata/network/frr-k8s/001-crd.yaml from the upstream API definitions.
🤖 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.

Inline comments:
In `@bindata/network/frr-k8s/001-crd.yaml`:
- Around line 186-201: Update the 4-byte ASN Route Target validation rule in the
CRD to enforce the global administrator upper bound of 4294967295, replacing the
incorrect lower-bound condition and preserving the existing format checks. Apply
the same validation change in the corresponding openshift/frr source and
regenerate or sync the FRR-K8s CRD.

---

Nitpick comments:
In `@bindata/network/frr-k8s/001-crd.yaml`:
- Around line 139-152: Remove the duplicated enum validation contributing to
advertiseVNIs in the upstream API type, retaining a single Disabled/All enum
definition, and correct the description text from “Avertise all VNIs” to
“Advertise all VNIs”; then re-sync bindata/network/frr-k8s/001-crd.yaml from the
upstream API definitions.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Pro Plus

Run ID: 4a36b318-73ef-45d5-944f-03c7893b0914

📥 Commits

Reviewing files that changed from the base of the PR and between d3ad345 and 18a3d28.

📒 Files selected for processing (1)
  • bindata/network/frr-k8s/001-crd.yaml

Comment on lines +186 to +201
- message: RT with 4-byte ASN global administrator
must have format GHJK:MN where GHJK <= 4294967295
and MN <= 65535
rule: self.split(':').size() != 2 || self.split(':')[0].contains('.')
|| !self.split(':')[0].matches('[0-9]+')
|| !self.split(':')[1].matches('[0-9]+')
|| uint(self.split(':')[0]) <= 65535u ||
uint(self.split(':')[1]) <= 65535u
- message: RT with 2-byte ASN global administrator
must have format EF:OPQR where EF <= 65535
and OPQR <= 4294967295
rule: self.split(':').size() != 2 || self.split(':')[0].contains('.')
|| !self.split(':')[0].matches('[0-9]+')
|| !self.split(':')[1].matches('[0-9]+')
|| uint(self.split(':')[0]) > 65535u ||
uint(self.split(':')[1]) <= 4294967295u

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the gap with a CEL evaluation of the 4-byte ASN rule.
pip install --quiet cel-python 2>/dev/null
python - <<'PY'
import celpy
env = celpy.Environment()
rule = ("self.split(':').size() != 2 || self.split(':')[0].contains('.') "
        "|| !self.split(':')[0].matches('[0-9]+') || !self.split(':')[1].matches('[0-9]+') "
        "|| uint(self.split(':')[0]) <= 65535u || uint(self.split(':')[1]) <= 65535u")
prog = env.program(env.compile(rule))
for v in ["65000:100", "192.0.2.1:100", "99999999999:100", "4294967296:100"]:
    print(v, prog.evaluate({"self": celpy.celtypes.StringType(v)}))
PY

Repository: openshift/cluster-network-operator

Length of output: 290


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Find FRR-K8s CRD files:"
fd -a '001-crd\.yaml$|00.*crd\.yaml$' . | sed 's#^\./##' | rg 'frr-k8s|FRR|frr' || true

echo
echo "Relevant rule lines:"
if [ -f bindata/network/frr-k8s/001-crd.yaml ]; then
  sed -n '160,215p' bindata/network/frr-k8s/001-crd.yaml | cat -n
fi

echo
echo "Search for FRR RT/RD/l3vni CEL rule definitions:"
rg -n "global administrator|RouteTarget|routeTargets|l3vni|importRTs|RD|rd|matches\\(.*\\)'|contains\\('\\.')" bindata/network/frr-k8s . || true

echo
echo "Search exact rule strings:"
rg -n "self\\.split\\(':')\\.size\\(\\) != 2|GHJK|OPQR|4-byte ASN|2-byte ASN" bindata/network/frr-k8s . || true

Repository: openshift/cluster-network-operator

Length of output: 5581


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Validate Python/CEL setup:"
python3 - <<'PY'
try:
    import celpy, celpy.celtypes
    print("celpy available", celpy.__version__ if hasattr(celpy, '__version__') else "")
except Exception as e:
    print("celpy unavailable:", type(e).__name__, e)
PY

echo
echo "Evaluate validation rules with a read-only CEL probe:"
python3 - <<'PY'
try:
    import celpy, celpy.celtypes
except Exception:
    exit(77)

env = celpy.Environment()
compile = env.compile
evaluate = lambda rule, value: env.program(compile(rule)).evaluate({"self": celpy.celtypes.StringType(value)}).value()

cases = ["65000:100", "192.0.2.1:100", "99999999999:100", "4294967296:100", "4294967295:65536", "4294967296:65536"]
rules = {
    "colon_size": "self.split(':').size() == 2",
    "global_non_ipv4_numeric": "self.split(':').size() != 2 || (isIP(self.split(':')[0]) or self.split(':')[0].matches('[0-9]+'))",
    "local_numeric": "self.split(':').size() != 2 or self.split(':')[1].matches('[0-9]+')",
    "ipv4_local_bound": "self.split(':').size() != 2 or !self.split(':')[0].contains('.') or (self.split(':')[1].matches('[0-9]+') and uint(self.split(':')[1]) <= 65535u)",
    "4byte_rule": "self.split(':').size() != 2 or self.split(':')[0].contains('.') or !self.split(':')[0].matches('[0-9]+') or !self.split(':')[1].matches('[0-9]+') or uint(self.split(':')[0]) <= 65535u or uint(self.split(':')[1]) <= 65535u",
    "2byte_rule": "self.split(':').size() != 2 or self.split(':')[0].contains('.') or !self.split(':')[0].matches('[0-9]+') or !self.split(':')[1].matches('[0-9]+') or uint(self.split(':')[0]) > 65535u or uint(self.split(':')[1]) <= 4294967295u",
}

print("value\tcolon_size\tglobal_non_ipv4_numeric\tlocal_numeric\tipv4_local_bound\t4byte_rule\t2byte_rule")
for v in cases:
    print(v, "\t".join(str(evaluate(rules[k], v)) for k in rules))
PY

Repository: openshift/cluster-network-operator

Length of output: 319


🌐 Web query:

OpenShift CNO FRR-K8s 001-crd.yaml RouteTarget CEL validation rules

💡 Result:

Based on current OpenShift and OVN-Kubernetes technical documentation, CEL (Common Expression Language) validation rules for RouteTarget are specifically associated with the OVN-Kubernetes project's UserDefinedNetwork (and related EVPN) CRDs, not the OpenShift Cluster Network Operator's (CNO) frr-k8s 001-crd.yaml [1][2][3]. Recent updates have improved the robustness of these RouteTarget validations [1][2]. Specifically, developers identified an issue where unanchored regex patterns in CEL rules allowed invalid strings (e.g., those with substring matches) to pass validation [1]. To fix this, the CEL validation rules were updated to use anchored regex, ensuring the entire field value conforms to the required format [1]. Technical details regarding the RouteTarget CEL validation: - Purpose: Ensures that RouteTarget fields (used in EVPN/VRF configurations) follow the required ASN:VNI or similar format [4][3]. - Regex Anchoring: The rules utilize ^ and $ anchors in matches() calls to enforce that the entire string is evaluated [1]. - Leading Zeros: Recommendations and updates have been proposed to tighten the regex (e.g., ^[1-9][0-9]*:[1-9][0-9]*$) to prevent non-canonical representations such as leading zeros (e.g., 00001:00001) [3]. - Implementation Location: These validations are defined within the ovn-kubernetes codebase, specifically within files like go-controller/pkg/crd/userdefinednetwork/v1/evpn.go [1][2][3]. If you are looking at 001-crd.yaml within the cluster-network-operator repository for frr-k8s, note that this file primarily defines resources like FRRConfiguration and FRRK8sConfiguration [5][6]. These CNO-managed CRDs focus on BGP neighbor configurations (e.g., ASN, localASN, and address family settings) rather than OVN-Kubernetes EVPN RouteTargets [5][6][7].

Citations:


🌐 Web query:

FRR-K8s 99999999999:100 route target 4-byte ASN maximum 4294967295 validation

💡 Result:

In the context of FRR-K8s (the Kubernetes-native BGP implementation based on FRRouting), configuration parameters such as Autonomous System Numbers (ASN) are validated to support the 4-byte ASN range [1][2][3]. The maximum valid value for a 4-byte ASN is 4294967295 (UINT32_MAX) [1][2][3]. Regarding the specific configuration string 99999999999💯 1. ASN Validation: The value 99999999999 exceeds the maximum allowed 4-byte ASN of 4294967295 [1][3][4]. Consequently, any attempt to use 99999999999 as an ASN in a route target or neighbor configuration will fail validation in current FRR-K8s and FRR versions [4]. 2. FRR Technical Context: FRRouting and associated tools have implemented updates to ensure proper parsing and validation of 4-byte ASNs [4]. Earlier implementations often relied on 2-byte ASN limits (65535) or incorrectly handled 4-byte values, leading to overflow errors or malformed configuration [4][5]. Modern FRR configurations and Kubernetes Custom Resource Definitions (CRDs) for FRR-K8s explicitly define the upper bound for ASN fields as 4294967295 [1][2][3]. 3. Extended Community Parsing: Specifically for Extended Communities (such as Route Targets), FRR has been updated to use 64-bit integers during parsing to correctly distinguish between valid 4-byte ASNs and values that exceed the 32-bit limit, preventing configuration errors [4]. Attempts to input values exceeding 4294967295 will be rejected by the parser as malformed [4]. In summary, the value 99999999999 is invalid for use as an ASN in FRR-K8s because it is greater than the maximum 4-byte ASN (4294967295) [1][4].

Citations:


Enforce the 4-byte global administrator upper bound in Route Target validation.

The 4-byte ASN branch still rejects values with uint(self.split(':')[0]) <= 65535u; values above 65535 fall through without checking <= 4294967295. This lets inputs like 99999999999:100 pass the CRD CEL validation while maxLength: 21 allows 11-digit administrators. Add the 4-byte global bound to the FRR-K8s CRD and sync it from openshift/frr.

🤖 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 `@bindata/network/frr-k8s/001-crd.yaml` around lines 186 - 201, Update the
4-byte ASN Route Target validation rule in the CRD to enforce the global
administrator upper bound of 4294967295, replacing the incorrect lower-bound
condition and preserving the existing format checks. Apply the same validation
change in the corresponding openshift/frr source and regenerate or sync the
FRR-K8s CRD.

@oribon

oribon commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

/verified by ci

in openshift/frr#135

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

Copy link
Copy Markdown
Contributor

@oribon: This PR has been marked as verified by ci.

Details

In response to this:

/verified by ci

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.

@oribon

oribon commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

/test frrk8s-e2e

1 similar comment
@oribon

oribon commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

/test frrk8s-e2e

@openshift-ci

openshift-ci Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

@oribon: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/5.0-upgrade-from-stable-4.22-e2e-gcp-ovn-upgrade 18a3d28 link false /test 5.0-upgrade-from-stable-4.22-e2e-gcp-ovn-upgrade

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.

@oribon

oribon commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

/test frrk8s-e2e

@oribon

oribon commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

/test e2e-metal-ipi-ovn-dualstack-bgp
/test e2e-metal-ipi-ovn-dualstack-bgp-local-gw

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. verified Signifies that the PR passed pre-merge verification criteria

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants