Multiple VxLAN tunnels - egress service 41/53541/16
authorOlga Schukin <olga.schukin@hpe.com>
Sun, 19 Mar 2017 10:23:40 +0000 (12:23 +0200)
committerHema Gopalakrishnan <hema.gopalkrishnan@ericsson.com>
Wed, 10 May 2017 05:31:02 +0000 (11:01 +0530)
- default egress service would be bound to the logical tunnel
- OF select group based on the actual list of tunnel members in the
  logical group
- set the oper status of logic tunnel according the states of the group members
- admin status of logic tunnel affects the states of the group members

Depends-On:
 https://git.opendaylight.org/gerrit/52871
 https://git.opendaylight.org/gerrit/52993
 https://git.opendaylight.org/gerrit/53603

Change-Id: Ica0801aa274615cedc36c60d661a0d5d411e1bd0
Signed-off-by: Olga Schukin <olga.schukin@hpe.com>
13 files changed:
interfacemanager/interfacemanager-api/src/main/java/org/opendaylight/genius/interfacemanager/globals/IfmConstants.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/IfmUtil.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/commons/InterfaceManagerCommonUtils.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/commons/InterfaceMetaUtils.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/renderer/ovs/confighelpers/OvsInterfaceConfigAddHelper.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/renderer/ovs/confighelpers/OvsInterfaceConfigRemoveHelper.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/servicebindings/flowbased/utilities/FlowBasedServicesUtils.java
itm/itm-api/src/main/java/org/opendaylight/genius/itm/globals/ITMConstants.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmInternalTunnelAddWorker.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmInternalTunnelDeleteWorker.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmTunnelAggregationHelper.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/listeners/InterfaceChildInfoListener.java [new file with mode: 0644]
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/listeners/InterfaceStateListener.java

