Merge " changes for REST API to make TZ specific parameters (transport zone name...
authorFaseela K <faseela.k@ericsson.com>
Tue, 4 Oct 2016 09:51:40 +0000 (09:51 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 4 Oct 2016 09:51:40 +0000 (09:51 +0000)
42 files changed:
alivenessmonitor/alivenessmonitor-api/src/main/yang/aliveness-monitor.yang
alivenessmonitor/alivenessmonitor-impl/src/main/java/org/opendaylight/genius/alivenessmonitor/internal/AlivenessProtocolHandlerARP.java
arputil/arputil-impl/src/main/java/org/opendaylight/genius/arputil/internal/ArpUtilImpl.java
commons/config-parent/pom.xml
features/pom.xml
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/IfmUtil.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/InterfacemgrProvider.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/commons/InterfaceManagerCommonUtils.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/listeners/InterfaceInventoryStateListener.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/listeners/InterfaceTopologyStateListener.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/listeners/TerminationPointStateListener.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/renderer/ovs/statehelpers/OvsInterfaceStateUpdateHelper.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/renderer/ovs/statehelpers/OvsInterfaceTopologyStateUpdateHelper.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/renderer/ovs/utilities/InterfaceBatchHandler.java [moved from interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/renderer/ovs/utilities/BatchHandler.java with 75% similarity]
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/renderer/ovs/utilities/SouthboundUtils.java
interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/rpcservice/InterfaceManagerRpcService.java
interfacemanager/interfacemanager-impl/src/test/java/org/opendaylight/genius/interfacemanager/test/TopologyStateInterfaceTest.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/listeners/TransportZoneListener.java
mdsalutil/mdsalutil-api/pom.xml
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/datastoreutils/AsyncClusteredDataChangeListenerBase.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/datastoreutils/AsyncClusteredDataTreeChangeListenerBase.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/datastoreutils/AsyncDataChangeListenerBase.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/datastoreutils/AsyncDataTreeChangeListenerBase.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/datastoreutils/DataStoreJobCoordinator.java [changed mode: 0644->0755]
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/datastoreutils/JobEntry.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/mdsalutil/ActionType.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/mdsalutil/MDSALUtil.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/mdsalutil/NWUtil.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/mdsalutil/NwConstants.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/mdsalutil/NxMatchFieldType.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/batching/ActionableResourceImpl.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/batching/DefaultBatchHandler.java [new file with mode: 0644]
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/batching/ResourceBatchingManager.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/batching/ResourceHandler.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/batching/SubTransaction.java [new file with mode: 0644]
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/batching/SubTransactionImpl.java [new file with mode: 0644]
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/clustering/ClusteringUtils.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/hwvtep/DebugEvent.java [new file with mode: 0644]
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/hwvtep/HwvtepHACache.java [new file with mode: 0644]
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/hwvtep/HwvtepSouthboundConstants.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/hwvtep/NodeEvent.java [new file with mode: 0644]
mdsalutil/mdsalutil-api/src/test/java/org/opendaylight/genius/mdsalutil/hwvtep/HwvtepHACacheTest.java [new file with mode: 0644]

index cb76b2cb87ce917735b471bdf7db6728ea57a490..8573bad8316f36daf5a325401a3cf92616c18753 100644 (file)
@@ -7,6 +7,11 @@ module aliveness-monitor {
         revision-date "2013-07-15";
     }
 
+    import ietf-yang-types {
+        prefix yang;
+        revision-date "2013-07-15";
+    }
+
     revision "2016-04-11" {
         description "YANG model describes methods for monitoring endpoints.";
     }
@@ -31,6 +36,7 @@ typedef ether-types {
                 leaf ip-address { type inet:ip-address; }
             }
             case interface {
+                 leaf mac-address { type yang:phys-address; }
                  leaf interface-ip { type inet:ip-address; }
                  leaf interface-name { type string; }
             }
index 88e808caf7490548f71b645483e18447f4548504..111014c718bd2cb34b641977e8fa483e9e09bac6 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.genius.alivenessmonitor.internal;
 import static org.opendaylight.genius.alivenessmonitor.internal.AlivenessMonitorConstants.SEPERATOR;
 import static org.opendaylight.genius.alivenessmonitor.internal.AlivenessMonitorUtil.toStringIpAddress;
 
+import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.util.concurrent.FutureCallback;
@@ -26,6 +27,7 @@ import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.packet.ARP;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
+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.genius.alivenessmonitor.rev160411.EtherTypes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.endpoint.EndpointType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.endpoint.endpoint.type.Interface;
@@ -116,42 +118,46 @@ public class AlivenessProtocolHandlerARP extends AbstractAlivenessProtocolHandle
         }
         EndpointType source = monitorInfo.getSource().getEndpointType();
         final String sourceInterface = Preconditions.checkNotNull(getInterfaceName(source),
-                                       "Source interface is required to send ARP Packet for monitoring");
+                "Source interface is required to send ARP Packet for monitoring");
 
         final String srcIp = Preconditions.checkNotNull(getIpAddress(source),
-                                    "Source Ip address is required to send ARP Packet for monitoring");
-
-        EndpointType target = monitorInfo.getDestination().getEndpointType();
-        final String targetIp = Preconditions.checkNotNull(getIpAddress(target),
-                                      "Target Ip address is required to send ARP Packet for monitoring");
-
-        if (LOG.isTraceEnabled()) {
-            LOG.trace("sendArpRequest interface {}, senderIPAddress {}, targetAddress {}", sourceInterface, srcIp, targetIp);
-        }
-
-        List<InterfaceAddress> addresses = Collections.singletonList(
-                           new InterfaceAddressBuilder().setInterface(sourceInterface)
-                                                        .setIpAddress(IpAddressBuilder.getDefaultInstance(srcIp)).build());
-        SendArpRequestInput input = new SendArpRequestInputBuilder().setInterfaceAddress(addresses)
-                                                                    .setIpaddress(IpAddressBuilder.getDefaultInstance(targetIp)).build();
-        Future<RpcResult<Void>> future = arpService.sendArpRequest(input);
-
-        final String msgFormat = String.format("Send ARP Request on interface %s to destination %s", sourceInterface, targetIp);
-        Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
-            @Override
-            public void onFailure(Throwable error) {
-                LOG.error("Error - {}", msgFormat, error);
+                "Source Ip address is required to send ARP Packet for monitoring");
+        final Optional<PhysAddress> srcMacAddressOptional = getMacAddress(source);
+        if(srcMacAddressOptional.isPresent())
+        {
+            PhysAddress srcMacAddress = srcMacAddressOptional.get();
+            EndpointType target = monitorInfo.getDestination().getEndpointType();
+            final String targetIp = Preconditions.checkNotNull(getIpAddress(target),
+                    "Target Ip address is required to send ARP Packet for monitoring");
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("sendArpRequest interface {}, senderIPAddress {}, targetAddress {}", sourceInterface, srcIp, targetIp);
+            }
+            InterfaceAddressBuilder interfaceAddressBuilder = new InterfaceAddressBuilder().setInterface(sourceInterface)
+                    .setIpAddress(IpAddressBuilder.getDefaultInstance(srcIp));
+            if (srcMacAddress != null) {
+                interfaceAddressBuilder.setMacaddress(srcMacAddress);
             }
+            List<InterfaceAddress> addresses = Collections.singletonList(interfaceAddressBuilder.build());
+            SendArpRequestInput input = new SendArpRequestInputBuilder().setInterfaceAddress(addresses)
+                    .setIpaddress(IpAddressBuilder.getDefaultInstance(targetIp)).build();
+            Future<RpcResult<Void>> future = arpService.sendArpRequest(input);
+            final String msgFormat = String.format("Send ARP Request on interface %s to destination %s", sourceInterface, targetIp);
+            Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
+                @Override
+                public void onFailure(Throwable error) {
+                    LOG.error("Error - {}", msgFormat, error);
+                }
 
-            @Override
-            public void onSuccess(RpcResult<Void> result) {
-                if(!result.isSuccessful()) {
-                    LOG.warn("Rpc call to {} failed {}", msgFormat, getErrorText(result.getErrors()));
-                } else {
-                    LOG.debug("Successful RPC Result - {}", msgFormat);
+                @Override
+                public void onSuccess(RpcResult<Void> result) {
+                    if(!result.isSuccessful()) {
+                        LOG.warn("Rpc call to {} failed {}", msgFormat, getErrorText(result.getErrors()));
+                    } else {
+                        LOG.debug("Successful RPC Result - {}", msgFormat);
+                    }
                 }
-            }
-        });
+            });
+        }
     }
 
     private String getErrorText(Collection<RpcError> errors) {
@@ -186,6 +192,14 @@ public class AlivenessProtocolHandlerARP extends AbstractAlivenessProtocolHandle
         return ipAddress;
     }
 
