Search in sources :

Example 6 with MatchProtocol

use of org.batfish.datamodel.routing_policy.expr.MatchProtocol in project batfish by batfish.

the class JuniperConfiguration method initDefaultBgpExportPolicy.

private void initDefaultBgpExportPolicy() {
    if (_c.getRoutingPolicies().containsKey(DEFAULT_BGP_EXPORT_POLICY_NAME)) {
        return;
    }
    // set up default export policy (accept bgp routes)
    RoutingPolicy defaultBgpExportPolicy = new RoutingPolicy(DEFAULT_BGP_EXPORT_POLICY_NAME, _c);
    _c.getRoutingPolicies().put(DEFAULT_BGP_EXPORT_POLICY_NAME, defaultBgpExportPolicy);
    If defaultBgpExportPolicyConditional = new If();
    defaultBgpExportPolicy.getStatements().add(defaultBgpExportPolicyConditional);
    // guard
    Disjunction isBgp = new Disjunction();
    isBgp.getDisjuncts().add(new MatchProtocol(RoutingProtocol.BGP));
    isBgp.getDisjuncts().add(new MatchProtocol(RoutingProtocol.IBGP));
    defaultBgpExportPolicyConditional.setGuard(isBgp);
    PsThenAccept.INSTANCE.applyTo(defaultBgpExportPolicyConditional.getTrueStatements(), this, _c, _w);
    PsThenReject.INSTANCE.applyTo(defaultBgpExportPolicyConditional.getFalseStatements(), this, _c, _w);
}
Also used : Disjunction(org.batfish.datamodel.routing_policy.expr.Disjunction) RoutingPolicy(org.batfish.datamodel.routing_policy.RoutingPolicy) If(org.batfish.datamodel.routing_policy.statement.If) MatchProtocol(org.batfish.datamodel.routing_policy.expr.MatchProtocol)

Example 7 with MatchProtocol

use of org.batfish.datamodel.routing_policy.expr.MatchProtocol in project batfish by batfish.

the class JuniperConfiguration method createBgpProcess.

