Search in sources :

Example 66 with BoolExpr

use of com.microsoft.z3.BoolExpr 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)

Example 67 with BoolExpr

use of com.microsoft.z3.BoolExpr in project batfish by batfish.

the class CounterExample method buildFlowHistoryDiff.

/*
   * Create a trace-based counterexample demonstrating
   * the difference between two networks on a single packet.
   */
FlowHistory buildFlowHistoryDiff(String testRigName, Collection<String> sourceRouters, Encoder enc, Encoder enc2, Map<String, BoolExpr> reach, Map<String, BoolExpr> reach2) {
    FlowHistory fh = new FlowHistory();
    assert (reach2 != null);
    for (String source : sourceRouters) {
        BoolExpr sourceVar1 = reach.get(source);
        BoolExpr sourceVar2 = reach2.get(source);
        String val1 = evaluate(sourceVar1);
        String val2 = evaluate(sourceVar2);
        if (!Objects.equals(val1, val2)) {
            Tuple<Flow, FlowTrace> diff = buildFlowTrace(enc, source);
            Tuple<Flow, FlowTrace> base = buildFlowTrace(enc2, source);
            SortedSet<Edge> failedLinksDiff = buildFailedLinks(enc);
            SortedSet<Edge> failedLinksBase = buildFailedLinks(enc2);
            SortedSet<BgpAdvertisement> envRoutesDiff = buildEnvRoutingTable(enc);
            SortedSet<BgpAdvertisement> envRoutesBase = buildEnvRoutingTable(enc2);
            Environment baseEnv = new Environment("BASE", testRigName, failedLinksBase, null, null, null, null, envRoutesBase);
            Environment failedEnv = new Environment("DELTA", testRigName, failedLinksDiff, null, null, null, null, envRoutesDiff);
            fh.addFlowTrace(base.getFirst(), "BASE", baseEnv, base.getSecond());
            fh.addFlowTrace(diff.getFirst(), "DELTA", failedEnv, diff.getSecond());
        }
    }
    return fh;
}
Also used : BoolExpr(com.microsoft.z3.BoolExpr) BgpAdvertisement(org.batfish.datamodel.BgpAdvertisement) FlowHistory(org.batfish.datamodel.FlowHistory) FlowTrace(org.batfish.datamodel.FlowTrace) Environment(org.batfish.datamodel.pojo.Environment) Edge(org.batfish.datamodel.Edge) GraphEdge(org.batfish.symbolic.GraphEdge) Flow(org.batfish.datamodel.Flow)

Example 68 with BoolExpr

use of com.microsoft.z3.BoolExpr in project batfish by batfish.

the class CounterExample method buildEnvRoutingTable.

