Search in sources :

Example 1 with HeaderLocationQuestion

use of org.batfish.datamodel.questions.smt.HeaderLocationQuestion in project batfish by batfish.

the class PropertyChecker method checkReachability.

/*
   * Check if a collection of routers will be reachable to
   * one or more destinations.
   */
public AnswerElement checkReachability(HeaderLocationQuestion q) {
    return checkProperty(q, (enc, srcRouters, destPorts) -> {
        PropertyAdder pa = new PropertyAdder(enc.getMainSlice());
        return pa.instrumentReachability(destPorts);
    }, (vp) -> {
        if (vp.getResult().isVerified()) {
            return new SmtReachabilityAnswerElement(vp.getResult(), new FlowHistory());
        } else {
            FlowHistory fh;
            CounterExample ce = new CounterExample(vp.getModel());
            String testrigName = _batfish.getTestrigName();
            if (q.getDiffType() != null) {
                fh = ce.buildFlowHistoryDiff(testrigName, vp.getSrcRouters(), vp.getEnc(), vp.getEncDiff(), vp.getProp(), vp.getPropDiff());
            } else {
                Map<String, Boolean> reachVals = vp.getProp().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> ce.isTrue(entry.getValue()) ^ q.getNegate()));
                fh = ce.buildFlowHistory(testrigName, vp.getSrcRouters(), vp.getEnc(), reachVals);
            }
            return new SmtReachabilityAnswerElement(vp.getResult(), fh);
        }
    });
}
Also used : HeaderSpace(org.batfish.datamodel.HeaderSpace) PatternUtils(org.batfish.symbolic.utils.PatternUtils) SmtOneAnswerElement(org.batfish.symbolic.answers.SmtOneAnswerElement) SortedSet(java.util.SortedSet) FlowHistory(org.batfish.datamodel.FlowHistory) Flow(org.batfish.datamodel.Flow) HeaderQuestion(org.batfish.datamodel.questions.smt.HeaderQuestion) EnvironmentType(org.batfish.datamodel.questions.smt.EnvironmentType) Map(java.util.Map) NetworkSlice(org.batfish.symbolic.abstraction.NetworkSlice) SmtDeterminismAnswerElement(org.batfish.symbolic.answers.SmtDeterminismAnswerElement) EnumMap(java.util.EnumMap) Collection(java.util.Collection) Set(java.util.Set) SmtReachabilityAnswerElement(org.batfish.symbolic.answers.SmtReachabilityAnswerElement) Graph(org.batfish.symbolic.Graph) PathRegexes(org.batfish.symbolic.utils.PathRegexes) Collectors(java.util.stream.Collectors) IBatfish(org.batfish.common.plugin.IBatfish) Settings(org.batfish.config.Settings) Model(com.microsoft.z3.Model) List(java.util.List) Stream(java.util.stream.Stream) Entry(java.util.Map.Entry) TriFunction(org.batfish.symbolic.utils.TriFunction) Optional(java.util.Optional) AnswerElement(org.batfish.datamodel.answers.AnswerElement) Pattern(java.util.regex.Pattern) SortedMap(java.util.SortedMap) IpWildcard(org.batfish.datamodel.IpWildcard) Ip(org.batfish.datamodel.Ip) Iterables(com.google.common.collect.Iterables) CommunityVar(org.batfish.symbolic.CommunityVar) Context(com.microsoft.z3.Context) HashMap(java.util.HashMap) BatfishException(org.batfish.common.BatfishException) Function(java.util.function.Function) Supplier(java.util.function.Supplier) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Abstraction(org.batfish.symbolic.abstraction.Abstraction) BoolExpr(com.microsoft.z3.BoolExpr) Configuration(org.batfish.datamodel.Configuration) ArithExpr(com.microsoft.z3.ArithExpr) Nullable(javax.annotation.Nullable) SmtManyAnswerElement(org.batfish.symbolic.answers.SmtManyAnswerElement) StaticRoute(org.batfish.datamodel.StaticRoute) BitVecExpr(com.microsoft.z3.BitVecExpr) Tuple(org.batfish.symbolic.utils.Tuple) GraphEdge(org.batfish.symbolic.GraphEdge) TreeMap(java.util.TreeMap) Expr(com.microsoft.z3.Expr) Protocol(org.batfish.symbolic.Protocol) HeaderLocationQuestion(org.batfish.datamodel.questions.smt.HeaderLocationQuestion) Table2(org.batfish.symbolic.collections.Table2) Collections(java.util.Collections) Prefix(org.batfish.datamodel.Prefix) DestinationClasses(org.batfish.symbolic.abstraction.DestinationClasses) FlowHistory(org.batfish.datamodel.FlowHistory) SmtReachabilityAnswerElement(org.batfish.symbolic.answers.SmtReachabilityAnswerElement) Map(java.util.Map) EnumMap(java.util.EnumMap) SortedMap(java.util.SortedMap) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap)

Example 2 with HeaderLocationQuestion

use of org.batfish.datamodel.questions.smt.HeaderLocationQuestion in project batfish by batfish.

the class PropertyChecker method checkProperty.

/*
   * General purpose logic for checking a property that holds that
   * handles the various flags and parameters for a query with endpoints
   *
   * q is the question from the user.
   * instrument instruments each router in the graph as needed to check the property.
   * answer takes the result from Z3 and produces the answer for the user.
   *
   */
private AnswerElement checkProperty(HeaderLocationQuestion q, TriFunction<Encoder, Set<String>, Set<GraphEdge>, Map<String, BoolExpr>> instrument, Function<VerifyParam, AnswerElement> answer) {
    long totalTime = System.currentTimeMillis();
    PathRegexes p = new PathRegexes(q);
    Graph graph = new Graph(_batfish);
    Set<GraphEdge> destPorts = findFinalInterfaces(graph, p);
    List<String> sourceRouters = PatternUtils.findMatchingSourceNodes(graph, p);
    if (destPorts.isEmpty()) {
        throw new BatfishException("Set of valid destination interfaces is empty");
    }
    if (sourceRouters.isEmpty()) {
        throw new BatfishException("Set of valid ingress nodes is empty");
    }
    inferDestinationHeaderSpace(graph, destPorts, q);
    Set<GraphEdge> failOptions = failLinkSet(graph, q);
    Tuple<Stream<Supplier<NetworkSlice>>, Long> ecs = findAllNetworkSlices(q, graph, true);
    Stream<Supplier<NetworkSlice>> stream = ecs.getFirst();
    Long timeAbstraction = ecs.getSecond();
    AnswerElement[] answerElement = new AnswerElement[1];
    VerificationResult[] result = new VerificationResult[2];
    List<VerificationStats> ecStats = new ArrayList<>();
    // Checks ECs in parallel, but short circuits when a counterexample is found
    boolean hasCounterExample = stream.anyMatch(lazyEc -> {
        long timeEc = System.currentTimeMillis();
        NetworkSlice slice = lazyEc.get();
        timeEc = System.currentTimeMillis() - timeEc;
        synchronized (_lock) {
            // Make sure the headerspace is correct
            HeaderLocationQuestion question = new HeaderLocationQuestion(q);
            question.setHeaderSpace(slice.getHeaderSpace());
            // Get the EC graph and mapping
            Graph g = slice.getGraph();
            Set<String> srcRouters = mapConcreteToAbstract(slice, sourceRouters);
            long timeEncoding = System.currentTimeMillis();
            Encoder enc = new Encoder(_settings, g, question);
            enc.computeEncoding();
            timeEncoding = System.currentTimeMillis() - timeEncoding;
            // Add environment constraints for base case
            if (question.getDiffType() != null) {
                if (question.getEnvDiff()) {
                    addEnvironmentConstraints(enc, question.getDeltaEnvironmentType());
                }
            } else {
                addEnvironmentConstraints(enc, question.getBaseEnvironmentType());
            }
            Map<String, BoolExpr> prop = instrument.apply(enc, srcRouters, destPorts);
            // If this is a equivalence query, we create a second copy of the network
            Encoder enc2 = null;
            Map<String, BoolExpr> prop2 = null;
            if (question.getDiffType() != null) {
                HeaderLocationQuestion q2 = new HeaderLocationQuestion(question);
                q2.setFailures(0);
                long timeDiffEncoding = System.currentTimeMillis();
                enc2 = new Encoder(enc, g, q2);
                enc2.computeEncoding();
                timeDiffEncoding = System.currentTimeMillis() - timeDiffEncoding;
                timeEncoding += timeDiffEncoding;
            }
            if (question.getDiffType() != null) {
                assert (enc2 != null);
                // create a map for enc2 to lookup a related environment variable from enc
                Table2<GraphEdge, EdgeType, SymbolicRoute> relatedEnv = new Table2<>();
                enc2.getMainSlice().getLogicalGraph().getEnvironmentVars().forEach((lge, r) -> relatedEnv.put(lge.getEdge(), lge.getEdgeType(), r));
                BoolExpr related = enc.mkTrue();
                addEnvironmentConstraints(enc2, question.getBaseEnvironmentType());
                if (!question.getEnvDiff()) {
                    related = relateEnvironments(enc, enc2);
                }
                prop2 = instrument.apply(enc2, srcRouters, destPorts);
                // Add diff constraints
                BoolExpr required = enc.mkTrue();
                for (String source : srcRouters) {
                    BoolExpr sourceProp1 = prop.get(source);
                    BoolExpr sourceProp2 = prop2.get(source);
                    BoolExpr val;
                    switch(q.getDiffType()) {
                        case INCREASED:
                            val = enc.mkImplies(sourceProp1, sourceProp2);
                            break;
                        case REDUCED:
                            val = enc.mkImplies(sourceProp2, sourceProp1);
                            break;
                        case ANY:
                            val = enc.mkEq(sourceProp1, sourceProp2);
                            break;
                        default:
                            throw new BatfishException("Missing case: " + q.getDiffType());
                    }
                    required = enc.mkAnd(required, val);
                }
                related = enc.mkAnd(related, relatePackets(enc, enc2));
                enc.add(related);
                enc.add(enc.mkNot(required));
            } else {
                // Not a differential query; just a query on a single version of the network.
                BoolExpr allProp = enc.mkTrue();
                for (String router : srcRouters) {
                    BoolExpr r = prop.get(router);
                    if (q.getNegate()) {
                        r = enc.mkNot(r);
                    }
                    allProp = enc.mkAnd(allProp, r);
                }
                enc.add(enc.mkNot(allProp));
            }
            addFailureConstraints(enc, destPorts, failOptions);
            Tuple<VerificationResult, Model> tup = enc.verify();
            VerificationResult res = tup.getFirst();
            Model model = tup.getSecond();
            if (q.getBenchmark()) {
                VerificationStats stats = res.getStats();
                stats.setAvgComputeEcTime(timeEc);
                stats.setMaxComputeEcTime(timeEc);
                stats.setMinComputeEcTime(timeEc);
                stats.setAvgEncodingTime(timeEncoding);
                stats.setMaxEncodingTime(timeEncoding);
                stats.setMinEncodingTime(timeEncoding);
                stats.setTimeCreateBdds((double) timeAbstraction);
                synchronized (_lock) {
                    ecStats.add(stats);
                }
            }
            if (!res.isVerified()) {
                VerifyParam vp = new VerifyParam(res, model, srcRouters, enc, enc2, prop, prop2);
                AnswerElement ae = answer.apply(vp);
                synchronized (_lock) {
                    answerElement[0] = ae;
                    result[0] = res;
                }
                return true;
            }
            synchronized (_lock) {
                result[1] = res;
            }
            return false;
        }
    });
    totalTime = (System.currentTimeMillis() - totalTime);
    VerificationResult res;
    AnswerElement ae;
    if (hasCounterExample) {
        res = result[0];
        ae = answerElement[0];
    } else {
        res = result[1];
        VerifyParam vp = new VerifyParam(res, null, null, null, null, null, null);
        ae = answer.apply(vp);
    }
    if (q.getBenchmark()) {
        VerificationStats stats = VerificationStats.combineAll(ecStats, totalTime);
        res.setStats(stats);
    }
    return ae;
}
Also used : BoolExpr(com.microsoft.z3.BoolExpr) HeaderLocationQuestion(org.batfish.datamodel.questions.smt.HeaderLocationQuestion) ArrayList(java.util.ArrayList) PathRegexes(org.batfish.symbolic.utils.PathRegexes) NetworkSlice(org.batfish.symbolic.abstraction.NetworkSlice) Table2(org.batfish.symbolic.collections.Table2) Stream(java.util.stream.Stream) Supplier(java.util.function.Supplier) BatfishException(org.batfish.common.BatfishException) SmtOneAnswerElement(org.batfish.symbolic.answers.SmtOneAnswerElement) SmtDeterminismAnswerElement(org.batfish.symbolic.answers.SmtDeterminismAnswerElement) SmtReachabilityAnswerElement(org.batfish.symbolic.answers.SmtReachabilityAnswerElement) AnswerElement(org.batfish.datamodel.answers.AnswerElement) SmtManyAnswerElement(org.batfish.symbolic.answers.SmtManyAnswerElement) Graph(org.batfish.symbolic.Graph) Model(com.microsoft.z3.Model) GraphEdge(org.batfish.symbolic.GraphEdge)

Aggregations

BoolExpr (com.microsoft.z3.BoolExpr)2 Model (com.microsoft.z3.Model)2 ArrayList (java.util.ArrayList)2 Supplier (java.util.function.Supplier)2 Stream (java.util.stream.Stream)2 BatfishException (org.batfish.common.BatfishException)2 AnswerElement (org.batfish.datamodel.answers.AnswerElement)2 Iterables (com.google.common.collect.Iterables)1 ArithExpr (com.microsoft.z3.ArithExpr)1 BitVecExpr (com.microsoft.z3.BitVecExpr)1 Context (com.microsoft.z3.Context)1 Expr (com.microsoft.z3.Expr)1 Collection (java.util.Collection)1 Collections (java.util.Collections)1 EnumMap (java.util.EnumMap)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Map (java.util.Map)1 Entry (java.util.Map.Entry)1