Search in sources :

Example 1 with Route

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

the class BdpEngine method debugIterations.

private String debugIterations(String msg, Map<Integer, SortedSet<Route>> iterationRoutes, int first, int last) {
    StringBuilder sb = new StringBuilder();
    sb.append(msg);
    sb.append("\n");
    SortedSet<Route> initialRoutes = iterationRoutes.get(first);
    sb.append("Initial routes (iteration " + first + "):\n");
    for (Route route : initialRoutes) {
        String routeStr = route.prettyPrint(null);
        sb.append(routeStr);
    }
    for (int i = first + 1; i <= last; i++) {
        SortedSet<Route> baseRoutes = iterationRoutes.get(i - 1);
        SortedSet<Route> deltaRoutes = iterationRoutes.get(i);
        SortedSet<Route> added = CommonUtil.difference(deltaRoutes, baseRoutes, TreeSet<Route>::new);
        SortedSet<Route> removed = CommonUtil.difference(baseRoutes, deltaRoutes, TreeSet<Route>::new);
        SortedSet<Route> changed = CommonUtil.union(added, removed, TreeSet<Route>::new);
        sb.append("Changed routes (iteration " + (i - 1) + " ==> " + i + "):\n");
        for (Route route : changed) {
            String diffSymbol = added.contains(route) ? "+" : "-";
            String routeStr = route.prettyPrint(diffSymbol);
            sb.append(routeStr);
        }
    }
    String errorMessage = sb.toString();
    return errorMessage;
}
Also used : TreeSet(java.util.TreeSet) AbstractRoute(org.batfish.datamodel.AbstractRoute) Route(org.batfish.datamodel.Route)

Example 2 with Route

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

the class BdpEngine method computeOutputRoutes.

private SortedSet<Route> computeOutputRoutes(Map<String, Node> nodes, Map<Ip, String> ipOwners) {
    SortedSet<Route> outputRoutes = new TreeSet<>();
    nodes.forEach((hostname, node) -> {
        node._virtualRouters.forEach((vrName, vr) -> {
            for (AbstractRoute route : vr._mainRib.getRoutes()) {
                RouteBuilder rb = new RouteBuilder();
                rb.setNode(hostname);
                rb.setNetwork(route.getNetwork());
                Ip nextHopIp = route.getNextHopIp();
                if (route.getProtocol() == RoutingProtocol.CONNECTED || (route.getProtocol() == RoutingProtocol.STATIC && nextHopIp.equals(Route.UNSET_ROUTE_NEXT_HOP_IP)) || Interface.NULL_INTERFACE_NAME.equals(route.getNextHopInterface())) {
                    rb.setNextHop(Configuration.NODE_NONE_NAME);
                }
                if (!nextHopIp.equals(Route.UNSET_ROUTE_NEXT_HOP_IP)) {
                    rb.setNextHopIp(nextHopIp);
                    String nextHop = ipOwners.get(nextHopIp);
                    if (nextHop != null) {
                        rb.setNextHop(nextHop);
                    }
                }
                rb.setNextHopInterface(route.getNextHopInterface());
                rb.setAdministrativeCost(route.getAdministrativeCost());
                rb.setCost(route.getMetric());
                rb.setProtocol(route.getProtocol());
                rb.setTag(route.getTag());
                rb.setVrf(vrName);
                Route outputRoute = rb.build();
                outputRoutes.add(outputRoute);
            }
        });
    });
    return outputRoutes;
}
Also used : AbstractRoute(org.batfish.datamodel.AbstractRoute) RouteBuilder(org.batfish.datamodel.RouteBuilder) TreeSet(java.util.TreeSet) Ip(org.batfish.datamodel.Ip) AbstractRoute(org.batfish.datamodel.AbstractRoute) Route(org.batfish.datamodel.Route)

Example 3 with Route

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

the class BdpEngine method computeFixedPoint.

/**
 * Attempt to compute the fixed point of the data plane.
 *
 * @param nodes A dictionary of configuration-wrapping Bdp nodes keyed by name
 * @param topology The topology representing physical adjacencies between interface of the nodes
 * @param dp The output data plane
 * @param externalAdverts Optional external BGP advertisements fed into the data plane computation
 * @param ae The output answer element in which to store a report of the computation. Also
 *     contains the current recovery iteration.
 * @param recoveryIterationHashCodes Dependent-route computation iteration hash-code dictionaries,
 *     themselves keyed by outer recovery iteration.
 * @return true iff the computation is oscillating
 */
