Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for reporting of switch BGP states by metal-core #598

Merged
merged 2 commits into from
Jan 23, 2025
Merged
Changes from 1 commit
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
Next Next commit
feat: add support for reporting of switch BGP states by metal-core
  • Loading branch information
mwennrich committed Nov 25, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit 55f2d19a66e0e6f81a292dcde5ef810e7abbdabd
25 changes: 18 additions & 7 deletions cmd/metal-api/internal/metal/network.go
Original file line number Diff line number Diff line change
@@ -41,13 +41,14 @@ type MacAddress string

// Nic information.
type Nic struct {
MacAddress MacAddress `rethinkdb:"macAddress" json:"macAddress"`
Name string `rethinkdb:"name" json:"name"`
Identifier string `rethinkdb:"identifier" json:"identifier"`
Vrf string `rethinkdb:"vrf" json:"vrf"`
Neighbors Nics `rethinkdb:"neighbors" json:"neighbors"`
Hostname string `rethinkdb:"hostname" json:"hostname"`
State *NicState `rethinkdb:"state" json:"state"`
MacAddress MacAddress `rethinkdb:"macAddress" json:"macAddress"`
Name string `rethinkdb:"name" json:"name"`
Identifier string `rethinkdb:"identifier" json:"identifier"`
Vrf string `rethinkdb:"vrf" json:"vrf"`
Neighbors Nics `rethinkdb:"neighbors" json:"neighbors"`
Hostname string `rethinkdb:"hostname" json:"hostname"`
State *NicState `rethinkdb:"state" json:"state"`
BGPPortState *SwitchBGPPortState `rethinkdb:"bgpPortState" json:"bgpPortState"`
}

// NicState represents the desired and actual state of a network interface
@@ -59,6 +60,16 @@ type NicState struct {
Actual SwitchPortStatus `rethinkdb:"actual" json:"actual"`
}

type SwitchBGPPortState struct {
Neighbor string
PeerGroup string
VrfName string
BgpState string
BgpTimerUpEstablished int64
SentPrefixCounter int64
AcceptedPrefixCounter int64
}

// SetState updates the NicState with the given SwitchPortStatus. It returns
// a new NicState and a bool indicating if the state was changed.
//
59 changes: 48 additions & 11 deletions cmd/metal-api/internal/service/switch-service.go
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import (
"log/slog"
"net/http"
"net/netip"
"reflect"
"sort"
"strconv"
"strings"
@@ -325,6 +326,35 @@ func (r *switchResource) notifySwitch(request *restful.Request, response *restfu
}
}

if requestPayload.BGPPortStates != nil {
r.log.Debug("bgp port states", "id", id, "states", requestPayload.BGPPortStates)
for i, nic := range newSwitch.Nics {
bpsnew, ok := requestPayload.BGPPortStates[nic.Name]
if !ok && nic.BGPPortState == nil {
continue
}
if nic.BGPPortState == nil {
newSwitch.Nics[i].BGPPortState = nil
switchUpdated = true
}
if reflect.DeepEqual(nic.BGPPortState, &bpsnew) {
mwennrich marked this conversation as resolved.
Show resolved Hide resolved
continue
}

r.log.Debug("bgp port state", "id", id, "nic", nic.Name, "state", bpsnew)
newSwitch.Nics[i].BGPPortState = &metal.SwitchBGPPortState{
Neighbor: bpsnew.Neighbor,
PeerGroup: bpsnew.PeerGroup,
VrfName: bpsnew.VrfName,
BgpState: bpsnew.BgpState,
BgpTimerUpEstablished: bpsnew.BgpTimerUpEstablished,
SentPrefixCounter: bpsnew.SentPrefixCounter,
AcceptedPrefixCounter: bpsnew.AcceptedPrefixCounter,
}
switchUpdated = true
}
}

