use of org.batfish.datamodel.Interface 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.datamodel.Interface 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.Interface in project batfish by batfish.
the class Graph method initIbgpNeighbors.
// TODO: very inefficient
/*
* Initialize iBGP neighbors by looking for nieghbors
* with the same AS number.
*/
private void initIbgpNeighbors() {
Map<String, Ip> ips = new HashMap<>();
Table2<String, String, BgpNeighbor> neighbors = new Table2<>();
// Match iBGP sessions with pairs of routers and BgpNeighbor
for (Entry<String, Configuration> entry : _configurations.entrySet()) {
String router = entry.getKey();
Configuration conf = entry.getValue();
BgpProcess p = conf.getDefaultVrf().getBgpProcess();
if (p != null) {
for (BgpNeighbor n : p.getNeighbors().values()) {
if (n.getLocalAs().equals(n.getRemoteAs())) {
ips.put(router, n.getLocalIp());
}
}
}
}
for (Entry<String, Configuration> entry : _configurations.entrySet()) {
String router = entry.getKey();
Configuration conf = entry.getValue();
BgpProcess p = conf.getDefaultVrf().getBgpProcess();
if (p != null) {
for (Entry<Prefix, BgpNeighbor> entry2 : p.getNeighbors().entrySet()) {
Prefix pfx = entry2.getKey();
BgpNeighbor n = entry2.getValue();
if (n.getLocalAs().equals(n.getRemoteAs())) {
for (Entry<String, Ip> ipEntry : ips.entrySet()) {
String r = ipEntry.getKey();
Ip ip = ipEntry.getValue();
if (!router.equals(r) && pfx.containsIp(ip)) {
neighbors.put(router, r, n);
}
}
}
}
}
}
// Add abstract graph edges for iBGP sessions
Table2<String, String, GraphEdge> reverse = new Table2<>();
neighbors.forEach((r1, r2, n1) -> {
Interface iface1 = createIbgpInterface(n1, r2);
BgpNeighbor n2 = neighbors.get(r2, r1);
GraphEdge ge;
if (n2 != null) {
Interface iface2 = createIbgpInterface(n2, r1);
ge = new GraphEdge(iface1, iface2, r1, r2, true, false);
} else {
ge = new GraphEdge(iface1, null, r1, null, true, false);
}
_allEdges.add(ge);
_ibgpNeighbors.put(ge, n1);
reverse.put(r1, r2, ge);
List<GraphEdge> edges = _edgeMap.get(r1);
if (edges != null) {
edges.add(ge);
} else {
edges = new ArrayList<>();
edges.add(ge);
_edgeMap.put(r1, edges);
}
});
// Add other end to ibgp edges
reverse.forEach((r1, r2, ge1) -> {
GraphEdge ge2 = reverse.get(r2, r1);
_otherEnd.put(ge1, ge2);
});
// Configure Route Reflector information
Integer[] id = new Integer[1];
id[0] = 1;
neighbors.forEach((r1, ns) -> {
if (!_originatorId.containsKey(r1)) {
_originatorId.put(r1, id[0]);
id[0]++;
}
Set<String> clients = new HashSet<>();
ns.forEach((r2, n) -> {
if (n.getRouteReflectorClient()) {
clients.add(r2);
_routeReflectorParent.put(r2, r1);
}
});
_routeReflectorClients.put(r1, clients);
});
}
use of org.batfish.datamodel.Interface in project batfish by batfish.
the class PatternUtils method findMatchingEdges.
public static List<GraphEdge> findMatchingEdges(Graph graph, Pattern p1, Pattern p2, Pattern p3, Pattern p4) {
List<GraphEdge> acc = new ArrayList<>();
for (Entry<String, List<GraphEdge>> entry : graph.getEdgeMap().entrySet()) {
String router = entry.getKey();
List<GraphEdge> edges = entry.getValue();
Matcher m1 = p1.matcher(router);
Matcher m2 = p2.matcher(router);
if (m1.matches() && !m2.matches()) {
for (GraphEdge edge : edges) {
if (!edge.isAbstract()) {
Interface i = edge.getStart();
String ifaceName = i.getName();
Matcher m3 = p3.matcher(ifaceName);
Matcher m4 = p4.matcher(ifaceName);
if (m3.matches() && !m4.matches()) {
acc.add(edge);
}
}
}
}
}
return acc;
}
use of org.batfish.datamodel.Interface in project batfish by batfish.
the class BdpDataPlanePluginTest method testStaticInterfaceRoutesWithoutEdge.
@Test
public void testStaticInterfaceRoutesWithoutEdge() {
NetworkFactory nf = new NetworkFactory();
Configuration c = nf.configurationBuilder().setConfigurationFormat(ConfigurationFormat.CISCO_IOS).build();
Vrf vrf = nf.vrfBuilder().setOwner(c).setName(DEFAULT_VRF_NAME).build();
Interface i = nf.interfaceBuilder().setOwner(c).setVrf(vrf).setAddress(new InterfaceAddress("10.0.0.0/24")).setActive(true).build();
StaticRoute srBoth = StaticRoute.builder().setNetwork(Prefix.parse("10.0.1.0/24")).setNextHopInterface(i.getName()).setNextHopIp(new Ip("10.0.0.1")).build();
vrf.getStaticRoutes().add(srBoth);
StaticRoute srJustInterface = StaticRoute.builder().setNetwork(Prefix.parse("10.0.2.0/24")).setNextHopInterface(i.getName()).build();
vrf.getStaticRoutes().add(srJustInterface);
BdpEngine engine = new BdpEngine(new MockBdpSettings(), new BatfishLogger(BatfishLogger.LEVELSTR_DEBUG, false), (a, b) -> new AtomicInteger());
Topology topology = new Topology(Collections.emptySortedSet());
BdpDataPlane dp = engine.computeDataPlane(false, ImmutableMap.of(c.getName(), c), topology, Collections.emptySet(), new BdpAnswerElement());
// generating fibs should not crash
dp.getFibs();
}
Aggregations