private boolean computeFixedPoint(SortedMap<String, Node> nodes, Topology topology, BdpDataPlane dp, Set<BgpAdvertisement> externalAdverts, BdpAnswerElement ae, SortedMap<Integer, SortedMap<Integer, Integer>> recoveryIterationHashCodes, SortedMap<Integer, SortedSet<Prefix>> iterationOscillatingPrefixes) {
    try (ActiveSpan computeFixedPointSpan = GlobalTracer.get().buildSpan("Computing fixed point").startActive()) {
        // avoid unused warning
        assert computeFixedPointSpan != null;
        SortedSet<Prefix> oscillatingPrefixes = ae.getOscillatingPrefixes();
        // BEGIN DONE ONCE (except main rib)
        // For each virtual router, setup the initial easy-to-do routes and init protocol-based RIBs:
        AtomicInteger initialCompleted = _newBatch.apply("Compute initial connected and static routes, ospf setup, bgp setup", nodes.size());
        try (ActiveSpan initRibsBdpSpan = GlobalTracer.get().buildSpan("Initializing easy routes for BDP").startActive()) {
            // avoid unused warning
            assert initRibsBdpSpan != null;
            nodes.values().parallelStream().forEach(n -> {
                for (VirtualRouter vr : n._virtualRouters.values()) {
                    vr.initRibsForBdp(dp.getIpOwners(), externalAdverts);
                }
                initialCompleted.incrementAndGet();
            });
        }
        // OSPF internal routes
        int numOspfInternalIterations;
        try (ActiveSpan ospfInternalRoutesSpan = GlobalTracer.get().buildSpan("Initializing OSPF internal routes").startActive()) {
            assert ospfInternalRoutesSpan != null;
            numOspfInternalIterations = initOspfInternalRoutes(nodes, topology);
        }
        // RIP internal routes
        try (ActiveSpan ripInternalRoutesSpan = GlobalTracer.get().buildSpan("Initializing RIP internal routes").startActive()) {
            assert ripInternalRoutesSpan != null;
            initRipInternalRoutes(nodes, topology);
        }
        // Prep for traceroutes
        nodes.values().parallelStream().forEach(n -> n._virtualRouters.values().forEach(vr -> {
            vr.importRib(vr._mainRib, vr._independentRib);
            // Needed for activateStaticRoutes
            vr._prevMainRib = vr._mainRib;
            vr.activateStaticRoutes();
        }));
        // Update bgp neighbors with reachability
        dp.setNodes(nodes);
        computeFibs(nodes);
        dp.setTopology(topology);
        initRemoteBgpNeighbors(nodes.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, e -> e.getValue().getConfiguration())), dp.getIpOwners(), true, this, dp);
        // END DONE ONCE
        /*
       * Setup maps to track iterations. We need this for oscillation detection.
       * Specifically, if we detect that an iteration hashcode (a hash of all the nodes' RIBs)
       * has been previously encountered, we go into recovery mode.
       * Recovery mode means enabling "lockstep route propagation" for oscillating prefixes.
       *
       * Lockstep route propagation only allows one of the neighbors to propagate routes for
       * oscillating prefixes in a given iteration.
       * E.g., lexicographically lower neighbor propagates routes during
       * odd iterations, and lex-higher neighbor during even iterations.
       */
        Map<Integer, SortedSet<Integer>> iterationsByHashCode = new HashMap<>();
        SortedMap<Integer, Integer> iterationHashCodes = new TreeMap<>();
        Map<Integer, SortedSet<Route>> iterationRoutes = null;
        Map<Integer, SortedMap<String, SortedMap<String, SortedSet<AbstractRoute>>>> iterationAbstractRoutes = null;
        if (_settings.getBdpRecordAllIterations()) {
            if (_settings.getBdpDetail()) {
                iterationAbstractRoutes = new TreeMap<>();
            } else {
                iterationRoutes = new TreeMap<>();
            }
        } else if (_maxRecordedIterations > 0) {
            if (_settings.getBdpDetail()) {
                iterationAbstractRoutes = new LRUMap<>(_maxRecordedIterations);
            } else {
                iterationRoutes = new LRUMap<>(_maxRecordedIterations);
            }
        }
        AtomicBoolean dependentRoutesChanged = new AtomicBoolean(false);
        AtomicBoolean evenDependentRoutesChanged = new AtomicBoolean(false);
        AtomicBoolean oddDependentRoutesChanged = new AtomicBoolean(false);
        int numDependentRoutesIterations = 0;
        // Go into iteration mode, until the routes converge (or oscillation is detected)
        do {
            numDependentRoutesIterations++;
            AtomicBoolean currentChangedMonitor;
            if (oscillatingPrefixes.isEmpty()) {
                currentChangedMonitor = dependentRoutesChanged;
            } else if (numDependentRoutesIterations % 2 == 0) {
                currentChangedMonitor = evenDependentRoutesChanged;
            } else {
                currentChangedMonitor = oddDependentRoutesChanged;
            }
            currentChangedMonitor.set(false);
            computeDependentRoutesIteration(nodes, topology, dp, numDependentRoutesIterations, oscillatingPrefixes);
            /* Collect sizes of certain RIBs this iteration */
            computeIterationStatistics(nodes, ae, numDependentRoutesIterations);
            recordIterationDebugInfo(nodes, dp, iterationRoutes, iterationAbstractRoutes, numDependentRoutesIterations);
            // Check to see if hash has changed
            AtomicInteger checkFixedPointCompleted = _newBatch.apply("Iteration " + numDependentRoutesIterations + ": Check if fixed-point reached", nodes.size());
            // This hashcode uniquely identifies the iteration (i.e., network state)
            int iterationHashCode = computeIterationHashCode(nodes);
            SortedSet<Integer> iterationsWithThisHashCode = iterationsByHashCode.computeIfAbsent(iterationHashCode, h -> new TreeSet<>());
            iterationHashCodes.put(numDependentRoutesIterations, iterationHashCode);
            int minNumberOfUnchangedIterationsForConvergence = oscillatingPrefixes.isEmpty() ? 1 : 2;
            if (iterationsWithThisHashCode.isEmpty() || (!oscillatingPrefixes.isEmpty() && iterationsWithThisHashCode.equals(Collections.singleton(numDependentRoutesIterations - 1)))) {
                iterationsWithThisHashCode.add(numDependentRoutesIterations);
            } else if (!iterationsWithThisHashCode.contains(numDependentRoutesIterations - minNumberOfUnchangedIterationsForConvergence)) {
                int lowestIterationWithThisHashCode = iterationsWithThisHashCode.first();
                int completedOscillationRecoveryAttempts = ae.getCompletedOscillationRecoveryAttempts();
                if (!oscillatingPrefixes.isEmpty()) {
                    completedOscillationRecoveryAttempts++;
                    ae.setCompletedOscillationRecoveryAttempts(completedOscillationRecoveryAttempts);
                }
                recoveryIterationHashCodes.put(completedOscillationRecoveryAttempts, iterationHashCodes);
                handleOscillation(recoveryIterationHashCodes, iterationRoutes, iterationAbstractRoutes, lowestIterationWithThisHashCode, numDependentRoutesIterations, iterationOscillatingPrefixes, ae);
                return true;
            }
            compareToPreviousIteration(nodes, currentChangedMonitor, checkFixedPointCompleted);
            computeFibs(nodes);
            initRemoteBgpNeighbors(nodes.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, e -> e.getValue().getConfiguration())), dp.getIpOwners(), true, this, dp);
        } while (checkDependentRoutesChanged(dependentRoutesChanged, evenDependentRoutesChanged, oddDependentRoutesChanged, oscillatingPrefixes, numDependentRoutesIterations));
        AtomicInteger computeBgpAdvertisementsToOutsideCompleted = _newBatch.apply("Compute BGP advertisements sent to outside", nodes.size());
        nodes.values().parallelStream().forEach(n -> {
            for (VirtualRouter vr : n._virtualRouters.values()) {
                vr.computeBgpAdvertisementsToOutside(dp.getIpOwners());
            }
            computeBgpAdvertisementsToOutsideCompleted.incrementAndGet();
        });
        // Set iteration stats in the answer
        ae.setOspfInternalIterations(numOspfInternalIterations);
        ae.setDependentRoutesIterations(numDependentRoutesIterations);
        return false;
    }
}
Also used : SortedSet(java.util.SortedSet) BiFunction(java.util.function.BiFunction) LRUMap(org.apache.commons.collections4.map.LRUMap) FlowTrace(org.batfish.datamodel.FlowTrace) InterfaceAddress(org.batfish.datamodel.InterfaceAddress) Edge(org.batfish.datamodel.Edge) Interface(org.batfish.datamodel.Interface) Flow(org.batfish.datamodel.Flow) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Topology(org.batfish.datamodel.Topology) CommonUtil.initRemoteBgpNeighbors(org.batfish.common.util.CommonUtil.initRemoteBgpNeighbors) Map(java.util.Map) DataPlane(org.batfish.datamodel.DataPlane) ImmutableMap(com.google.common.collect.ImmutableMap) FlowDisposition(org.batfish.datamodel.FlowDisposition) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) List(java.util.List) SourceNat(org.batfish.datamodel.SourceNat) Entry(java.util.Map.Entry) Optional(java.util.Optional) SortedMap(java.util.SortedMap) BatfishLogger(org.batfish.common.BatfishLogger) Ip(org.batfish.datamodel.Ip) RouteBuilder(org.batfish.datamodel.RouteBuilder) NodeInterfacePair(org.batfish.datamodel.collections.NodeInterfacePair) FilterResult(org.batfish.datamodel.FilterResult) RoutingProtocol(org.batfish.datamodel.RoutingProtocol) BdpAnswerElement(org.batfish.datamodel.answers.BdpAnswerElement) CommonUtil(org.batfish.common.util.CommonUtil) FlowTraceHop(org.batfish.datamodel.FlowTraceHop) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) BatfishException(org.batfish.common.BatfishException) BgpProcess(org.batfish.datamodel.BgpProcess) IpAccessList(org.batfish.datamodel.IpAccessList) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) BgpAdvertisement(org.batfish.datamodel.BgpAdvertisement) AbstractRoute(org.batfish.datamodel.AbstractRoute) Version(org.batfish.common.Version) FlowProcessor(org.batfish.common.plugin.FlowProcessor) Configuration(org.batfish.datamodel.Configuration) LineAction(org.batfish.datamodel.LineAction) LinkedHashSet(java.util.LinkedHashSet) Nullable(javax.annotation.Nullable) ImmutableSortedSet(com.google.common.collect.ImmutableSortedSet) Route(org.batfish.datamodel.Route) GlobalTracer(io.opentracing.util.GlobalTracer) BdpOscillationException(org.batfish.common.BdpOscillationException) TreeMap(java.util.TreeMap) ActiveSpan(io.opentracing.ActiveSpan) Collections(java.util.Collections) Prefix(org.batfish.datamodel.Prefix) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) Prefix(org.batfish.datamodel.Prefix) TreeMap(java.util.TreeMap) SortedSet(java.util.SortedSet) ImmutableSortedSet(com.google.common.collect.ImmutableSortedSet) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Entry(java.util.Map.Entry) ActiveSpan(io.opentracing.ActiveSpan) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) LRUMap(org.apache.commons.collections4.map.LRUMap) SortedMap(java.util.SortedMap)

