MRI version bumpup for Aluminium
[netvirt.git] / neutronvpn / impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronSubnetGwMacResolver.java
index 3f9ee75d05e464e3ea2f3e950856374a9a15bfa5..35ace8967349b7a26141781ce4bb17ece790fd5c 100644 (file)
@@ -10,23 +10,27 @@ package org.opendaylight.netvirt.neutronvpn;
 
 import com.google.common.util.concurrent.JdkFutureAdapters;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import java.math.BigInteger;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
-import javax.annotation.Nullable;
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.genius.arputil.api.ArpConstants;
+import org.opendaylight.genius.mdsalutil.NWUtil;
 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.vpnmanager.api.ICentralizedSwitchProvider;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
@@ -35,11 +39,18 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.Se
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6.nd.util.rev170210.Ipv6NdUtilService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6.nd.util.rev170210.SendNeighborSolicitationInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6.nd.util.rev170210.SendNeighborSolicitationInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6.nd.util.rev170210.SendNeighborSolicitationOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router.ExternalGatewayInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.Uint64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -48,23 +59,23 @@ public class NeutronSubnetGwMacResolver {
     private static final Logger LOG = LoggerFactory.getLogger(NeutronSubnetGwMacResolver.class);
     private static final long L3_INSTALL_DELAY_MILLIS = 5000;
 
-    private final DataBroker broker;
     private final OdlArputilService arpUtilService;
     private final IElanService elanService;
     private final ICentralizedSwitchProvider cswitchProvider;
     private final NeutronvpnUtils neutronvpnUtils;
     private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(
             new ThreadFactoryBuilder().setNameFormat("Gw-Mac-Res").build());
+    private final Ipv6NdUtilService ipv6NdUtilService;
 
     @Inject
-    public NeutronSubnetGwMacResolver(final DataBroker broker,
-            final OdlArputilService arputilService, final IElanService elanService,
-            final ICentralizedSwitchProvider cswitchProvider, final NeutronvpnUtils neutronvpnUtils) {
-        this.broker = broker;
+    public NeutronSubnetGwMacResolver(final OdlArputilService arputilService, final IElanService elanService,
+            final ICentralizedSwitchProvider cswitchProvider, final NeutronvpnUtils neutronvpnUtils,
+            final Ipv6NdUtilService ipv6NdUtilService) {
         this.arpUtilService = arputilService;
         this.elanService = elanService;
         this.cswitchProvider = cswitchProvider;
         this.neutronvpnUtils = neutronvpnUtils;
+        this.ipv6NdUtilService = ipv6NdUtilService;
     }
 
     // TODO Clean up the exception handling
@@ -117,8 +128,8 @@ public class NeutronSubnetGwMacResolver {
             return;
         }
 
-        List<FixedIps> fixedIps = extPort.getFixedIps();
-        if (fixedIps == null || fixedIps.isEmpty()) {
+        Map<FixedIpsKey, FixedIps> keyFixedIpsMap = extPort.getFixedIps();
+        if (keyFixedIpsMap == null || keyFixedIpsMap.isEmpty()) {
             LOG.trace("External GW port {} for router {} has no fixed IPs", extPort.getUuid().getValue(),
                     router.getUuid().getValue());
             return;
@@ -131,11 +142,18 @@ public class NeutronSubnetGwMacResolver {
             return;
         }
 
-        for (FixedIps fixIp : fixedIps) {
+        for (FixedIps fixIp : keyFixedIpsMap.values()) {
             Uuid subnetId = fixIp.getSubnetId();
             IpAddress srcIpAddress = fixIp.getIpAddress();
             IpAddress dstIpAddress = getExternalGwIpAddress(subnetId);
-            sendArpRequest(srcIpAddress, dstIpAddress, macAddress, extInterface);
+            String srcIpAddressString = srcIpAddress.stringValue();
+            String dstIpAddressString = dstIpAddress.stringValue();
+            if (NWUtil.isIpv4Address(srcIpAddressString)) {
+                sendArpRequest(srcIpAddress, dstIpAddress, macAddress, extInterface);
+            } else {
+                sendNeighborSolication(new Ipv6Address(srcIpAddressString),macAddress,
+                        new Ipv6Address(dstIpAddressString), extInterface);
+            }
         }
 
     }
@@ -165,6 +183,31 @@ public class NeutronSubnetGwMacResolver {
         }
     }
 
+    private void sendNeighborSolication(Ipv6Address srcIpv6Address,
+            MacAddress srcMac, Ipv6Address dstIpv6Address, String interfaceName) {
+        List<org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6
+            .nd.util.rev170210.interfaces.InterfaceAddress> interfaceAddresses = new ArrayList<>();
+        interfaceAddresses.add(new org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6
+                .nd.util.rev170210.interfaces.InterfaceAddressBuilder()
+            .setInterface(interfaceName)
+            .setSrcIpAddress(srcIpv6Address)
+            .setSrcMacAddress(new PhysAddress(srcMac.getValue())).build());
+        SendNeighborSolicitationInput input = new SendNeighborSolicitationInputBuilder()
+                .setInterfaceAddress(interfaceAddresses).setTargetIpAddress(dstIpv6Address)
+                .build();
+        try {
+            Future<RpcResult<SendNeighborSolicitationOutput>> result = ipv6NdUtilService
+                    .sendNeighborSolicitation(input);
+            RpcResult<SendNeighborSolicitationOutput> rpcResult = result.get();
+            if (!rpcResult.isSuccessful()) {
+                LOG.error("sendNeighborSolicitationToOfGroup: RPC Call failed for input={} and Errors={}", input,
+                        rpcResult.getErrors());
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Failed to send NS packet to ELAN group, input={}", input, e);
+        }
+    }
+
     @Nullable
     private Port getRouterExtGatewayPort(Router router) {
         if (router == null) {
@@ -196,8 +239,8 @@ public class NeutronSubnetGwMacResolver {
             return null;
         }
 
-        BigInteger primarySwitch = cswitchProvider.getPrimarySwitchForRouter(routerName);
-        if (primarySwitch == null || BigInteger.ZERO.equals(primarySwitch)) {
+        Uint64 primarySwitch = cswitchProvider.getPrimarySwitchForRouter(routerName);
+        if (primarySwitch == null || Uint64.ZERO.equals(primarySwitch)) {
             LOG.warn("Primary switch has not been allocated for router {}", routerName);
             return null;
         }