TAC Webinar03 2023 - BGP States
This dashboards helps to provide current and historical BGP status and provides link flap counters.
Note
Some of the BGP states are not streamed by default and the /Smash/routing/bgp/bgpPeerInfoStatus/default/bgpPeerStatisticsEntry
needs to be added to the TerminAttr include list using the tastreaming.TerminattrStreaming service API.
Examples can be found here
Pre-requisites
Devices will need to be tagged with tag label
site_name
and the label value of the site’s name, for example a customer has 3 sites: ABC, DEF, XYZTag
site_name:ALL
to all devicesTag
site_name:ABC
to ABC devicesrepeat for DEF and XYZ
Devices with multiple supervisors upon supervisor failover might not show the correct states
BGP Summary
# set vars
let afis = newDict()
let afi_name = newDict()
let bgpPeerAfiSafiActive = newDict() | setFields("l2vpnEvpn", 3, "ipv4Unicast", 1)
let bgpPeerAfiSafiActiveName = newDict() | setFields("l2vpnEvpn","L2VPN EVPN", "ipv4Unicast", "IPv4 Unicast")
# Get all devices from a specific site
let devices = merge(`analytics:/tags/labels/devices/site_name/value/<_SITE_NAME>/elements`)
let bgpNeighbors =`analytics:/Devices/*/versioned-data/routing/bgp/status/vrf/*/bgpPeerInfoStatusEntry/*`
if _device != "" {
let bgpNeighbors = bgpNeighbors | fields(_device)
} else {
if str(_SITE_NAME) != "" {
let bgpNeighbors = bgpNeighbors | where(dictHasKey(devices, complexKey("{\"deviceID\": \""+_key+"\"}")))
}
}
let bgpPeerInfoStatusEntry = `*:/Sysdb/cell/1/routing/bgp/export/vrfBgpPeerInfoStatusEntryTable/*/bgpPeerInfoStatusEntry/*`
let bgpPeerStatisticsEntry = `*:/Smash/routing/bgp/bgpPeerInfoStatus/*/bgpPeerStatisticsEntry`
# This is the table
let result = newDict()
let id = 0
# Lets loop over every device
for deviceKey, deviceSessions in bgpNeighbors{
# And each session on the devices
if _device == "" || deviceKey == _device {
for vrfKey, vrfValue in deviceSessions{
# Check if _vrf is empty or if the current vrfKey is in _vrf
if length(_vrf) == 0 || _vrf == vrfKey {
for ip, sessionData in vrfValue {
let data = merge(sessionData)
# Add one to the ID
let id = id + 1
result[id] = newDict()
# This is where we add the various columns
result[id]["0. Device"] = deviceKey
result[id]["1. Status"] = data["bgpState"]["Name"]
result[id]["2. Peering Address"] = data["bgpPeerLocalAddr"]
result[id]["3. Neighbor Address"] = data["key"]
result[id]["4. Neighbor AS"] = data["bgpPeerAs"]["value"]
result[id]["6. VRF"] = vrfKey
if dictHasKey(bgpPeerInfoStatusEntry, deviceKey) && dictHasKey(bgpPeerStatisticsEntry, deviceKey) {
if dictHasKey(bgpPeerInfoStatusEntry[deviceKey], vrfKey) {
let test = merge(bgpPeerInfoStatusEntry[deviceKey][vrfKey][ip])
for kafi, kval in test["bgpPeerAfiSafiActive"]{
if kval == true {
afis[deviceKey] = bgpPeerAfiSafiActive[kafi]
afi_name[deviceKey] = bgpPeerAfiSafiActiveName[kafi]
result[id]["7. AFI/SAFI"] = afi_name[deviceKey]
}
}
result[id]["5. Peer Description"] = test["bgpPeerDescription"]
}
if dictHasKey(bgpPeerStatisticsEntry[deviceKey], vrfKey) {
let bgpPeerAfiSafiStats = merge(bgpPeerStatisticsEntry[deviceKey][vrfKey])
if dictHasKey(afis, deviceKey) && dictHasKey(bgpPeerAfiSafiStats, ip){
result[id]["8. PfxRcd"] = bgpPeerAfiSafiStats[ip]["bgpPeerAfiSafiStats"][afis[deviceKey]]["prefixIn"]
result[id]["9. PfxAcc"] = bgpPeerAfiSafiStats[ip]["bgpPeerAfiSafiStats"][afis[deviceKey]]["prefixAcceptedIn"]
}
}
} else {
# need to figure out why sometimes there's no prefix info
result[id]["8. PfxRcd"] = "N/A"
result[id]["9. PfxAcc"] = "N/A"
}
if dictHasKey(data, "bgpPeerIntoOrOutOfEstablishedTime") {
result[id]["10. Up/Down"] = str(duration(1000000000*round(num(now() - time(data["bgpPeerIntoOrOutOfEstablishedTime"]*1000000000))/1000000000)))
}
}
}
}
}
}
result
BGP Sessions Flaps
let data =`analytics:/Devices/*/versioned-data/routing/bgp/status/vrf/default/bgpPeerInfoStatusEntry/*`[24h]
let devices = merge(`analytics:/tags/labels/devices/site_name/value/<_SITE_NAME>/elements`)
let data = data | where(dictHasKey(devices, complexKey("{\"deviceID\": \""+_key+"\"}")))
let result = newDict()
for device, deviceValues in data {
let establishedNeighbors = newDict()
let flapCount = 0
for ip, tseries in deviceValues{
for timestamp, values in tseries {
if dictHasKey(values, "bgpState"){
if values["bgpState"]["Name"] == "Established"{
let flapCount = flapCount +1
establishedNeighbors[ip] = true
}
}
}
}
let count = flapCount - length(establishedNeighbors)
if count > 0 {
result[device] = newDict() | setFields("Flaps", count )
}
}
result
BGP Historical state tracker
# BGP Session historical state tracker
let data = `analytics:/Devices/<_bgpDevice>/versioned-data/routing/bgp/status/vrf/default/bgpPeerInfoStatusEntry/*`[4h]
let res = newDict()
for ip, tseries in data {
for timestamp, values in tseries {
# only show selected neighbors or all if none selected
if length(_NeighborIP) == 0 || dictHasKey(_NeighborIP, ip){
if !dictHasKey(res, str(timestamp)) {
res[str(timestamp)] = newDict() | setFields(ip, dictHasKey(values, "bgpState") ? values["bgpState"]["Name"] : 0)
} else {
res[str(timestamp)][ip] = dictHasKey(values, "bgpState") ? values["bgpState"]["Name"] : 0
}
}
}
}
res
BGP Syslog Messages
let data = `<_bgpDevice>:/Logs/var/log/messages`[48h] | field("line") | where(reMatch(_value, "BGP"))
let logs = newDict()
for timest, logentry in data {
logs[str(timest+(_tz_offset))] = newDict()
logs[str(timest+(_tz_offset))]["Log"] = logentry
}
logs