+    private Optional <PhysAddress> getMacAddress(EndpointType source) {
+        Optional <PhysAddress> result = Optional.absent();
+        if (source instanceof Interface) {
+            result =  Optional.of(((Interface)source).getMacAddress());
+        }
+        return result;
+    }
+
     private String getInterfaceName(EndpointType endpoint) {
         String interfaceName = null;
         if(endpoint instanceof Interface) {
index 21bc23de3d4e8d004caf67bcd4dc71f897788e70..586c04ec0aa2f110fd27d96bceb8949334ae78f2 100644 (file)
@@ -288,7 +288,6 @@ public class ArpUtilImpl implements OdlArputilService,
                     String macAddr = interfaceAddress.getMacaddress().getValue();
                     srcMac = HexEncode.bytesFromHexString(macAddr);
                 }
-
                 checkNotNull(srcMac, FAILED_TO_GET_SRC_MAC_FOR_INTERFACE,
                         interfaceName, ref.getValue());
                 checkNotNull(srcIpBytes, FAILED_TO_GET_SRC_IP_FOR_INTERFACE,
index 42a7f4ab69422f5754faf33dc4ec14b2efc2c5cf..43d854917085e7591a8b746ab58e7a448d9e25e0 100644 (file)
@@ -31,6 +31,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <model.bgp.version>2013.07.15.10-SNAPSHOT</model.bgp.version>
     <openflowplugin.version>0.4.0-SNAPSHOT</openflowplugin.version>
     <genius.ovsdb.version>1.4.0-SNAPSHOT</genius.ovsdb.version>
+    <genius.infrautils.version>1.1.0-SNAPSHOT</genius.infrautils.version>
     <liblldp.version>0.12.0-SNAPSHOT</liblldp.version>
     <karaf.shell.console.version>3.0.3</karaf.shell.console.version>
   </properties>
index a47bf315009c85d770deb8721c7f61717a4494d2..5c0b8da25b6ae4b0b6f479b663a50e445a3f7b45 100644 (file)
@@ -293,20 +293,27 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
     </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
-      <artifactId>resourcemanager-impl</artifactId>
+      <artifactId>fcapsapplication-impl</artifactId>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>resourcemanager-api</artifactId>
       <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>resourcemanager-impl</artifactId>
       <version>${project.version}</version>
-      <type>xml</type>
-      <classifier>config</classifier>
     </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
-      <artifactId>resourcemanager-api</artifactId>
+      <artifactId>resourcemanager-impl</artifactId>
       <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
     </dependency>
   </dependencies>
 </project>
index b3a776c7df6f10da08c50707bfe1f0d397253d9c..1907e6e9aa4a409b43c6017a740da9c3c78e6e4b 100755 (executable)
@@ -8,7 +8,7 @@
 package org.opendaylight.genius.interfacemanager;
 
 import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableMap;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
@@ -57,6 +57,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlanGpe;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
@@ -77,7 +78,6 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdenti
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import java.util.concurrent.Callable;
 
 import static org.opendaylight.genius.interfacemanager.globals.InterfaceInfo.InterfaceType.VLAN_INTERFACE;
 
@@ -85,14 +85,14 @@ public class IfmUtil {
     private static final Logger LOG = LoggerFactory.getLogger(IfmUtil.class);
     private static final int INVALID_ID = 0;
 
-    public static final ImmutableBiMap<Class<? extends TunnelTypeBase>, InterfaceInfo.InterfaceType> TUNNEL_TYPE_MAP =
-            new ImmutableBiMap.Builder<Class<? extends TunnelTypeBase>, InterfaceInfo.InterfaceType>()
+    private static final ImmutableMap<Class<? extends TunnelTypeBase>, InterfaceInfo.InterfaceType> TUNNEL_TYPE_MAP =
+            new ImmutableMap.Builder<Class<? extends TunnelTypeBase>, InterfaceInfo.InterfaceType>()
                     .put(TunnelTypeGre.class, InterfaceInfo.InterfaceType.GRE_TRUNK_INTERFACE)
                     .put(TunnelTypeMplsOverGre.class, InterfaceInfo.InterfaceType.MPLS_OVER_GRE)
                     .put(TunnelTypeVxlan.class, InterfaceInfo.InterfaceType.VXLAN_TRUNK_INTERFACE)
+                    .put(TunnelTypeVxlanGpe.class, InterfaceInfo.InterfaceType.VXLAN_TRUNK_INTERFACE)
                     .build();
 
-
     public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
         /*
          * NodeConnectorId is of form 'openflow:dpnid:portnum'
@@ -294,7 +294,7 @@ public class IfmUtil {
                                                                     int        actionKeyStart,
                                                                     boolean isDefaultEgress,
                                                                     int ifIndex) {
-        List<ActionInfo> result = new ArrayList<ActionInfo>();
+        List<ActionInfo> result = new ArrayList<>();
         switch (ifaceType) {
             case VLAN_INTERFACE:
                 if(isDefaultEgress) {
@@ -433,15 +433,16 @@ public class IfmUtil {
     }
 
     public static InterfaceInfo.InterfaceType getInterfaceType(Interface iface) {
-        InterfaceInfo.InterfaceType interfaceType =
-                org.opendaylight.genius.interfacemanager.globals.InterfaceInfo.InterfaceType.UNKNOWN_INTERFACE;
-        Class<? extends org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType> ifType = iface.getType();
+        InterfaceInfo.InterfaceType interfaceType = org.opendaylight.genius.interfacemanager.globals.InterfaceInfo.InterfaceType.UNKNOWN_INTERFACE;
+        Class<? extends org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType> ifType = iface
+                .getType();
 
         if (ifType.isAssignableFrom(L2vlan.class)) {
-            interfaceType =  VLAN_INTERFACE;
+            interfaceType = VLAN_INTERFACE;
         } else if (ifType.isAssignableFrom(Tunnel.class)) {
             IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
-            Class<? extends  org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase> tunnelType = ifTunnel.getTunnelInterfaceType();
+            Class<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase> tunnelType = ifTunnel
+                    .getTunnelInterfaceType();
             interfaceType = TUNNEL_TYPE_MAP.get(tunnelType);
         }
         return interfaceType;
@@ -490,15 +491,12 @@ public class IfmUtil {
         LOG.info("Unbinding Service from : {}", interfaceName);
         DataStoreJobCoordinator dataStoreJobCoordinator = DataStoreJobCoordinator.getInstance();
         dataStoreJobCoordinator.enqueueJob(interfaceName,
-                new Callable<List<ListenableFuture<Void>>>() {
-                    @Override
-                    public List<ListenableFuture<Void>> call() throws Exception {
-                        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
-                        t.delete(LogicalDatastoreType.CONFIGURATION, boundServicesInstanceIdentifier);
-                        List<ListenableFuture<Void>> futures = new ArrayList<>();
-                        futures.add(t.submit());
-                        return futures;
-                    }
+                () -> {
+                    WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+                    t.delete(LogicalDatastoreType.CONFIGURATION, boundServicesInstanceIdentifier);
+                    List<ListenableFuture<Void>> futures = new ArrayList<>();
+                    futures.add(t.submit());
+                    return futures;
                 }
         );
     }
index d94dffd63cee8bcf641b06c2cfdfa8f3799b8b64..113bb79d5581300c0a0bd2695d82cb7b3346697e 100644 (file)
@@ -41,7 +41,7 @@ import org.opendaylight.genius.interfacemanager.listeners.InterfaceTopologyState
 import org.opendaylight.genius.interfacemanager.listeners.TerminationPointStateListener;
 import org.opendaylight.genius.interfacemanager.listeners.VlanMemberConfigListener;
 import org.opendaylight.genius.interfacemanager.pmcounters.NodeConnectorStatsImpl;
-import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.BatchHandler;
+import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.InterfaceBatchHandler;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.BatchingUtils;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.IfmClusterUtils;
 import org.opendaylight.genius.interfacemanager.rpcservice.InterfaceManagerRpcService;
@@ -165,7 +165,7 @@ public class InterfacemgrProvider implements BindingAwareProvider, AutoCloseable
             createIdPool();
 
             IfmClusterUtils.registerEntityForOwnership(this, entityOwnershipService);
-            BatchingUtils.registerWithBatchManager(new BatchHandler(), this.dataBroker);
+            BatchingUtils.registerWithBatchManager(new InterfaceBatchHandler(), this.dataBroker);
             alivenessManager = rpcProviderRegistry.getRpcService(AlivenessMonitorService.class);
             interfaceManagerRpcService = new InterfaceManagerRpcService(dataBroker, mdsalManager);
             rpcRegistration = getRpcProviderRegistry().addRpcImplementation(
index 7be3c1801416c6621a0664dab907c7bc17615191..b1ebc2b16103534618fd6c5d53b2ab21854a00ab 100644 (file)
@@ -65,6 +65,9 @@ public class InterfaceManagerCommonUtils {
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceManagerCommonUtils.class);
     private static ConcurrentHashMap<String, Interface> interfaceConfigMap = new ConcurrentHashMap<>();
     private static ConcurrentHashMap<String, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceStateMap = new ConcurrentHashMap<>();
+    private static ConcurrentHashMap<String, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus> bfdStateMap =
+            new ConcurrentHashMap<String, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus>();
+
     private static final String NOVA_OR_TUNNEL_PORT_REGEX = "(tap|vhu)[0-9a-f]{8}-[0-9a-f]{2}|tun[0-9a-f]{11}";
     private static final Pattern pattern = Pattern.compile(NOVA_OR_TUNNEL_PORT_REGEX);
 
@@ -334,6 +337,12 @@ public class InterfaceManagerCommonUtils {
         }
     }
 
+    public static boolean checkIfBfdStateIsDown(String interfaceName){
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus =
+                InterfaceManagerCommonUtils.getBfdStateFromCache(interfaceName);
+        return (operStatus == org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down);
+    }
+
     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface addStateEntry(
             Interface interfaceInfo, String interfaceName, WriteTransaction transaction, IdManagerService idManager,
             PhysAddress physAddress,
@@ -344,7 +353,8 @@ public class InterfaceManagerCommonUtils {
         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
         Integer ifIndex = null;
         if (interfaceInfo != null) {
-            if (!interfaceInfo.isEnabled()) {
+            if(!interfaceInfo.isEnabled() || (InterfaceManagerCommonUtils.isTunnelInterface(interfaceInfo) &&
+                    checkIfBfdStateIsDown(interfaceInfo.getName()))){
                 operStatus = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
             }
 
@@ -464,6 +474,19 @@ public class InterfaceManagerCommonUtils {
         interfaceStateMap.remove(iface.getName());
     }
 
+    public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus getBfdStateFromCache(String interfaceName) {
+        return bfdStateMap.get(interfaceName);
+    }
+
+    public static void addBfdStateToCache(String interfaceName,
+                                          org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus) {
+        bfdStateMap.put(interfaceName, operStatus);
+    }
+
+    public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus removeBfdStateFromCache(String interfaceName){
+        return bfdStateMap.remove(interfaceName);
+    }
+
     public static boolean isNovaOrTunnelPort(String portName) {
 
         Matcher matcher = pattern.matcher(portName);
index 84d4e4151407de1a66ad4615e78bc0a3c53c5ebc..8ba42de682384ef56a1983c90ad5f3846641d234 100644 (file)
@@ -86,18 +86,10 @@ public class InterfaceInventoryStateListener extends AsyncClusteredDataTreeChang
                 String portName = flowCapableNodeConnectorOld.getName();
                 NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
 
-                //VM Migration: Skip OFPPR_DELETE event received after OFPPR_ADD for same interface from Older DPN
-                NodeConnectorId nodeConnectorIdOld = IfmUtil.getNodeConnectorIdFromInterface(portName, dataBroker);
-                if (InterfaceManagerCommonUtils.isNovaOrTunnelPort(portName)) {
-                    if (nodeConnectorIdOld != null && !nodeConnectorId.equals(nodeConnectorIdOld)) {
-                        LOG.debug("Dropping the NodeConnector Remove Event for the interface: {}, {}, {}", portName, nodeConnectorId, nodeConnectorIdOld);
-                        return;
-                    }
-                } else {
+                if (!InterfaceManagerCommonUtils.isNovaOrTunnelPort(portName)) {
                     portName = getDpnPrefixedPortName(nodeConnectorId, portName);
                 }
-                boolean isNodePresent = InterfaceManagerCommonUtils.isNodePresent(dataBroker, nodeConnectorId);
-                remove(nodeConnectorId, nodeConnectorIdOld, flowCapableNodeConnectorOld, portName, isNodePresent);
+                remove(nodeConnectorId, null, flowCapableNodeConnectorOld, portName, true);
             }
         });
     }
@@ -133,8 +125,7 @@ public class InterfaceInventoryStateListener extends AsyncClusteredDataTreeChang
                     NodeConnectorId nodeConnectorIdOld = IfmUtil.getNodeConnectorIdFromInterface(portName, dataBroker);
                     if (nodeConnectorIdOld != null && !nodeConnectorId.equals(nodeConnectorIdOld)) {
                         LOG.debug("Triggering NodeConnector Remove Event for the interface: {}, {}, {}", portName, nodeConnectorId, nodeConnectorIdOld);
-                        boolean isNodePresent = InterfaceManagerCommonUtils.isNodePresent(dataBroker, nodeConnectorIdOld);
-                        remove(nodeConnectorId, nodeConnectorIdOld, fcNodeConnectorNew, portName, isNodePresent);
+                        remove(nodeConnectorId, nodeConnectorIdOld, fcNodeConnectorNew, portName, false);
                         //Adding a delay of 10sec for VM migration, so applications can process remove and add events
                         try {
                             Thread.sleep(IfmConstants.DELAY_TIME_IN_MILLISECOND);
@@ -154,10 +145,11 @@ public class InterfaceInventoryStateListener extends AsyncClusteredDataTreeChang
     }
 
     private void remove(NodeConnectorId nodeConnectorIdNew, NodeConnectorId nodeConnectorIdOld,
-                        FlowCapableNodeConnector fcNodeConnectorNew, String portName, boolean isNodePresent) {
+                        FlowCapableNodeConnector fcNodeConnectorNew, String portName, boolean isNetworkEvent) {
+        boolean isNodePresent = InterfaceManagerCommonUtils.isNodePresent(dataBroker, nodeConnectorIdNew);
         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
-        InterfaceStateRemoveWorker portStateRemoveWorker = new InterfaceStateRemoveWorker(idManager,
-                nodeConnectorIdNew, nodeConnectorIdOld, fcNodeConnectorNew, portName, isNodePresent);
+        InterfaceStateRemoveWorker portStateRemoveWorker = new InterfaceStateRemoveWorker(idManager, nodeConnectorIdNew,
+                nodeConnectorIdOld, fcNodeConnectorNew, portName, isNodePresent, isNetworkEvent, true);
         coordinator.enqueueJob(portName, portStateRemoveWorker, IfmConstants.JOB_MAX_RETRIES);
     }
 
@@ -253,37 +245,54 @@ public class InterfaceInventoryStateListener extends AsyncClusteredDataTreeChang
 
     private class InterfaceStateRemoveWorker implements Callable {
         private final NodeConnectorId nodeConnectorIdNew;
-        private final NodeConnectorId nodeConnectorIdOld;
+        private NodeConnectorId nodeConnectorIdOld;
         FlowCapableNodeConnector fcNodeConnectorOld;
         private final String interfaceName;
         private final IdManagerService idManager;
         private final boolean isNodePresent;
+        private final boolean isNetworkEvent;
+        private final boolean isParentInterface;
 
         public InterfaceStateRemoveWorker(IdManagerService idManager, NodeConnectorId nodeConnectorIdNew,
                                           NodeConnectorId nodeConnectorIdOld,
                                           FlowCapableNodeConnector fcNodeConnectorOld,
                                           String portName,
-                                          boolean isNodePresent) {
+                                          boolean isNodePresent,
+                                          boolean isNetworkEvent,
+                                          boolean isParentInterface) {
             this.nodeConnectorIdNew = nodeConnectorIdNew;
             this.nodeConnectorIdOld = nodeConnectorIdOld;
             this.fcNodeConnectorOld = fcNodeConnectorOld;
             this.interfaceName = portName;
             this.idManager = idManager;
             this.isNodePresent = isNodePresent;
+            this.isNetworkEvent = isNetworkEvent;
+            this.isParentInterface = isParentInterface;
         }
 
         @Override
         public Object call() throws Exception {
             // If another renderer(for eg : CSS) needs to be supported, check can be performed here
             // to call the respective helpers.
-            List<ListenableFuture<Void>> futures = OvsInterfaceStateRemoveHelper.removeInterfaceStateConfiguration(idManager, mdsalApiManager, alivenessMonitorService,
+
+            List<ListenableFuture<Void>> futures = null;
+            //VM Migration: Skip OFPPR_DELETE event received after OFPPR_ADD for same interface from Older DPN
+            if (isParentInterface && isNetworkEvent) {
+                nodeConnectorIdOld = IfmUtil.getNodeConnectorIdFromInterface(interfaceName, dataBroker);
+                if(nodeConnectorIdOld != null && !nodeConnectorIdNew.equals(nodeConnectorIdOld)) {
+                    LOG.debug("Dropping the NodeConnector Remove Event for the interface: {}, {}, {}", interfaceName, nodeConnectorIdNew, nodeConnectorIdOld);
+                    return futures;
+                }
+            }
+
+            futures = OvsInterfaceStateRemoveHelper.removeInterfaceStateConfiguration(idManager, mdsalApiManager, alivenessMonitorService,
                     nodeConnectorIdNew, nodeConnectorIdOld, dataBroker, interfaceName, fcNodeConnectorOld, isNodePresent);
 
             List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(dataBroker, interfaceName);
             for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
                 // Fetch all interfaces on this port and trigger remove worker for each of them
-                InterfaceStateRemoveWorker interfaceStateRemoveWorker = new InterfaceStateRemoveWorker(idManager,
-                        nodeConnectorIdNew, nodeConnectorIdOld, fcNodeConnectorOld, interfaceChildEntry.getChildInterface(), isNodePresent);
+                InterfaceStateRemoveWorker interfaceStateRemoveWorker = new InterfaceStateRemoveWorker(idManager, nodeConnectorIdNew,
+                        nodeConnectorIdOld, fcNodeConnectorOld, interfaceChildEntry.getChildInterface(), isNodePresent, isNetworkEvent, false);
                 DataStoreJobCoordinator.getInstance().enqueueJob(interfaceName, interfaceStateRemoveWorker);
             }
             return futures;
index 77f6f9320bab0def30ae1ef62fddcebe24e86c21..fee90fdf206487d7298267886d8662523fa7b2d2 100644 (file)
@@ -10,13 +10,16 @@ package org.opendaylight.genius.interfacemanager.listeners;
 import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
 import org.opendaylight.genius.datastoreutils.AsyncDataChangeListenerBase;
+import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.interfacemanager.IfmConstants;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceTopologyStateAddHelper;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceTopologyStateRemoveHelper;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceTopologyStateUpdateHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
@@ -28,7 +31,7 @@ import org.slf4j.LoggerFactory;
 import java.util.List;
 import java.util.concurrent.Callable;
 
-public class InterfaceTopologyStateListener extends AsyncDataChangeListenerBase<OvsdbBridgeAugmentation, InterfaceTopologyStateListener> {
+public class InterfaceTopologyStateListener extends AsyncDataTreeChangeListenerBase<OvsdbBridgeAugmentation, InterfaceTopologyStateListener> {
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceTopologyStateListener.class);
     private DataBroker dataBroker;
 
@@ -44,15 +47,10 @@ public class InterfaceTopologyStateListener extends AsyncDataChangeListenerBase<
     }
 
     @Override
-    protected DataChangeListener getDataChangeListener() {
+    protected InterfaceTopologyStateListener getDataTreeChangeListener() {
         return InterfaceTopologyStateListener.this;
     }
 
-    @Override
-    protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
-        return AsyncDataBroker.DataChangeScope.ONE;
-    }
-
     @Override
     protected void remove(InstanceIdentifier<OvsdbBridgeAugmentation> identifier, OvsdbBridgeAugmentation bridgeOld) {
         LOG.debug("Received Remove DataChange Notification for identifier: {}, ovsdbBridgeAugmentation: {}",
@@ -67,11 +65,13 @@ public class InterfaceTopologyStateListener extends AsyncDataChangeListenerBase<
                           OvsdbBridgeAugmentation bridgeNew) {
         LOG.debug("Received Update DataChange Notification for identifier: {}, ovsdbBridgeAugmentation old: {}, new: {}.",
                 identifier, bridgeOld, bridgeNew);
-        if(bridgeOld.getDatapathId()== null && bridgeNew.getDatapathId()!= null){
+        DatapathId oldDpid = bridgeOld.getDatapathId();
+        DatapathId newDpid = bridgeNew.getDatapathId();
+        if(oldDpid == null && newDpid != null){
             DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
             RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, bridgeNew);
             jobCoordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker, IfmConstants.JOB_MAX_RETRIES);
-        } else if(!bridgeOld.getDatapathId().equals(bridgeNew.getDatapathId())){
+        } else if(oldDpid != null && !oldDpid.equals(newDpid)){
             DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
             RendererStateUpdateWorker rendererStateAddWorker = new RendererStateUpdateWorker(identifier, bridgeNew, bridgeOld);
             jobCoordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker, IfmConstants.JOB_MAX_RETRIES);
index 911882d888354d609ab8bc27dbfa5dc264f5ad06..325065dc007ba2ade62b254eff176b2a03c79935 100644 (file)
@@ -11,9 +11,11 @@ import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.AsyncDataChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.interfacemanager.IfmConstants;
+import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceTopologyStateUpdateHelper;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
@@ -27,7 +29,7 @@ import org.slf4j.LoggerFactory;
 import java.util.List;
 import java.util.concurrent.Callable;
 
-public class TerminationPointStateListener extends AsyncDataChangeListenerBase<OvsdbTerminationPointAugmentation, TerminationPointStateListener> {
+public class TerminationPointStateListener extends AsyncClusteredDataTreeChangeListenerBase<OvsdbTerminationPointAugmentation, TerminationPointStateListener> {
     private static final Logger LOG = LoggerFactory.getLogger(TerminationPointStateListener.class);
     private DataBroker dataBroker;
 
@@ -43,18 +45,20 @@ public class TerminationPointStateListener extends AsyncDataChangeListenerBase<O
     }
 
     @Override
-    protected DataChangeListener getDataChangeListener() {
+    protected TerminationPointStateListener getDataTreeChangeListener() {
         return TerminationPointStateListener.this;
     }
 
-    @Override
-    protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
-        return AsyncDataBroker.DataChangeScope.SUBTREE;
-    }
-
     @Override
     protected void remove(InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
                           OvsdbTerminationPointAugmentation tpOld) {
+        LOG.debug("Received remove DataChange Notification for ovsdb termination point {}", tpOld.getName());
+        if (tpOld.getInterfaceBfdStatus() != null) {
+            LOG.debug("Received termination point removed notification with bfd status values {}", tpOld.getName());
+            DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+            RendererStateRemoveWorker rendererStateRemoveWorker = new RendererStateRemoveWorker(tpOld);
+            jobCoordinator.enqueueJob(tpOld.getName(), rendererStateRemoveWorker);
+        }
     }
 
     @Override
@@ -104,4 +108,20 @@ public class TerminationPointStateListener extends AsyncDataChangeListenerBase<O
                     terminationPointNew);
         }
     }
+
+    private class RendererStateRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
+        OvsdbTerminationPointAugmentation terminationPointOld;
+
+
+        public RendererStateRemoveWorker(OvsdbTerminationPointAugmentation tpNew) {
+            this.terminationPointOld = tpNew;
+        }
+
+        @Override
+        public List<ListenableFuture<Void>> call() throws Exception {
+            LOG.debug("Removing bfd state from cache, if any, for {}", terminationPointOld.getName());
+            InterfaceManagerCommonUtils.removeBfdStateFromCache(terminationPointOld.getName());
+            return null;
+        }
+    }
 }
index 4bc45165bdcc0f627871d24f767b2f935148bdc2..74c7d6e05752b56484fc57dc1a45c40a64c9a0ed 100644 (file)
@@ -63,6 +63,19 @@ public class OvsInterfaceStateUpdateHelper {
             return futures;
         }
 
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
+                InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
+
+        // For tunnels, derive the final opstate based on the bfd tunnel monitoring status
+        if(modifyTunnel(iface, opstateModified) && InterfaceManagerCommonUtils.checkIfBfdStateIsDown(iface.getName())){
+            operStatusNew = Interface.OperStatus.Down;
+            opstateModified = operStatusNew.equals(operStatusOld);
+        }
+
+        if (!opstateModified && !hardwareAddressModified) {
+            LOG.debug("If State entry for port: {} Not Modified.", interfaceName);
+            return futures;
+        }
         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
         if (hardwareAddressModified) {
             LOG.debug("Hw-Address Modified for Port: {}", interfaceName);
@@ -70,9 +83,8 @@ public class OvsInterfaceStateUpdateHelper {
             ifaceBuilder.setPhysAddress(physAddress);
         }
         // modify the attributes in interface operational DS
-        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
-                handleInterfaceStateUpdates(interfaceName, transaction, dataBroker,
-                        ifaceBuilder, opstateModified, flowCapableNodeConnectorNew.getName(), operStatusNew);
+        handleInterfaceStateUpdates(iface, transaction, dataBroker,
+                        ifaceBuilder, opstateModified, interfaceName, flowCapableNodeConnectorNew.getName(), operStatusNew);
 
         // start/stop monitoring based on opState
         if(modifyTunnel(iface, opstateModified)){
@@ -91,8 +103,9 @@ public class OvsInterfaceStateUpdateHelper {
 
         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
-                handleInterfaceStateUpdates(interfaceName,transaction, dataBroker,
-                        ifaceBuilder, true, flowCapableNodeConnector.getName(),
+                InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
+        handleInterfaceStateUpdates(iface,transaction, dataBroker,
+                        ifaceBuilder, true, interfaceName, flowCapableNodeConnector.getName(),
                         Interface.OperStatus.Unknown);
         if (InterfaceManagerCommonUtils.isTunnelInterface(iface)){
             handleTunnelMonitoringUpdates(alivenessMonitorService, dataBroker, iface.getAugmentation(IfTunnel.class),
@@ -108,28 +121,22 @@ public class OvsInterfaceStateUpdateHelper {
         return operStatus;
     }
 
-    public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
-    handleInterfaceStateUpdates(String interfaceName, WriteTransaction transaction,
-                                DataBroker dataBroker, InterfaceBuilder ifaceBuilder, boolean opStateModified,
-                                String portName,
-                                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opState){
-        LOG.debug("updating interface state entry for {}", interfaceName);
-        InstanceIdentifier<Interface> ifStateId = IfmUtil.buildStateInterfaceId(interfaceName);
-        ifaceBuilder.setKey(new InterfaceKey(interfaceName));
-        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
-                InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
+    public static void handleInterfaceStateUpdates(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+                                                   WriteTransaction transaction, DataBroker dataBroker, InterfaceBuilder ifaceBuilder, boolean opStateModified,
+                                                   String interfaceName, String portName, Interface.OperStatus opState){
         // if interface config DS is null, do the update only for the lower-layer-interfaces
         // which have no corresponding config entries
-        if(iface == null && interfaceName != portName){
-            return null;
+        if(iface == null && !interfaceName.equals(portName)) {
+            return;
         }
+        LOG.debug("updating interface state entry for {}", interfaceName);
+        InstanceIdentifier<Interface> ifStateId = IfmUtil.buildStateInterfaceId(interfaceName);
+        ifaceBuilder.setKey(new InterfaceKey(interfaceName));
         if (modifyOpState(iface, opStateModified)) {
             LOG.debug("updating interface oper status as {} for {}", opState.name(), interfaceName);
             ifaceBuilder.setOperStatus(opState);
         }
         transaction.merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build(), false);
-
-        return iface;
     }
 
     public static void handleTunnelMonitoringUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
index f1fef81d30253fb042b2e8c29d1954e9b014aa79..b1119d20c2844ac95d35599e1f9e6872132cf031 100644 (file)
@@ -10,10 +10,13 @@ package org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers;
 import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.interfacemanager.IfmUtil;
 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
+import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.IfmClusterUtils;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils;
+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.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdStatus;
@@ -25,6 +28,7 @@ import org.slf4j.LoggerFactory;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Callable;
 
 public class OvsInterfaceTopologyStateUpdateHelper {
     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceTopologyStateUpdateHelper.class);
@@ -61,19 +65,32 @@ public class OvsInterfaceTopologyStateUpdateHelper {
         return futures;
     }
 
-    public static List<ListenableFuture<Void>> updateTunnelState(DataBroker dataBroker,
-                                                                 OvsdbTerminationPointAugmentation terminationPointNew) {
-        List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
-
-        if (InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(terminationPointNew.getName(), dataBroker) == null) {
-            return futures;
+    public static List<ListenableFuture<Void>> updateTunnelState(final DataBroker dataBroker,
+                                                                 final OvsdbTerminationPointAugmentation terminationPointNew) {
+        final Interface interfaceState = InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(terminationPointNew.getName(), dataBroker);
+        final Interface.OperStatus interfaceOperStatus = getTunnelOpState(terminationPointNew.getInterfaceBfdStatus());
+        InterfaceManagerCommonUtils.addBfdStateToCache(terminationPointNew.getName(), interfaceOperStatus);
+        if(interfaceState != null && interfaceState.getOperStatus() != Interface.OperStatus.Unknown) {
+            IfmClusterUtils.runOnlyInLeaderNode(new Runnable() {
+                @Override
+                public void run() {
+                    DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+                    jobCoordinator.enqueueJob(terminationPointNew.getName(), new Callable<List<ListenableFuture<Void>>>() {
+                        @Override
+                        public List<ListenableFuture<Void>> call() throws Exception {
+                            // update opstate of interface if TEP has gone down/up as a result of BFD monitoring
+                            final List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
+                            LOG.debug("updating tunnel state for interface {}", terminationPointNew.getName());
+                            WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+                            InterfaceManagerCommonUtils.updateOpState(transaction, terminationPointNew.getName(), interfaceOperStatus);
+                            futures.add(transaction.submit());
+                            return futures;
+                        }
+                    });
+                }
+            });
         }
-        // update opstate of interface if TEP has gone down/up as a result of BFD monitoring
-        LOG.debug("updating tunnel state for interface {}", terminationPointNew.getName());
-        WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
-        InterfaceManagerCommonUtils.updateOpState(transaction, terminationPointNew.getName(), getTunnelOpState(terminationPointNew.getInterfaceBfdStatus()));
-        futures.add(transaction.submit());
-        return futures;
+        return null;
     }
 
     private static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus
@@ -12,15 +12,15 @@ 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.utils.batching.ResourceHandler;
-//import org.opendaylight.genius.utils.batching.SubTransaction;
-//import org.opendaylight.genius.utils.batching.SubTransactionImpl;
+import org.opendaylight.genius.utils.batching.SubTransaction;
+import org.opendaylight.genius.utils.batching.SubTransactionImpl;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 import java.util.List;
 
-public class BatchHandler implements ResourceHandler {
-    public void update(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier, Object original, Object update) {
+public class InterfaceBatchHandler implements ResourceHandler {
+    public void update(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier, Object original, Object update,List<SubTransaction> transactionObjects) {
         if (update != null && !(update instanceof DataObject)) {
             return;
         }
@@ -29,11 +29,10 @@ public class BatchHandler implements ResourceHandler {
         }
         tx.merge(datastoreType, identifier, (DataObject)update, true);
 
-        // TODO enable retries
-        //buildSubTransactions(transactionObjects, identifier, update, SubTransaction.UPDATE);
+        buildSubTransactions(transactionObjects, identifier, update, SubTransaction.UPDATE);
     }
 
-    public void create(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier, Object data) {
+    public void create(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier, Object data,List<SubTransaction> transactionObjects) {
         if (data != null && !(data instanceof DataObject)) {
             return;
         }
@@ -41,11 +40,11 @@ public class BatchHandler implements ResourceHandler {
             return;
         }
         tx.put(datastoreType, identifier, (DataObject)data, true);
-        // TODO enable retries
-        //buildSubTransactions(transactionObjects, identifier, data, SubTransaction.CREATE);
+
+        buildSubTransactions(transactionObjects, identifier, data, SubTransaction.CREATE);
     }
 
-    public void delete(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier, Object data) {
+    public void delete(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier, Object data,List<SubTransaction> transactionObjects) {
         if (data != null && !(data instanceof DataObject)) {
             return;
         }
@@ -54,8 +53,7 @@ public class BatchHandler implements ResourceHandler {
         }
         tx.delete(datastoreType, identifier);
 
-        // TODO enable retries
-        //buildSubTransactions(transactionObjects, identifier, data, SubTransaction.DELETE);
+        buildSubTransactions(transactionObjects, identifier, data, SubTransaction.DELETE);
     }
 
     public DataBroker getResourceBroker() {
@@ -74,8 +72,7 @@ public class BatchHandler implements ResourceHandler {
         return LogicalDatastoreType.CONFIGURATION;
     }
 
-    //TODO
-    /*private void buildSubTransactions(List<SubTransaction> transactionObjects, InstanceIdentifier identifier,
+    private void buildSubTransactions(List<SubTransaction> transactionObjects, InstanceIdentifier identifier,
                                               Object data, short subTransactionType) {
         // enable retries
         SubTransaction subTransaction = new SubTransactionImpl();
@@ -83,5 +80,5 @@ public class BatchHandler implements ResourceHandler {
         subTransaction.setInstance(data);
         subTransaction.setAction(subTransactionType);
         transactionObjects.add(subTransaction);
-    }*/
+    }
 }
index b2ee2c0ba71067dc8832181c0110db01b3a14a80..77c74682c2546940a76c5fff03bf6d52887cadc0 100644 (file)
@@ -70,7 +70,7 @@ public class SouthboundUtils {
     static final String BFD_PARAM_CPATH_DOWN = "cpath_down";
     static final String BFD_PARAM_CHECK_TNL_KEY = "check_tnl_key";
 
-    // bfd params
+    // BFD parameters
     public static final String BFD_OP_STATE = "state";
     public static final String BFD_STATE_UP = "up";
     private static final String BFD_MIN_RX_VAL = "1000";
@@ -84,8 +84,9 @@ public class SouthboundUtils {
     private static final String TUNNEL_OPTIONS_KEY = "key";
     private static final String TUNNEL_OPTIONS_LOCAL_IP = "local_ip";
     private static final String TUNNEL_OPTIONS_REMOTE_IP = "remote_ip";
+    private static final String TUNNEL_OPTIONS_DESTINATION_PORT = "dst_port";
 
-    // Options for VxLAN-GPE + NSH tunnels
+    // Option values for VxLAN-GPE + NSH tunnels
     private static final String TUNNEL_OPTIONS_EXTS = "exts";
     private static final String TUNNEL_OPTIONS_NSI = "nsi";
     private static final String TUNNEL_OPTIONS_NSP = "nsp";
@@ -94,10 +95,13 @@ public class SouthboundUtils {
     private static final String TUNNEL_OPTIONS_NSHC3 = "nshc3";
     private static final String TUNNEL_OPTIONS_NSHC4 = "nshc4";
 
-    // Values for VxLAN-GPE + NSH tunnels
+    // Option values for VxLAN-GPE + NSH tunnels
     private static final String TUNNEL_OPTIONS_VALUE_FLOW = "flow";
     private static final String TUNNEL_OPTIONS_VALUE_GPE = "gpe";
+     // UDP port for VxLAN-GPE Tunnels
+    private static final String TUNNEL_OPTIONS_VALUE_GPE_DESTINATION_PORT = "4880";
 
+    //
     public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
 
     // To keep the mapping between Tunnel Types and Tunnel Interfaces
@@ -118,7 +122,7 @@ public class SouthboundUtils {
     }
 
     /*
-     * add all tunnels ports corresponding to the bridge to the topology config
+     * Add all tunnels ports corresponding to the bridge to the topology config
      * DS
      */
     public static void addAllPortsToBridge(BridgeEntry bridgeEntry, DataBroker dataBroker,
@@ -220,6 +224,8 @@ public class SouthboundUtils {
             options.put(TUNNEL_OPTIONS_NSHC2, TUNNEL_OPTIONS_VALUE_FLOW);
             options.put(TUNNEL_OPTIONS_NSHC3, TUNNEL_OPTIONS_VALUE_FLOW);
             options.put(TUNNEL_OPTIONS_NSHC4, TUNNEL_OPTIONS_VALUE_FLOW);
+            // VxLAN-GPE interfaces will not use the default UDP port to avoid problems with other meshes
+            options.put(TUNNEL_OPTIONS_DESTINATION_PORT, TUNNEL_OPTIONS_VALUE_GPE_DESTINATION_PORT);
         }
         addTerminationPoint(bridgeIid, portName, vlanId, type, options, ifTunnel);
     }
@@ -330,6 +336,5 @@ public class SouthboundUtils {
             return true;
         }
         return false;
-
     }
 }
index 7947feddeb6d3beb4f6aa181cf20a4b2a5935ce6..69887087f8aba50d06b615a55424dd3fd3d23b13 100644 (file)
@@ -106,27 +106,42 @@ public class InterfaceManagerRpcService implements OdlInterfaceRpcService {
             BigInteger dpId = null;
             InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
             Interface interfaceInfo = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+            if (interfaceInfo == null) {
+                rpcResultBuilder = getRpcErrorResultForGetDpnIdRpc(interfaceName, "missing Interface in Config DataStore");
+                return Futures.immediateFuture(rpcResultBuilder.build());
+            }
             if (Tunnel.class.equals(interfaceInfo.getType())) {
                 ParentRefs parentRefs = interfaceInfo.getAugmentation(ParentRefs.class);
                 dpId = parentRefs.getDatapathNodeIdentifier();
             } else {
                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
                         InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName, dataBroker);
-                String lowerLayerIf = ifState.getLowerLayerIf().get(0);
-                NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
-                dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+                if (ifState != null) {
+                    String lowerLayerIf = ifState.getLowerLayerIf().get(0);
+                    NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
+                    dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+                } else {
+                     rpcResultBuilder = getRpcErrorResultForGetDpnIdRpc(interfaceName, "missing Interface-state");
+                     return Futures.immediateFuture(rpcResultBuilder.build());
+                }
             }
             GetDpidFromInterfaceOutputBuilder output = new GetDpidFromInterfaceOutputBuilder().setDpid(
                     (dpId));
             rpcResultBuilder = RpcResultBuilder.success();
             rpcResultBuilder.withResult(output.build());
         } catch (Exception e) {
-            LOG.error("Retrieval of datapath id for the key {} failed due to {}", interfaceName, e);
-            rpcResultBuilder = RpcResultBuilder.failed();
+            rpcResultBuilder = getRpcErrorResultForGetDpnIdRpc(interfaceName, e.getMessage());
         }
         return Futures.immediateFuture(rpcResultBuilder.build());
     }
 
