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;
}
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);
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();
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);
private void addPeerToDisconnectedSharedList() {
if(this.session != null) {
- ConnectedPeers.getInstance().insertDesconectedPeer(this.session.getBgpId());
+ this.rib.getCacheDisconnectedPeers().insertDisconnectedPeer(this.session.getBgpId());
}
}
--- /dev/null
+/*
+ * 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);
+ }
+}
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;
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;
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());
}
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();
}
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);
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);
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;
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,
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);
} 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
public Optional<BGPOpenConfigProvider> getOpenConfigProvider() {
return Optional.fromNullable(this.openConfigProvider);
}
+
+ @Override
+ public CacheDisconnectedPeers getCacheDisconnectedPeers() {
+ return this.cacheDisconnectedPeers;
+ }
}
@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);
--- /dev/null
+/*
+ * 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);
+}
* 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();
}
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() {