Skip to content

Commit 3b35fcc

Browse files
committed
feat: define CRDs for VRF type
A VRF is composed by a single route distinguisher (RD), and a set of route targets (RTs). This set might be empty. Each route target is composed by the address families it affects and an action for it (e.g., import or export). The ipv4-evpn and ipv6-evpn will apply the route target actions to the EVPN context of the device.
1 parent bdc24c5 commit 3b35fcc

14 files changed

+638
-4
lines changed

PROJECT

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,13 @@ resources:
2828
kind: Device
2929
path: github.com/ironcore-dev/network-operator/api/v1alpha1
3030
version: v1alpha1
31+
- api:
32+
crdVersion: v1
33+
namespaced: true
34+
controller: true
35+
domain: cloud.sap
36+
group: networking
37+
kind: VRF
38+
path: github.com/ironcore-dev/network-operator/api/v1alpha1
39+
version: v1alpha1
3140
version: "3"

api/v1alpha1/vrf_types.go

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
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+
10+
// VRFSpec defines the basic structure of a Virtual Routing and Forwarding (VRF) instance/context. A VRF has one single Route
11+
// Distinguisher (RD) and a set of Route Targets (RTs), which can be empty. RTs define how the VRF learns about extra routes.
12+
type VRFSpec struct {
13+
// DeviceName is a ref to the device owning this VRF. Device must exist in the same namespace as the VRF.
14+
//
15+
// +required
16+
// +kubebuilder:validation:MinLength=1
17+
// +kubebuilder:validation:MaxLength=63
18+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="deviceName is immutable"
19+
DeviceName string `json:"deviceName,omitempty"`
20+
21+
// Name defines the name of the VRF.
22+
//
23+
// +required
24+
// +kubebuilder:validation:MaxLength=32
25+
// +kubebuilder:validation:MinLength=1
26+
// +kubebuilder:validation:Pattern=`^[a-zA-Z0-9]+$`
27+
Name string `json:"name,omitempty"`
28+
29+
// AdminState defines the administrative state of the VRF.
30+
//
31+
// +required
32+
// +kubebuilder:validation:Enum=Up;Down
33+
AdminState AdminState `json:"adminState,omitempty"`
34+
35+
// RD defines the Route Distinguisher (RD) for the VRF as per RFC 4364
36+
//
37+
// +kubebuilder:validation:Pattern=`^([0-9]+:[0-9]+|([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]+)$`
38+
// +required
39+
RD string `json:"routeDistinguisher,omitempty"`
40+
41+
// RTs defines the list of Route Targets (RTs) associated with the VRF.
42+
//
43+
// +optional
44+
RTs []RouteTarget `json:"routeTargets,omitempty"`
45+
46+
// TODO(nikatza): Discuss in weekly, depends on #30
47+
// ProviderConfigRef is a reference to a resource holding the provider-specific configuration of this VRF
48+
// (e.g., a layer-3 VNI on cisco).
49+
//
50+
// +optional
51+
// ProviderConfigRef *any `json:"providerConfigRef,omitempty"` // TODO: any is a placeholder until we discuss #30
52+
}
53+
54+
// VRFStatus defines the observed state of VRF.
55+
type VRFStatus struct {
56+
// The conditions are a list of status objects that describe the state of the D.
57+
// +listType=map
58+
// +listMapKey=type
59+
// +patchStrategy=merge
60+
// +patchMergeKey=type
61+
// +optional
62+
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
63+
}
64+
65+
// +kubebuilder:object:root=true
66+
// +kubebuilder:subresource:status
67+
// +kubebuilder:resource:path=vrfs
68+
// +kubebuilder:resource:singular=vrf
69+
// +kubebuilder:resource:shortName=vrf
70+
// +kubebuilder:printcolumn:name="VRF",type=string,JSONPath=`.spec.name`
71+
// +kubebuilder:printcolumn:name="Admin State",type=string,JSONPath=`.spec.adminState`
72+
// +kubebuilder:printcolumn:name="Device",type=string,JSONPath=`.spec.deviceName`
73+
// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
74+
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
75+
//
76+
// VRF is the Schema for the VRFs API
77+
type VRF struct {
78+
metav1.TypeMeta `json:",inline"`
79+
metav1.ObjectMeta `json:"metadata,omitempty,omitzero"`
80+
81+
Spec VRFSpec `json:"spec,omitempty"`
82+
Status VRFStatus `json:"status,omitempty"`
83+
}
84+
85+
// +kubebuilder:object:root=true
86+
87+
// VRFList contains a list of VRF
88+
type VRFList struct {
89+
metav1.TypeMeta `json:",inline"`
90+
metav1.ListMeta `json:"metadata,omitempty"`
91+
Items []VRF `json:"items"`
92+
}
93+
94+
// RouteTarget defines the structure for a single route target in a VRF. A RT is essentially an extended BGP
95+
// community used to control route import/export between VRFs. RTs may be also be associated with address
96+
// families (IPv4, IPv6), and might be also added to the EVPN via the ipv4-evpn and ipv6-evpn address families.
97+
type RouteTarget struct {
98+
// Value specifies the Route Target (RT) value as per RFC 4364.
99+
//
100+
// +kubebuilder:validation:Pattern=`^([0-9]+:[0-9]+|([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]+)$`
101+
Value string `json:"value,omitempty"`
102+
103+
// AddressFamily specifies the address families for the Route Target. Families ipv4-evpn and ipv6-evpn indicate
104+
// that the RT should be applied to the EVPN contexts (see RFC 7432).
105+
//
106+
// +kubebuilder:validation:MinItems=1
107+
AddressFamilies []AddressFamily `json:"addressFamilies,omitempty"`
108+
109+
// Action specifies how this RT should be used within the VRF.
110+
//
111+
// +kubebuilder:validation:Enum=none;import;export;both
112+
Action RTAction `json:"action,omitempty"`
113+
}
114+
115+
// +kubebuilder:validation:Enum=ipv4;ipv6;ipv4-evpn;ipv6-evpn
116+
type AddressFamily string
117+
118+
const (
119+
AddressFamilyIPv4 AddressFamily = "ipv4"
120+
AddressFamilyIPv6 AddressFamily = "ipv6"
121+
AddressFamilyIPv4EVPN AddressFamily = "ipv4-evpn"
122+
AddressFamilyIPv6EVPN AddressFamily = "ipv6-evpn"
123+
)
124+
125+
type RTAction string
126+
127+
const (
128+
RTNone RTAction = "none"
129+
RTImport RTAction = "import"
130+
RTExport RTAction = "export"
131+
RTBoth RTAction = "both"
132+
)
133+
134+
func init() {
135+
SchemeBuilder.Register(&VRF{}, &VRFList{})
136+
}

api/v1alpha1/zz_generated.deepcopy.go

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

config/crd/bases/networking.cloud.sap_devices.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
controller-gen.kubebuilder.io/version: v0.18.0
6+
controller-gen.kubebuilder.io/version: v0.19.0
77
name: devices.networking.cloud.sap
88
spec:
99
group: networking.cloud.sap

config/crd/bases/networking.cloud.sap_interfaces.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
controller-gen.kubebuilder.io/version: v0.18.0
6+
controller-gen.kubebuilder.io/version: v0.19.0
77
name: interfaces.networking.cloud.sap
88
spec:
99
group: networking.cloud.sap

0 commit comments

Comments
 (0)