Search in sources :

Example 26 with ArithExpr

use of com.microsoft.z3.ArithExpr in project batfish by batfish.

the class PropertyChecker method checkEqualLength.

/*
   * Computes whether a collection of source routers will always have
   * equal path length to destination port(s).
   */
public AnswerElement checkEqualLength(HeaderLocationQuestion q) {
    return checkProperty(q, (enc, srcRouters, destPorts) -> {
        PropertyAdder pa = new PropertyAdder(enc.getMainSlice());
        Map<String, ArithExpr> lenVars = pa.instrumentPathLength(destPorts);
        Map<String, BoolExpr> eqVars = new HashMap<>();
        List<Expr> lens = new ArrayList<>();
        for (String router : srcRouters) {
            lens.add(lenVars.get(router));
        }
        BoolExpr allEqual = PropertyAdder.allEqual(enc.getCtx(), lens);
        enc.add(enc.mkNot(allEqual));
        for (Entry<String, ArithExpr> entry : lenVars.entrySet()) {
            String name = entry.getKey();
            BoolExpr b = srcRouters.contains(name) ? allEqual : enc.mkTrue();
            eqVars.put(name, b);
        }
        return eqVars;
    }, (vp) -> new SmtOneAnswerElement(vp.getResult()));
}
Also used : ArithExpr(com.microsoft.z3.ArithExpr) BoolExpr(com.microsoft.z3.BoolExpr) BoolExpr(com.microsoft.z3.BoolExpr) ArithExpr(com.microsoft.z3.ArithExpr) BitVecExpr(com.microsoft.z3.BitVecExpr) Expr(com.microsoft.z3.Expr) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) SmtOneAnswerElement(org.batfish.symbolic.answers.SmtOneAnswerElement)

Example 27 with ArithExpr

use of com.microsoft.z3.ArithExpr 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 28 with ArithExpr

use of com.microsoft.z3.ArithExpr in project batfish by batfish.

the class TransferSSA method matchPrefixSet.

/*
   * Converts a prefix set to a boolean expression.
   */
private TransferResult<BoolExpr, BoolExpr> matchPrefixSet(Configuration conf, PrefixSetExpr e, SymbolicRoute other) {
    ArithExpr otherLen = other.getPrefixLength();
    TransferResult<BoolExpr, BoolExpr> result = new TransferResult<>();
    if (e instanceof ExplicitPrefixSet) {
        ExplicitPrefixSet x = (ExplicitPrefixSet) e;
        Set<PrefixRange> ranges = x.getPrefixSpace().getPrefixRanges();
        if (ranges.isEmpty()) {
            return result.setReturnValue(_enc.mkTrue());
        }
        // by checking for static/connected/OSPF routes specifically.
        if (ranges.size() == 1) {
            for (PrefixRange r : ranges) {
                int start = r.getLengthRange().getStart();
                int end = r.getLengthRange().getEnd();
                Prefix pfx = r.getPrefix();
                if (start == end && start == pfx.getPrefixLength()) {
                    String router = _conf.getName();
                    Set<Prefix> origin = _enc.getOriginatedNetworks().get(router, Protocol.BGP);
                    if (origin != null && origin.contains(pfx)) {
                        // Compute static and connected routes
                        Set<Prefix> ostatic = _enc.getOriginatedNetworks().get(router, Protocol.STATIC);
                        Set<Prefix> oconn = _enc.getOriginatedNetworks().get(router, Protocol.CONNECTED);
                        boolean hasStatic = ostatic != null && ostatic.contains(pfx);
                        boolean hasConnected = oconn != null && oconn.contains(pfx);
                        ArithExpr originLength = _enc.mkInt(pfx.getPrefixLength());
                        if (hasStatic || hasConnected) {
                            BoolExpr directRoute = _enc.isRelevantFor(originLength, r);
                            ArithExpr newLength = _enc.mkIf(directRoute, originLength, otherLen);
                            result = result.addChangedVariable("PREFIX-LEN", newLength);
                            return result.setReturnValue(directRoute);
                        } else {
                            // Also use network statement if OSPF has a route with the correct length
                            SymbolicRoute rec = _enc.getBestNeighborPerProtocol(router, Protocol.OSPF);
                            if (rec != null) {
                                BoolExpr ospfRelevant = _enc.isRelevantFor(rec.getPrefixLength(), r);
                                ArithExpr newLength = _enc.mkIf(ospfRelevant, originLength, otherLen);
                                result = result.addChangedVariable("PREFIX-LEN", newLength);
                                return result.setReturnValue(ospfRelevant);
                            }
                        }
                    }
                }
            }
        }
        // Compute if the other best route is relevant for this match statement
        BoolExpr acc = _enc.mkFalse();
        for (PrefixRange range : ranges) {
            acc = _enc.mkOr(acc, _enc.isRelevantFor(otherLen, range));
        }
        return result.setReturnValue(acc);
    } else if (e instanceof NamedPrefixSet) {
        NamedPrefixSet x = (NamedPrefixSet) e;
        String name = x.getName();
        RouteFilterList fl = conf.getRouteFilterLists().get(name);
        return result.setReturnValue(matchFilterList(fl, other));
    } else {
        throw new BatfishException("TODO: match prefix set: " + e);
    }
}
Also used : ArithExpr(com.microsoft.z3.ArithExpr) BoolExpr(com.microsoft.z3.BoolExpr) BatfishException(org.batfish.common.BatfishException) PrefixRange(org.batfish.datamodel.PrefixRange) NamedPrefixSet(org.batfish.datamodel.routing_policy.expr.NamedPrefixSet) Prefix(org.batfish.datamodel.Prefix) TransferResult(org.batfish.symbolic.TransferResult) ExplicitPrefixSet(org.batfish.datamodel.routing_policy.expr.ExplicitPrefixSet) RouteFilterList(org.batfish.datamodel.RouteFilterList)

Example 29 with ArithExpr

use of com.microsoft.z3.ArithExpr 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)

Aggregations

ArithExpr (com.microsoft.z3.ArithExpr)27 BoolExpr (com.microsoft.z3.BoolExpr)25 HashMap (java.util.HashMap)12 GraphEdge (org.batfish.symbolic.GraphEdge)10 BitVecExpr (com.microsoft.z3.BitVecExpr)7 Prefix (org.batfish.datamodel.Prefix)6 Graph (org.batfish.symbolic.Graph)6 List (java.util.List)5 Map (java.util.Map)5 Context (com.microsoft.z3.Context)4 Solver (com.microsoft.z3.Solver)4 HashSet (java.util.HashSet)4 Interface (org.batfish.datamodel.Interface)4 CommunityVar (org.batfish.symbolic.CommunityVar)4 Expr (com.microsoft.z3.Expr)3 BatfishException (org.batfish.common.BatfishException)3 SubRange (org.batfish.datamodel.SubRange)3 RoutingPolicy (org.batfish.datamodel.routing_policy.RoutingPolicy)3 BooleanExpr (org.batfish.datamodel.routing_policy.expr.BooleanExpr)3 SmtOneAnswerElement (org.batfish.symbolic.answers.SmtOneAnswerElement)3