Search in sources :

Example 1 with Tuple

use of org.batfish.symbolic.utils.Tuple in project batfish by batfish.

the class AbstractionBuilder method collectInterfaceInformation.

private void collectInterfaceInformation(Set<String> partition, boolean isUniversal) {
    for (String router : partition) {
        List<GraphEdge> edges = _graph.getEdgeMap().get(router);
        for (GraphEdge edge : edges) {
            String peer = edge.getPeer();
            InterfacePolicy ipol = _importPol.get(edge);
            GraphEdge otherEnd = _graph.getOtherEnd().get(edge);
            InterfacePolicy epol = null;
            if (otherEnd != null) {
                epol = _exportPol.get(otherEnd);
            }
            // Update the existential map
            Integer peerGroup = (peer == null ? (_graph.isExternal(edge) ? EBGP_INDEX : HOST_OR_LOOPBACK_INDEX) : _abstractGroups.getHandle(peer));
            EdgePolicy pair = new EdgePolicy(ipol, epol);
            EdgePolicyToRole ee = new EdgePolicyToRole(peerGroup, pair);
            if (isUniversal) {
                // Universal abstraction
                Tuple<String, EdgePolicyToRole> tup = new Tuple<>(peer, ee);
                Set<Tuple<String, EdgePolicyToRole>> group = _universalMap.computeIfAbsent(router, k -> new HashSet<>());
                group.add(tup);
            } else {
                // Existential abstraction
                Integer i = _existentialMap.get(router, ee);
                i = (i == null ? 1 : i + 1);
                _existentialMap.put(router, ee, i);
            }
            // Update the id map
            if (peerGroup >= 0) {
                Set<EdgePolicyToRole> x = _eeMap.computeIfAbsent(router, peerGroup, (k1, k2) -> new HashSet<>());
                x.add(ee);
                Set<EdgePolicy> y = _polMap.computeIfAbsent(router, peerGroup, (k1, k2) -> new HashSet<>());
                y.add(pair);
            }
        }
    }
}
Also used : GraphEdge(org.batfish.symbolic.GraphEdge) Tuple(org.batfish.symbolic.utils.Tuple)

Example 2 with Tuple

use of org.batfish.symbolic.utils.Tuple in project batfish by batfish.

the class DestinationClasses method addCatchAllCase.

/**
 * Adds a catch-all headerspace to the headerspace map. The catch-all case matches dstIps, does
 * not match notDstIps, and doesn't match anything matched by anything in destinationMap.
 *
 * @param dstIps A list of destination IPs that should be in the catch-all headerspace.
 * @param notDstIps A list of destination IPs that should not be in the catch-all headerspace.
 * @param destinationMap Inversion of the prefix trie -- from sets of destinations to prefixes
 */
private void addCatchAllCase(List<Prefix> dstIps, List<Prefix> notDstIps, Map<Set<String>, List<Prefix>> destinationMap) {
    HeaderSpace catchAll = createHeaderSpace(dstIps);
    catchAll.setNotDstIps(Stream.concat(notDstIps.stream(), destinationMap.values().stream().flatMap(Collection::stream)).map(IpWildcard::new).collect(Collectors.toSet()));
    if (_headerspace != null) {
        copyAllButDestinationIp(catchAll, _headerspace);
    }
    if (!catchAll.getNotDstIps().equals(catchAll.getDstIps())) {
        _headerspaceMap.put(new HashSet<>(), new Tuple<>(catchAll, new Tuple<>(null, true)));
    }
}
Also used : IpWildcard(org.batfish.datamodel.IpWildcard) Collection(java.util.Collection) HeaderSpace(org.batfish.datamodel.HeaderSpace) Tuple(org.batfish.symbolic.utils.Tuple)

Example 3 with Tuple

use of org.batfish.symbolic.utils.Tuple in project batfish by batfish.

the class Encoder method verify.

/**
 * Checks that a property is always true by seeing if the encoding is unsatisfiable. mkIf the
 * model is satisfiable, then there is a counter example to the property.
 *
 * @return A VerificationResult indicating the status of the check.
 */