index 1fd987134092b88c4c55665868668403698edfd9..09ec689603352d998a7772e4eff32f16f4a413b9 100644 (file)
@@ -28,7 +28,6 @@ public class IfmConstants {
     public static final long IFM_ID_POOL_END = 65535;
 
     public static final long VXLAN_GROUPID_MIN = 300000L;
-
     // Group Prefix
     public static final long VLAN_GROUP_START = 1000;
     public static final long TRUNK_GROUP_START = 20000;
index 95594bf6b67943d9668da294b3b6404475e156fc..f6f3dc5443a6e6c0b5d8ea1b45fe7e238b6bce6f 100755 (executable)
@@ -35,6 +35,7 @@ import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
 import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
 import org.opendaylight.genius.mdsalutil.actions.ActionPushVlan;
@@ -220,11 +221,13 @@ public class IfmUtil {
     }
 
     public static List<Instruction> getEgressInstructionsForInterface(Interface interfaceInfo, String portNo,
-            Long tunnelKey, boolean isDefaultEgress, int ifIndex) {
+                                                                      Long tunnelKey, boolean isDefaultEgress,
+                                                                      int ifIndex, long groupId) {
         List<Instruction> instructions = new ArrayList<>();
         InterfaceInfo.InterfaceType ifaceType = getInterfaceType(interfaceInfo);
-        List<Action> actionList = MDSALUtil.buildActions(getEgressActionInfosForInterface(interfaceInfo, portNo,
-                ifaceType, tunnelKey, 0, isDefaultEgress, ifIndex));
+        List<Action> actionList = MDSALUtil.buildActions(
+                getEgressActionInfosForInterface(interfaceInfo, portNo, ifaceType, tunnelKey, 0,
+                                                 isDefaultEgress, ifIndex, groupId));
         instructions.add(MDSALUtil.buildApplyActionsInstruction(actionList));
         return instructions;
     }
@@ -267,7 +270,7 @@ public class IfmUtil {
 
         InterfaceInfo.InterfaceType ifaceType = getInterfaceType(interfaceInfo);
         return getEgressActionInfosForInterface(interfaceInfo, portNo, ifaceType, tunnelKey, actionKeyStart,
-                isDefaultEgress, ifState.getIfIndex());
+                isDefaultEgress, ifState.getIfIndex(), 0);
     }
 
     /**
@@ -286,7 +289,7 @@ public class IfmUtil {
     @SuppressWarnings("fallthrough")
     public static List<ActionInfo> getEgressActionInfosForInterface(Interface interfaceInfo, String portNo,
             InterfaceInfo.InterfaceType ifaceType, Long tunnelKey, int actionKeyStart, boolean isDefaultEgress,
-            int ifIndex) {
+            int ifIndex, long groupId) {
         List<ActionInfo> result = new ArrayList<>();
         switch (ifaceType) {
             case MPLS_OVER_GRE:
@@ -340,11 +343,12 @@ public class IfmUtil {
                 break;
             case LOGICAL_GROUP_INTERFACE:
                 if (isDefaultEgress) {
-                    LOG.debug("MULTIPLE_VxLAN_TUNNELS: default egress action treatment will be added later");
+                    result.add(new ActionGroup(groupId));
                 } else {
                     addEgressActionInfosForInterface(ifIndex, actionKeyStart, result);
                 }
                 break;
+
             default:
                 LOG.warn("Interface Type {} not handled yet", ifaceType);
                 break;
@@ -450,7 +454,8 @@ public class IfmUtil {
             Class<? extends org.opendaylight.yang.gen.v1.urn.opendaylight
                     .genius.interfacemanager.rev160406.TunnelTypeBase> tunnelType = ifTunnel
                     .getTunnelInterfaceType();
-            interfaceType = TUNNEL_TYPE_MAP.get(tunnelType);
+            interfaceType = tunnelType.isAssignableFrom(TunnelTypeLogicalGroup.class)
+                    ? InterfaceInfo.InterfaceType.LOGICAL_GROUP_INTERFACE :  TUNNEL_TYPE_MAP.get(tunnelType);
         }
         return interfaceType;
     }
index b6da7ea162bf3ef749bc0a787ed38b176bb365d7..69571353bbc6c8be8cd5a75ba14185842cbaa360 100644 (file)
@@ -61,6 +61,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.met
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
@@ -211,6 +212,10 @@ public final class InterfaceManagerCommonUtils {
 
     public static void makeTunnelIngressFlow(List<ListenableFuture<Void>> futures, IMdsalApiManager mdsalApiManager,
             IfTunnel tunnel, BigInteger dpnId, long portNo, String interfaceName, int ifIndex, int addOrRemoveFlow) {
+
+        if (tunnel != null && tunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeLogicalGroup.class)) {
+            return;
+        }
         LOG.debug("make tunnel ingress flow for {}", interfaceName);
         String flowRef = InterfaceManagerCommonUtils.getTunnelInterfaceFlowRef(dpnId,
                 NwConstants.VLAN_INTERFACE_INGRESS_TABLE, interfaceName);
index 2efe8464c1ee372a883a29cbacf8bd6dba42d5d5..d4b7e5b2477fc424da6560b1ea92fd98d6a08a75 100644 (file)
@@ -227,7 +227,7 @@ public class InterfaceMetaUtils {
         BatchingUtils.write(id, ifIndexInterface, BatchingUtils.EntityType.DEFAULT_OPERATIONAL);
     }
 
-    public static void removeLportTagInterfaceMap(IdManagerService idManager, WriteTransaction tx, String infName) {
+    public static int removeLportTagInterfaceMap(IdManagerService idManager, WriteTransaction tx, String infName) {
         // workaround to get the id to remove from lport tag interface map
         Integer ifIndex = IfmUtil.allocateId(idManager, IfmConstants.IFM_IDPOOL_NAME, infName);
         IfmUtil.releaseId(idManager, IfmConstants.IFM_IDPOOL_NAME, infName);
@@ -235,6 +235,7 @@ public class InterfaceMetaUtils {
         InstanceIdentifier<IfIndexInterface> id = InstanceIdentifier.builder(IfIndexesInterfaceMap.class)
                 .child(IfIndexInterface.class, new IfIndexInterfaceKey(ifIndex)).build();
         tx.delete(LogicalDatastoreType.OPERATIONAL, id);
+        return ifIndex;
     }
 
     public static void addBridgeRefToBridgeInterfaceEntry(BigInteger dpId, OvsdbBridgeRef ovsdbBridgeRef,
index f57efd76bac70095cc372f8e57ae64bbc045678a..a12f30acba2c9844363d6bba9fb82141291491ac 100644 (file)
@@ -12,8 +12,10 @@ import com.google.common.base.Strings;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.math.BigInteger;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Callable;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
@@ -24,6 +26,7 @@ import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUt
 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils;
 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
@@ -39,6 +42,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -117,7 +122,8 @@ public class OvsInterfaceConfigAddHelper {
         LOG.info("adding tunnel configuration for interface {}", interfaceNew.getName());
 
         if (ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeLogicalGroup.class)) {
-            addLogicalTunnelGroup(interfaceNew, idManager, defaultOperShardTransaction);
+            addLogicalTunnelGroup(interfaceNew, idManager, mdsalApiManager, dataBroker,
+                                  defaultOperShardTransaction, futures);
             return;
         }
         boolean createTunnelPort = true;
@@ -223,14 +229,34 @@ public class OvsInterfaceConfigAddHelper {
         }
     }
 
-    private static void addLogicalTunnelGroup(Interface itfNew, IdManagerService idManager, WriteTransaction tx) {
-        LOG.debug("MULTIPLE_VxLAN_TUNNELS: adding Interface State for logic tunnel group {}", itfNew.getName());
-        InterfaceManagerCommonUtils.addStateEntry(itfNew, itfNew.getName(), tx,
-                                                  idManager, null /*physAddress*/,
-                                                  org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
-                                                  .interfaces.rev140508.interfaces.state.Interface.OperStatus.Up,
-                                                  org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
-                                                  .interfaces.rev140508.interfaces.state.Interface.AdminStatus.Up,
-                                                  null /*nodeConnectorId*/);
+    private static long createLogicalTunnelSelectGroup(BigInteger srcDpnId, String interfaceName,
+                                                int lportTag, IMdsalApiManager mdsalManager) {
+        long groupId = IfmUtil.getLogicalTunnelSelectGroupId(lportTag);
+        Group group = MDSALUtil.buildGroup(groupId, interfaceName, GroupTypes.GroupSelect,
+                                           MDSALUtil.buildBucketLists(Collections.emptyList()));
+        LOG.debug("MULTIPLE_VxLAN_TUNNELS: group id {} installed for {} srcDpnId {}",
+                group.getGroupId().getValue(), interfaceName, srcDpnId);
+        mdsalManager.syncInstallGroup(srcDpnId, group, IfmConstants.DELAY_TIME_IN_MILLISECOND);
+        return groupId;
+    }
+
+    private static void addLogicalTunnelGroup(Interface itfNew, IdManagerService idManager,
+                                              IMdsalApiManager mdsalApiManager, DataBroker broker,
+                                              WriteTransaction tx, List<ListenableFuture<Void>> futures) {
+        String ifaceName = itfNew.getName();
+        LOG.debug("MULTIPLE_VxLAN_TUNNELS: adding Interface State for logic tunnel group {}", ifaceName);
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
+            .Interface ifState = InterfaceManagerCommonUtils.addStateEntry(itfNew, ifaceName, tx,
+                    idManager, null /*physAddress*/,
+                    org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
+                    .interfaces.rev140508.interfaces.state.Interface.OperStatus.Up,
+                    org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
+                    .interfaces.rev140508.interfaces.state.Interface.AdminStatus.Up,
+                    null /*nodeConnectorId*/);
+        long groupId = createLogicalTunnelSelectGroup(IfmUtil.getDpnFromInterface(ifState),
+                                                      itfNew.getName(), ifState.getIfIndex(), mdsalApiManager);
+        FlowBasedServicesUtils.bindDefaultEgressDispatcherService(broker, futures, itfNew,
+                                                                  ifaceName, ifState.getIfIndex(), groupId);
     }
+
 }
index 428b91555b8fd967646a24da8931249088245e36..9c56a3490394917409a053436999255a968e4161 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.genius.interfacemanager.renderer.ovs.confighelpers;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.math.BigInteger;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Callable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -22,6 +23,7 @@ import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUt
 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils;
 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
