BUG: 4831 33/34733/15
authorOm Prakash <op317q@att.com>
Sat, 20 Feb 2016 19:45:30 +0000 (14:45 -0500)
committerOm Prakash <op317q@att.com>
Fri, 26 Feb 2016 01:59:57 +0000 (20:59 -0500)
The BGP specification mandates a maximum BGP message size of 4096 octets. As BGP is extended to support newer AFI/SAFIs,
there is a need to extend the maximum message size beyond 4096 octets. This code fix will update the BGP specification by providing an
extension to BGP to extend its current message size from 4096 octets to 65535 octets.
The major Design/code change for this fix is to modify Bgp-Message yang to add bgp-extended-message-capability in BGP Message.
BgpExtendedMessageUtil class is written to looks for Bgp Extended Message Capability in capabilities.odl-bgp-rib-impl-cfg.yang
is modifed to add extended message capability preference for Speaker and Peer.BGPSessionImpl class has been enhanced
to inject extended message capability of maximun frame size 65535.

BUG: 4831
Change-Id: Icb8731395106bc8164b830e57ea316e31702a4a7
Signed-off-by: Om Prakash <op317q@att.com>
18 files changed:
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BgpExtendedMessageUtil.java [new file with mode: 0644]
bgp/parser-api/src/main/yang/bgp-message.yang
bgp/parser-api/src/test/java/org/opendaylight/protocol/bgp/parser/APITest.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/BGPActivator.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/open/BgpExtendedMessageCapabilityHandler.java [new file with mode: 0644]
bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/BgpExtendedMessageCapabilityHandlerTest.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPHandlerFactory.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPMessageHeaderDecoder.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionProposalImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionStats.java
bgp/rib-impl/src/main/yang/odl-bgp-rib-impl-cfg.yang
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ApiTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/BGPDispatcherImplTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionImplTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/FSMTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/StrictBGPPeerRegistryTest.java
bgp/rib-mock/src/main/java/org/opendaylight/protocol/bgp/rib/mock/EventBusRegistration.java

diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BgpExtendedMessageUtil.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BgpExtendedMessageUtil.java
new file mode 100644 (file)
index 0000000..09071e1
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016 AT&T Services, 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.parser;
+
+import java.util.List;
+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.open.message.BgpParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilities;
+
+public final class BgpExtendedMessageUtil {
+
+    private BgpExtendedMessageUtil() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Looks for Bgp Extended Message Capability in capabilities .
+     *
+     * @param open remote BGP open message
+     * @return flag
+     */
+    public static boolean advertizedBgpExtendedMessageCapability(final Open open) {
+        // Look for Bgp Extended Message capability very defensively
+        final List<BgpParameters> params = open.getBgpParameters();
+        if (params != null) {
+            for (final BgpParameters p : params) {
+                for (final OptionalCapabilities oc : p.getOptionalCapabilities()) {
+                    if (oc.getCParameters() != null && oc.getCParameters().getBgpExtendedMessageCapability() != null) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+}
index 4b7088ba08fc9accf320b34b6946657999bf0a06..89b92c07688f776ba6c58dda3a79c5e4b18be166 100644 (file)
@@ -92,6 +92,9 @@ module bgp-message {
                             type inet:as-number;
                         }
                     }
+                    container bgp-extended-message-capability {
+                        reference "https://www.ietf.org/archive/id/draft-ietf-idr-bgp-extended-messages-11.txt";
+                    }
                 }
             }
         }
@@ -221,4 +224,4 @@ module bgp-message {
             type binary;
         }
     }
-}
+}
\ No newline at end of file
index 56a5165cf72d57e6eaf1389dcf5b20062db2354e..12cfe6f21793f481f2d9e276c51ac5ef1cfc4aba 100644 (file)
@@ -24,6 +24,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilitiesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.BgpExtendedMessageCapabilityBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.MultiprotocolCapabilityBuilder;
@@ -73,6 +74,20 @@ public class APITest {
         assertEquals(10, AsNumberUtil.advertizedAsNumber(open2).getValue().intValue());
     }
 
