@Override
 public void onPacketReceived(PacketReceived potentialArp) {
   Arp arp = ArpResolverUtils.getArpFrom(potentialArp);
   if (arp != null) {
     if (arp.getOperation() != ArpOperation.REPLY.intValue()) {
       LOG.trace("Packet is not ARP REPLY packet.");
       return;
     }
     if (LOG.isTraceEnabled()) {
       LOG.trace("ARP REPLY received - {}", ArpUtils.getArpToStringFormat(arp));
     }
     NodeKey nodeKey = potentialArp.getIngress().getValue().firstKeyOf(Node.class, NodeKey.class);
     if (nodeKey == null) {
       LOG.info("Unknown source node of ARP packet: {}", potentialArp);
       return;
     }
     Ipv4Address gatewayIpAddress = ArpUtils.bytesToIp(arp.getSenderProtocolAddress());
     MacAddress gatewayMacAddress = ArpUtils.bytesToMac(arp.getSenderHardwareAddress());
     ArpResolverMetadata candidateGatewayIp = gatewayToArpMetadataMap.get(gatewayIpAddress);
     if (candidateGatewayIp != null) {
       LOG.debug(
           "Resolved MAC for Gateway Ip {} is {}",
           gatewayIpAddress.getValue(),
           gatewayMacAddress.getValue());
       candidateGatewayIp.setGatewayMacAddress(gatewayMacAddress);
       resetFlowToRemove(gatewayIpAddress, candidateGatewayIp);
     }
   }
 }
  /**
   * Method do following actions: 1. Install flow to direct ARP response packet to controller 2.
   * Send ARP request packet out on all port of the given External network bridge. 3. Cache the flow
   * that need to be removed once ARP resolution is done. 4. Return listenable future so that user
   * can add callback to get the MacAddress
   *
   * @param externalNetworkBridgeDpid Broadcast ARP request packet on this bridge
   * @param gatewayIp IP address for which MAC need to be resolved
   * @param sourceIpAddress Source Ip address for the ARP request packet
   * @param sourceMacAddress Source Mac address for the ARP request packet
   * @param periodicRefresh Enable/Disable periodic refresh of the Gateway Mac address
   * @return Future object
   */
  @Override
  public ListenableFuture<MacAddress> resolveMacAddress(
      final GatewayMacResolverListener gatewayMacResolverListener,
      final Long externalNetworkBridgeDpid,
      final Boolean refreshExternalNetworkBridgeDpidIfNeeded,
      final Ipv4Address gatewayIp,
      final Ipv4Address sourceIpAddress,
      final MacAddress sourceMacAddress,
      final Boolean periodicRefresh) {
    Preconditions.checkNotNull(refreshExternalNetworkBridgeDpidIfNeeded);
    Preconditions.checkNotNull(sourceIpAddress);
    Preconditions.checkNotNull(sourceMacAddress);
    Preconditions.checkNotNull(gatewayIp);

    LOG.info(
        "Trigger Mac resolution for gateway {}, using source ip {} and mac {}",
        gatewayIp.getValue(),
        sourceIpAddress.getValue(),
        sourceMacAddress.getValue());

    init();
    if (gatewayToArpMetadataMap.containsKey(gatewayIp)) {
      if (gatewayToArpMetadataMap.get(gatewayIp).getGatewayMacAddress() != null) {
        return arpWatcherWall.submit(
            new Callable<MacAddress>() {

              @Override
              public MacAddress call() throws Exception {
                return gatewayToArpMetadataMap.get(gatewayIp).getGatewayMacAddress();
              }
            });
      }
    } else {
      gatewayToArpMetadataMap.put(
          gatewayIp,
          new ArpResolverMetadata(
              gatewayMacResolverListener,
              externalNetworkBridgeDpid,
              refreshExternalNetworkBridgeDpidIfNeeded,
              gatewayIp,
              sourceIpAddress,
              sourceMacAddress,
              periodicRefresh));
    }

    final Node externalNetworkBridge = getExternalBridge(externalNetworkBridgeDpid);
    if (externalNetworkBridge == null) {
      if (!refreshExternalNetworkBridgeDpidIfNeeded) {
        LOG.error(
            "MAC address for gateway {} can not be resolved, because external bridge {} "
                + "is not connected to controller.",
            gatewayIp.getValue(),
            externalNetworkBridgeDpid);
      } else {
        LOG.debug(
            "MAC address for gateway {} can not be resolved, since dpid was not refreshed yet",
            gatewayIp.getValue());
      }
      return null;
    }

    sendGatewayArpRequest(externalNetworkBridge, gatewayIp, sourceIpAddress, sourceMacAddress);

    // Wait for MacAddress population in cache
    return waitForMacAddress(gatewayIp);
  }