Search in sources :

Example 6 with GraphEdge

use of org.batfish.symbolic.GraphEdge 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 7 with GraphEdge

use of org.batfish.symbolic.GraphEdge in project batfish by batfish.

the class EncoderSlice method initForwardingAcross.

/*
   * Initialize boolean expressions to represent that traffic sent along
   * and edge will reach the other side of the edge.
   */
private void initForwardingAcross() {
    _symbolicDecisions.getDataForwarding().forEach((router, edge, var) -> {
        BoolExpr inAcl;
        if (edge.getEnd() == null) {
            inAcl = mkTrue();
        } else {
            GraphEdge ge = getGraph().getOtherEnd().get(edge);
            inAcl = _inboundAcls.get(ge);
            if (inAcl == null) {
                inAcl = mkTrue();
            }
        }
        _forwardsAcross.put(router, edge, mkAnd(var, inAcl));
    });
}
Also used : BoolExpr(com.microsoft.z3.BoolExpr) GraphEdge(org.batfish.symbolic.GraphEdge)

Example 8 with GraphEdge

use of org.batfish.symbolic.GraphEdge in project batfish by batfish.

the class EncoderSlice method addImportConstraint.

/*
   * Creates the transfer function to represent import filters
   * between two symbolic records. The import filter depends
   * heavily on the protocol.
   */
