use of com.microsoft.z3.Expr in project batfish by batfish.
the class SymbolicRoute method addExprs.
// TODO: depends on configuration
/*
* Check if a particular protocol on a router is configured
* to use multipath routing or not.
*/
/* private boolean isMultipath(String router, Protocol proto, boolean isIbgp) {
Configuration conf = _enc.getGraph().getConfigurations().get(router);
if (proto.isConnected()) {
return true;
} else if (proto.isStatic()) {
return true;
} else if (proto.isOspf()) {
return true;
} else if (proto.isBgp()) {
BgpProcess p = conf.getDefaultVrf().getBgpProcess();
if (isIbgp) {
return p.getMultipathIbgp();
} else {
return p.getMultipathEbgp();
}
} else {
return true;
}
} */
private void addExprs(EncoderSlice enc) {
Map<String, Expr> all = enc.getAllVariables();
all.put(_permitted.toString(), _permitted);
if (_adminDist != null) {
all.put(_adminDist.toString(), _adminDist);
}
if (_med != null) {
all.put(_med.toString(), _med);
}
if (_localPref != null) {
all.put(_localPref.toString(), _localPref);
}
if (_metric != null) {
all.put(_metric.toString(), _metric);
}
if (_prefixLength != null) {
all.put(_prefixLength.toString(), _prefixLength);
}
if (_routerId != null) {
all.put(_routerId.toString(), _routerId);
}
if (_bgpInternal != null) {
all.put(_bgpInternal.toString(), _bgpInternal);
}
if (_ospfArea != null) {
all.put(_ospfArea.getBitVec().toString(), _ospfArea.getBitVec());
}
if (_ospfType != null) {
all.put(_ospfType.getBitVec().toString(), _ospfType.getBitVec());
}
if (_clientId != null) {
all.put(_clientId.getBitVec().toString(), _clientId.getBitVec());
}
if (_igpMetric != null) {
all.put(_igpMetric.toString(), _igpMetric);
}
for (BoolExpr var : _communities.values()) {
all.put(var.toString(), var);
}
}
use of com.microsoft.z3.Expr in project batfish by batfish.
the class TransferSSA method compute.
/*
* Convert a list of statements into a Z3 boolean expression for the transfer function.
*/
private TransferResult<BoolExpr, BoolExpr> compute(List<Statement> statements, TransferParam<SymbolicRoute> p, TransferResult<BoolExpr, BoolExpr> result) {
boolean doesReturn = false;
for (Statement stmt : statements) {
if (stmt instanceof StaticStatement) {
StaticStatement ss = (StaticStatement) stmt;
switch(ss.getType()) {
case ExitAccept:
doesReturn = true;
p.debug("ExitAccept");
result = returnValue(p, result, true);
break;
case ReturnTrue:
doesReturn = true;
p.debug("ReturnTrue");
result = returnValue(p, result, true);
break;
case ExitReject:
doesReturn = true;
p.debug("ExitReject");
result = returnValue(p, result, false);
break;
case ReturnFalse:
doesReturn = true;
p.debug("ReturnFalse");
result = returnValue(p, result, false);
break;
case SetDefaultActionAccept:
p.debug("SetDefaulActionAccept");
p = p.setDefaultAccept(true);
break;
case SetDefaultActionReject:
p.debug("SetDefaultActionReject");
p = p.setDefaultAccept(false);
break;
case SetLocalDefaultActionAccept:
p.debug("SetLocalDefaultActionAccept");
p = p.setDefaultAcceptLocal(true);
break;
case SetLocalDefaultActionReject:
p.debug("SetLocalDefaultActionReject");
p = p.setDefaultAcceptLocal(false);
break;
case ReturnLocalDefaultAction:
p.debug("ReturnLocalDefaultAction");
// TODO: need to set local default action in an environment
if (p.getDefaultAcceptLocal()) {
result = returnValue(p, result, true);
} else {
result = returnValue(p, result, false);
}
break;
case FallThrough:
p.debug("Fallthrough");
result = fallthrough(p, result);
break;
case Return:
// TODO: assumming this happens at the end of the function, so it is ignored for now.
p.debug("Return");
break;
case RemovePrivateAs:
p.debug("RemovePrivateAs");
System.out.println("Warning: use of unimplemented feature RemovePrivateAs");
break;
default:
throw new BatfishException("TODO: computeTransferFunction: " + ss.getType());
}
} else if (stmt instanceof If) {
p.debug("If");
If i = (If) stmt;
TransferResult<BoolExpr, BoolExpr> r = compute(i.getGuard(), p);
result = result.addChangedVariables(r);
BoolExpr guard = (BoolExpr) r.getReturnValue().simplify();
String str = guard.toString();
// If there are updates in the guard, add them to the parameter p before entering branches
for (Pair<String, Expr> changed : r.getChangedVariables()) {
p.debug("CHANGED: " + changed.getFirst());
updateSingleValue(p, changed.getFirst(), changed.getSecond());
}
p.debug("guard: " + str);
// If we know the branch ahead of time, then specialize
switch(str) {
case "true":
p.debug("True Branch");
result = compute(i.getTrueStatements(), p.indent(), result);
break;
case "false":
p.debug("False Branch");
compute(i.getFalseStatements(), p.indent(), result);
break;
default:
p.debug("True Branch");
// clear changed variables before proceeding
TransferParam<SymbolicRoute> p1 = p.indent().setData(p.getData().copy());
TransferParam<SymbolicRoute> p2 = p.indent().setData(p.getData().copy());
TransferResult<BoolExpr, BoolExpr> trueBranch = compute(i.getTrueStatements(), p1, initialResult());
p.debug("False Branch");
TransferResult<BoolExpr, BoolExpr> falseBranch = compute(i.getFalseStatements(), p2, initialResult());
p.debug("JOIN");
PList<Pair<String, Pair<Expr, Expr>>> pairs = trueBranch.mergeChangedVariables(falseBranch);
// Extract and deal with the return value first so that other
// variables have this reflected in their value
int idx = pairs.find(pair -> pair.getFirst().equals("RETURN"));
if (idx >= 0) {
Pair<String, Pair<Expr, Expr>> ret = pairs.get(idx);
pairs = pairs.minus(idx);
pairs = pairs.plus(pairs.size(), ret);
}
for (Pair<String, Pair<Expr, Expr>> pair : pairs) {
String s = pair.getFirst();
p.debug("CHANGED: " + s);
Pair<Expr, Expr> x = joinPoint(p, result, guard, pair);
result = result.addChangedVariable(s, x.getFirst());
if (s.equals("RETURN")) {
result = result.setReturnValue((BoolExpr) x.getFirst()).setReturnAssignedValue((BoolExpr) x.getSecond());
}
if (s.equals("FALLTHROUGH")) {
result = result.setFallthroughValue((BoolExpr) x.getFirst()).setReturnAssignedValue((BoolExpr) x.getSecond());
}
}
break;
}
} else if (stmt instanceof SetDefaultPolicy) {
p.debug("SetDefaultPolicy");
p = p.setDefaultPolicy((SetDefaultPolicy) stmt);
} else if (stmt instanceof SetMetric) {
p.debug("SetMetric");
// TODO: what is the semantics for BGP? Is this MED?
if (!_current.getProto().isBgp()) {
SetMetric sm = (SetMetric) stmt;
LongExpr ie = sm.getMetric();
ArithExpr newValue = applyLongExprModification(p.getData().getMetric(), ie);
newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getMetric(), newValue);
ArithExpr x = createArithVariableWith(p, "METRIC", newValue);
p.getData().setMetric(x);
result = result.addChangedVariable("METRIC", x);
}
} else if (stmt instanceof SetOspfMetricType) {
p.debug("SetOspfMetricType");
SetOspfMetricType somt = (SetOspfMetricType) stmt;
OspfMetricType mt = somt.getMetricType();
SymbolicOspfType t;
if (mt == OspfMetricType.E1) {
t = new SymbolicOspfType(_enc, OspfType.E1);
} else {
t = new SymbolicOspfType(_enc, OspfType.E2);
}
BitVecExpr newValue = t.getBitVec();
newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getOspfType().getBitVec(), newValue);
BitVecExpr x = createBitVecVariableWith(p, "OSPF-TYPE", 2, newValue);
p.getData().getOspfType().setBitVec(x);
result = result.addChangedVariable("OSPF-TYPE", x);
} else if (stmt instanceof SetLocalPreference) {
p.debug("SetLocalPreference");
SetLocalPreference slp = (SetLocalPreference) stmt;
IntExpr ie = slp.getLocalPreference();
ArithExpr newValue = applyIntExprModification(p.getData().getLocalPref(), ie);
newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getLocalPref(), newValue);
ArithExpr x = createArithVariableWith(p, "LOCAL-PREF", newValue);
p.getData().setLocalPref(x);
result = result.addChangedVariable("LOCAL-PREF", x);
} else if (stmt instanceof AddCommunity) {
p.debug("AddCommunity");
AddCommunity ac = (AddCommunity) stmt;
Set<CommunityVar> comms = _enc.getGraph().findAllCommunities(_conf, ac.getExpr());
for (CommunityVar cvar : comms) {
BoolExpr newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getCommunities().get(cvar), _enc.mkTrue());
BoolExpr x = createBoolVariableWith(p, cvar.getValue(), newValue);
p.getData().getCommunities().put(cvar, x);
result = result.addChangedVariable(cvar.getValue(), x);
}
} else if (stmt instanceof SetCommunity) {
p.debug("SetCommunity");
SetCommunity sc = (SetCommunity) stmt;
Set<CommunityVar> comms = _enc.getGraph().findAllCommunities(_conf, sc.getExpr());
for (CommunityVar cvar : comms) {
BoolExpr newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getCommunities().get(cvar), _enc.mkTrue());
BoolExpr x = createBoolVariableWith(p, cvar.getValue(), newValue);
p.getData().getCommunities().put(cvar, x);
result = result.addChangedVariable(cvar.getValue(), x);
}
} else if (stmt instanceof DeleteCommunity) {
p.debug("DeleteCommunity");
DeleteCommunity ac = (DeleteCommunity) stmt;
Set<CommunityVar> comms = _enc.getGraph().findAllCommunities(_conf, ac.getExpr());
Set<CommunityVar> toDelete = new HashSet<>();
// Find comms to delete
for (CommunityVar cvar : comms) {
if (cvar.getType() == Type.REGEX) {
toDelete.addAll(_enc.getCommunityDependencies().get(cvar));
} else {
toDelete.add(cvar);
}
}
// Delete each community
for (CommunityVar cvar : toDelete) {
BoolExpr newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getCommunities().get(cvar), _enc.mkFalse());
BoolExpr x = createBoolVariableWith(p, cvar.getValue(), newValue);
p.getData().getCommunities().put(cvar, x);
result = result.addChangedVariable(cvar.getValue(), x);
}
} else if (stmt instanceof RetainCommunity) {
p.debug("RetainCommunity");
// no op
} else if (stmt instanceof PrependAsPath) {
p.debug("PrependAsPath");
PrependAsPath pap = (PrependAsPath) stmt;
Integer prependCost = prependLength(pap.getExpr());
ArithExpr newValue = _enc.mkSum(p.getData().getMetric(), _enc.mkInt(prependCost));
newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getMetric(), newValue);
ArithExpr x = createArithVariableWith(p, "METRIC", newValue);
p.getData().setMetric(x);
result = result.addChangedVariable("METRIC", x);
} else if (stmt instanceof SetOrigin) {
p.debug("SetOrigin");
System.out.println("Warning: use of unimplemented feature SetOrigin");
} else if (stmt instanceof SetNextHop) {
p.debug("SetNextHop");
System.out.println("Warning: use of unimplemented feature SetNextHop");
} else {
String s = (_isExport ? "export" : "import");
String msg = String.format("Unimplemented feature %s for %s transfer function on interface %s", stmt.toString(), s, _graphEdge.toString());
throw new BatfishException(msg);
}
}
// If this is the outermost call, then we relate the variables
if (p.getInitialCall()) {
p.debug("InitialCall finalizing");
// Apply the default action
if (!doesReturn) {
p.debug("Applying default action: " + p.getDefaultAccept());
if (p.getDefaultAccept()) {
result = returnValue(p, result, true);
} else {
result = returnValue(p, result, false);
}
}
BoolExpr related = relateVariables(p, result);
BoolExpr retValue = _enc.mkIf(result.getReturnValue(), related, _enc.mkNot(_current.getPermitted()));
result = result.setReturnValue(retValue);
}
return result;
}
use of com.microsoft.z3.Expr in project batfish by batfish.
the class TransferSSA method compute.
/*
* Convert a Batfish AST boolean expression to a symbolic Z3 boolean expression
* by performing inlining of stateful side effects.
*/
private TransferResult<BoolExpr, BoolExpr> compute(BooleanExpr expr, TransferParam<SymbolicRoute> p) {
// TODO: right now everything is IPV4
if (expr instanceof MatchIpv4) {
p.debug("MatchIpv4");
return fromExpr(_enc.mkTrue());
}
if (expr instanceof MatchIpv6) {
p.debug("MatchIpv6");
return fromExpr(_enc.mkFalse());
}
if (expr instanceof Conjunction) {
p.debug("Conjunction");
Conjunction c = (Conjunction) expr;
BoolExpr acc = _enc.mkTrue();
TransferResult<BoolExpr, BoolExpr> result = new TransferResult<>();
for (BooleanExpr be : c.getConjuncts()) {
TransferResult<BoolExpr, BoolExpr> r = compute(be, p.indent());
result = result.addChangedVariables(r);
acc = _enc.mkAnd(acc, r.getReturnValue());
}
p.debug("has changed variable");
return result.setReturnValue(acc);
}
if (expr instanceof Disjunction) {
p.debug("Disjunction");
Disjunction d = (Disjunction) expr;
BoolExpr acc = _enc.mkFalse();
TransferResult<BoolExpr, BoolExpr> result = new TransferResult<>();
for (BooleanExpr be : d.getDisjuncts()) {
TransferResult<BoolExpr, BoolExpr> r = compute(be, p.indent());
result = result.addChangedVariables(r);
acc = _enc.mkOr(acc, r.getReturnValue());
}
p.debug("has changed variable");
return result.setReturnValue(acc);
}
if (expr instanceof ConjunctionChain) {
p.debug("ConjunctionChain");
ConjunctionChain d = (ConjunctionChain) expr;
List<BooleanExpr> conjuncts = new ArrayList<>(d.getSubroutines());
if (p.getDefaultPolicy() != null) {
BooleanExpr be = new CallExpr(p.getDefaultPolicy().getDefaultPolicy());
conjuncts.add(be);
}
if (conjuncts.size() == 0) {
return fromExpr(_enc.mkTrue());
} else {
TransferResult<BoolExpr, BoolExpr> result = new TransferResult<>();
BoolExpr acc = _enc.mkFalse();
for (int i = conjuncts.size() - 1; i >= 0; i--) {
BooleanExpr conjunct = conjuncts.get(i);
TransferParam<SymbolicRoute> param = p.setDefaultPolicy(null).setChainContext(TransferParam.ChainContext.CONJUNCTION);
TransferResult<BoolExpr, BoolExpr> r = compute(conjunct, param);
result = result.addChangedVariables(r);
acc = _enc.mkIf(r.getFallthroughValue(), acc, r.getReturnValue());
}
p.debug("ConjunctionChain Result: " + acc);
return result.setReturnValue(acc);
}
}
if (expr instanceof DisjunctionChain) {
p.debug("DisjunctionChain");
DisjunctionChain d = (DisjunctionChain) expr;
List<BooleanExpr> disjuncts = new ArrayList<>(d.getSubroutines());
if (p.getDefaultPolicy() != null) {
BooleanExpr be = new CallExpr(p.getDefaultPolicy().getDefaultPolicy());
disjuncts.add(be);
}
if (disjuncts.size() == 0) {
return fromExpr(_enc.mkTrue());
} else {
TransferResult<BoolExpr, BoolExpr> result = new TransferResult<>();
BoolExpr acc = _enc.mkFalse();
for (int i = disjuncts.size() - 1; i >= 0; i--) {
BooleanExpr disjunct = disjuncts.get(i);
TransferParam<SymbolicRoute> param = p.setDefaultPolicy(null).setChainContext(TransferParam.ChainContext.CONJUNCTION);
TransferResult<BoolExpr, BoolExpr> r = compute(disjunct, param);
result.addChangedVariables(r);
acc = _enc.mkIf(r.getFallthroughValue(), acc, r.getReturnValue());
}
p.debug("DisjunctionChain Result: " + acc);
return result.setReturnValue(acc);
}
}
if (expr instanceof Not) {
p.debug("mkNot");
Not n = (Not) expr;
TransferResult<BoolExpr, BoolExpr> result = compute(n.getExpr(), p);
return result.setReturnValue(_enc.mkNot(result.getReturnValue()));
}
if (expr instanceof MatchProtocol) {
MatchProtocol mp = (MatchProtocol) expr;
Protocol proto = Protocol.fromRoutingProtocol(mp.getProtocol());
if (proto == null) {
p.debug("MatchProtocol(" + mp.getProtocol().protocolName() + "): false");
return fromExpr(_enc.mkFalse());
}
if (_other.getProtocolHistory() == null) {
BoolExpr protoMatch = _enc.mkBool(proto.equals(_proto));
p.debug("MatchProtocol(" + mp.getProtocol().protocolName() + "): " + protoMatch);
return fromExpr(protoMatch);
}
BoolExpr protoMatch = _other.getProtocolHistory().checkIfValue(proto);
p.debug("MatchProtocol(" + mp.getProtocol().protocolName() + "): " + protoMatch);
return fromExpr(protoMatch);
}
if (expr instanceof MatchPrefixSet) {
p.debug("MatchPrefixSet");
MatchPrefixSet m = (MatchPrefixSet) expr;
// For BGP, may change prefix length
TransferResult<BoolExpr, BoolExpr> result = matchPrefixSet(_conf, m.getPrefixSet(), p.getData());
return result.setReturnAssignedValue(_enc.mkTrue());
// TODO: implement me
} else if (expr instanceof MatchPrefix6Set) {
p.debug("MatchPrefix6Set");
return fromExpr(_enc.mkFalse());
} else if (expr instanceof CallExpr) {
p.debug("CallExpr");
// TODO: the call can modify certain fields, need to keep track of these variables
CallExpr c = (CallExpr) expr;
String name = c.getCalledPolicyName();
RoutingPolicy pol = _conf.getRoutingPolicies().get(name);
p = p.setCallContext(TransferParam.CallContext.EXPR_CALL);
TransferResult<BoolExpr, BoolExpr> r = compute(pol.getStatements(), p.indent().enterScope(name), initialResult());
p.debug("CallExpr (return): " + r.getReturnValue());
p.debug("CallExpr (fallthrough): " + r.getFallthroughValue());
return r;
} else if (expr instanceof WithEnvironmentExpr) {
p.debug("WithEnvironmentExpr");
// TODO: this is not correct
WithEnvironmentExpr we = (WithEnvironmentExpr) expr;
// TODO: postStatements() and preStatements()
return compute(we.getExpr(), p);
} else if (expr instanceof MatchCommunitySet) {
p.debug("MatchCommunitySet");
MatchCommunitySet mcs = (MatchCommunitySet) expr;
return fromExpr(matchCommunitySet(_conf, mcs.getExpr(), p.getData()));
} else if (expr instanceof BooleanExprs.StaticBooleanExpr) {
BooleanExprs.StaticBooleanExpr b = (BooleanExprs.StaticBooleanExpr) expr;
switch(b.getType()) {
case CallExprContext:
p.debug("CallExprContext");
return fromExpr(_enc.mkBool(p.getCallContext() == TransferParam.CallContext.EXPR_CALL));
case CallStatementContext:
p.debug("CallStmtContext");
return fromExpr(_enc.mkBool(p.getCallContext() == TransferParam.CallContext.STMT_CALL));
case True:
p.debug("True");
return fromExpr(_enc.mkTrue());
case False:
p.debug("False");
return fromExpr(_enc.mkFalse());
default:
throw new BatfishException("Unhandled " + BooleanExprs.class.getCanonicalName() + ": " + b.getType());
}
} else if (expr instanceof MatchAsPath) {
p.debug("MatchAsPath");
System.out.println("Warning: use of unimplemented feature MatchAsPath");
return fromExpr(_enc.mkFalse());
}
String s = (_isExport ? "export" : "import");
String msg = String.format("Unimplemented feature %s for %s transfer function on interface %s", expr.toString(), s, _graphEdge.toString());
throw new BatfishException(msg);
}
use of com.microsoft.z3.Expr in project batfish by batfish.
the class TransferResult method mergeChangedVariables.
// TODO: this really needs to use persistent set data types
public PList<Pair<String, Pair<Expr, Expr>>> mergeChangedVariables(TransferResult<U, T> other) {
Set<String> seen = new HashSet<>();
PList<Pair<String, Pair<Expr, Expr>>> vars = PList.empty();
for (Pair<String, Expr> cv1 : this._changedVariables) {
String s = cv1.getFirst();
Expr x = cv1.getSecond();
if (!seen.contains(s)) {
seen.add(s);
Expr e = find(other._changedVariables, s);
Pair<Expr, Expr> pair = new Pair<>(x, e);
vars = vars.plus(new Pair<>(s, pair));
}
}
for (Pair<String, Expr> cv1 : other._changedVariables) {
String s = cv1.getFirst();
Expr x = cv1.getSecond();
if (!seen.contains(s)) {
seen.add(s);
Expr e = find(this._changedVariables, s);
// preserve order
Pair<Expr, Expr> pair = new Pair<>(e, x);
vars = vars.plus(new Pair<>(s, pair));
}
}
return vars;
}
use of com.microsoft.z3.Expr in project batfish by batfish.
the class VerificationResult method debug.
public void debug(EncoderSlice enc, boolean showConstraints, String filter) {
if (showConstraints) {
System.out.println("================= Constraints ==================");
for (BoolExpr be : enc.getSolver().getAssertions()) {
String x = be.simplify().toString();
if (filter == null || x.contains(filter)) {
System.out.println(x);
}
}
}
if (_verified) {
System.out.println("verified");
} else {
System.out.println("================= Model ================");
enc.getSymbolicDecisions().getDataForwarding().forEach((router, map) -> map.forEach((edge, e) -> {
String expr = e.toString();
if (expr.contains("DATA-")) {
String result = _model.get(expr);
if ("true".equals(result)) {
System.out.println(edge);
}
}
}));
System.out.println("");
_model.forEach((var, val) -> {
if (filter == null || var.contains(filter)) {
System.out.println(var + "=" + val);
}
});
}
if (enc.getUnsatCore().getDoTrack()) {
System.out.println("================= Unsat Core ================");
for (BoolExpr be : enc.getSolver().getUnsatCore()) {
BoolExpr constraint = enc.getUnsatCore().getTrackingVars().get(be.toString());
System.out.println("Var: " + be);
System.out.println(constraint);
System.out.println("");
}
}
}
Aggregations