Bug-2081: PCEP statistics 67/11767/7
authorMilos Fabian <milfabia@cisco.com>
Mon, 6 Oct 2014 07:19:01 +0000 (09:19 +0200)
committerMilos Fabian <milfabia@cisco.com>
Thu, 16 Oct 2014 08:17:39 +0000 (10:17 +0200)
-PCEP session statistics:
-received/sent messages count
-received/sent error msgs count
-last sent msg timestamp
-last received/sent error type/value
-unknown msgs received count
-local and remote peer preferences
-keepalive, deadtimer, ip address, session-id
-PCEP session listener statistics
-remote peer stateful preferences
-session duration
-delegated lsps count
-synchronization status
-last received report msg timestamp
-received report msg count
-sent init/update msg count
-request time measurement
-tear down session op.
-reset statistics op.

-statistics are related to pcep-topology-provider config module
-reachable via JMX, NETCONF, Restconf as operational data

Change-Id: I40fd658028e386040fd6c90d805a5724aff6bddd
Signed-off-by: Milos Fabian <milfabia@cisco.com>
19 files changed:
pcep/api/src/main/java/org/opendaylight/protocol/pcep/PCEPSession.java
pcep/api/src/main/yang/pcep-session-stats.yang [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionImpl.java
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionRuntimeMXBean.java [deleted file]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionState.java [new file with mode: 0644]
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/AbstractPCEPSessionTest.java
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPDispatcherImplTest.java
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPSessionImplTest.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/AbstractTopologySessionListener.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/PCEPRequest.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/PCEPTopologyProvider.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/ServerSessionManager.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/SessionListenerState.java [new file with mode: 0644]
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/Stateful02TopologySessionListener.java
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/Stateful07TopologySessionListener.java
pcep/topology-provider/src/main/java/org/opendaylight/controller/config/yang/pcep/topology/provider/PCEPTopologyProviderModule.java
pcep/topology-provider/src/main/yang/odl-pcep-topology-provider-cfg.yang
pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/AbstractPCEPSessionTest.java
pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/Stateful07TopologySessionListenerTest.java

index bb15c92b02627bd7b375db2f618d1d611c81e112..1d5efe2548e027a79c602fe03832c8291d3f9805 100644 (file)
@@ -8,10 +8,9 @@
 package org.opendaylight.protocol.pcep;
 
 import io.netty.util.concurrent.Future;
-
 import java.net.InetAddress;
-
 import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.PcepSessionState;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.Tlvs;
 
@@ -21,7 +20,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.typ
  * manually. If the session is up, it has to redirect messages to/from user. Handles also malformed messages and unknown
  * requests.
  */
-public interface PCEPSession extends ProtocolSession<Message> {
+public interface PCEPSession extends ProtocolSession<Message>, PcepSessionState {
 
     /**
      * Sends message from user to PCE/PCC. If the user sends an Open Message, the session returns an error (open message
@@ -38,4 +37,6 @@ public interface PCEPSession extends ProtocolSession<Message> {
     Tlvs getRemoteTlvs();
 
     InetAddress getRemoteAddress();
+
+    void resetStats();
 }
diff --git a/pcep/api/src/main/yang/pcep-session-stats.yang b/pcep/api/src/main/yang/pcep-session-stats.yang
new file mode 100644 (file)
index 0000000..035ebb3
--- /dev/null
@@ -0,0 +1,124 @@
+// vi: set smarttab et sw=4 tabstop=4:
+module pcep-session-stats {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:pcep:stats";
+    prefix "pcep-stats";
+
+    organization "Cisco Systems, Inc.";
+
+    contact "Milos Fabian <milfabia@cisco.com>";
+
+    description
+        "This module contains the base YANG definitions for
+         PCEP session statistics.
+
+        Copyright (c)2014 Cisco Systems, Inc. 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";
+
+    revision "2014-10-06" {
+        description
+            "Initial revision";
+    }
+
+    grouping error {
+        description "PCEP Error-type/value.";
+        leaf error-type {
+            type uint8;
+            default 0;
+        }
+        leaf error-value {
+            type uint8;
+            default 0;
+        }
+    }
+
+    grouping preferences {
+        leaf keepalive {
+            description "Advertised keep-alive value.";
+            type uint8;
+            default 0;
+        }
+
+        leaf deadtimer {
+            description "Advertised deadtimer value.";
+            type uint8;
+            default 0;
+        }
+
+        leaf ip-address {
+            description "Peer's IP address.";
+            type string;
+            default "";
+        }
+
+        leaf session-id {
+            description "Peer's session identifier.";
+            type uint16;
+            default 0;
+        }
+    }
+
+    grouping pcep-session-state {
+        description "PCEP session statistics.";
+
+        container messages {
+            description "The statistics of PCEP received/sent messages from the PCE point of view.";
+            leaf received-msg-count {
+                description "Total number of received PCEP messages.";
+                type uint32;
+            }
+
+            leaf sent-msg-count {
+                description "Total number of sent PCEP messages.";
+                type uint32;
+            }
+
+            leaf last-sent-msg-timestamp {
+                description "The timestamp of last sent message.";
+                type uint32;
+            }
+
+            leaf unknown-msg-received {
+                description "The number of received unknown messages.";
+                type uint16;
+            }
+
+            container error-messages {
+                description "The message statistics of received/sent PCErr messages.";
+                leaf received-error-msg-count {
+                    description "Total number of received PCErr messages.";
+                    type uint32;
+                }
+
+                leaf sent-error-msg-count {
+                    description "Total number of sent PCErr messages.";
+                    type uint32;
+                }
+
+                container last-received-error {
+                    description "Type/value tuple of last received error.";
+                    uses error;
+                }
+
+                container last-sent-error {
+                    description "Type/value tuple of last sent error.";
+                    uses error;
+                }
+            }
+        }
+
+        container local-pref {
+            description "The local (PCE) preferences.";
+            uses preferences;
+        }
+
+        container peer-pref {
+            description "The remote peer (PCC) preferences.";
+            uses preferences;
+        }
+    }
+}
\ No newline at end of file
index 5739ad1767c4b3248b595179d03b5174b681b966..a4aed7154d38d55091af687b12f9617576424668 100644 (file)
@@ -28,6 +28,9 @@ import org.opendaylight.protocol.pcep.PCEPSession;
 import org.opendaylight.protocol.pcep.PCEPSessionListener;
 import org.opendaylight.protocol.pcep.TerminationReason;
 import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.LocalPref;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.Messages;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.PeerPref;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.CloseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Keepalive;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.KeepaliveBuilder;
@@ -35,11 +38,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.typ
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.KeepaliveMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.OpenMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.PcerrMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.close.message.CCloseMessageBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.close.object.CCloseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.keepalive.message.KeepaliveMessageBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.Open;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.Tlvs;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -47,7 +52,7 @@ import org.slf4j.LoggerFactory;
  * Implementation of PCEPSession. (Not final for testing.)
  */
 @VisibleForTesting
-public class PCEPSessionImpl extends AbstractProtocolSession<Message> implements PCEPSession, PCEPSessionRuntimeMXBean {
+public class PCEPSessionImpl extends AbstractProtocolSession<Message> implements PCEPSession {
     /**
      * System.nanoTime value about when was sent the last message Protected to be updated also in tests.
      */
@@ -75,10 +80,6 @@ public class PCEPSessionImpl extends AbstractProtocolSession<Message> implements
 
     private static final Logger LOG = LoggerFactory.getLogger(PCEPSessionImpl.class);
 
-    private int sentMsgCount = 0;
-
-    private int receivedMsgCount = 0;
-
     private int maxUnknownMessages;
 
     // True if the listener should not be notified about events
@@ -88,6 +89,8 @@ public class PCEPSessionImpl extends AbstractProtocolSession<Message> implements
 
     private final Keepalive kaMessage = new KeepaliveBuilder().setKeepaliveMessage(new KeepaliveMessageBuilder().build()).build();
 
+    private final PCEPSessionState sessionState;
+
     PCEPSessionImpl(final PCEPSessionListener listener, final int maxUnknownMessages, final Channel channel,
         final Open localOpen, final Open remoteOpen) {
         this.listener = Preconditions.checkNotNull(listener);
@@ -121,6 +124,15 @@ public class PCEPSessionImpl extends AbstractProtocolSession<Message> implements
 
         LOG.info("Session {}[{}] <-> {}[{}] started", channel.localAddress(), localOpen.getSessionId(), channel.remoteAddress(),
             remoteOpen.getSessionId());
+        this.sessionState = new PCEPSessionState(remoteOpen, localOpen, channel);
+    }
+
+    public Integer getKeepAliveTimerValue() {
+        return this.localOpen.getKeepalive().intValue();
+    }
+
+    public Integer getDeadTimerValue() {
+        return this.remoteOpen.getDeadTimer().intValue();
     }
 
     /**
@@ -184,10 +196,13 @@ public class PCEPSessionImpl extends AbstractProtocolSession<Message> implements
     public Future<Void> sendMessage(final Message msg) {
         final ChannelFuture f = this.channel.writeAndFlush(msg);
         this.lastMessageSentAt = System.nanoTime();
+        this.sessionState.updateLastSentMsg();
         if (!(msg instanceof KeepaliveMessage)) {
             LOG.debug("PCEP Message enqueued: {}", msg);
         }
-        this.sentMsgCount++;
+        if (msg instanceof PcerrMessage) {
+            this.sessionState.setLastSentError(msg);
+        }
 
         f.addListener(new ChannelFutureListener() {
             @Override
@@ -223,7 +238,7 @@ public class PCEPSessionImpl extends AbstractProtocolSession<Message> implements
         this.closed = true;
         this.sendMessage(new CloseBuilder().setCCloseMessage(
             new CCloseMessageBuilder().setCClose(new CCloseBuilder().setReason(reason.getShortValue()).build()).build()).build());
-        this.channel.close();
+        this.close();
     }
 
     @Override
@@ -300,7 +315,7 @@ public class PCEPSessionImpl extends AbstractProtocolSession<Message> implements
     public synchronized void handleMessage(final Message msg) {
         // Update last reception time
         this.lastMessageReceivedAt = System.nanoTime();
-        this.receivedMsgCount++;
+        this.sessionState.updateLastReceivedMsg();
         if (!(msg instanceof KeepaliveMessage)) {
             LOG.debug("PCEP message {} received.", msg);
         }
@@ -318,74 +333,57 @@ public class PCEPSessionImpl extends AbstractProtocolSession<Message> implements
             this.close();
         } else {
             // This message needs to be handled by the user
+            if (msg instanceof PcerrMessage) {
+                this.sessionState.setLastReceivedError(msg);
+            }
             this.listener.onMessage(this, msg);
         }
     }
 
-    /**
-     * @return the sentMsgCount
-     */
-
     @Override
-    public final Integer getSentMsgCount() {
-        return this.sentMsgCount;
+    public final String toString() {
+        return addToStringAttributes(Objects.toStringHelper(this)).toString();
     }
 
-    /**
-     * @return the receivedMsgCount
-     */
-
-    @Override
-    public final Integer getReceivedMsgCount() {
-        return this.receivedMsgCount;
+    protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+        toStringHelper.add("channel", this.channel);
+        toStringHelper.add("localOpen", this.localOpen);
+        toStringHelper.add("remoteOpen", this.remoteOpen);
+        return toStringHelper;
     }
 
     @Override
-    public final Integer getDeadTimerValue() {
-        return Integer.valueOf(this.remoteOpen.getDeadTimer());
+    @VisibleForTesting
+    public void sessionUp() {
+        this.listener.onSessionUp(this);
     }
 
-    @Override
-    public final Integer getKeepAliveTimerValue() {
-        return Integer.valueOf(this.localOpen.getKeepalive());
+    @VisibleForTesting
+    protected final Queue<Long> getUnknownMessagesTimes() {
+        return this.unknownMessagesTimes;
     }
 
     @Override
-    public final String getPeerAddress() {
-        final InetSocketAddress a = (InetSocketAddress) this.channel.remoteAddress();
-        return a.getHostName();
+    public Messages getMessages() {
+        return this.sessionState.getMessages(this.unknownMessagesTimes.size());
     }
 
     @Override
-    public void tearDown() {
-        this.close();
+    public LocalPref getLocalPref() {
+        return this.sessionState.getLocalPref();
     }
 
     @Override
-    public final String toString() {
-        return addToStringAttributes(Objects.toStringHelper(this)).toString();
-    }
-
-    protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
-        toStringHelper.add("channel", this.channel);
-        toStringHelper.add("localOpen", this.localOpen);
-        toStringHelper.add("remoteOpen", this.remoteOpen);
-        return toStringHelper;
+    public PeerPref getPeerPref() {
+        return this.sessionState.getPeerPref();
     }
 
     @Override
-    @VisibleForTesting
-    public void sessionUp() {
-        this.listener.onSessionUp(this);
+    public Class<? extends DataContainer> getImplementedInterface() {
+        throw new UnsupportedOperationException();
     }
-
     @Override
-    public String getNodeIdentifier() {
-        return "";
-    }
-
-    @VisibleForTesting
-    protected final Queue<Long> getUnknownMessagesTimes() {
-        return this.unknownMessagesTimes;
+    public void resetStats() {
+        this.sessionState.reset();
     }
 }
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionRuntimeMXBean.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionRuntimeMXBean.java
deleted file mode 100644 (file)
index 6d951cf..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2013 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.protocol.pcep.impl;
-
-import java.io.IOException;
-
-public interface PCEPSessionRuntimeMXBean {
-    // FIXME: BUG-194: remove once operations are generated
-
-    Integer getDeadTimerValue();
-
-    Integer getKeepAliveTimerValue();
-
-    Integer getReceivedMsgCount();
-
-    Integer getSentMsgCount();
-
-    String getPeerAddress();
-
-    String getNodeIdentifier();
-
-    void tearDown() throws IOException;
-}
diff --git a/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionState.java b/pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionState.java
new file mode 100644 (file)
index 0000000..be4e34b
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2014 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.protocol.pcep.impl;
+
+import com.google.common.base.Preconditions;
+import io.netty.channel.Channel;
+import java.net.InetSocketAddress;
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.LocalPref;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.LocalPrefBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.Messages;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.MessagesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.PeerPref;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.PeerPrefBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.messages.ErrorMessagesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.messages.error.messages.LastReceivedErrorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.messages.error.messages.LastSentErrorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.PcerrMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.Open;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcep.error.object.ErrorObject;
+
+final class PCEPSessionState {
+    private long sentMsgCount = 0;
+    private long receivedMsgCount = 0;
+    private long sentErrMsgCount = 0;
+    private long receivedErrMsgCount = 0;
+    private long lastSentMsgTimestamp = 0;
+    private final PeerPref peerPref;
+    private final LocalPref localPref;
+    private final LastReceivedErrorBuilder lastReceivedErrorBuilder;
+    private final LastSentErrorBuilder lastSentErrorBuilder;
+    private final ErrorMessagesBuilder errorsBuilder;
+    private final MessagesBuilder msgsBuilder;
+
+    public PCEPSessionState(final Open remoteOpen, final Open localOpen, final Channel channel) {
+        Preconditions.checkNotNull(remoteOpen);
+        Preconditions.checkNotNull(localOpen);
+        Preconditions.checkNotNull(channel);
+        this.peerPref = getRemotePref(remoteOpen, channel);
+        this.localPref = getLocalPref(localOpen, channel);
+        this.lastReceivedErrorBuilder = new LastReceivedErrorBuilder();
+        this.lastSentErrorBuilder = new LastSentErrorBuilder();
+        this.errorsBuilder = new ErrorMessagesBuilder();
+        this.msgsBuilder = new MessagesBuilder();
+    }
+
+    public Messages getMessages(final int unknownMessagesCount) {
+        this.errorsBuilder.setReceivedErrorMsgCount(this.receivedErrMsgCount);
+        this.errorsBuilder.setSentErrorMsgCount(this.sentErrMsgCount);
+        this.errorsBuilder.setLastReceivedError(this.lastReceivedErrorBuilder.build());
+        this.errorsBuilder.setLastSentError(this.lastSentErrorBuilder.build());
+        this.msgsBuilder.setLastSentMsgTimestamp(TimeUnit.MILLISECONDS.toSeconds(this.lastSentMsgTimestamp));
+        this.msgsBuilder.setReceivedMsgCount(this.receivedMsgCount);
+        this.msgsBuilder.setSentMsgCount(this.sentMsgCount);
+        this.msgsBuilder.setUnknownMsgReceived(unknownMessagesCount);
+        this.msgsBuilder.setErrorMessages(this.errorsBuilder.build());
+        return this.msgsBuilder.build();
+    }
+
+    public void reset() {
+        this.receivedMsgCount = 0;
+        this.sentMsgCount = 0;
+        this.receivedErrMsgCount = 0;
+        this.sentErrMsgCount = 0;
+        this.lastSentMsgTimestamp = 0;
+        this.lastReceivedErrorBuilder.setErrorType((short) 0);
+        this.lastReceivedErrorBuilder.setErrorValue((short) 0);
+        this.lastSentErrorBuilder.setErrorType((short) 0);
+        this.lastSentErrorBuilder.setErrorValue((short) 0);
+    }
+
+    public LocalPref getLocalPref() {
+        return this.localPref;
+    }
+
+    public PeerPref getPeerPref() {
+        return this.peerPref;
+    }
+
+    public void setLastSentError(final Message msg) {
+        this.sentErrMsgCount++;
+        final ErrorObject errObj = getErrorObject(msg);
+        this.lastSentErrorBuilder.setErrorType(errObj.getType());
+        this.lastSentErrorBuilder.setErrorValue(errObj.getValue());
+    }
+
+    public void setLastReceivedError(final Message msg) {
+        final ErrorObject errObj = getErrorObject(msg);
+        this.receivedErrMsgCount++;
+        this.lastReceivedErrorBuilder.setErrorType(errObj.getType());
+        this.lastReceivedErrorBuilder.setErrorValue(errObj.getValue());
+    }
+
+    public void updateLastReceivedMsg() {
+        this.receivedMsgCount++;
+    }
+
+    public void updateLastSentMsg() {
+        this.lastSentMsgTimestamp = System.currentTimeMillis();
+        this.sentMsgCount++;
+    }
+
+    private static ErrorObject getErrorObject(final Message msg) {
+        Preconditions.checkNotNull(msg);
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.PcerrMessage errMsg =
+                ((PcerrMessage) msg).getPcerrMessage();
+        return errMsg.getErrors().get(errMsg.getErrors().size() - 1).getErrorObject();
+    }
+
+    private static PeerPref getRemotePref(final Open open, final Channel channel) {
+        final PeerPrefBuilder peerBuilder = new PeerPrefBuilder();
+        peerBuilder.setDeadtimer(open.getDeadTimer());
+        peerBuilder.setKeepalive(open.getKeepalive());
+        peerBuilder.setIpAddress(((InetSocketAddress) channel.remoteAddress()).getAddress().getHostAddress());
+        peerBuilder.setSessionId(open.getSessionId().intValue());
+        return peerBuilder.build();
+    }
+
+    private static LocalPref getLocalPref(final Open open, final Channel channel) {
+        final LocalPrefBuilder peerBuilder = new LocalPrefBuilder();
+        peerBuilder.setDeadtimer(open.getDeadTimer());
+        peerBuilder.setKeepalive(open.getKeepalive());
+        peerBuilder.setIpAddress(((InetSocketAddress) channel.localAddress()).getAddress().getHostAddress());
+        peerBuilder.setSessionId(open.getSessionId().intValue());
+        return peerBuilder.build();
+    }
+}
index 4eb9f9d2d141fb37663e3a6c474049103ebaf5a7..bb491f59006eb8a132ea186a1123157f3a88e451 100644 (file)
@@ -40,6 +40,10 @@ import org.opendaylight.yangtools.yang.binding.Notification;
 
 public class AbstractPCEPSessionTest {
 
+    protected static final String IP_ADDRESS = "127.0.0.1";
+    protected static final short KEEP_ALIVE = 15;
+    protected static final short DEADTIMER = 40;
+
     @Mock
     protected Channel channel;
 
@@ -85,12 +89,12 @@ public class AbstractPCEPSessionTest {
         doReturn(this.pipeline).when(this.pipeline).replace(any(ChannelHandler.class), any(String.class), any(ChannelHandler.class));
         doReturn(true).when(this.channel).isActive();
         doReturn(mock(ChannelFuture.class)).when(this.channel).close();
-        doReturn(InetSocketAddress.createUnresolved("127.0.0.1", 4189)).when(this.channel).remoteAddress();
-        doReturn(InetSocketAddress.createUnresolved("127.0.0.1", 4189)).when(this.channel).localAddress();
+        doReturn(new InetSocketAddress(IP_ADDRESS, 4189)).when(this.channel).remoteAddress();
+        doReturn(new InetSocketAddress(IP_ADDRESS, 4189)).when(this.channel).localAddress();
         this.openMsg = new OpenBuilder().setOpenMessage(
                 new OpenMessageBuilder().setOpen(
                         new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder().setDeadTimer(
-                                (short) 45).setKeepalive((short) 15).build()).build()).build();
+                                DEADTIMER).setKeepalive(KEEP_ALIVE).setSessionId((short) 0).build()).build()).build();
         this.kaMsg = new KeepaliveBuilder().setKeepaliveMessage(new KeepaliveMessageBuilder().build()).build();
 
         this.listener = new SimpleSessionListener();
index fc52bcdee92d43381c077ab868a0a7b15d608427..f513a2a29818bdb3ce31c84378ac91a4f46d9667 100644 (file)
@@ -91,11 +91,11 @@ public class PCEPDispatcherImplTest {
                 }).get();
 
         Assert.assertTrue(futureChannel.channel().isActive());
-        Assert.assertEquals(CLIENT1_ADDRESS.getAddress().getHostAddress(), session1.getPeerAddress());
+        Assert.assertEquals(CLIENT1_ADDRESS.getAddress().getHostAddress(), session1.getPeerPref().getIpAddress());
         Assert.assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
         Assert.assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
 
-        Assert.assertEquals(CLIENT2_ADDRESS.getAddress().getHostAddress(), session2.getPeerAddress());
+        Assert.assertEquals(CLIENT2_ADDRESS.getAddress().getHostAddress(), session2.getPeerPref().getIpAddress());
         Assert.assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
         Assert.assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
 
index 4b653345f92ba3cf8aadea1831f1e9530cbc7720..46f632237dc594553d30fc50484c67164f1f709f 100644 (file)
@@ -15,6 +15,10 @@ import org.junit.Test;
 import org.mockito.Mockito;
 import org.opendaylight.protocol.pcep.TerminationReason;
 import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.LocalPref;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.Messages;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.PeerPref;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.messages.ErrorMessages;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.CloseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcreq;
@@ -34,34 +38,36 @@ public class PCEPSessionImplTest extends AbstractPCEPSessionTest {
 
     @After
     public void tearDown() {
-        this.session.tearDown();
+        this.session.close();
     }
 
     @Test
     public void testPcepSessionImpl() throws InterruptedException {
         Assert.assertTrue(this.listener.up);
 
-        Assert.assertEquals(45, this.session.getDeadTimerValue().intValue());
-        Assert.assertEquals(15, this.session.getKeepAliveTimerValue().intValue());
         this.session.handleMessage(this.kaMsg);
-        Assert.assertEquals(1, this.session.getReceivedMsgCount().intValue());
+        Assert.assertEquals(1, this.session.getMessages().getReceivedMsgCount().intValue());
 
         this.session.handleMessage(new PcreqBuilder().build());
-        Assert.assertEquals(2, this.session.getReceivedMsgCount().intValue());
+        Assert.assertEquals(2, this.session.getMessages().getReceivedMsgCount().intValue());
         Assert.assertEquals(1, this.listener.messages.size());
         Assert.assertTrue(this.listener.messages.get(0) instanceof Pcreq);
+        Assert.assertEquals(2, this.session.getMessages().getReceivedMsgCount().intValue());
 
         this.session.handleMessage(new CloseBuilder().build());
-        Assert.assertEquals(3, this.session.getReceivedMsgCount().intValue());
+        Assert.assertEquals(3, this.session.getMessages().getReceivedMsgCount().intValue());
         Assert.assertEquals(1, this.listener.messages.size());
         Assert.assertTrue(this.channel.isActive());
         Mockito.verify(this.channel, Mockito.times(1)).close();
+
+        this.session.resetStats();
+        Assert.assertEquals(0, this.session.getMessages().getReceivedMsgCount().longValue());
     }
 
     @Test
     public void testAttemptSecondSession() {
         this.session.handleMessage(this.openMsg);
-        Assert.assertEquals(1, this.session.getReceivedMsgCount().intValue());
+        Assert.assertEquals(1, this.session.getMessages().getReceivedMsgCount().intValue());
         Assert.assertEquals(1, this.msgsSend.size());
         Assert.assertTrue(this.msgsSend.get(0) instanceof Pcerr);
         final Pcerr pcErr = (Pcerr) this.msgsSend.get(0);
@@ -77,7 +83,7 @@ public class PCEPSessionImplTest extends AbstractPCEPSessionTest {
         final Pcerr pcErr = (Pcerr) this.msgsSend.get(0);
         final ErrorObject errorObj = pcErr.getPcerrMessage().getErrors().get(0).getErrorObject();
         Assert.assertEquals(PCEPErrors.CAPABILITY_NOT_SUPPORTED, PCEPErrors.forValue(errorObj.getType(), errorObj.getValue()));
-        Assert.assertEquals(1, this.session.getUnknownMessagesTimes().size());
+        Assert.assertEquals(1, this.session.getMessages().getUnknownMsgReceived().intValue());
         // exceeded max. unknown messages count - terminate session
         Assert.assertTrue(this.msgsSend.get(1) instanceof CloseMessage);
         final CloseMessage closeMsg = (CloseMessage) this.msgsSend.get(1);
@@ -93,7 +99,7 @@ public class PCEPSessionImplTest extends AbstractPCEPSessionTest {
     }
 
     @Test
-    public void voidTestCloseSessionWithReason() {
+    public void testCloseSessionWithReason() {
         this.session.close(TerminationReason.Unknown);
         Assert.assertEquals(1, this.msgsSend.size());
         Assert.assertTrue(this.msgsSend.get(0) instanceof CloseMessage);
@@ -101,4 +107,40 @@ public class PCEPSessionImplTest extends AbstractPCEPSessionTest {
         Assert.assertEquals(TerminationReason.Unknown, TerminationReason.forValue(closeMsg.getCCloseMessage().getCClose().getReason()));
         Mockito.verify(this.channel, Mockito.times(1)).close();
     }
+
+    @Test
+    public void testSessionStatistics() {
+        this.session.handleMessage(Util.createErrorMessage(PCEPErrors.LSP_RSVP_ERROR, null));
+        Assert.assertEquals(IP_ADDRESS, this.session.getPeerPref().getIpAddress());
+        final PeerPref peerPref = this.session.getPeerPref();
+        Assert.assertEquals(IP_ADDRESS, peerPref.getIpAddress());
+        Assert.assertEquals(DEADTIMER, peerPref.getDeadtimer().shortValue());
+        Assert.assertEquals(KEEP_ALIVE, peerPref.getKeepalive().shortValue());
+        Assert.assertEquals(0, peerPref.getSessionId().intValue());
+        final LocalPref localPref = this.session.getLocalPref();
+        Assert.assertEquals(IP_ADDRESS, localPref.getIpAddress());
+        Assert.assertEquals(DEADTIMER, localPref.getDeadtimer().shortValue());
+        Assert.assertEquals(KEEP_ALIVE, localPref.getKeepalive().shortValue());
+        Assert.assertEquals(0, localPref.getSessionId().intValue());
+        final Messages msgs = this.session.getMessages();
+        Assert.assertEquals(1, msgs.getReceivedMsgCount().longValue());
+        Assert.assertEquals(0, msgs.getSentMsgCount().longValue());
+        Assert.assertEquals(0, msgs.getUnknownMsgReceived().longValue());
+        final ErrorMessages errMsgs = msgs.getErrorMessages();
+        Assert.assertEquals(1, errMsgs.getReceivedErrorMsgCount().intValue());
+        Assert.assertEquals(0, errMsgs.getSentErrorMsgCount().intValue());
+        Assert.assertEquals(PCEPErrors.LSP_RSVP_ERROR.getErrorType(), errMsgs.getLastReceivedError().getErrorType().shortValue());
+        Assert.assertEquals(PCEPErrors.LSP_RSVP_ERROR.getErrorValue(), errMsgs.getLastReceivedError().getErrorValue().shortValue());
+
+        this.session.sendMessage(Util.createErrorMessage(PCEPErrors.UNKNOWN_PLSP_ID, null));
+        final Messages msgs2 = this.session.getMessages();
+        Assert.assertEquals(1, msgs2.getReceivedMsgCount().longValue());
+        Assert.assertEquals(1, msgs2.getSentMsgCount().longValue());
+        Assert.assertEquals(0, msgs2.getUnknownMsgReceived().longValue());
+        final ErrorMessages errMsgs2 = msgs2.getErrorMessages();
+        Assert.assertEquals(1, errMsgs2.getReceivedErrorMsgCount().intValue());
+        Assert.assertEquals(1, errMsgs2.getSentErrorMsgCount().intValue());
+        Assert.assertEquals(PCEPErrors.UNKNOWN_PLSP_ID.getErrorType(), errMsgs2.getLastSentError().getErrorType().shortValue());
+        Assert.assertEquals(PCEPErrors.UNKNOWN_PLSP_ID.getErrorValue(), errMsgs2.getLastSentError().getErrorValue().shortValue());
+    }
 }
index 2424fec4857e30ccef33bdf53dd9b789a5adb42f..1531ddc0d1720a572ff249e24c1ffddd03dc6b4d 100644 (file)
@@ -21,6 +21,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.ListenerStateRuntimeMXBean;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.ListenerStateRuntimeRegistration;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.PeerCapabilities;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.ReplyTime;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.SessionState;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.StatefulMessages;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -59,7 +65,7 @@ import org.slf4j.LoggerFactory;
  * @param <S> identifier type of requests
  * @param <L> identifier type for LSPs
  */
-public abstract class AbstractTopologySessionListener<S, L> implements PCEPSessionListener, TopologySessionListener {
+public abstract class AbstractTopologySessionListener<S, L> implements PCEPSessionListener, TopologySessionListener, ListenerStateRuntimeMXBean {
     protected static final class MessageContext {
         private final Collection<PCEPRequest> requests = new ArrayList<>();
         private final WriteTransaction trans;
@@ -92,6 +98,7 @@ public abstract class AbstractTopologySessionListener<S, L> implements PCEPSessi
             return this.version;
         }
     };
+
     private static final Logger LOG = LoggerFactory.getLogger(AbstractTopologySessionListener.class);
 
     protected static final String MISSING_XML_TAG = "Mandatory XML tags are missing.";
@@ -111,8 +118,12 @@ public abstract class AbstractTopologySessionListener<S, L> implements PCEPSessi
     private boolean synced = false;
     private PCEPSession session;
 
+    private ListenerStateRuntimeRegistration registration;
+    private final SessionListenerState listenerState;
+
     protected AbstractTopologySessionListener(final ServerSessionManager serverSessionManager) {
         this.serverSessionManager = Preconditions.checkNotNull(serverSessionManager);
+        this.listenerState = new SessionListenerState();
     }
 
     @Override
@@ -160,6 +171,10 @@ public abstract class AbstractTopologySessionListener<S, L> implements PCEPSessi
 
         this.session = session;
         this.nodeState = state;
+        this.listenerState.init(session);
+        if (this.serverSessionManager.getRuntimeRootRegistration().isPresent()) {
+            this.registration = this.serverSessionManager.getRuntimeRootRegistration().get().register(this);
+        }
         LOG.info("Session with {} attached to topology node {}", session.getRemoteAddress(), state.getNodeId());
     }
 
@@ -230,6 +245,9 @@ public abstract class AbstractTopologySessionListener<S, L> implements PCEPSessi
 
     @Override
     public void close() {
+        if (this.registration != null) {
+            this.registration.close();
+        }
         if (this.session != null) {
             this.session.close(TerminationReason.Unknown);
         }
@@ -237,6 +255,7 @@ public abstract class AbstractTopologySessionListener<S, L> implements PCEPSessi
 
     protected final synchronized PCEPRequest removeRequest(final S id) {
         final PCEPRequest ret = this.requests.remove(id);
+        this.listenerState.processRequestStats(ret.getElapsedMillis());
         LOG.trace("Removed request {} object {}", id, ret);
         return ret;
     }
@@ -244,6 +263,7 @@ public abstract class AbstractTopologySessionListener<S, L> implements PCEPSessi
     protected final synchronized ListenableFuture<OperationResult> sendMessage(final Message message, final S requestId,
         final Metadata metadata) {
         final io.netty.util.concurrent.Future<Void> f = this.session.sendMessage(message);
+        this.listenerState.updateStatefulSentMsg(message);
         final PCEPRequest req = new PCEPRequest(metadata);
         this.requests.put(requestId, req);
 
@@ -418,4 +438,53 @@ public abstract class AbstractTopologySessionListener<S, L> implements PCEPSessi
     }
 
     protected abstract Object validateReportedLsp(final Optional<ReportedLsp> rep, final LspId input);
+
+    protected SessionListenerState getSessionListenerState() {
+        return this.listenerState;
+    }
+
+    @Override
+    public Integer getDelegatedLspsCount() {
+        return this.lsps.size();
+    }
+
+    @Override
+    public Boolean getSynchronized() {
+        return this.synced;
+    }
+
+    @Override
+    public StatefulMessages getStatefulMessages() {
+        return this.listenerState.getStatefulMessages();
+    }
+
+    @Override
+    public void resetStats() {
+        this.listenerState.resetStats(this.session);
+    }
+
+    @Override
+    public ReplyTime getReplyTime() {
+        return this.listenerState.getReplyTime();
+    }
+
+    @Override
+    public PeerCapabilities getPeerCapabilities() {
+        return this.listenerState.getPeerCapabilities();
+    }
+
+    @Override
+    public void tearDownSession() {
+        this.close();
+    }
+
+    @Override
+    public SessionState getSessionState() {
+        return this.listenerState.getSessionState(this.session);
+    }
+
+    @Override
+    public String getPeerId() {
+        return this.session.getPeerPref().getIpAddress();
+    }
 }
index 95a3e082fa91ce176fb2f18b97665c539101edfc..5feea8267476392e97b6fba4eb6cb406084eacda 100644 (file)
@@ -7,9 +7,10 @@
  */
 package org.opendaylight.bgpcep.pcep.topology.provider;
 
+import com.google.common.base.Stopwatch;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.SettableFuture;
-
+import java.util.concurrent.TimeUnit;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.lsp.metadata.Metadata;
 import org.slf4j.Logger;
@@ -26,11 +27,13 @@ final class PCEPRequest {
     private final SettableFuture<OperationResult> future;
     private final Metadata metadata;
     private volatile State state;
+    private final Stopwatch stopwatch;
 
     PCEPRequest(final Metadata metadata) {
         this.future = SettableFuture.create();
         this.metadata = metadata;
         this.state = State.UNSENT;
+        this.stopwatch = new Stopwatch().start();
     }
 
     protected ListenableFuture<OperationResult> getFuture() {
@@ -59,4 +62,8 @@ final class PCEPRequest {
             state = State.UNACKED;
         }
     }
+
+    public long getElapsedMillis() {
+        return this.stopwatch.elapsed(TimeUnit.MILLISECONDS);
+    }
 }
\ No newline at end of file
index 0b2699e443b47bb8a695900298a7c93c8a0987fd..e85737a86c9c60380ce883bd45184fbc7d32f63e 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.bgpcep.pcep.topology.provider;
 
+import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
@@ -15,6 +16,7 @@ import java.net.InetSocketAddress;
 import java.util.concurrent.ExecutionException;
 import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
 import org.opendaylight.bgpcep.topology.DefaultTopologyReference;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.PCEPTopologyProviderRuntimeRegistrator;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
@@ -50,10 +52,14 @@ public final class PCEPTopologyProvider extends DefaultTopologyReference impleme
 
     public static PCEPTopologyProvider create(final PCEPDispatcher dispatcher, final InetSocketAddress address, final KeyMapping keys,
             final InstructionScheduler scheduler, final DataBroker dataBroker, final RpcProviderRegistry rpcRegistry,
-            final InstanceIdentifier<Topology> topology, final TopologySessionListenerFactory listenerFactory) throws InterruptedException,
+            final InstanceIdentifier<Topology> topology, final TopologySessionListenerFactory listenerFactory,
+            Optional<PCEPTopologyProviderRuntimeRegistrator> runtimeRootRegistrator) throws InterruptedException,
             ExecutionException, ReadFailedException, TransactionCommitFailedException {
 
         final ServerSessionManager manager = new ServerSessionManager(dataBroker, topology, listenerFactory);
+        if (runtimeRootRegistrator.isPresent()) {
+            manager.registerRuntimeRootRegistartion(runtimeRootRegistrator.get());
+        }
         final ChannelFuture f = dispatcher.createServer(address, keys, manager);
         f.get();
 
index afc7172f89ee03f5af6a32431cdc4aec6eb8217a..f3afdfae8392a313d417838b71aee3a716575ee7 100644 (file)
@@ -15,6 +15,9 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.PCEPTopologyProviderRuntimeMXBean;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.PCEPTopologyProviderRuntimeRegistration;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.PCEPTopologyProviderRuntimeRegistrator;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
@@ -47,7 +50,7 @@ import org.slf4j.LoggerFactory;
 /**
  *
  */
-final class ServerSessionManager implements SessionListenerFactory<PCEPSessionListener>, AutoCloseable, TopologySessionRPCs {
+final class ServerSessionManager implements SessionListenerFactory<PCEPSessionListener>, AutoCloseable, TopologySessionRPCs, PCEPTopologyProviderRuntimeMXBean {
     private static final Logger LOG = LoggerFactory.getLogger(ServerSessionManager.class);
     private static final long DEFAULT_HOLD_STATE_NANOS = TimeUnit.MINUTES.toNanos(5);
 
@@ -56,6 +59,7 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
     private final TopologySessionListenerFactory listenerFactory;
     private final InstanceIdentifier<Topology> topology;
     private final DataBroker broker;
+    private Optional<PCEPTopologyProviderRuntimeRegistration> runtimeRootRegistration = Optional.absent();
 
     public ServerSessionManager(final DataBroker broker, final InstanceIdentifier<Topology> topology,
             final TopologySessionListenerFactory listenerFactory) throws ReadFailedException, TransactionCommitFailedException {
@@ -165,6 +169,9 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
 
     @Override
     public void close() throws TransactionCommitFailedException {
+        if (this.runtimeRootRegistration.isPresent()) {
+            this.runtimeRootRegistration.get().close();
+        }
         for (final TopologySessionListener sessionListener : this.nodes.values()) {
             sessionListener.close();
         }
@@ -175,4 +182,12 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
         t.delete(LogicalDatastoreType.OPERATIONAL, this.topology);
         t.submit().checkedGet();
     }
+
+    public void registerRuntimeRootRegistartion(final PCEPTopologyProviderRuntimeRegistrator runtimeRootRegistrator) {
+        this.runtimeRootRegistration = Optional.of(runtimeRootRegistrator.register(this));
+    }
+
+    public Optional<PCEPTopologyProviderRuntimeRegistration> getRuntimeRootRegistration() {
+        return this.runtimeRootRegistration;
+    }
 }
diff --git a/pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/SessionListenerState.java b/pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/SessionListenerState.java
new file mode 100644 (file)
index 0000000..65dc595
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2014 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.bgpcep.pcep.topology.provider;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Stopwatch;
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.ErrorMessages;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.LastReceivedError;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.LastSentError;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.LocalPref;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.Messages;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.PeerCapabilities;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.PeerPref;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.ReplyTime;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.SessionState;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.StatefulMessages;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Pcinitiate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcupd;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
+
+final class SessionListenerState {
+    private long lastReceivedRptMsgTimestamp = 0;
+    private long receivedRptMsgCount = 0;
+    private long sentUpdMsgCount = 0;
+    private long sentInitMsgCount = 0;
+    private PeerCapabilities capa;
+    private LocalPref localPref;
+    private PeerPref peerPref;
+    private final Stopwatch sessionUpDuration;
+
+    private long minReplyTime = 0;
+    private long maxReplyTime = 0;
+    private long totalTime = 0;
+    private long reqCount = 0;
+
+    public SessionListenerState() {
+        this.sessionUpDuration = new Stopwatch();
+        this.capa = new PeerCapabilities();
+    }
+
+    public void init(final PCEPSession session) {
+        Preconditions.checkNotNull(session);
+        this.localPref = getLocalPref(session.getLocalPref());
+        this.peerPref = getPeerPref(session.getPeerPref());
+        this.sessionUpDuration.start();
+    }
+
+    public void processRequestStats(final long duration) {
+        if (this.minReplyTime == 0) {
+            this.minReplyTime = duration;
+        } else {
+            if (duration < this.minReplyTime) {
+                this.minReplyTime = duration;
+            }
+        }
+        if (duration > this.maxReplyTime) {
+            this.maxReplyTime = duration;
+        }
+        this.totalTime += duration;
+        this.reqCount++;
+    }
+
+    public StatefulMessages getStatefulMessages() {
+        final StatefulMessages msgs = new StatefulMessages();
+        msgs.setLastReceivedRptMsgTimestamp(TimeUnit.MILLISECONDS.toSeconds(this.lastReceivedRptMsgTimestamp));
+        msgs.setReceivedRptMsgCount(this.receivedRptMsgCount);
+        msgs.setSentInitMsgCount(this.sentInitMsgCount);
+        msgs.setSentUpdMsgCount(this.sentUpdMsgCount);
+        return msgs;
+    }
+
+    public void resetStats(final PCEPSession session) {
+        Preconditions.checkNotNull(session);
+        this.receivedRptMsgCount = 0;
+        this.sentInitMsgCount = 0;
+        this.sentUpdMsgCount = 0;
+        this.lastReceivedRptMsgTimestamp = 0;
+        this.maxReplyTime = 0;
+        this.minReplyTime = 0;
+        this.totalTime = 0;
+        this.reqCount = 0;
+        session.resetStats();
+    }
+
+    public ReplyTime getReplyTime() {
+        final ReplyTime time = new ReplyTime();
+        long avg = 0;
+        if (this.reqCount != 0) {
+            avg = this.totalTime / this.reqCount;
+        }
+        time.setAverageTime(avg);
+        time.setMaxTime(this.maxReplyTime);
+        time.setMinTime(this.minReplyTime);
+        return time;
+    }
+
+    public PeerCapabilities getPeerCapabilities() {
+        return this.capa;
+    }
+
+    public SessionState getSessionState(final PCEPSession session) {
+        Preconditions.checkNotNull(session);
+        final SessionState state = new SessionState();
+        state.setLocalPref(this.localPref);
+        state.setPeerPref(this.peerPref);
+        state.setMessages(getMessageStats(session.getMessages()));
+        state.setSessionDuration(formatElapsedTime(this.sessionUpDuration.elapsed(TimeUnit.SECONDS)));
+        return state;
+    }
+
+    public void setPeerCapabilities(final PeerCapabilities capabilities) {
+        this.capa = Preconditions.checkNotNull(capabilities);
+    }
+
+    public void updateLastReceivedRptMsg() {
+        this.lastReceivedRptMsgTimestamp = System.currentTimeMillis();
+        this.receivedRptMsgCount++;
+    }
+
+    public void updateStatefulSentMsg(final Message msg) {
+        if (msg instanceof Pcinitiate || msg instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated._00.rev140113.Pcinitiate) {
+            this.sentInitMsgCount++;
+        } else if (msg instanceof Pcupd || msg instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.stateful._02.rev140110.Pcupd) {
+            this.sentUpdMsgCount++;
+        }
+    }
+
+    private static LocalPref getLocalPref(final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.LocalPref localPref) {
+        final LocalPref local = new LocalPref();
+        local.setDeadtimer(localPref.getDeadtimer());
+        local.setIpAddress(localPref.getIpAddress());
+        local.setKeepalive(localPref.getKeepalive());
+        local.setSessionId(localPref.getSessionId());
+        return local;
+    }
+
+    private static PeerPref getPeerPref(final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.PeerPref peerPref) {
+        final PeerPref peer = new PeerPref();
+        peer.setDeadtimer(peerPref.getDeadtimer());
+        peer.setIpAddress(peerPref.getIpAddress());
+        peer.setKeepalive(peerPref.getKeepalive());
+        peer.setSessionId(peerPref.getSessionId());
+        return peer;
+    }
+
+    private static Messages getMessageStats(final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.stats.rev141006.pcep.session.state.Messages messages) {
+        final LastReceivedError lastReceivedError = new LastReceivedError();
+        lastReceivedError.setErrorType(messages.getErrorMessages().getLastReceivedError().getErrorType());
+        lastReceivedError.setErrorValue(messages.getErrorMessages().getLastReceivedError().getErrorValue());
+        final LastSentError lastSentError = new LastSentError();
+        lastSentError.setErrorType(messages.getErrorMessages().getLastSentError().getErrorType());
+        lastSentError.setErrorValue(messages.getErrorMessages().getLastSentError().getErrorValue());
+        final ErrorMessages errMsgs = new ErrorMessages();
+        errMsgs.setLastReceivedError(lastReceivedError);
+        errMsgs.setLastSentError(lastSentError);
+        errMsgs.setReceivedErrorMsgCount(messages.getErrorMessages().getReceivedErrorMsgCount());
+        errMsgs.setSentErrorMsgCount(messages.getErrorMessages().getSentErrorMsgCount());
+        final Messages msgs = new Messages();
+        msgs.setErrorMessages(errMsgs);
+        msgs.setLastSentMsgTimestamp(messages.getLastSentMsgTimestamp());
+        msgs.setReceivedMsgCount(messages.getReceivedMsgCount());
+        msgs.setSentMsgCount(messages.getSentMsgCount());
+        msgs.setUnknownMsgReceived(msgs.getUnknownMsgReceived());
+        return msgs;
+    }
+
+    private static String formatElapsedTime(final long seconds) {
+        return String.format("%2d:%02d:%02d:%02d",
+                TimeUnit.SECONDS.toDays(seconds),
+                TimeUnit.SECONDS.toHours(seconds) - TimeUnit.DAYS.toHours(TimeUnit.SECONDS.toDays(seconds)),
+                TimeUnit.SECONDS.toMinutes(seconds) - TimeUnit.HOURS.toMinutes(TimeUnit.SECONDS.toHours(seconds)),
+                seconds - TimeUnit.MINUTES.toSeconds(TimeUnit.SECONDS.toMinutes(seconds)));
+    }
+}
index ecbd986a7aa8ccc785145900174fdfe1bf333558..fb9542ec1fe3e1787e4ebfb8ca97e345f8826498 100644 (file)
@@ -17,8 +17,10 @@ import com.google.common.util.concurrent.ListenableFuture;
 import java.net.InetAddress;
 import java.nio.ByteBuffer;
 import java.util.Collections;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.PeerCapabilities;
 import org.opendaylight.protocol.pcep.PCEPSession;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated._00.rev140113.PcinitiateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated._00.rev140113.Stateful1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated._00.rev140113.pcinitiate.message.PcinitiateMessageBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated._00.rev140113.pcinitiate.message.pcinitiate.message.RequestsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.stateful._02.rev140110.Arguments1;
@@ -78,6 +80,7 @@ public class Stateful02TopologySessionListener extends AbstractTopologySessionLi
         if (tlv != null) {
             final Stateful stateful = tlv.getStateful();
             if (stateful != null) {
+                getSessionListenerState().setPeerCapabilities(getCapabilities(stateful));
                 pccBuilder.setReportedLsp(Collections.<ReportedLsp> emptyList());
                 pccBuilder.setStateSync(PccSyncState.InitialResync);
                 pccBuilder.setStatefulTlv(new StatefulTlvBuilder().addAugmentation(StatefulTlv1.class, new StatefulTlv1Builder(tlv).build()).build());
@@ -95,6 +98,7 @@ public class Stateful02TopologySessionListener extends AbstractTopologySessionLi
             return true;
         }
 
+        getSessionListenerState().updateLastReceivedRptMsg();
         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.stateful._02.rev140110.pcrpt.message.PcrptMessage rpt = ((PcrptMessage) message).getPcrptMessage();
         for (final Reports r : rpt.getReports()) {
             final Lsp lsp = r.getLsp();
@@ -285,4 +289,17 @@ public class Stateful02TopologySessionListener extends AbstractTopologySessionLi
         Preconditions.checkState(reportedLsp != null, "Reported LSP does not contain LSP object.");
         return reportedLsp;
     }
+
+    private static PeerCapabilities getCapabilities(final Stateful stateful) {
+        final PeerCapabilities capa = new PeerCapabilities();
+        capa.setStateful(true);
+        if (stateful.isLspUpdateCapability() != null) {
+            capa.setActive(stateful.isLspUpdateCapability());
+        }
+        final Stateful1 stateful1 = stateful.getAugmentation(Stateful1.class);
+        if (stateful1 != null && stateful1.isInitiation() != null) {
+            capa.setInstantiation(stateful1.isInitiation());
+        }
+        return capa;
+    }
 }
index ba15a73366669d18d9daf0a6a0b66e0f4c19660f..64ada921bb1a631323b4b1701af42e07a6729b48 100644 (file)
@@ -20,10 +20,12 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicLong;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.PeerCapabilities;
 import org.opendaylight.protocol.pcep.PCEPSession;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.PcinitiateBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Stateful1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.PcinitiateMessageBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.RequestsBuilder;
@@ -92,6 +94,7 @@ final class Stateful07TopologySessionListener extends AbstractTopologySessionLis
         if (tlvs != null && tlvs.getAugmentation(Tlvs1.class) != null) {
             final Stateful stateful = tlvs.getAugmentation(Tlvs1.class).getStateful();
             if (stateful != null) {
+                getSessionListenerState().setPeerCapabilities(getCapabilities(stateful));
                 pccBuilder.setReportedLsp(Collections.<ReportedLsp> emptyList());
                 pccBuilder.setStateSync(PccSyncState.InitialResync);
                 pccBuilder.setStatefulTlv(new StatefulTlvBuilder().addAugmentation(StatefulTlv1.class,
@@ -134,6 +137,7 @@ final class Stateful07TopologySessionListener extends AbstractTopologySessionLis
         if (!(message instanceof PcrptMessage)) {
             return true;
         }
+        getSessionListenerState().updateLastReceivedRptMsg();
         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.PcrptMessage rpt = ((PcrptMessage) message).getPcrptMessage();
         for (final Reports report : rpt.getReports()) {
             final Lsp lsp = report.getLsp();
@@ -388,4 +392,17 @@ final class Stateful07TopologySessionListener extends AbstractTopologySessionLis
         Preconditions.checkState(reportedLsp != null, "Reported LSP does not contain LSP object.");
         return reportedLsp;
     }
+
+    private static PeerCapabilities getCapabilities(final Stateful stateful) {
+        final PeerCapabilities capa = new PeerCapabilities();
+        capa.setStateful(true);
+        if (stateful.isLspUpdateCapability() != null) {
+            capa.setActive(stateful.isLspUpdateCapability());
+        }
+        final Stateful1 stateful1 = stateful.getAugmentation(Stateful1.class);
+        if (stateful1 != null && stateful1.isInitiation() != null) {
+            capa.setInstantiation(stateful1.isInitiation());
+        }
+        return capa;
+    }
 }
index 433e975f5c5244f0c285b9615ab800deb18dfd05..e9e35eea1b6eef6fb8dd236d514b31b30c558f26 100644 (file)
 package org.opendaylight.controller.config.yang.pcep.topology.provider;
 
 import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
 import com.google.common.net.InetAddresses;
-
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.util.concurrent.ExecutionException;
-
 import org.opendaylight.bgpcep.pcep.topology.provider.PCEPTopologyProvider;
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
 import org.opendaylight.controller.config.yang.pcep.impl.PCEPDispatcherImplModuleMXBean;
@@ -134,7 +133,8 @@ public final class PCEPTopologyProviderModule extends
 
         try {
             return PCEPTopologyProvider.create(getDispatcherDependency(), address, keys.isEmpty() ? null : keys, getSchedulerDependency(),
-                    getDataProviderDependency(), getRpcRegistryDependency(), topology, getStatefulPluginDependency());
+                    getDataProviderDependency(), getRpcRegistryDependency(), topology, getStatefulPluginDependency(),
+                    Optional.of(getRootRuntimeBeanRegistratorWrapper()));
         } catch (InterruptedException | ExecutionException | TransactionCommitFailedException | ReadFailedException e) {
             LOG.error("Failed to instantiate topology provider at {}", address, e);
             throw new IllegalStateException("Failed to instantiate provider", e);
index 5390d8e3b72fde2282abd5a6534f467ca1fbbd80..f719de4abad90858613bedfa0b7afbbeff5951f2 100644 (file)
@@ -12,6 +12,8 @@ module odl-pcep-topology-provider-cfg {
     import odl-pcep-api-cfg { prefix pcep; revision-date 2013-04-09; }
     import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
     import odl-tcpmd5-cfg { prefix tcpmd5; revision-date 2014-04-27; }
+    import rpc-context { prefix rpcx; revision-date 2013-06-17; }
+    import pcep-session-stats { prefix pcep-stats; revision-date 2014-10-06; }
 
     organization "Cisco Systems, Inc.";
 
@@ -158,5 +160,131 @@ module odl-pcep-topology-provider-cfg {
             }
         }
     }
+
+    identity session-rpc;
+
+    grouping stateful-preferences {
+        leaf instantiation {
+            description "Represents peer's instantiation capability.";
+            type boolean;
+            default "false";
+        }
+
+        leaf stateful {
+            description "Represents peer's stateful/stateless capability.";
+            type boolean;
+            default "false";
+        }
+
+        leaf active {
+            description "Represents peer's LSP update capability.";
+            type boolean;
+            default "false";
+        }
+    }
+
+    augment "/config:modules/config:module/config:state" {
+        case pcep-topology-provider {
+            when "/config:modules/config:module/config:type = 'pcep-topology-provider'";
+            list listener-state {
+                description "Statistics gained from session listener.";
+                config:inner-state-bean;
+                rpcx:rpc-context-instance "session-rpc";
+
+                key "peer-id";
+
+                leaf peer-id {
+                    type string;
+                }
+
+                container session-state {
+                    leaf session-duration {
+                        description "Elapsed time (in d:H:m:s) from session-up until now.";
+                        type string;
+                    }
+                    uses pcep-stats:pcep-session-state;
+                }
+
+                container peer-capabilities {
+                    description "Remote peer's (PCC) advertised stateful capabilities.";
+                    uses stateful-preferences;
+                }
+
+                leaf delegated-lsps-count {
+                    description "The number of delegated LSPs (tunnels) from PCC.";
+                    type uint16;
+                }
+
+                leaf synchronized {
+                    description "Represents synchronization status.";
+                    type boolean;
+                }
+
+                container stateful-messages {
+                    description "The statistics of sent/received PCEP stateful messages.";
+                    leaf last-received-rpt-msg-timestamp {
+                        description "The timestamp of last received PCRpt message.";
+                        type uint32;
+                    }
+
+                    leaf received-rpt-msg-count {
+                        description "The number of received PcRpt messages.";
+                        type uint32;
+                    }
+
+                    leaf sent-upd-msg-count {
+                        description "The number of sent PCUpd messages.";
+                        type uint32;
+                    }
+
+                    leaf sent-init-msg-count {
+                        description "The number of sent PCInitiate messages.";
+                        type uint32;
+                    }
+                }
+
+                container reply-time {
+                    description "Measures time elapsed from request's send to reply's received.";
+
+                    leaf average-time {
+                        description "Average time (in milliseconds) of gauged values.";
+                        type uint32;
+                    }
+
+                    leaf min-time {
+                        description "Minimal measured time value (in milliseconds).";
+                        type uint32;
+                    }
+
+                    leaf max-time {
+                        description "Maximal measured time value (in milliseconds).";
+                        type uint32;
+                    }
+                }
+              }
+          }
+    }
+
+    rpc tear-down-session {
+        description "Closes the session between PCE and PCC.";
+        input {
+            uses rpcx:rpc-context-ref {
+                refine context-instance {
+                    rpcx:rpc-context-instance session-rpc;
+                }
+            }
+        }
+    }
+
+    rpc reset-stats {
+        description "Resets statistics like message counters and timestamps. (set to 0)";
+        input {
+            uses rpcx:rpc-context-ref {
+                refine context-instance {
+                    rpcx:rpc-context-instance session-rpc;
+                }
+            }
+        }
+    }
 }
 
index 92090701f8ca3ab0f45f792d5fbfc6c6f9309756..956467b48c118447c7a5b0a6269c8df4b4804306 100644 (file)
@@ -73,6 +73,8 @@ public abstract class AbstractPCEPSessionTest<T extends TopologySessionListenerF
     protected static final String ERO_IP_PREFIX = TEST_ADDRESS + IPV4_MASK;
     protected static final String NEW_DESTINATION_ADDRESS = "127.0.1.0";
     protected static final String DST_IP_PREFIX = NEW_DESTINATION_ADDRESS + IPV4_MASK;
+    protected static final short DEAD_TIMER = 30;
+    protected static final short KEEP_ALIVE = 10;
 
     protected List<Notification> receivedMsgs;
 
@@ -92,7 +94,7 @@ public abstract class AbstractPCEPSessionTest<T extends TopologySessionListenerF
 
     private T listenerFactory;
 
-    private final Open localPrefs = new OpenBuilder().setDeadTimer((short) 30).setKeepalive((short) 10).build();
+    private final Open localPrefs = new OpenBuilder().setDeadTimer((short) 30).setKeepalive((short) 10).setSessionId((short) 0).build();
 
     protected ServerSessionManager manager;
 
index dbe62927e5f28d6ada3cfae4a8e46d53bf64bdcd..7dd9bb3e3dd3ab153bff579e4a33811817393b25 100644 (file)
@@ -23,9 +23,9 @@ import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.opendaylight.controller.config.yang.pcep.topology.provider.SessionState;
 import org.opendaylight.protocol.pcep.PCEPCloseTermination;
 import org.opendaylight.protocol.pcep.TerminationReason;
 import org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil;
@@ -104,6 +104,18 @@ public class Stateful07TopologySessionListenerTest extends AbstractPCEPSessionTe
     public void testStateful07TopologySessionListener() throws Exception {
         this.listener.onSessionUp(this.session);
 
+        assertEquals(TEST_ADDRESS, this.listener.getPeerId());
+        final SessionState state = this.listener.getSessionState();
+        assertNotNull(state);
+        assertEquals(DEAD_TIMER, state.getLocalPref().getDeadtimer().shortValue());
+        assertEquals(KEEP_ALIVE, state.getLocalPref().getKeepalive().shortValue());
+        assertEquals(0, state.getLocalPref().getSessionId().intValue());
+        assertEquals(TEST_ADDRESS, state.getLocalPref().getIpAddress());
+        assertEquals(DEAD_TIMER, state.getPeerPref().getDeadtimer().shortValue());
+        assertEquals(KEEP_ALIVE, state.getPeerPref().getKeepalive().shortValue());
+        assertEquals(0, state.getPeerPref().getSessionId().intValue());
+        assertEquals(TEST_ADDRESS, state.getPeerPref().getIpAddress());
+
         // add-lsp
         this.topologyRpcs.addLsp(createAddLspInput());
         assertEquals(1, this.receivedMsgs.size());
@@ -139,6 +151,14 @@ public class Stateful07TopologySessionListenerTest extends AbstractPCEPSessionTe
         Path path = reportedLsp.getPath().get(0);
         assertEquals(1, path.getEro().getSubobject().size());
         assertEquals(ERO_IP_PREFIX, getLastEroIpPrefix(path.getEro()));
+        // check stats
+        assertEquals(1, this.listener.getDelegatedLspsCount().intValue());
+        assertTrue(this.listener.getSynchronized());
+        assertTrue(this.listener.getStatefulMessages().getLastReceivedRptMsgTimestamp() > 0);
+        assertEquals(2, this.listener.getStatefulMessages().getReceivedRptMsgCount().intValue());
+        assertEquals(1, this.listener.getStatefulMessages().getSentInitMsgCount().intValue());
+        assertEquals(0, this.listener.getStatefulMessages().getSentUpdMsgCount().intValue());
+        assertNotNull(this.listener.getSessionState());
 
         // update-lsp
         org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.update.lsp.args.ArgumentsBuilder updArgsBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.update.lsp.args.ArgumentsBuilder();
@@ -165,6 +185,18 @@ public class Stateful07TopologySessionListenerTest extends AbstractPCEPSessionTe
         path = reportedLsp.getPath().get(0);
         assertEquals(2, path.getEro().getSubobject().size());
         assertEquals(DST_IP_PREFIX, getLastEroIpPrefix(path.getEro()));
+        // check stats
+        assertEquals(1, this.listener.getDelegatedLspsCount().intValue());
+        assertTrue(this.listener.getSynchronized());
+        assertTrue(this.listener.getStatefulMessages().getLastReceivedRptMsgTimestamp() > 0);
+        assertEquals(3, this.listener.getStatefulMessages().getReceivedRptMsgCount().intValue());
+        assertEquals(1, this.listener.getStatefulMessages().getSentInitMsgCount().intValue());
+        assertEquals(1, this.listener.getStatefulMessages().getSentUpdMsgCount().intValue());
+        assertTrue(this.listener.getReplyTime().getAverageTime() > 0);
+        assertTrue(this.listener.getReplyTime().getMaxTime() > 0);
+        assertFalse(this.listener.getPeerCapabilities().getActive());
+        assertFalse(this.listener.getPeerCapabilities().getInstantiation());
+        assertTrue(this.listener.getPeerCapabilities().getStateful());
 
         // ensure-operational
         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.ensure.lsp.operational.args.ArgumentsBuilder ensureArgs = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.ensure.lsp.operational.args.ArgumentsBuilder();
@@ -190,13 +222,28 @@ public class Stateful07TopologySessionListenerTest extends AbstractPCEPSessionTe
         topology = getTopology().get();
         pcc = topology.getNode().get(0).getAugmentation(Node1.class).getPathComputationClient();
         assertEquals(0, pcc.getReportedLsp().size());
+        // check stats
+        assertEquals(0, this.listener.getDelegatedLspsCount().intValue());
+        assertTrue(this.listener.getSynchronized());
+        assertTrue(this.listener.getStatefulMessages().getLastReceivedRptMsgTimestamp() > 0);
+        assertEquals(4, this.listener.getStatefulMessages().getReceivedRptMsgCount().intValue());
+        assertEquals(2, this.listener.getStatefulMessages().getSentInitMsgCount().intValue());
+        assertEquals(1, this.listener.getStatefulMessages().getSentUpdMsgCount().intValue());
+        this.listener.resetStats();
+        assertEquals(0, this.listener.getStatefulMessages().getLastReceivedRptMsgTimestamp().longValue());
+        assertEquals(0, this.listener.getStatefulMessages().getReceivedRptMsgCount().intValue());
+        assertEquals(0, this.listener.getStatefulMessages().getSentInitMsgCount().intValue());
+        assertEquals(0, this.listener.getStatefulMessages().getSentUpdMsgCount().intValue());
+        assertEquals(0, this.listener.getReplyTime().getAverageTime().longValue());
+        assertEquals(0, this.listener.getReplyTime().getMaxTime().longValue());
+        assertEquals(0, this.listener.getReplyTime().getMinTime().longValue());
     }
 
     @Test
     public void testOnUnhandledErrorMessage() {
         final Message errorMsg = AbstractMessageParser.createErrorMsg(PCEPErrors.NON_ZERO_PLSPID, Optional.<Rp>absent());
         this.listener.onSessionUp(this.session);
-        Assert.assertTrue(this.listener.onMessage(Optional.<AbstractTopologySessionListener.MessageContext>absent().orNull(), errorMsg));
+        assertTrue(this.listener.onMessage(Optional.<AbstractTopologySessionListener.MessageContext>absent().orNull(), errorMsg));
     }
 
     @Test
@@ -207,11 +254,11 @@ public class Stateful07TopologySessionListenerTest extends AbstractPCEPSessionTe
         this.listener.onMessage(this.session, errorMsg);
 
         final AddLspOutput output = futureOutput.get().getResult();
-        Assert.assertEquals(FailureType.Failed ,output.getFailure());
-        Assert.assertEquals(1, output.getError().size());
+        assertEquals(FailureType.Failed ,output.getFailure());
+        assertEquals(1, output.getError().size());
         final ErrorObject err = output.getError().get(0).getErrorObject();
-        Assert.assertEquals(PCEPErrors.NON_ZERO_PLSPID.getErrorType(), err.getType().shortValue());
-        Assert.assertEquals(PCEPErrors.NON_ZERO_PLSPID.getErrorValue(), err.getValue().shortValue());
+        assertEquals(PCEPErrors.NON_ZERO_PLSPID.getErrorType(), err.getType().shortValue());
+        assertEquals(PCEPErrors.NON_ZERO_PLSPID.getErrorValue(), err.getValue().shortValue());
     }
 
     @Test
@@ -222,7 +269,7 @@ public class Stateful07TopologySessionListenerTest extends AbstractPCEPSessionTe
         this.listener.onSessionDown(this.session, new IllegalArgumentException());
         final AddLspOutput output = futureOutput.get().getResult();
         // deal with unsent request after session down
-        Assert.assertEquals(FailureType.Unsent, output.getFailure());
+        assertEquals(FailureType.Unsent, output.getFailure());
     }
 
     @Test
@@ -239,11 +286,11 @@ public class Stateful07TopologySessionListenerTest extends AbstractPCEPSessionTe
                 inetAddress, inetAddress, inetAddress);
         final Pcrpt pcRpt = MsgBuilderUtil.createPcRtpMessage(new LspBuilder(req.getLsp()).setTlvs(tlvs).setSync(true).setRemove(false).setOperational(OperationalStatus.Active).build(), Optional.of(MsgBuilderUtil.createSrp(srpId)), MsgBuilderUtil.createPath(req.getEro().getSubobject()));
         this.listener.onMessage(this.session, pcRpt);
-        Assert.assertEquals(1, getTopology().get().getNode().size());
+        assertEquals(1, getTopology().get().getNode().size());
 
         // node should be removed after termination
         this.listener.onSessionTerminated(this.session, new PCEPCloseTermination(TerminationReason.Unknown));
-        Assert.assertEquals(0, getTopology().get().getNode().size());
+        assertEquals(0, getTopology().get().getNode().size());
     }
 
     @Test