private void addImportConstraint(LogicalEdge e, SymbolicRoute varsOther, Configuration conf, Protocol proto, GraphEdge ge, String router) {
    SymbolicRoute vars = e.getSymbolicRecord();
    Interface iface = ge.getStart();
    ArithExpr failed = getSymbolicFailures().getFailedVariable(e.getEdge());
    assert (failed != null);
    BoolExpr notFailed = mkEq(failed, mkInt(0));
    if (vars.getIsUsed()) {
        if (proto.isConnected()) {
            Prefix p = iface.getAddress().getPrefix();
            BoolExpr relevant = mkAnd(interfaceActive(iface, proto), isRelevantFor(p, _symbolicPacket.getDstIp()), notFailed);
            BoolExpr per = vars.getPermitted();
            BoolExpr len = safeEq(vars.getPrefixLength(), mkInt(p.getPrefixLength()));
            BoolExpr ad = safeEq(vars.getAdminDist(), mkInt(1));
            BoolExpr lp = safeEq(vars.getLocalPref(), mkInt(0));
            BoolExpr met = safeEq(vars.getMetric(), mkInt(0));
            BoolExpr values = mkAnd(per, len, ad, lp, met);
            add(mkIf(relevant, values, mkNot(vars.getPermitted())));
        }
        if (proto.isStatic()) {
            List<StaticRoute> srs = getGraph().getStaticRoutes().get(router, iface.getName());
            assert (srs != null);
            BoolExpr acc = mkNot(vars.getPermitted());
            for (StaticRoute sr : srs) {
                Prefix p = sr.getNetwork();
                BoolExpr relevant = mkAnd(interfaceActive(iface, proto), isRelevantFor(p, _symbolicPacket.getDstIp()), notFailed);
                BoolExpr per = vars.getPermitted();
                BoolExpr len = safeEq(vars.getPrefixLength(), mkInt(p.getPrefixLength()));
                BoolExpr ad = safeEq(vars.getAdminDist(), mkInt(sr.getAdministrativeCost()));
                BoolExpr lp = safeEq(vars.getLocalPref(), mkInt(0));
                BoolExpr met = safeEq(vars.getMetric(), mkInt(0));
                BoolExpr values = mkAnd(per, len, ad, lp, met);
                acc = mkIf(relevant, values, acc);
            }
            add(acc);
        }
        if (proto.isOspf() || proto.isBgp()) {
            BoolExpr val = mkNot(vars.getPermitted());
            if (varsOther != null) {
                // BoolExpr isRoot = relevantOrigination(originations);
                BoolExpr active = interfaceActive(iface, proto);
                // Handle iBGP by checking reachability to the next hop to send messages
                boolean isNonClient = (proto.isBgp()) && (getGraph().peerType(ge) != Graph.BgpSendType.TO_EBGP);
                boolean isClient = (proto.isBgp()) && (getGraph().peerType(ge) == Graph.BgpSendType.TO_RR);
                BoolExpr receiveMessage;
                String currentRouter = ge.getRouter();
                String peerRouter = ge.getPeer();
                if (_encoder.getModelIgp() && isNonClient) {
                    // Lookup reachabilty based on peer next-hop
                    receiveMessage = _encoder.getSliceReachability().get(currentRouter).get(peerRouter);
                /* EncoderSlice peerSlice = _encoder.getSlice(peerRouter);
            BoolExpr srcPort = mkEq(peerSlice.getSymbolicPacket().getSrcPort(), mkInt(179));
            BoolExpr srcIp = mkEq(peerSlice.getSymbolicPacket().getSrcIp(), mkInt(0));
            BoolExpr tcpAck = mkEq(peerSlice.getSymbolicPacket().getTcpAck(), mkFalse());
            BoolExpr tcpCwr = mkEq(peerSlice.getSymbolicPacket().getTcpCwr(), mkFalse());
            BoolExpr tcpEce = mkEq(peerSlice.getSymbolicPacket().getTcpEce(), mkFalse());
            BoolExpr tcpFin = mkEq(peerSlice.getSymbolicPacket().getTcpFin(), mkFalse());
            BoolExpr tcpPsh = mkEq(peerSlice.getSymbolicPacket().getTcpPsh(), mkFalse());
            BoolExpr tcpRst = mkEq(peerSlice.getSymbolicPacket().getTcpRst(), mkFalse());
            BoolExpr tcpSyn = mkEq(peerSlice.getSymbolicPacket().getTcpSyn(), mkFalse());
            BoolExpr tcpUrg = mkEq(peerSlice.getSymbolicPacket().getTcpUrg(), mkFalse());
            BoolExpr icmpCode = mkEq(peerSlice.getSymbolicPacket().getIcmpCode(), mkInt(0));
            BoolExpr icmpType = mkEq(peerSlice.getSymbolicPacket().getIcmpType(), mkInt(0));
            BoolExpr all =
                mkAnd(srcPort, srcIp, tcpAck,
                    tcpCwr, tcpEce, tcpFin, tcpPsh, tcpRst, tcpSyn, tcpUrg, icmpCode, icmpType);
            receiveMessage = mkImplies(all, receiveMessage); */
                } else if (_encoder.getModelIgp() && isClient) {
                    // Lookup reachability based on client id tag to find next hop
                    BoolExpr acc = mkTrue();
                    for (Map.Entry<String, Integer> entry : getGraph().getOriginatorId().entrySet()) {
                        String r = entry.getKey();
                        Integer id = entry.getValue();
                        if (!r.equals(currentRouter)) {
                            BoolExpr reach = _encoder.getSliceReachability().get(currentRouter).get(r);
                            /* EncoderSlice peerSlice = _encoder.getSlice(r);
                BoolExpr srcPort = mkEq(peerSlice.getSymbolicPacket().getSrcPort(), mkInt(179));
                BoolExpr srcIp = mkEq(peerSlice.getSymbolicPacket().getSrcIp(), mkInt(0));
                BoolExpr tcpAck = mkEq(peerSlice.getSymbolicPacket().getTcpAck(), mkFalse());
                BoolExpr tcpCwr = mkEq(peerSlice.getSymbolicPacket().getTcpCwr(), mkFalse());
                BoolExpr tcpEce = mkEq(peerSlice.getSymbolicPacket().getTcpEce(), mkFalse());
                BoolExpr tcpFin = mkEq(peerSlice.getSymbolicPacket().getTcpFin(), mkFalse());
                BoolExpr tcpPsh = mkEq(peerSlice.getSymbolicPacket().getTcpPsh(), mkFalse());
                BoolExpr tcpRst = mkEq(peerSlice.getSymbolicPacket().getTcpRst(), mkFalse());
                BoolExpr tcpSyn = mkEq(peerSlice.getSymbolicPacket().getTcpSyn(), mkFalse());
                BoolExpr tcpUrg = mkEq(peerSlice.getSymbolicPacket().getTcpUrg(), mkFalse());
                BoolExpr icmpCode = mkEq(peerSlice.getSymbolicPacket().getIcmpCode(), mkInt(0));
                BoolExpr icmpType = mkEq(peerSlice.getSymbolicPacket().getIcmpType(), mkInt(0));
                BoolExpr all =
                    mkAnd(srcPort, srcIp, tcpAck,
                        tcpCwr, tcpEce, tcpFin, tcpPsh, tcpRst, tcpSyn, tcpUrg, icmpCode, icmpType);
                reach = mkImplies(all, reach); */
                            acc = mkAnd(acc, mkImplies(varsOther.getClientId().checkIfValue(id), reach));
                        }
                    }
                    receiveMessage = acc;
                // Just check if the link is failed
                } else {
                    receiveMessage = notFailed;
                }
                // Take into account BGP loop prevention
                // The path length will prevent any isolated loops
                BoolExpr loop = mkFalse();
                if (proto.isBgp() && ge.getPeer() != null) {
                    String peer = ge.getPeer();
                    GraphEdge gePeer = getGraph().getOtherEnd().get(ge);
                    loop = getSymbolicDecisions().getControlForwarding().get(peer, gePeer);
                }
                assert (loop != null);
                BoolExpr usable = mkAnd(mkNot(loop), active, varsOther.getPermitted(), receiveMessage);
                BoolExpr importFunction;
                RoutingPolicy pol = getGraph().findImportRoutingPolicy(router, proto, e.getEdge());
                if (Encoder.ENABLE_DEBUGGING && pol != null) {
                    System.out.println("Import Policy: " + pol.getName());
                }
                List<Statement> statements;
                if (pol == null) {
                    Statements.StaticStatement s = new Statements.StaticStatement(Statements.ExitAccept);
                    statements = Collections.singletonList(s);
                } else {
                    statements = pol.getStatements();
                }
                // OSPF cost calculated based on incoming interface
                Integer cost = proto.isOspf() ? addedCost(proto, ge) : 0;
                TransferSSA f = new TransferSSA(this, conf, varsOther, vars, proto, statements, cost, ge, false);
                importFunction = f.compute();
                BoolExpr acc = mkIf(usable, importFunction, val);
                if (Encoder.ENABLE_DEBUGGING) {
                    System.out.println("IMPORT FUNCTION: " + router + " " + varsOther.getName());
                    System.out.println(importFunction.simplify());
                    System.out.println("\n\n");
                }
                add(acc);
            } else {
                add(val);
            }
        }
    }
}
Also used : ArithExpr(com.microsoft.z3.ArithExpr) BoolExpr(com.microsoft.z3.BoolExpr) StaticRoute(org.batfish.datamodel.StaticRoute) Statement(org.batfish.datamodel.routing_policy.statement.Statement) RoutingPolicy(org.batfish.datamodel.routing_policy.RoutingPolicy) Prefix(org.batfish.datamodel.Prefix) Entry(java.util.Map.Entry) Statements(org.batfish.datamodel.routing_policy.statement.Statements) GraphEdge(org.batfish.symbolic.GraphEdge) Interface(org.batfish.datamodel.Interface)

