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

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
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) {
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))
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
Loading