Bug 4579 - Periodic ARP resolver is missing callback for MAC updates
[netvirt.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / openflow13 / services / arp / GatewayMacResolverService.java
index d6ce3d8b7c4a5700ae81c087b04db56e82866b43..3c1ab52410b9fa41b585e6789c154778cf0b6cec 100644 (file)
@@ -21,16 +21,14 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 
-import javax.annotation.Nullable;
-
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.ovsdb.openstack.netvirt.api.GatewayMacResolver;
+import org.opendaylight.ovsdb.openstack.netvirt.api.GatewayMacResolverListener;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.NetvirtProvidersProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
@@ -92,7 +90,7 @@ public class GatewayMacResolverService extends AbstractServiceInstance
                                         implements ConfigInterface, GatewayMacResolver,PacketProcessingListener {
 
     private static final Logger LOG = LoggerFactory.getLogger(GatewayMacResolverService.class);
-    private static final short TABEL_FOR_ARP_FLOW = 0;
+    private static final short TABLE_FOR_ARP_FLOW = 0;
     private static final String ARP_REPLY_TO_CONTROLLER_FLOW_NAME = "GatewayArpReplyRouter";
     private static final int ARP_REPLY_TO_CONTROLLER_FLOW_PRIORITY = 10000;
     private static final Instruction SEND_TO_CONTROLLER_INSTRUCTION;
@@ -100,11 +98,11 @@ public class GatewayMacResolverService extends AbstractServiceInstance
     private SalFlowService flowService;
     private final AtomicLong flowCookie = new AtomicLong();
     private final ConcurrentMap<Ipv4Address, ArpResolverMetadata> gatewayToArpMetadataMap =
-            new ConcurrentHashMap<Ipv4Address, ArpResolverMetadata>();
-    private final int ARP_WATCH_BROTHERS = 10;
-    private final int WAIT_CYCLES = 3;
-    private final int PER_CYCLE_WAIT_DURATION = 1000;
-    private final int REFRESH_INTERVAL = 10;
+            new ConcurrentHashMap<>();
+    private static final int ARP_WATCH_BROTHERS = 10;
+    private static final int WAIT_CYCLES = 3;
+    private static final int PER_CYCLE_WAIT_DURATION = 1000;
+    private static final int REFRESH_INTERVAL = 10;
     private final ListeningExecutorService arpWatcherWall = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(ARP_WATCH_BROTHERS));
     private final ScheduledExecutorService gatewayMacRefresherPool = Executors.newScheduledThreadPool(1);
     private final ScheduledExecutorService refreshRequester = Executors.newSingleThreadScheduledExecutor();
@@ -160,9 +158,9 @@ public class GatewayMacResolverService extends AbstractServiceInstance
                                     }
 
                                     LOG.debug("Refresh Gateway Mac for gateway {} using source ip {} and mac {} for ARP request",
-                                            gatewayIp.getValue(),gatewayMetaData.getArpRequestSourceIp().getValue(),gatewayMetaData.getArpRequestMacAddress().getValue());
+                                            gatewayIp.getValue(),gatewayMetaData.getArpRequestSourceIp().getValue(),gatewayMetaData.getArpRequestSourceMacAddress().getValue());
 
-                                    sendGatewayArpRequest(externalNetworkBridge,gatewayIp,gatewayMetaData.getArpRequestSourceIp(), gatewayMetaData.getArpRequestMacAddress());
+                                    sendGatewayArpRequest(externalNetworkBridge,gatewayIp,gatewayMetaData.getArpRequestSourceIp(), gatewayMetaData.getArpRequestSourceMacAddress());
                                 }
                             }, 1, TimeUnit.SECONDS);
                         }
@@ -183,12 +181,13 @@ public class GatewayMacResolverService extends AbstractServiceInstance
      * @param sourceMacAddress Source Mac address for the ARP request packet
      * @param periodicRefresh Enable/Disable periodic refresh of the Gateway Mac address
      * NOTE:Periodic refresh is not supported yet.
-     * @param gatewayIp  Resolve MAC address of this Gateway Ip
      * @return Future object
      */
     @Override
