Skip to content
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
53 changes: 28 additions & 25 deletions collector/bgp.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ func processBGPSummary(ch chan<- prometheus.Metric, jsonBGPSum []byte, AFI strin

var peerDesc map[string]bgpVRF
var err error
if *bgpPeerTypes || *bgpPeerDescs || *bgpPeerGroups {
if *bgpPeerTypes || *bgpPeerDescs || *bgpPeerGroups || *bgpAcceptedFilteredPrefixes {
peerDesc, err = getBGPPeerDesc()
if err != nil {
return err
Expand Down Expand Up @@ -333,8 +333,8 @@ func processBGPSummary(ch chan<- prometheus.Metric, jsonBGPSum []byte, AFI strin
newGauge(ch, bgpDesc["prefixReceivedCount"], prefixReceived, peerLabels...)

if *bgpAcceptedFilteredPrefixes {
wg.Add(1)
go getPeerAcceptedFilteredRoutes(ch, wg, AFI, safiName[4:], vrfName, peerIP, prefixReceived, logger, bgpDesc, peerLabels...)
afiSafi := strings.ToLower(AFI) + safiName[4:]
processPeerAcceptedFilteredPrefixes(ch, afiSafi, peerDesc[vrfName].BGPNeighbors[peerIP].AddressFamilyInfo, prefixReceived, bgpDesc, peerLabels)
}

var peerDescTypes map[string]string
Expand Down Expand Up @@ -423,30 +423,27 @@ type bgpRoutes struct {
Routes map[string][]json.RawMessage `json:"routes"`
}

func getPeerAcceptedFilteredRoutes(ch chan<- prometheus.Metric, wg *sync.WaitGroup, AFI string, SAFI string, vrfName string, neighbor string, prefixesReceived float64, logger *slog.Logger, bgpDesc map[string]*prometheus.Desc, peerLabels ...string) {
defer wg.Done()

var cmd string
if strings.ToLower(vrfName) == "default" {
cmd = fmt.Sprintf("show bgp %s %s neighbors %s routes json", strings.ToLower(AFI), strings.ToLower(SAFI), neighbor)
} else {
cmd = fmt.Sprintf("show bgp vrf %s %s %s neighbors %s routes json", vrfName, strings.ToLower(AFI), strings.ToLower(SAFI), neighbor)
}

output, err := executeBGPCommand(cmd)
if err != nil {
logger.Error("get neighbor accepted filtered routes failed", "afi", AFI, "safi", SAFI, "vrf", vrfName, "neighbor", neighbor, "err", err)
return
// processPeerAcceptedFilteredPrefixes writes the accepted and filtered prefix
// counts for a peer using the acceptedPrefixCounter
func processPeerAcceptedFilteredPrefixes(ch chan<- prometheus.Metric, afiSafi string, afInfo map[string]bgpNeighborAFISAFI, prefixesReceived float64, bgpDesc map[string]*prometheus.Desc, peerLabels []string) {
info, ok := afInfo[afiSafi]
if !ok {
// normalize the afi/safi key to handle older FRR versions that use
// a space-separated form (e.g. "IPv4 Unicast") instead of the camelCased
// form (e.g. "ipv4Unicast").
want := strings.ToLower(strings.ReplaceAll(afiSafi, " ", ""))
for k, v := range afInfo {
if strings.ToLower(strings.ReplaceAll(k, " ", "")) == want {
info, ok = v, true
break
}
}
}

var routes bgpRoutes
if err := json.Unmarshal(output, &routes); err != nil {
logger.Error("get neighbor accepted filtered routes failed", "afi", AFI, "safi", SAFI, "vrf", vrfName, "neighbor", neighbor, "err", err)
if !ok {
return
}

prefixesAccepted := float64(len(routes.Routes))

prefixesAccepted := float64(info.AcceptedPrefixCounter)
newGauge(ch, bgpDesc["prefixAcceptedCount"], prefixesAccepted, peerLabels...)
newGauge(ch, bgpDesc["prefixFilteredCount"], prefixesReceived-prefixesAccepted, peerLabels...)
}
Expand Down Expand Up @@ -621,8 +618,14 @@ type bgpVRF struct {
}

type bgpNeighbor struct {
Desc string `json:"nbrDesc"`
PeerGroup string `json:"peerGroup"`
Desc string `json:"nbrDesc"`
PeerGroup string `json:"peerGroup"`
AddressFamilyInfo map[string]bgpNeighborAFISAFI `json:"addressFamilyInfo"`
}

type bgpNeighborAFISAFI struct {
AcceptedPrefixCounter uint32 `json:"acceptedPrefixCounter"`
SentPrefixCounter uint32 `json:"sentPrefixCounter"`
}

type bgpNextHopInterfaces struct {
Expand Down
34 changes: 34 additions & 0 deletions collector/bgp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,40 @@ func TestProcessPeerPrefixPresence(t *testing.T) {
compareMetrics(t, gotMetrics, expected)
}

func TestProcessPeerAcceptedFilteredPrefixes(t *testing.T) {
peerLabels := []string{"default", "ipv4", "unicast", "64512", "192.168.0.2", "64513"}
desc := getBGPDesc()

// Exact key match, plus fallbacks for case ("ipv4unicast") and the
// space-separated form older FRR versions emit ("IPv4 Unicast").
for _, afInfo := range []map[string]bgpNeighborAFISAFI{
{"ipv4Unicast": {AcceptedPrefixCounter: 90, SentPrefixCounter: 5}},
{"ipv4unicast": {AcceptedPrefixCounter: 90, SentPrefixCounter: 5}},
{"IPv4 Unicast": {AcceptedPrefixCounter: 90, SentPrefixCounter: 5}},
} {
ch := make(chan prometheus.Metric, 2)
processPeerAcceptedFilteredPrefixes(ch, "ipv4Unicast", afInfo, 100.0, desc, peerLabels)
close(ch)

gotMetrics := collectMetrics(t, ch)
expected := map[string]float64{
"frr_bgp_peer_prefixes_accepted_count_total{afi=ipv4,local_as=64512,peer=192.168.0.2,peer_as=64513,safi=unicast,vrf=default}": 90.0,
"frr_bgp_peer_prefixes_filtered_count_total{afi=ipv4,local_as=64512,peer=192.168.0.2,peer_as=64513,safi=unicast,vrf=default}": 10.0,
}
compareMetrics(t, gotMetrics, expected)
}

// No matching address family: nothing should be emitted.
ch := make(chan prometheus.Metric, 2)
processPeerAcceptedFilteredPrefixes(ch, "ipv6Unicast", map[string]bgpNeighborAFISAFI{
"ipv4Unicast": {AcceptedPrefixCounter: 90},
}, 100.0, desc, peerLabels)
close(ch)
if got := collectMetrics(t, ch); len(got) != 0 {
t.Errorf("expected no metrics for missing address family, got %d", len(got))
}
}

func TestProcessBGPNexthop(t *testing.T) {
expected := map[string]bgpNextHop{
"default": {
Expand Down
Loading