use of org.batfish.datamodel.routing_policy.expr.DisjunctionChain in project batfish by batfish.
the class RoutingPolicyTests method testRoutingPolicyDeepCircularReference.
/**
* Policy with actual circular reference deep in the policy
*/
@Test
public void testRoutingPolicyDeepCircularReference() {
String parentPolicyName = "parent";
CallStatement callStatement = new CallStatement(parentPolicyName);
BufferedStatement bs = new BufferedStatement(callStatement);
WithEnvironmentExpr we1 = new WithEnvironmentExpr();
we1.setPostStatements(ImmutableList.of(bs));
If if1 = new If();
if1.setGuard(we1);
WithEnvironmentExpr we2 = new WithEnvironmentExpr();
we2.setPostTrueStatements(ImmutableList.of(if1));
If if2 = new If();
if2.setGuard(we2);
If if3 = new If();
if3.setTrueStatements(ImmutableList.of(if2));
If if4 = new If();
if4.setFalseStatements(ImmutableList.of(if3));
WithEnvironmentExpr we3 = new WithEnvironmentExpr();
we3.setPreStatements(ImmutableList.of(if4));
WithEnvironmentExpr we4 = new WithEnvironmentExpr();
we4.setExpr(we3);
Conjunction conj = new Conjunction();
conj.setConjuncts(ImmutableList.of(we4));
ConjunctionChain conjunctionChain = new ConjunctionChain(ImmutableList.of(conj));
Disjunction disjunction = new Disjunction();
disjunction.setDisjuncts(ImmutableList.of(conjunctionChain));
DisjunctionChain disjunctionChain = new DisjunctionChain(ImmutableList.of(disjunction));
Not not = new Not(disjunctionChain);
If if5 = new If();
if5.setGuard(not);
_rpb.setName(parentPolicyName).setStatements(ImmutableList.of(if5)).build();
_c.computeRoutingPolicySources(_w);
/*
* A circular reference warning should be emitted containing the name of the circularly
* referenced policy.
*/
assertThat(_w.getRedFlagWarnings(), not(empty()));
assertThat(_w.getRedFlagWarnings().iterator().next().getText(), containsString(parentPolicyName));
}
use of org.batfish.datamodel.routing_policy.expr.DisjunctionChain in project batfish by batfish.
the class JuniperConfiguration method createBgpProcess.
private BgpProcess createBgpProcess(RoutingInstance routingInstance) {
initDefaultBgpExportPolicy();
initDefaultBgpImportPolicy();
String vrfName = routingInstance.getName();
Vrf vrf = _c.getVrfs().get(vrfName);
BgpProcess proc = new BgpProcess();
Ip routerId = routingInstance.getRouterId();
if (routerId == null) {
routerId = _defaultRoutingInstance.getRouterId();
if (routerId == null) {
routerId = Ip.ZERO;
}
}
proc.setRouterId(routerId);
BgpGroup mg = routingInstance.getMasterBgpGroup();
boolean multipathEbgp = false;
boolean multipathIbgp = false;
boolean multipathMultipleAs = false;
boolean multipathEbgpSet = false;
boolean multipathIbgpSet = false;
boolean multipathMultipleAsSet = false;
if (mg.getLocalAs() == null) {
Integer routingInstanceAs = routingInstance.getAs();
if (routingInstanceAs == null) {
routingInstanceAs = _defaultRoutingInstance.getAs();
}
if (routingInstanceAs == null) {
_w.redFlag("BGP BROKEN FOR THIS ROUTER: Cannot determine local autonomous system");
} else {
mg.setLocalAs(routingInstanceAs);
}
}
// Set default authentication algorithm if missing
if (mg.getAuthenticationAlgorithm() == null) {
mg.setAuthenticationAlgorithm(DEFAULT_BGP_AUTHENTICATION_ALGORITHM);
}
for (IpBgpGroup ig : routingInstance.getIpBgpGroups().values()) {
ig.cascadeInheritance();
}
_unreferencedBgpGroups = new TreeMap<>();
int fakeIpCounter = 0;
for (Entry<String, NamedBgpGroup> e : routingInstance.getNamedBgpGroups().entrySet()) {
fakeIpCounter++;
String name = e.getKey();
NamedBgpGroup group = e.getValue();
if (!group.getIpv6() && !group.getInherited()) {
_unreferencedBgpGroups.put(name, group.getDefinitionLine());
Ip fakeIp = new Ip(-1 * fakeIpCounter);
IpBgpGroup dummy = new IpBgpGroup(fakeIp);
dummy.setParent(group);
dummy.cascadeInheritance();
routingInstance.getIpBgpGroups().put(fakeIp, dummy);
}
}
for (Entry<Ip, IpBgpGroup> e : routingInstance.getIpBgpGroups().entrySet()) {
Ip ip = e.getKey();
IpBgpGroup ig = e.getValue();
BgpNeighbor neighbor = new BgpNeighbor(ip, _c);
neighbor.setVrf(vrfName);
// route reflection
Ip declaredClusterId = ig.getClusterId();
if (declaredClusterId != null) {
neighbor.setRouteReflectorClient(true);
neighbor.setClusterId(declaredClusterId.asLong());
} else {
neighbor.setClusterId(routerId.asLong());
}
// multipath multiple-as
boolean currentGroupMultipathMultipleAs = ig.getMultipathMultipleAs();
if (multipathMultipleAsSet && currentGroupMultipathMultipleAs != multipathMultipleAs) {
_w.redFlag("Currently do not support mixed multipath-multiple-as/non-multipath-multiple-as bgp" + "groups on Juniper - FORCING NON-MULTIPATH-MULTIPLE-AS");
multipathMultipleAs = false;
} else {
multipathMultipleAs = currentGroupMultipathMultipleAs;
multipathMultipleAsSet = true;
}
String authenticationKeyChainName = ig.getAuthenticationKeyChainName();
if (ig.getAuthenticationKeyChainName() != null) {
if (!_c.getAuthenticationKeyChains().containsKey(authenticationKeyChainName)) {
authenticationKeyChainName = null;
} else if (ig.getAuthenticationKey() != null) {
_w.redFlag("Both authentication-key and authentication-key-chain specified for neighbor " + ig.getRemoteAddress());
}
}
BgpAuthenticationSettings bgpAuthenticationSettings = new BgpAuthenticationSettings();
bgpAuthenticationSettings.setAuthenticationAlgorithm(ig.getAuthenticationAlgorithm());
bgpAuthenticationSettings.setAuthenticationKey(ig.getAuthenticationKey());
bgpAuthenticationSettings.setAuthenticationKeyChainName(authenticationKeyChainName);
neighbor.setAuthenticationSettings(bgpAuthenticationSettings);
Boolean ebgpMultihop = ig.getEbgpMultihop();
if (ebgpMultihop == null) {
ebgpMultihop = false;
}
neighbor.setEbgpMultihop(ebgpMultihop);
Integer loops = ig.getLoops();
boolean allowLocalAsIn = loops != null && loops > 0;
neighbor.setAllowLocalAsIn(allowLocalAsIn);
Boolean advertisePeerAs = ig.getAdvertisePeerAs();
if (advertisePeerAs == null) {
advertisePeerAs = false;
}
neighbor.setAllowRemoteAsOut(advertisePeerAs);
Boolean advertiseExternal = ig.getAdvertiseExternal();
if (advertiseExternal == null) {
advertiseExternal = false;
}
neighbor.setAdvertiseExternal(advertiseExternal);
Boolean advertiseInactive = ig.getAdvertiseInactive();
if (advertiseInactive == null) {
advertiseInactive = false;
}
neighbor.setAdvertiseInactive(advertiseInactive);
neighbor.setGroup(ig.getGroupName());
// import policies
String peerImportPolicyName = "~PEER_IMPORT_POLICY:" + ig.getRemoteAddress() + "~";
neighbor.setImportPolicy(peerImportPolicyName);
RoutingPolicy peerImportPolicy = new RoutingPolicy(peerImportPolicyName, _c);
_c.getRoutingPolicies().put(peerImportPolicyName, peerImportPolicy);
// default import policy is to accept
peerImportPolicy.getStatements().add(new SetDefaultPolicy(DEFAULT_BGP_IMPORT_POLICY_NAME));
peerImportPolicy.getStatements().add(Statements.SetDefaultActionAccept.toStaticStatement());
List<BooleanExpr> importPolicyCalls = new ArrayList<>();
ig.getImportPolicies().forEach((importPolicyName, importPolicyLine) -> {
PolicyStatement importPolicy = _policyStatements.get(importPolicyName);
if (importPolicy == null) {
undefined(JuniperStructureType.POLICY_STATEMENT, importPolicyName, JuniperStructureUsage.BGP_IMPORT_POLICY, importPolicyLine);
} else {
setPolicyStatementReferent(importPolicyName, ig.getImportPolicies(), "BGP import policy for neighbor: " + ig.getRemoteAddress());
CallExpr callPolicy = new CallExpr(importPolicyName);
importPolicyCalls.add(callPolicy);
}
});
If peerImportPolicyConditional = new If();
DisjunctionChain importPolicyChain = new DisjunctionChain(importPolicyCalls);
peerImportPolicyConditional.setGuard(importPolicyChain);
peerImportPolicy.getStatements().add(peerImportPolicyConditional);
peerImportPolicyConditional.getTrueStatements().add(Statements.ExitAccept.toStaticStatement());
peerImportPolicyConditional.getFalseStatements().add(Statements.ExitReject.toStaticStatement());
// export policies
String peerExportPolicyName = "~PEER_EXPORT_POLICY:" + ig.getRemoteAddress() + "~";
neighbor.setExportPolicy(peerExportPolicyName);
RoutingPolicy peerExportPolicy = new RoutingPolicy(peerExportPolicyName, _c);
_c.getRoutingPolicies().put(peerExportPolicyName, peerExportPolicy);
peerExportPolicy.getStatements().add(new SetDefaultPolicy(DEFAULT_BGP_EXPORT_POLICY_NAME));
/*
* For new BGP advertisements, i.e. those that are created from non-BGP
* routes, an origin code must be set. By default, Juniper sets the origin
* code to IGP.
*/
If setOriginForNonBgp = new If();
Disjunction isBgp = new Disjunction();
isBgp.getDisjuncts().add(new MatchProtocol(RoutingProtocol.BGP));
isBgp.getDisjuncts().add(new MatchProtocol(RoutingProtocol.IBGP));
setOriginForNonBgp.setGuard(isBgp);
setOriginForNonBgp.getFalseStatements().add(new SetOrigin(new LiteralOrigin(OriginType.IGP, null)));
peerExportPolicy.getStatements().add(setOriginForNonBgp);
List<BooleanExpr> exportPolicyCalls = new ArrayList<>();
ig.getExportPolicies().forEach((exportPolicyName, exportPolicyLine) -> {
PolicyStatement exportPolicy = _policyStatements.get(exportPolicyName);
if (exportPolicy == null) {
undefined(JuniperStructureType.POLICY_STATEMENT, exportPolicyName, JuniperStructureUsage.BGP_EXPORT_POLICY, exportPolicyLine);
} else {
setPolicyStatementReferent(exportPolicyName, ig.getExportPolicies(), "BGP export policy for neighbor: " + ig.getRemoteAddress());
CallExpr callPolicy = new CallExpr(exportPolicyName);
exportPolicyCalls.add(callPolicy);
}
});
If peerExportPolicyConditional = new If();
DisjunctionChain exportPolicyChain = new DisjunctionChain(exportPolicyCalls);
peerExportPolicyConditional.setGuard(exportPolicyChain);
peerExportPolicyConditional.getTrueStatements().add(Statements.ExitAccept.toStaticStatement());
peerExportPolicyConditional.getFalseStatements().add(Statements.ExitReject.toStaticStatement());
peerExportPolicy.getStatements().add(peerExportPolicyConditional);
// inherit local-as
neighbor.setLocalAs(ig.getLocalAs());
if (neighbor.getLocalAs() == null) {
_w.redFlag("Missing local-as for neighbor: " + ig.getRemoteAddress());
continue;
}
/*
* inherit peer-as, or use local-as if internal
*
* Also set multipath
*/
if (ig.getType() == BgpGroupType.INTERNAL) {
neighbor.setRemoteAs(ig.getLocalAs());
boolean currentGroupMultipathIbgp = ig.getMultipath();
if (multipathIbgpSet && currentGroupMultipathIbgp != multipathIbgp) {
_w.redFlag("Currently do not support mixed iBGP multipath/non-multipath bgp groups on Juniper " + "- FORCING NON-MULTIPATH IBGP");
multipathIbgp = false;
} else {
multipathIbgp = currentGroupMultipathIbgp;
multipathIbgpSet = true;
}
} else {
neighbor.setRemoteAs(ig.getPeerAs());
boolean currentGroupMultipathEbgp = ig.getMultipath();
if (multipathEbgpSet && currentGroupMultipathEbgp != multipathEbgp) {
_w.redFlag("Currently do not support mixed eBGP multipath/non-multipath bgp groups on Juniper " + "- FORCING NON-MULTIPATH EBGP");
multipathEbgp = false;
} else {
multipathEbgp = currentGroupMultipathEbgp;
multipathEbgpSet = true;
}
}
// TODO: implement better behavior than setting default metric to 0
neighbor.setDefaultMetric(0);
// TODO: find out if there is a juniper equivalent of cisco
// send-community
neighbor.setSendCommunity(true);
// inherit update-source
Ip localIp = ig.getLocalAddress();
if (localIp == null) {
// peer
outerloop: for (org.batfish.datamodel.Interface iface : vrf.getInterfaces().values()) {
for (InterfaceAddress address : iface.getAllAddresses()) {
if (address.getPrefix().containsIp(ip)) {
localIp = address.getIp();
break outerloop;
}
}
}
}
if (localIp == null && _defaultAddressSelection) {
initFirstLoopbackInterface();
if (_lo0 != null) {
InterfaceAddress lo0Unit0Address = _lo0.getPrimaryAddress();
if (lo0Unit0Address != null) {
localIp = lo0Unit0Address.getIp();
}
}
}
if (localIp == null && ip.valid()) {
_w.redFlag("Could not determine local ip for bgp peering with neighbor ip: " + ip);
} else {
neighbor.setLocalIp(localIp);
}
if (neighbor.getGroup() == null || !_unreferencedBgpGroups.containsKey(neighbor.getGroup())) {
proc.getNeighbors().put(neighbor.getPrefix(), neighbor);
}
}
proc.setMultipathEbgp(multipathEbgpSet);
proc.setMultipathIbgp(multipathIbgp);
MultipathEquivalentAsPathMatchMode multipathEquivalentAsPathMatchMode = multipathMultipleAs ? MultipathEquivalentAsPathMatchMode.PATH_LENGTH : MultipathEquivalentAsPathMatchMode.FIRST_AS;
proc.setMultipathEquivalentAsPathMatchMode(multipathEquivalentAsPathMatchMode);
return proc;
}
use of org.batfish.datamodel.routing_policy.expr.DisjunctionChain 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 org.batfish.datamodel.routing_policy.expr.DisjunctionChain 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.expr.DisjunctionChain in project batfish by batfish.
the class AstVisitor method visit.
/*
* Walk starting from an AST boolean expression
*/
public void visit(Configuration conf, BooleanExpr e, Consumer<Statement> fs, Consumer<BooleanExpr> fe) {
fe.accept(e);
if (e instanceof Conjunction) {
Conjunction c = (Conjunction) e;
for (BooleanExpr be : c.getConjuncts()) {
visit(conf, be, fs, fe);
}
} else if (e instanceof Disjunction) {
Disjunction d = (Disjunction) e;
for (BooleanExpr be : d.getDisjuncts()) {
visit(conf, be, fs, fe);
}
} else if (e instanceof ConjunctionChain) {
ConjunctionChain c = (ConjunctionChain) e;
for (BooleanExpr be : c.getSubroutines()) {
visit(conf, be, fs, fe);
}
} else if (e instanceof DisjunctionChain) {
DisjunctionChain d = (DisjunctionChain) e;
for (BooleanExpr be : d.getSubroutines()) {
visit(conf, be, fs, fe);
}
} else if (e instanceof Not) {
Not n = (Not) e;
visit(conf, n.getExpr(), fs, fe);
} else if (e instanceof CallExpr) {
CallExpr c = (CallExpr) e;
RoutingPolicy rp = conf.getRoutingPolicies().get(c.getCalledPolicyName());
visit(conf, rp.getStatements(), fs, fe);
}
}
Aggregations