BUG-4592: Route Refresh message implementation 23/35923/7
authorIveta Halanova <ihalanov@cisco.com>
Tue, 8 Mar 2016 11:37:38 +0000 (12:37 +0100)
committerIveta Halanova <ihalanov@cisco.com>
Thu, 10 Mar 2016 12:45:49 +0000 (13:45 +0100)
Updated yang model and added new notification.
Implemented parser and registered.
Updated MultiprotocolCapabilitiesUtil class.
Updated and added unit tests.

Change-Id: If389ff6e793bbbae49e8d2fb16071397e121518a
Signed-off-by: Iveta Halanova <ihalanov@cisco.com>
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/MultiprotocolCapabilitiesUtil.java [deleted file]
bgp/parser-api/src/main/yang/bgp-multiprotocol.yang
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/BGPRouteRefreshMessageParser.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/open/MultiProtocolCapabilityHandler.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/open/RouteRefreshCapabilityHandler.java
bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/ParserTest.java
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/MultiprotocolCapabilitiesUtil.java [new file with mode: 0644]
bgp/parser-spi/src/test/java/org/opendaylight/protocol/bgp/parser/spi/UtilsTest.java
bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java

diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/MultiprotocolCapabilitiesUtil.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/MultiprotocolCapabilitiesUtil.java
deleted file mode 100644 (file)
index b6ada64..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.protocol.bgp.parser;
-
-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.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.RouteRefreshCapabilityBuilder;
-
-public final class MultiprotocolCapabilitiesUtil {
-
-    public static final CParameters RR_CAPABILITY = new CParametersBuilder().addAugmentation(CParameters1.class,
-        new CParameters1Builder().setRouteRefreshCapability(new RouteRefreshCapabilityBuilder().build()).build()).build();
-
-    // move common functionality will be added
-}
index 5480bd6ed8d0b1a870017b6b7d9adf0846eb417a..c50a2bf4afc7bc3b44fa20f603fea2efc0bc57f2 100644 (file)
@@ -141,4 +141,10 @@ module bgp-multiprotocol {
             }
         }
     }
+
+    notification route-refresh {
+        description "ROUTE-REFRESH message";
+        reference "https://tools.ietf.org/html/rfc2918#section-3";
+        uses bgp-table-type;
+    }
 }
index 71c0a34ec0801359e4db2c9a14bf9cb38d1b457b..833f9a3d0e0660e2114f0442da60f550325eee2f 100644 (file)
@@ -12,6 +12,7 @@ import java.util.List;
 import org.opendaylight.protocol.bgp.parser.impl.message.BGPKeepAliveMessageParser;
 import org.opendaylight.protocol.bgp.parser.impl.message.BGPNotificationMessageParser;
 import org.opendaylight.protocol.bgp.parser.impl.message.BGPOpenMessageParser;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPRouteRefreshMessageParser;
 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;
