use of org.batfish.symbolic.answers.SmtOneAnswerElement in project batfish by batfish.
the class PropertyChecker method checkRoutingLoop.
/*
* Checks for routing loops in the network. For efficiency reasons,
* we only check for loops with routers that use static routes since
* these can override the usual loop-prevention mechanisms.
*/
public AnswerElement checkRoutingLoop(HeaderQuestion q) {
Graph graph = new Graph(_batfish);
// Collect all relevant destinations
List<Prefix> prefixes = new ArrayList<>();
graph.getStaticRoutes().forEach((router, ifaceName, srs) -> {
for (StaticRoute sr : srs) {
prefixes.add(sr.getNetwork());
}
});
SortedSet<IpWildcard> pfxs = new TreeSet<>();
for (Prefix prefix : prefixes) {
pfxs.add(new IpWildcard(prefix));
}
q.getHeaderSpace().setDstIps(pfxs);
// Collect all routers that use static routes as a
// potential node along a loop
List<String> routers = new ArrayList<>();
for (Entry<String, Configuration> entry : graph.getConfigurations().entrySet()) {
String router = entry.getKey();
Configuration conf = entry.getValue();
if (conf.getDefaultVrf().getStaticRoutes().size() > 0) {
routers.add(router);
}
}
Encoder enc = new Encoder(_settings, graph, q);
enc.computeEncoding();
Context ctx = enc.getCtx();
EncoderSlice slice = enc.getMainSlice();
PropertyAdder pa = new PropertyAdder(slice);
BoolExpr someLoop = ctx.mkBool(false);
for (String router : routers) {
BoolExpr hasLoop = pa.instrumentLoop(router);
someLoop = ctx.mkOr(someLoop, hasLoop);
}
enc.add(someLoop);
VerificationResult result = enc.verify().getFirst();
return new SmtOneAnswerElement(result);
}
use of org.batfish.symbolic.answers.SmtOneAnswerElement in project batfish by batfish.
the class PropertyChecker method checkBlackHole.
/*
* Compute if there can ever be a black hole for routers that are
* not at the edge of the network. This is almost certainly a bug.
*/
public AnswerElement checkBlackHole(HeaderQuestion q) {
Graph graph = new Graph(_batfish);
Encoder enc = new Encoder(_settings, graph, q);
enc.computeEncoding();
Context ctx = enc.getCtx();
EncoderSlice slice = enc.getMainSlice();
// Collect routers that have no host/environment edge
List<String> toCheck = new ArrayList<>();
for (Entry<String, List<GraphEdge>> entry : graph.getEdgeMap().entrySet()) {
String router = entry.getKey();
List<GraphEdge> edges = entry.getValue();
boolean check = true;
for (GraphEdge edge : edges) {
if (edge.getEnd() == null) {
check = false;
break;
}
}
if (check) {
toCheck.add(router);
}
}
// Ensure the router never receives traffic and then drops the traffic
BoolExpr someBlackHole = ctx.mkBool(false);
for (String router : toCheck) {
Map<GraphEdge, BoolExpr> edges = slice.getSymbolicDecisions().getDataForwarding().get(router);
BoolExpr doesNotFwd = ctx.mkBool(true);
for (Map.Entry<GraphEdge, BoolExpr> entry : edges.entrySet()) {
BoolExpr dataFwd = entry.getValue();
doesNotFwd = ctx.mkAnd(doesNotFwd, ctx.mkNot(dataFwd));
}
BoolExpr isFwdTo = ctx.mkBool(false);
Set<String> neighbors = graph.getNeighbors().get(router);
for (String n : neighbors) {
for (Map.Entry<GraphEdge, BoolExpr> entry : slice.getSymbolicDecisions().getDataForwarding().get(n).entrySet()) {
GraphEdge ge = entry.getKey();
BoolExpr fwd = entry.getValue();
if (router.equals(ge.getPeer())) {
isFwdTo = ctx.mkOr(isFwdTo, fwd);
}
}
}
someBlackHole = ctx.mkOr(someBlackHole, ctx.mkAnd(isFwdTo, doesNotFwd));
}
enc.add(someBlackHole);
VerificationResult result = enc.verify().getFirst();
return new SmtOneAnswerElement(result);
}
use of org.batfish.symbolic.answers.SmtOneAnswerElement in project batfish by batfish.
the class PropertyChecker method checkForwarding.
/*
* Compute the forwarding behavior for the network. This adds no
* additional constraints on top of the base network encoding.
* Forwarding will be determined only for a particular network
* environment, failure scenario, and data plane packet.
*/
public AnswerElement checkForwarding(HeaderQuestion question) {
long totalTime = System.currentTimeMillis();
HeaderQuestion q = new HeaderQuestion(question);
q.setFailures(0);
Tuple<Stream<Supplier<NetworkSlice>>, Long> ecs = findAllNetworkSlices(q, null, true);
Stream<Supplier<NetworkSlice>> stream = ecs.getFirst();
Long timeAbstraction = ecs.getSecond();
Optional<Supplier<NetworkSlice>> opt = stream.findFirst();
if (!opt.isPresent()) {
throw new BatfishException("Unexpected Error: checkForwarding");
}
long timeEc = System.currentTimeMillis();
Supplier<NetworkSlice> sup = opt.get();
NetworkSlice slice = sup.get();
timeEc = System.currentTimeMillis() - timeEc;
Graph g = slice.getGraph();
q = new HeaderQuestion(q);
q.setHeaderSpace(slice.getHeaderSpace());
long timeEncoding = System.currentTimeMillis();
Encoder encoder = new Encoder(_settings, g, q);
encoder.computeEncoding();
addEnvironmentConstraints(encoder, q.getBaseEnvironmentType());
timeEncoding = System.currentTimeMillis() - timeEncoding;
VerificationResult result = encoder.verify().getFirst();
totalTime = System.currentTimeMillis() - totalTime;
VerificationStats stats = result.getStats();
if (q.getBenchmark()) {
stats.setTimeCreateBdds((double) timeAbstraction);
stats.setTotalTime(totalTime);
stats.setAvgComputeEcTime(timeEc);
stats.setMaxComputeEcTime(timeEc);
stats.setMinComputeEcTime(timeEc);
stats.setAvgEncodingTime(timeEncoding);
stats.setMaxEncodingTime(timeEncoding);
stats.setMinEncodingTime(timeEncoding);
stats.setTimeCreateBdds((double) timeAbstraction);
}
return new SmtOneAnswerElement(result);
}
use of org.batfish.symbolic.answers.SmtOneAnswerElement in project batfish by batfish.
the class PropertyChecker method checkBoundedLength.
/*
* Compute whether the path length will always be bounded by a constant k
* for a collection of source routers to any of a number of destination ports.
*/
public AnswerElement checkBoundedLength(HeaderLocationQuestion q, int k) {
return checkProperty(q, (enc, srcRouters, destPorts) -> {
ArithExpr bound = enc.mkInt(k);
PropertyAdder pa = new PropertyAdder(enc.getMainSlice());
Map<String, ArithExpr> lenVars = pa.instrumentPathLength(destPorts);
Map<String, BoolExpr> boundVars = new HashMap<>();
lenVars.forEach((n, ae) -> boundVars.put(n, enc.mkLe(ae, bound)));
return boundVars;
}, (vp) -> new SmtOneAnswerElement(vp.getResult()));
}
use of org.batfish.symbolic.answers.SmtOneAnswerElement in project batfish by batfish.
the class PropertyChecker method checkMultipathConsistency.
/*
* Computes multipath consistency, which ensures traffic that travels
* multiple paths will be treated equivalently by each path
* (i.e., dropped or accepted by each).
*/
public AnswerElement checkMultipathConsistency(HeaderLocationQuestion q) {
if (q.getNegate()) {
throw new BatfishException("Negation not implemented for smt-multipath-consistency.");
}
PathRegexes p = new PathRegexes(q);
Graph graph = new Graph(_batfish);
Set<GraphEdge> destPorts = findFinalInterfaces(graph, p);
inferDestinationHeaderSpace(graph, destPorts, q);
Encoder enc = new Encoder(_settings, graph, q);
enc.computeEncoding();
EncoderSlice slice = enc.getMainSlice();
PropertyAdder pa = new PropertyAdder(slice);
Map<String, BoolExpr> reachableVars = pa.instrumentReachability(destPorts);
BoolExpr acc = enc.mkFalse();
for (Map.Entry<String, Configuration> entry : graph.getConfigurations().entrySet()) {
String router = entry.getKey();
BoolExpr reach = reachableVars.get(router);
BoolExpr all = enc.mkTrue();
for (GraphEdge edge : graph.getEdgeMap().get(router)) {
BoolExpr dataFwd = slice.getForwardsAcross().get(router, edge);
BoolExpr ctrFwd = slice.getSymbolicDecisions().getControlForwarding().get(router, edge);
assert (ctrFwd != null);
BoolExpr peerReach = enc.mkTrue();
if (edge.getPeer() != null) {
peerReach = reachableVars.get(edge.getPeer());
}
BoolExpr imp = enc.mkImplies(ctrFwd, enc.mkAnd(dataFwd, peerReach));
all = enc.mkAnd(all, imp);
}
acc = enc.mkOr(acc, enc.mkNot(enc.mkImplies(reach, all)));
}
enc.add(acc);
VerificationResult res = enc.verify().getFirst();
return new SmtOneAnswerElement(res);
}
Aggregations