Search in sources :

Example 36 with Prefix

use of org.batfish.datamodel.Prefix in project batfish by batfish.

the class EncoderSlice method initOriginatedPrefixes.

private void initOriginatedPrefixes() {
    for (Entry<String, Configuration> entry : getGraph().getConfigurations().entrySet()) {
        String router = entry.getKey();
        Configuration conf = entry.getValue();
        for (Protocol proto : _optimizations.getProtocols().get(router)) {
            Set<Prefix> prefixes = Graph.getOriginatedNetworks(conf, proto);
            _originatedNetworks.put(router, proto, prefixes);
        }
    }
}
Also used : Configuration(org.batfish.datamodel.Configuration) Prefix(org.batfish.datamodel.Prefix) IpProtocol(org.batfish.datamodel.IpProtocol) RoutingProtocol(org.batfish.datamodel.RoutingProtocol) Protocol(org.batfish.symbolic.Protocol) MatchProtocol(org.batfish.datamodel.routing_policy.expr.MatchProtocol)

Example 37 with Prefix

use of org.batfish.datamodel.Prefix 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 38 with Prefix

use of org.batfish.datamodel.Prefix in project batfish by batfish.

the class EncoderSlice method addImportConstraint.

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

Example 39 with Prefix

use of org.batfish.datamodel.Prefix in project batfish by batfish.

the class Optimizations method computeCanMergeExportVars.

/*
   * Determines when we can merge export variables into a single copy.
   * This will be safe when there is no peer-specific export filter.
   */
private void computeCanMergeExportVars() {
    Graph g = _encoderSlice.getGraph();
    HeaderQuestion q = _encoderSlice.getEncoder().getQuestion();
    boolean noFailures = q.getFailures() == 0;
    _encoderSlice.getGraph().getConfigurations().forEach((router, conf) -> {
        HashMap<Protocol, Boolean> map = new HashMap<>();
        _sliceCanKeepSingleExportVar.put(router, map);
        // the neighbor already being the root of the tree.
        for (Protocol proto : getProtocols().get(router)) {
            if (proto.isConnected() || proto.isStatic()) {
                map.put(proto, noFailures && Optimizations.ENABLE_EXPORT_MERGE_OPTIMIZATION);
            } else if (proto.isOspf()) {
                // Ensure all interfaces are active
                boolean allIfacesActive = true;
                for (GraphEdge edge : g.getEdgeMap().get(router)) {
                    if (g.isEdgeUsed(conf, proto, edge)) {
                        Interface iface = edge.getStart();
                        allIfacesActive = allIfacesActive && g.isInterfaceActive(proto, iface);
                    }
                }
                // Ensure single area for this router
                Set<Long> areas = _encoderSlice.getGraph().getAreaIds().get(router);
                boolean singleArea = areas.size() <= 1;
                map.put(proto, noFailures && allIfacesActive && singleArea && ENABLE_EXPORT_MERGE_OPTIMIZATION);
            } else if (proto.isBgp()) {
                boolean acc = true;
                BgpProcess p = conf.getDefaultVrf().getBgpProcess();
                for (Map.Entry<Prefix, BgpNeighbor> e : p.getNeighbors().entrySet()) {
                    BgpNeighbor n = e.getValue();
                    // If iBGP used, then don't merge
                    if (n.getLocalAs().equals(n.getRemoteAs())) {
                        acc = false;
                        break;
                    }
                    // If not the default export policy, then don't merge
                    if (!isDefaultBgpExport(conf, n)) {
                        acc = false;
                        break;
                    }
                }
                map.put(proto, noFailures && acc && ENABLE_EXPORT_MERGE_OPTIMIZATION);
            } else {
                throw new BatfishException("Error: unkown protocol: " + proto.name());
            }
        }
    });
}
Also used : BatfishException(org.batfish.common.BatfishException) HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) BgpProcess(org.batfish.datamodel.BgpProcess) Prefix(org.batfish.datamodel.Prefix) BgpNeighbor(org.batfish.datamodel.BgpNeighbor) Graph(org.batfish.symbolic.Graph) HeaderQuestion(org.batfish.datamodel.questions.smt.HeaderQuestion) Protocol(org.batfish.symbolic.Protocol) GraphEdge(org.batfish.symbolic.GraphEdge) HashMap(java.util.HashMap) Map(java.util.Map) Interface(org.batfish.datamodel.Interface)

Example 40 with Prefix

use of org.batfish.datamodel.Prefix in project batfish by batfish.

the class Optimizations method computeRelevantAggregates.

/*
   * Computes aggregates that are applicable to the encoding.
   */
private void computeRelevantAggregates() {
    _encoderSlice.getGraph().getConfigurations().forEach((router, conf) -> {
        List<GeneratedRoute> routes = new ArrayList<>();
        _relevantAggregates.put(router, routes);
        for (GeneratedRoute gr : conf.getDefaultVrf().getGeneratedRoutes()) {
            Prefix p = gr.getNetwork();
            if (_encoderSlice.relevantPrefix(p)) {
                routes.add(gr);
            }
        }
    });
}
Also used : ArrayList(java.util.ArrayList) GeneratedRoute(org.batfish.datamodel.GeneratedRoute) Prefix(org.batfish.datamodel.Prefix)

Aggregations

Prefix (org.batfish.datamodel.Prefix)133 Ip (org.batfish.datamodel.Ip)53 Configuration (org.batfish.datamodel.Configuration)33 InterfaceAddress (org.batfish.datamodel.InterfaceAddress)29 Interface (org.batfish.datamodel.Interface)28 BatfishException (org.batfish.common.BatfishException)22 RoutingPolicy (org.batfish.datamodel.routing_policy.RoutingPolicy)20 SubRange (org.batfish.datamodel.SubRange)19 HashMap (java.util.HashMap)18 StaticRoute (org.batfish.datamodel.StaticRoute)18 Test (org.junit.Test)18 ArrayList (java.util.ArrayList)17 BgpNeighbor (org.batfish.datamodel.BgpNeighbor)17 BgpProcess (org.batfish.datamodel.BgpProcess)17 SortedSet (java.util.SortedSet)16 TreeSet (java.util.TreeSet)16 AbstractRoute (org.batfish.datamodel.AbstractRoute)16 RoutingProtocol (org.batfish.datamodel.RoutingProtocol)16 TreeMap (java.util.TreeMap)14 HashSet (java.util.HashSet)13