use of org.batfish.symbolic.CommunityVar in project batfish by batfish.
the class PropertyChecker method checkLocalEquivalence.
/*
* Computes whether or not two routers are equivalent.
* To be equivalent, each router must have identical intefaces.
*
* We then relate the environments on each interface for each router
* so that they are required to be equal.
*
* We finally check that their forwarding decisions and exported messages
* will be equal given their equal inputs.
*/
public AnswerElement checkLocalEquivalence(Pattern n, boolean strict, boolean fullModel) {
Graph graph = new Graph(_batfish);
List<String> routers = PatternUtils.findMatchingNodes(graph, n, Pattern.compile(""));
HeaderQuestion q = new HeaderQuestion();
q.setFullModel(fullModel);
q.setFailures(0);
q.setBaseEnvironmentType(EnvironmentType.ANY);
Collections.sort(routers);
SortedMap<String, VerificationResult> result = new TreeMap<>();
int len = routers.size();
if (len <= 1) {
return new SmtManyAnswerElement(new TreeMap<>());
}
for (int i = 0; i < len - 1; i++) {
String r1 = routers.get(i);
String r2 = routers.get(i + 1);
// TODO: reorder to encode after checking if we can compare them
// Create transfer function for router 1
Set<String> toModel1 = new TreeSet<>();
toModel1.add(r1);
Graph g1 = new Graph(_batfish, null, toModel1);
Encoder e1 = new Encoder(_settings, g1, q);
e1.computeEncoding();
Context ctx = e1.getCtx();
// Create transfer function for router 2
Set<String> toModel2 = new TreeSet<>();
toModel2.add(r2);
Graph g2 = new Graph(_batfish, null, toModel2);
Encoder e2 = new Encoder(e1, g2);
e2.computeEncoding();
EncoderSlice slice1 = e1.getMainSlice();
EncoderSlice slice2 = e2.getMainSlice();
// Ensure that the two routers have the same interfaces for comparison
Pattern p = Pattern.compile(".*");
Pattern neg = Pattern.compile("");
List<GraphEdge> edges1 = PatternUtils.findMatchingEdges(g1, p, neg, p, neg);
List<GraphEdge> edges2 = PatternUtils.findMatchingEdges(g2, p, neg, p, neg);
Set<String> ifaces1 = interfaces(edges1);
Set<String> ifaces2 = interfaces(edges2);
if (!(ifaces1.containsAll(ifaces2) && ifaces2.containsAll(ifaces1))) {
String msg = String.format("Routers %s and %s have different interfaces", r1, r2);
System.out.println(msg);
return new SmtManyAnswerElement(new TreeMap<>());
}
// TODO: check running same protocols?
Map<String, Map<Protocol, Map<String, EnumMap<EdgeType, LogicalEdge>>>> lgeMap2 = logicalEdgeMap(slice2);
BoolExpr equalEnvs = ctx.mkBool(true);
BoolExpr equalOutputs = ctx.mkBool(true);
BoolExpr equalIncomingAcls = ctx.mkBool(true);
Configuration conf1 = g1.getConfigurations().get(r1);
Configuration conf2 = g2.getConfigurations().get(r2);
// Set environments equal
Set<String> communities = new HashSet<>();
Set<SymbolicRoute> envRecords = new HashSet<>();
for (Protocol proto1 : slice1.getProtocols().get(r1)) {
for (ArrayList<LogicalEdge> es : slice1.getLogicalGraph().getLogicalEdges().get(r1).get(proto1)) {
for (LogicalEdge lge1 : es) {
String ifaceName = lge1.getEdge().getStart().getName();
LogicalEdge lge2 = lgeMap2.get(r2).get(proto1).get(ifaceName).get(lge1.getEdgeType());
if (lge1.getEdgeType() == EdgeType.IMPORT) {
SymbolicRoute vars1 = slice1.getLogicalGraph().getEnvironmentVars().get(lge1);
SymbolicRoute vars2 = slice2.getLogicalGraph().getEnvironmentVars().get(lge2);
BoolExpr aclIn1 = slice1.getIncomingAcls().get(lge1.getEdge());
BoolExpr aclIn2 = slice2.getIncomingAcls().get(lge2.getEdge());
if (aclIn1 == null) {
aclIn1 = ctx.mkBool(true);
}
if (aclIn2 == null) {
aclIn2 = ctx.mkBool(true);
}
equalIncomingAcls = ctx.mkAnd(equalIncomingAcls, ctx.mkEq(aclIn1, aclIn2));
boolean hasEnv1 = (vars1 != null);
boolean hasEnv2 = (vars2 != null);
if (hasEnv1 && hasEnv2) {
BoolExpr samePermitted = ctx.mkEq(vars1.getPermitted(), vars2.getPermitted());
// Set communities equal
BoolExpr equalComms = e1.mkTrue();
for (Map.Entry<CommunityVar, BoolExpr> entry : vars1.getCommunities().entrySet()) {
CommunityVar cvar = entry.getKey();
BoolExpr ce1 = entry.getValue();
BoolExpr ce2 = vars2.getCommunities().get(cvar);
if (ce2 != null) {
equalComms = e1.mkAnd(equalComms, e1.mkEq(ce1, ce2));
}
}
// Set communities belonging to one but not the other
// off, but give a warning of the difference
BoolExpr unsetComms = e1.mkTrue();
for (Map.Entry<CommunityVar, BoolExpr> entry : vars1.getCommunities().entrySet()) {
CommunityVar cvar = entry.getKey();
BoolExpr ce1 = entry.getValue();
BoolExpr ce2 = vars2.getCommunities().get(cvar);
if (ce2 == null) {
if (!communities.contains(cvar.getValue())) {
communities.add(cvar.getValue());
/* String msg =
String.format(
"Warning: community %s found for router %s but not %s.",
cvar.getValue(), conf1.getEnvName(), conf2.getEnvName());
System.out.println(msg); */
}
unsetComms = e1.mkAnd(unsetComms, e1.mkNot(ce1));
}
}
// Do the same thing for communities missing from the other side
for (Map.Entry<CommunityVar, BoolExpr> entry : vars2.getCommunities().entrySet()) {
CommunityVar cvar = entry.getKey();
BoolExpr ce2 = entry.getValue();
BoolExpr ce1 = vars1.getCommunities().get(cvar);
if (ce1 == null) {
if (!communities.contains(cvar.getValue())) {
communities.add(cvar.getValue());
/* String msg =
String.format(
"Warning: community %s found for router %s but not %s.",
cvar.getValue(), conf2.getEnvName(), conf1.getEnvName());
System.out.println(msg); */
}
unsetComms = e1.mkAnd(unsetComms, e1.mkNot(ce2));
}
}
envRecords.add(vars1);
BoolExpr equalVars = slice1.equal(conf1, proto1, vars1, vars2, lge1, true);
equalEnvs = ctx.mkAnd(equalEnvs, unsetComms, samePermitted, equalVars, equalComms);
} else if (hasEnv1 || hasEnv2) {
System.out.println("Edge1: " + lge1);
System.out.println("Edge2: " + lge2);
throw new BatfishException("one had environment");
}
} else {
SymbolicRoute out1 = lge1.getSymbolicRecord();
SymbolicRoute out2 = lge2.getSymbolicRecord();
equalOutputs = ctx.mkAnd(equalOutputs, slice1.equal(conf1, proto1, out1, out2, lge1, false));
}
}
}
}
// check the stronger version of local equivalence
if (strict) {
for (SymbolicRoute env1 : envRecords) {
for (SymbolicRoute env2 : envRecords) {
if (!env1.equals(env2)) {
BoolExpr c = e2.mkImplies(env1.getPermitted(), e2.mkNot(env2.getPermitted()));
e2.add(c);
}
}
}
}
// TODO: check both have same environment vars (e.g., screw up configuring peer connection)
// Create assumptions
BoolExpr validDest;
validDest = ignoredDestinations(ctx, slice1, r1, conf1);
validDest = ctx.mkAnd(validDest, ignoredDestinations(ctx, slice2, r2, conf2));
SymbolicPacket p1 = slice1.getSymbolicPacket();
SymbolicPacket p2 = slice2.getSymbolicPacket();
BoolExpr equalPackets = p1.mkEqual(p2);
BoolExpr assumptions = ctx.mkAnd(equalEnvs, equalPackets, validDest);
// Create the requirements
// Best choices should be the same
BoolExpr required;
if (strict) {
SymbolicRoute best1 = e1.getMainSlice().getSymbolicDecisions().getBestNeighbor().get(conf1.getName());
SymbolicRoute best2 = e2.getMainSlice().getSymbolicDecisions().getBestNeighbor().get(conf2.getName());
// Just pick some protocol for defaults, shouldn't matter for best choice
required = equal(e2, conf2, best1, best2);
} else {
// Forwarding decisions should be the sames
Map<String, GraphEdge> geMap2 = interfaceMap(edges2);
BoolExpr sameForwarding = ctx.mkBool(true);
for (GraphEdge ge1 : edges1) {
GraphEdge ge2 = geMap2.get(ge1.getStart().getName());
BoolExpr dataFwd1 = slice1.getSymbolicDecisions().getDataForwarding().get(r1, ge1);
BoolExpr dataFwd2 = slice2.getSymbolicDecisions().getDataForwarding().get(r2, ge2);
assert (dataFwd1 != null);
assert (dataFwd2 != null);
sameForwarding = ctx.mkAnd(sameForwarding, ctx.mkEq(dataFwd1, dataFwd2));
}
// equalOutputs, equalIncomingAcls);
required = ctx.mkAnd(sameForwarding);
}
e2.add(assumptions);
e2.add(ctx.mkNot(required));
VerificationResult res = e2.verify().getFirst();
String name = r1 + "<-->" + r2;
result.put(name, res);
}
return new SmtManyAnswerElement(result);
}
use of org.batfish.symbolic.CommunityVar 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 org.batfish.symbolic.CommunityVar in project batfish by batfish.
the class TransferSSA method matchCommunitySet.
/*
* Converts a community set to a boolean expression
*/
private BoolExpr matchCommunitySet(Configuration conf, CommunitySetExpr e, SymbolicRoute other) {
if (e instanceof InlineCommunitySet) {
Set<CommunityVar> comms = _enc.getGraph().findAllCommunities(conf, e);
BoolExpr acc = _enc.mkTrue();
for (CommunityVar comm : comms) {
BoolExpr c = other.getCommunities().get(comm);
if (c == null) {
throw new BatfishException("matchCommunitySet: should not be null");
}
acc = _enc.mkAnd(acc, c);
}
return acc;
}
if (e instanceof NamedCommunitySet) {
NamedCommunitySet x = (NamedCommunitySet) e;
CommunityList cl = conf.getCommunityLists().get(x.getName());
return matchCommunityList(cl, other);
}
throw new BatfishException("TODO: match community set");
}
use of org.batfish.symbolic.CommunityVar in project batfish by batfish.
the class TransferSSA method relateVariables.
/*
* Relate the symbolic control plane route variables
*/
private BoolExpr relateVariables(TransferParam<SymbolicRoute> p, TransferResult<BoolExpr, BoolExpr> result) {
ArithExpr defaultLen = _enc.mkInt(_enc.defaultLength());
ArithExpr defaultAd = _enc.defaultAdminDistance(_conf, _proto, p.getData());
ArithExpr defaultMed = _enc.mkInt(_enc.defaultMed(_proto));
ArithExpr defaultLp = _enc.mkInt(_enc.defaultLocalPref());
ArithExpr defaultId = _enc.mkInt(_enc.defaultId());
ArithExpr defaultMet = _enc.mkInt(_enc.defaultMetric());
// TODO: remove all isChanged calls with actual symbolic values that test for a change
boolean isIbgp = _graphEdge.isAbstract() && _proto.isBgp();
// Update prefix length when aggregation
BoolExpr len = _enc.safeEq(_current.getPrefixLength(), getOrDefault(p.getData().getPrefixLength(), defaultLen));
BoolExpr per = _enc.safeEq(_current.getPermitted(), p.getData().getPermitted());
// Only update the router id for import edges
BoolExpr id = _enc.mkTrue();
if (!_isExport) {
id = _enc.safeEq(_current.getRouterId(), getOrDefault(p.getData().getRouterId(), defaultId));
}
// Update OSPF area id
BoolExpr area;
if (p.getData().getOspfArea() == null || _iface.getOspfAreaName() == null) {
area = _enc.mkTrue();
} else {
area = _enc.safeEqEnum(_current.getOspfArea(), _iface.getOspfAreaName());
}
// Set the IGP metric accordingly
BoolExpr igpMet = _enc.mkTrue();
boolean isNonClient = _graphEdge.isAbstract() && (_enc.getGraph().peerType(_graphEdge) != Graph.BgpSendType.TO_EBGP);
boolean isClient = _graphEdge.isAbstract() && (_enc.getGraph().peerType(_graphEdge) == Graph.BgpSendType.TO_RR);
if (_graphEdge.isAbstract() && _current.getIgpMetric() != null) {
String router = _graphEdge.getRouter();
String peer = _graphEdge.getPeer();
// Case where it is a non client, we lookup the next-hop
if (isNonClient) {
EncoderSlice s = _enc.getEncoder().getSlice(peer);
SymbolicRoute r = s.getSymbolicDecisions().getBestNeighbor().get(router);
igpMet = _enc.mkEq(_current.getIgpMetric(), r.getMetric());
}
// Case where it is a client, next-hop depends on the clientId tag we added
if (isClient) {
BoolExpr acc = _enc.mkTrue();
for (Map.Entry<String, Integer> entry : _enc.getGraph().getOriginatorId().entrySet()) {
String r = entry.getKey();
Integer clientId = entry.getValue();
if (!r.equals(router)) {
EncoderSlice s = _enc.getEncoder().getSlice(r);
SymbolicRoute record = s.getSymbolicDecisions().getBestNeighbor().get(r);
BoolExpr eq = _enc.mkEq(_current.getIgpMetric(), record.getMetric());
acc = _enc.mkAnd(acc, _enc.mkImplies(p.getData().getClientId().checkIfValue(clientId), eq));
}
}
igpMet = acc;
}
}
// Set whether or not is iBGP or not on import
BoolExpr isInternal = // TODO: and !isExport?
_enc.safeEq(_current.getBgpInternal(), _enc.mkBool(isIbgp));
// Update OSPF type
BoolExpr type;
if (result.isChanged("OSPF-TYPE")) {
type = _enc.safeEqEnum(_current.getOspfType(), p.getData().getOspfType());
} else {
boolean hasAreaIface = _iface.getOspfAreaName() != null;
boolean hasArea = p.getData().getOspfArea() != null;
boolean hasType = p.getData().getOspfType() != null;
boolean areaPossiblyChanged = hasType && hasArea && hasAreaIface;
// Check if area changed
if (areaPossiblyChanged) {
BoolExpr internal = p.getData().getOspfType().isInternal();
BoolExpr same = p.getData().getOspfArea().checkIfValue(_iface.getOspfAreaName());
BoolExpr update = _enc.mkAnd(internal, _enc.mkNot(same));
BoolExpr copyOld = _enc.safeEqEnum(_current.getOspfType(), p.getData().getOspfType());
type = _enc.mkIf(update, _current.getOspfType().checkIfValue(OspfType.OIA), copyOld);
} else {
type = _enc.safeEqEnum(_current.getOspfType(), p.getData().getOspfType());
}
}
BoolExpr comms = _enc.mkTrue();
// update all community values
for (Map.Entry<CommunityVar, BoolExpr> entry : _current.getCommunities().entrySet()) {
CommunityVar cvar = entry.getKey();
BoolExpr e = entry.getValue();
BoolExpr eOther = p.getData().getCommunities().get(cvar);
// Update the communities if they should be sent
if (sendCommunity()) {
if (cvar.getType() != CommunityVar.Type.REGEX) {
comms = _enc.mkAnd(comms, _enc.mkEq(e, eOther));
}
} else {
comms = _enc.mkAnd(comms, _enc.mkNot(e));
}
}
ArithExpr otherAd = (p.getData().getAdminDist() == null ? defaultAd : p.getData().getAdminDist());
ArithExpr otherMed = (p.getData().getMed() == null ? defaultMed : p.getData().getMed());
ArithExpr otherLp = getOrDefault(p.getData().getLocalPref(), defaultLp);
ArithExpr otherMet = getOrDefault(p.getData().getMetric(), defaultMet);
// otherMet = applyMetricUpdate(otherMet);
BoolExpr ad = _enc.safeEq(_current.getAdminDist(), otherAd);
BoolExpr history = _enc.equalHistories(_current, p.getData());
BoolExpr med = _enc.safeEq(_current.getMed(), otherMed);
BoolExpr met = _enc.safeEq(_current.getMetric(), otherMet);
BoolExpr lp = _enc.safeEq(_current.getLocalPref(), otherLp);
// If this was an external route, then we need to add the correct next-hop tag
boolean isEbgpEdge = _enc.getGraph().getEbgpNeighbors().get(_graphEdge) != null;
BoolExpr cid = _enc.mkTrue();
if (_isExport && _proto.isBgp() && p.getData().getClientId() != null) {
if (isEbgpEdge) {
cid = _current.getClientId().checkIfValue(0);
} else {
cid = _enc.safeEqEnum(_current.getClientId(), p.getData().getClientId());
}
}
if (!_isExport && _proto.isBgp() && p.getData().getClientId() != null) {
BoolExpr fromExternal = p.getData().getClientId().checkIfValue(0);
BoolExpr edgeIsInternal = _enc.mkBool(!isClient && !isNonClient);
BoolExpr copyOver = _enc.safeEqEnum(_current.getClientId(), p.getData().getClientId());
Integer x = _enc.getGraph().getOriginatorId().get(_graphEdge.getRouter());
SymbolicOriginatorId soid = _current.getClientId();
BoolExpr setNewValue = (x == null ? soid.checkIfValue(0) : soid.checkIfValue(x));
cid = _enc.mkIf(_enc.mkAnd(fromExternal, edgeIsInternal), setNewValue, copyOver);
}
BoolExpr updates = _enc.mkAnd(per, len, ad, med, lp, met, id, cid, type, area, comms, history, isInternal, igpMet);
BoolExpr noOverflow = noOverflow(otherMet, _proto);
return _enc.mkIf(noOverflow, updates, _enc.mkNot(_current.getPermitted()));
}
use of org.batfish.symbolic.CommunityVar in project batfish by batfish.
the class TransferBDD method zeroedRecord.
/*
* A record of default values that represent the value of the
* outputs if the route is filtered / dropped in the policy
*/
private BDDRoute zeroedRecord() {
BDDRoute rec = new BDDRoute(_comms);
rec.getMetric().setValue(0);
rec.getLocalPref().setValue(0);
rec.getAdminDist().setValue(0);
rec.getPrefixLength().setValue(0);
rec.getMed().setValue(0);
rec.getPrefix().setValue(0);
for (CommunityVar comm : _comms) {
rec.getCommunities().put(comm, factory.zero());
}
rec.getProtocolHistory().getInteger().setValue(0);
return rec;
}
Aggregations