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;
* 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
Tlvs getRemoteTlvs();
InetAddress getRemoteAddress();
+
+ void resetStats();
}
--- /dev/null
+// 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
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;
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;
* 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.
*/
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
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);
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();
}
/**
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
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
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);
}
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();
}
}
+++ /dev/null
-/*
- * 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;
-}
--- /dev/null
+/*
+ * 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();
+ }
+}
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;
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();
}).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());
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;
@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);
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);
}
@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);
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());
+ }
}
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;
* @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;
return this.version;
}
};
+
private static final Logger LOG = LoggerFactory.getLogger(AbstractTopologySessionListener.class);
protected static final String MISSING_XML_TAG = "Mandatory XML tags are missing.";
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
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());
}
@Override
public void close() {
+ if (this.registration != null) {
+ this.registration.close();
+ }
if (this.session != null) {
this.session.close(TerminationReason.Unknown);
}
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;
}
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);
}
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();
+ }
}
*/
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;
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() {
state = State.UNACKED;
}
}
+
+ public long getElapsedMillis() {
+ return this.stopwatch.elapsed(TimeUnit.MILLISECONDS);
+ }
}
\ No newline at end of file
*/
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;
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;
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();
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;
/**
*
*/
-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);
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 {
@Override
public void close() throws TransactionCommitFailedException {
+ if (this.runtimeRootRegistration.isPresent()) {
+ this.runtimeRootRegistration.get().close();
+ }
for (final TopologySessionListener sessionListener : this.nodes.values()) {
sessionListener.close();
}
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;
+ }
}
--- /dev/null
+/*
+ * 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)));
+ }
+}
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;
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());
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();
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;
+ }
}
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;
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,
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();
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;
+ }
}
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;
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);
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.";
}
}
}
+
+ 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;
+ }
+ }
+ }
+ }
}
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;
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;
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;
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());
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();
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();
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
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
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
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