Search in sources :

Example 1 with IpOwners

use of org.batfish.common.topology.IpOwners in project batfish by batfish.

the class BgpTopologyUtils method addActivePeerEdges.

private static void addActivePeerEdges(BgpPeerConfigId neighborId, MutableValueGraph<BgpPeerConfigId, BgpSessionProperties> graph, NetworkConfigurations nc, Map<Ip, Map<String, Set<String>>> ipOwners, Map<String, Multimap<String, BgpPeerConfigId>> receivers, Set<Ip> potentialLocalIps, boolean checkReachability, TracerouteEngine tracerouteEngine) {
    BgpActivePeerConfig neighbor = nc.getBgpPointToPointPeerConfig(neighborId);
    if (neighbor == null || potentialLocalIps.isEmpty() || neighbor.getLocalAs() == null || neighbor.getPeerAddress() == null || neighbor.getRemoteAsns().isEmpty()) {
        return;
    }
    // Find nodes that own the neighbor's peer address
    Map<String, Set<String>> possibleVrfs = ipOwners.get(neighbor.getPeerAddress());
    if (possibleVrfs == null) {
        return;
    }
    Set<BgpPeerConfigId> alreadyEstablished = graph.adjacentNodes(neighborId);
    for (Entry<String, Set<String>> entry : possibleVrfs.entrySet()) {
        String node = entry.getKey();
        Set<String> vrfs = entry.getValue();
        Multimap<String, BgpPeerConfigId> receiversByVrf = receivers.get(node);
        if (receiversByVrf == null) {
            continue;
        }
        for (String vrf : vrfs) {
            receiversByVrf.get(vrf).stream().filter(candidateId -> !alreadyEstablished.contains(candidateId)).forEach(candidateId -> {
                // Ensure candidate has compatible local/remote AS, isn't in same vrf as initiator
                BgpPeerConfig candidate = nc.getBgpPeerConfig(candidateId);
                if (!bgpCandidatePassesSanityChecks(neighborId, neighbor, candidateId, candidate)) {
                    return;
                }
                // Check if neighbor has any feasible local IPs compatible with this candidate
                Set<Ip> feasibleLocalIpsForPeeringWithCandidate = getFeasibleLocalIps(potentialLocalIps, candidate);
                if (feasibleLocalIpsForPeeringWithCandidate.isEmpty()) {
                    return;
                }
                if (!checkReachability) {
                    feasibleLocalIpsForPeeringWithCandidate.forEach(ip -> addEdges(neighbor, neighborId, ip, candidateId, graph, nc));
                } else {
                    initiateBgpSessions(neighborId, candidateId, neighbor, feasibleLocalIpsForPeeringWithCandidate, tracerouteEngine).stream().filter(BgpSessionInitiationResult::isSuccessful).map(initiationResult -> initiationResult.getFlow().getSrcIp()).forEach(srcIp -> addEdges(neighbor, neighborId, srcIp, candidateId, graph, nc));
                }
            });
        }
    }
}
Also used : BgpPeerConfigType(org.batfish.datamodel.BgpPeerConfigId.BgpPeerConfigType) IpProtocol(org.batfish.datamodel.IpProtocol) Hop(org.batfish.datamodel.flow.Hop) FibForward(org.batfish.datamodel.FibForward) FibNextVrf(org.batfish.datamodel.FibNextVrf) Trace(org.batfish.datamodel.flow.Trace) Interface(org.batfish.datamodel.Interface) ValueGraphBuilder(com.google.common.graph.ValueGraphBuilder) Flow(org.batfish.datamodel.Flow) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) NetworkConfigurations(org.batfish.datamodel.NetworkConfigurations) Map(java.util.Map) Network(com.google.common.graph.Network) NamedPort(org.batfish.datamodel.NamedPort) Vrf(org.batfish.datamodel.Vrf) IpOwners(org.batfish.common.topology.IpOwners) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) LinkedListMultimap(com.google.common.collect.LinkedListMultimap) ImmutableSet(com.google.common.collect.ImmutableSet) BgpPeerConfig(org.batfish.datamodel.BgpPeerConfig) ImmutableMap(com.google.common.collect.ImmutableMap) FlowDisposition(org.batfish.datamodel.FlowDisposition) FibActionVisitor(org.batfish.datamodel.visitors.FibActionVisitor) Set(java.util.Set) TraceAndReverseFlow(org.batfish.datamodel.flow.TraceAndReverseFlow) Objects(java.util.Objects) List(java.util.List) BgpPassivePeerConfig(org.batfish.datamodel.BgpPassivePeerConfig) L3Adjacencies(org.batfish.common.topology.L3Adjacencies) Entry(java.util.Map.Entry) Ip(org.batfish.datamodel.Ip) LongSpace(org.batfish.datamodel.LongSpace) NodeInterfacePair(org.batfish.datamodel.collections.NodeInterfacePair) TracerouteEngine(org.batfish.common.plugin.TracerouteEngine) BgpActivePeerConfig(org.batfish.datamodel.BgpActivePeerConfig) HashMap(java.util.HashMap) BgpProcess(org.batfish.datamodel.BgpProcess) Multimap(com.google.common.collect.Multimap) BgpPeerConfigId(org.batfish.datamodel.BgpPeerConfigId) ImmutableList(com.google.common.collect.ImmutableList) Configuration(org.batfish.datamodel.Configuration) FibNullRoute(org.batfish.datamodel.FibNullRoute) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) ConcreteInterfaceAddress(org.batfish.datamodel.ConcreteInterfaceAddress) Fib(org.batfish.datamodel.Fib) MoreObjects(com.google.common.base.MoreObjects) SetMultimap(com.google.common.collect.SetMultimap) SessionType(org.batfish.datamodel.BgpSessionProperties.SessionType) MutableValueGraph(com.google.common.graph.MutableValueGraph) BgpSessionProperties(org.batfish.datamodel.BgpSessionProperties) VisibleForTesting(com.google.common.annotations.VisibleForTesting) FibEntry(org.batfish.datamodel.FibEntry) BgpUnnumberedPeerConfig(org.batfish.datamodel.BgpUnnumberedPeerConfig) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) Ip(org.batfish.datamodel.Ip) BgpPeerConfig(org.batfish.datamodel.BgpPeerConfig) BgpActivePeerConfig(org.batfish.datamodel.BgpActivePeerConfig) BgpPeerConfigId(org.batfish.datamodel.BgpPeerConfigId)

