Search in sources :

Example 11 with CommunityVar

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

the class PropertyChecker method checkLocalEquivalence.

/*
   * Computes whether or not two routers are equivalent.
   * To be equivalent, each router must have identical intefaces.
   *
   * We then relate the environments on each interface for each router
   * so that they are required to be equal.
   *
   * We finally check that their forwarding decisions and exported messages
   * will be equal given their equal inputs.
   */
public AnswerElement checkLocalEquivalence(Pattern n, boolean strict, boolean fullModel) {
    Graph graph = new Graph(_batfish);
    List<String> routers = PatternUtils.findMatchingNodes(graph, n, Pattern.compile(""));
    HeaderQuestion q = new HeaderQuestion();
    q.setFullModel(fullModel);
    q.setFailures(0);
    q.setBaseEnvironmentType(EnvironmentType.ANY);
    Collections.sort(routers);
    SortedMap<String, VerificationResult> result = new TreeMap<>();
    int len = routers.size();
    if (len <= 1) {
        return new SmtManyAnswerElement(new TreeMap<>());
    }
    for (int i = 0; i < len - 1; i++) {
        String r1 = routers.get(i);
        String r2 = routers.get(i + 1);
        // TODO: reorder to encode after checking if we can compare them
        // Create transfer function for router 1
        Set<String> toModel1 = new TreeSet<>();
        toModel1.add(r1);
        Graph g1 = new Graph(_batfish, null, toModel1);
        Encoder e1 = new Encoder(_settings, g1, q);
        e1.computeEncoding();
        Context ctx = e1.getCtx();
        // Create transfer function for router 2
        Set<String> toModel2 = new TreeSet<>();
        toModel2.add(r2);
        Graph g2 = new Graph(_batfish, null, toModel2);
        Encoder e2 = new Encoder(e1, g2);
        e2.computeEncoding();
        EncoderSlice slice1 = e1.getMainSlice();
        EncoderSlice slice2 = e2.getMainSlice();
        // Ensure that the two routers have the same interfaces for comparison
        Pattern p = Pattern.compile(".*");
        Pattern neg = Pattern.compile("");
        List<GraphEdge> edges1 = PatternUtils.findMatchingEdges(g1, p, neg, p, neg);
        List<GraphEdge> edges2 = PatternUtils.findMatchingEdges(g2, p, neg, p, neg);
        Set<String> ifaces1 = interfaces(edges1);
        Set<String> ifaces2 = interfaces(edges2);
        if (!(ifaces1.containsAll(ifaces2) && ifaces2.containsAll(ifaces1))) {
            String msg = String.format("Routers %s and %s have different interfaces", r1, r2);
            System.out.println(msg);
            return new SmtManyAnswerElement(new TreeMap<>());
        }
        // TODO: check running same protocols?
        Map<String, Map<Protocol, Map<String, EnumMap<EdgeType, LogicalEdge>>>> lgeMap2 = logicalEdgeMap(slice2);
        BoolExpr equalEnvs = ctx.mkBool(true);
        BoolExpr equalOutputs = ctx.mkBool(true);
        BoolExpr equalIncomingAcls = ctx.mkBool(true);
        Configuration conf1 = g1.getConfigurations().get(r1);
        Configuration conf2 = g2.getConfigurations().get(r2);
        // Set environments equal
        Set<String> communities = new HashSet<>();
        Set<SymbolicRoute> envRecords = new HashSet<>();
        for (Protocol proto1 : slice1.getProtocols().get(r1)) {
            for (ArrayList<LogicalEdge> es : slice1.getLogicalGraph().getLogicalEdges().get(r1).get(proto1)) {
                for (LogicalEdge lge1 : es) {
                    String ifaceName = lge1.getEdge().getStart().getName();
                    LogicalEdge lge2 = lgeMap2.get(r2).get(proto1).get(ifaceName).get(lge1.getEdgeType());
                    if (lge1.getEdgeType() == EdgeType.IMPORT) {
                        SymbolicRoute vars1 = slice1.getLogicalGraph().getEnvironmentVars().get(lge1);
                        SymbolicRoute vars2 = slice2.getLogicalGraph().getEnvironmentVars().get(lge2);
                        BoolExpr aclIn1 = slice1.getIncomingAcls().get(lge1.getEdge());
                        BoolExpr aclIn2 = slice2.getIncomingAcls().get(lge2.getEdge());
                        if (aclIn1 == null) {
                            aclIn1 = ctx.mkBool(true);
                        }
                        if (aclIn2 == null) {
                            aclIn2 = ctx.mkBool(true);
                        }
                        equalIncomingAcls = ctx.mkAnd(equalIncomingAcls, ctx.mkEq(aclIn1, aclIn2));
                        boolean hasEnv1 = (vars1 != null);
                        boolean hasEnv2 = (vars2 != null);
                        if (hasEnv1 && hasEnv2) {
                            BoolExpr samePermitted = ctx.mkEq(vars1.getPermitted(), vars2.getPermitted());
                            // Set communities equal
                            BoolExpr equalComms = e1.mkTrue();
                            for (Map.Entry<CommunityVar, BoolExpr> entry : vars1.getCommunities().entrySet()) {
                                CommunityVar cvar = entry.getKey();
                                BoolExpr ce1 = entry.getValue();
                                BoolExpr ce2 = vars2.getCommunities().get(cvar);
                                if (ce2 != null) {
                                    equalComms = e1.mkAnd(equalComms, e1.mkEq(ce1, ce2));
                                }
                            }
                            // Set communities belonging to one but not the other
                            // off, but give a warning of the difference
                            BoolExpr unsetComms = e1.mkTrue();
                            for (Map.Entry<CommunityVar, BoolExpr> entry : vars1.getCommunities().entrySet()) {
                                CommunityVar cvar = entry.getKey();
                                BoolExpr ce1 = entry.getValue();
                                BoolExpr ce2 = vars2.getCommunities().get(cvar);
                                if (ce2 == null) {
                                    if (!communities.contains(cvar.getValue())) {
                                        communities.add(cvar.getValue());
                                    /* String msg =
                       String.format(
                           "Warning: community %s found for router %s but not %s.",
                           cvar.getValue(), conf1.getEnvName(), conf2.getEnvName());
                      System.out.println(msg); */
                                    }
                                    unsetComms = e1.mkAnd(unsetComms, e1.mkNot(ce1));
                                }
                            }
                            // Do the same thing for communities missing from the other side
                            for (Map.Entry<CommunityVar, BoolExpr> entry : vars2.getCommunities().entrySet()) {
                                CommunityVar cvar = entry.getKey();
                                BoolExpr ce2 = entry.getValue();
                                BoolExpr ce1 = vars1.getCommunities().get(cvar);
                                if (ce1 == null) {
                                    if (!communities.contains(cvar.getValue())) {
                                        communities.add(cvar.getValue());
                                    /* String msg =
                       String.format(
                           "Warning: community %s found for router %s but not %s.",
                           cvar.getValue(), conf2.getEnvName(), conf1.getEnvName());
                      System.out.println(msg); */
                                    }
                                    unsetComms = e1.mkAnd(unsetComms, e1.mkNot(ce2));
                                }
                            }
                            envRecords.add(vars1);
                            BoolExpr equalVars = slice1.equal(conf1, proto1, vars1, vars2, lge1, true);
                            equalEnvs = ctx.mkAnd(equalEnvs, unsetComms, samePermitted, equalVars, equalComms);
                        } else if (hasEnv1 || hasEnv2) {
                            System.out.println("Edge1: " + lge1);
                            System.out.println("Edge2: " + lge2);
                            throw new BatfishException("one had environment");
                        }
                    } else {
                        SymbolicRoute out1 = lge1.getSymbolicRecord();
                        SymbolicRoute out2 = lge2.getSymbolicRecord();
                        equalOutputs = ctx.mkAnd(equalOutputs, slice1.equal(conf1, proto1, out1, out2, lge1, false));
                    }
                }
            }
        }
        // check the stronger version of local equivalence
        if (strict) {
            for (SymbolicRoute env1 : envRecords) {
                for (SymbolicRoute env2 : envRecords) {
                    if (!env1.equals(env2)) {
                        BoolExpr c = e2.mkImplies(env1.getPermitted(), e2.mkNot(env2.getPermitted()));
                        e2.add(c);
                    }
                }
            }
        }
        // TODO: check both have same environment vars (e.g., screw up configuring peer connection)
        // Create assumptions
        BoolExpr validDest;
        validDest = ignoredDestinations(ctx, slice1, r1, conf1);
        validDest = ctx.mkAnd(validDest, ignoredDestinations(ctx, slice2, r2, conf2));
        SymbolicPacket p1 = slice1.getSymbolicPacket();
        SymbolicPacket p2 = slice2.getSymbolicPacket();
        BoolExpr equalPackets = p1.mkEqual(p2);
        BoolExpr assumptions = ctx.mkAnd(equalEnvs, equalPackets, validDest);
        // Create the requirements
        // Best choices should be the same
        BoolExpr required;
        if (strict) {
            SymbolicRoute best1 = e1.getMainSlice().getSymbolicDecisions().getBestNeighbor().get(conf1.getName());
            SymbolicRoute best2 = e2.getMainSlice().getSymbolicDecisions().getBestNeighbor().get(conf2.getName());
            // Just pick some protocol for defaults, shouldn't matter for best choice
            required = equal(e2, conf2, best1, best2);
        } else {
            // Forwarding decisions should be the sames
            Map<String, GraphEdge> geMap2 = interfaceMap(edges2);
            BoolExpr sameForwarding = ctx.mkBool(true);
            for (GraphEdge ge1 : edges1) {
                GraphEdge ge2 = geMap2.get(ge1.getStart().getName());
                BoolExpr dataFwd1 = slice1.getSymbolicDecisions().getDataForwarding().get(r1, ge1);
                BoolExpr dataFwd2 = slice2.getSymbolicDecisions().getDataForwarding().get(r2, ge2);
                assert (dataFwd1 != null);
                assert (dataFwd2 != null);
                sameForwarding = ctx.mkAnd(sameForwarding, ctx.mkEq(dataFwd1, dataFwd2));
            }
            // equalOutputs, equalIncomingAcls);
            required = ctx.mkAnd(sameForwarding);
        }
        e2.add(assumptions);
        e2.add(ctx.mkNot(required));
        VerificationResult res = e2.verify().getFirst();
        String name = r1 + "<-->" + r2;
        result.put(name, res);
    }
    return new SmtManyAnswerElement(result);
}
Also used : BoolExpr(com.microsoft.z3.BoolExpr) Configuration(org.batfish.datamodel.Configuration) TreeSet(java.util.TreeSet) SmtManyAnswerElement(org.batfish.symbolic.answers.SmtManyAnswerElement) Protocol(org.batfish.symbolic.Protocol) EnumMap(java.util.EnumMap) HashSet(java.util.HashSet) Context(com.microsoft.z3.Context) Pattern(java.util.regex.Pattern) BatfishException(org.batfish.common.BatfishException) TreeMap(java.util.TreeMap) CommunityVar(org.batfish.symbolic.CommunityVar) Graph(org.batfish.symbolic.Graph) HeaderQuestion(org.batfish.datamodel.questions.smt.HeaderQuestion) 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 12 with CommunityVar

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