private BgpProcess createBgpProcess(RoutingInstance routingInstance) {
    initDefaultBgpExportPolicy();
    initDefaultBgpImportPolicy();
    String vrfName = routingInstance.getName();
    Vrf vrf = _c.getVrfs().get(vrfName);
    BgpProcess proc = new BgpProcess();
    Ip routerId = routingInstance.getRouterId();
    if (routerId == null) {
        routerId = _defaultRoutingInstance.getRouterId();
        if (routerId == null) {
            routerId = Ip.ZERO;
        }
    }
    proc.setRouterId(routerId);
    BgpGroup mg = routingInstance.getMasterBgpGroup();
    boolean multipathEbgp = false;
    boolean multipathIbgp = false;
    boolean multipathMultipleAs = false;
    boolean multipathEbgpSet = false;
    boolean multipathIbgpSet = false;
    boolean multipathMultipleAsSet = false;
    if (mg.getLocalAs() == null) {
        Integer routingInstanceAs = routingInstance.getAs();
        if (routingInstanceAs == null) {
            routingInstanceAs = _defaultRoutingInstance.getAs();
        }
        if (routingInstanceAs == null) {
            _w.redFlag("BGP BROKEN FOR THIS ROUTER: Cannot determine local autonomous system");
        } else {
            mg.setLocalAs(routingInstanceAs);
        }
    }
    // Set default authentication algorithm if missing
    if (mg.getAuthenticationAlgorithm() == null) {
        mg.setAuthenticationAlgorithm(DEFAULT_BGP_AUTHENTICATION_ALGORITHM);
    }
    for (IpBgpGroup ig : routingInstance.getIpBgpGroups().values()) {
        ig.cascadeInheritance();
    }
    _unreferencedBgpGroups = new TreeMap<>();
    int fakeIpCounter = 0;
    for (Entry<String, NamedBgpGroup> e : routingInstance.getNamedBgpGroups().entrySet()) {
        fakeIpCounter++;
        String name = e.getKey();
        NamedBgpGroup group = e.getValue();
        if (!group.getIpv6() && !group.getInherited()) {
            _unreferencedBgpGroups.put(name, group.getDefinitionLine());
            Ip fakeIp = new Ip(-1 * fakeIpCounter);
            IpBgpGroup dummy = new IpBgpGroup(fakeIp);
            dummy.setParent(group);
            dummy.cascadeInheritance();
            routingInstance.getIpBgpGroups().put(fakeIp, dummy);
        }
    }
    for (Entry<Ip, IpBgpGroup> e : routingInstance.getIpBgpGroups().entrySet()) {
        Ip ip = e.getKey();
        IpBgpGroup ig = e.getValue();
        BgpNeighbor neighbor = new BgpNeighbor(ip, _c);
        neighbor.setVrf(vrfName);
        // route reflection
        Ip declaredClusterId = ig.getClusterId();
        if (declaredClusterId != null) {
            neighbor.setRouteReflectorClient(true);
            neighbor.setClusterId(declaredClusterId.asLong());
        } else {
            neighbor.setClusterId(routerId.asLong());
        }
        // multipath multiple-as
        boolean currentGroupMultipathMultipleAs = ig.getMultipathMultipleAs();
        if (multipathMultipleAsSet && currentGroupMultipathMultipleAs != multipathMultipleAs) {
            _w.redFlag("Currently do not support mixed multipath-multiple-as/non-multipath-multiple-as bgp" + "groups on Juniper - FORCING NON-MULTIPATH-MULTIPLE-AS");
            multipathMultipleAs = false;
        } else {
            multipathMultipleAs = currentGroupMultipathMultipleAs;
            multipathMultipleAsSet = true;
        }
        String authenticationKeyChainName = ig.getAuthenticationKeyChainName();
        if (ig.getAuthenticationKeyChainName() != null) {
            if (!_c.getAuthenticationKeyChains().containsKey(authenticationKeyChainName)) {
                authenticationKeyChainName = null;
            } else if (ig.getAuthenticationKey() != null) {
                _w.redFlag("Both authentication-key and authentication-key-chain specified for neighbor " + ig.getRemoteAddress());
            }
        }
        BgpAuthenticationSettings bgpAuthenticationSettings = new BgpAuthenticationSettings();
        bgpAuthenticationSettings.setAuthenticationAlgorithm(ig.getAuthenticationAlgorithm());
        bgpAuthenticationSettings.setAuthenticationKey(ig.getAuthenticationKey());
        bgpAuthenticationSettings.setAuthenticationKeyChainName(authenticationKeyChainName);
        neighbor.setAuthenticationSettings(bgpAuthenticationSettings);
        Boolean ebgpMultihop = ig.getEbgpMultihop();
        if (ebgpMultihop == null) {
            ebgpMultihop = false;
        }
        neighbor.setEbgpMultihop(ebgpMultihop);
        Integer loops = ig.getLoops();
        boolean allowLocalAsIn = loops != null && loops > 0;
        neighbor.setAllowLocalAsIn(allowLocalAsIn);
        Boolean advertisePeerAs = ig.getAdvertisePeerAs();
        if (advertisePeerAs == null) {
            advertisePeerAs = false;
        }
        neighbor.setAllowRemoteAsOut(advertisePeerAs);
        Boolean advertiseExternal = ig.getAdvertiseExternal();
        if (advertiseExternal == null) {
            advertiseExternal = false;
        }
        neighbor.setAdvertiseExternal(advertiseExternal);
        Boolean advertiseInactive = ig.getAdvertiseInactive();
        if (advertiseInactive == null) {
            advertiseInactive = false;
        }
        neighbor.setAdvertiseInactive(advertiseInactive);
        neighbor.setGroup(ig.getGroupName());
        // import policies
        String peerImportPolicyName = "~PEER_IMPORT_POLICY:" + ig.getRemoteAddress() + "~";
        neighbor.setImportPolicy(peerImportPolicyName);
        RoutingPolicy peerImportPolicy = new RoutingPolicy(peerImportPolicyName, _c);
        _c.getRoutingPolicies().put(peerImportPolicyName, peerImportPolicy);
        // default import policy is to accept
        peerImportPolicy.getStatements().add(new SetDefaultPolicy(DEFAULT_BGP_IMPORT_POLICY_NAME));
        peerImportPolicy.getStatements().add(Statements.SetDefaultActionAccept.toStaticStatement());
        List<BooleanExpr> importPolicyCalls = new ArrayList<>();
        ig.getImportPolicies().forEach((importPolicyName, importPolicyLine) -> {
            PolicyStatement importPolicy = _policyStatements.get(importPolicyName);
            if (importPolicy == null) {
                undefined(JuniperStructureType.POLICY_STATEMENT, importPolicyName, JuniperStructureUsage.BGP_IMPORT_POLICY, importPolicyLine);
            } else {
                setPolicyStatementReferent(importPolicyName, ig.getImportPolicies(), "BGP import policy for neighbor: " + ig.getRemoteAddress());
                CallExpr callPolicy = new CallExpr(importPolicyName);
                importPolicyCalls.add(callPolicy);
            }
        });
        If peerImportPolicyConditional = new If();
        DisjunctionChain importPolicyChain = new DisjunctionChain(importPolicyCalls);
        peerImportPolicyConditional.setGuard(importPolicyChain);
        peerImportPolicy.getStatements().add(peerImportPolicyConditional);
        peerImportPolicyConditional.getTrueStatements().add(Statements.ExitAccept.toStaticStatement());
        peerImportPolicyConditional.getFalseStatements().add(Statements.ExitReject.toStaticStatement());
        // export policies
        String peerExportPolicyName = "~PEER_EXPORT_POLICY:" + ig.getRemoteAddress() + "~";
        neighbor.setExportPolicy(peerExportPolicyName);
        RoutingPolicy peerExportPolicy = new RoutingPolicy(peerExportPolicyName, _c);
        _c.getRoutingPolicies().put(peerExportPolicyName, peerExportPolicy);
        peerExportPolicy.getStatements().add(new SetDefaultPolicy(DEFAULT_BGP_EXPORT_POLICY_NAME));
        /*
       * For new BGP advertisements, i.e. those that are created from non-BGP
       * routes, an origin code must be set. By default, Juniper sets the origin
       * code to IGP.
       */
        If setOriginForNonBgp = new If();
        Disjunction isBgp = new Disjunction();
        isBgp.getDisjuncts().add(new MatchProtocol(RoutingProtocol.BGP));
        isBgp.getDisjuncts().add(new MatchProtocol(RoutingProtocol.IBGP));
        setOriginForNonBgp.setGuard(isBgp);
        setOriginForNonBgp.getFalseStatements().add(new SetOrigin(new LiteralOrigin(OriginType.IGP, null)));
        peerExportPolicy.getStatements().add(setOriginForNonBgp);
        List<BooleanExpr> exportPolicyCalls = new ArrayList<>();
        ig.getExportPolicies().forEach((exportPolicyName, exportPolicyLine) -> {
            PolicyStatement exportPolicy = _policyStatements.get(exportPolicyName);
            if (exportPolicy == null) {
                undefined(JuniperStructureType.POLICY_STATEMENT, exportPolicyName, JuniperStructureUsage.BGP_EXPORT_POLICY, exportPolicyLine);
            } else {
                setPolicyStatementReferent(exportPolicyName, ig.getExportPolicies(), "BGP export policy for neighbor: " + ig.getRemoteAddress());
                CallExpr callPolicy = new CallExpr(exportPolicyName);
                exportPolicyCalls.add(callPolicy);
            }
        });
        If peerExportPolicyConditional = new If();
        DisjunctionChain exportPolicyChain = new DisjunctionChain(exportPolicyCalls);
        peerExportPolicyConditional.setGuard(exportPolicyChain);
        peerExportPolicyConditional.getTrueStatements().add(Statements.ExitAccept.toStaticStatement());
        peerExportPolicyConditional.getFalseStatements().add(Statements.ExitReject.toStaticStatement());
        peerExportPolicy.getStatements().add(peerExportPolicyConditional);
        // inherit local-as
        neighbor.setLocalAs(ig.getLocalAs());
        if (neighbor.getLocalAs() == null) {
            _w.redFlag("Missing local-as for neighbor: " + ig.getRemoteAddress());
            continue;
        }
        /*
       * inherit peer-as, or use local-as if internal
       *
       * Also set multipath
       */
        if (ig.getType() == BgpGroupType.INTERNAL) {
            neighbor.setRemoteAs(ig.getLocalAs());
            boolean currentGroupMultipathIbgp = ig.getMultipath();
            if (multipathIbgpSet && currentGroupMultipathIbgp != multipathIbgp) {
                _w.redFlag("Currently do not support mixed iBGP multipath/non-multipath bgp groups on Juniper " + "- FORCING NON-MULTIPATH IBGP");
                multipathIbgp = false;
            } else {
                multipathIbgp = currentGroupMultipathIbgp;
                multipathIbgpSet = true;
            }
        } else {
            neighbor.setRemoteAs(ig.getPeerAs());
            boolean currentGroupMultipathEbgp = ig.getMultipath();
            if (multipathEbgpSet && currentGroupMultipathEbgp != multipathEbgp) {
                _w.redFlag("Currently do not support mixed eBGP multipath/non-multipath bgp groups on Juniper " + "- FORCING NON-MULTIPATH EBGP");
                multipathEbgp = false;
            } else {
                multipathEbgp = currentGroupMultipathEbgp;
                multipathEbgpSet = true;
            }
        }
        // TODO: implement better behavior than setting default metric to 0
        neighbor.setDefaultMetric(0);
        // TODO: find out if there is a juniper equivalent of cisco
        // send-community
        neighbor.setSendCommunity(true);
        // inherit update-source
        Ip localIp = ig.getLocalAddress();
        if (localIp == null) {
            // peer
            outerloop: for (org.batfish.datamodel.Interface iface : vrf.getInterfaces().values()) {
                for (InterfaceAddress address : iface.getAllAddresses()) {
                    if (address.getPrefix().containsIp(ip)) {
                        localIp = address.getIp();
                        break outerloop;
                    }
                }
            }
        }
        if (localIp == null && _defaultAddressSelection) {
            initFirstLoopbackInterface();
            if (_lo0 != null) {
                InterfaceAddress lo0Unit0Address = _lo0.getPrimaryAddress();
                if (lo0Unit0Address != null) {
                    localIp = lo0Unit0Address.getIp();
                }
            }
        }
        if (localIp == null && ip.valid()) {
            _w.redFlag("Could not determine local ip for bgp peering with neighbor ip: " + ip);
        } else {
            neighbor.setLocalIp(localIp);
        }
        if (neighbor.getGroup() == null || !_unreferencedBgpGroups.containsKey(neighbor.getGroup())) {
            proc.getNeighbors().put(neighbor.getPrefix(), neighbor);
        }
    }
    proc.setMultipathEbgp(multipathEbgpSet);
    proc.setMultipathIbgp(multipathIbgp);
    MultipathEquivalentAsPathMatchMode multipathEquivalentAsPathMatchMode = multipathMultipleAs ? MultipathEquivalentAsPathMatchMode.PATH_LENGTH : MultipathEquivalentAsPathMatchMode.FIRST_AS;
    proc.setMultipathEquivalentAsPathMatchMode(multipathEquivalentAsPathMatchMode);
    return proc;
}
Also used : BgpProcess(org.batfish.datamodel.BgpProcess) LiteralOrigin(org.batfish.datamodel.routing_policy.expr.LiteralOrigin) Ip(org.batfish.datamodel.Ip) ArrayList(java.util.ArrayList) Vrf(org.batfish.datamodel.Vrf) MultipathEquivalentAsPathMatchMode(org.batfish.datamodel.MultipathEquivalentAsPathMatchMode) BgpNeighbor(org.batfish.datamodel.BgpNeighbor) CallExpr(org.batfish.datamodel.routing_policy.expr.CallExpr) DisjunctionChain(org.batfish.datamodel.routing_policy.expr.DisjunctionChain) BooleanExpr(org.batfish.datamodel.routing_policy.expr.BooleanExpr) BgpAuthenticationSettings(org.batfish.datamodel.BgpAuthenticationSettings) InterfaceAddress(org.batfish.datamodel.InterfaceAddress) SetOrigin(org.batfish.datamodel.routing_policy.statement.SetOrigin) RoutingPolicy(org.batfish.datamodel.routing_policy.RoutingPolicy) SetDefaultPolicy(org.batfish.datamodel.routing_policy.statement.SetDefaultPolicy) MatchProtocol(org.batfish.datamodel.routing_policy.expr.MatchProtocol) Disjunction(org.batfish.datamodel.routing_policy.expr.Disjunction) If(org.batfish.datamodel.routing_policy.statement.If)