Example 2 with IpOwners

use of org.batfish.common.topology.IpOwners in project batfish by batfish.

the class BgpTopologyUtils method initBgpTopology.

/**
 * Compute the BGP topology -- a network of {@link BgpPeerConfigId}s connected by {@link
 * BgpSessionProperties}.
 *
 * @param configurations node configurations, keyed by hostname
 * @param ipVrfOwners network Ip owners (see {@link IpOwners#computeIpNodeOwners(Map, boolean)}
 *     for reference)
 * @param keepInvalid whether to keep improperly configured neighbors. If performing configuration
 *     checks, you probably want this set to {@code true}, otherwise (e.g., computing dataplane)
 *     you want this to be {@code false}.
 * @param checkReachability whether to perform dataplane-level checks to ensure that neighbors are
 *     reachable and sessions can be established correctly. <b>Note:</b> this is different from
 *     {@code keepInvalid=false}, which only does filters invalid neighbors at the control-plane
 *     level
 * @param tracerouteEngine an instance of {@link TracerouteEngine} for doing reachability checks.
 * @param l3Adjacencies {@link L3Adjacencies} of the network, for checking BGP unnumbered
 *     reachability.
 * @return A graph ({@link Network}) representing all BGP peerings.
 */
@Nonnull
public static BgpTopology initBgpTopology(Map<String, Configuration> configurations, Map<Ip, Map<String, Set<String>>> ipVrfOwners, boolean keepInvalid, boolean checkReachability, @Nullable TracerouteEngine tracerouteEngine, Map<String, Map<String, Fib>> fibs, L3Adjacencies l3Adjacencies) {
    checkArgument(!checkReachability || !keepInvalid, "Cannot check reachability while keeping invalid peers");
    checkArgument(!checkReachability || tracerouteEngine != null, "Cannot check reachability without a traceroute engine");
    // TODO: handle duplicate ips on different vrfs
    NetworkConfigurations networkConfigurations = NetworkConfigurations.of(configurations);
    /*
     * First pass: identify all addresses "owned" by BgpNeighbors, add neighbor ids as vertices to
     * the graph; dynamically determine local IPs as needed
     */
    MutableValueGraph<BgpPeerConfigId, BgpSessionProperties> graph = ValueGraphBuilder.directed().allowsSelfLoops(false).build();
    /*
     * Multimap of active peers' BgpPeerConfigIds to all IPs that each peer may use as local IP
     * when initiating a session. For a peer with an explicitly configured local IP, that IP is
     * the only value associated with the peer in this map. Otherwise:
     * - If FIBs are provided, the map contains all local IPs with which the peer may initiate,
     *   as inferred by getPotentialSrcIps().
     * - Else no IPs are associated with the peer.
     */
    ImmutableSetMultimap.Builder<BgpPeerConfigId, Ip> localIpsBuilder = ImmutableSetMultimap.builder();
    for (Configuration node : configurations.values()) {
        String hostname = node.getHostname();
        for (Vrf vrf : node.getVrfs().values()) {
            String vrfName = vrf.getName();
            BgpProcess proc = vrf.getBgpProcess();
            if (proc == null) {
                // nothing to do if no bgp process on this VRF
                continue;
            }
            Fib fib = fibs.getOrDefault(hostname, ImmutableMap.of()).get(vrfName);
            for (Entry<Ip, BgpActivePeerConfig> e : proc.getActiveNeighbors().entrySet()) {
                Ip peerAddress = e.getKey();
                BgpActivePeerConfig config = e.getValue();
                if (!keepInvalid && !bgpConfigPassesSanityChecks(config, hostname, vrfName, ipVrfOwners)) {
                    continue;
                }
                BgpPeerConfigId neighborId = new BgpPeerConfigId(hostname, vrfName, peerAddress.toPrefix(), false);
                graph.addNode(neighborId);
                if (config.getLocalIp() != null) {
                    localIpsBuilder.put(neighborId, config.getLocalIp());
                } else if (fib != null) {
                    // No explicitly configured local IP. Check for dynamically resolvable local IPs.
                    localIpsBuilder.putAll(neighborId, getPotentialSrcIps(peerAddress, fib, node));
                }
            }
            // Dynamic peers: map of prefix to BgpPassivePeerConfig
            proc.getPassiveNeighbors().entrySet().stream().filter(entry -> keepInvalid || bgpConfigPassesSanityChecks(entry.getValue(), hostname, vrfName, ipVrfOwners)).forEach(entry -> graph.addNode(new BgpPeerConfigId(hostname, vrfName, entry.getKey(), true)));
            // Unnumbered BGP peers: map of interface name to BgpUnnumberedPeerConfig
            proc.getInterfaceNeighbors().entrySet().stream().filter(e -> keepInvalid || bgpConfigPassesSanityChecks(e.getValue(), hostname, vrfName, ipVrfOwners)).forEach(e -> graph.addNode(new BgpPeerConfigId(hostname, vrf.getName(), e.getKey())));
        }
    }
    // Second pass: add edges to the graph. Note, these are directed edges.
    Map<String, Multimap<String, BgpPeerConfigId>> receivers = new HashMap<>();
    for (BgpPeerConfigId peer : graph.nodes()) {
        if (peer.getType() == BgpPeerConfigType.UNNUMBERED) {
            // Unnumbered configs only form sessions with each other
            continue;
        }
        Multimap<String, BgpPeerConfigId> vrf = receivers.computeIfAbsent(peer.getHostname(), name -> LinkedListMultimap.create());
        vrf.put(peer.getVrfName(), peer);
    }
    SetMultimap<BgpPeerConfigId, Ip> localIps = localIpsBuilder.build();
    for (BgpPeerConfigId neighborId : graph.nodes()) {
        switch(neighborId.getType()) {
            case DYNAMIC:
                // Passive end of the peering cannot initiate a connection
                continue;
            case ACTIVE:
                addActivePeerEdges(neighborId, graph, networkConfigurations, ipVrfOwners, receivers, localIps.get(neighborId), checkReachability, tracerouteEngine);
                break;
            case UNNUMBERED:
                addUnnumberedPeerEdges(neighborId, graph, networkConfigurations, l3Adjacencies);
                break;
            default:
                throw new IllegalArgumentException(String.format("Unrecognized peer type: %s", neighborId));
        }
    }
    return new BgpTopology(graph);
}
Also used : BgpPeerConfigType(org.batfish.datamodel.BgpPeerConfigId.BgpPeerConfigType) IpProtocol(org.batfish.datamodel.IpProtocol) Hop(org.batfish.datamodel.flow.Hop) FibForward(org.batfish.datamodel.FibForward) FibNextVrf(org.batfish.datamodel.FibNextVrf) Trace(org.batfish.datamodel.flow.Trace) Interface(org.batfish.datamodel.Interface) ValueGraphBuilder(com.google.common.graph.ValueGraphBuilder) Flow(org.batfish.datamodel.Flow) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) NetworkConfigurations(org.batfish.datamodel.NetworkConfigurations) Map(java.util.Map) Network(com.google.common.graph.Network) NamedPort(org.batfish.datamodel.NamedPort) Vrf(org.batfish.datamodel.Vrf) IpOwners(org.batfish.common.topology.IpOwners) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) LinkedListMultimap(com.google.common.collect.LinkedListMultimap) ImmutableSet(com.google.common.collect.ImmutableSet) BgpPeerConfig(org.batfish.datamodel.BgpPeerConfig) ImmutableMap(com.google.common.collect.ImmutableMap) FlowDisposition(org.batfish.datamodel.FlowDisposition) FibActionVisitor(org.batfish.datamodel.visitors.FibActionVisitor) Set(java.util.Set) TraceAndReverseFlow(org.batfish.datamodel.flow.TraceAndReverseFlow) Objects(java.util.Objects) List(java.util.List) BgpPassivePeerConfig(org.batfish.datamodel.BgpPassivePeerConfig) L3Adjacencies(org.batfish.common.topology.L3Adjacencies) Entry(java.util.Map.Entry) Ip(org.batfish.datamodel.Ip) LongSpace(org.batfish.datamodel.LongSpace) NodeInterfacePair(org.batfish.datamodel.collections.NodeInterfacePair) TracerouteEngine(org.batfish.common.plugin.TracerouteEngine) BgpActivePeerConfig(org.batfish.datamodel.BgpActivePeerConfig) HashMap(java.util.HashMap) BgpProcess(org.batfish.datamodel.BgpProcess) Multimap(com.google.common.collect.Multimap) BgpPeerConfigId(org.batfish.datamodel.BgpPeerConfigId) ImmutableList(com.google.common.collect.ImmutableList) Configuration(org.batfish.datamodel.Configuration) FibNullRoute(org.batfish.datamodel.FibNullRoute) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) ConcreteInterfaceAddress(org.batfish.datamodel.ConcreteInterfaceAddress) Fib(org.batfish.datamodel.Fib) MoreObjects(com.google.common.base.MoreObjects) SetMultimap(com.google.common.collect.SetMultimap) SessionType(org.batfish.datamodel.BgpSessionProperties.SessionType) MutableValueGraph(com.google.common.graph.MutableValueGraph) BgpSessionProperties(org.batfish.datamodel.BgpSessionProperties) VisibleForTesting(com.google.common.annotations.VisibleForTesting) FibEntry(org.batfish.datamodel.FibEntry) BgpUnnumberedPeerConfig(org.batfish.datamodel.BgpUnnumberedPeerConfig) Configuration(org.batfish.datamodel.Configuration) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) BgpProcess(org.batfish.datamodel.BgpProcess) HashMap(java.util.HashMap) NetworkConfigurations(org.batfish.datamodel.NetworkConfigurations) Ip(org.batfish.datamodel.Ip) FibNextVrf(org.batfish.datamodel.FibNextVrf) Vrf(org.batfish.datamodel.Vrf) BgpSessionProperties(org.batfish.datamodel.BgpSessionProperties) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) LinkedListMultimap(com.google.common.collect.LinkedListMultimap) Multimap(com.google.common.collect.Multimap) SetMultimap(com.google.common.collect.SetMultimap) BgpActivePeerConfig(org.batfish.datamodel.BgpActivePeerConfig) BgpPeerConfigId(org.batfish.datamodel.BgpPeerConfigId) Fib(org.batfish.datamodel.Fib) Nonnull(javax.annotation.Nonnull)