public Tuple<VerificationResult, Model> verify() {
    EncoderSlice mainSlice = _slices.get(MAIN_SLICE_NAME);
    int numVariables = _allVariables.size();
    int numConstraints = _solver.getAssertions().length;
    int numNodes = mainSlice.getGraph().getConfigurations().size();
    int numEdges = 0;
    for (Map.Entry<String, Set<String>> e : mainSlice.getGraph().getNeighbors().entrySet()) {
        numEdges += e.getValue().size();
    }
    long start = System.currentTimeMillis();
    Status status = _solver.check();
    long time = System.currentTimeMillis() - start;
    VerificationStats stats = null;
    if (_question.getBenchmark()) {
        stats = new VerificationStats();
        stats.setAvgNumNodes(numNodes);
        stats.setMaxNumNodes(numNodes);
        stats.setMinNumNodes(numNodes);
        stats.setAvgNumEdges(numEdges);
        stats.setMaxNumEdges(numEdges);
        stats.setMinNumEdges(numEdges);
        stats.setAvgNumVariables(numVariables);
        stats.setMaxNumVariables(numVariables);
        stats.setMinNumVariables(numVariables);
        stats.setAvgNumConstraints(numConstraints);
        stats.setMaxNumConstraints(numConstraints);
        stats.setMinNumConstraints(numConstraints);
        stats.setAvgSolverTime(time);
        stats.setMaxSolverTime(time);
        stats.setMinSolverTime(time);
    }
    if (status == Status.UNSATISFIABLE) {
        VerificationResult res = new VerificationResult(true, null, null, null, null, null, stats);
        return new Tuple<>(res, null);
    } else if (status == Status.UNKNOWN) {
        throw new BatfishException("ERROR: satisfiability unknown");
    } else {
        VerificationResult result;
        Model m;
        while (true) {
            m = _solver.getModel();
            SortedMap<String, String> model = new TreeMap<>();
            SortedMap<String, String> packetModel = new TreeMap<>();
            SortedSet<String> fwdModel = new TreeSet<>();
            SortedMap<String, SortedMap<String, String>> envModel = new TreeMap<>();
            SortedSet<String> failures = new TreeSet<>();
            buildCounterExample(this, m, model, packetModel, fwdModel, envModel, failures);
            if (_previousEncoder != null) {
                buildCounterExample(_previousEncoder, m, model, packetModel, fwdModel, envModel, failures);
            }
            result = new VerificationResult(false, model, packetModel, envModel, fwdModel, failures, stats);
            if (!_question.getMinimize()) {
                break;
            }
            BoolExpr blocking = environmentBlockingClause(m);
            add(blocking);
            Status s = _solver.check();
            if (s == Status.UNSATISFIABLE) {
                break;
            }
            if (s == Status.UNKNOWN) {
                throw new BatfishException("ERROR: satisfiability unknown");
            }
        }
        return new Tuple<>(result, m);
    }
}
Also used : Status(com.microsoft.z3.Status) BatfishException(org.batfish.common.BatfishException) BoolExpr(com.microsoft.z3.BoolExpr) SortedSet(java.util.SortedSet) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) Set(java.util.Set) SortedSet(java.util.SortedSet) SortedMap(java.util.SortedMap) Model(com.microsoft.z3.Model) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) SortedMap(java.util.SortedMap) Tuple(org.batfish.symbolic.utils.Tuple)

Example 4 with Tuple

use of org.batfish.symbolic.utils.Tuple 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 5 with Tuple

use of org.batfish.symbolic.utils.Tuple in project batfish by batfish.

the class PropertyChecker method findAllNetworkSlices.

private Tuple<Stream<Supplier<NetworkSlice>>, Long> findAllNetworkSlices(HeaderQuestion q, @Nullable Graph graph, boolean useDefaultCase) {
    if (q.getUseAbstraction()) {
        HeaderSpace h = q.getHeaderSpace();
        int numFailures = q.getFailures();
        System.out.println("Start verification");
        System.out.println("Using headerspace: " + h.getDstIps());
        DestinationClasses dcs = DestinationClasses.create(_batfish, graph, h, useDefaultCase);
        System.out.println("Number of edges: " + dcs.getGraph().getAllRealEdges().size());
        System.out.println("Created destination classes");
        System.out.println("Num Classes: " + dcs.getHeaderspaceMap().size());
        long l = System.currentTimeMillis();
        ArrayList<Supplier<NetworkSlice>> ecs = NetworkSlice.allSlices(dcs, numFailures);
        l = System.currentTimeMillis() - l;
        System.out.println("Created BDDs");
        return new Tuple<>(ecs.parallelStream(), l);
    } else {
        List<Supplier<NetworkSlice>> singleEc = new ArrayList<>();
        Graph g = graph == null ? new Graph(_batfish) : graph;
        Abstraction a = new Abstraction(g, null);
        NetworkSlice slice = new NetworkSlice(q.getHeaderSpace(), a, false);
        Supplier<NetworkSlice> sup = () -> slice;
        singleEc.add(sup);
        return new Tuple<>(singleEc.stream(), 0L);
    }
}
Also used : ArrayList(java.util.ArrayList) HeaderSpace(org.batfish.datamodel.HeaderSpace) DestinationClasses(org.batfish.symbolic.abstraction.DestinationClasses) Abstraction(org.batfish.symbolic.abstraction.Abstraction) NetworkSlice(org.batfish.symbolic.abstraction.NetworkSlice) Graph(org.batfish.symbolic.Graph) Supplier(java.util.function.Supplier) Tuple(org.batfish.symbolic.utils.Tuple)

Aggregations

Tuple (org.batfish.symbolic.utils.Tuple)9 ArrayList (java.util.ArrayList)4 Set (java.util.Set)4 TreeSet (java.util.TreeSet)4 HeaderSpace (org.batfish.datamodel.HeaderSpace)4 HashMap (java.util.HashMap)3 HashSet (java.util.HashSet)3 SortedSet (java.util.SortedSet)3 GraphEdge (org.batfish.symbolic.GraphEdge)3 BoolExpr (com.microsoft.z3.BoolExpr)2 List (java.util.List)2 Supplier (java.util.function.Supplier)2 Prefix (org.batfish.datamodel.Prefix)2 Graph (org.batfish.symbolic.Graph)2 Model (com.microsoft.z3.Model)1 Status (com.microsoft.z3.Status)1 Collection (java.util.Collection)1 Map (java.util.Map)1 SortedMap (java.util.SortedMap)1 TreeMap (java.util.TreeMap)1