Bug 4827: Consumer specific parsers for BGP add-path 90/35590/15
authorMilos Fabian <milfabia@cisco.com>
Wed, 24 Feb 2016 07:49:24 +0000 (08:49 +0100)
committerRobert Varga <nite@hq.sk>
Wed, 20 Apr 2016 14:51:52 +0000 (14:51 +0000)
The BGP add-path introduces extended form of NLRI (path-id added)
but new NLRI is not distiguishable from regular NLRI
(i.e. code points are the same).
The add-path capabilities are neighbor specific and information
about supported capabilities is available once the session with
a peer goes up. Also the BGP extension provides read-only
consumption of handlers registers, hence easiest way is to pass
the consumer-specific add-path constrain via input arguments.

Extend parser's registers to handle user defined constraints.
Added new NLRI registrator for add-path NLRI parsers.
Added PeerSpecificParserConstraint which can carry any future
user specific constraint to be used during parsing process.
Added MultiPathSupport interface to carry peer's specific
add-path capabilities.

Change-Id: Ieb361c726bd67f74fc653d3423870659404f1b9d
Signed-off-by: Milos Fabian <milfabia@cisco.com>
20 files changed:
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPUpdateMessageParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPReachAttributeParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPUnreachAttributeParser.java
bgp/parser-mock/src/main/java/org/opendaylight/protocol/bgp/parser/mock/BGPMessageParserMock.java
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/AbstractMessageRegistry.java
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/AttributeParser.java
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/AttributeRegistry.java
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/MessageParser.java
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/MessageRegistry.java
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/MultiPathSupport.java [new file with mode: 0644]
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/NlriParser.java
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/NlriRegistry.java
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/PeerConstraint.java [new file with mode: 0644]
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/PeerSpecificParserConstraint.java [new file with mode: 0644]
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/pojo/SimpleAttributeRegistry.java
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/pojo/SimpleMessageRegistry.java
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/pojo/SimpleNlriRegistry.java
bgp/parser-spi/src/test/java/org/opendaylight/protocol/bgp/parser/spi/AbstractMessageRegistryTest.java
bgp/parser-spi/src/test/java/org/opendaylight/protocol/bgp/parser/spi/pojo/BgpTestActivator.java
bgp/parser-spi/src/test/java/org/opendaylight/protocol/bgp/parser/spi/pojo/SimpleRegistryTest.java

index bd28048a23f9e590c4660101fd0c9668cc0a7ddf..52a8313d47a1f57f15c0c44069e5914fc0c406d4 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.protocol.bgp.parser.spi.AttributeRegistry;
 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.PeerSpecificParserConstraint;
 import org.opendaylight.protocol.util.ByteArray;
 import org.opendaylight.protocol.util.ByteBufWriteUtil;
 import org.opendaylight.protocol.util.Ipv4Util;
@@ -57,37 +58,7 @@ public final class BGPUpdateMessageParser implements MessageParser, MessageSeria
 
     @Override
     public Update parseMessageBody(final ByteBuf buffer, final int messageLength) throws BGPDocumentedException {
-        Preconditions.checkArgument(buffer != null && buffer.isReadable(), "Buffer cannot be null or empty.");
-
-        final UpdateBuilder builder = new UpdateBuilder();
-
-        final int withdrawnRoutesLength = buffer.readUnsignedShort();
-        if (withdrawnRoutesLength > 0) {
-            final List<Ipv4Prefix> withdrawnRoutes = Ipv4Util.prefixListForBytes(ByteArray.readBytes(buffer, withdrawnRoutesLength));
-            builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setWithdrawnRoutes(withdrawnRoutes).build());
-        }
-        final int totalPathAttrLength = buffer.readUnsignedShort();
-
-        if (withdrawnRoutesLength == 0 && totalPathAttrLength == 0) {
-            return builder.build();
-        }
-        if (totalPathAttrLength > 0) {
-            try {
-                final Attributes pathAttributes = this.reg.parseAttributes(buffer.readSlice(totalPathAttrLength));
-                builder.setAttributes(pathAttributes);
-            } catch (final BGPParsingException | RuntimeException e) {
-                // Catch everything else and turn it into a BGPDocumentedException
-                LOG.warn("Could not parse BGP attributes", e);
-                throw new BGPDocumentedException("Could not parse BGP attributes.", BGPError.MALFORMED_ATTR_LIST, e);
-            }
-        }
-        final List<Ipv4Prefix> nlri = Ipv4Util.prefixListForBytes(ByteArray.readAllBytes(buffer));
-        if (!nlri.isEmpty()) {
-            builder.setNlri(new NlriBuilder().setNlri(nlri).build());
-        }
-        final Update msg = builder.build();
-        LOG.debug("BGP Update message was parsed {}.", msg);
-        return msg;
+        return parseMessageBody(buffer, messageLength, null);
     }
 
     @Override
@@ -123,4 +94,41 @@ public final class BGPUpdateMessageParser implements MessageParser, MessageSeria
         }
         MessageUtil.formatMessage(TYPE, messageBody, bytes);
     }
