NETVIRT-1037: Upstream Fixes --- Review-1.
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / TunnelInterfaceStateListener.java
index 5846bb3e742fea2999f1642fcd9f1a217dad9bb1..4ad3998ab2ee14d0831d96c1d42be4ce484b07c2 100644 (file)
@@ -16,11 +16,16 @@ import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.Future;
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Singleton;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -29,9 +34,11 @@ import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
+import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
-import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
+import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
 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.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
@@ -52,17 +59,19 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGate
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.extraroute.rds.map.extraroute.rds.DestPrefixes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+@Singleton
 public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBase<StateTunnelList,
         TunnelInterfaceStateListener> {
     private static final Logger LOG = LoggerFactory.getLogger(TunnelInterfaceStateListener.class);
@@ -86,6 +95,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
     /**
      * Responsible for listening to tunnel interface state change.
      */
+    @Inject
     public TunnelInterfaceStateListener(final DataBroker dataBroker,
         final IFibManager fibManager,
         final OdlInterfaceRpcService ifaceMgrRpcService,
@@ -101,6 +111,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
         this.jobCoordinator = jobCoordinator;
     }
 
+    @PostConstruct
     public void start() {
         LOG.info("{} start", getClass().getSimpleName());
         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
@@ -204,6 +215,20 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
         handleTunnelEventForDPN(add, UpdateRouteAction.ADVERTISE_ROUTE, TunnelAction.TUNNEL_EP_ADD);
     }
 
+    public enum TunnelEventProcessingMethod {
+        POPULATESUBNETS(0), MANAGEREMOTEROUTES(1);
+
+        private final int method;
+
+        TunnelEventProcessingMethod(int id) {
+            this.method = id;
+        }
+
+        public int getValue() {
+            return method;
+        }
+    }
+
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     private void handleTunnelEventForDPN(StateTunnelList stateTunnelList, UpdateRouteAction action,
@@ -269,7 +294,6 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                 LOG.error("handleTunnelEventForDPN: Exception {} when querying for GetDpnInterfaceList for srcDpnid {}"
                         + " srcTepIp {} destTepIp {}, trace {}", e, srcDpnId, srcTepIp, destTepIp, e.getStackTrace());
             }
-
             // Get the list of VpnInterfaces from Intf Mgr for a destDPN only for internal tunnel.
             if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
                 remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
@@ -299,11 +323,98 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
             String intfName = null;
             List<Uuid> subnetList = new ArrayList<>();
             Map<Long, String> vpnIdRdMap = new HashMap<>();
+            Set<String> listVpnName = new HashSet<String>();
 
             while (interfacelistIter.hasNext()) {
                 intfName = interfacelistIter.next();
-                final VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, intfName);
+                VpnInterface vpnInterface =
+                     VpnUtil.getConfiguredVpnInterface(dataBroker, intfName);
+                if (vpnInterface != null) {
+                    listVpnName.addAll(VpnHelper
+                        .getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
+                    handleTunnelEventForDPNVpn(stateTunnelList, action, vpnIdRdMap,
+                                         tunnelAction, isTepDeletedOnDpn,
+                                         subnetList, TunnelEventProcessingMethod.POPULATESUBNETS,
+                                         vpnInterface);
+                }
+            }
+            /*
+             * Iterate over the list of VpnInterface for destDPN and get the prefix .
+             * Create remote rule for each of those prefix on srcDPN.
+             */
+            interfacelistIter = destDpninterfacelist.iterator();
+            while (interfacelistIter.hasNext()) {
+                intfName = interfacelistIter.next();
+                VpnInterface vpnInterface =
+                    VpnUtil.getConfiguredVpnInterface(dataBroker, intfName);
                 if (vpnInterface != null) {
+                    handleTunnelEventForDPNVpn(stateTunnelList, action, vpnIdRdMap,
+                                    tunnelAction, isTepDeletedOnDpn,
+                                    subnetList, TunnelEventProcessingMethod.MANAGEREMOTEROUTES,
+                                    vpnInterface);
+                }
+            }
+
+            //Iterate over the VpnId-to-Rd map.
+            for (Map.Entry<Long, String> entry : vpnIdRdMap.entrySet()) {
+                Long vpnId = entry.getKey();
+                rd = entry.getValue();
+                if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
+                    && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
+                    fibManager.populateExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
+                } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
+                    && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
+                    fibManager.cleanUpExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
+                }
+            }
+            if (listVpnName.size() >= 1) {
+                if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
+                    for (Uuid subnetId : subnetList) {
+                        // Populate the List of subnets
+                        vpnSubnetRouteHandler.updateSubnetRouteOnTunnelUpEvent(subnetId, srcDpnId);
+                    }
+                }
+                if ((tunnelAction == TunnelAction.TUNNEL_EP_DELETE) && isTepDeletedOnDpn) {
+                    for (Uuid subnetId : subnetList) {
+                        // Populate the List of subnets
+                        vpnSubnetRouteHandler.updateSubnetRouteOnTunnelDownEvent(subnetId, srcDpnId);
+                    }
+                }
+            }
+        } catch (RuntimeException e) {
+            LOG.error("handleTunnelEventForDpn: Unable to handle the tunnel event for srcDpnId {} srcTepIp {}"
+                     + " remoteDpnId {} destTepIp {}", srcDpnId, srcTepIp, remoteDpnId, destTepIp, e);
+        }
+    }
+
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    private void handleTunnelEventForDPNVpn(StateTunnelList stateTunnelList, UpdateRouteAction action,
+                                            Map<Long, String> vpnIdRdMap, TunnelAction tunnelAction,
+                                            boolean isTepDeletedOnDpn, List<Uuid> subnetList,
+                                            TunnelEventProcessingMethod method,
+                                            VpnInterface cfgVpnInterface) {
+        String rd;
+        String intfName = cfgVpnInterface.getName();
+        final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
+        String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
+        String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
+        int tunTypeVal = getTunnelType(stateTunnelList);
+        BigInteger remoteDpnId = null;
+        if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
+            remoteDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
+        }
+        if (cfgVpnInterface.getVpnInstanceNames() == null) {
+            LOG.warn("handleTunnelEventForDpn: no vpnName found for interface {}", intfName);
+            return;
+        }
+        for (VpnInstanceNames vpnInstance : cfgVpnInterface.getVpnInstanceNames()) {
+            String vpnName = vpnInstance.getVpnName();
+            if (method == TunnelEventProcessingMethod.POPULATESUBNETS) {
+                Optional<VpnInterfaceOpDataEntry> opVpnInterface = VpnUtil
+                           .getVpnInterfaceOpDataEntry(dataBroker, intfName, vpnName);
+                if (opVpnInterface.isPresent() && !opVpnInterface.get().isScheduledForRemove()) {
+                    VpnInterfaceOpDataEntry vpnInterface  = opVpnInterface.get();
                     jobCoordinator.enqueueJob("VPNINTERFACE-" + intfName,
                             new UpdateVpnInterfaceOnTunnelEvent(tunnelAction,
                                     vpnInterface,
@@ -327,30 +438,24 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                         }
                     }
                     //Populate the map for VpnId-to-Rd
-                    long vpnId = VpnUtil.getVpnId(dataBroker, vpnInterface.getVpnInstanceName());
-                    rd = VpnUtil.getVpnRd(dataBroker, vpnInterface.getVpnInstanceName());
+                    long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
+                    rd = VpnUtil.getVpnRd(dataBroker, vpnName);
                     vpnIdRdMap.put(vpnId, rd);
                 }
-            }
-
-            /*
-             * Iterate over the list of VpnInterface for destDPN and get the prefix .
-             * Create remote rule for each of those prefix on srcDPN.
-             */
-            interfacelistIter = destDpninterfacelist.iterator();
-            while (interfacelistIter.hasNext()) {
-                intfName = interfacelistIter.next();
-                final VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, intfName);
-                if (vpnInterface != null) {
-                    Adjacencies adjacencies = vpnInterface.getAugmentation(Adjacencies.class);
+            } else if (method == TunnelEventProcessingMethod.MANAGEREMOTEROUTES) {
+                Optional<VpnInterfaceOpDataEntry> opVpnInterface = VpnUtil.getVpnInterfaceOpDataEntry(dataBroker,
+                                                                                intfName, vpnName);
+                if (opVpnInterface.isPresent()) {
+                    VpnInterfaceOpDataEntry vpnInterface  = opVpnInterface.get();
+                    AdjacenciesOp adjacencies = vpnInterface.getAugmentation(AdjacenciesOp.class);
                     List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency()
                             : Collections.emptyList();
                     String prefix = null;
                     long vpnId = VpnUtil.getVpnId(dataBroker, vpnInterface.getVpnInstanceName());
                     if (vpnIdRdMap.containsKey(vpnId)) {
                         rd = vpnIdRdMap.get(vpnId);
-                        LOG.info("handleTunnelEventForDPN: Remote DpnId {} VpnId {} rd {} VpnInterface {} srcTepIp {}"
-                                + " destTepIp {}", remoteDpnId, vpnId, rd , vpnInterface, srcTepIp, destTepIp);
+                        LOG.info("handleTunnelEventForDPN: Remote DpnId {} VpnId {} rd {} VpnInterface {} srcTepIp "
+                                + "{} destTepIp {}", remoteDpnId, vpnId, rd , vpnInterface, srcTepIp, destTepIp);
                         for (Adjacency adj : adjList) {
                             prefix = adj.getIpAddress();
                             long label = adj.getLabel();
@@ -367,48 +472,17 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                     }
                 }
             }
-
-            //Iterate over the VpnId-to-Rd map.
-            for (Map.Entry<Long, String> entry : vpnIdRdMap.entrySet()) {
-                Long vpnId = entry.getKey();
-                rd = entry.getValue();
-                if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
-                    && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
-                    fibManager.populateExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
-                } else if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
-                    && tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
-                    fibManager.cleanUpExternalRoutesOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
-                }
-            }
-
-            if (tunnelAction == TunnelAction.TUNNEL_EP_ADD) {
-                for (Uuid subnetId : subnetList) {
-                    // Populate the List of subnets
-                    vpnSubnetRouteHandler.updateSubnetRouteOnTunnelUpEvent(subnetId, srcDpnId);
-                }
-            }
-
-            if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE && isTepDeletedOnDpn) {
-                for (Uuid subnetId : subnetList) {
-                    // Populate the List of subnets
-                    vpnSubnetRouteHandler.updateSubnetRouteOnTunnelDownEvent(subnetId, srcDpnId);
-                }
-            }
-        } catch (RuntimeException e) {
-            LOG.error("handleTunnelEventForDPN: Unable to handle the tunnel event for srcDpnId {} srcTepIp {}"
-                    + " remoteDpnid {} destTepIp {}", srcDpnId, srcTepIp, remoteDpnId, destTepIp, e);
         }
     }
 
-
     private class UpdateVpnInterfaceOnTunnelEvent implements Callable {
-        private final VpnInterface vpnInterface;
+        private final VpnInterfaceOpDataEntry vpnInterface;
         private final StateTunnelList stateTunnelList;
         private final TunnelAction tunnelAction;
         private final boolean isTepDeletedOnDpn;
 
         UpdateVpnInterfaceOnTunnelEvent(TunnelAction tunnelAction,
-            VpnInterface vpnInterface,
+            VpnInterfaceOpDataEntry vpnInterface,
             StateTunnelList stateTunnelList,
             boolean isTepDeletedOnDpn) {
             this.stateTunnelList = stateTunnelList;