Skip to content

Commit da79c82

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 da79c82

14 files changed

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

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)