the class TransferSSA method compute.

/*
   * Convert a list of statements into a Z3 boolean expression for the transfer function.
   */
private TransferResult<BoolExpr, BoolExpr> compute(List<Statement> statements, TransferParam<SymbolicRoute> p, TransferResult<BoolExpr, BoolExpr> result) {
    boolean doesReturn = false;
    for (Statement stmt : statements) {
        if (stmt instanceof StaticStatement) {
            StaticStatement ss = (StaticStatement) stmt;
            switch(ss.getType()) {
                case ExitAccept:
                    doesReturn = true;
                    p.debug("ExitAccept");
                    result = returnValue(p, result, true);
                    break;
                case ReturnTrue:
                    doesReturn = true;
                    p.debug("ReturnTrue");
                    result = returnValue(p, result, true);
                    break;
                case ExitReject:
                    doesReturn = true;
                    p.debug("ExitReject");
                    result = returnValue(p, result, false);
                    break;
                case ReturnFalse:
                    doesReturn = true;
                    p.debug("ReturnFalse");
                    result = returnValue(p, result, false);
                    break;
                case SetDefaultActionAccept:
                    p.debug("SetDefaulActionAccept");
                    p = p.setDefaultAccept(true);
                    break;
                case SetDefaultActionReject:
                    p.debug("SetDefaultActionReject");
                    p = p.setDefaultAccept(false);
                    break;
                case SetLocalDefaultActionAccept:
                    p.debug("SetLocalDefaultActionAccept");
                    p = p.setDefaultAcceptLocal(true);
                    break;
                case SetLocalDefaultActionReject:
                    p.debug("SetLocalDefaultActionReject");
                    p = p.setDefaultAcceptLocal(false);
                    break;
                case ReturnLocalDefaultAction:
                    p.debug("ReturnLocalDefaultAction");
                    // TODO: need to set local default action in an environment
                    if (p.getDefaultAcceptLocal()) {
                        result = returnValue(p, result, true);
                    } else {
                        result = returnValue(p, result, false);
                    }
                    break;
                case FallThrough:
                    p.debug("Fallthrough");
                    result = fallthrough(p, result);
                    break;
                case Return:
                    // TODO: assumming this happens at the end of the function, so it is ignored for now.
                    p.debug("Return");
                    break;
                case RemovePrivateAs:
                    p.debug("RemovePrivateAs");
                    System.out.println("Warning: use of unimplemented feature RemovePrivateAs");
                    break;
                default:
                    throw new BatfishException("TODO: computeTransferFunction: " + ss.getType());
            }
        } else if (stmt instanceof If) {
            p.debug("If");
            If i = (If) stmt;
            TransferResult<BoolExpr, BoolExpr> r = compute(i.getGuard(), p);
            result = result.addChangedVariables(r);
            BoolExpr guard = (BoolExpr) r.getReturnValue().simplify();
            String str = guard.toString();
            // If there are updates in the guard, add them to the parameter p before entering branches
            for (Pair<String, Expr> changed : r.getChangedVariables()) {
                p.debug("CHANGED: " + changed.getFirst());
                updateSingleValue(p, changed.getFirst(), changed.getSecond());
            }
            p.debug("guard: " + str);
            // If we know the branch ahead of time, then specialize
            switch(str) {
                case "true":
                    p.debug("True Branch");
                    result = compute(i.getTrueStatements(), p.indent(), result);
                    break;
                case "false":
                    p.debug("False Branch");
                    compute(i.getFalseStatements(), p.indent(), result);
                    break;
                default:
                    p.debug("True Branch");
                    // clear changed variables before proceeding
                    TransferParam<SymbolicRoute> p1 = p.indent().setData(p.getData().copy());
                    TransferParam<SymbolicRoute> p2 = p.indent().setData(p.getData().copy());
                    TransferResult<BoolExpr, BoolExpr> trueBranch = compute(i.getTrueStatements(), p1, initialResult());
                    p.debug("False Branch");
                    TransferResult<BoolExpr, BoolExpr> falseBranch = compute(i.getFalseStatements(), p2, initialResult());
                    p.debug("JOIN");
                    PList<Pair<String, Pair<Expr, Expr>>> pairs = trueBranch.mergeChangedVariables(falseBranch);
                    // Extract and deal with the return value first so that other
                    // variables have this reflected in their value
                    int idx = pairs.find(pair -> pair.getFirst().equals("RETURN"));
                    if (idx >= 0) {
                        Pair<String, Pair<Expr, Expr>> ret = pairs.get(idx);
                        pairs = pairs.minus(idx);
                        pairs = pairs.plus(pairs.size(), ret);
                    }
                    for (Pair<String, Pair<Expr, Expr>> pair : pairs) {
                        String s = pair.getFirst();
                        p.debug("CHANGED: " + s);
                        Pair<Expr, Expr> x = joinPoint(p, result, guard, pair);
                        result = result.addChangedVariable(s, x.getFirst());
                        if (s.equals("RETURN")) {
                            result = result.setReturnValue((BoolExpr) x.getFirst()).setReturnAssignedValue((BoolExpr) x.getSecond());
                        }
                        if (s.equals("FALLTHROUGH")) {
                            result = result.setFallthroughValue((BoolExpr) x.getFirst()).setReturnAssignedValue((BoolExpr) x.getSecond());
                        }
                    }
                    break;
            }
        } else if (stmt instanceof SetDefaultPolicy) {
            p.debug("SetDefaultPolicy");
            p = p.setDefaultPolicy((SetDefaultPolicy) stmt);
        } else if (stmt instanceof SetMetric) {
            p.debug("SetMetric");
            // TODO: what is the semantics for BGP? Is this MED?
            if (!_current.getProto().isBgp()) {
                SetMetric sm = (SetMetric) stmt;
                LongExpr ie = sm.getMetric();
                ArithExpr newValue = applyLongExprModification(p.getData().getMetric(), ie);
                newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getMetric(), newValue);
                ArithExpr x = createArithVariableWith(p, "METRIC", newValue);
                p.getData().setMetric(x);
                result = result.addChangedVariable("METRIC", x);
            }
        } else if (stmt instanceof SetOspfMetricType) {
            p.debug("SetOspfMetricType");
            SetOspfMetricType somt = (SetOspfMetricType) stmt;
            OspfMetricType mt = somt.getMetricType();
            SymbolicOspfType t;
            if (mt == OspfMetricType.E1) {
                t = new SymbolicOspfType(_enc, OspfType.E1);
            } else {
                t = new SymbolicOspfType(_enc, OspfType.E2);
            }
            BitVecExpr newValue = t.getBitVec();
            newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getOspfType().getBitVec(), newValue);
            BitVecExpr x = createBitVecVariableWith(p, "OSPF-TYPE", 2, newValue);
            p.getData().getOspfType().setBitVec(x);
            result = result.addChangedVariable("OSPF-TYPE", x);
        } else if (stmt instanceof SetLocalPreference) {
            p.debug("SetLocalPreference");
            SetLocalPreference slp = (SetLocalPreference) stmt;
            IntExpr ie = slp.getLocalPreference();
            ArithExpr newValue = applyIntExprModification(p.getData().getLocalPref(), ie);
            newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getLocalPref(), newValue);
            ArithExpr x = createArithVariableWith(p, "LOCAL-PREF", newValue);
            p.getData().setLocalPref(x);
            result = result.addChangedVariable("LOCAL-PREF", x);
        } else if (stmt instanceof AddCommunity) {
            p.debug("AddCommunity");
            AddCommunity ac = (AddCommunity) stmt;
            Set<CommunityVar> comms = _enc.getGraph().findAllCommunities(_conf, ac.getExpr());
            for (CommunityVar cvar : comms) {
                BoolExpr newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getCommunities().get(cvar), _enc.mkTrue());
                BoolExpr x = createBoolVariableWith(p, cvar.getValue(), newValue);
                p.getData().getCommunities().put(cvar, x);
                result = result.addChangedVariable(cvar.getValue(), x);
            }
        } else if (stmt instanceof SetCommunity) {
            p.debug("SetCommunity");
            SetCommunity sc = (SetCommunity) stmt;
            Set<CommunityVar> comms = _enc.getGraph().findAllCommunities(_conf, sc.getExpr());
            for (CommunityVar cvar : comms) {
                BoolExpr newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getCommunities().get(cvar), _enc.mkTrue());
                BoolExpr x = createBoolVariableWith(p, cvar.getValue(), newValue);
                p.getData().getCommunities().put(cvar, x);
                result = result.addChangedVariable(cvar.getValue(), x);
            }
        } else if (stmt instanceof DeleteCommunity) {
            p.debug("DeleteCommunity");
            DeleteCommunity ac = (DeleteCommunity) stmt;
            Set<CommunityVar> comms = _enc.getGraph().findAllCommunities(_conf, ac.getExpr());
            Set<CommunityVar> toDelete = new HashSet<>();
            // Find comms to delete
            for (CommunityVar cvar : comms) {
                if (cvar.getType() == Type.REGEX) {
                    toDelete.addAll(_enc.getCommunityDependencies().get(cvar));
                } else {
                    toDelete.add(cvar);
                }
            }
            // Delete each community
            for (CommunityVar cvar : toDelete) {
                BoolExpr newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getCommunities().get(cvar), _enc.mkFalse());
                BoolExpr x = createBoolVariableWith(p, cvar.getValue(), newValue);
                p.getData().getCommunities().put(cvar, x);
                result = result.addChangedVariable(cvar.getValue(), x);
            }
        } else if (stmt instanceof RetainCommunity) {
            p.debug("RetainCommunity");
        // no op
        } else if (stmt instanceof PrependAsPath) {
            p.debug("PrependAsPath");
            PrependAsPath pap = (PrependAsPath) stmt;
            Integer prependCost = prependLength(pap.getExpr());
            ArithExpr newValue = _enc.mkSum(p.getData().getMetric(), _enc.mkInt(prependCost));
            newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getMetric(), newValue);
            ArithExpr x = createArithVariableWith(p, "METRIC", newValue);
            p.getData().setMetric(x);
            result = result.addChangedVariable("METRIC", x);
        } else if (stmt instanceof SetOrigin) {
            p.debug("SetOrigin");
            System.out.println("Warning: use of unimplemented feature SetOrigin");
        } else if (stmt instanceof SetNextHop) {
            p.debug("SetNextHop");
            System.out.println("Warning: use of unimplemented feature SetNextHop");
        } else {
            String s = (_isExport ? "export" : "import");
            String msg = String.format("Unimplemented feature %s for %s transfer function on interface %s", stmt.toString(), s, _graphEdge.toString());
            throw new BatfishException(msg);
        }
    }
    // If this is the outermost call, then we relate the variables
    if (p.getInitialCall()) {
        p.debug("InitialCall finalizing");
        // Apply the default action
        if (!doesReturn) {
            p.debug("Applying default action: " + p.getDefaultAccept());
            if (p.getDefaultAccept()) {
                result = returnValue(p, result, true);
            } else {
                result = returnValue(p, result, false);
            }
        }
        BoolExpr related = relateVariables(p, result);
        BoolExpr retValue = _enc.mkIf(result.getReturnValue(), related, _enc.mkNot(_current.getPermitted()));
        result = result.setReturnValue(retValue);
    }
    return result;
}
Also used : IncrementMetric(org.batfish.datamodel.routing_policy.expr.IncrementMetric) MatchAsPath(org.batfish.datamodel.routing_policy.expr.MatchAsPath) RetainCommunity(org.batfish.datamodel.routing_policy.statement.RetainCommunity) Not(org.batfish.datamodel.routing_policy.expr.Not) Disjunction(org.batfish.datamodel.routing_policy.expr.Disjunction) CommunityListLine(org.batfish.datamodel.CommunityListLine) RouteFilterList(org.batfish.datamodel.RouteFilterList) Interface(org.batfish.datamodel.Interface) Map(java.util.Map) AddCommunity(org.batfish.datamodel.routing_policy.statement.AddCommunity) MatchCommunitySet(org.batfish.datamodel.routing_policy.expr.MatchCommunitySet) DecrementLocalPreference(org.batfish.datamodel.routing_policy.expr.DecrementLocalPreference) Pair(org.batfish.common.Pair) MatchPrefix6Set(org.batfish.datamodel.routing_policy.expr.MatchPrefix6Set) Statement(org.batfish.datamodel.routing_policy.statement.Statement) Conjunction(org.batfish.datamodel.routing_policy.expr.Conjunction) InlineCommunitySet(org.batfish.datamodel.routing_policy.expr.InlineCommunitySet) DisjunctionChain(org.batfish.datamodel.routing_policy.expr.DisjunctionChain) Set(java.util.Set) IntExpr(org.batfish.datamodel.routing_policy.expr.IntExpr) CommunitySetExpr(org.batfish.datamodel.routing_policy.expr.CommunitySetExpr) StaticStatement(org.batfish.datamodel.routing_policy.statement.Statements.StaticStatement) Graph(org.batfish.symbolic.Graph) DeleteCommunity(org.batfish.datamodel.routing_policy.statement.DeleteCommunity) List(java.util.List) RoutingPolicy(org.batfish.datamodel.routing_policy.RoutingPolicy) CallExpr(org.batfish.datamodel.routing_policy.expr.CallExpr) IncrementLocalPreference(org.batfish.datamodel.routing_policy.expr.IncrementLocalPreference) BooleanExprs(org.batfish.datamodel.routing_policy.expr.BooleanExprs) BgpNeighbor(org.batfish.datamodel.BgpNeighbor) MatchProtocol(org.batfish.datamodel.routing_policy.expr.MatchProtocol) NamedPrefixSet(org.batfish.datamodel.routing_policy.expr.NamedPrefixSet) SetDefaultPolicy(org.batfish.datamodel.routing_policy.statement.SetDefaultPolicy) OspfMetricType(org.batfish.datamodel.OspfMetricType) BooleanExpr(org.batfish.datamodel.routing_policy.expr.BooleanExpr) AsPathListExpr(org.batfish.datamodel.routing_policy.expr.AsPathListExpr) If(org.batfish.datamodel.routing_policy.statement.If) CommunityVar(org.batfish.symbolic.CommunityVar) HashMap(java.util.HashMap) DecrementMetric(org.batfish.datamodel.routing_policy.expr.DecrementMetric) BatfishException(org.batfish.common.BatfishException) LiteralInt(org.batfish.datamodel.routing_policy.expr.LiteralInt) SetNextHop(org.batfish.datamodel.routing_policy.statement.SetNextHop) ArrayList(java.util.ArrayList) SetOrigin(org.batfish.datamodel.routing_policy.statement.SetOrigin) HashSet(java.util.HashSet) LiteralLong(org.batfish.datamodel.routing_policy.expr.LiteralLong) CommunityList(org.batfish.datamodel.CommunityList) TransferResult(org.batfish.symbolic.TransferResult) RouteFilterLine(org.batfish.datamodel.RouteFilterLine) SubRange(org.batfish.datamodel.SubRange) Type(org.batfish.symbolic.CommunityVar.Type) BoolExpr(com.microsoft.z3.BoolExpr) Configuration(org.batfish.datamodel.Configuration) MatchIpv4(org.batfish.datamodel.routing_policy.expr.MatchIpv4) LineAction(org.batfish.datamodel.LineAction) ArithExpr(com.microsoft.z3.ArithExpr) MatchIpv6(org.batfish.datamodel.routing_policy.expr.MatchIpv6) WithEnvironmentExpr(org.batfish.datamodel.routing_policy.expr.WithEnvironmentExpr) ExplicitPrefixSet(org.batfish.datamodel.routing_policy.expr.ExplicitPrefixSet) PrefixRange(org.batfish.datamodel.PrefixRange) PrefixSetExpr(org.batfish.datamodel.routing_policy.expr.PrefixSetExpr) BitVecExpr(com.microsoft.z3.BitVecExpr) MatchPrefixSet(org.batfish.datamodel.routing_policy.expr.MatchPrefixSet) GraphEdge(org.batfish.symbolic.GraphEdge) SetCommunity(org.batfish.datamodel.routing_policy.statement.SetCommunity) NamedCommunitySet(org.batfish.datamodel.routing_policy.expr.NamedCommunitySet) PrependAsPath(org.batfish.datamodel.routing_policy.statement.PrependAsPath) TransferParam(org.batfish.symbolic.TransferParam) Expr(com.microsoft.z3.Expr) GeneratedRoute(org.batfish.datamodel.GeneratedRoute) MultipliedAs(org.batfish.datamodel.routing_policy.expr.MultipliedAs) OspfType(org.batfish.symbolic.OspfType) LongExpr(org.batfish.datamodel.routing_policy.expr.LongExpr) Protocol(org.batfish.symbolic.Protocol) SetLocalPreference(org.batfish.datamodel.routing_policy.statement.SetLocalPreference) Collections(java.util.Collections) ConjunctionChain(org.batfish.datamodel.routing_policy.expr.ConjunctionChain) LiteralAsList(org.batfish.datamodel.routing_policy.expr.LiteralAsList) SetMetric(org.batfish.datamodel.routing_policy.statement.SetMetric) Prefix(org.batfish.datamodel.Prefix) SetOspfMetricType(org.batfish.datamodel.routing_policy.statement.SetOspfMetricType) PList(org.batfish.symbolic.collections.PList) BoolExpr(com.microsoft.z3.BoolExpr) MatchCommunitySet(org.batfish.datamodel.routing_policy.expr.MatchCommunitySet) MatchPrefix6Set(org.batfish.datamodel.routing_policy.expr.MatchPrefix6Set) InlineCommunitySet(org.batfish.datamodel.routing_policy.expr.InlineCommunitySet) Set(java.util.Set) NamedPrefixSet(org.batfish.datamodel.routing_policy.expr.NamedPrefixSet) HashSet(java.util.HashSet) ExplicitPrefixSet(org.batfish.datamodel.routing_policy.expr.ExplicitPrefixSet) MatchPrefixSet(org.batfish.datamodel.routing_policy.expr.MatchPrefixSet) NamedCommunitySet(org.batfish.datamodel.routing_policy.expr.NamedCommunitySet) PList(org.batfish.symbolic.collections.PList) TransferResult(org.batfish.symbolic.TransferResult) RetainCommunity(org.batfish.datamodel.routing_policy.statement.RetainCommunity) SetMetric(org.batfish.datamodel.routing_policy.statement.SetMetric) SetCommunity(org.batfish.datamodel.routing_policy.statement.SetCommunity) SetNextHop(org.batfish.datamodel.routing_policy.statement.SetNextHop) Pair(org.batfish.common.Pair) LongExpr(org.batfish.datamodel.routing_policy.expr.LongExpr) HashSet(java.util.HashSet) ArithExpr(com.microsoft.z3.ArithExpr) BatfishException(org.batfish.common.BatfishException) StaticStatement(org.batfish.datamodel.routing_policy.statement.Statements.StaticStatement) Statement(org.batfish.datamodel.routing_policy.statement.Statement) StaticStatement(org.batfish.datamodel.routing_policy.statement.Statements.StaticStatement) SetOrigin(org.batfish.datamodel.routing_policy.statement.SetOrigin) DeleteCommunity(org.batfish.datamodel.routing_policy.statement.DeleteCommunity) SetDefaultPolicy(org.batfish.datamodel.routing_policy.statement.SetDefaultPolicy) AddCommunity(org.batfish.datamodel.routing_policy.statement.AddCommunity) CommunityVar(org.batfish.symbolic.CommunityVar) BitVecExpr(com.microsoft.z3.BitVecExpr) IntExpr(org.batfish.datamodel.routing_policy.expr.IntExpr) CommunitySetExpr(org.batfish.datamodel.routing_policy.expr.CommunitySetExpr) CallExpr(org.batfish.datamodel.routing_policy.expr.CallExpr) BooleanExpr(org.batfish.datamodel.routing_policy.expr.BooleanExpr) AsPathListExpr(org.batfish.datamodel.routing_policy.expr.AsPathListExpr) BoolExpr(com.microsoft.z3.BoolExpr) ArithExpr(com.microsoft.z3.ArithExpr) WithEnvironmentExpr(org.batfish.datamodel.routing_policy.expr.WithEnvironmentExpr) PrefixSetExpr(org.batfish.datamodel.routing_policy.expr.PrefixSetExpr) BitVecExpr(com.microsoft.z3.BitVecExpr) Expr(com.microsoft.z3.Expr) LongExpr(org.batfish.datamodel.routing_policy.expr.LongExpr) OspfMetricType(org.batfish.datamodel.OspfMetricType) SetOspfMetricType(org.batfish.datamodel.routing_policy.statement.SetOspfMetricType) SetLocalPreference(org.batfish.datamodel.routing_policy.statement.SetLocalPreference) TransferParam(org.batfish.symbolic.TransferParam) PrependAsPath(org.batfish.datamodel.routing_policy.statement.PrependAsPath) SetOspfMetricType(org.batfish.datamodel.routing_policy.statement.SetOspfMetricType) IntExpr(org.batfish.datamodel.routing_policy.expr.IntExpr) If(org.batfish.datamodel.routing_policy.statement.If)

