BUG-5876 Enhance BGP Speaker and Peer Stats II 96/40396/15
authorKevin Wang <kevixw@gmail.com>
Fri, 27 May 2016 23:30:20 +0000 (16:30 -0700)
committerMilos Fabian <milfabia@cisco.com>
Sat, 16 Jul 2016 07:14:49 +0000 (07:14 +0000)
- Refactor BGPPeer to seperate stats code
- Implement route counter

Change-Id: Ia9aa6d7f06b96efa0dcf00fb319f0473e6c2775e
Signed-off-by: Kevin Wang <kevixw@gmail.com>
28 files changed:
bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPApplicationPeerModule.java
bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/RIBImplModule.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibOutListener.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/EffectiveRibInWriter.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriter.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPSessionPreferences.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/RIB.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/UnsignedInt32Counter.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/peer/BGPPeerStats.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/peer/BGPPeerStatsImpl.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/peer/BGPSessionStats.java [moved from bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPSessionStatistics.java with 86% similarity]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/peer/BGPSessionStatsImpl.java [moved from bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionStats.java with 79% similarity]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/peer/route/PerTableTypeRouteCounter.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/rib/impl/BGPRenderStats.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/rib/impl/BGPRenderStatsImpl.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/rib/impl/RIBImplRuntimeMXBeanImpl.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/controller/config/yang/bgp/rib/impl/AbstractRIBImplModuleTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AbstractRIBTestSetup.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionImplTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriterTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ParserToSalTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AbstractRIBSupport.java
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/RIBSupport.java

index cb5948fedd6433a1ad6fd4384701f43359298119..8430e15eea7bae6298d3d4994a9b8d253e871931 100755 (executable)
@@ -8,6 +8,7 @@
 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;
@@ -32,8 +33,6 @@ import org.opendaylight.yangtools.concepts.ListenerRegistration;
 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
  */
index f0c2d067a6141ca1c94e8ff64b839805a41d32b6..14ca638db41efbaf8320728e5d3b37117b74c2d5 100755 (executable)
@@ -69,9 +69,11 @@ public final class RIBImplModule extends org.opendaylight.controller.config.yang
     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;
     }
 
index f910598bd9866fd08a435b488889e477dc532867..4bea1975a096fa4790605173ea887fce228d9159 100644 (file)
@@ -20,6 +20,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
 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;
@@ -63,20 +64,25 @@ final class AdjRibOutListener implements DOMDataTreeChangeListener {
     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
@@ -131,6 +137,7 @@ final class AdjRibOutListener implements DOMDataTreeChangeListener {
     }
 
     private Update withdraw(final MapEntryNode route) {
+        this.routeCounter.decreaseCount();
         if (!this.mpSupport) {
             return buildUpdate(Collections.<MapEntryNode>emptyList(), Collections.singleton(route), routeAttributes(route));
         }
@@ -138,6 +145,7 @@ final class AdjRibOutListener implements DOMDataTreeChangeListener {
     }
 
     private Update advertise(final MapEntryNode route) {
+        this.routeCounter.increaseCount();
         if (!this.mpSupport) {
             return buildUpdate(Collections.singleton(route), Collections.<MapEntryNode>emptyList(), routeAttributes(route));
         }
index e9bc25e3edeaeb0ddef871821c492ee80ef09a32..3f4ea3e144df53d242c48c1d292ff1352fc7180d 100644 (file)
@@ -75,6 +75,7 @@ public class ApplicationPeer implements AutoCloseable, org.opendaylight.protocol
         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);
index 062425f3457baec8d7fb6395f8b20abee676fd0f..e3ea6fb98e34d174bef3b38b21922cf5a838a24f 100644 (file)
@@ -12,7 +12,6 @@ import static org.opendaylight.protocol.bgp.rib.impl.AdjRibInWriter.isLearnNone;
 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;
@@ -24,13 +23,11 @@ import java.util.Optional;
 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;
@@ -41,9 +38,11 @@ import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
 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;
@@ -51,7 +50,6 @@ import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
 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;
@@ -80,8 +78,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.type
 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;
@@ -111,12 +107,12 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
     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;
@@ -126,6 +122,10 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
         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) {
@@ -292,10 +292,12 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
         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);
         }
