L2 gateway functionality related fixes. 63/39763/3
authorSomashekar Byrappa <somashekar.byrappa@ericsson.com>
Thu, 2 Jun 2016 12:05:30 +0000 (17:35 +0530)
committerSomashekar Byrappa <somashekar.byrappa@ericsson.com>
Mon, 6 Jun 2016 12:08:27 +0000 (17:38 +0530)
+ Earlier during l2gw connection delete, remote ucast macs to be deleted
were the combination from ELAN MAC table plus other Elan L2Gateway devices
local macs. This logic is changed. Now remote ucast macs for that particular elan is
read/filtered from node config DS.

+ If batch deletion operation fails, macs are deleted sequentially.

+ During deletion of logical switch, updated to delete entry from
LogicalSwitchDeletedTasks.

+ Renamed LogicalSwitchDeletedJob to DeleteLogicalSwitchJob which
reflects its functionality.

+ Corrected job key in DeleteL2GwDeviceMacsFromElanJob.

Change-Id: Ice6892c7a0bd8d703ba5527fa34afe613180230d
Signed-off-by: Somashekar Byrappa <somashekar.byrappa@ericsson.com>
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/jobs/DeleteL2GwDeviceMacsFromElanJob.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/jobs/DeleteLogicalSwitchJob.java [moved from vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/jobs/LogicalSwitchDeletedJob.java with 85% similarity]
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/utils/ElanL2GatewayUtils.java

index 3fb23d1c0ee8825e90708ad9c78d48eba9af1b8c..6fc6bc27289fcc3b0c93deebeca7a2f44c6b0c57 100644 (file)
@@ -71,8 +71,17 @@ public class DeleteL2GwDeviceMacsFromElanJob implements Callable<List<Listenable
         this.macAddresses = macAddresses;
     }
 
+    /**
+     * Gets the job key.
+     *
+     * @return the job key
+     */
     public String getJobKey() {
-        return JOB_KEY_PREFIX + this.elanName;
+        String jobKey = JOB_KEY_PREFIX + this.elanName;
+        if (macAddresses != null && macAddresses.size() == 1) {
+            jobKey += ":" + macAddresses.get(0).getValue();
+        }
+        return jobKey;
     }
 
     /*
@@ -20,9 +20,9 @@ import java.util.List;
 import java.util.concurrent.Callable;
 
 /**
- * The Class LogicalSwitchDeletedJob.
+ * The Class DeleteLogicalSwitchJob.
  */
