Skip to content

docs: add DPDK-accelerated underlay enhancement - #549

Merged
fedepaol merged 1 commit into
openperouter:mainfrom
zeeke:docs/dpdk-underlay
Aug 24, 2026
Merged

fedepaol merged 1 commit into
openperouter:mainfrom
zeeke:docs/dpdk-underlay

Conversation

@zeeke

@zeeke zeeke commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Proposes a new GroutPort mode for the UnderlayInterface union that binds an SR-IOV VF directly to grout via DPDK, replacing the current TAP+remote= mechanism on the underlay fast path. Defines VF selection (by PCI address, netdev name, or PF+VF index), inline IPAM for DPDK-bound interfaces, and the controller provisioning flow.

Is this a BUG FIX or a FEATURE ?:

Uncomment only one, leave it on its own line:

/kind bug
/kind cleanup
/kind feature
/kind design
/kind flake
/kind failing
/kind documentation
/kind regression
/kind example

What this PR does / why we need it:

Discuss the accelerated datapath for Grout, on the underlay side.

Special notes for your reviewer:

Acceleration on the host side (L2VNI and L3VNI) will be proposed later.

Release note:

None

AI Guidelines Acknowledgment:

  • I have reviewed all changes in this PR, including any AI-generated content, and I take full responsibility for its accuracy and correctness.

Summary by CodeRabbit

  • New Features

    • Added opt-in DPDK-accelerated underlay support through grout configuration.
    • Supports configurable MTU, receive queue count, and queue size.
    • Preserves and restores network device settings during setup and teardown.
    • Existing TAP-based underlay behavior remains the default.
  • Documentation

    • Added configuration examples, validation rules, datapath limitations, error-handling guidance, and testing coverage.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request proposes a design enhancement to optimize the underlay datapath for Grout by bypassing the kernel. By allowing the direct binding of SR-IOV Virtual Functions to DPDK, the system achieves line-rate forwarding for underlay traffic. The changes include a new API configuration for GroutPort, comprehensive VF selection mechanisms, and a strategy for managing IPAM and port lifecycle in a user-space environment.

Highlights

  • New GroutPort Mode: Introduces a GroutPort mode to the UnderlayInterface union, enabling direct DPDK port attachment for SR-IOV Virtual Functions.
  • Performance Optimization: Replaces the existing TAP+remote= mechanism to eliminate kernel overhead on the underlay fast path by moving traffic entirely to user-space.
  • Flexible VF Selection: Adds a VFSelector API that supports identifying target VFs via PCI address, netdev name, or PF+VF index.
  • Inline IPAM: Implements inline IPAM support for DPDK-bound interfaces, as standard CNI IPAM plugins are incompatible with non-kernel netdevs.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces a design proposal for DPDK-accelerated underlay ports in Grout, replacing the TAP-based underlay mechanism with direct DPDK port attachment using SR-IOV Virtual Functions. The review feedback highlights several inconsistencies and areas for improvement in the design document: the overview table uses 'CNIDevice' instead of the API enum 'CNI'; the 'VF Selection' table is missing the 'netdevName' selector; the YAML examples do not match the proposed Go API types due to missing 'vfSelector' nesting and type discriminators; the IPAM validation needs CEL rules to properly enforce the dual-stack constraint of at most one IPv4 and one IPv6 address; and there is a typo ('CTODO') in the 'GroutPortOptions' struct.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +69 to +73
| Mode | Behavior | IPAM | Datapath |
|------|----------|------|----------|
| `NetworkDevice` | Moves host device; grout creates TAP+`remote=` | Native (CIDR-derived) | TAP PMD (kernel TC redirect) |
| `CNIDevice` | Invokes CNI plugin | Delegated to CNI | Kernel or TAP PMD |
| `GroutPort` | Binds a VF to grout as a DPDK port | Inline in spec | DPDK PMD (user-space) |

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.

medium

The table lists the mode as CNIDevice, but the actual enum value in the API types is CNI (as defined in UnderlayInterface and used in the YAML examples of the previous enhancement). It would be clearer to use CNI in the table to avoid confusion.

Suggested change:

| Mode | Behavior | IPAM | Datapath |
|------|----------|------|----------|
| `NetworkDevice` | Moves host device; grout creates TAP+`remote=` | Native (CIDR-derived) | TAP PMD (kernel TC redirect) |
| `CNI` | Invokes CNI plugin | Delegated to CNI | Kernel or TAP PMD |
| `GroutPort` | Binds a VF to grout as a DPDK port | Inline in spec | DPDK PMD (user-space) |

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.

I think gemini hallucinated.

Let's align everything w/ the Device suffix - please call this new attribute GroutDevice.

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +84 to +88
| Selector | Use case |
|----------|----------|
| `pciAddress` | Exact VF PCI Address (e.g. `0000:03:02.0`) |
| `pfName`, `vfIndex` | PF name + VF index (e.g. `enp3s0f0` + `2`) |

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.

medium

The VFSelector union struct defines NetdevName as a valid selector option, and the resolution flow describes how it is resolved. However, it is missing from the "VF Selection" summary table. It should be added for completeness.

Suggested change:

| Selector | Use case |
|----------|----------|
| `pciAddress` | Exact VF PCI Address (e.g. `0000:03:02.0`) |
| `netdevName` | VF Netdev Name (e.g. `eth1`) |
| `pfName`, `vfIndex` | PF name + VF index (e.g. `enp3s0f0` + `2`) |

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +118 to +122
groutPort:
pciAddress: "0000:03:02.0"
ipam:
addresses:
- 192.168.1.10/24

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.

medium

The YAML example does not match the proposed Go API types. GroutPortConfig contains a nested VFSelector struct under the vfSelector field, which is a union and requires a type discriminator. The fields pciAddress and ipam are currently shown directly under groutPort without the vfSelector wrapper.

Suggested change
groutPort:
pciAddress: "0000:03:02.0"
ipam:
addresses:
- 192.168.1.10/24
groutPort:
vfSelector:
type: PCIAddress
pciAddress: "0000:03:02.0"
ipam:
addresses:
- 192.168.1.10/24

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +145 to +150
groutPort:
pfName: enp3s0f0
vfIndex: 0
ipam:
addresses:
- 192.168.1.10/24

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.

medium

Similar to the first example, the YAML here does not match the proposed Go API types. The pfName and vfIndex fields should be nested under vfSelector.pfVFIndex, and the type discriminator PFVFIndex must be specified.

Suggested change
groutPort:
pfName: enp3s0f0
vfIndex: 0
ipam:
addresses:
- 192.168.1.10/24
groutPort:
vfSelector:
type: PFVFIndex
pfVFIndex:
pfName: enp3s0f0
vfIndex: 0
ipam:
addresses:
- 192.168.1.10/24

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +196 to +201
type GroutPortIPAM struct {
// At most one IPv4 and one IPv6 (dual-stack).
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=2
Addresses []string `json:"addresses"`
}

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.

medium

The comment states "At most one IPv4 and one IPv6 (dual-stack)." However, the kubebuilder validation only limits the slice size to 2 (MaxItems=2). To enforce the dual-stack constraint (preventing two IPv4 or two IPv6 addresses), CEL validation rules should be added, similar to those used in TunnelEndpointConfig.

Suggested change:

type GroutPortIPAM struct {
	// At most one IPv4 and one IPv6 (dual-stack).
	// +kubebuilder:validation:MinItems=1
	// +kubebuilder:validation:MaxItems=2
	// +kubebuilder:validation:XValidation:rule="self.all(c, isCIDR(c))",message="all entries must be valid CIDRs"
	// +kubebuilder:validation:XValidation:rule="self.filter(c, isCIDR(c) && cidr(c).ip().family() == 4).size() <= 1",message="at most one IPv4 address is allowed"
	// +kubebuilder:validation:XValidation:rule="self.filter(c, isCIDR(c) && cidr(c).ip().family() == 6).size() <= 1",message="at most one IPv6 address is allowed"
	Addresses []string `json:"addresses"`
}