Example 4 with Route

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

the class NxosRoutingTableExtractor method exitRoute.

@Override
public void exitRoute(RouteContext ctx) {
    if (ctx.protocol().LOCAL() != null) {
        return;
    }
    if (_currentVrfRoutes == null) {
        initVrf(Configuration.DEFAULT_VRF_NAME);
    }
    RoutingProtocol protocol = toProtocol(ctx.protocol());
    String nextHopInterface = Route.UNSET_NEXT_HOP_INTERFACE;
    if (ctx.nexthopint != null) {
        nextHopInterface = ctx.nexthopint.getText();
    }
    int admin = toInteger(ctx.admin);
    int cost = toInteger(ctx.cost);
    Ip nextHopIp = Route.UNSET_ROUTE_NEXT_HOP_IP;
    if (protocol != RoutingProtocol.CONNECTED && ctx.nexthop != null) {
        nextHopIp = new Ip(ctx.nexthop.getText());
    }
    RouteBuilder rb = new RouteBuilder();
    rb.setNode(_hostname);
    rb.setNetwork(_currentPrefix);
    if (protocol == RoutingProtocol.CONNECTED || (protocol == RoutingProtocol.STATIC && nextHopIp.equals(Route.UNSET_ROUTE_NEXT_HOP_IP)) || Interface.NULL_INTERFACE_NAME.equals(nextHopInterface)) {
        rb.setNextHop(Configuration.NODE_NONE_NAME);
    }
    if (!nextHopIp.equals(Route.UNSET_ROUTE_NEXT_HOP_IP)) {
        rb.setNextHopIp(nextHopIp);
        String nextHop = _ipOwners.get(nextHopIp);
        if (nextHop != null) {
            rb.setNextHop(nextHop);
        }
    }
    if (nextHopInterface != null) {
        rb.setNextHopInterface(nextHopInterface);
    }
    rb.setAdministrativeCost(admin);
    rb.setCost(cost);
    rb.setProtocol(protocol);
    rb.setTag(Route.UNSET_ROUTE_TAG);
    rb.setVrf(_currentVrfName);
    Route route = rb.build();
    _currentVrfRoutes.add(route);
}
Also used : RoutingProtocol(org.batfish.datamodel.RoutingProtocol) RouteBuilder(org.batfish.datamodel.RouteBuilder) Ip(org.batfish.datamodel.Ip) Route(org.batfish.datamodel.Route)