+
+    @Override
+    public Update parseMessageBody(final ByteBuf buffer, final int messageLength, final PeerSpecificParserConstraint constraint)
+            throws BGPDocumentedException {
+        Preconditions.checkArgument(buffer != null && buffer.isReadable(), "Buffer cannot be null or empty.");
+
+        final UpdateBuilder builder = new UpdateBuilder();
+
+        final int withdrawnRoutesLength = buffer.readUnsignedShort();
+        if (withdrawnRoutesLength > 0) {
+            // TODO handle NLRI with multiple paths - requires modified yang data model
+            final List<Ipv4Prefix> withdrawnRoutes = Ipv4Util.prefixListForBytes(ByteArray.readBytes(buffer, withdrawnRoutesLength));
+            builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setWithdrawnRoutes(withdrawnRoutes).build());
+        }
+        final int totalPathAttrLength = buffer.readUnsignedShort();
+
+        if (withdrawnRoutesLength == 0 && totalPathAttrLength == 0) {
+            return builder.build();
+        }
+        if (totalPathAttrLength > 0) {
+            try {
+                final Attributes attributes = this.reg.parseAttributes(buffer.readSlice(totalPathAttrLength), constraint);
+                builder.setAttributes(attributes);
+            } catch (final RuntimeException | BGPParsingException e) {
+                // Catch everything else and turn it into a BGPDocumentedException
+                throw new BGPDocumentedException("Could not parse BGP attributes.", BGPError.MALFORMED_ATTR_LIST, e);
+            }
+        }
+        final List<Ipv4Prefix> nlri = Ipv4Util.prefixListForBytes(ByteArray.readAllBytes(buffer));
+        if (!nlri.isEmpty()) {
+            // TODO handle NLRI with multiple paths - requires modified yang data model
+            builder.setNlri(new NlriBuilder().setNlri(nlri).build());
+        }
+        final Update msg = builder.build();
+        LOG.debug("BGP Update message was parsed {}.", msg);
+        return msg;
+    }
 }
index 27997fa8eae27401816c4a940578d61a1a8146a1..6bb57cdd6923f09db3f43b1dec19c48acca23d68 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
 import org.opendaylight.protocol.bgp.parser.spi.AttributeUtil;
 import org.opendaylight.protocol.bgp.parser.spi.NlriRegistry;
 import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