SortedSet<BgpAdvertisement> buildEnvRoutingTable(Encoder enc) {
    SortedSet<BgpAdvertisement> routes = new TreeSet<>();
    EncoderSlice slice = enc.getMainSlice();
    LogicalGraph lg = slice.getLogicalGraph();
    for (Entry<LogicalEdge, SymbolicRoute> entry : lg.getEnvironmentVars().entrySet()) {
        LogicalEdge lge = entry.getKey();
        SymbolicRoute record = entry.getValue();
        // If there is an external advertisement
        if (boolVal(record.getPermitted())) {
            // If we actually use it
            GraphEdge ge = lge.getEdge();
            String router = ge.getRouter();
            SymbolicDecisions decisions = slice.getSymbolicDecisions();
            BoolExpr ctrFwd = decisions.getControlForwarding().get(router, ge);
            assert ctrFwd != null;
            if (boolVal(ctrFwd)) {
                SymbolicRoute r = decisions.getBestNeighbor().get(router);
                SymbolicPacket pkt = slice.getSymbolicPacket();
                Flow f = buildFlow(pkt, router);
                Prefix pfx = buildPrefix(r, f);
                int pathLength = intVal(r.getMetric());
                // Create dummy information
                BgpNeighbor n = slice.getGraph().getEbgpNeighbors().get(lge.getEdge());
                String srcNode = "as" + n.getRemoteAs();
                Ip zeroIp = new Ip(0);
                Ip dstIp = n.getLocalIp();
                // Recover AS path
                List<SortedSet<Integer>> asSets = new ArrayList<>();
                for (int i = 0; i < pathLength; i++) {
                    SortedSet<Integer> asSet = new TreeSet<>();
                    asSet.add(-1);
                    asSets.add(asSet);
                }
                AsPath path = new AsPath(asSets);
                // Recover communities
                SortedSet<Long> communities = new TreeSet<>();
                for (Entry<CommunityVar, BoolExpr> entry2 : r.getCommunities().entrySet()) {
                    CommunityVar cvar = entry2.getKey();
                    BoolExpr expr = entry2.getValue();
                    if (cvar.getType() == Type.EXACT && boolVal(expr)) {
                        communities.add(cvar.asLong());
                    }
                }
                BgpAdvertisement adv = new BgpAdvertisement(BgpAdvertisementType.EBGP_RECEIVED, pfx, zeroIp, srcNode, "default", zeroIp, router, "default", dstIp, RoutingProtocol.BGP, OriginType.EGP, 100, 80, zeroIp, path, communities, new TreeSet<>(), 0);
                routes.add(adv);
            }
        }
    }
    return routes;
}
Also used : BoolExpr(com.microsoft.z3.BoolExpr) Ip(org.batfish.datamodel.Ip) ArrayList(java.util.ArrayList) Prefix(org.batfish.datamodel.Prefix) SortedSet(java.util.SortedSet) BgpNeighbor(org.batfish.datamodel.BgpNeighbor) TreeSet(java.util.TreeSet) Flow(org.batfish.datamodel.Flow) CommunityVar(org.batfish.symbolic.CommunityVar) BgpAdvertisement(org.batfish.datamodel.BgpAdvertisement) AsPath(org.batfish.datamodel.AsPath) GraphEdge(org.batfish.symbolic.GraphEdge)

Example 69 with BoolExpr

use of com.microsoft.z3.BoolExpr in project batfish by batfish.

the class PropertyChecker method checkDeterminism.

/*
   * Check if there exist multiple stable solutions to the network.
   * If so, reports the forwarding differences between the two cases.
   */
public AnswerElement checkDeterminism(HeaderQuestion q) {
    Graph graph = new Graph(_batfish);
    Encoder enc1 = new Encoder(_settings, graph, q);
    Encoder enc2 = new Encoder(enc1, graph, q);
    enc1.computeEncoding();
    enc2.computeEncoding();
    addEnvironmentConstraints(enc1, q.getBaseEnvironmentType());
    BoolExpr relatedFailures = relateFailures(enc1, enc2);
    BoolExpr relatedEnvs = relateEnvironments(enc1, enc2);
    BoolExpr relatedPkts = relatePackets(enc1, enc2);
    BoolExpr related = enc1.mkAnd(relatedFailures, relatedEnvs, relatedPkts);
    BoolExpr required = enc1.mkTrue();
    for (GraphEdge ge : graph.getAllRealEdges()) {
        SymbolicDecisions d1 = enc1.getMainSlice().getSymbolicDecisions();
        SymbolicDecisions d2 = enc2.getMainSlice().getSymbolicDecisions();
        BoolExpr dataFwd1 = d1.getDataForwarding().get(ge.getRouter(), ge);
        BoolExpr dataFwd2 = d2.getDataForwarding().get(ge.getRouter(), ge);
        assert dataFwd1 != null;
        assert dataFwd2 != null;
        required = enc1.mkAnd(required, enc1.mkEq(dataFwd1, dataFwd2));
    }
    enc1.add(related);
    enc1.add(enc1.mkNot(required));
    Tuple<VerificationResult, Model> tup = enc1.verify();
    VerificationResult res = tup.getFirst();
    Model model = tup.getSecond();
    SortedSet<String> case1 = null;
    SortedSet<String> case2 = null;
    Flow flow = null;
    CounterExample ce = new CounterExample(model);
    if (!res.isVerified()) {
        case1 = new TreeSet<>();
        case2 = new TreeSet<>();
        flow = ce.buildFlow(enc1.getMainSlice().getSymbolicPacket(), "(none)");
        for (GraphEdge ge : graph.getAllRealEdges()) {
            SymbolicDecisions d1 = enc1.getMainSlice().getSymbolicDecisions();
            SymbolicDecisions d2 = enc2.getMainSlice().getSymbolicDecisions();
            BoolExpr dataFwd1 = d1.getDataForwarding().get(ge.getRouter(), ge);
            BoolExpr dataFwd2 = d2.getDataForwarding().get(ge.getRouter(), ge);
            assert dataFwd1 != null;
            assert dataFwd2 != null;
            boolean b1 = ce.boolVal(dataFwd1);
            boolean b2 = ce.boolVal(dataFwd2);
            if (b1 != b2) {
                if (b1) {
                    String route = ce.buildRoute(enc1.getMainSlice(), ge);
                    String msg = ge + " -- " + route;
                    case1.add(msg);
                }
                if (b2) {
                    String route = ce.buildRoute(enc2.getMainSlice(), ge);
                    String msg = ge + " -- " + route;
                    case2.add(msg);
                }
            }
        }
    }
    // Ensure canonical order
    boolean less = (case1 == null || (case1.first().compareTo(case2.first()) < 0));
    if (less) {
        return new SmtDeterminismAnswerElement(flow, case1, case2);
    } else {
        return new SmtDeterminismAnswerElement(flow, case2, case1);
    }
}
Also used : BoolExpr(com.microsoft.z3.BoolExpr) Flow(org.batfish.datamodel.Flow) Graph(org.batfish.symbolic.Graph) Model(com.microsoft.z3.Model) SmtDeterminismAnswerElement(org.batfish.symbolic.answers.SmtDeterminismAnswerElement) GraphEdge(org.batfish.symbolic.GraphEdge)

