Provide Add Path support for all AFI/SAFI
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / AbstractBGPSessionNegotiator.java
index 596c1a1ba6daa552983b6942ece425519448e122..7cbb6f4d04a1cc9537f39d9c3ab7d5d74c123f21 100644 (file)
@@ -8,14 +8,15 @@
 
 package org.opendaylight.protocol.bgp.rib.impl;
 
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
 import io.netty.channel.Channel;
-import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
 import io.netty.util.concurrent.Promise;
+import io.netty.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 import javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
@@ -24,15 +25,16 @@ import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
 import org.opendaylight.protocol.bgp.rib.spi.BGPSessionListener;
 import org.opendaylight.protocol.bgp.rib.spi.SessionNegotiator;
+import org.opendaylight.protocol.util.Ipv6Util;
 import org.opendaylight.protocol.util.Values;
 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.Ipv4Address;
-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.KeepaliveBuilder;
-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.NotifyBuilder;
-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.OpenBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.Keepalive;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.KeepaliveBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.Notify;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.NotifyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.Open;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.OpenBuilder;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -79,11 +81,13 @@ abstract class AbstractBGPSessionNegotiator extends ChannelInboundHandlerAdapter
     private State state = State.IDLE;
     @GuardedBy("this")
     private BGPSessionImpl session;
+    @GuardedBy("this")
+    private ScheduledFuture<?> pending;
 
     AbstractBGPSessionNegotiator(final Promise<BGPSessionImpl> promise, final Channel channel,
             final BGPPeerRegistry registry) {
-        this.promise = Preconditions.checkNotNull(promise);
-        this.channel = Preconditions.checkNotNull(channel);
+        this.promise = requireNonNull(promise);
+        this.channel = requireNonNull(channel);
         this.registry = registry;
     }
 
@@ -113,16 +117,14 @@ abstract class AbstractBGPSessionNegotiator extends ChannelInboundHandlerAdapter
                 preferences.getBgpId()).setBgpParameters(preferences.getParams()).build());
             if (this.state != State.FINISHED) {
                 this.state = State.OPEN_SENT;
-                this.channel.eventLoop().schedule(new Runnable() {
-                    @Override
-                    public void run() {
-                        synchronized (AbstractBGPSessionNegotiator.this) {
-                            if (AbstractBGPSessionNegotiator.this.state != State.FINISHED) {
-                                AbstractBGPSessionNegotiator.this
-                                    .sendMessage(buildErrorNotify(BGPError.HOLD_TIMER_EXPIRED));
-                                negotiationFailed(new BGPDocumentedException("HoldTimer expired", BGPError.FSM_ERROR));
-                                AbstractBGPSessionNegotiator.this.state = State.FINISHED;
-                            }
+                this.pending = this.channel.eventLoop().schedule(() -> {
+                    synchronized (AbstractBGPSessionNegotiator.this) {
+                        AbstractBGPSessionNegotiator.this.pending = null;
+                        if (AbstractBGPSessionNegotiator.this.state != State.FINISHED) {
+                            AbstractBGPSessionNegotiator.this
+                                .sendMessage(buildErrorNotify(BGPError.HOLD_TIMER_EXPIRED));
+                            negotiationFailed(new BGPDocumentedException("HoldTimer expired", BGPError.FSM_ERROR));
+                            AbstractBGPSessionNegotiator.this.state = State.FINISHED;
                         }
                     }
                 }, INITIAL_HOLDTIMER, TimeUnit.MINUTES);
@@ -134,7 +136,11 @@ abstract class AbstractBGPSessionNegotiator extends ChannelInboundHandlerAdapter
     }
 
     private IpAddress getRemoteIp() {
-        return StrictBGPPeerRegistry.getIpAddress(this.channel.remoteAddress());
+        final IpAddress remoteIp = StrictBGPPeerRegistry.getIpAddress(this.channel.remoteAddress());
+        if (remoteIp.getIpv6Address() != null) {
+            return new IpAddress(Ipv6Util.getFullForm(remoteIp.getIpv6Address()));
+        }
+        return remoteIp;
     }
 
     protected synchronized void handleMessage(final Notification msg) {
@@ -248,19 +254,21 @@ abstract class AbstractBGPSessionNegotiator extends ChannelInboundHandlerAdapter
     private void negotiationFailedCloseChannel(final Throwable cause) {
         LOG.debug("Negotiation on channel {} failed", this.channel, cause);
         this.channel.close();
-        this.promise.setFailure(cause);
+        synchronized (AbstractBGPSessionNegotiator.this) {
+            if (this.pending != null && this.pending.isCancellable()) {
+                this.pending.cancel(true);
+                this.pending = null;
+            }
+        }
     }
 
     private void sendMessage(final Notification msg) {
-        this.channel.writeAndFlush(msg).addListener(new ChannelFutureListener() {
-            @Override
-            public void operationComplete(final ChannelFuture f) {
-                if (!f.isSuccess()) {
-                    LOG.warn("Failed to send message {} to channel {}", msg,  AbstractBGPSessionNegotiator.this.channel, f.cause());
-                    negotiationFailedCloseChannel(f.cause());
-                } else {
-                    LOG.trace("Message {} sent to channel {}", msg, AbstractBGPSessionNegotiator.this.channel);
-                }
+        this.channel.writeAndFlush(msg).addListener((ChannelFutureListener) f -> {
+            if (!f.isSuccess()) {
+                LOG.warn("Failed to send message {} to channel {}", msg,  AbstractBGPSessionNegotiator.this.channel, f.cause());
+                negotiationFailedCloseChannel(f.cause());
+            } else {
+                LOG.trace("Message {} sent to channel {}", msg, AbstractBGPSessionNegotiator.this.channel);
             }
         });
     }