@@ -37,6 +39,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -159,7 +163,8 @@ public class OvsInterfaceConfigRemoveHelper {
         // delete bridge to tunnel interface mappings
         InterfaceMetaUtils.deleteBridgeInterfaceEntry(bridgeEntryKey, bridgeInterfaceEntries, bridgeEntryIid,
                 defaultConfigShardTransaction, interfaceName);
-        InterfaceMetaUtils.removeLportTagInterfaceMap(idManager, defaultOperationalShardTransaction, interfaceName);
+        int lportTag = InterfaceMetaUtils.removeLportTagInterfaceMap(idManager, defaultOperationalShardTransaction,
+                                                                     interfaceName);
         cleanUpInterfaceWithUnknownState(interfaceName, parentRefs, ifTunnel, dataBroker,
                 defaultOperationalShardTransaction, idManager);
         // stop LLDP monitoring for the tunnel interface
@@ -169,7 +174,8 @@ public class OvsInterfaceConfigRemoveHelper {
             removeMultipleVxlanTunnelsConfiguration(interfaceName, parentRefs);
 
         } else if (ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeLogicalGroup.class)) {
-            removeLogicalTunnelGroup(interfaceName, idManager, dataBroker, defaultOperationalShardTransaction);
+            removeLogicalTunnelGroup(dpId, interfaceName, lportTag, idManager, mdsalApiManager, dataBroker,
+                                     defaultOperationalShardTransaction);
         }
     }
 
@@ -256,12 +262,23 @@ public class OvsInterfaceConfigRemoveHelper {
         }
     }
 
-    private static void removeLogicalTunnelGroup(String ifaceName, IdManagerService idManager,
-                                                 DataBroker dataBroker, WriteTransaction tx) {
+    private static void removeLogicalTunnelSelectGroup(BigInteger srcDpnId, String interfaceName, int lportTag,
+                                                       IMdsalApiManager mdsalManager) {
+        long groupId = IfmUtil.getLogicalTunnelSelectGroupId(lportTag);
+        Group group = MDSALUtil.buildGroup(groupId, interfaceName, GroupTypes.GroupSelect,
+                                           MDSALUtil.buildBucketLists(Collections.emptyList()));
+        LOG.debug("MULTIPLE_VxLAN_TUNNELS: group id {} removed for {} srcDpnId {}",
+                group.getGroupId().getValue(), interfaceName, srcDpnId);
+        mdsalManager.syncRemoveGroup(srcDpnId, group);
+    }
+
+    private static void removeLogicalTunnelGroup(BigInteger dpnId, String ifaceName, int lportTag,
+            IdManagerService idManager, IMdsalApiManager mdsalApiManager, DataBroker dataBroker, WriteTransaction tx) {
         LOG.debug("MULTIPLE_VxLAN_TUNNELS: unbind & delete Interface State for logic tunnel group {}", ifaceName);
         FlowBasedServicesUtils.unbindDefaultEgressDispatcherService(dataBroker, ifaceName);
         InterfaceManagerCommonUtils.deleteInterfaceStateInformation(ifaceName, tx, idManager);
         InterfaceManagerCommonUtils.deleteParentInterfaceEntry(ifaceName);
+        removeLogicalTunnelSelectGroup(dpnId, ifaceName, lportTag, mdsalApiManager);
     }
 
     private static void removeMultipleVxlanTunnelsConfiguration(String ifaceName, ParentRefs parentRef) {
index 8836bc9db1025e483825130798873248d401184e..0fa737bd2b1ead5e77f360da5cacdfb2fd6b46ad 100644 (file)
@@ -13,6 +13,7 @@ import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import org.apache.commons.lang3.StringUtils;
 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;
@@ -413,16 +414,31 @@ public class FlowBasedServicesUtils {
     }
 
     public static void bindDefaultEgressDispatcherService(DataBroker dataBroker, List<ListenableFuture<Void>> futures,
-            Interface interfaceInfo, String portNo, String interfaceName, int ifIndex) {
+                                                          Interface interfaceInfo, String portNo,
+                                                          String interfaceName, int ifIndex) {
+        List<Instruction> instructions =
+                IfmUtil.getEgressInstructionsForInterface(interfaceInfo, portNo, null, true, ifIndex, 0);
+        bindDefaultEgressDispatcherService(dataBroker, futures, interfaceName, instructions);
+    }
+
+    public static void bindDefaultEgressDispatcherService(DataBroker dataBroker, List<ListenableFuture<Void>> futures,
+            Interface interfaceInfo, String interfaceName, int ifIndex, long groupId) {
+        List<Instruction> instructions =
+             IfmUtil.getEgressInstructionsForInterface(interfaceInfo, StringUtils.EMPTY, null, true, ifIndex, groupId);
+        bindDefaultEgressDispatcherService(dataBroker, futures, interfaceName, instructions);
+    }
+
+    public static void bindDefaultEgressDispatcherService(DataBroker dataBroker, List<ListenableFuture<Void>> futures,
+            String interfaceName, List<Instruction> instructions) {
         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
         int priority = ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME,
-                NwConstants.DEFAULT_EGRESS_SERVICE_INDEX);
-        List<Instruction> instructions = IfmUtil.getEgressInstructionsForInterface(interfaceInfo, portNo, null, true,
-                ifIndex);
-        BoundServices serviceInfo = getBoundServices(String.format("%s.%s", "default", interfaceName),
-                ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME,
-                        NwConstants.DEFAULT_EGRESS_SERVICE_INDEX),
-                priority, NwConstants.EGRESS_DISPATCHER_TABLE_COOKIE, instructions);
+                                             NwConstants.DEFAULT_EGRESS_SERVICE_INDEX);
+        BoundServices
+                serviceInfo =
+                getBoundServices(String.format("%s.%s", "default", interfaceName),
+                        ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME,
+                                              NwConstants.DEFAULT_EGRESS_SERVICE_INDEX),
+                        priority, NwConstants.EGRESS_DISPATCHER_TABLE_COOKIE, instructions);
         IfmUtil.bindService(tx, interfaceName, serviceInfo, ServiceModeEgress.class);
         futures.add(tx.submit());
     }
