From 5c9c1e1abcbf33ed901aa3cb10d0f573920e3ee6 Mon Sep 17 00:00:00 2001 From: Sven Rosenzweig Date: Thu, 9 Jul 2026 12:05:49 +0200 Subject: [PATCH] feat: Implement BFD for BGPPeers Signed-off-by: Sven Rosenzweig --- api/core/v1alpha1/bfd_types.go | 41 ++++++++++ api/core/v1alpha1/bgp_peer_types.go | 5 ++ api/core/v1alpha1/interface_types.go | 33 -------- api/core/v1alpha1/zz_generated.deepcopy.go | 5 ++ ...gppeers.networking.metal.ironcore.dev.yaml | 37 +++++++++ ...erfaces.networking.metal.ironcore.dev.yaml | 3 +- ...etworking.metal.ironcore.dev_bgppeers.yaml | 37 +++++++++ ...working.metal.ironcore.dev_interfaces.yaml | 3 +- docs/api-reference/index.md | 6 +- internal/provider/cisco/iosxr/bgp_peer.go | 6 ++ internal/provider/cisco/iosxr/provider.go | 27 ++++++ internal/provider/cisco/nxos/bgp.go | 82 +++++++++++++++++-- internal/provider/cisco/nxos/bgp_test.go | 3 + internal/provider/cisco/nxos/provider.go | 11 +++ .../cisco/nxos/testdata/bgp_dom_rp.json | 1 + .../cisco/nxos/testdata/bgp_peer.json | 1 + .../nxos/testdata/bgp_peer_local_as.json | 1 + 17 files changed, 258 insertions(+), 44 deletions(-) create mode 100644 api/core/v1alpha1/bfd_types.go diff --git a/api/core/v1alpha1/bfd_types.go b/api/core/v1alpha1/bfd_types.go new file mode 100644 index 000000000..21d762f52 --- /dev/null +++ b/api/core/v1alpha1/bfd_types.go @@ -0,0 +1,41 @@ +// SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and IronCore contributors +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// BFD defines the Bidirectional Forwarding Detection configuration for interfaces, bgp peerings and static routes. +type BFD struct { + // Enabled indicates whether BFD is enabled on the network object. + // +required + Enabled bool `json:"enabled"` + + // DesiredMinimumTxInterval is the minimum interval between transmission of BFD control + // packets that the operator desires. This value is advertised to the peer. + // The actual interval used is the maximum of this value and the remote + // required-minimum-receive interval value. + // +optional + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$" + DesiredMinimumTxInterval *metav1.Duration `json:"desiredMinimumTxInterval,omitempty"` + + // RequiredMinimumReceive is the minimum interval between received BFD control packets + // that this system should support. This value is advertised to the remote peer to + // indicate the maximum frequency between BFD control packets that is acceptable + // to the local system. + // +optional + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$" + RequiredMinimumReceive *metav1.Duration `json:"requiredMinimumReceive,omitempty"` + + // DetectionMultiplier is the number of packets that must be missed to declare + // this session as down. The detection interval for the BFD session is calculated + // by multiplying the value of the negotiated transmission interval by this value. + // +optional + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=255 + DetectionMultiplier *int32 `json:"detectionMultiplier,omitempty"` +} diff --git a/api/core/v1alpha1/bgp_peer_types.go b/api/core/v1alpha1/bgp_peer_types.go index c0c141108..a44b1712a 100644 --- a/api/core/v1alpha1/bgp_peer_types.go +++ b/api/core/v1alpha1/bgp_peer_types.go @@ -64,6 +64,11 @@ type BGPPeerSpec struct { // LocalAS configures the local AS number and how it factors into BGP announcements for this peer. // +optional LocalAS *LocalAS `json:"localAS,omitempty"` + + // BFD defines the Bidirectional Forwarding Detection configuration for the interface. + // BFD is only applicable for Layer 3 interfaces. + // +optional + BFD *BFD `json:"bfd,omitempty"` } // LocalAS defines the local AS configuration and how it factors in BGP announcements. diff --git a/api/core/v1alpha1/interface_types.go b/api/core/v1alpha1/interface_types.go index e6fca4498..70743d964 100644 --- a/api/core/v1alpha1/interface_types.go +++ b/api/core/v1alpha1/interface_types.go @@ -266,39 +266,6 @@ type InterfaceIPv4Unnumbered struct { InterfaceRef LocalObjectReference `json:"interfaceRef"` } -// BFD defines the Bidirectional Forwarding Detection configuration for an interface. -type BFD struct { - // Enabled indicates whether BFD is enabled on the interface. - // +required - Enabled bool `json:"enabled"` - - // DesiredMinimumTxInterval is the minimum interval between transmission of BFD control - // packets that the operator desires. This value is advertised to the peer. - // The actual interval used is the maximum of this value and the remote - // required-minimum-receive interval value. - // +optional - // +kubebuilder:validation:Type=string - // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$" - DesiredMinimumTxInterval *metav1.Duration `json:"desiredMinimumTxInterval,omitempty"` - - // RequiredMinimumReceive is the minimum interval between received BFD control packets - // that this system should support. This value is advertised to the remote peer to - // indicate the maximum frequency between BFD control packets that is acceptable - // to the local system. - // +optional - // +kubebuilder:validation:Type=string - // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$" - RequiredMinimumReceive *metav1.Duration `json:"requiredMinimumReceive,omitempty"` - - // DetectionMultiplier is the number of packets that must be missed to declare - // this session as down. The detection interval for the BFD session is calculated - // by multiplying the value of the negotiated transmission interval by this value. - // +optional - // +kubebuilder:validation:Minimum=1 - // +kubebuilder:validation:Maximum=255 - DetectionMultiplier *int32 `json:"detectionMultiplier,omitempty"` -} - // Ethernet defines the ethernet-specific configuration for physical interfaces. type Ethernet struct { // FECMode specifies the Forward Error Correction mode for the interface. diff --git a/api/core/v1alpha1/zz_generated.deepcopy.go b/api/core/v1alpha1/zz_generated.deepcopy.go index 62dfc807d..0ac6c1b56 100644 --- a/api/core/v1alpha1/zz_generated.deepcopy.go +++ b/api/core/v1alpha1/zz_generated.deepcopy.go @@ -849,6 +849,11 @@ func (in *BGPPeerSpec) DeepCopyInto(out *BGPPeerSpec) { *out = new(LocalAS) (*in).DeepCopyInto(*out) } + if in.BFD != nil { + in, out := &in.BFD, &out.BFD + *out = new(BFD) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BGPPeerSpec. diff --git a/charts/network-operator/templates/crd/bgppeers.networking.metal.ironcore.dev.yaml b/charts/network-operator/templates/crd/bgppeers.networking.metal.ironcore.dev.yaml index ff32caaf8..926782495 100644 --- a/charts/network-operator/templates/crd/bgppeers.networking.metal.ironcore.dev.yaml +++ b/charts/network-operator/templates/crd/bgppeers.networking.metal.ironcore.dev.yaml @@ -291,6 +291,43 @@ spec: ASNumber is the autonomous system number (ASN) of the BGP peer. Supports both plain format (1-4294967295) and dotted notation (1-65535.0-65535) as per RFC 5396. x-kubernetes-int-or-string: true + bfd: + description: |- + BFD defines the Bidirectional Forwarding Detection configuration for the interface. + BFD is only applicable for Layer 3 interfaces. + properties: + desiredMinimumTxInterval: + description: |- + DesiredMinimumTxInterval is the minimum interval between transmission of BFD control + packets that the operator desires. This value is advertised to the peer. + The actual interval used is the maximum of this value and the remote + required-minimum-receive interval value. + pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ + type: string + detectionMultiplier: + description: |- + DetectionMultiplier is the number of packets that must be missed to declare + this session as down. The detection interval for the BFD session is calculated + by multiplying the value of the negotiated transmission interval by this value. + format: int32 + maximum: 255 + minimum: 1 + type: integer + enabled: + description: Enabled indicates whether BFD is enabled on the network + object. + type: boolean + requiredMinimumReceive: + description: |- + RequiredMinimumReceive is the minimum interval between received BFD control packets + that this system should support. This value is advertised to the remote peer to + indicate the maximum frequency between BFD control packets that is acceptable + to the local system. + pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ + type: string + required: + - enabled + type: object bgpRef: description: |- BgpRef is a reference to the BGP instance this peer belongs to. diff --git a/charts/network-operator/templates/crd/interfaces.networking.metal.ironcore.dev.yaml b/charts/network-operator/templates/crd/interfaces.networking.metal.ironcore.dev.yaml index 396ebd76f..f22c86cdb 100644 --- a/charts/network-operator/templates/crd/interfaces.networking.metal.ironcore.dev.yaml +++ b/charts/network-operator/templates/crd/interfaces.networking.metal.ironcore.dev.yaml @@ -180,7 +180,8 @@ spec: minimum: 1 type: integer enabled: - description: Enabled indicates whether BFD is enabled on the interface. + description: Enabled indicates whether BFD is enabled on the network + object. type: boolean requiredMinimumReceive: description: |- diff --git a/config/crd/bases/networking.metal.ironcore.dev_bgppeers.yaml b/config/crd/bases/networking.metal.ironcore.dev_bgppeers.yaml index 379cb55df..efa2452fe 100644 --- a/config/crd/bases/networking.metal.ironcore.dev_bgppeers.yaml +++ b/config/crd/bases/networking.metal.ironcore.dev_bgppeers.yaml @@ -288,6 +288,43 @@ spec: ASNumber is the autonomous system number (ASN) of the BGP peer. Supports both plain format (1-4294967295) and dotted notation (1-65535.0-65535) as per RFC 5396. x-kubernetes-int-or-string: true + bfd: + description: |- + BFD defines the Bidirectional Forwarding Detection configuration for the interface. + BFD is only applicable for Layer 3 interfaces. + properties: + desiredMinimumTxInterval: + description: |- + DesiredMinimumTxInterval is the minimum interval between transmission of BFD control + packets that the operator desires. This value is advertised to the peer. + The actual interval used is the maximum of this value and the remote + required-minimum-receive interval value. + pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ + type: string + detectionMultiplier: + description: |- + DetectionMultiplier is the number of packets that must be missed to declare + this session as down. The detection interval for the BFD session is calculated + by multiplying the value of the negotiated transmission interval by this value. + format: int32 + maximum: 255 + minimum: 1 + type: integer + enabled: + description: Enabled indicates whether BFD is enabled on the network + object. + type: boolean + requiredMinimumReceive: + description: |- + RequiredMinimumReceive is the minimum interval between received BFD control packets + that this system should support. This value is advertised to the remote peer to + indicate the maximum frequency between BFD control packets that is acceptable + to the local system. + pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ + type: string + required: + - enabled + type: object bgpRef: description: |- BgpRef is a reference to the BGP instance this peer belongs to. diff --git a/config/crd/bases/networking.metal.ironcore.dev_interfaces.yaml b/config/crd/bases/networking.metal.ironcore.dev_interfaces.yaml index ea0449394..94f870941 100644 --- a/config/crd/bases/networking.metal.ironcore.dev_interfaces.yaml +++ b/config/crd/bases/networking.metal.ironcore.dev_interfaces.yaml @@ -177,7 +177,8 @@ spec: minimum: 1 type: integer enabled: - description: Enabled indicates whether BFD is enabled on the interface. + description: Enabled indicates whether BFD is enabled on the network + object. type: boolean requiredMinimumReceive: description: |- diff --git a/docs/api-reference/index.md b/docs/api-reference/index.md index 5cb2dd745..cb62ec60e 100644 --- a/docs/api-reference/index.md +++ b/docs/api-reference/index.md @@ -432,16 +432,17 @@ _Appears in:_ -BFD defines the Bidirectional Forwarding Detection configuration for an interface. +BFD defines the Bidirectional Forwarding Detection configuration for interfaces, bgp peerings and static routes. _Appears in:_ +- [BGPPeerSpec](#bgppeerspec) - [InterfaceSpec](#interfacespec) | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `enabled` _boolean_ | Enabled indicates whether BFD is enabled on the interface. | | Required: \{\}
| +| `enabled` _boolean_ | Enabled indicates whether BFD is enabled on the network object. | | Required: \{\}
| | `desiredMinimumTxInterval` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#duration-v1-meta)_ | DesiredMinimumTxInterval is the minimum interval between transmission of BFD control
packets that the operator desires. This value is advertised to the peer.
The actual interval used is the maximum of this value and the remote
required-minimum-receive interval value. | | Pattern: `^([0-9]+(\.[0-9]+)?(ns\|us\|µs\|ms\|s\|m\|h))+$`
Type: string
Optional: \{\}
| | `requiredMinimumReceive` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#duration-v1-meta)_ | RequiredMinimumReceive is the minimum interval between received BFD control packets
that this system should support. This value is advertised to the remote peer to
indicate the maximum frequency between BFD control packets that is acceptable
to the local system. | | Pattern: `^([0-9]+(\.[0-9]+)?(ns\|us\|µs\|ms\|s\|m\|h))+$`
Type: string
Optional: \{\}
| | `detectionMultiplier` _integer_ | DetectionMultiplier is the number of packets that must be missed to declare
this session as down. The detection interval for the BFD session is calculated
by multiplying the value of the negotiated transmission interval by this value. | | Maximum: 255
Minimum: 1
Optional: \{\}
| @@ -730,6 +731,7 @@ _Appears in:_ | `localAddress` _[BGPPeerLocalAddress](#bgppeerlocaladdress)_ | LocalAddress specifies the local address configuration for the BGP session with this peer.
This determines the source address/interface for BGP packets sent to this peer. | | Optional: \{\}
| | `addressFamilies` _[BGPPeerAddressFamilies](#bgppeeraddressfamilies)_ | AddressFamilies configures address family specific settings for this BGP peer.
Controls which address families are enabled and their specific configuration. | | Optional: \{\}
| | `localAS` _[LocalAS](#localas)_ | LocalAS configures the local AS number and how it factors into BGP announcements for this peer. | | Optional: \{\}
| +| `bfd` _[BFD](#bfd)_ | BFD defines the Bidirectional Forwarding Detection configuration for the interface.
BFD is only applicable for Layer 3 interfaces. | | Optional: \{\}
| #### BGPPeerStatus diff --git a/internal/provider/cisco/iosxr/bgp_peer.go b/internal/provider/cisco/iosxr/bgp_peer.go index 369c7813d..f8a025a84 100644 --- a/internal/provider/cisco/iosxr/bgp_peer.go +++ b/internal/provider/cisco/iosxr/bgp_peer.go @@ -71,6 +71,12 @@ type BGPPeer struct { Name string `json:"vrf-name"` RD RouteDistinguisher `json:"rd,omitzero"` Neighbors NeighborList `json:"neighbors,omitzero"` + BFD *BFD `json:"bfd,omitzero"` +} + +type BFD struct { + MinInterval uint32 `json:"minimum-interval,omitempty"` + Multiplier uint32 `json:"multiplier,omitempty"` } // ActivatedAddressFamilies is required for IOS XR to activate the Address-Family under the BGP process diff --git a/internal/provider/cisco/iosxr/provider.go b/internal/provider/cisco/iosxr/provider.go index c05255a09..68e79dbda 100644 --- a/internal/provider/cisco/iosxr/provider.go +++ b/internal/provider/cisco/iosxr/provider.go @@ -7,10 +7,12 @@ import ( "context" "errors" "fmt" + "math" "net" "time" "github.com/ironcore-dev/network-operator/api/core/v1alpha1" + "github.com/ironcore-dev/network-operator/internal/apistatus" "github.com/ironcore-dev/network-operator/internal/deviceutil" "github.com/ironcore-dev/network-operator/internal/provider" "github.com/ironcore-dev/network-operator/internal/transport/gnmiext" @@ -477,6 +479,31 @@ func (p *Provider) EnsureBGPPeer(ctx context.Context, req *provider.EnsureBGPPee RD: rd, } + if req.BGPPeer.Spec.BFD != nil && req.BGPPeer.Spec.BFD.Enabled { + bfd := &BFD{} + if req.BGPPeer.Spec.BFD.RequiredMinimumReceive != nil { + ms := req.BGPPeer.Spec.BFD.RequiredMinimumReceive.Duration + if ms < 0 || ms > math.MaxUint32 { + return apistatus.NewInvalidArgumentError(apistatus.FieldViolation{ + Field: "spec.bfd.requiredMinimumReceive", + Description: "BFD minimum receive interval must be between 0ms and 4294967295ms", + }) + } + bfd.MinInterval = uint32(ms) + } + if req.BGPPeer.Spec.BFD.DetectionMultiplier != nil { + multiplier := *req.BGPPeer.Spec.BFD.DetectionMultiplier + if multiplier < 0 { + return apistatus.NewInvalidArgumentError(apistatus.FieldViolation{ + Field: "spec.bfd.detectionMultiplier", + Description: "BFD detection multiplier must be non-negative", + }) + } + bfd.Multiplier = uint32(multiplier) + } + peer.BFD = bfd + } + if req.BGPPeer.Spec.AddressFamilies != nil && (req.BGPPeer.Spec.AddressFamilies.Ipv6Unicast != nil || req.BGPPeer.Spec.AddressFamilies.L2vpnEvpn != nil) { return errors.New("bgp peer: ipv6 unicast or l2vpnEvpn address family is currently not supported") } diff --git a/internal/provider/cisco/nxos/bgp.go b/internal/provider/cisco/nxos/bgp.go index 54a9a5a19..f344b687c 100644 --- a/internal/provider/cisco/nxos/bgp.go +++ b/internal/provider/cisco/nxos/bgp.go @@ -11,6 +11,7 @@ import ( nxv1alpha1 "github.com/ironcore-dev/network-operator/api/cisco/nx/v1alpha1" "github.com/ironcore-dev/network-operator/api/core/v1alpha1" + "github.com/ironcore-dev/network-operator/internal/apistatus" "github.com/ironcore-dev/network-operator/internal/transport/gnmiext" ) @@ -189,22 +190,74 @@ func (af *BGPDomAfItem) SetMultipath(m *v1alpha1.BGPMultipath) error { } type BGPPeer struct { - VRFName string `json:"-"` - Addr string `json:"addr"` - AdminSt AdminSt `json:"adminSt"` - Asn string `json:"asn"` - AsnType PeerAsnType `json:"asnType"` - Name string `json:"name,omitempty"` - SrcIf string `json:"srcIf,omitempty"` + VRFName string `json:"-"` + Addr string `json:"addr"` + Name string `json:"name,omitempty"` + AdminSt AdminSt `json:"adminSt"` + Asn string `json:"asn"` + AsnType PeerAsnType `json:"asnType"` + SrcIf string `json:"srcIf,omitempty"` + + // BFD enablement + PeerControl PeerControlType `json:"ctrl,omitempty"` + // Bfd Type: none (default), single-hop, multi-hop + // Rely on default, if peer is directly connected then a single hop session is selected, + // if the peer is not connected then a multi hop session type is selected + BfdType BfdType `json:"bfdType"` + BfdMultihop *BGPNeighborBfd `json:"mhbfdintvl-items,omitzero"` + LocalAsnItems struct { AsnPropagate AsnPropagate `json:"asnPropagate"` LocalAsn string `json:"localAsn"` } `json:"localasn-items,omitzero"` + AfItems struct { PeerAfList gnmiext.List[AddressFamily, *BGPPeerAfItem] `json:"PeerAf-list,omitzero"` } `json:"af-items,omitzero"` } +type BGPNeighborBfd struct { + DetectMult uint32 `json:"multiplier"` + MinRxIntvlMs uint32 `json:"minRxMs"` + MinTxIntvlMs uint32 `json:"minTxMs"` +} + +func NewBGPNeighborBfd(peer *v1alpha1.BFD) (*BGPNeighborBfd, error) { + bfd := &BGPNeighborBfd{} + if peer.DetectionMultiplier != nil { + multiplier := *peer.DetectionMultiplier + if multiplier < 0 { + return nil, apistatus.NewInvalidArgumentError(apistatus.FieldViolation{ + Field: "spec.bfd.detectionMultiplier", + Description: "BFD detection multiplier must be non-negative", + }) + } + bfd.DetectMult = uint32(multiplier) + } + if peer.RequiredMinimumReceive != nil { + ms := peer.RequiredMinimumReceive.Duration + + if ms < 250 || ms > 999 { + return nil, apistatus.NewInvalidArgumentError(apistatus.FieldViolation{ + Field: "spec.bfd.requiredMinimumReceive", + Description: "BFD minimum receive interval must be between 250ms and 999ms", + }) + } + bfd.MinRxIntvlMs = uint32(ms) + } + if peer.DesiredMinimumTxInterval != nil { + ms := peer.DesiredMinimumTxInterval.Duration + if ms < 250 || ms > 999 { + return nil, apistatus.NewInvalidArgumentError(apistatus.FieldViolation{ + Field: "spec.bfd.desiredMinimumTxInterval", + Description: "BFD desired minimum transmit interval must be between 250ms and 999ms", + }) + } + bfd.MinTxIntvlMs = uint32(ms) + } + return bfd, nil +} + type AsnPropagate string const ( @@ -364,6 +417,21 @@ const ( const RouteReflectorClient = "rr-client" +type PeerControlType string + +const ( + PeerControlTypeBFD PeerControlType = "bfd" +) + +type BfdType string + +const ( + // BfdTypeNone relies on default BFD session type selection + BfdTypeNone BfdType = "none" + BfdTypeSingleHop BfdType = "single-hop" + BfdTypeMultiHop BfdType = "multi-hop" +) + type BorderGatewayPeerType string const ( diff --git a/internal/provider/cisco/nxos/bgp_test.go b/internal/provider/cisco/nxos/bgp_test.go index cb983faf2..fa82289ab 100644 --- a/internal/provider/cisco/nxos/bgp_test.go +++ b/internal/provider/cisco/nxos/bgp_test.go @@ -31,6 +31,7 @@ func init() { AdminSt: AdminStEnabled, Asn: "65000", AsnType: PeerAsnTypeNone, + BfdType: BfdTypeNone, Name: "EVPN peering with spine", SrcIf: "lo0", } @@ -51,6 +52,7 @@ func init() { AdminSt: AdminStEnabled, Asn: "65000", AsnType: PeerAsnTypeNone, + BfdType: BfdTypeNone, } bgpPeerRpAf := &BGPPeerAfItem{ SendComExt: AdminStDisabled, @@ -81,6 +83,7 @@ func init() { AdminSt: AdminStEnabled, Asn: "65001", AsnType: PeerAsnTypeNone, + BfdType: BfdTypeNone, } bgpPeerLocalAs.LocalAsnItems.AsnPropagate = AsnPropagateNone bgpPeerLocalAs.LocalAsnItems.LocalAsn = "65002" diff --git a/internal/provider/cisco/nxos/provider.go b/internal/provider/cisco/nxos/provider.go index 29f91d86f..eeb672343 100644 --- a/internal/provider/cisco/nxos/provider.go +++ b/internal/provider/cisco/nxos/provider.go @@ -548,6 +548,17 @@ func (p *Provider) EnsureBGPPeer(ctx context.Context, req *provider.EnsureBGPPee pe := new(BGPPeer) pe.VRFName = bgp.Name pe.Addr = req.BGPPeer.Spec.Address + + pe.BfdType = BfdTypeNone + if req.BGPPeer.Spec.BFD != nil && req.BGPPeer.Spec.BFD.Enabled { + bfd, err := NewBGPNeighborBfd(req.BGPPeer.Spec.BFD) + if err != nil { + return err + } + pe.PeerControl = PeerControlTypeBFD + pe.BfdMultihop = bfd + } + pe.AdminSt = AdminStEnabled if req.BGPPeer.Spec.AdminState == v1alpha1.AdminStateDown { pe.AdminSt = AdminStDisabled diff --git a/internal/provider/cisco/nxos/testdata/bgp_dom_rp.json b/internal/provider/cisco/nxos/testdata/bgp_dom_rp.json index 1c09a4564..825fa6c15 100644 --- a/internal/provider/cisco/nxos/testdata/bgp_dom_rp.json +++ b/internal/provider/cisco/nxos/testdata/bgp_dom_rp.json @@ -13,6 +13,7 @@ "adminSt": "enabled", "asn": "65000", "asnType": "none", + "bfdType": "none", "af-items": { "PeerAf-list": [ { diff --git a/internal/provider/cisco/nxos/testdata/bgp_peer.json b/internal/provider/cisco/nxos/testdata/bgp_peer.json index b8e6ee166..2492c4b58 100644 --- a/internal/provider/cisco/nxos/testdata/bgp_peer.json +++ b/internal/provider/cisco/nxos/testdata/bgp_peer.json @@ -12,6 +12,7 @@ "adminSt": "enabled", "asn": "65000", "asnType": "none", + "bfdType": "none", "name": "EVPN peering with spine", "srcIf": "lo0", "af-items": { diff --git a/internal/provider/cisco/nxos/testdata/bgp_peer_local_as.json b/internal/provider/cisco/nxos/testdata/bgp_peer_local_as.json index 89b6a813f..a988c8fa6 100644 --- a/internal/provider/cisco/nxos/testdata/bgp_peer_local_as.json +++ b/internal/provider/cisco/nxos/testdata/bgp_peer_local_as.json @@ -13,6 +13,7 @@ "adminSt": "enabled", "asn": "65001", "asnType": "none", + "bfdType": "none", "localasn-items": { "asnPropagate": "none", "localAsn": "65002"