batfish/pybatfish

bf_fork_snapshot overwrites BASE_SNAPSHOT

Closed this issue · 1 comments

EDIT : Looks like the issue is the default reference snapshot that is used in the questions is changed to the forked snapshot.

My understanding is that the command:

bf_fork_snapshot(BASE_SNAPSHOT_NAME, 'spine2-failure', deactivate_nodes=['spine2'], overwrite=True)

Should create a new snapshot with spine2 deactivated. Overwriting any snapshot named 'spine2-failure'. From running this command I can see that (via bf_list_snapshots(verbose=True)) that the timestamps of the BASE_SNAPSHOT and 'spine2-failure' show this behaviour.

However, if I run a question against the BASE_SNAPSHOT it shows the results of the forked snapshot. i.e spine2 being deactivated. Summary below:

>>> bf_init_snapshot(SNAPSHOT_PATH, name=BASE_SNAPSHOT_NAME, overwrite=True)
>>> tr_answer = bfq.traceroute(startLocation="server1",headers=HeaderConstraints(dstIps='server2')).answer().frame()
>>> len(tr_answer['Traces'][0])
>>> 8

>>> bf_fork_snapshot(BASE_SNAPSHOT_NAME, 'spine2-failure', deactivate_nodes=['spine2'], overwrite=True)
>>> tr_answer = bfq.traceroute(startLocation="server1",headers=HeaderConstraints(dstIps='server2')).answer().frame()
>>> len(tr_answer['Traces'][0])
>>> 4

The traces are reduced due to spine2 being now down. Verbose output below:

>>> pprint_traceroute(tr_answer)
# FLOW = start=server1 [172.16.1.1:49152->172.16.2.1:33434 UDP length=512]

-- TRACE0
node: server1
  ORIGINATED(default)
  FORWARDED(Routes: static [Network: 0.0.0.0/0, Next Hop IP:172.16.1.254])
  TRANSMITTED(eth1)
node: leaf1
  RECEIVED(Vlan10)
  FORWARDED(Routes: bgp [Network: 172.16.2.0/24, Next Hop IP:1.1.1.1])
  TRANSMITTED(Ethernet1/1)
node: spine1
  RECEIVED(Ethernet1/1)
  FORWARDED(Routes: bgp [Network: 172.16.2.0/24, Next Hop IP:4.4.4.4])
  TRANSMITTED(Ethernet1/3)
node: leaf2
  RECEIVED(Ethernet1/3)
  FORWARDED(Routes: connected [Network: 172.16.2.0/24, Next Hop IP:AUTO/NONE(-1l)])
  TRANSMITTED(Vlan20)
node: server2
  RECEIVED(eth1)
  ACCEPTED(InboundStep)

-- TRACE1
node: server1
  ORIGINATED(default)
  FORWARDED(Routes: static [Network: 0.0.0.0/0, Next Hop IP:172.16.1.254])
  TRANSMITTED(eth1)
node: leaf1
  RECEIVED(Vlan10)
  FORWARDED(Routes: bgp [Network: 172.16.2.0/24, Next Hop IP:1.1.1.1])
  TRANSMITTED(Ethernet1/1)
node: spine1
  RECEIVED(Ethernet1/1)
  FORWARDED(Routes: bgp [Network: 172.16.2.0/24, Next Hop IP:4.4.4.4])
  TRANSMITTED(Ethernet1/4)
node: leaf2
  RECEIVED(Ethernet1/4)
  FORWARDED(Routes: connected [Network: 172.16.2.0/24, Next Hop IP:AUTO/NONE(-1l)])
  TRANSMITTED(Vlan20)
node: server2
  RECEIVED(eth1)
  ACCEPTED(InboundStep)

-- TRACE2
node: server1
  ORIGINATED(default)
  FORWARDED(Routes: static [Network: 0.0.0.0/0, Next Hop IP:172.16.1.254])
  TRANSMITTED(eth1)
node: leaf1
  RECEIVED(Vlan10)
  FORWARDED(Routes: bgp [Network: 172.16.2.0/24, Next Hop IP:1.1.1.1])
  TRANSMITTED(Ethernet1/2)
node: spine1
  RECEIVED(Ethernet1/2)
  FORWARDED(Routes: bgp [Network: 172.16.2.0/24, Next Hop IP:4.4.4.4])
  TRANSMITTED(Ethernet1/3)
node: leaf2
  RECEIVED(Ethernet1/3)
  FORWARDED(Routes: connected [Network: 172.16.2.0/24, Next Hop IP:AUTO/NONE(-1l)])
  TRANSMITTED(Vlan20)
node: server2
  RECEIVED(eth1)
  ACCEPTED(InboundStep)

-- TRACE3
node: server1
  ORIGINATED(default)
  FORWARDED(Routes: static [Network: 0.0.0.0/0, Next Hop IP:172.16.1.254])
  TRANSMITTED(eth1)
node: leaf1
  RECEIVED(Vlan10)
  FORWARDED(Routes: bgp [Network: 172.16.2.0/24, Next Hop IP:1.1.1.1])
  TRANSMITTED(Ethernet1/2)
node: spine1
  RECEIVED(Ethernet1/2)
  FORWARDED(Routes: bgp [Network: 172.16.2.0/24, Next Hop IP:4.4.4.4])
  TRANSMITTED(Ethernet1/4)
node: leaf2
  RECEIVED(Ethernet1/4)
  FORWARDED(Routes: connected [Network: 172.16.2.0/24, Next Hop IP:AUTO/NONE(-1l)])
  TRANSMITTED(Vlan20)
node: server2
  RECEIVED(eth1)
  ACCEPTED(InboundStep)

Hi @rickdonato That is the expected behavior. You can only have one "current" snapshot at a time. By performing a fork, you set the current snapshot to the spine-failure snapshot.

The best way to ask questions involving two or more snapshots is to explicitly pass snapshot and reference_snapshot parameters to the answer function.

To ask the traceroute on the base snapshot:
tr_answer = bfq.traceroute(startLocation="server1",headers=HeaderConstraints(dstIps='server2')).answer(snapshot=BASE_SNAPSHOT).frame()

To see the traceroute difference between snapshots ("current" will be failed spine, "original" will be base)
tr_answer = bfq.traceroute(startLocation="server1",headers=HeaderConstraints(dstIps='server2')).answer(snapshot='spine-failure', reference_snapshot=BASE_SNAPSHOT).frame()