-public class LogicalSwitchDeletedJob implements Callable<List<ListenableFuture<Void>>> {
+public class DeleteLogicalSwitchJob implements Callable<List<ListenableFuture<Void>>> {
     private DataBroker broker;
 
     /** The logical switch name. */
@@ -31,9 +31,9 @@ public class LogicalSwitchDeletedJob implements Callable<List<ListenableFuture<V
     /** The physical device. */
     private NodeId hwvtepNodeId;
 
-    private static final Logger LOG = LoggerFactory.getLogger(LogicalSwitchDeletedJob.class);
+    private static final Logger LOG = LoggerFactory.getLogger(DeleteLogicalSwitchJob.class);
 
-    public LogicalSwitchDeletedJob(DataBroker broker, NodeId hwvtepNodeId, String logicalSwitchName) {
+    public DeleteLogicalSwitchJob(DataBroker broker, NodeId hwvtepNodeId, String logicalSwitchName) {
         this.broker = broker;
         this.hwvtepNodeId = hwvtepNodeId;
         this.logicalSwitchName = logicalSwitchName;
index b95af91c667ce844279b89737d6ff1e71ab19a31..1f9f6c7ac1fea267000d63e1fc3804f01c85b0bb 100644 (file)
@@ -20,12 +20,12 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
-
+import java.util.stream.Collectors;
 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;
 import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteL2GwDeviceMacsFromElanJob;
-import org.opendaylight.netvirt.elan.l2gw.jobs.LogicalSwitchDeletedJob;
+import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteLogicalSwitchJob;
 import org.opendaylight.netvirt.elan.l2gw.listeners.HwvtepPhysicalLocatorListener;
 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
 import org.opendaylight.netvirt.elan.utils.ElanConstants;
@@ -46,6 +46,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 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.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
@@ -604,71 +605,67 @@ public class ElanL2GatewayUtils {
      */
     public static ListenableFuture<Void> deleteElanMacsFromL2GatewayDevice(L2GatewayDevice l2GatewayDevice,
             String elanName) {
-        List<MacAddress> elanMacTableEntries = getElanMacTableEntries(elanName);
-        List<MacAddress> elanL2GatewayDevicesLocalMacs = getElanL2GatewayDevicesLocalMacs(l2GatewayDevice, elanName);
-
-        List<MacAddress> lstElanLocalMacs = new ArrayList<>(elanMacTableEntries);
-        lstElanLocalMacs.addAll(elanL2GatewayDevicesLocalMacs);
+        String hwvtepNodeId = l2GatewayDevice.getHwvtepNodeId();
+        String logicalSwitch = getLogicalSwitchFromElan(elanName);
 
-        return HwvtepUtils.deleteRemoteUcastMacs(broker, new NodeId(l2GatewayDevice.getHwvtepNodeId()),
-                elanName, lstElanLocalMacs);
-    }
+        List<MacAddress> lstElanMacs =
+                getRemoteUcastMacs(new NodeId(hwvtepNodeId), logicalSwitch, LogicalDatastoreType.CONFIGURATION);
+        ListenableFuture<Void> future =
+                HwvtepUtils.deleteRemoteUcastMacs(broker, new NodeId(hwvtepNodeId), logicalSwitch, lstElanMacs);
 
-    /**
-     * Gets the elan mac table entries.
-     *
-     * @param elanName
-     *            the elan name
-     * @return the elan mac table entries as list
-     */
-    public static List<MacAddress> getElanMacTableEntries(String elanName) {
-        MacTable macTable = ElanUtils.getElanMacTable(elanName);
-        if (macTable == null || macTable.getMacEntry() == null || macTable.getMacEntry().isEmpty()) {
-            LOG.trace("MacTable is empty for elan: {}", elanName);
-            return Collections.emptyList();
-        }
-        List<MacAddress> lstMacs = Lists.transform(macTable.getMacEntry(), new Function<MacEntry, MacAddress>() {
+        Futures.addCallback(future, new FutureCallback<Void>() {
             @Override
-            public MacAddress apply(MacEntry macEntry) {
-                return (macEntry != null) ? new MacAddress(macEntry.getMacAddress().getValue()) : null;
+            public void onSuccess(Void noarg) {
+                LOG.trace("Successful in batch deletion of elan [{}] macs from l2gw device [{}]", elanName,
+                        hwvtepNodeId);
             }
+
+            @Override
+            public void onFailure(Throwable error) {
+                LOG.warn(String.format(
+                        "Failed during batch delete of elan [%s] macs from l2gw device [%s]. Retrying with sequential deletes.",
+                        elanName, hwvtepNodeId), error);
+                if (lstElanMacs != null && !lstElanMacs.isEmpty()) {
+                    for (MacAddress mac : lstElanMacs) {
+                        HwvtepUtils.deleteRemoteUcastMac(broker, new NodeId(hwvtepNodeId), logicalSwitch, mac);
+                    }
+                }
+            };
         });
-        return lstMacs;
+
+        if (LOG.isDebugEnabled()) {
+            List<String> elanMacs = lstElanMacs.stream().map(mac -> mac.getValue()).collect(Collectors.toList());
+            LOG.debug("Deleting elan [{}] macs from node [{}]. Deleted macs = {}", elanName, hwvtepNodeId, elanMacs);
+        }
+        return future;
     }
 
     /**
-     * Gets the elan l2 gateway devices local macs.
+     * Gets the remote ucast macs from hwvtep node filtering based on logical
+     * switch.
      *
-     * @param l2GwDeviceToBeExcluded
-     *            the l2 gw device to be excluded
-     * @param elanName
-     *            the elan name
-     * @return the elan l2 gateway devices local macs
+     * @param hwvtepNodeId the hwvtep node id
+     * @param logicalSwitch the logical switch
+     * @param datastoreType the datastore type
+     * @return the remote ucast macs
      */
-    public static List<MacAddress> getElanL2GatewayDevicesLocalMacs(L2GatewayDevice l2GwDeviceToBeExcluded,
-            String elanName) {
-        List<MacAddress> lstL2GatewayDeviceMacs = new ArrayList<>();
-
-        ConcurrentMap<String, L2GatewayDevice> elanL2GwDevicesFromCache = ElanL2GwCacheUtils
-                .getInvolvedL2GwDevices(elanName);
-        if (elanL2GwDevicesFromCache != null) {
-            for (L2GatewayDevice otherDevice : elanL2GwDevicesFromCache.values()) {
-                if (!otherDevice.getHwvtepNodeId().equals(l2GwDeviceToBeExcluded.getHwvtepNodeId())) {
-                    List<LocalUcastMacs> lstUcastLocalMacs = otherDevice.getUcastLocalMacs();
-                    if (lstUcastLocalMacs != null) {
-                        List<MacAddress> l2GwDeviceMacs = Lists.transform(lstUcastLocalMacs,
-                                new Function<LocalUcastMacs, MacAddress>() {
-                                    @Override
-                                    public MacAddress apply(LocalUcastMacs localUcastMac) {
-                                        return (localUcastMac != null) ? localUcastMac.getMacEntryKey() : null;
-                                    }
-                                });
-                        lstL2GatewayDeviceMacs.addAll(l2GwDeviceMacs);
-                    }
-                }
+    public static List<MacAddress> getRemoteUcastMacs(NodeId hwvtepNodeId, String logicalSwitch,
+            LogicalDatastoreType datastoreType) {
+        List<MacAddress> lstMacs = Collections.emptyList();
+        Node hwvtepNode = HwvtepUtils.getHwVtepNode(broker, datastoreType, hwvtepNodeId);
+        if (hwvtepNode != null) {
+            List<RemoteUcastMacs> remoteUcastMacs =
+                    hwvtepNode.getAugmentation(HwvtepGlobalAugmentation.class).getRemoteUcastMacs();
+            if (remoteUcastMacs != null && !remoteUcastMacs.isEmpty()) {
+                // Filtering remoteUcastMacs based on the logical switch and
+                // forming a list of MacAddress
+                lstMacs = remoteUcastMacs.stream()
+                        .filter(mac -> logicalSwitch.equals(mac.getLogicalSwitchRef().getValue()
+                                .firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue()))
+                        .map(mac -> mac.getMacEntryKey()).collect(Collectors.toList());
             }
         }
-        return lstL2GatewayDeviceMacs;
+        return lstMacs;
     }
 
     /**
@@ -1100,14 +1097,17 @@ public class ElanL2GatewayUtils {
         TimerTask logicalSwitchDeleteTask = new TimerTask() {
             @Override
             public void run() {
-                LogicalSwitchDeletedJob logicalSwitchDeletedJob = new LogicalSwitchDeletedJob(broker, hwvtepNodeId,
-                        lsName);
-                ElanL2GatewayUtils.dataStoreJobCoordinator.enqueueJob(logicalSwitchDeletedJob.getJobKey(),
-                        logicalSwitchDeletedJob, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
+                Pair<NodeId, String> nodeIdLogicalSwitchNamePair =
+                        new ImmutablePair<NodeId, String>(hwvtepNodeId, lsName);
+                LogicalSwitchDeletedTasks.remove(nodeIdLogicalSwitchNamePair);
+
+                DeleteLogicalSwitchJob deleteLsJob = new DeleteLogicalSwitchJob(broker, hwvtepNodeId, lsName);
+                ElanL2GatewayUtils.dataStoreJobCoordinator.enqueueJob(deleteLsJob.getJobKey(), deleteLsJob,
+                        SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
             }
         };
         Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<NodeId, String>(hwvtepNodeId, lsName);
-        LogicalSwitchDeletedTasks.putIfAbsent(nodeIdLogicalSwitchNamePair, logicalSwitchDeleteTask);
+        LogicalSwitchDeletedTasks.put(nodeIdLogicalSwitchNamePair, logicalSwitchDeleteTask);
         LogicalSwitchDeleteJobTimer.schedule(logicalSwitchDeleteTask, LOGICAL_SWITCH_DELETE_DELAY);
     }