@@ -73,6 +74,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.path.attributes.attributes.Origin;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.OriginatorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.message.WithdrawnRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.RouteRefresh;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.AddPathCapability;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.GracefulRestartCapability;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.MultiprotocolCapability;
@@ -243,6 +245,12 @@ public final class BGPActivator extends AbstractBGPExtensionProviderActivator {
         final BGPKeepAliveMessageParser kamp = new BGPKeepAliveMessageParser();
         regs.add(context.registerMessageParser(BGPKeepAliveMessageParser.TYPE, kamp));
         regs.add(context.registerMessageSerializer(Keepalive.class, kamp));
+
+        final AddressFamilyRegistry afiReg = context.getAddressFamilyRegistry();
+        final SubsequentAddressFamilyRegistry safiReg = context.getSubsequentAddressFamilyRegistry();
+        final BGPRouteRefreshMessageParser rrmp = new BGPRouteRefreshMessageParser(afiReg, safiReg);
+        regs.add(context.registerMessageParser(BGPRouteRefreshMessageParser.TYPE, rrmp));
+        regs.add(context.registerMessageSerializer(RouteRefresh.class, rrmp));
     }
 
     private void registerExtendedCommunities(final List<AutoCloseable> regs, final BGPExtensionProviderContext context) {
diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPRouteRefreshMessageParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPRouteRefreshMessageParser.java
new file mode 100644 (file)
index 0000000..a66924c
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.impl.message;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.spi.AddressFamilyRegistry;
+import org.opendaylight.protocol.bgp.parser.spi.MessageParser;
+import org.opendaylight.protocol.bgp.parser.spi.MessageSerializer;
+import org.opendaylight.protocol.bgp.parser.spi.MessageUtil;
+import org.opendaylight.protocol.bgp.parser.spi.MultiprotocolCapabilitiesUtil;
+import org.opendaylight.protocol.bgp.parser.spi.SubsequentAddressFamilyRegistry;
+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.RouteRefresh;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.RouteRefreshBuilder;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class BGPRouteRefreshMessageParser implements MessageParser, MessageSerializer {
+    // https://tools.ietf.org/html/rfc2918#section-3
+
+    private static final Logger LOG = LoggerFactory.getLogger(BGPRouteRefreshMessageParser.class);
+
+    public static final int TYPE = 5;
+    private static final int TRIPLET_BYTE_SIZE = 4;
+
+    private final AddressFamilyRegistry afiReg;
+    private final SubsequentAddressFamilyRegistry safiReg;
+
+    public BGPRouteRefreshMessageParser(final AddressFamilyRegistry afiReg, final SubsequentAddressFamilyRegistry safiReg) {
+        this.afiReg = Preconditions.checkNotNull(afiReg);
+        this.safiReg = Preconditions.checkNotNull(safiReg);
+    }
+
+    /**
+     * Serializes BGP Route Refresh message.
+     *
+     * @param message to be serialized
+     * @param bytes ByteBuf where the message will be serialized
+     */
+    @Override
+    public void serializeMessage(final Notification message, final ByteBuf bytes) {
+        Preconditions.checkArgument(message instanceof RouteRefresh, "Message is not of type RouteRefresh.");
+        final RouteRefresh msg = (RouteRefresh) message;
+
+        final ByteBuf msgBuf = Unpooled.buffer(TRIPLET_BYTE_SIZE);
+        MultiprotocolCapabilitiesUtil.serializeMPAfiSafi(this.afiReg, this.safiReg, msg.getAfi(), msg.getSafi(), msgBuf);
+
+        LOG.trace("RouteRefresh message serialized to: {}", ByteBufUtil.hexDump(msgBuf));
+        MessageUtil.formatMessage(TYPE, msgBuf, bytes);
+    }
+
+    /**
+     * Parses BGP Route Refresh message to bytes.
+     *
+     * @param body ByteBuf to be parsed
+     * @param messageLength the length of the message
+     * @return {@link RouteRefresh} which represents BGP notification message
+     * @throws BGPDocumentedException if parsing goes wrong
+     */
+    @Override
+    public RouteRefresh parseMessageBody(final ByteBuf body, final int messageLength) throws BGPDocumentedException {
+        Preconditions.checkArgument(body != null, "Body buffer cannot be null.");
+        if (body.readableBytes() < TRIPLET_BYTE_SIZE) {
+            throw BGPDocumentedException.badMessageLength("RouteRefresh message is too small.", messageLength);
+        }
+        try {
+            final BgpTableType parsedAfiSafi = MultiprotocolCapabilitiesUtil.parseMPAfiSafi(body, this.afiReg, this.safiReg);
+            return new RouteRefreshBuilder().setAfi(parsedAfiSafi.getAfi()).setSafi(parsedAfiSafi.getSafi()).build();
+        } catch (final BGPParsingException e) {
+            throw new BGPDocumentedException("Unsupported afi/safi in Route Refresh message.", BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED);
+        }
+    }
+}
index 7bae54ea9c504288f317eb030cdeb5a0c7471624..8934837d2a303bc414077fa0e7c5d125857e2248 100644 (file)
@@ -16,15 +16,15 @@ import org.opendaylight.protocol.bgp.parser.spi.AddressFamilyRegistry;
 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.protocol.bgp.parser.spi.MultiprotocolCapabilitiesUtil;
 import org.opendaylight.protocol.bgp.parser.spi.SubsequentAddressFamilyRegistry;
 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.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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.MultiprotocolCapability;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.MultiprotocolCapabilityBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily;
 
 public final class MultiProtocolCapabilityHandler implements CapabilityParser, CapabilitySerializer {
     public static final int CODE = 1;
@@ -32,8 +32,6 @@ public final class MultiProtocolCapabilityHandler implements CapabilityParser, C
     private final AddressFamilyRegistry afiReg;
     private final SubsequentAddressFamilyRegistry safiReg;
 
-    private static final int RESERVED = 1;
-
     public MultiProtocolCapabilityHandler(final AddressFamilyRegistry afiReg, final SubsequentAddressFamilyRegistry safiReg) {
         this.afiReg = Preconditions.checkNotNull(afiReg);
         this.safiReg = Preconditions.checkNotNull(safiReg);
@@ -41,21 +39,10 @@ public final class MultiProtocolCapabilityHandler implements CapabilityParser, C
 
     @Override
     public CParameters parseCapability(final ByteBuf buffer) throws BGPDocumentedException, BGPParsingException {
-        final int afiVal = buffer.readUnsignedShort();
-        final Class<? extends AddressFamily> afi = this.afiReg.classForFamily(afiVal);
-        if (afi == null) {
-            throw new BGPParsingException("Address Family Identifier: '" + afiVal + "' not supported.");
-        }
-        // skip reserved
-        buffer.skipBytes(RESERVED);
-        final int safiVal = buffer.readUnsignedByte();
-        final Class<? extends SubsequentAddressFamily> safi = this.safiReg.classForFamily(safiVal);
-        if (safi == null) {
-            throw new BGPParsingException("Subsequent Address Family Identifier: '" + safiVal + "' not supported.");
-        }
+        final BgpTableType parsedAfiSafi = MultiprotocolCapabilitiesUtil.parseMPAfiSafi(buffer, this.afiReg, this.safiReg);
 
         return new CParametersBuilder().addAugmentation(CParameters1.class,new CParameters1Builder().setMultiprotocolCapability(
-            new MultiprotocolCapabilityBuilder().setAfi(afi).setSafi(safi).build()).build()).build();
+            new MultiprotocolCapabilityBuilder().setAfi(parsedAfiSafi.getAfi()).setSafi(parsedAfiSafi.getSafi()).build()).build()).build();
     }
 
     @Override
@@ -67,17 +54,9 @@ public final class MultiProtocolCapabilityHandler implements CapabilityParser, C
         final MultiprotocolCapability mp = capability.getAugmentation(CParameters1.class).getMultiprotocolCapability();
 
         final ByteBuf capBuffer = Unpooled.buffer();
-        final Class<? extends AddressFamily> afi = mp.getAfi();
-        final Integer afival = this.afiReg.numberForClass(afi);
-        Preconditions.checkArgument(afival != null, "Unhandled address family " + afi);
-        capBuffer.writeShort(afival);
-
-        final Class<? extends SubsequentAddressFamily> safi = mp.getSafi();
-        final Integer safival = this.safiReg.numberForClass(safi);
-        Preconditions.checkArgument(safival != null, "Unhandled subsequent address family " + safi);
-        capBuffer.writeZero(RESERVED);
-        capBuffer.writeByte(safival);
+        MultiprotocolCapabilitiesUtil.serializeMPAfiSafi(this.afiReg, this.safiReg, mp.getAfi(), mp.getSafi(), capBuffer);
 
         CapabilityUtil.formatCapability(CODE, capBuffer, byteAggregator);
     }
