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;
@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
}
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;
+ }
}
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;
@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);
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;
@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);
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;
/**
// 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);
+ }
}
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);
@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);
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 });
}
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;
*/
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);
+ }
}
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);
}
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);
+ }
}
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);
}
--- /dev/null
+/*
+ * 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);
+
+}
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);
+ }
}
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();
}
--- /dev/null
+/*
+ * 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 {
+
+}
--- /dev/null
+/*
+ * 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);
+
+}
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;
};
}
- 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)));
}
}
}
+ 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);
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();
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;
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
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;
@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();
}
@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);
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) {
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();
}
}
}
@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();
}
};
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;
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();
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();
}
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;
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;
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;
};
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));
}
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));
}
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
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
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
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());
}
}