Example 8 with MatchProtocol

use of org.batfish.datamodel.routing_policy.expr.MatchProtocol 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 9 with MatchProtocol

use of org.batfish.datamodel.routing_policy.expr.MatchProtocol in project batfish by batfish.

the class TransferBDD method compute.

/*
   * Convert a Batfish AST boolean expression to a symbolic Z3 boolean expression
   * by performing inlining of stateful side effects.
   */
private TransferResult<TransferReturn, BDD> compute(BooleanExpr expr, TransferParam<BDDRoute> p) {
    // TODO: right now everything is IPV4
    if (expr instanceof MatchIpv4) {
        p.debug("MatchIpv4");
        TransferReturn ret = new TransferReturn(p.getData(), factory.one());
        p.debug("MatchIpv4 Result: " + ret);
        return fromExpr(ret);
    }
    if (expr instanceof MatchIpv6) {
        p.debug("MatchIpv6");
        TransferReturn ret = new TransferReturn(p.getData(), factory.zero());
        return fromExpr(ret);
    }
    if (expr instanceof Conjunction) {
        p.debug("Conjunction");
        Conjunction c = (Conjunction) expr;
        BDD acc = factory.one();
        TransferResult<TransferReturn, BDD> result = new TransferResult<>();
        for (BooleanExpr be : c.getConjuncts()) {
            TransferResult<TransferReturn, BDD> r = compute(be, p.indent());
            acc = acc.and(r.getReturnValue().getSecond());
        }
        TransferReturn ret = new TransferReturn(p.getData(), acc);
        p.debug("Conjunction return: " + acc);
        return result.setReturnValue(ret);
    }
    if (expr instanceof Disjunction) {
        p.debug("Disjunction");
        Disjunction d = (Disjunction) expr;
        BDD acc = factory.zero();
        TransferResult<TransferReturn, BDD> result = new TransferResult<>();
        for (BooleanExpr be : d.getDisjuncts()) {
            TransferResult<TransferReturn, BDD> r = compute(be, p.indent());
            result = result.addChangedVariables(r);
            acc = acc.or(r.getReturnValue().getSecond());
        }
        TransferReturn ret = new TransferReturn(p.getData(), acc);
        p.debug("Disjunction return: " + acc);
        return result.setReturnValue(ret);
    }
    // TODO: thread the BDDRecord through calls
    if (expr instanceof ConjunctionChain) {
        p.debug("ConjunctionChain");
        ConjunctionChain d = (ConjunctionChain) expr;
        List<BooleanExpr> conjuncts = new ArrayList<>(d.getSubroutines());
        if (p.getDefaultPolicy() != null) {
            BooleanExpr be = new CallExpr(p.getDefaultPolicy().getDefaultPolicy());
            conjuncts.add(be);
        }
        if (conjuncts.size() == 0) {
            TransferReturn ret = new TransferReturn(p.getData(), factory.one());
            return fromExpr(ret);
        } else {
            TransferResult<TransferReturn, BDD> result = new TransferResult<>();
            TransferParam<BDDRoute> record = p;
            BDD acc = factory.zero();
            for (int i = conjuncts.size() - 1; i >= 0; i--) {
                BooleanExpr conjunct = conjuncts.get(i);
                TransferParam<BDDRoute> param = record.setDefaultPolicy(null).setChainContext(TransferParam.ChainContext.CONJUNCTION).indent();
                TransferResult<TransferReturn, BDD> r = compute(conjunct, param);
                record = record.setData(r.getReturnValue().getFirst());
                acc = ite(r.getFallthroughValue(), acc, r.getReturnValue().getSecond());
            }
            TransferReturn ret = new TransferReturn(record.getData(), acc);
            return result.setReturnValue(ret);
        }
    }
    if (expr instanceof DisjunctionChain) {
        p.debug("DisjunctionChain");
        DisjunctionChain d = (DisjunctionChain) expr;
        List<BooleanExpr> disjuncts = new ArrayList<>(d.getSubroutines());
        if (p.getDefaultPolicy() != null) {
            BooleanExpr be = new CallExpr(p.getDefaultPolicy().getDefaultPolicy());
            disjuncts.add(be);
        }
        if (disjuncts.size() == 0) {
            TransferReturn ret = new TransferReturn(p.getData(), factory.zero());
            return fromExpr(ret);
        } else {
            TransferResult<TransferReturn, BDD> result = new TransferResult<>();
            TransferParam<BDDRoute> record = p;
            BDD acc = factory.zero();
            for (int i = disjuncts.size() - 1; i >= 0; i--) {
                BooleanExpr disjunct = disjuncts.get(i);
                TransferParam<BDDRoute> param = record.setDefaultPolicy(null).setChainContext(TransferParam.ChainContext.CONJUNCTION).indent();
                TransferResult<TransferReturn, BDD> r = compute(disjunct, param);
                record = record.setData(r.getReturnValue().getFirst());
                acc = ite(r.getFallthroughValue(), acc, r.getReturnValue().getSecond());
            }
            TransferReturn ret = new TransferReturn(record.getData(), acc);
            return result.setReturnValue(ret);
        }
    }
    if (expr instanceof Not) {
        p.debug("mkNot");
        Not n = (Not) expr;
        TransferResult<TransferReturn, BDD> result = compute(n.getExpr(), p);
        TransferReturn r = result.getReturnValue();
        TransferReturn ret = new TransferReturn(r.getFirst(), r.getSecond().not());
        return result.setReturnValue(ret);
    }
    if (expr instanceof MatchProtocol) {
        MatchProtocol mp = (MatchProtocol) expr;
        Protocol proto = Protocol.fromRoutingProtocol(mp.getProtocol());
        if (proto == null) {
            p.debug("MatchProtocol(" + mp.getProtocol().protocolName() + "): false");
            TransferReturn ret = new TransferReturn(p.getData(), factory.zero());
            return fromExpr(ret);
        }
        BDD protoMatch = p.getData().getProtocolHistory().value(proto);
        p.debug("MatchProtocol(" + mp.getProtocol().protocolName() + "): " + protoMatch);
        TransferReturn ret = new TransferReturn(p.getData(), protoMatch);
        return fromExpr(ret);
    }
    if (expr instanceof MatchPrefixSet) {
        p.debug("MatchPrefixSet");
        MatchPrefixSet m = (MatchPrefixSet) expr;
        BDD r = matchPrefixSet(p.indent(), _conf, m.getPrefixSet(), p.getData());
        TransferReturn ret = new TransferReturn(p.getData(), r);
        return fromExpr(ret);
    // TODO: implement me
    } else if (expr instanceof MatchPrefix6Set) {
        p.debug("MatchPrefix6Set");
        TransferReturn ret = new TransferReturn(p.getData(), factory.zero());
        return fromExpr(ret);
    } else if (expr instanceof CallExpr) {
        p.debug("CallExpr");
        CallExpr c = (CallExpr) expr;
        String router = _conf.getName();
        String name = c.getCalledPolicyName();
        TransferResult<TransferReturn, BDD> r = CACHE.get(router, name);
        if (r != null) {
            return r;
        }
        RoutingPolicy pol = _conf.getRoutingPolicies().get(name);
        p = p.setCallContext(TransferParam.CallContext.EXPR_CALL);
        r = compute(pol.getStatements(), p.indent().enterScope(name));
        CACHE.put(router, name, r);
        return r;
    } else if (expr instanceof WithEnvironmentExpr) {
        p.debug("WithEnvironmentExpr");
        // TODO: this is not correct
        WithEnvironmentExpr we = (WithEnvironmentExpr) expr;
        // TODO: postStatements() and preStatements()
        return compute(we.getExpr(), p.deepCopy());
    } else if (expr instanceof MatchCommunitySet) {
        p.debug("MatchCommunitySet");
        MatchCommunitySet mcs = (MatchCommunitySet) expr;
        BDD c = matchCommunitySet(p.indent(), _conf, mcs.getExpr(), p.getData());
        TransferReturn ret = new TransferReturn(p.getData(), c);
        return fromExpr(ret);
    } else if (expr instanceof BooleanExprs.StaticBooleanExpr) {
        BooleanExprs.StaticBooleanExpr b = (BooleanExprs.StaticBooleanExpr) expr;
        TransferReturn ret;
        switch(b.getType()) {
            case CallExprContext:
                p.debug("CallExprContext");
                BDD x1 = mkBDD(p.getCallContext() == TransferParam.CallContext.EXPR_CALL);
                ret = new TransferReturn(p.getData(), x1);
                return fromExpr(ret);
            case CallStatementContext:
                p.debug("CallStmtContext");
                BDD x2 = mkBDD(p.getCallContext() == TransferParam.CallContext.STMT_CALL);
                ret = new TransferReturn(p.getData(), x2);
                return fromExpr(ret);
            case True:
                p.debug("True");
                ret = new TransferReturn(p.getData(), factory.one());
                return fromExpr(ret);
            case False:
                p.debug("False");
                ret = new TransferReturn(p.getData(), factory.zero());
                return fromExpr(ret);
            default:
                throw new BatfishException("Unhandled " + BooleanExprs.class.getCanonicalName() + ": " + b.getType());
        }
    } else if (expr instanceof MatchAsPath) {
        p.debug("MatchAsPath");
        // System.out.println("Warning: use of unimplemented feature MatchAsPath");
        TransferReturn ret = new TransferReturn(p.getData(), factory.one());
        return fromExpr(ret);
    }
    throw new BatfishException("TODO: compute expr transfer function: " + expr);
}
Also used : MatchPrefix6Set(org.batfish.datamodel.routing_policy.expr.MatchPrefix6Set) BDD(net.sf.javabdd.BDD) ArrayList(java.util.ArrayList) MatchCommunitySet(org.batfish.datamodel.routing_policy.expr.MatchCommunitySet) TransferResult(org.batfish.symbolic.TransferResult) WithEnvironmentExpr(org.batfish.datamodel.routing_policy.expr.WithEnvironmentExpr) BooleanExprs(org.batfish.datamodel.routing_policy.expr.BooleanExprs) Conjunction(org.batfish.datamodel.routing_policy.expr.Conjunction) CallExpr(org.batfish.datamodel.routing_policy.expr.CallExpr) DisjunctionChain(org.batfish.datamodel.routing_policy.expr.DisjunctionChain) MatchProtocol(org.batfish.datamodel.routing_policy.expr.MatchProtocol) Protocol(org.batfish.symbolic.Protocol) MatchAsPath(org.batfish.datamodel.routing_policy.expr.MatchAsPath) BooleanExpr(org.batfish.datamodel.routing_policy.expr.BooleanExpr) BatfishException(org.batfish.common.BatfishException) MatchPrefixSet(org.batfish.datamodel.routing_policy.expr.MatchPrefixSet) MatchIpv6(org.batfish.datamodel.routing_policy.expr.MatchIpv6) RoutingPolicy(org.batfish.datamodel.routing_policy.RoutingPolicy) ConjunctionChain(org.batfish.datamodel.routing_policy.expr.ConjunctionChain) MatchIpv4(org.batfish.datamodel.routing_policy.expr.MatchIpv4) MatchProtocol(org.batfish.datamodel.routing_policy.expr.MatchProtocol) Disjunction(org.batfish.datamodel.routing_policy.expr.Disjunction) Not(org.batfish.datamodel.routing_policy.expr.Not)