index 0ea5f676644003bf61481f3e9bbb9a9cb5f4c0cd..ac87f1b184c62abe1209db6a55619240029bd70a 100644 (file)
@@ -21,6 +21,8 @@ public class ITMConstants {
     public static final String ITM_IDPOOL_SIZE = "100000";
 
     public static final long DELAY_TIME_IN_MILLISECOND = 5000;
+    public static final int REG6_START_INDEX = 0;
+    public static final int REG6_END_INDEX = 31;
 
     public static final int LLDP_SERVICE_ID = 0;
     // Tunnel Monitoring
index d44a6a35c8277bb239222be84f9c3e284dfd2ca1..15b1e1b9f4a5f6f322f1fe422b15b62e40f9c753 100644 (file)
@@ -207,11 +207,13 @@ public class ItmInternalTunnelAddWorker {
                 + "source IP - {}, destination IP - {} gateway IP - {}",
                 trunkInterfaceName, srcte.getInterfaceName(), srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress);
         boolean useOfTunnel = ItmUtils.falseIfNull(srcte.isOptionOfTunnel());
+
         List<TunnelOptions> tunOptions = ItmUtils.buildTunnelOptions(srcte, itmCfg);
+        Boolean isMonitorEnabled = tunType.isAssignableFrom(TunnelTypeLogicalGroup.class) ? false : monitorEnabled;
         Interface iface = ItmUtils.buildTunnelInterface(srcDpnId, trunkInterfaceName,
                 String.format("%s %s",ItmUtils.convertTunnelTypetoString(tunType), "Trunk Interface"),
                 true, tunType, srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress, srcte.getVLANID(), true,
-                monitorEnabled, monitorProtocol, monitorInterval, useOfTunnel, parentInterfaceName, tunOptions);
+                isMonitorEnabled, monitorProtocol, monitorInterval, useOfTunnel, parentInterfaceName, tunOptions);
         LOG.debug(" Trunk Interface builder - {} ", iface);
         InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
         LOG.debug(" Trunk Interface Identifier - {} ", trunkIdentifier);
index d73a11a3afa01dd2cf1e0e4f39d3e7d59a6ffff3..131c9376f83b7e05f2fdec07537126fedfd051f1 100644 (file)
@@ -228,7 +228,6 @@ public class ItmInternalTunnelDeleteWorker {
                 new String(srcTep.getIpAddress().getValue()),
                 dstTep.getTunnelType().getName());
         removeLogicalGroupTunnel(dstDpnId, srcDpnId, dataBroker);
