use of org.batfish.symbolic.Protocol in project batfish by batfish.
the class EncoderSlice method addEnvironmentVariables.
/*
* Initialize all environment symbolic records for BGP.
*/
private void addEnvironmentVariables() {
// If not the main slice, just use the main slice
if (!isMainSlice()) {
Map<LogicalEdge, SymbolicRoute> envs = _logicalGraph.getEnvironmentVars();
EncoderSlice main = _encoder.getMainSlice();
LogicalGraph lg = main.getLogicalGraph();
Map<LogicalEdge, SymbolicRoute> existing = lg.getEnvironmentVars();
envs.putAll(existing);
return;
}
// Otherwise create it anew
for (String router : getGraph().getRouters()) {
for (Protocol proto : getProtocols().get(router)) {
if (proto.isBgp()) {
List<ArrayList<LogicalEdge>> les = _logicalGraph.getLogicalEdges().get(router, proto);
assert (les != null);
for (ArrayList<LogicalEdge> eList : les) {
for (LogicalEdge e : eList) {
if (e.getEdgeType() == EdgeType.IMPORT) {
GraphEdge ge = e.getEdge();
BgpNeighbor n = getGraph().getEbgpNeighbors().get(ge);
if (n != null && ge.getEnd() == null) {
if (!isMainSlice()) {
LogicalGraph lg = _encoder.getMainSlice().getLogicalGraph();
SymbolicRoute r = lg.getEnvironmentVars().get(e);
_logicalGraph.getEnvironmentVars().put(e, r);
} else {
String address;
if (n.getAddress() == null) {
address = "null";
} else {
address = n.getAddress().toString();
}
String ifaceName = "ENV-" + address;
String name = String.format("%d_%s%s_%s_%s_%s", _encoder.getId(), _sliceName, router, proto.name(), "EXPORT", ifaceName);
SymbolicRoute vars = new SymbolicRoute(this, name, router, proto, _optimizations, null, ge.isAbstract());
getAllSymbolicRecords().add(vars);
_logicalGraph.getEnvironmentVars().put(e, vars);
}
}
}
}
}
}
}
}
}
use of org.batfish.symbolic.Protocol in project batfish by batfish.
the class EncoderSlice method addSymbolicRecords.
/*
* Initialize all control-plane message symbolic records.
* Also maps each logical graph edge to its opposite edge.
*/
private void addSymbolicRecords() {
Map<String, Map<Protocol, Map<GraphEdge, ArrayList<LogicalEdge>>>> importInverseMap = new HashMap<>();
Map<String, Map<Protocol, Map<GraphEdge, ArrayList<LogicalEdge>>>> exportInverseMap = new HashMap<>();
Map<String, Map<Protocol, SymbolicRoute>> singleExportMap = new HashMap<>();
// add edge EXPORT and IMPORT state variables
for (Entry<String, List<GraphEdge>> entry : getGraph().getEdgeMap().entrySet()) {
String router = entry.getKey();
List<GraphEdge> edges = entry.getValue();
Map<Protocol, SymbolicRoute> singleProtoMap;
singleProtoMap = new HashMap<>();
Map<Protocol, Map<GraphEdge, ArrayList<LogicalEdge>>> importEnumMap;
importEnumMap = new HashMap<>();
Map<Protocol, Map<GraphEdge, ArrayList<LogicalEdge>>> exportEnumMap;
exportEnumMap = new HashMap<>();
singleExportMap.put(router, singleProtoMap);
importInverseMap.put(router, importEnumMap);
exportInverseMap.put(router, exportEnumMap);
for (Protocol proto : getProtocols().get(router)) {
// Add redistribution variables
Set<Protocol> r = _logicalGraph.getRedistributedProtocols().get(router, proto);
assert r != null;
if (proto.isOspf() && r.size() > 1) {
// Add the ospf redistributed record if needed
String rname = String.format("%d_%s%s_%s_%s", _encoder.getId(), _sliceName, router, proto.name(), "Redistributed");
SymbolicRoute rec = new SymbolicRoute(this, rname, router, proto, _optimizations, null, false);
_ospfRedistributed.put(router, rec);
getAllSymbolicRecords().add(rec);
}
Boolean useSingleExport = _optimizations.getSliceCanKeepSingleExportVar().get(router, proto);
assert (useSingleExport != null);
Map<GraphEdge, ArrayList<LogicalEdge>> importGraphEdgeMap = new HashMap<>();
Map<GraphEdge, ArrayList<LogicalEdge>> exportGraphEdgeMap = new HashMap<>();
importEnumMap.put(proto, importGraphEdgeMap);
exportEnumMap.put(proto, exportGraphEdgeMap);
for (GraphEdge e : edges) {
Configuration conf = getGraph().getConfigurations().get(router);
if (getGraph().isEdgeUsed(conf, proto, e)) {
ArrayList<LogicalEdge> importEdgeList = new ArrayList<>();
ArrayList<LogicalEdge> exportEdgeList = new ArrayList<>();
importGraphEdgeMap.put(e, importEdgeList);
exportGraphEdgeMap.put(e, exportEdgeList);
for (int len = 0; len <= BITS; len++) {
String ifaceName = e.getStart().getName();
if (!proto.isConnected() && !proto.isStatic()) {
// to reuse the existing variables instead of creating new ones
if (useSingleExport) {
SymbolicRoute singleVars = singleExportMap.get(router).get(proto);
SymbolicRoute ev1;
if (singleVars == null) {
String name = String.format("%d_%s%s_%s_%s_%s", _encoder.getId(), _sliceName, router, proto.name(), "SINGLE-EXPORT", "");
ev1 = new SymbolicRoute(this, name, router, proto, _optimizations, null, e.isAbstract());
singleProtoMap.put(proto, ev1);
getAllSymbolicRecords().add(ev1);
} else {
ev1 = singleVars;
}
LogicalEdge eExport = new LogicalEdge(e, EdgeType.EXPORT, ev1);
exportEdgeList.add(eExport);
} else {
String name = String.format("%d_%s%s_%s_%s_%s", _encoder.getId(), _sliceName, router, proto.name(), "EXPORT", ifaceName);
SymbolicRoute ev1 = new SymbolicRoute(this, name, router, proto, _optimizations, null, e.isAbstract());
LogicalEdge eExport = new LogicalEdge(e, EdgeType.EXPORT, ev1);
exportEdgeList.add(eExport);
getAllSymbolicRecords().add(ev1);
}
}
boolean notNeeded = _optimizations.getSliceCanCombineImportExportVars().get(router).get(proto).contains(e);
Interface i = e.getStart();
Prefix p = i.getAddress().getPrefix();
boolean doModel = !(proto.isConnected() && p != null && !relevantPrefix(p));
// PolicyQuotient: Don't model the connected interfaces that aren't relevant
if (doModel) {
if (notNeeded) {
String name = String.format("%d_%s%s_%s_%s_%s", _encoder.getId(), _sliceName, router, proto.name(), "IMPORT", ifaceName);
SymbolicRoute ev2 = new SymbolicRoute(name, proto);
LogicalEdge eImport = new LogicalEdge(e, EdgeType.IMPORT, ev2);
importEdgeList.add(eImport);
} else {
String name = String.format("%d_%s%s_%s_%s_%s", _encoder.getId(), _sliceName, router, proto.name(), "IMPORT", ifaceName);
SymbolicRoute ev2 = new SymbolicRoute(this, name, router, proto, _optimizations, null, e.isAbstract());
LogicalEdge eImport = new LogicalEdge(e, EdgeType.IMPORT, ev2);
importEdgeList.add(eImport);
getAllSymbolicRecords().add(ev2);
}
}
}
List<ArrayList<LogicalEdge>> es = _logicalGraph.getLogicalEdges().get(router, proto);
assert (es != null);
ArrayList<LogicalEdge> allEdges = new ArrayList<>();
allEdges.addAll(importEdgeList);
allEdges.addAll(exportEdgeList);
es.add(allEdges);
}
}
}
}
// Build a map to find the opposite of a given edge
_logicalGraph.getLogicalEdges().forEach((router, edgeLists) -> {
for (Protocol proto : getProtocols().get(router)) {
for (ArrayList<LogicalEdge> edgeList : edgeLists.get(proto)) {
for (LogicalEdge e : edgeList) {
GraphEdge edge = e.getEdge();
Map<GraphEdge, ArrayList<LogicalEdge>> m;
if (edge.getPeer() != null) {
if (e.getEdgeType() == EdgeType.IMPORT) {
m = exportInverseMap.get(edge.getPeer()).get(proto);
} else {
m = importInverseMap.get(edge.getPeer()).get(proto);
}
if (m != null) {
GraphEdge otherEdge = getGraph().getOtherEnd().get(edge);
ArrayList<LogicalEdge> list = m.get(otherEdge);
if (list == null) {
m.put(otherEdge, new ArrayList<>());
} else if (list.size() > 0) {
LogicalEdge other = list.get(0);
_logicalGraph.getOtherEnd().put(e, other);
}
}
}
}
}
}
});
}
use of org.batfish.symbolic.Protocol in project batfish by batfish.
the class Optimizations method initProtocols.
/*
* Determine which protocols need to be modeled given the range of
* destination IPs specified by the encoder.
*/
private void initProtocols() {
Graph g = _encoderSlice.getGraph();
g.getConfigurations().forEach((router, conf) -> getProtocols().put(router, new ArrayList<>()));
g.getConfigurations().forEach((router, conf) -> {
List<Protocol> protos = getProtocols().get(router);
if (conf.getDefaultVrf().getOspfProcess() != null) {
protos.add(Protocol.OSPF);
}
// TODO: do we want to model BGP's impact on IGP in other slices?
if (conf.getDefaultVrf().getBgpProcess() != null && _encoderSlice.isMainSlice()) {
protos.add(Protocol.BGP);
}
if (needToModelConnected(conf)) {
protos.add(Protocol.CONNECTED);
}
if (needToModelStatic(conf)) {
protos.add(Protocol.STATIC);
}
});
}
use of org.batfish.symbolic.Protocol in project batfish by batfish.
the class Optimizations method hasExportVariables.
/*
* Check if a graph edge will have export variables for a given protocol.
* This will happen when the edge's interface is used in the protocol
* and the other end of the interface is internal.
*/
private boolean hasExportVariables(GraphEdge e, Protocol proto) {
if (e.getEnd() != null) {
String peer = e.getPeer();
List<Protocol> peerProtocols = getProtocols().get(peer);
if (peerProtocols.contains(proto)) {
Configuration peerConf = _encoderSlice.getGraph().getConfigurations().get(peer);
GraphEdge other = _encoderSlice.getGraph().getOtherEnd().get(e);
if (_encoderSlice.getGraph().isEdgeUsed(peerConf, proto, other)) {
return true;
}
}
}
return false;
}
use of org.batfish.symbolic.Protocol in project batfish by batfish.
the class Optimizations method computeCanMergeImportExportVars.
/*
* Determine when import and export variables can be merged along an edge.
* This will be safe when there is no peer-specific import filter
*/
private void computeCanMergeImportExportVars() {
_encoderSlice.getGraph().getConfigurations().forEach((router, conf) -> {
Map<Protocol, List<GraphEdge>> map = new HashMap<>();
_sliceCanCombineImportExportVars.put(router, map);
for (Protocol proto : getProtocols().get(router)) {
List<GraphEdge> edges = new ArrayList<>();
if (Optimizations.ENABLE_IMPORT_EXPORT_MERGE_OPTIMIZATION && !proto.isConnected() && !proto.isStatic() && !proto.isOspf()) {
for (GraphEdge ge : _encoderSlice.getGraph().getEdgeMap().get(router)) {
// Don't merge when an abstract edge is used.
boolean safeMergeEdge = _encoderSlice.getGraph().isEdgeUsed(conf, proto, ge) && !ge.isAbstract();
// Don't merge when bgp internal/external can differ
boolean sameInternal = (ge.getPeer() == null) || (_needBgpInternal.contains(router) == _needBgpInternal.contains(ge.getPeer()));
// Check if there are any local modifications on import
boolean isPure = true;
RoutingPolicy pol = _encoderSlice.getGraph().findImportRoutingPolicy(router, proto, ge);
if (pol != null) {
isPure = false;
}
boolean noFailures = _encoderSlice.getEncoder().getFailures() == 0;
if (safeMergeEdge && sameInternal && isPure && noFailures && hasExportVariables(ge, proto)) {
edges.add(ge);
}
}
}
map.put(proto, edges);
}
});
}
Aggregations