Example 70 with BoolExpr

use of com.microsoft.z3.BoolExpr in project batfish by batfish.

the class PropertyChecker method checkBoundedLength.

/*
   * Compute whether the path length will always be bounded by a constant k
   * for a collection of source routers to any of a number of destination ports.
   */
public AnswerElement checkBoundedLength(HeaderLocationQuestion q, int k) {
    return checkProperty(q, (enc, srcRouters, destPorts) -> {
        ArithExpr bound = enc.mkInt(k);
        PropertyAdder pa = new PropertyAdder(enc.getMainSlice());
        Map<String, ArithExpr> lenVars = pa.instrumentPathLength(destPorts);
        Map<String, BoolExpr> boundVars = new HashMap<>();
        lenVars.forEach((n, ae) -> boundVars.put(n, enc.mkLe(ae, bound)));
        return boundVars;
    }, (vp) -> new SmtOneAnswerElement(vp.getResult()));
}
Also used : ArithExpr(com.microsoft.z3.ArithExpr) BoolExpr(com.microsoft.z3.BoolExpr) HashMap(java.util.HashMap) SmtOneAnswerElement(org.batfish.symbolic.answers.SmtOneAnswerElement)

Aggregations

BoolExpr (com.microsoft.z3.BoolExpr)141 Status (com.microsoft.z3.Status)55 Test (org.junit.Test)51 ArithExpr (com.microsoft.z3.ArithExpr)27 GraphEdge (org.batfish.symbolic.GraphEdge)25 Context (com.microsoft.z3.Context)24 HashMap (java.util.HashMap)22 Expr (com.microsoft.z3.Expr)21 Set (java.util.Set)20 Collectors (java.util.stream.Collectors)18 BitVecExpr (com.microsoft.z3.BitVecExpr)17 Event (dartagnan.program.Event)17 MemEvent (dartagnan.program.MemEvent)17 Program (dartagnan.program.Program)16 Map (java.util.Map)16 Local (dartagnan.program.Local)15 ArrayList (java.util.ArrayList)15 BatfishException (org.batfish.common.BatfishException)14 Graph (org.batfish.symbolic.Graph)14 com.microsoft.z3 (com.microsoft.z3)12