import subprocess
import json
import re
def parse_bgp_routes(bgp_output):
"""
Parse BGP route table output and return structured data.
Args:
bgp_output (str): Raw BGP table output
Returns:
dict: Structured BGP routes data
"""
routes = []
lines = bgp_output.strip().split('\n')
route_start_idx = None
for i, line in enumerate(lines):
if 'Network' in line and 'Next Hop' in line:
route_start_idx = i + 1
break
if route_start_idx is None:
return {"routes": routes}
for line in lines[route_start_idx:]:
line = line.strip()
if not line or line.startswith('Total number') or line.startswith('IPv6'):
continue
if not line.startswith('*>'):
continue
pattern = r'^\*>\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(.+)$'
match = re.match(pattern, line)
if match:
network = match.group(1)
next_hop = match.group(2)
metric = int(match.group(3))
loc_prf = 0
weight = int(match.group(4))
path_info = match.group(5).strip()
path_parts = path_info.split()
as_path = []
for part in path_parts:
if part.isdigit():
as_path.append(part)
path = ' '.join(as_path) if as_path else ""
route = {
"network": network,
"nextHop": next_hop,
"metric": metric,
"locPrf": loc_prf,
"weight": weight,
"path": path
}
routes.append(route)
return {"routes": routes}
def get_bgp_routes_json():
"""
Get BGP routes from sample data and return as JSON.
Returns:
str: JSON string of BGP routes
"""
output_text = """IPv4
BGP table version is 0, local router ID is 169.254.0.185
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete
Network Next Hop Metric LocPrf Weight Path
*> 10.0.0.0 169.254.0.186 100 0 65100 ?
*> 10.2.0.0/16 169.254.0.185 100 32768 i
*> 10.5.0.0/16 169.254.0.185 100 32768 i
*> 10.6.0.0/16 169.254.0.185 100 32768 i
*> 10.10.0.0/16 169.254.0.185 100 32768 i
*> 10.42.0.0/16 169.254.0.185 100 32768 i
*> 10.56.0.0/16 169.254.0.185 100 32768 i
*> 10.133.0.0/21 169.254.0.185 100 32768 i
*> 10.192.2.0/23 169.254.0.186 100 0 65100 ?
*> 10.192.6.0/23 169.254.0.186 100 0 65100 ?
*> 10.208.0.0/18 169.254.0.185 100 32768 i
*> 10.210.0.0/20 169.254.0.186 100 0 65100 ?
*> 10.210.64.0/18 169.254.0.186 100 0 65100 ?
*> 10.210.128.0/20 169.254.0.186 100 0 65100 ?
*> 10.211.0.0/17 169.254.0.186 100 0 65100 ?
*> 10.211.128.0/17 169.254.0.186 100 0 65100 ?
*> 10.216.0.0/16 169.254.0.186 100 0 65100 ?
*> 10.224.64.0/19 169.254.0.185 100 32768 i
*> 10.227.128.0/18 169.254.0.185 100 32768 i
*> 10.227.192.0/18 169.254.0.185 100 32768 i
*> 10.228.64.0/18 169.254.0.185 100 32768 i
*> 10.228.128.0/18 169.254.0.185 100 32768 i
*> 10.228.192.0/18 169.254.0.185 100 32768 i
*> 10.229.64.0/18 169.254.0.185 100 32768 i
*> 10.229.128.0/18 169.254.0.185 100 32768 i
*> 10.229.192.0/18 169.254.0.185 100 32768 i
*> 10.230.0.0/18 169.254.0.185 100 32768 i
*> 10.230.64.0/18 169.254.0.185 100 32768 i
*> 10.230.128.0/18 169.254.0.185 100 32768 i
*> 10.230.192.0/18 169.254.0.185 100 32768 i
*> 10.246.48.0/20 169.254.0.185 100 32768 i
*> 10.254.192.0/18 169.254.0.185 100 32768 i
*> 10.255.0.0/18 169.254.0.185 100 32768 i
*> 10.255.64.0/18 169.254.0.185 100 32768 i
*> 10.255.128.0/18 169.254.0.185 100 32768 i
*> 10.255.192.0/19 169.254.0.185 100 32768 i
*> 10.255.224.0/19 169.254.0.185 100 32768 i
*> 100.64.0.64/27 169.254.0.185 100 32768 i
*> 100.64.0.96/27 169.254.0.185 100 32768 i
*> 100.64.0.128/27 169.254.0.185 100 32768 i
*> 100.64.0.160/27 169.254.0.185 100 32768 i
*> 172.16.0.0/12 169.254.0.186 100 0 65100 69999 21222 ?
*> 240.0.0.0/4 169.254.0.186 100 0 65100 69999 21222 ?
*> 253.128.0.0/14 169.254.0.186 100 0 65100 ?
*> 253.132.0.0/20 169.254.0.186 100 0 65100 ?
Total number of prefixes 45
IPv6
No BGP network exists"""
parsed_data = parse_bgp_routes(output_text)
return json.dumps(parsed_data, indent=2)
def get_specific_network(prefix):
all_routes = json.loads(get_bgp_routes_json())
for route in all_routes["routes"]:
if route["network"] == prefix:
return route
return None
def main():
"""Main function to demonstrate the BGP parser."""
print(get_bgp_routes_json())
print(get_specific_network("10.42.0.0/16"))
if __name__ == "__main__":
main()