Skip to content

Commit

Permalink
feat: add support for reporting of switch BGP states by metal-core
Browse files Browse the repository at this point in the history
  • Loading branch information
mwennrich committed Nov 25, 2024
1 parent 3c22c0d commit 55f2d19
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 27 deletions.
25 changes: 18 additions & 7 deletions cmd/metal-api/internal/metal/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
//
Expand Down
59 changes: 48 additions & 11 deletions cmd/metal-api/internal/service/switch-service.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"log/slog"
"net/http"
"net/netip"
"reflect"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -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) {
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))
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
30 changes: 21 additions & 9 deletions cmd/metal-api/internal/service/v1/switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
85 changes: 85 additions & 0 deletions spec/metal-api.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down Expand Up @@ -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": {
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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"
},
Expand Down

0 comments on commit 55f2d19

Please sign in to comment.