Search in sources :

Example 16 with GraphEdge

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);
}
Also used : Context(com.microsoft.z3.Context) BoolExpr(com.microsoft.z3.BoolExpr) Solver(com.microsoft.z3.Solver) Graph(org.batfish.symbolic.Graph) HashMap(java.util.HashMap) List(java.util.List) GraphEdge(org.batfish.symbolic.GraphEdge)

Example 17 with GraphEdge

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)));
            }
        }
    }
}
Also used : IpWildcard(org.batfish.datamodel.IpWildcard) Ip(org.batfish.datamodel.Ip) HeaderSpace(org.batfish.datamodel.HeaderSpace) Prefix(org.batfish.datamodel.Prefix) GraphEdge(org.batfish.symbolic.GraphEdge)

Example 18 with GraphEdge

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;
}
Also used : ArithExpr(com.microsoft.z3.ArithExpr) BoolExpr(com.microsoft.z3.BoolExpr) GraphEdge(org.batfish.symbolic.GraphEdge)

Example 19 with GraphEdge

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);
}
Also used : Context(com.microsoft.z3.Context) BoolExpr(com.microsoft.z3.BoolExpr) ArrayList(java.util.ArrayList) SmtOneAnswerElement(org.batfish.symbolic.answers.SmtOneAnswerElement) Graph(org.batfish.symbolic.Graph) List(java.util.List) ArrayList(java.util.ArrayList) GraphEdge(org.batfish.symbolic.GraphEdge) Map(java.util.Map) EnumMap(java.util.EnumMap) SortedMap(java.util.SortedMap) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap)

Example 20 with GraphEdge

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);
        }
    }
}
Also used : BoolExpr(com.microsoft.z3.BoolExpr) Ip(org.batfish.datamodel.Ip) ArrayList(java.util.ArrayList) Prefix(org.batfish.datamodel.Prefix) TreeSet(java.util.TreeSet) IpAccessListLine(org.batfish.datamodel.IpAccessListLine) IpProtocol(org.batfish.datamodel.IpProtocol) RoutingProtocol(org.batfish.datamodel.RoutingProtocol) Protocol(org.batfish.symbolic.Protocol) Flow(org.batfish.datamodel.Flow) FlowTraceHop(org.batfish.datamodel.FlowTraceHop) FlowTrace(org.batfish.datamodel.FlowTrace) IpAccessList(org.batfish.datamodel.IpAccessList) FilterResult(org.batfish.datamodel.FilterResult) GraphEdge(org.batfish.symbolic.GraphEdge) Tuple(org.batfish.symbolic.utils.Tuple) Interface(org.batfish.datamodel.Interface)

Aggregations

GraphEdge (org.batfish.symbolic.GraphEdge)47 BoolExpr (com.microsoft.z3.BoolExpr)23 HashMap (java.util.HashMap)19 ArrayList (java.util.ArrayList)16 List (java.util.List)16 Graph (org.batfish.symbolic.Graph)14 TreeSet (java.util.TreeSet)13 Prefix (org.batfish.datamodel.Prefix)12 ArithExpr (com.microsoft.z3.ArithExpr)10 Configuration (org.batfish.datamodel.Configuration)10 Protocol (org.batfish.symbolic.Protocol)10 HashSet (java.util.HashSet)8 Interface (org.batfish.datamodel.Interface)8 Context (com.microsoft.z3.Context)7 Map (java.util.Map)7 Ip (org.batfish.datamodel.Ip)7 IpAccessList (org.batfish.datamodel.IpAccessList)7 TreeMap (java.util.TreeMap)6 IpProtocol (org.batfish.datamodel.IpProtocol)6 BitVecExpr (com.microsoft.z3.BitVecExpr)5