BUG-5097: Modified CacheDeletedPeers to to be local for each RIB 38/34238/2
authorClaudio D. Gasparini <cgaspari@cisco.com>
Mon, 8 Feb 2016 09:20:06 +0000 (10:20 +0100)
committerClaudio D. Gasparini <cgaspari@cisco.com>
Mon, 8 Feb 2016 13:33:35 +0000 (14:33 +0100)
Modified CacheDeletedPeers to to be local for each RIB

Change-Id: Ie6ec3a74686fbff7f700de97cad919d0f3bc0b9e
Signed-off-by: Claudio D. Gasparini <cgaspari@cisco.com>
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibInWriter.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/CacheDisconnectedPeersImpl.java [new file with mode: 0644]
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/RIBSupportContextImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/CacheDisconnectedPeers.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/RIB.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriterTest.java

index 4491b7d3c5844825470c886fb0fded6bbe12110d..f4f738e118ea98aec8a03323c2c2f50e726d77b3 100644 (file)
@@ -11,7 +11,6 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMap.Builder;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -198,12 +197,6 @@ final class AdjRibInWriter {
     }
 
     private YangInstanceIdentifier createEmptyPeerStructure(final PeerId newPeerId, final boolean isAppPeer, final DOMDataWriteTransaction tx) {
-        if (this.peerId != null) {
-            // Wipe old peer data completely
-            tx.delete(LogicalDatastoreType.OPERATIONAL, this.ribPath.node(Peer.QNAME).node(new NodeIdentifierWithPredicates(Peer.QNAME, PEER_ID_QNAME,
-                this.peerId.getValue())));
-        }
-        // Install new empty peer structure
         final NodeIdentifierWithPredicates peerKey = IdentifierUtils.domPeerId(newPeerId);
         final YangInstanceIdentifier newPeerPath = this.ribPath.node(Peer.QNAME).node(peerKey);
 
@@ -227,22 +220,6 @@ final class AdjRibInWriter {
         return pb.build();
     }
 
-    /**
-     * Clean all routes in specified tables
-     *
-     * @param tableTypes Tables to clean.
-     */
-    void cleanTables(final Collection<TablesKey> tableTypes) {
-        final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
-
-        for (final TablesKey k : tableTypes) {
-            LOG.debug("Clearing table {}", k);
-            this.tables.get(k).clearTable(tx);
-        }
-
-        tx.submit();
-    }
-
     void removePeer() {
         if(this.peerPath != null) {
             final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
index d7cabadc858cb8f1d5835ef9817cf7b183dfe4a6..46cc38a2459e2d6d6915b78e68a5ec09a5540aa6 100644 (file)
@@ -197,7 +197,6 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
         this.session = session;
         this.rawIdentifier = InetAddresses.forString(session.getBgpId().getValue()).getAddress();
         final PeerId peerId = RouterIds.createPeerId(session.getBgpId());
-        ConnectedPeers.getInstance().reconnected(peerId);
         createAdjRibOutListener(peerId);
 
         this.ribWriter = this.ribWriter.transform(peerId, this.rib.getRibSupportContext(), this.tables, false);
@@ -287,7 +286,7 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
 
     private void addPeerToDisconnectedSharedList() {
         if(this.session != null) {
-            ConnectedPeers.getInstance().insertDesconectedPeer(this.session.getBgpId());
+            this.rib.getCacheDisconnectedPeers().insertDisconnectedPeer(this.session.getBgpId());
         }
     }
 
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/CacheDisconnectedPeersImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/CacheDisconnectedPeersImpl.java
new file mode 100644 (file)
index 0000000..548be47
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.protocol.bgp.rib.impl.spi.CacheDisconnectedPeers;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerId;
+
+public final class CacheDisconnectedPeersImpl implements CacheDisconnectedPeers {
+    private static Cache<PeerId, Boolean> cache = CacheBuilder.newBuilder().expireAfterAccess(30, TimeUnit.SECONDS).build();
+
+    CacheDisconnectedPeersImpl() {
+    }
+
+    @Override
+    public boolean isPeerDisconnected(final PeerId peerId) {
+        if (this.cache.getIfPresent(peerId) != null) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void reconnected(final PeerId peerId) {
+        this.cache.asMap().remove(peerId);
+    }
+
+    @Override
+    public void insertDisconnectedPeer(final Ipv4Address peerId) {
+        this.cache.put(RouterIds.createPeerId(peerId), true);
+    }
+}
index abd8d6f81abe5d15cddc775c26f66ae023d52090..f3c9589c234ef69476f455162b9e8e50ce08c072 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
 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.CacheDisconnectedPeers;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
 import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
 import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
@@ -75,9 +76,10 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
     private final TablesKey localTablesKey;
     private final RIBSupportContextRegistry registry;
     private final ListenerRegistration<LocRibWriter> reg;
+    private final CacheDisconnectedPeers cacheDisconnectedPeers;
 
     private LocRibWriter(final RIBSupportContextRegistry registry, final DOMTransactionChain chain, final YangInstanceIdentifier target, final Long ourAs,
-        final DOMDataTreeChangeService service, final PolicyDatabase pd, final TablesKey tablesKey) {
+        final DOMDataTreeChangeService service, final PolicyDatabase pd, final TablesKey tablesKey, final CacheDisconnectedPeers cacheDisconnectedPeers) {
         this.chain = Preconditions.checkNotNull(chain);
         this.tableKey = RibSupportUtils.toYangTablesKey(tablesKey);
         this.localTablesKey = tablesKey;
@@ -87,6 +89,7 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
         this.ribSupport = this.registry.getRIBSupportContext(tablesKey).getRibSupport();
         this.attributesIdentifier = this.ribSupport.routeAttributesIdentifier();
         this.peerPolicyTracker = new ExportPolicyPeerTracker(pd);
+        this.cacheDisconnectedPeers = cacheDisconnectedPeers;
 
         final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
         tx.merge(LogicalDatastoreType.OPERATIONAL, this.locRibTarget.node(Routes.QNAME), this.ribSupport.emptyRoutes());
@@ -99,14 +102,13 @@ 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) {
-        return new LocRibWriter(registry, chain, target, ourAs.getValue(), service, pd, tablesKey);
+        @Nonnull final AsNumber ourAs, @Nonnull final DOMDataTreeChangeService service, @Nonnull final PolicyDatabase pd, final CacheDisconnectedPeers cacheDisconnectedPeers) {
+        return new LocRibWriter(registry, chain, target, ourAs.getValue(), service, pd, tablesKey, cacheDisconnectedPeers);
     }
 
     @Override
     public void close() {
         this.reg.close();
-        // FIXME: wipe the local rib
         // FIXME: wait for the chain to close? unfortunately RIBImpl is the listener, so that may require some work
         this.chain.close();
     }
@@ -218,10 +220,12 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
         return this.ribSupport.routePath(rootPath.node(AdjRibOut.QNAME).node(Tables.QNAME).node(this.tableKey).node(ROUTES_IDENTIFIER), routeId);
     }
 
-    private void filterOutPeerRole(final PeerId peerId, final DataTreeCandidateNode rootNode, final YangInstanceIdentifier rootPath, final Map<YangInstanceIdentifier, PeerId> deletedPeers) {
+    private void filterOutPeerRole(final PeerId peerId, final DataTreeCandidateNode rootNode, final YangInstanceIdentifier rootPath,
+        final Map<YangInstanceIdentifier, PeerId> deletedPeers) {
         final DataTreeCandidateNode roleChange = rootNode.getModifiedChild(AbstractPeerRoleTracker.PEER_ROLE_NID);
         if (roleChange != null) {
             if (!rootNode.getModificationType().equals(ModificationType.DELETE)) {
+                this.cacheDisconnectedPeers.reconnected(peerId);
                 this.peerPolicyTracker.onDataTreeChanged(roleChange, IdentifierUtils.peerPath(rootPath));
             } else {
                 deletedPeers.put(IdentifierUtils.peerPath(rootPath), peerId);
@@ -326,7 +330,7 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
                 for (final Entry<PeerId, YangInstanceIdentifier> pid : peerGroup.getPeers()) {
                     final PeerId peerDestiny = pid.getKey();
                     if (!routePeerId.equals(peerDestiny) && isTableSupported(peerDestiny) && !deletedPeers.containsValue(peerDestiny) &&
-                        !ConnectedPeers.getInstance().isPeerDisconnected(peerDestiny)) {
+                        !this.cacheDisconnectedPeers.isPeerDisconnected(peerDestiny)) {
                         final YangInstanceIdentifier routeTarget = getRouteTarget(pid.getValue(), routeId);
                         if (value != null && effectiveAttributes != null) {
                             LOG.debug("Write route {} to peers AdjRibsOut {}", value, peerDestiny);
index 2c69709e3ab53cdce3a3295b30da7986db5552b2..727b0ad4fed60dc1faf72914a4d0a8fff57bd60c 100644 (file)
@@ -37,6 +37,7 @@ import org.opendaylight.protocol.bgp.openconfig.spi.BGPConfigModuleTracker;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigProvider;
 import org.opendaylight.protocol.bgp.rib.DefaultRibReference;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
+import org.opendaylight.protocol.bgp.rib.impl.spi.CacheDisconnectedPeers;
 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;
@@ -105,6 +106,7 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
     private final List<LocRibWriter> locRibs = new ArrayList<>();
     private final BGPConfigModuleTracker configModuleTracker;
     private final BGPOpenConfigProvider openConfigProvider;
+    private final CacheDisconnectedPeers cacheDisconnectedPeers;
 
     public RIBImpl(final RibId ribId, final AsNumber localAs, final Ipv4Address localBgpId, final Ipv4Address clusterId, final RIBExtensionConsumerContext extensions,
         final BGPDispatcher dispatcher, final ReconnectStrategyFactory tcpStrategyFactory, final BindingCodecTreeFactory codecFactory,
@@ -128,6 +130,7 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
         this.yangRibId = yangRibIdBuilder.nodeWithKey(Rib.QNAME, RIB_ID_QNAME, ribId.getValue()).build();
         this.configModuleTracker = moduleTracker;
         this.openConfigProvider = openConfigProvider;
+        this.cacheDisconnectedPeers = new CacheDisconnectedPeersImpl();
 
         LOG.debug("Instantiating RIB table {} at {}", ribId, this.yangRibId);
 
@@ -207,7 +210,8 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
         } catch (final TransactionCommitFailedException e1) {
             LOG.error("Failed to initiate LocRIB for key {}", key, e1);
         }
-        this.locRibs.add(LocRibWriter.create(this.ribContextRegistry, key, createPeerChain(this), getYangRibId(), this.localAs, getService(), pd));
+        this.locRibs.add(LocRibWriter.create(this.ribContextRegistry, key, createPeerChain(this), getYangRibId(), this.localAs, getService(), pd,
+            this.cacheDisconnectedPeers));
     }
 
     @Override
@@ -350,4 +354,9 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
     public Optional<BGPOpenConfigProvider> getOpenConfigProvider() {
         return Optional.fromNullable(this.openConfigProvider);
     }
+
+    @Override
+    public CacheDisconnectedPeers getCacheDisconnectedPeers() {
+        return this.cacheDisconnectedPeers;
+    }
 }
index 747305e2bdf881195ce4799ef1fb9feb3d6401f2..b9213aa5eabfa4557fc55ec891477a18a4440dee 100644 (file)
@@ -51,6 +51,7 @@ class RIBSupportContextImpl extends RIBSupportContext {
 
     @Override
     public void clearTable(final DOMDataWriteTransaction tx, final YangInstanceIdentifier tableId) {
+        //TODO: Change this method name to createTable which is more appropriate
         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> tb = ImmutableNodes.mapEntryBuilder();
         tb.withNodeIdentifier((NodeIdentifierWithPredicates)tableId.getLastPathArgument());
         tb.withChild(EMPTY_TABLE_ATTRIBUTES);
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/CacheDisconnectedPeers.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/CacheDisconnectedPeers.java
new file mode 100644 (file)
index 0000000..ea59746
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerId;
+
+public interface CacheDisconnectedPeers {
+
+    /**
+     * Check whether Peer is inside the cache List
+     * @return True if peer is contained on CacheList
+     */
+    boolean isPeerDisconnected(PeerId peerId);
+
+    /***
+     * Remove Peer from cache in case of reconnection
+     * @param peerId
+     */
+    void reconnected(PeerId peerId);
+
+    /***
+     * Insert disconnected peer to cache
+     * @param peerId
+     */
+    void insertDisconnectedPeer(Ipv4Address peerId);
+}
index d5fabf6a4877a6545ed57ee077bf491c45acfff9..b411204c74e5d01afe2748364cf1eb49ea02ac06 100644 (file)
@@ -85,4 +85,12 @@ public interface RIB {
      * not available.
      */
     Optional<BGPOpenConfigProvider> getOpenConfigProvider();
+
+    /**
+     * Return cache disconnected peers which allows us to avoid update
+     * DS from a peer already disconnected, when multiple peers are disconnected
+     * at the same time and their own exportPolicy has not been updated yet.
+     * @return
+     */
+    CacheDisconnectedPeers getCacheDisconnectedPeers();
 }
index 147c8c99b409481eb211ea61016704699a85e75c..6b7b2daf15e2824a94f256a04dd74b7bfca1fd3e 100644 (file)
@@ -120,7 +120,8 @@ public class LocRibWriterTest {
         Mockito.doReturn(this.future).when(this.domTransWrite).submit();
         Mockito.doReturn(null).when(this.service).registerDataTreeChangeListener(Mockito.any(DOMDataTreeIdentifier.class), Mockito.any(DOMDataTreeChangeListener.class));
         Mockito.doReturn(Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(Routes.QNAME)).addChild(Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(Ipv4Routes.QNAME)).withChild(ImmutableNodes.mapNodeBuilder(Ipv4Route.QNAME).build()).build()).build()).when(this.ribSupport).emptyRoutes();
-        this.locRibWriter = LocRibWriter.create(this.registry, this.tablesKey, this.chain, YangInstanceIdentifier.of(BgpRib.QNAME), new AsNumber((long) 35), this.service, this.pd);
+        this.locRibWriter = LocRibWriter.create(this.registry, this.tablesKey, this.chain, YangInstanceIdentifier.of(BgpRib.QNAME),
+            new AsNumber((long) 35), this.service, this.pd, new CacheDisconnectedPeersImpl());
     }
 
     private DataTreeCandidate prepareUpdate() {