Example 9 with GraphEdge

use of org.batfish.symbolic.GraphEdge in project batfish by batfish.

the class EncoderSlice method addForwardingVariables.

/*
   * Initalizes variables representing the control plane and
   * data plane final forwarding decisions
   */
private void addForwardingVariables() {
    for (Entry<String, List<GraphEdge>> entry : getGraph().getEdgeMap().entrySet()) {
        String router = entry.getKey();
        List<GraphEdge> edges = entry.getValue();
        for (GraphEdge edge : edges) {
            String iface = edge.getStart().getName();
            String cName = _encoder.getId() + "_" + _sliceName + "CONTROL-FORWARDING_" + router + "_" + iface;
            BoolExpr cForward = getCtx().mkBoolConst(cName);
            getAllVariables().put(cForward.toString(), cForward);
            _symbolicDecisions.getControlForwarding().put(router, edge, cForward);
            // Don't add data forwarding variable for abstract edge
            if (!edge.isAbstract()) {
                String dName = _encoder.getId() + "_" + _sliceName + "DATA-FORWARDING_" + router + "_" + iface;
                BoolExpr dForward = getCtx().mkBoolConst(dName);
                getAllVariables().put(dForward.toString(), dForward);
                _symbolicDecisions.getDataForwarding().put(router, edge, dForward);
            }
        }
    }
}
Also used : BoolExpr(com.microsoft.z3.BoolExpr) IpAccessList(org.batfish.datamodel.IpAccessList) ArrayList(java.util.ArrayList) List(java.util.List) GraphEdge(org.batfish.symbolic.GraphEdge)