Example 3 with IpOwners

use of org.batfish.common.topology.IpOwners in project batfish by batfish.

the class ForwardingAnalysisImplTest method testDispositionWithTopology.

// If two nodes are in the same subnet but not connected per the given topology,
// sending packets from one to the other should result in Neighbor Unreachable.
@Test
public void testDispositionWithTopology() {
    Prefix prefix = Prefix.parse("1.0.0.0/24");
    IpSpace ipSpace = prefix.toIpSpace();
    Ip ip2 = Ip.parse("1.0.0.2");
    Configuration c1 = _cb.setHostname("c1").build();
    Configuration c2 = _cb.setHostname("c2").build();
    Vrf v1 = _vb.setName("v1").setOwner(c1).build();
    Vrf v2 = _vb.setName("v2").setOwner(c2).build();
    Interface i1 = _ib.setAddresses(ConcreteInterfaceAddress.parse("1.0.0.1/24")).setName("i1").setOwner(c1).setVrf(v1).build();
    Interface i2 = _ib.setAddresses(ConcreteInterfaceAddress.parse("1.0.0.2/24")).setName("i2").setOwner(c2).setVrf(v2).build();
    StaticRoute route1 = StaticRoute.testBuilder().setNetwork(prefix).setNextHopInterface(i1.getName()).setAdministrativeCost(1).build();
    StaticRoute route2 = StaticRoute.testBuilder().setNextHopInterface(i2.getName()).setNetwork(prefix).setAdministrativeCost(1).build();
    v1.setStaticRoutes(ImmutableSortedSet.of(route1));
    v2.setStaticRoutes(ImmutableSortedSet.of(route2));
    MockFib fib1 = MockFib.builder().setMatchingIps(ImmutableMap.of(prefix, ipSpace)).setFibEntries(ImmutableMap.of(prefix.getFirstHostIp(), ImmutableSet.of(new FibEntry(FibForward.of(null, i1.getName()), ImmutableList.of(route1))))).build();
    MockFib fib2 = MockFib.builder().setMatchingIps(ImmutableMap.of(prefix, ipSpace)).setFibEntries(ImmutableMap.of(prefix.getFirstHostIp(), ImmutableSet.of(new FibEntry(FibForward.of(null, i2.getName()), ImmutableList.of(route2))))).build();
    Map<String, Map<String, Fib>> fibs = ImmutableMap.of(c1.getHostname(), ImmutableMap.of(v1.getName(), fib1), c2.getHostname(), ImmutableMap.of(v2.getName(), fib2));
    Map<String, Configuration> configs = ImmutableMap.of(c1.getHostname(), c1, c2.getHostname(), c2);
    IpOwners ipOwners = new TestIpOwners(configs);
    ForwardingAnalysis analysis = new ForwardingAnalysisImpl(configs, fibs, Topology.EMPTY, computeLocationInfo(ipOwners, configs), ipOwners);
    InterfaceForwardingBehavior i1ForwardingBehavior = analysis.getVrfForwardingBehavior().get(c1.getHostname()).get(v1.getName()).getInterfaceForwardingBehavior().get(i1.getName());
    assertFalse(i1ForwardingBehavior.getDeliveredToSubnet().containsIp(ip2, c1.getIpSpaces()));
    assertTrue(i1ForwardingBehavior.getNeighborUnreachable().containsIp(ip2, c1.getIpSpaces()));
    assertFalse(i1ForwardingBehavior.getInsufficientInfo().containsIp(ip2, c1.getIpSpaces()));
}
Also used : ForwardingAnalysisImpl.computeArpFalseNextHopIp(org.batfish.datamodel.ForwardingAnalysisImpl.computeArpFalseNextHopIp) ForwardingAnalysisImpl.computeArpTrueEdgeNextHopIp(org.batfish.datamodel.ForwardingAnalysisImpl.computeArpTrueEdgeNextHopIp) ForwardingAnalysisImpl.computeRoutesWhereDstIpCanBeArpIp(org.batfish.datamodel.ForwardingAnalysisImpl.computeRoutesWhereDstIpCanBeArpIp) IpSpaceMatchers.containsIp(org.batfish.datamodel.matchers.IpSpaceMatchers.containsIp) ForwardingAnalysisImpl.computeArpTrueEdgeDestIp(org.batfish.datamodel.ForwardingAnalysisImpl.computeArpTrueEdgeDestIp) ForwardingAnalysisImpl.computeArpFalseDestIp(org.batfish.datamodel.ForwardingAnalysisImpl.computeArpFalseDestIp) ForwardingAnalysisImpl.computeOwnedIpsByVrf(org.batfish.datamodel.ForwardingAnalysisImpl.computeOwnedIpsByVrf) IpOwners(org.batfish.common.topology.IpOwners) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableSortedMap(com.google.common.collect.ImmutableSortedMap) ForwardingAnalysisImpl.computeRoutesWithNextHopIpArpFalseForInterface(org.batfish.datamodel.ForwardingAnalysisImpl.computeRoutesWithNextHopIpArpFalseForInterface) Test(org.junit.Test)

