From f788c62da35bdf882dfe6023ce5cd2e5ed38a3f1 Mon Sep 17 00:00:00 2001 From: Adam Trizuljak Date: Fri, 11 Sep 2026 17:25:45 +0200 Subject: [PATCH 1/2] Add multisite ingress replication field to VNI and EVPNInstance Signed-off-by: Adam Trizuljak --- api/core/v1alpha1/evpninstance_types.go | 8 +++++++ ...stances.networking.metal.ironcore.dev.yaml | 8 +++++++ ...king.metal.ironcore.dev_evpninstances.yaml | 8 +++++++ docs/api-reference/index.md | 1 + internal/provider/cisco/nxos/nve.go | 1 + internal/provider/cisco/nxos/nve_test.go | 6 +++++ internal/provider/cisco/nxos/provider.go | 1 + .../provider/cisco/nxos/testdata/vni.json | 1 + .../vni_multisite_ingress_replication.json | 23 +++++++++++++++++++ .../cisco-nxos-gnmi/evpninstance.txtar | 1 + 10 files changed, 58 insertions(+) create mode 100644 internal/provider/cisco/nxos/testdata/vni_multisite_ingress_replication.json diff --git a/api/core/v1alpha1/evpninstance_types.go b/api/core/v1alpha1/evpninstance_types.go index 6c055c44a..85ee90511 100644 --- a/api/core/v1alpha1/evpninstance_types.go +++ b/api/core/v1alpha1/evpninstance_types.go @@ -51,6 +51,14 @@ type EVPNInstanceSpec struct { // +kubebuilder:validation:Format=ipv4 MulticastGroupAddress string `json:"multicastGroupAddress,omitempty"` + // MultisiteIngRepl enables per-VNI multisite ingress replication. + // When true, BUM traffic for this VNI is replicated to remote VTEP peers + // in the multisite domain via ingress replication. + // Typically used on Border Gateway (BGW) nodes. + // +optional + // +kubebuilder:default=false + MultisiteIngRepl bool `json:"multisiteIngRepl,omitempty"` + // RouteDistinguisher is the route distinguisher for the EVI. // This field is only applicable when Type is Bridged (MAC-VRF). // For Routed type, the route distinguisher is configured on the referenced VRF instead. diff --git a/charts/network-operator/templates/crd/evpninstances.networking.metal.ironcore.dev.yaml b/charts/network-operator/templates/crd/evpninstances.networking.metal.ironcore.dev.yaml index c9b00bfb1..a17d92f38 100644 --- a/charts/network-operator/templates/crd/evpninstances.networking.metal.ironcore.dev.yaml +++ b/charts/network-operator/templates/crd/evpninstances.networking.metal.ironcore.dev.yaml @@ -96,6 +96,14 @@ spec: The address must be in the valid multicast range (224.0.0.0 - 239.255.255.255). format: ipv4 type: string + multisiteIngRepl: + default: false + description: |- + MultisiteIngRepl enables per-VNI multisite ingress replication. + When true, BUM traffic for this VNI is replicated to remote VTEP peers + in the multisite domain via ingress replication. + Typically used on Border Gateway (BGW) nodes. + type: boolean providerConfigRef: description: |- ProviderConfigRef is a reference to a resource holding the provider-specific configuration of this interface. diff --git a/config/crd/bases/networking.metal.ironcore.dev_evpninstances.yaml b/config/crd/bases/networking.metal.ironcore.dev_evpninstances.yaml index b407a4b2f..bb7942849 100644 --- a/config/crd/bases/networking.metal.ironcore.dev_evpninstances.yaml +++ b/config/crd/bases/networking.metal.ironcore.dev_evpninstances.yaml @@ -93,6 +93,14 @@ spec: The address must be in the valid multicast range (224.0.0.0 - 239.255.255.255). format: ipv4 type: string + multisiteIngRepl: + default: false + description: |- + MultisiteIngRepl enables per-VNI multisite ingress replication. + When true, BUM traffic for this VNI is replicated to remote VTEP peers + in the multisite domain via ingress replication. + Typically used on Border Gateway (BGW) nodes. + type: boolean providerConfigRef: description: |- ProviderConfigRef is a reference to a resource holding the provider-specific configuration of this interface. diff --git a/docs/api-reference/index.md b/docs/api-reference/index.md index e7664c675..fce884186 100644 --- a/docs/api-reference/index.md +++ b/docs/api-reference/index.md @@ -1939,6 +1939,7 @@ _Appears in:_ | `vni` _integer_ | VNI is the VXLAN Network Identifier.
Immutable. | | Maximum: 1.6777214e+07
Minimum: 1
Required: \{\}
| | `type` _[EVPNInstanceType](#evpninstancetype)_ | Type specifies the EVPN instance type.
Immutable. | | Enum: [Bridged Routed]
Required: \{\}
| | `multicastGroupAddress` _string_ | MulticastGroupAddress specifies the IPv4 multicast group address used for BUM (Broadcast, Unknown unicast, Multicast) traffic.
The address must be in the valid multicast range (224.0.0.0 - 239.255.255.255). | | Format: ipv4
Optional: \{\}
| +| `multisiteIngRepl` _boolean_ | MultisiteIngRepl enables per-VNI multisite ingress replication.
When true, BUM traffic for this VNI is replicated to remote VTEP peers
in the multisite domain via ingress replication.
Typically used on Border Gateway (BGW) nodes. | false | Optional: \{\}
| | `routeDistinguisher` _string_ | RouteDistinguisher is the route distinguisher for the EVI.
This field is only applicable when Type is Bridged (MAC-VRF).
For Routed type, the route distinguisher is configured on the referenced VRF instead.
Set to "Auto" for automatic derivation (equivalent to "rd auto").
Formats supported:
- "Auto" (automatic derivation)
- Type 0: ASN(0-65535):Number(0-4294967295)
- Type 1: IPv4:Number(0-65535)
- Type 2: ASN(65536-4294967295):Number(0-65535) | | Optional: \{\}
| | `routeTargets` _[EVPNRouteTarget](#evpnroutetarget) array_ | RouteTargets is the list of route targets for the EVI. | | MinItems: 1
Optional: \{\}
| | `vlanRef` _[LocalObjectReference](#localobjectreference)_ | VLANRef is a reference to a VLAN resource for which this EVPNInstance builds the MAC-VRF.
This field is only applicable when Type is Bridged (L2VNI).
The VLAN resource must exist in the same namespace.
Immutable. | | Optional: \{\}
| diff --git a/internal/provider/cisco/nxos/nve.go b/internal/provider/cisco/nxos/nve.go index a1272c1ba..e69acf9f3 100644 --- a/internal/provider/cisco/nxos/nve.go +++ b/internal/provider/cisco/nxos/nve.go @@ -67,6 +67,7 @@ func (n *NVE) XPath() string { type VNI struct { AssociateVrfFlag bool `json:"associateVrfFlag"` McastGroup Option[string] `json:"mcastGroup"` + MultisiteIngRepl bool `json:"multisiteIngRepl"` Vni int32 `json:"vni"` } diff --git a/internal/provider/cisco/nxos/nve_test.go b/internal/provider/cisco/nxos/nve_test.go index 30667cb71..40c4c9f68 100644 --- a/internal/provider/cisco/nxos/nve_test.go +++ b/internal/provider/cisco/nxos/nve_test.go @@ -22,6 +22,12 @@ func init() { McastGroup: NewOption("239.1.1.100"), } Register("vni", vni) + + vniMultisite := &VNI{ + Vni: 100010, + MultisiteIngRepl: true, + } + Register("vni_multisite_ingress_replication", vniMultisite) nveInfraVLANs := &NVEInfraVLANs{ InfraVLANList: []*NVEInfraVLAN{ {ID: 4052}, diff --git a/internal/provider/cisco/nxos/provider.go b/internal/provider/cisco/nxos/provider.go index 697eec851..65bf3de1e 100644 --- a/internal/provider/cisco/nxos/provider.go +++ b/internal/provider/cisco/nxos/provider.go @@ -1117,6 +1117,7 @@ func (p *Provider) EnsureEVPNInstance(ctx context.Context, req *provider.EVPNIns if req.EVPNInstance.Spec.MulticastGroupAddress != "" { vni.McastGroup = NewOption(req.EVPNInstance.Spec.MulticastGroupAddress) } + vni.MultisiteIngRepl = req.EVPNInstance.Spec.MultisiteIngRepl sb.Update(vni) switch req.EVPNInstance.Spec.Type { diff --git a/internal/provider/cisco/nxos/testdata/vni.json b/internal/provider/cisco/nxos/testdata/vni.json index 8f4e8cfe0..748cbafaf 100644 --- a/internal/provider/cisco/nxos/testdata/vni.json +++ b/internal/provider/cisco/nxos/testdata/vni.json @@ -10,6 +10,7 @@ { "associateVrfFlag": false, "mcastGroup": "239.1.1.100", + "multisiteIngRepl": false, "vni": 100010 } ] diff --git a/internal/provider/cisco/nxos/testdata/vni_multisite_ingress_replication.json b/internal/provider/cisco/nxos/testdata/vni_multisite_ingress_replication.json new file mode 100644 index 000000000..30392cd68 --- /dev/null +++ b/internal/provider/cisco/nxos/testdata/vni_multisite_ingress_replication.json @@ -0,0 +1,23 @@ +{ + "eps-items": { + "epId-items": { + "Ep-list": [ + { + "epId": "1", + "nws-items": { + "vni-items": { + "Nw-list": [ + { + "associateVrfFlag": false, + "mcastGroup": "DME_UNSET_PROPERTY_MARKER", + "multisiteIngRepl": true, + "vni": 100010 + } + ] + } + } + } + ] + } + } +} diff --git a/test/gnmi/testdata/cisco-nxos-gnmi/evpninstance.txtar b/test/gnmi/testdata/cisco-nxos-gnmi/evpninstance.txtar index fd0fae846..253f67c4e 100644 --- a/test/gnmi/testdata/cisco-nxos-gnmi/evpninstance.txtar +++ b/test/gnmi/testdata/cisco-nxos-gnmi/evpninstance.txtar @@ -86,6 +86,7 @@ spec: { "associateVrfFlag": false, "mcastGroup": "DME_UNSET_PROPERTY_MARKER", + "multisiteIngRepl": false, "vni": 10100 } ] From aa68674583e429986617c5f4402fda7a04f49784 Mon Sep 17 00:00:00 2001 From: Adam Trizuljak Date: Thu, 17 Sep 2026 13:09:50 +0200 Subject: [PATCH 2/2] Set multisiteIngRepl to correct values The field is not a boolean but a string field with allowed values disable, enable, enableOptimized Signed-off-by: Adam Trizuljak --- api/core/v1alpha1/evpninstance_types.go | 21 +++++++++++++---- ...stances.networking.metal.ironcore.dev.yaml | 12 ++++++---- ...king.metal.ironcore.dev_evpninstances.yaml | 12 ++++++---- internal/provider/cisco/nxos/nve.go | 18 +++++++++++---- internal/provider/cisco/nxos/nve_test.go | 13 ++++++++--- internal/provider/cisco/nxos/provider.go | 9 +++++++- .../provider/cisco/nxos/testdata/vni.json | 2 +- .../vni_multisite_ingress_replication.json | 2 +- ...ltisite_ingress_replication_optimized.json | 23 +++++++++++++++++++ .../cisco-nxos-gnmi/evpninstance.txtar | 2 +- 10 files changed, 91 insertions(+), 23 deletions(-) create mode 100644 internal/provider/cisco/nxos/testdata/vni_multisite_ingress_replication_optimized.json diff --git a/api/core/v1alpha1/evpninstance_types.go b/api/core/v1alpha1/evpninstance_types.go index 85ee90511..4c42de4f2 100644 --- a/api/core/v1alpha1/evpninstance_types.go +++ b/api/core/v1alpha1/evpninstance_types.go @@ -51,13 +51,13 @@ type EVPNInstanceSpec struct { // +kubebuilder:validation:Format=ipv4 MulticastGroupAddress string `json:"multicastGroupAddress,omitempty"` - // MultisiteIngRepl enables per-VNI multisite ingress replication. - // When true, BUM traffic for this VNI is replicated to remote VTEP peers + // MultisiteIngRepl controls per-VNI multisite ingress replication. + // When enabled, BUM traffic for this VNI is replicated to remote VTEP peers // in the multisite domain via ingress replication. // Typically used on Border Gateway (BGW) nodes. // +optional - // +kubebuilder:default=false - MultisiteIngRepl bool `json:"multisiteIngRepl,omitempty"` + // +kubebuilder:default=Disabled + MultisiteIngRepl MultisiteIngReplMode `json:"multisiteIngRepl,omitempty"` // RouteDistinguisher is the route distinguisher for the EVI. // This field is only applicable when Type is Bridged (MAC-VRF). @@ -109,6 +109,19 @@ const ( EVPNInstanceTypeRouted EVPNInstanceType = "Routed" ) +// MultisiteIngReplMode defines the per-VNI multisite ingress-replication mode. +// +kubebuilder:validation:Enum=Disabled;Enabled;EnabledOptimized +type MultisiteIngReplMode string + +const ( + // MultisiteIngReplDisabled disables multisite ingress replication (default). + MultisiteIngReplDisabled MultisiteIngReplMode = "Disabled" + // MultisiteIngReplEnabled enables multisite ingress replication. + MultisiteIngReplEnabled MultisiteIngReplMode = "Enabled" + // MultisiteIngReplEnabledOptimized enables optimized multisite ingress replication. + MultisiteIngReplEnabledOptimized MultisiteIngReplMode = "EnabledOptimized" +) + type EVPNRouteTarget struct { // Value is the route target value, must have the format as RouteDistinguisher. // +required diff --git a/charts/network-operator/templates/crd/evpninstances.networking.metal.ironcore.dev.yaml b/charts/network-operator/templates/crd/evpninstances.networking.metal.ironcore.dev.yaml index a17d92f38..00fb04aa7 100644 --- a/charts/network-operator/templates/crd/evpninstances.networking.metal.ironcore.dev.yaml +++ b/charts/network-operator/templates/crd/evpninstances.networking.metal.ironcore.dev.yaml @@ -97,13 +97,17 @@ spec: format: ipv4 type: string multisiteIngRepl: - default: false + default: Disabled description: |- - MultisiteIngRepl enables per-VNI multisite ingress replication. - When true, BUM traffic for this VNI is replicated to remote VTEP peers + MultisiteIngRepl controls per-VNI multisite ingress replication. + When enabled, BUM traffic for this VNI is replicated to remote VTEP peers in the multisite domain via ingress replication. Typically used on Border Gateway (BGW) nodes. - type: boolean + enum: + - Disabled + - Enabled + - EnabledOptimized + type: string providerConfigRef: description: |- ProviderConfigRef is a reference to a resource holding the provider-specific configuration of this interface. diff --git a/config/crd/bases/networking.metal.ironcore.dev_evpninstances.yaml b/config/crd/bases/networking.metal.ironcore.dev_evpninstances.yaml index bb7942849..34e5b505c 100644 --- a/config/crd/bases/networking.metal.ironcore.dev_evpninstances.yaml +++ b/config/crd/bases/networking.metal.ironcore.dev_evpninstances.yaml @@ -94,13 +94,17 @@ spec: format: ipv4 type: string multisiteIngRepl: - default: false + default: Disabled description: |- - MultisiteIngRepl enables per-VNI multisite ingress replication. - When true, BUM traffic for this VNI is replicated to remote VTEP peers + MultisiteIngRepl controls per-VNI multisite ingress replication. + When enabled, BUM traffic for this VNI is replicated to remote VTEP peers in the multisite domain via ingress replication. Typically used on Border Gateway (BGW) nodes. - type: boolean + enum: + - Disabled + - Enabled + - EnabledOptimized + type: string providerConfigRef: description: |- ProviderConfigRef is a reference to a resource holding the provider-specific configuration of this interface. diff --git a/internal/provider/cisco/nxos/nve.go b/internal/provider/cisco/nxos/nve.go index e69acf9f3..31df304c8 100644 --- a/internal/provider/cisco/nxos/nve.go +++ b/internal/provider/cisco/nxos/nve.go @@ -64,11 +64,21 @@ func (n *NVE) XPath() string { return "System/eps-items/epId-items/Ep-list[epId=1]" } +// MultisiteIngRepl represents the per-VNI multisite ingress-replication state +// on NX-OS (nvo_MultisiteIngReplStateT). +type MultisiteIngRepl string + +const ( + MultisiteIngReplDisable MultisiteIngRepl = "disable" + MultisiteIngReplEnable MultisiteIngRepl = "enable" + MultisiteIngReplEnableOptimized MultisiteIngRepl = "enableOptimized" +) + type VNI struct { - AssociateVrfFlag bool `json:"associateVrfFlag"` - McastGroup Option[string] `json:"mcastGroup"` - MultisiteIngRepl bool `json:"multisiteIngRepl"` - Vni int32 `json:"vni"` + AssociateVrfFlag bool `json:"associateVrfFlag"` + McastGroup Option[string] `json:"mcastGroup"` + MultisiteIngRepl MultisiteIngRepl `json:"multisiteIngRepl"` + Vni int32 `json:"vni"` } func (*VNI) IsListItem() {} diff --git a/internal/provider/cisco/nxos/nve_test.go b/internal/provider/cisco/nxos/nve_test.go index 40c4c9f68..52110131d 100644 --- a/internal/provider/cisco/nxos/nve_test.go +++ b/internal/provider/cisco/nxos/nve_test.go @@ -18,16 +18,23 @@ func init() { Register("nve", nve) vni := &VNI{ - Vni: 100010, - McastGroup: NewOption("239.1.1.100"), + Vni: 100010, + McastGroup: NewOption("239.1.1.100"), + MultisiteIngRepl: MultisiteIngReplDisable, } Register("vni", vni) vniMultisite := &VNI{ Vni: 100010, - MultisiteIngRepl: true, + MultisiteIngRepl: MultisiteIngReplEnable, } Register("vni_multisite_ingress_replication", vniMultisite) + + vniMultisiteOptimized := &VNI{ + Vni: 100010, + MultisiteIngRepl: MultisiteIngReplEnableOptimized, + } + Register("vni_multisite_ingress_replication_optimized", vniMultisiteOptimized) nveInfraVLANs := &NVEInfraVLANs{ InfraVLANList: []*NVEInfraVLAN{ {ID: 4052}, diff --git a/internal/provider/cisco/nxos/provider.go b/internal/provider/cisco/nxos/provider.go index 65bf3de1e..1de2ce1ec 100644 --- a/internal/provider/cisco/nxos/provider.go +++ b/internal/provider/cisco/nxos/provider.go @@ -1117,7 +1117,14 @@ func (p *Provider) EnsureEVPNInstance(ctx context.Context, req *provider.EVPNIns if req.EVPNInstance.Spec.MulticastGroupAddress != "" { vni.McastGroup = NewOption(req.EVPNInstance.Spec.MulticastGroupAddress) } - vni.MultisiteIngRepl = req.EVPNInstance.Spec.MultisiteIngRepl + switch req.EVPNInstance.Spec.MultisiteIngRepl { + case v1alpha1.MultisiteIngReplEnabled: + vni.MultisiteIngRepl = MultisiteIngReplEnable + case v1alpha1.MultisiteIngReplEnabledOptimized: + vni.MultisiteIngRepl = MultisiteIngReplEnableOptimized + default: + vni.MultisiteIngRepl = MultisiteIngReplDisable + } sb.Update(vni) switch req.EVPNInstance.Spec.Type { diff --git a/internal/provider/cisco/nxos/testdata/vni.json b/internal/provider/cisco/nxos/testdata/vni.json index 748cbafaf..5ac112405 100644 --- a/internal/provider/cisco/nxos/testdata/vni.json +++ b/internal/provider/cisco/nxos/testdata/vni.json @@ -10,7 +10,7 @@ { "associateVrfFlag": false, "mcastGroup": "239.1.1.100", - "multisiteIngRepl": false, + "multisiteIngRepl": "disable", "vni": 100010 } ] diff --git a/internal/provider/cisco/nxos/testdata/vni_multisite_ingress_replication.json b/internal/provider/cisco/nxos/testdata/vni_multisite_ingress_replication.json index 30392cd68..671187a5c 100644 --- a/internal/provider/cisco/nxos/testdata/vni_multisite_ingress_replication.json +++ b/internal/provider/cisco/nxos/testdata/vni_multisite_ingress_replication.json @@ -10,7 +10,7 @@ { "associateVrfFlag": false, "mcastGroup": "DME_UNSET_PROPERTY_MARKER", - "multisiteIngRepl": true, + "multisiteIngRepl": "enable", "vni": 100010 } ] diff --git a/internal/provider/cisco/nxos/testdata/vni_multisite_ingress_replication_optimized.json b/internal/provider/cisco/nxos/testdata/vni_multisite_ingress_replication_optimized.json new file mode 100644 index 000000000..6eef332fa --- /dev/null +++ b/internal/provider/cisco/nxos/testdata/vni_multisite_ingress_replication_optimized.json @@ -0,0 +1,23 @@ +{ + "eps-items": { + "epId-items": { + "Ep-list": [ + { + "epId": "1", + "nws-items": { + "vni-items": { + "Nw-list": [ + { + "associateVrfFlag": false, + "mcastGroup": "DME_UNSET_PROPERTY_MARKER", + "multisiteIngRepl": "enableOptimized", + "vni": 100010 + } + ] + } + } + } + ] + } + } +} diff --git a/test/gnmi/testdata/cisco-nxos-gnmi/evpninstance.txtar b/test/gnmi/testdata/cisco-nxos-gnmi/evpninstance.txtar index 253f67c4e..50f67ffdd 100644 --- a/test/gnmi/testdata/cisco-nxos-gnmi/evpninstance.txtar +++ b/test/gnmi/testdata/cisco-nxos-gnmi/evpninstance.txtar @@ -86,7 +86,7 @@ spec: { "associateVrfFlag": false, "mcastGroup": "DME_UNSET_PROPERTY_MARKER", - "multisiteIngRepl": false, + "multisiteIngRepl": "disable", "vni": 10100 } ]