Skip to content

Commit 8efb425

Browse files
committed
udn, nad template: Support localnet topology
When CUDN network.spec specifies Localnet topology, generate the NAD accordingly. Signed-off-by: Or Mergi <[email protected]>
1 parent 082457c commit 8efb425

File tree

4 files changed

+92
-4
lines changed

4 files changed

+92
-4
lines changed

go-controller/pkg/clustermanager/userdefinednetwork/template/net-attach-def-template.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type SpecGetter interface {
3131
GetTopology() userdefinednetworkv1.NetworkTopology
3232
GetLayer3() *userdefinednetworkv1.Layer3Config
3333
GetLayer2() *userdefinednetworkv1.Layer2Config
34+
GetLocalnet() *userdefinednetworkv1.LocalnetConfig
3435
}
3536

3637
func RenderNetAttachDefManifest(obj client.Object, targetNamespace string) (*netv1.NetworkAttachmentDefinition, error) {
@@ -109,7 +110,8 @@ func renderNADLabels(obj client.Object) map[string]string {
109110

110111
func validateTopology(spec SpecGetter) error {
111112
if spec.GetTopology() == userdefinednetworkv1.NetworkTopologyLayer3 && spec.GetLayer3() == nil ||
112-
spec.GetTopology() == userdefinednetworkv1.NetworkTopologyLayer2 && spec.GetLayer2() == nil {
113+
spec.GetTopology() == userdefinednetworkv1.NetworkTopologyLayer2 && spec.GetLayer2() == nil ||
114+
spec.GetTopology() == userdefinednetworkv1.NetworkTopologyLocalnet && spec.GetLocalnet() == nil {
113115
return fmt.Errorf("topology %[1]s is specified but %[1]s config is nil", spec.GetTopology())
114116
}
115117
return nil
@@ -150,6 +152,18 @@ func renderCNINetworkConfig(networkName, nadName string, spec SpecGetter) (map[s
150152
netConfSpec.AllowPersistentIPs = cfg.IPAM != nil && cfg.IPAM.Lifecycle == userdefinednetworkv1.IPAMLifecyclePersistent
151153
netConfSpec.Subnets = cidrString(cfg.Subnets)
152154
netConfSpec.JoinSubnet = cidrString(renderJoinSubnets(cfg.Role, cfg.JoinSubnets))
155+
case userdefinednetworkv1.NetworkTopologyLocalnet:
156+
cfg := spec.GetLocalnet()
157+
netConfSpec.Role = strings.ToLower(string(cfg.Role))
158+
netConfSpec.MTU = int(cfg.MTU)
159+
netConfSpec.AllowPersistentIPs = cfg.IPAM != nil && cfg.IPAM.Lifecycle == userdefinednetworkv1.IPAMLifecyclePersistent
160+
netConfSpec.Subnets = cidrString(cfg.Subnets)
161+
netConfSpec.ExcludeSubnets = cidrString(cfg.ExcludeSubnets)
162+
netConfSpec.PhysicalNetworkName = cfg.PhysicalNetworkName
163+
164+
if cfg.VLAN != nil && cfg.VLAN.Access != nil {
165+
netConfSpec.VLANID = int(cfg.VLAN.Access.ID)
166+
}
153167
}
154168

155169
if err := util.ValidateNetConf(nadName, netConfSpec); err != nil {
@@ -185,7 +199,15 @@ func renderCNINetworkConfig(networkName, nadName string, spec SpecGetter) (map[s
185199
if netConfSpec.AllowPersistentIPs {
186200
cniNetConf["allowPersistentIPs"] = netConfSpec.AllowPersistentIPs
187201
}
188-
202+
if netConfSpec.PhysicalNetworkName != "" {
203+
cniNetConf["physicalNetworkName"] = netConfSpec.PhysicalNetworkName
204+
}
205+
if len(netConfSpec.ExcludeSubnets) > 0 {
206+
cniNetConf["excludeSubnets"] = netConfSpec.ExcludeSubnets
207+
}
208+
if netConfSpec.VLANID != 0 {
209+
cniNetConf["vlanID"] = netConfSpec.VLANID
210+
}
189211
return cniNetConf, nil
190212
}
191213

go-controller/pkg/clustermanager/userdefinednetwork/template/net-attach-def-template_test.go

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ var _ = Describe("NetAttachDefTemplate", func() {
169169
),
170170
)
171171

172-
DescribeTable("should fail to render NAD, given",
172+
DescribeTable("should fail to render NAD manifest, given",
173173
func(obj client.Object) {
174174
_, err := RenderNetAttachDefManifest(obj, "test")
175175
Expect(err).To(HaveOccurred())
@@ -223,10 +223,35 @@ var _ = Describe("NetAttachDefTemplate", func() {
223223
&udnv1.ClusterUserDefinedNetwork{Spec: udnv1.ClusterUserDefinedNetworkSpec{Network: udnv1.NetworkSpec{
224224
Topology: udnv1.NetworkTopologyLayer2, Layer3: &udnv1.Layer3Config{}}}},
225225
),
226+
Entry("CUDN, invalid topology: topology layer2 & localnet config",
227+
&udnv1.ClusterUserDefinedNetwork{Spec: udnv1.ClusterUserDefinedNetworkSpec{Network: udnv1.NetworkSpec{
228+
Topology: udnv1.NetworkTopologyLayer2, Localnet: &udnv1.LocalnetConfig{}}}},
229+
),
226230
Entry("CUDN, invalid topology: topology layer3 & layer2 config",
227231
&udnv1.ClusterUserDefinedNetwork{Spec: udnv1.ClusterUserDefinedNetworkSpec{Network: udnv1.NetworkSpec{
228232
Topology: udnv1.NetworkTopologyLayer3, Layer2: &udnv1.Layer2Config{}}}},
229233
),
234+
Entry("CUDN, invalid topology: topology layer3 & localnet config",
235+
&udnv1.ClusterUserDefinedNetwork{Spec: udnv1.ClusterUserDefinedNetworkSpec{Network: udnv1.NetworkSpec{
236+
Topology: udnv1.NetworkTopologyLayer3, Localnet: &udnv1.LocalnetConfig{}}}},
237+
),
238+
Entry("CUDN, invalid topology: topology localnet & layer2 config",
239+
&udnv1.ClusterUserDefinedNetwork{Spec: udnv1.ClusterUserDefinedNetworkSpec{Network: udnv1.NetworkSpec{
240+
Topology: udnv1.NetworkTopologyLocalnet, Layer2: &udnv1.Layer2Config{}}}},
241+
),
242+
Entry("CUDN, invalid topology: topology localnet & layer3 config",
243+
&udnv1.ClusterUserDefinedNetwork{Spec: udnv1.ClusterUserDefinedNetworkSpec{Network: udnv1.NetworkSpec{
244+
Topology: udnv1.NetworkTopologyLocalnet, Layer3: &udnv1.Layer3Config{}}}},
245+
),
246+
Entry("CUDN, localnet: excludeSubnets not in range of subnets",
247+
&udnv1.ClusterUserDefinedNetwork{Spec: udnv1.ClusterUserDefinedNetworkSpec{Network: udnv1.NetworkSpec{
248+
Topology: udnv1.NetworkTopologyLocalnet,
249+
Localnet: &udnv1.LocalnetConfig{Role: udnv1.NetworkRoleSecondary, PhysicalNetworkName: "localnet1",
250+
Subnets: udnv1.DualStackCIDRs{"192.168.0.0/16", "2001:dbb::/64"},
251+
ExcludeSubnets: []udnv1.CIDR{"192.200.0.0/30", "2001:aaa::/127", "192.300.0.1/32", "2001:bbb::1/120"},
252+
},
253+
}}},
254+
),
230255
)
231256

232257
It("should return no error given no UDN", func() {
@@ -492,7 +517,7 @@ var _ = Describe("NetAttachDefTemplate", func() {
492517
"allowPersistentIPs": true
493518
}`,
494519
),
495-
Entry("secondary network",
520+
Entry("secondary network, layer2",
496521
udnv1.NetworkSpec{
497522
Topology: udnv1.NetworkTopologyLayer2,
498523
Layer2: &udnv1.Layer2Config{
@@ -516,5 +541,35 @@ var _ = Describe("NetAttachDefTemplate", func() {
516541
"allowPersistentIPs": true
517542
}`,
518543
),
544+
Entry("secondary network, localnet",
545+
udnv1.NetworkSpec{
546+
Topology: udnv1.NetworkTopologyLocalnet,
547+
Localnet: &udnv1.LocalnetConfig{
548+
Role: udnv1.NetworkRoleSecondary,
549+
PhysicalNetworkName: "mylocalnet1",
550+
MTU: 1600,
551+
VLAN: &udnv1.VLANConfig{Mode: udnv1.VLANModeAccess, Access: &udnv1.AccessVLANConfig{ID: 200}},
552+
Subnets: udnv1.DualStackCIDRs{"192.168.100.0/24", "2001:dbb::/64"},
553+
ExcludeSubnets: []udnv1.CIDR{"192.168.100.1/32", "2001:dbb::0/128"},
554+
IPAM: &udnv1.IPAMConfig{
555+
Lifecycle: udnv1.IPAMLifecyclePersistent,
556+
},
557+
},
558+
},
559+
`{
560+
"cniVersion": "1.0.0",
561+
"type": "ovn-k8s-cni-overlay",
562+
"name": "cluster_udn_test-net",
563+
"netAttachDefName": "mynamespace/test-net",
564+
"role": "secondary",
565+
"topology": "localnet",
566+
"physicalNetworkName": "mylocalnet1",
567+
"subnets": "192.168.100.0/24,2001:dbb::/64",
568+
"excludeSubnets": "192.168.100.1/32,2001:dbb::0/128",
569+
"mtu": 1600,
570+
"vlanID": 200,
571+
"allowPersistentIPs": true
572+
}`,
573+
),
519574
)
520575
})

go-controller/pkg/crd/userdefinednetwork/v1/cudn.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ type ClusterUserDefinedNetworkList struct {
8585
Items []ClusterUserDefinedNetwork `json:"items"`
8686
}
8787

88+
const NetworkTopologyLocalnet NetworkTopology = "Localnet"
89+
8890
// +kubebuilder:validation:XValidation:rule="!has(self.ipam) || !has(self.ipam.mode) || self.ipam.mode == 'Enabled' ? has(self.subnets) : !has(self.subnets)", message="Subnets is required with ipam.mode is Enabled or unset, and forbidden otherwise"
8991
// +kubebuilder:validation:XValidation:rule="!has(self.excludeSubnets) || has(self.subnets)", message="excludeSubnets must be unset when subnets is unset"
9092
// +kubebuilder:validation:XValidation:rule="!has(self.subnets) || !has(self.mtu) || !self.subnets.exists_one(i, isCIDR(i) && cidr(i).ip().family() == 6) || self.mtu >= 1280", message="MTU should be greater than or equal to 1280 when an IPv6 subnet is used"

go-controller/pkg/crd/userdefinednetwork/v1/spec.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ func (s *UserDefinedNetworkSpec) GetLayer2() *Layer2Config {
1212
return s.Layer2
1313
}
1414

15+
func (s *UserDefinedNetworkSpec) GetLocalnet() *LocalnetConfig {
16+
// localnet is not supported
17+
return nil
18+
}
19+
1520
func (s *NetworkSpec) GetTopology() NetworkTopology {
1621
return s.Topology
1722
}
@@ -23,3 +28,7 @@ func (s *NetworkSpec) GetLayer3() *Layer3Config {
2328
func (s *NetworkSpec) GetLayer2() *Layer2Config {
2429
return s.Layer2
2530
}
31+
32+
func (s *NetworkSpec) GetLocalnet() *LocalnetConfig {
33+
return s.Localnet
34+
}

0 commit comments

Comments
 (0)