-
     }
 
     private static boolean checkIfTrunkExists(BigInteger srcDpnId, BigInteger dstDpnId,
index 09d7d876318c9ec30c9b026d917be86eb4e8138a..85df6cc44bc1be91c19449e1046c52f633481a80 100644 (file)
@@ -8,38 +8,77 @@
 
 package org.opendaylight.genius.itm.confighelpers;
 
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import java.math.BigInteger;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-
+import java.util.concurrent.Callable;
 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;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
+import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
+import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo.InterfaceAdminState;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.itm.globals.ITMConstants;
 import org.opendaylight.genius.itm.impl.ItmUtils;
+import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.InterfaceChildInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.itm.config.TunnelAggregation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 @Singleton
 public class ItmTunnelAggregationHelper {
 
+    public static final int ADD_TUNNEL = 0;
+    public static final int DEL_TUNNEL = 1;
+    public static final int MOD_TUNNEL = 2;
+    public static final int MOD_GROUP_TUNNEL = 3;
+    public static final int DEFAULT_WEIGHT = 1;
+    public static final long INVALID_ID = 0;
+
     private static final Logger LOG = LoggerFactory.getLogger(ItmTunnelAggregationHelper.class);
     private static boolean tunnelAggregationEnabled;
     private final IInterfaceManager interfaceManager;
+    private final IMdsalApiManager mdsalManager;
 
     @Inject
-    public ItmTunnelAggregationHelper(final IInterfaceManager interfaceMngr, final ItmConfig itmConfig) {
+    public ItmTunnelAggregationHelper(final IInterfaceManager interfaceMngr,
+                                      final IMdsalApiManager mdsalMngr, final ItmConfig itmConfig) {
         interfaceManager = interfaceMngr;
+        mdsalManager = mdsalMngr;
         initTunnelAggregationConfig(itmConfig);
     }
 
@@ -47,17 +86,66 @@ public class ItmTunnelAggregationHelper {
         return tunnelAggregationEnabled;
     }
 
-    public void createLogicalTunnelSelectGroup(BigInteger srcDpnId, String interfaceName, int lporttag,
-                                               IMdsalApiManager mdsalManager) {
-        long groupId = interfaceManager.getLogicalTunnelSelectGroupId(lporttag);
-        if (groupId == 0 || mdsalManager.groupExists(srcDpnId, groupId)) {
+    public void createLogicalTunnelSelectGroup(BigInteger srcDpnId, String interfaceName, int lportTag) {
+        Group group = prepareLogicalTunnelSelectGroup(srcDpnId, interfaceName, lportTag);
+        LOG.debug("MULTIPLE_VxLAN_TUNNELS: group id {} installed for {} srcDpnId {}",
+                group.getGroupId().getValue(), interfaceName, srcDpnId);
+        mdsalManager.syncInstallGroup(srcDpnId, group, ITMConstants.DELAY_TIME_IN_MILLISECOND);
+    }
+
+    public void updateLogicalTunnelSelectGroup(InterfaceParentEntry entry, DataBroker broker) {
+        String logicTunnelName = entry.getParentInterface();
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
+                    .interfaces.Interface ifaceConfig = ItmUtils.getInterface(logicTunnelName, interfaceManager);
+        if (ifaceConfig == null || !ifaceConfig.getType().isAssignableFrom(Tunnel.class)) {
             return;
         }
-        LOG.debug("MULTIPLE_VxLAN_TUNNELS: id {} allocated for the logical select group {} srcDpnId {}",
-                      groupId, interfaceName, srcDpnId);
-        Group group = MDSALUtil.buildGroup(groupId, interfaceName, GroupTypes.GroupSelect,
-                                           MDSALUtil.buildBucketLists(Collections.emptyList()));
-        mdsalManager.syncInstallGroup(srcDpnId, group, ITMConstants.DELAY_TIME_IN_MILLISECOND);
+        IfTunnel ifTunnel = ifaceConfig.getAugmentation(IfTunnel.class);
+        if (!ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeLogicalGroup.class)) {
+            return;
+        }
+        LOG.debug("MULTIPLE_VxLAN_TUNNELS: updateLogicalTunnelSelectGroup name {}", logicTunnelName);
+        DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+        TunnelAggregationUpdateWorker worker =
+                new TunnelAggregationUpdateWorker(null, null, ifaceConfig, entry, MOD_GROUP_TUNNEL, broker);
+        coordinator.enqueueJob(logicTunnelName, worker);
+    }
+
+    public void updateLogicalTunnelState(Interface ifaceState, int tunnelAction, DataBroker broker) {
+        updateLogicalTunnelState(null, ifaceState, tunnelAction, broker);
+    }
+
+    public void updateLogicalTunnelState(Interface ifStateOrigin, Interface ifStateUpdated,
+                                                int tunnelAction, DataBroker broker) {
+        boolean tunnelAggregationEnabled = isTunnelAggregationEnabled();
+        if (!tunnelAggregationEnabled || ifStateUpdated == null) {
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: updateLogicalTunnelState - wrong configuration -"
+                    + " tunnelAggregationEnabled {} ifStateUpdated {}", tunnelAggregationEnabled, ifStateUpdated);
+            return;
+        }
+        String ifName = ifStateUpdated.getName();
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
+                ItmUtils.getInterface(ifName, interfaceManager);
+        IfTunnel ifTunnel = iface != null ? iface.getAugmentation(IfTunnel.class) : null;
+        if (iface == null || ifTunnel == null) {
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: updateLogicalTunnelState - not tunnel interface {}", ifName);
+            return;
+        }
+        String logicTunnelName = null;
+        if (ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeLogicalGroup.class)) {
+            logicTunnelName = ifStateUpdated.getName();
+        } else {
+            ParentRefs parentRefs = iface.getAugmentation(ParentRefs.class);
+            if (ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class) && parentRefs != null) {
+                logicTunnelName = parentRefs.getParentInterface();
+            }
+        }
+        if (logicTunnelName != null) {
+            DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+            TunnelAggregationUpdateWorker worker =
+                    new TunnelAggregationUpdateWorker(ifStateOrigin, ifStateUpdated, iface, null, tunnelAction, broker);
+            coordinator.enqueueJob(logicTunnelName, worker);
+        }
     }
 
     private void initTunnelAggregationConfig(ItmConfig itmConfig) {
@@ -78,4 +166,300 @@ public class ItmTunnelAggregationHelper {
         tunnelAggregationEnabled = tunnelAggregationConfigEnabled;
     }
 
+    private Group prepareLogicalTunnelSelectGroup(BigInteger srcDpnId, String interfaceName, int lportTag) {
+        long groupId = interfaceManager.getLogicalTunnelSelectGroupId(lportTag);
+        Group group = MDSALUtil.buildGroup(groupId, interfaceName, GroupTypes.GroupSelect,
+                                           MDSALUtil.buildBucketLists(Collections.emptyList()));
+        return group;
+    }
+
+    private Bucket createBucket(String interfaceName, IfTunnel ifTunnel, ParentRefs parentRefs,
+                                       Integer ifIndex, int bucketId, int portNumber) {
+        List<ActionInfo> listActionInfo = interfaceManager.getInterfaceEgressActions(interfaceName);
+        if (listActionInfo == null || listActionInfo.isEmpty()) {
+            LOG.warn("MULTIPLE_VxLAN_TUNNELS: could not build Egress bucket for {}", interfaceName);
+        }
+        Integer portWeight = ifTunnel.getWeight() != null ? ifTunnel.getWeight() : DEFAULT_WEIGHT;
+        Bucket buckt = MDSALUtil.buildBucket(MDSALUtil.buildActions(listActionInfo), portWeight, bucketId,
+                                             portNumber, MDSALUtil.WATCH_GROUP);
+        return buckt;
+    }
+
+    private void updateTunnelAggregationGroup(InterfaceParentEntry parentEntry) {
+        String logicTunnelName = parentEntry.getParentInterface();
+        InternalTunnel logicInternalTunnel = ItmUtils.itmCache.getInternalTunnel(logicTunnelName);
+        if (logicInternalTunnel == null) {
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: {} not found in internal tunnels list", logicTunnelName);
+            return;
+        }
+        InterfaceInfo ifLogicTunnel = interfaceManager.getInterfaceInfoFromOperationalDataStore(logicTunnelName);
+        long groupId = ifLogicTunnel != null
+                ? interfaceManager.getLogicalTunnelSelectGroupId(ifLogicTunnel.getInterfaceTag()) : INVALID_ID;
+        BigInteger srcDpnId = logicInternalTunnel.getSourceDPN();
+        List<Bucket> listBuckets = new ArrayList<>();
+        List<InterfaceChildEntry> interfaceChildEntries = parentEntry.getInterfaceChildEntry();
+        if (interfaceChildEntries == null || interfaceChildEntries.isEmpty()) {
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: empty child list in group {}", parentEntry.getParentInterface());
+            return;
+        }
+        for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
+            String curChildName = interfaceChildEntry.getChildInterface();
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
+                        childIface = ItmUtils.getInterface(curChildName, interfaceManager);
+            IfTunnel ifTunnel = childIface != null ? childIface.getAugmentation(IfTunnel.class) : null;
+            if (ifTunnel == null || !ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
+                LOG.debug("MULTIPLE_VxLAN_TUNNELS: not tunnel interface {} found in group {}",
+                        curChildName, logicTunnelName);
+                continue;
+            }
+            ParentRefs parentRefs = childIface.getAugmentation(ParentRefs.class);
+            if (parentRefs == null) {
+                LOG.debug("MULTIPLE_VxLAN_TUNNELS: parent refs not specified for interface {} in group {}",
+                        curChildName, logicTunnelName);
+                continue;
+            }
+            InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(curChildName);
+            if (ifInfo == null) {
+                LOG.debug("MULTIPLE_VxLAN_TUNNELS: interface state not found for {} in groupId {}",
+                        curChildName, groupId);
+                continue;
+            }
+            int bucketId = interfaceChildEntries.indexOf(interfaceChildEntry);
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: updateTunnelAggregationGroup - add bucketId {} to groupId {}",
+                    bucketId, groupId);
+            Bucket buckt = createBucket(curChildName, ifTunnel, parentRefs, ifInfo.getInterfaceTag(),
+                                        bucketId, ifInfo.getPortNo());
+            listBuckets.add(buckt);
+        }
+        if (!listBuckets.isEmpty()) {
+            Group group = MDSALUtil.buildGroup(groupId, logicTunnelName, GroupTypes.GroupSelect,
+                                               MDSALUtil.buildBucketLists(listBuckets));
+            mdsalManager.syncInstallGroup(srcDpnId, group, ITMConstants.DELAY_TIME_IN_MILLISECOND);
+        }
+    }
+
+    private void updateTunnelAggregationGroupBucket(Interface ifaceState, IfTunnel ifTunnel,
+                                                    ParentRefs parentRefs, InterfaceParentEntry groupParentEntry,
+                                                    int action, WriteTransaction tx) {
+        String logicTunnelName = parentRefs.getParentInterface();
+        List<InterfaceChildEntry> interfaceChildEntries = groupParentEntry.getInterfaceChildEntry();
+        if (interfaceChildEntries == null) {
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: empty child list in group {}", groupParentEntry.getParentInterface());
+            return;
+        }
+        String ifaceName = ifaceState.getName();
+        InterfaceChildEntry childEntry = new InterfaceChildEntryBuilder().setChildInterface(ifaceName)
+                .setKey(new InterfaceChildEntryKey(ifaceName)).build();
+        int bucketId = interfaceChildEntries.indexOf(childEntry);
+        if (bucketId == -1) {
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: wrong child id for {} in group {}", ifaceName,
+                    groupParentEntry.getParentInterface());
+            return;
+        }
+        InterfaceInfo ifLogicTunnel = interfaceManager.getInterfaceInfoFromOperationalDataStore(logicTunnelName);
+        long groupId = ifLogicTunnel != null
+                ? interfaceManager.getLogicalTunnelSelectGroupId(ifLogicTunnel.getInterfaceTag()) : INVALID_ID;
+        if (groupId == INVALID_ID) {
+            LOG.warn("MULTIPLE_VxLAN_TUNNELS: unknown group id for logic tunnel {}", logicTunnelName);
+            return;
+        }
+        String lowerLayerIf = ifaceState.getLowerLayerIf().get(0); // openflow:dpnid:portnum
+        String[] split = lowerLayerIf.split(IfmConstants.OF_URI_SEPARATOR);
+        BigInteger srcDpnId = new BigInteger(split[1]);
+        int portNumber = Integer.parseInt(split[2]);
+        if (action == ADD_TUNNEL) {
+            if (!mdsalManager.groupExists(srcDpnId, groupId)) {
+                createLogicalTunnelSelectGroup(srcDpnId, logicTunnelName, ifLogicTunnel.getInterfaceTag());
+            }
+            Bucket buckt = createBucket(ifaceName, ifTunnel, parentRefs, ifaceState.getIfIndex(), bucketId, portNumber);
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: add bucketId {} to groupId {}", bucketId, groupId);
+            mdsalManager.addBucketToTx(srcDpnId, groupId, buckt, tx);
+        } else {
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: remove bucketId {} from groupId {}", bucketId, groupId);
+            mdsalManager.removeBucketToTx(srcDpnId, groupId, bucketId, tx);
+        }
+    }
+
+    private void updateLogicalTunnelGroupOperStatus(String logicalTunnelIfaceName, Interface ifaceState,
+                                                           InterfaceParentEntry parentEntry,
+                                                           DataBroker broker, WriteTransaction tx) {
+        if (parentEntry == null) {
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: uninitialized parent entry {}", logicalTunnelIfaceName);
+            return;
+        }
+        OperStatus newOperStatus = getAggregatedOperStatus(ifaceState, parentEntry);
+        if (logicalTunnelIfaceName.equals(ifaceState.getName())) { //the current interface is logical tunnel itself
+            if (ifaceState.getOperStatus() != newOperStatus) {
+                updateInterfaceOperStatus(logicalTunnelIfaceName, ifaceState, newOperStatus, tx);
+            }
+        } else {
+            InterfaceInfo ifLogicInfo =
+                    interfaceManager.getInterfaceInfoFromOperationalDataStore(logicalTunnelIfaceName);
+            if (isLogicalTunnelStateUpdateNeeded(newOperStatus, ifLogicInfo)) {
+                InstanceIdentifier<Interface> id = ItmUtils.buildStateInterfaceId(logicalTunnelIfaceName);
+                Optional<Interface> ifState = ItmUtils.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+                if (ifState.isPresent()) {
+                    Interface ifStateLogicTunnel = ifState.get();
+                    updateInterfaceOperStatus(logicalTunnelIfaceName, ifStateLogicTunnel, newOperStatus, tx);
+                }
+            }
+        }
+    }
+
+    private boolean isLogicalTunnelStateUpdateNeeded(OperStatus newOperStatus, InterfaceInfo ifLogicInfo) {
+        return ifLogicInfo != null && ((ifLogicInfo.getOpState() == InterfaceInfo.InterfaceOpState.UP
+                && newOperStatus == OperStatus.Down)
+                || (ifLogicInfo.getOpState() == InterfaceInfo.InterfaceOpState.DOWN && newOperStatus == OperStatus.Up));
+    }
+
+    private OperStatus getAggregatedOperStatus(Interface ifaceState, InterfaceParentEntry parentEntry) {
+        String logicalTunnelName = parentEntry.getParentInterface();
+        if (!logicalTunnelName.equals(ifaceState.getName()) && ifaceState.getOperStatus() == OperStatus.Up) {
+            return OperStatus.Up;
+        }
+
+        List<InterfaceChildEntry> interfaceChildEntries = parentEntry.getInterfaceChildEntry();
+        if (interfaceChildEntries == null || interfaceChildEntries.isEmpty()) {
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: OperStatus is Down, because of the empty child list in group {}",
+                    parentEntry.getParentInterface());
+            return OperStatus.Down;
+        }
+        for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
+            String curChildInterface = interfaceChildEntry.getChildInterface();
+            if (!curChildInterface.equals(ifaceState.getName())) {
+                InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(curChildInterface);
+                if (ifInfo != null && InterfaceInfo.InterfaceOpState.UP.equals(ifInfo.getOpState())) {
+                    return OperStatus.Up;
+                }
+            }
+        }
+        return OperStatus.Down;
+    }
+
+    private void updateInterfaceOperStatus(String ifaceName, Interface ifaceState,
+                                           OperStatus st, WriteTransaction tx) {
+        LOG.debug("MULTIPLE_VxLAN_TUNNELS: update OperStatus to be {} for {}", st.toString(), ifaceName);
+        InstanceIdentifier<Interface> idLogicGroup = ItmUtils.buildStateInterfaceId(ifaceName);
+        InterfaceBuilder ifaceBuilderChild = new InterfaceBuilder(ifaceState);
+        ifaceBuilderChild.setOperStatus(st);
+        tx.merge(LogicalDatastoreType.OPERATIONAL, idLogicGroup, ifaceBuilderChild.build(), true);
+    }
+
+    private void updateLogicalTunnelAdminStatus(String logicalTunnelName, Interface ifOrigin,
+            Interface ifUpdated, InterfaceParentEntry parentEntry, WriteTransaction tx) {
+
+        if (ifOrigin == null || ifUpdated == null || ifOrigin.getAdminStatus() == ifUpdated.getAdminStatus()) {
+            return;
+        }
+        List<InterfaceChildEntry> interfaceChildEntries = parentEntry.getInterfaceChildEntry();
+        if (interfaceChildEntries == null || interfaceChildEntries.isEmpty()) {
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: empty child list in group {}", logicalTunnelName);
+            return;
+        }
+        for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
+            String curChildInterface = interfaceChildEntry.getChildInterface();
+            updateInterfaceAdminStatus(curChildInterface, ifUpdated.getAdminStatus(), tx);
+        }
+    }
+
+    private void updateInterfaceAdminStatus(String logicalTunnelName, Interface ifState, WriteTransaction tx) {
+        InterfaceInfo ifLogicTunnelInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(logicalTunnelName);
+        if (ifLogicTunnelInfo == null) {
+            return;
+        }
+        if (ifState.getAdminStatus() == AdminStatus.Up
+                && ifLogicTunnelInfo.getAdminState() != InterfaceAdminState.ENABLED) {
+            updateInterfaceAdminStatus(ifState.getName(), AdminStatus.Down, tx);
+        }
+    }
+
+    private void updateInterfaceAdminStatus(String ifaceName, AdminStatus st, WriteTransaction tx) {
+        LOG.debug("MULTIPLE_VxLAN_TUNNELS: update AdminStatus to be {} for {}", st.toString(), ifaceName);
+        InstanceIdentifier<Interface> id = ItmUtils.buildStateInterfaceId(ifaceName);
+        InterfaceBuilder ifaceBuilderChild = new InterfaceBuilder();
+        ifaceBuilderChild.setKey(new InterfaceKey(ifaceName));
+        ifaceBuilderChild.setAdminStatus(st);
+        tx.merge(LogicalDatastoreType.OPERATIONAL, id, ifaceBuilderChild.build(), true);
+    }
+
+    private class TunnelAggregationUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
+
+        private final Interface ifStateOrigin;
+        private final Interface ifStateUpdated;
+        private final DataBroker dataBroker;
+        private final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
+                                                    .interfaces.rev140508.interfaces.Interface ifaceConfig;
+        private final int ifaceAction;
+        private final InterfaceParentEntry parentEntry;
+
+        TunnelAggregationUpdateWorker(Interface ifStateOrig, Interface ifStateUpdated,
+                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
+                .interfaces.Interface iface, InterfaceParentEntry entry, int action, DataBroker broker) {
+            this.ifStateOrigin = ifStateOrig;
+            this.ifStateUpdated = ifStateUpdated;
+            this.ifaceConfig = iface;
+            this.ifaceAction = action;
+            this.dataBroker  = broker;
+            this.parentEntry = entry;
+        }
+
+        @Override
+        public List<ListenableFuture<Void>> call() throws Exception {
+            List<ListenableFuture<Void>> futures = new ArrayList<>();
+            if (ifaceAction == MOD_GROUP_TUNNEL) {
+                updateTunnelAggregationGroup(parentEntry);
+                return futures;
+            }
+            IfTunnel ifTunnel = ifaceConfig != null ? ifaceConfig.getAugmentation(IfTunnel.class) : null;
+            if (ifTunnel == null) {
+                LOG.debug("MULTIPLE_VxLAN_TUNNELS: not tunnel interface {}", ifaceConfig.getName());
+                return futures;
+            }
+            WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+            if (ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeLogicalGroup.class)) {
+                String logicTunnelIfaceName = ifStateUpdated.getName();
+                InterfaceParentEntry parentEntry = getInterfaceParentEntry(logicTunnelIfaceName);
+                updateLogicalTunnelGroupOperStatus(logicTunnelIfaceName, ifStateUpdated, parentEntry, dataBroker, tx);
+                updateLogicalTunnelAdminStatus(logicTunnelIfaceName, ifStateOrigin, ifStateUpdated,
+                                                    parentEntry, tx);
+                futures.add(tx.submit());
+                return futures;
+            }
+            if (!ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
+                LOG.debug("MULTIPLE_VxLAN_TUNNELS: wrong tunnel type {}", ifTunnel.getTunnelInterfaceType());
+                return futures;
+            }
+            ParentRefs parentRefs = ifaceConfig.getAugmentation(ParentRefs.class);
+            if (parentRefs == null) {
+                LOG.debug("MULTIPLE_VxLAN_TUNNELS: not updated parent ref for {}", ifaceConfig.getName());
+                return futures;
+            }
+            String logicTunnelIfaceName = parentRefs.getParentInterface();
+            InterfaceParentEntry groupEntry = getInterfaceParentEntry(logicTunnelIfaceName);
+            if (groupEntry == null) {
+                LOG.debug("MULTIPLE_VxLAN_TUNNELS: not found InterfaceParentEntry for {}", logicTunnelIfaceName);
+                return futures;
+            }
+            if (ifaceAction == ADD_TUNNEL) {
+                updateInterfaceAdminStatus(logicTunnelIfaceName, ifStateUpdated, tx);
+                updateTunnelAggregationGroupBucket(ifStateUpdated, ifTunnel, parentRefs, groupEntry, ifaceAction, tx);
+            } else if (ifaceAction == DEL_TUNNEL) {
+                updateTunnelAggregationGroupBucket(ifStateUpdated, ifTunnel, parentRefs, groupEntry, ifaceAction, tx);
+            }
+            updateLogicalTunnelGroupOperStatus(logicTunnelIfaceName, ifStateUpdated, groupEntry, dataBroker, tx);
+            futures.add(tx.submit());
+            return futures;
+        }
+
+        private InterfaceParentEntry getInterfaceParentEntry(String logicalGroupName) {
+            InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(logicalGroupName);
+            InstanceIdentifier.InstanceIdentifierBuilder<InterfaceParentEntry> intfIdBuilder =
+                    InstanceIdentifier.builder(InterfaceChildInfo.class)
+                            .child(InterfaceParentEntry.class, interfaceParentEntryKey);
+            InstanceIdentifier<InterfaceParentEntry> intfId = intfIdBuilder.build();
+            Optional<InterfaceParentEntry> groupChildInfo =
+                    ItmUtils.read(LogicalDatastoreType.CONFIGURATION, intfId, dataBroker);
+            return groupChildInfo.isPresent() ? groupChildInfo.get() : null;
+        }
+    }
 }
diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/listeners/InterfaceChildInfoListener.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/listeners/InterfaceChildInfoListener.java
new file mode 100644 (file)
index 0000000..b060645
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright © 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.genius.itm.listeners;
+
+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.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.itm.confighelpers.ItmTunnelAggregationHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.InterfaceChildInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class InterfaceChildInfoListener extends AsyncDataTreeChangeListenerBase<InterfaceParentEntry,
+                                                                                InterfaceChildInfoListener> {
+    private static final Logger LOG = LoggerFactory.getLogger(InterfaceChildInfoListener.class);
+    private final DataBroker dataBroker;
+    private final ItmTunnelAggregationHelper tunnelAggregationHelper;
+
+    @Inject
+    public InterfaceChildInfoListener(final DataBroker dataBroker, final ItmTunnelAggregationHelper tunnelAggregation) {
+        super(InterfaceParentEntry.class, InterfaceChildInfoListener.class);
+        this.dataBroker = dataBroker;
+        this.tunnelAggregationHelper = tunnelAggregation;
+    }
+
+    @PostConstruct
+    public void start() {
+        registerListener(LogicalDatastoreType.CONFIGURATION, this.dataBroker);
+        LOG.info("InterfaceChildInfoListener Started");
+    }
+
+    @Override
+    @PreDestroy
+    public void close() {
+        LOG.info("InterfaceChildInfoListener Closed");
+    }
+
+    @Override
+    protected InstanceIdentifier<InterfaceParentEntry> getWildCardPath() {
+        return InstanceIdentifier.create(InterfaceChildInfo.class).child(InterfaceParentEntry.class);
+    }
+
+    @Override
+    protected void remove(InstanceIdentifier<InterfaceParentEntry> key, InterfaceParentEntry data) {
+        if (tunnelAggregationHelper.isTunnelAggregationEnabled()) {
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: InterfaceChildInfoListener remove for {}", data.getParentInterface());
+            tunnelAggregationHelper.updateLogicalTunnelSelectGroup(data, dataBroker);
+        }
+    }
+
+    @Override
+    protected void update(InstanceIdentifier<InterfaceParentEntry> key, InterfaceParentEntry oldData,
+                          InterfaceParentEntry data) {
+        if (tunnelAggregationHelper.isTunnelAggregationEnabled()) {
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: InterfaceChildInfoListener update for {}", data.getParentInterface());
+            tunnelAggregationHelper.updateLogicalTunnelSelectGroup(data, dataBroker);
+        }
+    }
+
+    @Override
+    protected void add(InstanceIdentifier<InterfaceParentEntry> key, InterfaceParentEntry data) {
+        if (tunnelAggregationHelper.isTunnelAggregationEnabled()) {
+            LOG.debug("MULTIPLE_VxLAN_TUNNELS: InterfaceChildInfoListener add for {}", data.getParentInterface());
+            tunnelAggregationHelper.updateLogicalTunnelSelectGroup(data, dataBroker);
+        }
+    }
+
+    @Override
+    protected InterfaceChildInfoListener getDataTreeChangeListener() {
+        return this;
+    }
+}
index 2c86c471b49fa0ab996c575e28c328b5a8c62172..2507bf919c17178c8e6e01c31178a5c4be0983a1 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
+import org.opendaylight.genius.itm.confighelpers.ItmTunnelAggregationHelper;
 import org.opendaylight.genius.itm.confighelpers.ItmTunnelStateAddHelper;
 import org.opendaylight.genius.itm.confighelpers.ItmTunnelStateRemoveHelper;
 import org.opendaylight.genius.itm.confighelpers.ItmTunnelStateUpdateHelper;
