use of org.batfish.datamodel.routing_policy.statement.SetMetric 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.statement.SetMetric in project batfish by batfish.
the class TransferBDD method compute.
/*
* Convert a list of statements into a Z3 boolean expression for the transfer function.
*/
private TransferResult<TransferReturn, BDD> compute(List<Statement> statements, TransferParam<BDDRoute> p) {
boolean doesReturn = false;
TransferResult<TransferReturn, BDD> result = new TransferResult<>();
result = result.setReturnValue(new TransferReturn(p.getData(), factory.zero())).setFallthroughValue(factory.zero()).setReturnAssignedValue(factory.zero());
for (Statement stmt : statements) {
if (stmt instanceof StaticStatement) {
StaticStatement ss = (StaticStatement) stmt;
switch(ss.getType()) {
case ExitAccept:
doesReturn = true;
p.debug("ExitAccept");
result = returnValue(result, true);
break;
case ReturnTrue:
doesReturn = true;
p.debug("ReturnTrue");
result = returnValue(result, true);
break;
case ExitReject:
doesReturn = true;
p.debug("ExitReject");
result = returnValue(result, false);
break;
case ReturnFalse:
doesReturn = true;
p.debug("ReturnFalse");
result = returnValue(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(result, true);
} else {
result = returnValue(result, false);
}
break;
case FallThrough:
p.debug("Fallthrough");
result = fallthrough(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<TransferReturn, BDD> r = compute(i.getGuard(), p.indent());
BDD guard = r.getReturnValue().getSecond();
p.debug("guard: ");
BDDRoute current = result.getReturnValue().getFirst();
TransferParam<BDDRoute> pTrue = p.indent().setData(current.deepCopy());
TransferParam<BDDRoute> pFalse = p.indent().setData(current.deepCopy());
p.debug("True Branch");
TransferResult<TransferReturn, BDD> trueBranch = compute(i.getTrueStatements(), pTrue);
p.debug("True Branch: " + trueBranch.getReturnValue().getFirst().hashCode());
p.debug("False Branch");
TransferResult<TransferReturn, BDD> falseBranch = compute(i.getFalseStatements(), pFalse);
p.debug("False Branch: " + trueBranch.getReturnValue().getFirst().hashCode());
BDDRoute r1 = trueBranch.getReturnValue().getFirst();
BDDRoute r2 = falseBranch.getReturnValue().getFirst();
BDDRoute recordVal = ite(guard, r1, r2);
// update return values
BDD returnVal = ite(guard, trueBranch.getReturnValue().getSecond(), falseBranch.getReturnValue().getSecond());
// p.debug("New Return Value (neg): " + returnVal.not());
BDD returnAss = ite(guard, trueBranch.getReturnAssignedValue(), falseBranch.getReturnAssignedValue());
// p.debug("New Return Assigned: " + returnAss);
BDD fallThrough = ite(guard, trueBranch.getFallthroughValue(), falseBranch.getFallthroughValue());
// p.debug("New fallthrough: " + fallThrough);
result = result.setReturnValue(new TransferReturn(recordVal, returnVal)).setReturnAssignedValue(returnAss).setFallthroughValue(fallThrough);
p.debug("If return: " + result.getReturnValue().getFirst().hashCode());
} else if (stmt instanceof SetDefaultPolicy) {
p.debug("SetDefaultPolicy");
p = p.setDefaultPolicy((SetDefaultPolicy) stmt);
} else if (stmt instanceof SetMetric) {
p.debug("SetMetric");
SetMetric sm = (SetMetric) stmt;
LongExpr ie = sm.getMetric();
BDD isBGP = p.getData().getProtocolHistory().value(Protocol.BGP);
BDD updateMed = isBGP.and(result.getReturnAssignedValue());
BDD updateMet = isBGP.not().and(result.getReturnAssignedValue());
BDDInteger newValue = applyLongExprModification(p.indent(), p.getData().getMetric(), ie);
BDDInteger med = ite(updateMed, p.getData().getMed(), newValue);
BDDInteger met = ite(updateMet, p.getData().getMetric(), newValue);
p.getData().setMetric(met);
p.getData().setMetric(med);
} else if (stmt instanceof SetOspfMetricType) {
p.debug("SetOspfMetricType");
SetOspfMetricType somt = (SetOspfMetricType) stmt;
OspfMetricType mt = somt.getMetricType();
BDDDomain<OspfType> current = result.getReturnValue().getFirst().getOspfMetric();
BDDDomain<OspfType> newValue = new BDDDomain<>(current);
if (mt == OspfMetricType.E1) {
p.indent().debug("Value: E1");
newValue.setValue(OspfType.E1);
} else {
p.indent().debug("Value: E2");
newValue.setValue(OspfType.E1);
}
newValue = ite(result.getReturnAssignedValue(), p.getData().getOspfMetric(), newValue);
p.getData().setOspfMetric(newValue);
} else if (stmt instanceof SetLocalPreference) {
p.debug("SetLocalPreference");
SetLocalPreference slp = (SetLocalPreference) stmt;
IntExpr ie = slp.getLocalPreference();
BDDInteger newValue = applyIntExprModification(p.indent(), p.getData().getLocalPref(), ie);
newValue = ite(result.getReturnAssignedValue(), p.getData().getLocalPref(), newValue);
p.getData().setLocalPref(newValue);
} else if (stmt instanceof AddCommunity) {
p.debug("AddCommunity");
AddCommunity ac = (AddCommunity) stmt;
Set<CommunityVar> comms = _graph.findAllCommunities(_conf, ac.getExpr());
for (CommunityVar cvar : comms) {
if (!_policyQuotient.getCommsAssignedButNotMatched().contains(cvar)) {
p.indent().debug("Value: " + cvar);
BDD comm = p.getData().getCommunities().get(cvar);
BDD newValue = ite(result.getReturnAssignedValue(), comm, factory.one());
p.indent().debug("New Value: " + newValue);
p.getData().getCommunities().put(cvar, newValue);
}
}
} else if (stmt instanceof SetCommunity) {
p.debug("SetCommunity");
SetCommunity sc = (SetCommunity) stmt;
Set<CommunityVar> comms = _graph.findAllCommunities(_conf, sc.getExpr());
for (CommunityVar cvar : comms) {
if (!_policyQuotient.getCommsAssignedButNotMatched().contains(cvar)) {
p.indent().debug("Value: " + cvar);
BDD comm = p.getData().getCommunities().get(cvar);
BDD newValue = ite(result.getReturnAssignedValue(), comm, factory.one());
p.indent().debug("New Value: " + newValue);
p.getData().getCommunities().put(cvar, newValue);
}
}
} else if (stmt instanceof DeleteCommunity) {
p.debug("DeleteCommunity");
DeleteCommunity ac = (DeleteCommunity) stmt;
Set<CommunityVar> comms = _graph.findAllCommunities(_conf, ac.getExpr());
Set<CommunityVar> toDelete = new HashSet<>();
// Find comms to delete
for (CommunityVar cvar : comms) {
if (cvar.getType() == Type.REGEX) {
toDelete.addAll(_commDeps.get(cvar));
} else {
toDelete.add(cvar);
}
}
// Delete the comms
for (CommunityVar cvar : toDelete) {
if (!_policyQuotient.getCommsAssignedButNotMatched().contains(cvar)) {
p.indent().debug("Value: " + cvar.getValue() + ", " + cvar.getType());
BDD comm = p.getData().getCommunities().get(cvar);
BDD newValue = ite(result.getReturnAssignedValue(), comm, factory.zero());
p.indent().debug("New Value: " + newValue);
p.getData().getCommunities().put(cvar, newValue);
}
}
} 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());
p.indent().debug("Cost: " + prependCost);
BDDInteger met = p.getData().getMetric();
BDDInteger newValue = met.add(BDDInteger.makeFromValue(met.getFactory(), 32, prependCost));
newValue = ite(result.getReturnAssignedValue(), p.getData().getMetric(), newValue);
p.getData().setMetric(newValue);
} else if (stmt instanceof SetOrigin) {
p.debug("SetOrigin");
// System.out.println("Warning: use of unimplemented feature SetOrigin");
// TODO: implement me
} else if (stmt instanceof SetNextHop) {
p.debug("SetNextHop");
// System.out.println("Warning: use of unimplemented feature SetNextHop");
// TODO: implement me
} else {
throw new BatfishException("TODO: statement transfer function: " + stmt);
}
}
// 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(result, true);
} else {
result = returnValue(result, false);
}
}
// Set all the values to 0 if the return is not true;
TransferReturn ret = result.getReturnValue();
BDDRoute retVal = ite(ret.getSecond(), ret.getFirst(), zeroedRecord());
result = result.setReturnValue(new TransferReturn(retVal, ret.getSecond()));
}
return result;
}
use of org.batfish.datamodel.routing_policy.statement.SetMetric in project batfish by batfish.
the class CiscoConfiguration method toRipProcess.
private org.batfish.datamodel.RipProcess toRipProcess(RipProcess proc, String vrfName, Configuration c, CiscoConfiguration oldConfig) {
org.batfish.datamodel.RipProcess newProcess = new org.batfish.datamodel.RipProcess();
org.batfish.datamodel.Vrf vrf = c.getVrfs().get(vrfName);
// establish areas and associated interfaces
SortedSet<Prefix> networks = proc.getNetworks();
for (Entry<String, org.batfish.datamodel.Interface> e : vrf.getInterfaces().entrySet()) {
String ifaceName = e.getKey();
org.batfish.datamodel.Interface i = e.getValue();
InterfaceAddress interfaceAddress = i.getAddress();
if (interfaceAddress == null) {
continue;
}
Prefix interfaceNetwork = interfaceAddress.getPrefix();
if (networks.contains(interfaceNetwork)) {
newProcess.getInterfaces().add(ifaceName);
i.setRipEnabled(true);
boolean passive = proc.getPassiveInterfaceList().contains(i.getName()) || (proc.getPassiveInterfaceDefault() && !proc.getActiveInterfaceList().contains(ifaceName));
i.setOspfPassive(passive);
}
}
String ripExportPolicyName = "~RIP_EXPORT_POLICY:" + vrfName + "~";
RoutingPolicy ripExportPolicy = new RoutingPolicy(ripExportPolicyName, c);
c.getRoutingPolicies().put(ripExportPolicyName, ripExportPolicy);
List<Statement> ripExportStatements = ripExportPolicy.getStatements();
newProcess.setExportPolicy(ripExportPolicyName);
// policy map for default information
if (proc.getDefaultInformationOriginate()) {
If ripExportDefault = new If();
ripExportStatements.add(ripExportDefault);
ripExportDefault.setComment("RIP export default route");
Conjunction ripExportDefaultConditions = new Conjunction();
List<Statement> ripExportDefaultStatements = ripExportDefault.getTrueStatements();
ripExportDefaultConditions.getConjuncts().add(new MatchPrefixSet(new DestinationNetwork(), new ExplicitPrefixSet(new PrefixSpace(Collections.singleton(new PrefixRange(Prefix.ZERO, new SubRange(0, 0)))))));
long metric = proc.getDefaultInformationMetric();
ripExportDefaultStatements.add(new SetMetric(new LiteralLong(metric)));
// add default export map with metric
String defaultOriginateMapName = proc.getDefaultInformationOriginateMap();
if (defaultOriginateMapName != null) {
int defaultOriginateMapLine = proc.getDefaultInformationOriginateMapLine();
RoutingPolicy ripDefaultGenerationPolicy = c.getRoutingPolicies().get(defaultOriginateMapName);
if (ripDefaultGenerationPolicy == null) {
undefined(CiscoStructureType.ROUTE_MAP, defaultOriginateMapName, CiscoStructureUsage.RIP_DEFAULT_ORIGINATE_ROUTE_MAP, defaultOriginateMapLine);
} else {
RouteMap generationRouteMap = _routeMaps.get(defaultOriginateMapName);
generationRouteMap.getReferers().put(proc, "rip 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 {
// 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());
}
ripExportDefaultConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.AGGREGATE));
ripExportDefaultStatements.add(Statements.ExitAccept.toStaticStatement());
ripExportDefault.setGuard(ripExportDefaultConditions);
}
// policy for redistributing connected routes
RipRedistributionPolicy rcp = proc.getRedistributionPolicies().get(RoutingProtocol.CONNECTED);
if (rcp != null) {
If ripExportConnected = new If();
ripExportConnected.setComment("RIP export connected routes");
Conjunction ripExportConnectedConditions = new Conjunction();
ripExportConnectedConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.CONNECTED));
List<Statement> ripExportConnectedStatements = ripExportConnected.getTrueStatements();
Long metric = rcp.getMetric();
boolean explicitMetric = metric != null;
if (!explicitMetric) {
metric = RipRedistributionPolicy.DEFAULT_REDISTRIBUTE_CONNECTED_METRIC;
}
ripExportStatements.add(new SetMetric(new LiteralLong(metric)));
ripExportStatements.add(ripExportConnected);
// 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.RIP_REDISTRIBUTE_CONNECTED_MAP, exportConnectedRouteMapLine);
} else {
exportConnectedRouteMap.getReferers().put(proc, "rip redistribute connected route-map");
ripExportConnectedConditions.getConjuncts().add(new CallExpr(exportConnectedRouteMapName));
}
}
ripExportConnectedStatements.add(Statements.ExitAccept.toStaticStatement());
ripExportConnected.setGuard(ripExportConnectedConditions);
}
// policy map for redistributing static routes
RipRedistributionPolicy rsp = proc.getRedistributionPolicies().get(RoutingProtocol.STATIC);
if (rsp != null) {
If ripExportStatic = new If();
ripExportStatic.setComment("RIP export static routes");
Conjunction ripExportStaticConditions = new Conjunction();
ripExportStaticConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.STATIC));
List<Statement> ripExportStaticStatements = ripExportStatic.getTrueStatements();
ripExportStaticConditions.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();
boolean explicitMetric = metric != null;
if (!explicitMetric) {
metric = RipRedistributionPolicy.DEFAULT_REDISTRIBUTE_STATIC_METRIC;
}
ripExportStatements.add(new SetMetric(new LiteralLong(metric)));
ripExportStatements.add(ripExportStatic);
// 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.RIP_REDISTRIBUTE_STATIC_MAP, exportStaticRouteMapLine);
} else {
exportStaticRouteMap.getReferers().put(proc, "rip redistribute static route-map");
ripExportStaticConditions.getConjuncts().add(new CallExpr(exportStaticRouteMapName));
}
}
ripExportStaticStatements.add(Statements.ExitAccept.toStaticStatement());
ripExportStatic.setGuard(ripExportStaticConditions);
}
// policy map for redistributing bgp routes
RipRedistributionPolicy rbp = proc.getRedistributionPolicies().get(RoutingProtocol.BGP);
if (rbp != null) {
If ripExportBgp = new If();
ripExportBgp.setComment("RIP export bgp routes");
Conjunction ripExportBgpConditions = new Conjunction();
ripExportBgpConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.BGP));
List<Statement> ripExportBgpStatements = ripExportBgp.getTrueStatements();
ripExportBgpConditions.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();
boolean explicitMetric = metric != null;
if (!explicitMetric) {
metric = RipRedistributionPolicy.DEFAULT_REDISTRIBUTE_BGP_METRIC;
}
ripExportStatements.add(new SetMetric(new LiteralLong(metric)));
ripExportStatements.add(ripExportBgp);
// 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.RIP_REDISTRIBUTE_BGP_MAP, exportBgpRouteMapLine);
} else {
exportBgpRouteMap.getReferers().put(proc, "rip redistribute bgp route-map");
ripExportBgpConditions.getConjuncts().add(new CallExpr(exportBgpRouteMapName));
}
}
ripExportBgpStatements.add(Statements.ExitAccept.toStaticStatement());
ripExportBgp.setGuard(ripExportBgpConditions);
}
return newProcess;
}
use of org.batfish.datamodel.routing_policy.statement.SetMetric 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.datamodel.routing_policy.statement.SetMetric in project batfish by batfish.
the class OspfTest method getExportPolicyStatements.
private static List<Statement> getExportPolicyStatements(InterfaceAddress address) {
long externalOspfMetric = 20L;
If exportIfMatchL2Prefix = new If();
exportIfMatchL2Prefix.setGuard(new MatchPrefixSet(new DestinationNetwork(), new ExplicitPrefixSet(new PrefixSpace(ImmutableSet.of(PrefixRange.fromPrefix(address.getPrefix()))))));
exportIfMatchL2Prefix.setTrueStatements(ImmutableList.of(new SetOspfMetricType(OspfMetricType.E1), new SetMetric(new LiteralLong(externalOspfMetric)), Statements.ExitAccept.toStaticStatement()));
exportIfMatchL2Prefix.setFalseStatements(ImmutableList.of(Statements.ExitReject.toStaticStatement()));
return ImmutableList.of(exportIfMatchL2Prefix);
}
Aggregations