{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Getting Started with Batfish\n",
"\n",
"This notebook uses pybatfish, a Python-based SDK for Batfish, to analyze a sample network. It shows how to submit your configurations and other network data for analysis and how to query its vendor-neutral network model. [Other notebooks](https://github.com/batfish/pybatfish/tree/master/jupyter_notebooks) show how to use Batfish for different types of network validation tasks. \n",
"\n",
"Check out a video demo of an earlier version of this notebook [here](https://www.youtube.com/watch?v=Ca7kPAtfFqo).\n",
"\n",
"### Initializing a Network and Snapshot\n",
"\n",
"A *network* is a logical group of routers and links. It can be your entire network or a subset of it. A *snapshot* is a collection of information (configuration files, routing data, up/down status of nodes and links) that represent the network state. Snapshots can contain the actual state of the network or candidate states (e.g, those corresponding to a planned change) that you want to analyze."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# Import packages\n",
"%run startup.py\n",
"bf = Session(host=\"localhost\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`SNAPSHOT_PATH` below can be updated to point to a custom snapshot directory, see the [Batfish instructions](https://github.com/batfish/batfish/wiki/Packaging-snapshots-for-analysis) for how to package data for analysis.
\n",
"More example networks are available in the [networks](https://github.com/batfish/batfish/tree/master/networks) folder of the Batfish repository."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'example_snapshot'"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Assign a friendly name to your network and snapshot\n",
"NETWORK_NAME = \"example_network\"\n",
"SNAPSHOT_NAME = \"example_snapshot\"\n",
"\n",
"SNAPSHOT_PATH = \"networks/example\"\n",
"\n",
"# Now create the network and initialize the snapshot\n",
"bf.set_network(NETWORK_NAME)\n",
"bf.init_snapshot(SNAPSHOT_PATH, name=SNAPSHOT_NAME, overwrite=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you used the example we provided, the network you initialized above is illustrated below. You can download/view devices' configuration files [here](https://github.com/batfish/pybatfish/tree/master/jupyter_notebooks/networks/example).\n",
"\n",
"\n",
"\n",
"***"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Querying the Network Model\n",
"\n",
"Batfish creates a comprehensive vendor-neutral device and network model which can be queried for information about devices, interfaces, VRFs, routes, etc. It offers a set of *questions* to query this model."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# You can also use tab-completion on the Batfish question module - bf.q. -> press TAB key,\n",
"# uncomment and try on the following line\n",
"# bf.q.\n",
"\n",
"# In IPython and Jupyter you can use the \"?\" shorthand to get help on a question\n",
"?bf.q.nodeProperties\n",
"\n",
"# help(bf.q.nodeProperties) # in standard Python console"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"***\n",
"\n",
"### Getting status of parsed files\n",
"\n",
"Batfish may ignore certain lines in the configuration. To retrieve the parsing status of snapshot files, use the `fileParseStatus()` question."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"parse_status = bf.q.fileParseStatus().answer().frame()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`answer()` runs the question and returns the answer in a JSON format. \n",
"\n",
"`frame()` wraps the answer as [pandas dataframe](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
| \n", " | File_Name | \n", "Status | \n", "File_Format | \n", "Nodes | \n", "
|---|---|---|---|---|
| 0 | \n", "configs/as1border1.cfg | \n", "PASSED | \n", "CISCO_IOS | \n", "['as1border1'] | \n", "
| 1 | \n", "configs/as1border2.cfg | \n", "PASSED | \n", "CISCO_IOS | \n", "['as1border2'] | \n", "
| 2 | \n", "configs/as1core1.cfg | \n", "PASSED | \n", "CISCO_IOS | \n", "['as1core1'] | \n", "
| 3 | \n", "configs/as2border1.cfg | \n", "PASSED | \n", "CISCO_IOS | \n", "['as2border1'] | \n", "
| 4 | \n", "configs/as2border2.cfg | \n", "PASSED | \n", "CISCO_IOS | \n", "['as2border2'] | \n", "
| 5 | \n", "configs/as2core1.cfg | \n", "PASSED | \n", "CISCO_IOS | \n", "['as2core1'] | \n", "
| 6 | \n", "configs/as2core2.cfg | \n", "PASSED | \n", "CISCO_IOS | \n", "['as2core2'] | \n", "
| 7 | \n", "configs/as2dept1.cfg | \n", "PASSED | \n", "CISCO_IOS | \n", "['as2dept1'] | \n", "
| 8 | \n", "configs/as2dist1.cfg | \n", "PASSED | \n", "CISCO_IOS | \n", "['as2dist1'] | \n", "
| 9 | \n", "configs/as2dist2.cfg | \n", "PASSED | \n", "CISCO_IOS | \n", "['as2dist2'] | \n", "
| 10 | \n", "configs/as3border1.cfg | \n", "PASSED | \n", "CISCO_IOS | \n", "['as3border1'] | \n", "
| 11 | \n", "configs/as3border2.cfg | \n", "PASSED | \n", "CISCO_IOS | \n", "['as3border2'] | \n", "
| 12 | \n", "configs/as3core1.cfg | \n", "PASSED | \n", "CISCO_IOS | \n", "['as3core1'] | \n", "
| 13 | \n", "hosts/host1.json | \n", "PASSED | \n", "HOST | \n", "['host1'] | \n", "
| 14 | \n", "hosts/host2.json | \n", "PASSED | \n", "HOST | \n", "['host2'] | \n", "
| 15 | \n", "iptables/host1.iptables | \n", "PASSED | \n", "IPTABLES | \n", "['iptables/host1.iptables'] | \n", "
| 16 | \n", "iptables/host2.iptables | \n", "PASSED | \n", "IPTABLES | \n", "['iptables/host2.iptables'] | \n", "
| \n", " | File_Name | \n", "Status | \n", "File_Format | \n", "Nodes | \n", "
|---|
| \n", " | Filename | \n", "Line | \n", "Text | \n", "Parser_Context | \n", "Comment | \n", "
|---|
| \n", " | Node | \n", "Domain_Name | \n", "Interfaces | \n", "NTP_Servers | \n", "
|---|---|---|---|---|
| 0 | \n", "as2border2 | \n", "lab.local | \n", "['Ethernet0/0', 'GigabitEthernet0/0', 'GigabitEthernet1/0', 'GigabitEthernet2/0', 'Loopback0'] | \n", "['18.18.18.18'] | \n", "
| 1 | \n", "as3border1 | \n", "lab.local | \n", "['Ethernet0/0', 'GigabitEthernet0/0', 'GigabitEthernet1/0', 'Loopback0'] | \n", "['18.18.18.18', '23.23.23.23'] | \n", "
| 2 | \n", "as3border2 | \n", "lab.local | \n", "['Ethernet0/0', 'GigabitEthernet0/0', 'GigabitEthernet1/0', 'Loopback0'] | \n", "['18.18.18.18', '23.23.23.23'] | \n", "
| 3 | \n", "as1border2 | \n", "lab.local | \n", "['Ethernet0/0', 'GigabitEthernet0/0', 'GigabitEthernet1/0', 'GigabitEthernet2/0', 'Loopback0'] | \n", "['18.18.18.18', '23.23.23.23'] | \n", "
| 4 | \n", "as2border1 | \n", "lab.local | \n", "['Ethernet0/0', 'GigabitEthernet0/0', 'GigabitEthernet1/0', 'GigabitEthernet2/0', 'Loopback0'] | \n", "['18.18.18.18', '23.23.23.23'] | \n", "
| 5 | \n", "as1border1 | \n", "lab.local | \n", "['Ethernet0/0', 'GigabitEthernet0/0', 'GigabitEthernet1/0', 'Loopback0'] | \n", "[] | \n", "
| \n", " | Interface | \n", "Bandwidth | \n", "Primary_Address | \n", "VRF | \n", "
|---|---|---|---|---|
| 0 | \n", "as1border1[Loopback0] | \n", "8000000000.0 | \n", "1.1.1.1/32 | \n", "default | \n", "
| 1 | \n", "as1border2[Loopback0] | \n", "8000000000.0 | \n", "1.2.2.2/32 | \n", "default | \n", "
| 2 | \n", "as1core1[Loopback0] | \n", "8000000000.0 | \n", "1.10.1.1/32 | \n", "default | \n", "
| 3 | \n", "as2border1[Loopback0] | \n", "8000000000.0 | \n", "2.1.1.1/32 | \n", "default | \n", "
| 4 | \n", "as2border2[Loopback0] | \n", "8000000000.0 | \n", "2.1.1.2/32 | \n", "default | \n", "
| 5 | \n", "as2core1[Loopback0] | \n", "8000000000.0 | \n", "2.1.2.1/32 | \n", "default | \n", "
| 6 | \n", "as2core2[Loopback0] | \n", "8000000000.0 | \n", "2.1.2.2/32 | \n", "default | \n", "
| 7 | \n", "as2dept1[Loopback0] | \n", "8000000000.0 | \n", "2.1.1.2/32 | \n", "default | \n", "
| 8 | \n", "as2dist1[Loopback0] | \n", "8000000000.0 | \n", "2.1.3.1/32 | \n", "default | \n", "
| 9 | \n", "as2dist2[Loopback0] | \n", "8000000000.0 | \n", "2.1.3.2/32 | \n", "default | \n", "
| 10 | \n", "as3border1[Loopback0] | \n", "8000000000.0 | \n", "3.1.1.1/32 | \n", "default | \n", "
| 11 | \n", "as3border2[Loopback0] | \n", "8000000000.0 | \n", "3.2.2.2/32 | \n", "default | \n", "
| 12 | \n", "as3core1[Loopback0] | \n", "8000000000.0 | \n", "3.10.1.1/32 | \n", "default | \n", "
| \n", " | File_Name | \n", "Struct_Type | \n", "Ref_Name | \n", "Context | \n", "Lines | \n", "
|---|---|---|---|---|---|
| 0 | \n", "configs/as2core2.cfg | \n", "route-map | \n", "filter-bogons | \n", "bgp inbound route-map | \n", "configs/as2core2.cfg:[110] | \n", "
| \n", " | Interface | \n", "IPs | \n", "Remote_Interface | \n", "Remote_IPs | \n", "
|---|---|---|---|---|
| 0 | \n", "as1border1[GigabitEthernet0/0] | \n", "['1.0.1.1'] | \n", "as1core1[GigabitEthernet1/0] | \n", "['1.0.1.2'] | \n", "
| 1 | \n", "as1border1[GigabitEthernet1/0] | \n", "['10.12.11.1'] | \n", "as2border1[GigabitEthernet0/0] | \n", "['10.12.11.2'] | \n", "
| \n", " | Node | \n", "IP | \n", "Interface | \n", "AS_Number | \n", "Remote_Node | \n", "Remote_IP | \n", "Remote_Interface | \n", "Remote_AS_Number | \n", "
|---|---|---|---|---|---|---|---|---|
| 0 | \n", "as1border1 | \n", "10.12.11.1 | \n", "None | \n", "1 | \n", "as2border1 | \n", "10.12.11.2 | \n", "None | \n", "2 | \n", "
| 1 | \n", "as1border1 | \n", "1.1.1.1 | \n", "None | \n", "1 | \n", "as1core1 | \n", "1.10.1.1 | \n", "None | \n", "1 | \n", "
| \n", " | Flow | \n", "Traces | \n", "TraceCount | \n", "
|---|---|---|---|
| 0 | \n", "Start Location: host1 Src IP: 2.128.0.101 Src Port: 49152 Dst IP: 1.0.2.2 Dst Port: 33434 IP Protocol: UDP | \n",
" ACCEPTED 1. node: host1 ORIGINATED(default) FORWARDED(Forwarded out interface: eth0 with resolved next-hop IP: 2.128.0.1, Routes: [static (Network: 0.0.0.0/0, Next Hop: interface eth0 ip 2.128.0.1)]) PERMITTED(filter::OUTPUT (EGRESS_FILTER)) TRANSMITTED(eth0) 2. node: as2dept1 RECEIVED(GigabitEthernet2/0) PERMITTED(RESTRICT_HOST_TRAFFIC_IN (INGRESS_FILTER)) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 2.34.101.3, Routes: [bgp (Network: 1.0.2.0/24, Next Hop: ip 2.34.101.3)]) TRANSMITTED(GigabitEthernet0/0) 3. node: as2dist1 RECEIVED(GigabitEthernet2/0) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 2.23.11.2, Routes: [ibgp (Network: 1.0.2.0/24, Next Hop: ip 10.12.11.1)]) TRANSMITTED(GigabitEthernet0/0) 4. node: as2core1 RECEIVED(GigabitEthernet2/0) PERMITTED(blocktelnet (INGRESS_FILTER)) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 2.12.11.1, Routes: [ibgp (Network: 1.0.2.0/24, Next Hop: ip 10.12.11.1)]) TRANSMITTED(GigabitEthernet0/0) 5. node: as2border1 RECEIVED(GigabitEthernet1/0) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 10.12.11.1, Routes: [bgp (Network: 1.0.2.0/24, Next Hop: ip 10.12.11.1)]) PERMITTED(INSIDE_TO_AS1 (EGRESS_FILTER)) TRANSMITTED(GigabitEthernet0/0) 6. node: as1border1 RECEIVED(GigabitEthernet1/0) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 1.0.1.2, Routes: [ospf (Network: 1.0.2.0/24, Next Hop: interface GigabitEthernet0/0 ip 1.0.1.2)]) TRANSMITTED(GigabitEthernet0/0) 7. node: as1core1 RECEIVED(GigabitEthernet1/0) ACCEPTED(GigabitEthernet0/0) ACCEPTED 1. node: host1 ORIGINATED(default) FORWARDED(Forwarded out interface: eth0 with resolved next-hop IP: 2.128.0.1, Routes: [static (Network: 0.0.0.0/0, Next Hop: interface eth0 ip 2.128.0.1)]) PERMITTED(filter::OUTPUT (EGRESS_FILTER)) TRANSMITTED(eth0) 2. node: as2dept1 RECEIVED(GigabitEthernet2/0) PERMITTED(RESTRICT_HOST_TRAFFIC_IN (INGRESS_FILTER)) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 2.34.101.3, Routes: [bgp (Network: 1.0.2.0/24, Next Hop: ip 2.34.101.3)]) TRANSMITTED(GigabitEthernet0/0) 3. node: as2dist1 RECEIVED(GigabitEthernet2/0) FORWARDED(Forwarded out interface: GigabitEthernet1/0 with resolved next-hop IP: 2.23.21.2, Routes: [ibgp (Network: 1.0.2.0/24, Next Hop: ip 10.12.11.1)]) TRANSMITTED(GigabitEthernet1/0) 4. node: as2core2 RECEIVED(GigabitEthernet3/0) FORWARDED(Forwarded out interface: GigabitEthernet1/0 with resolved next-hop IP: 2.12.12.1, Routes: [ibgp (Network: 1.0.2.0/24, Next Hop: ip 10.12.11.1)]) TRANSMITTED(GigabitEthernet1/0) 5. node: as2border1 RECEIVED(GigabitEthernet2/0) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 10.12.11.1, Routes: [bgp (Network: 1.0.2.0/24, Next Hop: ip 10.12.11.1)]) PERMITTED(INSIDE_TO_AS1 (EGRESS_FILTER)) TRANSMITTED(GigabitEthernet0/0) 6. node: as1border1 RECEIVED(GigabitEthernet1/0) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 1.0.1.2, Routes: [ospf (Network: 1.0.2.0/24, Next Hop: interface GigabitEthernet0/0 ip 1.0.1.2)]) TRANSMITTED(GigabitEthernet0/0) 7. node: as1core1 RECEIVED(GigabitEthernet1/0) ACCEPTED(GigabitEthernet0/0) ACCEPTED 1. node: host1 ORIGINATED(default) FORWARDED(Forwarded out interface: eth0 with resolved next-hop IP: 2.128.0.1, Routes: [static (Network: 0.0.0.0/0, Next Hop: interface eth0 ip 2.128.0.1)]) PERMITTED(filter::OUTPUT (EGRESS_FILTER)) TRANSMITTED(eth0) 2. node: as2dept1 RECEIVED(GigabitEthernet2/0) PERMITTED(RESTRICT_HOST_TRAFFIC_IN (INGRESS_FILTER)) FORWARDED(Forwarded out interface: GigabitEthernet1/0 with resolved next-hop IP: 2.34.201.3, Routes: [bgp (Network: 1.0.2.0/24, Next Hop: ip 2.34.201.3)]) TRANSMITTED(GigabitEthernet1/0) 3. node: as2dist2 RECEIVED(GigabitEthernet2/0) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 2.23.22.2, Routes: [ibgp (Network: 1.0.2.0/24, Next Hop: ip 10.12.11.1)]) TRANSMITTED(GigabitEthernet0/0) 4. node: as2core2 RECEIVED(GigabitEthernet2/0) FORWARDED(Forwarded out interface: GigabitEthernet1/0 with resolved next-hop IP: 2.12.12.1, Routes: [ibgp (Network: 1.0.2.0/24, Next Hop: ip 10.12.11.1)]) TRANSMITTED(GigabitEthernet1/0) 5. node: as2border1 RECEIVED(GigabitEthernet2/0) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 10.12.11.1, Routes: [bgp (Network: 1.0.2.0/24, Next Hop: ip 10.12.11.1)]) PERMITTED(INSIDE_TO_AS1 (EGRESS_FILTER)) TRANSMITTED(GigabitEthernet0/0) 6. node: as1border1 RECEIVED(GigabitEthernet1/0) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 1.0.1.2, Routes: [ospf (Network: 1.0.2.0/24, Next Hop: interface GigabitEthernet0/0 ip 1.0.1.2)]) TRANSMITTED(GigabitEthernet0/0) 7. node: as1core1 RECEIVED(GigabitEthernet1/0) ACCEPTED(GigabitEthernet0/0) ACCEPTED 1. node: host1 ORIGINATED(default) FORWARDED(Forwarded out interface: eth0 with resolved next-hop IP: 2.128.0.1, Routes: [static (Network: 0.0.0.0/0, Next Hop: interface eth0 ip 2.128.0.1)]) PERMITTED(filter::OUTPUT (EGRESS_FILTER)) TRANSMITTED(eth0) 2. node: as2dept1 RECEIVED(GigabitEthernet2/0) PERMITTED(RESTRICT_HOST_TRAFFIC_IN (INGRESS_FILTER)) FORWARDED(Forwarded out interface: GigabitEthernet1/0 with resolved next-hop IP: 2.34.201.3, Routes: [bgp (Network: 1.0.2.0/24, Next Hop: ip 2.34.201.3)]) TRANSMITTED(GigabitEthernet1/0) 3. node: as2dist2 RECEIVED(GigabitEthernet2/0) FORWARDED(Forwarded out interface: GigabitEthernet1/0 with resolved next-hop IP: 2.23.12.2, Routes: [ibgp (Network: 1.0.2.0/24, Next Hop: ip 10.12.11.1)]) TRANSMITTED(GigabitEthernet1/0) 4. node: as2core1 RECEIVED(GigabitEthernet3/0) PERMITTED(blocktelnet (INGRESS_FILTER)) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 2.12.11.1, Routes: [ibgp (Network: 1.0.2.0/24, Next Hop: ip 10.12.11.1)]) TRANSMITTED(GigabitEthernet0/0) 5. node: as2border1 RECEIVED(GigabitEthernet1/0) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 10.12.11.1, Routes: [bgp (Network: 1.0.2.0/24, Next Hop: ip 10.12.11.1)]) PERMITTED(INSIDE_TO_AS1 (EGRESS_FILTER)) TRANSMITTED(GigabitEthernet0/0) 6. node: as1border1 RECEIVED(GigabitEthernet1/0) FORWARDED(Forwarded out interface: GigabitEthernet0/0 with resolved next-hop IP: 1.0.1.2, Routes: [ospf (Network: 1.0.2.0/24, Next Hop: interface GigabitEthernet0/0 ip 1.0.1.2)]) TRANSMITTED(GigabitEthernet0/0) 7. node: as1core1 RECEIVED(GigabitEthernet1/0) ACCEPTED(GigabitEthernet0/0) | \n",
" 4 | \n", "
| \n", " | Node | \n", "VRF | \n", "Network | \n", "Next_Hop | \n", "Next_Hop_IP | \n", "Next_Hop_Interface | \n", "Protocol | \n", "Metric | \n", "Admin_Distance | \n", "Tag | \n", "
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | \n", "as3core1 | \n", "default | \n", "90.90.90.0/24 | \n", "interface GigabitEthernet2/0 | \n", "AUTO/NONE(-1l) | \n", "GigabitEthernet2/0 | \n", "connected | \n", "0 | \n", "0 | \n", "None | \n", "
| 1 | \n", "as3core1 | \n", "default | \n", "90.90.90.0/24 | \n", "interface GigabitEthernet3/0 | \n", "AUTO/NONE(-1l) | \n", "GigabitEthernet3/0 | \n", "connected | \n", "0 | \n", "0 | \n", "None | \n", "