Comment thread enhancements/grout-dpdk-underlay.md Outdated
// +kubebuilder:validation:Maximum=64
RXQueues *int `json:"rxQueues,omitempty"`

CTODO - add fields [mtu MTU],[rxqs N_RXQ], [qsize Q_SIZE]

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.

medium

There is a placeholder comment with a typo CTODO instead of TODO. This should be cleaned up or properly defined as part of the proposed API.

Suggested change
CTODO - add fields [mtu MTU],[rxqs N_RXQ], [qsize Q_SIZE]
// TODO: add fields [mtu MTU],[rxqs N_RXQ], [qsize Q_SIZE]

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +28 to +30
- **Support IPAM for DPDK-bound interfaces.** A VF bound to a DPDK
driver has no kernel netdev, so CNI IPAM plugins cannot assign an IP
to it. `GroutPort` carries inline IPAM applied via `grcli`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Slight precision needed: bifurcated DPDK drivers do have a kernel netdev which is used (required in fact) only for control plane operations (MTU change, link state, mac address filter, etc.). But the IP address must not be configured on it.

Comment thread enhancements/grout-dpdk-underlay.md Outdated

| Risk | Mitigation |
|------|------------|
| VF not available (not created, already bound) | Clear error at reconcile with PCI address and resolution source |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What component is expected to allocate the VFs? Should it be delegated to nmstate?

If so, who will take care of re-binding the device to vfio-pci (most DPDK drivers) or move the linux netdev to the router namespace (bifurcated drivers, e.g. mlx5)?

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.

What component is expected to allocate the VFs? Should it be delegated to nmstate?

yes, either nmstate or any other configuration would be on the user. At least at this stage of the development.

If so, who will take care of re-binding the device to vfio-pci (most DPDK drivers) or move the linux netdev to the router namespace (bifurcated drivers, e.g. mlx5)?

For vfio-pci driver, the controller will do nothing on the VF during setup/teardown. Just passing the PCIAddress to a grcli interaface add ...

For bifurcated drivers, the controller will also move the netlink in and out of the perouter namespace during setup/teardown

@zeeke
zeeke force-pushed the docs/dpdk-underlay branch from c438030 to 57d8ed4 Compare July 6, 2026 14:23
@zeeke
zeeke force-pushed the docs/dpdk-underlay branch from 57d8ed4 to 8622fca Compare July 16, 2026 11:03
@maiqueb
maiqueb self-requested a review July 30, 2026 15:08
Comment thread enhancements/grout-dpdk-underlay.md Outdated
a VF directly via DPDK so that underlay traffic avoids the kernel
entirely and achieves line-rate forwarding.

#### Story 2: VF Selection by PCI Address

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 a user would want this if they have story 3? Also, the pci address is likely to be different on each node I think

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.

In real applications, this lets you bind PFs without needing to use SR-IOV or VFs.

for testing purposes, this will become useful when we'll deal with qEMU environment.

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.

In real applications, this lets you bind PFs without needing to use SR-IOV or VFs.

not sure I understood what you mean by "needing to user sr-iov"

for testing purposes, this will become useful when we'll deal with qEMU environment.

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.

In real applications, this lets you bind PFs without needing to use SR-IOV or VFs.

not sure I understood what you mean by "needing to user sr-iov"

for testing purposes, this will become useful when we'll deal with qEMU environment.

A DPDK application can run on a Physical Function by using its PCI address. The fact that the SR-IOV technology has been invented is to let multiple DPDK application use the same NIC, each of them using a different VF. But it's not mandatory.

Also, there are NICs that does not support SR-IOV (i.e. VFs) but can be used by Grout and DPDK.
@rjarry do you mind checking this last statement?

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.

fine, but then we need to reword where we talk about vfs because it's not really only about vfs.

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.