Example 13 with CommunityVar

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

the class TransferSSA method matchCommunitySet.

/*
   * Converts a community set to a boolean expression
   */
private BoolExpr matchCommunitySet(Configuration conf, CommunitySetExpr e, SymbolicRoute other) {
    if (e instanceof InlineCommunitySet) {
        Set<CommunityVar> comms = _enc.getGraph().findAllCommunities(conf, e);
        BoolExpr acc = _enc.mkTrue();
        for (CommunityVar comm : comms) {
            BoolExpr c = other.getCommunities().get(comm);
            if (c == null) {
                throw new BatfishException("matchCommunitySet: should not be null");
            }
            acc = _enc.mkAnd(acc, c);
        }
        return acc;
    }
    if (e instanceof NamedCommunitySet) {
        NamedCommunitySet x = (NamedCommunitySet) e;
        CommunityList cl = conf.getCommunityLists().get(x.getName());
        return matchCommunityList(cl, other);
    }
    throw new BatfishException("TODO: match community set");
}
Also used : CommunityVar(org.batfish.symbolic.CommunityVar) BoolExpr(com.microsoft.z3.BoolExpr) BatfishException(org.batfish.common.BatfishException) NamedCommunitySet(org.batfish.datamodel.routing_policy.expr.NamedCommunitySet) CommunityList(org.batfish.datamodel.CommunityList) InlineCommunitySet(org.batfish.datamodel.routing_policy.expr.InlineCommunitySet)

