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

Implement ListSessions of BGP API #271

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
73 changes: 41 additions & 32 deletions protocols/bgp/api/session.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions protocols/bgp/api/session.proto
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ message Session {
SessionStats stats = 6;
uint64 established_since = 7;
string description = 8;
string vrf_name = 9;
}

message SessionStats {
Expand Down
24 changes: 24 additions & 0 deletions protocols/bgp/metrics/bgp_peer_metrics.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package metrics

import (
"fmt"
"time"

bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/bgp/api"
)

const (
Expand Down Expand Up @@ -48,3 +50,25 @@ type BGPPeerMetrics struct {
// AddressFamilies provides metrics on AFI/SAFI level
AddressFamilies []*BGPAddressFamilyMetrics
}

// GetStateAsProto returns the state of this peer to be used by the BGP API
func (m *BGPPeerMetrics) GetStateAsProto() api.Session_State {
switch m.State {
case StateDown:
return api.Session_Active // substitution
case StateIdle:
return api.Session_Idle
case StateConnect:
return api.Session_Connect
case StateActive:
return api.Session_Active
case StateOpenSent:
return api.Session_OpenSent
case StateOpenConfirm:
return api.Session_OpenConfirmed
case StateEstablished:
return api.Session_Established
default:
panic(fmt.Sprintf("Unknown state: %v", m.State))
}
}
72 changes: 71 additions & 1 deletion protocols/bgp/server/bgp_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import (
"fmt"

"github.com/bio-routing/bio-rd/protocols/bgp/api"
"github.com/bio-routing/bio-rd/protocols/bgp/metrics"
"github.com/bio-routing/bio-rd/route"
"github.com/pkg/errors"

bnet "github.com/bio-routing/bio-rd/net"
routeapi "github.com/bio-routing/bio-rd/route/api"
Expand All @@ -22,8 +24,76 @@ func NewBGPAPIServer(s BGPServer) *BGPAPIServer {
}
}

// ListSessions lists all sessions the BGP server currently has
func (s *BGPAPIServer) ListSessions(ctx context.Context, in *api.ListSessionsRequest) (*api.ListSessionsResponse, error) {
return nil, fmt.Errorf("Not implemented yet")
bgpMetrics, err := s.srv.Metrics()
if err != nil {
return nil, errors.Wrap(err, "Could not get peer metrics")
}

sessions := make([]*api.Session, 0)
for _, peerIP := range s.srv.GetPeers() {
peer := s.srv.GetPeerConfig(peerIP)
// find metrics for peer
var peerMetrics *metrics.BGPPeerMetrics
for _, peerMetricsEntry := range bgpMetrics.Peers {
if *peerMetricsEntry.IP == *peer.PeerAddress {
peerMetrics = peerMetricsEntry
break
}
}
if peerMetrics == nil {
return nil, fmt.Errorf("Could not find metrics for neighbor %s", peer.PeerAddress)
}

if in.Filter != nil {
if in.Filter.NeighborIp != nil {
filterNeighbor := bnet.IPFromProtoIP(in.Filter.NeighborIp)
if *filterNeighbor != *peerIP {
continue
}
}
if in.Filter.VrfName != "" {
if in.Filter.VrfName != peerMetrics.VRF {
continue
}
}
}

estSince := peerMetrics.Since.Unix()
if estSince < 0 {
// time not set, peer probably not up
estSince = 0
}
var routesReceived, routesSent uint64
for _, afiPeerMetrics := range peerMetrics.AddressFamilies {
routesReceived += afiPeerMetrics.RoutesReceived
routesSent += afiPeerMetrics.RoutesSent
}

session := &api.Session{
LocalAddress: peer.LocalAddress.ToProto(),
NeighborAddress: peer.PeerAddress.ToProto(),
LocalAsn: peer.LocalAS,
PeerAsn: peer.PeerAS,
Status: peerMetrics.GetStateAsProto(),
Stats: &api.SessionStats{
MessagesIn: peerMetrics.UpdatesReceived,
MessagesOut: peerMetrics.UpdatesSent,
RoutesReceived: routesReceived,
RoutesExported: routesSent,
},
EstablishedSince: uint64(estSince),
Description: peer.Description,
VrfName: peerMetrics.VRF,
}
sessions = append(sessions, session)
}

resp := &api.ListSessionsResponse{
Sessions: sessions,
}
return resp, nil
}

// DumpRIBIn dumps the RIB in of a peer for a given AFI/SAFI
Expand Down
Loading