package org.opendaylight.controller.config.yang.bgp.rib.impl;
import com.google.common.base.Optional;
+import java.util.Collections;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import java.util.Collections;
-
/**
* Application peer handler which handles translation from custom RIB into local RIB
*/
public java.lang.AutoCloseable createInstance() {
final Map<TablesKey, PathSelectionMode> pathSelectionStrategies = mapBestPathSelectionStrategyByFamily(getRibPathSelectionModeDependency());
final RIBImpl rib = new RIBImpl(getRibId(), getLocalAs(), getBgpRibId(), getClusterId(), getExtensionsDependency(),
- getBgpDispatcherDependency(), getCodecTreeFactoryDependency(), getDataProviderDependency(), getDomDataProviderDependency(), getLocalTableDependency(), pathSelectionStrategies, classLoadingStrategy(),
+ getBgpDispatcherDependency(), getCodecTreeFactoryDependency(), getDomDataProviderDependency(), getLocalTableDependency(), pathSelectionStrategies, classLoadingStrategy(),
new RIBImplModuleTracker(getGlobalWriter()), getOpenconfigProviderDependency());
registerSchemaContextListener(rib);
+
+ rib.registerRootRuntimeBean(getRootRuntimeBeanRegistratorWrapper());
return rib;
}
import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
import org.opendaylight.protocol.bgp.rib.impl.spi.Codecs;
import org.opendaylight.protocol.bgp.rib.impl.spi.CodecsRegistry;
+import org.opendaylight.protocol.bgp.rib.impl.stats.UnsignedInt32Counter;
import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
private final RIBSupport support;
private final boolean mpSupport;
private final ListenerRegistration<AdjRibOutListener> registerDataTreeChangeListener;
+ private final UnsignedInt32Counter routeCounter;
private AdjRibOutListener(final PeerId peerId, final TablesKey tablesKey, final YangInstanceIdentifier ribId,
final CodecsRegistry registry, final RIBSupport support, final DOMDataTreeChangeService service,
- final ChannelOutputLimiter session, final boolean mpSupport) {
+ final ChannelOutputLimiter session, final boolean mpSupport, final UnsignedInt32Counter routeCounter) {
this.session = Preconditions.checkNotNull(session);
this.support = Preconditions.checkNotNull(support);
this.codecs = registry.getCodecs(this.support);
this.mpSupport = mpSupport;
final YangInstanceIdentifier adjRibOutId = ribId.node(Peer.QNAME).node(IdentifierUtils.domPeerId(peerId)).node(AdjRibOut.QNAME).node(Tables.QNAME).node(RibSupportUtils.toYangTablesKey(tablesKey));
this.registerDataTreeChangeListener = service.registerDataTreeChangeListener(new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, adjRibOutId), this);
+ this.routeCounter = routeCounter;
}
- static AdjRibOutListener create(@Nonnull final PeerId peerId, @Nonnull final TablesKey tablesKey, @Nonnull final YangInstanceIdentifier ribId, @Nonnull final CodecsRegistry registry, @Nonnull final RIBSupport support, @Nonnull final DOMDataTreeChangeService service, @Nonnull final ChannelOutputLimiter session, @Nonnull final boolean mpSupport) {
- return new AdjRibOutListener(peerId, tablesKey, ribId, registry, support, service, session, mpSupport);
+ static AdjRibOutListener create(@Nonnull final PeerId peerId, @Nonnull final TablesKey tablesKey, @Nonnull final YangInstanceIdentifier ribId,
+ @Nonnull final CodecsRegistry registry, @Nonnull final RIBSupport support, @Nonnull final DOMDataTreeChangeService service,
+ @Nonnull final ChannelOutputLimiter session, @Nonnull final boolean mpSupport, @Nonnull final UnsignedInt32Counter routeCounter
+ ) {
+ return new AdjRibOutListener(peerId, tablesKey, ribId, registry, support, service, session, mpSupport, routeCounter);
}
@Override
}
private Update withdraw(final MapEntryNode route) {
+ this.routeCounter.decreaseCount();
if (!this.mpSupport) {
return buildUpdate(Collections.<MapEntryNode>emptyList(), Collections.singleton(route), routeAttributes(route));
}
}
private Update advertise(final MapEntryNode route) {
+ this.routeCounter.increaseCount();
if (!this.mpSupport) {
return buildUpdate(Collections.singleton(route), Collections.<MapEntryNode>emptyList(), routeAttributes(route));
}
final YangInstanceIdentifier peerIId = targetRib.getYangRibId().node(Peer.QNAME).node(peerId);
this.adjRibsInId = peerIId.node(AdjRibIn.QNAME).node(Tables.QNAME);
this.chain = targetRib.createPeerChain(this);
+ //TODO need to create effective rib in writer with route counter here
this.effectiveRibInWriter = EffectiveRibInWriter.create(targetRib.getService(), targetRib.createPeerChain(this), peerIId,
targetRib.getImportPolicyPeerTracker(), targetRib.getRibSupportContext(), PeerRole.Internal);
this.writerChain = targetRib.createPeerChain(this);
import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
import com.google.common.net.InetAddresses;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.concurrent.GuardedBy;
-import org.opendaylight.controller.config.api.IdentityAttributeRef;
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.controller.md.sal.common.api.data.AsyncTransaction;
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.parser.BGPError;
import org.opendaylight.protocol.bgp.parser.impl.message.update.LocalPreferenceAttributeParser;
import org.opendaylight.protocol.bgp.parser.spi.MessageUtil;
-import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionStatistics;
+import org.opendaylight.protocol.bgp.rib.impl.stats.peer.BGPPeerStats;
+import org.opendaylight.protocol.bgp.rib.impl.stats.peer.BGPSessionStats;
import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContext;
+import org.opendaylight.protocol.bgp.rib.impl.stats.peer.BGPPeerStatsImpl;
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.opendaylight.protocol.bgp.rib.spi.Peer;
import org.opendaylight.protocol.bgp.rib.spi.RouterIds;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.ZeroBasedCounter32;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.prefixes.DestinationIpv4Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.prefixes.destination.ipv4.Ipv4Prefixes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.prefixes.destination.ipv4.Ipv4PrefixesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.Notification;
-import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
-import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final String name;
private BGPPeerRuntimeRegistrator registrator;
private BGPPeerRuntimeRegistration runtimeReg;
- private long sessionEstablishedCounter = 0L;
private final Map<TablesKey, AdjRibOutListener> adjRibOutListenerSet = new HashMap();
private final RpcProviderRegistry rpcRegistry;
private RoutedRpcRegistration<BgpPeerRpcService> rpcRegistration;
private final PeerRole peerRole;
private final Optional<SimpleRoutingPolicy> simpleRoutingPolicy;
+ private final BGPPeerStats peerStats;
public BGPPeer(final String name, final RIB rib, final PeerRole role, final SimpleRoutingPolicy peerStatus, final RpcProviderRegistry rpcRegistry) {
this.peerRole = role;
this.chain = rib.createPeerChain(this);
this.ribWriter = AdjRibInWriter.create(rib.getYangRibId(), this.peerRole, this.simpleRoutingPolicy, this.chain);
this.rpcRegistry = rpcRegistry;
+ this.peerStats = new BGPPeerStatsImpl(this.name, this.tables);
+
+ // add current peer to "configured BGP peer" stats
+ this.rib.getRenderStats().getConfiguredPeerCounter().increaseCount();
}
public BGPPeer(final String name, final RIB rib, final PeerRole role, final RpcProviderRegistry rpcRegistry) {
if(!isLearnNone(this.simpleRoutingPolicy)) {
final YangInstanceIdentifier peerIId = this.rib.getYangRibId().node(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer.QNAME).node(IdentifierUtils.domPeerId(peerId));
this.effRibInWriter = EffectiveRibInWriter.create(this.rib.getService(), this.rib.createPeerChain(this), peerIId, ((RIBImpl) this.rib).getImportPolicyPeerTracker(),
- this.rib.getRibSupportContext(), this.peerRole);
+ this.rib.getRibSupportContext(), this.peerRole, this.peerStats.getEffectiveRibInRouteCounters(), this.peerStats.getAdjRibInRouteCounters());
}
this.ribWriter = this.ribWriter.transform(peerId, this.rib.getRibSupportContext(), this.tables, addPathTablesType);
- this.sessionEstablishedCounter++;
+
+ // register BGP Peer stats
+ this.peerStats.getSessionEstablishedCounter().increaseCount();
if (this.registrator != null) {
this.runtimeReg = this.registrator.register(this);
}
this.rib.getInstanceIdentifier().child(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer.class, new PeerKey(peerId));
this.rpcRegistration.registerPath(PeerContext.class, path);
}
+
+ this.rib.getRenderStats().getConnectedPeerCounter().increaseCount();
}
private void createAdjRibOutListener(final PeerId peerId) {
// not particularly nice
if (context != null && this.session instanceof BGPSessionImpl) {
this.adjRibOutListenerSet.put(key, AdjRibOutListener.create(peerId, key, this.rib.getYangRibId(), this.rib.getCodecsRegistry(),
- context.getRibSupport(), ((RIBImpl) this.rib).getService(), ((BGPSessionImpl) this.session).getLimiter(), mpSupport));
+ context.getRibSupport(), ((RIBImpl) this.rib).getService(), ((BGPSessionImpl) this.session).getLimiter(), mpSupport, peerStats.getAdjRibOutRouteCounters().init(key)));
}
}
LOG.warn("Error closing session with peer", e);
}
this.session = null;
+
+ this.rib.getRenderStats().getConnectedPeerCounter().decreaseCount();
}
}
@Override
public void resetStats() {
- if (this.session instanceof BGPSessionStatistics) {
- ((BGPSessionStatistics) this.session).resetSessionStats();
+ if (this.session instanceof BGPSessionStats) {
+ ((BGPSessionStats) this.session).resetBgpSessionStats();
}
}
@Override
public BgpSessionState getBgpSessionState() {
- if (this.session instanceof BGPSessionStatistics) {
- return ((BGPSessionStatistics) this.session).getBgpSessionState();
+ if (this.session instanceof BGPSessionStats) {
+ return ((BGPSessionStats) this.session).getBgpSessionState();
}
return new BgpSessionState();
}
@Override
public synchronized BgpPeerState getBgpPeerState() {
- final BgpPeerState peerState = new BgpPeerState();
- final List<RouteTable> routes = Lists.newArrayList();
- for (final TablesKey tablesKey : this.tables) {
- final RouteTable routeTable = new RouteTable();
- // FIXME: DEPRECATED, use setAfi() and setSafi() instead
- routeTable.setTableType("afi=" + tablesKey.getAfi().getSimpleName() + ",safi=" + tablesKey.getSafi().getSimpleName());
- final QName afiQName = BindingReflections.findQName(tablesKey.getAfi()).intern();
- final QName safiQName = BindingReflections.findQName(tablesKey.getSafi()).intern();
- routeTable.setAfi(new IdentityAttributeRef(afiQName.toString()));
- routeTable.setSafi(new IdentityAttributeRef(safiQName.toString()));
- routes.add(routeTable);
- }
- peerState.setRouteTable(routes);
- peerState.setSessionEstablishedCount(new ZeroBasedCounter32(this.sessionEstablishedCounter));
- return peerState;
+ return peerStats.getBgpPeerState();
}
@Override
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+import io.netty.buffer.ByteBufUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import org.opendaylight.protocol.bgp.parser.spi.pojo.MultiPathSupportImpl;
import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
-import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionStatistics;
+import org.opendaylight.protocol.bgp.rib.impl.stats.peer.BGPSessionStats;
+import org.opendaylight.protocol.bgp.rib.impl.stats.peer.BGPSessionStatsImpl;
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 SimpleChannelInboundHandler<Notification> implements BGPSession, BGPSessionStatistics, AutoCloseable {
+public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> implements BGPSession, BGPSessionStats, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(BGPSessionImpl.class);
private final BGPPeerRegistry peerRegistry;
private final ChannelOutputLimiter limiter;
- private BGPSessionStats sessionStats;
+ private BGPSessionStatsImpl sessionStats;
public BGPSessionImpl(final BGPSessionListener listener, final Channel channel, final Open remoteOpen, final BGPSessionPreferences localPreferences,
final BGPPeerRegistry peerRegistry) {
this(listener, channel, remoteOpen, localPreferences.getHoldTime(), peerRegistry);
- this.sessionStats = new BGPSessionStats(remoteOpen, this.holdTimerValue, this.keepAlive, channel, Optional.of(localPreferences), this.tableTypes, this.addPathTypes);
+ this.sessionStats = new BGPSessionStatsImpl(this, remoteOpen, this.holdTimerValue, this.keepAlive, channel, Optional.of(localPreferences), this.tableTypes, this.addPathTypes);
}
public BGPSessionImpl(final BGPSessionListener listener, final Channel channel, final Open remoteOpen, final int localHoldTimer,
}, this.keepAlive, TimeUnit.SECONDS);
}
this.bgpId = remoteOpen.getBgpIdentifier();
- this.sessionStats = new BGPSessionStats(remoteOpen, this.holdTimerValue, this.keepAlive, channel, Optional.<BGPSessionPreferences>absent(),
+ this.sessionStats = new BGPSessionStatsImpl(this, remoteOpen, this.holdTimerValue, this.keepAlive, channel, Optional.<BGPSessionPreferences>absent(),
this.tableTypes, this.addPathTypes);
}
synchronized void handleMessage(final Notification msg) throws BGPDocumentedException {
// Update last reception time
this.lastMessageReceivedAt = System.nanoTime();
- this.sessionStats.updateReceivedMsgTotal();
if (msg instanceof Open) {
// Open messages should not be present here
this.terminate(new BGPDocumentedException(null, BGPError.FSM_ERROR));
} else if (msg instanceof Notify) {
+ final Notify notify = (Notify) msg;
// Notifications are handled internally
- LOG.info("Session closed because Notification message received: {} / {}", ((Notify) msg).getErrorCode(),
- ((Notify) msg).getErrorSubcode());
+ LOG.info("Session closed because Notification message received: {} / {}, data={}", notify.getErrorCode(),
+ notify.getErrorSubcode(), notify.getData() != null ? ByteBufUtil.hexDump(notify.getData()) : null);
this.closeWithoutMessage();
this.listener.onSessionTerminated(this, new BGPTerminationReason(
- BGPError.forValue(((Notify) msg).getErrorCode(), ((Notify) msg).getErrorSubcode())));
- this.sessionStats.updateReceivedMsgErr((Notify) msg);
+ BGPError.forValue(notify.getErrorCode(), notify.getErrorSubcode())));
} else if (msg instanceof Keepalive) {
// Keepalives are handled internally
- LOG.trace("Received KeepAlive messsage.");
+ LOG.trace("Received KeepAlive message.");
this.kaCounter++;
- this.sessionStats.updateReceivedMsgKA();
if (this.kaCounter >= 2) {
this.sync.kaReceived();
}
} else if (msg instanceof RouteRefresh) {
this.listener.onMessage(this, msg);
- this.sessionStats.updateReceivedMsgRR();
} else if (msg instanceof Update) {
this.listener.onMessage(this, msg);
this.sync.updReceived((Update) msg);
- this.sessionStats.updateReceivedMsgUpd();
} else {
LOG.warn("Ignoring unhandled message: {}.", msg.getClass());
}
+
+ this.sessionStats.updateReceivedMsg(msg);
}
synchronized void endOfInput() {
}
});
this.lastMessageSentAt = System.nanoTime();
- this.sessionStats.updateSentMsgTotal();
- if (msg instanceof Update) {
- this.sessionStats.updateSentMsgUpd();
- } else if (msg instanceof Notify) {
- this.sessionStats.updateSentMsgErr((Notify) msg);
- }
+ this.sessionStats.updateSentMsg(msg);
return future;
}
@Override
public synchronized BgpSessionState getBgpSessionState() {
- return this.sessionStats.getBgpSessionState(this.state);
+ return this.sessionStats.getBgpSessionState();
}
@Override
- public synchronized void resetSessionStats() {
- this.sessionStats.resetStats();
+ public synchronized void resetBgpSessionStats() {
+ this.sessionStats.resetBgpSessionStats();
}
public ChannelOutputLimiter getLimiter() {
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContext;
import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
+import org.opendaylight.protocol.bgp.rib.impl.stats.peer.route.PerTableTypeRouteCounter;
import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.AdjRibIn;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.EffectiveRibIn;
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;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
private final YangInstanceIdentifier effRibTables;
private final ListenerRegistration<?> reg;
private final DOMTransactionChain chain;
+ private final PerTableTypeRouteCounter effectiveRibInRouteCounters;
+ private final PerTableTypeRouteCounter adjRibInRouteCounters;
+ private final Map<TablesKey, Set<YangInstanceIdentifier>> effectiveRibInRouteMap = new ConcurrentHashMap<>();
+ private final Map<TablesKey, Set<YangInstanceIdentifier>> adjRibInRouteMap = new ConcurrentHashMap<>();
- AdjInTracker(final DOMDataTreeChangeService service, final RIBSupportContextRegistry registry, final DOMTransactionChain chain, final YangInstanceIdentifier peerIId) {
+ AdjInTracker(final DOMDataTreeChangeService service, final RIBSupportContextRegistry registry, final DOMTransactionChain chain, final YangInstanceIdentifier peerIId,
+ @Nonnull final PerTableTypeRouteCounter effectiveRibInRouteCounters, @Nonnull final PerTableTypeRouteCounter adjRibInRouteCounters) {
this.registry = Preconditions.checkNotNull(registry);
this.chain = Preconditions.checkNotNull(chain);
this.peerIId = Preconditions.checkNotNull(peerIId);
this.effRibTables = this.peerIId.node(EffectiveRibIn.QNAME).node(Tables.QNAME);
+ this.effectiveRibInRouteCounters = Preconditions.checkNotNull(effectiveRibInRouteCounters);
+ this.adjRibInRouteCounters = Preconditions.checkNotNull(adjRibInRouteCounters);
final DOMDataTreeIdentifier treeId = new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, this.peerIId.node(AdjRibIn.QNAME).node(Tables.QNAME));
LOG.debug("Registered Effective RIB on {}", this.peerIId);
this.reg = service.registerDataTreeChangeListener(treeId, this);
}
+ /**
+ * @deprecated Should always pass in route counter
+ * @param service
+ * @param registry
+ * @param chain
+ * @param peerIId
+ */
+ @Deprecated
+ AdjInTracker(final DOMDataTreeChangeService service, final RIBSupportContextRegistry registry, final DOMTransactionChain chain, final YangInstanceIdentifier peerIId) {
+ this(service, registry, chain, peerIId, new PerTableTypeRouteCounter("effective-rib-in"), new PerTableTypeRouteCounter("adj-rib-in"));
+ }
+
+ private void updateRoute(@Nonnull final PerTableTypeRouteCounter counter, @Nonnull final Map<TablesKey, Set<YangInstanceIdentifier>> routeMap,
+ @Nonnull final TablesKey tablesKey, @Nonnull final YangInstanceIdentifier routeId) {
+ routeMap.putIfAbsent(tablesKey, new HashSet<>());
+ routeMap.get(tablesKey).add(routeId);
+
+ updateRouteCounter(counter, routeMap,tablesKey);
+ }
+
+ private void deleteRoute(@Nonnull final PerTableTypeRouteCounter counter, @Nonnull final Map<TablesKey, Set<YangInstanceIdentifier>> routeMap,
+ @Nonnull final TablesKey tablesKey, @Nonnull final YangInstanceIdentifier routeId) {
+ if (routeMap.containsKey(tablesKey)) {
+ routeMap.get(tablesKey).remove(routeId);
+ }
+
+ updateRouteCounter(counter, routeMap,tablesKey);
+ }
+
+ private void deleteRoute(@Nonnull final PerTableTypeRouteCounter counter, @Nonnull final Map<TablesKey, Set<YangInstanceIdentifier>> routeMap,
+ @Nonnull final TablesKey tablesKey) {
+ routeMap.remove(tablesKey);
+
+ updateRouteCounter(counter, routeMap,tablesKey);
+ }
+
+ private void updateRouteCounter(@Nonnull final PerTableTypeRouteCounter counter, @Nonnull final Map<TablesKey, Set<YangInstanceIdentifier>> routeMap,
+ @Nonnull final TablesKey tablesKey) {
+ counter.getCounterOrSetDefault(tablesKey)
+ .setCount(routeMap.getOrDefault(tablesKey, new HashSet<>()).size());
+ }
+
private void processRoute(final DOMDataWriteTransaction tx, final RIBSupport ribSupport, final AbstractImportPolicy policy, final YangInstanceIdentifier routesPath, final DataTreeCandidateNode route) {
LOG.debug("Process route {}", route.getIdentifier());
final YangInstanceIdentifier routeId = ribSupport.routePath(routesPath, route.getIdentifier());
+ final TablesKey tablesKey = new TablesKey(ribSupport.getAfi(), ribSupport.getSafi());
switch (route.getModificationType()) {
case DELETE:
case DISAPPEARED:
tx.delete(LogicalDatastoreType.OPERATIONAL, routeId);
+ LOG.debug("Route deleted. routeId={}", routeId);
+
+ deleteRoute(adjRibInRouteCounters, adjRibInRouteMap, tablesKey, routeId);
+ deleteRoute(effectiveRibInRouteCounters, effectiveRibInRouteMap, tablesKey, routeId);
break;
case UNMODIFIED:
// No-op
case SUBTREE_MODIFIED:
case WRITE:
tx.put(LogicalDatastoreType.OPERATIONAL, routeId, route.getDataAfter().get());
+ // count adj-rib-in route first
+ updateRoute(adjRibInRouteCounters, adjRibInRouteMap, tablesKey, routeId);
+ updateRoute(effectiveRibInRouteCounters, effectiveRibInRouteMap, tablesKey, routeId);
// Lookup per-table attributes from RIBSupport
final ContainerNode advertisedAttrs = (ContainerNode) NormalizedNodes.findNode(route.getDataAfter(), ribSupport.routeAttributesIdentifier()).orNull();
final ContainerNode effectiveAttrs;
if (effectiveAttrs != null) {
tx.put(LogicalDatastoreType.OPERATIONAL, routeId.node(ribSupport.routeAttributesIdentifier()), effectiveAttrs);
+
+ updateRoute(effectiveRibInRouteCounters, effectiveRibInRouteMap, tablesKey, routeId);
} else {
LOG.warn("Route {} advertised empty attributes", routeId);
tx.delete(LogicalDatastoreType.OPERATIONAL, routeId);
+
+ deleteRoute(effectiveRibInRouteCounters, effectiveRibInRouteMap, tablesKey, routeId);
}
break;
default:
}
private void processTableChildren(final DOMDataWriteTransaction tx, final RIBSupport ribSupport, final YangInstanceIdentifier tablePath, final Collection<DataTreeCandidateNode> children) {
-
for (final DataTreeCandidateNode child : children) {
final PathArgument childIdentifier = child.getIdentifier();
final Optional<NormalizedNode<?, ?>> childDataAfter = child.getDataAfter();
+ final TablesKey tablesKey = new TablesKey(ribSupport.getAfi(), ribSupport.getSafi());
LOG.debug("Process table {} type {}, dataAfter {}, dataBefore {}", childIdentifier, child
.getModificationType(), childDataAfter, child.getDataBefore());
final YangInstanceIdentifier childPath = tablePath.node(childIdentifier);
switch (child.getModificationType()) {
case DELETE:
case DISAPPEARED:
- tx.delete(LogicalDatastoreType.OPERATIONAL, tablePath.node(childIdentifier));
+ tx.delete(LogicalDatastoreType.OPERATIONAL, childPath);
+ LOG.debug("Route deleted. routeId={}", childPath);
+
+ deleteRoute(adjRibInRouteCounters, adjRibInRouteMap, tablesKey, childPath);
+ deleteRoute(effectiveRibInRouteCounters, effectiveRibInRouteMap, tablesKey, childPath);
break;
case UNMODIFIED:
// No-op
final PathArgument lastArg = table.getIdentifier();
Verify.verify(lastArg instanceof NodeIdentifierWithPredicates, "Unexpected type %s in path %s", lastArg.getClass(), rootPath);
final NodeIdentifierWithPredicates tableKey = (NodeIdentifierWithPredicates) lastArg;
+ final RIBSupport ribSupport = getRibSupport(tableKey).getRibSupport();
final ModificationType modificationType = root.getModificationType();
switch (modificationType) {
case DELETE:
case DISAPPEARED:
final YangInstanceIdentifier effectiveTablePath = effectiveTablePath(tableKey);
LOG.debug("Delete Effective Table {} modification type {}, ", effectiveTablePath, modificationType);
+
// delete the corresponding effective table
tx.delete(LogicalDatastoreType.OPERATIONAL, effectiveTablePath);
+
+ deleteRoute(adjRibInRouteCounters, adjRibInRouteMap, new TablesKey(ribSupport.getAfi(), ribSupport.getSafi()));
+ deleteRoute(effectiveRibInRouteCounters, effectiveRibInRouteMap, new TablesKey(ribSupport.getAfi(), ribSupport.getSafi()));
break;
case SUBTREE_MODIFIED:
modifyTable(tx, tableKey, table);
private final AdjInTracker adjInTracker;
private final AbstractImportPolicy importPolicy;
+ @Deprecated
static EffectiveRibInWriter create(@Nonnull final DOMDataTreeChangeService service, @Nonnull final DOMTransactionChain chain,
@Nonnull final YangInstanceIdentifier peerIId, @Nonnull final ImportPolicyPeerTracker importPolicyPeerTracker, @Nonnull final RIBSupportContextRegistry registry, final PeerRole peerRole) {
return new EffectiveRibInWriter(service, chain, peerIId, importPolicyPeerTracker, registry, peerRole);
}
+ static EffectiveRibInWriter create(@Nonnull final DOMDataTreeChangeService service, @Nonnull final DOMTransactionChain chain,
+ @Nonnull final YangInstanceIdentifier peerIId, @Nonnull final ImportPolicyPeerTracker importPolicyPeerTracker, @Nonnull final RIBSupportContextRegistry registry, final PeerRole peerRole,
+ @Nonnull final PerTableTypeRouteCounter effectiveRouteCounters, @Nonnull final PerTableTypeRouteCounter adjRibInRouteCounters) {
+ return new EffectiveRibInWriter(service, chain, peerIId, importPolicyPeerTracker, registry, peerRole, effectiveRouteCounters, adjRibInRouteCounters);
+ }
+
+ @Deprecated
private EffectiveRibInWriter(final DOMDataTreeChangeService service, final DOMTransactionChain chain, final YangInstanceIdentifier peerIId,
final ImportPolicyPeerTracker importPolicyPeerTracker, final RIBSupportContextRegistry registry, final PeerRole peerRole) {
importPolicyPeerTracker.peerRoleChanged(peerIId, peerRole);
this.adjInTracker = new AdjInTracker(service, registry, chain, peerIId);
}
+ private EffectiveRibInWriter(final DOMDataTreeChangeService service, final DOMTransactionChain chain, final YangInstanceIdentifier peerIId,
+ final ImportPolicyPeerTracker importPolicyPeerTracker, final RIBSupportContextRegistry registry, final PeerRole peerRole,
+ @Nonnull final PerTableTypeRouteCounter effectiveRouteCounters, @Nonnull final PerTableTypeRouteCounter adjRibInRouteCounters) {
+ importPolicyPeerTracker.peerRoleChanged(peerIId, peerRole);
+ this.importPolicy = importPolicyPeerTracker.policyFor(IdentifierUtils.peerId((NodeIdentifierWithPredicates) peerIId.getLastPathArgument()));
+ this.adjInTracker = new AdjInTracker(service, registry, chain, peerIId, effectiveRouteCounters, adjRibInRouteCounters);
+ }
+
@Override
public void close() {
this.adjInTracker.close();
import org.opendaylight.protocol.bgp.mode.api.PathSelectionMode;
import org.opendaylight.protocol.bgp.mode.api.RouteEntry;
import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
+import org.opendaylight.protocol.bgp.rib.impl.stats.UnsignedInt32Counter;
import org.opendaylight.protocol.bgp.rib.spi.CacheDisconnectedPeers;
import org.opendaylight.protocol.bgp.rib.spi.ExportPolicyPeerTracker;
import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
private final ListenerRegistration<LocRibWriter> reg;
private final CacheDisconnectedPeers cacheDisconnectedPeers;
private final PathSelectionMode pathSelectionMode;
+ private final UnsignedInt32Counter routeCounter;
private LocRibWriter(final RIBSupportContextRegistry registry, final DOMTransactionChain chain, final YangInstanceIdentifier target, final Long ourAs,
final DOMDataTreeChangeService service, final PolicyDatabase pd, final TablesKey tablesKey, final CacheDisconnectedPeers cacheDisconnectedPeers,
- @Nonnull final PathSelectionMode pathSelectionMode) {
+ @Nonnull final PathSelectionMode pathSelectionMode, final UnsignedInt32Counter routeCounter) {
this.chain = Preconditions.checkNotNull(chain);
this.tableKey = RibSupportUtils.toYangTablesKey(tablesKey);
this.localTablesKey = tablesKey;
this.peerPolicyTracker = new ExportPolicyPeerTrackerImpl(pd, this.localTablesKey);
this.cacheDisconnectedPeers = cacheDisconnectedPeers;
this.pathSelectionMode = pathSelectionMode;
+ this.routeCounter = routeCounter;
final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
tx.merge(LogicalDatastoreType.OPERATIONAL, this.locRibTarget.node(Routes.QNAME), this.ribSupport.emptyRoutes());
public static LocRibWriter create(@Nonnull final RIBSupportContextRegistry registry, @Nonnull final TablesKey tablesKey, @Nonnull final DOMTransactionChain chain,
@Nonnull final YangInstanceIdentifier target, @Nonnull final AsNumber ourAs, @Nonnull final DOMDataTreeChangeService service, @Nonnull final PolicyDatabase pd,
- final CacheDisconnectedPeers cacheDisconnectedPeers, @Nonnull final PathSelectionMode pathSelectionStrategy) {
- return new LocRibWriter(registry, chain, target, ourAs.getValue(), service, pd, tablesKey, cacheDisconnectedPeers, pathSelectionStrategy);
+ final CacheDisconnectedPeers cacheDisconnectedPeers, @Nonnull final PathSelectionMode pathSelectionStrategy, @Nonnull final UnsignedInt32Counter routeCounter) {
+ return new LocRibWriter(registry, chain, target, ourAs.getValue(), service, pd, tablesKey, cacheDisconnectedPeers, pathSelectionStrategy, routeCounter);
}
@Override
LOG.debug("Updated route {} entry {}", routeId, entry);
routes.put(routeUpdateKey, entry);
}
+ updateRouteCounter();
+ }
+
+ /**
+ * Update the statistic of loc-rib route
+ */
+ private void updateRouteCounter() {
+ routeCounter.setCount(this.routeEntries.size());
}
private void walkThrough(final DOMDataWriteTransaction tx, final Map<RouteUpdateKey, RouteEntry> toUpdate) {
import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.RIBImplRuntimeRegistration;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.RIBImplRuntimeRegistrator;
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.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.protocol.bgp.rib.impl.spi.CodecsRegistry;
import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
+import org.opendaylight.protocol.bgp.rib.impl.stats.rib.impl.BGPRenderStats;
+import org.opendaylight.protocol.bgp.rib.impl.stats.rib.impl.RIBImplRuntimeMXBeanImpl;
import org.opendaylight.protocol.bgp.rib.spi.CacheDisconnectedPeers;
import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.bgp.rib.rib.loc.rib.tables.routes.Ipv4RoutesCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.bgp.rib.rib.loc.rib.tables.routes.Ipv6RoutesCase;
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.rib.rev130925.BgpRib;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.RibId;
private final BgpId bgpIdentifier;
private final Set<BgpTableType> localTables;
private final Set<TablesKey> localTablesKeys;
- private final DataBroker dataBroker;
private final DOMDataBroker domDataBroker;
private final RIBExtensionConsumerContext extensions;
private final YangInstanceIdentifier yangRibId;
private final CacheDisconnectedPeers cacheDisconnectedPeers;
private final Map<TablesKey, PathSelectionMode> bestPathSelectionStrategies;
private final ImportPolicyPeerTracker importPolicyPeerTracker;
+ private final RIBImplRuntimeMXBeanImpl renderStats;
+ private RIBImplRuntimeRegistrator registrator = null;
+ private RIBImplRuntimeRegistration runtimeReg = null;
public RIBImpl(final RibId ribId, final AsNumber localAs, final BgpId localBgpId, final ClusterIdentifier clusterId, final RIBExtensionConsumerContext extensions,
final BGPDispatcher dispatcher, final BindingCodecTreeFactory codecFactory,
- final DataBroker dps, final DOMDataBroker domDataBroker, final List<BgpTableType> localTables,
+ final DOMDataBroker domDataBroker, final List<BgpTableType> localTables,
@Nonnull final Map<TablesKey, PathSelectionMode> bestPathSelectionStrategies, final GeneratedClassLoadingStrategy classStrategy,
final BGPConfigModuleTracker moduleTracker, final BGPOpenConfigProvider openConfigProvider) {
super(InstanceIdentifier.create(BgpRib.class).child(Rib.class, new RibKey(Preconditions.checkNotNull(ribId))));
this.dispatcher = Preconditions.checkNotNull(dispatcher);
this.localTables = ImmutableSet.copyOf(localTables);
this.localTablesKeys = new HashSet<>();
- this.dataBroker = dps;
this.domDataBroker = Preconditions.checkNotNull(domDataBroker);
this.extensions = Preconditions.checkNotNull(extensions);
this.codecsRegistry = CodecsRegistryImpl.create(codecFactory, classStrategy);
this.openConfigProvider = openConfigProvider;
this.cacheDisconnectedPeers = new CacheDisconnectedPeersImpl();
this.bestPathSelectionStrategies = Preconditions.checkNotNull(bestPathSelectionStrategies);
+ final ClusterIdentifier cId = (clusterId == null) ? new ClusterIdentifier(localBgpId) : clusterId;
+ this.renderStats = new RIBImplRuntimeMXBeanImpl(localBgpId, ribId, localAs, cId);
LOG.debug("Instantiating RIB table {} at {}", ribId, this.yangRibId);
} catch (final TransactionCommitFailedException e) {
LOG.error("Failed to initiate RIB {}", this.yangRibId, e);
}
- final ClusterIdentifier cId = (clusterId == null) ? new ClusterIdentifier(localBgpId) : new ClusterIdentifier(clusterId);
final PolicyDatabase policyDatabase = new PolicyDatabase(localAs.getValue(), localBgpId, cId);
this.importPolicyPeerTracker = new ImportPolicyPeerTracker(policyDatabase);
}
}
- public RIBImpl(final RibId ribId, final AsNumber localAs, final BgpId localBgpId, final ClusterIdentifier clusterId, final RIBExtensionConsumerContext extensions,
- final BGPDispatcher dispatcher, final BindingCodecTreeFactory codecFactory,
- final DataBroker dps, final DOMDataBroker domDataBroker, final List<BgpTableType> localTables,
- final Map<TablesKey, PathSelectionMode> bestPathSelectionstrategies, final GeneratedClassLoadingStrategy classStrategy) {
+ public RIBImpl(final RibId ribId, final AsNumber localAs, final BgpId localBgpId, @Nullable final ClusterIdentifier clusterId, final RIBExtensionConsumerContext extensions,
+ final BGPDispatcher dispatcher, final BindingCodecTreeFactory codecFactory,
+ final DOMDataBroker domDataBroker, final List<BgpTableType> localTables,
+ final Map<TablesKey, PathSelectionMode> bestPathSelectionstrategies, final GeneratedClassLoadingStrategy classStrategy) {
this(ribId, localAs, localBgpId, clusterId, extensions, dispatcher, codecFactory,
- dps, domDataBroker, localTables, bestPathSelectionstrategies, classStrategy, null, null);
+ domDataBroker, localTables, bestPathSelectionstrategies, classStrategy, null, null);
+ }
+
+ public synchronized void registerRootRuntimeBean(final RIBImplRuntimeRegistrator registrator) {
+ this.registrator = registrator;
+
+ initStatsRuntimeBean();
+ }
+
+ /**
+ * Register the statistic runtime bean
+ */
+ private void initStatsRuntimeBean() {
+ if (this.registrator != null) {
+ LOG.debug("Initializing Render Status runtime bean..");
+ this.runtimeReg = this.registrator.register(renderStats);
+ }
+ }
+
+ private void stopStatsRuntimeBean() {
+ if (this.runtimeReg != null) {
+ LOG.debug("Destroying Render Status runtime bean..");
+ this.runtimeReg.close();
+ this.runtimeReg = null;
+ }
+ // reset all the stats
+ renderStats.getLocRibRouteCounter().resetAll();
}
private void startLocRib(final TablesKey key, final PolicyDatabase pd) {
if (pathSelectionStrategy == null) {
pathSelectionStrategy = BasePathSelectionModeFactory.createBestPathSelectionStrategy();
}
+
this.locRibs.add(LocRibWriter.create(this.ribContextRegistry, key, createPeerChain(this), getYangRibId(), this.localAs, getService(), pd,
- this.cacheDisconnectedPeers, pathSelectionStrategy));
+ this.cacheDisconnectedPeers, pathSelectionStrategy, this.renderStats.getLocRibRouteCounter().init(key)));
}
@Override
LOG.warn("Could not close LocalRib reference: {}", locRib, e);
}
}
+
+ stopStatsRuntimeBean();
+
if (this.configModuleTracker != null) {
this.configModuleTracker.onInstanceClose();
}
LOG.info("RIB {} closed successfully", getInstanceIdentifier());
}
- @Override
- public long getRoutesCount(final TablesKey key) {
- try (final ReadOnlyTransaction tx = this.dataBroker.newReadOnlyTransaction()) {
- final Optional<Tables> tableMaybe = tx.read(LogicalDatastoreType.OPERATIONAL,
- getInstanceIdentifier().child(LocRib.class).child(Tables.class, key)).checkedGet();
- if (tableMaybe.isPresent()) {
- final Tables table = tableMaybe.get();
- return countIpRoutes(table.getRoutes());
- }
- } catch (final ReadFailedException e) {
- LOG.debug("Failed to read tables", e);
- }
- return 0;
- }
-
- private int countIpRoutes(final Routes routes) {
- if (routes instanceof Ipv4RoutesCase) {
- final Ipv4RoutesCase routesCase = (Ipv4RoutesCase) routes;
- if (routesCase.getIpv4Routes() != null && routesCase.getIpv4Routes().getIpv4Route() != null) {
- return routesCase.getIpv4Routes().getIpv4Route().size();
- }
- } else if (routes instanceof Ipv6RoutesCase) {
- final Ipv6RoutesCase routesCase = (Ipv6RoutesCase) routes;
- if (routesCase.getIpv6Routes() != null && routesCase.getIpv6Routes().getIpv6Route() != null) {
- return routesCase.getIpv6Routes().getIpv6Route().size();
- }
- }
- return 0;
- }
-
public Set<TablesKey> getLocalTablesKeys() {
return this.localTablesKeys;
}
return (DOMDataTreeChangeService) this.service;
}
+ @Override
+ public BGPRenderStats getRenderStats() {
+ return this.renderStats;
+ }
+
@Override
public YangInstanceIdentifier getYangRibId() {
return this.yangRibId;
final List<BgpParameters> params) {
this.as = as;
this.hold = hold;
- this.bgpId = bgpId;
+ this.bgpId = (bgpId != null) ? new BgpId(bgpId) : null;
this.remoteAs = remoteAs;
this.params = params;
}
import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigProvider;
import org.opendaylight.protocol.bgp.rib.RibReference;
+import org.opendaylight.protocol.bgp.rib.impl.stats.rib.impl.BGPRenderStats;
import org.opendaylight.protocol.bgp.rib.spi.CacheDisconnectedPeers;
import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
BGPDispatcher getDispatcher();
- long getRoutesCount(TablesKey key);
-
/**
* Allocate a new transaction chain for use with a peer.
*
* @return DOMDataTreeChangeService
*/
DOMDataTreeChangeService getService();
+
+ BGPRenderStats getRenderStats();
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Brocade Communications 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.stats;
+
+import com.google.common.base.Preconditions;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.ZeroBasedCounter32;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Kevin Wang
+ */
+@ThreadSafe
+public class UnsignedInt32Counter {
+ private static final Logger LOG = LoggerFactory.getLogger(UnsignedInt32Counter.class);
+ private static final long MAX_VALUE = 4294967295L;
+
+ private final String counterName;
+ private final AtomicLong count = new AtomicLong();
+
+ public UnsignedInt32Counter(@Nonnull final String counterName) {
+ this.counterName = Preconditions.checkNotNull(counterName);
+ }
+
+ private static long safetyCheck(final long value) {
+ return Math.min(Math.max(0L, value), MAX_VALUE);
+ }
+
+ public long increaseCount(final long change) {
+ final long result;
+ if (change == 0) {
+ result = getCount();
+ } else {
+ Preconditions.checkArgument(change > 0, "Count number %s must be a positive number.", change);
+ result = this.count.addAndGet(change);
+ LOG.debug("Counter [{}] is increased by {}. Current count: {}", this.counterName, change, result);
+ if (result > MAX_VALUE) {
+ LOG.warn("Counter [{}] has exceeded the max allowed value {}. Counter's current value {} is invalid.", this.counterName, MAX_VALUE, result);
+ }
+ }
+ return result;
+ }
+
+ public long increaseCount() {
+ return this.increaseCount(1);
+ }
+
+ public long decreaseCount(final long change) {
+ final long result;
+ if (change == 0) {
+ result = getCount();
+ } else {
+ Preconditions.checkArgument(change > 0, "Count number %s must be a positive number.", change);
+ result = this.count.addAndGet(-change);
+ LOG.debug("Counter [{}] is decreased by {}. Current count: {}", this.counterName, change, result);
+ if (result < 0) {
+ // In most case, we do not want the BGP session get into trouble due to an ERROR in counter
+ // so here we print ERROR log instead of throwing out exception
+ LOG.warn("Counter {} must not be less than 0. Counter's current value {} is invalid.", this.counterName, result);
+ }
+ }
+ return result;
+ }
+
+ public long decreaseCount() {
+ return this.decreaseCount(1);
+ }
+
+ public long getCount() {
+ return this.count.get();
+ }
+
+ public void setCount(final long count) {
+ final long result = getCount();
+ if (count != result) {
+ LOG.debug("Value of counter [{}] changes to {} (previous value is {})", this.counterName, count, result);
+ this.count.set(count);
+ }
+ }
+
+ public void resetCount() {
+ LOG.debug("Value of counter [{}] is reset to 0.", this.counterName);
+ setCount(0L);
+ }
+
+ public ZeroBasedCounter32 getCountAsZeroBasedCounter32() {
+ return new ZeroBasedCounter32(safetyCheck(getCount()));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Brocade Communications 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.stats.peer;
+
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpPeerState;
+import org.opendaylight.protocol.bgp.rib.impl.stats.UnsignedInt32Counter;
+import org.opendaylight.protocol.bgp.rib.impl.stats.peer.route.PerTableTypeRouteCounter;
+
+/**
+ * @author Kevin Wang
+ */
+public interface BGPPeerStats {
+ BgpPeerState getBgpPeerState();
+
+ PerTableTypeRouteCounter getAdjRibInRouteCounters();
+
+ PerTableTypeRouteCounter getAdjRibOutRouteCounters();
+
+ PerTableTypeRouteCounter getEffectiveRibInRouteCounters();
+
+ UnsignedInt32Counter getSessionEstablishedCounter();
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Brocade Communications 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.stats.peer;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpPeerState;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.RouteTable;
+import org.opendaylight.protocol.bgp.rib.impl.stats.UnsignedInt32Counter;
+import org.opendaylight.protocol.bgp.rib.impl.stats.peer.route.PerTableTypeRouteCounter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Kevin Wang
+ */
+public final class BGPPeerStatsImpl implements BGPPeerStats {
+ private static final Logger LOG = LoggerFactory.getLogger(BGPPeerStatsImpl.class);
+
+ private final Set<TablesKey> tablesKeySet;
+ private final PerTableTypeRouteCounter adjRibInRouteCounters;
+ private final PerTableTypeRouteCounter adjRibOutRouteCounters;
+ private final PerTableTypeRouteCounter effectiveRibInRouteCounters;
+ private final UnsignedInt32Counter sessionEstablishedCounter = new UnsignedInt32Counter("SESSION ESTABLISHED");
+ private final String peerName;
+
+ public BGPPeerStatsImpl(@Nonnull final String peerName, @Nonnull final Set<TablesKey> tablesKeySet) {
+ this.peerName = Preconditions.checkNotNull(peerName);
+ this.tablesKeySet = Preconditions.checkNotNull(tablesKeySet);
+ this.adjRibInRouteCounters = new PerTableTypeRouteCounter("["+ this.peerName +"] adj-rib-in route", tablesKeySet);
+ this.adjRibOutRouteCounters = new PerTableTypeRouteCounter("["+ this.peerName +"] adj-rib-out route", tablesKeySet);
+ this.effectiveRibInRouteCounters = new PerTableTypeRouteCounter("["+ this.peerName +"] effective-rib-in route", tablesKeySet);
+ }
+
+ public PerTableTypeRouteCounter getAdjRibInRouteCounters() {
+ return adjRibInRouteCounters;
+ }
+
+ public PerTableTypeRouteCounter getAdjRibOutRouteCounters() {
+ return adjRibOutRouteCounters;
+ }
+
+ public PerTableTypeRouteCounter getEffectiveRibInRouteCounters() {
+ return effectiveRibInRouteCounters;
+ }
+
+ private RouteTable createRouteTable(@Nonnull final TablesKey tablesKey) {
+ Preconditions.checkNotNull(tablesKey);
+ final RouteTable routeTable = new RouteTable();
+ // FIXME: setTableType() is DEPRECATED, use setAfi() and setSafi() instead
+ routeTable.setTableType("afi=" + tablesKey.getAfi().getSimpleName() + ",safi=" + tablesKey.getSafi().getSimpleName());
+
+ final QName afiQName = BindingReflections.findQName(tablesKey.getAfi()).intern();
+ final QName safiQName = BindingReflections.findQName(tablesKey.getSafi()).intern();
+ routeTable.setAfi(new IdentityAttributeRef(afiQName.toString()));
+ routeTable.setSafi(new IdentityAttributeRef(safiQName.toString()));
+ // we want to get default counter in case particular route table is not initialized (e.g. adj-rib-out is not initialized in some cases)
+ routeTable.setAdjRibInRoutesCount(adjRibInRouteCounters.getCounterOrDefault(tablesKey).getCountAsZeroBasedCounter32());
+ routeTable.setAdjRibOutRoutesCount(adjRibOutRouteCounters.getCounterOrDefault(tablesKey).getCountAsZeroBasedCounter32());
+ routeTable.setEffectiveRibInRoutesCount(effectiveRibInRouteCounters.getCounterOrDefault(tablesKey).getCountAsZeroBasedCounter32());
+
+ return routeTable;
+ }
+
+ @Override
+ public BgpPeerState getBgpPeerState() {
+ final BgpPeerState peerState = new BgpPeerState();
+ final List<RouteTable> routes = Lists.newArrayList();
+ this.tablesKeySet.stream().forEach(tablesKey -> routes.add(createRouteTable(tablesKey)));
+ peerState.setRouteTable(routes);
+ peerState.setSessionEstablishedCount(this.sessionEstablishedCounter.getCountAsZeroBasedCounter32());
+ return peerState;
+ }
+
+ @Override
+ public UnsignedInt32Counter getSessionEstablishedCounter() {
+ return this.sessionEstablishedCounter;
+ }
+}
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.protocol.bgp.rib.impl.spi;
+package org.opendaylight.protocol.bgp.rib.impl.stats.peer;
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 {
+public interface BGPSessionStats {
/**
* Retrieves actual BGP session state. Containing all information collected from the session.
/**
* Resets BGP session statistics. Sets counters values to zero.
*/
- void resetSessionStats();
+ void resetBgpSessionStats();
}
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.protocol.bgp.rib.impl;
+package org.opendaylight.protocol.bgp.rib.impl.stats.peer;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
import org.opendaylight.controller.config.api.IdentityAttributeRef;
import org.opendaylight.controller.config.yang.bgp.rib.impl.AdvertisedAddPathTableTypes;
import org.opendaylight.controller.config.yang.bgp.rib.impl.AdvertizedTableTypes;
import org.opendaylight.controller.config.yang.bgp.rib.impl.Sent;
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.BGPSessionImpl;
import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
import org.opendaylight.protocol.util.StatisticsUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Timestamp;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.ZeroBasedCounter32;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Keepalive;
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.Update;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParameters;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilities;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParameters;
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.CParameters1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.RouteRefresh;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.MultiprotocolCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.add.path.capability.AddressFamilies;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpId;
+import org.opendaylight.yangtools.yang.binding.Notification;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class BGPSessionStatsImpl implements BGPSessionStats {
+ private static final Logger LOG = LoggerFactory.getLogger(BGPSessionStatsImpl.class);
-public final class BGPSessionStats {
private final Stopwatch sessionStopwatch;
private final BgpSessionState stats;
+ private final BGPSessionImpl session;
private final TotalMsgs totalMsgs = new TotalMsgs();
private final KeepAliveMsgs kaMsgs = new KeepAliveMsgs();
private final UpdateMsgs updMsgs = new UpdateMsgs();
private final ErrorSentTotal errMsgsSentTotal = new ErrorSentTotal();
private final ErrorReceivedTotal errMsgsRecvTotal = new ErrorReceivedTotal();
- public BGPSessionStats(final Open remoteOpen, final int holdTimerValue, final int keepAlive, final Channel channel,
- final Optional<BGPSessionPreferences> localPreferences, final Collection<BgpTableType> tableTypes, final List<AddressFamilies> addPathTypes) {
+ public BGPSessionStatsImpl(@Nonnull final BGPSessionImpl session, @Nonnull final Open remoteOpen, final int holdTimerValue, final int keepAlive, @Nonnull final Channel channel,
+ @Nonnull final Optional<BGPSessionPreferences> localPreferences, @Nonnull final Collection<BgpTableType> tableTypes, @Nonnull final List<AddressFamilies> addPathTypes) {
+ this.session = session;
this.sessionStopwatch = Stopwatch.createUnstarted();
this.stats = new BgpSessionState();
this.stats.setHoldtimeCurrent(holdTimerValue);
initMsgs();
}
- private void initMsgs() {
- this.totalMsgs.setReceived(newReceivedInstance());
- this.totalMsgs.setSent(newSentInstance());
- this.kaMsgs.setReceived(newReceivedInstance());
- this.kaMsgs.setSent(newSentInstance());
- this.updMsgs.setReceived(newReceivedInstance());
- this.updMsgs.setSent(newSentInstance());
- this.rrMsgs.setReceived(newReceivedInstance());
- this.rrMsgs.setSent(newSentInstance());
- this.errMsgsSentTotal.setCount(new ZeroBasedCounter32(0L));
- this.errMsgsRecvTotal.setCount(new ZeroBasedCounter32(0L));
- this.errMsgs.getErrorSent().clear();
- this.errMsgs.getErrorReceived().clear();
- }
-
- 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 updateSentMsgRR() {
- updateSentMsg(this.rrMsgs.getSent());
- }
-
- public void updateReceivedMsgRR() {
- updateReceivedMsg(this.rrMsgs.getReceived());
- }
-
- public void updateReceivedMsgErr(final Notify error) {
- Preconditions.checkNotNull(error);
- final List<ErrorReceived> errList = this.errMsgs.getErrorReceived();
- ErrorReceived received = null;
- for (ErrorReceived err : errList) {
- if (err.getErrorCode().equals(error.getErrorCode()) && err.getErrorSubcode().equals(error.getErrorSubcode())) {
- received = err;
- break;
- }
- }
- if (null == received) {
- received = new ErrorReceived();
- received.setErrorCode(error.getErrorCode());
- received.setErrorSubcode(error.getErrorSubcode());
- received.setCount(new ZeroBasedCounter32(0L));
- errList.add(received);
- }
- received.setCount(new ZeroBasedCounter32(received.getCount().getValue() + 1));
- final Timestamp curTimestamp = new Timestamp(StatisticsUtil.getCurrentTimestampInSeconds());
- received.setTimestamp(curTimestamp);
- this.errMsgsRecvTotal.setCount(new ZeroBasedCounter32(this.errMsgsRecvTotal.getCount().getValue() + 1));
- this.errMsgsRecvTotal.setTimestamp(curTimestamp);
- }
-
- public void updateSentMsgErr(final Notify error) {
- Preconditions.checkNotNull(error);
- final List<ErrorSent> errList = this.errMsgs.getErrorSent();
- ErrorSent sent = null;
- for (ErrorSent err : errList) {
- if (err.getErrorCode().equals(error.getErrorCode()) && err.getErrorSubcode().equals(error.getErrorSubcode())) {
- sent = err;
- break;
- }
- }
- if (null == sent) {
- sent = new ErrorSent();
- sent.setErrorCode(error.getErrorCode());
- sent.setErrorSubcode(error.getErrorSubcode());
- sent.setCount(new ZeroBasedCounter32(0L));
- errList.add(sent);
- }
- sent.setCount(new ZeroBasedCounter32(sent.getCount().getValue() + 1));
- final Timestamp curTimestamp = new Timestamp(StatisticsUtil.getCurrentTimestampInSeconds());
- sent.setTimestamp(curTimestamp);
- this.errMsgsSentTotal.setCount(new ZeroBasedCounter32(this.errMsgsSentTotal.getCount().getValue() + 1));
- this.errMsgsSentTotal.setTimestamp(curTimestamp);
- }
-
- 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);
- msgs.setRouteRefreshMsgs(this.rrMsgs);
- 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 Received newReceivedInstance() {
final Received recv = new Received();
recv.setCount(new ZeroBasedCounter32(0L));
private static AdvertizedTableTypes addTableType(final BgpTableType type) {
Preconditions.checkNotNull(type);
final AdvertizedTableTypes att = new AdvertizedTableTypes();
- att.setAfi(new IdentityAttributeRef(BindingReflections.findQName(type.getAfi()).intern().toString()));
- att.setSafi(new IdentityAttributeRef(BindingReflections.findQName(type.getSafi()).intern().toString()));
+ final QName afi = BindingReflections.findQName(type.getAfi()).intern();
+ final QName safi = BindingReflections.findQName(type.getSafi()).intern();
+ att.setAfi(new IdentityAttributeRef(afi.toString()));
+ att.setSafi(new IdentityAttributeRef(safi.toString()));
return att;
}
pref.setHost(IpAddressBuilder.getDefaultInstance(isa.getAddress().getHostAddress()));
pref.setPort(new PortNumber(isa.getPort()));
final List<AdvertizedTableTypes> tt = new ArrayList<>();
+ final List<AdvertisedAddPathTableTypes> attList = new ArrayList<>();
if (localPreferences.isPresent()) {
final BGPSessionPreferences localPref = localPreferences.get();
- pref.setBgpId(new BgpId(localPref.getBgpId().getValue()));
+ pref.setBgpId(localPref.getBgpId());
pref.setAs(localPref.getMyAs());
pref.setHoldtimer(localPref.getHoldTime());
if (localPref.getParams() != null) {
if (mc != null) {
final AdvertizedTableTypes att = new AdvertizedTableTypes();
att.setAfi(new IdentityAttributeRef(BindingReflections.findQName(mc.getAfi()).intern().toString()));
- att.setAfi(new IdentityAttributeRef(BindingReflections.findQName(mc.getSafi()).intern().toString()));
+ att.setSafi(new IdentityAttributeRef(BindingReflections.findQName(mc.getSafi()).intern().toString()));
tt.add(att);
}
if (capabilities.getGracefulRestartCapability() != null) {
pref.setGrCapability(true);
}
- // FIXME add path capability is deprecated
if (capabilities.getAddPathCapability() != null) {
+ // FIXME: add path capability is deprecated, replaced by addPathTableTypes
pref.setAddPathCapability(true);
+
+ final List<AdvertisedAddPathTableTypes> addPathTableTypeList = capabilities.getAddPathCapability()
+ .getAddressFamilies()
+ .stream()
+ .map(BGPSessionStatsImpl::addAddPathTableType)
+ .collect(Collectors.toList());
+ attList.addAll(addPathTableTypeList);
}
if (capabilities.getRouteRefreshCapability() != null) {
pref.setRouteRefreshCapability(true);
}
}
pref.setAdvertizedTableTypes(tt);
+ pref.setAdvertisedAddPathTableTypes(attList);
return pref;
}
pref.setAs(new AsNumber(remoteOpen.getMyAsNumber().longValue()));
pref.setHoldtimer(remoteOpen.getHoldTimer());
- final List<AdvertizedTableTypes> tt = tableTypes.stream().map(BGPSessionStats::addTableType).collect(Collectors.toList());
- final List<AdvertisedAddPathTableTypes> addPathTableTypeList = addPathTypes.stream().map(BGPSessionStats::addAddPathTableType)
+ final List<AdvertizedTableTypes> tt = tableTypes.stream().map(BGPSessionStatsImpl::addTableType).collect(Collectors.toList());
+ final List<AdvertisedAddPathTableTypes> addPathTableTypeList = addPathTypes.stream().map(BGPSessionStatsImpl::addAddPathTableType)
.collect(Collectors.toList());
if (remoteOpen.getBgpParameters() != null) {
if (capabilities.getGracefulRestartCapability() != null) {
pref.setGrCapability(true);
}
- // FIXME add path capability is deprecated
+ // FIXME: add-path-capability is deprecated in Boron
if (capabilities.getAddPathCapability() != null) {
pref.setAddPathCapability(true);
}
pref.setAdvertisedAddPathTableTypes(addPathTableTypeList);
return pref;
}
+
+ private void initMsgs() {
+ this.totalMsgs.setReceived(newReceivedInstance());
+ this.totalMsgs.setSent(newSentInstance());
+ this.kaMsgs.setReceived(newReceivedInstance());
+ this.kaMsgs.setSent(newSentInstance());
+ this.updMsgs.setReceived(newReceivedInstance());
+ this.updMsgs.setSent(newSentInstance());
+ this.rrMsgs.setReceived(newReceivedInstance());
+ this.rrMsgs.setSent(newSentInstance());
+ this.errMsgsSentTotal.setCount(new ZeroBasedCounter32(0L));
+ this.errMsgsRecvTotal.setCount(new ZeroBasedCounter32(0L));
+ this.errMsgs.getErrorSent().clear();
+ this.errMsgs.getErrorReceived().clear();
+ }
+
+ public void startSessionStopwatch() {
+ this.sessionStopwatch.start();
+ }
+
+ private void updateSentMsgTotal() {
+ updateSentMsg(this.totalMsgs.getSent());
+ }
+
+ private void updateReceivedMsgTotal() {
+ updateReceivedMsg(this.totalMsgs.getReceived());
+ }
+
+ private void updateReceivedMsgKA() {
+ updateReceivedMsg(this.kaMsgs.getReceived());
+ }
+
+ public void updateSentMsgKA() {
+ updateSentMsg(this.kaMsgs.getSent());
+ }
+
+ private void updateSentMsgUpd() {
+ updateSentMsg(this.updMsgs.getSent());
+ }
+
+ private void updateReceivedMsgUpd() {
+ updateReceivedMsg(this.updMsgs.getReceived());
+ }
+
+ private void updateSentMsgRR() {
+ updateSentMsg(this.rrMsgs.getSent());
+ }
+
+ private void updateReceivedMsgRR() {
+ updateReceivedMsg(this.rrMsgs.getReceived());
+ }
+
+ private void updateReceivedMsgErr(@Nonnull final Notify error) {
+ Preconditions.checkNotNull(error);
+ final List<ErrorReceived> errList = this.errMsgs.getErrorReceived();
+ ErrorReceived received = null;
+ for (ErrorReceived err : errList) {
+ if (err.getErrorCode().equals(error.getErrorCode()) && err.getErrorSubcode().equals(error.getErrorSubcode())) {
+ received = err;
+ break;
+ }
+ }
+ if (null == received) {
+ received = new ErrorReceived();
+ received.setErrorCode(error.getErrorCode());
+ received.setErrorSubcode(error.getErrorSubcode());
+ received.setCount(new ZeroBasedCounter32(0L));
+ errList.add(received);
+ }
+ received.setCount(new ZeroBasedCounter32(received.getCount().getValue() + 1));
+ final Timestamp curTimestamp = new Timestamp(StatisticsUtil.getCurrentTimestampInSeconds());
+ received.setTimestamp(curTimestamp);
+ this.errMsgsRecvTotal.setCount(new ZeroBasedCounter32(this.errMsgsRecvTotal.getCount().getValue() + 1));
+ this.errMsgsRecvTotal.setTimestamp(curTimestamp);
+ }
+
+ private void updateSentMsgErr(@Nonnull final Notify error) {
+ Preconditions.checkNotNull(error);
+ final List<ErrorSent> errList = this.errMsgs.getErrorSent();
+ ErrorSent sent = null;
+ for (ErrorSent err : errList) {
+ if (err.getErrorCode().equals(error.getErrorCode()) && err.getErrorSubcode().equals(error.getErrorSubcode())) {
+ sent = err;
+ break;
+ }
+ }
+ if (null == sent) {
+ sent = new ErrorSent();
+ sent.setErrorCode(error.getErrorCode());
+ sent.setErrorSubcode(error.getErrorSubcode());
+ sent.setCount(new ZeroBasedCounter32(0L));
+ errList.add(sent);
+ }
+ sent.setCount(new ZeroBasedCounter32(sent.getCount().getValue() + 1));
+ final Timestamp curTimestamp = new Timestamp(StatisticsUtil.getCurrentTimestampInSeconds());
+ sent.setTimestamp(curTimestamp);
+ this.errMsgsSentTotal.setCount(new ZeroBasedCounter32(this.errMsgsSentTotal.getCount().getValue() + 1));
+ this.errMsgsSentTotal.setTimestamp(curTimestamp);
+ }
+
+ @Override
+ public BgpSessionState getBgpSessionState() {
+ final MessagesStats msgs = new MessagesStats();
+ msgs.setTotalMsgs(this.totalMsgs);
+ msgs.setErrorMsgs(this.errMsgs);
+ msgs.setKeepAliveMsgs(this.kaMsgs);
+ msgs.setUpdateMsgs(this.updMsgs);
+ msgs.setRouteRefreshMsgs(this.rrMsgs);
+ this.stats.setSessionDuration(StatisticsUtil.formatElapsedTime(this.sessionStopwatch.elapsed(TimeUnit.SECONDS)));
+ this.stats.setSessionState(this.session.getState().toString());
+ this.stats.setMessagesStats(msgs);
+ return this.stats;
+ }
+
+ @Override
+ public void resetBgpSessionStats() {
+ initMsgs();
+ }
+
+ public void updateReceivedMsg(Notification msg) {
+ LOG.trace("Updating received BGP session message count..");
+ this.updateReceivedMsgTotal();
+ if (msg instanceof Notify) {
+ this.updateReceivedMsgErr((Notify) msg);
+ } else if (msg instanceof Keepalive) {
+ this.updateReceivedMsgKA();
+ } else if (msg instanceof RouteRefresh) {
+ this.updateReceivedMsgRR();
+ } else if (msg instanceof Update) {
+ this.updateReceivedMsgUpd();
+ }
+ }
+
+ public void updateSentMsg(Notification msg) {
+ LOG.trace("Updating sent BGP session message count..");
+ this.updateSentMsgTotal();
+ if (msg instanceof Update) {
+ this.updateSentMsgUpd();
+ } else if (msg instanceof Notify) {
+ this.updateSentMsgErr((Notify) msg);
+ } else if (msg instanceof RouteRefresh) {
+ this.updateSentMsgRR();
+ }
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Brocade Communications 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.stats.peer.route;
+
+import com.google.common.base.Preconditions;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.annotation.Nonnull;
+import org.opendaylight.protocol.bgp.rib.impl.stats.UnsignedInt32Counter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Kevin Wang
+ */
+public final class PerTableTypeRouteCounter {
+ private static final Logger LOG = LoggerFactory.getLogger(PerTableTypeRouteCounter.class);
+
+ private final Map<TablesKey, UnsignedInt32Counter> counters = new ConcurrentHashMap<>();
+ private final String counterName;
+
+ private final UnsignedInt32Counter createCounter(@Nonnull final TablesKey tablesKey) {
+ return new UnsignedInt32Counter(this.counterName + tablesKey.toString());
+ }
+
+ public PerTableTypeRouteCounter(@Nonnull final String counterName) {
+ this.counterName = Preconditions.checkNotNull(counterName);
+ }
+
+ public PerTableTypeRouteCounter(@Nonnull final String counterName, @Nonnull final Set<TablesKey> tablesKeySet) {
+ this(counterName);
+ init(tablesKeySet);
+ }
+
+ public final synchronized void init(@Nonnull Set<TablesKey> tablesKeySet) {
+ tablesKeySet.stream().forEach(tablesKey -> init(tablesKey));
+ }
+
+ public final synchronized UnsignedInt32Counter init(@Nonnull final TablesKey tablesKey) {
+ UnsignedInt32Counter counter = this.counters.get(Preconditions.checkNotNull(tablesKey));
+ if (counter == null) {
+ this.counters.put(tablesKey, counter = createCounter(tablesKey));
+ }
+ LOG.debug("Initializing route counter for tablesKey {}", tablesKey);
+ counter.resetCount();
+ return counter;
+ }
+
+ /**
+ * Get the counter for given tablesKey. Return an empty counter if it doesn't exist
+ * NOTE: the created empty counter won't be put into the original map
+ * @param tablesKey
+ * @return
+ */
+ @Nonnull public final UnsignedInt32Counter getCounterOrDefault(@Nonnull final TablesKey tablesKey) {
+ return this.counters.getOrDefault(Preconditions.checkNotNull(tablesKey), createCounter(tablesKey));
+ }
+
+ /**
+ * Get the counter with given tablesKey
+ * @param tablesKey
+ * @return
+ */
+ public final UnsignedInt32Counter getCounter(@Nonnull final TablesKey tablesKey) {
+ return this.counters.get(Preconditions.checkNotNull(tablesKey));
+ }
+
+ /**
+ * Get the counter with given tablesKey. Create an empty counter if it doesn't exist
+ * This method will put the created empty counter back to map
+ * @param tablesKey
+ * @return
+ */
+ public final UnsignedInt32Counter getCounterOrSetDefault(@Nonnull final TablesKey tablesKey) {
+ if (!this.counters.containsKey(tablesKey)) {
+ return init(tablesKey);
+ } else {
+ return this.counters.get(Preconditions.checkNotNull(tablesKey));
+ }
+ }
+
+ public final Map<TablesKey, UnsignedInt32Counter> getCounters() {
+ return this.counters;
+ }
+
+ public final void resetAll() {
+ LOG.debug("Resetting all route counters..");
+ this.counters.values().stream().forEach(v -> v.resetCount());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Brocade Communications 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.stats.rib.impl;
+
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpRenderState;
+import org.opendaylight.protocol.bgp.rib.impl.stats.UnsignedInt32Counter;
+import org.opendaylight.protocol.bgp.rib.impl.stats.peer.route.PerTableTypeRouteCounter;
+
+/**
+ * @author Kevin Wang
+ */
+public interface BGPRenderStats {
+ BgpRenderState getBgpRenderState();
+
+ PerTableTypeRouteCounter getLocRibRouteCounter();
+
+ UnsignedInt32Counter getConfiguredPeerCounter();
+
+ UnsignedInt32Counter getConnectedPeerCounter();
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Brocade Communications 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.stats.rib.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpRenderState;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.LocRibRouteTable;
+import org.opendaylight.protocol.bgp.rib.impl.stats.UnsignedInt32Counter;
+import org.opendaylight.protocol.bgp.rib.impl.stats.peer.route.PerTableTypeRouteCounter;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.ZeroBasedCounter32;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.RibId;
+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.types.rev130919.BgpId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+
+/**
+ * @author Kevin Wang
+ */
+public class BGPRenderStatsImpl implements BGPRenderStats {
+ private final PerTableTypeRouteCounter locRibRouteCounter = new PerTableTypeRouteCounter("loc-rib route");
+ private final BgpId bgpId;
+ private final RibId ribId;
+ private final ClusterIdentifier clusterId;
+ private final AsNumber localAs;
+ private final UnsignedInt32Counter configuredPeerCounter;
+ private final UnsignedInt32Counter connectedPeerCounter;
+
+ public BGPRenderStatsImpl(@Nonnull final BgpId bgpId, @Nonnull final RibId ribId, @Nonnull final AsNumber localAs, @Nullable final ClusterIdentifier clusterId) {
+ this.bgpId = Preconditions.checkNotNull(bgpId);
+ this.ribId = Preconditions.checkNotNull(ribId);
+ this.localAs = localAs;
+ this.clusterId = clusterId;
+ this.configuredPeerCounter = new UnsignedInt32Counter("Configured Peer of BGP-RIB "+ this.ribId.getValue());
+ this.connectedPeerCounter = new UnsignedInt32Counter("Connected Peer of BGP-RIB "+ this.ribId.getValue());
+ }
+
+ @Override
+ public BgpRenderState getBgpRenderState() {
+ final BgpRenderState renderState = new BgpRenderState();
+ renderState.setRibId(this.ribId);
+ renderState.setBgpRibId(this.bgpId);
+ renderState.setClusterId(this.clusterId);
+ renderState.setLocalAs(this.localAs);
+ renderState.setConfiguredPeerCount(this.configuredPeerCounter.getCountAsZeroBasedCounter32());
+ renderState.setConnectedPeerCount(this.connectedPeerCounter.getCountAsZeroBasedCounter32());
+ // fill in the the statistic part
+ final UnsignedInt32Counter totalRouteCount = new UnsignedInt32Counter("Total Loc-Rib Route Count");
+ final List<LocRibRouteTable> locRibRouteTableList = new ArrayList<>();
+ this.locRibRouteCounter.getCounters()
+ .entrySet()
+ .stream()
+ .forEach(e -> {
+ final LocRibRouteTable table = new LocRibRouteTable();
+ final QName afi = BindingReflections.getQName(e.getKey().getAfi()).intern();
+ final QName safi = BindingReflections.getQName(e.getKey().getSafi()).intern();
+ table.setAfi(new IdentityAttributeRef(afi.toString()));
+ table.setSafi(new IdentityAttributeRef(safi.toString()));
+ table.setRoutesCount(e.getValue().getCountAsZeroBasedCounter32());
+
+ locRibRouteTableList.add(table);
+ totalRouteCount.increaseCount(e.getValue().getCount());
+ });
+ renderState.setLocRibRouteTable(locRibRouteTableList);
+ renderState.setLocRibRoutesCount(totalRouteCount.getCountAsZeroBasedCounter32());
+ return renderState;
+ }
+
+ @Override
+ public PerTableTypeRouteCounter getLocRibRouteCounter() {
+ return this.locRibRouteCounter;
+ }
+
+ @Override
+ public UnsignedInt32Counter getConfiguredPeerCounter() {
+ return this.configuredPeerCounter;
+ }
+
+ @Override
+ public UnsignedInt32Counter getConnectedPeerCounter() {
+ return this.connectedPeerCounter;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Brocade Communications 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.stats.rib.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpRenderState;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.RIBImplRuntimeMXBean;
+import org.opendaylight.protocol.bgp.rib.impl.stats.UnsignedInt32Counter;
+import org.opendaylight.protocol.bgp.rib.impl.stats.peer.route.PerTableTypeRouteCounter;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.RibId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
+
+/**
+ * @author Kevin Wang
+ */
+public class RIBImplRuntimeMXBeanImpl implements BGPRenderStats, RIBImplRuntimeMXBean {
+ private final BGPRenderStats renderStats;
+
+ public RIBImplRuntimeMXBeanImpl(@Nonnull final BgpId bgpId, @Nonnull final RibId ribId, @Nonnull final AsNumber localAs, @Nullable final ClusterIdentifier clusterId) {
+ renderStats = new BGPRenderStatsImpl(bgpId, ribId, localAs, clusterId);
+ }
+
+ @Override
+ public BgpRenderState getBgpRenderState() {
+ return this.renderStats.getBgpRenderState();
+ }
+
+ @Override
+ public PerTableTypeRouteCounter getLocRibRouteCounter() {
+ return this.renderStats.getLocRibRouteCounter();
+ }
+
+ @Override
+ public UnsignedInt32Counter getConfiguredPeerCounter() {
+ return this.renderStats.getConfiguredPeerCounter();
+ }
+
+ @Override
+ public UnsignedInt32Counter getConnectedPeerCounter() {
+ return this.renderStats.getConnectedPeerCounter();
+ }
+}
mxBean.setExtensions(createRibExtensionsInstance(transaction));
mxBean.setRibId(ribId);
mxBean.setLocalAs(localAs);
- mxBean.setBgpRibId(bgpId != null ? new BgpId(bgpId) : null);
- mxBean.setClusterId(clusterId != null ? new ClusterIdentifier(clusterId) : null);
+ mxBean.setBgpRibId(bgpId);
+ mxBean.setClusterId(clusterId);
return nameCreated;
}
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
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.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
import org.opendaylight.protocol.bgp.rib.spi.SimpleRIBExtensionProviderContext;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.routes.ipv4.routes.Ipv4Route;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
public class AbstractRIBTestSetup {
private RIBImpl rib;
- private final ClusterIdentifier clusterId = new ClusterIdentifier("128.0.0.1");
- private final BgpId ribId = new BgpId("127.0.0.1");
- static final Class<? extends AddressFamily> AFI = Ipv4AddressFamily.class;
- static final Class<? extends SubsequentAddressFamily> SAFI = UnicastSubsequentAddressFamily.class;
- static final TablesKey KEY = new TablesKey(AFI, SAFI);
+ private static final ClusterIdentifier CLUSTER_ID = new ClusterIdentifier("128.0.0.1");
+ private static final BgpId RIB_ID = new BgpId("127.0.0.1");
+ protected static final Class<? extends AddressFamily> AFI = Ipv4AddressFamily.class;
+ protected static final Class<? extends SubsequentAddressFamily> SAFI = UnicastSubsequentAddressFamily.class;
+ protected static final QName AFI_QNAME = BindingReflections.findQName(AFI).intern();
+ protected static final QName SAFI_QNAME = BindingReflections.findQName(SAFI).intern();
+ protected static final TablesKey KEY = new TablesKey(AFI, SAFI);
private BindingCodecTreeFactory codecFactory;
private RIBActivator a1;
RIBSupport ribSupport;
- static final QName PREFIX_QNAME = QName.create(Ipv4Route.QNAME, "prefix").intern();
+ protected static final QName PREFIX_QNAME = QName.create(Ipv4Route.QNAME, "prefix").intern();
@Mock
private BGPDispatcher dispatcher;
- @Mock
- private DataBroker dps;
-
@Mock
private DOMDataBroker dom;
this.a1 = new RIBActivator();
this.a1.startRIBExtensionProvider(context);
mockedMethods();
- this.rib = new RIBImpl(new RibId("test"), new AsNumber(5L), this.ribId,
- this.clusterId, context , this.dispatcher, this.codecFactory, this.dps, this.dom,
+ this.rib = new RIBImpl(new RibId("test"), new AsNumber(5L), this.RIB_ID,
+ this.CLUSTER_ID, context, this.dispatcher, this.codecFactory, this.dom,
localTables, Collections.singletonMap(new TablesKey(AFI, SAFI), BasePathSelectionModeFactory.createBestPathSelectionStrategy()),
GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy());
this.rib.onGlobalContextUpdated(schemaContext);
final Map<Class<? extends DOMDataBrokerExtension>, DOMDataBrokerExtension> map = new HashMap<>();
map.put(DOMDataTreeChangeService.class, this.service);
Mockito.doNothing().when(readTx).close();
- Mockito.doReturn(readTx).when(this.dps).newReadOnlyTransaction();
final CheckedFuture<Optional<DataObject>, ReadFailedException> readFuture = Mockito.mock(CheckedFuture.class);
Mockito.doNothing().when(this.domTransWrite).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class));
Mockito.doNothing().when(this.domTransWrite).delete(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class));
Mockito.doNothing().when(this.domTransWrite).merge(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class));
Mockito.doReturn(Optional.<DataObject>absent()).when(readFuture).checkedGet();
Mockito.doReturn(readFuture).when(readTx).read(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(InstanceIdentifier.class));
- Mockito.doReturn(this.chain).when(this.dps).createTransactionChain(Mockito.any(RIBImpl.class));
Mockito.doNothing().when(this.domChain).close();
Mockito.doReturn(this.domTransWrite).when(this.domChain).newWriteOnlyTransaction();
Mockito.doNothing().when(getTransaction()).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.eq(YangInstanceIdentifier.of(BgpRib.QNAME)), Mockito.any(NormalizedNode.class));
assertEquals(BGPError.CEASE.getCode(), state.getMessagesStats().getErrorMsgs().getErrorSent().get(0).getErrorCode().shortValue());
assertEquals(BGPError.CEASE.getSubcode(), state.getMessagesStats().getErrorMsgs().getErrorSent().get(0).getErrorSubcode().shortValue());
- this.bgpSession.resetSessionStats();
+ this.bgpSession.resetBgpSessionStats();
assertEquals(0, state.getMessagesStats().getTotalMsgs().getReceived().getCount().getValue().longValue());
assertEquals(0, state.getMessagesStats().getTotalMsgs().getSent().getCount().getValue().longValue());
assertEquals(0, state.getMessagesStats().getErrorMsgs().getErrorSentTotal().getCount().getValue().longValue());
import org.opendaylight.protocol.bgp.mode.impl.base.BasePathSelectionModeFactory;
import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContext;
import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
+import org.opendaylight.protocol.bgp.rib.impl.stats.UnsignedInt32Counter;
import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
private final List<YangInstanceIdentifier> routes = new ArrayList<>();
private final TablesKey tablesKey = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
+ private final UnsignedInt32Counter routeCounter = new UnsignedInt32Counter("loc-rib");
@Before
public void setUp() throws Exception {
doReturn(this.future).when(this.domTransWrite).submit();
doReturn(null).when(this.service).registerDataTreeChangeListener(any(DOMDataTreeIdentifier.class), any(DOMDataTreeChangeListener.class));
this.locRibWriter = LocRibWriter.create(this.registry, this.tablesKey, this.chain, YangInstanceIdentifier.of(BgpRib.QNAME),
- new AsNumber((long) 35), this.service, this.pd, new CacheDisconnectedPeersImpl(), BasePathSelectionModeFactory.createBestPathSelectionStrategy());
+ new AsNumber((long) 35), this.service, this.pd, new CacheDisconnectedPeersImpl(), BasePathSelectionModeFactory.createBestPathSelectionStrategy(),
+ routeCounter);
}
private DataTreeCandidate prepareUpdate() {
final List<BgpTableType> tables = ImmutableList.of(
(BgpTableType) new BgpTableTypeImpl(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class));
final RIBImpl rib = new RIBImpl(new RibId(TEST_RIB_ID), new AsNumber(72L), new BgpId("127.0.0.1"), null, this.ext2, this.dispatcher,
- this.codecFactory, getDataBroker(), getDomBroker(), tables,
+ this.codecFactory, getDomBroker(), tables,
Collections.singletonMap(new TablesKey(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class),
BasePathSelectionModeFactory.createBestPathSelectionStrategy()), GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy());
assertTablesExists(tables, true);
public void testWithoutLinkstate() throws InterruptedException, ExecutionException {
final List<BgpTableType> tables = ImmutableList.of((BgpTableType) new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class));
final RIBImpl rib = new RIBImpl(new RibId(TEST_RIB_ID), new AsNumber(72L), new BgpId("127.0.0.1"), null, this.ext1, this.dispatcher,
- this.codecFactory, getDataBroker(), getDomBroker(), tables,
+ this.codecFactory, getDomBroker(), tables,
Collections.singletonMap(new TablesKey(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class),
BasePathSelectionModeFactory.createBestPathSelectionStrategy()), GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy());
rib.onGlobalContextUpdated(this.schemaService.getGlobalContext());
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.RouteTable;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
import org.opendaylight.protocol.bgp.parser.BGPError;
this.mockSession();
assertEquals("testPeer", this.classic.getName());
this.classic.onSessionUp(this.session);
+ assertEquals(1, this.classic.getBgpPeerState().getSessionEstablishedCount().getValue().intValue());
Assert.assertArrayEquals(new byte[] {1, 1, 1, 1}, this.classic.getRawIdentifier());
assertEquals("BGPPeer{name=testPeer, tables=[TablesKey [_afi=class org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily, _safi=class org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily]]}", this.classic.toString());
testingPeer.onSessionUp(this.session);
assertEquals(3, this.routes.size());
assertEquals(1, testingPeer.getBgpPeerState().getSessionEstablishedCount().getValue().intValue());
- assertEquals(1, testingPeer.getBgpPeerState().getRouteTable().size());
+ final List<RouteTable> routeTables = testingPeer.getBgpPeerState().getRouteTable();
+ assertEquals(1, routeTables.size());
+ final RouteTable routeTable = routeTables.get(0);
+ assertEquals(AFI_QNAME.toString(), routeTable.getAfi().getqNameOfIdentity());
+ assertEquals(SAFI_QNAME.toString(), routeTable.getSafi().getqNameOfIdentity());
assertNotNull(testingPeer.getBgpSessionState());
}
return this.routesListIdentifier;
}
+ @Nonnull
+ @Override
public final Class<? extends AddressFamily> getAfi() {
return afiClass;
}
+ @Nonnull
+ @Override
public final Class<? extends SubsequentAddressFamily> getSafi() {
return safiClass;
}
final AttributesBuilder ab = new AttributesBuilder(attr);
final CNextHop hop = ab.getCNextHop();
+ LOG.debug("cnextHop before={}", hop);
// do not preserve next hop in attributes if we are using MpReach
ab.setCNextHop(null);
if (!advertised.isEmpty()) {
final MpReachNlri mb = buildReach(advertised, hop);
ab.addAugmentation(Attributes1.class, new Attributes1Builder().setMpReachNlri(mb).build());
+ LOG.debug("mpreach nexthop={}", mb);
}
if (!withdrawn.isEmpty()) {
final MpUnreachNlri mb = buildUnreach(withdrawn);
ab.addAugmentation(Attributes2.class, new Attributes2Builder().setMpUnreachNlri(mb).build());
+ LOG.debug("mpunrach mb={}", mb);
}
ub.setAttributes(ab.build());
+ LOG.debug("update {}", ub.build());
return ub.build();
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Routes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
*/
@Nonnull Update buildUpdate(@Nonnull Collection<MapEntryNode> advertised, @Nonnull Collection<MapEntryNode> withdrawn, @Nonnull Attributes attr);
+ @Nonnull Class<? extends AddressFamily> getAfi();
+
+ @Nonnull Class<? extends SubsequentAddressFamily> getSafi();
interface ApplyRoute {
void apply(DOMDataWriteTransaction tx, YangInstanceIdentifier base, NodeIdentifierWithPredicates routeKey, DataContainerNode<?> route,