Avoid NPE for IPv6 external subnets 45/72145/4
authorSridhar Gaddam <sgaddam@redhat.com>
Sun, 20 May 2018 15:25:09 +0000 (20:55 +0530)
committerAswin Suryanarayanan <asuryana@redhat.com>
Fri, 15 Jun 2018 18:04:31 +0000 (18:04 +0000)
Currently when we create an IPv6 subnet in the external
network, we see couple of exceptions in Netvirt. This
patch avoids these exceptions. Support for IPv6 external
connectivity (for FLAT/VLAN based provider networks)
will be added via a separate patch.

Change-Id: I115d7b684ecf8bf6a5324ecdb4f9916583637e57
Signed-off-by: Sridhar Gaddam <sgaddam@redhat.com>
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/AbstractSnatService.java
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/ConntrackBasedSnatService.java
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatUtil.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnNatManager.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/CentralizedSwitchChangeListener.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnManagerImpl.java

index 6afb0ad1247e9f1ea37eefbda02b5df1f0b3ccbf..1c392c8a33c01e951e7d1e1ffd63acf432b4ac94 100644 (file)
@@ -24,6 +24,7 @@ import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MatchInfo;
 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
+import org.opendaylight.genius.mdsalutil.NWUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
 import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadMetadata;
@@ -147,24 +148,22 @@ public abstract class AbstractSnatService implements SnatServiceListener {
         String routerName = routers.getRouterName();
         Long routerId = NatUtil.getVpnId(dataBroker, routerName);
         installDefaultFibRouteForSNAT(dpnId, routerId, addOrRemove);
-        List<ExternalIps> externalIps = routers.getExternalIps();
-        if (externalIps.isEmpty()) {
-            LOG.error("AbstractSnatService: installSnatCommonEntriesForNaptSwitch no externalIP present"
-                    + " for routerId {}",
-                    routerId);
-            return;
-        }
-        //The logic now handle only one external IP per router, others if present will be ignored.
-        String externalIp = externalIps.get(0).getIpAddress();
         String externalGwMac = routers.getExtGwMacAddress();
-        Uuid externalSubnetId = externalIps.get(0).getSubnetId();
-        long extSubnetId = NatConstants.INVALID_ID;
-        if (addOrRemove == NwConstants.ADD_FLOW) {
-            extSubnetId = NatUtil.getExternalSubnetVpnId(dataBroker,externalSubnetId);
+        for (ExternalIps externalIp : routers.getExternalIps()) {
+            if (!NWUtil.isIpv4Address(externalIp.getIpAddress())) {
+                // In this class we handle only IPv4 use-cases.
+                continue;
+            }
+            //The logic now handle only one external IP per router, others if present will be ignored.
+            long extSubnetId = NatConstants.INVALID_ID;
+            if (addOrRemove == NwConstants.ADD_FLOW) {
+                extSubnetId = NatUtil.getExternalSubnetVpnId(dataBroker, externalIp.getSubnetId());
+            }
+            installInboundFibEntry(dpnId, externalIp.getIpAddress(), routerId, extSubnetId,
+                routers.getNetworkId().getValue(), externalIp.getSubnetId().getValue(), externalGwMac, addOrRemove);
+            installInboundTerminatingServiceTblEntry(dpnId, routerId, extSubnetId, addOrRemove);
+            break;
         }
-        installInboundFibEntry(dpnId, externalIp, routerId, extSubnetId, routers.getNetworkId()
-                .getValue(), externalSubnetId.getValue(), externalGwMac, addOrRemove);
-        installInboundTerminatingServiceTblEntry(dpnId, routerId, extSubnetId, addOrRemove);
     }
 
     protected void installSnatCommonEntriesForNonNaptSwitch(Routers routers, BigInteger primarySwitchId,
index 49e1f39c09471578a8785198a46458c21fd90bea..ac5dc3c7f6d02eacbe2e41b8477cc5b16b1a4340 100644 (file)
@@ -11,7 +11,6 @@ import com.google.common.base.Optional;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
-
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
@@ -20,6 +19,7 @@ import org.opendaylight.genius.mdsalutil.InstructionInfo;
 import org.opendaylight.genius.mdsalutil.MatchInfo;
 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
+import org.opendaylight.genius.mdsalutil.NWUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction;
@@ -37,7 +37,6 @@ import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchCtState;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnFootprintService;
 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.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
@@ -85,35 +84,33 @@ public abstract class ConntrackBasedSnatService extends AbstractSnatService {
 
         String extGwMacAddress = NatUtil.getExtGwMacAddFromRouterName(getDataBroker(), routerName);
         createOutboundTblTrackEntry(dpnId, routerId, extGwMacAddress, addOrRemove);
-        List<ExternalIps> externalIps = routers.getExternalIps();
-        if (externalIps.isEmpty()) {
-            LOG.error("AbstractSnatService: installSnatCommonEntriesForNaptSwitch no externalIP present"
-                    + " for routerId {}",
-                    routerId);
-            return;
-        }
-        //The logic now handle only one external IP per router, others if present will be ignored.
-        String externalIp = externalIps.get(0).getIpAddress();
-        Uuid externalSubnetId = externalIps.get(0).getSubnetId();
-        long extSubnetId = NatConstants.INVALID_ID;
-        if (addOrRemove == NwConstants.ADD_FLOW) {
-            extSubnetId = NatUtil.getExternalSubnetVpnId(getDataBroker(),externalSubnetId);
-        }
-        createOutboundTblEntry(dpnId, routerId, externalIp, elanId, extGwMacAddress, addOrRemove);
-        installNaptPfibFlow(routers, dpnId, routerId, extSubnetId, addOrRemove);
+        for (ExternalIps externalIp : routers.getExternalIps()) {
+            if (!NWUtil.isIpv4Address(externalIp.getIpAddress())) {
+                // In this class we handle only IPv4 use-cases.
+                continue;
+            }
+            //The logic now handle only one external IP per router, others if present will be ignored.
+            long extSubnetId = NatConstants.INVALID_ID;
+            if (addOrRemove == NwConstants.ADD_FLOW) {
+                extSubnetId = NatUtil.getExternalSubnetVpnId(getDataBroker(), externalIp.getSubnetId());
+            }
+            createOutboundTblEntry(dpnId, routerId, externalIp.getIpAddress(), elanId, extGwMacAddress, addOrRemove);
+            installNaptPfibFlow(routers, dpnId, routerId, extSubnetId, addOrRemove);
 
-        //Install Inbound NAT entries
-        installInboundEntry(dpnId, routerId, externalIp, elanId, extSubnetId, addOrRemove);
-        installNaptPfibEntry(dpnId, routerId, addOrRemove);
+            //Install Inbound NAT entries
+            installInboundEntry(dpnId, routerId, externalIp.getIpAddress(), elanId, extSubnetId, addOrRemove);
+            installNaptPfibEntry(dpnId, routerId, addOrRemove);
 
-        String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
-        Optional<Subnets> externalSubnet = NatUtil.getOptionalExternalSubnets(dataBroker, externalSubnetId);
-        if (externalSubnet.isPresent()) {
-            String externalVpn =  externalSubnetId.getValue();
-            String vpnRd = NatUtil.getVpnRd(dataBroker, externalVpn);
-            vpnFootprintService.updateVpnToDpnMapping(dpnId, externalVpn, vpnRd, null /* interfaceName*/,
-                new ImmutablePair<>(IpAddresses.IpAddressSource.ExternalFixedIP, fibExternalIp),
-                addOrRemove == NwConstants.ADD_FLOW);
+            String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp.getIpAddress());
+            Optional<Subnets> externalSubnet = NatUtil.getOptionalExternalSubnets(dataBroker, externalIp.getSubnetId());
+            if (externalSubnet.isPresent()) {
+                String externalVpn =  externalIp.getSubnetId().getValue();
+                String vpnRd = NatUtil.getVpnRd(dataBroker, externalVpn);
+                vpnFootprintService.updateVpnToDpnMapping(dpnId, externalVpn, vpnRd, null /* interfaceName*/,
+                        new ImmutablePair<>(IpAddresses.IpAddressSource.ExternalFixedIP, fibExternalIp),
+                        addOrRemove == NwConstants.ADD_FLOW);
+            }
+            break;
         }
     }
 
index 33e4e9c0dc7d036435aaf238d4cf068987516ac9..e99fad97509f4f0568a92c2c5b05a1903552c11b 100644 (file)
@@ -1462,6 +1462,10 @@ public final class NatUtil {
             return null;
         }
 
+        if (null != gatewayIp.getIpv6Address()) {
+            return null;
+        }
+
         InstanceIdentifier<VpnPortipToPort> portIpInst = InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
             .child(VpnPortipToPort.class, new VpnPortipToPortKey(gatewayIp.getIpv4Address().getValue(), vpnName))
             .build();
index 1c63f954a286856836a78dde690555598f36470f..21a32ca1aa6fd9af24b5d193e9f4c367f905ed72 100644 (file)
@@ -200,12 +200,12 @@ public class NeutronvpnNatManager implements AutoCloseable {
                         List<ExternalFixedIps> origExtFixedIps = origExtGw.getExternalFixedIps();
                         HashSet<String> origFixedIpSet = new HashSet<>();
                         for (ExternalFixedIps fixedIps : origExtFixedIps) {
-                            origFixedIpSet.add(fixedIps.getIpAddress().getIpv4Address().getValue());
+                            origFixedIpSet.add(String.valueOf(fixedIps.getIpAddress().getValue()));
                         }
                         List<ExternalFixedIps> newExtFixedIps = newExtGw.getExternalFixedIps();
                         HashSet<String> updFixedIpSet = new HashSet<>();
                         for (ExternalFixedIps fixedIps : newExtFixedIps) {
-                            updFixedIpSet.add(fixedIps.getIpAddress().getIpv4Address().getValue());
+                            updFixedIpSet.add(String.valueOf(fixedIps.getIpAddress().getValue()));
                         }
                         // returns true if external subnets have changed
                         return !origFixedIpSet.equals(updFixedIpSet) ? true : false;
@@ -756,7 +756,7 @@ public class NeutronvpnNatManager implements AutoCloseable {
 
     private void addExternalFixedIpToExternalIpsList(List<ExternalIps> externalIps, ExternalFixedIps fixedIps) {
         Uuid subnetId = fixedIps.getSubnetId();
-        String ip = fixedIps.getIpAddress().getIpv4Address().getValue();
+        String ip = String.valueOf(fixedIps.getIpAddress().getValue());
         ExternalIpsBuilder externalIpsBuilder = new ExternalIpsBuilder();
         externalIpsBuilder.withKey(new ExternalIpsKey(ip, subnetId));
         externalIpsBuilder.setIpAddress(ip);
index 18d1f3ca4f27a7c1ef97e78355b8d7817634fbb2..b491ad3deba54d41905e783fbb694fda2f0c019f 100644 (file)
@@ -130,21 +130,28 @@ public class CentralizedSwitchChangeListener
             LOG.error("CentralizedSwitchChangeListener: setupRouterGwFlows no externalIP present");
             return;
         }
-        Uuid subnetVpnName = externalIps.get(0).getSubnetId();
+
+        for (ExternalIps extIp: router.getExternalIps()) {
+            Uuid subnetVpnName = extIp.getSubnetId();
+            if (addOrRemove == NwConstants.ADD_FLOW) {
+                vpnManager.addRouterGwMacFlow(routerName, extGwMacAddress, primarySwitchId, extNetworkId,
+                        subnetVpnName.getValue(), writeTx);
+                externalRouterDataUtil.addtoRouterMap(router);
+            } else {
+                vpnManager.removeRouterGwMacFlow(routerName, extGwMacAddress, primarySwitchId, extNetworkId,
+                        subnetVpnName.getValue(), writeTx);
+                externalRouterDataUtil.removeFromRouterMap(router);
+            }
+        }
+
         if (addOrRemove == NwConstants.ADD_FLOW) {
-            vpnManager.addRouterGwMacFlow(routerName, extGwMacAddress, primarySwitchId, extNetworkId,
-                    subnetVpnName.getValue(), writeTx);
             vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
                     VpnUtil.getIpsListFromExternalIps(router.getExternalIps()),
                     extGwMacAddress, primarySwitchId, extNetworkId, writeTx);
-            externalRouterDataUtil.addtoRouterMap(router);
         } else {
-            vpnManager.removeRouterGwMacFlow(routerName, extGwMacAddress, primarySwitchId, extNetworkId,
-                    subnetVpnName.getValue(), writeTx);
             vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName,
                     VpnUtil.getIpsListFromExternalIps(router.getExternalIps()),
                     extGwMacAddress, primarySwitchId, extNetworkId);
-            externalRouterDataUtil.removeFromRouterMap(router);
         }
     }
 }
