use of org.batfish.datamodel.routing_policy.RoutingPolicy in project batfish by batfish.
the class Optimizations method isDefaultBgpExport.
/*
* Determine if a BGP neighbor uses the default export policy
*/
private boolean isDefaultBgpExport(Configuration conf, BgpNeighbor n) {
// Check if valid neighbor
if (n == null || n.getExportPolicy() == null) {
return true;
}
// Ensure a single if statement
RoutingPolicy pol = conf.getRoutingPolicies().get(n.getExportPolicy());
List<Statement> stmts = pol.getStatements();
if (stmts.size() != 1) {
return false;
}
Statement s = stmts.get(0);
if (!(s instanceof If)) {
return false;
}
// Ensure that the true branch accepts and the false branch rejects
If i = (If) s;
BooleanExpr be = i.getGuard();
List<Statement> trueStmts = i.getTrueStatements();
List<Statement> falseStmts = i.getFalseStatements();
if (trueStmts.size() != 1 || falseStmts.size() != 1) {
return false;
}
Statement s1 = trueStmts.get(0);
Statement s2 = falseStmts.get(0);
if (!(s1 instanceof Statements.StaticStatement) || !(s2 instanceof Statements.StaticStatement)) {
return false;
}
Statements.StaticStatement x = (Statements.StaticStatement) s1;
Statements.StaticStatement y = (Statements.StaticStatement) s2;
if (x.getType() != Statements.ExitAccept || y.getType() != Statements.ExitReject) {
return false;
}
// Ensure condition just hands off to the common export policy
if (!(be instanceof CallExpr)) {
return false;
}
CallExpr ce = (CallExpr) be;
return ce.getCalledPolicyName().contains(Graph.BGP_COMMON_FILTER_LIST_NAME);
}
use of org.batfish.datamodel.routing_policy.RoutingPolicy in project batfish by batfish.
the class Optimizations method computeCanMergeImportExportVars.
/*
* Determine when import and export variables can be merged along an edge.
* This will be safe when there is no peer-specific import filter
*/
private void computeCanMergeImportExportVars() {
_encoderSlice.getGraph().getConfigurations().forEach((router, conf) -> {
Map<Protocol, List<GraphEdge>> map = new HashMap<>();
_sliceCanCombineImportExportVars.put(router, map);
for (Protocol proto : getProtocols().get(router)) {
List<GraphEdge> edges = new ArrayList<>();
if (Optimizations.ENABLE_IMPORT_EXPORT_MERGE_OPTIMIZATION && !proto.isConnected() && !proto.isStatic() && !proto.isOspf()) {
for (GraphEdge ge : _encoderSlice.getGraph().getEdgeMap().get(router)) {
// Don't merge when an abstract edge is used.
boolean safeMergeEdge = _encoderSlice.getGraph().isEdgeUsed(conf, proto, ge) && !ge.isAbstract();
// Don't merge when bgp internal/external can differ
boolean sameInternal = (ge.getPeer() == null) || (_needBgpInternal.contains(router) == _needBgpInternal.contains(ge.getPeer()));
// Check if there are any local modifications on import
boolean isPure = true;
RoutingPolicy pol = _encoderSlice.getGraph().findImportRoutingPolicy(router, proto, ge);
if (pol != null) {
isPure = false;
}
boolean noFailures = _encoderSlice.getEncoder().getFailures() == 0;
if (safeMergeEdge && sameInternal && isPure && noFailures && hasExportVariables(ge, proto)) {
edges.add(ge);
}
}
}
map.put(proto, edges);
}
});
}
use of org.batfish.datamodel.routing_policy.RoutingPolicy 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 org.batfish.datamodel.routing_policy.RoutingPolicy in project batfish by batfish.
the class VyosConfiguration method convertRouteMaps.
private void convertRouteMaps() {
for (Entry<String, RouteMap> e : _routeMaps.entrySet()) {
String name = e.getKey();
RouteMap routeMap = e.getValue();
RoutingPolicy rp = toRoutingPolicy(routeMap);
_c.getRoutingPolicies().put(name, rp);
}
}
use of org.batfish.datamodel.routing_policy.RoutingPolicy in project batfish by batfish.
the class VyosConfiguration method toRoutingPolicy.
private RoutingPolicy toRoutingPolicy(RouteMap routeMap) {
String name = routeMap.getName();
RoutingPolicy routingPolicy = new RoutingPolicy(name, _c);
List<Statement> statements = routingPolicy.getStatements();
for (Entry<Integer, RouteMapRule> e : routeMap.getRules().entrySet()) {
String ruleName = Integer.toString(e.getKey());
RouteMapRule rule = e.getValue();
If ifStatement = new If();
List<Statement> trueStatements = ifStatement.getTrueStatements();
ifStatement.setComment(ruleName);
Conjunction conj = new Conjunction();
for (RouteMapMatch match : rule.getMatches()) {
conj.getConjuncts().add(match.toBooleanExpr(this, _c, _w));
}
ifStatement.setGuard(conj.simplify());
switch(rule.getAction()) {
case ACCEPT:
trueStatements.add(Statements.ExitAccept.toStaticStatement());
break;
case REJECT:
trueStatements.add(Statements.ExitReject.toStaticStatement());
break;
default:
throw new BatfishException("Invalid action");
}
statements.add(ifStatement);
}
statements.add(Statements.ExitReject.toStaticStatement());
return routingPolicy;
}
Aggregations