import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
import org.opendaylight.protocol.bgp.parser.BGPParsingException;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder;
*/
void parseAttribute(@Nonnull ByteBuf buffer, @Nonnull AttributesBuilder builder,
@Nullable PeerSpecificParserConstraint constraint) throws BGPDocumentedException, BGPParsingException;
+
+ /**
+ * Determine whether a duplicate attribute should be ignored or {@link BGPError#MALFORMED_ATTR_LIST} should be
+ * raised. This is useful for MP_REACH/MP_UNREACH attributes, which need to emit a Notification under RFC7606
+ * rules.
+ *
+ * @param errorHandling Revised error handling type
+ * @return True if the duplicate attribute should be ignored, false if a BGPError should be raised.
+ */
+ default boolean ignoreDuplicates(final @Nonnull RevisedErrorHandling errorHandling) {
+ return true;
+ }
}
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.bgp.parser.spi.RevisedErrorHandling;
import org.opendaylight.protocol.concepts.AbstractRegistration;
import org.opendaylight.protocol.concepts.HandlerRegistry;
import org.opendaylight.protocol.util.BitArray;
private static final int TRANSITIVE_BIT = 1;
private static final int PARTIAL_BIT = 2;
private static final int EXTENDED_LENGTH_BIT = 3;
- private final HandlerRegistry<DataContainer, AttributeParser, AttributeSerializer> handlers = new HandlerRegistry<>();
+
+ private final HandlerRegistry<DataContainer, AttributeParser, AttributeSerializer> handlers =
+ new HandlerRegistry<>();
private final Map<AbstractRegistration, AttributeSerializer> serializers = new LinkedHashMap<>();
private final AtomicReference<Iterable<AttributeSerializer>> roSerializers =
new AtomicReference<>(this.serializers.values());
return this.handlers.registerParser(attributeType, parser);
}
- synchronized AutoCloseable registerAttributeSerializer(final Class<? extends DataObject> paramClass, final AttributeSerializer serializer) {
+ synchronized AutoCloseable registerAttributeSerializer(final Class<? extends DataObject> paramClass,
+ final AttributeSerializer serializer) {
final AbstractRegistration reg = this.handlers.registerSerializer(paramClass, serializer);
this.serializers.put(reg, serializer);
};
}
- private void addAttribute(final ByteBuf buffer, final Map<Integer, RawAttribute> attributes)
- throws BGPDocumentedException {
+ private void addAttribute(final ByteBuf buffer, final RevisedErrorHandling errorHandling,
+ 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) {
- processUnrecognized(flags, type, buffer, len);
- } else {
- attributes.put(type, new RawAttribute(parser, buffer.readSlice(len)));
+ final AttributeParser parser = this.handlers.getParser(type);
+ if (attributes.containsKey(type)) {
+ if (parser != null && !parser.ignoreDuplicates(errorHandling)) {
+ throw new BGPDocumentedException("Duplicate attribute " + type, BGPError.MALFORMED_ATTR_LIST);
}
- } else {
LOG.debug("Ignoring duplicate attribute type {}", type);
+ return;
+ }
+
+ if (parser == null) {
+ 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);
+ throw new BGPDocumentedException("Well known attribute not recognized.",
+ BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED);
}
final UnrecognizedAttributes unrecognizedAttribute = new UnrecognizedAttributesBuilder()
.withKey(new UnrecognizedAttributesKey((short) type))
@Override
public Attributes parseAttributes(final ByteBuf buffer, final PeerSpecificParserConstraint constraint)
throws BGPDocumentedException, BGPParsingException {
+ final RevisedErrorHandling errorHandling = RevisedErrorHandling.from(constraint);
final Map<Integer, RawAttribute> attributes = new TreeMap<>();
while (buffer.isReadable()) {
- addAttribute(buffer, attributes);
+ addAttribute(buffer, errorHandling, attributes);
}
/*
* TreeMap guarantees that we will be invoking the parser in the order
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.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.rev130715.Ipv4Address;
private static final MultiPathSupport ADD_PATH_SUPPORT = tableType -> 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);
- }
- };
+ private static final PeerSpecificParserConstraint CONSTRAINT;
+
+ static {
+ PeerSpecificParserConstraintImpl c = new PeerSpecificParserConstraintImpl();
+ c.addPeerConstraint(MultiPathSupport.class, ADD_PATH_SUPPORT);
+ CONSTRAINT = c;
+ }
protected BGPExtensionProviderContext ctx;
private BgpTestActivator activator;