@@ -41,13 +42,16 @@ public class InterfaceStateListener extends AsyncDataTreeChangeListenerBase<Inte
 
     private final DataBroker broker;
     private final IInterfaceManager ifaceManager;
+    private final ItmTunnelAggregationHelper tunnelAggregationHelper;
 
     @Inject
-    public InterfaceStateListener(final DataBroker dataBroker,IInterfaceManager iinterfacemanager) {
+    public InterfaceStateListener(final DataBroker dataBroker,IInterfaceManager iinterfacemanager,
+            final ItmTunnelAggregationHelper tunnelAggregation) {
 
         super(Interface.class, InterfaceStateListener.class);
         this.broker = dataBroker;
         this.ifaceManager = iinterfacemanager;
+        this.tunnelAggregationHelper = tunnelAggregation;
     }
 
     @PostConstruct
@@ -93,6 +97,9 @@ public class InterfaceStateListener extends AsyncDataTreeChangeListenerBase<Inte
             DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
             ItmTunnelAddWorker itmTunnelAddWorker = new ItmTunnelAddWorker(iface);
             jobCoordinator.enqueueJob(ITMConstants.ITM_PREFIX + iface.getName(), itmTunnelAddWorker);
+            if (tunnelAggregationHelper.isTunnelAggregationEnabled()) {
+                tunnelAggregationHelper.updateLogicalTunnelState(iface, ItmTunnelAggregationHelper.ADD_TUNNEL, broker);
+            }
         }
     }
 