rewording

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry I had missed this notification. Yes it would make sense you allow selecting interfaces by explicit PCI address for qemu testing purposes (qemu igc emulated sriov devices do not handle VF to VF communication unless the same vlan id is explicitly configured on the two VFs hardware filters (which grout does not do). Since we need one of the VFs to be a "trunk", we cannot use that solution to run virtualized tests.

The alternative solution is to use plain virtio interfaces and give them to grout as PFs. Then plug the host side tap interfaces to a Linux bridge that will perform the vlan switching (emulating the internal igc VF switch).

Comment thread enhancements/grout-dpdk-underlay.md Outdated
|------|----------|------|----------|
| `NetworkDevice` | Moves host device; grout creates TAP+`remote=` | Native (CIDR-derived) | TAP PMD (kernel TC redirect) |
| `CNI` | Invokes CNI plugin | Delegated to CNI | Kernel |
| `GroutPort` | Binds a VF to grout as a DPDK port | Inline in spec | DPDK PMD (user-space) |

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.

I feel like groutport is a bit generic. We should mention it's a sriov vf, and optionally that it relates to grout. Something like acceleratedVF? FastDatapathVF? dpdkVF?

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.

It can also be a Physical Function.
Besides that, I'm open to suggestions

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.

but the enhancement describes vfs only, mind expanding then?

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.

updated the description

Comment thread enhancements/grout-dpdk-underlay.md Outdated
3. **Create grout port** —
`grcli interface add port u_<name> devargs <pci> [mtu MTU] [rxqs N_RXQ] [qsize Q_SIZE]`
Options are appended only when set in `portOptions`.
4. **Assign addresses** —

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.

how are addresses assigned? The proposal doesn't say that

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.

That's a good point, and I'm still in the process of defining it.
My current ideas are:
a. put an GroutDevice.Addresses map[string]string[] map array with all the addresses to add to the port for each node (the map is nodeName -> list of addresses)

b. add a GroutDevice.CIDR field and use the nodeIndex to assign IP Address.

c. The user puts the addresses on the network device and the perouter reads them. This is my favorite, but it also implies
c1. The perouter takes care of binding/unbinding the driver of the device (i.e. an Intel device is configured by the user as a netlink device, then the controller saves the addresses to a file and binds the vfio-pci driver)
c2. The controller needs to store the IP addresses in some persistence layer, make the SetupUnderlay a stateful operation

Comment thread enhancements/grout-dpdk-underlay.md Outdated
- **PFVFIndex**: read symlink `/sys/class/net/<pf>/device/virtfn<idx>`,
extract PCI address from target path.

*Optional*: The resolved PCI address is stored in Underlay status for observability.

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.

we don't have underlay status

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.

ok, removing

Comment thread enhancements/grout-dpdk-underlay.md Outdated
PFName *string `json:"pfName,omitempty"`
// +kubebuilder:validation:Minimum=0
VFIndex *int `json:"vfIndex,omitempty"`
IPAM GroutPortIPAM `json:"ipam"`

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.

do we envision allowing dhcp too?

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.

integrating grout w/ any CNI based approach will not be straightforward.

Grout takes away the IPs to the user space, which will cause CNI CHECK to fail.

This integration deserves - IMHO - a separate enhancement (or a new chapter focusing on the grout integration).

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +69 to +73
| Mode | Behavior | IPAM | Datapath |
|------|----------|------|----------|
| `NetworkDevice` | Moves host device; grout creates TAP+`remote=` | Native (CIDR-derived) | TAP PMD (kernel TC redirect) |
| `CNIDevice` | Invokes CNI plugin | Delegated to CNI | Kernel or TAP PMD |
| `GroutPort` | Binds a VF to grout as a DPDK port | Inline in spec | DPDK PMD (user-space) |

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.

I think gemini hallucinated.

Let's align everything w/ the Device suffix - please call this new attribute GroutDevice.

Comment thread enhancements/grout-dpdk-underlay.md Outdated
PFName *string `json:"pfName,omitempty"`
// +kubebuilder:validation:Minimum=0
VFIndex *int `json:"vfIndex,omitempty"`
IPAM GroutPortIPAM `json:"ipam"`

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.

integrating grout w/ any CNI based approach will not be straightforward.

Grout takes away the IPs to the user space, which will cause CNI CHECK to fail.

This integration deserves - IMHO - a separate enhancement (or a new chapter focusing on the grout integration).

@zeeke
zeeke force-pushed the docs/dpdk-underlay branch from 8622fca to 2848444 Compare August 3, 2026 16:21
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The proposal adds opt-in DPDK attachment for NetworkDevice underlays through a Grout field. It specifies API options, device lifecycle handling, IP migration, route setup, teardown restoration, datapath validation, tests, and rejected alternatives.

Changes

Grout DPDK underlay

Layer / File(s) Summary
Underlay contract and configuration
enhancements/grout-dpdk-underlay.md
Defines the optional NetworkDevice.Grout field, GroutPortOptions, DPDK behavior, validation rules, and YAML examples.
Device resolution and lifecycle
enhancements/grout-dpdk-underlay.md
Describes PCI resolution, state persistence, driver binding, Grout port creation, IP migration, FRR route installation, teardown, and recovery handling.
Datapath validation and coverage
enhancements/grout-dpdk-underlay.md
Specifies Kind and QEMU lifecycle tests, option validation tests, and rejected integration alternatives.

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

Sequence Diagram(s)

sequenceDiagram
  participant Controller
  participant SysfsNetlink
  participant Grout
  participant FRR
  Controller->>SysfsNetlink: Resolve interfaceName to PCI device
  Controller->>SysfsNetlink: Persist state and bind the DPDK driver
  Controller->>Grout: Create and configure the Grout port
  Controller->>Grout: Migrate IP addresses
  Controller->>FRR: Install the connected route
  Controller->>Grout: Remove the Grout port during teardown
  Controller->>SysfsNetlink: Restore driver, namespace, and IP state
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the documentation change for DPDK-accelerated underlay support.
Description check ✅ Passed The description covers the feature, purpose, reviewer notes, release note, and AI acknowledgment, with only minor template deviations.
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.
✨ 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.

@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: 6

🧹 Nitpick comments (2)
enhancements/grout-dpdk-underlay.md (2)

246-256: 🎯 Functional Correctness | 🔵 Trivial | 🏗️ Heavy lift

Make the test plan exercise GroutDevice.

The Kind tests use net_tap, so they do not test VF resolution or DPDK port creation. Add tests for sysfs selector resolution, VF validation, port options, inline IPAM, idempotent reconciliation, namespace-move rollback, and address/route teardown.

Replace VFSelector with tests for the inline pciAddress, pfName, and vfIndex fields defined above.

🤖 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 `@enhancements/grout-dpdk-underlay.md` around lines 246 - 256, The Test Plan
should explicitly exercise GroutDevice behavior beyond net_tap port creation:
add coverage for sysfs selector resolution using inline pciAddress, pfName, and
vfIndex fields, VF validation, DPDK port options, inline IPAM, idempotent
reconciliation, namespace-move rollback, and address/route teardown. Remove the
VFSelector sub-struct validation reference and replace it with validation tests
for the inline selector fields.

48-58: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Fix skipped Markdown heading levels.

Use ### for the story headings under ## User Stories. Use #### for the example headings under ### API Examples. This resolves the reported MD001 warnings and preserves document navigation.

Also applies to: 111-111

🤖 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 `@enhancements/grout-dpdk-underlay.md` around lines 48 - 58, Update the story
headings in the documentation to use ### beneath the ## User Stories section,
and use #### for example headings beneath ### API Examples. Apply the same
heading-level corrections to the corresponding later section identified in the
diff.

Source: Linters/SAST tools

🤖 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 `@enhancements/grout-dpdk-underlay.md`:
- Around line 101-105: Define a deterministic interface-name derivation from
GroutPortConfig and use it consistently in port creation, address assignment,
route operations, and deletion. Replace raw interface add and repeated
address-add operations with idempotent ensure/update reconciliation so retries
after partial success converge without duplicate resources, while preserving
existing port options.
- Around line 94-107: Update the setup flow around the namespace move and
subsequent grout port, address, and route creation to track completed steps and
clean them up in reverse order when any later step fails, including moving the
netlink device back to its original namespace. Make cleanup idempotent so
retries do not fail when resources are already absent, and preserve the existing
successful setup behavior.
- Around line 221-225: Update the PCIAddress handling described in the sysfs
validation flow to verify the selected PCI node is an SR-IOV VF and has a
supported driver before allowing grcli interface add; reject PFs and unrelated
devices. If PF selection is intended, explicitly revise the API and safety rules
to document and enforce that behavior.
- Around line 104-107: Expand the “Kernel route for FRR” section to define FRR’s
execution context, the interface or forwarding path used to reach Grout for BGP
traffic, and the local endpoint and ARP/ND behavior for both vfio-pci and
bifurcated-driver cases. Document the corresponding teardown steps that remove
the route and any FRR-to-Grout connectivity state.
- Around line 66-74: Extend the underlay reconciliation pipeline in
internal/grout/underlay.go to recognize GroutDevice alongside
UnderlayInterfaceNetDev and UnderlayInterfaceCNIDev, including its internal kind
and API-to-hostnetwork conversion. Add the corresponding RestoreUnderlay cleanup
branch so GroutDevice reaches grcli and is restored correctly instead of
returning unsupported kind.
- Around line 164-173: Update UnderlayInterface in
api/v1alpha1/underlay_types.go rather than replacing its existing API contract:
retain UnderlayInterfaceType, the CNIDevice discriminator value, and the
existing NetworkDevice and CNIDevice payload types, while adding GroutDevice
with the corresponding grout-port payload. Mark Type as required and configure
union validation so the discriminator selects exactly one matching payload.

---

Nitpick comments:
In `@enhancements/grout-dpdk-underlay.md`:
- Around line 246-256: The Test Plan should explicitly exercise GroutDevice
behavior beyond net_tap port creation: add coverage for sysfs selector
resolution using inline pciAddress, pfName, and vfIndex fields, VF validation,
DPDK port options, inline IPAM, idempotent reconciliation, namespace-move
rollback, and address/route teardown. Remove the VFSelector sub-struct
validation reference and replace it with validation tests for the inline
selector fields.
- Around line 48-58: Update the story headings in the documentation to use ###
beneath the ## User Stories section, and use #### for example headings beneath
### API Examples. Apply the same heading-level corrections to the corresponding
later section identified in the diff.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 816ee8f0-0baa-4ff3-bfc5-121fbbf2f177

📥 Commits

Reviewing files that changed from the base of the PR and between 183e182 and 2848444.

📒 Files selected for processing (1)
  • enhancements/grout-dpdk-underlay.md

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment thread enhancements/grout-dpdk-underlay.md
Comment thread enhancements/grout-dpdk-underlay.md Outdated
@zeeke
zeeke force-pushed the docs/dpdk-underlay branch 2 times, most recently from 6a83fcb to 8a606e0 Compare August 4, 2026 12:51

@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: 5

🧹 Nitpick comments (1)
enhancements/grout-dpdk-underlay.md (1)

317-325: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Exercise GroutDevice in the test plan.

The Kind test uses net_tap devargs, which tests the existing TAP path rather than PCI DPDK binding. Add tests for selector resolution, driver and IP migration, state recovery, route cleanup, and retry behavior.

🤖 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 `@enhancements/grout-dpdk-underlay.md` around lines 317 - 325, Update the Test
Plan section to explicitly exercise GroutDevice beyond the net_tap path,
covering selector resolution, driver and IP migration, state recovery, route
cleanup, and retry behavior; retain the existing Kind and QEMU E2E coverage.
🤖 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 `@enhancements/grout-dpdk-underlay.md`:
- Around line 326-327: Update the validation tests described in the GroutDevice
test plan to use the declared flat selector fields in GroutDeviceConfig rather
than a VFSelector sub-struct. Cover no selector, multiple selector groups,
missing vfIndex, missing pfName, and valid pciAddress, PF-name/vfIndex, and
netlinkName selector combinations.
- Around line 105-107: Resolve the GroutDevice IPAM behavior consistently across
the document: choose either API-supplied inline addresses or preconfigured host
addresses, then align selector validation, port setup, route handling, teardown,
risk-table requirements, and examples with that choice. Update the referenced
sections so the minimum address requirement and rejected/accepted inputs are
identical everywhere.
- Around line 120-123: Update the Underlay setup flow around saving original
state to reserve each PCI device before any host mutation or shared state write.
Acquire a per-PCI reservation, then atomically create the state file with the
owning resource identity; reject competing owners before allowing them to
overwrite originalDriver or addresses. Apply the same reservation and ownership
handling to the corresponding flows identified near the other referenced
sections, and release the reservation during teardown.
- Line 57: The four user story headings (including Story 1: High-Throughput
Underlay and the other stories at lines 62, 66, 71) are currently using level-4
heading syntax (####) but should use level-3 heading syntax (###) since they are
direct children under the ## User Stories section. Update each of these four
story headings from #### to ### to establish the correct hierarchy. The API
Examples sections that appear under each story (at lines 140, 164, 186) should
remain as level-4 headings (####) as they are nested under the story sections.
- Around line 295-301: Update the DPDK teardown restore-driver flow to first
unbind the PCI device from its current driver, including vfio-pci, before
writing it to the original driver’s bind file. After rebinding, verify the
device’s driver symlink points to the recorded original driver, while preserving
the bifurcated-driver netlink move behavior.

---

Nitpick comments:
In `@enhancements/grout-dpdk-underlay.md`:
- Around line 317-325: Update the Test Plan section to explicitly exercise
GroutDevice beyond the net_tap path, covering selector resolution, driver and IP
migration, state recovery, route cleanup, and retry behavior; retain the
existing Kind and QEMU E2E coverage.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2e8fddd7-b9ce-4fed-beaa-b7e4f2c8465b

📥 Commits

Reviewing files that changed from the base of the PR and between 2848444 and 8a606e0.

📒 Files selected for processing (1)
  • enhancements/grout-dpdk-underlay.md

Comment thread enhancements/grout-dpdk-underlay.md Outdated

## User Stories

#### Story 1: High-Throughput Underlay

@coderabbitai coderabbitai Bot Aug 4, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the Markdown heading hierarchy.

Use level-3 headings for the four user stories under ## User Stories. Use level-4 headings for the API examples under ### API Examples. This resolves markdownlint MD001.

Also applies to: 62-62, 66-66, 71-71, 140-140, 164-164, 186-186

🧰 Tools
🪛 markdownlint-cli2 (0.23.1)

[warning] 57-57: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4

(MD001, heading-increment)

🤖 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 `@enhancements/grout-dpdk-underlay.md` at line 57, The four user story headings
(including Story 1: High-Throughput Underlay and the other stories at lines 62,
66, 71) are currently using level-4 heading syntax (####) but should use level-3
heading syntax (###) since they are direct children under the ## User Stories
section. Update each of these four story headings from #### to ### to establish
the correct hierarchy. The API Examples sections that appear under each story
(at lines 140, 164, 186) should remain as level-4 headings (####) as they are
nested under the story sections.

Source: Linters/SAST tools

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.

yes, this should be using level 3 headings (remove one hash).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@maiqueb, agreed. Change each user story heading from #### to ###. Keep the nested #### API Examples headings unchanged.

You are interacting with an AI system.

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +120 to +123
2. **Save original state** — Read the IP addresses from the netlink
device and the current kernel driver name (from
`/sys/bus/pci/devices/<addr>/driver`). Write both to a per-device
state file at `/var/run/openperouter/grout/<pci-address>.json`.

@coderabbitai coderabbitai Bot Aug 4, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Reserve the PCI device before writing shared state.

Two Underlays can write the same /var/run/openperouter/grout/<pci-address>.json before grcli reports the device as busy. The later write can replace originalDriver and addresses; teardown can then restore the wrong state or disrupt the active owner. Acquire a per-PCI reservation and atomically create state with the owning resource identity before any host mutation.

Also applies to: 257-272, 315-315

🤖 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 `@enhancements/grout-dpdk-underlay.md` around lines 120 - 123, Update the
Underlay setup flow around saving original state to reserve each PCI device
before any host mutation or shared state write. Acquire a per-PCI reservation,
then atomically create the state file with the owning resource identity; reject
competing owners before allowing them to overwrite originalDriver or addresses.
Apply the same reservation and ownership handling to the corresponding flows
identified near the other referenced sections, and release the reservation
during teardown.

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.

this is needed IMHO.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@maiqueb, agreed. The proposal should define a per-PCI reservation before it writes the state file or changes the device. The state file should record the owning Underlay identity and use atomic creation. Teardown should verify ownership before restoration and release the reservation after successful cleanup.

🐇 ✅

You are interacting with an AI system.

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.

are you sure? do we handle multiple Underlays host configuration in parallel for the kernel datapath?
also, do we need to handle the case two different Underlays objects target the same device? Isn't it handled by webhooks?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

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.

are you sure? do we handle multiple Underlays host configuration in parallel for the kernel datapath? also, do we need to handle the case two different Underlays objects target the same device? Isn't it handled by webhooks?

you're right to push back - we can't have multiple underlays targeting the same node. My bad on not realizing the implications of this comment.

Comment thread enhancements/grout-dpdk-underlay.md
Comment thread enhancements/grout-dpdk-underlay.md Outdated
@zeeke
zeeke force-pushed the docs/dpdk-underlay branch from 8a606e0 to a50b84d Compare August 4, 2026 13:06
Comment thread enhancements/grout-dpdk-underlay.md Outdated
a VF directly via DPDK so that underlay traffic avoids the kernel
entirely and achieves line-rate forwarding.

#### Story 2: VF Selection by PCI Address

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.

fine, but then we need to reword where we talk about vfs because it's not really only about vfs.

Comment thread enhancements/grout-dpdk-underlay.md Outdated
index so that the controller resolves the correct VF without requiring
me to look up PCI addresses.

#### Story 4: VF Selection by Netlink Name

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.

is this vf only?

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.

fixing

Comment thread enhancements/grout-dpdk-underlay.md Outdated
```go
// +union
type UnderlayInterface struct {
// +kubebuilder:validation:Enum=NetworkDevice;CNI;GroutDevice

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.

wrong indentation? github is showing this differently

Comment thread enhancements/grout-dpdk-underlay.md Outdated
|------|----------|------|----------|
| `NetworkDevice` | Moves host device; grout creates TAP+`remote=` | Native (CIDR-derived) | TAP PMD (kernel TC redirect) |
| `CNIDevice` | Invokes CNI plugin | Delegated to CNI | Kernel |
| `GroutDevice` | Binds a network device to grout as a DPDK port | Scraped from kernel netdev | DPDK PMD (user-space) |

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.

I am having second thoughs about this. We are mixing how we are selecting the interface and what we are going to do with them.
Basically, when we run in grout mode, the differences between networkdevice and groutdevice.netlink name is only how we are going to operate it.

I wonder if the selection mechanism should be part of networkdevice in any case, with networkdevice being expanded as what you are suggesting for groutdevice, with an underlayacceleratedmode knob that tells how to use it (with the proper validation of what can and can't be done on each mode).

@zeeke zeeke Aug 6, 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.

If I got your idea, it would become:

Underlay
 .Spec
  .NetworkDevice
     // selects the device by netlink name. kernel mode stays like it is right now. 
     // grout mode would create a TAP device over it unless .AcceleratedDatapath.Enabled is active)
    .InterfaceName     

     // select the device by PF netlink name and VF index number. 
     // Once the device is selected, kernel and grout mode acts as per InterfaceName
    .PFName, .VFIndex

     // select the device via its PCI address. in kernel mode, it's mandatory that 
     //  the device binds a kernel driver. in grout mode, it can even be a DPDK driver. 
     //(though if it's bound to a kernel driver, the controller can steal the addresses)
    .PCIAddress         

   .AcceleratedDatapath   
       .Enabled        // Valid only if in grout mode. if true, create grout PCI ports instead of TAP devices
       .MTU, RXQueues, QSize // tune grout interface creation

I don't see any advantage or drawback in moving to this format.

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.

@maiqueb, any thoughts on these API shapes?

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.

shouldn't PFName and VFIndex be attributes of AcceleratedDatapath ?

also, I think the enabled attribute redundant - if you're specifying the AcceleratedDatapath configuration, then, you want it enabled. If you don't, well ... you don't want it.

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.

shouldn't PFName and VFIndex be attributes of AcceleratedDatapath ?

it selects a device, so it can also be used for the kernel datapath, in case we want to use a VF. But it's probably a scenario that has absolutely no meaning in the real world.

What if we start with just the netlink name only (maybe specified via .NetworkDevice.InterfaceName) ?

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.

in general, the semantics of networkdevice is "I want to select this device"
on the other hand, the previous version had the device selection semantic (pci address, netlink name, etc) and also the implicit semantic of doing acceletared datapath for that.

My proposal was to keep the concerns separate, the selection on one side and the acceleration on the other.

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.

I update the doc to meet this new approach. I dropped the PCIAddress and PFName+VFIndex device selectors.

I think this is a way simpler initial approach. the user has to put the ip address on the netlink device, as he would for the kernel datapath.

If the Underlay.Spec.Interfaces[].NetworkDevice.Grout field is not nil, the controller knows it has to set up a DPDK port.

I chose Grout as the field name because AcceleratedDatapath is too generic. subfields there are meaningful to grout, and other accelerated implementations (if there will be any) will probably need other knobs.

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.

Fair enough, I like this more

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.

@maiqueb please have a look, I think it's reasonable

@zeeke
zeeke force-pushed the docs/dpdk-underlay branch from a50b84d to e0dd4ec Compare August 6, 2026 12:52
@coderabbitai

coderabbitai Bot commented Aug 6, 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.

@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: 2

🧹 Nitpick comments (1)
enhancements/grout-dpdk-underlay.md (1)

328-334: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for GroutDevice, not only the fallback path.

The Kind test exercises net_tap, which validates existing NetworkDevice behavior rather than PCI/VF resolution, driver transitions, DPDK port creation, IP migration, or rollback. Keep it as fallback regression coverage and add fake-sysfs/fake-grcli controller tests plus a hardware-compatible lane. Confirm that the QEMU lane uses real VF passthrough or another setup that provides virtfn sysfs links.

🤖 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 `@enhancements/grout-dpdk-underlay.md` around lines 328 - 334, Add test
coverage for the GroutDevice path in addition to the existing Kind net_tap
fallback tests: introduce fake-sysfs and fake-grcli controller tests covering
PCI/VF resolution, driver transitions, DPDK port creation, IP migration, and
rollback, and ensure the QEMU lane uses real VF passthrough or an equivalent
setup exposing virtfn sysfs links.
🤖 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 `@enhancements/grout-dpdk-underlay.md`:
- Around line 131-136: Expand the DPDK binding workflow in the Port Creation
Flow and its associated risk note to document supported NICs/PMDs, VFIO/IOMMU
prerequisites, per-NIC binding commands or driver_override, and post-bind
verification. Ensure non-bifurcated handling unbinds only the target device,
restores its original driver if vfio-pci binding fails, and returns an error
safely; keep the bifurcated mlx5 path distinct.
- Around line 120-126: Update the GroutDevice resolution rules for pciAddress
and pfName + vfIndex so the PCI net directory must contain exactly one netlink
entry before reading or saving IP state; if it contains zero or multiple
entries, require an explicit netlinkName mapping and reject ambiguous migration
rather than selecting a netdev.

---

Nitpick comments:
In `@enhancements/grout-dpdk-underlay.md`:
- Around line 328-334: Add test coverage for the GroutDevice path in addition to
the existing Kind net_tap fallback tests: introduce fake-sysfs and fake-grcli
controller tests covering PCI/VF resolution, driver transitions, DPDK port
creation, IP migration, and rollback, and ensure the QEMU lane uses real VF
passthrough or an equivalent setup exposing virtfn sysfs links.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1ed2db36-1723-44bb-ac09-7d1baaaebef5

📥 Commits

Reviewing files that changed from the base of the PR and between 1538527 and e0dd4ec.

📒 Files selected for processing (1)
  • enhancements/grout-dpdk-underlay.md

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +120 to +126
- `pciAddress`: look up the netlink name via
`/sys/bus/pci/devices/<addr>/net/`.
- `pfName` + `vfIndex`: read symlink
`/sys/class/net/<pfName>/device/virtfn<vfIndex>`, extract PCI
address, then look up netlink name as above.
- `netlinkName`: look up the PCI address via
`/sys/class/net/<name>/device` symlink.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
git ls-files | rg 'enhancements/grout-dpdk-underlay\.md$' || true

echo "== file size =="
wc -l enhancements/grout-dpdk-underlay.md 2>/dev/null || true

echo "== relevant sections =="
sed -n '90,140p' enhancements/grout-dpdk-underlay.md 2>/dev/null || true
printf '\n--- lines 260-310 ---\n'
sed -n '260,310p' enhancements/grout-dpdk-underlay.md 2>/dev/null || true

echo "== search pci/netlink context in repo =="
rg -n "pciAddress|netlinkName|pfName|vfIndex|virtfn|net/|/device|Grout|dpdk" enhancements/grout-dpdk-underlay.md . --glob '!**/.git' | head -n 200

Repository: openperouter/openperouter

Length of output: 24297


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate underlay conversion/reconciliation code =="
rg -n "GroutDevice|PCIAddress|PFName|VFIndex|NetlinkName|migrateAddressesToGrout|GroutConfigurator|groutDevice" internal cmd . --glob '!**/vendor/**' --glob '!**/.git' | head -n 300

echo "== underlay.go sections =="
sed -n '1,230p' internal/grout/underlay.go 2>/dev/null || true

echo "== candidates containing selector resolution symbols =="
rg -l "pciAddress|pfName|vfIndex|netlinkName|/sys/bus/pci|/sys/class/net" --glob '!**/.git' .

Repository: openperouter/openperouter

Length of output: 13161


Require a unique GroutDevice netlink name before migration.

With pciAddress or pfName + vfIndex, /sys/bus/pci/devices/<addr>/net/ is not guaranteed to contain one netdev when PFs or representors are configured. Enforce exactly one entry or require an explicit netlinkName mapping before reading/saving IP state, or address migration will use the wrong netdev name.

🤖 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 `@enhancements/grout-dpdk-underlay.md` around lines 120 - 126, Update the
GroutDevice resolution rules for pciAddress and pfName + vfIndex so the PCI net
directory must contain exactly one netlink entry before reading or saving IP
state; if it contains zero or multiple entries, require an explicit netlinkName
mapping and reject ambiguous migration rather than selecting a netdev.

Comment thread enhancements/grout-dpdk-underlay.md
@zeeke
zeeke force-pushed the docs/dpdk-underlay branch from e0dd4ec to 7b9ad93 Compare August 7, 2026 15:30

@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: 3

🧹 Nitpick comments (1)
enhancements/grout-dpdk-underlay.md (1)

295-305: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Test the DPDK lifecycle, not only the TAP path.

The Kind test uses net_tap devargs, so it does not test NetworkDevice.Grout. Add QEMU cases that assert PCI attachment, driver transitions, address migration, FRR reachability, partial-failure rollback, teardown restoration, and reconciliation after controller restart. Add validation cases for every supported selector and invalid selector combination.

🤖 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 `@enhancements/grout-dpdk-underlay.md` around lines 295 - 305, The Test Plan
must cover the full DPDK lifecycle beyond the Kind TAP scenario. Expand the QEMU
cases to validate NetworkDevice.Grout PCI attachment, driver transitions,
address migration, FRR reachability, partial-failure rollback, teardown
restoration, and reconciliation after controller restart; expand validation
tests to cover every supported selector and invalid selector combination.
🤖 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 `@enhancements/grout-dpdk-underlay.md`:
- Around line 90-92: The router configuration reconciliation path must reject a
grout underlay when the datapath is kernel before any configurators run. Add
this validation to conversion.ValidateUnderlays so webhook, static, and other
non-webhook inputs share the same check, or return immediately from
datapathConfigurator.Validate before frrConfigurator and
datapathConfigurator.Configure are invoked.
- Around line 96-108: Update the documented Port Creation Flow to persist an
owner-to-PCI mapping before any device mutation, then use that mapping as the
primary identity source during setup, retries, re-reconcile, and teardown.
Ensure the flow no longer depends on resolving the PCI address from
interfaceName after the original netdev disappears, while retaining
interfaceName only for the initial lookup.
- Around line 81-92: Define an internal DPDK underlay kind for
NetworkDevice.Grout and update networkDeviceInterfaceToHost to select it when
grout is set, while preserving the existing netdev mapping otherwise. Handle
this kind in SetupUnderlay and RestoreUnderlay using the real grcli DPDK
bind/unbind path rather than ConfigureUnderlayNetDevInterface or TAP remote
creation, and reject Grout during webhook validation unless datapath is grout.

---

Nitpick comments:
In `@enhancements/grout-dpdk-underlay.md`:
- Around line 295-305: The Test Plan must cover the full DPDK lifecycle beyond
the Kind TAP scenario. Expand the QEMU cases to validate NetworkDevice.Grout PCI
attachment, driver transitions, address migration, FRR reachability,
partial-failure rollback, teardown restoration, and reconciliation after
controller restart; expand validation tests to cover every supported selector
and invalid selector combination.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5d3d9f00-33d3-4104-ae29-193a9077103e

📥 Commits

Reviewing files that changed from the base of the PR and between e0dd4ec and 7b9ad93.

📒 Files selected for processing (1)
  • enhancements/grout-dpdk-underlay.md

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +81 to +92
The existing `NetworkDevice` type gains an optional `grout` field. When
present, the controller binds the device as a DPDK port instead of
creating a TAP+`remote=` bridge:

| `grout` field | Behavior | IPAM | Datapath |
|---------------|----------|------|----------|
| Absent | Moves host device; grout creates TAP+`remote=` | Native (CIDR-derived) | TAP PMD (kernel TC redirect) |
| Present | Binds device to DPDK driver; creates grout port | Scraped from kernel netdev | DPDK PMD (user-space) |

The `grout` field is only valid when `--datapath=grout`. The controller
rejects it in kernel datapath mode. A webhook validation must be
implemented for this.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "Grout|UnderlayInterfaceNetDev|UnderlayInterfaceCNIDev|RestoreUnderlay|configureUnderlayPort|interface add" internal --glob '*.go'

Repository: openperouter/openperouter

Length of output: 10643


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and inspect the relevant API types, conversion paths, and grout underlay implementation.
printf '== candidate files ==\n'
git ls-files | rg 'api|type\.go|host_conversion|validate_datapath|grout_config|grout' | sed -n '1,200p'

printf '\n== api NetworkDevice type references ==\n'
rg -n "NetworkDevice|type Underlay|Grout" --glob '*.go' internal | sed -n '1,220p'

printf '\n== enhance doc relevant lines ==\n'
sed -n '70,100p' enhancements/grout-dpdk-underlay.md 2>/dev/null || true

printf '\n== host_conversion relevant ranges ==\n'
sed -n '420,575p' internal/conversion/host_conversion.go
sed -n '960,1050p' internal/conversion/host_conversion_test.go

printf '\n== grout underlay implementation ==\n'
sed -n '1,190p' internal/grout/underlay.go
sed -n '16,60p' internal/controller/routerconfiguration/grout_config.go

Repository: openperouter/openperouter

Length of output: 45014


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '== API validation and host conversion callers around datapath ==\n'
sed -n '145,235p' internal/controller/routerconfiguration/grout_config.go
sed -n '215,240p' internal/controller/routerconfiguration/grout_config.go
sed -n '1,70p' internal/conversion/validate_datapath.go
sed -n '200,235p' internal/conversion/validate_grout.go

printf '\n== API NetworkDevice type definitions ==\n'
rg -n -C 4 "NetworkDevice|type.*UnderlayInterface|Grout" api/v1alpha1/underlay_types.go api/v1alpha1/*.go internal/controller/routerconfiguration/*reader*.go internal/staticconfiguration reader_test.go internal/staticconfiguration reader.go 2>/dev/null || true

printf '\n== direct NetworkDevice.Grout mentions ==\n'
rg -n "NetworkDevice[^-]*Grout|\.Grout\b|networkDevice\.Grout|NetworkDevice.*InterfaceName" --glob '*.go' .

Repository: openperouter/openperouter

Length of output: 50381


Define the DPDK NetworkDevice.Grout reconciliation branch.

NetworkDevice currently only exposes interfaceName, and networkDeviceInterfaceToHost maps every NetworkDevice entry to hostnetwork.UnderlayInterfaceKind: "netdev". That path then calls ConfigureUnderlayNetDevInterface followed by internal/grout.ConfigureUnderlayPort, which creates a net_tap<p>,remote=<iface>,iface=... TAP port. Add a DPDK-specific internal kind and handle it in SetupUnderlay, RestoreUnderlay, webhook validation, and networkDeviceInterfaceToHost so grout selects a real grcli DPDK bind path instead of the existing TAP+remote= path.

🧰 Tools
🪛 LanguageTool

[grammar] ~81-~81: Ensure spelling is correct
Context: ... NetworkDevice type gains an optional grout field. When present, the controller bin...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 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 `@enhancements/grout-dpdk-underlay.md` around lines 81 - 92, Define an internal
DPDK underlay kind for NetworkDevice.Grout and update
networkDeviceInterfaceToHost to select it when grout is set, while preserving
the existing netdev mapping otherwise. Handle this kind in SetupUnderlay and
RestoreUnderlay using the real grcli DPDK bind/unbind path rather than
ConfigureUnderlayNetDevInterface or TAP remote creation, and reject Grout during
webhook validation unless datapath is grout.

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +96 to +108
The device is identified by the existing `interfaceName` field on
`NetworkDevice`, which is the kernel netlink device name (e.g.
`enp3s0f0v0`). The controller resolves the PCI address from sysfs at
reconcile time via `/sys/class/net/<name>/device`.

### Port Creation Flow

1. **Resolve device** — Read the PCI address from
`/sys/class/net/<interfaceName>/device` symlink.
2. **Save original state** — Read the IP addresses from the netlink
device and the current kernel driver name (from
`/sys/bus/pci/devices/<addr>/driver`). Write both to a per-device
state file at `/var/run/openperouter/grout/<pci-address>.json`.

@coderabbitai coderabbitai Bot Aug 7, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Persist the resource-to-device identity across re-reconcile.

After non-bifurcated binding, the original netdev is gone. After a bifurcated move, it is no longer visible under the host /sys/class/net. The documented flow still starts from interfaceName, while the state file is read only at teardown. A controller restart or retry therefore cannot resolve the PCI device or locate the existing port. Persist an owner-to-PCI mapping before mutation and use it for setup, retry, and teardown.

Also applies to: 240-253, 260-267

🤖 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 `@enhancements/grout-dpdk-underlay.md` around lines 96 - 108, Update the
documented Port Creation Flow to persist an owner-to-PCI mapping before any
device mutation, then use that mapping as the primary identity source during
setup, retries, re-reconcile, and teardown. Ensure the flow no longer depends on
resolving the PCI address from interfaceName after the original netdev
disappears, while retaining interfaceName only for the initial lookup.

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.

this one also sounds required.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@maiqueb, agreed. The controller must persist the owner-to-PCI mapping before it changes device ownership or driver binding. Reconcile, retry, recovery, and teardown must use this mapping as the primary device identity. interfaceName must only support the initial PCI lookup.

🐇✅

You are interacting with an AI system.

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 is valid. we can't save the device state by its pci_address.
We must use Underlay.spec.interfaces[].networkDevice.interfaceName
updating

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment thread enhancements/grout-dpdk-underlay.md Outdated
```go
// NetworkDevice moves an existing host network device into the router netns.
type NetworkDevice struct {
// interfaceName is the name of the host network device to move into

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.

nit: gh is highlighting the indentatio, not sure what it means

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.

fixed the indentation replacing tabs with 2 spaces

Comment thread enhancements/grout-dpdk-underlay.md Outdated
}

type GroutPortOptions struct {
// +kubebuilder:validation:Minimum=68

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.

same here

Comment thread enhancements/grout-dpdk-underlay.md Outdated
type GroutPortOptions struct {
// +kubebuilder:validation:Minimum=68
// +kubebuilder:validation:Maximum=9702
MTU *int `json:"mtu,omitempty"`

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.

can you document the fields?

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.

added doc. mostly taken from https://www.mankier.com/1/grcli-interface

@rjarry can you review it?

@fedepaol

Copy link
Copy Markdown
Contributor

A few very small nits, but LGTM

@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: 2

♻️ Duplicate comments (3)
enhancements/grout-dpdk-underlay.md (3)

103-121: ⚠️ Potential issue | 🟠 Major

Add reverse-order rollback for partial setup.

If driver binding succeeds but port creation, address assignment, or route setup fails, the device remains partially configured. Track completed steps and undo them in reverse order. Restore the original driver or namespace, delete the Grout port and route, and keep recovery state until cleanup completes. Make retries idempotent.

🤖 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 `@enhancements/grout-dpdk-underlay.md` around lines 103 - 121, Extend the setup
flow described in the device-state handling and Grout port creation steps to
track each completed operation and roll back completed steps in reverse order
when port creation, address assignment, or route setup fails. Restore the saved
driver or namespace, remove the created Grout port and kernel route, retain
recovery state until cleanup succeeds, and make retries idempotent.

94-99: ⚠️ Potential issue | 🟠 Major

Align device selection with the PR contract.

The PR objective lists PCI address, netlink name, and PF plus VF index selectors. This proposal supports only interfaceName. It cannot select a pre-bound DPDK device or identify a VF from its PF. Add the missing selectors and validation, or update the objective and examples to state interface-name-only support.

Also applies to: 267-274, 325-335

🤖 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 `@enhancements/grout-dpdk-underlay.md` around lines 94 - 99, Align the “Device
Selection” proposal with the stated PR contract: either define PCI address and
PF-plus-VF-index selectors with their validation and reconciliation behavior
alongside interfaceName, including support for pre-bound DPDK devices, or revise
the objective and all affected examples to explicitly promise
interface-name-only selection. Apply the same alignment to the referenced device
configuration and validation sections.

103-108: ⚠️ Potential issue | 🟠 Major

Use one stable owner identity for state and Grout resources.

The state file is keyed only by PCI address, while u_<name> has no defined derivation. Two Underlays can overwrite saved state, or a retry can delete the wrong port. Reserve the PCI device, atomically create state with the owning Underlay identity, derive deterministic resource names, and use the same identity during teardown.

Also applies to: 115-119, 247-260, 299-300

🤖 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 `@enhancements/grout-dpdk-underlay.md` around lines 103 - 108, Update the
Underlay setup and teardown flow around PCI resolution and the referenced Grout
resource operations to reserve each PCI device before use, atomically create its
state file with the owning Underlay identity, and reject conflicting owners.
Derive deterministic Grout resource names from that same stable identity instead
of an unspecified u_<name>, and require ownership validation during retries and
teardown so one Underlay cannot overwrite state or delete another Underlay’s
port.
🧹 Nitpick comments (1)
enhancements/grout-dpdk-underlay.md (1)

304-312: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Exercise the new DPDK path in tests.

The Kind test verifies net_tap devargs, which covers the existing TAP path rather than NetworkDevice.Grout. Add tests for Grout selection, IP migration, port options, route setup, binding or namespace rollback, and teardown. Keep QEMU for real DPDK binding.

🤖 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 `@enhancements/grout-dpdk-underlay.md` around lines 304 - 312, The Kind test
plan must exercise NetworkDevice.Grout instead of only validating the existing
net_tap path. Add coverage for Grout selection, IP migration, port options,
route setup, binding or namespace rollback, and teardown; retain QEMU tests for
real DPDK binding.
🤖 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 `@enhancements/grout-dpdk-underlay.md`:
- Around line 127-128: Resolve the IPAM contract consistently across the
documented setup paths: either add API-supplied addresses to GroutPortOptions
with explicit precedence over host configuration and teardown behavior, or
remove the inline-IPAM objective and require host addresses. Update the affected
examples and risk guidance, and reject zero-address setup whenever the BGP path
requires an underlay address.
- Around line 195-208: Update the NetworkDevice type comment to describe both
lifecycle modes: without grout, the host device is moved into the router netns;
with grout, non-bifurcated devices are unbound while bifurcated devices are
moved into the router netns.

---

Duplicate comments:
In `@enhancements/grout-dpdk-underlay.md`:
- Around line 103-121: Extend the setup flow described in the device-state
handling and Grout port creation steps to track each completed operation and
roll back completed steps in reverse order when port creation, address
assignment, or route setup fails. Restore the saved driver or namespace, remove
the created Grout port and kernel route, retain recovery state until cleanup
succeeds, and make retries idempotent.
- Around line 94-99: Align the “Device Selection” proposal with the stated PR
contract: either define PCI address and PF-plus-VF-index selectors with their
validation and reconciliation behavior alongside interfaceName, including
support for pre-bound DPDK devices, or revise the objective and all affected
examples to explicitly promise interface-name-only selection. Apply the same
alignment to the referenced device configuration and validation sections.
- Around line 103-108: Update the Underlay setup and teardown flow around PCI
resolution and the referenced Grout resource operations to reserve each PCI
device before use, atomically create its state file with the owning Underlay
identity, and reject conflicting owners. Derive deterministic Grout resource
names from that same stable identity instead of an unspecified u_<name>, and
require ownership validation during retries and teardown so one Underlay cannot
overwrite state or delete another Underlay’s port.

---

Nitpick comments:
In `@enhancements/grout-dpdk-underlay.md`:
- Around line 304-312: The Kind test plan must exercise NetworkDevice.Grout
instead of only validating the existing net_tap path. Add coverage for Grout
selection, IP migration, port options, route setup, binding or namespace
rollback, and teardown; retain QEMU tests for real DPDK binding.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d7346672-b6bd-4ed6-a126-8c1d752ef7a0

📥 Commits

Reviewing files that changed from the base of the PR and between 7b9ad93 and bc1a778.

📒 Files selected for processing (1)
  • enhancements/grout-dpdk-underlay.md

Comment thread enhancements/grout-dpdk-underlay.md
Comment thread enhancements/grout-dpdk-underlay.md Outdated

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

Some questions.

Comment thread enhancements/grout-dpdk-underlay.md Outdated

## User Stories

#### Story 1: High-Throughput Underlay

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.

yes, this should be using level 3 headings (remove one hash).

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +68 to +70
As an operator running grout, I want to add `grout: {}` to an existing
`NetworkDevice` interface to switch it from TAP mode to DPDK mode
without changing anything else in my Underlay spec.

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.

this user story gets into the "how".

Let's describe what we want (have per device DPDK mode via the underlay spec) instead. Or something similar.

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +72 to +75
#### Story 3: Tuning Port Parameters
As an operator, I want to set MTU, RX queue count, and queue size on
a DPDK-bound underlay port to match my NIC capabilities and traffic
profile.

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.

these params could be useful for other device types (maybe we can exclude CNI from it, since I assume each plugin can allow mtu configuration).

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.

MTU is kind of particular, and I agree it can be relevant for other device types. But RX queues and queue size are not.
I'd drop the MTU field and keep the others under the same field grout {}.

Does it look good?

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.

if you're certain you don't need to configure the MTU of the grout attachment, then by all means, remove it.

Comment thread enhancements/grout-dpdk-underlay.md Outdated

### Overview

The existing `NetworkDevice` type gains an optional `grout` field. When

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.

Could this mechanism might be useful / used in the future for other attachment types ?

Can we use any other name ? I am trying to avoid coupling the API with a specific implementation. Having a more generic name could allow the attribute to be re-used in the future. Maybe userSpaceConfig, or accelerationConfig.

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.

In my opinion, it's very unlikely to have another accelerated datapath other than Grout. And even if it exists in the future, I don't know if the grout subfields will have any meaning. So acceleratedConfig might contain something meaningless to the new implementation.

BTW, if you have any preference in the name, I'm happy to follow that.

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.

@fedepaol thoughts ? I'd really like to avoid having the name of another component in our public facing API.

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.

the problem is, at this point in time we don't know. The name is the name of the datapath implementation (similar to "kernel") and not a component, doesn't sound a big deal to me.

What we risk is having duplicated fields if:

  • another datapath implementation comes
  • the different datapath has those 3 fields, with the same semantic and meaning

all of this seems quite unlikely to me, and if it ever comes, we can have a new generic field and start the deprecation path for the grout one.

But, for the same reason (we won't have another datapath rather than grout, and if so there won't be overlap) I don't see any issue in naming it fastDatapathConfig or something like that.

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.

it sounds good to me
going for fastDatapathConfig ? acceleratedConfig ?

Comment thread enhancements/grout-dpdk-underlay.md Outdated
Comment on lines +120 to +123
2. **Save original state** — Read the IP addresses from the netlink
device and the current kernel driver name (from
`/sys/bus/pci/devices/<addr>/driver`). Write both to a per-device
state file at `/var/run/openperouter/grout/<pci-address>.json`.

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.

this is needed IMHO.

Comment thread enhancements/grout-dpdk-underlay.md Outdated
| Device not available (no kernel netdev) | Clear error at reconcile with device name |
| No IP address configured on the device | The grout port is configured with zero IP addresses |
| `vfio-pci` module not loaded | Check before binding; surface actionable error in status |
| State file lost (e.g. `/var/run` cleared) | Log warning; operator must manually rebind driver and restore IP |

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.

how will the operator know to which IP to use ? Can it be recovered from elsewhere ?...

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.

the "operator" here refers to the user, the one who configured the cluster and the perouter deployment. he knew the IP address at the deployment time, so he could still get them from somewhere.

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.

the "user" could actually be an automation.

IMHO, we need to highlight this in the documentation - the IP address for this attachment must be persisted somewhere , or be known to whoever setup the cluster.

Not sure where in the enhancement to actually add that info.

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.

but is it any different than kernelmode?
For NetworkDevice and kernel datapath, the user (or any automation on behalf of him), sets the ip addresses on the underlay network device. Once the user creates an Underlay object targeting that netlink, the interface disappears from the host, and it comes back when the Underlay object is deleted.

The same interaction is supposed to happen for grout. The fact that, under the hood, the controller strips the addresses out of the netlink to give them to grout, then saves them to a file, is a matter of implementation, isn't it?

If there are any details we want to nail down at this stage, I can add it to this enhancement

| `vfio-pci` module not loaded | Check before binding; surface actionable error in status |
| State file lost (e.g. `/var/run` cleared) | Log warning; operator must manually rebind driver and restore IP |
| Driver rebind fails at teardown | Retry with backoff; leave state file for manual recovery |
| Multiple Underlays claim the same device | `grcli interface add` fails with "device busy"; surfaced in status |

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.

we can't have multiple underlays in the same node, can we ? I think this is a non-issue.

Comment on lines +307 to +310
- **E2E tests / QEMU**: Deploy a cluster based on KVM / QEMU with emulated
SR-IOV NICs. Running the entire e2etest suite is hard, as the same clab
topology can't be implemented with VMs. A small set of test cases will be
implemented for this lane, using a simple FRR BGP peer in a container.

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.

this will be hard, but I agree we can't rely on actual HW for these tests.

| Driver rebind fails at teardown | Retry with backoff; leave state file for manual recovery |
| Multiple Underlays claim the same device | `grcli interface add` fails with "device busy"; surfaced in status |

### Test Plan

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.

I believe we should also test the resiliency of the solution, for instance, checking if we can recover from losing the grout state file (this iface has these IPs, and this PCI addr).

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.

I think that state file is our last lifeline. I think there is no other way to recover the IP addresses.

what resilience case did you have in mind?

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.

I just wanted to understand how could we ever recover from this scenario.

I might be asking for too much, given that in non-grout mode we are in the same situation (can't recover the IP if we ever delete it).

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.

yep, in non-grout mode we are in a similar situation, though the controller does not strip the address out of the netlink, so it's less likely to lose the addresses in oblivion.

A similar problem is handled in e2etest by the check_veths utility.

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.

I do think we should try to account for that scenario.

At the very least, by recording the limitation (both in our docs, and in an issue) for our future, smarter selves to address.

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.

Sounds good. I opened an issue to track this problem

Comment on lines +320 to +323
**Why not chosen:** The SR-IOV CNI moves a kernel netdev into a
container namespace — it does not hand off to grout's DPDK port creation.
IPAM via CNI is meaningless for DPDK-bound interfaces (no kernel netdev
to assign the IP to).

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.

so I hear that this alternative is just not feasible ?

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.

  • we would have to bind the right driver anyway, as the sriov-cni assumes the driver is already binded.
  • In case of vfio-pci, we wouldn't know where the user should put the IP addresses of the port.

so, I think it would create more problem than solutions

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.

yes, I agree. I am pretty much asking if it should even be mentioned as an alternative. Because I don't see any good in it :)

@zeeke
zeeke force-pushed the docs/dpdk-underlay branch from bc1a778 to 516fd0e Compare August 11, 2026 14:36
Proposes a new GroutPort mode for the UnderlayInterface union that
binds an SR-IOV VF directly to grout via DPDK, replacing the current
TAP+remote= mechanism on the underlay fast path. Defines VF selection
(by PCI address, netdev name, or PF+VF index), IP address management
and driver bind/unbind flow.

Signed-off-by: Andrea Panattoni <apanatto@redhat.com>
@zeeke
zeeke force-pushed the docs/dpdk-underlay branch from 516fd0e to bdc10f2 Compare August 17, 2026 08:59
@zeeke

zeeke commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Renamed Underlay.Spec.Interfaces[].NetworkDevice.Grout to Underlay.Spec.Interfaces[].NetworkDevice.AcceleratedConfig.

@fedepaol @maiqueb please take a nother look when you have time

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

Thank you.

Comment thread enhancements/grout-dpdk-underlay.md
| Driver rebind fails at teardown | Retry with backoff; leave state file for manual recovery |
| Multiple Underlays claim the same device | `grcli interface add` fails with "device busy"; surfaced in status |

### Test Plan

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.

I do think we should try to account for that scenario.

At the very least, by recording the limitation (both in our docs, and in an issue) for our future, smarter selves to address.

@fedepaol

Copy link
Copy Markdown
Contributor

Merging, thanks!

@fedepaol
fedepaol merged commit 2178532 into openperouter:main Aug 24, 2026
19 of 20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants