class ForwardingAnalysisImpl implements ForwardingAnalysis, Serializable {

  @VisibleForTesting
  static Map<String, Map<String, Map<String, Set<AbstractRoute>>>>
      computeRoutesWhereDstIpCanBeArpIp(
          Map<String, Map<String, Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>>>>
              nextHopInterfacesByNodeVrf,
          Map<String, Map<String, Map<String, Set<AbstractRoute>>>> routesWithNextHop) {
    Span span = GlobalTracer.get().buildSpan("construct BDDFlowConstraintGenerator").start();
    try (Scope scope = GlobalTracer.get().scopeManager().activate(span)) {
      assert scope != null; // avoid unused warning
      return toImmutableMap(
          routesWithNextHop,
          Entry::getKey /* hostname */,
          nodeEntry -> {
            String hostname = nodeEntry.getKey();
            return toImmutableMap(
                nodeEntry.getValue(),
                Entry::getKey /* vrf */,
                vrfEntry -> {
                  String vrf = vrfEntry.getKey();
                  Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>> nextHopInterfaces =
                      nextHopInterfacesByNodeVrf.get(hostname).get(vrf);
                  return toImmutableMap(
                      vrfEntry.getValue(),
                      Entry::getKey /* interface */,
                      ifaceEntry -> {
                        String iface = ifaceEntry.getKey();
                        // return a set of routes where each route has
                        // some final next hop ip unset
                        return ifaceEntry.getValue() // routes with this interface as
                            // outgoing interfaces
                            .stream()
                            .filter(
                                route ->
                                    nextHopInterfaces
                                        .get(route)
                                        .get(iface) // final next hop ips
                                        .containsKey(Route.UNSET_ROUTE_NEXT_HOP_IP))
                            .collect(ImmutableSet.toImmutableSet());
                      });
                });
          });
    } finally {
      span.finish();
    }
  }

  public  ForwardingAnalysisImpl(
      Map<String, Configuration> configurations,
      Map<String, Map<String, Fib>> fibs,
      Topology topology,
      Map<Location, LocationInfo> locationInfo);

}