Example 14 with CommunityVar

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

the class TransferSSA method relateVariables.

/*
   * Relate the symbolic control plane route variables
   */
private BoolExpr relateVariables(TransferParam<SymbolicRoute> p, TransferResult<BoolExpr, BoolExpr> result) {
    ArithExpr defaultLen = _enc.mkInt(_enc.defaultLength());
    ArithExpr defaultAd = _enc.defaultAdminDistance(_conf, _proto, p.getData());
    ArithExpr defaultMed = _enc.mkInt(_enc.defaultMed(_proto));
    ArithExpr defaultLp = _enc.mkInt(_enc.defaultLocalPref());
    ArithExpr defaultId = _enc.mkInt(_enc.defaultId());
    ArithExpr defaultMet = _enc.mkInt(_enc.defaultMetric());
    // TODO: remove all isChanged calls with actual symbolic values that test for a change
    boolean isIbgp = _graphEdge.isAbstract() && _proto.isBgp();
    // Update prefix length when aggregation
    BoolExpr len = _enc.safeEq(_current.getPrefixLength(), getOrDefault(p.getData().getPrefixLength(), defaultLen));
    BoolExpr per = _enc.safeEq(_current.getPermitted(), p.getData().getPermitted());
    // Only update the router id for import edges
    BoolExpr id = _enc.mkTrue();
    if (!_isExport) {
        id = _enc.safeEq(_current.getRouterId(), getOrDefault(p.getData().getRouterId(), defaultId));
    }
    // Update OSPF area id
    BoolExpr area;
    if (p.getData().getOspfArea() == null || _iface.getOspfAreaName() == null) {
        area = _enc.mkTrue();
    } else {
        area = _enc.safeEqEnum(_current.getOspfArea(), _iface.getOspfAreaName());
    }
    // Set the IGP metric accordingly
    BoolExpr igpMet = _enc.mkTrue();
    boolean isNonClient = _graphEdge.isAbstract() && (_enc.getGraph().peerType(_graphEdge) != Graph.BgpSendType.TO_EBGP);
    boolean isClient = _graphEdge.isAbstract() && (_enc.getGraph().peerType(_graphEdge) == Graph.BgpSendType.TO_RR);
    if (_graphEdge.isAbstract() && _current.getIgpMetric() != null) {
        String router = _graphEdge.getRouter();
        String peer = _graphEdge.getPeer();
        // Case where it is a non client, we lookup the next-hop
        if (isNonClient) {
            EncoderSlice s = _enc.getEncoder().getSlice(peer);
            SymbolicRoute r = s.getSymbolicDecisions().getBestNeighbor().get(router);
            igpMet = _enc.mkEq(_current.getIgpMetric(), r.getMetric());
        }
        // Case where it is a client, next-hop depends on the clientId tag we added
        if (isClient) {
            BoolExpr acc = _enc.mkTrue();
            for (Map.Entry<String, Integer> entry : _enc.getGraph().getOriginatorId().entrySet()) {
                String r = entry.getKey();
                Integer clientId = entry.getValue();
                if (!r.equals(router)) {
                    EncoderSlice s = _enc.getEncoder().getSlice(r);
                    SymbolicRoute record = s.getSymbolicDecisions().getBestNeighbor().get(r);
                    BoolExpr eq = _enc.mkEq(_current.getIgpMetric(), record.getMetric());
                    acc = _enc.mkAnd(acc, _enc.mkImplies(p.getData().getClientId().checkIfValue(clientId), eq));
                }
            }
            igpMet = acc;
        }
    }
    // Set whether or not is iBGP or not on import
    BoolExpr isInternal = // TODO: and !isExport?
    _enc.safeEq(_current.getBgpInternal(), _enc.mkBool(isIbgp));
    // Update OSPF type
    BoolExpr type;
    if (result.isChanged("OSPF-TYPE")) {
        type = _enc.safeEqEnum(_current.getOspfType(), p.getData().getOspfType());
    } else {
        boolean hasAreaIface = _iface.getOspfAreaName() != null;
        boolean hasArea = p.getData().getOspfArea() != null;
        boolean hasType = p.getData().getOspfType() != null;
        boolean areaPossiblyChanged = hasType && hasArea && hasAreaIface;
        // Check if area changed
        if (areaPossiblyChanged) {
            BoolExpr internal = p.getData().getOspfType().isInternal();
            BoolExpr same = p.getData().getOspfArea().checkIfValue(_iface.getOspfAreaName());
            BoolExpr update = _enc.mkAnd(internal, _enc.mkNot(same));
            BoolExpr copyOld = _enc.safeEqEnum(_current.getOspfType(), p.getData().getOspfType());
            type = _enc.mkIf(update, _current.getOspfType().checkIfValue(OspfType.OIA), copyOld);
        } else {
            type = _enc.safeEqEnum(_current.getOspfType(), p.getData().getOspfType());
        }
    }
    BoolExpr comms = _enc.mkTrue();
    // update all community values
    for (Map.Entry<CommunityVar, BoolExpr> entry : _current.getCommunities().entrySet()) {
        CommunityVar cvar = entry.getKey();
        BoolExpr e = entry.getValue();
        BoolExpr eOther = p.getData().getCommunities().get(cvar);
        // Update the communities if they should be sent
        if (sendCommunity()) {
            if (cvar.getType() != CommunityVar.Type.REGEX) {
                comms = _enc.mkAnd(comms, _enc.mkEq(e, eOther));
            }
        } else {
            comms = _enc.mkAnd(comms, _enc.mkNot(e));
        }
    }
    ArithExpr otherAd = (p.getData().getAdminDist() == null ? defaultAd : p.getData().getAdminDist());
    ArithExpr otherMed = (p.getData().getMed() == null ? defaultMed : p.getData().getMed());
    ArithExpr otherLp = getOrDefault(p.getData().getLocalPref(), defaultLp);
    ArithExpr otherMet = getOrDefault(p.getData().getMetric(), defaultMet);
    // otherMet = applyMetricUpdate(otherMet);
    BoolExpr ad = _enc.safeEq(_current.getAdminDist(), otherAd);
    BoolExpr history = _enc.equalHistories(_current, p.getData());
    BoolExpr med = _enc.safeEq(_current.getMed(), otherMed);
    BoolExpr met = _enc.safeEq(_current.getMetric(), otherMet);
    BoolExpr lp = _enc.safeEq(_current.getLocalPref(), otherLp);
    // If this was an external route, then we need to add the correct next-hop tag
    boolean isEbgpEdge = _enc.getGraph().getEbgpNeighbors().get(_graphEdge) != null;
    BoolExpr cid = _enc.mkTrue();
    if (_isExport && _proto.isBgp() && p.getData().getClientId() != null) {
        if (isEbgpEdge) {
            cid = _current.getClientId().checkIfValue(0);
        } else {
            cid = _enc.safeEqEnum(_current.getClientId(), p.getData().getClientId());
        }
    }
    if (!_isExport && _proto.isBgp() && p.getData().getClientId() != null) {
        BoolExpr fromExternal = p.getData().getClientId().checkIfValue(0);
        BoolExpr edgeIsInternal = _enc.mkBool(!isClient && !isNonClient);
        BoolExpr copyOver = _enc.safeEqEnum(_current.getClientId(), p.getData().getClientId());
        Integer x = _enc.getGraph().getOriginatorId().get(_graphEdge.getRouter());
        SymbolicOriginatorId soid = _current.getClientId();
        BoolExpr setNewValue = (x == null ? soid.checkIfValue(0) : soid.checkIfValue(x));
        cid = _enc.mkIf(_enc.mkAnd(fromExternal, edgeIsInternal), setNewValue, copyOver);
    }
    BoolExpr updates = _enc.mkAnd(per, len, ad, med, lp, met, id, cid, type, area, comms, history, isInternal, igpMet);
    BoolExpr noOverflow = noOverflow(otherMet, _proto);
    return _enc.mkIf(noOverflow, updates, _enc.mkNot(_current.getPermitted()));
}
Also used : ArithExpr(com.microsoft.z3.ArithExpr) CommunityVar(org.batfish.symbolic.CommunityVar) BoolExpr(com.microsoft.z3.BoolExpr) Map(java.util.Map) HashMap(java.util.HashMap)