index c1479b17836753cc2310447b5a5d8bd59389d56e..447931e8bd89e6dbb825f8f4ec7cf777691e5d67 100644 (file)
@@ -44,6 +44,7 @@ import org.opendaylight.netvirt.elan.arp.responder.ArpResponderUtil;
 import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
+import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
@@ -563,6 +564,10 @@ public class VpnManagerImpl implements IVpnManager {
             ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
                 tx -> {
                     for (String fixedIp : fixedIps) {
+                        IpVersionChoice ipVersionChoice = VpnUtil.getIpVersionFromString(fixedIp);
+                        if (ipVersionChoice == IpVersionChoice.IPV6) {
+                            continue;
+                        }
                         installArpResponderFlowsToExternalNetworkIp(macAddress, dpnId, extInterfaceName, lportTag,
                                 fixedIp);
                     }
@@ -570,6 +575,10 @@ public class VpnManagerImpl implements IVpnManager {
             ListenableFutures.addErrorLogging(future, LOG, "Commit transaction");
         } else {
             for (String fixedIp : fixedIps) {
+                IpVersionChoice ipVersionChoice = VpnUtil.getIpVersionFromString(fixedIp);
+                if (ipVersionChoice == IpVersionChoice.IPV6) {
+                    continue;
+                }
                 installArpResponderFlowsToExternalNetworkIp(macAddress, dpnId, extInterfaceName, lportTag,
                         fixedIp);
             }