use of org.batfish.symbolic.GraphEdge in project batfish by batfish.
the class PropertyAdder method instrumentLoop.
/*
* Instruments the network to check if a router will be part
* of a routing loop.
*/
BoolExpr instrumentLoop(String router) {
Context ctx = _encoderSlice.getCtx();
Solver solver = _encoderSlice.getSolver();
String sliceName = _encoderSlice.getSliceName();
// Add on-loop variables to track a loop
Map<String, BoolExpr> onLoop = new HashMap<>();
Graph graph = _encoderSlice.getGraph();
for (String r : graph.getRouters()) {
String name = _encoderSlice.getEncoder().getId() + "_" + sliceName + "_on-loop_" + router + "_" + r;
BoolExpr var = ctx.mkBoolConst(name);
onLoop.put(r, var);
_encoderSlice.getAllVariables().put(var.toString(), var);
}
for (Entry<String, List<GraphEdge>> entry : graph.getEdgeMap().entrySet()) {
String r = entry.getKey();
List<GraphEdge> edges = entry.getValue();
BoolExpr var = onLoop.get(r);
BoolExpr acc = ctx.mkBool(false);
for (GraphEdge edge : edges) {
if (!edge.isAbstract()) {
BoolExpr fwd = _encoderSlice.getForwardsAcross().get(r, edge);
String peer = edge.getPeer();
if (peer != null) {
if (peer.equals(router)) {
// If next hop is static route router, then on loop
acc = ctx.mkOr(acc, fwd);
} else {
// Otherwise check if next hop also is on the loop
BoolExpr peerOnLoop = onLoop.get(peer);
acc = ctx.mkOr(acc, ctx.mkAnd(fwd, peerOnLoop));
}
}
}
}
solver.add(ctx.mkEq(var, acc));
}
return onLoop.get(router);
}
use of org.batfish.symbolic.GraphEdge in project batfish by batfish.
the class PropertyChecker method inferDestinationHeaderSpace.
private void inferDestinationHeaderSpace(Graph g, Collection<GraphEdge> destPorts, HeaderLocationQuestion q) {
// Skip inference if the destination IP headerspace does not need to be inferred.
if (!q.getHeaderSpace().getDstIps().isEmpty()) {
return;
}
// Infer relevant destination IP headerspace from interfaces
HeaderSpace headerSpace = q.getHeaderSpace();
for (GraphEdge ge : destPorts) {
// it can be any prefix, so we leave it unconstrained
if (g.isExternal(ge)) {
headerSpace.setDstIps(Collections.emptySet());
headerSpace.setNotDstIps(Collections.emptySet());
break;
}
// If we don't know what is on the other end
if (ge.getPeer() == null) {
Prefix pfx = ge.getStart().getAddress().getPrefix();
IpWildcard dst = new IpWildcard(pfx);
headerSpace.setDstIps(Iterables.concat(headerSpace.getDstIps(), Collections.singleton(dst)));
} else {
// If host, add the subnet but not the neighbor's address
if (g.isHost(ge.getRouter())) {
Prefix pfx = ge.getStart().getAddress().getPrefix();
IpWildcard dst = new IpWildcard(pfx);
headerSpace.setDstIps(Iterables.concat(headerSpace.getDstIps(), Collections.singleton(dst)));
Ip ip = ge.getEnd().getAddress().getIp();
IpWildcard dst2 = new IpWildcard(ip);
headerSpace.setNotDstIps(Iterables.concat(headerSpace.getNotDstIps(), Collections.singleton(dst2)));
} else {
// Otherwise, we add the exact address
Ip ip = ge.getStart().getAddress().getIp();
IpWildcard dst = new IpWildcard(ip);
headerSpace.setDstIps(Iterables.concat(headerSpace.getDstIps(), Collections.singleton(dst)));
}
}
}
}
use of org.batfish.symbolic.GraphEdge in project batfish by batfish.
the class PropertyChecker method relateFailures.
private BoolExpr relateFailures(Encoder enc1, Encoder enc2) {
BoolExpr related = enc1.mkTrue();
for (GraphEdge ge : enc1.getMainSlice().getGraph().getAllRealEdges()) {
ArithExpr a1 = enc1.getSymbolicFailures().getFailedVariable(ge);
ArithExpr a2 = enc2.getSymbolicFailures().getFailedVariable(ge);
assert a1 != null;
assert a2 != null;
related = enc1.mkEq(a1, a2);
}
return related;
}
use of org.batfish.symbolic.GraphEdge in project batfish by batfish.
the class PropertyChecker method checkBlackHole.
/*
* Compute if there can ever be a black hole for routers that are
* not at the edge of the network. This is almost certainly a bug.
*/
public AnswerElement checkBlackHole(HeaderQuestion q) {
Graph graph = new Graph(_batfish);
Encoder enc = new Encoder(_settings, graph, q);
enc.computeEncoding();
Context ctx = enc.getCtx();
EncoderSlice slice = enc.getMainSlice();
// Collect routers that have no host/environment edge
List<String> toCheck = new ArrayList<>();
for (Entry<String, List<GraphEdge>> entry : graph.getEdgeMap().entrySet()) {
String router = entry.getKey();
List<GraphEdge> edges = entry.getValue();
boolean check = true;
for (GraphEdge edge : edges) {
if (edge.getEnd() == null) {
check = false;
break;
}
}
if (check) {
toCheck.add(router);
}
}
// Ensure the router never receives traffic and then drops the traffic
BoolExpr someBlackHole = ctx.mkBool(false);
for (String router : toCheck) {
Map<GraphEdge, BoolExpr> edges = slice.getSymbolicDecisions().getDataForwarding().get(router);
BoolExpr doesNotFwd = ctx.mkBool(true);
for (Map.Entry<GraphEdge, BoolExpr> entry : edges.entrySet()) {
BoolExpr dataFwd = entry.getValue();
doesNotFwd = ctx.mkAnd(doesNotFwd, ctx.mkNot(dataFwd));
}
BoolExpr isFwdTo = ctx.mkBool(false);
Set<String> neighbors = graph.getNeighbors().get(router);
for (String n : neighbors) {
for (Map.Entry<GraphEdge, BoolExpr> entry : slice.getSymbolicDecisions().getDataForwarding().get(n).entrySet()) {
GraphEdge ge = entry.getKey();
BoolExpr fwd = entry.getValue();
if (router.equals(ge.getPeer())) {
isFwdTo = ctx.mkOr(isFwdTo, fwd);
}
}
}
someBlackHole = ctx.mkOr(someBlackHole, ctx.mkAnd(isFwdTo, doesNotFwd));
}
enc.add(someBlackHole);
VerificationResult result = enc.verify().getFirst();
return new SmtOneAnswerElement(result);
}
use of org.batfish.symbolic.GraphEdge in project batfish by batfish.
the class CounterExample method buildFlowTrace.
/*
* Build flow information for a given hop along a path
*/
Tuple<Flow, FlowTrace> buildFlowTrace(Encoder enc, String router) {
EncoderSlice slice = enc.getMainSlice();
SymbolicPacket pkt = slice.getSymbolicPacket();
SymbolicDecisions decisions = slice.getSymbolicDecisions();
Flow f = buildFlow(pkt, router);
SortedSet<String> visited = new TreeSet<>();
List<FlowTraceHop> hops = new ArrayList<>();
String current = router;
while (true) {
visited.add(current);
// Get the forwarding variables
Map<GraphEdge, BoolExpr> dfwd = decisions.getDataForwarding().get(current);
Map<GraphEdge, BoolExpr> cfwd = decisions.getControlForwarding().get(current);
Map<GraphEdge, BoolExpr> across = enc.getMainSlice().getForwardsAcross().get(current);
// Find the route used
SymbolicRoute r = decisions.getBestNeighbor().get(current);
Protocol proto = buildProcotol(r, slice, current);
Prefix pfx = buildPrefix(r, f);
// pick the next router
boolean found = false;
for (Entry<GraphEdge, BoolExpr> entry : dfwd.entrySet()) {
GraphEdge ge = entry.getKey();
BoolExpr dexpr = entry.getValue();
BoolExpr cexpr = cfwd.get(ge);
BoolExpr aexpr = across.get(ge);
String route = buildRoute(pfx, proto, ge);
if (isTrue(dexpr)) {
hops.add(buildFlowTraceHop(ge, route));
if (ge.getPeer() != null && visited.contains(ge.getPeer())) {
FlowTrace ft = new FlowTrace(FlowDisposition.LOOP, hops, "LOOP");
return new Tuple<>(f, ft);
}
if (isFalse(aexpr)) {
Interface i = ge.getEnd();
IpAccessList acl = i.getIncomingFilter();
FilterResult fr = acl.filter(f);
String line = "default deny";
if (fr.getMatchLine() != null) {
line = acl.getLines().get(fr.getMatchLine()).getName();
}
String note = String.format("DENIED_IN{%s}{%s}", acl.getName(), line);
FlowTrace ft = new FlowTrace(FlowDisposition.DENIED_IN, hops, note);
return new Tuple<>(f, ft);
}
boolean isLoopback = slice.getGraph().isLoopback(ge);
if (isLoopback) {
FlowTrace ft = new FlowTrace(FlowDisposition.ACCEPTED, hops, "ACCEPTED");
return new Tuple<>(f, ft);
}
if (ge.getPeer() == null) {
boolean isBgpPeering = slice.getGraph().getEbgpNeighbors().get(ge) != null;
if (isBgpPeering) {
FlowTrace ft = new FlowTrace(FlowDisposition.ACCEPTED, hops, "ACCEPTED");
return new Tuple<>(f, ft);
} else {
FlowTrace ft = new FlowTrace(FlowDisposition.NEIGHBOR_UNREACHABLE_OR_EXITS_NETWORK, hops, "NEIGHBOR_UNREACHABLE_OR_EXITS_NETWORK");
return new Tuple<>(f, ft);
}
}
if (slice.getGraph().isHost(ge.getPeer())) {
FlowTrace ft = new FlowTrace(FlowDisposition.ACCEPTED, hops, "ACCEPTED");
return new Tuple<>(f, ft);
}
current = ge.getPeer();
found = true;
break;
} else if (isTrue(cexpr)) {
hops.add(buildFlowTraceHop(ge, route));
Interface i = ge.getStart();
IpAccessList acl = i.getOutgoingFilter();
FilterResult fr = acl.filter(f);
IpAccessListLine line = acl.getLines().get(fr.getMatchLine());
String note = String.format("DENIED_OUT{%s}{%s}", acl.getName(), line.getName());
FlowTrace ft = new FlowTrace(FlowDisposition.DENIED_OUT, hops, note);
return new Tuple<>(f, ft);
}
}
if (!found) {
BoolExpr permitted = r.getPermitted();
if (boolVal(permitted)) {
// Check if there is an accepting interface
for (GraphEdge ge : slice.getGraph().getEdgeMap().get(current)) {
Interface i = ge.getStart();
Ip ip = i.getAddress().getIp();
if (ip.equals(f.getDstIp())) {
FlowTrace ft = new FlowTrace(FlowDisposition.ACCEPTED, hops, "ACCEPTED");
return new Tuple<>(f, ft);
}
}
FlowTrace ft = new FlowTrace(FlowDisposition.NEIGHBOR_UNREACHABLE_OR_EXITS_NETWORK, hops, "NEIGHBOR_UNREACHABLE_OR_EXITS_NETWORK");
return new Tuple<>(f, ft);
}
FlowTrace ft = new FlowTrace(FlowDisposition.NO_ROUTE, hops, "NO_ROUTE");
return new Tuple<>(f, ft);
}
}
}
Aggregations