+
 }
\ No newline at end of file
index 4400b519d3530e7c4457f420e938d91bce8198e1..f16a587f653f41c28effff775d21db044790c142 100644 (file)
@@ -11,10 +11,10 @@ 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.MultiprotocolCapabilitiesUtil;
 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.protocol.bgp.parser.spi.MultiprotocolCapabilitiesUtil;
 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.multiprotocol.rev130919.CParameters1;
 
index 232a1f739ade55e7ba265724e4035c2eb6195e67..caa9ce1432c8d93503c0b2742fc7c96e3bb597c6 100644 (file)
@@ -14,7 +14,6 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import java.net.UnknownHostException;
@@ -34,6 +33,10 @@ 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;
 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.rev130919.ProtocolVersion;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.RouteRefresh;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.RouteRefreshBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
 import org.opendaylight.yangtools.yang.binding.Notification;
 
 public class ParserTest {
@@ -63,6 +66,10 @@ public class ParserTest {
         (byte) 0x04, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x72, (byte) 0x04, (byte) 0x04, (byte) 0x00, (byte) 0x04, (byte) 0x2b, (byte) 0x2b, (byte) 0x2b, (byte) 0x2b
     };
 
+    private static final byte[] RR_MSG = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+        (byte) 0xff, (byte) 0x00, (byte) 0x17, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01 };
+
     static MessageRegistry reg;
 
     @BeforeClass
