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%2Fconfig%2FBgpPeer.java;h=123f3ce8d8e907572daf20e8b3c4dfc9561582c9;hb=5cfd57fe4d2e1d62e822f7d90ef6a0a12441b30b;hp=45fc73aa58a3e33f6c83fbdce835a610761bc356;hpb=542dfab18ce3a8af9535870ece0faf611ac5f7d2;p=bgpcep.git diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java index 45fc73aa58..123f3ce8d8 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java @@ -5,36 +5,41 @@ * 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.config; +import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; -import com.google.common.base.Preconditions; import com.google.common.collect.Iterables; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import io.netty.util.concurrent.Future; import java.net.InetSocketAddress; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; -import javax.annotation.concurrent.GuardedBy; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; -import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.checkerframework.checker.lock.qual.GuardedBy; +import org.opendaylight.mdsal.binding.api.RpcProviderService; import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer; import org.opendaylight.protocol.bgp.parser.BgpExtendedMessageUtil; import org.opendaylight.protocol.bgp.parser.spi.MultiprotocolCapabilitiesUtil; +import org.opendaylight.protocol.bgp.parser.spi.RevisedErrorHandlingSupport; import org.opendaylight.protocol.bgp.rib.impl.BGPPeer; +import org.opendaylight.protocol.bgp.rib.impl.BgpPeerUtil; import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher; 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.RIB; import org.opendaylight.protocol.bgp.rib.spi.state.BGPPeerState; -import org.opendaylight.protocol.bgp.rib.spi.state.BGPPeerStateConsumer; +import org.opendaylight.protocol.bgp.rib.spi.state.BGPPeerStateProvider; +import org.opendaylight.protocol.bgp.rib.spi.state.BGPStateProviderRegistry; import org.opendaylight.protocol.concepts.KeyMapping; import org.opendaylight.protocol.util.Ipv4Util; import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafi; @@ -44,48 +49,47 @@ import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.n import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.peer.group.PeerGroup; import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp; 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.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.open.message.BgpParameters; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.open.message.BgpParametersBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.open.message.bgp.parameters.OptionalCapabilities; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.open.message.bgp.parameters.OptionalCapabilitiesBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.open.message.bgp.parameters.optional.capabilities.CParametersBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapabilityBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.BgpTableType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.CParameters1; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.CParameters1Builder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.mp.capabilities.AddPathCapabilityBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.mp.capabilities.MultiprotocolCapabilityBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.mp.capabilities.add.path.capability.AddressFamilies; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180321.NeighborPeerGroupConfig; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.PeerRole; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.rib.TablesKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier; +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.open.message.bgp.parameters.OptionalCapabilities; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.open.message.bgp.parameters.OptionalCapabilitiesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.open.message.bgp.parameters.optional.capabilities.CParametersBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapabilityBuilder; +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.CParameters1Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.AddPathCapabilityBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.MultiprotocolCapabilityBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.add.path.capability.AddressFamilies; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.NeighborPeerGroupConfig; +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.rib.TablesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.ClusterIdentifier; +import org.opendaylight.yangtools.concepts.Registration; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.osgi.framework.ServiceRegistration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public final class BgpPeer implements PeerBean, BGPPeerStateConsumer { - +public class BgpPeer extends PeerBean { private static final Logger LOG = LoggerFactory.getLogger(BgpPeer.class); - private final RpcProviderRegistry rpcRegistry; - @GuardedBy("this") - private ServiceRegistration serviceRegistration; + private final RpcProviderService rpcRegistry; + private final BGPStateProviderRegistry stateProviderRegistry; + @GuardedBy("this") private Neighbor currentConfiguration; @GuardedBy("this") private BgpPeerSingletonService bgpPeerSingletonService; + @GuardedBy("this") + private Registration stateProviderRegistration; - public BgpPeer(final RpcProviderRegistry rpcRegistry) { - this.rpcRegistry = rpcRegistry; + public BgpPeer(final RpcProviderService rpcRegistry, final BGPStateProviderRegistry stateProviderRegistry) { + this.rpcRegistry = requireNonNull(rpcRegistry); + this.stateProviderRegistry = requireNonNull(stateProviderRegistry); } - private static List getBgpParameters(final AfiSafis afiSafis, final RIB rib, - final BGPTableTypeRegistryConsumer tableTypeRegistry) { - final List tlvs = new ArrayList<>(); + private static List getBgpCapabilities(final AfiSafis afiSafis, final RIB rib, + final BGPTableTypeRegistryConsumer tableTypeRegistry) { final List caps = new ArrayList<>(); caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setAs4BytesCapability( new As4BytesCapabilityBuilder().setAsNumber(rib.getLocalAs()).build()).build()).build()); @@ -95,222 +99,270 @@ public final class BgpPeer implements PeerBean, BGPPeerStateConsumer { caps.add(new OptionalCapabilitiesBuilder() .setCParameters(MultiprotocolCapabilitiesUtil.RR_CAPABILITY).build()); - final List afiSafi = OpenConfigMappingUtil.getAfiSafiWithDefault(afiSafis, false); - final List addPathCapability = OpenConfigMappingUtil - .toAddPathCapability(afiSafi, tableTypeRegistry); + final Collection afiSafi = OpenConfigMappingUtil.getAfiSafiWithDefault(afiSafis, false).values(); + final List addPathCapability = OpenConfigMappingUtil.toAddPathCapability(afiSafi, + tableTypeRegistry); if (!addPathCapability.isEmpty()) { caps.add(new OptionalCapabilitiesBuilder() - .setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class, - new CParameters1Builder().setAddPathCapability( - new AddPathCapabilityBuilder() - .setAddressFamilies(addPathCapability).build()).build()).build()).build()); + .setCParameters(new CParametersBuilder() + .addAugmentation(new CParameters1Builder() + .setAddPathCapability(new AddPathCapabilityBuilder() + .setAddressFamilies(addPathCapability) + .build()) + .build()) + .build()) + .build()); } final List tableTypes = OpenConfigMappingUtil.toTableTypes(afiSafi, tableTypeRegistry); for (final BgpTableType tableType : tableTypes) { if (!rib.getLocalTables().contains(tableType)) { - LOG.info("RIB instance does not list {} " + - "in its local tables. Incoming data will be dropped.", tableType); + LOG.info("RIB instance does not list {} in its local tables. Incoming data will be dropped.", + tableType); } - caps.add(new OptionalCapabilitiesBuilder().setCParameters( - new CParametersBuilder().addAugmentation(CParameters1.class, - new CParameters1Builder().setMultiprotocolCapability( - new MultiprotocolCapabilityBuilder(tableType).build()).build()).build()).build()); - } - tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(caps).build()); - return tlvs; - } - - private static Optional getPassword(final KeyMapping key) { - if (key != null) { - return Optional.of(Iterables.getOnlyElement(key.values())); + caps.add(new OptionalCapabilitiesBuilder() + .setCParameters(new CParametersBuilder() + .addAugmentation(new CParameters1Builder() + .setMultiprotocolCapability(new MultiprotocolCapabilityBuilder(tableType).build()) + .build()) + .build()) + .build()); } - return Optional.empty(); + return caps; } @Override - public synchronized void start(final RIB rib, final Neighbor neighbor, final InstanceIdentifier bgpIid, + synchronized void start(final RIB rib, final Neighbor neighbor, final InstanceIdentifier bgpIid, final PeerGroupConfigLoader peerGroupLoader, final BGPTableTypeRegistryConsumer tableTypeRegistry) { - Preconditions.checkState(this.bgpPeerSingletonService == null, - "Previous peer instance was not closed."); - - this.bgpPeerSingletonService = new BgpPeerSingletonService(rib, neighbor, bgpIid, peerGroupLoader, + checkState(bgpPeerSingletonService == null, "Previous peer instance was not closed."); + LOG.info("Starting BgPeer instance {}", neighbor.getNeighborAddress()); + bgpPeerSingletonService = new BgpPeerSingletonService(rib, neighbor, bgpIid, peerGroupLoader, tableTypeRegistry); - this.currentConfiguration = neighbor; - } - - @Override - public synchronized void restart(final RIB rib, final InstanceIdentifier bgpIid, - final PeerGroupConfigLoader peerGroupLoader, final BGPTableTypeRegistryConsumer tableTypeRegistry) { - Preconditions.checkState(this.currentConfiguration != null); - start(rib, this.currentConfiguration, bgpIid, peerGroupLoader, tableTypeRegistry); + currentConfiguration = neighbor; + stateProviderRegistration = stateProviderRegistry.register(this); } @Override - public synchronized void close() { - if (this.serviceRegistration != null) { - this.serviceRegistration.unregister(); - this.serviceRegistration = null; + synchronized ListenableFuture stop() { + if (bgpPeerSingletonService == null) { + LOG.info("BGP Peer {} already closed, skipping", currentConfiguration.getNeighborAddress()); + return Futures.immediateVoidFuture(); } + LOG.info("Closing BGP Peer {}", currentConfiguration.getNeighborAddress()); + if (stateProviderRegistration != null) { + stateProviderRegistration.close(); + stateProviderRegistration = null; + } + + final var future = bgpPeerSingletonService.closeServiceInstance(); + bgpPeerSingletonService = null; + return future; } @Override - public synchronized void instantiateServiceInstance() { - if (this.bgpPeerSingletonService != null) { - this.bgpPeerSingletonService.instantiateServiceInstance(); + synchronized void instantiateServiceInstance() { + if (bgpPeerSingletonService != null) { + bgpPeerSingletonService.instantiateServiceInstance(); } } @Override - public synchronized ListenableFuture closeServiceInstance() { - if (this.bgpPeerSingletonService != null) { - final ListenableFuture fut = this.bgpPeerSingletonService.closeServiceInstance(); - this.bgpPeerSingletonService = null; - return fut; - } - return Futures.immediateFuture(null); + synchronized ListenableFuture closeServiceInstance() { + return bgpPeerSingletonService != null ? bgpPeerSingletonService.closeServiceInstance() + : Futures.immediateVoidFuture(); } @Override - public synchronized Boolean containsEqualConfiguration(final Neighbor neighbor) { - if (this.currentConfiguration == null) { + synchronized boolean containsEqualConfiguration(final Neighbor neighbor) { + if (currentConfiguration == null) { return false; } - final AfiSafis actAfiSafi = this.currentConfiguration.getAfiSafis(); + final AfiSafis actAfiSafi = currentConfiguration.getAfiSafis(); final AfiSafis extAfiSafi = neighbor.getAfiSafis(); - final List actualSafi = actAfiSafi != null ? actAfiSafi.getAfiSafi() : Collections.emptyList(); - final List extSafi = extAfiSafi != null ? extAfiSafi.getAfiSafi() : Collections.emptyList(); + final Collection actualSafi = actAfiSafi != null ? actAfiSafi.nonnullAfiSafi().values() + : Collections.emptyList(); + final Collection extSafi = extAfiSafi != null ? extAfiSafi.nonnullAfiSafi().values() + : Collections.emptyList(); return actualSafi.containsAll(extSafi) && extSafi.containsAll(actualSafi) - && Objects.equals(this.currentConfiguration.getConfig(), neighbor.getConfig()) - && Objects.equals(this.currentConfiguration.getNeighborAddress(), neighbor.getNeighborAddress()) - && Objects.equals(this.currentConfiguration.getAddPaths(), neighbor.getAddPaths()) - && Objects.equals(this.currentConfiguration.getApplyPolicy(), neighbor.getApplyPolicy()) - && Objects.equals(this.currentConfiguration.getAsPathOptions(), neighbor.getAsPathOptions()) - && Objects.equals(this.currentConfiguration.getEbgpMultihop(), neighbor.getEbgpMultihop()) - && Objects.equals(this.currentConfiguration.getGracefulRestart(), neighbor.getGracefulRestart()) - && Objects.equals(this.currentConfiguration.getErrorHandling(), neighbor.getErrorHandling()) - && Objects.equals(this.currentConfiguration.getLoggingOptions(), neighbor.getLoggingOptions()) - && Objects.equals(this.currentConfiguration.getRouteReflector(), neighbor.getRouteReflector()) - && Objects.equals(this.currentConfiguration.getState(), neighbor.getState()) - && Objects.equals(this.currentConfiguration.getTimers(), neighbor.getTimers()) - && Objects.equals(this.currentConfiguration.getTransport(), neighbor.getTransport()); + && Objects.equals(currentConfiguration.getConfig(), neighbor.getConfig()) + && Objects.equals(currentConfiguration.getNeighborAddress(), neighbor.getNeighborAddress()) + && Objects.equals(currentConfiguration.getAddPaths(), neighbor.getAddPaths()) + && Objects.equals(currentConfiguration.getApplyPolicy(), neighbor.getApplyPolicy()) + && Objects.equals(currentConfiguration.getAsPathOptions(), neighbor.getAsPathOptions()) + && Objects.equals(currentConfiguration.getEbgpMultihop(), neighbor.getEbgpMultihop()) + && Objects.equals(currentConfiguration.getGracefulRestart(), neighbor.getGracefulRestart()) + && Objects.equals(currentConfiguration.getErrorHandling(), neighbor.getErrorHandling()) + && Objects.equals(currentConfiguration.getLoggingOptions(), neighbor.getLoggingOptions()) + && Objects.equals(currentConfiguration.getRouteReflector(), neighbor.getRouteReflector()) + && Objects.equals(currentConfiguration.getState(), neighbor.getState()) + && Objects.equals(currentConfiguration.getTimers(), neighbor.getTimers()) + && Objects.equals(currentConfiguration.getTransport(), neighbor.getTransport()); + } + + @Override + synchronized Neighbor getCurrentConfiguration() { + return currentConfiguration; } @Override public synchronized BGPPeerState getPeerState() { - if (this.bgpPeerSingletonService == null) { + if (bgpPeerSingletonService == null) { return null; } - return this.bgpPeerSingletonService.getPeerState(); - } - - synchronized void setServiceRegistration(final ServiceRegistration serviceRegistration) { - this.serviceRegistration = serviceRegistration; + return bgpPeerSingletonService.getPeerState(); } synchronized void removePeer(final BGPPeerRegistry bgpPeerRegistry) { - if (BgpPeer.this.currentConfiguration != null) { - bgpPeerRegistry.removePeer(BgpPeer.this.currentConfiguration.getNeighborAddress()); + if (currentConfiguration != null) { + bgpPeerRegistry.removePeer(OpenConfigMappingUtil.convertIpAddress( + currentConfiguration.getNeighborAddress())); } } - private final class BgpPeerSingletonService implements BGPPeerStateConsumer { - private boolean activeConnection; + private final class BgpPeerSingletonService implements BGPPeerStateProvider { + private final boolean activeConnection; private final BGPDispatcher dispatcher; private final InetSocketAddress inetAddress; private final int retryTimer; private final KeyMapping keys; private final InetSocketAddress localAddress; private final BGPPeer bgpPeer; - private final IpAddress neighborAddress; + private final IpAddressNoZone neighborAddress; private final BGPSessionPreferences prefs; private Future connection; private boolean isServiceInstantiated; + private final List finalCapabilities; + private final int gracefulRestartTimer; + private final RevisedErrorHandlingSupport errorHandling; + private BgpPeerSingletonService(final RIB rib, final Neighbor neighbor, final InstanceIdentifier bgpIid, final PeerGroupConfigLoader peerGroupLoader, final BGPTableTypeRegistryConsumer tableTypeRegistry) { - this.neighborAddress = neighbor.getNeighborAddress(); + neighborAddress = OpenConfigMappingUtil.convertIpAddress(neighbor.getNeighborAddress()); PeerGroup peerGroup = null; String peerGroupName = null; final Config neighborConfig = neighbor.getConfig(); if (neighborConfig != null) { - final NeighborPeerGroupConfig pgConfig = neighborConfig.getAugmentation(NeighborPeerGroupConfig.class); + final NeighborPeerGroupConfig pgConfig = neighborConfig.augmentation(NeighborPeerGroupConfig.class); if (pgConfig != null) { peerGroupName = StringUtils.substringBetween(pgConfig.getPeerGroup(), "=\"", "\""); peerGroup = peerGroupLoader.getPeerGroup(bgpIid, peerGroupName); } } - final AfiSafis afisSAfis; + final AfiSafis afisSafis; if (peerGroup != null && peerGroup.getAfiSafis() != null) { - afisSAfis = peerGroup.getAfiSafis(); + afisSafis = peerGroup.getAfiSafis(); } else { - afisSAfis = requireNonNull(neighbor.getAfiSafis(), "Missing mandatory AFIs/SAFIs"); + afisSafis = requireNonNull(neighbor.getAfiSafis(), "Missing mandatory AFIs/SAFIs"); } - final Set afiSafisAdvertized = OpenConfigMappingUtil - .toTableKey(afisSAfis.getAfiSafi(), tableTypeRegistry); + final Set afiSafisAdvertized = OpenConfigMappingUtil.toTableKey(afisSafis.getAfiSafi(), + tableTypeRegistry); final PeerRole role = OpenConfigMappingUtil.toPeerRole(neighbor, peerGroup); + final ClusterIdentifier clusterId = OpenConfigMappingUtil - .getNeighborClusterIdentifier(neighbor.getConfig()); - final List bgpParameters = getBgpParameters(afisSAfis, rib, tableTypeRegistry); + .getNeighborClusterIdentifier(neighbor.getRouteReflector(), peerGroup); + final int hold = OpenConfigMappingUtil.getHoldTimer(neighbor, peerGroup); + gracefulRestartTimer = OpenConfigMappingUtil.getGracefulRestartTimer(neighbor, peerGroup, hold); + final Set gracefulTables = GracefulRestartUtil.getGracefulTables( + afisSafis.nonnullAfiSafi().values(), tableTypeRegistry); + final Map llGracefulTimers = GracefulRestartUtil.getLlGracefulTimers( + afisSafis.nonnullAfiSafi().values(), tableTypeRegistry); + finalCapabilities = getBgpCapabilities(afisSafis, rib, tableTypeRegistry); + final List bgpParameters = getInitialBgpParameters(gracefulTables, llGracefulTimers); final KeyMapping keyMapping = OpenConfigMappingUtil.getNeighborKey(neighbor); - final IpAddress neighborLocalAddress = OpenConfigMappingUtil.getLocalAddress(neighbor.getTransport()); - int hold = OpenConfigMappingUtil.getHoldTimer(neighbor, peerGroup); + final IpAddressNoZone neighborLocalAddress = OpenConfigMappingUtil.getLocalAddress(neighbor.getTransport()); final AsNumber globalAs = rib.getLocalAs(); final AsNumber neighborRemoteAs = OpenConfigMappingUtil .getRemotePeerAs(neighbor.getConfig(), peerGroup, globalAs); - final AsNumber neighborLocalAs = OpenConfigMappingUtil.getLocalPeerAs(neighbor.getConfig(), globalAs); + final AsNumber neighborLocalAs; + if (role == PeerRole.Ebgp) { + neighborLocalAs = OpenConfigMappingUtil.getLocalPeerAs(neighbor.getConfig(), globalAs); + } else { + neighborLocalAs = globalAs; + } - this.bgpPeer = new BGPPeer(this.neighborAddress, peerGroupName, rib, role, clusterId, neighborLocalAs, - BgpPeer.this.rpcRegistry, afiSafisAdvertized, Collections.emptySet()); - this.prefs = new BGPSessionPreferences(neighborLocalAs, hold, rib.getBgpIdentifier(), - neighborRemoteAs, bgpParameters, getPassword(keyMapping)); - this.activeConnection = OpenConfigMappingUtil.isActive(neighbor, peerGroup); - this.retryTimer = OpenConfigMappingUtil.getRetryTimer(neighbor, peerGroup); - this.dispatcher = rib.getDispatcher(); + errorHandling = OpenConfigMappingUtil.getRevisedErrorHandling(role, peerGroup, neighbor); + bgpPeer = new BGPPeer(tableTypeRegistry, neighborAddress, peerGroupName, rib, role, clusterId, + neighborLocalAs, rpcRegistry, afiSafisAdvertized, gracefulTables, llGracefulTimers, + BgpPeer.this); + prefs = new BGPSessionPreferences(neighborLocalAs, hold, rib.getBgpIdentifier(), + neighborRemoteAs, bgpParameters, + keyMapping == null ? Optional.empty() + : Optional.of(Iterables.getOnlyElement(keyMapping.asMap().values()))); + activeConnection = OpenConfigMappingUtil.isActive(neighbor, peerGroup); + retryTimer = OpenConfigMappingUtil.getRetryTimer(neighbor, peerGroup); + dispatcher = rib.getDispatcher(); final PortNumber port = OpenConfigMappingUtil.getPort(neighbor, peerGroup); - this.inetAddress = Ipv4Util.toInetSocketAddress(this.neighborAddress, port); + inetAddress = Ipv4Util.toInetSocketAddress(neighborAddress, port); if (neighborLocalAddress != null) { - this.localAddress = Ipv4Util.toInetSocketAddress(neighborLocalAddress, port); + localAddress = Ipv4Util.toInetSocketAddress(neighborLocalAddress, port); } else { - this.localAddress = null; + localAddress = null; } - this.keys = keyMapping; + keys = keyMapping; + LOG.info("New BGP Peer {}:{} AS {} instance for BGP id {} created with activeConnection: {}", + inetAddress, localAddress, neighborRemoteAs, prefs.getBgpId(), activeConnection); } - private synchronized void instantiateServiceInstance() { - this.isServiceInstantiated = true; - LOG.info("Peer instantiated {}", this.neighborAddress); - this.bgpPeer.instantiateServiceInstance(); - this.dispatcher.getBGPPeerRegistry().addPeer(this.neighborAddress, this.bgpPeer, this.prefs); - if (this.activeConnection) { - this.connection = this.dispatcher.createReconnectingClient(this.inetAddress, this.localAddress, - this.retryTimer, this.keys); + private List getInitialBgpParameters(final Set gracefulTables, + final Map llGracefulTimers) { + final Set llGracefulRestarts = llGracefulTimers.entrySet().stream() + .map(entry -> new BgpPeerUtil.LlGracefulRestartDTO(entry.getKey(), entry.getValue(), false)) + .collect(Collectors.toSet()); + return Collections.singletonList( + GracefulRestartUtil.getGracefulBgpParameters(finalCapabilities, gracefulTables, + Collections.emptySet(), gracefulRestartTimer, false, llGracefulRestarts)); + } + + synchronized void instantiateServiceInstance() { + if (isServiceInstantiated) { + LOG.warn("Peer {} has already been instantiated", neighborAddress); + return; + } + isServiceInstantiated = true; + LOG.info("Peer instantiated {}", neighborAddress); + bgpPeer.instantiateServiceInstance(); + dispatcher.getBGPPeerRegistry().addPeer(neighborAddress, bgpPeer, prefs); + if (activeConnection) { + connection = dispatcher.createReconnectingClient(inetAddress, localAddress, retryTimer, keys); } } - private synchronized ListenableFuture closeServiceInstance() { - if (!this.isServiceInstantiated) { - LOG.info("Peer {} already closed", this.neighborAddress); - return Futures.immediateFuture(null); + synchronized ListenableFuture closeServiceInstance() { + if (!isServiceInstantiated) { + LOG.info("Peer {} already closed", neighborAddress); + return Futures.immediateVoidFuture(); } - LOG.info("Close Peer {}", this.neighborAddress); - this.isServiceInstantiated = false; - if (this.connection != null) { - this.connection.cancel(true); - this.connection = null; + LOG.info("Close Peer {}", neighborAddress); + isServiceInstantiated = false; + if (connection != null) { + connection.cancel(true); + connection = null; } - final ListenableFuture future = this.bgpPeer.close(); - removePeer(this.dispatcher.getBGPPeerRegistry()); + final var future = bgpPeer.close(); + removePeer(dispatcher.getBGPPeerRegistry()); return future; } @Override public BGPPeerState getPeerState() { - return this.bgpPeer.getPeerState(); + return bgpPeer.getPeerState(); } } + + public synchronized List getBgpFixedCapabilities() { + return bgpPeerSingletonService.finalCapabilities; + } + + public synchronized int getGracefulRestartTimer() { + return bgpPeerSingletonService.gracefulRestartTimer; + } + + public synchronized Optional getErrorHandling() { + return Optional.ofNullable(bgpPeerSingletonService.errorHandling); + } }