Example 10 with MatchProtocol

use of org.batfish.datamodel.routing_policy.expr.MatchProtocol in project batfish by batfish.

the class CiscoConfiguration method toRipProcess.

private org.batfish.datamodel.RipProcess toRipProcess(RipProcess proc, String vrfName, Configuration c, CiscoConfiguration oldConfig) {
    org.batfish.datamodel.RipProcess newProcess = new org.batfish.datamodel.RipProcess();
    org.batfish.datamodel.Vrf vrf = c.getVrfs().get(vrfName);
    // establish areas and associated interfaces
    SortedSet<Prefix> networks = proc.getNetworks();
    for (Entry<String, org.batfish.datamodel.Interface> e : vrf.getInterfaces().entrySet()) {
        String ifaceName = e.getKey();
        org.batfish.datamodel.Interface i = e.getValue();
        InterfaceAddress interfaceAddress = i.getAddress();
        if (interfaceAddress == null) {
            continue;
        }
        Prefix interfaceNetwork = interfaceAddress.getPrefix();
        if (networks.contains(interfaceNetwork)) {
            newProcess.getInterfaces().add(ifaceName);
            i.setRipEnabled(true);
            boolean passive = proc.getPassiveInterfaceList().contains(i.getName()) || (proc.getPassiveInterfaceDefault() && !proc.getActiveInterfaceList().contains(ifaceName));
            i.setOspfPassive(passive);
        }
    }
    String ripExportPolicyName = "~RIP_EXPORT_POLICY:" + vrfName + "~";
    RoutingPolicy ripExportPolicy = new RoutingPolicy(ripExportPolicyName, c);
    c.getRoutingPolicies().put(ripExportPolicyName, ripExportPolicy);
    List<Statement> ripExportStatements = ripExportPolicy.getStatements();
    newProcess.setExportPolicy(ripExportPolicyName);
    // policy map for default information
    if (proc.getDefaultInformationOriginate()) {
        If ripExportDefault = new If();
        ripExportStatements.add(ripExportDefault);
        ripExportDefault.setComment("RIP export default route");
        Conjunction ripExportDefaultConditions = new Conjunction();
        List<Statement> ripExportDefaultStatements = ripExportDefault.getTrueStatements();
        ripExportDefaultConditions.getConjuncts().add(new MatchPrefixSet(new DestinationNetwork(), new ExplicitPrefixSet(new PrefixSpace(Collections.singleton(new PrefixRange(Prefix.ZERO, new SubRange(0, 0)))))));
        long metric = proc.getDefaultInformationMetric();
        ripExportDefaultStatements.add(new SetMetric(new LiteralLong(metric)));
        // add default export map with metric
        String defaultOriginateMapName = proc.getDefaultInformationOriginateMap();
        if (defaultOriginateMapName != null) {
            int defaultOriginateMapLine = proc.getDefaultInformationOriginateMapLine();
            RoutingPolicy ripDefaultGenerationPolicy = c.getRoutingPolicies().get(defaultOriginateMapName);
            if (ripDefaultGenerationPolicy == null) {
                undefined(CiscoStructureType.ROUTE_MAP, defaultOriginateMapName, CiscoStructureUsage.RIP_DEFAULT_ORIGINATE_ROUTE_MAP, defaultOriginateMapLine);
            } else {
                RouteMap generationRouteMap = _routeMaps.get(defaultOriginateMapName);
                generationRouteMap.getReferers().put(proc, "rip default-originate route-map");
                GeneratedRoute.Builder route = new GeneratedRoute.Builder();
                route.setNetwork(Prefix.ZERO);
                route.setAdmin(MAX_ADMINISTRATIVE_COST);
                route.setGenerationPolicy(defaultOriginateMapName);
                newProcess.getGeneratedRoutes().add(route.build());
            }
        } else {
            // add generated aggregate with no precondition
            GeneratedRoute.Builder route = new GeneratedRoute.Builder();
            route.setNetwork(Prefix.ZERO);
            route.setAdmin(MAX_ADMINISTRATIVE_COST);
            newProcess.getGeneratedRoutes().add(route.build());
        }
        ripExportDefaultConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.AGGREGATE));
        ripExportDefaultStatements.add(Statements.ExitAccept.toStaticStatement());
        ripExportDefault.setGuard(ripExportDefaultConditions);
    }
    // policy for redistributing connected routes
    RipRedistributionPolicy rcp = proc.getRedistributionPolicies().get(RoutingProtocol.CONNECTED);
    if (rcp != null) {
        If ripExportConnected = new If();
        ripExportConnected.setComment("RIP export connected routes");
        Conjunction ripExportConnectedConditions = new Conjunction();
        ripExportConnectedConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.CONNECTED));
        List<Statement> ripExportConnectedStatements = ripExportConnected.getTrueStatements();
        Long metric = rcp.getMetric();
        boolean explicitMetric = metric != null;
        if (!explicitMetric) {
            metric = RipRedistributionPolicy.DEFAULT_REDISTRIBUTE_CONNECTED_METRIC;
        }
        ripExportStatements.add(new SetMetric(new LiteralLong(metric)));
        ripExportStatements.add(ripExportConnected);
        // add default export map with metric
        String exportConnectedRouteMapName = rcp.getRouteMap();
        if (exportConnectedRouteMapName != null) {
            int exportConnectedRouteMapLine = rcp.getRouteMapLine();
            RouteMap exportConnectedRouteMap = _routeMaps.get(exportConnectedRouteMapName);
            if (exportConnectedRouteMap == null) {
                undefined(CiscoStructureType.ROUTE_MAP, exportConnectedRouteMapName, CiscoStructureUsage.RIP_REDISTRIBUTE_CONNECTED_MAP, exportConnectedRouteMapLine);
            } else {
                exportConnectedRouteMap.getReferers().put(proc, "rip redistribute connected route-map");
                ripExportConnectedConditions.getConjuncts().add(new CallExpr(exportConnectedRouteMapName));
            }
        }
        ripExportConnectedStatements.add(Statements.ExitAccept.toStaticStatement());
        ripExportConnected.setGuard(ripExportConnectedConditions);
    }
    // policy map for redistributing static routes
    RipRedistributionPolicy rsp = proc.getRedistributionPolicies().get(RoutingProtocol.STATIC);
    if (rsp != null) {
        If ripExportStatic = new If();
        ripExportStatic.setComment("RIP export static routes");
        Conjunction ripExportStaticConditions = new Conjunction();
        ripExportStaticConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.STATIC));
        List<Statement> ripExportStaticStatements = ripExportStatic.getTrueStatements();
        ripExportStaticConditions.getConjuncts().add(new Not(new MatchPrefixSet(new DestinationNetwork(), new ExplicitPrefixSet(new PrefixSpace(Collections.singleton(new PrefixRange(Prefix.ZERO, new SubRange(0, 0))))))));
        Long metric = rsp.getMetric();
        boolean explicitMetric = metric != null;
        if (!explicitMetric) {
            metric = RipRedistributionPolicy.DEFAULT_REDISTRIBUTE_STATIC_METRIC;
        }
        ripExportStatements.add(new SetMetric(new LiteralLong(metric)));
        ripExportStatements.add(ripExportStatic);
        // add export map with metric
        String exportStaticRouteMapName = rsp.getRouteMap();
        if (exportStaticRouteMapName != null) {
            int exportStaticRouteMapLine = rsp.getRouteMapLine();
            RouteMap exportStaticRouteMap = _routeMaps.get(exportStaticRouteMapName);
            if (exportStaticRouteMap == null) {
                undefined(CiscoStructureType.ROUTE_MAP, exportStaticRouteMapName, CiscoStructureUsage.RIP_REDISTRIBUTE_STATIC_MAP, exportStaticRouteMapLine);
            } else {
                exportStaticRouteMap.getReferers().put(proc, "rip redistribute static route-map");
                ripExportStaticConditions.getConjuncts().add(new CallExpr(exportStaticRouteMapName));
            }
        }
        ripExportStaticStatements.add(Statements.ExitAccept.toStaticStatement());
        ripExportStatic.setGuard(ripExportStaticConditions);
    }
    // policy map for redistributing bgp routes
    RipRedistributionPolicy rbp = proc.getRedistributionPolicies().get(RoutingProtocol.BGP);
    if (rbp != null) {
        If ripExportBgp = new If();
        ripExportBgp.setComment("RIP export bgp routes");
        Conjunction ripExportBgpConditions = new Conjunction();
        ripExportBgpConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.BGP));
        List<Statement> ripExportBgpStatements = ripExportBgp.getTrueStatements();
        ripExportBgpConditions.getConjuncts().add(new Not(new MatchPrefixSet(new DestinationNetwork(), new ExplicitPrefixSet(new PrefixSpace(Collections.singleton(new PrefixRange(Prefix.ZERO, new SubRange(0, 0))))))));
        Long metric = rbp.getMetric();
        boolean explicitMetric = metric != null;
        if (!explicitMetric) {
            metric = RipRedistributionPolicy.DEFAULT_REDISTRIBUTE_BGP_METRIC;
        }
        ripExportStatements.add(new SetMetric(new LiteralLong(metric)));
        ripExportStatements.add(ripExportBgp);
        // add export map with metric
        String exportBgpRouteMapName = rbp.getRouteMap();
        if (exportBgpRouteMapName != null) {
            int exportBgpRouteMapLine = rbp.getRouteMapLine();
            RouteMap exportBgpRouteMap = _routeMaps.get(exportBgpRouteMapName);
            if (exportBgpRouteMap == null) {
                undefined(CiscoStructureType.ROUTE_MAP, exportBgpRouteMapName, CiscoStructureUsage.RIP_REDISTRIBUTE_BGP_MAP, exportBgpRouteMapLine);
            } else {
                exportBgpRouteMap.getReferers().put(proc, "rip redistribute bgp route-map");
                ripExportBgpConditions.getConjuncts().add(new CallExpr(exportBgpRouteMapName));
            }
        }
        ripExportBgpStatements.add(Statements.ExitAccept.toStaticStatement());
        ripExportBgp.setGuard(ripExportBgpConditions);
    }
    return newProcess;
}
Also used : Prefix(org.batfish.datamodel.Prefix) SetMetric(org.batfish.datamodel.routing_policy.statement.SetMetric) Conjunction(org.batfish.datamodel.routing_policy.expr.Conjunction) CallExpr(org.batfish.datamodel.routing_policy.expr.CallExpr) SubRange(org.batfish.datamodel.SubRange) PrefixRange(org.batfish.datamodel.PrefixRange) InterfaceAddress(org.batfish.datamodel.InterfaceAddress) CallStatement(org.batfish.datamodel.routing_policy.statement.CallStatement) Statement(org.batfish.datamodel.routing_policy.statement.Statement) MatchPrefixSet(org.batfish.datamodel.routing_policy.expr.MatchPrefixSet) PrefixSpace(org.batfish.datamodel.PrefixSpace) RoutingPolicy(org.batfish.datamodel.routing_policy.RoutingPolicy) LiteralLong(org.batfish.datamodel.routing_policy.expr.LiteralLong) MatchProtocol(org.batfish.datamodel.routing_policy.expr.MatchProtocol) Not(org.batfish.datamodel.routing_policy.expr.Not) DestinationNetwork(org.batfish.datamodel.routing_policy.expr.DestinationNetwork) ExplicitPrefixSet(org.batfish.datamodel.routing_policy.expr.ExplicitPrefixSet) LiteralLong(org.batfish.datamodel.routing_policy.expr.LiteralLong) GeneratedRoute(org.batfish.datamodel.GeneratedRoute) If(org.batfish.datamodel.routing_policy.statement.If)