@@ -306,6 +308,8 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
                 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) {
@@ -326,7 +330,7 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
         // 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)));
         }
     }
 
@@ -404,6 +408,8 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
                 LOG.warn("Error closing session with peer", e);
             }
             this.session = null;
+
+            this.rib.getRenderStats().getConnectedPeerCounter().decreaseCount();
         }
     }
 
@@ -424,8 +430,8 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
 
     @Override
     public void resetStats() {
-        if (this.session instanceof BGPSessionStatistics) {
-            ((BGPSessionStatistics) this.session).resetSessionStats();
+        if (this.session instanceof BGPSessionStats) {
+            ((BGPSessionStats) this.session).resetBgpSessionStats();
         }
     }
 
@@ -435,29 +441,15 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
 
     @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
index 1bd5a3a2b7ffa6cbc24326f6df57fdace5a7bdde..3abc1ab406e86204d083d4bdc3d790c83ddb9569 100644 (file)
@@ -14,6 +14,7 @@ import com.google.common.base.Optional;
 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;
@@ -37,7 +38,8 @@ import org.opendaylight.protocol.bgp.parser.spi.MultiPathSupport;
 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;
@@ -64,7 +66,7 @@ import org.slf4j.Logger;
 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);
 
@@ -127,12 +129,12 @@ public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> im
     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,
@@ -202,7 +204,7 @@ public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> im
             }, 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);
     }
 
@@ -222,37 +224,35 @@ public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> im
     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() {
@@ -276,12 +276,7 @@ public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> im
                 }
             });
         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;
     }
 
@@ -452,12 +447,12 @@ public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> im
 
     @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() {
index 6d926c0f064a6096f8ed35fd0d2ce6edd546b888..6d5a209dfc84a295687eae5c9acdfa489027f14d 100644 (file)
@@ -11,6 +11,10 @@ import com.google.common.base.Optional;
 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;
@@ -21,12 +25,14 @@ import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 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;
@@ -65,25 +71,79 @@ final class EffectiveRibInWriter implements AutoCloseable {
         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
@@ -92,6 +152,9 @@ final class EffectiveRibInWriter implements AutoCloseable {
             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;
@@ -106,9 +169,13 @@ final class EffectiveRibInWriter implements AutoCloseable {
 
                 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:
@@ -118,17 +185,21 @@ final class EffectiveRibInWriter implements AutoCloseable {
         }
 
         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
@@ -227,14 +298,19 @@ final class EffectiveRibInWriter implements AutoCloseable {
             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);
@@ -261,11 +337,19 @@ final class EffectiveRibInWriter implements AutoCloseable {
     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);
@@ -273,6 +357,14 @@ final class EffectiveRibInWriter implements AutoCloseable {
         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();
index 5f20add75a02988a5b21efc6e1c29278da2f3f73..827cd832e95940577b2bdf65122a2ed0a3efeaec 100644 (file)
@@ -27,6 +27,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 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;
@@ -85,10 +86,11 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
     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;
@@ -99,6 +101,7 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
         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());
@@ -112,8 +115,8 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
 
     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
@@ -271,6 +274,14 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
             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) {
index 91018671d737942c2cbcbc9d30054c82d3238b7f..b7fdd9f42028e46e35b0a4a0b1bd0a16266c012e 100755 (executable)
@@ -21,12 +21,12 @@ import java.util.Map.Entry;
 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;
@@ -44,13 +44,13 @@ import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
 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;
@@ -96,7 +96,6 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
     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;
@@ -109,10 +108,13 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
     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))));
@@ -122,7 +124,6 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
         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);
@@ -133,6 +134,8 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
         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);
 
@@ -160,7 +163,6 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
         } 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);
 
@@ -179,12 +181,38 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
         }
     }
 
-    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) {
@@ -217,8 +245,9 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
         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
@@ -243,6 +272,9 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
                 LOG.warn("Could not close LocalRib reference: {}", locRib, e);
             }
         }