+    private RpcResultBuilder<GetDpidFromInterfaceOutput> getRpcErrorResultForGetDpnIdRpc(String interfaceName, String errMsg) {
+        errMsg = String.format("Retrieval of datapath id for the key {%s} failed due to %s", interfaceName, errMsg);
+        LOG.error(errMsg);
+        RpcResultBuilder<GetDpidFromInterfaceOutput> rpcResultBuilder = RpcResultBuilder.<GetDpidFromInterfaceOutput>failed().withError(RpcError.ErrorType.APPLICATION, errMsg);
+        return rpcResultBuilder;
+    }
+
     @Override
     public Future<RpcResult<Void>> createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
@@ -256,7 +271,12 @@ public class InterfaceManagerRpcService implements OdlInterfaceRpcService {
         try {
             InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
             Interface interfaceInfo = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
-
+            if (interfaceInfo == null) {
+                String errMsg = String.format("Retrieval of Interface Type for the key {%s} failed due to missing Interface in Config DataStore", interfaceName);
+                LOG.error(errMsg);
+                rpcResultBuilder = RpcResultBuilder.<GetInterfaceTypeOutput>failed().withError(RpcError.ErrorType.APPLICATION, errMsg);
+                return Futures.immediateFuture(rpcResultBuilder.build());
+            }
             GetInterfaceTypeOutputBuilder output = new GetInterfaceTypeOutputBuilder().setInterfaceType(interfaceInfo.getType());
             rpcResultBuilder = RpcResultBuilder.success();
             rpcResultBuilder.withResult(output.build());
@@ -274,7 +294,12 @@ public class InterfaceManagerRpcService implements OdlInterfaceRpcService {
         try {
             InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
             Interface interfaceInfo = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
-
+            if (interfaceInfo == null) {
+                String errMsg = String.format("Retrieval of Tunnel Type for the key {%s} failed due to missing Interface in Config DataStore", interfaceName);
+                LOG.error(errMsg);
+                rpcResultBuilder = RpcResultBuilder.<GetTunnelTypeOutput>failed().withError(RpcError.ErrorType.APPLICATION, errMsg);
+                return Futures.immediateFuture(rpcResultBuilder.build());
+            }
             if (Tunnel.class.equals(interfaceInfo.getType())) {
                 IfTunnel tnl = interfaceInfo.getAugmentation(IfTunnel.class);
                 Class <? extends TunnelTypeBase> tun_type = tnl.getTunnelInterfaceType();
@@ -321,22 +346,32 @@ public class InterfaceManagerRpcService implements OdlInterfaceRpcService {
             long portNo = 0;
             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
                     InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName, dataBroker);
-            String lowerLayerIf = ifState.getLowerLayerIf().get(0);
-            NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
-            dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
-            portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
-            // FIXME Assuming portName and interfaceName are same
-            GetPortFromInterfaceOutputBuilder output = new GetPortFromInterfaceOutputBuilder().setDpid(dpId).
-                    setPortname(interfaceName).setPortno(Long.valueOf(portNo));
-            rpcResultBuilder = RpcResultBuilder.success();
-            rpcResultBuilder.withResult(output.build());
+            if (ifState != null) {
+                String lowerLayerIf = ifState.getLowerLayerIf().get(0);
+                NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
+                dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+                portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+                // FIXME Assuming portName and interfaceName are same
+                GetPortFromInterfaceOutputBuilder output = new GetPortFromInterfaceOutputBuilder().setDpid(dpId).
+                        setPortname(interfaceName).setPortno(Long.valueOf(portNo));
+                rpcResultBuilder = RpcResultBuilder.success();
+                rpcResultBuilder.withResult(output.build());
+            } else {
+                rpcResultBuilder = getRpcErrorResultForGetPortRpc(interfaceName, "missing Interface state");
+            }
         }catch(Exception e){
-            LOG.error("Retrieval of lport tag for the key {} failed due to {}" ,input.getIntfName(), e);
-            rpcResultBuilder = RpcResultBuilder.failed();
+            rpcResultBuilder = getRpcErrorResultForGetPortRpc(interfaceName, e.getMessage());
         }
         return Futures.immediateFuture(rpcResultBuilder.build());
     }
 
+    private RpcResultBuilder<GetPortFromInterfaceOutput> getRpcErrorResultForGetPortRpc(String interfaceName, String errMsg) {
+        errMsg = String.format("Retrieval of Port for the key {%s} failed due to %s", interfaceName, errMsg);
+        LOG.error(errMsg);
+        RpcResultBuilder<GetPortFromInterfaceOutput> rpcResultBuilder = RpcResultBuilder.<GetPortFromInterfaceOutput>failed().withError(RpcError.ErrorType.APPLICATION, errMsg);
+        return rpcResultBuilder;
+    }
+
     @Override
     public Future<RpcResult<GetNodeconnectorIdFromInterfaceOutput>> getNodeconnectorIdFromInterface(GetNodeconnectorIdFromInterfaceInput input) {
         String interfaceName = input.getIntfName();
index f16c442e36985db001138b8d8ad6db9038aafab3..681b1bf6d0913b3ec013cb3f03f837f9a83a3edf 100644 (file)
@@ -18,6 +18,7 @@ import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -30,6 +31,7 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.interfacemanager.IfmUtil;
+import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
 import org.opendaylight.genius.interfacemanager.renderer.hwvtep.utilities.SouthboundUtils;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceTopologyStateAddHelper;
@@ -213,20 +215,14 @@ public class TopologyStateInterfaceTest {
 
         List<InterfaceBfdStatus> interfaceBfdStatus = new ArrayList<>();
         interfaceBfdStatus.add(new InterfaceBfdStatusBuilder().setBfdStatusKey(SouthboundUtils.BFD_OP_STATE).setBfdStatusValue(SouthboundUtils.BFD_STATE_UP).build());
-
-        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState = new InterfaceBuilder().setKey(new InterfaceKey(InterfaceManagerTestUtil.interfaceName)).build();
-        Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedInterface = Optional.of(ifState);
+        Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedInterface = Optional.absent();
 
         doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
                 LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
         updateHelper.updateTunnelState(dataBroker, newTerminationPoint);
 
         //verify
-        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
-            IfmUtil.buildStateInterfaceId(InterfaceManagerTestUtil.tunnelInterfaceName);
-        InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setOperStatus(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down);
-        ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(InterfaceManagerTestUtil.tunnelInterfaceName));
-        verify(mockWriteTx).merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build(), false);
+        Assert.assertNotNull(InterfaceManagerCommonUtils.getBfdStateFromCache(newTerminationPoint.getName()));
 
     }
 }
index 1bce8c68177cda8855921a13cc3d62b7b8abe1da..4d6e05479df19f686b3d0a7fa35389de85a34c40 100644 (file)
@@ -51,8 +51,8 @@ import org.slf4j.LoggerFactory;
  */
 public class TransportZoneListener extends AsyncDataTreeChangeListenerBase<TransportZone, TransportZoneListener> implements AutoCloseable{
     private static final Logger LOG = LoggerFactory.getLogger(TransportZoneListener.class);
-    private DataBroker dataBroker;
-    private IdManagerService idManagerService;
+    private final DataBroker dataBroker;
+    private final IdManagerService idManagerService;
     private IMdsalApiManager mdsalManager;
     private ITMManager itmManager;
 
@@ -109,7 +109,7 @@ public class TransportZoneListener extends AsyncDataTreeChangeListenerBase<Trans
         List<DPNTEPsInfo> opDpnList = createDPNTepInfo(tzOld);
         List<HwVtep> hwVtepList = createhWVteps(tzOld);
         LOG.trace("Delete: Invoking deleteTunnels in ItmManager with DpnList {}", opDpnList);
-        if(opDpnList.size()>0 || hwVtepList.size()>0) {
+        if(!opDpnList.isEmpty() || !hwVtepList.isEmpty()) {
             LOG.trace("Delete: Invoking ItmManager");
             LOG.trace("Delete: Invoking ItmManager with hwVtep List {} " , hwVtepList);
             // itmManager.deleteTunnels(opDpnList);
@@ -146,12 +146,12 @@ public class TransportZoneListener extends AsyncDataTreeChangeListenerBase<Trans
         LOG.trace("newcopy"+newDpnTepsListcopy);
         LOG.trace("oldcopy Size "+oldDpnTepsList.size());
         LOG.trace("newcopy Size "+newDpnTepsList.size());
-        if(newDpnTepsList.size() > 0) {
+        if(!newDpnTepsList.isEmpty()) {
             LOG.trace( "Adding TEPs " );
             ItmTepAddWorker addWorker = new ItmTepAddWorker(newDpnTepsList, Collections.<HwVtep>emptyList(), dataBroker, idManagerService, mdsalManager);
             coordinator.enqueueJob(tzNew.getZoneName(), addWorker);
         }
-        if(oldDpnTepsList.size() > 0) {
+        if(!oldDpnTepsList.isEmpty()) {
             LOG.trace( "Removing TEPs " );
             ItmTepRemoveWorker removeWorker = new ItmTepRemoveWorker(oldDpnTepsList, Collections.<HwVtep>emptyList(),
                     tzOld, dataBroker, idManagerService, mdsalManager);
@@ -174,18 +174,17 @@ public class TransportZoneListener extends AsyncDataTreeChangeListenerBase<Trans
         LOG.trace("newHwList" + newHwList);
         LOG.trace("oldHwListcopy" + oldHwListcopy);
         LOG.trace("newHwListcopy" + newHwListcopy);
-        if(newHwList.size() > 0) {
+        if(!newHwList.isEmpty()) {
             LOG.trace( "Adding HW TEPs " );
             ItmTepAddWorker addWorker = new ItmTepAddWorker(Collections.<DPNTEPsInfo>emptyList(), newHwList, dataBroker, idManagerService, mdsalManager);
             coordinator.enqueueJob(tzNew.getZoneName(), addWorker);
         }
-        if (oldHwList.size() > 0) {
+        if (!oldHwList.isEmpty()) {
             LOG.trace("Removing HW TEPs ");
             ItmTepRemoveWorker removeWorker = new ItmTepRemoveWorker(Collections.<DPNTEPsInfo>emptyList(), oldHwList,
                     tzOld, dataBroker, idManagerService, mdsalManager);
             coordinator.enqueueJob(tzNew.getZoneName(), removeWorker);
         }
-
     }
 
     @Override
@@ -194,7 +193,7 @@ public class TransportZoneListener extends AsyncDataTreeChangeListenerBase<Trans
         List<DPNTEPsInfo> opDpnList = createDPNTepInfo(tzNew);
         List<HwVtep> hwVtepList = createhWVteps(tzNew);
         LOG.trace("Add: Operational dpnTepInfo - Before invoking ItmManager {}", opDpnList);
-        if(opDpnList.size()>0 || hwVtepList.size()>0) {
+        if(!opDpnList.isEmpty() || !hwVtepList.isEmpty()) {
             LOG.trace("Add: Invoking ItmManager with DPN List {} " , opDpnList);
             LOG.trace("Add: Invoking ItmManager with hwVtep List {} " , hwVtepList);
             //itmManager.build_all_tunnels(opDpnList);
@@ -204,15 +203,14 @@ public class TransportZoneListener extends AsyncDataTreeChangeListenerBase<Trans
         }
     }
 
-    private List<DPNTEPsInfo> createDPNTepInfo(TransportZone transportZone){
-
+    private List<DPNTEPsInfo> createDPNTepInfo(TransportZone transportZone) {
         Map<BigInteger, List<TunnelEndPoints>> mapDPNToTunnelEndpt = new ConcurrentHashMap<>();
         List<DPNTEPsInfo> dpnTepInfo = new ArrayList<>();
         // List<TransportZone> transportZoneList = transportZones.getTransportZone();
         // for(TransportZone transportZone : transportZoneList) {
-        String zone_name = transportZone.getZoneName();
-        Class<? extends TunnelTypeBase> tunnel_type = transportZone.getTunnelType();
-        LOG.trace("Transport Zone_name: {}", zone_name);
+        String zoneName = transportZone.getZoneName();
+        Class<? extends TunnelTypeBase> tunnelType = transportZone.getTunnelType();
+        LOG.trace("Transport Zone_name: {}", zoneName);
         List<Subnets> subnetsList = transportZone.getSubnets();
         if(subnetsList!=null){
             for (Subnets subnet : subnetsList) {
@@ -229,7 +227,7 @@ public class TransportZoneListener extends AsyncDataTreeChangeListenerBase<Trans
                         LOG.trace("DpnID: {}, port: {}, ipAddress: {}", dpnID, port, ipAddress);
                         TunnelEndPoints tunnelEndPoints =
                                 ItmUtils.createTunnelEndPoints(dpnID, ipAddress, port, vlanID, ipPrefix,
-                                        gatewayIP, zone_name, tunnel_type);
+                                        gatewayIP, zoneName, tunnelType);
                         List<TunnelEndPoints> tunnelEndPointsList = mapDPNToTunnelEndpt.get(dpnID);
                         if (tunnelEndPointsList != null) {
                             LOG.trace("Existing DPN info list in the Map: {} ", dpnID);
@@ -245,7 +243,7 @@ public class TransportZoneListener extends AsyncDataTreeChangeListenerBase<Trans
             }
         }
         //}
-        if(mapDPNToTunnelEndpt.size()>0){
+        if(!mapDPNToTunnelEndpt.isEmpty()){
             Set<BigInteger> keys = mapDPNToTunnelEndpt.keySet();
             LOG.trace("List of dpns in the Map: {} ", keys);
             for(BigInteger key: keys){
@@ -275,12 +273,12 @@ public class TransportZoneListener extends AsyncDataTreeChangeListenerBase<Trans
                 List<DeviceVteps> deviceVtepsList = subnet.getDeviceVteps();
                 if (deviceVtepsList != null) {
                     for (DeviceVteps vteps : deviceVtepsList) {
-                        String topo_id = vteps.getTopologyId();
-                        String node_id = vteps.getNodeId();
+                        String topologyId = vteps.getTopologyId();
+                        String nodeId = vteps.getNodeId();
                         IpAddress ipAddress = vteps.getIpAddress();
-                        LOG.trace("topo-id: {}, node-id: {}, ipAddress: {}", topo_id, node_id, ipAddress);
+                        LOG.trace("topo-id: {}, node-id: {}, ipAddress: {}", topologyId, nodeId, ipAddress);
                         //TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(dpnID, ipAddress, port, vlanID, ipPrefix, gatewayIP, zone_name, tunnel_type);
-                        HwVtep hwVtep = ItmUtils.createHwVtepObject(topo_id, node_id, ipAddress, ipPrefix, gatewayIP, vlanID, tunnel_type, transportZone);
+                        HwVtep hwVtep = ItmUtils.createHwVtepObject(topologyId, nodeId, ipAddress, ipPrefix, gatewayIP, vlanID, tunnel_type, transportZone);
 
                         if (hwVtepsList != null) {
                             LOG.trace("Existing hwVteps");
index 37650745c454ad091de36b6d93c7d4768487c01a..e3c952892f2df6165d5d8e59596f96eb7d2b41eb 100644 (file)
@@ -20,6 +20,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <artifactId>mdsalutil-api</artifactId>
   <version>0.2.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
+
 <dependencies>
   <dependency>
     <groupId>org.opendaylight.openflowplugin.model</groupId>
@@ -56,6 +57,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <artifactId>utils.config</artifactId>
     <version>${genius.ovsdb.version}</version>
   </dependency>
+  <dependency>
+      <groupId>org.opendaylight.infrautils</groupId>
+      <artifactId>inject</artifactId>
+      <version>${genius.infrautils.version}</version>
+  </dependency>
   <dependency>
     <groupId>com.google.guava</groupId>
     <artifactId>guava-testlib</artifactId>
index 3739740e9fa039a79a4fabc47754b921da8acb79..e5e4f86cd344487f048c75ab7d5a8230d330beed 100644 (file)
@@ -16,6 +16,7 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+import javax.annotation.PreDestroy;
 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
@@ -128,6 +129,7 @@ public abstract class AsyncClusteredDataChangeListenerBase<T extends DataObject,
     }
 
     @Override
+    @PreDestroy
     public void close() throws Exception {
         if (listenerRegistration != null) {
             try {
index afd0aff93ab40f1f0a0c0444760421efe4fbf437..b77763d79fe0c8fddc25fdfaf246ba7ce2918811 100644 (file)
@@ -22,10 +22,10 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.Collection;
-import java.util.concurrent.Callable;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+import javax.annotation.PreDestroy;
 
 public abstract class AsyncClusteredDataTreeChangeListenerBase<T extends DataObject, K extends ClusteredDataTreeChangeListener> implements ClusteredDataTreeChangeListener<T>, AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(AsyncClusteredDataTreeChangeListenerBase.class);
@@ -67,12 +67,7 @@ public abstract class AsyncClusteredDataTreeChangeListenerBase<T extends DataObj
         final DataTreeIdentifier<T> treeId = new DataTreeIdentifier<>(dsType, getWildCardPath());
         try {
             TaskRetryLooper looper = new TaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
-            listenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<K>>() {
-                @Override
-                public ListenerRegistration<K> call() throws Exception {
-                    return db.registerDataTreeChangeListener(treeId, getDataTreeChangeListener());
-                }
-            });
+            listenerRegistration = looper.loopUntilNoException(() -> db.registerDataTreeChangeListener(treeId, getDataTreeChangeListener()));
         } catch (final Exception e) {
             LOG.warn("{}: Data Tree Change listener registration failed.", eventClazz.getName());
             LOG.debug("{}: Data Tree Change listener registration failed: {}", eventClazz.getName(), e);
@@ -81,6 +76,7 @@ public abstract class AsyncClusteredDataTreeChangeListenerBase<T extends DataObj
     }
 
     @Override
+    @PreDestroy
     public void close() throws Exception {
         if (listenerRegistration != null) {
             try {
index 6d94f15f42bdb755302864efde6f0bf5d3296be5..6d46e30db08c6bc5768cd646f421ca8f4c58c96c 100644 (file)
@@ -16,6 +16,7 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+import javax.annotation.PreDestroy;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
@@ -128,6 +129,7 @@ public abstract class AsyncDataChangeListenerBase<T extends DataObject, K extend
     }
 
     @Override
+    @PreDestroy
     public void close() throws Exception {
         if (listenerRegistration != null) {
             try {
index 3a509bde58ec171b73e71bb630bff45664c3e31d..e8064884f53f89e0d7a354a277412dc8fdd4daff 100644 (file)
@@ -10,10 +10,11 @@ package org.opendaylight.genius.datastoreutils;
 
 import com.google.common.base.Preconditions;
 import java.util.Collection;
-import java.util.concurrent.Callable;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
@@ -26,7 +27,9 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public abstract class AsyncDataTreeChangeListenerBase<T extends DataObject, K extends DataTreeChangeListener> implements DataTreeChangeListener<T>, AutoCloseable {
+public abstract class AsyncDataTreeChangeListenerBase<T extends DataObject, K extends DataTreeChangeListener>
+        implements DataTreeChangeListener<T>, AutoCloseable {
+
     private static final Logger LOG = LoggerFactory.getLogger(AsyncDataTreeChangeListenerBase.class);
 
     private static final int DATATREE_CHANGE_HANDLER_THREAD_POOL_CORE_SIZE = 1;
@@ -66,12 +69,7 @@ public abstract class AsyncDataTreeChangeListenerBase<T extends DataObject, K ex
         final DataTreeIdentifier<T> treeId = new DataTreeIdentifier<>(dsType, getWildCardPath());
         try {
             TaskRetryLooper looper = new TaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
-            listenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<K>>() {
-                @Override
-                public ListenerRegistration<K> call() throws Exception {
-                    return db.registerDataTreeChangeListener(treeId, getDataTreeChangeListener());
-                }
-            });
+            listenerRegistration = looper.loopUntilNoException(() -> db.registerDataTreeChangeListener(treeId, getDataTreeChangeListener()));
         } catch (final Exception e) {
             LOG.warn("{}: Data Tree Change listener registration failed.", eventClazz.getName());
             LOG.debug("{}: Data Tree Change listener registration failed: {}", eventClazz.getName(), e);
@@ -79,7 +77,23 @@ public abstract class AsyncDataTreeChangeListenerBase<T extends DataObject, K ex
         }
     }
 
+    /**
+     * Subclasses override this and place initialization logic here, notably
+     * calls to registerListener(). Note that the overriding method MUST repeat
+     * the PostConstruct annotation, because JSR 250 specifies that lifecycle
+     * methods "are called unless a subclass of the declaring class overrides
+     * the method without repeating the annotation".  (The blueprint-maven-plugin
+     * would gen. XML which calls PostConstruct annotated methods even if they are
+     * in a subclass without repeating the annotation, but this is wrong and not
+     * JSR 250 compliant, and while working in BP, then causes issues e.g. when
+     * wiring with Guice for tests, so do always repeat it.)
+     */
+    @PostConstruct
+    protected void init() {
+    }
+
     @Override
+    @PreDestroy
     public void close() throws Exception {
         if (listenerRegistration != null) {
             try {
@@ -104,8 +118,6 @@ public abstract class AsyncDataTreeChangeListenerBase<T extends DataObject, K ex
             this.changes = changes;
         }
 
-
-
         @Override
         public void run() {
             for (DataTreeModification<T> change : changes) {
old mode 100644 (file)
new mode 100755 (executable)
index 30a6321..e93bcad
@@ -100,11 +100,10 @@ public class DataStoreJobCoordinator {
             if (jobQueue == null) {
                 jobQueue = new JobQueue();
             }
+            LOG.trace("Adding jobkey {} to queue {} with size {}", key, hashKey, jobEntriesMap.size());
             jobQueue.addEntry(jobEntry);
             jobEntriesMap.put(key, jobQueue);
         }
-
-        jobQueueMap.put(hashKey, jobEntriesMap); // Is this really needed ?
         reentrantLock.lock();
         try {
             waitCondition.signal();
@@ -117,11 +116,14 @@ public class DataStoreJobCoordinator {
      * clearJob is used to cleanup the submitted job from the jobqueue.
      **/
     private void clearJob(JobEntry jobEntry) {
-        Map<String, JobQueue> jobEntriesMap = jobQueueMap.get(getHashKey(jobEntry.getKey()));
+        Integer hashKey = getHashKey(jobEntry.getKey());
+        Map<String, JobQueue> jobEntriesMap = jobQueueMap.get(hashKey);
+        LOG.trace("About to clear jobkey {} from queue {}", jobEntry.getKey(), hashKey);
         synchronized (jobEntriesMap) {
             JobQueue jobQueue = jobEntriesMap.get(jobEntry.getKey());
             jobQueue.setExecutingEntry(null);
             if (jobQueue.getWaitingEntries().isEmpty()) {
+                LOG.trace("Clear jobkey {} from queue {}", jobEntry.getKey(), hashKey);
                 jobEntriesMap.remove(jobEntry.getKey());
             }
         }
@@ -156,6 +158,7 @@ public class DataStoreJobCoordinator {
          */
         @Override
         public void onSuccess(List<Void> voids) {
+            LOG.trace("Job {} completed successfully", jobEntry.getKey());
             clearJob(jobEntry);
         }
 
@@ -170,7 +173,8 @@ public class DataStoreJobCoordinator {
 
         @Override
         public void onFailure(Throwable throwable) {
-            LOG.warn("Job: {} failed with exception: {}", jobEntry, throwable.getStackTrace());
+            LOG.warn("Job: {} failed with exception: {} {}", jobEntry, throwable.getClass().getSimpleName(),
+                    throwable.getStackTrace());
             if (jobEntry.getMainWorker() == null) {
                 LOG.error("Job: {} failed with Double-Fault. Bailing Out.", jobEntry);
                 clearJob(jobEntry);
@@ -244,12 +248,17 @@ public class DataStoreJobCoordinator {
         @Override
         public void run() {
             List<ListenableFuture<Void>> futures = null;
+            long jobStartTimestamp = System.currentTimeMillis();
+            LOG.trace("Running job {}", jobEntry.getKey());
+
             try {
                 futures = jobEntry.getMainWorker().call();
+                long jobExecutionTime = System.currentTimeMillis() - jobStartTimestamp;
+                LOG.trace("Job {} took {}ms to complete", jobEntry.getKey(), jobExecutionTime);
             } catch (Exception e){
-                LOG.error("Exception when executing jobEntry: {}, exception: {}", jobEntry, e.getStackTrace());
-                e.printStackTrace();
+                LOG.error("Exception when executing jobEntry: {}", jobEntry, e);
             }
+
             if (futures == null || futures.isEmpty()) {
                 clearJob(jobEntry);
                 return;
@@ -264,20 +273,20 @@ public class DataStoreJobCoordinator {
     private class JobQueueHandler implements Runnable {
         @Override
         public void run() {
-            LOG.debug("Starting JobQueue Handler Thread.");
+            LOG.info("Starting JobQueue Handler Thread with pool size {}", THREADPOOL_SIZE);
             while (true) {
                 try {
                     for (int i = 0; i < THREADPOOL_SIZE; i++) {
                         Map<String, JobQueue> jobEntriesMap = jobQueueMap.get(i);
                         if (jobEntriesMap.isEmpty()) {
-                            Thread.sleep(500);
                             continue;
                         }
 
+                        LOG.trace("JobQueueHandler handling queue {} with size {}", i, jobEntriesMap.size());
                         synchronized (jobEntriesMap) {
-                            Iterator it = jobEntriesMap.entrySet().iterator();
+                            Iterator<Map.Entry<String, JobQueue>> it = jobEntriesMap.entrySet().iterator();
                             while (it.hasNext()) {
-                                Map.Entry<String, JobQueue> entry = (Map.Entry)it.next();
+                                Map.Entry<String, JobQueue> entry = it.next();
                                 if (entry.getValue().getExecutingEntry() != null) {
                                     continue;
                                 }
@@ -285,6 +294,7 @@ public class DataStoreJobCoordinator {
                                 if (jobEntry != null) {
                                     entry.getValue().setExecutingEntry(jobEntry);
                                     MainTask worker = new MainTask(jobEntry);
+                                    LOG.trace("Executing job {} from queue {}", jobEntry.getKey(), i);
                                     fjPool.execute(worker);
                                 } else {
                                     it.remove();
@@ -293,13 +303,13 @@ public class DataStoreJobCoordinator {
                         }
                     }
 
-                    if (jobQueueMap.isEmpty()) {
-                        reentrantLock.lock();
-                        try {
+                    reentrantLock.lock();
+                    try {
+                        if (isJobQueueEmpty()) {
                             waitCondition.await();
-                        } finally {
-                            reentrantLock.unlock();
                         }
+                    } finally {
+                        reentrantLock.unlock();
                     }
                 } catch (Exception e) {
                     LOG.error("Exception while executing the tasks {} ", e);
@@ -309,4 +319,15 @@ public class DataStoreJobCoordinator {
             }
         }
     }
-}
\ No newline at end of file
+
+    private boolean isJobQueueEmpty() {
+        for (int i = 0; i < THREADPOOL_SIZE; i++) {
+            Map<String, JobQueue> jobEntriesMap = jobQueueMap.get(i);
+            if (!jobEntriesMap.isEmpty()) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
index dadd79c89f06999a9ff23729ae75cf507072dadd..c827d16d2274997c43fa7f165d23e251c4422681 100644 (file)
@@ -60,6 +60,10 @@ public class JobEntry {
         return rollbackWorker;
     }
 
+    public int getRetryCount() {
+        return retryCount.get();
+    }
+
     public int decrementRetryCountAndGet() {
         return retryCount.decrementAndGet();
     }
index 5f2d8f5acbadb067cc24077d62fe538062967738..1d33154d692b7a3ac70bfd19682506935eeef5fc 100644 (file)
@@ -12,8 +12,11 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.opendaylight.genius.mdsalutil.NwConstants.LearnFlowModsType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder;
@@ -23,6 +26,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
@@ -38,32 +43,24 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.ProtocolMatchFieldsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.protocol.match.fields.PbbBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.protocol.match.fields.PbbBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionResubmitRpcAddGroupCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxOfInPortCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionConntrackNodesNodeTableFlowApplyActionsCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegLoadNodesNodeTableFlowApplyActionsCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.conntrack.grouping.NxConntrack;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.conntrack.grouping.NxConntrackBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoadBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.nx.reg.load.Dst;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.nx.reg.load.DstBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfEthDstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfIpDstCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCaseBuilder;
@@ -76,11 +73,23 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPortBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionConntrackNodesNodeTableFlowApplyActionsCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionLearnNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegLoadNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegMoveNodesNodeTableFlowApplyActionsCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.conntrack.grouping.NxConntrackBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.learn.grouping.NxLearnBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.learn.grouping.nx.learn.FlowMods;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.learn.grouping.nx.learn.FlowModsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoadBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.nx.reg.load.Dst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.nx.reg.load.DstBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMove;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMoveBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.nx.reg.move.SrcBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.resubmit.grouping.NxResubmitBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfEthSrcCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfIpSrcCaseBuilder;
+
 
 public enum ActionType {
     group {
@@ -577,6 +586,70 @@ public enum ActionType {
 
         }
 
+    },
+    move_src_dst_ip {
+        @Override
+        public Action buildAction(int newActionKey, ActionInfo actionInfo) {
+
+            ActionBuilder ab = new ActionBuilder();
+            NxRegMove regMove = new NxRegMoveBuilder()
+                    .setSrc(new SrcBuilder().setSrcChoice(new SrcOfIpSrcCaseBuilder().setOfIpSrc(Boolean.TRUE).build())
+                            .setStart(0).build())
+                    .setDst(new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.nx.reg.move.DstBuilder()
+                            .setDstChoice(new DstOfIpDstCaseBuilder().setOfIpDst(Boolean.TRUE).build()).setStart(0)
+                            .setEnd(31).build())
+                    .build();
+            ab.setAction(new NxActionRegMoveNodesNodeTableFlowApplyActionsCaseBuilder().setNxRegMove(regMove).build());
+            ab.setKey(new ActionKey(newActionKey));
+            return ab.build();
+        }
+    },
+
+    move_src_dst_eth {
+        @Override
+        public Action buildAction(int newActionKey, ActionInfo actionInfo) {
+            ActionBuilder ab = new ActionBuilder();
+            NxRegMove regMove = new NxRegMoveBuilder().setSrc(new SrcBuilder()
+                    .setSrcChoice(new SrcOfEthSrcCaseBuilder().setOfEthSrc(Boolean.TRUE).build()).setStart(0).build())
+                    .setDst(new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.nx.reg.move.DstBuilder()
+                            .setDstChoice(new DstOfEthDstCaseBuilder().setOfEthDst(Boolean.TRUE).build()).setStart(0)
+                            .setEnd(47).build())
+                    .build();
+            ab.setAction(new NxActionRegMoveNodesNodeTableFlowApplyActionsCaseBuilder().setNxRegMove(regMove).build());
+            ab.setKey(new ActionKey(newActionKey));
+            return ab.build();
+        }
+    },
+
+    set_icmp_type {
+        @Override
+        public Action buildAction(int newActionKey, ActionInfo actionInfo) {
+            String[] actionValues = actionInfo.getActionValues();
+
+            ActionBuilder ab = new ActionBuilder();
+            Icmpv4MatchBuilder icmpb = new Icmpv4MatchBuilder().setIcmpv4Type(Short.parseShort(actionValues[0]));
+            ab.setAction(new SetFieldCaseBuilder()
+                    .setSetField(new SetFieldBuilder().setIcmpv4Match(icmpb.build()).build()).build());
+            ab.setKey(new ActionKey(newActionKey));
+            return ab.build();
+        }
+
+    },
+    nx_load_in_port {
+        @Override
+        public Action buildAction(int newActionKey, ActionInfo actionInfo) {
+            BigInteger[] actionValues = actionInfo.getBigActionValues();
+            NxRegLoad rb = new NxRegLoadBuilder()
+                    .setDst(new DstBuilder()
+                            .setDstChoice(new DstNxOfInPortCaseBuilder().setOfInPort(Boolean.TRUE).build())
+                            .setStart(Integer.valueOf(0)).setEnd(Integer.valueOf(15)).build())
+                    .setValue(actionValues[0]).build();
+            ActionBuilder ab = new ActionBuilder();
+            ab.setKey(new ActionKey(newActionKey));
+            ab.setOrder(newActionKey);
+            ab.setAction(new NxActionRegLoadNodesNodeTableFlowApplyActionsCaseBuilder().setNxRegLoad(rb).build());
+            return ab.build();
+        }
     };
 
     private static final int RADIX_HEX = 16;
index 324a0e4fa5ef0f2a9ee126188bc7cf34719149b3..0b60288349af02acdaaaa4df0f33c532d1138768 100644 (file)
@@ -89,10 +89,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdenti
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Joiner;
 import com.google.common.base.Optional;
-import com.google.common.primitives.Bytes;
-import com.google.common.primitives.Ints;
 import com.google.common.util.concurrent.CheckedFuture;
 
 public class MDSALUtil {
@@ -235,14 +232,11 @@ public class MDSALUtil {
     }
 
     public static String longToIp(long ip, long mask) {
-        StringBuilder sb = new StringBuilder(15);
-        Joiner joiner = Joiner.on('.');
-
-        joiner.appendTo(sb, Bytes.asList(Ints.toByteArray((int) ip)));
-
-        sb.append("/" + mask);
-
-        return sb.toString();
+        return ((ip & 0xFF000000) >> 3 * 8) + "." +
+               ((ip & 0x00FF0000) >> 2 * 8) + "." +
+               ((ip & 0x0000FF00) >>     8) + "." +
+                (ip & 0x000000FF) +
+                (mask == 0 ? "" : "/" + mask);
     }
 
 
@@ -619,6 +613,5 @@ public class MDSALUtil {
                                 .child(Node.class, new NodeKey(new NodeId("openflow:" + dpnId))).toInstance()))
                 .setIngress(ncRef).setEgress(ncRef).build();
     }
-
 }
 
index 7a489d409614dc4285b00141f3b7876a480f3750..036afcdf15279aa7146a206bd1621a3f26b0cc2c 100644 (file)
@@ -7,8 +7,19 @@
  */
 package org.opendaylight.genius.mdsalutil;
 
+import java.math.BigInteger;
 import java.net.InetAddress;
+import java.util.LinkedList;
+import java.util.List;
 
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Optional;
 import com.google.common.primitives.UnsignedBytes;
 
 public class NWUtil {
@@ -60,8 +71,8 @@ public class NWUtil {
 
         StringBuilder sb = new StringBuilder(18);
 
-        for (int i = 0; i < ipAddress.length; i++) {
-            sb.append(UnsignedBytes.toString(ipAddress[i], 10));
+        for (byte ipAddres : ipAddress) {
+            sb.append(UnsignedBytes.toString(ipAddres, 10));
             sb.append(".");
         }
 
@@ -77,9 +88,9 @@ public class NWUtil {
 
         StringBuilder sb = new StringBuilder(18);
 
-        for (int i = 0; i < macAddress.length; i++) {
-            String tmp = UnsignedBytes.toString(macAddress[i], 16).toUpperCase();
-            if(tmp.length() == 1 || macAddress[i] == (byte)0) {
+        for (byte macAddres : macAddress) {
+            String tmp = UnsignedBytes.toString(macAddres, 16).toUpperCase();
+            if(tmp.length() == 1 || macAddres == (byte)0) {
                 sb.append("0");
             }
             sb.append(tmp);
@@ -89,4 +100,30 @@ public class NWUtil {
         sb.setLength(17);
         return sb.toString();
     }
+
+    /**
+     * Returns the ids of the currently operative DPNs
+     *
+     * @param dataBroker
+     * @return
+     */
+    public static List<BigInteger> getOperativeDPNs(DataBroker dataBroker) {
+        List<BigInteger> result = new LinkedList<BigInteger>();
+        InstanceIdentifier<Nodes> nodesInstanceIdentifier = InstanceIdentifier.builder(Nodes.class).build();
+        Optional<Nodes> nodesOptional = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
+                                                       nodesInstanceIdentifier);
+        if (!nodesOptional.isPresent()) {
+            return result;
+        }
+        Nodes nodes = nodesOptional.get();
+        List<Node> nodeList = nodes.getNode();
+        for (Node node : nodeList) {
+            NodeId nodeId = node.getId();
+            if (nodeId != null) {
+                BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeId);
+                result.add(dpnId);
+            }
+        }
+        return result;
+    }
 }
index adf3843d0d80f0d3d145458ca5d56a67a22af706..65fbc40e2c39fecd5d7f4f2e2ac6bc18e3c5a74f 100644 (file)
@@ -48,10 +48,11 @@ public final class NwConstants {
 
     // Ingress (w.r.t switch) service indexes
     public static final short DEFAULT_SERVICE_INDEX = 0;
-    public static final short DHCP_SERVICE_INDEX = 1;
-    public static final short ACL_SERVICE_INDEX = 2;
+    public static final short ACL_SERVICE_INDEX = 1;
+    public static final short DHCP_SERVICE_INDEX = 2;
     public static final short IPV6_SERVICE_INDEX = 3;
     public static final short SCF_SERVICE_INDEX = 4;
+    public static final short SFC_SERVICE_INDEX = 4;
     public static final short L3VPN_SERVICE_INDEX = 5;
     public static final short ELAN_SERVICE_INDEX = 6;
     public static final short DEFAULT_EGRESS_SERVICE_INDEX = 7;
@@ -60,6 +61,7 @@ public final class NwConstants {
     public static final String ACL_SERVICE_NAME = "ACL_SERVICE";
     public static final String IPV6_SERVICE_NAME = "IPV6_SERVICE";
     public static final String SCF_SERVICE_NAME = "SCF_SERVICE";
+    public static final String SFC_SERVICE_NAME = "SFC_SERVICE";
     public static final String L3VPN_SERVICE_NAME = "L3VPN_SERVICE";
     public static final String ELAN_SERVICE_NAME = "ELAN_SERVICE";
     public static final String DEFAULT_EGRESS_SERVICE_NAME = "DEFAULT_EGRESS_SERVICE";
@@ -118,6 +120,10 @@ public final class NwConstants {
     public static final short SCF_UP_SUB_FILTER_TCP_BASED_TABLE = 70;
     public static final short SCF_DOWN_SUB_FILTER_TCP_BASED_TABLE = 72;
     public static final short SCF_CHAIN_FWD_TABLE = 75;
+    public static final short SFC_TRANSPORT_INGRESS_TABLE = 76;
+    public static final short SFC_TRANSPORT_PATH_MAPPER_TABLE = 77;
+    public static final short SFC_TRANSPORT_NEXT_HOP_TABLE = 78;
+    public static final short SFC_TRANSPORT_EGRESS_TABLE = 79;
     public static final short L3_INTERFACE_TABLE = 80;
     public static final short EGRESS_LPORT_DISPATCHER_TABLE = 220;
     public static final short EGRESS_ACL_TABLE = 251;
index 620aac772b85c6c5041ce019852236d6eca808e9..632d1d3107d973a6b51ffb104a0cae541836da0d 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MatchField;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
@@ -26,6 +27,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlowBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxCtStateKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxCtZoneKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg5Key;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg6Key;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmOfTcpDstKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmOfTcpSrcKey;
@@ -252,6 +254,40 @@ public enum NxMatchFieldType {
             }
         }
     },
+    nxm_reg_5 {
+        @Override
+        protected Class<? extends MatchField> getMatchType() {
+            return NxmNxReg.class;
+        }
+
+        @Override
+        public void createInnerMatchBuilder(NxMatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+            NxmNxRegBuilder nxmNxRegBuilder = (NxmNxRegBuilder) mapMatchBuilder.get(NxmNxRegBuilder.class);
+
+            if (nxmNxRegBuilder == null) {
+                nxmNxRegBuilder = new NxmNxRegBuilder();
+                mapMatchBuilder.put(NxmNxRegBuilder.class, nxmNxRegBuilder);
+            }
+
+            nxmNxRegBuilder.setReg(NxmNxReg5.class).setValue(matchInfo.getMatchValues()[0]).build();
+        }
+
+        @Override
+        public void setMatch(MatchBuilder matchBuilderInOut, MatchInfoBase matchInfo,
+                             Map<Class<?>, Object> mapMatchBuilder) {
+            NxmNxRegBuilder nxmNxRegBuilder = (NxmNxRegBuilder) mapMatchBuilder.remove(NxmNxRegBuilder.class);
+
+            if (nxmNxRegBuilder != null) {
+                NxAugMatchNodesNodeTableFlow nxAugMatch = new NxAugMatchNodesNodeTableFlowBuilder()
+                        .setNxmNxReg(nxmNxRegBuilder.build()).build();
+                GeneralAugMatchNodesNodeTableFlow existingAugmentations = matchBuilderInOut
+                        .getAugmentation(GeneralAugMatchNodesNodeTableFlow.class);
+                GeneralAugMatchNodesNodeTableFlow genAugMatch = generalAugMatchBuilder(existingAugmentations,
+                        nxAugMatch, NxmNxReg5Key.class);
+                matchBuilderInOut.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, genAugMatch);
+            }
+        }
+    },
     nxm_reg_6 {
         @Override
         protected Class<? extends MatchField> getMatchType() {
index 72cb125d8aa6b8b2ec90e919c870aaa69eaa2c78..2f981649a08ad0a3613e8604add7e27bb16773de 100644 (file)
@@ -16,10 +16,18 @@ public class ActionableResourceImpl implements ActionableResource {
     private InstanceIdentifier identifier;
     private short action;
 
-    public ActionableResourceImpl(String key) {
+    public ActionableResourceImpl(String key){
         this.key = key;
     }
 
+    public ActionableResourceImpl(String key, InstanceIdentifier identifier, short action,Object updatedData, Object oldData) {
+        this.instance = updatedData;
+        this.oldInstance = oldData;
+        this.key = key;
+        this.identifier = identifier;
+        this.action = action;
+    }
+
     public void setInstance(Object instance) {
         this.instance = instance;
     }
diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/batching/DefaultBatchHandler.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/batching/DefaultBatchHandler.java
new file mode 100644 (file)
index 0000000..564da9c
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2016 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.utils.batching;
+
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+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.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+
+public class DefaultBatchHandler implements ResourceHandler {
+
+    private static DataBroker dataBroker;
+    public static Integer batchSize;
+    public static Integer batchInterval;
+    public LogicalDatastoreType datastoreType;
+
+    public DefaultBatchHandler(DataBroker  dataBroker,LogicalDatastoreType dataStoreType,Integer batchSize,Integer batchInterval) {
+
+        this.dataBroker = dataBroker;
+        this.batchSize = batchSize;
+        this.batchInterval = batchInterval;
+        this.datastoreType = dataStoreType;
+
+    }
+    public void update(WriteTransaction tx, LogicalDatastoreType datastoreType,
+                       final InstanceIdentifier identifier, final Object original, final Object update, List<SubTransaction> transactionObjects) {
+        if ((update != null) && !(update instanceof DataObject)) {
+            return;
+        }
+        if (datastoreType != getDatastoreType()) {
+            return;
+        }
+
+        SubTransaction subTransaction = new SubTransactionImpl();
+        subTransaction.setAction(SubTransaction.UPDATE);
+        subTransaction.setInstance(update);
+        subTransaction.setInstanceIdentifier(identifier);
+        transactionObjects.add(subTransaction);
+
+        tx.merge(datastoreType, identifier, (DataObject) update, true);
+    }
+
+    public void create(WriteTransaction tx, final LogicalDatastoreType datastoreType,
+                       final InstanceIdentifier identifier, final Object data, List<SubTransaction> transactionObjects) {
+        if ((data != null) && !(data instanceof DataObject)) {
+            return;
+        }
+        if (datastoreType != getDatastoreType()) {
+            return;
+        }
+
+        SubTransaction subTransaction = new SubTransactionImpl();
+        subTransaction.setAction(SubTransaction.CREATE);
+        subTransaction.setInstance(data);
+        subTransaction.setInstanceIdentifier(identifier);
+        transactionObjects.add(subTransaction);
+
+        tx.put(datastoreType, identifier, (DataObject) data, true);
+    }
+
+    public void delete(WriteTransaction tx, final LogicalDatastoreType datastoreType,
+                       final InstanceIdentifier identifier, final Object data, List<SubTransaction> transactionObjects) {
+        if ((data != null) && !(data instanceof DataObject)) {
+            return;
+        }
+        if (datastoreType != getDatastoreType()) {
+            return;
+        }
+
+        SubTransaction subTransaction = new SubTransactionImpl();
+        subTransaction.setAction(SubTransaction.DELETE);
+        subTransaction.setInstanceIdentifier(identifier);
+        transactionObjects.add(subTransaction);
+
+        tx.delete(datastoreType, identifier);
+    }
+
+    public DataBroker getResourceBroker() {
+        return dataBroker;
+    }
+
+    public int getBatchSize() {
+        return batchSize;
+    }
+
+    public int getBatchInterval() {
+        return batchInterval;
+    }
+
+    public LogicalDatastoreType getDatastoreType() {
+        return datastoreType;
+    }
+}
+
index 4fe13a29786b9965850011590fcb5836bae87f52..9718740fd1b8dec4fea10bd05f25d0fd472a0824 100644 (file)
@@ -56,6 +56,9 @@ public class ResourceBatchingManager implements AutoCloseable {
     public void registerBatchableResource(String resourceType, final BlockingQueue<ActionableResource> resQueue, final ResourceHandler resHandler) {
         Preconditions.checkNotNull(resQueue, "ResourceQueue to use for batching cannot not be null.");
         Preconditions.checkNotNull(resHandler, "ResourceHandler cannot not be null.");
+        if (resourceHandlerMapper.contains(resourceType)) {
+            throw new RuntimeException("Resource type already registered");
+        }
         resourceHandlerMapper.put(resourceType, new ImmutablePair<BlockingQueue, ResourceHandler>(resQueue, resHandler));
         ScheduledThreadPoolExecutor resDelegatorService =(ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1);
         resourceBatchingThreadMapper.put(resourceType, resDelegatorService);
@@ -65,6 +68,41 @@ public class ResourceBatchingManager implements AutoCloseable {
             resDelegatorService.scheduleWithFixedDelay(new Batcher(resourceType), INITIAL_DELAY, resHandler.getBatchInterval(), TIME_UNIT);
     }
 
+    public void put(String resourceType, InstanceIdentifier identifier, DataObject updatedData) {
+        BlockingQueue<ActionableResource> queue = getQueue(resourceType);
+        if (queue != null) {
+            ActionableResource actResource = new ActionableResourceImpl(identifier.toString(),
+                    identifier, ActionableResource.CREATE, updatedData, null/*oldData*/);
+            queue.add(actResource);
+        }
+    }
+
+    public void merge(String resourceType, InstanceIdentifier identifier, DataObject updatedData) {
+        BlockingQueue<ActionableResource> queue = getQueue(resourceType);
+        if (queue != null) {
+            ActionableResource actResource = new ActionableResourceImpl(identifier.toString(),
+                    identifier, ActionableResource.UPDATE, updatedData, null/*oldData*/);
+            queue.add(actResource);
+        }
+    }
+
+    public void delete(String resourceType, InstanceIdentifier identifier) {
+        BlockingQueue<ActionableResource> queue = getQueue(resourceType);
+        if (queue != null) {
+            ActionableResource actResource = new ActionableResourceImpl(identifier.toString(),
+                    identifier, ActionableResource.DELETE, null, null/*oldData*/);
+            queue.add(actResource);
+        }
+    }
+
+    private BlockingQueue<ActionableResource> getQueue(String resourceType) {
+        if (resourceHandlerMapper.containsKey(resourceType)) {
+            return resourceHandlerMapper.get(resourceType).getLeft();
+        }
+        return null;
+    }
+
+
     public void deregisterBatchableResource(String resourceType) {
         resourceHandlerMapper.remove(resourceType);
         resourceBatchingThreadMapper.remove(resourceType);
@@ -150,24 +188,25 @@ public class ResourceBatchingManager implements AutoCloseable {
                 DataBroker broker = resHandler.getResourceBroker();
                 LogicalDatastoreType dsType = resHandler.getDatastoreType();
                 WriteTransaction tx = broker.newWriteOnlyTransaction();
+                List<SubTransaction> transactionObjects = new ArrayList<>();
                 for (ActionableResource actResource : actResourceList)
                 {
                     switch (actResource.getAction()) {
                         case ActionableResource.CREATE:
                             identifier = actResource.getInstanceIdentifier();
                             instance = actResource.getInstance();
-                            resHandler.create(tx, dsType, identifier, instance);
+                            resHandler.create(tx, dsType, identifier, instance,transactionObjects);
                             break;
                         case ActionableResource.UPDATE:
                             identifier = actResource.getInstanceIdentifier();
                             Object updated = actResource.getInstance();
                             Object original = actResource.getOldInstance();
-                            resHandler.update(tx, dsType, identifier, original, updated);
+                            resHandler.update(tx, dsType, identifier, original, updated,transactionObjects);
                             break;
                         case ActionableResource.DELETE:
                             identifier = actResource.getInstanceIdentifier();
                             instance = actResource.getInstance();
-                            resHandler.delete(tx, dsType, identifier, instance);
+                            resHandler.delete(tx, dsType, identifier, instance,transactionObjects);
                             break;
                         default:
                             LOG.error("Unable to determine Action for ResourceType {} with ResourceKey {}", resourceType,
@@ -187,7 +226,31 @@ public class ResourceBatchingManager implements AutoCloseable {
 
                 } catch (InterruptedException | ExecutionException e)
                 {
-                    LOG.error("Exception occurred while writing to datastore: " + e);
+                    LOG.error("Exception occurred while batch writing to datastore {} ", e);
+                    LOG.info("Trying to submit transaction operations one at a time for resType {}", resourceType);
+                    for (SubTransaction object : transactionObjects) {
+                        WriteTransaction writeTransaction = broker.newWriteOnlyTransaction();
+                        switch (object.getAction()) {
+                            case SubTransaction.CREATE :
+                                writeTransaction.put(dsType, object.getInstanceIdentifier(), (DataObject)object.getInstance(), true);
+                                break;
+                            case SubTransaction.DELETE :
+                                writeTransaction.delete(dsType, object.getInstanceIdentifier());
+                                break;
+                            case SubTransaction.UPDATE :
+                                writeTransaction.merge(dsType, object.getInstanceIdentifier(), (DataObject)object.getInstance(), true);
+                                break;
+                            default:
+                                LOG.error("Unable to determine Action for transaction object with id {}", object.getInstanceIdentifier());
+                        }
+                        CheckedFuture<Void, TransactionCommitFailedException> futureOperation = writeTransaction.submit();
+                        try {
+                            futureOperation.get();
+                        } catch (InterruptedException | ExecutionException exception) {
+                            LOG.error("Error {} to datastore (path, data) : ({}, {})", object.getAction(), object.getInstanceIdentifier(), object.getInstance());
+                            LOG.error(exception.getMessage());
+                        }
+                    }
                 }
 
             } catch (final Exception e)
index e352d9447c9b28a39686c5fd7d3ab1f6942c970f..c8757185e1640d5afa74ce7a723d157868b8395b 100644 (file)
@@ -12,11 +12,13 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
+import java.util.List;
+
 public interface ResourceHandler {
-    void create(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifer, Object vrfEntry);
-    void delete(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifer, Object vrfEntry);
+    void create(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifer, Object vrfEntry,List<SubTransaction> transactionObjects);
+    void delete(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifer, Object vrfEntry,List<SubTransaction> transactionObjects);
     void update(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier, Object original,
-                Object update);
+                Object update,List<SubTransaction> transactionObjects);
     LogicalDatastoreType getDatastoreType();
     int getBatchSize();
     int getBatchInterval();
diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/batching/SubTransaction.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/batching/SubTransaction.java
new file mode 100644 (file)
index 0000000..eb03725
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016 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.utils.batching;
+
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public interface SubTransaction {
+    static final short CREATE = 1;
+    static final short UPDATE = 2;
+    static final short DELETE = 3;
+
+    InstanceIdentifier getInstanceIdentifier();
+    void setInstanceIdentifier(InstanceIdentifier identifier);
+    Object getInstance();
+    void setInstance(Object instance);
+    short getAction();
+    void setAction(short action);
+}
diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/batching/SubTransactionImpl.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/batching/SubTransactionImpl.java
new file mode 100644 (file)
index 0000000..f785816
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016 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.utils.batching;
+
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubTransactionImpl implements SubTransaction {
+    private Object instance;
+    private InstanceIdentifier identifier;
+    private short action;
+
+    public SubTransactionImpl() { }
+
+    public void setInstance(Object instance) {
+        this.instance = instance;
+    }
+
+    public Object getInstance() {
+        return this.instance;
+    }
+
+    public void setInstanceIdentifier(InstanceIdentifier identifier) {
+        this.identifier = identifier;
+    }
+
+    public InstanceIdentifier getInstanceIdentifier() {
+        return this.identifier;
+    }
+
+    public void setAction(short action) {
+        this.action = action;
+    }
+
+    public short getAction(){
+        return action;
+    }
+}
index a835b57b3f958d6e5a230116dd65de19bc401ac9..705e6c65138a725f086772d5cb08c185b8e75491 100644 (file)
@@ -24,9 +24,11 @@ import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipS
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.utils.SystemPropertyReader;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class ClusteringUtils {
-
+    private static final Logger LOG = LoggerFactory.getLogger(ClusteringUtils.class);
     static DataStoreJobCoordinator dataStoreJobCoordinator;
 
     static DataStoreJobCoordinator getDataStoreJobCoordinator() {
@@ -88,6 +90,8 @@ public class ClusteringUtils {
                         return getResultFuture();
                     }
                 }
+                LOG.trace("EntityOwnershipState for entity type {} is not yet available. {} retries left",
+                        entity.getType(), retries);
                 Thread.sleep(sleepBetweenRetries);
             }
             checkNodeEntityfuture.setException(new EntityOwnerNotPresentException("Entity Owner Not Present"));
diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/hwvtep/DebugEvent.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/hwvtep/DebugEvent.java
new file mode 100644 (file)
index 0000000..2745915
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016 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.utils.hwvtep;
+
+public abstract class DebugEvent {
+
+    private final long eventTimeStamp;
+
+    public DebugEvent() {
+        this.eventTimeStamp = System.currentTimeMillis();
+    }
+
+    public long getEventTimeStamp() {
+        return eventTimeStamp;
+    }
+}
diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/hwvtep/HwvtepHACache.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/hwvtep/HwvtepHACache.java
new file mode 100644 (file)
index 0000000..0c97bb9
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2016 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.utils.hwvtep;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.LinkedBlockingQueue;
+
+public class HwvtepHACache {
+
+    private static final int MAX_EVENT_BUFFER_SIZE = 500000;
+    private static final int EVENT_DRAIN_BUFFER_SIZE = 100000;
+
+    private static HwvtepHACache instance = new HwvtepHACache();
+
+    private ConcurrentHashMap<InstanceIdentifier<Node>, Set<InstanceIdentifier<Node>>> parentToChildMap = new ConcurrentHashMap<>();
+    private ConcurrentHashMap<InstanceIdentifier<Node>, InstanceIdentifier<Node>> childToParentMap = new ConcurrentHashMap<>();
+    private ConcurrentHashMap<String, Boolean> childNodeIds = new ConcurrentHashMap<>();
+    private ConcurrentHashMap<String, Boolean> connectedNodes = new ConcurrentHashMap<>();
+    private LinkedBlockingQueue<DebugEvent> debugEvents = new LinkedBlockingQueue<>(MAX_EVENT_BUFFER_SIZE);
+
+    public static HwvtepHACache getInstance() {
+        return instance;
+    }
+
+    public  synchronized void addChild(InstanceIdentifier<Node> parent, InstanceIdentifier<Node> child) {
+        if (parent == null || child == null) {
+            return;
+        }
+        if (parentToChildMap.get(parent) == null) {
+            parentToChildMap.put(parent, new HashSet<InstanceIdentifier<Node>>());
+        }
+        parentToChildMap.get(parent).add(child);
+        childToParentMap.put(child, parent);
+        String childNodeId = child.firstKeyOf(Node.class).getNodeId().getValue();
+        childNodeIds.put(childNodeId, Boolean.TRUE);
+        addDebugEvent(new NodeEvent.ChildAddedEvent(childNodeId));
+    }
+
+    public boolean isHAEnabledDevice(InstanceIdentifier<?> iid) {
+        boolean enabled = childToParentMap.containsKey(iid);
+        if (!enabled) {
+            String psNodeId = iid.firstKeyOf(Node.class).getNodeId().getValue();
+            int idx = psNodeId.indexOf(HwvtepSouthboundConstants.PSWITCH_URI_PREFIX);
+            if (idx > 0) {
+                String globalNodeId = psNodeId.substring(0, idx - 1);
+                return childNodeIds.containsKey(globalNodeId);
+            }
+        }
+        return enabled;
+    }
+
+    public  boolean isHAParentNode(InstanceIdentifier<Node> node) {
+        return parentToChildMap.containsKey(node);
+    }
+
+    public  Set<InstanceIdentifier<Node>> getChildrenForHANode(InstanceIdentifier<Node> parent) {
+        if (parent != null && parentToChildMap.containsKey(parent)) {
+            return new HashSet(parentToChildMap.get(parent));
+        } else {
+            return Collections.emptySet();
+        }
+    }
+
+    public  Set<InstanceIdentifier<Node>> getHAParentNodes() {
+        return parentToChildMap.keySet();
+    }
+
+    public  Set<InstanceIdentifier<Node>> getHAChildNodes() {
+        return childToParentMap.keySet();
+    }
+
+    public  InstanceIdentifier<Node> getParent(InstanceIdentifier<Node> child) {
+        if (child != null) {
+            return childToParentMap.get(child);
+        }
+        return null;
+    }
+
+    public  synchronized void cleanupParent(InstanceIdentifier<Node> parent) {
+        if (parent == null) {
+            return;
+        }
+
+        if (parentToChildMap.get(parent) != null) {
+            Set<InstanceIdentifier<Node>> childs = parentToChildMap.get(parent);
+            for (InstanceIdentifier<Node> child : childs) {
+                childToParentMap.remove(child);
+                String childNodeId = child.firstKeyOf(Node.class).getNodeId().getValue();
+                childNodeIds.remove(childNodeId);
+            }
+        }
+        parentToChildMap.remove(parent);
+    }
+
+    public void updateConnectedNodeStatus(InstanceIdentifier<Node> iid) {
+        String nodeId = iid.firstKeyOf(Node.class).getNodeId().getValue();
+        connectedNodes.put(nodeId, true);
+        DebugEvent event = new NodeEvent.NodeConnectedEvent(nodeId);
+        addDebugEvent(event);
+    }
+
+    public void updateDisconnectedNodeStatus(InstanceIdentifier<Node> iid) {
+        String nodeId = iid.firstKeyOf(Node.class).getNodeId().getValue();
+        connectedNodes.put(nodeId, false);
+        DebugEvent event = new NodeEvent.NodeDisconnectedEvent(nodeId);
+        addDebugEvent(event);
+    }
+
+    public Map<String, Boolean> getConnectedNodes() {
+        return ImmutableMap.copyOf(connectedNodes);
+    }
+
+    public void addDebugEvent(DebugEvent debugEvent) {
+        //Try adding the event to event queue
+        if (!debugEvents.offer(debugEvent)) {
+            //buffer is exhausted
+            Collection<DebugEvent> list = new ArrayList<>();
+            //do not clear all events , make some place by clearing few old events
+            debugEvents.drainTo(list, EVENT_DRAIN_BUFFER_SIZE);
+            debugEvents.offer(debugEvent);
+        }
+    }
+
+    public List<DebugEvent> getNodeEvents() {
+        return ImmutableList.copyOf(debugEvents);
+    }
+}
index be75d8b5f78eb5260ece401c789eda72461c5c17..44b70f3468383486def713ae4f1c5d1662e2e2b1 100644 (file)
@@ -7,22 +7,23 @@
  */
 package org.opendaylight.genius.utils.hwvtep;
 
+import com.google.common.collect.ImmutableBiMap;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeVxlanOverIpv4;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
 
-import com.google.common.collect.ImmutableBiMap;
-
 // TODO (eperefr) Remove this class once it's been added to hwvtep-southbound
 public class HwvtepSouthboundConstants {
 
-    public static final TopologyId HWVTEP_TOPOLOGY_ID = new TopologyId("hwvtep:1");
     public static final String HWVTEP_ENTITY_TYPE = "hwvtep";
-    public static final Object PSWITCH_URI_PREFIX = "physicalswitch";
     public static final ImmutableBiMap<Class<? extends EncapsulationTypeBase>, String> ENCAPS_TYPE_MAP = new ImmutableBiMap.Builder<Class<? extends EncapsulationTypeBase>, String>()
             .put(EncapsulationTypeVxlanOverIpv4.class, "vxlan_over_ipv4").build();
     public static final String ELAN_ENTITY_TYPE = "elan";
     public static final String ELAN_ENTITY_NAME = "elan";
     public static final String TEP_PREFIX = "vxlan_over_ipv4:";
+    public static final String PSWITCH_URI_PREFIX = "physicalswitch";
+    public static final TopologyId HWVTEP_TOPOLOGY_ID = new TopologyId(new Uri("hwvtep:1"));
 }
 
diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/hwvtep/NodeEvent.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/utils/hwvtep/NodeEvent.java
new file mode 100644 (file)
index 0000000..de4bc81
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016 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.utils.hwvtep;
+
+import java.io.PrintStream;
+import java.util.Objects;
+
+public abstract class NodeEvent extends DebugEvent {
+
+    protected final String nodeId;
+
+    public NodeEvent(String nodeId) {
+        super();
+        this.nodeId = nodeId;
+    }
+
+    public String getNodeId() {
+        return nodeId;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (this == other) {
+            return true;
+        }
+        if (other instanceof NodeEvent) {
+            return Objects.equals(nodeId, ((NodeEvent) other).nodeId);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return nodeId != null ? nodeId.hashCode() : 0;
+    }
+
+    static enum NodeStatus {
+        Connected,Disconnected;
+    }
+
+    public static class NodeConnectedEvent extends NodeEvent {
+
+        public NodeConnectedEvent(String nodeId) {
+            super(nodeId);
+        }
+
+        public void print(PrintStream out) {
+            out.print(nodeId);
+            out.print(" connected");
+        }
+    }
+
+    public static class NodeDisconnectedEvent extends NodeEvent {
+
+        public NodeDisconnectedEvent(String nodeId) {
+            super(nodeId);
+        }
+
+        public void print(PrintStream out) {
+            out.print(nodeId);
+            out.print(" disconnected");
+        }
+    }
+
+    public static class ChildAddedEvent extends NodeEvent {
+
+        public ChildAddedEvent(String nodeId) {
+            super(nodeId);
+        }
+
+        public void print(PrintStream out) {
+            out.print(nodeId);
+            out.print(" became HA child");
+        }
+    }
+}
diff --git a/mdsalutil/mdsalutil-api/src/test/java/org/opendaylight/genius/mdsalutil/hwvtep/HwvtepHACacheTest.java b/mdsalutil/mdsalutil-api/src/test/java/org/opendaylight/genius/mdsalutil/hwvtep/HwvtepHACacheTest.java
new file mode 100644 (file)
index 0000000..8d9817a
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2016 Red Hat 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.mdsalutil.hwvtep;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.genius.utils.hwvtep.DebugEvent;
+import org.opendaylight.genius.utils.hwvtep.HwvtepHACache;
+import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
+import org.opendaylight.genius.utils.hwvtep.NodeEvent;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class HwvtepHACacheTest {
+
+    HwvtepHACache hwvtepHACache = HwvtepHACache.getInstance();
+
+    @Test
+    public void testAddHAChild() {
+
+        InstanceIdentifier<Node> parent = newNodeInstanceIdentifier("ha");
+        InstanceIdentifier<Node> child1 = newNodeInstanceIdentifier("d1");
+        InstanceIdentifier<Node> child2 = newNodeInstanceIdentifier("d1");
+        String child1NodeId = child1.firstKeyOf(Node.class).getNodeId().getValue();
+        String child2NodeId = child2.firstKeyOf(Node.class).getNodeId().getValue();
+
+        hwvtepHACache.addChild(parent, child1);
+
+        assertTrue(hwvtepHACache.isHAEnabledDevice(child1));
+        assertTrue(hwvtepHACache.isHAParentNode(parent));
+
+        hwvtepHACache.addChild(parent, child2);
+        assertTrue(hwvtepHACache.isHAEnabledDevice(child1));
+        assertTrue(hwvtepHACache.isHAEnabledDevice(child2));
+        assertTrue(hwvtepHACache.isHAParentNode(parent));
+
+        assertTrue(hwvtepHACache.getHAChildNodes().contains(child1));
+        assertTrue(hwvtepHACache.getHAChildNodes().contains(child2));
+        assertTrue(hwvtepHACache.getHAParentNodes().contains(parent));
+
+        assertTrue(hwvtepHACache.getChildrenForHANode(parent).contains(child1));
+        assertTrue(hwvtepHACache.getChildrenForHANode(parent).contains(child2));
+
+        List<DebugEvent> events = hwvtepHACache.getNodeEvents();
+        assertTrue(events.contains(new NodeEvent.ChildAddedEvent(child1NodeId)));
+        assertTrue(events.contains(new NodeEvent.ChildAddedEvent(child2NodeId)));
+
+        hwvtepHACache.updateConnectedNodeStatus(child1);
+        assertTrue(hwvtepHACache.getNodeEvents().contains(new NodeEvent.NodeConnectedEvent(child1NodeId)));
+
+        hwvtepHACache.updateDisconnectedNodeStatus(child1);
+        assertTrue(hwvtepHACache.getNodeEvents().contains(new NodeEvent.NodeDisconnectedEvent(child1NodeId)));
+
+        hwvtepHACache.cleanupParent(parent);
+        assertFalse(hwvtepHACache.isHAEnabledDevice(child1));
+        assertFalse(hwvtepHACache.isHAEnabledDevice(child2));
+        assertFalse(hwvtepHACache.isHAParentNode(parent));
+    }
+
+    public static InstanceIdentifier<Node> newNodeInstanceIdentifier(String id) {
+        String nodeString = "hwvtep://uuid/" + java.util.UUID.nameUUIDFromBytes(id.getBytes()).toString();
+        NodeId nodeId = new NodeId(new Uri(nodeString));
+        NodeKey nodeKey = new NodeKey(nodeId);
+        TopologyKey topoKey = new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID);
+        return InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, topoKey)
+                .child(Node.class, nodeKey)
+                .build();
+    }
+}