Example 4 with IpOwners

use of org.batfish.common.topology.IpOwners in project batfish by batfish.

the class ForwardingAnalysisImplTest method testUnknownedNextHopIpOwnedArpIp.

/**
 * Test that if a route has an unowned next hop IP, but it resolves to an owned ARP IP and we
 * don't get an ARP response, we get insufficient info.
 */
@Test
public void testUnknownedNextHopIpOwnedArpIp() {
    Configuration n1 = _cb.setHostname("n1").build();
    Vrf v1 = _vb.setOwner(n1).build();
    Interface i1 = _ib.setOwner(n1).setVrf(v1).setAddress(ConcreteInterfaceAddress.parse("10.0.1.0/31")).build();
    // unowned
    Ip arpIp = Ip.parse("3.3.3.3");
    StaticRoute route = StaticRoute.testBuilder().setNetwork(Prefix.parse("1.1.1.1/32")).setNextHopIp(Ip.parse("2.2.2.2")).setAdmin(1).build();
    MockFib fib1 = MockFib.builder().setMatchingIps(ImmutableMap.of(route.getNetwork(), route.getNetwork().toIpSpace())).setFibEntries(ImmutableMap.of(arpIp, ImmutableSet.of(new FibEntry(FibForward.of(arpIp, i1.getName()), ImmutableList.of(route))))).build();
    Map<String, Configuration> configs = ImmutableMap.of(n1.getHostname(), n1);
    Map<String, Map<String, Fib>> fibs = ImmutableMap.of(n1.getHostname(), ImmutableMap.of(v1.getName(), fib1));
    IpOwners ipOwners = new TestIpOwners(configs);
    ForwardingAnalysis fa = new ForwardingAnalysisImpl(configs, fibs, Topology.EMPTY, computeLocationInfo(ipOwners, configs), ipOwners);
    InterfaceForwardingBehavior ifb = fa.getVrfForwardingBehavior().get(n1.getHostname()).get(v1.getName()).getInterfaceForwardingBehavior().get(i1.getName());
    assertThat(ifb.getInsufficientInfo(), not(containsIp(route.getNetwork().getStartIp())));
    assertThat(ifb.getExitsNetwork(), containsIp(route.getNetwork().getStartIp()));
}
Also used : ForwardingAnalysisImpl.computeArpFalseNextHopIp(org.batfish.datamodel.ForwardingAnalysisImpl.computeArpFalseNextHopIp) ForwardingAnalysisImpl.computeArpTrueEdgeNextHopIp(org.batfish.datamodel.ForwardingAnalysisImpl.computeArpTrueEdgeNextHopIp) ForwardingAnalysisImpl.computeRoutesWhereDstIpCanBeArpIp(org.batfish.datamodel.ForwardingAnalysisImpl.computeRoutesWhereDstIpCanBeArpIp) IpSpaceMatchers.containsIp(org.batfish.datamodel.matchers.IpSpaceMatchers.containsIp) ForwardingAnalysisImpl.computeArpTrueEdgeDestIp(org.batfish.datamodel.ForwardingAnalysisImpl.computeArpTrueEdgeDestIp) ForwardingAnalysisImpl.computeArpFalseDestIp(org.batfish.datamodel.ForwardingAnalysisImpl.computeArpFalseDestIp) ForwardingAnalysisImpl.computeOwnedIpsByVrf(org.batfish.datamodel.ForwardingAnalysisImpl.computeOwnedIpsByVrf) IpOwners(org.batfish.common.topology.IpOwners) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableSortedMap(com.google.common.collect.ImmutableSortedMap) ForwardingAnalysisImpl.computeRoutesWithNextHopIpArpFalseForInterface(org.batfish.datamodel.ForwardingAnalysisImpl.computeRoutesWithNextHopIpArpFalseForInterface) Test(org.junit.Test)