+
+        stopStatsRuntimeBean();
+
         if (this.configModuleTracker != null) {
             this.configModuleTracker.onInstanceClose();
         }
@@ -278,36 +310,6 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
         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;
     }
@@ -317,6 +319,11 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
         return (DOMDataTreeChangeService) this.service;
     }
 
+    @Override
+    public BGPRenderStats getRenderStats() {
+        return this.renderStats;
+    }
+
     @Override
     public YangInstanceIdentifier getYangRibId() {
         return this.yangRibId;
index 7a9d81643e830a39a6badac615ff177197601ab9..0bfb76a6daae60b0ecd8fcf73963ef462f37778c 100644 (file)
@@ -41,7 +41,7 @@ public final class BGPSessionPreferences {
         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;
     }
index 864636df6e5504fdf1395705512fb990986491bb..d95f347b943d8e4d2a48b851a1627404cc4eab2e 100755 (executable)
@@ -15,6 +15,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
 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;
@@ -42,8 +43,6 @@ public interface RIB  extends RibReference {
 
     BGPDispatcher getDispatcher();
 
-    long getRoutesCount(TablesKey key);
-
     /**
      * Allocate a new transaction chain for use with a peer.
      *
@@ -99,4 +98,6 @@ public interface RIB  extends RibReference {
      * @return DOMDataTreeChangeService
      */
     DOMDataTreeChangeService getService();
+
+    BGPRenderStats getRenderStats();
 }
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/UnsignedInt32Counter.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/UnsignedInt32Counter.java
new file mode 100644 (file)
index 0000000..50fdd88
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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()));
+    }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/peer/BGPPeerStats.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/peer/BGPPeerStats.java
new file mode 100644 (file)
index 0000000..3949441
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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();
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/peer/BGPPeerStatsImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/peer/BGPPeerStatsImpl.java
new file mode 100644 (file)
index 0000000..665bd09
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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;
+    }
+}
similarity index 86%
rename from bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPSessionStatistics.java
rename to bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/peer/BGPSessionStats.java
index 5fc87b66038c454d087fb4aaef84344a5ff1529a..e9e310d8539f89548ffff1bbb68c4c2ed7f3a7de 100644 (file)
@@ -6,14 +6,14 @@
  * 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.
@@ -25,5 +25,5 @@ public interface BGPSessionStatistics {
     /**
      * Resets BGP session statistics. Sets counters values to zero.
      */
-    void resetSessionStats();
+    void resetBgpSessionStats();
 }
similarity index 79%
rename from bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionStats.java
rename to bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/peer/BGPSessionStatsImpl.java
index 8878b56899c652cbb39af2b3f370b4037e7287ba..7175c9e189c83ce5b3829e49273d3d0e79842c26 100644 (file)
@@ -6,7 +6,7 @@
  * 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;
@@ -18,6 +18,7 @@ import java.util.Collection;
 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;
@@ -36,7 +37,7 @@ import org.opendaylight.controller.config.yang.bgp.rib.impl.RouteRefreshMsgs;
 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;
@@ -44,21 +45,31 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 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();
@@ -67,8 +78,9 @@ public final class BGPSessionStats {
     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);
@@ -82,123 +94,6 @@ public final class BGPSessionStats {
         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));
@@ -228,8 +123,10 @@ public final class BGPSessionStats {
     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;
     }
 
@@ -249,9 +146,10 @@ public final class BGPSessionStats {
         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) {
@@ -264,15 +162,22 @@ public final class BGPSessionStats {
                             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);
@@ -289,6 +194,7 @@ public final class BGPSessionStats {
             }
         }
         pref.setAdvertizedTableTypes(tt);
+        pref.setAdvertisedAddPathTableTypes(attList);
         return pref;
     }
 
@@ -304,8 +210,8 @@ public final class BGPSessionStats {
         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) {
@@ -320,7 +226,7 @@ public final class BGPSessionStats {
                         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);
                         }