Example 15 with CommunityVar

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

the class TransferBDD method zeroedRecord.

/*
   * A record of default values that represent the value of the
   * outputs if the route is filtered / dropped in the policy
   */
private BDDRoute zeroedRecord() {
    BDDRoute rec = new BDDRoute(_comms);
    rec.getMetric().setValue(0);
    rec.getLocalPref().setValue(0);
    rec.getAdminDist().setValue(0);
    rec.getPrefixLength().setValue(0);
    rec.getMed().setValue(0);
    rec.getPrefix().setValue(0);
    for (CommunityVar comm : _comms) {
        rec.getCommunities().put(comm, factory.zero());
    }
    rec.getProtocolHistory().getInteger().setValue(0);
    return rec;
}
Also used : CommunityVar(org.batfish.symbolic.CommunityVar)

Aggregations

CommunityVar (org.batfish.symbolic.CommunityVar)16 BoolExpr (com.microsoft.z3.BoolExpr)12 HashMap (java.util.HashMap)7 Map (java.util.Map)7 ArithExpr (com.microsoft.z3.ArithExpr)6 BatfishException (org.batfish.common.BatfishException)6 BitVecExpr (com.microsoft.z3.BitVecExpr)4 Expr (com.microsoft.z3.Expr)4 ArrayList (java.util.ArrayList)4 Prefix (org.batfish.datamodel.Prefix)4 InlineCommunitySet (org.batfish.datamodel.routing_policy.expr.InlineCommunitySet)4 HashSet (java.util.HashSet)3 TreeMap (java.util.TreeMap)3 BDD (net.sf.javabdd.BDD)3 CommunityList (org.batfish.datamodel.CommunityList)3 CommunityListLine (org.batfish.datamodel.CommunityListLine)3 NamedCommunitySet (org.batfish.datamodel.routing_policy.expr.NamedCommunitySet)3 GraphEdge (org.batfish.symbolic.GraphEdge)3 Protocol (org.batfish.symbolic.Protocol)3 Set (java.util.Set)2