Example 5 with IpOwners

use of org.batfish.common.topology.IpOwners in project batfish by batfish.

the class IncrementalBdpEngine method computeDataPlane.

ComputeDataPlaneResult computeDataPlane(Map<String, Configuration> configurations, TopologyContext initialTopologyContext, Set<BgpAdvertisement> externalAdverts, IpOwners initialIpOwners) {
    LOGGER.info("Computing Data Plane using iBDP");
    Map<Ip, Map<String, Set<String>>> initialIpVrfOwners = initialIpOwners.getIpVrfOwners();
    // Generate our nodes, keyed by name, sorted for determinism
    SortedMap<String, Node> nodes = toImmutableSortedMap(configurations.values(), Configuration::getHostname, Node::new);
    // A collection of all the virtual routers in random order enables parallelization across all
    // VRs, and likely spreads nodes with similar hostnames across different cores. In contrast,
    // nodes.values().parallelStream().flatMap(get vrs stream) is only node-parallel and clusters
    // nodes by hostname. See https://github.com/batfish/batfish/pull/7054 description.
    List<VirtualRouter> vrs = toListInRandomOrder(nodes.values().stream().flatMap(n -> n.getVirtualRouters().stream()));
    NetworkConfigurations networkConfigurations = NetworkConfigurations.of(configurations);
    /*
     * Run the data plane computation here:
     * - First, let the IGP routes converge
     * - Second, re-init BGP neighbors with reachability checks
     * - Third, let the EGP routes converge
     * - Finally, compute FIBs, return answer
     */
    IncrementalBdpAnswerElement answerElement = new IncrementalBdpAnswerElement();
    // TODO: eventually, IGP needs to be part of fixed-point below, because tunnels.
    computeIgpDataPlane(nodes, vrs, initialTopologyContext, answerElement);
    LOGGER.info("Initialize virtual routers before topology fixed point");
    vrs.parallelStream().forEach(vr -> vr.initForEgpComputationBeforeTopologyLoop(externalAdverts, initialIpVrfOwners));
    /*
     * Perform a fixed-point computation, in which every round the topology is updated based
     * on what we have learned in the previous round.
     */
    // Since the topology iterations are incremental, clear fields that are pruned to get the real
    // topology. They are not actually yet included in topologies.
    TopologyContext priorTopologyContext = initialTopologyContext.toBuilder().setIpsecTopology(IpsecTopology.EMPTY).setTunnelTopology(TunnelTopology.EMPTY).setVxlanTopology(VxlanTopology.EMPTY).build();
    PartialDataplane currentDataplane = nextDataplane(priorTopologyContext, nodes, vrs, initialIpOwners);
    TopologyContext currentTopologyContext = nextTopologyContext(priorTopologyContext, currentDataplane, initialTopologyContext, networkConfigurations, initialIpVrfOwners);
    Map<String, Collection<TrackRoute>> trackRoutesByHostname = collectTrackRoutes(configurations);
    Map<String, Collection<TrackReachability>> trackReachabilitiesByHostname = collectTrackReachabilities(configurations);
    Map<String, Map<TrackReachability, Boolean>> currentTrackReachabilityResultsByHostname = nextTrackReachabilityResultsByHostname(currentDataplane, currentTopologyContext, configurations, trackReachabilitiesByHostname);
    Map<String, Map<TrackRoute, Boolean>> currentTrackRouteResultsByHostname = nextTrackRoutesByHostname(trackRoutesByHostname, nodes);
    DataPlaneTrackMethodEvaluatorProvider currentTrackMethodEvaluatorProvider = nextTrackMethodEvaluatorProvider(currentTrackReachabilityResultsByHostname, currentTrackRouteResultsByHostname);
    DataPlaneIpOwners currentIpOwners = new DataPlaneIpOwners(configurations, currentTopologyContext.getL3Adjacencies(), currentTrackMethodEvaluatorProvider);
    int topologyIterations = 0;
    boolean converged = false;
    while (!converged && topologyIterations++ < MAX_TOPOLOGY_ITERATIONS) {
        LOGGER.info("Starting topology iteration {}", topologyIterations);
        boolean isOscillating = computeNonMonotonicPortionOfDataPlane(nodes, vrs, answerElement, currentTopologyContext, initialTopologyContext.getLayer3Topology(), currentIpOwners, networkConfigurations, currentTrackMethodEvaluatorProvider);
        if (isOscillating) {
            // If we are oscillating here, network has no stable solution.
            LOGGER.error("Network has no stable solution");
            throw new BdpOscillationException("Network has no stable solution");
        }
        updateLayer3Vnis(vrs);
        // free the old one
        currentDataplane = null;
        currentDataplane = nextDataplane(currentTopologyContext, nodes, vrs, currentIpOwners);
        TopologyContext nextTopologyContext = nextTopologyContext(currentTopologyContext, currentDataplane, initialTopologyContext, networkConfigurations, currentIpOwners.getIpVrfOwners());
        Map<String, Map<TrackReachability, Boolean>> nextTrackReachabilityResultsByHostname = nextTrackReachabilityResultsByHostname(currentDataplane, currentTopologyContext, configurations, trackReachabilitiesByHostname);
        Map<String, Map<TrackRoute, Boolean>> nextTrackRouteResultsByHostname = nextTrackRoutesByHostname(trackRoutesByHostname, nodes);
        currentTrackMethodEvaluatorProvider = nextTrackMethodEvaluatorProvider(nextTrackReachabilityResultsByHostname, nextTrackRouteResultsByHostname);
        DataPlaneIpOwners nextIpOwners = new DataPlaneIpOwners(configurations, nextTopologyContext.getL3Adjacencies(), currentTrackMethodEvaluatorProvider);
        converged = currentTopologyContext.equals(nextTopologyContext) && currentTrackReachabilityResultsByHostname.equals(nextTrackReachabilityResultsByHostname) && currentTrackRouteResultsByHostname.equals(nextTrackRouteResultsByHostname) && currentIpOwners.equals(nextIpOwners);
        currentTopologyContext = nextTopologyContext;
        currentTrackReachabilityResultsByHostname = nextTrackReachabilityResultsByHostname;
        currentTrackRouteResultsByHostname = nextTrackRouteResultsByHostname;
        currentIpOwners = nextIpOwners;
    }
    if (!converged) {
        LOGGER.error("Could not reach a fixed point topology in {} iterations", MAX_TOPOLOGY_ITERATIONS);
        throw new BdpOscillationException(String.format("Could not reach a fixed point topology in %d iterations", MAX_TOPOLOGY_ITERATIONS));
    }
    // Generate the answers from the computation, compute final FIBs
    // TODO: Properly finalize topologies, IpOwners, etc.
    LOGGER.info("Finalizing dataplane");
    answerElement.setVersion(BatfishVersion.getVersionStatic());
    IncrementalDataPlane finalDataplane = IncrementalDataPlane.builder().setNodes(nodes).setPartialDataplane(currentDataplane).build();
    return new IbdpResult(answerElement, finalDataplane, currentTopologyContext, nodes);
}
Also used : TunnelTopology(org.batfish.common.topology.TunnelTopology) SortedSet(java.util.SortedSet) VxlanTopology(org.batfish.datamodel.vxlan.VxlanTopology) BgpTopology(org.batfish.datamodel.bgp.BgpTopology) IsisRoute(org.batfish.datamodel.IsisRoute) GenericTrackMethodVisitor(org.batfish.datamodel.tracking.GenericTrackMethodVisitor) Rib(org.batfish.dataplane.rib.Rib) BatfishVersion(org.batfish.version.BatfishVersion) Edge(org.batfish.datamodel.Edge) NegatedTrackMethod(org.batfish.datamodel.tracking.NegatedTrackMethod) NetworkConfigurations(org.batfish.datamodel.NetworkConfigurations) Topology(org.batfish.datamodel.Topology) TopologyUtil.computeLayer2Topology(org.batfish.common.topology.TopologyUtil.computeLayer2Topology) Map(java.util.Map) IpOwners(org.batfish.common.topology.IpOwners) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Collection(java.util.Collection) Set(java.util.Set) CollectionUtil.toImmutableSortedMap(org.batfish.common.util.CollectionUtil.toImmutableSortedMap) TracerouteEngineImpl(org.batfish.dataplane.TracerouteEngineImpl) StreamUtil.toListInRandomOrder(org.batfish.common.util.StreamUtil.toListInRandomOrder) List(java.util.List) PreDataPlaneTrackMethodEvaluator(org.batfish.datamodel.tracking.PreDataPlaneTrackMethodEvaluator) TopologyUtil.computeRawLayer3Topology(org.batfish.common.topology.TopologyUtil.computeRawLayer3Topology) Stream(java.util.stream.Stream) Logger(org.apache.logging.log4j.Logger) VxlanTopologyUtils.prunedVxlanTopology(org.batfish.datamodel.vxlan.VxlanTopologyUtils.prunedVxlanTopology) TrackInterface(org.batfish.datamodel.tracking.TrackInterface) EigrpTopology(org.batfish.datamodel.eigrp.EigrpTopology) L3Adjacencies(org.batfish.common.topology.L3Adjacencies) Entry(java.util.Map.Entry) OspfTopology(org.batfish.datamodel.ospf.OspfTopology) Schedule(org.batfish.dataplane.ibdp.schedule.IbdpSchedule.Schedule) IpsecUtil.toEdgeSet(org.batfish.common.util.IpsecUtil.toEdgeSet) SortedMap(java.util.SortedMap) Ip(org.batfish.datamodel.Ip) DataPlaneTrackMethodEvaluatorProvider(org.batfish.dataplane.ibdp.DataplaneTrackEvaluator.DataPlaneTrackMethodEvaluatorProvider) TrackMethodReference(org.batfish.datamodel.tracking.TrackMethodReference) TrackReachabilityUtils.evaluateTrackReachability(org.batfish.dataplane.ibdp.TrackReachabilityUtils.evaluateTrackReachability) HybridL3Adjacencies(org.batfish.common.topology.HybridL3Adjacencies) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) TracerouteEngine(org.batfish.common.plugin.TracerouteEngine) GlobalBroadcastNoPointToPoint(org.batfish.common.topology.GlobalBroadcastNoPointToPoint) IpsecUtil.retainReachableIpsecEdges(org.batfish.common.util.IpsecUtil.retainReachableIpsecEdges) HashMap(java.util.HashMap) BroadcastL3Adjacencies(org.batfish.common.topology.broadcast.BroadcastL3Adjacencies) Function(java.util.function.Function) TreeSet(java.util.TreeSet) BgpAdvertisement(org.batfish.datamodel.BgpAdvertisement) TrackReachability(org.batfish.datamodel.tracking.TrackReachability) AbstractRoute(org.batfish.datamodel.AbstractRoute) Configuration(org.batfish.datamodel.Configuration) TopologyUtil.computeLayer3Topology(org.batfish.common.topology.TopologyUtil.computeLayer3Topology) ComputeDataPlaneResult(org.batfish.common.plugin.DataPlanePlugin.ComputeDataPlaneResult) Nonnull(javax.annotation.Nonnull) BgpTopologyUtils.initBgpTopology(org.batfish.datamodel.bgp.BgpTopologyUtils.initBgpTopology) IpsecTopology(org.batfish.datamodel.ipsec.IpsecTopology) IncrementalBdpAnswerElement(org.batfish.datamodel.answers.IncrementalBdpAnswerElement) IbdpSchedule(org.batfish.dataplane.ibdp.schedule.IbdpSchedule) TopologyUtil.pruneUnreachableTunnelEdges(org.batfish.common.topology.TopologyUtil.pruneUnreachableTunnelEdges) AbstractRib.importRib(org.batfish.dataplane.rib.AbstractRib.importRib) TrackTrue(org.batfish.datamodel.tracking.TrackTrue) VxlanTopologyUtils.computeNextVxlanTopologyModuloReachability(org.batfish.datamodel.vxlan.VxlanTopologyUtils.computeNextVxlanTopologyModuloReachability) BdpOscillationException(org.batfish.common.BdpOscillationException) VxlanTopologyUtils.vxlanTopologyToLayer3Edges(org.batfish.datamodel.vxlan.VxlanTopologyUtils.vxlanTopologyToLayer3Edges) EigrpTopologyUtils(org.batfish.datamodel.eigrp.EigrpTopologyUtils) TrackRoute(org.batfish.datamodel.tracking.TrackRoute) Layer2Topology(org.batfish.common.topology.Layer2Topology) RibDelta(org.batfish.dataplane.rib.RibDelta) VisibleForTesting(com.google.common.annotations.VisibleForTesting) LogManager(org.apache.logging.log4j.LogManager) Layer1Topologies(org.batfish.common.topology.Layer1Topologies) Configuration(org.batfish.datamodel.Configuration) Ip(org.batfish.datamodel.Ip) BdpOscillationException(org.batfish.common.BdpOscillationException) NetworkConfigurations(org.batfish.datamodel.NetworkConfigurations) DataPlaneTrackMethodEvaluatorProvider(org.batfish.dataplane.ibdp.DataplaneTrackEvaluator.DataPlaneTrackMethodEvaluatorProvider) GlobalBroadcastNoPointToPoint(org.batfish.common.topology.GlobalBroadcastNoPointToPoint) IncrementalBdpAnswerElement(org.batfish.datamodel.answers.IncrementalBdpAnswerElement) Collection(java.util.Collection) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) CollectionUtil.toImmutableSortedMap(org.batfish.common.util.CollectionUtil.toImmutableSortedMap) SortedMap(java.util.SortedMap) HashMap(java.util.HashMap)

Aggregations

ImmutableMap (com.google.common.collect.ImmutableMap)6 Map (java.util.Map)6 IpOwners (org.batfish.common.topology.IpOwners)6 VisibleForTesting (com.google.common.annotations.VisibleForTesting)4 ImmutableSet (com.google.common.collect.ImmutableSet)4 HashMap (java.util.HashMap)4 List (java.util.List)4 Entry (java.util.Map.Entry)4 Set (java.util.Set)4 Nonnull (javax.annotation.Nonnull)4 TracerouteEngine (org.batfish.common.plugin.TracerouteEngine)4 L3Adjacencies (org.batfish.common.topology.L3Adjacencies)4 Configuration (org.batfish.datamodel.Configuration)4 Ip (org.batfish.datamodel.Ip)3 NetworkConfigurations (org.batfish.datamodel.NetworkConfigurations)3 MoreObjects (com.google.common.base.MoreObjects)2 Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)2 ImmutableList (com.google.common.collect.ImmutableList)2 ImmutableSetMultimap (com.google.common.collect.ImmutableSetMultimap)2 ImmutableSortedMap (com.google.common.collect.ImmutableSortedMap)2