@@ -131,7 +138,7 @@ public class ParserTest {
     @Test
     public void testOpenMessage() throws UnknownHostException, BGPParsingException, BGPDocumentedException {
         final Notification open = new OpenBuilder().setMyAsNumber(100).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("20.20.20.20")).setVersion(
-                new ProtocolVersion((short) 4)).build();
+            new ProtocolVersion((short) 4)).build();
         final ByteBuf bytes = Unpooled.buffer();
         ParserTest.reg.serializeMessage(open, bytes);
         assertArrayEquals(openBMsg, ByteArray.getAllBytes(bytes));
@@ -200,7 +207,7 @@ public class ParserTest {
     @Test
     public void testNotificationMsg() throws BGPParsingException, BGPDocumentedException {
         Notification notMsg = new NotifyBuilder().setErrorCode(BGPError.OPT_PARAM_NOT_SUPPORTED.getCode()).setErrorSubcode(
-                BGPError.OPT_PARAM_NOT_SUPPORTED.getSubcode()).setData(new byte[] { 4, 9 }).build();
+            BGPError.OPT_PARAM_NOT_SUPPORTED.getSubcode()).setData(new byte[] { 4, 9 }).build();
         final ByteBuf bytes = Unpooled.buffer();
         ParserTest.reg.serializeMessage(notMsg, bytes);
         assertArrayEquals(notificationBMsg, ByteArray.subByte(bytes.array(),0,bytes.writerIndex()));
@@ -270,4 +277,16 @@ public class ParserTest {
         }
         fail();
     }
+
+    @Test
+    public void testRouteRefreshMsg() throws BGPDocumentedException, BGPParsingException {
+        final Notification rrMsg = new RouteRefreshBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).build();
+        final ByteBuf buffer = Unpooled.buffer();
+        ParserTest.reg.serializeMessage(rrMsg, buffer);
+        assertArrayEquals(RR_MSG, ByteArray.getAllBytes(buffer));
+
+        final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(ByteArray.getAllBytes(buffer)));
+
+        assertTrue(m instanceof RouteRefresh);
+    }
 }
diff --git a/bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/MultiprotocolCapabilitiesUtil.java b/bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/MultiprotocolCapabilitiesUtil.java
new file mode 100644 (file)
index 0000000..a1679b5
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.spi;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
+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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.RouteRefreshCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily;
+
+public final class MultiprotocolCapabilitiesUtil {
+
+    public static final CParameters RR_CAPABILITY = new CParametersBuilder().addAugmentation(CParameters1.class,
+        new CParameters1Builder().setRouteRefreshCapability(new RouteRefreshCapabilityBuilder().build()).build()).build();
+
+    private static final int RESERVED = 1;
+
+    public static void serializeMPAfiSafi(final AddressFamilyRegistry afiReg, final SubsequentAddressFamilyRegistry safiReg,
+        final Class<? extends AddressFamily> afi, final Class<? extends SubsequentAddressFamily> safi, final ByteBuf capBuffer) {
+        final Integer afival = afiReg.numberForClass(afi);
+        Preconditions.checkArgument(afival != null, "Unhandled address family " + afi);
+        capBuffer.writeShort(afival);
+
+        capBuffer.writeZero(RESERVED);
+
+        final Integer safival = safiReg.numberForClass(safi);
+        Preconditions.checkArgument(safival != null, "Unhandled subsequent address family " + safi);
+        capBuffer.writeByte(safival);
+    }
+
+    public static BgpTableType parseMPAfiSafi(final ByteBuf buffer, final AddressFamilyRegistry afiReg, final SubsequentAddressFamilyRegistry safiReg) throws BGPParsingException {
+        final int afiVal = buffer.readUnsignedShort();
+        final Class<? extends AddressFamily> afi = afiReg.classForFamily(afiVal);
+        if (afi == null) {
+            throw new BGPParsingException("Address Family Identifier: '" + afiVal + "' not supported.");
+        }
+        // skip reserved
+        buffer.skipBytes(RESERVED);
+        final int safiVal = buffer.readUnsignedByte();
+        final Class<? extends SubsequentAddressFamily> safi = safiReg.classForFamily(safiVal);
+        if (safi == null) {
+            throw new BGPParsingException("Subsequent Address Family Identifier: '" + safiVal + "' not supported.");
+        }
+        return new BgpTableTypeImpl(afi, safi);
+    }
+}
index f570de1a71e6c057153f82d8dd4a5ae26d405c9f..fb5f9d0024b322ee174d7c30dac73fa479d6ec73 100644 (file)
@@ -8,22 +8,43 @@
 package org.opendaylight.protocol.bgp.parser.spi;
 
 import static org.junit.Assert.assertArrayEquals;
