final BGPSessionPreferences prefs = new BGPSessionPreferences(r.getLocalAs(), getHoldtimer(), r.getBgpIdentifier(), tlvs);
final BGPPeer bgpClientPeer = new BGPPeer(peerName(getHostWithoutValue()), r);
+ bgpClientPeer.registerRootRuntimeBean(getRootRuntimeBeanRegistratorWrapper());
getPeerRegistryBackwards().addPeer(getHostWithoutValue(), bgpClientPeer, prefs);
try {
final BGPSessionListener peer = this.registry.getPeer(getRemoteIp(), getSourceId(openObj, getPreferences()), getDestinationId(openObj, getPreferences()));
this.sendMessage(new KeepaliveBuilder().build());
- this.session = new BGPSessionImpl(peer, this.channel, openObj, getPreferences().getHoldTime());
+ this.session = new BGPSessionImpl(peer, this.channel, openObj, getPreferences());
this.state = State.OpenConfirm;
LOG.debug("Channel {} moved to OpenConfirm state with remote proposal {}", this.channel, openObj);
} catch (final BGPDocumentedException e) {
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
import com.google.common.net.InetAddresses;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BGPPeerRuntimeMXBean;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BGPPeerRuntimeRegistration;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BGPPeerRuntimeRegistrator;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpPeerState;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpSessionState;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.RouteTable;
import org.opendaylight.protocol.bgp.rib.impl.spi.AdjRIBsOutRegistration;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionStatistics;
import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
import org.opendaylight.protocol.bgp.rib.impl.spi.ReusableBGPPeer;
import org.opendaylight.protocol.bgp.rib.spi.BGPSession;
* Class representing a peer. We have a single instance for each peer, which provides translation from BGP events into
* RIB actions.
*/
-public class BGPPeer implements ReusableBGPPeer, Peer, AutoCloseable {
+public class BGPPeer implements ReusableBGPPeer, Peer, AutoCloseable, BGPPeerRuntimeMXBean {
+
private static final Logger LOG = LoggerFactory.getLogger(BGPPeer.class);
@GuardedBy("this")
@GuardedBy("this")
private AdjRIBsOutRegistration reg;
+ private BGPPeerRuntimeRegistrator registrator;
+ private BGPPeerRuntimeRegistration runtimeReg;
+ private long sessionEstablishedCounter = 0L;
+
public BGPPeer(final String name, final RIB rib) {
this.rib = Preconditions.checkNotNull(rib);
this.name = name;
if (session instanceof BGPSessionImpl) {
reg = rib.registerRIBsOut(this, new SessionRIBsOut((BGPSessionImpl) session));
}
+ this.sessionEstablishedCounter++;
+ if (this.registrator != null) {
+ this.runtimeReg = this.registrator.register(this);
+ }
}
private synchronized void cleanup() {
@GuardedBy("this")
private void dropConnection() {
+ if (this.runtimeReg != null) {
+ this.runtimeReg.close();
+ this.runtimeReg = null;
+ }
if (this.session != null) {
this.session.close();
this.session = null;
public synchronized byte[] getRawIdentifier() {
return rawIdentifier;
}
+
+ @Override
+ public void resetSession() {
+ releaseConnection();
+ }
+
+ @Override
+ public void resetStats() {
+ if (this.session instanceof BGPSessionStatistics) {
+ ((BGPSessionStatistics) session).resetSessionStats();
+ }
+ }
+
+ public void registerRootRuntimeBean(final BGPPeerRuntimeRegistrator registrator) {
+ this.registrator = registrator;
+ }
+
+ @Override
+ public BgpSessionState getBgpSessionState() {
+ if (this.session instanceof BGPSessionStatistics) {
+ return ((BGPSessionStatistics) session).getBgpSesionState();
+ }
+ return new BgpSessionState();
+ }
+
+ @Override
+ public BgpPeerState getBgpPeerState() {
+ final BgpPeerState peerState = new BgpPeerState();
+ final List<RouteTable> routes = Lists.newArrayList();
+ for (final TablesKey tablesKey : this.tables) {
+ final RouteTable routeTable = new RouteTable();
+ routeTable.setTableType("afi=" + tablesKey.getAfi().getSimpleName() + ",safi=" + tablesKey.getSafi().getSimpleName());
+ routeTable.setRoutesCount(this.rib.getRoutesCount(tablesKey));
+ routes.add(routeTable);
+ }
+ peerState.setRouteTable(routes);
+ peerState.setSessionEstablishedCount(this.sessionEstablishedCounter);
+ return peerState;
+ }
}
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
import io.netty.channel.Channel;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpSessionState;
import org.opendaylight.protocol.bgp.parser.AsNumberUtil;
import org.opendaylight.protocol.bgp.parser.BGPError;
import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionStatistics;
import org.opendaylight.protocol.bgp.rib.spi.BGPSession;
import org.opendaylight.protocol.bgp.rib.spi.BGPSessionListener;
import org.opendaylight.protocol.bgp.rib.spi.BGPTerminationReason;
import org.slf4j.LoggerFactory;
@VisibleForTesting
-public class BGPSessionImpl extends AbstractProtocolSession<Notification> implements BGPSession {
+public class BGPSessionImpl extends AbstractProtocolSession<Notification> implements BGPSession, BGPSessionStatistics {
private static final Logger LOG = LoggerFactory.getLogger(BGPSessionImpl.class);
private final int keepAlive;
private final AsNumber asNumber;
private final Ipv4Address bgpId;
+ private BGPSessionStats sessionStats;
+
+ public BGPSessionImpl(final BGPSessionListener listener, final Channel channel, final Open remoteOpen, final BGPSessionPreferences localPreferences) {
+ this(listener, channel, remoteOpen, localPreferences.getHoldTime());
+ this.sessionStats = new BGPSessionStats(remoteOpen, this.holdTimerValue, this.keepAlive, channel, Optional.of(localPreferences), this.tableTypes);
+ }
public BGPSessionImpl(final BGPSessionListener listener, final Channel channel, final Open remoteOpen, final int localHoldTimer) {
this.listener = Preconditions.checkNotNull(listener);
for (final BgpParameters param : remoteOpen.getBgpParameters()) {
final CParameters cp = param.getCParameters();
if (cp instanceof MultiprotocolCase) {
- final TablesKey tt = new TablesKey(((MultiprotocolCase) cp).getMultiprotocolCapability().getAfi(), ((MultiprotocolCase) cp).getMultiprotocolCapability().getSafi());
+ final TablesKey tt = new TablesKey(((MultiprotocolCase) cp).getMultiprotocolCapability().getAfi(),
+ ((MultiprotocolCase) cp).getMultiprotocolCapability().getSafi());
LOG.trace("Added table type to sync {}", tt);
tts.add(tt);
tats.add(new BgpTableTypeImpl(tt.getAfi(), tt.getSafi()));
}, this.keepAlive, TimeUnit.SECONDS);
}
this.bgpId = remoteOpen.getBgpIdentifier();
+ this.sessionStats = new BGPSessionStats(remoteOpen, this.holdTimerValue, this.keepAlive, channel, Optional.<BGPSessionPreferences>absent(),
+ this.tableTypes);
}
@Override
public synchronized void handleMessage(final Notification msg) {
// Update last reception time
this.lastMessageReceivedAt = System.nanoTime();
+ this.sessionStats.updateReceivedMsgTotal();
if (msg instanceof Open) {
// Open messages should not be present here
this.closeWithoutMessage();
this.listener.onSessionTerminated(this, new BGPTerminationReason(BGPError.forValue(((Notify) msg).getErrorCode(),
((Notify) msg).getErrorSubcode())));
+ this.sessionStats.updateReceivedMsgErr((Notify) msg);
} else if (msg instanceof Keepalive) {
// Keepalives are handled internally
LOG.trace("Received KeepAlive messsage.");
this.kaCounter++;
+ this.sessionStats.updateReceivedMsgKA();
if (this.kaCounter >= 2) {
this.sync.kaReceived();
}
// All others are passed up
this.listener.onMessage(this, msg);
this.sync.updReceived((Update) msg);
+ this.sessionStats.updateReceivedMsgUpd();
}
}
}
});
this.lastMessageSentAt = System.nanoTime();
+ this.sessionStats.updateSentMsgTotal();
+ if (msg instanceof Update) {
+ this.sessionStats.updateSentMsgUpd();
+ } else if (msg instanceof Notify) {
+ this.sessionStats.updateSentMsgErr((Notify) msg);
+ }
} catch (final Exception e) {
LOG.warn("Message {} was not sent.", msg, e);
}
if (ct >= nextKeepalive) {
this.sendMessage(KEEP_ALIVE);
nextKeepalive = this.lastMessageSentAt + TimeUnit.SECONDS.toNanos(this.keepAlive);
+ this.sessionStats.updateSentMsgKA();
}
this.channel.eventLoop().schedule(new Runnable() {
@Override
@Override
protected synchronized void sessionUp() {
+ this.sessionStats.startSessionStopwatch();
this.state = State.Up;
this.listener.onSessionUp(this);
}
synchronized void schedule(final Runnable task) {
Preconditions.checkState(this.channel != null);
this.channel.eventLoop().submit(task);
-
}
@VisibleForTesting
protected synchronized void setLastMessageSentAt(final long lastMessageSentAt) {
this.lastMessageSentAt = lastMessageSentAt;
}
+
+ @Override
+ public BgpSessionState getBgpSesionState() {
+ return this.sessionStats.getBgpSessionState(this.state);
+ }
+
+ @Override
+ public synchronized void resetSessionStats() {
+ this.sessionStats.resetStats();
+ }
}
--- /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.bgp.rib.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Lists;
+import io.netty.channel.Channel;
+import java.net.InetSocketAddress;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.AdvertizedTableTypes;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpSessionState;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.ErrorMsgs;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.ErrorReceived;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.ErrorSent;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.KeepAliveMsgs;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.MessagesStats;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.PeerPreferences;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.Received;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.Sent;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.SpeakerPreferences;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.TotalMsgs;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.UpdateMsgs;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionImpl.State;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.util.StatisticsUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Notify;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Open;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.bgp.parameters.CParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.bgp.parameters.c.parameters.As4BytesCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.c.parameters.MultiprotocolCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.c.parameters.multiprotocol._case.MultiprotocolCapability;
+
+final class BGPSessionStats {
+ private final Stopwatch sessionStopwatch;
+ private final BgpSessionState stats;
+ private final TotalMsgs totalMsgs = new TotalMsgs();
+ private final KeepAliveMsgs kaMsgs = new KeepAliveMsgs();
+ private final UpdateMsgs updMsgs = new UpdateMsgs();
+ private final ErrorMsgs errMsgs = new ErrorMsgs();
+
+ public BGPSessionStats(final Open remoteOpen, final int holdTimerValue, final int keepAlive, final Channel channel,
+ final Optional<BGPSessionPreferences> localPreferences, final Collection<BgpTableType> tableTypes) {
+ this.sessionStopwatch = new Stopwatch();
+ this.stats = new BgpSessionState();
+ this.stats.setHoldtimeCurrent(holdTimerValue);
+ this.stats.setKeepaliveCurrent(keepAlive);
+ this.stats.setPeerPreferences(setPeerPref(remoteOpen, channel, tableTypes));
+ this.stats.setSpeakerPreferences(setSpeakerPref(channel, localPreferences));
+ initMsgs();
+ }
+
+ private void initMsgs() {
+ this.totalMsgs.setReceived(new Received());
+ this.totalMsgs.setSent(new Sent());
+ this.kaMsgs.setReceived(new Received());
+ this.kaMsgs.setSent(new Sent());
+ this.updMsgs.setReceived(new Received());
+ this.updMsgs.setSent(new Sent());
+ this.errMsgs.setErrorReceived(new ErrorReceived());
+ this.errMsgs.setErrorSent(new ErrorSent());
+ }
+
+ public void startSessionStopwatch() {
+ this.sessionStopwatch.start();
+ }
+
+ public void updateSentMsgTotal() {
+ updateSentMsg(this.totalMsgs.getSent());
+ }
+
+ public void updateReceivedMsgTotal() {
+ updateReceivedMsg(this.totalMsgs.getReceived());
+ }
+
+ public void updateReceivedMsgKA() {
+ updateReceivedMsg(this.kaMsgs.getReceived());
+ }
+
+ public void updateSentMsgKA() {
+ updateSentMsg(this.kaMsgs.getSent());
+ }
+
+ public void updateSentMsgUpd() {
+ updateSentMsg(this.updMsgs.getSent());
+ }
+
+ public void updateReceivedMsgUpd() {
+ updateReceivedMsg(this.updMsgs.getReceived());
+ }
+
+ public void updateReceivedMsgErr(final Notify error) {
+ Preconditions.checkNotNull(error);
+ final ErrorReceived received = this.errMsgs.getErrorReceived();
+ received.setCount(received.getCount() + 1);
+ received.setTimestamp(StatisticsUtil.getCurrentTimestampInSeconds());
+ received.setCode(error.getErrorCode());
+ received.setSubCode(error.getErrorSubcode());
+ }
+
+ public void updateSentMsgErr(final Notify error) {
+ Preconditions.checkNotNull(error);
+ final ErrorSent sent = this.errMsgs.getErrorSent();
+ sent.setCount(sent.getCount() + 1);
+ sent.setTimestamp(StatisticsUtil.getCurrentTimestampInSeconds());
+ sent.setCode(error.getErrorCode());
+ sent.setSubCode(error.getErrorSubcode());
+ }
+
+ public BgpSessionState getBgpSessionState(final State state) {
+ Preconditions.checkNotNull(state);
+ final MessagesStats msgs = new MessagesStats();
+ msgs.setTotalMsgs(this.totalMsgs);
+ msgs.setErrorMsgs(this.errMsgs);
+ msgs.setKeepAliveMsgs(this.kaMsgs);
+ msgs.setUpdateMsgs(this.updMsgs);
+ this.stats.setSessionDuration(StatisticsUtil.formatElapsedTime(this.sessionStopwatch.elapsed(TimeUnit.SECONDS)));
+ this.stats.setSessionState(state.toString());
+ this.stats.setMessagesStats(msgs);
+ return this.stats;
+ }
+
+ public void resetStats() {
+ initMsgs();
+ }
+
+ private static void updateReceivedMsg(final Received received) {
+ Preconditions.checkNotNull(received);
+ received.setCount(received.getCount() + 1);
+ received.setTimestamp(StatisticsUtil.getCurrentTimestampInSeconds());
+ }
+
+ private static boolean isAs4ByteCapable(final CParameters cp) {
+ if (cp instanceof As4BytesCase) {
+ return ((As4BytesCase) cp).getAs4BytesCapability() != null;
+ }
+ return false;
+ }
+
+ private static void updateSentMsg(final Sent sent) {
+ Preconditions.checkNotNull(sent);
+ sent.setCount(sent.getCount() + 1);
+ sent.setTimestamp(StatisticsUtil.getCurrentTimestampInSeconds());
+ }
+
+ private static AdvertizedTableTypes addTableType(final BgpTableType type) {
+ Preconditions.checkNotNull(type);
+ final AdvertizedTableTypes att = new AdvertizedTableTypes();
+ att.setAfi(type.getAfi().getSimpleName());
+ att.setSafi(type.getSafi().getSimpleName());
+ return att;
+ }
+
+ private static SpeakerPreferences setSpeakerPref(final Channel channel, final Optional<BGPSessionPreferences> localPreferences) {
+ Preconditions.checkNotNull(channel);
+ final SpeakerPreferences pref = new SpeakerPreferences();
+ final InetSocketAddress isa = (InetSocketAddress) channel.localAddress();
+ pref.setAddress(isa.getAddress().getHostAddress());
+ pref.setPort(isa.getPort());
+ final List<AdvertizedTableTypes> tt = Lists.newArrayList();
+ if (localPreferences.isPresent()) {
+ final BGPSessionPreferences localPref = localPreferences.get();
+ pref.setBgpId(localPref.getBgpId().getValue());
+ pref.setAs(localPref.getMyAs().getValue());
+ pref.setHoldtime(localPref.getHoldTime());
+ if (localPref.getParams() != null && !localPref.getParams().isEmpty()) {
+ for (final BgpParameters param : localPref.getParams()) {
+ final CParameters cp = param.getCParameters();
+ if (cp instanceof MultiprotocolCase) {
+ final MultiprotocolCapability mc = ((MultiprotocolCase) cp).getMultiprotocolCapability();
+ final AdvertizedTableTypes att = new AdvertizedTableTypes();
+ att.setAfi(mc.getAfi().getSimpleName());
+ att.setSafi(mc.getSafi().getSimpleName());
+ tt.add(att);
+ }
+ pref.setFourOctetAsCapability(isAs4ByteCapable(cp));
+ }
+ }
+ }
+ pref.setAdvertizedTableTypes(tt);
+ return pref;
+ }
+
+ private static PeerPreferences setPeerPref(final Open remoteOpen, final Channel channel, final Collection<BgpTableType> tableTypes) {
+ Preconditions.checkNotNull(remoteOpen);
+ Preconditions.checkNotNull(channel);
+ final PeerPreferences pref = new PeerPreferences();
+ final InetSocketAddress isa = (InetSocketAddress) channel.remoteAddress();
+ pref.setAddress(isa.getAddress().getHostAddress());
+ pref.setPort(isa.getPort());
+ pref.setBgpId(remoteOpen.getBgpIdentifier().getValue());
+ pref.setAs(remoteOpen.getMyAsNumber().longValue());
+ pref.setHoldtime(remoteOpen.getHoldTimer());
+ final List<AdvertizedTableTypes> tt = Lists.newArrayList();
+ for (final BgpTableType t : tableTypes) {
+ tt.add(addTableType(t));
+ }
+ if (remoteOpen.getBgpParameters() != null && !remoteOpen.getBgpParameters().isEmpty()) {
+ for (final BgpParameters param : remoteOpen.getBgpParameters()) {
+ pref.setFourOctetAsCapability(isAs4ByteCapable(param.getCParameters()));
+ }
+ }
+ pref.setAdvertizedTableTypes(tt);
+ return pref;
+ }
+}
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.protocol.bgp.rib.DefaultRibReference;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.Rib;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.RibBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.RibKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.LocRib;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.LocRibBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.routes.Ipv4RoutesCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.routes.Ipv6RoutesCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
private final List<BgpTableType> localTables;
private final RIBTables tables;
private final BlockingQueue<Peer> peers;
+ private final DataBroker dataBroker;
private final Thread scheduler = new Thread(new Runnable() {
@Override
this.localTables = ImmutableList.copyOf(localTables);
this.tables = new RIBTables(extensions);
this.peers = new LinkedBlockingQueue<>();
+ this.dataBroker = dps;
LOG.debug("Instantiating RIB table {} at {}", ribId, getInstanceIdentifier());
public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
LOG.info("RIB {} closed successfully", getInstanceIdentifier());
}
+
+ @Override
+ public long getRoutesCount(final TablesKey key) {
+ try {
+ final Optional<Tables> tableMaybe = this.dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.OPERATIONAL,
+ getInstanceIdentifier().child(LocRib.class).child(Tables.class, key)).checkedGet();
+ if (tableMaybe.isPresent()) {
+ final Tables table = tableMaybe.get();
+ if (table.getRoutes() instanceof Ipv4RoutesCase) {
+ final Ipv4RoutesCase routesCase = (Ipv4RoutesCase) table.getRoutes();
+ if (routesCase.getIpv4Routes() != null && routesCase.getIpv4Routes().getIpv4Route() != null) {
+ return routesCase.getIpv4Routes().getIpv4Route().size();
+ }
+ } else if (table.getRoutes() instanceof Ipv6RoutesCase) {
+ final Ipv6RoutesCase routesCase = (Ipv6RoutesCase) table.getRoutes();
+ if (routesCase.getIpv6Routes() != null && routesCase.getIpv6Routes().getIpv6Route() != null) {
+ return routesCase.getIpv6Routes().getIpv6Route().size();
+ }
+ }
+ }
+ } catch (ReadFailedException e) {
+ //no-op
+ }
+ return 0;
+ }
}
--- /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.bgp.rib.impl.spi;
+
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpSessionState;
+
+/**
+ * Serves to expose BGP session statistics to the BGP Peer, to which the session is related.
+ */
+public interface BGPSessionStatistics {
+
+ /**
+ * Retrieves actual BGP session state. Containing all information collected from the session.
+ *
+ * @return State of the BGP session.
+ */
+ BgpSessionState getBgpSesionState();
+
+ /**
+ * Resets BGP session statistics. Sets counters values to zero.
+ */
+ void resetSessionStats();
+}
package org.opendaylight.protocol.bgp.rib.impl.spi;
import java.util.List;
-
import org.opendaylight.protocol.bgp.rib.spi.Peer;
import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
ReconnectStrategyFactory getSessionStrategyFactory();
AdjRIBsOutRegistration registerRIBsOut(Peer bgpPeer, AdjRIBsOut aro);
+
+ long getRoutesCount(TablesKey key);
}
import protocol-framework { prefix pf; revision-date 2014-03-13; }
import odl-tcpmd5-cfg { prefix tcpmd5; revision-date 2014-04-27; }
import odl-tcpmd5-netty-cfg { prefix tcpmd5n; revision-date 2014-04-27; }
+ import rpc-context { prefix rpcx; revision-date 2013-06-17; }
organization "Cisco Systems, Inc.";
}
}
+ grouping message-state {
+ leaf count {
+ description "Total number of BGP messages.";
+ type uint32;
+ default 0;
+ }
+
+ leaf timestamp {
+ description "The BGP message timestamp (seconds).";
+ type uint32;
+ default 0;
+ }
+ }
+
+ grouping message-stats {
+ container received {
+ description "The received BGP messages statistics.";
+ uses message-state;
+ }
+
+ container sent {
+ description "The sent BGP messages statistics.";
+ uses message-state;
+ }
+ }
+
+ grouping error {
+ leaf code {
+ description "The BGP error code.";
+ type uint8;
+ default 0;
+ }
+
+ leaf sub-code {
+ description "The BGP error sub-code.";
+ type uint8;
+ default 0;
+ }
+ }
+
+ grouping preferences {
+ leaf bgp-id {
+ description "The BGP Identifier.";
+ type string;
+ default "";
+ }
+
+ leaf address {
+ description "The IP address of BGP connection.";
+ type string;
+ default "";
+ }
+
+ leaf port {
+ description "The port for connection between the BGP peers.";
+ type uint16;
+ default 0;
+ }
+
+ leaf as {
+ description "Autonomous system number.";
+ type uint32;
+ default 0;
+ }
+
+ leaf holdtime {
+ description "Time interval (in seconds) for HoldTimer proposed by the peer.";
+ type uint16;
+ default 0;
+ }
+
+ leaf four-octet-as-capability {
+ description "The BGP peer 4 byte AS numbers support capability.";
+ type boolean;
+ default "false";
+ }
+
+ list advertized-table-types {
+ description "The BGP Table-type capabilities advertized by the BGP peer.";
+ leaf afi {
+ description "Address Family Identifier.";
+ type string;
+ default "";
+ }
+ leaf safi {
+ description "Subsequent Address Family Identifier.";
+ type string;
+ default "";
+ }
+ }
+ }
+
+ identity peer-rpc;
+
+ augment "/config:modules/config:module/config:state" {
+ case bgp-peer {
+ when "/config:modules/config:module/config:type = 'bgp-peer'";
+
+ rpcx:rpc-context-instance "peer-rpc";
+
+ container bgp-peer-state {
+ list route-table {
+
+ leaf table-type {
+ description "The table name - composed of AFI and SAFI.";
+ type string;
+ }
+
+ leaf routes-count {
+ description "The total number of routes in table.";
+ type uint32;
+ default 0;
+ }
+ }
+
+ leaf session-established-count {
+ description "The total number of time the BGP session was transitioned to Up state.";
+ type uint32;
+ default 0;
+ }
+ }
+
+ container bgp-session-state {
+
+ leaf session-state {
+ description "The BGP peer connection state.";
+ type string;
+ }
+
+ leaf session-duration {
+ description "The session duration (time formated d:HH:mm:ss).";
+ type string;
+ }
+
+ leaf holdtime-current {
+ description "Time interval (in seconds) for HoldTimer established with the peer.";
+ type uint16;
+ default 0;
+ }
+
+ leaf keepalive-current {
+ description "Time interval (in seconds) for KeepAlive established with the peer.";
+ type uint16;
+ default 0;
+ }
+
+ container speaker-preferences {
+ description "The BGP speaker preferences, to which this BGP peer is connected.";
+ uses preferences;
+ }
+
+ container peer-preferences {
+ description "The BGP peer preferences.";
+ uses preferences;
+ }
+
+ container messages-stats {
+ description "The BGP messages statistics.";
+ container total-msgs {
+ description "The statistics for all received/sent BGP messages.";
+ uses message-stats;
+ }
+
+ container keep-alive-msgs {
+ description "The statistics for received/sent BGP Keep-Alive messages.";
+ uses message-stats;
+ }
+
+ container update-msgs {
+ description "The statistics for received/sent BGP Update messages.";
+ uses message-stats;
+ }
+
+ container error-msgs {
+ container error-received {
+ description "The received BGP Error (notification) messages statistics.";
+ uses message-state;
+ uses error;
+ }
+
+ container error-sent {
+ description "The sent BGP Error (notification) messages statistics.";
+ uses message-state;
+ uses error;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ rpc reset-session {
+ description "Restart the session between BGP peers";
+ input {
+ uses rpcx:rpc-context-ref {
+ refine context-instance {
+ rpcx:rpc-context-instance peer-rpc;
+ }
+ }
+ }
+ }
+
+ rpc reset-stats {
+ description "Reset the BGP peer statistics.";
+ input {
+ uses rpcx:rpc-context-ref {
+ refine context-instance {
+ rpcx:rpc-context-instance peer-rpc;
+ }
+ }
+ }
+ }
+
identity rib-impl {
base config:module-type;
config:provided-service bgprib:rib;
import io.netty.channel.Channel;
import io.netty.channel.EventLoop;
import java.math.BigInteger;
+import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import org.mockito.stubbing.Answer;
import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
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.AsyncDataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsIn;
@SuppressWarnings("unchecked")
@Before
- public void setUp() throws InterruptedException, ExecutionException {
+ public void setUp() throws InterruptedException, ExecutionException, ReadFailedException {
MockitoAnnotations.initMocks(this);
final List<BgpTableType> localTables = new ArrayList<>();
this.routes = new ArrayList<>();
this.r = new RIBImpl(new RibId("test"), new AsNumber(5L), new Ipv4Address("127.0.0.1"),
context , this.dispatcher, this.tcpStrategyFactory, this.tcpStrategyFactory, this.dps, localTables);
this.peer = new ApplicationPeer(new ApplicationRibId("t"), new Ipv4Address("127.0.0.1"), this.r);
+ final ReadOnlyTransaction readTx = Mockito.mock(ReadOnlyTransaction.class);
+ Mockito.doReturn(readTx).when(this.dps).newReadOnlyTransaction();
+ final CheckedFuture<Optional<DataObject>, ReadFailedException> readFuture = Mockito.mock(CheckedFuture.class);
+ Mockito.doReturn(Optional.<DataObject>absent()).when(readFuture).checkedGet();
+ Mockito.doReturn(readFuture).when(readTx).read(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(InstanceIdentifier.class));
}
@Test
Mockito.doReturn(null).when(this.eventLoop).schedule(any(Runnable.class), any(long.class), any(TimeUnit.class));
Mockito.doReturn(Boolean.TRUE).when(this.channel).isWritable();
Mockito.doReturn(null).when(this.channel).close();
+ Mockito.doReturn(new InetSocketAddress("localhost", 12345)).when(this.channel).remoteAddress();
+ Mockito.doReturn(new InetSocketAddress("localhost", 12345)).when(this.channel).localAddress();
final List<BgpParameters> params = Lists.newArrayList(new BgpParametersBuilder().setCParameters(new MultiprotocolCaseBuilder()
.setMultiprotocolCapability(new MultiprotocolCapabilityBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).build()).build()).build());
this.session = new BGPSessionImpl(this.classic, this.channel, new OpenBuilder().setBgpIdentifier(new Ipv4Address("1.1.1.1")).setHoldTimer(50).setMyAsNumber(72).setBgpParameters(params).build(), 30);
assertEquals(2, this.routes.size());
//create new peer so that it gets advertized routes from RIB
- final BGPPeer testingPeer = new BGPPeer("testingPeer", this.r);
- testingPeer.onSessionUp(this.session);
- assertEquals(4, this.routes.size());
+ try (final BGPPeer testingPeer = new BGPPeer("testingPeer", this.r)) {
+ testingPeer.onSessionUp(this.session);
+ assertEquals(4, this.routes.size());
+ assertEquals(1, testingPeer.getBgpPeerState().getSessionEstablishedCount().intValue());
+ assertEquals(1, testingPeer.getBgpPeerState().getRouteTable().size());
+ assertNotNull(testingPeer.getBgpSessionState());
+ }
ub.setNlri(null);
ub.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setWithdrawnRoutes(prefs).build());
package org.opendaylight.protocol.bgp.rib.impl;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpSessionState;
import org.opendaylight.protocol.bgp.parser.BGPError;
import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
private static final int HOLD_TIMER = 3;
private static final AsNumber AS_NUMBER = new AsNumber(30L);
private static final Ipv4Address BGP_ID = new Ipv4Address("1.1.1.2");
+ private static final String LOCAL_IP = "1.1.1.4";
+ private static final int LOCAL_PORT = 12345;
@Mock
private EventLoop eventLoop;
}).when(this.eventLoop).schedule(any(Runnable.class), any(long.class), any(TimeUnit.class));
doReturn("TestingChannel").when(this.speakerListener).toString();
doReturn(new InetSocketAddress(InetAddress.getByName(BGP_ID.getValue()), 179)).when(this.speakerListener).remoteAddress();
+ doReturn(new InetSocketAddress(InetAddress.getByName(LOCAL_IP), LOCAL_PORT)).when(this.speakerListener).localAddress();
doReturn(this.pipeline).when(this.speakerListener).pipeline();
doReturn(this.pipeline).when(this.pipeline).replace(any(ChannelHandler.class), any(String.class), any(ChannelHandler.class));
doReturn(mock(ChannelFuture.class)).when(this.speakerListener).close();
@Test
public void testBGPSession() {
this.bgpSession.sessionUp();
- Assert.assertEquals(BGPSessionImpl.State.Up, this.bgpSession.getState());
- Assert.assertEquals(AS_NUMBER, this.bgpSession.getAsNumber());
- Assert.assertEquals(BGP_ID, this.bgpSession.getBgpId());
- Assert.assertEquals(1, this.bgpSession.getAdvertisedTableTypes().size());
- Assert.assertTrue(this.listener.up);
+ assertEquals(BGPSessionImpl.State.Up, this.bgpSession.getState());
+ assertEquals(AS_NUMBER, this.bgpSession.getAsNumber());
+ assertEquals(BGP_ID, this.bgpSession.getBgpId());
+ assertEquals(1, this.bgpSession.getAdvertisedTableTypes().size());
+ assertTrue(this.listener.up);
+ //test stats
+ BgpSessionState state = this.bgpSession.getBgpSesionState();
+ assertEquals(HOLD_TIMER, state.getHoldtimeCurrent().intValue());
+ assertEquals(1, state.getKeepaliveCurrent().intValue());
+ assertEquals("Up", state.getSessionState());
+ assertEquals(BGP_ID.getValue(), state.getPeerPreferences().getAddress());
+ assertEquals(AS_NUMBER.getValue(), state.getPeerPreferences().getAs());
+ assertEquals(BGP_ID.getValue(), state.getPeerPreferences().getBgpId());
+ assertEquals(1, state.getPeerPreferences().getAdvertizedTableTypes().size());
+ assertEquals(HOLD_TIMER, state.getPeerPreferences().getHoldtime().intValue());
+ assertTrue(state.getPeerPreferences().getFourOctetAsCapability());
+ assertEquals(LOCAL_IP, state.getSpeakerPreferences().getAddress());
+ assertEquals(LOCAL_PORT, state.getSpeakerPreferences().getPort().intValue());
+ assertEquals(0, state.getMessagesStats().getTotalMsgs().getReceived().getCount().longValue());
+ assertEquals(0, state.getMessagesStats().getTotalMsgs().getSent().getCount().longValue());
this.bgpSession.handleMessage(new UpdateBuilder().build());
- Assert.assertEquals(1, this.listener.getListMsg().size());
- Assert.assertTrue(this.listener.getListMsg().get(0) instanceof Update);
+ assertEquals(1, this.listener.getListMsg().size());
+ assertTrue(this.listener.getListMsg().get(0) instanceof Update);
+ assertEquals(1, state.getMessagesStats().getTotalMsgs().getReceived().getCount().longValue());
+ assertEquals(1, state.getMessagesStats().getUpdateMsgs().getReceived().getCount().longValue());
+ assertEquals(0, state.getMessagesStats().getUpdateMsgs().getSent().getCount().longValue());
this.bgpSession.handleMessage(new KeepaliveBuilder().build());
this.bgpSession.handleMessage(new KeepaliveBuilder().build());
+ assertEquals(3, state.getMessagesStats().getTotalMsgs().getReceived().getCount().longValue());
+ assertEquals(2, state.getMessagesStats().getKeepAliveMsgs().getReceived().getCount().longValue());
+ assertEquals(0, state.getMessagesStats().getKeepAliveMsgs().getSent().getCount().longValue());
this.bgpSession.close();
- Assert.assertEquals(BGPSessionImpl.State.Idle, this.bgpSession.getState());
- Assert.assertEquals(1, this.receivedMsgs.size());
- Assert.assertTrue(this.receivedMsgs.get(0) instanceof Notify);
+ assertEquals(BGPSessionImpl.State.Idle, this.bgpSession.getState());
+ assertEquals(1, this.receivedMsgs.size());
+ assertTrue(this.receivedMsgs.get(0) instanceof Notify);
final Notify error = (Notify) this.receivedMsgs.get(0);
- Assert.assertEquals(BGPError.CEASE.getCode(), error.getErrorCode().shortValue());
+ assertEquals(BGPError.CEASE.getCode(), error.getErrorCode().shortValue());
+ assertEquals(BGPError.CEASE.getSubcode(), error.getErrorSubcode().shortValue());
Mockito.verify(this.speakerListener).close();
+ assertEquals(3, state.getMessagesStats().getTotalMsgs().getReceived().getCount().longValue());
+ assertEquals(1, state.getMessagesStats().getTotalMsgs().getSent().getCount().longValue());
+ assertEquals(1, state.getMessagesStats().getErrorMsgs().getErrorSent().getCount().longValue());
+ assertEquals(BGPError.CEASE.getCode(), state.getMessagesStats().getErrorMsgs().getErrorSent().getCode().shortValue());
+ assertEquals(BGPError.CEASE.getSubcode(), state.getMessagesStats().getErrorMsgs().getErrorSent().getSubCode().shortValue());
+
+ this.bgpSession.resetSessionStats();
+ assertEquals(0, state.getMessagesStats().getTotalMsgs().getReceived().getCount().longValue());
+ assertEquals(0, state.getMessagesStats().getTotalMsgs().getSent().getCount().longValue());
+ assertEquals(0, state.getMessagesStats().getErrorMsgs().getErrorSent().getCount().longValue());
}
@Test
@Test
public void testHandleNotifyMsg() {
this.bgpSession.handleMessage(new NotifyBuilder().setErrorCode(BGPError.BAD_BGP_ID.getCode()).setErrorSubcode(BGPError.BAD_BGP_ID.getSubcode()).build());
+ assertEquals(1, this.bgpSession.getBgpSesionState().getMessagesStats().getErrorMsgs().getErrorReceived().getCount().longValue());
+ assertEquals(BGPError.BAD_BGP_ID.getCode(), this.bgpSession.getBgpSesionState().getMessagesStats().getErrorMsgs().getErrorReceived().getCode().shortValue());
+ assertEquals(BGPError.BAD_BGP_ID.getSubcode(), this.bgpSession.getBgpSesionState().getMessagesStats().getErrorMsgs().getErrorReceived().getSubCode().shortValue());
Assert.assertEquals(BGPSessionImpl.State.Idle, this.bgpSession.getState());
Mockito.verify(this.speakerListener).close();
}
doReturn(null).when(this.eventLoop).schedule(any(Runnable.class), any(long.class), any(TimeUnit.class));
doReturn("TestingChannel").when(this.speakerListener).toString();
doReturn(new InetSocketAddress(peerAddress, 179)).when(this.speakerListener).remoteAddress();
+ doReturn(new InetSocketAddress(peerAddress, 179)).when(this.speakerListener).localAddress();
doReturn(this.pipeline).when(this.speakerListener).pipeline();
doReturn(this.pipeline).when(this.pipeline).replace(any(ChannelHandler.class), any(String.class), any(ChannelHandler.class));
doReturn(mock(ChannelFuture.class)).when(this.speakerListener).close();
import com.google.common.base.Preconditions;
import io.netty.channel.Channel;
import java.net.InetSocketAddress;
-import java.util.concurrent.TimeUnit;
+import org.opendaylight.protocol.util.StatisticsUtil;
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;
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.setLastSentMsgTimestamp(this.lastSentMsgTimestamp);
this.msgsBuilder.setReceivedMsgCount(this.receivedMsgCount);
this.msgsBuilder.setSentMsgCount(this.sentMsgCount);
this.msgsBuilder.setUnknownMsgReceived(unknownMessagesCount);
}
public void updateLastSentMsg() {
- this.lastSentMsgTimestamp = System.currentTimeMillis();
+ this.lastSentMsgTimestamp = StatisticsUtil.getCurrentTimestampInSeconds();
this.sentMsgCount++;
}
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.protocol.util.StatisticsUtil;
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;
public StatefulMessages getStatefulMessages() {
final StatefulMessages msgs = new StatefulMessages();
- msgs.setLastReceivedRptMsgTimestamp(TimeUnit.MILLISECONDS.toSeconds(this.lastReceivedRptMsgTimestamp));
+ msgs.setLastReceivedRptMsgTimestamp(this.lastReceivedRptMsgTimestamp);
msgs.setReceivedRptMsgCount(this.receivedRptMsgCount);
msgs.setSentInitMsgCount(this.sentInitMsgCount);
msgs.setSentUpdMsgCount(this.sentUpdMsgCount);
state.setLocalPref(this.localPref);
state.setPeerPref(this.peerPref);
state.setMessages(getMessageStats(session.getMessages()));
- state.setSessionDuration(formatElapsedTime(this.sessionUpDuration.elapsed(TimeUnit.SECONDS)));
+ state.setSessionDuration(StatisticsUtil.formatElapsedTime(this.sessionUpDuration.elapsed(TimeUnit.SECONDS)));
return state;
}
}
public void updateLastReceivedRptMsg() {
- this.lastReceivedRptMsgTimestamp = System.currentTimeMillis();
+ this.lastReceivedRptMsgTimestamp = StatisticsUtil.getCurrentTimestampInSeconds();
this.receivedRptMsgCount++;
}
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)));
- }
}
--- /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.util;
+
+import com.google.common.base.Preconditions;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Statistics utility class.
+ */
+public final class StatisticsUtil {
+
+ private StatisticsUtil() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Formats elapsed time in seconds to form days:hours:minutes:seconds.
+ *
+ * @param seconds Elapsed time in seconds.
+ * @return Formated time as string d:hh:mm:ss
+ */
+ public static String formatElapsedTime(final long seconds) {
+ Preconditions.checkArgument(seconds >= 0);
+ return String.format("%1d:%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)));
+ }
+
+ /**
+ * Get current time in seconds.
+ *
+ * @return the difference, measured in seconds, between the current time and midnight, January 1, 1970 UTC.
+ * @see System.currentTimeMillis()
+ */
+ public static long getCurrentTimestampInSeconds() {
+ return TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
+ }
+}
--- /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.util;
+
+import static org.junit.Assert.assertEquals;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import org.junit.Test;
+
+public class StatisticsUtilTest {
+
+ @Test
+ public void testGetCurrentTimestampInSeconds() {
+ assertEquals(System.currentTimeMillis() / 1000, StatisticsUtil.getCurrentTimestampInSeconds());
+ }
+
+ @Test
+ public void testFormatElapsedTime() {
+ assertEquals("1:01:01:01", StatisticsUtil.formatElapsedTime(90061));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testFormatElapsedTimeInvalidInput() {
+ StatisticsUtil.formatElapsedTime(-1);
+ }
+
+ @Test(expected=UnsupportedOperationException.class)
+ public void testPrivateConstructor() throws Throwable {
+ final Constructor<StatisticsUtil> c = StatisticsUtil.class.getDeclaredConstructor();
+ c.setAccessible(true);
+ try {
+ c.newInstance();
+ } catch (InvocationTargetException e) {
+ throw e.getCause();
+ }
+ }
+
+}