use of org.batfish.datamodel.FlowTrace in project batfish by batfish.
the class CounterExample method buildFlowHistoryDiff.
/*
* Create a trace-based counterexample demonstrating
* the difference between two networks on a single packet.
*/
FlowHistory buildFlowHistoryDiff(String testRigName, Collection<String> sourceRouters, Encoder enc, Encoder enc2, Map<String, BoolExpr> reach, Map<String, BoolExpr> reach2) {
FlowHistory fh = new FlowHistory();
assert (reach2 != null);
for (String source : sourceRouters) {
BoolExpr sourceVar1 = reach.get(source);
BoolExpr sourceVar2 = reach2.get(source);
String val1 = evaluate(sourceVar1);
String val2 = evaluate(sourceVar2);
if (!Objects.equals(val1, val2)) {
Tuple<Flow, FlowTrace> diff = buildFlowTrace(enc, source);
Tuple<Flow, FlowTrace> base = buildFlowTrace(enc2, source);
SortedSet<Edge> failedLinksDiff = buildFailedLinks(enc);
SortedSet<Edge> failedLinksBase = buildFailedLinks(enc2);
SortedSet<BgpAdvertisement> envRoutesDiff = buildEnvRoutingTable(enc);
SortedSet<BgpAdvertisement> envRoutesBase = buildEnvRoutingTable(enc2);
Environment baseEnv = new Environment("BASE", testRigName, failedLinksBase, null, null, null, null, envRoutesBase);
Environment failedEnv = new Environment("DELTA", testRigName, failedLinksDiff, null, null, null, null, envRoutesDiff);
fh.addFlowTrace(base.getFirst(), "BASE", baseEnv, base.getSecond());
fh.addFlowTrace(diff.getFirst(), "DELTA", failedEnv, diff.getSecond());
}
}
return fh;
}
use of org.batfish.datamodel.FlowTrace in project batfish by batfish.
the class NodJobTest method testNatted.
/**
* Test that traffic originating from 3.0.0.0 is NATed
*/
@Test
public void testNatted() {
HeaderSpace headerSpace = new HeaderSpace();
headerSpace.setSrcIps(ImmutableList.of(new IpWildcard("3.0.0.0")));
NodJob nodJob = getNodJob(headerSpace);
Context z3Context = new Context();
SmtInput smtInput = nodJob.computeSmtInput(System.currentTimeMillis(), z3Context);
Map<OriginateVrf, Map<String, Long>> fieldConstraintsByOriginateVrf = nodJob.getOriginateVrfConstraints(z3Context, smtInput);
assertThat(fieldConstraintsByOriginateVrf.entrySet(), hasSize(1));
assertThat(fieldConstraintsByOriginateVrf, hasKey(_originateVrf));
Map<String, Long> fieldConstraints = fieldConstraintsByOriginateVrf.get(_originateVrf);
// Only one OriginateVrf choice, so this must be 0
assertThat(fieldConstraints, hasEntry(OriginateVrfInstrumentation.ORIGINATE_VRF_FIELD_NAME, new Long(0)));
assertThat(fieldConstraints, hasEntry(BasicHeaderField.ORIG_SRC_IP.getName(), new Ip("3.0.0.0").asLong()));
assertThat(fieldConstraints, hasEntry(equalTo(BasicHeaderField.SRC_IP.getName()), not(equalTo(new Ip("3.0.0.0").asLong()))));
assertThat(fieldConstraints, hasEntry(BasicHeaderField.SRC_IP.getName(), new Ip("1.0.0.10").asLong()));
Set<Flow> flows = nodJob.getFlows(fieldConstraintsByOriginateVrf);
_bdpDataPlanePlugin.processFlows(flows, _dataPlane);
List<FlowTrace> flowTraces = _bdpDataPlanePlugin.getHistoryFlowTraces(_dataPlane);
flowTraces.forEach(trace -> {
assertThat(trace.getNotes(), is("ACCEPTED"));
List<FlowTraceHop> hops = trace.getHops();
assertThat(hops, hasSize(1));
FlowTraceHop hop = hops.get(0);
assertThat(hop.getTransformedFlow(), notNullValue());
assertThat(hop.getTransformedFlow().getSrcIp(), equalTo(new Ip("1.0.0.10")));
});
}
use of org.batfish.datamodel.FlowTrace in project batfish by batfish.
the class BdpEngine method processCurrentNextHopInterfaceEdges.
private boolean processCurrentNextHopInterfaceEdges(BdpDataPlane dp, String currentNodeName, Set<Edge> visitedEdges, List<FlowTraceHop> hopsSoFar, Set<FlowTrace> flowTraces, Flow originalFlow, Flow transformedFlow, Ip dstIp, Set<String> dstIpOwners, @Nullable String nextHopInterfaceName, SortedSet<String> routesForThisNextHopInterface, @Nullable Ip finalNextHopIp, @Nullable NodeInterfacePair nextHopInterface, SortedSet<Edge> edges, boolean arp) {
boolean continueToNextNextHopInterface = false;
int unreachableNeighbors = 0;
int potentialNeighbors = 0;
for (Edge edge : edges) {
if (!edge.getNode1().equals(currentNodeName)) {
continue;
}
potentialNeighbors++;
List<FlowTraceHop> newHops = new ArrayList<>(hopsSoFar);
Set<Edge> newVisitedEdges = new LinkedHashSet<>(visitedEdges);
FlowTraceHop newHop = new FlowTraceHop(edge, routesForThisNextHopInterface, hopFlow(originalFlow, transformedFlow));
newVisitedEdges.add(edge);
newHops.add(newHop);
/*
* Check to see whether neighbor would refrain from sending ARP reply
* (NEIGHBOR_UNREACHABLE)
*
* This occurs if:
*
* - Using interface-only route
*
* AND
*
* - Neighbor does not own arpIp
*
* AND EITHER
*
* -- Neighbor not using proxy-arp
*
* - OR
*
* -- Subnet of neighbor's receiving-interface contains arpIp
*/
if (arp) {
Ip arpIp;
Set<String> arpIpOwners;
if (finalNextHopIp == null) {
arpIp = dstIp;
arpIpOwners = dstIpOwners;
} else {
arpIp = finalNextHopIp;
arpIpOwners = dp._ipOwners.get(arpIp);
}
// using interface-only route
String node2 = edge.getNode2();
if (arpIpOwners == null || !arpIpOwners.contains(node2)) {
// neighbor does not own arpIp
String int2Name = edge.getInt2();
Interface int2 = dp._nodes.get(node2)._c.getInterfaces().get(int2Name);
boolean neighborUnreachable = false;
Boolean proxyArp = int2.getProxyArp();
if (proxyArp == null || !proxyArp) {
// TODO: proxyArp probably shouldn't be null
neighborUnreachable = true;
} else {
for (InterfaceAddress address : int2.getAllAddresses()) {
if (address.getPrefix().containsIp(arpIp)) {
neighborUnreachable = true;
break;
}
}
}
if (neighborUnreachable) {
unreachableNeighbors++;
continue;
}
}
}
if (visitedEdges.contains(edge)) {
FlowTrace trace = new FlowTrace(FlowDisposition.LOOP, newHops, FlowDisposition.LOOP.toString());
flowTraces.add(trace);
potentialNeighbors--;
continue;
}
String nextNodeName = edge.getNode2();
// now check output filter and input filter
if (nextHopInterfaceName != null) {
IpAccessList outFilter = dp._nodes.get(currentNodeName)._c.getInterfaces().get(nextHopInterfaceName).getOutgoingFilter();
if (outFilter != null) {
FlowDisposition disposition = FlowDisposition.DENIED_OUT;
boolean denied = flowTraceDeniedHelper(flowTraces, originalFlow, transformedFlow, newHops, outFilter, disposition);
if (denied) {
potentialNeighbors--;
continue;
}
}
}
IpAccessList inFilter = dp._nodes.get(nextNodeName)._c.getInterfaces().get(edge.getInt2()).getIncomingFilter();
if (inFilter != null) {
FlowDisposition disposition = FlowDisposition.DENIED_IN;
boolean denied = flowTraceDeniedHelper(flowTraces, originalFlow, transformedFlow, newHops, inFilter, disposition);
if (denied) {
potentialNeighbors--;
continue;
}
}
// recurse
collectFlowTraces(dp, nextNodeName, newVisitedEdges, newHops, flowTraces, originalFlow, transformedFlow);
}
if (arp && unreachableNeighbors > 0 && unreachableNeighbors == potentialNeighbors) {
FlowTrace trace = neighborUnreachableTrace(hopsSoFar, nextHopInterface, routesForThisNextHopInterface, originalFlow, transformedFlow);
flowTraces.add(trace);
continueToNextNextHopInterface = true;
}
return continueToNextNextHopInterface;
}
use of org.batfish.datamodel.FlowTrace in project batfish by batfish.
the class BdpEngine method neighborUnreachableTrace.
private FlowTrace neighborUnreachableTrace(List<FlowTraceHop> completedHops, NodeInterfacePair srcInterface, SortedSet<String> routes, Flow originalFlow, Flow transformedFlow) {
Edge neighborUnreachbleEdge = new Edge(srcInterface, new NodeInterfacePair(Configuration.NODE_NONE_NAME, Interface.NULL_INTERFACE_NAME));
FlowTraceHop neighborUnreachableHop = new FlowTraceHop(neighborUnreachbleEdge, routes, hopFlow(originalFlow, transformedFlow));
List<FlowTraceHop> newHops = new ArrayList<>(completedHops);
newHops.add(neighborUnreachableHop);
FlowTrace trace = new FlowTrace(FlowDisposition.NEIGHBOR_UNREACHABLE_OR_EXITS_NETWORK, newHops, FlowDisposition.NEIGHBOR_UNREACHABLE_OR_EXITS_NETWORK.toString());
return trace;
}
use of org.batfish.datamodel.FlowTrace in project batfish by batfish.
the class Batfish method populateFlowHistory.
private void populateFlowHistory(FlowHistory flowHistory, String envTag, Environment environment, String flowTag) {
DataPlanePlugin dataPlanePlugin = getDataPlanePlugin();
List<Flow> flows = dataPlanePlugin.getHistoryFlows(loadDataPlane());
List<FlowTrace> flowTraces = dataPlanePlugin.getHistoryFlowTraces(loadDataPlane());
int numEntries = flows.size();
for (int i = 0; i < numEntries; i++) {
Flow flow = flows.get(i);
if (flow.getTag().equals(flowTag)) {
FlowTrace flowTrace = flowTraces.get(i);
flowHistory.addFlowTrace(flow, envTag, environment, flowTrace);
}
}
}
Aggregations