Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions internal/provider/cisco/nxos/bgp.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ var (
_ gnmiext.DataElement = (*BGP)(nil)
_ gnmiext.DataElement = (*BGPDom)(nil)
_ gnmiext.DataElement = (*BGPDomItems)(nil)
_ gnmiext.DataElement = (*BGPDomAfItems)(nil)
_ gnmiext.DataElement = (*BGPDomAfItem)(nil)
_ gnmiext.DataElement = (*BGPPeerGroup)(nil)
)

Expand Down Expand Up @@ -45,12 +47,9 @@ func (*BGP) XPath() string {
}

type BGPDom struct {
Name string `json:"name"`
RtrID string `json:"rtrId"`
RtrIDAuto AdminSt `json:"rtrIdAuto"`
AfItems struct {
DomAfList gnmiext.List[AddressFamily, *BGPDomAfItem] `json:"DomAf-list,omitzero"`
} `json:"af-items,omitzero"`
Name string `json:"name"`
RtrID string `json:"rtrId"`
RtrIDAuto AdminSt `json:"rtrIdAuto"`
PeerContItems struct {
PeerContList gnmiext.List[string, *BGPPeerGroup] `json:"PeerCont-list,omitzero"`
} `json:"peercont-items,omitzero"`
Expand Down Expand Up @@ -87,7 +86,18 @@ func (g *BGPPeerGroup) XPath() string {
return "System/bgp-items/inst-items/dom-items/Dom-list[name=" + g.VRFName + "]/peercont-items/PeerCont-list[name=" + g.Name + "]"
}

// BGPDomAfItems is the list container for all address families under a BGP domain.
type BGPDomAfItems struct {
Name string `json:"-"` // VRF name, for XPath construction
DomAfList gnmiext.List[AddressFamily, *BGPDomAfItem] `json:"DomAf-list,omitzero"`
}

func (a *BGPDomAfItems) XPath() string {
return "System/bgp-items/inst-items/dom-items/Dom-list[name=" + a.Name + "]/af-items"
}

type BGPDomAfItem struct {
VRFName string `json:"-"` // for XPath construction
// Maximum number of equal-cost paths for iBGP
MaxEcmp int8 `json:"maxEcmp,omitempty"`
// Maximum number of equal-cost paths for eBGP
Expand Down Expand Up @@ -163,6 +173,12 @@ func (af *BGPDomAfItem) UnmarshalJSON(v []byte) error {

func (af *BGPDomAfItem) Key() AddressFamily { return af.Type }

func (*BGPDomAfItem) IsListItem() {}

func (af *BGPDomAfItem) XPath() string {
return "System/bgp-items/inst-items/dom-items/Dom-list[name=" + af.VRFName + "]/af-items/DomAf-list[type=" + string(af.Type) + "]"
}

// NewInterLeakPDirect creates an InterLeakP entry for redistributing directly
// connected routes into a BGP address family.
func NewInterLeakPDirect(rtMap string) *InterLeakP {
Expand Down
66 changes: 31 additions & 35 deletions internal/provider/cisco/nxos/bgp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,44 @@
package nxos

func init() {
bgpDom := &BGPDom{Name: DefaultVRFName, RtrID: "1.1.1.1", RtrIDAuto: AdminStDisabled}
bgpDom.AfItems.DomAfList.Set(&BGPDomAfItem{
Type: AddressFamilyL2EVPN,
RetainRttAll: AdminStEnabled,
})
Register("bgp_dom", bgpDom)
bgp := &BGP{AdminSt: AdminStEnabled, Asn: "65000"}
Register("bgp", bgp)

bgpDomVrf := &BGPDom{Name: "CC-MGMT", RtrID: "1.1.1.1", RtrIDAuto: AdminStDisabled}
Register("bgp_dom_vrf", bgpDomVrf)
Register("bgp_dom", &BGPDom{Name: DefaultVRFName, RtrID: "1.1.1.1", RtrIDAuto: AdminStDisabled})

Register("bgp_dom_vrf", &BGPDom{Name: "CC-MGMT", RtrID: "1.1.1.1", RtrIDAuto: AdminStDisabled})

Register("bgp_dom_af", &BGPDomAfItem{
VRFName: DefaultVRFName,
Type: AddressFamilyIPv4Unicast,
ExportGwIP: AdminStDisabled,
AdvertL2vpnEvpn: AdminStDisabled,
})

bgpDomAdvPip := &BGPDom{Name: DefaultVRFName, RtrID: "1.1.1.1", RtrIDAuto: AdminStDisabled}
bgpDomAdvPip.AfItems.DomAfList.Set(&BGPDomAfItem{
Register("bgp_dom_af_advpip", &BGPDomAfItem{
VRFName: DefaultVRFName,
Type: AddressFamilyL2EVPN,
AdvPip: AdminStEnabled,
RetainRttAll: AdminStEnabled,
})
Register("bgp_dom_advpip", bgpDomAdvPip)

bgp := &BGP{AdminSt: AdminStEnabled, Asn: "65000"}
Register("bgp", bgp)
Register("bgp_dom_af_exp", &BGPDomAfItem{
VRFName: DefaultVRFName,
Type: AddressFamilyIPv4Unicast,
ExportGwIP: AdminStEnabled,
AdvertL2vpnEvpn: AdminStDisabled,
})

Register("bgp_dom_af_advl2vpnevpn", &BGPDomAfItem{
VRFName: DefaultVRFName,
Type: AddressFamilyIPv4Unicast,
ExportGwIP: AdminStDisabled,
AdvertL2vpnEvpn: AdminStEnabled,
})

rdstItem := &BGPDomAfItem{VRFName: DefaultVRFName, Type: AddressFamilyIPv4Unicast, ExportGwIP: AdminStDisabled, AdvertL2vpnEvpn: AdminStDisabled}
rdstItem.InterLeakPItems.InterLeakPList.Set(NewInterLeakPDirect("ROUTE_MAP"))
Register("bgp_dom_af_rdst", rdstItem)

bgpPeer := &BGPPeer{
VRFName: DefaultVRFName,
Expand Down Expand Up @@ -62,28 +80,6 @@ func init() {
bgpPeerRp.AfItems.PeerAfList.Set(bgpPeerRpAf)
Register("bgp_dom_rp", bgpPeerRp)

bgpDomRdst := &BGPDom{Name: "CC-CLOUD01", RtrID: "1.1.1.1", RtrIDAuto: AdminStDisabled}
rdstItem := &BGPDomAfItem{Type: AddressFamilyIPv4Unicast, ExportGwIP: AdminStDisabled, AdvertL2vpnEvpn: AdminStDisabled}
rdstItem.InterLeakPItems.InterLeakPList.Set(NewInterLeakPDirect("ROUTE_MAP"))
bgpDomRdst.AfItems.DomAfList.Set(rdstItem)
Register("bgp_dom_rdst", bgpDomRdst)

bgpDomExp := &BGPDom{Name: "CC-CLOUD01", RtrID: "1.1.1.1", RtrIDAuto: AdminStDisabled}
bgpDomExp.AfItems.DomAfList.Set(&BGPDomAfItem{
Type: AddressFamilyIPv4Unicast,
ExportGwIP: AdminStEnabled,
AdvertL2vpnEvpn: AdminStDisabled,
})
Register("bgp_dom_exp", bgpDomExp)

bgpDomAdvL2vpnEvpn := &BGPDom{Name: "CC-CLOUD01", RtrID: "1.1.1.1", RtrIDAuto: AdminStDisabled}
bgpDomAdvL2vpnEvpn.AfItems.DomAfList.Set(&BGPDomAfItem{
Type: AddressFamilyIPv4Unicast,
ExportGwIP: AdminStDisabled,
AdvertL2vpnEvpn: AdminStEnabled,
})
Register("bgp_dom_advl2vpnevpn", bgpDomAdvL2vpnEvpn)

bgpPeerLocalAs := &BGPPeer{
VRFName: DefaultVRFName,
Addr: "1.1.1.1",
Expand Down
70 changes: 57 additions & 13 deletions internal/provider/cisco/nxos/intf.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,15 @@ var (
_ gnmiext.DataElement = (*ICMPIf)(nil)
_ gnmiext.DataElement = (*PortChannel)(nil)
_ gnmiext.DataElement = (*PortChannelOperItems)(nil)
_ gnmiext.DataElement = (*PortChannelMemberItems)(nil)
_ gnmiext.DataElement = (*PortChannelMember)(nil)
_ gnmiext.DataElement = (*SwitchVirtualInterface)(nil)
_ gnmiext.DataElement = (*SwitchVirtualInterfaceOperItems)(nil)
_ gnmiext.DataElement = (*EncapRoutedInterface)(nil)
_ gnmiext.DataElement = (*EncapRoutedInterfaceOperItems)(nil)
_ gnmiext.DataElement = (*AddrItem)(nil)
_ gnmiext.DataElement = (*IntfAddrItems)(nil)
_ gnmiext.DataElement = (*IntfAddr)(nil)
_ gnmiext.DataElement = (*FabricFwdIf)(nil)
)

Expand Down Expand Up @@ -294,17 +298,31 @@ type PortChannel struct {
SuspIndividual AdminSt4 `json:"suspIndividual"`
UserCfgdFlags UserFlags `json:"userCfgdFlags"`
RtvrfMbrItems *VrfMember `json:"rtvrfMbr-items,omitempty"`
RsmbrIfsItems struct {
RsMbrIfsList gnmiext.List[string, *PortChannelMember] `json:"RsMbrIfs-list,omitzero"`
} `json:"rsmbrIfs-items,omitzero"`
AggrExtdItems struct {
AggrExtdItems struct {
BufferBoost AdminSt4 `json:"bufferBoost,omitempty"`
} `json:"aggrExtd-items,omitzero"`
}

func (*PortChannel) IsListItem() {}

func (p *PortChannel) XPath() string {
return "System/intf-items/aggr-items/AggrIf-list[id=" + p.ID + "]"
}

// PortChannelMemberItems is the list container for fetching port-channel members.
type PortChannelMemberItems struct {
ID string `json:"-"`
RsMbrIfsList gnmiext.List[string, *PortChannelMember] `json:"RsMbrIfs-list,omitzero"`
}

func (m *PortChannelMemberItems) XPath() string {
return "System/intf-items/aggr-items/AggrIf-list[id=" + m.ID + "]/rsmbrIfs-items"
}

type PortChannelMember struct {
TDn string `json:"tDn"`
Force bool `json:"isMbrForce,omitempty"`
PortChannelID string `json:"-"`
TDn string `json:"tDn"`
Force bool `json:"isMbrForce,omitempty"`
}

func NewPortChannelMember(name string) *PortChannelMember {
Expand All @@ -316,10 +334,13 @@ func NewPortChannelMember(name string) *PortChannelMember {

func (m *PortChannelMember) Key() string { return m.TDn }

func (*PortChannel) IsListItem() {}
func (*PortChannelMember) IsListItem() {}

func (p *PortChannel) XPath() string {
return "System/intf-items/aggr-items/AggrIf-list[id=" + p.ID + "]"
func (m *PortChannelMember) XPath() string {
// Escape brackets in tDn so ygot.StringToStructuredPath does not
// treat them as key delimiters.
tDn := strings.NewReplacer("[", `\[`, "]", `\]`).Replace(m.TDn)
return "System/intf-items/aggr-items/AggrIf-list[id=" + m.PortChannelID + "]/rsmbrIfs-items/RsMbrIfs-list[tDn=" + tDn + "]"
}

type PortChannelOperItems struct {
Expand Down Expand Up @@ -413,10 +434,6 @@ type AddrItem struct {
// empty there to keep the payload free of it.
UseLinkLocalAddr AdminSt `json:"useLinkLocalAddr,omitempty"`

AddrItems struct {
AddrList gnmiext.List[string, *IntfAddr] `json:"Addr-list,omitzero"`
} `json:"addr-items,omitzero"`

// Is6 indicates whether the addresses are IPv6 (true) or IPv4 (false).
// This field is not serialized to JSON and is only used internally to
// determine the correct XPath for the address.
Expand All @@ -439,7 +456,25 @@ func (a *AddrItem) XPath() string {
return "System/ipv4-items/inst-items/dom-items/Dom-list[name=" + a.Vrf + "]/if-items/If-list[id=" + a.ID + "]"
}

// IntfAddrItems is the list container for fetching addresses on an interface.
type IntfAddrItems struct {
ID string `json:"-"`
Vrf string `json:"-"`
Is6 bool `json:"-"`
AddrList gnmiext.List[string, *IntfAddr] `json:"Addr-list,omitzero"`
}

func (a *IntfAddrItems) XPath() string {
if a.Is6 {
return "System/ipv6-items/inst-items/dom-items/Dom-list[name=" + a.Vrf + "]/if-items/If-list[id=" + a.ID + "]/addr-items"
}
return "System/ipv4-items/inst-items/dom-items/Dom-list[name=" + a.Vrf + "]/if-items/If-list[id=" + a.ID + "]/addr-items"
}

type IntfAddr struct {
ID string `json:"-"`
Vrf string `json:"-"`
Is6 bool `json:"-"`
Addr string `json:"addr"`
Pref int `json:"pref"`
Tag int `json:"tag"`
Expand All @@ -448,6 +483,15 @@ type IntfAddr struct {

func (a *IntfAddr) Key() string { return a.Addr }

func (*IntfAddr) IsListItem() {}

func (a *IntfAddr) XPath() string {
if a.Is6 {
return "System/ipv6-items/inst-items/dom-items/Dom-list[name=" + a.Vrf + "]/if-items/If-list[id=" + a.ID + "]/addr-items/Addr-list[addr=" + a.Addr + "]"
}
return "System/ipv4-items/inst-items/dom-items/Dom-list[name=" + a.Vrf + "]/if-items/If-list[id=" + a.ID + "]/addr-items/Addr-list[addr=" + a.Addr + "]"
}

type IntfAddrType string

const (
Expand Down
37 changes: 22 additions & 15 deletions internal/provider/cisco/nxos/intf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,24 +164,30 @@ func init() {
Descr: NewOption("L3 Subinterface on eth1/1"),
})

intfAddr4 := &AddrItem{ID: "lo0", Vrf: DefaultVRFName}
intfAddr4.AddrItems.AddrList.Set(&IntfAddr{
Register("intf_addr4", &IntfAddr{
ID: "lo0",
Vrf: DefaultVRFName,
Is6: false,
Addr: "10.0.0.10/32",
Pref: 0,
Tag: 0,
Type: "primary",
})
Register("intf_addr4", intfAddr4)

intfAddr6 := &AddrItem{ID: "lo0", Vrf: DefaultVRFName, Is6: true, UseLinkLocalAddr: AdminStDisabled}
intfAddr6.AddrItems.AddrList.Set(&IntfAddr{Addr: "2001:db8:1::1/64", Type: IntfAddrTypePrimary})
intfAddr6.AddrItems.AddrList.Set(&IntfAddr{Addr: "2001:db8:2::1/64", Type: IntfAddrTypePrimary})
Register("intf_addr6", intfAddr6)
Register("intf_addr6", &AddrItem{ID: "lo0", Vrf: DefaultVRFName, Is6: true, UseLinkLocalAddr: AdminStDisabled})

Register("intf_addr6_addr", &IntfAddr{
ID: "lo0",
Vrf: DefaultVRFName,
Is6: true,
Addr: "2001:db8:1::1/64",
Type: IntfAddrTypePrimary,
})

// "ipv6 address use-link-local-only", as required for unnumbered peering.
Register("intf_lladdr6", &AddrItem{ID: "eth1/1", Vrf: DefaultVRFName, Is6: true, UseLinkLocalAddr: AdminStEnabled})

pc := &PortChannel{
Register("pc", &PortChannel{
AccessVlan: DefaultVLAN,
AdminSt: AdminStUp,
Descr: NewOption("vPC Leaf1 to Host1"),
Expand All @@ -195,9 +201,12 @@ func init() {
NativeVlan: DefaultVLAN,
SuspIndividual: AdminStEnable,
UserCfgdFlags: UserFlagAdminState,
}
pc.RsmbrIfsItems.RsMbrIfsList.Set(NewPortChannelMember("eth1/10"))
Register("pc", pc)
})

pcMember := NewPortChannelMember("eth1/10")
pcMember.PortChannelID = "po10"
Register("pc_member", pcMember)

Register("pc_trunk_vlans", &TrunkVlans{IfName: "po10", Vlans: "10"})

Register("pc_rtd", &PortChannel{
Expand All @@ -220,7 +229,7 @@ func init() {
}{BufferBoost: AdminStEnable},
})

pcLacp := &PortChannel{
Register("pc_lacp", &PortChannel{
AccessVlan: DefaultVLAN,
AdminSt: AdminStUp,
Descr: NewOption("vPC Leaf1 to Host1 (LACP)"),
Expand All @@ -234,9 +243,7 @@ func init() {
NativeVlan: DefaultVLAN,
SuspIndividual: AdminStDisable,
UserCfgdFlags: UserFlagAdminState,
}
pcLacp.RsmbrIfsItems.RsMbrIfsList.Set(NewPortChannelMember("eth1/1"))
Register("pc_lacp", pcLacp)
})

svi := &SwitchVirtualInterface{
AdminSt: AdminStUp,
Expand Down
23 changes: 18 additions & 5 deletions internal/provider/cisco/nxos/lldp.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,31 @@ const (
var (
_ gnmiext.DataElement = (*LLDP)(nil)
_ gnmiext.Defaultable = (*LLDP)(nil)
_ gnmiext.DataElement = (*LLDPIfItems)(nil)
_ gnmiext.DataElement = (*LLDPIfItem)(nil)
)

type LLDP struct {
// HoldTime is the number of seconds that a receiving device should hold the information sent by another device before discarding it.
HoldTime uint16 `json:"holdTime"`
// InitDelay is the number of seconds for LLDP to initialize on any interface.
InitDelay uint16 `json:"initDelayTime"`
// IfItems contains the per-interface LLDP configuration.
IfItems struct {
IfList gnmiext.List[string, *LLDPIfItem] `json:"If-list,omitzero"`
} `json:"if-items,omitzero"`
}

func (*LLDP) IsListItem() {}

func (*LLDP) XPath() string {
return "System/lldp-items/inst-items"
}

func (*LLDP) IsListItem() {}
// LLDPIfItems is the list container for fetching per-interface LLDP configuration.
type LLDPIfItems struct {
IfList gnmiext.List[string, *LLDPIfItem] `json:"If-list,omitzero"`
}

func (*LLDPIfItems) XPath() string {
return "System/lldp-items/inst-items/if-items"
}

func (l *LLDP) Default() {
l.HoldTime = defaultLLDPHoldTime
Expand All @@ -45,6 +52,12 @@ type LLDPIfItem struct {

func (i *LLDPIfItem) Key() string { return i.InterfaceName }

func (*LLDPIfItem) IsListItem() {}

func (i *LLDPIfItem) XPath() string {
return "System/lldp-items/inst-items/if-items/If-list[id=" + i.InterfaceName + "]"
}

type LLDPOper struct {
OperSt OperSt `json:"operSt"`
}
Expand Down
Loading
Loading