-    public ListenableFuture<MacAddress> resolveMacAddress( final Long externalNetworkBridgeDpid, final Ipv4Address gatewayIp,
-            final Ipv4Address sourceIpAddress, final MacAddress sourceMacAddress, final Boolean periodicRefresh){
+    public ListenableFuture<MacAddress> resolveMacAddress(
+            final GatewayMacResolverListener gatewayMacResolverListener, final Long externalNetworkBridgeDpid,
+            final Ipv4Address gatewayIp, final Ipv4Address sourceIpAddress, final MacAddress sourceMacAddress,
+            final Boolean periodicRefresh){
         Preconditions.checkNotNull(sourceIpAddress);
         Preconditions.checkNotNull(sourceMacAddress);
         Preconditions.checkNotNull(gatewayIp);
@@ -208,7 +207,7 @@ public class GatewayMacResolverService extends AbstractServiceInstance
                 });
             }
         }else{
-            gatewayToArpMetadataMap.put(gatewayIp,new ArpResolverMetadata(
+            gatewayToArpMetadataMap.put(gatewayIp,new ArpResolverMetadata(gatewayMacResolverListener,
                     externalNetworkBridgeDpid, gatewayIp,sourceIpAddress,sourceMacAddress,periodicRefresh));
         }
 
@@ -260,16 +259,24 @@ public class GatewayMacResolverService extends AbstractServiceInstance
                 }
                 LOG.debug("Flow to route ARP Reply to Controller installed successfully : {}", flowIid);
 
+                ArpResolverMetadata gatewayArpMetadata = gatewayToArpMetadataMap.get(gatewayIp);
+                if (gatewayArpMetadata == null) {
+                    LOG.warn("No metadata found for gatewayIp: {}", gatewayIp);
+                    return;
+                }
+
                 //cache metadata
-                gatewayToArpMetadataMap.get(gatewayIp).setFlowToRemove(
-                        new RemoveFlowInputBuilder(arpReplyToControllerFlow).setNode(nodeRef).build());
+                gatewayArpMetadata.setFlowToRemove(new RemoveFlowInputBuilder(arpReplyToControllerFlow).setNode(nodeRef).build());
+
+                //get MAC DA for ARP packets
+                MacAddress arpRequestDestMacAddress = gatewayArpMetadata.getArpRequestDestMacAddress();
 
-                //Broadcast ARP request packets
+                //Send ARP request packets
                 for (NodeConnector egressNc : externalNetworkBridge.getNodeConnector()) {
                     KeyedInstanceIdentifier<NodeConnector, NodeConnectorKey> egressNcIid = nodeIid.child(
                             NodeConnector.class, new NodeConnectorKey(egressNc.getId()));
                     ListenableFuture<RpcResult<Void>> futureSendArpResult = arpSender.sendArp(
-                            senderAddress, gatewayIp, egressNcIid);
+                            senderAddress, gatewayIp, arpRequestDestMacAddress, egressNcIid);
                     Futures.addCallback(futureSendArpResult, logResult(gatewayIp, egressNcIid));
                 }
             }
@@ -305,17 +312,10 @@ public class GatewayMacResolverService extends AbstractServiceInstance
         });
     }
 
-    private static @Nullable Ipv4Address getIPv4Addresses(IpAddress ipAddress) {
-        if (ipAddress.getIpv4Address() == null) {
-            return null;
-        }
-        return ipAddress.getIpv4Address();
-    }
-
     private Flow createArpReplyToControllerFlow(final ArpMessageAddress senderAddress, final Ipv4Address ipForRequestedMac) {
         checkNotNull(senderAddress);
         checkNotNull(ipForRequestedMac);
-        FlowBuilder arpFlow = new FlowBuilder().setTableId(TABEL_FOR_ARP_FLOW)
+        FlowBuilder arpFlow = new FlowBuilder().setTableId(TABLE_FOR_ARP_FLOW)
             .setFlowName(ARP_REPLY_TO_CONTROLLER_FLOW_NAME)
             .setPriority(ARP_REPLY_TO_CONTROLLER_FLOW_PRIORITY)
             .setBufferId(OFConstants.OFP_NO_BUFFER)
@@ -330,11 +330,11 @@ public class GatewayMacResolverService extends AbstractServiceInstance
         arpFlow.setMatch(match);
         arpFlow.setInstructions(new InstructionsBuilder().setInstruction(
                 ImmutableList.of(SEND_TO_CONTROLLER_INSTRUCTION)).build());
-        arpFlow.setId(createFlowId(senderAddress, ipForRequestedMac));
+        arpFlow.setId(createFlowId(ipForRequestedMac));
         return arpFlow.build();
     }
 
-    private FlowId createFlowId(ArpMessageAddress senderAddress, Ipv4Address ipForRequestedMac) {
+    private FlowId createFlowId(Ipv4Address ipForRequestedMac) {
         String flowId = ARP_REPLY_TO_CONTROLLER_FLOW_NAME + "|" + ipForRequestedMac.getValue();
         return new FlowId(flowId);
     }