@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); }