if switchUpdated {
if err := r.ds.UpdateSwitch(oldSwitch, &newSwitch); err != nil {
r.sendError(request, response, defaultError(err))
@@ -1151,12 +1181,13 @@ func (r *switchResource) makeSwitchNics(s *metal.Switch, nws metal.NetworkMap, i
filter = &f
}
nic := v1.SwitchNic{
MacAddress: string(n.MacAddress),
Name: n.Name,
Identifier: n.Identifier,
Vrf: n.Vrf,
BGPFilter: filter,
Actual: v1.SwitchPortStatusUnknown,
MacAddress: string(n.MacAddress),
Name: n.Name,
Identifier: n.Identifier,
Vrf: n.Vrf,
BGPFilter: filter,
Actual: v1.SwitchPortStatusUnknown,
BGPPortState: n.BGPPortState,
}
if n.State != nil {
if n.State.Desired != nil {
@@ -1191,15 +1222,21 @@ func (r *switchResource) makeSwitchCons(s *metal.Switch) []v1.SwitchConnection {
// connection map.
n := nicMap[mc.Nic.Name]
state := metal.SwitchPortStatusUnknown
var bps *metal.SwitchBGPPortState
if n != nil && n.State != nil {
state = n.State.Actual
}
if n != nil && n.BGPPortState != nil {
bps = n.BGPPortState
}

nic := v1.SwitchNic{
MacAddress: string(mc.Nic.MacAddress),
Name: mc.Nic.Name,
Identifier: mc.Nic.Identifier,
Vrf: mc.Nic.Vrf,
Actual: v1.SwitchPortStatus(state),
MacAddress: string(mc.Nic.MacAddress),
Name: mc.Nic.Name,
Identifier: mc.Nic.Identifier,
Vrf: mc.Nic.Vrf,
Actual: v1.SwitchPortStatus(state),
BGPPortState: bps,
}
con := v1.SwitchConnection{
Nic: nic,
30 changes: 21 additions & 9 deletions cmd/metal-api/internal/service/v1/switch.go
Original file line number Diff line number Diff line change
@@ -40,12 +40,13 @@ type SwitchOS struct {
type SwitchNics []SwitchNic

type SwitchNic struct {
MacAddress string `json:"mac" description:"the mac address of this network interface"`
Name string `json:"name" description:"the name of this network interface"`
Identifier string `json:"identifier" description:"the identifier of this network interface"`
Vrf string `json:"vrf" description:"the vrf this network interface is part of" optional:"true"`
BGPFilter *BGPFilter `json:"filter" description:"configures the bgp filter applied at the switch port" optional:"true"`
Actual SwitchPortStatus `json:"actual" description:"the current state of the nic" enum:"UP|DOWN|UNKNOWN"`
MacAddress string `json:"mac" description:"the mac address of this network interface"`
Name string `json:"name" description:"the name of this network interface"`
Identifier string `json:"identifier" description:"the identifier of this network interface"`
Vrf string `json:"vrf" description:"the vrf this network interface is part of" optional:"true"`
BGPFilter *BGPFilter `json:"filter" description:"configures the bgp filter applied at the switch port" optional:"true"`
Actual SwitchPortStatus `json:"actual" description:"the current state of the nic" enum:"UP|DOWN|UNKNOWN"`
BGPPortState *metal.SwitchBGPPortState `json:"bgp_port_state" description:"the current bgp port state" optional:"true"`
}

type BGPFilter struct {
@@ -100,9 +101,20 @@ type SwitchMigrateRequest struct {
// to the metal-api after a sync operation. It contains the duration of
// the sync, any error that occurred, and the updated switch port states.
type SwitchNotifyRequest struct {
Duration time.Duration `json:"sync_duration" description:"the duration of the switch synchronization"`
Error *string `json:"error"`
PortStates map[string]SwitchPortStatus `json:"port_states" description:"the current switch port states"`
Duration time.Duration `json:"sync_duration" description:"the duration of the switch synchronization"`
Error *string `json:"error"`
PortStates map[string]SwitchPortStatus `json:"port_states" description:"the current switch port states"`
BGPPortStates map[string]SwitchBGPPortState `json:"bgp_port_states" description:"the current bgp port states" optional:"true"`
}

type SwitchBGPPortState struct {
Neighbor string
PeerGroup string
VrfName string
BgpState string
BgpTimerUpEstablished int64
SentPrefixCounter int64
AcceptedPrefixCounter int64
}

type SwitchNotifyResponse struct {
85 changes: 85 additions & 0 deletions spec/metal-api.json
Original file line number Diff line number Diff line change
@@ -348,6 +348,43 @@
"type": "HTTPErrorResponse"
}
},
"metal.SwitchBGPPortState": {
"properties": {
"AcceptedPrefixCounter": {
"format": "int64",
"type": "integer"
},
"BgpState": {
"type": "string"
},
"BgpTimerUpEstablished": {
"format": "int64",
"type": "integer"
},
"Neighbor": {
"type": "string"
},
"PeerGroup": {
"type": "string"
},
"SentPrefixCounter": {
"format": "int64",
"type": "integer"
},
"VrfName": {
"type": "string"
}
},
"required": [
"AcceptedPrefixCounter",
"BgpState",
"BgpTimerUpEstablished",
"Neighbor",
"PeerGroup",
"SentPrefixCounter",
"VrfName"
]
},
"rest.HealthResponse": {
"properties": {
"message": {
@@ -5135,6 +5172,43 @@
"id"
]
},
"v1.SwitchBGPPortState": {
"properties": {
"AcceptedPrefixCounter": {
"format": "int64",
"type": "integer"
},
"BgpState": {
"type": "string"
},
"BgpTimerUpEstablished": {
"format": "int64",
"type": "integer"
},
"Neighbor": {
"type": "string"
},
"PeerGroup": {
"type": "string"
},
"SentPrefixCounter": {
"format": "int64",
"type": "integer"
},
"VrfName": {
"type": "string"
}
},
"required": [
"AcceptedPrefixCounter",
"BgpState",
"BgpTimerUpEstablished",
"Neighbor",
"PeerGroup",
"SentPrefixCounter",
"VrfName"
]
},
"v1.SwitchBase": {
"description": "A switch that can register at the api.",
"properties": {
@@ -5231,6 +5305,10 @@
],
"type": "string"
},
"bgp_port_state": {
"$ref": "#/definitions/metal.SwitchBGPPortState",
"description": "the current bgp port state"
},
"filter": {
"$ref": "#/definitions/v1.BGPFilter",
"description": "configures the bgp filter applied at the switch port"
@@ -5261,6 +5339,13 @@
},
"v1.SwitchNotifyRequest": {
"properties": {
"bgp_port_states": {
"additionalProperties": {
"$ref": "#/definitions/v1.SwitchBGPPortState"
},
"description": "the current bgp port states",
"type": "object"
},
"error": {
"type": "string"
},
Loading