Skip to content

Commit 4fb8e47

Browse files
[NX-OS] Define UserCfgdFlags as Bitmask
This change introduces a formal type for the `UserCfgdFlags` used on interface configuration which corresponds to the Bitmask that is used internally to represent this value. Possible options and it's structure can be obtained from: https://pubhub.devnetcloud.com/media/dme-docs-10-4-3/docs/System/l1:PhysIf/
1 parent eb84b83 commit 4fb8e47

File tree

3 files changed

+90
-13
lines changed

3 files changed

+90
-13
lines changed

internal/provider/cisco/nxos/intf.go

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package nxos
55

66
import (
77
"context"
8+
"encoding/json"
89
"errors"
910
"fmt"
1011
"slices"
@@ -71,7 +72,7 @@ type PhysIf struct {
7172
Mode SwitchportMode `json:"mode"`
7273
NativeVlan string `json:"nativeVlan"`
7374
TrunkVlans string `json:"trunkVlans"`
74-
UserCfgdFlags string `json:"userCfgdFlags"`
75+
UserCfgdFlags UserFlags `json:"userCfgdFlags"`
7576
RtvrfMbrItems *VrfMember `json:"rtvrfMbr-items,omitempty"`
7677
}
7778

@@ -90,14 +91,12 @@ func (p *PhysIf) Validate() error {
9091

9192
func (p *PhysIf) Default() {
9293
p.AccessVlan = DefaultVLAN
93-
p.AdminSt = AdminStDown
9494
p.Layer = Layer2
9595
p.MTU = DefaultMTU
9696
p.Medium = MediumBroadcast
9797
p.Mode = SwitchportModeAccess
9898
p.NativeVlan = DefaultVLAN
9999
p.TrunkVlans = DefaultVLANRange
100-
p.UserCfgdFlags = "admin_state"
101100
}
102101

103102
type PhysIfOperItems struct {
@@ -157,7 +156,7 @@ type PortChannel struct {
157156
PcMode PortChannelMode `json:"pcMode"`
158157
NativeVlan string `json:"nativeVlan"`
159158
TrunkVlans string `json:"trunkVlans"`
160-
UserCfgdFlags string `json:"userCfgdFlags"`
159+
UserCfgdFlags UserFlags `json:"userCfgdFlags"`
161160
RsmbrIfsItems struct {
162161
RsMbrIfsList gnmiext.List[string, *PortChannelMember] `json:"RsMbrIfs-list,omitzero"`
163162
} `json:"rsmbrIfs-items,omitzero"`
@@ -472,3 +471,83 @@ const (
472471
PortChannelModeActive PortChannelMode = "active"
473472
PortChannelModePassive PortChannelMode = "passive"
474473
)
474+
475+
// UserFlags represents the user configured flags for an interface.
476+
// It supports a combination of the following flags:
477+
// 1 - admin_state
478+
// 2 - admin_layer
479+
// 4 - admin_router_mac
480+
// 8 - admin_dce_mode
481+
// 16 - admin_mtu
482+
type UserFlags uint8
483+
484+
const (
485+
UserFlagAdminState UserFlags = 1 << iota
486+
UserFlagAdminLayer
487+
UserFlagAdminRouterMac
488+
UserFlagAdminDceMode
489+
UserFlagAdminMTU
490+
)
491+
492+
var (
493+
_ fmt.Stringer = UserFlags(0)
494+
_ json.Marshaler = UserFlags(0)
495+
_ json.Unmarshaler = (*UserFlags)(nil)
496+
)
497+
498+
// UnmarshalJSON implements json.Unmarshaler.
499+
func (f *UserFlags) UnmarshalJSON([]byte) error {
500+
var s string
501+
if err := json.Unmarshal([]byte(s), &s); err != nil {
502+
return err
503+
}
504+
505+
var flags UserFlags
506+
for flag := range strings.SplitSeq(s, ",") {
507+
switch strings.TrimSpace(flag) {
508+
case "admin_state":
509+
flags |= UserFlagAdminState
510+
case "admin_layer":
511+
flags |= UserFlagAdminLayer
512+
case "admin_router_mac":
513+
flags |= UserFlagAdminRouterMac
514+
case "admin_dce_mode":
515+
flags |= UserFlagAdminDceMode
516+
case "admin_mtu":
517+
flags |= UserFlagAdminMTU
518+
case "":
519+
// ignore empty flag
520+
default:
521+
return fmt.Errorf("interface: unknown user flag %q", flag)
522+
}
523+
}
524+
*f = flags
525+
return nil
526+
}
527+
528+
// MarshalJSON implements json.Marshaler.
529+
func (f UserFlags) MarshalJSON() ([]byte, error) {
530+
return json.Marshal(f.String())
531+
}
532+
533+
// String implements fmt.Stringer.
534+
func (f UserFlags) String() string {
535+
var flags []string
536+
if f&UserFlagAdminState != 0 {
537+
flags = append(flags, "admin_state")
538+
}
539+
if f&UserFlagAdminLayer != 0 {
540+
flags = append(flags, "admin_layer")
541+
}
542+
if f&UserFlagAdminRouterMac != 0 {
543+
flags = append(flags, "admin_router_mac")
544+
}
545+
if f&UserFlagAdminDceMode != 0 {
546+
flags = append(flags, "admin_dce_mode")
547+
}
548+
if f&UserFlagAdminMTU != 0 {
549+
flags = append(flags, "admin_mtu")
550+
}
551+
slices.Sort(flags)
552+
return strings.Join(flags, ",")
553+
}

internal/provider/cisco/nxos/intf_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func init() {
2222
AccessVlan: DefaultVLAN,
2323
NativeVlan: DefaultVLAN,
2424
TrunkVlans: DefaultVLANRange,
25-
UserCfgdFlags: "admin_layer,admin_mtu,admin_state",
25+
UserCfgdFlags: UserFlagAdminState | UserFlagAdminLayer | UserFlagAdminMTU,
2626
})
2727

2828
Register("physif_switchport", &PhysIf{
@@ -35,7 +35,7 @@ func init() {
3535
AccessVlan: DefaultVLAN,
3636
NativeVlan: DefaultVLAN,
3737
TrunkVlans: "10",
38-
UserCfgdFlags: "admin_state",
38+
UserCfgdFlags: UserFlagAdminState,
3939
})
4040

4141
intfAddr4 := &AddrItem{ID: "lo0", Vrf: DefaultVRFName}
@@ -57,7 +57,7 @@ func init() {
5757
PcMode: PortChannelModeActive,
5858
NativeVlan: DefaultVLAN,
5959
TrunkVlans: "10",
60-
UserCfgdFlags: "admin_state",
60+
UserCfgdFlags: UserFlagAdminState,
6161
}
6262
pc.RsmbrIfsItems.RsMbrIfsList.Set(NewPortChannelMember("eth1/10"))
6363
Register("pc", pc)

internal/provider/cisco/nxos/provider.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -641,15 +641,15 @@ func (p *Provider) EnsureInterface(ctx context.Context, req *provider.EnsureInte
641641
if req.Interface.Spec.AdminState == v1alpha1.AdminStateUp {
642642
p.AdminSt = AdminStUp
643643
}
644+
p.UserCfgdFlags = UserFlagAdminState | UserFlagAdminLayer
644645
// TODO: If the interface is a member of a port-channel, do the following:
645646
// 1) If the mtu has been explicitly configured on the port-channel and matches the mtu on the physical interface, adopt the "admin_mtu" flag.
646647
// 2) If the mtu on the port-channel differs from the mtu on the physical interface, return an error.
647648
// 3) If the mtu has not been explicitly configured on the port-channel, do not adopt the "admin_mtu" flag.
648649
if req.Interface.Spec.MTU != 0 {
649650
p.MTU = req.Interface.Spec.MTU
650-
p.UserCfgdFlags = "admin_mtu," + p.UserCfgdFlags
651+
p.UserCfgdFlags |= UserFlagAdminMTU
651652
}
652-
p.UserCfgdFlags = "admin_layer," + p.UserCfgdFlags
653653
if req.IPv4 != nil {
654654
p.Layer = Layer3
655655
}
@@ -723,16 +723,14 @@ func (p *Provider) EnsureInterface(ctx context.Context, req *provider.EnsureInte
723723
pc.AccessVlan = DefaultVLAN
724724
pc.NativeVlan = DefaultVLAN
725725
pc.TrunkVlans = DefaultVLANRange
726-
pc.UserCfgdFlags = "admin_state"
726+
pc.UserCfgdFlags = UserFlagAdminState | UserFlagAdminLayer
727727

728728
pc.MTU = DefaultMTU
729729
if req.Interface.Spec.MTU != 0 {
730730
pc.MTU = req.Interface.Spec.MTU
731-
pc.UserCfgdFlags = "admin_mtu," + pc.UserCfgdFlags
731+
pc.UserCfgdFlags |= UserFlagAdminMTU
732732
}
733733

734-
pc.UserCfgdFlags = "admin_layer," + pc.UserCfgdFlags
735-
736734
pc.PcMode = PortChannelModeActive
737735
switch m := req.Interface.Spec.Aggregation.ControlProtocol.Mode; m {
738736
case v1alpha1.LACPModeActive:

0 commit comments

Comments
 (0)