@@ -105,6 +112,9 @@ public class InterfaceStateListener extends AsyncDataTreeChangeListenerBase<Inte
             DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
             ItmTunnelRemoveWorker itmTunnelRemoveWorker = new ItmTunnelRemoveWorker(iface);
             jobCoordinator.enqueueJob(ITMConstants.ITM_PREFIX + iface.getName(), itmTunnelRemoveWorker);
+            if (tunnelAggregationHelper.isTunnelAggregationEnabled()) {
+                tunnelAggregationHelper.updateLogicalTunnelState(iface, ItmTunnelAggregationHelper.DEL_TUNNEL, broker);
+            }
         }
     }
 
@@ -123,6 +133,10 @@ public class InterfaceStateListener extends AsyncDataTreeChangeListenerBase<Inte
                 ItmTunnelUpdateWorker itmTunnelUpdateWorker = new ItmTunnelUpdateWorker(original, update);
                 jobCoordinator.enqueueJob(ITMConstants.ITM_PREFIX + original.getName(), itmTunnelUpdateWorker);
             }
+            if (tunnelAggregationHelper.isTunnelAggregationEnabled()) {
+                tunnelAggregationHelper.updateLogicalTunnelState(original, update,
+                                                                 ItmTunnelAggregationHelper.MOD_TUNNEL, broker);
+            }
         }
     }