MRI version bumpup for Aluminium
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / VpnSubnetRouteHandler.java
index 366e3edddb6c33eb0ba24fde7f695667555d4b9c..ac6076b6317b39880c1419ff723776f7f78050dd 100644 (file)
@@ -7,7 +7,6 @@
  */
 package org.opendaylight.netvirt.vpnmanager;
 
-import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -16,14 +15,16 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
 import javax.inject.Inject;
 import javax.inject.Singleton;
+import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
@@ -46,6 +47,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.sub
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpnKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
@@ -63,6 +65,7 @@ import org.slf4j.LoggerFactory;
 public class VpnSubnetRouteHandler {
     private static final Logger LOG = LoggerFactory.getLogger(VpnSubnetRouteHandler.class);
     private static final String LOGGING_PREFIX = "SUBNETROUTE:";
+    private static final String VPN_EVENT_SOURCE_SUBNET_ROUTE = "vpnSubnetRouteEvent";
     private final DataBroker dataBroker;
     private final SubnetOpDpnManager subOpDpnManager;
     private final IBgpManager bgpManager;
@@ -107,7 +110,7 @@ public class VpnSubnetRouteHandler {
         }
         String vpnName = subnetmap.getVpnId().getValue();
         Uint32 vpnId = waitAndGetVpnIdIfInvalid(vpnName);
-        if (vpnId.longValue() == VpnConstants.INVALID_ID) {
+        if (VpnConstants.INVALID_ID.equals(vpnId)) {
             LOG.error(
                     "{} onSubnetAddedToVpn: VpnInstance to VPNId mapping not yet available for VpnName {} "
                             + "processing subnet {} with IP {}, bailing out now.",
@@ -180,7 +183,7 @@ public class VpnSubnetRouteHandler {
             subOpBuilder.setSubnetToDpn(new ArrayList<>());
             subOpBuilder.setRouteAdvState(TaskState.Idle);
             subOpBuilder.setElanTag(elanTag);
-            Long l3Vni = vpnInstanceOpData.getL3vni().toJava();
+            Long l3Vni = vpnInstanceOpData.getL3vni() != null ? vpnInstanceOpData.getL3vni().toJava() : 0L;
             subOpBuilder.setL3vni(l3Vni);
             subOpEntry = subOpBuilder.build();
             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier,
@@ -196,7 +199,7 @@ public class VpnSubnetRouteHandler {
             LOG.error("{} onSubnetAddedToVpn: Unable to handle subnet {} with ip {} added to vpn {}", LOGGING_PREFIX,
                     subnetId.getValue(), subnetIp, vpnName, e);
             return;
-        } catch (ReadFailedException e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("{} onSubnetAddedToVpn: Failed to read data store for subnet {} ip {} vpn {}", LOGGING_PREFIX,
                     subnetId, subnetIp, vpnName);
             return;
@@ -266,7 +269,7 @@ public class VpnSubnetRouteHandler {
         } catch (RuntimeException e) {
             LOG.error("{} onSubnetAddedToVpn: Unable to handle subnet {} with ip {} added to vpn {}", LOGGING_PREFIX,
                     subnetId.getValue(), subnetIp, vpnName, e);
-        } catch (ReadFailedException e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("{} onSubnetAddedToVpn: Failed to read data store for subnet {} ip {} vpn {}", LOGGING_PREFIX,
                     subnetId, subnetIp, vpnName);
         } catch (TransactionCommitFailedException ex) {
@@ -279,7 +282,7 @@ public class VpnSubnetRouteHandler {
 
     private Uint32 waitAndGetVpnIdIfInvalid(String vpnName) {
         Uint32 vpnId = vpnUtil.getVpnId(vpnName);
-        if (vpnId.longValue() == VpnConstants.INVALID_ID) {
+        if (VpnConstants.INVALID_ID.equals(vpnId)) {
             LOG.debug("VpnId is invalid, waiting to fetch again: vpnName={}, vpnId={}", vpnName, vpnId);
             vpnOpDataSyncer.waitForVpnDataReady(VpnOpDataType.vpnInstanceToId, vpnName,
                     VpnConstants.PER_VPN_INSTANCE_MAX_WAIT_TIME_IN_MILLISECONDS);
@@ -376,7 +379,7 @@ public class VpnSubnetRouteHandler {
             LOG.error("{} onSubnetDeletedFromVpn: Removal of SubnetOpDataEntry for subnet {} subnetIp {}"
                             + " vpnId {} failed", LOGGING_PREFIX, subnetId.getValue(), subnetmap.getSubnetIp(),
                     subnetmap.getVpnId(), ex);
-        } catch (ReadFailedException e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("{} onSubnetDeletedFromVpn: Failed to read data store for subnet {} ip {} vpn {}",
                     LOGGING_PREFIX, subnetId, subnetmap.getSubnetIp(), subnetmap.getVpnId());
         } finally {
@@ -409,7 +412,7 @@ public class VpnSubnetRouteHandler {
             }
             LOG.info("{} onSubnetUpdatedInVpn: subnet {} with Ip {} updated successfully for vpn {}", LOGGING_PREFIX,
                     subnetId.getValue(), subnetIp, vpnName);
-        } catch (ReadFailedException e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("onSubnetUpdatedInVpn: Failed to read data store for subnet{} ip {} elanTag {} vpn {}",subnetId,
                     subnetIp, elanTag, vpnName);
         }
@@ -482,9 +485,8 @@ public class VpnSubnetRouteHandler {
             }
             SubnetOpDataEntry subnetOpDataEntry = optionalSubs.get();
             SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(subnetOpDataEntry);
-            List<SubnetToDpn> subDpnList = subOpBuilder.getSubnetToDpn();
-            subDpnList.add(subDpn);
-            subOpBuilder.setSubnetToDpn(subDpnList);
+            subOpBuilder.setSubnetToDpn(concat(new ArrayList<SubnetToDpn>(subnetOpDataEntry.getSubnetToDpn().values()),
+                    subDpn));
             if (subOpBuilder.getRouteAdvState() != TaskState.Advertised) {
                 if (subOpBuilder.getNhDpnId() == null) {
                     // No nexthop selected yet, elect one now
@@ -505,7 +507,7 @@ public class VpnSubnetRouteHandler {
         } catch (RuntimeException e) { //TODO: Avoid this
             LOG.error("{} onPortAddedToSubnet: Unable to handle port {} added to subnet {}", LOGGING_PREFIX,
                     portId.getValue(), subnetId.getValue(), e);
-        } catch (ReadFailedException e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("{} onPortAddedToSubnet: Failed to read data store for port {} subnet {}", LOGGING_PREFIX,
                     portId, subnetId);
         } catch (TransactionCommitFailedException e) {
@@ -574,7 +576,7 @@ public class VpnSubnetRouteHandler {
         } catch (RuntimeException e) {
             LOG.error("{} onPortRemovedFromSubnet: Unable to handle port {} removed from subnet {}", LOGGING_PREFIX,
                     portId.getValue(), subnetId.getValue(), e);
-        } catch (ReadFailedException e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("{} onPortRemovedFromSubnet: Failed to read data store for port {} subnet {}", LOGGING_PREFIX,
                     portId, subnetId);
         } catch (TransactionCommitFailedException e) {
@@ -620,9 +622,8 @@ public class VpnSubnetRouteHandler {
                     subOpBuilder.getRouteAdvState(), subOpBuilder.getLastAdvState());
             boolean isExternalSubnetVpn = VpnUtil.isExternalSubnetVpn(subnetOpDataEntry.getVpnName(),
                     subnetId.getValue());
-            List<SubnetToDpn> subDpnList = subOpBuilder.getSubnetToDpn();
-            subDpnList.add(subDpn);
-            subOpBuilder.setSubnetToDpn(subDpnList);
+            subOpBuilder.setSubnetToDpn(concat(new ArrayList<SubnetToDpn>(subnetOpDataEntry.getSubnetToDpn().values()),
+                    subDpn));
             if (subOpBuilder.getRouteAdvState() != TaskState.Advertised) {
                 if (subOpBuilder.getNhDpnId() == null) {
                     // No nexthop selected yet, elect one now
@@ -643,7 +644,7 @@ public class VpnSubnetRouteHandler {
         } catch (RuntimeException e) {
             LOG.error("{} onInterfaceUp: Unable to handle interface up event for port {} in subnet {}",
                     LOGGING_PREFIX, intfName, subnetId.getValue(), e);
-        } catch (ReadFailedException e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("{} onInterfaceUp: Failed to read data store for interface {} dpn {} subnet {}", LOGGING_PREFIX,
                     intfName, dpnId, subnetId);
         } catch (TransactionCommitFailedException e) {
@@ -704,7 +705,7 @@ public class VpnSubnetRouteHandler {
         } catch (RuntimeException e) { //TODO: Remove RuntimeException
             LOG.error("{} onInterfaceDown: Unable to handle interface down event for port {} in subnet {}",
                     LOGGING_PREFIX, interfaceName, subnetId.getValue(), e);
-        } catch (ReadFailedException e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("{} onInterfaceDown: Failed to read data store for interface {} dpn {} subnet {}",
                     LOGGING_PREFIX, interfaceName, dpnId, subnetId.getValue(), e);
         } catch (TransactionCommitFailedException ex) {
@@ -764,7 +765,7 @@ public class VpnSubnetRouteHandler {
         } catch (TransactionCommitFailedException ex) {
             LOG.error("{} updateSubnetRouteOnTunnelUpEvent: Failed to update subnetRoute for subnet {} on dpn {}",
                     LOGGING_PREFIX, subnetId.getValue(), dpnId.toString(), ex);
-        } catch (ReadFailedException e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("{} updateSubnetRouteOnTunnelUpEvent: Failed to read data store for subnet {} on dpn {}",
                     LOGGING_PREFIX, subnetId.getValue(), dpnId.toString(), e);
         }
@@ -812,7 +813,7 @@ public class VpnSubnetRouteHandler {
         } catch (RuntimeException e) {
             LOG.error("{} updateSubnetRouteOnTunnelDownEvent: Unable to handle tunnel down event for subnetId {}"
                     + " dpnId {}", LOGGING_PREFIX, subnetId.getValue(), dpnId.toString(), e);
-        } catch (ReadFailedException e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("{} Failed to read data store for subnet {} dpn {}", LOGGING_PREFIX, subnetId, dpnId);
         } catch (TransactionCommitFailedException e) {
             LOG.error("{} updateSubnetRouteOnTunnelDownEvent: Updation of SubnetOpDataEntry for subnet {}"
@@ -835,6 +836,11 @@ public class VpnSubnetRouteHandler {
                 l3vni = subOpBuilder.getL3vni();
             } else {
                 label = subOpBuilder.getLabel();
+                if (label.longValue() == VpnConstants.INVALID_LABEL) {
+                    LOG.error("publishSubnetRouteToBgp: Label not found for rd {}, subnetIp {}",
+                            subOpBuilder.getVrfId(), subOpBuilder.getSubnetCidr());
+                    return;
+                }
             }
             bgpManager.advertisePrefix(subOpBuilder.getVrfId(), null /*macAddress*/, subOpBuilder.getSubnetCidr(),
                     Arrays.asList(nextHopIp), encapType,  label, l3vni,
@@ -931,11 +937,11 @@ public class VpnSubnetRouteHandler {
     }
 
     public void deleteSubnetRouteFibEntryFromDS(String rd, String prefix, String vpnName) {
-        fibManager.removeFibEntry(rd, prefix, null);
+        fibManager.removeFibEntry(rd, prefix, VPN_EVENT_SOURCE_SUBNET_ROUTE, null);
         List<VpnInstanceOpDataEntry> vpnsToImportRoute = vpnUtil.getVpnsImportingMyRoute(vpnName);
         for (VpnInstanceOpDataEntry vpnInstance : vpnsToImportRoute) {
             String importingRd = vpnInstance.getVrfId();
-            fibManager.removeFibEntry(importingRd, prefix, null);
+            fibManager.removeFibEntry(importingRd, prefix, VPN_EVENT_SOURCE_SUBNET_ROUTE, null);
             LOG.info("SUBNETROUTE: deleteSubnetRouteFibEntryFromDS: Deleted imported subnet route rd {} prefix {}"
                     + " from vpn {} importingRd {}", rd, prefix, vpnInstance.getVpnInstanceName(), importingRd);
         }
@@ -947,9 +953,7 @@ public class VpnSubnetRouteHandler {
     @SuppressWarnings("checkstyle:IllegalCatch")
     private void electNewDpnForSubnetRoute(SubnetOpDataEntryBuilder subOpBuilder, @Nullable Uint64 oldDpnId,
                                            Uuid subnetId, Uuid networkId, boolean isBgpVpn) {
-        List<SubnetToDpn> subDpnList = null;
         boolean isRouteAdvertised = false;
-        subDpnList = subOpBuilder.getSubnetToDpn();
         String rd = subOpBuilder.getVrfId();
         String subnetIp = subOpBuilder.getSubnetCidr();
         String vpnName = subOpBuilder.getVpnName();
@@ -987,24 +991,27 @@ public class VpnSubnetRouteHandler {
 
         String nhTepIp = null;
         Uint64 nhDpnId = null;
-        for (SubnetToDpn subnetToDpn : subDpnList) {
-            if (subnetToDpn.getDpnId().equals(oldDpnId)) {
-                // Is this same is as input dpnId, then ignore it
-                continue;
-            }
-            nhDpnId = subnetToDpn.getDpnId();
-            if (vpnNodeListener.isConnectedNode(nhDpnId)) {
-                // selected dpnId is connected to ODL
-                // but does it have a TEP configured at all?
-                try {
-                    nhTepIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, nhDpnId);
-                    if (nhTepIp != null) {
-                        isAlternateDpnSelected = true;
-                        break;
+        Map<SubnetToDpnKey, SubnetToDpn> toDpnKeySubnetToDpnMap = subOpBuilder.getSubnetToDpn();
+        if (toDpnKeySubnetToDpnMap != null) {
+            for (SubnetToDpn subnetToDpn : toDpnKeySubnetToDpnMap.values()) {
+                if (subnetToDpn.getDpnId().equals(oldDpnId)) {
+                    // Is this same is as input dpnId, then ignore it
+                    continue;
+                }
+                nhDpnId = subnetToDpn.getDpnId();
+                if (vpnNodeListener.isConnectedNode(nhDpnId)) {
+                    // selected dpnId is connected to ODL
+                    // but does it have a TEP configured at all?
+                    try {
+                        nhTepIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, nhDpnId);
+                        if (nhTepIp != null) {
+                            isAlternateDpnSelected = true;
+                            break;
+                        }
+                    } catch (Exception e) {
+                        LOG.warn("{} electNewDpnForSubnetRoute: Unable to find TepIp for rd {} subnetroute subnetip {}"
+                                + " for dpnid {}, attempt next", LOGGING_PREFIX, rd, subnetIp, nhDpnId.toString(), e);
                     }
-                } catch (Exception e) {
-                    LOG.warn("{} electNewDpnForSubnetRoute: Unable to find TepIp for rd {} subnetroute subnetip {}"
-                            + " for dpnid {}, attempt next", LOGGING_PREFIX, rd, subnetIp, nhDpnId.toString(), e);
                 }
             }
         }
@@ -1050,9 +1057,18 @@ public class VpnSubnetRouteHandler {
         }
     }
 
-    private boolean isRouteAdvertised(SubnetOpDataEntryBuilder subOpBuilder) {
+    private static boolean isRouteAdvertised(SubnetOpDataEntryBuilder subOpBuilder) {
         return subOpBuilder.getRouteAdvState() == TaskState.Advertised
                 || subOpBuilder.getRouteAdvState() == TaskState.PendingAdvertise;
     }
+
+    private static @NonNull List<SubnetToDpn> concat(@Nullable List<SubnetToDpn> list, @NonNull SubnetToDpn entry) {
+        final List<SubnetToDpn> ret = new ArrayList<>();
+        if (list != null) {
+            ret.addAll(list);
+        }
+        ret.add(entry);
+        return ret;
+    }
 }