X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=bgp%2Frib-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fprotocol%2Fbgp%2Frib%2Fimpl%2FBGPPeer.java;h=937382a0f9a71c5ae1eede7e28d7eff88dd949fd;hb=0fdeddbe3d072a88428599421191f0f60b2864e4;hp=b46c4385ed013893d6f6122935143cf8a1267c8b;hpb=e39eb55cea13c4923050d41a0eebf50804fdd85e;p=bgpcep.git diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java index b46c4385ed..937382a0f9 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java @@ -10,7 +10,6 @@ package org.opendaylight.protocol.bgp.rib.impl; import static java.util.Objects.requireNonNull; import com.google.common.base.MoreObjects; -import com.google.common.base.Objects; import com.google.common.base.Stopwatch; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; @@ -29,17 +28,19 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import javax.annotation.concurrent.GuardedBy; -import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction; -import org.opendaylight.controller.md.sal.common.api.data.TransactionChain; -import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration; -import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.checkerframework.checker.lock.qual.GuardedBy; +import org.checkerframework.checker.lock.qual.Holding; +import org.opendaylight.mdsal.binding.api.RpcProviderService; +import org.opendaylight.mdsal.binding.api.Transaction; +import org.opendaylight.mdsal.binding.api.TransactionChain; import org.opendaylight.mdsal.common.api.CommitInfo; +import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction; +import org.opendaylight.mdsal.dom.api.DOMTransactionChain; import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer; import org.opendaylight.protocol.bgp.parser.BGPDocumentedException; import org.opendaylight.protocol.bgp.parser.BGPError; @@ -59,19 +60,18 @@ import org.opendaylight.protocol.bgp.rib.spi.RouterIds; import org.opendaylight.protocol.bgp.rib.spi.state.BGPSessionState; import org.opendaylight.protocol.bgp.rib.spi.state.BGPTimersState; import org.opendaylight.protocol.bgp.rib.spi.state.BGPTransportState; -import org.opendaylight.protocol.concepts.AbstractRegistration; import org.opendaylight.protocol.util.Ipv4Util; 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.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.prefixes.DestinationIpv4Builder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.prefixes.destination.ipv4.Ipv4Prefixes; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.prefixes.destination.ipv4.Ipv4PrefixesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationIpv4CaseBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.Update; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.BgpParameters; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.update.message.Nlri; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.Update; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.open.message.BgpParameters; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.Attributes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.update.message.Nlri; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpAddPathTableType; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.RouteRefresh; @@ -85,18 +85,19 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mult import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.peer.rpc.rev180329.BgpPeerRpcService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.peer.rpc.rev180329.PeerContext; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerRole; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.PeerKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.peer.AdjRibOut; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.AddressFamily; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.ClusterIdentifier; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv4AddressFamily; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteTarget; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.SubsequentAddressFamily; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.UnicastSubsequentAddressFamily; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.AddressFamily; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.ClusterIdentifier; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Ipv4AddressFamily; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.RouteTarget; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.SubsequentAddressFamily; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.UnicastSubsequentAddressFamily; +import org.opendaylight.yangtools.concepts.ObjectRegistration; +import org.opendaylight.yangtools.concepts.Registration; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.opendaylight.yangtools.yang.binding.Notification; @@ -110,20 +111,21 @@ import org.slf4j.LoggerFactory; */ public class BGPPeer extends AbstractPeer implements BGPSessionListener { private static final Logger LOG = LoggerFactory.getLogger(BGPPeer.class); - private static final TablesKey IPV4_UCAST_TABLE_KEY = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class); + private static final TablesKey IPV4_UCAST_TABLE_KEY = new TablesKey(Ipv4AddressFamily.class, + UnicastSubsequentAddressFamily.class); - private Set tables = Collections.emptySet(); + private ImmutableSet tables = ImmutableSet.of(); private final RIB rib; private final Map adjRibOutListenerSet = new HashMap<>(); private final List rtMemberships = new ArrayList<>(); - private final RpcProviderRegistry rpcRegistry; + private final RpcProviderService rpcRegistry; private final BGPTableTypeRegistryConsumer tableTypeRegistry; private final BgpPeer bgpPeer; private InstanceIdentifier peerRibOutIId; private KeyedInstanceIdentifier peerIId; @GuardedBy("this") - private AbstractRegistration trackerRegistration; + private Registration trackerRegistration; private final LoadingCache> tablesIId = CacheBuilder.newBuilder() .build(new CacheLoader>() { @@ -134,33 +136,35 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { }); @GuardedBy("this") - private BGPSession session; + private BGPSession currentSession; @GuardedBy("this") private AdjRibInWriter ribWriter; @GuardedBy("this") private EffectiveRibInWriter effRibInWriter; - private RoutedRpcRegistration rpcRegistration; + private ObjectRegistration rpcRegistration; private Map addPathTableMaps = Collections.emptyMap(); private YangInstanceIdentifier peerPath; private boolean sessionUp; + private boolean llgrSupport; private Stopwatch peerRestartStopwatch; - private long selectionDeferralTimerSeconds; + private long currentSelectionDeferralTimerSeconds; private final List missingEOT = new ArrayList<>(); public BGPPeer( final BGPTableTypeRegistryConsumer tableTypeRegistry, - final IpAddress neighborAddress, + final IpAddressNoZone neighborAddress, final String peerGroupName, final RIB rib, final PeerRole role, final ClusterIdentifier clusterId, final AsNumber localAs, - final RpcProviderRegistry rpcRegistry, + final RpcProviderService rpcRegistry, final Set afiSafisAdvertized, final Set afiSafisGracefulAdvertized, + final Map llGracefulTablesAdvertised, final BgpPeer bgpPeer) { super(rib, Ipv4Util.toStringIP(neighborAddress), peerGroupName, role, clusterId, - localAs, neighborAddress, afiSafisAdvertized, afiSafisGracefulAdvertized, Collections.emptyMap()); + localAs, neighborAddress, afiSafisAdvertized, afiSafisGracefulAdvertized, llGracefulTablesAdvertised); this.tableTypeRegistry = requireNonNull(tableTypeRegistry); this.rib = requireNonNull(rib); this.rpcRegistry = rpcRegistry; @@ -210,8 +214,8 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { Optional nlriAnounced = Optional.empty(); if (isAnyNlriAnnounced) { - nlriAnounced = message.getNlri().stream().filter(n -> Objects.equal(n.getPrefix(), w.getPrefix()) - && Objects.equal(n.getPathId(), w.getPathId())) + nlriAnounced = message.getNlri().stream().filter(n -> Objects.equals(n.getPrefix(), w.getPrefix()) + && Objects.equals(n.getPathId(), w.getPathId())) .findAny(); } if (!nlriAnounced.isPresent()) { @@ -231,6 +235,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { } public synchronized void instantiateServiceInstance() { + createDomChain(); this.ribWriter = AdjRibInWriter.create(this.rib.getYangRibId(), this.peerRole, this); setActive(true); } @@ -259,13 +264,14 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { final Class rrSafi = message.getSafi(); final TablesKey key = new TablesKey(rrAfi, rrSafi); - final AdjRibOutListener listener = this.adjRibOutListenerSet.get(key); - if (listener != null) { - listener.close(); - this.adjRibOutListenerSet.remove(key); - createAdjRibOutListener(key, listener.isMpSupported()); - } else { - LOG.info("Ignoring RouteRefresh message. Afi/Safi is not supported: {}, {}.", rrAfi, rrSafi); + synchronized (this) { + final AdjRibOutListener listener = this.adjRibOutListenerSet.remove(key); + if (listener != null) { + listener.close(); + createAdjRibOutListener(key, listener.isMpSupported()); + } else { + LOG.info("Ignoring RouteRefresh message. Afi/Safi is not supported: {}, {}.", rrAfi, rrSafi); + } } } @@ -306,7 +312,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { if (mpReach != null) { this.ribWriter.updateRoutes(mpReach, nextHopToAttribute(attrs, mpReach)); } - MpUnreachNlri mpUnreach; + final MpUnreachNlri mpUnreach; if (message.getWithdrawnRoutes() != null) { mpUnreach = prefixesToMpUnreach(message, isAnyNlriAnnounced); } else { @@ -329,13 +335,14 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { } } - private synchronized void handleGracefulEndOfRib() { + @Holding("this") + private void handleGracefulEndOfRib() { if (isLocalRestarting()) { if (this.missingEOT.isEmpty()) { createEffRibInWriter(); this.effRibInWriter.init(); registerPrefixesCounters(this.effRibInWriter, this.effRibInWriter); - for (final TablesKey key : this.tables) { + for (final TablesKey key : getAfiSafisAdvertized()) { createAdjRibOutListener(key, true); } setLocalRestartingState(false); @@ -346,16 +353,21 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { @Override public synchronized void onSessionUp(final BGPSession session) { - this.session = session; + this.currentSession = session; this.sessionUp = true; this.bindingChain = this.rib.createPeerChain(this); - if (this.session instanceof BGPSessionStateProvider) { - ((BGPSessionStateProvider) this.session).registerMessagesCounter(this); + if (this.currentSession instanceof BGPSessionStateProvider) { + ((BGPSessionStateProvider) this.currentSession).registerMessagesCounter(this); } final GracefulRestartCapability advertisedGracefulRestartCapability = session.getAdvertisedGracefulRestartCapability(); - final List advertisedTables = - advertisedGracefulRestartCapability.getTables(); + final List advertisedTables = + advertisedGracefulRestartCapability.getTables(); + final List advertisedLLTables = + session.getAdvertisedLlGracefulRestartCapability().getTables(); + final List addPathTablesType = session.getAdvertisedAddPathTableTypes(); final Set advertizedTableTypes = session.getAdvertisedTableTypes(); LOG.info("Session with peer {} went up with tables {} and Add Path tables {}", this.name, @@ -363,6 +375,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { final Set setTables = advertizedTableTypes.stream().map(t -> new TablesKey(t.getAfi(), t.getSafi())) .collect(Collectors.toSet()); this.tables = ImmutableSet.copyOf(setTables); + this.addPathTableMaps = mapTableTypesFamilies(addPathTablesType); final boolean restartingLocally = isLocalRestarting(); @@ -382,13 +395,10 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { this.tables, this.addPathTableMaps); if (this.rpcRegistry != null) { - this.rpcRegistration = this.rpcRegistry.addRoutedRpcImplementation(BgpPeerRpcService.class, - new BgpPeerRpc(this, session, this.tables)); - final KeyedInstanceIdentifier path = this.rib.getInstanceIdentifier() - .child(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib - .rib.Peer.class, new PeerKey(this.peerId)); - this.rpcRegistration.registerPath(PeerContext.class, path); + this.rpcRegistration = this.rpcRegistry.registerRpcImplementation(BgpPeerRpcService.class, + new BgpPeerRpc(this, session, this.tables), ImmutableSet.of(this.rib.getInstanceIdentifier().child( + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib + .Peer.class, new PeerKey(this.peerId)))); } } else { final Set forwardingTables; @@ -409,18 +419,39 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { this.missingEOT.addAll(this.tables); } } - if (advertisedTables == null || - advertisedTables.isEmpty()) { + if (advertisedTables == null || advertisedTables.isEmpty()) { setAdvertizedGracefulRestartTableTypes(Collections.emptyList()); } else { setAdvertizedGracefulRestartTableTypes(advertisedTables.stream() .map(t -> new TablesKey(t.getAfi(), t.getSafi())).collect(Collectors.toList())); } - final int restartTime = advertisedGracefulRestartCapability.getRestartTime(); - setAfiSafiGracefulRestartState(restartTime, false, restartingLocally); + setAfiSafiGracefulRestartState(advertisedGracefulRestartCapability.getRestartTime().toJava(), false, + restartingLocally); + + final Map llTablesReceived; + if (advertisedLLTables != null) { + llTablesReceived = new HashMap<>(); + for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp + .capabilities.ll.graceful.restart.capability.Tables table : advertisedLLTables) { + llTablesReceived.put(new TablesKey(table.getAfi(), table.getSafi()), + table.getLongLivedStaleTime().getValue().intValue()); + } + } else { + llTablesReceived = Collections.emptyMap(); + } + setAdvertizedLlGracefulRestartTableTypes(llTablesReceived); + + if (!llTablesReceived.isEmpty()) { + llgrSupport = true; + // FIXME: propagate preserved tables + } else { + // FIXME: clear preserved tables + llgrSupport = false; + } + if (!restartingLocally) { addBgp4Support(); - for (final TablesKey key : this.tables) { + for (final TablesKey key : getAfiSafisAdvertized()) { createAdjRibOutListener(key, true); } } @@ -428,7 +459,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { // SpotBugs does not grok Optional.ifPresent() and thinks we are using unsynchronized access final Optional errorHandling = this.bgpPeer.getErrorHandling(); if (errorHandling.isPresent()) { - this.session.addDecoderConstraint(RevisedErrorHandlingSupport.class, errorHandling.get()); + this.currentSession.addDecoderConstraint(RevisedErrorHandlingSupport.class, errorHandling.get()); } } @@ -438,14 +469,15 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { private synchronized void createEffRibInWriter() { this.effRibInWriter = new EffectiveRibInWriter(this, this.rib, - this.rib.createPeerChain(this), - this.peerIId, this.tables, this.tableTypeRegistry, - this.rtMemberships, - this.rtCache); + this.rib.createPeerDOMChain(this), + this.peerPath, this.tables, this.tableTypeRegistry, + this.rtMemberships, + this.rtCache); } //try to add a support for old-school BGP-4, if peer did not advertise IPv4-Unicast MP capability - private synchronized void addBgp4Support() { + @Holding("this") + private void addBgp4Support() { if (!this.tables.contains(IPV4_UCAST_TABLE_KEY)) { final HashSet newSet = new HashSet<>(this.tables); newSet.add(IPV4_UCAST_TABLE_KEY); @@ -454,13 +486,13 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { } } - private synchronized void createAdjRibOutListener(final TablesKey key, - final boolean mpSupport) { + @Holding("this") + private void createAdjRibOutListener(final TablesKey key, final boolean mpSupport) { final RIBSupport ribSupport = this.rib.getRibSupportContext().getRIBSupport(key); // not particularly nice - if (ribSupport != null && this.session instanceof BGPSessionImpl) { - final ChannelOutputLimiter limiter = ((BGPSessionImpl) this.session).getLimiter(); + if (ribSupport != null && this.currentSession instanceof BGPSessionImpl) { + final ChannelOutputLimiter limiter = ((BGPSessionImpl) this.currentSession).getLimiter(); final AdjRibOutListener adjRibOut = AdjRibOutListener.create(this.peerId, key, this.rib.getYangRibId(), this.rib.getCodecsRegistry(), ribSupport, this.rib.getService(), limiter, mpSupport); @@ -470,11 +502,11 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { } @Override - public synchronized void onSessionDown(final BGPSession session, final Exception e) { - if (e.getMessage().equals(BGPSessionImpl.END_OF_INPUT)) { + public synchronized void onSessionDown(final BGPSession session, final Exception exc) { + if (exc.getMessage().equals(BGPSessionImpl.END_OF_INPUT)) { LOG.info("Session with peer {} went down", this.name); } else { - LOG.info("Session with peer {} went down", this.name, e); + LOG.info("Session with peer {} went down", this.name, exc); } releaseConnectionGracefully(); } @@ -487,10 +519,8 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { @Override public String toString() { - return MoreObjects.toStringHelper(this) - .add("name", this.name) - .add("tables", this.tables).toString(); - } + return MoreObjects.toStringHelper(this).add("name", this.name).add("tables", this.tables).toString(); + } @Override public synchronized FluentFuture releaseConnection() { @@ -512,19 +542,25 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { } releaseBindingChain(); - if (this.session != null) { + closeSession(); + return future; + } + + @Holding("this") + @SuppressWarnings("checkstyle:illegalCatch") + private void closeSession() { + if (this.currentSession != null) { try { if (isRestartingGracefully()) { - this.session.closeWithoutMessage(); + this.currentSession.closeWithoutMessage(); } else { - this.session.close(); + this.currentSession.close(); } } catch (final Exception e) { LOG.warn("Error closing session with peer", e); } - this.session = null; + this.currentSession = null; } - return future; } private Set getGracefulTables() { @@ -548,7 +584,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { if (this.effRibInWriter != null) { this.effRibInWriter.close(); } - this.tables = Collections.emptySet(); + this.tables = ImmutableSet.of(); this.addPathTableMaps = Collections.emptyMap(); future = removePeer(this.peerPath); resetState(); @@ -568,10 +604,10 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { final long elapsedNanos = this.peerRestartStopwatch.elapsed(TimeUnit.NANOSECONDS); if (elapsedNanos >= peerRestartTimeNanos) { setAfiSafiGracefulRestartState(0, false, false); - onSessionTerminated(this.session, new BGPTerminationReason(BGPError.HOLD_TIMER_EXPIRED)); + onSessionTerminated(this.currentSession, new BGPTerminationReason(BGPError.HOLD_TIMER_EXPIRED)); } - new ScheduledThreadPoolExecutor(1) - .schedule(this::handleRestartTimer, peerRestartTimeNanos - elapsedNanos, TimeUnit.NANOSECONDS); + + currentSession.schedule(this::handleRestartTimer, peerRestartTimeNanos - elapsedNanos, TimeUnit.NANOSECONDS); } private synchronized void handleSelectionReferralTimer() { @@ -579,14 +615,14 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { return; } - final long referalTimerNanos = TimeUnit.SECONDS.toNanos(this.selectionDeferralTimerSeconds); + final long referalTimerNanos = TimeUnit.SECONDS.toNanos(this.currentSelectionDeferralTimerSeconds); final long elapsedNanos = this.peerRestartStopwatch.elapsed(TimeUnit.NANOSECONDS); if (elapsedNanos >= referalTimerNanos) { this.missingEOT.clear(); handleGracefulEndOfRib(); } - new ScheduledThreadPoolExecutor(1) - .schedule(this::handleSelectionReferralTimer, referalTimerNanos - elapsedNanos, TimeUnit.NANOSECONDS); + currentSession.schedule(this::handleSelectionReferralTimer, referalTimerNanos - elapsedNanos, + TimeUnit.NANOSECONDS); } private void releaseConnectionGracefully() { @@ -604,7 +640,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { @Override public boolean supportsTable(final TablesKey tableKey) { - return this.tables.contains(tableKey) && this.sessionUp; + return this.sessionUp && getAfiSafisAdvertized().contains(tableKey); } @Override @@ -613,8 +649,15 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { } @Override - public synchronized void onTransactionChainFailed(final TransactionChain chain, - final AsyncTransaction transaction, final Throwable cause) { + public synchronized void onTransactionChainFailed(final DOMTransactionChain chain, + final DOMDataTreeTransaction transaction, final Throwable cause) { + LOG.error("Transaction domChain failed.", cause); + releaseConnection(); + } + + @Override + public synchronized void onTransactionChainFailed(final TransactionChain chain, final Transaction transaction, + final Throwable cause) { LOG.error("Transaction domChain failed.", cause); releaseConnection(); } @@ -626,24 +669,24 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { @Override public synchronized BGPSessionState getBGPSessionState() { - if (this.session instanceof BGPSessionStateProvider) { - return ((BGPSessionStateProvider) this.session).getBGPSessionState(); + if (this.currentSession instanceof BGPSessionStateProvider) { + return ((BGPSessionStateProvider) this.currentSession).getBGPSessionState(); } return null; } @Override public synchronized BGPTimersState getBGPTimersState() { - if (this.session instanceof BGPSessionStateProvider) { - return ((BGPSessionStateProvider) this.session).getBGPTimersState(); + if (this.currentSession instanceof BGPSessionStateProvider) { + return ((BGPSessionStateProvider) this.currentSession).getBGPTimersState(); } return null; } @Override public synchronized BGPTransportState getBGPTransportState() { - if (this.session instanceof BGPSessionStateProvider) { - return ((BGPSessionStateProvider) this.session).getBGPTransportState(); + if (this.currentSession instanceof BGPSessionStateProvider) { + return ((BGPSessionStateProvider) this.currentSession).getBGPTransportState(); } return null; } @@ -662,11 +705,16 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener { "Peer is not capable of graceful restart")); } setGracefulPreferences(true, tablesToPreserve); - this.selectionDeferralTimerSeconds = selectionDeferralTimerSeconds; + this.currentSelectionDeferralTimerSeconds = selectionDeferralTimerSeconds; setLocalRestartingState(true); return releaseConnection(); } + @Override + boolean supportsLLGR() { + return this.llgrSupport; + } + private synchronized void setGracefulPreferences(final boolean localRestarting, final Set preservedTables) { final Set gracefulTables = this.tables.stream()