Example 10 with GraphEdge

use of org.batfish.symbolic.GraphEdge in project batfish by batfish.

the class EncoderSlice method addDataForwardingConstraints.

/*
   * Constraints for the final data plane forwarding behavior.
   * Forwarding occurs in the data plane if the control plane decides
   * to use an interface, and no ACL blocks the packet:
   *
   * data_fwd(iface) = control_fwd(iface) and not acl(iface)
   */
private void addDataForwardingConstraints() {
    for (Entry<String, List<GraphEdge>> entry : getGraph().getEdgeMap().entrySet()) {
        String router = entry.getKey();
        List<GraphEdge> edges = entry.getValue();
        for (GraphEdge ge : edges) {
            // setup forwarding for non-abstract edges
            if (!ge.isAbstract()) {
                BoolExpr fwd = mkFalse();
                BoolExpr cForward = _symbolicDecisions.getControlForwarding().get(router, ge);
                BoolExpr dForward = _symbolicDecisions.getDataForwarding().get(router, ge);
                assert (cForward != null);
                assert (dForward != null);
                // out the current edge ge, the we use ge.
                for (GraphEdge ge2 : getGraph().getEdgeMap().get(router)) {
                    if (ge2.isAbstract()) {
                        BoolExpr ctrlFwd = getSymbolicDecisions().getControlForwarding().get(router, ge2);
                        Graph.BgpSendType st = getGraph().peerType(ge2);
                        // If Route reflectors, then next hop based on ID
                        if (st == Graph.BgpSendType.TO_RR) {
                            SymbolicRoute record = getSymbolicDecisions().getBestNeighbor().get(router);
                            // adjust for iBGP in main slice
                            BoolExpr acc = mkFalse();
                            if (isMainSlice()) {
                                for (Entry<String, Integer> entry2 : getGraph().getOriginatorId().entrySet()) {
                                    String r = entry2.getKey();
                                    Integer id = entry2.getValue();
                                    EncoderSlice s = _encoder.getSlice(r);
                                    // Make sure
                                    if (otherSliceHasEdge(s, router, ge)) {
                                        BoolExpr outEdge = s.getSymbolicDecisions().getDataForwarding().get(router, ge);
                                        acc = mkOr(acc, mkAnd(record.getClientId().checkIfValue(id), outEdge));
                                    }
                                }
                            }
                            fwd = mkOr(fwd, mkAnd(ctrlFwd, acc));
                        } else {
                            // adjust for iBGP in main slice
                            if (isMainSlice()) {
                                EncoderSlice s = _encoder.getSlice(ge2.getPeer());
                                if (otherSliceHasEdge(s, router, ge)) {
                                    BoolExpr outEdge = s.getSymbolicDecisions().getDataForwarding().get(router, ge);
                                    fwd = mkOr(fwd, mkAnd(ctrlFwd, outEdge));
                                }
                            }
                        }
                    }
                }
                fwd = mkOr(fwd, cForward);
                BoolExpr acl = _outboundAcls.get(ge);
                if (acl == null) {
                    acl = mkTrue();
                }
                BoolExpr notBlocked = mkAnd(fwd, acl);
                add(mkEq(notBlocked, dForward));
            }
        }
    }
}
Also used : BoolExpr(com.microsoft.z3.BoolExpr) Graph(org.batfish.symbolic.Graph) IpAccessList(org.batfish.datamodel.IpAccessList) ArrayList(java.util.ArrayList) List(java.util.List) GraphEdge(org.batfish.symbolic.GraphEdge)

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