Example 5 with Route

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

the class BdpDataPlanePluginTest method testIosRtStaticMatchesBdp.

@Test
public void testIosRtStaticMatchesBdp() throws IOException {
    String testrigResourcePrefix = TESTRIGS_PREFIX + "ios-rt-static-ad";
    List<String> configurationNames = ImmutableList.of("r1");
    List<String> routingTableNames = ImmutableList.of("r1");
    Batfish batfish = BatfishTestUtils.getBatfishFromTestrigText(TestrigText.builder().setConfigurationText(testrigResourcePrefix, configurationNames).setRoutingTablesText(testrigResourcePrefix, routingTableNames).build(), _folder);
    BdpDataPlanePlugin dataPlanePlugin = new BdpDataPlanePlugin();
    dataPlanePlugin.initialize(batfish);
    batfish.computeDataPlane(false);
    SortedMap<String, RoutesByVrf> environmentRoutes = batfish.loadEnvironmentRoutingTables();
    SortedMap<String, SortedMap<String, SortedSet<AbstractRoute>>> routes = dataPlanePlugin.getRoutes(batfish.loadDataPlane());
    Prefix staticRoutePrefix = Prefix.parse("10.0.0.0/8");
    SortedSet<AbstractRoute> r1BdpRoutes = routes.get("r1").get(DEFAULT_VRF_NAME);
    AbstractRoute r1BdpRoute = r1BdpRoutes.stream().filter(r -> r.getNetwork().equals(staticRoutePrefix)).findFirst().get();
    SortedSet<Route> r1EnvironmentRoutes = environmentRoutes.get("r1").get(DEFAULT_VRF_NAME);
    Route r1EnvironmentRoute = r1EnvironmentRoutes.stream().filter(r -> r.getNetwork().equals(staticRoutePrefix)).findFirst().get();
    assertThat(r1BdpRoute.getAdministrativeCost(), equalTo(r1EnvironmentRoute.getAdministrativeCost()));
    assertThat(r1BdpRoute.getMetric(), equalTo(r1EnvironmentRoute.getMetric()));
    assertThat(r1BdpRoute.getProtocol(), equalTo(r1EnvironmentRoute.getProtocol()));
}
Also used : AbstractRoute(org.batfish.datamodel.AbstractRoute) Matchers.containsString(org.hamcrest.Matchers.containsString) Prefix(org.batfish.datamodel.Prefix) SortedMap(java.util.SortedMap) ImmutableSortedMap(com.google.common.collect.ImmutableSortedMap) RoutesByVrf(org.batfish.datamodel.collections.RoutesByVrf) Batfish(org.batfish.main.Batfish) AbstractRoute(org.batfish.datamodel.AbstractRoute) BgpRoute(org.batfish.datamodel.BgpRoute) StaticRoute(org.batfish.datamodel.StaticRoute) Route(org.batfish.datamodel.Route) Test(org.junit.Test)

Aggregations

Route (org.batfish.datamodel.Route)9 AbstractRoute (org.batfish.datamodel.AbstractRoute)6 Ip (org.batfish.datamodel.Ip)6 Prefix (org.batfish.datamodel.Prefix)6 TreeSet (java.util.TreeSet)5 RouteBuilder (org.batfish.datamodel.RouteBuilder)5 RoutingProtocol (org.batfish.datamodel.RoutingProtocol)5 SortedSet (java.util.SortedSet)4 ImmutableSortedSet (com.google.common.collect.ImmutableSortedSet)3 LinkedHashSet (java.util.LinkedHashSet)3 Map (java.util.Map)3 Entry (java.util.Map.Entry)3 Set (java.util.Set)3 SortedMap (java.util.SortedMap)3 Configuration (org.batfish.datamodel.Configuration)3 Interface (org.batfish.datamodel.Interface)3 ImmutableMap (com.google.common.collect.ImmutableMap)2 List (java.util.List)2 TreeMap (java.util.TreeMap)2 BgpAdvertisement (org.batfish.datamodel.BgpAdvertisement)2