@@ -339,4 +245,148 @@ public final class BGPSessionStats {
         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();
+        }
+    }
 }
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/peer/route/PerTableTypeRouteCounter.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/peer/route/PerTableTypeRouteCounter.java
new file mode 100644 (file)
index 0000000..acaf267
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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());
+    }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/rib/impl/BGPRenderStats.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/rib/impl/BGPRenderStats.java
new file mode 100644 (file)
index 0000000..aec3889
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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();
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/rib/impl/BGPRenderStatsImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/rib/impl/BGPRenderStatsImpl.java
new file mode 100644 (file)
index 0000000..42cfa69
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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;
+    }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/rib/impl/RIBImplRuntimeMXBeanImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/stats/rib/impl/RIBImplRuntimeMXBeanImpl.java
new file mode 100644 (file)
index 0000000..c6870ce
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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();
+    }
+}
index 88d9f76b17cd37829a8b9bfdd8b17e7e8dd565d9..8863ca047c2b95bd9392487a0edd27662ac26f95 100755 (executable)
@@ -318,8 +318,8 @@ public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
         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;
     }
 
index a73a6dc11d58a3ab99c7abf0bb288e6a80b48bdf..c74b57ac4ea9f5e5ea7e6792559d6a76e8b8b339 100755 (executable)
@@ -25,7 +25,6 @@ import org.mockito.Mock;
 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;
@@ -44,7 +43,6 @@ import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderContext;
 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;
@@ -89,22 +87,21 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 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;
 
@@ -145,8 +142,8 @@ public class AbstractRIBTestSetup {
         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);
@@ -178,14 +175,12 @@ public class AbstractRIBTestSetup {
         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));
index 52229f9a68e1307387317112f338471606277573..607e5e1055f7e0e4705951e47d5c3e5e9d59d687 100644 (file)
@@ -206,7 +206,7 @@ public class BGPSessionImplTest {
         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());
index 8aab078ae6d45d7ed6573a130a817d5b82b243e6..dacd8dd81807742f1b9e4613f1cb090f40c27f25 100644 (file)
@@ -37,6 +37,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 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;
@@ -81,6 +82,7 @@ public class LocRibWriterTest {
 
     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 {
@@ -114,7 +116,8 @@ public class LocRibWriterTest {
         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() {
index 2b28847ac2e0bd66109acd0bb72ac7fe8a537565..75cadeac9e4b6a5a3536b602fc3756fbedfc8350 100755 (executable)
@@ -133,7 +133,7 @@ public class ParserToSalTest extends AbstractDataBrokerTest {
         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);
@@ -148,7 +148,7 @@ public class ParserToSalTest extends AbstractDataBrokerTest {
     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());
index db7a0f4879362d2e34a36d1bae81569c6e7df42c..9e5f9339b77163b2e2f36d89604119d0cef49ae6 100644 (file)
@@ -30,6 +30,8 @@ import org.junit.Test;
 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;
@@ -139,6 +141,7 @@ public class PeerTest extends AbstractRIBTestSetup {
         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());
 
@@ -171,7 +174,11 @@ public class PeerTest extends AbstractRIBTestSetup {
             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());
         }
 
index d82c24e0a7591d16f2531edc24c8d04c1c3b3442..e7708e1311b4f519c4c37b14bc5edc856a345c47 100644 (file)
@@ -141,10 +141,14 @@ public abstract class AbstractRIBSupport implements RIBSupport {
         return this.routesListIdentifier;
     }
 
+    @Nonnull
+    @Override
     public final Class<? extends AddressFamily> getAfi() {
         return afiClass;
     }
 
+    @Nonnull
+    @Override
     public final Class<? extends SubsequentAddressFamily> getSafi() {
         return safiClass;
     }
@@ -316,19 +320,23 @@ public abstract class AbstractRIBSupport implements RIBSupport {
         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();
     }
 
index c47a7bd23175388186eb0e1b271cfc7ce7c2a69c..50b19d084d3f232e84892c994379b7bc47408f11 100644 (file)
@@ -15,6 +15,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 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;
@@ -167,6 +169,9 @@ public interface RIBSupport extends AddPathRibSupport {
      */
     @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,