@Test public void testComputeRoutesWithNextHopIpArpTrue() { String c1 = "c1"; String i1 = "i1"; String c2 = "c2"; String i2 = "i2"; Edge e1 = Edge.of(c1, i1, c2, i2); Map<String, Map<String, IpSpace>> arpReplies = ImmutableMap.of(c2, ImmutableMap.of(i2, P2.getStartIp().toIpSpace())); Topology topology = new Topology(ImmutableSortedSet.of(e1)); String v1 = "v1"; AbstractRoute r1 = StaticRoute.builder() .setNetwork(P1) .setNextHopIp(P2.getStartIp()) .setAdministrativeCost(1) .build(); AbstractRoute r2 = StaticRoute.builder() .setNetwork(P1) .setNextHopIp(P2.getEndIp()) .setAdministrativeCost(1) .build(); Map<String, Map<String, Map<String, Set<AbstractRoute>>>> routesWithNextHop = ImmutableMap.of(c1, ImmutableMap.of(v1, ImmutableMap.of(i1, ImmutableSet.of(r1, r2)))); AbstractRoute ifaceRoute = new ConnectedRoute(P2, i1); Map<String, Map<String, Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>>>> nextHopInterfacesByNodeVrf = ImmutableMap.of( c1, ImmutableMap.of( v1, ImmutableMap.of( r1, ImmutableMap.of( i1, ImmutableMap.of(r1.getNextHopIp(), ImmutableSet.of(ifaceRoute))), r2, ImmutableMap.of( i1, ImmutableMap.of(r2.getNextHopIp(), ImmutableSet.of(ifaceRoute)))))); Map<String, Map<String, Map<Edge, Set<AbstractRoute>>>> result = computeRoutesWithNextHopIpArpTrue( nextHopInterfacesByNodeVrf, topology, arpReplies, routesWithNextHop); assertThat( result, equalTo( ImmutableMap.of(c1, ImmutableMap.of(v1, ImmutableMap.of(e1, ImmutableSet.of(r1)))))); }
@VisibleForTesting static Map<String, Map<String, Map<Edge, Set<AbstractRoute>>>> computeRoutesWithNextHopIpArpTrue( Map<String, Map<String, Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>>>> nextHopInterfacesByNodeVrf, Topology topology, Map<String, Map<String, IpSpace>> arpReplies, Map<String, Map<String, Map<String, Set<AbstractRoute>>>> routesWithNextHop) { Span span = GlobalTracer.get() .buildSpan("ForwardingAnalysisImpl.computeRoutesWithNextHopIpArpTrue") .start(); try (Scope scope = GlobalTracer.get().scopeManager().activate(span)) { assert scope != null; return toImmutableMap( routesWithNextHop, Entry::getKey, nodeEntry -> toImmutableMap( nodeEntry.getValue(), Entry::getKey, vrfEntry -> { String hostname = nodeEntry.getKey(); String vrf = vrfEntry.getKey(); Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>> nextHopInterfaces = nextHopInterfacesByNodeVrf.get(hostname).get(vrf); return vrfEntry.getValue().entrySet().stream() .flatMap( ifaceEntry -> { String outInterface = ifaceEntry.getKey(); Set<AbstractRoute> candidateRoutes = ifaceEntry.getValue(); NodeInterfacePair out = NodeInterfacePair.of(hostname, outInterface); Set<NodeInterfacePair> receivers = topology.getNeighbors(out); return receivers.stream() .map( receiver -> { String recvNode = receiver.getHostname(); String recvInterface = receiver.getInterface(); IpSpace recvReplies = arpReplies.get(recvNode).get(recvInterface); Edge edge = new Edge(out, receiver); Set<AbstractRoute> routes = candidateRoutes.stream() .filter( route -> nextHopInterfaces.get(route) .get(outInterface) .keySet() .stream() .filter( ip -> !Route.UNSET_ROUTE_NEXT_HOP_IP .equals(ip)) .anyMatch( nextHopIp -> recvReplies.containsIp( nextHopIp, ImmutableMap.of()))) .collect(ImmutableSet.toImmutableSet()); return routes.isEmpty() ? null : Maps.immutableEntry(edge, routes); }) .filter(Objects::nonNull); }) .collect(ImmutableMap.toImmutableMap(Entry::getKey, Entry::getValue)); })); } finally { span.finish(); } }
ForwardingAnalysisImpl implements ForwardingAnalysis, Serializable { @VisibleForTesting static Map<String, Map<String, Map<Edge, Set<AbstractRoute>>>> computeRoutesWithNextHopIpArpTrue( Map<String, Map<String, Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>>>> nextHopInterfacesByNodeVrf, Topology topology, Map<String, Map<String, IpSpace>> arpReplies, Map<String, Map<String, Map<String, Set<AbstractRoute>>>> routesWithNextHop) { Span span = GlobalTracer.get() .buildSpan("ForwardingAnalysisImpl.computeRoutesWithNextHopIpArpTrue") .start(); try (Scope scope = GlobalTracer.get().scopeManager().activate(span)) { assert scope != null; return toImmutableMap( routesWithNextHop, Entry::getKey, nodeEntry -> toImmutableMap( nodeEntry.getValue(), Entry::getKey, vrfEntry -> { String hostname = nodeEntry.getKey(); String vrf = vrfEntry.getKey(); Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>> nextHopInterfaces = nextHopInterfacesByNodeVrf.get(hostname).get(vrf); return vrfEntry.getValue().entrySet().stream() .flatMap( ifaceEntry -> { String outInterface = ifaceEntry.getKey(); Set<AbstractRoute> candidateRoutes = ifaceEntry.getValue(); NodeInterfacePair out = NodeInterfacePair.of(hostname, outInterface); Set<NodeInterfacePair> receivers = topology.getNeighbors(out); return receivers.stream() .map( receiver -> { String recvNode = receiver.getHostname(); String recvInterface = receiver.getInterface(); IpSpace recvReplies = arpReplies.get(recvNode).get(recvInterface); Edge edge = new Edge(out, receiver); Set<AbstractRoute> routes = candidateRoutes.stream() .filter( route -> nextHopInterfaces.get(route) .get(outInterface) .keySet() .stream() .filter( ip -> !Route.UNSET_ROUTE_NEXT_HOP_IP .equals(ip)) .anyMatch( nextHopIp -> recvReplies.containsIp( nextHopIp, ImmutableMap.of()))) .collect(ImmutableSet.toImmutableSet()); return routes.isEmpty() ? null : Maps.immutableEntry(edge, routes); }) .filter(Objects::nonNull); }) .collect(ImmutableMap.toImmutableMap(Entry::getKey, Entry::getValue)); })); } finally { span.finish(); } } }
ForwardingAnalysisImpl implements ForwardingAnalysis, Serializable { @VisibleForTesting static Map<String, Map<String, Map<Edge, Set<AbstractRoute>>>> computeRoutesWithNextHopIpArpTrue( Map<String, Map<String, Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>>>> nextHopInterfacesByNodeVrf, Topology topology, Map<String, Map<String, IpSpace>> arpReplies, Map<String, Map<String, Map<String, Set<AbstractRoute>>>> routesWithNextHop) { Span span = GlobalTracer.get() .buildSpan("ForwardingAnalysisImpl.computeRoutesWithNextHopIpArpTrue") .start(); try (Scope scope = GlobalTracer.get().scopeManager().activate(span)) { assert scope != null; return toImmutableMap( routesWithNextHop, Entry::getKey, nodeEntry -> toImmutableMap( nodeEntry.getValue(), Entry::getKey, vrfEntry -> { String hostname = nodeEntry.getKey(); String vrf = vrfEntry.getKey(); Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>> nextHopInterfaces = nextHopInterfacesByNodeVrf.get(hostname).get(vrf); return vrfEntry.getValue().entrySet().stream() .flatMap( ifaceEntry -> { String outInterface = ifaceEntry.getKey(); Set<AbstractRoute> candidateRoutes = ifaceEntry.getValue(); NodeInterfacePair out = NodeInterfacePair.of(hostname, outInterface); Set<NodeInterfacePair> receivers = topology.getNeighbors(out); return receivers.stream() .map( receiver -> { String recvNode = receiver.getHostname(); String recvInterface = receiver.getInterface(); IpSpace recvReplies = arpReplies.get(recvNode).get(recvInterface); Edge edge = new Edge(out, receiver); Set<AbstractRoute> routes = candidateRoutes.stream() .filter( route -> nextHopInterfaces.get(route) .get(outInterface) .keySet() .stream() .filter( ip -> !Route.UNSET_ROUTE_NEXT_HOP_IP .equals(ip)) .anyMatch( nextHopIp -> recvReplies.containsIp( nextHopIp, ImmutableMap.of()))) .collect(ImmutableSet.toImmutableSet()); return routes.isEmpty() ? null : Maps.immutableEntry(edge, routes); }) .filter(Objects::nonNull); }) .collect(ImmutableMap.toImmutableMap(Entry::getKey, Entry::getValue)); })); } finally { span.finish(); } } ForwardingAnalysisImpl(
      Map<String, Configuration> configurations,
      Map<String, Map<String, Fib>> fibs,
      Topology topology,
      Map<Location, LocationInfo> locationInfo); }
ForwardingAnalysisImpl implements ForwardingAnalysis, Serializable { @VisibleForTesting static Map<String, Map<String, Map<Edge, Set<AbstractRoute>>>> computeRoutesWithNextHopIpArpTrue( Map<String, Map<String, Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>>>> nextHopInterfacesByNodeVrf, Topology topology, Map<String, Map<String, IpSpace>> arpReplies, Map<String, Map<String, Map<String, Set<AbstractRoute>>>> routesWithNextHop) { Span span = GlobalTracer.get() .buildSpan("ForwardingAnalysisImpl.computeRoutesWithNextHopIpArpTrue") .start(); try (Scope scope = GlobalTracer.get().scopeManager().activate(span)) { assert scope != null; return toImmutableMap( routesWithNextHop, Entry::getKey, nodeEntry -> toImmutableMap( nodeEntry.getValue(), Entry::getKey, vrfEntry -> { String hostname = nodeEntry.getKey(); String vrf = vrfEntry.getKey(); Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>> nextHopInterfaces = nextHopInterfacesByNodeVrf.get(hostname).get(vrf); return vrfEntry.getValue().entrySet().stream() .flatMap( ifaceEntry -> { String outInterface = ifaceEntry.getKey(); Set<AbstractRoute> candidateRoutes = ifaceEntry.getValue(); NodeInterfacePair out = NodeInterfacePair.of(hostname, outInterface); Set<NodeInterfacePair> receivers = topology.getNeighbors(out); return receivers.stream() .map( receiver -> { String recvNode = receiver.getHostname(); String recvInterface = receiver.getInterface(); IpSpace recvReplies = arpReplies.get(recvNode).get(recvInterface); Edge edge = new Edge(out, receiver); Set<AbstractRoute> routes = candidateRoutes.stream() .filter( route -> nextHopInterfaces.get(route) .get(outInterface) .keySet() .stream() .filter( ip -> !Route.UNSET_ROUTE_NEXT_HOP_IP .equals(ip)) .anyMatch( nextHopIp -> recvReplies.containsIp( nextHopIp, ImmutableMap.of()))) .collect(ImmutableSet.toImmutableSet()); return routes.isEmpty() ? null : Maps.immutableEntry(edge, routes); }) .filter(Objects::nonNull); }) .collect(ImmutableMap.toImmutableMap(Entry::getKey, Entry::getValue)); })); } finally { span.finish(); } } ForwardingAnalysisImpl(
      Map<String, Configuration> configurations,
      Map<String, Map<String, Fib>> fibs,
      Topology topology,
      Map<Location, LocationInfo> locationInfo); @Nonnull @Override Map<String, Map<String, Map<String, IpSpace>>> getAcceptsIps(); @Override Map<String, Map<String, IpSpace>> getArpReplies(); @Override Map<String, Map<String, Map<Edge, IpSpace>>> getArpTrueEdge(); @Override Map<String, Map<String, Map<String, IpSpace>>> getNextVrfIps(); @Override Map<String, Map<String, IpSpace>> getNullRoutedIps(); @Override Map<String, Map<String, IpSpace>> getRoutableIps(); @Override Map<String, Map<String, Map<String, IpSpace>>> getDeliveredToSubnet(); @Override Map<String, Map<String, Map<String, IpSpace>>> getExitsNetwork(); @Override Map<String, Map<String, Map<String, IpSpace>>> getNeighborUnreachable(); @Override Map<String, Map<String, Map<String, IpSpace>>> getInsufficientInfo(); }
