Bug 3597 - added session statistics for switch connect/disconnect events 59/22259/1
authorMartin Bobak <mbobak@cisco.com>
Fri, 5 Jun 2015 15:05:55 +0000 (17:05 +0200)
committermichal rehak <mirehak@cisco.com>
Wed, 10 Jun 2015 08:10:05 +0000 (08:10 +0000)
    Change-Id: I75f388721a678ba00e10b352bd87d1b3ca9833c3
Signed-off-by: Martin Bobak <mbobak@cisco.com>
Change-Id: Ia702621740bbc7190813ff286d6b76158bd59f64
Signed-off-by: Martin Bobak <mbobak@cisco.com>
(cherry picked from commit 1ab03d3178b3d81f46ef6c94ba8e742327e89921)

openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/ConnectionContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/ConnectionManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/listener/HandshakeListenerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/karaf/ResetSessionStatsComandProvider.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/karaf/ShowSessionStatsCommandProvider.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/ofpspecific/SessionStatistics.java [new file with mode: 0644]
openflowplugin-impl/src/main/resources/OSGI-INF/blueprint/commands.xml
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/listener/SystemNotificationsListenerImplTest.java

index dea0ecb187f0eac894481fc986ec7ec9ead353f5..31603a77cee28e98ed770eb2e596f40996e8f8e6 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandle
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.connection.OutboundQueueProvider;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceDisconnectedHandler;
+import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.SessionStatistics;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
 import org.slf4j.Logger;
