class ForwardingAnalysisImpl implements ForwardingAnalysis, Serializable {

  @VisibleForTesting
  static Map<String, Map<String, Map<Edge, IpSpace>>> computeArpTrueEdgeDestIp(
      Map<String, Map<String, Map<Prefix, IpSpace>>> matchingIps,
      Map<String, Map<String, Map<Edge, Set<AbstractRoute>>>> routesWithDestIpEdge,
      Map<String, Map<String, IpSpace>> arpReplies) {
    Span span =
        GlobalTracer.get().buildSpan("ForwardingAnalysisImpl.computeArpTrueEdgeDestIp").start();
    try (Scope scope = GlobalTracer.get().scopeManager().activate(span)) {
      assert scope != null; // avoid unused warning
      return toImmutableMap(
          routesWithDestIpEdge,
          Entry::getKey, // node
          nodeEntry ->
              toImmutableMap(
                  nodeEntry.getValue(),
                  Entry::getKey, // vrf
                  vrfEntry ->
                      toImmutableMap(
                          vrfEntry.getValue(),
                          Entry::getKey, // edge
                          edgeEntry -> {
                            Edge edge = edgeEntry.getKey();
                            Set<AbstractRoute> routes = edgeEntry.getValue();
                            String hostname = edge.getNode1();
                            String vrf = vrfEntry.getKey();
                            IpSpace dstIpMatchesSomeRoutePrefix =
                                computeRouteMatchConditions(
                                    routes, matchingIps.get(hostname).get(vrf));
                            String recvNode = edge.getNode2();
                            String recvInterface = edge.getInt2();
                            IpSpace recvReplies = arpReplies.get(recvNode).get(recvInterface);
                            return AclIpSpace.rejecting(dstIpMatchesSomeRoutePrefix.complement())
                                .thenPermitting(recvReplies)
                                .build();
                          })));
    } finally {
      span.finish();
    }
  }

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

}