Skip to content

Add EthernetSegment resource and NX-OS provider implementation#378

Merged
felix-kaestner merged 1 commit into
mainfrom
evpn-multihoming
Jul 1, 2026
Merged

Add EthernetSegment resource and NX-OS provider implementation#378
felix-kaestner merged 1 commit into
mainfrom
evpn-multihoming

Conversation

@felix-kaestner

Copy link
Copy Markdown
Contributor

Introduce the EthernetSegment API type for EVPN multi-homing (RFC 7432 Section 5) with controller, CRD, and NX-OS provider.

The controller validates that the referenced interface is an aggregate with switchport configuration and watches for switchport state transitions. The NX-OS provider enables EVPN multihoming globally, configures the ESI per port-channel via a subtree patch, and rejects SingleActive mode and vPC coexistence with typed terminal errors.

@felix-kaestner felix-kaestner force-pushed the evpn-multihoming branch 3 times, most recently from e562595 to 6dc0ffb Compare May 28, 2026 19:50
@felix-kaestner felix-kaestner marked this pull request as ready for review May 28, 2026 20:01
@felix-kaestner felix-kaestner requested a review from a team as a code owner May 28, 2026 20:01
@felix-kaestner felix-kaestner marked this pull request as draft June 4, 2026 09:23

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

Nice, many thanks for this PR! There are some issues that can we could resolve quickly, so I hope we can merge it soon.

We may want to include the ethernet-segment routes in this API, however it would only mean an extension (and preferably in a follow-up).

Looking forward! 🔥

Comment thread api/core/v1alpha1/ethernetsegment_types.go Outdated
Comment thread internal/controller/core/ethernetsegment_controller.go
Comment thread internal/controller/core/ethernetsegment_controller.go Outdated
Comment thread internal/controller/core/ethernetsegment_controller_test.go
Comment thread internal/provider/cisco/nxos/testdata/esi_interface.json
Comment thread internal/provider/cisco/nxos/provider.go Outdated
@felix-kaestner felix-kaestner requested a review from nikatza June 26, 2026 17:17
@felix-kaestner felix-kaestner marked this pull request as ready for review June 26, 2026 17:17
@felix-kaestner felix-kaestner force-pushed the evpn-multihoming branch 3 times, most recently from ee5879c to cd9e8a1 Compare June 29, 2026 09:50
Comment thread api/core/v1alpha1/ethernetsegment_types.go

