diff --git a/api/core/v1alpha1/evpninstance_types.go b/api/core/v1alpha1/evpninstance_types.go
index 6c055c44a..50bdeec6c 100644
--- a/api/core/v1alpha1/evpninstance_types.go
+++ b/api/core/v1alpha1/evpninstance_types.go
@@ -85,6 +85,11 @@ type EVPNInstanceSpec struct {
// +optional
// +kubebuilder:validation:XValidation:rule="self.name == oldSelf.name",message="VRFRef is immutable"
VRFRef *LocalObjectReference `json:"vrfRef,omitempty"`
+
+ // SuppressARP overrides the NVE-level ARP suppression setting for this VNI.
+ // When unset, the NVE-level SuppressARP setting takes precedence.
+ // +optional
+ SuppressARP *bool `json:"suppressARP,omitempty"`
}
// EVPNInstanceType defines the type of EVPN instance.
diff --git a/api/core/v1alpha1/zz_generated.deepcopy.go b/api/core/v1alpha1/zz_generated.deepcopy.go
index 5e0a83e3a..999db7845 100644
--- a/api/core/v1alpha1/zz_generated.deepcopy.go
+++ b/api/core/v1alpha1/zz_generated.deepcopy.go
@@ -2049,6 +2049,11 @@ func (in *EVPNInstanceSpec) DeepCopyInto(out *EVPNInstanceSpec) {
*out = new(LocalObjectReference)
**out = **in
}
+ if in.SuppressARP != nil {
+ in, out := &in.SuppressARP, &out.SuppressARP
+ *out = new(bool)
+ **out = **in
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EVPNInstanceSpec.
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..f60ae8062 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
@@ -168,6 +168,11 @@ spec:
x-kubernetes-list-map-keys:
- value
x-kubernetes-list-type: map
+ suppressARP:
+ description: |-
+ SuppressARP overrides the NVE-level ARP suppression setting for this VNI.
+ When unset, the NVE-level SuppressARP setting takes precedence.
+ type: boolean
type:
description: |-
Type specifies the EVPN instance type.
diff --git a/config/crd/bases/networking.metal.ironcore.dev_evpninstances.yaml b/config/crd/bases/networking.metal.ironcore.dev_evpninstances.yaml
index b407a4b2f..c9ac37195 100644
--- a/config/crd/bases/networking.metal.ironcore.dev_evpninstances.yaml
+++ b/config/crd/bases/networking.metal.ironcore.dev_evpninstances.yaml
@@ -165,6 +165,11 @@ spec:
x-kubernetes-list-map-keys:
- value
x-kubernetes-list-type: map
+ suppressARP:
+ description: |-
+ SuppressARP overrides the NVE-level ARP suppression setting for this VNI.
+ When unset, the NVE-level SuppressARP setting takes precedence.
+ type: boolean
type:
description: |-
Type specifies the EVPN instance type.
diff --git a/docs/api-reference/index.md b/docs/api-reference/index.md
index e7664c675..8d5a46bdf 100644
--- a/docs/api-reference/index.md
+++ b/docs/api-reference/index.md
@@ -1943,6 +1943,7 @@ _Appears in:_
| `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: \{\}
|
| `vrfRef` _[LocalObjectReference](#localobjectreference)_ | VRFRef is a reference to a VRF resource for which this EVPNInstance provides the L3VNI.
This field is only applicable when Type is Routed (L3VNI).
The VRF resource must exist in the same namespace.
Immutable. | | Optional: \{\}
|
+| `suppressARP` _boolean_ | SuppressARP overrides the NVE-level ARP suppression setting for this VNI.
When unset, the NVE-level SuppressARP setting takes precedence. | | Optional: \{\}
|
#### EVPNInstanceStatus
diff --git a/internal/provider/cisco/nxos/nve.go b/internal/provider/cisco/nxos/nve.go
index a1272c1ba..d920e6a15 100644
--- a/internal/provider/cisco/nxos/nve.go
+++ b/internal/provider/cisco/nxos/nve.go
@@ -64,10 +64,17 @@ func (n *NVE) XPath() string {
return "System/eps-items/epId-items/Ep-list[epId=1]"
}
+const (
+ suppressARPOff = "off"
+ suppressARPEnabled = "enabled"
+ suppressARPDisabled = "disabled"
+)
+
type VNI struct {
AssociateVrfFlag bool `json:"associateVrfFlag"`
McastGroup Option[string] `json:"mcastGroup"`
Vni int32 `json:"vni"`
+ SuppressARP string `json:"suppressARP"`
}
func (*VNI) IsListItem() {}
diff --git a/internal/provider/cisco/nxos/nve_test.go b/internal/provider/cisco/nxos/nve_test.go
index 30667cb71..b0711ab2b 100644
--- a/internal/provider/cisco/nxos/nve_test.go
+++ b/internal/provider/cisco/nxos/nve_test.go
@@ -18,10 +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"),
+ SuppressARP: suppressARPOff,
}
Register("vni", vni)
+
+ vniSuppressARPTrue := &VNI{
+ Vni: 100011,
+ SuppressARP: suppressARPEnabled,
+ }
+ Register("vni_suppress_arp_true", vniSuppressARPTrue)
+
+ vniSuppressARPFalse := &VNI{
+ Vni: 100012,
+ SuppressARP: suppressARPDisabled,
+ }
+ Register("vni_suppress_arp_false", vniSuppressARPFalse)
nveInfraVLANs := &NVEInfraVLANs{
InfraVLANList: []*NVEInfraVLAN{
{ID: 4052},
diff --git a/internal/provider/cisco/nxos/provider.go b/internal/provider/cisco/nxos/provider.go
index 697eec851..501391142 100644
--- a/internal/provider/cisco/nxos/provider.go
+++ b/internal/provider/cisco/nxos/provider.go
@@ -1117,6 +1117,14 @@ func (p *Provider) EnsureEVPNInstance(ctx context.Context, req *provider.EVPNIns
if req.EVPNInstance.Spec.MulticastGroupAddress != "" {
vni.McastGroup = NewOption(req.EVPNInstance.Spec.MulticastGroupAddress)
}
+ switch {
+ case req.EVPNInstance.Spec.SuppressARP == nil:
+ vni.SuppressARP = suppressARPOff
+ case *req.EVPNInstance.Spec.SuppressARP:
+ vni.SuppressARP = suppressARPEnabled
+ default:
+ vni.SuppressARP = suppressARPDisabled
+ }
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..b8f008234 100644
--- a/internal/provider/cisco/nxos/testdata/vni.json
+++ b/internal/provider/cisco/nxos/testdata/vni.json
@@ -10,7 +10,8 @@
{
"associateVrfFlag": false,
"mcastGroup": "239.1.1.100",
- "vni": 100010
+ "vni": 100010,
+ "suppressARP": "off"
}
]
}
diff --git a/internal/provider/cisco/nxos/testdata/vni_suppress_arp_false.json b/internal/provider/cisco/nxos/testdata/vni_suppress_arp_false.json
new file mode 100644
index 000000000..227624317
--- /dev/null
+++ b/internal/provider/cisco/nxos/testdata/vni_suppress_arp_false.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",
+ "vni": 100012,
+ "suppressARP": "disabled"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ }
+}
diff --git a/internal/provider/cisco/nxos/testdata/vni_suppress_arp_true.json b/internal/provider/cisco/nxos/testdata/vni_suppress_arp_true.json
new file mode 100644
index 000000000..3ee15787d
--- /dev/null
+++ b/internal/provider/cisco/nxos/testdata/vni_suppress_arp_true.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",
+ "vni": 100011,
+ "suppressARP": "enabled"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ }
+}
diff --git a/test/gnmi/testdata/cisco-nxos-gnmi/evpninstance.txtar b/test/gnmi/testdata/cisco-nxos-gnmi/evpninstance.txtar
index fd0fae846..1dd37c90f 100644
--- a/test/gnmi/testdata/cisco-nxos-gnmi/evpninstance.txtar
+++ b/test/gnmi/testdata/cisco-nxos-gnmi/evpninstance.txtar
@@ -86,7 +86,8 @@ spec:
{
"associateVrfFlag": false,
"mcastGroup": "DME_UNSET_PROPERTY_MARKER",
- "vni": 10100
+ "vni": 10100,
+ "suppressARP": "off"
}
]
}