Skip to content

Commit 2afcc9f

Browse files
committed
Add SpanningTree config to Cisco NX provider
1 parent 6a1a547 commit 2afcc9f

File tree

3 files changed

+71
-29
lines changed

3 files changed

+71
-29
lines changed

api/core/v1alpha1/interface_types.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ const (
119119

120120
// Switchport defines the switchport configuration for an interface.
121121
// +kubebuilder:validation:XValidation:rule="self.mode != 'Access' || has(self.accessVlan)", message="accessVlan must be specified when mode is Access"
122-
// +kubebuilder:validation:XValidation:rule="self.mode != 'Trunk' || has(self.nativeVlan)", message="nativeVlan must be specified when mode is Trunk"
123122
type Switchport struct {
124123
// Mode defines the switchport mode, such as access or trunk.
125124
// +required
@@ -147,6 +146,10 @@ type Switchport struct {
147146
// +kubebuilder:validation:items:Minimum=1
148147
// +kubebuilder:validation:items:Maximum=4094
149148
AllowedVlans []int32 `json:"allowedVlans,omitempty"`
149+
150+
// SpanningTreeMode defines the spanning tree mode for the switchport.
151+
// +optional
152+
SpanningTreeMode *SpanningTreeMode `json:"spanningTree,omitempty"`
150153
}
151154

152155
// SwitchportMode represents the switchport mode of an interface.
@@ -160,6 +163,17 @@ const (
160163
SwitchportModeTrunk SwitchportMode = "Trunk"
161164
)
162165

166+
// SpanningTreeMode represents the spanning tree mode of a switchport.
167+
// +kubebuilder:validation:Enum=Edge;Network;Trunk;Default
168+
type SpanningTreeMode string
169+
170+
const (
171+
SpanningTreeModeEdge SpanningTreeMode = "Edge"
172+
SpanningTreeModeNetwork SpanningTreeMode = "Network"
173+
SpanningTreeModeTrunk SpanningTreeMode = "Trunk"
174+
SpanningTreeModeDefault SpanningTreeMode = "Default"
175+
)
176+
163177
// InterfaceIPv4 defines the IPv4 configuration for an interface.
164178
// +kubebuilder:validation:XValidation:rule="!has(self.addresses) || !has(self.unnumbered)", message="addresses and unnumbered are mutually exclusive"
165179
// +kubebuilder:validation:XValidation:rule="!has(self.unnumbered) || !self.anycastGateway", message="anycastGateway and unnumbered are mutually exclusive"

config/crd/bases/networking.metal.ironcore.dev_interfaces.yaml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,14 +312,21 @@ spec:
312312
maximum: 4094
313313
minimum: 1
314314
type: integer
315+
spanningTree:
316+
description: SpanningTreeMode defines the spanning tree mode for
317+
the switchport.
318+
enum:
319+
- Edge
320+
- Network
321+
- Trunk
322+
- Default
323+
type: string
315324
required:
316325
- mode
317326
type: object
318327
x-kubernetes-validations:
319328
- message: accessVlan must be specified when mode is Access
320329
rule: self.mode != 'Access' || has(self.accessVlan)
321-
- message: nativeVlan must be specified when mode is Trunk
322-
rule: self.mode != 'Trunk' || has(self.nativeVlan)
323330
type:
324331
description: Type indicates the type of the interface.
325332
enum:

internal/provider/cisco/nxos/provider.go

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,9 @@ func (p *Provider) EnsureInterface(ctx context.Context, req *provider.EnsureInte
673673
p.AccessVlan = fmt.Sprintf("vlan-%d", req.Interface.Spec.Switchport.AccessVlan)
674674
case v1alpha1.SwitchportModeTrunk:
675675
p.Mode = SwitchportModeTrunk
676-
p.NativeVlan = fmt.Sprintf("vlan-%d", req.Interface.Spec.Switchport.NativeVlan)
676+
if req.Interface.Spec.Switchport.NativeVlan != 0 {
677+
p.NativeVlan = fmt.Sprintf("vlan-%d", req.Interface.Spec.Switchport.NativeVlan)
678+
}
677679
if len(req.Interface.Spec.Switchport.AllowedVlans) > 0 {
678680
p.TrunkVlans = Range(req.Interface.Spec.Switchport.AllowedVlans)
679681
}
@@ -751,13 +753,32 @@ func (p *Provider) EnsureInterface(ctx context.Context, req *provider.EnsureInte
751753
pc.AccessVlan = fmt.Sprintf("vlan-%d", req.Interface.Spec.Switchport.AccessVlan)
752754
case v1alpha1.SwitchportModeTrunk:
753755
pc.Mode = SwitchportModeTrunk
754-
pc.NativeVlan = fmt.Sprintf("vlan-%d", req.Interface.Spec.Switchport.NativeVlan)
756+
if req.Interface.Spec.Switchport.NativeVlan != 0 {
757+
pc.NativeVlan = fmt.Sprintf("vlan-%d", req.Interface.Spec.Switchport.NativeVlan)
758+
}
755759
if len(req.Interface.Spec.Switchport.AllowedVlans) > 0 {
756760
pc.TrunkVlans = Range(req.Interface.Spec.Switchport.AllowedVlans)
757761
}
758762
default:
759763
return fmt.Errorf("invalid switchport mode: %s", req.Interface.Spec.Switchport.Mode)
760764
}
765+
766+
if req.Interface.Spec.Switchport.SpanningTreeMode != nil {
767+
stp := new(SpanningTree)
768+
switch *req.Interface.Spec.Switchport.SpanningTreeMode {
769+
case v1alpha1.SpanningTreeModeEdge:
770+
stp.Mode = SpanningTreeModeEdge
771+
case v1alpha1.SpanningTreeModeNetwork:
772+
stp.Mode = SpanningTreeModeNetwork
773+
case v1alpha1.SpanningTreeModeTrunk:
774+
stp.Mode = SpanningTreeModeTrunk
775+
case v1alpha1.SpanningTreeModeDefault:
776+
stp.Mode = SpanningTreeModeDefault
777+
default:
778+
return fmt.Errorf("invalid spanning tree mode: %v", *req.Interface.Spec.Switchport.SpanningTreeMode)
779+
}
780+
conf = append(conf, stp)
781+
}
761782
}
762783

763784
for _, member := range req.Members {
@@ -774,9 +795,9 @@ func (p *Provider) EnsureInterface(ctx context.Context, req *provider.EnsureInte
774795
}
775796

776797
// Delete the existing VPC interface entry if the MultiChassisID has changed or got removed.
777-
if vpc := v.GetListItemByInterface(name); vpc != nil {
778-
if req.MultiChassisID == nil || int(*req.MultiChassisID) != vpc.ID {
779-
if err := p.client.Delete(ctx, vpc); err != nil {
798+
if vpcdomain := v.GetListItemByInterface(name); vpcdomain != nil {
799+
if req.MultiChassisID == nil || int(*req.MultiChassisID) != vpcdomain.ID {
800+
if err := p.client.Delete(ctx, vpcdomain); err != nil {
780801
return err
781802
}
782803
}
@@ -936,8 +957,8 @@ func (p *Provider) DeleteInterface(ctx context.Context, req *provider.InterfaceR
936957
}
937958

938959
// Make sure to delete any associated VPC interface.
939-
if vpc := v.GetListItemByInterface(name); vpc != nil {
940-
conf = append(conf, vpc)
960+
if vpcdomain := v.GetListItemByInterface(name); vpcdomain != nil {
961+
conf = append(conf, vpcdomain)
941962
}
942963

943964
case v1alpha1.InterfaceTypeRoutedVLAN:
@@ -2141,8 +2162,8 @@ func (p *Provider) ResetSystemSettings(ctx context.Context) error {
21412162
)
21422163
}
21432164

2144-
// VPCStatus represents the operational status of a vPC configuration on the device.
2145-
type VPCStatus struct {
2165+
// VPCDomainStatus represents the operational status of a vPC configuration on the device.
2166+
type VPCDomainStatus struct {
21462167
// KeepAliveStatus indicates whether the keepalive link is operationally up (true) or down (false).
21472168
KeepAliveStatus bool
21482169
// KeepAliveStatusMessage provides additional human-readable information returned by the device
@@ -2166,10 +2187,10 @@ func (p *Provider) EnsureVPCDomain(ctx context.Context, vpcdomain *nxv1alpha1.VP
21662187
f.Name = "vpc"
21672188
f.AdminSt = AdminStEnabled
21682189

2169-
v := new(VPC)
2170-
v.Id = vpc.Spec.DomainID
2190+
v := new(VPCDomain)
2191+
v.Id = vpcdomain.Spec.DomainID
21712192

2172-
switch vpc.Spec.AdminState {
2193+
switch vpcdomain.Spec.AdminState {
21732194
case "enabled":
21742195
v.AdminSt = NewOption(AdminStEnabled)
21752196
case "disabled":
@@ -2199,7 +2220,7 @@ func (p *Provider) EnsureVPCDomain(ctx context.Context, vpcdomain *nxv1alpha1.VP
21992220
v.FastConvergence = NewOption(AdminStEnabled)
22002221
}
22012222

2202-
peer := vpc.Spec.Peer
2223+
peer := vpcdomain.Spec.Peer
22032224

22042225
v.PeerSwitch = AdminStDisabled
22052226
if peer.Switch.Enabled {
@@ -2224,13 +2245,13 @@ func (p *Provider) EnsureVPCDomain(ctx context.Context, vpcdomain *nxv1alpha1.VP
22242245

22252246
ipaddr := net.ParseIP(peer.KeepAlive.Destination)
22262247
if ipaddr == nil {
2227-
return fmt.Errorf("nxos-vpc: invalid keep-alive destination IP address %q", peer.KeepAlive.Destination)
2248+
return fmt.Errorf("invalid keep-alive destination IP address %q", peer.KeepAlive.Destination)
22282249
}
22292250
v.KeepAliveItems.DestIP = peer.KeepAlive.Destination
22302251

22312252
ipaddr = net.ParseIP(peer.KeepAlive.Source)
22322253
if ipaddr == nil {
2233-
return fmt.Errorf("nxos-vpc: invalid keep-alive source IP address %q", peer.KeepAlive.Source)
2254+
return fmt.Errorf("invalid keep-alive source IP address %q", peer.KeepAlive.Source)
22342255
}
22352256
v.KeepAliveItems.SrcIP = peer.KeepAlive.Source
22362257

@@ -2247,16 +2268,16 @@ func (p *Provider) EnsureVPCDomain(ctx context.Context, vpcdomain *nxv1alpha1.VP
22472268
return p.client.Patch(ctx, f, v)
22482269
}
22492270

2250-
func (p *Provider) DeleteVPC(ctx context.Context) error {
2251-
v := new(VPC)
2271+
func (p *Provider) DeleteVPCDomain(ctx context.Context) error {
2272+
v := new(VPCDomain)
22522273
return p.client.Delete(ctx, v)
22532274
}
22542275

22552276
// GetStatusVPC retrieves the current status of the vPC configuration on the device.
2256-
func (p *Provider) GetStatusVPC(ctx context.Context) (VPCStatus, error) {
2257-
vpcOper := new(VPCOper)
2258-
if err := p.client.GetState(ctx, vpcOper); err != nil && !errors.Is(err, gnmiext.ErrNil) {
2259-
return VPCStatus{}, err
2277+
func (p *Provider) GetStatusVPCDomain(ctx context.Context) (VPCDomainStatus, error) {
2278+
vdOper := new(VPCDomainOper)
2279+
if err := p.client.GetState(ctx, vdOper); err != nil && !errors.Is(err, gnmiext.ErrNil) {
2280+
return VPCDomainStatus{}, err
22602281
}
22612282

22622283
vpcSt := VPCDomainStatus{}
@@ -2284,15 +2305,15 @@ func (p *Provider) GetStatusVPC(ctx context.Context) (VPCStatus, error) {
22842305
case vpcRoleElectionNotDone:
22852306
vpcSt.Role = nxv1alpha1.VPCDomainRoleUnknown
22862307
case vpcRolePrimary:
2287-
vpcSt.Role = nxv1alpha1.VPCRolePrimary
2308+
vpcSt.Role = nxv1alpha1.VPCDomainRolePrimary
22882309
case vpcRoleSecondary:
2289-
vpcSt.Role = nxv1alpha1.VPCRoleSecondary
2310+
vpcSt.Role = nxv1alpha1.VPCDomainRoleSecondary
22902311
case vpcRolePrimaryOperationalSecondary:
2291-
vpcSt.Role = nxv1alpha1.VPCRolePrimaryOperationalSecondary
2312+
vpcSt.Role = nxv1alpha1.VPCDomainRolePrimaryOperationalSecondary
22922313
case vpcRoleSecondaryOperationalPrimary:
2293-
vpcSt.Role = nxv1alpha1.VPCRoleSecondaryOperationalPrimary
2314+
vpcSt.Role = nxv1alpha1.VPCDomainRoleSecondaryOperationalPrimary
22942315
default:
2295-
vpcSt.Role = nxv1alpha1.VPCRoleUnknown
2316+
vpcSt.Role = nxv1alpha1.VPCDomainRoleUnknown
22962317
}
22972318
return vpcSt, nil
22982319
}

0 commit comments

Comments
 (0)