// ESIType is the ESI derivation type parsed from the first byte of ESI.
// +optional
ESIType ESIType `json:"esiType,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.

Wouldn't it make more sense to use a mutating webhook for this? After all this is immutable after creation, right?

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.

Also saw this thread now indicating that the device may not always support the requested state. I am wondering if we shouldn't go into configured=False then because intent!=configured.

@felix-kaestner felix-kaestner Jul 1, 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.

Status.ESIType is populated from the device state (read-back from the operational ESI's first byte), not defaulted from user input. So a mutating webhook wouldn't apply here. The spec field ESIType is already immutable via CEL validation.

Regarding Configured=False for unsupported states: the provider returns an error for unsupported ESI types, which the controller surfaces as a terminal error and sets Configured=False. So this case is already covered.

mh.State = AdminStEnabled
mh.EadEviRoute = true
mh.DfElectionMode = DfElectModeModulo
mh.DfElectionTime = "3.0"

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 the device's default?

@felix-kaestner felix-kaestner Jul 1, 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.

Yes, 3 seconds is the NX-OS default for the DF election hold timer. We set it explicitly so that the desired-state payload is fully declarative — otherwise a gNMI GET would return "3.0" from the device but our desired state would have no value, causing a perpetual reconcile diff.

Only DfElectionMode=Modulo is not device default, as it would be the Cisco specific PerFlow. However, the mode is contained in the spec, with a default value of Modulo, so we use that here (adhering to the spec).

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.

EadEviRoute is also not device default, but we set it always to true as the cross-vendor default set by this project.

return fmt.Errorf("ESI type %s is not supported by this provider", req.EthernetSegment.Spec.ESIType)
}

return p.Patch(ctx, f, mh, mm, es)

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 you see any option to not patch all of these entities for each ES? Everything but es are singeltons, aren't they? I am not seeing them being cleaned up. Do you think a (vendored) global ESI Multi-Homing config would make sense?

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.

You are right that some of these entities are global singletons on NX-OS and not per ES. However, the options like DF in openconfig are per ES, hence we added it also the spec.

/openconfig-ethernet-segments		
  ethernet-segments
    ethernet-segment[name]
      name
      config
      state
      df-election
        config
        df-election-method
        preference
        revertive
        election-wait-time

Things like the feature activation or the EvpnMulticastItems are static values, same for all ES, so setting those paths in every ES's reconcilation is not a conflict. Only the DfElectionTime in the MultihomingItems would lead to conflict between multiple ES resources.

@felix-kaestner felix-kaestner force-pushed the evpn-multihoming branch 2 times, most recently from b77f315 to ffd6194 Compare July 1, 2026 08:14
Introduce the EthernetSegment API type for EVPN multi-homing
(RFC 7432 Section 5) with controller, CRD, and NX-OS provider.

The controller validates that the referenced interface is an
aggregate with switchport configuration and watches for switchport
state transitions. The NX-OS provider enables EVPN multihoming
globally, configures the ESI per port-channel via a subtree patch,
and rejects SingleActive mode and vPC coexistence with typed
terminal errors.

Signed-off-by: Felix Kästner <felix.kaestner@sap.com>
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

Merging this branch changes the coverage (1 decrease, 1 increase)

Impacted Packages Coverage Δ 🤖
github.com/ironcore-dev/network-operator/api/core/v1alpha1 0.00% (ø)
github.com/ironcore-dev/network-operator/cmd 0.00% (ø)
github.com/ironcore-dev/network-operator/internal/controller/core 63.84% (+0.30%) 👍
github.com/ironcore-dev/network-operator/internal/provider 52.00% (ø)
github.com/ironcore-dev/network-operator/internal/provider/cisco/nxos 9.78% (-0.21%) 👎

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/ironcore-dev/network-operator/api/core/v1alpha1/ethernetsegment_types.go 0.00% (ø) 0 0 0
github.com/ironcore-dev/network-operator/api/core/v1alpha1/groupversion_info.go 0.00% (ø) 0 0 0
github.com/ironcore-dev/network-operator/api/core/v1alpha1/zz_generated.deepcopy.go 0.00% (ø) 0 0 0
github.com/ironcore-dev/network-operator/cmd/main.go 0.00% (ø) 0 0 0
github.com/ironcore-dev/network-operator/internal/controller/core/ethernetsegment_controller.go 66.83% (+66.83%) 208 (+208) 139 (+139) 69 (+69) 🌟
github.com/ironcore-dev/network-operator/internal/provider/cisco/nxos/esi.go 30.00% (+30.00%) 10 (+10) 3 (+3) 7 (+7) 🌟
github.com/ironcore-dev/network-operator/internal/provider/cisco/nxos/provider.go 0.05% (-0.00%) 1880 (+75) 1 1879 (+75) 👎
github.com/ironcore-dev/network-operator/internal/provider/provider.go 52.00% (ø) 25 13 12

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • github.com/ironcore-dev/network-operator/internal/controller/core/ethernetsegment_controller_test.go
  • github.com/ironcore-dev/network-operator/internal/controller/core/suite_test.go
  • github.com/ironcore-dev/network-operator/internal/provider/cisco/nxos/esi_test.go

@felix-kaestner felix-kaestner requested a review from swagner-de July 1, 2026 08:41
@felix-kaestner felix-kaestner merged commit b3e5aa4 into main Jul 1, 2026
20 checks passed
@felix-kaestner felix-kaestner deleted the evpn-multihoming branch July 1, 2026 11:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants