Search in sources :

Example 1 with Table2

use of org.batfish.symbolic.collections.Table2 in project batfish by batfish.

the class AbstractionBuilder method collectNeighborByAbstractId.

/*
   * Collect concrete neighbors by their abstract ids
   */
private Table2<String, Integer, Set<String>> collectNeighborByAbstractId() {
    // organize neighbors by abstract id
    Table2<String, Integer, Set<String>> neighborByAbstractId = new Table2<>();
    for (Entry<String, List<GraphEdge>> entry : _graph.getEdgeMap().entrySet()) {
        String router = entry.getKey();
        List<GraphEdge> edges = entry.getValue();
        for (GraphEdge ge : edges) {
            String peer = ge.getPeer();
            if (peer != null) {
                Integer j = _abstractGroups.getHandle(peer);
                Set<String> existing = neighborByAbstractId.get(router, j);
                if (existing != null) {
                    existing.add(peer);
                } else {
                    Set<String> neighbors = new HashSet<>();
                    neighbors.add(peer);
                    neighborByAbstractId.put(router, j, neighbors);
                }
            }
        }
    }
    return neighborByAbstractId;
}
Also used : SortedSet(java.util.SortedSet) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) Set(java.util.Set) Table2(org.batfish.symbolic.collections.Table2) ArrayList(java.util.ArrayList) List(java.util.List) GraphEdge(org.batfish.symbolic.GraphEdge) HashSet(java.util.HashSet)

Example 2 with Table2

use of org.batfish.symbolic.collections.Table2 in project batfish by batfish.

the class BatfishCompressor method compress.

public Map<String, Configuration> compress(HeaderSpace h) {
    DestinationClasses dcs = DestinationClasses.create(_batfish, _graph, h, true);
    ArrayList<Supplier<NetworkSlice>> ecs = NetworkSlice.allSlices(dcs, 0);
    Optional<Map<GraphEdge, EquivalenceClassFilter>> opt = ecs.stream().map(Supplier::get).map(this::processSlice).reduce(this::mergeFilters);
    if (!opt.isPresent()) {
        return new HashMap<>();
    }
    Map<GraphEdge, EquivalenceClassFilter> filters = opt.get();
    Table2<String, GraphEdge, EquivalenceClassFilter> filtersByRouter = new Table2<>();
    for (Entry<GraphEdge, EquivalenceClassFilter> entry : filters.entrySet()) {
        GraphEdge ge = entry.getKey();
        filtersByRouter.put(ge.getRouter(), ge, entry.getValue());
    }
    return applyFilters(filtersByRouter);
}
Also used : HashMap(java.util.HashMap) Table2(org.batfish.symbolic.collections.Table2) Supplier(java.util.function.Supplier) HashMap(java.util.HashMap) Map(java.util.Map) GraphEdge(org.batfish.symbolic.GraphEdge)

Example 3 with Table2

use of org.batfish.symbolic.collections.Table2 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)

Example 4 with Table2

use of org.batfish.symbolic.collections.Table2 in project batfish by batfish.

the class PropertyChecker method relateEnvironments.

private BoolExpr relateEnvironments(Encoder enc1, Encoder enc2) {
    // create a map for enc2 to lookup a related environment variable from enc
    Table2<GraphEdge, EdgeType, SymbolicRoute> relatedEnv = new Table2<>();
    for (Entry<LogicalEdge, SymbolicRoute> entry : enc2.getMainSlice().getLogicalGraph().getEnvironmentVars().entrySet()) {
        LogicalEdge lge = entry.getKey();
        SymbolicRoute r = entry.getValue();
        relatedEnv.put(lge.getEdge(), lge.getEdgeType(), r);
    }
    // relate environments if necessary
    BoolExpr related = enc1.mkTrue();
    Map<LogicalEdge, SymbolicRoute> map = enc1.getMainSlice().getLogicalGraph().getEnvironmentVars();
    for (Map.Entry<LogicalEdge, SymbolicRoute> entry : map.entrySet()) {
        LogicalEdge le = entry.getKey();
        SymbolicRoute r1 = entry.getValue();
        String router = le.getEdge().getRouter();
        Configuration conf = enc1.getMainSlice().getGraph().getConfigurations().get(router);
        // Lookup the same environment variable in the other copy
        // The copy will have a different name but the same edge and type
        SymbolicRoute r2 = relatedEnv.get(le.getEdge(), le.getEdgeType());
        assert r2 != null;
        BoolExpr x = equal(enc1, conf, r1, r2);
        related = enc1.mkAnd(related, x);
    }
    return related;
}
Also used : BoolExpr(com.microsoft.z3.BoolExpr) Configuration(org.batfish.datamodel.Configuration) Table2(org.batfish.symbolic.collections.Table2) 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 5 with Table2

use of org.batfish.symbolic.collections.Table2 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);
    });
}
Also used : Configuration(org.batfish.datamodel.Configuration) HashMap(java.util.HashMap) BgpProcess(org.batfish.datamodel.BgpProcess) Ip(org.batfish.datamodel.Ip) Prefix(org.batfish.datamodel.Prefix) BgpNeighbor(org.batfish.datamodel.BgpNeighbor) Table2(org.batfish.symbolic.collections.Table2) Interface(org.batfish.datamodel.Interface) HashSet(java.util.HashSet)

Aggregations

Table2 (org.batfish.symbolic.collections.Table2)5 GraphEdge (org.batfish.symbolic.GraphEdge)4 HashMap (java.util.HashMap)3 BoolExpr (com.microsoft.z3.BoolExpr)2 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 Map (java.util.Map)2 Supplier (java.util.function.Supplier)2 Configuration (org.batfish.datamodel.Configuration)2 Model (com.microsoft.z3.Model)1 EnumMap (java.util.EnumMap)1 List (java.util.List)1 Set (java.util.Set)1 SortedMap (java.util.SortedMap)1 SortedSet (java.util.SortedSet)1 TreeMap (java.util.TreeMap)1 TreeSet (java.util.TreeSet)1 Stream (java.util.stream.Stream)1 BatfishException (org.batfish.common.BatfishException)1 BgpNeighbor (org.batfish.datamodel.BgpNeighbor)1