Centralized Route Analysis with Batfish

Centralized Route Analysis with Batfish

I'm sure, by now that it's no surprise that I`m a huge fan of Batfish! More details on why here.

Today I wanted to share with you one of the features that Batfish provides - route analysis. In short,

Batfish allows you to model your entire network and then query/analyze the routes centrally.

This feature is super useful for troubleshooting, and also for educational purposes to see how different configurations impact and change the calculated routes, whilst not needing the horsepower to run a ton of VMs!

Below is a an example:

>>> bfq.routes().answer().frame()
...
        Node      VRF        Network Next_Hop     Next_Hop_IP Next_Hop_Interface   Protocol Metric Admin_Distance    Tag
0     spine2  default  10.2.128.0/30     None  AUTO/NONE(-1l)        Ethernet1/1  connected      0              0      0
1     spine2  default    10.2.0.5/32     None  AUTO/NONE(-1l)        Ethernet1/4      local      0              0      0
2      leaf1  default     2.2.2.2/32   spine2        10.2.0.5            dynamic       ospf     41            110   None
3    server1  default      0.0.0.0/0    leaf1    172.16.1.254               eth1     static      0              1   None
4      leaf1  default     2.2.2.2/32   spine2        10.2.0.1            dynamic       ospf     41            110   None
..       ...      ...            ...      ...             ...                ...        ...    ...            ...    ...
112    leaf2  default  172.16.1.0/24   spine2         2.2.2.2            dynamic        bgp      0             20  64520
113  server1  default  172.16.1.1/32     None  AUTO/NONE(-1l)               eth1      local      0              0   None
114   spine1  default    10.1.0.1/32     None  AUTO/NONE(-1l)        Ethernet1/4      local      0              0      0
...

But, there is more! You can also query the BGP RIB using the rib='bgp' input, giving you further details about the route such as the AS_PATH etc.

>>> bfq.routes(rib='bgp').answer().frame().iloc[0]
...
Node                          leaf2
VRF                         default
Network               172.16.1.0/24
Next_Hop_IP                 1.1.1.1
Next_Hop_Interface          dynamic
Protocol                        bgp
AS_Path                 64520 64521
Metric                            0
Local_Pref                      100
Communities                      []
Origin_Protocol                 bgp
Origin_Type                     igp
Originator_Id               1.1.1.1
Cluster_List                   None
Tag                           64520
Name: 0, dtype: object

Finally, we can programmatically work with this data by returning it in a structured data format (Python dictionary), shown below - then, as they say, we are off to the races!

print(dict(bfq.routes(rib='bgp').answer()))
...
'rows': [
    {
           'Node': {'id': 'node-leaf2', 'name': 'leaf2'},
           'VRF': 'default',
           'Network': '172.16.1.0/24',
           'Next_Hop_IP': '1.1.1.1',
           'Next_Hop_Interface': 'dynamic',
           'Protocol': 'bgp',
           'AS_Path': '64520 64521',
           'Metric': 0,
           'Local_Pref': 100,
           'Communities': [],
           'Origin_Protocol': 'bgp',
           'Origin_Type': 'igp',
           'Originator_Id': '1.1.1.1',
           'Cluster_List': None,
           'Tag': 64520
    },
...

Subscribe to our newsletter and stay updated.

Don't miss anything. Get all the latest posts delivered straight to your inbox.
Great! Check your inbox and click the link to confirm your subscription.
Error! Please enter a valid email address!