Aggregations

MatchProtocol (org.batfish.datamodel.routing_policy.expr.MatchProtocol)14 RoutingPolicy (org.batfish.datamodel.routing_policy.RoutingPolicy)10 BooleanExpr (org.batfish.datamodel.routing_policy.expr.BooleanExpr)8 Conjunction (org.batfish.datamodel.routing_policy.expr.Conjunction)8 Disjunction (org.batfish.datamodel.routing_policy.expr.Disjunction)8 If (org.batfish.datamodel.routing_policy.statement.If)8 MatchPrefixSet (org.batfish.datamodel.routing_policy.expr.MatchPrefixSet)7 Not (org.batfish.datamodel.routing_policy.expr.Not)7 ArrayList (java.util.ArrayList)6 Prefix (org.batfish.datamodel.Prefix)6 CallExpr (org.batfish.datamodel.routing_policy.expr.CallExpr)6 BatfishException (org.batfish.common.BatfishException)5 InterfaceAddress (org.batfish.datamodel.InterfaceAddress)5 Statement (org.batfish.datamodel.routing_policy.statement.Statement)5 Ip (org.batfish.datamodel.Ip)4 PrefixRange (org.batfish.datamodel.PrefixRange)4 SubRange (org.batfish.datamodel.SubRange)4 DestinationNetwork (org.batfish.datamodel.routing_policy.expr.DestinationNetwork)4 ExplicitPrefixSet (org.batfish.datamodel.routing_policy.expr.ExplicitPrefixSet)4 HashSet (java.util.HashSet)3