+    @Test
+    public void testBgpExtendedMessageUtil() {
+        final List<BgpParameters> params = new ArrayList<>();
+        final List<OptionalCapabilities> capas = new ArrayList<>();
+        capas.add(new OptionalCapabilitiesBuilder().setCParameters( new CParametersBuilder().addAugmentation(
+            CParameters1.class, new CParameters1Builder().setMultiprotocolCapability( new MultiprotocolCapabilityBuilder()
+                .build()).build()).build()).build());
+        capas.add(new OptionalCapabilitiesBuilder().setCParameters(
+                new CParametersBuilder().setBgpExtendedMessageCapability(new BgpExtendedMessageCapabilityBuilder().build()).build()).build());
+        params.add(new BgpParametersBuilder().setOptionalCapabilities(capas).build());
+        final Open open1 = new OpenBuilder().setBgpParameters(params).build();
+        assertEquals(true, BgpExtendedMessageUtil.advertizedBgpExtendedMessageCapability(open1));
+    }
+
     @Test(expected=UnsupportedOperationException.class)
     public void testAsNumberUtilPrivateConstructor() throws Throwable {
         final Constructor<AsNumberUtil> c = AsNumberUtil.class.getDeclaredConstructor();
index 0c26f09fda332d52b8a1711d2f74a2b45e628ed8..d78f8a3fd0d0f2f5ed6eb8739500e04ea094d439 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.protocol.bgp.parser.impl.message.BGPOpenMessageParser;
 import org.opendaylight.protocol.bgp.parser.impl.message.BGPUpdateMessageParser;
 import org.opendaylight.protocol.bgp.parser.impl.message.open.AddPathCapabilityHandler;
 import org.opendaylight.protocol.bgp.parser.impl.message.open.As4CapabilityHandler;
+import org.opendaylight.protocol.bgp.parser.impl.message.open.BgpExtendedMessageCapabilityHandler;
 import org.opendaylight.protocol.bgp.parser.impl.message.open.CapabilityParameterParser;
 import org.opendaylight.protocol.bgp.parser.impl.message.open.GracefulCapabilityHandler;
 import org.opendaylight.protocol.bgp.parser.impl.message.open.MultiProtocolCapabilityHandler;
@@ -58,6 +59,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParameters;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.BgpExtendedMessageCapability;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.Aggregator;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.Aigp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AsPath;
@@ -150,6 +152,10 @@ public final class BGPActivator extends AbstractBGPExtensionProviderActivator {
         final CapabilityParameterParser cpp = new CapabilityParameterParser(context.getCapabilityRegistry());
         regs.add(context.registerParameterParser(CapabilityParameterParser.TYPE, cpp));
         regs.add(context.registerParameterSerializer(BgpParameters.class, cpp));
+
+        final BgpExtendedMessageCapabilityHandler bgpextmessage = new BgpExtendedMessageCapabilityHandler();
+        regs.add(context.registerCapabilityParser(BgpExtendedMessageCapabilityHandler.CODE, bgpextmessage));
+        regs.add(context.registerCapabilitySerializer(BgpExtendedMessageCapability.class, bgpextmessage));
     }
 
     private void registerAttributeParsers(final List<AutoCloseable> regs, final BGPExtensionProviderContext context) {
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/open/BgpExtendedMessageCapabilityHandler.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/open/BgpExtendedMessageCapabilityHandler.java
new file mode 100644 (file)
index 0000000..29e09c5
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016 AT&T 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.parser.impl.message.open;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.spi.CapabilityParser;
+import org.opendaylight.protocol.bgp.parser.spi.CapabilitySerializer;
+import org.opendaylight.protocol.bgp.parser.spi.CapabilityUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.BgpExtendedMessageCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.BgpExtendedMessageCapabilityBuilder;
+
+public final class BgpExtendedMessageCapabilityHandler implements CapabilityParser, CapabilitySerializer {
+    public static final int CODE = 6;
+    @Override
+    public CParameters parseCapability(final ByteBuf buffer) throws BGPDocumentedException, BGPParsingException {
+        return new CParametersBuilder().setBgpExtendedMessageCapability(new BgpExtendedMessageCapabilityBuilder().build()).build();
+    }
+
+    @Override
+    public void serializeCapability(final CParameters capability, final ByteBuf byteAggregator) {
+        final BgpExtendedMessageCapability bgpMessageSize = capability.getBgpExtendedMessageCapability();
+        if (bgpMessageSize != null) {
+            CapabilityUtil.formatCapability(CODE, Unpooled.EMPTY_BUFFER, byteAggregator);
+        }
+    }
+}
\ No newline at end of file
diff --git a/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/BgpExtendedMessageCapabilityHandlerTest.java b/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/BgpExtendedMessageCapabilityHandlerTest.java
new file mode 100644 (file)
index 0000000..d79f5be
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016 AT&T Services, 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.parser.impl;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.message.open.BgpExtendedMessageCapabilityHandler;
+import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
+import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.BgpExtendedMessageCapabilityBuilder;
+
+public class BgpExtendedMessageCapabilityHandlerTest {
+
+    private BGPExtensionProviderContext ctx;
+
+    @Before
+    public void setUp() {
+        this.ctx = ServiceLoaderBGPExtensionProviderContext.getSingletonInstance();
+    }
+
+    @Test
+    public void testBgpExtendedMessageCapabilityHandler() throws BGPDocumentedException, BGPParsingException {
+        final BgpExtendedMessageCapabilityHandler handler = new BgpExtendedMessageCapabilityHandler();
+
+        final byte[] bgpExeBytes = {(byte) 0x06, (byte) 0x00};
+        final BgpExtendedMessageCapabilityBuilder bgpExtBuilder = new BgpExtendedMessageCapabilityBuilder();
+
+        final ByteBuf buffer = Unpooled.buffer(bgpExeBytes.length);
+        handler.serializeCapability( new CParametersBuilder().setBgpExtendedMessageCapability(bgpExtBuilder.build()).build(), buffer);
+        Assert.assertArrayEquals(bgpExeBytes, buffer.array());
+        Assert.assertEquals(handler.parseCapability(Unpooled.wrappedBuffer(bgpExeBytes)), new CParametersBuilder().setBgpExtendedMessageCapability(bgpExtBuilder.build()).build());
+
+        final byte[] bgpExeBytes2 = {(byte) 0x40, (byte) 0x06};
+        buffer.clear();
+        handler.serializeCapability(new CParametersBuilder().setBgpExtendedMessageCapability(bgpExtBuilder.build()).build(), buffer);
+        Assert.assertNotSame(bgpExeBytes2, buffer.array());
+    }
+
+}
index d364ed97d1c8b035a0015f2bdfce73c67e9e49a3..a59033a8951ac3f5ede826659ad5bd8133f7df57 100644 (file)
@@ -31,6 +31,6 @@ public class BGPHandlerFactory {
     }
 
     public ChannelHandler[] getDecoders() {
-        return new ChannelHandler[] { new BGPMessageHeaderDecoder(), new BGPByteToMessageDecoder(this.registry), };
+        return new ChannelHandler[] { BGPMessageHeaderDecoder.getBGPMessageHeaderDecoder(), new BGPByteToMessageDecoder(this.registry), };
     }
 }
index 0db26f967174a43b02e293bf03c1d46f22671df5..b22e3fbb7b0c9aa77f34cb0d59912a5a7cb7631e 100644 (file)
@@ -14,8 +14,6 @@ import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
  */
 public final class BGPMessageHeaderDecoder extends LengthFieldBasedFrameDecoder {
 
-    private static final int MAX_FRAME_SIZE = 4096;
-
     private static final int MARKER_SIZE = 16;
 
     /*
@@ -23,6 +21,10 @@ public final class BGPMessageHeaderDecoder extends LengthFieldBasedFrameDecoder
      */
     private static final int LENGTH_SIZE = 2;
 
+    private static final int MAX_FRAME_SIZE = 4096;
+
+    private static final int EXTENDED_MAX_FRAME_SIZE = 65535;
+
     /*
 
      0                   1                   2                   3
@@ -41,7 +43,18 @@ public final class BGPMessageHeaderDecoder extends LengthFieldBasedFrameDecoder
 
      */
 
-    public BGPMessageHeaderDecoder() {
-        super(MAX_FRAME_SIZE, MARKER_SIZE, LENGTH_SIZE, -MARKER_SIZE - LENGTH_SIZE, 0);
+
+    private BGPMessageHeaderDecoder(final int maxFrameSize) {
+        super(maxFrameSize, MARKER_SIZE, LENGTH_SIZE, -MARKER_SIZE - LENGTH_SIZE, 0);
     }
+
+    public static BGPMessageHeaderDecoder getBGPMessageHeaderDecoder() {
+        return new BGPMessageHeaderDecoder(MAX_FRAME_SIZE);
+    }
+
+    public static BGPMessageHeaderDecoder getExtendedBGPMessageHeaderDecoder() {
+        return new BGPMessageHeaderDecoder(EXTENDED_MAX_FRAME_SIZE);
+    }
+
+
 }
index cfc01e536d527ee0932af30004bb2003fd24b6fe..f5ca215fac8e3d84f6c50af04825103893b8487b 100644 (file)
@@ -26,6 +26,7 @@ import javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpSessionState;
 import org.opendaylight.protocol.bgp.parser.AsNumberUtil;
 import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BgpExtendedMessageUtil;
 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
@@ -61,6 +62,8 @@ public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> im
 
     private static final int KA_TO_DEADTIMER_RATIO = 3;
 
+    private static final String EXTENDED_MSG_DECODER = "EXTENDED_MSG_DECODER";
+
     static final String END_OF_INPUT = "End of input detected. Close the session.";
 
     /**
@@ -132,6 +135,10 @@ public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> im
         this.keepAlive = this.holdTimerValue / KA_TO_DEADTIMER_RATIO;
         this.asNumber = AsNumberUtil.advertizedAsNumber(remoteOpen);
         this.peerRegistry = peerRegistry;
+        final boolean enableExMess = BgpExtendedMessageUtil.advertizedBgpExtendedMessageCapability(remoteOpen);
+        if (enableExMess) {
+            this.channel.pipeline().replace(BGPMessageHeaderDecoder.class, EXTENDED_MSG_DECODER, BGPMessageHeaderDecoder.getExtendedBGPMessageHeaderDecoder());
+        }
 
         final Set<TablesKey> tts = Sets.newHashSet();
         final Set<BgpTableType> tats = Sets.newHashSet();
@@ -179,7 +186,7 @@ public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> im
     public synchronized void close() {
         if (this.state != State.IDLE && this.channel.isActive()) {
             this.writeAndFlush(new NotifyBuilder().setErrorCode(BGPError.CEASE.getCode()).setErrorSubcode(
-                BGPError.CEASE.getSubcode()).build());
+                    BGPError.CEASE.getSubcode()).build());
         }
         this.closeWithoutMessage();
     }
@@ -200,10 +207,10 @@ public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> im
         } else if (msg instanceof Notify) {
             // Notifications are handled internally
             LOG.info("Session closed because Notification message received: {} / {}", ((Notify) msg).getErrorCode(),
-                ((Notify) msg).getErrorSubcode());
+                    ((Notify) msg).getErrorSubcode());
             this.closeWithoutMessage();
             this.listener.onSessionTerminated(this, new BGPTerminationReason(BGPError.forValue(((Notify) msg).getErrorCode(),
-                ((Notify) msg).getErrorSubcode())));
+                    ((Notify) msg).getErrorSubcode())));
             this.sessionStats.updateReceivedMsgErr((Notify) msg);
         } else if (msg instanceof Keepalive) {
             // Keepalives are handled internally
@@ -231,16 +238,16 @@ public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> im
     @GuardedBy("this")
     private void writeEpilogue(final ChannelFuture future, final Notification msg) {
         future.addListener(
-            new ChannelFutureListener() {
-                @Override
-                public void operationComplete(final ChannelFuture f) {
-                    if (!f.isSuccess()) {
-                        LOG.warn("Failed to send message {} to socket {}", msg, f.cause(), BGPSessionImpl.this.channel);
-                    } else {
-                        LOG.trace("Message {} sent to socket {}", msg, BGPSessionImpl.this.channel);
+                new ChannelFutureListener() {
+                    @Override
+                    public void operationComplete(final ChannelFuture f) {
+                        if (!f.isSuccess()) {
+                            LOG.warn("Failed to send message {} to socket {}", msg, f.cause(), BGPSessionImpl.this.channel);
+                        } else {
+                            LOG.trace("Message {} sent to socket {}", msg, BGPSessionImpl.this.channel);
+                        }
                     }
-                }
-            });
+                });
         this.lastMessageSentAt = System.nanoTime();
         this.sessionStats.updateSentMsgTotal();
         if (msg instanceof Update) {
index 4bb881ef67b21c7cd8faff9cb06415f87f32d0a3..ddab64ee32b4ca041f0571e11e3dbf09a2f19c98 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilitiesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.BgpExtendedMessageCapabilityBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.GracefulRestartCapabilityBuilder;
@@ -56,6 +57,8 @@ public final class BGPSessionProposalImpl implements BGPSessionProposal {
         }
         caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setAs4BytesCapability(
             new As4BytesCapabilityBuilder().setAsNumber(as).build()).build()).build());
+        caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setBgpExtendedMessageCapability(
+            new BgpExtendedMessageCapabilityBuilder().build()).build()).build());
         caps.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(
             CParameters1.class, new CParameters1Builder().setGracefulRestartCapability(
                 new GracefulRestartCapabilityBuilder().build()).build()).build()).build());
index 15894e09892fe8ef19271870c727ae2c62e496d2..1a2c725269f5cf63dd6c6358b852fd1ae0585667 100644 (file)
@@ -182,6 +182,9 @@ final class BGPSessionStats {
                             pref.setGrCapability(cParam.getAugmentation(CParameters1.class).getGracefulRestartCapability() != null);
                             pref.setFourOctetAsCapability(cParam.getAs4BytesCapability() != null);
                             pref.setAddPathCapability(cParam.getAugmentation(CParameters1.class).getAddPathCapability() != null);
+                            if (cParam.getBgpExtendedMessageCapability() !=null) {
+                                pref.setBgpExtendedMessageCapability(true);
+                            }
                         }
                     }
                 }
@@ -214,6 +217,9 @@ final class BGPSessionStats {
                         cParam.getAugmentation(CParameters1.class).getGracefulRestartCapability() != null);
                     pref.setAddPathCapability(cParam.getAugmentation(CParameters1.class) != null &&
                         cParam.getAugmentation(CParameters1.class).getAddPathCapability() != null);
+                    if (cParam.getBgpExtendedMessageCapability() !=null) {
+                        pref.setBgpExtendedMessageCapability(true);
+                    }
                 }
 
             }
index e5be6c7f20d9d1bfb8fc75a663964684566d3599..6d872e8eb6d137eec5a1036f8514fe7516586046 100644 (file)
@@ -484,6 +484,12 @@ module odl-bgp-rib-impl-cfg {
             default "false";
         }
 
+        leaf bgp-extended-message-capability {
+            description "The bgp extended message support capability.";
+            type boolean;
+            default "false";
+        }
+
         leaf gr-capability {
             description "BGP graceful restart support capability.";
             type boolean;
index 651aded837aae577108705dbf45c4820314c63c8..8f2c06c2c61479ba47727e10adaefb2bc3c3ac00 100644 (file)
@@ -27,6 +27,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilitiesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.BgpExtendedMessageCapabilityBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.GracefulRestartCapabilityBuilder;
@@ -77,6 +78,8 @@ public class ApiTest {
     private void setOptionalCapabilities(final List<OptionalCapabilities> list) {
         list.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setAs4BytesCapability(
             new As4BytesCapabilityBuilder().setAsNumber(new AsNumber(58L)).build()).build()).build());
+        list.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setBgpExtendedMessageCapability(
+                    new BgpExtendedMessageCapabilityBuilder().build()).build()).build());
         list.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(
             CParameters1.class, new CParameters1Builder().setGracefulRestartCapability(
                 new GracefulRestartCapabilityBuilder().build()).build()).build()).build());
index 940da922ab9a5b92ad29b3d11f8984f964be83d7..1f9b125698454333bb942041d5804e2daca80d55 100644 (file)
@@ -42,6 +42,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilitiesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.BgpExtendedMessageCapabilityBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1Builder;
@@ -135,7 +136,9 @@ public class BGPDispatcherImplTest {
         capas.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(
             CParameters1.class, new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder()
                 .setAfi(this.ipv4tt.getAfi()).setSafi(this.ipv4tt.getSafi()).build()).build())
-            .setAs4BytesCapability(new As4BytesCapabilityBuilder().setAsNumber(new AsNumber(30L)).build()).build()).build());
+            .setAs4BytesCapability(new As4BytesCapabilityBuilder().setAsNumber(new AsNumber(30L)).build())
+            .setBgpExtendedMessageCapability(new BgpExtendedMessageCapabilityBuilder().build())
+            .build()).build());
         tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(capas).build());
         return new BGPSessionPreferences(AS_NUMBER, (short) 4, new Ipv4Address(socketAddress.getAddress().getHostAddress()), AS_NUMBER, tlvs);
     }
index 06fdec89142d8aeab18d4f5b48642295741de703..16ae56c3651941661fdaf5e2727942685465bbfe 100644 (file)
@@ -32,6 +32,7 @@ import java.util.concurrent.TimeUnit;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
@@ -56,6 +57,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilitiesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.BgpExtendedMessageCapabilityBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1Builder;
@@ -82,6 +84,9 @@ public class BGPSessionImplTest {
     @Mock
     private ChannelPipeline pipeline;
 
+    @Mock
+    private ChannelHandler channelHandler;
+
     private final BgpTableType ipv4tt = new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
 
     private final List<Notification> receivedMsgs = Lists.newArrayList();
@@ -104,7 +109,8 @@ public class BGPSessionImplTest {
             new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder()
                 .setAfi(this.ipv4tt.getAfi()).setSafi(this.ipv4tt.getSafi()).build())
                 .setGracefulRestartCapability(new GracefulRestartCapabilityBuilder().build()).build())
-                .setAs4BytesCapability(new As4BytesCapabilityBuilder().setAsNumber(AS_NUMBER).build()).build()).build()
+                .setAs4BytesCapability(new As4BytesCapabilityBuilder().setAsNumber(AS_NUMBER).build())
+                .setBgpExtendedMessageCapability(new BgpExtendedMessageCapabilityBuilder().build()).build()).build()
         );
         tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(capa).build());
 
@@ -136,6 +142,7 @@ public class BGPSessionImplTest {
         doReturn(new InetSocketAddress(InetAddress.getByName(LOCAL_IP), LOCAL_PORT)).when(this.speakerListener).localAddress();
         doReturn(this.pipeline).when(this.speakerListener).pipeline();
         doReturn(this.pipeline).when(this.pipeline).replace(any(ChannelHandler.class), any(String.class), any(ChannelHandler.class));
+        doReturn(this.channelHandler).when(this.pipeline).replace(Matchers.<Class<ChannelHandler>>any(), any(String.class), any(ChannelHandler.class));
         doReturn(this.pipeline).when(this.pipeline).addLast(any(ChannelHandler.class));
         doReturn(mock(ChannelFuture.class)).when(this.speakerListener).close();
         this.listener = new SimpleSessionListener();
@@ -157,10 +164,12 @@ public class BGPSessionImplTest {
         assertEquals(BGPSessionImpl.State.UP.name(), state.getSessionState());
         assertEquals(BGP_ID.getValue(), state.getPeerPreferences().getAddress());
         assertEquals(AS_NUMBER.getValue(), state.getPeerPreferences().getAs());
+        assertEquals(true, state.getPeerPreferences().getBgpExtendedMessageCapability());
         assertEquals(BGP_ID.getValue(), state.getPeerPreferences().getBgpId());
         assertEquals(1, state.getPeerPreferences().getAdvertizedTableTypes().size());
         assertEquals(HOLD_TIMER, state.getPeerPreferences().getHoldtime().intValue());
         assertTrue(state.getPeerPreferences().getFourOctetAsCapability().booleanValue());
+        assertTrue(state.getPeerPreferences().getBgpExtendedMessageCapability().booleanValue());
         assertTrue(state.getPeerPreferences().getGrCapability());
         assertEquals(LOCAL_IP, state.getSpeakerPreferences().getAddress());
         assertEquals(LOCAL_PORT, state.getSpeakerPreferences().getPort().intValue());
index 823a7f920ccb28dffa864f62bbe514c466983201..7ab05891fff9bc654aad057fd4d0b169bf6ff4b2 100644 (file)
@@ -31,6 +31,7 @@ import java.util.concurrent.TimeUnit;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
@@ -56,6 +57,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilitiesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.BgpExtendedMessageCapabilityBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1Builder;
@@ -79,6 +81,9 @@ public class FSMTest {
     @Mock
     private ChannelPipeline pipeline;
 
+    @Mock
+    private ChannelHandler channelHandler;
+
     private final BgpTableType ipv4tt = new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
 
     private final BgpTableType linkstatett = new BgpTableTypeImpl(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class);
@@ -100,7 +105,9 @@ public class FSMTest {
             new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder()
                 .setAfi(this.linkstatett.getAfi()).setSafi(this.linkstatett.getSafi()).build()).build()).build()).build());
         capas.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setAs4BytesCapability(
-            new As4BytesCapabilityBuilder().setAsNumber(new AsNumber(30L)).build()).build()).build());
+                new As4BytesCapabilityBuilder().setAsNumber(new AsNumber(30L)).build()).build()).build());
+        capas.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setBgpExtendedMessageCapability(
+                        new BgpExtendedMessageCapabilityBuilder().build()).build()).build());
         capas.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
             new CParameters1Builder().setGracefulRestartCapability(new GracefulRestartCapabilityBuilder().build()).build()).build()).build());
 
@@ -127,6 +134,7 @@ public class FSMTest {
         doReturn(new InetSocketAddress(peerAddress, 179)).when(this.speakerListener).localAddress();
         doReturn(this.pipeline).when(this.speakerListener).pipeline();
         doReturn(this.pipeline).when(this.pipeline).replace(any(ChannelHandler.class), any(String.class), any(ChannelHandler.class));
+        doReturn(this.channelHandler).when(this.pipeline).replace(Matchers.<Class<ChannelHandler>>any(), any(String.class), any(ChannelHandler.class));
         doReturn(this.pipeline).when(this.pipeline).addLast(any(ChannelHandler.class));
         doReturn(mock(ChannelFuture.class)).when(this.speakerListener).close();
 
@@ -184,6 +192,8 @@ public class FSMTest {
         capas.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
             new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder()
                 .setAfi(this.ipv4tt.getAfi()).setSafi(this.ipv4tt.getSafi()).build()).build()).build()).build());
+        capas.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setBgpExtendedMessageCapability(
+                new BgpExtendedMessageCapabilityBuilder().build()).build()).build());
         tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(capas).build());
         // Open Message without advertised four-octet AS Number capability
         this.clientSession.handleMessage(new OpenBuilder().setMyAsNumber(30).setHoldTimer(1).setVersion(
@@ -195,6 +205,27 @@ public class FSMTest {
         assertNotNull(((Notify) m).getData());
     }
 
+    @Test
+    public void testBgpExtendedMessageCapability() {
+        this.clientSession.channelActive(null);
+        assertEquals(1, this.receivedMsgs.size());
+        assertTrue(this.receivedMsgs.get(0) instanceof Open);
+
+        final List<BgpParameters> tlvs = Lists.newArrayList();
+        final List<OptionalCapabilities> capas = Lists.newArrayList();
+        capas.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().addAugmentation(CParameters1.class,
+                new CParameters1Builder().setMultiprotocolCapability(new MultiprotocolCapabilityBuilder()
+                        .setAfi(this.ipv4tt.getAfi()).setSafi(this.ipv4tt.getSafi()).build()).build()).build()).build());
+        capas.add(new OptionalCapabilitiesBuilder().setCParameters(new CParametersBuilder().setAs4BytesCapability(
+                new As4BytesCapabilityBuilder().setAsNumber(new AsNumber(30L)).build()).build()).build());
+        tlvs.add(new BgpParametersBuilder().setOptionalCapabilities(capas).build());
+        this.clientSession.handleMessage(new OpenBuilder().setMyAsNumber(30).setHoldTimer(1).setVersion(
+                new ProtocolVersion((short) 4)).setBgpParameters(tlvs).setBgpIdentifier(new Ipv4Address("1.1.1.2")).build());
+        assertEquals(2, this.receivedMsgs.size());
+        assertTrue(this.receivedMsgs.get(1) instanceof Keepalive);
+
+    }
+
     @Test
     public void sendNotification() {
         this.clientSession.channelActive(null);
index fd48d6581d437d2cffa6c4b6ea4b122ab5a3a21e..98420a5b4b8be3e20d8967ad8f0e81a526a190fb 100644 (file)
@@ -32,6 +32,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilitiesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.As4BytesCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.c.parameters.BgpExtendedMessageCapabilityBuilder;
 
 public class StrictBGPPeerRegistryTest {
 
@@ -50,7 +51,8 @@ public class StrictBGPPeerRegistryTest {
         final List<BgpParameters> params = Lists.newArrayList(new BgpParametersBuilder()
             .setOptionalCapabilities(Lists.newArrayList(new OptionalCapabilitiesBuilder()
                 .setCParameters(new CParametersBuilder()
-                    .setAs4BytesCapability(new As4BytesCapabilityBuilder().setAsNumber(as).build()).build()).build())).build());
+                    .setAs4BytesCapability(new As4BytesCapabilityBuilder().setAsNumber(as).build())
+                    .setBgpExtendedMessageCapability(new BgpExtendedMessageCapabilityBuilder().build()).build()).build())).build());
         return new OpenBuilder().setBgpIdentifier(bgpId).setBgpParameters(params).build();
     }
 
index efb2adef7a396f2b50ad1c02d65c5eafe5fd869a..8ca478e5f332039fc362b76f349309277d2ebeed 100644 (file)
@@ -156,6 +156,7 @@ final class EventBusRegistration extends AbstractListenerRegistration<BGPSession
             public AsNumber getAsNumber() {
                 return new AsNumber(AS);
             }
+
         });
     }
 }