ForwardingAnalysisImpl implements ForwardingAnalysis, Serializable { @VisibleForTesting static Map<String, Map<String, Map<Edge, Set<AbstractRoute>>>> computeRoutesWithNextHopIpArpTrue( Map<String, Map<String, Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>>>> nextHopInterfacesByNodeVrf, Topology topology, Map<String, Map<String, IpSpace>> arpReplies, Map<String, Map<String, Map<String, Set<AbstractRoute>>>> routesWithNextHop) { Span span = GlobalTracer.get() .buildSpan("ForwardingAnalysisImpl.computeRoutesWithNextHopIpArpTrue") .start(); try (Scope scope = GlobalTracer.get().scopeManager().activate(span)) { assert scope != null; return toImmutableMap( routesWithNextHop, Entry::getKey, nodeEntry -> toImmutableMap( nodeEntry.getValue(), Entry::getKey, vrfEntry -> { String hostname = nodeEntry.getKey(); String vrf = vrfEntry.getKey(); Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>> nextHopInterfaces = nextHopInterfacesByNodeVrf.get(hostname).get(vrf); return vrfEntry.getValue().entrySet().stream() .flatMap( ifaceEntry -> { String outInterface = ifaceEntry.getKey(); Set<AbstractRoute> candidateRoutes = ifaceEntry.getValue(); NodeInterfacePair out = NodeInterfacePair.of(hostname, outInterface); Set<NodeInterfacePair> receivers = topology.getNeighbors(out); return receivers.stream() .map( receiver -> { String recvNode = receiver.getHostname(); String recvInterface = receiver.getInterface(); IpSpace recvReplies = arpReplies.get(recvNode).get(recvInterface); Edge edge = new Edge(out, receiver); Set<AbstractRoute> routes = candidateRoutes.stream() .filter( route -> nextHopInterfaces.get(route) .get(outInterface) .keySet() .stream() .filter( ip -> !Route.UNSET_ROUTE_NEXT_HOP_IP .equals(ip)) .anyMatch( nextHopIp -> recvReplies.containsIp( nextHopIp, ImmutableMap.of()))) .collect(ImmutableSet.toImmutableSet()); return routes.isEmpty() ? null : Maps.immutableEntry(edge, routes); }) .filter(Objects::nonNull); }) .collect(ImmutableMap.toImmutableMap(Entry::getKey, Entry::getValue)); })); } finally { span.finish(); } } ForwardingAnalysisImpl(
      Map<String, Configuration> configurations,
      Map<String, Map<String, Fib>> fibs,
      Topology topology,
      Map<Location, LocationInfo> locationInfo); @Nonnull @Override Map<String, Map<String, Map<String, IpSpace>>> getAcceptsIps(); @Override Map<String, Map<String, IpSpace>> getArpReplies(); @Override Map<String, Map<String, Map<Edge, IpSpace>>> getArpTrueEdge(); @Override Map<String, Map<String, Map<String, IpSpace>>> getNextVrfIps(); @Override Map<String, Map<String, IpSpace>> getNullRoutedIps(); @Override Map<String, Map<String, IpSpace>> getRoutableIps(); @Override Map<String, Map<String, Map<String, IpSpace>>> getDeliveredToSubnet(); @Override Map<String, Map<String, Map<String, IpSpace>>> getExitsNetwork(); @Override Map<String, Map<String, Map<String, IpSpace>>> getNeighborUnreachable(); @Override Map<String, Map<String, Map<String, IpSpace>>> getInsufficientInfo();  }