@@ -88,6 +89,7 @@ public class ConnectionContextImpl implements ConnectionContext {
 
     @Override
     public void closeConnection(boolean propagate) {
+        SessionStatistics.countEvent(nodeId.toString(), SessionStatistics.ConnectionStatus.CONNECTION_DISCONNECTED_BY_OFP);
         final BigInteger datapathId = featuresReply != null ? featuresReply.getDatapathId() : BigInteger.ZERO;
         LOG.debug("Actively closing connection: {}, datapathId:{}.",
                 connectionAdapter.getRemoteAddress(), datapathId);
@@ -105,6 +107,7 @@ public class ConnectionContextImpl implements ConnectionContext {
 
     @Override
     public void onConnectionClosed() {
+        SessionStatistics.countEvent(nodeId.toString(), SessionStatistics.ConnectionStatus.CONNECTION_DISCONNECTED_BY_DEVICE);
         connectionState = ConnectionContext.CONNECTION_STATE.RIP;
 
         final InetSocketAddress remoteAddress = connectionAdapter.getRemoteAddress();
index 5cc50feef05da6bc798156191c41025b1fa6f4cc..8cca35254ab0cddae181a36052995f965c3e0a45 100644 (file)
@@ -24,6 +24,7 @@ import org.opendaylight.openflowplugin.impl.connection.listener.ConnectionReadyL
 import org.opendaylight.openflowplugin.impl.connection.listener.HandshakeListenerImpl;
 import org.opendaylight.openflowplugin.impl.connection.listener.OpenflowProtocolListenerInitialImpl;
 import org.opendaylight.openflowplugin.impl.connection.listener.SystemNotificationsListenerImpl;
+import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.SessionStatistics;
 import org.opendaylight.openflowplugin.openflow.md.core.ErrorHandlerSimpleImpl;
 import org.opendaylight.openflowplugin.openflow.md.core.HandshakeManagerImpl;
 import org.opendaylight.openflowplugin.openflow.md.core.ThreadPoolLoggingExecutor;
index 2f1261e79952e7c3596f53bc48b2ef2264b4cf81..a78fe057eba939832540e3d109ff3c2140811ff6 100644 (file)
@@ -11,6 +11,7 @@ import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext
 import org.opendaylight.openflowplugin.api.openflow.connection.HandshakeContext;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceConnectedHandler;
 import org.opendaylight.openflowplugin.api.openflow.md.core.HandshakeListener;
+import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.SessionStatistics;
 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
 import org.slf4j.Logger;
@@ -44,6 +45,7 @@ public class HandshakeListenerImpl implements HandshakeListener {
         connectionContext.setFeatures(featureOutput);
         connectionContext.setNodeId(InventoryDataServiceUtil.nodeIdFromDatapathId(featureOutput.getDatapathId()));
         deviceConnectedHandler.deviceConnected(connectionContext);
+        SessionStatistics.countEvent(connectionContext.getNodeId().toString(), SessionStatistics.ConnectionStatus.CONNECTION_CREATED);
     }
 
     @Override
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/karaf/ResetSessionStatsComandProvider.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/karaf/ResetSessionStatsComandProvider.java
new file mode 100644 (file)
index 0000000..3339b28
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. 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.openflowplugin.impl.karaf;
+
+import java.io.PrintStream;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter;
+
+/**
+ * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 28.5.2015.
+ */
+@Command(scope = "ofp", name = "reset-session-stats", description = "Resets session statistics counters.")
+public class ResetSessionStatsComandProvider extends OsgiCommandSupport {
+
+    @Override
+    protected Object doExecute() throws Exception {
+        PrintStream out = session.getConsole();
+        EventsTimeCounter.resetAllCounters();
+        out.print("Session statistics counters reset.\n");
+        return null;
+    }
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/karaf/ShowSessionStatsCommandProvider.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/karaf/ShowSessionStatsCommandProvider.java
new file mode 100644 (file)
index 0000000..c7733dc
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. 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.openflowplugin.impl.karaf;
+
+import java.io.PrintStream;
+import java.util.List;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
+import org.opendaylight.openflowplugin.impl.OpenFlowPluginProviderImpl;
+import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.SessionStatistics;
+
+/**
+ * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 21.5.2015.
+ */
+
+@Command(scope = "ofp", name = "show-session-stats", description = "Show session statistics.")
+public class ShowSessionStatsCommandProvider extends OsgiCommandSupport {
+
+    @Override
+    protected Object doExecute() throws Exception {
+        PrintStream out = session.getConsole();
+        final List<String> statistics = SessionStatistics.provideStatistics();
+        final StringBuilder result = new StringBuilder();
+        for (String line : statistics) {
+            result.append(line);
+            result.append("\n");
+        }
+        out.print(result.toString());
+        return null;
+    }
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/ofpspecific/SessionStatistics.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/ofpspecific/SessionStatistics.java
new file mode 100644 (file)
index 0000000..fcf106c
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. 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.openflowplugin.impl.statistics.ofpspecific;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLongFieldUpdater;
+
+/**
+ * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 5.6.2015.
+ */
+public class SessionStatistics {
+
+    private static final Map<String, Map<ConnectionStatus, EventCounter>> sessionEvents = new HashMap<>();
+
+    public static void countEvent(final String sessionId, final ConnectionStatus connectionStatus) {
+        Map<ConnectionStatus, EventCounter> sessionsConnectionEvents = getConnectionEvents(sessionId);
+        EventCounter connectionEvent = getConnectionEvent(sessionsConnectionEvents, connectionStatus);
+        connectionEvent.increment();
+    }
+
+    private static EventCounter getConnectionEvent(final Map<ConnectionStatus, EventCounter> sessionsConnectionEvents,
+                                                   final ConnectionStatus connectionStatus) {
+        EventCounter eventCounter = sessionsConnectionEvents.get(connectionStatus);
+        if (null == eventCounter) {
+            eventCounter = new EventCounter();
+            sessionsConnectionEvents.put(connectionStatus, eventCounter);
+        }
+        return eventCounter;
+    }
+
+    private static Map<ConnectionStatus, EventCounter> getConnectionEvents(final String sessionId) {
+        Map<ConnectionStatus, EventCounter> sessionConnectionEvents = sessionEvents.get(sessionId);
+        if (null == sessionConnectionEvents) {
+            sessionConnectionEvents = new HashMap<>();
+            sessionEvents.put(sessionId, sessionConnectionEvents);
+        }
+        return sessionConnectionEvents;
+    }
+
+
+    public static List<String> provideStatistics() {
+        List<String> dump = new ArrayList<>();
+        for (Map.Entry<String, Map<ConnectionStatus, EventCounter>> sessionEntries : sessionEvents.entrySet()) {
+            Map<ConnectionStatus, EventCounter> sessionEvents = sessionEntries.getValue();
+            dump.add(String.format("SESSION : %s", sessionEntries.getKey()));
+            for (Map.Entry<ConnectionStatus, EventCounter> sessionEvent : sessionEvents.entrySet()) {
+                dump.add(String.format(" %s : %d", sessionEvent.getKey().toString(), sessionEvent.getValue().getCount()));
+            }
+        }
+        return dump;
+
+    }
+
+    public enum ConnectionStatus {
+        CONNECTION_CREATED, CONNECTION_DISCONNECTED_BY_DEVICE, CONNECTION_DISCONNECTED_BY_OFP;
+    }
+
+    private static final class EventCounter {
+        private final AtomicLongFieldUpdater<EventCounter> UPDATER = AtomicLongFieldUpdater.newUpdater(EventCounter.class, "count");
+        private volatile long count;
+
+        public long getCount() {
+            return count;
+        }
+
+        public void increment() {
+            count = UPDATER.incrementAndGet(this);
+        }
+    }
+}
index ded2fbef37ee7eafabbfbaf282de4ca90c923904..80020bbe150a367cde1a5fb9f08803fd0f246599 100644 (file)
         <command name="ofp/show-time-counters">
             <action class="org.opendaylight.openflowplugin.impl.karaf.ShowEventTimesComandProvider"/>
         </command>
+        <command name="ofp/show-session-stats">
+            <action class="org.opendaylight.openflowplugin.impl.karaf.ShowSessionStatsCommandProvider"/>
+        </command>
         <command name="ofp/reset-time-counters">
             <action class="org.opendaylight.openflowplugin.impl.karaf.ResetEventTimesComandProvider"/>
         </command>
+        <command name="ofp/reset-session-stats">
+            <action class="org.opendaylight.openflowplugin.impl.karaf.ResetSessionStatsComandProvider"/>
+        </command>
     </command-bundle>
 
 
index 8c24fcc80686073d90d2aa01c0b1c57301012dab..f5cfaaa60e1e0fb22eca64591c4b69cbd595ea52 100644 (file)
@@ -21,6 +21,7 @@ import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutputBuilder;
@@ -47,11 +48,13 @@ public class SystemNotificationsListenerImplTest {
 
     private SystemNotificationsListenerImpl systemNotificationsListener;
     private ConnectionContextImpl connectionContextGolem;
+    private static final NodeId nodeId = new NodeId("OFP:TEST");
 
     @Before
     public void setUp() {
         connectionContextGolem = new ConnectionContextImpl(connectionAdapter);
         connectionContextGolem.changeStateToWorking();
+        connectionContextGolem.setNodeId(nodeId);
 
         Mockito.when(connectionAdapter.getRemoteAddress()).thenReturn(
                 InetSocketAddress.createUnresolved("unit-odl.example.org", 4242));
@@ -60,6 +63,7 @@ public class SystemNotificationsListenerImplTest {
 
         Mockito.when(connectionContext.getConnectionAdapter()).thenReturn(connectionAdapter);
         Mockito.when(connectionContext.getFeatures()).thenReturn(features);
+        Mockito.when(connectionContext.getNodeId()).thenReturn(nodeId);
 
         systemNotificationsListener = new SystemNotificationsListenerImpl(connectionContext);
     }