use of org.batfish.datamodel.routing_policy.expr.Not 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.Not in project batfish by batfish.
the class CiscoConfiguration method toOspfProcess.
private org.batfish.datamodel.OspfProcess toOspfProcess(OspfProcess proc, String vrfName, Configuration c, CiscoConfiguration oldConfig) {
org.batfish.datamodel.OspfProcess newProcess = new org.batfish.datamodel.OspfProcess();
org.batfish.datamodel.Vrf vrf = c.getVrfs().get(vrfName);
if (proc.getMaxMetricRouterLsa()) {
newProcess.setMaxMetricTransitLinks(OspfProcess.MAX_METRIC_ROUTER_LSA);
if (proc.getMaxMetricIncludeStub()) {
newProcess.setMaxMetricStubNetworks(OspfProcess.MAX_METRIC_ROUTER_LSA);
}
newProcess.setMaxMetricExternalNetworks(proc.getMaxMetricExternalLsa());
newProcess.setMaxMetricSummaryNetworks(proc.getMaxMetricSummaryLsa());
}
newProcess.setProcessId(proc.getName());
// establish areas and associated interfaces
Map<Long, OspfArea> areas = newProcess.getAreas();
Map<Long, ImmutableSortedSet.Builder<String>> areaInterfacesBuilders = new HashMap<>();
List<OspfNetwork> networks = new ArrayList<>();
networks.addAll(proc.getNetworks());
Collections.sort(networks, new Comparator<OspfNetwork>() {
// sort so longest prefixes are first
@Override
public int compare(OspfNetwork lhs, OspfNetwork rhs) {
int lhsPrefixLength = lhs.getPrefix().getPrefixLength();
int rhsPrefixLength = rhs.getPrefix().getPrefixLength();
// intentionally swapped
int result = Integer.compare(rhsPrefixLength, lhsPrefixLength);
if (result == 0) {
long lhsIp = lhs.getPrefix().getStartIp().asLong();
long rhsIp = rhs.getPrefix().getStartIp().asLong();
result = Long.compare(lhsIp, rhsIp);
}
return result;
}
});
// Set RFC 1583 compatibility
newProcess.setRfc1583Compatible(proc.getRfc1583Compatible());
for (Entry<String, org.batfish.datamodel.Interface> e : vrf.getInterfaces().entrySet()) {
String ifaceName = e.getKey();
org.batfish.datamodel.Interface iface = e.getValue();
InterfaceAddress interfaceAddress = iface.getAddress();
if (interfaceAddress == null) {
continue;
}
for (OspfNetwork network : networks) {
Prefix networkPrefix = network.getPrefix();
Ip networkAddress = networkPrefix.getStartIp();
Ip maskedInterfaceAddress = interfaceAddress.getIp().getNetworkAddress(networkPrefix.getPrefixLength());
if (maskedInterfaceAddress.equals(networkAddress)) {
// we have a longest prefix match
long areaNum = network.getArea();
OspfArea newArea = areas.computeIfAbsent(areaNum, OspfArea::new);
ImmutableSortedSet.Builder<String> newAreaInterfacesBuilder = areaInterfacesBuilders.computeIfAbsent(areaNum, n -> ImmutableSortedSet.naturalOrder());
newAreaInterfacesBuilder.add(ifaceName);
iface.setOspfArea(newArea);
iface.setOspfEnabled(true);
boolean passive = proc.getPassiveInterfaceList().contains(iface.getName()) || (proc.getPassiveInterfaceDefault() && !proc.getActiveInterfaceList().contains(iface.getName()));
iface.setOspfPassive(passive);
break;
}
}
areaInterfacesBuilders.forEach((areaNum, interfacesBuilder) -> areas.get(areaNum).setInterfaces(interfacesBuilder.build()));
}
// create summarization filters for inter-area routes
for (Entry<Long, Map<Prefix, OspfAreaSummary>> e1 : proc.getSummaries().entrySet()) {
long areaLong = e1.getKey();
Map<Prefix, OspfAreaSummary> summaries = e1.getValue();
OspfArea area = areas.get(areaLong);
String summaryFilterName = "~OSPF_SUMMARY_FILTER:" + vrfName + ":" + areaLong + "~";
RouteFilterList summaryFilter = new RouteFilterList(summaryFilterName);
c.getRouteFilterLists().put(summaryFilterName, summaryFilter);
if (area == null) {
area = new OspfArea(areaLong);
areas.put(areaLong, area);
}
area.setSummaryFilter(summaryFilterName);
for (Entry<Prefix, OspfAreaSummary> e2 : summaries.entrySet()) {
Prefix prefix = e2.getKey();
OspfAreaSummary summary = e2.getValue();
int prefixLength = prefix.getPrefixLength();
int filterMinPrefixLength = summary.getAdvertised() ? Math.min(Prefix.MAX_PREFIX_LENGTH, prefixLength + 1) : prefixLength;
summaryFilter.addLine(new RouteFilterLine(LineAction.REJECT, prefix, new SubRange(filterMinPrefixLength, Prefix.MAX_PREFIX_LENGTH)));
}
area.setSummaries(ImmutableSortedMap.copyOf(summaries));
summaryFilter.addLine(new RouteFilterLine(LineAction.ACCEPT, Prefix.ZERO, new SubRange(0, Prefix.MAX_PREFIX_LENGTH)));
}
String ospfExportPolicyName = "~OSPF_EXPORT_POLICY:" + vrfName + "~";
RoutingPolicy ospfExportPolicy = new RoutingPolicy(ospfExportPolicyName, c);
c.getRoutingPolicies().put(ospfExportPolicyName, ospfExportPolicy);
List<Statement> ospfExportStatements = ospfExportPolicy.getStatements();
newProcess.setExportPolicy(ospfExportPolicyName);
// policy map for default information
if (proc.getDefaultInformationOriginate()) {
If ospfExportDefault = new If();
ospfExportStatements.add(ospfExportDefault);
ospfExportDefault.setComment("OSPF export default route");
Conjunction ospfExportDefaultConditions = new Conjunction();
List<Statement> ospfExportDefaultStatements = ospfExportDefault.getTrueStatements();
ospfExportDefaultConditions.getConjuncts().add(new MatchPrefixSet(new DestinationNetwork(), new ExplicitPrefixSet(new PrefixSpace(Collections.singleton(new PrefixRange(Prefix.ZERO, new SubRange(0, 0)))))));
long metric = proc.getDefaultInformationMetric();
ospfExportDefaultStatements.add(new SetMetric(new LiteralLong(metric)));
OspfMetricType metricType = proc.getDefaultInformationMetricType();
ospfExportDefaultStatements.add(new SetOspfMetricType(metricType));
// add default export map with metric
String defaultOriginateMapName = proc.getDefaultInformationOriginateMap();
boolean useAggregateDefaultOnly;
if (defaultOriginateMapName != null) {
int defaultOriginateMapLine = proc.getDefaultInformationOriginateMapLine();
useAggregateDefaultOnly = true;
RoutingPolicy ospfDefaultGenerationPolicy = c.getRoutingPolicies().get(defaultOriginateMapName);
if (ospfDefaultGenerationPolicy == null) {
undefined(CiscoStructureType.ROUTE_MAP, defaultOriginateMapName, CiscoStructureUsage.OSPF_DEFAULT_ORIGINATE_ROUTE_MAP, defaultOriginateMapLine);
} else {
RouteMap generationRouteMap = _routeMaps.get(defaultOriginateMapName);
generationRouteMap.getReferers().put(proc, "ospf default-originate route-map");
GeneratedRoute.Builder route = new GeneratedRoute.Builder();
route.setNetwork(Prefix.ZERO);
route.setAdmin(MAX_ADMINISTRATIVE_COST);
route.setGenerationPolicy(defaultOriginateMapName);
newProcess.getGeneratedRoutes().add(route.build());
}
} else if (proc.getDefaultInformationOriginateAlways()) {
useAggregateDefaultOnly = true;
// add generated aggregate with no precondition
GeneratedRoute.Builder route = new GeneratedRoute.Builder();
route.setNetwork(Prefix.ZERO);
route.setAdmin(MAX_ADMINISTRATIVE_COST);
newProcess.getGeneratedRoutes().add(route.build());
} else {
// do not generate an aggregate default route;
// just redistribute any existing default route with the new metric
useAggregateDefaultOnly = false;
}
if (useAggregateDefaultOnly) {
ospfExportDefaultConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.AGGREGATE));
}
ospfExportDefaultStatements.add(Statements.ExitAccept.toStaticStatement());
ospfExportDefault.setGuard(ospfExportDefaultConditions);
}
// policy for redistributing connected routes
// TODO: honor subnets option
OspfRedistributionPolicy rcp = proc.getRedistributionPolicies().get(RoutingProtocol.CONNECTED);
if (rcp != null) {
If ospfExportConnected = new If();
ospfExportConnected.setComment("OSPF export connected routes");
Conjunction ospfExportConnectedConditions = new Conjunction();
ospfExportConnectedConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.CONNECTED));
List<Statement> ospfExportConnectedStatements = ospfExportConnected.getTrueStatements();
Long metric = rcp.getMetric();
OspfMetricType metricType = rcp.getMetricType();
ospfExportConnectedStatements.add(new SetOspfMetricType(metricType));
boolean explicitMetric = metric != null;
if (!explicitMetric) {
metric = proc.getDefaultMetric(_vendor, RoutingProtocol.CONNECTED);
}
ospfExportStatements.add(new SetMetric(new LiteralLong(metric)));
ospfExportStatements.add(ospfExportConnected);
// add default export map with metric
String exportConnectedRouteMapName = rcp.getRouteMap();
if (exportConnectedRouteMapName != null) {
int exportConnectedRouteMapLine = rcp.getRouteMapLine();
RouteMap exportConnectedRouteMap = _routeMaps.get(exportConnectedRouteMapName);
if (exportConnectedRouteMap == null) {
undefined(CiscoStructureType.ROUTE_MAP, exportConnectedRouteMapName, CiscoStructureUsage.OSPF_REDISTRIBUTE_CONNECTED_MAP, exportConnectedRouteMapLine);
} else {
exportConnectedRouteMap.getReferers().put(proc, "ospf redistribute connected route-map");
ospfExportConnectedConditions.getConjuncts().add(new CallExpr(exportConnectedRouteMapName));
}
}
ospfExportConnectedStatements.add(Statements.ExitAccept.toStaticStatement());
ospfExportConnected.setGuard(ospfExportConnectedConditions);
}
// policy map for redistributing static routes
// TODO: honor subnets option
OspfRedistributionPolicy rsp = proc.getRedistributionPolicies().get(RoutingProtocol.STATIC);
if (rsp != null) {
If ospfExportStatic = new If();
ospfExportStatic.setComment("OSPF export static routes");
Conjunction ospfExportStaticConditions = new Conjunction();
ospfExportStaticConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.STATIC));
List<Statement> ospfExportStaticStatements = ospfExportStatic.getTrueStatements();
ospfExportStaticConditions.getConjuncts().add(new Not(new MatchPrefixSet(new DestinationNetwork(), new ExplicitPrefixSet(new PrefixSpace(Collections.singleton(new PrefixRange(Prefix.ZERO, new SubRange(0, 0))))))));
Long metric = rsp.getMetric();
OspfMetricType metricType = rsp.getMetricType();
ospfExportStaticStatements.add(new SetOspfMetricType(metricType));
boolean explicitMetric = metric != null;
if (!explicitMetric) {
metric = proc.getDefaultMetric(_vendor, RoutingProtocol.STATIC);
}
ospfExportStatements.add(new SetMetric(new LiteralLong(metric)));
ospfExportStatements.add(ospfExportStatic);
// add export map with metric
String exportStaticRouteMapName = rsp.getRouteMap();
if (exportStaticRouteMapName != null) {
int exportStaticRouteMapLine = rsp.getRouteMapLine();
RouteMap exportStaticRouteMap = _routeMaps.get(exportStaticRouteMapName);
if (exportStaticRouteMap == null) {
undefined(CiscoStructureType.ROUTE_MAP, exportStaticRouteMapName, CiscoStructureUsage.OSPF_REDISTRIBUTE_STATIC_MAP, exportStaticRouteMapLine);
} else {
exportStaticRouteMap.getReferers().put(proc, "ospf redistribute static route-map");
ospfExportStaticConditions.getConjuncts().add(new CallExpr(exportStaticRouteMapName));
}
}
ospfExportStaticStatements.add(Statements.ExitAccept.toStaticStatement());
ospfExportStatic.setGuard(ospfExportStaticConditions);
}
// policy map for redistributing bgp routes
// TODO: honor subnets option
OspfRedistributionPolicy rbp = proc.getRedistributionPolicies().get(RoutingProtocol.BGP);
if (rbp != null) {
If ospfExportBgp = new If();
ospfExportBgp.setComment("OSPF export bgp routes");
Conjunction ospfExportBgpConditions = new Conjunction();
ospfExportBgpConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.BGP));
List<Statement> ospfExportBgpStatements = ospfExportBgp.getTrueStatements();
ospfExportBgpConditions.getConjuncts().add(new Not(new MatchPrefixSet(new DestinationNetwork(), new ExplicitPrefixSet(new PrefixSpace(Collections.singleton(new PrefixRange(Prefix.ZERO, new SubRange(0, 0))))))));
Long metric = rbp.getMetric();
OspfMetricType metricType = rbp.getMetricType();
ospfExportBgpStatements.add(new SetOspfMetricType(metricType));
boolean explicitMetric = metric != null;
if (!explicitMetric) {
metric = proc.getDefaultMetric(_vendor, RoutingProtocol.BGP);
}
ospfExportStatements.add(new SetMetric(new LiteralLong(metric)));
ospfExportStatements.add(ospfExportBgp);
// add export map with metric
String exportBgpRouteMapName = rbp.getRouteMap();
if (exportBgpRouteMapName != null) {
int exportBgpRouteMapLine = rbp.getRouteMapLine();
RouteMap exportBgpRouteMap = _routeMaps.get(exportBgpRouteMapName);
if (exportBgpRouteMap == null) {
undefined(CiscoStructureType.ROUTE_MAP, exportBgpRouteMapName, CiscoStructureUsage.OSPF_REDISTRIBUTE_BGP_MAP, exportBgpRouteMapLine);
} else {
exportBgpRouteMap.getReferers().put(proc, "ospf redistribute bgp route-map");
ospfExportBgpConditions.getConjuncts().add(new CallExpr(exportBgpRouteMapName));
}
}
ospfExportBgpStatements.add(Statements.ExitAccept.toStaticStatement());
ospfExportBgp.setGuard(ospfExportBgpConditions);
}
newProcess.setReferenceBandwidth(proc.getReferenceBandwidth());
Ip routerId = proc.getRouterId();
if (routerId == null) {
Map<String, Interface> interfacesToCheck;
Map<String, Interface> allInterfaces = oldConfig.getInterfaces();
Map<String, Interface> loopbackInterfaces = new HashMap<>();
for (Entry<String, Interface> e : allInterfaces.entrySet()) {
String ifaceName = e.getKey();
Interface iface = e.getValue();
if (ifaceName.toLowerCase().startsWith("loopback") && iface.getActive() && iface.getAddress() != null) {
loopbackInterfaces.put(ifaceName, iface);
}
}
if (loopbackInterfaces.isEmpty()) {
interfacesToCheck = allInterfaces;
} else {
interfacesToCheck = loopbackInterfaces;
}
Ip highestIp = Ip.ZERO;
for (Interface iface : interfacesToCheck.values()) {
if (!iface.getActive()) {
continue;
}
for (InterfaceAddress address : iface.getAllAddresses()) {
Ip ip = address.getIp();
if (highestIp.asLong() < ip.asLong()) {
highestIp = ip;
}
}
}
if (highestIp == Ip.ZERO) {
_w.redFlag("No candidates for OSPF router-id");
return null;
}
routerId = highestIp;
}
newProcess.setRouterId(routerId);
return newProcess;
}
use of org.batfish.datamodel.routing_policy.expr.Not in project batfish by batfish.
the class Graph method getOriginatedNetworks.
/*
* Collects and returns all originated prefixes for the given
* router as well as the protocol. Static routes and connected
* routes are treated as originating the prefix.
*/
public static Set<Prefix> getOriginatedNetworks(Configuration conf, Protocol proto) {
Set<Prefix> acc = new HashSet<>();
if (proto.isOspf()) {
OspfProcess ospf = conf.getDefaultVrf().getOspfProcess();
for (OspfArea area : ospf.getAreas().values()) {
for (String ifaceName : area.getInterfaces()) {
Interface iface = conf.getInterfaces().get(ifaceName);
if (iface.getActive() && iface.getOspfEnabled()) {
acc.add(iface.getAddress().getPrefix());
}
}
}
return acc;
}
if (proto.isBgp()) {
RoutingPolicy defaultPol = findCommonRoutingPolicy(conf, Protocol.BGP);
if (defaultPol != null) {
AstVisitor v = new AstVisitor();
v.visit(conf, defaultPol.getStatements(), stmt -> {
}, expr -> {
if (expr instanceof Conjunction) {
Conjunction c = (Conjunction) expr;
if (c.getConjuncts().size() >= 2) {
BooleanExpr be1 = c.getConjuncts().get(0);
BooleanExpr be2 = c.getConjuncts().get(1);
if (be1 instanceof MatchPrefixSet && be2 instanceof Not) {
MatchPrefixSet mps = (MatchPrefixSet) be1;
Not n = (Not) be2;
if (n.getExpr() instanceof MatchProtocol) {
MatchProtocol mp = (MatchProtocol) n.getExpr();
if (mp.getProtocol() == RoutingProtocol.BGP) {
PrefixSetExpr e = mps.getPrefixSet();
if (e instanceof ExplicitPrefixSet) {
ExplicitPrefixSet eps = (ExplicitPrefixSet) e;
Set<PrefixRange> ranges = eps.getPrefixSpace().getPrefixRanges();
for (PrefixRange r : ranges) {
acc.add(r.getPrefix());
}
}
}
}
}
}
}
});
}
return acc;
}
if (proto.isConnected()) {
for (Interface iface : conf.getInterfaces().values()) {
InterfaceAddress address = iface.getAddress();
if (address != null) {
acc.add(address.getPrefix());
}
}
return acc;
}
if (proto.isStatic()) {
for (StaticRoute sr : conf.getDefaultVrf().getStaticRoutes()) {
if (sr.getNetwork() != null) {
acc.add(sr.getNetwork());
}
}
return acc;
}
throw new BatfishException("ERROR: getOriginatedNetworks: " + proto.name());
}
use of org.batfish.datamodel.routing_policy.expr.Not in project batfish by batfish.
the class BatfishCompressor method matchExternalTraffic.
/**
* Create a filter that only allows traffic for those prefixes if it came from outside. EXTERNAL =
* (protocol is bgp or ibgp) and (the AS path is not an internal path) MATCH = destination matches
* the prefixTrie GUARD = EXTERNAL or MATCH (only allow this traffic through)
*/
@Nonnull
private BooleanExpr matchExternalTraffic() {
List<AsPathSetElem> elements = new ArrayList<>();
elements.add(new RegexAsPathSetElem(_internalRegex));
ExplicitAsPathSet expr = new ExplicitAsPathSet(elements);
MatchAsPath matchPath = new MatchAsPath(expr);
MatchProtocol mpBgp = new MatchProtocol(RoutingProtocol.BGP);
MatchProtocol mpIbgp = new MatchProtocol(RoutingProtocol.IBGP);
Disjunction d = new Disjunction();
List<BooleanExpr> disjuncts = new ArrayList<>();
disjuncts.add(mpBgp);
disjuncts.add(mpIbgp);
d.setDisjuncts(disjuncts);
Not n = new Not(matchPath);
Conjunction c = new Conjunction();
List<BooleanExpr> conjuncts = new ArrayList<>();
conjuncts.add(d);
conjuncts.add(n);
c.setConjuncts(conjuncts);
return c;
}
use of org.batfish.datamodel.routing_policy.expr.Not 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);
}
Aggregations