Skip to content

Commit 0ffe93f

Browse files
committed
feat: Virtual Tunnel End-Points (VTEPs)
* Adds generic support for VXLAN Tunnel End Point (VTEP). The core type `VTEP` requires at least two loopback interfaces on the same device, and an optional field for Multicastgroup. * The type `VTEP` has an admission webhook to validate that the provided multicast prefix is indeed a multicast prefix. This check is here limited to checking if first and last addresses are in a multicast group. * Adds a Cisco NXOS specfic type `cisco.nx.v1alpha1.VTEPConfig` that can be referenced in `ProviderConfigRef`. * Multicast prefix checks require extending the `IPPrefix` type with two methods that provide the first and the last IP in the prefix. * The `VTEPConfig` also modifies Cisco wide system settings along with NVE settings.
1 parent eeec70e commit 0ffe93f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+3334
-93
lines changed

.golangci.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,6 @@ linters:
130130
- github.com/mdlayher/arp
131131
# for github.com/sapcc/vpa_butler
132132
- k8s.io/client-go
133-
# for CVE-2025-22868
134-
- golang.org/x/oauth2
135133
toolchain-forbidden: true
136134
go-version-pattern: 1\.\d+(\.0)?$
137135
gosec:

PROJECT

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,27 @@ resources:
176176
kind: VLAN
177177
path: github.com/ironcore-dev/network-operator/api/core/v1alpha1
178178
version: v1alpha1
179+
- api:
180+
crdVersion: v1
181+
namespaced: true
182+
controller: true
183+
domain: networking.metal.ironcore.dev
184+
kind: VTEP
185+
path: github.com/ironcore-dev/network-operator/api/core/v1alpha1
186+
version: v1alpha1
187+
webhooks:
188+
validation: true
189+
webhookVersion: v1
190+
- api:
191+
crdVersion: v1
192+
namespaced: true
193+
domain: cisco.networking.metal.ironcore.dev
194+
group: nx
195+
kind: VTEPConfig
196+
controller: false
197+
path: github.com/ironcore-dev/network-operator/api/cisco/nx/v1alpha1
198+
version: v1alpha1
199+
webhooks:
200+
validation: true
201+
webhookVersion: v1
179202
version: "3"

Tiltfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ k8s_resource(new_name='ospf-underlay', objects=['underlay:ospf'], resource_deps=
102102
k8s_yaml('./config/samples/v1alpha1_vlan.yaml')
103103
k8s_resource(new_name='vlan-10', objects=['vlan-10:vlan'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
104104

105+
k8s_yaml('./config/samples/v1alpha1_vtep.yaml')
106+
k8s_yaml('./config/samples/cisco/nx/v1alpha1_vtepconfig.yaml')
107+
k8s_resource(new_name='vtep1', objects=['vtep1:vtep'], trigger_mode=TRIGGER_MODE_MANUAL, resource_deps=['lo0', 'lo1'], auto_init=False)
108+
k8s_resource(new_name='vtep1-cfg', objects=['vtep1-cfg:vtepconfig'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
109+
105110
print('🚀 network-operator development environment')
106111
print('👉 Edit the code inside the api/, cmd/, or internal/ directories')
107112
print('👉 Tilt will automatically rebuild and redeploy when changes are detected')

api/cisco/nx/v1alpha1/groupversion_info.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,8 @@ var (
2222
// AddToScheme adds the types in this group-version to the given scheme.
2323
AddToScheme = SchemeBuilder.AddToScheme
2424
)
25+
26+
// Reasons that are specific to [VTEPConfig] objects.
27+
const (
28+
VTEPConfigAlreadyExistsReason = "VTEPConfigAlreadyExists"
29+
)
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and IronCore contributors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package v1alpha1
5+
6+
import (
7+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8+
9+
v1alpha1 "github.com/ironcore-dev/network-operator/api/core/v1alpha1"
10+
)
11+
12+
// +kubebuilder:rbac:groups=nx.cisco.networking.metal.ironcore.dev,resources=vtepconfigs,verbs=get;list;watch
13+
14+
// VTEPConfig defines the Cisco-specific configuration of a VTEP/NVE
15+
type VTEPConfigSpec struct {
16+
// AdvertiseVirtualMAC controls if the VTEP should advertise a virtual MAC address
17+
// +optional
18+
// +kubebuilder:default=false
19+
AdvertiseVirtualMAC *bool `json:"advertiseVirtualMAC,omitempty"`
20+
21+
// HoldDownTime defines the duration for which the switch suppresses the advertisement of the NVE loopback address.
22+
// +optional
23+
// +kubebuilder:validation:Minimum=1
24+
// +kubebuilder:validation:Maximum=1500
25+
// +kubebuilder:default=180
26+
HoldDownTime uint16 `json:"holdDownTime,omitempty"`
27+
28+
// InfraVLANs specifies VLANs used by all SVI interfaces for uplink and vPC peer-links in VXLAN as infra-VLANs.
29+
// The total number of VLANs configured must not exceed 512.
30+
// Elements in the list must not overlap with each other.
31+
// +optional
32+
// +kubebuilder:validation:MaxItems=10
33+
InfraVLANs []VLANListItem `json:"infraVLANs,omitempty"`
34+
}
35+
36+
// VLANListItem represents a single VLAN ID or a range start-end. If ID is set, rangeMin and rangeMax must be absent. If ID is absent, both rangeMin
37+
// and rangeMax must be set.
38+
// +kubebuilder:validation:XValidation:rule="!has(self.rangeMax) || self.rangeMax > self.rangeMin",message="rangeMax must be greater than rangeMin"
39+
// +kubebuilder:validation:XValidation:rule="has(self.id) || (has(self.rangeMin) && has(self.rangeMax))",message="either ID or both rangeMin and rangeMax must be set"
40+
// +kubebuilder:validation:XValidation:rule="!has(self.id) || (!has(self.rangeMin) && !has(self.rangeMax))",message="rangeMin and rangeMax must be omitted when ID is set"
41+
type VLANListItem struct {
42+
// +optional
43+
// +kubebuilder:validation:Minimum=1
44+
// +kubebuilder:validation:Maximum=3967
45+
ID uint16 `json:"id,omitempty"`
46+
// +optional
47+
// +kubebuilder:validation:Minimum=1
48+
// +kubebuilder:validation:Maximum=3967
49+
RangeMin uint16 `json:"rangeMin,omitempty"`
50+
// +optional
51+
// +kubebuilder:validation:Minimum=1
52+
// +kubebuilder:validation:Maximum=3967
53+
RangeMax uint16 `json:"rangeMax,omitempty"`
54+
}
55+
56+
// +kubebuilder:object:root=true
57+
// +kubebuilder:resource:path=vtepconfigs
58+
// +kubebuilder:resource:singular=vtepconfig
59+
60+
// VTEPConfig is the Schema for the VTEP API
61+
type VTEPConfig struct {
62+
metav1.TypeMeta `json:",inline"`
63+
metav1.ObjectMeta `json:"metadata,omitempty,omitzero"`
64+
65+
// spec defines the desired state of VTEP
66+
// +required
67+
Spec VTEPConfigSpec `json:"spec"`
68+
}
69+
70+
// +kubebuilder:object:root=true
71+
72+
// VTEPList contains a list of VTEP
73+
type VTEPConfigList struct {
74+
metav1.TypeMeta `json:",inline"`
75+
metav1.ListMeta `json:"metadata,omitempty"`
76+
Items []VTEPConfig `json:"items"`
77+
}
78+
79+
// init registers the VTEPConfig type with the core v1alpha1 scheme and sets
80+
// itself as a dependency for the VTEP core type.
81+
func init() {
82+
v1alpha1.RegisterVTEPDependency(GroupVersion.WithKind("VTEPConfig"))
83+
SchemeBuilder.Register(&VTEPConfig{}, &VTEPConfigList{})
84+
}

api/cisco/nx/v1alpha1/zz_generated.deepcopy.go

Lines changed: 98 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/core/v1alpha1/groupversion_info.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ const (
105105

106106
// WaitingForDependenciesReason indicates that the resource is waiting for its dependencies to be ready.
107107
WaitingForDependenciesReason = "WaitingForDependencies"
108+
109+
// IncompatibleProviderConfigRef indicates that the referenced provider configuration is not compatible with the target platform.
110+
IncompatibleProviderConfigRef = "IncompatibleProviderConfigRef"
108111
)
109112

110113
// Reasons that are specific to [Interface] objects.

api/core/v1alpha1/ref_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type TypedLocalObjectReference struct {
3838
// +required
3939
// +kubebuilder:validation:MinLength=1
4040
// +kubebuilder:validation:MaxLength=253
41-
//+kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/)?([a-z0-9]([-a-z0-9]*[a-z0-9])?)$`
41+
// +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/)?([a-z0-9]([-a-z0-9]*[a-z0-9])?)$`
4242
APIVersion string `json:"apiVersion"`
4343
}
4444

0 commit comments

Comments
 (0)