use of net.sf.javabdd.BDD in project batfish by batfish.
the class TransferBDD method ite.
private BDDRoute ite(BDD guard, BDDRoute r1, BDDRoute r2) {
BDDRoute ret = new BDDRoute(_comms);
BDDInteger x;
BDDInteger y;
// update integer values based on condition
// x = r1.getPrefixLength();
// y = r2.getPrefixLength();
// ret.getPrefixLength().setValue(ite(guard, x, y));
// x = r1.getIp();
// y = r2.getIp();
// ret.getIp().setValue(ite(guard, x, y));
x = r1.getAdminDist();
y = r2.getAdminDist();
ret.getAdminDist().setValue(ite(guard, x, y));
x = r1.getLocalPref();
y = r2.getLocalPref();
ret.getLocalPref().setValue(ite(guard, x, y));
x = r1.getMetric();
y = r2.getMetric();
ret.getMetric().setValue(ite(guard, x, y));
x = r1.getMed();
y = r2.getMed();
ret.getMed().setValue(ite(guard, x, y));
r1.getCommunities().forEach((c, var1) -> {
BDD var2 = r2.getCommunities().get(c);
ret.getCommunities().put(c, ite(guard, var1, var2));
});
return ret;
}
use of net.sf.javabdd.BDD in project batfish by batfish.
the class TransferBDD method compute.
/*
* Convert a Batfish AST boolean expression to a symbolic Z3 boolean expression
* by performing inlining of stateful side effects.
*/
private TransferResult<TransferReturn, BDD> compute(BooleanExpr expr, TransferParam<BDDRoute> p) {
// TODO: right now everything is IPV4
if (expr instanceof MatchIpv4) {
p.debug("MatchIpv4");
TransferReturn ret = new TransferReturn(p.getData(), factory.one());
p.debug("MatchIpv4 Result: " + ret);
return fromExpr(ret);
}
if (expr instanceof MatchIpv6) {
p.debug("MatchIpv6");
TransferReturn ret = new TransferReturn(p.getData(), factory.zero());
return fromExpr(ret);
}
if (expr instanceof Conjunction) {
p.debug("Conjunction");
Conjunction c = (Conjunction) expr;
BDD acc = factory.one();
TransferResult<TransferReturn, BDD> result = new TransferResult<>();
for (BooleanExpr be : c.getConjuncts()) {
TransferResult<TransferReturn, BDD> r = compute(be, p.indent());
acc = acc.and(r.getReturnValue().getSecond());
}
TransferReturn ret = new TransferReturn(p.getData(), acc);
p.debug("Conjunction return: " + acc);
return result.setReturnValue(ret);
}
if (expr instanceof Disjunction) {
p.debug("Disjunction");
Disjunction d = (Disjunction) expr;
BDD acc = factory.zero();
TransferResult<TransferReturn, BDD> result = new TransferResult<>();
for (BooleanExpr be : d.getDisjuncts()) {
TransferResult<TransferReturn, BDD> r = compute(be, p.indent());
result = result.addChangedVariables(r);
acc = acc.or(r.getReturnValue().getSecond());
}
TransferReturn ret = new TransferReturn(p.getData(), acc);
p.debug("Disjunction return: " + acc);
return result.setReturnValue(ret);
}
// TODO: thread the BDDRecord through calls
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) {
TransferReturn ret = new TransferReturn(p.getData(), factory.one());
return fromExpr(ret);
} else {
TransferResult<TransferReturn, BDD> result = new TransferResult<>();
TransferParam<BDDRoute> record = p;
BDD acc = factory.zero();
for (int i = conjuncts.size() - 1; i >= 0; i--) {
BooleanExpr conjunct = conjuncts.get(i);
TransferParam<BDDRoute> param = record.setDefaultPolicy(null).setChainContext(TransferParam.ChainContext.CONJUNCTION).indent();
TransferResult<TransferReturn, BDD> r = compute(conjunct, param);
record = record.setData(r.getReturnValue().getFirst());
acc = ite(r.getFallthroughValue(), acc, r.getReturnValue().getSecond());
}
TransferReturn ret = new TransferReturn(record.getData(), acc);
return result.setReturnValue(ret);
}
}
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) {
TransferReturn ret = new TransferReturn(p.getData(), factory.zero());
return fromExpr(ret);
} else {
TransferResult<TransferReturn, BDD> result = new TransferResult<>();
TransferParam<BDDRoute> record = p;
BDD acc = factory.zero();
for (int i = disjuncts.size() - 1; i >= 0; i--) {
BooleanExpr disjunct = disjuncts.get(i);
TransferParam<BDDRoute> param = record.setDefaultPolicy(null).setChainContext(TransferParam.ChainContext.CONJUNCTION).indent();
TransferResult<TransferReturn, BDD> r = compute(disjunct, param);
record = record.setData(r.getReturnValue().getFirst());
acc = ite(r.getFallthroughValue(), acc, r.getReturnValue().getSecond());
}
TransferReturn ret = new TransferReturn(record.getData(), acc);
return result.setReturnValue(ret);
}
}
if (expr instanceof Not) {
p.debug("mkNot");
Not n = (Not) expr;
TransferResult<TransferReturn, BDD> result = compute(n.getExpr(), p);
TransferReturn r = result.getReturnValue();
TransferReturn ret = new TransferReturn(r.getFirst(), r.getSecond().not());
return result.setReturnValue(ret);
}
if (expr instanceof MatchProtocol) {
MatchProtocol mp = (MatchProtocol) expr;
Protocol proto = Protocol.fromRoutingProtocol(mp.getProtocol());
if (proto == null) {
p.debug("MatchProtocol(" + mp.getProtocol().protocolName() + "): false");
TransferReturn ret = new TransferReturn(p.getData(), factory.zero());
return fromExpr(ret);
}
BDD protoMatch = p.getData().getProtocolHistory().value(proto);
p.debug("MatchProtocol(" + mp.getProtocol().protocolName() + "): " + protoMatch);
TransferReturn ret = new TransferReturn(p.getData(), protoMatch);
return fromExpr(ret);
}
if (expr instanceof MatchPrefixSet) {
p.debug("MatchPrefixSet");
MatchPrefixSet m = (MatchPrefixSet) expr;
BDD r = matchPrefixSet(p.indent(), _conf, m.getPrefixSet(), p.getData());
TransferReturn ret = new TransferReturn(p.getData(), r);
return fromExpr(ret);
// TODO: implement me
} else if (expr instanceof MatchPrefix6Set) {
p.debug("MatchPrefix6Set");
TransferReturn ret = new TransferReturn(p.getData(), factory.zero());
return fromExpr(ret);
} else if (expr instanceof CallExpr) {
p.debug("CallExpr");
CallExpr c = (CallExpr) expr;
String router = _conf.getName();
String name = c.getCalledPolicyName();
TransferResult<TransferReturn, BDD> r = CACHE.get(router, name);
if (r != null) {
return r;
}
RoutingPolicy pol = _conf.getRoutingPolicies().get(name);
p = p.setCallContext(TransferParam.CallContext.EXPR_CALL);
r = compute(pol.getStatements(), p.indent().enterScope(name));
CACHE.put(router, name, r);
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.deepCopy());
} else if (expr instanceof MatchCommunitySet) {
p.debug("MatchCommunitySet");
MatchCommunitySet mcs = (MatchCommunitySet) expr;
BDD c = matchCommunitySet(p.indent(), _conf, mcs.getExpr(), p.getData());
TransferReturn ret = new TransferReturn(p.getData(), c);
return fromExpr(ret);
} else if (expr instanceof BooleanExprs.StaticBooleanExpr) {
BooleanExprs.StaticBooleanExpr b = (BooleanExprs.StaticBooleanExpr) expr;
TransferReturn ret;
switch(b.getType()) {
case CallExprContext:
p.debug("CallExprContext");
BDD x1 = mkBDD(p.getCallContext() == TransferParam.CallContext.EXPR_CALL);
ret = new TransferReturn(p.getData(), x1);
return fromExpr(ret);
case CallStatementContext:
p.debug("CallStmtContext");
BDD x2 = mkBDD(p.getCallContext() == TransferParam.CallContext.STMT_CALL);
ret = new TransferReturn(p.getData(), x2);
return fromExpr(ret);
case True:
p.debug("True");
ret = new TransferReturn(p.getData(), factory.one());
return fromExpr(ret);
case False:
p.debug("False");
ret = new TransferReturn(p.getData(), factory.zero());
return fromExpr(ret);
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");
TransferReturn ret = new TransferReturn(p.getData(), factory.one());
return fromExpr(ret);
}
throw new BatfishException("TODO: compute expr transfer function: " + expr);
}
use of net.sf.javabdd.BDD in project batfish by batfish.
the class TransferBDD method isRelevantFor.
/*
* Check if a prefix range match is applicable for the packet destination
* Ip address, given the prefix length variable.
*
* Since aggregation is modelled separately, we assume that prefixLen
* is not modified, and thus will contain only the underlying variables:
* [var(0), ..., var(n)]
*/
private BDD isRelevantFor(BDDRoute record, PrefixRange range) {
Prefix p = range.getPrefix();
SubRange r = range.getLengthRange();
int len = p.getPrefixLength();
int lower = r.getStart();
int upper = r.getEnd();
BDD lowerBitsMatch = firstBitsEqual(record.getPrefix().getBitvec(), p, len);
BDD acc = factory.zero();
if (lower == 0 && upper == 32) {
acc = factory.one();
} else {
for (int i = lower; i <= upper; i++) {
BDD equalLen = record.getPrefixLength().value(i);
acc = acc.or(equalLen);
}
}
return acc.and(lowerBitsMatch);
}
use of net.sf.javabdd.BDD in project batfish by batfish.
the class TransferBDD method matchPrefixSet.
/*
* Converts a prefix set to a boolean expression.
*/
private BDD matchPrefixSet(TransferParam<BDDRoute> p, Configuration conf, PrefixSetExpr e, BDDRoute other) {
if (e instanceof ExplicitPrefixSet) {
ExplicitPrefixSet x = (ExplicitPrefixSet) e;
Set<PrefixRange> ranges = x.getPrefixSpace().getPrefixRanges();
if (ranges.isEmpty()) {
p.debug("empty");
return factory.one();
}
BDD acc = factory.zero();
for (PrefixRange range : ranges) {
p.debug("Prefix Range: " + range);
if (!PrefixUtils.isContainedBy(range.getPrefix(), _ignoredNetworks)) {
acc = acc.or(isRelevantFor(other, range));
}
}
return acc;
} else if (e instanceof NamedPrefixSet) {
NamedPrefixSet x = (NamedPrefixSet) e;
p.debug("Named: " + x.getName());
String name = x.getName();
RouteFilterList fl = conf.getRouteFilterLists().get(name);
return matchFilterList(p, fl, other);
} else {
throw new BatfishException("TODO: match prefix set: " + e);
}
}
use of net.sf.javabdd.BDD in project batfish by batfish.
the class TransferBDD method matchFilterList.
/*
* Converts a route filter list to a boolean expression.
*/
private BDD matchFilterList(TransferParam<BDDRoute> p, RouteFilterList x, BDDRoute other) {
BDD acc = factory.zero();
List<RouteFilterLine> lines = new ArrayList<>(x.getLines());
Collections.reverse(lines);
for (RouteFilterLine line : lines) {
Prefix pfx = line.getPrefix();
if (!PrefixUtils.isContainedBy(pfx, _ignoredNetworks)) {
SubRange r = line.getLengthRange();
PrefixRange range = new PrefixRange(pfx, r);
p.debug("Prefix Range: " + range);
p.debug("Action: " + line.getAction());
BDD matches = isRelevantFor(other, range);
BDD action = mkBDD(line.getAction() == LineAction.ACCEPT);
acc = ite(matches, action, acc);
}
}
return acc;
}
Aggregations