use of org.batfish.symbolic.utils.Tuple in project batfish by batfish.
the class AbstractionBuilder method collectInterfaceInformation.
private void collectInterfaceInformation(Set<String> partition, boolean isUniversal) {
for (String router : partition) {
List<GraphEdge> edges = _graph.getEdgeMap().get(router);
for (GraphEdge edge : edges) {
String peer = edge.getPeer();
InterfacePolicy ipol = _importPol.get(edge);
GraphEdge otherEnd = _graph.getOtherEnd().get(edge);
InterfacePolicy epol = null;
if (otherEnd != null) {
epol = _exportPol.get(otherEnd);
}
// Update the existential map
Integer peerGroup = (peer == null ? (_graph.isExternal(edge) ? EBGP_INDEX : HOST_OR_LOOPBACK_INDEX) : _abstractGroups.getHandle(peer));
EdgePolicy pair = new EdgePolicy(ipol, epol);
EdgePolicyToRole ee = new EdgePolicyToRole(peerGroup, pair);
if (isUniversal) {
// Universal abstraction
Tuple<String, EdgePolicyToRole> tup = new Tuple<>(peer, ee);
Set<Tuple<String, EdgePolicyToRole>> group = _universalMap.computeIfAbsent(router, k -> new HashSet<>());
group.add(tup);
} else {
// Existential abstraction
Integer i = _existentialMap.get(router, ee);
i = (i == null ? 1 : i + 1);
_existentialMap.put(router, ee, i);
}
// Update the id map
if (peerGroup >= 0) {
Set<EdgePolicyToRole> x = _eeMap.computeIfAbsent(router, peerGroup, (k1, k2) -> new HashSet<>());
x.add(ee);
Set<EdgePolicy> y = _polMap.computeIfAbsent(router, peerGroup, (k1, k2) -> new HashSet<>());
y.add(pair);
}
}
}
}
use of org.batfish.symbolic.utils.Tuple in project batfish by batfish.
the class DestinationClasses method addCatchAllCase.
/**
* Adds a catch-all headerspace to the headerspace map. The catch-all case matches dstIps, does
* not match notDstIps, and doesn't match anything matched by anything in destinationMap.
*
* @param dstIps A list of destination IPs that should be in the catch-all headerspace.
* @param notDstIps A list of destination IPs that should not be in the catch-all headerspace.
* @param destinationMap Inversion of the prefix trie -- from sets of destinations to prefixes
*/
private void addCatchAllCase(List<Prefix> dstIps, List<Prefix> notDstIps, Map<Set<String>, List<Prefix>> destinationMap) {
HeaderSpace catchAll = createHeaderSpace(dstIps);
catchAll.setNotDstIps(Stream.concat(notDstIps.stream(), destinationMap.values().stream().flatMap(Collection::stream)).map(IpWildcard::new).collect(Collectors.toSet()));
if (_headerspace != null) {
copyAllButDestinationIp(catchAll, _headerspace);
}
if (!catchAll.getNotDstIps().equals(catchAll.getDstIps())) {
_headerspaceMap.put(new HashSet<>(), new Tuple<>(catchAll, new Tuple<>(null, true)));
}
}
use of org.batfish.symbolic.utils.Tuple in project batfish by batfish.
the class Encoder method verify.
/**
* Checks that a property is always true by seeing if the encoding is unsatisfiable. mkIf the
* model is satisfiable, then there is a counter example to the property.
*
* @return A VerificationResult indicating the status of the check.
*/
public Tuple<VerificationResult, Model> verify() {
EncoderSlice mainSlice = _slices.get(MAIN_SLICE_NAME);
int numVariables = _allVariables.size();
int numConstraints = _solver.getAssertions().length;
int numNodes = mainSlice.getGraph().getConfigurations().size();
int numEdges = 0;
for (Map.Entry<String, Set<String>> e : mainSlice.getGraph().getNeighbors().entrySet()) {
numEdges += e.getValue().size();
}
long start = System.currentTimeMillis();
Status status = _solver.check();
long time = System.currentTimeMillis() - start;
VerificationStats stats = null;
if (_question.getBenchmark()) {
stats = new VerificationStats();
stats.setAvgNumNodes(numNodes);
stats.setMaxNumNodes(numNodes);
stats.setMinNumNodes(numNodes);
stats.setAvgNumEdges(numEdges);
stats.setMaxNumEdges(numEdges);
stats.setMinNumEdges(numEdges);
stats.setAvgNumVariables(numVariables);
stats.setMaxNumVariables(numVariables);
stats.setMinNumVariables(numVariables);
stats.setAvgNumConstraints(numConstraints);
stats.setMaxNumConstraints(numConstraints);
stats.setMinNumConstraints(numConstraints);
stats.setAvgSolverTime(time);
stats.setMaxSolverTime(time);
stats.setMinSolverTime(time);
}
if (status == Status.UNSATISFIABLE) {
VerificationResult res = new VerificationResult(true, null, null, null, null, null, stats);
return new Tuple<>(res, null);
} else if (status == Status.UNKNOWN) {
throw new BatfishException("ERROR: satisfiability unknown");
} else {
VerificationResult result;
Model m;
while (true) {
m = _solver.getModel();
SortedMap<String, String> model = new TreeMap<>();
SortedMap<String, String> packetModel = new TreeMap<>();
SortedSet<String> fwdModel = new TreeSet<>();
SortedMap<String, SortedMap<String, String>> envModel = new TreeMap<>();
SortedSet<String> failures = new TreeSet<>();
buildCounterExample(this, m, model, packetModel, fwdModel, envModel, failures);
if (_previousEncoder != null) {
buildCounterExample(_previousEncoder, m, model, packetModel, fwdModel, envModel, failures);
}
result = new VerificationResult(false, model, packetModel, envModel, fwdModel, failures, stats);
if (!_question.getMinimize()) {
break;
}
BoolExpr blocking = environmentBlockingClause(m);
add(blocking);
Status s = _solver.check();
if (s == Status.UNSATISFIABLE) {
break;
}
if (s == Status.UNKNOWN) {
throw new BatfishException("ERROR: satisfiability unknown");
}
}
return new Tuple<>(result, m);
}
}
use of org.batfish.symbolic.utils.Tuple in project batfish by batfish.
the class CounterExample method buildFlowTrace.
/*
* Build flow information for a given hop along a path
*/
Tuple<Flow, FlowTrace> buildFlowTrace(Encoder enc, String router) {
EncoderSlice slice = enc.getMainSlice();
SymbolicPacket pkt = slice.getSymbolicPacket();
SymbolicDecisions decisions = slice.getSymbolicDecisions();
Flow f = buildFlow(pkt, router);
SortedSet<String> visited = new TreeSet<>();
List<FlowTraceHop> hops = new ArrayList<>();
String current = router;
while (true) {
visited.add(current);
// Get the forwarding variables
Map<GraphEdge, BoolExpr> dfwd = decisions.getDataForwarding().get(current);
Map<GraphEdge, BoolExpr> cfwd = decisions.getControlForwarding().get(current);
Map<GraphEdge, BoolExpr> across = enc.getMainSlice().getForwardsAcross().get(current);
// Find the route used
SymbolicRoute r = decisions.getBestNeighbor().get(current);
Protocol proto = buildProcotol(r, slice, current);
Prefix pfx = buildPrefix(r, f);
// pick the next router
boolean found = false;
for (Entry<GraphEdge, BoolExpr> entry : dfwd.entrySet()) {
GraphEdge ge = entry.getKey();
BoolExpr dexpr = entry.getValue();
BoolExpr cexpr = cfwd.get(ge);
BoolExpr aexpr = across.get(ge);
String route = buildRoute(pfx, proto, ge);
if (isTrue(dexpr)) {
hops.add(buildFlowTraceHop(ge, route));
if (ge.getPeer() != null && visited.contains(ge.getPeer())) {
FlowTrace ft = new FlowTrace(FlowDisposition.LOOP, hops, "LOOP");
return new Tuple<>(f, ft);
}
if (isFalse(aexpr)) {
Interface i = ge.getEnd();
IpAccessList acl = i.getIncomingFilter();
FilterResult fr = acl.filter(f);
String line = "default deny";
if (fr.getMatchLine() != null) {
line = acl.getLines().get(fr.getMatchLine()).getName();
}
String note = String.format("DENIED_IN{%s}{%s}", acl.getName(), line);
FlowTrace ft = new FlowTrace(FlowDisposition.DENIED_IN, hops, note);
return new Tuple<>(f, ft);
}
boolean isLoopback = slice.getGraph().isLoopback(ge);
if (isLoopback) {
FlowTrace ft = new FlowTrace(FlowDisposition.ACCEPTED, hops, "ACCEPTED");
return new Tuple<>(f, ft);
}
if (ge.getPeer() == null) {
boolean isBgpPeering = slice.getGraph().getEbgpNeighbors().get(ge) != null;
if (isBgpPeering) {
FlowTrace ft = new FlowTrace(FlowDisposition.ACCEPTED, hops, "ACCEPTED");
return new Tuple<>(f, ft);
} else {
FlowTrace ft = new FlowTrace(FlowDisposition.NEIGHBOR_UNREACHABLE_OR_EXITS_NETWORK, hops, "NEIGHBOR_UNREACHABLE_OR_EXITS_NETWORK");
return new Tuple<>(f, ft);
}
}
if (slice.getGraph().isHost(ge.getPeer())) {
FlowTrace ft = new FlowTrace(FlowDisposition.ACCEPTED, hops, "ACCEPTED");
return new Tuple<>(f, ft);
}
current = ge.getPeer();
found = true;
break;
} else if (isTrue(cexpr)) {
hops.add(buildFlowTraceHop(ge, route));
Interface i = ge.getStart();
IpAccessList acl = i.getOutgoingFilter();
FilterResult fr = acl.filter(f);
IpAccessListLine line = acl.getLines().get(fr.getMatchLine());
String note = String.format("DENIED_OUT{%s}{%s}", acl.getName(), line.getName());
FlowTrace ft = new FlowTrace(FlowDisposition.DENIED_OUT, hops, note);
return new Tuple<>(f, ft);
}
}
if (!found) {
BoolExpr permitted = r.getPermitted();
if (boolVal(permitted)) {
// Check if there is an accepting interface
for (GraphEdge ge : slice.getGraph().getEdgeMap().get(current)) {
Interface i = ge.getStart();
Ip ip = i.getAddress().getIp();
if (ip.equals(f.getDstIp())) {
FlowTrace ft = new FlowTrace(FlowDisposition.ACCEPTED, hops, "ACCEPTED");
return new Tuple<>(f, ft);
}
}
FlowTrace ft = new FlowTrace(FlowDisposition.NEIGHBOR_UNREACHABLE_OR_EXITS_NETWORK, hops, "NEIGHBOR_UNREACHABLE_OR_EXITS_NETWORK");
return new Tuple<>(f, ft);
}
FlowTrace ft = new FlowTrace(FlowDisposition.NO_ROUTE, hops, "NO_ROUTE");
return new Tuple<>(f, ft);
}
}
}
use of org.batfish.symbolic.utils.Tuple in project batfish by batfish.
the class PropertyChecker method findAllNetworkSlices.
private Tuple<Stream<Supplier<NetworkSlice>>, Long> findAllNetworkSlices(HeaderQuestion q, @Nullable Graph graph, boolean useDefaultCase) {
if (q.getUseAbstraction()) {
HeaderSpace h = q.getHeaderSpace();
int numFailures = q.getFailures();
System.out.println("Start verification");
System.out.println("Using headerspace: " + h.getDstIps());
DestinationClasses dcs = DestinationClasses.create(_batfish, graph, h, useDefaultCase);
System.out.println("Number of edges: " + dcs.getGraph().getAllRealEdges().size());
System.out.println("Created destination classes");
System.out.println("Num Classes: " + dcs.getHeaderspaceMap().size());
long l = System.currentTimeMillis();
ArrayList<Supplier<NetworkSlice>> ecs = NetworkSlice.allSlices(dcs, numFailures);
l = System.currentTimeMillis() - l;
System.out.println("Created BDDs");
return new Tuple<>(ecs.parallelStream(), l);
} else {
List<Supplier<NetworkSlice>> singleEc = new ArrayList<>();
Graph g = graph == null ? new Graph(_batfish) : graph;
Abstraction a = new Abstraction(g, null);
NetworkSlice slice = new NetworkSlice(q.getHeaderSpace(), a, false);
Supplier<NetworkSlice> sup = () -> slice;
singleEc.add(sup);
return new Tuple<>(singleEc.stream(), 0L);
}
}
Aggregations