use of org.batfish.datamodel.Interface in project batfish by batfish.
the class AbstractionBuilder method createAbstractConfig.
/*
* Creates a new Configuration from an old one for an abstract router
* by copying the old configuration, but removing any concrete interfaces,
* neighbors etc that do not correpond to any abstract neighbors.
*/
private Configuration createAbstractConfig(Set<String> abstractRouters, Configuration conf) {
Configuration abstractConf = new Configuration(conf.getHostname(), conf.getConfigurationFormat());
abstractConf.setDnsServers(conf.getDnsServers());
abstractConf.setDnsSourceInterface(conf.getDnsSourceInterface());
abstractConf.setDomainName(conf.getDomainName());
abstractConf.setAuthenticationKeyChains(conf.getAuthenticationKeyChains());
abstractConf.setIkeGateways(conf.getIkeGateways());
abstractConf.setDefaultCrossZoneAction(conf.getDefaultCrossZoneAction());
abstractConf.setIkePolicies(conf.getIkePolicies());
abstractConf.setIkeProposals(conf.getIkeProposals());
abstractConf.setDefaultInboundAction(conf.getDefaultInboundAction());
abstractConf.setIpAccessLists(conf.getIpAccessLists());
abstractConf.setIp6AccessLists(conf.getIp6AccessLists());
abstractConf.setRouteFilterLists(conf.getRouteFilterLists());
abstractConf.setRoute6FilterLists(conf.getRoute6FilterLists());
abstractConf.setIpsecPolicies(conf.getIpsecPolicies());
abstractConf.setIpsecProposals(conf.getIpsecProposals());
abstractConf.setIpsecVpns(conf.getIpsecVpns());
abstractConf.setLoggingServers(conf.getLoggingServers());
abstractConf.setLoggingSourceInterface(conf.getLoggingSourceInterface());
abstractConf.setNormalVlanRange(conf.getNormalVlanRange());
abstractConf.setNtpServers(conf.getNtpServers());
abstractConf.setNtpSourceInterface(conf.getNtpSourceInterface());
abstractConf.setRoles(conf.getRoles());
abstractConf.setSnmpSourceInterface(conf.getSnmpSourceInterface());
abstractConf.setSnmpTrapServers(conf.getSnmpTrapServers());
abstractConf.setTacacsServers(conf.getTacacsServers());
abstractConf.setTacacsSourceInterface(conf.getTacacsSourceInterface());
abstractConf.setVendorFamily(conf.getVendorFamily());
abstractConf.setZones(conf.getZones());
abstractConf.setCommunityLists(conf.getCommunityLists());
abstractConf.setRoutingPolicies(conf.getRoutingPolicies());
abstractConf.setRoute6FilterLists(conf.getRoute6FilterLists());
SortedSet<Interface> toRetain = new TreeSet<>();
SortedSet<IpLink> ipNeighbors = new TreeSet<>();
SortedSet<BgpNeighbor> bgpNeighbors = new TreeSet<>();
List<GraphEdge> edges = _graph.getEdgeMap().get(conf.getName());
for (GraphEdge ge : edges) {
boolean leavesNetwork = (ge.getPeer() == null);
if (leavesNetwork || (abstractRouters.contains(ge.getRouter()) && abstractRouters.contains(ge.getPeer()))) {
toRetain.add(ge.getStart());
Ip start = ge.getStart().getAddress().getIp();
if (!leavesNetwork) {
Ip end = ge.getEnd().getAddress().getIp();
ipNeighbors.add(new IpLink(start, end));
}
BgpNeighbor n = _graph.getEbgpNeighbors().get(ge);
if (n != null) {
bgpNeighbors.add(n);
}
}
}
// Update interfaces
NavigableMap<String, Interface> abstractInterfaces = new TreeMap<>();
for (Entry<String, Interface> entry : conf.getInterfaces().entrySet()) {
String name = entry.getKey();
Interface iface = entry.getValue();
if (toRetain.contains(iface)) {
abstractInterfaces.put(name, iface);
}
}
abstractConf.setInterfaces(abstractInterfaces);
// Update VRFs
Map<String, Vrf> abstractVrfs = new HashMap<>();
for (Entry<String, Vrf> entry : conf.getVrfs().entrySet()) {
String name = entry.getKey();
Vrf vrf = entry.getValue();
Vrf abstractVrf = new Vrf(name);
abstractVrf.setStaticRoutes(vrf.getStaticRoutes());
abstractVrf.setIsisProcess(vrf.getIsisProcess());
abstractVrf.setRipProcess(vrf.getRipProcess());
abstractVrf.setSnmpServer(vrf.getSnmpServer());
NavigableMap<String, Interface> abstractVrfInterfaces = new TreeMap<>();
for (Entry<String, Interface> entry2 : vrf.getInterfaces().entrySet()) {
String iname = entry2.getKey();
Interface iface = entry2.getValue();
if (toRetain.contains(iface)) {
abstractVrfInterfaces.put(iname, iface);
}
}
abstractVrf.setInterfaces(abstractVrfInterfaces);
abstractVrf.setInterfaceNames(new TreeSet<>(abstractVrfInterfaces.keySet()));
OspfProcess ospf = vrf.getOspfProcess();
if (ospf != null) {
OspfProcess abstractOspf = new OspfProcess();
abstractOspf.setAreas(ospf.getAreas());
abstractOspf.setExportPolicy(ospf.getExportPolicy());
abstractOspf.setReferenceBandwidth(ospf.getReferenceBandwidth());
abstractOspf.setRouterId(ospf.getRouterId());
// Copy over neighbors
Map<IpLink, OspfNeighbor> abstractNeighbors = new HashMap<>();
if (ospf.getOspfNeighbors() != null) {
for (Entry<IpLink, OspfNeighbor> entry2 : ospf.getOspfNeighbors().entrySet()) {
IpLink link = entry2.getKey();
OspfNeighbor neighbor = entry2.getValue();
if (ipNeighbors.contains(link)) {
abstractNeighbors.put(link, neighbor);
}
}
}
abstractOspf.setOspfNeighbors(abstractNeighbors);
abstractVrf.setOspfProcess(abstractOspf);
}
BgpProcess bgp = vrf.getBgpProcess();
if (bgp != null) {
BgpProcess abstractBgp = new BgpProcess();
abstractBgp.setMultipathEbgp(bgp.getMultipathEbgp());
abstractBgp.setMultipathIbgp(bgp.getMultipathIbgp());
abstractBgp.setRouterId(bgp.getRouterId());
abstractBgp.setOriginationSpace(bgp.getOriginationSpace());
// TODO: set bgp neighbors accordingly
// Copy over neighbors
SortedMap<Prefix, BgpNeighbor> abstractBgpNeighbors = new TreeMap<>();
if (bgp.getNeighbors() != null) {
for (Entry<Prefix, BgpNeighbor> entry2 : bgp.getNeighbors().entrySet()) {
Prefix prefix = entry2.getKey();
BgpNeighbor neighbor = entry2.getValue();
if (bgpNeighbors.contains(neighbor)) {
abstractBgpNeighbors.put(prefix, neighbor);
}
}
}
abstractBgp.setNeighbors(abstractBgpNeighbors);
abstractVrf.setBgpProcess(abstractBgp);
}
abstractVrfs.put(name, abstractVrf);
}
abstractConf.setVrfs(abstractVrfs);
return abstractConf;
}
use of org.batfish.datamodel.Interface in project batfish by batfish.
the class EncoderSlice method addExportConstraint.
/*
* Creates the transfer function to represent export filters
* between two symbolic records. The import filter depends
* heavily on the protocol.
*/
private void addExportConstraint(LogicalEdge e, SymbolicRoute varsOther, @Nullable SymbolicRoute ospfRedistribVars, @Nullable SymbolicRoute overallBest, Configuration conf, Protocol proto, GraphEdge ge, String router, boolean usedExport, Set<Prefix> originations) {
SymbolicRoute vars = e.getSymbolicRecord();
Interface iface = ge.getStart();
ArithExpr failed = getSymbolicFailures().getFailedVariable(e.getEdge());
assert (failed != null);
BoolExpr notFailed = mkEq(failed, mkInt(0));
// only add constraints once when using a single copy of export variables
if (!_optimizations.getSliceCanKeepSingleExportVar().get(router).get(proto) || !usedExport) {
if (proto.isConnected()) {
BoolExpr val = mkNot(vars.getPermitted());
add(val);
}
if (proto.isStatic()) {
BoolExpr val = mkNot(vars.getPermitted());
add(val);
}
if (proto.isOspf() || proto.isBgp()) {
// BGP cost based on export
Integer cost = proto.isBgp() ? addedCost(proto, ge) : 0;
BoolExpr val = mkNot(vars.getPermitted());
BoolExpr active = interfaceActive(iface, proto);
// Apply BGP export policy and cost based on peer type
// (1) EBGP --> ALL
// (2) CLIENT --> ALL
// (3) NONCLIENT --> EBGP, CLIENT
boolean isNonClientEdge = proto.isBgp() && getGraph().peerType(ge) != Graph.BgpSendType.TO_EBGP;
boolean isClientEdge = proto.isBgp() && getGraph().peerType(ge) == Graph.BgpSendType.TO_CLIENT;
boolean isInternalExport = varsOther.isBest() && _optimizations.getNeedBgpInternal().contains(router);
BoolExpr doExport = mkTrue();
if (isInternalExport && proto.isBgp() && isNonClientEdge) {
if (isClientEdge) {
cost = 0;
} else {
// Lookup if we learned from iBGP, and if so, don't export the route
SymbolicRoute other = getBestNeighborPerProtocol(router, proto);
assert other != null;
assert other.getBgpInternal() != null;
if (other.getBgpInternal() != null) {
doExport = mkNot(other.getBgpInternal());
cost = 0;
}
}
}
BoolExpr acc;
RoutingPolicy pol = getGraph().findExportRoutingPolicy(router, proto, e.getEdge());
if (Encoder.ENABLE_DEBUGGING && pol != null) {
System.out.println("Export policy (" + _sliceName + "," + ge + "): " + pol.getName());
}
// We have to wrap this with the right thing for some reason
List<Statement> statements;
Statements.StaticStatement s1 = new Statements.StaticStatement(Statements.ExitAccept);
Statements.StaticStatement s2 = new Statements.StaticStatement(Statements.ExitReject);
if (proto.isOspf()) {
If i = new If();
List<Statement> stmts = (pol == null ? Collections.singletonList(s2) : pol.getStatements());
i.setTrueStatements(Collections.singletonList(s1));
i.setFalseStatements(stmts);
BooleanExpr expr = new MatchProtocol(RoutingProtocol.OSPF);
i.setGuard(expr);
statements = Collections.singletonList(i);
} else {
statements = (pol == null ? Collections.singletonList(s1) : pol.getStatements());
}
TransferSSA f = new TransferSSA(this, conf, varsOther, vars, proto, statements, cost, ge, true);
acc = f.compute();
BoolExpr usable = mkAnd(active, doExport, varsOther.getPermitted(), notFailed);
// will maintain the same preference when adding to the cost.
if (ospfRedistribVars != null) {
assert overallBest != null;
f = new TransferSSA(this, conf, overallBest, ospfRedistribVars, proto, statements, cost, ge, true);
BoolExpr acc2 = f.compute();
// System.out.println("ADDING: \n" + acc2.simplify());
add(acc2);
BoolExpr usable2 = mkAnd(active, doExport, ospfRedistribVars.getPermitted(), notFailed);
BoolExpr geq = greaterOrEqual(conf, proto, ospfRedistribVars, varsOther, e);
BoolExpr isBetter = mkNot(mkAnd(ospfRedistribVars.getPermitted(), geq));
BoolExpr usesOspf = mkAnd(varsOther.getPermitted(), isBetter);
BoolExpr eq = equal(conf, proto, ospfRedistribVars, vars, e, false);
BoolExpr eqPer = mkEq(ospfRedistribVars.getPermitted(), vars.getPermitted());
acc = mkIf(usesOspf, mkIf(usable, acc, val), mkIf(usable2, mkAnd(eq, eqPer), val));
} else {
acc = mkIf(usable, acc, val);
}
for (Prefix p : originations) {
// For OSPF, we need to explicitly initiate a route
if (proto.isOspf()) {
BoolExpr ifaceUp = interfaceActive(iface, proto);
BoolExpr relevantPrefix = isRelevantFor(p, _symbolicPacket.getDstIp());
BoolExpr relevant = mkAnd(ifaceUp, relevantPrefix);
int adminDistance = defaultAdminDistance(conf, proto);
int prefixLength = p.getPrefixLength();
BoolExpr per = vars.getPermitted();
BoolExpr lp = safeEq(vars.getLocalPref(), mkInt(0));
BoolExpr ad = safeEq(vars.getAdminDist(), mkInt(adminDistance));
BoolExpr met = safeEq(vars.getMetric(), mkInt(cost));
BoolExpr med = safeEq(vars.getMed(), mkInt(100));
BoolExpr len = safeEq(vars.getPrefixLength(), mkInt(prefixLength));
BoolExpr type = safeEqEnum(vars.getOspfType(), OspfType.O);
BoolExpr area = safeEqEnum(vars.getOspfArea(), iface.getOspfAreaName());
BoolExpr internal = safeEq(vars.getBgpInternal(), mkFalse());
BoolExpr igpMet = safeEq(vars.getIgpMetric(), mkInt(0));
BoolExpr comms = mkTrue();
for (Map.Entry<CommunityVar, BoolExpr> entry : vars.getCommunities().entrySet()) {
comms = mkAnd(comms, mkNot(entry.getValue()));
}
BoolExpr values = mkAnd(per, lp, ad, met, med, len, type, area, internal, igpMet, comms);
// Don't originate OSPF route when there is a better redistributed route
if (ospfRedistribVars != null) {
BoolExpr betterLen = mkGt(ospfRedistribVars.getPrefixLength(), mkInt(prefixLength));
BoolExpr equalLen = mkEq(ospfRedistribVars.getPrefixLength(), mkInt(prefixLength));
BoolExpr betterAd = mkLt(ospfRedistribVars.getAdminDist(), mkInt(110));
BoolExpr better = mkOr(betterLen, mkAnd(equalLen, betterAd));
BoolExpr betterRedistributed = mkAnd(ospfRedistribVars.getPermitted(), better);
relevant = mkAnd(relevant, mkNot(betterRedistributed));
}
acc = mkIf(relevant, values, acc);
}
}
add(acc);
if (Encoder.ENABLE_DEBUGGING) {
System.out.println("EXPORT: " + router + " " + varsOther.getName() + " " + ge);
System.out.println(acc.simplify());
System.out.println("\n\n");
}
}
}
}
use of org.batfish.datamodel.Interface in project batfish by batfish.
the class EncoderSlice method addImportConstraint.
/*
* Creates the transfer function to represent import filters
* between two symbolic records. The import filter depends
* heavily on the protocol.
*/
private void addImportConstraint(LogicalEdge e, SymbolicRoute varsOther, Configuration conf, Protocol proto, GraphEdge ge, String router) {
SymbolicRoute vars = e.getSymbolicRecord();
Interface iface = ge.getStart();
ArithExpr failed = getSymbolicFailures().getFailedVariable(e.getEdge());
assert (failed != null);
BoolExpr notFailed = mkEq(failed, mkInt(0));
if (vars.getIsUsed()) {
if (proto.isConnected()) {
Prefix p = iface.getAddress().getPrefix();
BoolExpr relevant = mkAnd(interfaceActive(iface, proto), isRelevantFor(p, _symbolicPacket.getDstIp()), notFailed);
BoolExpr per = vars.getPermitted();
BoolExpr len = safeEq(vars.getPrefixLength(), mkInt(p.getPrefixLength()));
BoolExpr ad = safeEq(vars.getAdminDist(), mkInt(1));
BoolExpr lp = safeEq(vars.getLocalPref(), mkInt(0));
BoolExpr met = safeEq(vars.getMetric(), mkInt(0));
BoolExpr values = mkAnd(per, len, ad, lp, met);
add(mkIf(relevant, values, mkNot(vars.getPermitted())));
}
if (proto.isStatic()) {
List<StaticRoute> srs = getGraph().getStaticRoutes().get(router, iface.getName());
assert (srs != null);
BoolExpr acc = mkNot(vars.getPermitted());
for (StaticRoute sr : srs) {
Prefix p = sr.getNetwork();
BoolExpr relevant = mkAnd(interfaceActive(iface, proto), isRelevantFor(p, _symbolicPacket.getDstIp()), notFailed);
BoolExpr per = vars.getPermitted();
BoolExpr len = safeEq(vars.getPrefixLength(), mkInt(p.getPrefixLength()));
BoolExpr ad = safeEq(vars.getAdminDist(), mkInt(sr.getAdministrativeCost()));
BoolExpr lp = safeEq(vars.getLocalPref(), mkInt(0));
BoolExpr met = safeEq(vars.getMetric(), mkInt(0));
BoolExpr values = mkAnd(per, len, ad, lp, met);
acc = mkIf(relevant, values, acc);
}
add(acc);
}
if (proto.isOspf() || proto.isBgp()) {
BoolExpr val = mkNot(vars.getPermitted());
if (varsOther != null) {
// BoolExpr isRoot = relevantOrigination(originations);
BoolExpr active = interfaceActive(iface, proto);
// Handle iBGP by checking reachability to the next hop to send messages
boolean isNonClient = (proto.isBgp()) && (getGraph().peerType(ge) != Graph.BgpSendType.TO_EBGP);
boolean isClient = (proto.isBgp()) && (getGraph().peerType(ge) == Graph.BgpSendType.TO_RR);
BoolExpr receiveMessage;
String currentRouter = ge.getRouter();
String peerRouter = ge.getPeer();
if (_encoder.getModelIgp() && isNonClient) {
// Lookup reachabilty based on peer next-hop
receiveMessage = _encoder.getSliceReachability().get(currentRouter).get(peerRouter);
/* EncoderSlice peerSlice = _encoder.getSlice(peerRouter);
BoolExpr srcPort = mkEq(peerSlice.getSymbolicPacket().getSrcPort(), mkInt(179));
BoolExpr srcIp = mkEq(peerSlice.getSymbolicPacket().getSrcIp(), mkInt(0));
BoolExpr tcpAck = mkEq(peerSlice.getSymbolicPacket().getTcpAck(), mkFalse());
BoolExpr tcpCwr = mkEq(peerSlice.getSymbolicPacket().getTcpCwr(), mkFalse());
BoolExpr tcpEce = mkEq(peerSlice.getSymbolicPacket().getTcpEce(), mkFalse());
BoolExpr tcpFin = mkEq(peerSlice.getSymbolicPacket().getTcpFin(), mkFalse());
BoolExpr tcpPsh = mkEq(peerSlice.getSymbolicPacket().getTcpPsh(), mkFalse());
BoolExpr tcpRst = mkEq(peerSlice.getSymbolicPacket().getTcpRst(), mkFalse());
BoolExpr tcpSyn = mkEq(peerSlice.getSymbolicPacket().getTcpSyn(), mkFalse());
BoolExpr tcpUrg = mkEq(peerSlice.getSymbolicPacket().getTcpUrg(), mkFalse());
BoolExpr icmpCode = mkEq(peerSlice.getSymbolicPacket().getIcmpCode(), mkInt(0));
BoolExpr icmpType = mkEq(peerSlice.getSymbolicPacket().getIcmpType(), mkInt(0));
BoolExpr all =
mkAnd(srcPort, srcIp, tcpAck,
tcpCwr, tcpEce, tcpFin, tcpPsh, tcpRst, tcpSyn, tcpUrg, icmpCode, icmpType);
receiveMessage = mkImplies(all, receiveMessage); */
} else if (_encoder.getModelIgp() && isClient) {
// Lookup reachability based on client id tag to find next hop
BoolExpr acc = mkTrue();
for (Map.Entry<String, Integer> entry : getGraph().getOriginatorId().entrySet()) {
String r = entry.getKey();
Integer id = entry.getValue();
if (!r.equals(currentRouter)) {
BoolExpr reach = _encoder.getSliceReachability().get(currentRouter).get(r);
/* EncoderSlice peerSlice = _encoder.getSlice(r);
BoolExpr srcPort = mkEq(peerSlice.getSymbolicPacket().getSrcPort(), mkInt(179));
BoolExpr srcIp = mkEq(peerSlice.getSymbolicPacket().getSrcIp(), mkInt(0));
BoolExpr tcpAck = mkEq(peerSlice.getSymbolicPacket().getTcpAck(), mkFalse());
BoolExpr tcpCwr = mkEq(peerSlice.getSymbolicPacket().getTcpCwr(), mkFalse());
BoolExpr tcpEce = mkEq(peerSlice.getSymbolicPacket().getTcpEce(), mkFalse());
BoolExpr tcpFin = mkEq(peerSlice.getSymbolicPacket().getTcpFin(), mkFalse());
BoolExpr tcpPsh = mkEq(peerSlice.getSymbolicPacket().getTcpPsh(), mkFalse());
BoolExpr tcpRst = mkEq(peerSlice.getSymbolicPacket().getTcpRst(), mkFalse());
BoolExpr tcpSyn = mkEq(peerSlice.getSymbolicPacket().getTcpSyn(), mkFalse());
BoolExpr tcpUrg = mkEq(peerSlice.getSymbolicPacket().getTcpUrg(), mkFalse());
BoolExpr icmpCode = mkEq(peerSlice.getSymbolicPacket().getIcmpCode(), mkInt(0));
BoolExpr icmpType = mkEq(peerSlice.getSymbolicPacket().getIcmpType(), mkInt(0));
BoolExpr all =
mkAnd(srcPort, srcIp, tcpAck,
tcpCwr, tcpEce, tcpFin, tcpPsh, tcpRst, tcpSyn, tcpUrg, icmpCode, icmpType);
reach = mkImplies(all, reach); */
acc = mkAnd(acc, mkImplies(varsOther.getClientId().checkIfValue(id), reach));
}
}
receiveMessage = acc;
// Just check if the link is failed
} else {
receiveMessage = notFailed;
}
// Take into account BGP loop prevention
// The path length will prevent any isolated loops
BoolExpr loop = mkFalse();
if (proto.isBgp() && ge.getPeer() != null) {
String peer = ge.getPeer();
GraphEdge gePeer = getGraph().getOtherEnd().get(ge);
loop = getSymbolicDecisions().getControlForwarding().get(peer, gePeer);
}
assert (loop != null);
BoolExpr usable = mkAnd(mkNot(loop), active, varsOther.getPermitted(), receiveMessage);
BoolExpr importFunction;
RoutingPolicy pol = getGraph().findImportRoutingPolicy(router, proto, e.getEdge());
if (Encoder.ENABLE_DEBUGGING && pol != null) {
System.out.println("Import Policy: " + pol.getName());
}
List<Statement> statements;
if (pol == null) {
Statements.StaticStatement s = new Statements.StaticStatement(Statements.ExitAccept);
statements = Collections.singletonList(s);
} else {
statements = pol.getStatements();
}
// OSPF cost calculated based on incoming interface
Integer cost = proto.isOspf() ? addedCost(proto, ge) : 0;
TransferSSA f = new TransferSSA(this, conf, varsOther, vars, proto, statements, cost, ge, false);
importFunction = f.compute();
BoolExpr acc = mkIf(usable, importFunction, val);
if (Encoder.ENABLE_DEBUGGING) {
System.out.println("IMPORT FUNCTION: " + router + " " + varsOther.getName());
System.out.println(importFunction.simplify());
System.out.println("\n\n");
}
add(acc);
} else {
add(val);
}
}
}
}
use of org.batfish.datamodel.Interface in project batfish by batfish.
the class EncoderSlice method initAclFunctions.
/*
* Initialize boolean expressions to represent ACLs on each interface.
*/
private void initAclFunctions() {
for (Entry<String, List<GraphEdge>> entry : getGraph().getEdgeMap().entrySet()) {
String router = entry.getKey();
List<GraphEdge> edges = entry.getValue();
for (GraphEdge ge : edges) {
Interface i = ge.getStart();
IpAccessList outbound = i.getOutgoingFilter();
if (outbound != null) {
String outName = String.format("%d_%s_%s_%s_%s_%s", _encoder.getId(), _sliceName, router, i.getName(), "OUTBOUND", outbound.getName());
BoolExpr outAcl = getCtx().mkBoolConst(outName);
BoolExpr outAclFunc = computeACL(outbound);
add(mkEq(outAcl, outAclFunc));
_outboundAcls.put(ge, outAcl);
}
IpAccessList inbound = i.getIncomingFilter();
if (inbound != null) {
String inName = String.format("%d_%s_%s_%s_%s_%s", _encoder.getId(), _sliceName, router, i.getName(), "INBOUND", inbound.getName());
BoolExpr inAcl = getCtx().mkBoolConst(inName);
BoolExpr inAclFunc = computeACL(inbound);
add(mkEq(inAcl, inAclFunc));
_inboundAcls.put(ge, inAcl);
}
}
}
}
use of org.batfish.datamodel.Interface in project batfish by batfish.
the class Optimizations method computeCanMergeExportVars.
/*
* Determines when we can merge export variables into a single copy.
* This will be safe when there is no peer-specific export filter.
*/
private void computeCanMergeExportVars() {
Graph g = _encoderSlice.getGraph();
HeaderQuestion q = _encoderSlice.getEncoder().getQuestion();
boolean noFailures = q.getFailures() == 0;
_encoderSlice.getGraph().getConfigurations().forEach((router, conf) -> {
HashMap<Protocol, Boolean> map = new HashMap<>();
_sliceCanKeepSingleExportVar.put(router, map);
// the neighbor already being the root of the tree.
for (Protocol proto : getProtocols().get(router)) {
if (proto.isConnected() || proto.isStatic()) {
map.put(proto, noFailures && Optimizations.ENABLE_EXPORT_MERGE_OPTIMIZATION);
} else if (proto.isOspf()) {
// Ensure all interfaces are active
boolean allIfacesActive = true;
for (GraphEdge edge : g.getEdgeMap().get(router)) {
if (g.isEdgeUsed(conf, proto, edge)) {
Interface iface = edge.getStart();
allIfacesActive = allIfacesActive && g.isInterfaceActive(proto, iface);
}
}
// Ensure single area for this router
Set<Long> areas = _encoderSlice.getGraph().getAreaIds().get(router);
boolean singleArea = areas.size() <= 1;
map.put(proto, noFailures && allIfacesActive && singleArea && ENABLE_EXPORT_MERGE_OPTIMIZATION);
} else if (proto.isBgp()) {
boolean acc = true;
BgpProcess p = conf.getDefaultVrf().getBgpProcess();
for (Map.Entry<Prefix, BgpNeighbor> e : p.getNeighbors().entrySet()) {
BgpNeighbor n = e.getValue();
// If iBGP used, then don't merge
if (n.getLocalAs().equals(n.getRemoteAs())) {
acc = false;
break;
}
// If not the default export policy, then don't merge
if (!isDefaultBgpExport(conf, n)) {
acc = false;
break;
}
}
map.put(proto, noFailures && acc && ENABLE_EXPORT_MERGE_OPTIMIZATION);
} else {
throw new BatfishException("Error: unkown protocol: " + proto.name());
}
}
});
}
Aggregations