Search in sources :

Example 1 with Statements

use of org.batfish.datamodel.routing_policy.statement.Statements in project batfish by batfish.

the class EncoderSlice method addExportConstraint.

/*
   * Creates the transfer function to represent export filters
   * between two symbolic records. The import filter depends
   * heavily on the protocol.
   */
private void addExportConstraint(LogicalEdge e, SymbolicRoute varsOther, @Nullable SymbolicRoute ospfRedistribVars, @Nullable SymbolicRoute overallBest, Configuration conf, Protocol proto, GraphEdge ge, String router, boolean usedExport, Set<Prefix> originations) {
    SymbolicRoute vars = e.getSymbolicRecord();
    Interface iface = ge.getStart();
    ArithExpr failed = getSymbolicFailures().getFailedVariable(e.getEdge());
    assert (failed != null);
    BoolExpr notFailed = mkEq(failed, mkInt(0));
    // only add constraints once when using a single copy of export variables
    if (!_optimizations.getSliceCanKeepSingleExportVar().get(router).get(proto) || !usedExport) {
        if (proto.isConnected()) {
            BoolExpr val = mkNot(vars.getPermitted());
            add(val);
        }
        if (proto.isStatic()) {
            BoolExpr val = mkNot(vars.getPermitted());
            add(val);
        }
        if (proto.isOspf() || proto.isBgp()) {
            // BGP cost based on export
            Integer cost = proto.isBgp() ? addedCost(proto, ge) : 0;
            BoolExpr val = mkNot(vars.getPermitted());
            BoolExpr active = interfaceActive(iface, proto);
            // Apply BGP export policy and cost based on peer type
            // (1) EBGP --> ALL
            // (2) CLIENT --> ALL
            // (3) NONCLIENT --> EBGP, CLIENT
            boolean isNonClientEdge = proto.isBgp() && getGraph().peerType(ge) != Graph.BgpSendType.TO_EBGP;
            boolean isClientEdge = proto.isBgp() && getGraph().peerType(ge) == Graph.BgpSendType.TO_CLIENT;
            boolean isInternalExport = varsOther.isBest() && _optimizations.getNeedBgpInternal().contains(router);
            BoolExpr doExport = mkTrue();
            if (isInternalExport && proto.isBgp() && isNonClientEdge) {
                if (isClientEdge) {
                    cost = 0;
                } else {
                    // Lookup if we learned from iBGP, and if so, don't export the route
                    SymbolicRoute other = getBestNeighborPerProtocol(router, proto);
                    assert other != null;
                    assert other.getBgpInternal() != null;
                    if (other.getBgpInternal() != null) {
                        doExport = mkNot(other.getBgpInternal());
                        cost = 0;
                    }
                }
            }
            BoolExpr acc;
            RoutingPolicy pol = getGraph().findExportRoutingPolicy(router, proto, e.getEdge());
            if (Encoder.ENABLE_DEBUGGING && pol != null) {
                System.out.println("Export policy (" + _sliceName + "," + ge + "): " + pol.getName());
            }
            // We have to wrap this with the right thing for some reason
            List<Statement> statements;
            Statements.StaticStatement s1 = new Statements.StaticStatement(Statements.ExitAccept);
            Statements.StaticStatement s2 = new Statements.StaticStatement(Statements.ExitReject);
            if (proto.isOspf()) {
                If i = new If();
                List<Statement> stmts = (pol == null ? Collections.singletonList(s2) : pol.getStatements());
                i.setTrueStatements(Collections.singletonList(s1));
                i.setFalseStatements(stmts);
                BooleanExpr expr = new MatchProtocol(RoutingProtocol.OSPF);
                i.setGuard(expr);
                statements = Collections.singletonList(i);
            } else {
                statements = (pol == null ? Collections.singletonList(s1) : pol.getStatements());
            }
            TransferSSA f = new TransferSSA(this, conf, varsOther, vars, proto, statements, cost, ge, true);
            acc = f.compute();
            BoolExpr usable = mkAnd(active, doExport, varsOther.getPermitted(), notFailed);
            // will maintain the same preference when adding to the cost.
            if (ospfRedistribVars != null) {
                assert overallBest != null;
                f = new TransferSSA(this, conf, overallBest, ospfRedistribVars, proto, statements, cost, ge, true);
                BoolExpr acc2 = f.compute();
                // System.out.println("ADDING: \n" + acc2.simplify());
                add(acc2);
                BoolExpr usable2 = mkAnd(active, doExport, ospfRedistribVars.getPermitted(), notFailed);
                BoolExpr geq = greaterOrEqual(conf, proto, ospfRedistribVars, varsOther, e);
                BoolExpr isBetter = mkNot(mkAnd(ospfRedistribVars.getPermitted(), geq));
                BoolExpr usesOspf = mkAnd(varsOther.getPermitted(), isBetter);
                BoolExpr eq = equal(conf, proto, ospfRedistribVars, vars, e, false);
                BoolExpr eqPer = mkEq(ospfRedistribVars.getPermitted(), vars.getPermitted());
                acc = mkIf(usesOspf, mkIf(usable, acc, val), mkIf(usable2, mkAnd(eq, eqPer), val));
            } else {
                acc = mkIf(usable, acc, val);
            }
            for (Prefix p : originations) {
                // For OSPF, we need to explicitly initiate a route
                if (proto.isOspf()) {
                    BoolExpr ifaceUp = interfaceActive(iface, proto);
                    BoolExpr relevantPrefix = isRelevantFor(p, _symbolicPacket.getDstIp());
                    BoolExpr relevant = mkAnd(ifaceUp, relevantPrefix);
                    int adminDistance = defaultAdminDistance(conf, proto);
                    int prefixLength = p.getPrefixLength();
                    BoolExpr per = vars.getPermitted();
                    BoolExpr lp = safeEq(vars.getLocalPref(), mkInt(0));
                    BoolExpr ad = safeEq(vars.getAdminDist(), mkInt(adminDistance));
                    BoolExpr met = safeEq(vars.getMetric(), mkInt(cost));
                    BoolExpr med = safeEq(vars.getMed(), mkInt(100));
                    BoolExpr len = safeEq(vars.getPrefixLength(), mkInt(prefixLength));
                    BoolExpr type = safeEqEnum(vars.getOspfType(), OspfType.O);
                    BoolExpr area = safeEqEnum(vars.getOspfArea(), iface.getOspfAreaName());
                    BoolExpr internal = safeEq(vars.getBgpInternal(), mkFalse());
                    BoolExpr igpMet = safeEq(vars.getIgpMetric(), mkInt(0));
                    BoolExpr comms = mkTrue();
                    for (Map.Entry<CommunityVar, BoolExpr> entry : vars.getCommunities().entrySet()) {
                        comms = mkAnd(comms, mkNot(entry.getValue()));
                    }
                    BoolExpr values = mkAnd(per, lp, ad, met, med, len, type, area, internal, igpMet, comms);
                    // Don't originate OSPF route when there is a better redistributed route
                    if (ospfRedistribVars != null) {
                        BoolExpr betterLen = mkGt(ospfRedistribVars.getPrefixLength(), mkInt(prefixLength));
                        BoolExpr equalLen = mkEq(ospfRedistribVars.getPrefixLength(), mkInt(prefixLength));
                        BoolExpr betterAd = mkLt(ospfRedistribVars.getAdminDist(), mkInt(110));
                        BoolExpr better = mkOr(betterLen, mkAnd(equalLen, betterAd));
                        BoolExpr betterRedistributed = mkAnd(ospfRedistribVars.getPermitted(), better);
                        relevant = mkAnd(relevant, mkNot(betterRedistributed));
                    }
                    acc = mkIf(relevant, values, acc);
                }
            }
            add(acc);
            if (Encoder.ENABLE_DEBUGGING) {
                System.out.println("EXPORT: " + router + " " + varsOther.getName() + " " + ge);
                System.out.println(acc.simplify());
                System.out.println("\n\n");
            }
        }
    }
}
Also used : ArithExpr(com.microsoft.z3.ArithExpr) BoolExpr(com.microsoft.z3.BoolExpr) Statement(org.batfish.datamodel.routing_policy.statement.Statement) RoutingPolicy(org.batfish.datamodel.routing_policy.RoutingPolicy) Prefix(org.batfish.datamodel.Prefix) MatchProtocol(org.batfish.datamodel.routing_policy.expr.MatchProtocol) CommunityVar(org.batfish.symbolic.CommunityVar) Statements(org.batfish.datamodel.routing_policy.statement.Statements) If(org.batfish.datamodel.routing_policy.statement.If) HashMap(java.util.HashMap) Map(java.util.Map) Interface(org.batfish.datamodel.Interface) BooleanExpr(org.batfish.datamodel.routing_policy.expr.BooleanExpr)

Example 2 with Statements

use of org.batfish.datamodel.routing_policy.statement.Statements 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)

Aggregations

ArithExpr (com.microsoft.z3.ArithExpr)2 BoolExpr (com.microsoft.z3.BoolExpr)2 Interface (org.batfish.datamodel.Interface)2 Prefix (org.batfish.datamodel.Prefix)2 RoutingPolicy (org.batfish.datamodel.routing_policy.RoutingPolicy)2 Statement (org.batfish.datamodel.routing_policy.statement.Statement)2 Statements (org.batfish.datamodel.routing_policy.statement.Statements)2 HashMap (java.util.HashMap)1 Map (java.util.Map)1 Entry (java.util.Map.Entry)1 StaticRoute (org.batfish.datamodel.StaticRoute)1 BooleanExpr (org.batfish.datamodel.routing_policy.expr.BooleanExpr)1 MatchProtocol (org.batfish.datamodel.routing_policy.expr.MatchProtocol)1 If (org.batfish.datamodel.routing_policy.statement.If)1 CommunityVar (org.batfish.symbolic.CommunityVar)1 GraphEdge (org.batfish.symbolic.GraphEdge)1