-
+import static org.junit.Assert.assertEquals;
 import com.google.common.primitives.UnsignedBytes;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.util.Arrays;
+import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
 import org.opendaylight.protocol.util.ByteArray;
+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.types.rev130919.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
 
 public class UtilsTest {
 
+    @Mock private AddressFamilyRegistry afiReg;
+    @Mock private SubsequentAddressFamilyRegistry safiReg;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        Mockito.doReturn(1).when(this.afiReg).numberForClass(Ipv4AddressFamily.class);
+        Mockito.doReturn(Ipv4AddressFamily.class).when(this.afiReg).classForFamily(1);
+
+        Mockito.doReturn(1).when(this.safiReg).numberForClass(UnicastSubsequentAddressFamily.class);
+        Mockito.doReturn(UnicastSubsequentAddressFamily.class).when(this.safiReg).classForFamily(1);
+    }
+
     @Test
     public void testCapabilityUtil() {
         final byte[] result = new byte[] { 1, 2, 4, 8 };
-        ByteBuf aggregator = Unpooled.buffer();
+        final ByteBuf aggregator = Unpooled.buffer();
         CapabilityUtil.formatCapability(1, Unpooled.wrappedBuffer(new byte[] { 4, 8 }),aggregator);
         assertArrayEquals(result, ByteArray.getAllBytes(aggregator));
     }
@@ -34,7 +55,7 @@ public class UtilsTest {
             UnsignedBytes.MAX_VALUE, UnsignedBytes.MAX_VALUE, UnsignedBytes.MAX_VALUE, UnsignedBytes.MAX_VALUE, UnsignedBytes.MAX_VALUE,
             UnsignedBytes.MAX_VALUE, UnsignedBytes.MAX_VALUE, UnsignedBytes.MAX_VALUE, UnsignedBytes.MAX_VALUE, UnsignedBytes.MAX_VALUE,
             UnsignedBytes.MAX_VALUE, UnsignedBytes.MAX_VALUE, UnsignedBytes.MAX_VALUE, 0, 23, 3, 32, 5, 14, 21 };
-        ByteBuf formattedMessage = Unpooled.buffer();
+        final ByteBuf formattedMessage = Unpooled.buffer();
         MessageUtil.formatMessage(3, Unpooled.wrappedBuffer(new byte[] { 32, 5, 14, 21 }), formattedMessage);
         assertArrayEquals(result, ByteArray.getAllBytes(formattedMessage));
     }
