use of com.microsoft.z3.Context in project batfish by batfish.
the class PropertyAdder method allEqual.
static BoolExpr allEqual(Context ctx, List<Expr> exprs) {
BoolExpr acc = ctx.mkBool(true);
if (exprs.size() > 1) {
for (int i = 0; i < exprs.size() - 1; i++) {
Expr x = exprs.get(i);
Expr y = exprs.get(i + 1);
acc = ctx.mkAnd(acc, ctx.mkEq(x, y));
}
}
return acc;
}
use of com.microsoft.z3.Context in project batfish by batfish.
the class PropertyAdder method instrumentReachability.
/*
* Add reachability information to the network for a destination edge.
* Each router will have a boolean variable determining if it can reach
* the destination. A router is reachable if it has some neighbor that
* is also reachable.
*/
Map<String, BoolExpr> instrumentReachability(Set<GraphEdge> ges) {
Context ctx = _encoderSlice.getCtx();
Solver solver = _encoderSlice.getSolver();
EncoderSlice slice = _encoderSlice;
Map<String, BoolExpr> reachableVars = new HashMap<>();
Map<String, ArithExpr> idVars = new HashMap<>();
initializeReachabilityVars(slice, ctx, solver, reachableVars, idVars);
Graph g = _encoderSlice.getGraph();
for (Entry<String, List<GraphEdge>> entry : g.getEdgeMap().entrySet()) {
String router = entry.getKey();
List<GraphEdge> edges = entry.getValue();
ArithExpr id = idVars.get(router);
// Add the base case, reachable if we forward to a directly connected interface
BoolExpr hasDirectRoute = ctx.mkFalse();
BoolExpr isAbsorbed = ctx.mkFalse();
SymbolicRoute r = _encoderSlice.getBestNeighborPerProtocol(router, Protocol.CONNECTED);
for (GraphEdge ge : edges) {
if (!ge.isAbstract() && ges.contains(ge)) {
// If a host, consider reachable
if (g.isHost(router)) {
hasDirectRoute = ctx.mkTrue();
break;
}
// Reachable if we leave the network
if (ge.getPeer() == null) {
BoolExpr fwdIface = _encoderSlice.getForwardsAcross().get(ge.getRouter(), ge);
assert (fwdIface != null);
hasDirectRoute = ctx.mkOr(hasDirectRoute, fwdIface);
}
// Also reachable if connected route and we use it despite not forwarding
if (r != null) {
BitVecExpr dstIp = _encoderSlice.getSymbolicPacket().getDstIp();
BitVecExpr ip = ctx.mkBV(ge.getStart().getAddress().getIp().asLong(), 32);
BoolExpr reach = ctx.mkAnd(r.getPermitted(), ctx.mkEq(dstIp, ip));
isAbsorbed = ctx.mkOr(isAbsorbed, reach);
}
}
}
// Add the recursive case, where it is reachable through a neighbor
BoolExpr recursive = recursiveReachability(ctx, slice, edges, idVars, router, id);
BoolExpr guard = ctx.mkOr(hasDirectRoute, isAbsorbed);
BoolExpr cond = slice.mkIf(guard, ctx.mkEq(id, ctx.mkInt(1)), recursive);
solver.add(cond);
}
return reachableVars;
}
use of com.microsoft.z3.Context in project batfish by batfish.
the class PropertyAdder method instrumentLoop.
/*
* Instruments the network to check if a router will be part
* of a routing loop.
*/
BoolExpr instrumentLoop(String router) {
Context ctx = _encoderSlice.getCtx();
Solver solver = _encoderSlice.getSolver();
String sliceName = _encoderSlice.getSliceName();
// Add on-loop variables to track a loop
Map<String, BoolExpr> onLoop = new HashMap<>();
Graph graph = _encoderSlice.getGraph();
for (String r : graph.getRouters()) {
String name = _encoderSlice.getEncoder().getId() + "_" + sliceName + "_on-loop_" + router + "_" + r;
BoolExpr var = ctx.mkBoolConst(name);
onLoop.put(r, var);
_encoderSlice.getAllVariables().put(var.toString(), var);
}
for (Entry<String, List<GraphEdge>> entry : graph.getEdgeMap().entrySet()) {
String r = entry.getKey();
List<GraphEdge> edges = entry.getValue();
BoolExpr var = onLoop.get(r);
BoolExpr acc = ctx.mkBool(false);
for (GraphEdge edge : edges) {
if (!edge.isAbstract()) {
BoolExpr fwd = _encoderSlice.getForwardsAcross().get(r, edge);
String peer = edge.getPeer();
if (peer != null) {
if (peer.equals(router)) {
// If next hop is static route router, then on loop
acc = ctx.mkOr(acc, fwd);
} else {
// Otherwise check if next hop also is on the loop
BoolExpr peerOnLoop = onLoop.get(peer);
acc = ctx.mkOr(acc, ctx.mkAnd(fwd, peerOnLoop));
}
}
}
}
solver.add(ctx.mkEq(var, acc));
}
return onLoop.get(router);
}
use of com.microsoft.z3.Context 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 com.microsoft.z3.Context in project batfish by batfish.
the class PropertyChecker method addEnvironmentConstraints.
private void addEnvironmentConstraints(Encoder enc, EnvironmentType t) {
LogicalGraph lg = enc.getMainSlice().getLogicalGraph();
Context ctx = enc.getCtx();
switch(t) {
case ANY:
break;
case NONE:
for (SymbolicRoute vars : lg.getEnvironmentVars().values()) {
enc.add(ctx.mkNot(vars.getPermitted()));
}
break;
case SANE:
for (SymbolicRoute vars : lg.getEnvironmentVars().values()) {
enc.add(ctx.mkLe(vars.getMetric(), ctx.mkInt(50)));
}
break;
default:
break;
}
}
Aggregations