+import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AttributesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
@@ -38,8 +39,15 @@ public final class MPReachAttributeParser implements AttributeParser, AttributeS
 
     @Override
     public void parseAttribute(final ByteBuf buffer, final AttributesBuilder builder) throws BGPDocumentedException {
+        parseAttribute(buffer, builder, null);
+    }
+
+    @Override
+    public void parseAttribute(final ByteBuf buffer, final AttributesBuilder builder, final PeerSpecificParserConstraint constraint)
+            throws BGPDocumentedException {
         try {
-            final Attributes1 a = new Attributes1Builder().setMpReachNlri(this.reg.parseMpReach(buffer)).build();
+            final MpReachNlri mpReachNlri = this.reg.parseMpReach(buffer, constraint);
+            final Attributes1 a = new Attributes1Builder().setMpReachNlri(mpReachNlri).build();
             builder.addAugmentation(Attributes1.class, a);
         } catch (final BGPParsingException e) {
             throw new BGPDocumentedException("Could not parse MP_REACH_NLRI", BGPError.OPT_ATTR_ERROR, e);
index d4461265b051b9c82a478288991fe763a1505f47..33da3e066a0a0f95cf48d17b1b5d4396ea0621f7 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
 import org.opendaylight.protocol.bgp.parser.spi.AttributeUtil;
 import org.opendaylight.protocol.bgp.parser.spi.NlriRegistry;
 import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
+import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AttributesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
@@ -36,8 +37,15 @@ public final class MPUnreachAttributeParser implements AttributeParser, Attribut
 
     @Override
     public void parseAttribute(final ByteBuf buffer, final AttributesBuilder builder) throws BGPDocumentedException {
+        parseAttribute(buffer, builder, null);
+    }
+
+    @Override
+    public void parseAttribute(final ByteBuf buffer, final AttributesBuilder builder, final PeerSpecificParserConstraint constraint)
+            throws BGPDocumentedException {
         try {
-            final Attributes2 a = new Attributes2Builder().setMpUnreachNlri(this.reg.parseMpUnreach(buffer)).build();
+            final MpUnreachNlri mpUnreachNlri = this.reg.parseMpUnreach(buffer, constraint);
+            final Attributes2 a = new Attributes2Builder().setMpUnreachNlri(mpUnreachNlri).build();
             builder.addAugmentation(Attributes2.class, a);
         } catch (final BGPParsingException e) {
             throw new BGPDocumentedException("Could not parse MP_UNREACH_NLRI", BGPError.OPT_ATTR_ERROR, e);
index 43aa10638a28bba8241d6702a77fff7e320e222a..2b1460d876e893c2262522b8f10ecc1b95fac97f 100644 (file)
@@ -13,6 +13,7 @@ import java.util.Map;
 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
 import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry;
+import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
 import org.opendaylight.yangtools.yang.binding.Notification;
 
 /**
@@ -44,4 +45,10 @@ public class BGPMessageParserMock implements MessageRegistry {
         // no action needed, it's a mock for parsing, not serializing
         return;
     }
+
+    @Override
+    public Notification parseMessage(final ByteBuf bytes, final PeerSpecificParserConstraint constraint)
+            throws BGPDocumentedException, BGPParsingException {
+        return parseMessage(bytes);
+    }
 }
index 14aa5d9f52534b98885173f36de2cf152f6c5277..10bcae982b5e5d0f79b6a6b9e561699f238b0f42 100644 (file)
@@ -21,7 +21,8 @@ public abstract class AbstractMessageRegistry implements MessageRegistry {
 
     private static final byte[] MARKER;
 
-    protected abstract Notification parseBody(final int type, final ByteBuf body, final int messageLength) throws BGPDocumentedException;
+    protected abstract Notification parseBody(int type, ByteBuf body, int messageLength,
+            PeerSpecificParserConstraint constraint) throws BGPDocumentedException;
 
     protected abstract void serializeMessageImpl(final Notification message, final ByteBuf buffer);
 
@@ -32,6 +33,12 @@ public abstract class AbstractMessageRegistry implements MessageRegistry {
 
     @Override
     public final Notification parseMessage(final ByteBuf buffer) throws BGPDocumentedException, BGPParsingException {
+        return parseMessage(buffer, null);
+    }
+
+    @Override
+    public Notification parseMessage(final ByteBuf buffer, final PeerSpecificParserConstraint constraint)
+            throws BGPDocumentedException, BGPParsingException {
         Preconditions.checkArgument(buffer != null && buffer.isReadable(), "Array of bytes cannot be null or empty.");
         Preconditions.checkArgument(buffer.readableBytes() >= MessageUtil.COMMON_HEADER_LENGTH,
                 "Too few bytes in passed array. Passed: %s. Expected: >= %s.", buffer.readableBytes(), MessageUtil.COMMON_HEADER_LENGTH);
@@ -56,7 +63,7 @@ public abstract class AbstractMessageRegistry implements MessageRegistry {
 
         final ByteBuf msgBody = buffer.readSlice(messageLength - MessageUtil.COMMON_HEADER_LENGTH);
 
-        final Notification msg = parseBody(messageType, msgBody, messageLength);
+        final Notification msg = parseBody(messageType, msgBody, messageLength, constraint);
         if (msg == null) {
             throw new BGPDocumentedException("Unhandled message type " + messageType, BGPError.BAD_MSG_TYPE, new byte[] { typeBytes });
         }
index 3704c9acc19ff5c08b09132ee394db75e70f728b..f1806785592623c1d242eb03f5d172e426f1e90f 100644 (file)
@@ -8,6 +8,8 @@
 package org.opendaylight.protocol.bgp.parser.spi;
 
 import io.netty.buffer.ByteBuf;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AttributesBuilder;
@@ -17,11 +19,26 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
  */
 public interface AttributeParser {
     /**
-     * Parses attribute from ByteBuf buffer
+     * Parses attribute from ByteBuf buffer.
      *
-     * @param buffer encoded attribute body in Bytebuf
+     * @param buffer Encoded attribute body in ByteBuf.
      * @param builder Path attributes builder. Guaranteed to contain all valid attributes whose type is numerically
      *        lower than this attribute's type.
      */
-    void parseAttribute(final ByteBuf buffer, AttributesBuilder builder) throws BGPDocumentedException, BGPParsingException;
+    void parseAttribute(@Nonnull ByteBuf buffer, @Nonnull AttributesBuilder builder) throws BGPDocumentedException, BGPParsingException;
+
+    /**
+     * Invokes {@link #parseAttribute(ByteBuf, AttributesBuilder)}, so the constraint is omitted. Override for specific parser behavior.
+     *
+     * @param buffer Encoded attribute body in ByteBuf.
+     * @param builder Path attributes builder. Guaranteed to contain all valid attributes whose type is numerically
+     *        lower than this attribute's type.
+     * @param constraint Peer specific constraints.
+     * @throws BGPDocumentedException
+     * @throws BGPParsingException
+     */
+    default void parseAttribute(@Nonnull final ByteBuf buffer, @Nonnull final AttributesBuilder builder, @Nullable final PeerSpecificParserConstraint constraint)
+            throws BGPDocumentedException, BGPParsingException {
+        parseAttribute(buffer, builder);
+    }
 }
index f1f0208907e07ffa96fba80592e03b9d107ef79b..97bdd0cc1cf271a795c80cbc4f488e2454d69819 100644 (file)
@@ -8,14 +8,39 @@
 package org.opendaylight.protocol.bgp.parser.spi;
 
 import io.netty.buffer.ByteBuf;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 
+/**
+ *
+ */
 public interface AttributeRegistry {
 
-    Attributes parseAttributes(final ByteBuf buffer) throws BGPDocumentedException, BGPParsingException;
+    /**
+     * @deprecated Use {@link #parseAttributes(ByteBuf, PeerSpecificParserConstraint)}
+     */
+    @Deprecated
+    Attributes parseAttributes(ByteBuf buffer) throws BGPDocumentedException, BGPParsingException;
+
+    /**
+     * Parse BGP Attribute from buffer.
+     * @param buffer Input buffer.
+     * @param constraints Peer specific constraint.
+     * @return Decoded BGP Attribute.
+     * @throws BGPDocumentedException
+     * @throws BGPParsingException
+     */
+    @Nonnull Attributes parseAttributes(@Nonnull ByteBuf buffer, @Nullable PeerSpecificParserConstraint constraints)
+            throws BGPDocumentedException, BGPParsingException;
 
-    void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator);
+    /**
+     * Serialize BGP Attribute to buffer.
+     * @param attribute Input BGP Attribute.
+     * @param byteAggregator Output buffer.
+     */
+    void serializeAttribute(@Nonnull DataObject attribute, @Nonnull ByteBuf byteAggregator);
 }
index 0c9eec0814eabb66cfac4321a94568ae0938c472..8aa884a3b369a585dcbd7ace15704ba779fe1129 100644 (file)
@@ -8,10 +8,37 @@
 package org.opendaylight.protocol.bgp.parser.spi;
 
 import io.netty.buffer.ByteBuf;
-
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
 import org.opendaylight.yangtools.yang.binding.Notification;
 
+/**
+ * Common interface for message parser implementation.
+ */
 public interface MessageParser {
-    Notification parseMessageBody(ByteBuf body, int messageLength) throws BGPDocumentedException;
+
+    /**
+     * Parse BGP Message from buffer.
+     *
+     * @param body Encoded BGP message in ByteBuf.
+     * @param messageLength Length of the BGP message.
+     * @return Parsed BGP Message body.
+     * @throws BGPDocumentedException
+     */
+    @Nonnull Notification parseMessageBody(@Nonnull ByteBuf body, int messageLength) throws BGPDocumentedException;
+
+    /**
+     * Invokes {@link #parseMessageBody(ByteBuf, int)}, so the constraint is omitted. Override for specific parser behavior.
+     *
+     * @param body Encoded BGP message in ByteBuf.
+     * @param messageLength Length of the BGP message.
+     * @param constraint Peer specific constraints.
+     * @return Parsed BGP Message body.
+     * @throws BGPDocumentedException
+     */
+    @Nonnull default Notification parseMessageBody(@Nonnull final ByteBuf body, final int messageLength, @Nullable final PeerSpecificParserConstraint constraint)
+            throws BGPDocumentedException {
+        return parseMessageBody(body, messageLength);
+    }
 }
index 8c2da168dacb1b5fc352b44521e038e064bde22b..3ee9f5f763278abf7636b3da48fea0e99a89542d 100644 (file)
@@ -8,14 +8,40 @@
 package org.opendaylight.protocol.bgp.parser.spi;
 
 import io.netty.buffer.ByteBuf;
-
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
 import org.opendaylight.yangtools.yang.binding.Notification;
 
+/**
+ * BGP Message codec registry, provides services
+ * to encode/decode messages.
+ */
 public interface MessageRegistry {
 
-    Notification parseMessage(final ByteBuf bytes) throws BGPDocumentedException, BGPParsingException;
+    /**
+     * @deprecated Use {@link #parseMessage(ByteBuf, PeerSpecificParserConstraint)}
+     */
+    @Deprecated
+    Notification parseMessage(ByteBuf bytes) throws BGPDocumentedException, BGPParsingException;
+
+    /**
+     * Decode input buffer to BGP Message.
+     * @param bytes Input buffer with encoded message.
+     * @param constraint Peer specific constraint.
+     * @return Parsed BGP message.
+     * @throws BGPDocumentedException
+     * @throws BGPParsingException
+     */
+    @Nonnull Notification parseMessage(@Nonnull ByteBuf bytes, @Nullable PeerSpecificParserConstraint constraint)
+            throws BGPDocumentedException, BGPParsingException;
+
+    /**
+     * Encode input BGP Message to output buffer.
+     * @param message Input BGP Message to be serialized.
+     * @param buffer Output buffer where message is to be written.
+     */
+    void serializeMessage(@Nonnull Notification message, @Nonnull ByteBuf buffer);
 
-    void serializeMessage(final Notification message, final ByteBuf buffer);
 }
diff --git a/bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/MultiPathSupport.java b/bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/MultiPathSupport.java
new file mode 100644 (file)
index 0000000..65f7242
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
+
+/**
+ * Holds user specific add-path constraints per AFI/SAFI (table type)
+ *
+ */
+public interface MultiPathSupport extends PeerConstraint {
+
+    /**
+     * Check if requested AFI/SAFI is supported.
+     * @param tableType
+     * @return True if the table type is supported.
+     */
+    boolean isTableTypeSupported(BgpTableType tableType);
+
+}
index 0b5fd233c970f699b1791b145e9cbd7bb72037a9..e8557807ca09b5dfa6a7d3a88435b865a1ac61c3 100644 (file)
@@ -8,12 +8,58 @@
 package org.opendaylight.protocol.bgp.parser.spi;
 
 import io.netty.buffer.ByteBuf;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder;
 
+/**
+ * Common interface for NLRI parser implementation.
+ */
 public interface NlriParser {
-    void parseNlri(ByteBuf nlri, MpUnreachNlriBuilder builder) throws BGPParsingException;
 
-    void parseNlri(ByteBuf nlri, MpReachNlriBuilder builder) throws BGPParsingException;
+    /**
+     * Parse MP UN_REACH NLRI from buffer.
+     *
+     * @param nlri Encoded unreachabel NLRI in ByteBuf.
+     * @param builder MP UNREACH NLRI builder.
+     * @throws BGPParsingException
+     */
+    void parseNlri(@Nonnull ByteBuf nlri, @Nonnull MpUnreachNlriBuilder builder) throws BGPParsingException;
+
+    /**
+     * Parse MP REACH NLRI from buffer.
+     *
+     * @param nlri Encoded reachable NLRI in ByteBuf.
+     * @param builder MP REACH NLRI builder.
+     * @throws BGPParsingException
+     */
+    void parseNlri(@Nonnull ByteBuf nlri, @Nonnull MpReachNlriBuilder builder) throws BGPParsingException;
+
+    /**
+     * Invokes {@link #parseNlri(ByteBuf, MpReachNlriBuilder)}, so the constraint is omitted. Override for specific parser behavior.
+     *
+     * @param nlri Encoded reachable NLRI in ByteBuf.
+     * @param builder MP REACH NLRI builder.
+     * @param constraint Peer specific constraints.
+     * @throws BGPParsingException
+     */
+    default void parseNlri(@Nonnull final ByteBuf nlri, @Nonnull final MpReachNlriBuilder builder, @Nullable final PeerSpecificParserConstraint constraint)
+            throws BGPParsingException {
+        parseNlri(nlri, builder);
+    }
+
+    /**
+     * Invokes {@link #parseNlri(ByteBuf, MpUnreachNlriBuilder)}, so the constraint is omitted. Override for specific parser behavior.
+     *
+     * @param nlri Encoded unreachable NLRI in ByteBuf.
+     * @param builder MP UNREACH NLRI builder.
+     * @param constraint Peer specific constraints.
+     * @throws BGPParsingException
+     */
+    default void parseNlri(@Nonnull final ByteBuf nlri, @Nonnull final MpUnreachNlriBuilder builder, @Nullable final PeerSpecificParserConstraint constraint)
+            throws BGPParsingException {
+        parseNlri(nlri, builder);
+    }
 }
index 65f72a188a01ec7e93887c6c82f0b3f4fcfd915e..133443b2f8fc00998c6b46a3d786c349feda3664 100644 (file)
@@ -8,14 +8,66 @@
 package org.opendaylight.protocol.bgp.parser.spi;
 
 import io.netty.buffer.ByteBuf;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlri;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlri;
 
+/**
+ * The codec registry for BGP NLRI, offers
+ * services for NLRI encoding/decoding.
+ *
+ */
 public interface NlriRegistry {
-    MpReachNlri parseMpReach(final ByteBuf buffer) throws BGPParsingException;
-    MpUnreachNlri parseMpUnreach(final ByteBuf buffer) throws BGPParsingException;
-    void serializeMpReach(final MpReachNlri mpReachNlri,final ByteBuf byteAggregator);
-    void serializeMpUnReach(final MpUnreachNlri mpUnreachNlri,final ByteBuf byteAggregator);
+
+    /**
+     * @deprecated Use {@link #parseMpReach(ByteBuf, PeerSpecificParserConstraint)}
+     */
+    @Deprecated
+    MpReachNlri parseMpReach(ByteBuf buffer) throws BGPParsingException;
+
+    /**
+     * @deprecated Use {@link #parseMpUnreach(ByteBuf, PeerSpecificParserConstraint)}
+     */
+    @Deprecated
+    MpUnreachNlri parseMpUnreach(ByteBuf buffer) throws BGPParsingException;
+
+    /**
+     * Decode MP REACH NLRI Attribute.
+     * @param buffer Input buffer.
+     * @param constraint Peer specific constraint.
+     * @return Parsed reach NLRI.
+     * @throws BGPParsingException
+     */
+    @Nonnull MpReachNlri parseMpReach(@Nonnull ByteBuf buffer, @Nullable PeerSpecificParserConstraint constraint) throws BGPParsingException;
+
+    /**
+     * Decode MP REACH NLRI Attribute.
+     * @param buffer Input buffer.
+     * @param constraint Peer specific constraint.
+     * @return Parsed unreach NLRI.
+     * @throws BGPParsingException
+     */
+    @Nonnull MpUnreachNlri parseMpUnreach(@Nonnull ByteBuf buffer, @Nullable PeerSpecificParserConstraint constraint) throws BGPParsingException;
+
+    /**
+     * Encode BGP MP REACH NLRI Attribute.
+     * @param mpReachNlri Input reach NLRI.
+     * @param byteAggregator Output buffer.
+     */
+    void serializeMpReach(@Nonnull MpReachNlri mpReachNlri, @Nonnull ByteBuf byteAggregator);
+
+    /**
+     * Encode BGP MP UNREACH NLRI Attribute.
+     * @param mpUnreachNlri Input unreach NLRI.
+     * @param byteAggregator Output buffer.
+     */
+    void serializeMpUnReach(@Nonnull MpUnreachNlri mpUnreachNlri, @Nonnull ByteBuf byteAggregator);
+
+    /**
+     * Get all available NLRI encoders.
+     * @return Iterable of NLRI serializers.
+     */
     Iterable<NlriSerializer> getSerializers();
 }
diff --git a/bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/PeerConstraint.java b/bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/PeerConstraint.java
new file mode 100644 (file)
index 0000000..f40902b
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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;
+
+/**
+ * Marker interface for BGP peer specific constraints.
+ *
+ */
+public interface PeerConstraint {
+
+}
diff --git a/bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/PeerSpecificParserConstraint.java b/bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/PeerSpecificParserConstraint.java
new file mode 100644 (file)
index 0000000..b1ac40d
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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 java.util.Optional;
+import javax.annotation.Nonnull;
+
+/**
+ * Holds BGP peer specific constraints of PDU processing.
+ *
+ */
+public interface PeerSpecificParserConstraint {
+
+    /**
+     * Looks-up and optionally returns {@link PeerConstraint} service.
+     * @param peerConstraintType Class type of the service.
+     * @return Optional of the required service, absent if the service is not available.
+     */
+    @Nonnull <T extends PeerConstraint> Optional<T> getPeerConstraint(@Nonnull Class<T> peerConstraintType);
+
+}
index 923bb575096210ee118f47a7d5f540b18c5184e4..85152dc46ba4cd7ad0aba520fee8b4320acbe34d 100644 (file)
@@ -22,6 +22,7 @@ import org.opendaylight.protocol.bgp.parser.BGPParsingException;
 import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
 import org.opendaylight.protocol.bgp.parser.spi.AttributeRegistry;
 import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
+import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
 import org.opendaylight.protocol.concepts.AbstractRegistration;
 import org.opendaylight.protocol.concepts.HandlerRegistry;
 import org.opendaylight.protocol.util.BitArray;
@@ -82,24 +83,15 @@ final class SimpleAttributeRegistry implements AttributeRegistry {
         };
     }
 
-    private void addAttribute(final ByteBuf buffer, final Map<Integer, RawAttribute> attributes) throws BGPDocumentedException {
+    private void addAttribute(final ByteBuf buffer, final Map<Integer, RawAttribute> attributes)
+            throws BGPDocumentedException {
         final BitArray flags = BitArray.valueOf(buffer.readByte());
         final int type = buffer.readUnsignedByte();
         final int len = (flags.get(EXTENDED_LENGTH_BIT)) ? buffer.readUnsignedShort() : buffer.readUnsignedByte();
         if (!attributes.containsKey(type)) {
             final AttributeParser parser = this.handlers.getParser(type);
             if (parser == null) {
-                if (!flags.get(OPTIONAL_BIT)) {
-                    throw new BGPDocumentedException("Well known attribute not recognized.", BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED);
-                }
-                final UnrecognizedAttributes unrecognizedAttribute = new UnrecognizedAttributesBuilder()
-                    .setKey(new UnrecognizedAttributesKey((short)type))
-                    .setPartial(flags.get(PARTIAL_BIT))
-                    .setTransitive(flags.get(TRANSITIVE_BIT))
-                    .setType((short)type)
-                    .setValue(ByteArray.readBytes(buffer, len)).build();
-                this.unrecognizedAttributes.add(unrecognizedAttribute);
-                LOG.debug("Unrecognized attribute were parsed: {}", unrecognizedAttribute);
+                processUnrecognized(flags, type, buffer, len);
             } else {
                 attributes.put(type, new RawAttribute(parser, buffer.readSlice(len)));
             }
@@ -108,8 +100,28 @@ final class SimpleAttributeRegistry implements AttributeRegistry {
         }
     }
 
+    private void processUnrecognized(final BitArray flags, final int type, final ByteBuf buffer, final int len) throws BGPDocumentedException {
+        if (!flags.get(OPTIONAL_BIT)) {
+            throw new BGPDocumentedException("Well known attribute not recognized.", BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED);
+        }
+        final UnrecognizedAttributes unrecognizedAttribute = new UnrecognizedAttributesBuilder()
+            .setKey(new UnrecognizedAttributesKey((short) type))
+            .setPartial(flags.get(PARTIAL_BIT))
+            .setTransitive(flags.get(TRANSITIVE_BIT))
+            .setType((short) type)
+            .setValue(ByteArray.readBytes(buffer, len)).build();
+        this.unrecognizedAttributes.add(unrecognizedAttribute);
+        LOG.debug("Unrecognized attribute were parsed: {}", unrecognizedAttribute);
+    }
+
     @Override
     public Attributes parseAttributes(final ByteBuf buffer) throws BGPDocumentedException, BGPParsingException {
+        return parseAttributes(buffer, null);
+    }
+
+    @Override
+    public Attributes parseAttributes(final ByteBuf buffer, final PeerSpecificParserConstraint constraint)
+            throws BGPDocumentedException, BGPParsingException {
         final Map<Integer, RawAttribute> attributes = new TreeMap<>();
         while (buffer.isReadable()) {
             addAttribute(buffer, attributes);
@@ -123,7 +135,7 @@ final class SimpleAttributeRegistry implements AttributeRegistry {
             LOG.debug("Parsing attribute type {}", e.getKey());
 
             final RawAttribute a = e.getValue();
-            a.parser.parseAttribute(a.buffer, builder);
+            a.parser.parseAttribute(a.buffer, builder, constraint);
         }
         builder.setUnrecognizedAttributes(this.unrecognizedAttributes);
         return builder.build();
index dbeee1d9b43c209155dc2215283c41dd035da589..e8f036d1a5d7497691bc18f05a58a8cd53cfcd0b 100644 (file)
@@ -8,11 +8,11 @@
 package org.opendaylight.protocol.bgp.parser.spi.pojo;
 
 import io.netty.buffer.ByteBuf;
-
 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
 import org.opendaylight.protocol.bgp.parser.spi.AbstractMessageRegistry;
 import org.opendaylight.protocol.bgp.parser.spi.MessageParser;
 import org.opendaylight.protocol.bgp.parser.spi.MessageSerializer;
+import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
 import org.opendaylight.protocol.concepts.HandlerRegistry;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.Notification;
@@ -22,13 +22,13 @@ final class SimpleMessageRegistry extends AbstractMessageRegistry {
     private final HandlerRegistry<DataContainer, MessageParser, MessageSerializer> handlers = new HandlerRegistry<>();
 
     @Override
-    protected Notification parseBody(final int type, final ByteBuf body, final int messageLength) throws BGPDocumentedException {
+    protected Notification parseBody(final int type, final ByteBuf body, final int messageLength,
+            final PeerSpecificParserConstraint constraint) throws BGPDocumentedException {
         final MessageParser parser = this.handlers.getParser(type);
         if (parser == null) {
             return null;
         }
-
-        return parser.parseMessageBody(body, messageLength);
+        return parser.parseMessageBody(body, messageLength, constraint);
     }
 
     @Override
index 2f0e8d05656f2b5248340efb8389c0b350be1464..4b99349c2509daa1abf702e57bca1a60173b2850 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.protocol.bgp.parser.spi.NextHopParserSerializer;
 import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
 import org.opendaylight.protocol.bgp.parser.spi.NlriRegistry;
 import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
+import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
 import org.opendaylight.protocol.bgp.parser.spi.SubsequentAddressFamilyRegistry;
 import org.opendaylight.protocol.concepts.AbstractRegistration;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
@@ -140,13 +141,20 @@ final class SimpleNlriRegistry implements NlriRegistry {
 
     @Override
     public MpUnreachNlri parseMpUnreach(final ByteBuf buffer) throws BGPParsingException {
+        return parseMpUnreach(buffer, null);
+    }
+
+    @Override
+    public MpUnreachNlri parseMpUnreach(final ByteBuf buffer, final PeerSpecificParserConstraint constraint)
+            throws BGPParsingException {
         final MpUnreachNlriBuilder builder = new MpUnreachNlriBuilder();
         builder.setAfi(getAfi(buffer));
         builder.setSafi(getSafi(buffer));
 
-        final NlriParser parser = this.handlers.get(createKey(builder.getAfi(), builder.getSafi()));
         final ByteBuf nlri = buffer.slice();
-        parser.parseNlri(nlri, builder);
+        final BgpTableType key = createKey(builder.getAfi(), builder.getSafi());
+        final NlriParser parser = this.handlers.get(key);
+        parser.parseNlri(nlri, builder, constraint);
         return builder.build();
     }
 
@@ -192,6 +200,12 @@ final class SimpleNlriRegistry implements NlriRegistry {
 
     @Override
     public MpReachNlri parseMpReach(final ByteBuf buffer) throws BGPParsingException {
+        return parseMpReach(buffer, null);
+    }
+
+    @Override
+    public MpReachNlri parseMpReach(final ByteBuf buffer, final PeerSpecificParserConstraint constraint)
+            throws BGPParsingException {
         final MpReachNlriBuilder builder = new MpReachNlriBuilder();
         final Class<? extends AddressFamily> afi = getAfi(buffer);
         final Class<? extends SubsequentAddressFamily> safi = getSafi(buffer);
@@ -199,7 +213,6 @@ final class SimpleNlriRegistry implements NlriRegistry {
         builder.setSafi(safi);
 
         final BgpTableType key = createKey(builder.getAfi(), builder.getSafi());
-        final NlriParser parser = this.handlers.get(key);
 
         final int nextHopLength = buffer.readUnsignedByte();
         if (nextHopLength != 0) {
@@ -214,7 +227,8 @@ final class SimpleNlriRegistry implements NlriRegistry {
         buffer.skipBytes(RESERVED);
 
         final ByteBuf nlri = buffer.slice();
-        parser.parseNlri(nlri, builder);
+        final NlriParser parser = this.handlers.get(key);
+        parser.parseNlri(nlri, builder, constraint);
         return builder.build();
     }
 }
index eaef04d144d3ca1bbd3988a5b1101c29aa92bd05..97ac39437c38c51128c6d41f164b620b2e5f199c 100644 (file)
@@ -38,7 +38,8 @@ public class AbstractMessageRegistryTest {
         }
 
         @Override
-        protected Notification parseBody(final int type, final ByteBuf body, final int messageLength) throws BGPDocumentedException {
+        protected Notification parseBody(final int type, final ByteBuf body, final int messageLength,
+                final PeerSpecificParserConstraint constraint) throws BGPDocumentedException {
             return new KeepaliveBuilder().build();
         }
     };
index 39aa04e1a589bce7eb9e22467510a55cf01c0471..e8c38958a8f970fd1d5af18606c999b7cc0cfbb8 100644 (file)
@@ -30,6 +30,7 @@ import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
 import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
 import org.opendaylight.protocol.bgp.parser.spi.ParameterParser;
 import org.opendaylight.protocol.bgp.parser.spi.ParameterSerializer;
+import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
 import org.opendaylight.protocol.bgp.parser.spi.extended.community.ExtendedCommunityParser;
 import org.opendaylight.protocol.bgp.parser.spi.extended.community.ExtendedCommunitySerializer;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
@@ -136,7 +137,8 @@ public class BgpTestActivator extends AbstractBGPExtensionProviderActivator {
     private void initMock() {
         MockitoAnnotations.initMocks(this);
         try {
-            Mockito.doNothing().when(this.attrParser).parseAttribute(Mockito.any(ByteBuf.class), Mockito.any(AttributesBuilder.class));
+            Mockito.doNothing().when(this.attrParser).parseAttribute(Mockito.any(ByteBuf.class), Mockito.any(AttributesBuilder.class),
+                    Mockito.any(PeerSpecificParserConstraint.class));
             Mockito.doReturn(EMPTY).when(this.attrParser).toString();
             Mockito.doNothing().when(this.attrSerializer).serializeAttribute(Mockito.any(DataObject.class), Mockito.any(ByteBuf.class));
             Mockito.doReturn(EMPTY).when(this.attrSerializer).toString();
@@ -151,14 +153,16 @@ public class BgpTestActivator extends AbstractBGPExtensionProviderActivator {
             Mockito.doNothing().when(this.capaSerializer).serializeCapability(Mockito.any(CParameters.class), Mockito.any(ByteBuf.class));
             Mockito.doReturn(EMPTY).when(this.capaSerializer).toString();
 
-            Mockito.doReturn(Mockito.mock(Notification.class)).when(this.msgParser).parseMessageBody(Mockito.any(ByteBuf.class), Mockito.anyInt());
+            Mockito.doReturn(Mockito.mock(Notification.class)).when(this.msgParser).parseMessageBody(Mockito.any(ByteBuf.class), Mockito.anyInt(),
+                    Mockito.any(PeerSpecificParserConstraint.class));
             Mockito.doReturn(EMPTY).when(this.msgParser).toString();
             Mockito.doNothing().when(this.msgSerializer).serializeMessage(Mockito.any(Notification.class), Mockito.any(ByteBuf.class));
             Mockito.doReturn(EMPTY).when(this.msgSerializer).toString();
 
-            Mockito.doNothing().when(this.nlriParser).parseNlri(Mockito.any(ByteBuf.class), Mockito.any(MpUnreachNlriBuilder.class));
-            Mockito.doNothing().when(this.nlriParser).parseNlri(Mockito.any(ByteBuf.class), Mockito.any(MpReachNlriBuilder.class));
+            Mockito.doNothing().when(this.nlriParser).parseNlri(Mockito.any(ByteBuf.class), Mockito.any(MpUnreachNlriBuilder.class), Mockito.any());
+            Mockito.doNothing().when(this.nlriParser).parseNlri(Mockito.any(ByteBuf.class), Mockito.any(MpReachNlriBuilder.class), Mockito.any());
             Mockito.doReturn(EMPTY).when(this.nlriParser).toString();
+
         } catch (BGPDocumentedException | BGPParsingException e) {
             Assert.fail();
         }
index 8eeb0a9d80a00f1ecd071d2afaec5eaa10bebddd..3947fa833ce320ee9ef21309aa0d91690015f764 100644 (file)
@@ -14,8 +14,10 @@ import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
+import java.util.Optional;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -27,12 +29,16 @@ import org.opendaylight.protocol.bgp.parser.spi.AttributeRegistry;
 import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
 import org.opendaylight.protocol.bgp.parser.spi.CapabilityRegistry;
 import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry;
+import org.opendaylight.protocol.bgp.parser.spi.MultiPathSupport;
 import org.opendaylight.protocol.bgp.parser.spi.NlriRegistry;
 import org.opendaylight.protocol.bgp.parser.spi.ParameterRegistry;
+import org.opendaylight.protocol.bgp.parser.spi.PeerConstraint;
+import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
 import org.opendaylight.protocol.bgp.parser.spi.SubsequentAddressFamilyRegistry;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 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.path.attributes.AttributesBuilder;
+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.update.attributes.MpReachNlri;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlri;
@@ -47,6 +53,20 @@ import org.opendaylight.yangtools.yang.binding.Notification;
 
 public class SimpleRegistryTest {
 
+    private static final MultiPathSupport ADD_PATH_SUPPORT = new MultiPathSupport() {
+        @Override
+        public boolean isTableTypeSupported(final BgpTableType tableType) {
+            return true;
+        }
+    };
+
+    private static final PeerSpecificParserConstraint CONSTRAINT = new PeerSpecificParserConstraint() {
+        @Override
+        public <T extends PeerConstraint> Optional<T> getPeerConstraint(final Class<T> peerConstraintType) {
+            return (Optional<T>) Optional.of(ADD_PATH_SUPPORT);
+        }
+    };
+
     protected BGPExtensionProviderContext ctx;
     private BgpTestActivator activator;
 
@@ -70,8 +90,9 @@ public class SimpleRegistryTest {
         };
         final ByteBuf byteAggregator = Unpooled.buffer(attributeBytes.length);
         attrReg.serializeAttribute(Mockito.mock(DataObject.class), byteAggregator);
-        attrReg.parseAttributes(Unpooled.wrappedBuffer(attributeBytes));
-        verify(this.activator.attrParser, times(1)).parseAttribute(Mockito.any(ByteBuf.class), Mockito.any(AttributesBuilder.class));
+        attrReg.parseAttributes(Unpooled.wrappedBuffer(attributeBytes), CONSTRAINT);
+        verify(this.activator.attrParser, times(1)).parseAttribute(Mockito.any(ByteBuf.class), Mockito.any(AttributesBuilder.class),
+                Mockito.any(PeerSpecificParserConstraint.class));
         verify(this.activator.attrSerializer, times(1)).serializeAttribute(Mockito.any(DataObject.class), Mockito.any(ByteBuf.class));
     }
 
@@ -116,8 +137,9 @@ public class SimpleRegistryTest {
 
         final ByteBuf buffer = Unpooled.buffer(msgBytes.length);
         msgRegistry.serializeMessage(msg, buffer);
-        msgRegistry.parseMessage(Unpooled.wrappedBuffer(msgBytes));
-        verify(this.activator.msgParser, times(1)).parseMessageBody(Mockito.any(ByteBuf.class), Mockito.anyInt());
+        msgRegistry.parseMessage(Unpooled.wrappedBuffer(msgBytes), CONSTRAINT);
+        verify(this.activator.msgParser, times(1)).parseMessageBody(Mockito.any(ByteBuf.class), Mockito.anyInt(),
+                Mockito.any(PeerSpecificParserConstraint.class));
         verify(this.activator.msgSerializer, times(1)).serializeMessage(Mockito.any(Notification.class), Mockito.any(ByteBuf.class));
     }
 
@@ -149,8 +171,8 @@ public class SimpleRegistryTest {
         final ByteBuf buffer = Unpooled.buffer(mpReachBytes.length);
         nlriReg.serializeMpReach(mpReach, buffer);
         assertArrayEquals(mpReachBytes, buffer.array());
-        assertEquals(mpReach, nlriReg.parseMpReach(Unpooled.wrappedBuffer(mpReachBytes)));
-        verify(this.activator.nlriParser, times(1)).parseNlri(Mockito.any(ByteBuf.class), Mockito.any(MpReachNlriBuilder.class));
+        assertEquals(mpReach, nlriReg.parseMpReach(Unpooled.wrappedBuffer(mpReachBytes), CONSTRAINT));
+        verify(this.activator.nlriParser, times(1)).parseNlri(Mockito.any(ByteBuf.class), Mockito.any(MpReachNlriBuilder.class), Mockito.any());
     }
 
     @Test
@@ -166,7 +188,7 @@ public class SimpleRegistryTest {
         final ByteBuf buffer = Unpooled.buffer(mpReachBytes.length);
         nlriReg.serializeMpReach(mpReach, buffer);
         assertArrayEquals(mpReachBytes, buffer.array());
-        assertEquals(mpReach, nlriReg.parseMpReach(Unpooled.wrappedBuffer(mpReachBytes)));
+        assertEquals(mpReach, nlriReg.parseMpReach(Unpooled.wrappedBuffer(mpReachBytes), CONSTRAINT));
     }
 
     @Test
@@ -182,7 +204,7 @@ public class SimpleRegistryTest {
         final ByteBuf buffer = Unpooled.buffer(mpReachBytes.length);
         nlriReg.serializeMpReach(mpReach, buffer);
         assertArrayEquals(mpReachBytes, buffer.array());
-        assertEquals(mpReach, nlriReg.parseMpReach(Unpooled.wrappedBuffer(mpReachBytes)));
+        assertEquals(mpReach, nlriReg.parseMpReach(Unpooled.wrappedBuffer(mpReachBytes), CONSTRAINT));
     }
 
     @Test
@@ -195,7 +217,7 @@ public class SimpleRegistryTest {
         final ByteBuf buffer = Unpooled.buffer(mpUnreachBytes.length);
         nlriReg.serializeMpUnReach(mpUnreach, buffer);
         assertArrayEquals(mpUnreachBytes, buffer.array());
-        assertEquals(mpUnreach, nlriReg.parseMpUnreach(Unpooled.wrappedBuffer(mpUnreachBytes)));
-        verify(this.activator.nlriParser, times(1)).parseNlri(Mockito.any(ByteBuf.class), Mockito.any(MpUnreachNlriBuilder.class));
+        assertEquals(mpUnreach, nlriReg.parseMpUnreach(Unpooled.wrappedBuffer(mpUnreachBytes), CONSTRAINT));
+        verify(this.activator.nlriParser, times(1)).parseNlri(Mockito.any(ByteBuf.class), Mockito.any(MpUnreachNlriBuilder.class), Mockito.any());
     }
 }