@@ -42,7 +63,7 @@ public class UtilsTest {
     @Test
     public void testParameterUtil() {
         final byte[] result = new byte[] { 1, 2, 4, 8 };
-        ByteBuf aggregator = Unpooled.buffer();
+        final ByteBuf aggregator = Unpooled.buffer();
         ParameterUtil.formatParameter(1, Unpooled.wrappedBuffer(new byte[] { 4, 8 }), aggregator);
         assertArrayEquals(result, ByteArray.getAllBytes(aggregator));
     }
@@ -50,7 +71,7 @@ public class UtilsTest {
     @Test
     public void testAttributeUtil() {
         final byte[] result = new byte[] { 0x40, 03, 04, 10, 00, 00, 02 };
-        ByteBuf aggregator = Unpooled.buffer();
+        final ByteBuf aggregator = Unpooled.buffer();
         AttributeUtil.formatAttribute(64 , 3 , Unpooled.wrappedBuffer(new byte[] { 10, 0, 0, 2 }), aggregator);
         assertArrayEquals(result, ByteArray.getAllBytes(aggregator));
     }
@@ -63,18 +84,31 @@ public class UtilsTest {
         final byte[] result = new byte[262];
         System.arraycopy(header, 0, result, 0, header.length);
         System.arraycopy(value, 0, result, 4, value.length);
-        ByteBuf aggregator = Unpooled.buffer();
+        final ByteBuf aggregator = Unpooled.buffer();
         AttributeUtil.formatAttribute(AttributeUtil.TRANSITIVE , 3 , Unpooled.wrappedBuffer(value), aggregator);
         assertArrayEquals(result, ByteArray.getAllBytes(aggregator));
     }
 
+    @Test
+    public void testMultiprotocolCapabilitiesUtil() throws BGPParsingException {
+        final byte[] bytes = new byte[] {0, 1, 0, 1};
+        final ByteBuf bytesBuf = Unpooled.copiedBuffer(bytes);
+        final BgpTableType parsedAfiSafi = MultiprotocolCapabilitiesUtil.parseMPAfiSafi(bytesBuf, this.afiReg, this.safiReg);
+        assertEquals(Ipv4AddressFamily.class, parsedAfiSafi.getAfi());
+        assertEquals(UnicastSubsequentAddressFamily.class, parsedAfiSafi.getSafi());
+
+        final ByteBuf serializedAfiSafi = Unpooled.buffer(4);
+        MultiprotocolCapabilitiesUtil.serializeMPAfiSafi(this.afiReg, this.safiReg, Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class, serializedAfiSafi);
+        assertArrayEquals(bytes, serializedAfiSafi.array());
+    }
+
     @Test(expected=UnsupportedOperationException.class)
     public void testAttributeUtilPrivateConstructor() throws Throwable {
         final Constructor<AttributeUtil> c = AttributeUtil.class.getDeclaredConstructor();
         c.setAccessible(true);
         try {
             c.newInstance();
-        } catch (InvocationTargetException e) {
+        } catch (final InvocationTargetException e) {
             throw e.getCause();
         }
     }
@@ -85,7 +119,7 @@ public class UtilsTest {
         c.setAccessible(true);
         try {
             c.newInstance();
-        } catch (InvocationTargetException e) {
+        } catch (final InvocationTargetException e) {
             throw e.getCause();
         }
     }
@@ -96,7 +130,7 @@ public class UtilsTest {
         c.setAccessible(true);
         try {
             c.newInstance();
-        } catch (InvocationTargetException e) {
+        } catch (final InvocationTargetException e) {
             throw e.getCause();
         }
     }
@@ -107,7 +141,7 @@ public class UtilsTest {
         c.setAccessible(true);
         try {
             c.newInstance();
-        } catch (InvocationTargetException e) {
+        } catch (final InvocationTargetException e) {
             throw e.getCause();
         }
     }
index 619043c13cc1e6ef861fd851a5dad5cea2281e19..60ff67a91f5fa50b86876b20989d4d2d831c72ad 100644 (file)
@@ -32,7 +32,7 @@ import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigProvider;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenconfigMapper;
 import org.opendaylight.protocol.bgp.openconfig.spi.InstanceConfigurationIdentifier;
 import org.opendaylight.protocol.bgp.openconfig.spi.pojo.BGPPeerInstanceConfiguration;
-import org.opendaylight.protocol.bgp.parser.MultiprotocolCapabilitiesUtil;
+import org.opendaylight.protocol.bgp.parser.spi.MultiprotocolCapabilitiesUtil;
 import org.opendaylight.protocol.bgp.rib.impl.BGPPeer;
 import org.opendaylight.protocol.bgp.rib.impl.StrictBGPPeerRegistry;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;