From 5c3191cea50fe181792836866f955a4e3a0fc33a Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Fri, 11 Oct 2013 14:57:55 +0200 Subject: [PATCH] BUG-113: split out attribute parsers Change-Id: I9d60cbff4e2bcd914b5e4d4ff90fdf21707ff2ac Signed-off-by: Robert Varga --- .../impl/message/BGPUpdateMessageParser.java | 15 +- .../update/AS4AggregatorAttributeParser.java | 13 + .../update/AS4PathAttributeParser.java | 13 + .../update/AggregatorAttributeParser.java | 32 ++ .../message/update/AsPathAttributeParser.java | 74 ++++ .../AtomicAggregateAttributeParser.java | 14 + .../update/ClusterIdAttributeParser.java | 26 ++ .../update/CommunitiesAttributeParser.java | 27 ++ .../message/update/CommunitiesParser.java | 30 +- .../ExtendedCommunitiesAttributeParser.java | 28 ++ ...ser.java => LinkstateAttributeParser.java} | 26 +- .../LocalPreferenceAttributeParser.java | 15 + .../update/MPReachAttributeParser.java | 24 ++ .../impl/message/update/MPReachParser.java | 2 +- .../update/MPUnreachAttributeParser.java | 23 ++ ...MultiExitDiscriminatorAttributeParser.java | 15 + .../update/NextHopAttributeParser.java | 16 + .../message/update/OriginAttributeParser.java | 24 ++ .../update/OriginatorIdAttributeParser.java | 17 + .../message/update/PathAttributeParser.java | 317 ------------------ .../update/SimpleAttributeRegistry.java | 165 +++------ .../parser/impl/PathAttributeParserTest.java | 4 +- .../bgp/parser/spi/AttributeRegistry.java | 4 +- 23 files changed, 467 insertions(+), 457 deletions(-) create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AS4AggregatorAttributeParser.java create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AS4PathAttributeParser.java create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AggregatorAttributeParser.java create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AsPathAttributeParser.java create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AtomicAggregateAttributeParser.java create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/ClusterIdAttributeParser.java create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/CommunitiesAttributeParser.java create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/ExtendedCommunitiesAttributeParser.java rename bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/{LinkStateParser.java => LinkstateAttributeParser.java} (97%) create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LocalPreferenceAttributeParser.java create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPReachAttributeParser.java create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPUnreachAttributeParser.java create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MultiExitDiscriminatorAttributeParser.java create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/NextHopAttributeParser.java create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/OriginAttributeParser.java create mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/OriginatorIdAttributeParser.java delete mode 100644 bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/PathAttributeParser.java diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPUpdateMessageParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPUpdateMessageParser.java index 973774cde7..f4ec7d2803 100644 --- a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPUpdateMessageParser.java +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPUpdateMessageParser.java @@ -14,7 +14,8 @@ import java.util.List; import org.opendaylight.protocol.bgp.parser.BGPDocumentedException; import org.opendaylight.protocol.bgp.parser.BGPError; import org.opendaylight.protocol.bgp.parser.BGPParsingException; -import org.opendaylight.protocol.bgp.parser.impl.message.update.PathAttributeParser; +import org.opendaylight.protocol.bgp.parser.impl.message.update.SimpleAttributeRegistry; +import org.opendaylight.protocol.bgp.parser.spi.AttributeRegistry; import org.opendaylight.protocol.bgp.parser.spi.MessageParser; import org.opendaylight.protocol.concepts.Ipv4Util; import org.opendaylight.protocol.util.ByteArray; @@ -27,6 +28,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Preconditions; + /** * LENGTH fields, that denote the length of the fields with variable length, have fixed SIZE. * @@ -35,7 +38,7 @@ import org.slf4j.LoggerFactory; */ public class BGPUpdateMessageParser implements MessageParser { public static final int TYPE = 2; - public static final BGPUpdateMessageParser PARSER = new BGPUpdateMessageParser(); + public static final BGPUpdateMessageParser PARSER = new BGPUpdateMessageParser(SimpleAttributeRegistry.INSTANCE); private static Logger logger = LoggerFactory.getLogger(BGPUpdateMessageParser.class); @@ -49,9 +52,11 @@ public class BGPUpdateMessageParser implements MessageParser { */ public static final int TOTAL_PATH_ATTR_LENGTH_SIZE = 2; - // Constructors ------------------------------------------------------- - private BGPUpdateMessageParser() { + private final AttributeRegistry reg; + // Constructors ------------------------------------------------------- + public BGPUpdateMessageParser(final AttributeRegistry reg) { + this.reg = Preconditions.checkNotNull(reg); } // Getters & setters -------------------------------------------------- @@ -89,7 +94,7 @@ public class BGPUpdateMessageParser implements MessageParser { try { if (totalPathAttrLength > 0) { - final PathAttributes pathAttributes = PathAttributeParser.parseAttribute(ByteArray.subByte(body, byteOffset, + final PathAttributes pathAttributes = reg.parseAttributes(ByteArray.subByte(body, byteOffset, totalPathAttrLength)); byteOffset += totalPathAttrLength; eventBuilder.setPathAttributes(pathAttributes); diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AS4AggregatorAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AS4AggregatorAttributeParser.java new file mode 100644 index 0000000000..c768b49e20 --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AS4AggregatorAttributeParser.java @@ -0,0 +1,13 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; + +final class AS4AggregatorAttributeParser implements AttributeParser { + static final int TYPE = 17; + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { + // AS4 Aggregator is ignored + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AS4PathAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AS4PathAttributeParser.java new file mode 100644 index 0000000000..aeebf2459d --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AS4PathAttributeParser.java @@ -0,0 +1,13 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; + +final class AS4PathAttributeParser implements AttributeParser { + static final int TYPE = 18; + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { + // AS4 Path is ignored + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AggregatorAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AggregatorAttributeParser.java new file mode 100644 index 0000000000..92dda87efd --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AggregatorAttributeParser.java @@ -0,0 +1,32 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.protocol.concepts.IPv4; +import org.opendaylight.protocol.util.ByteArray; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber; +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.rev130918.path.attributes.Aggregator; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.AggregatorBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; + +final class AggregatorAttributeParser implements AttributeParser { + static final int TYPE = 7; + + /** + * Parse AGGREGATOR from bytes + * + * @param bytes byte array to be parsed + * @return {@link Aggregator} BGP Aggregator + */ + private static Aggregator parseAggregator(final byte[] bytes) { + final AsNumber asNumber = new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(bytes, 0, AsPathSegmentParser.AS_NUMBER_LENGTH))); + final Ipv4Address address = new Ipv4Address(IPv4.FAMILY.addressForBytes( + ByteArray.subByte(bytes, AsPathSegmentParser.AS_NUMBER_LENGTH, 4)).toString()); + return new AggregatorBuilder().setAsNumber(asNumber).setNetworkAddress(address).build(); + } + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { + builder.setAggregator(parseAggregator(bytes)); + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AsPathAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AsPathAttributeParser.java new file mode 100644 index 0000000000..e4f8037167 --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AsPathAttributeParser.java @@ -0,0 +1,74 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import java.util.List; + +import org.opendaylight.protocol.bgp.parser.BGPDocumentedException; +import org.opendaylight.protocol.bgp.parser.BGPError; +import org.opendaylight.protocol.bgp.parser.BGPParsingException; +import org.opendaylight.protocol.bgp.parser.impl.message.update.AsPathSegmentParser.SegmentType; +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.protocol.util.ByteArray; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.AsPath; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.AsPathBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.as.path.Segments; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.as.path.SegmentsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.CAListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.CASetBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.c.a.list.AsSequence; + +import com.google.common.collect.Lists; +import com.google.common.primitives.UnsignedBytes; + +final class AsPathAttributeParser implements AttributeParser { + static final int TYPE = 2; + + /** + * Parses AS_PATH from bytes. + * + * @param bytes byte array to be parsed + * @return new ASPath object + * @throws BGPDocumentedException if there is no AS_SEQUENCE present (mandatory) + * @throws BGPParsingException + */ + private static AsPath parseAsPath(final byte[] bytes) throws BGPDocumentedException, BGPParsingException { + int byteOffset = 0; + final List ases = Lists.newArrayList(); + boolean isSequence = false; + while (byteOffset < bytes.length) { + final int type = UnsignedBytes.toInt(bytes[byteOffset]); + final SegmentType segmentType = AsPathSegmentParser.parseType(type); + if (segmentType == null) { + throw new BGPParsingException("AS Path segment type unknown : " + type); + } + byteOffset += AsPathSegmentParser.TYPE_LENGTH; + + final int count = UnsignedBytes.toInt(bytes[byteOffset]); + byteOffset += AsPathSegmentParser.LENGTH_SIZE; + + if (segmentType == SegmentType.AS_SEQUENCE) { + final List numbers = AsPathSegmentParser.parseAsSequence(count, + ByteArray.subByte(bytes, byteOffset, count * AsPathSegmentParser.AS_NUMBER_LENGTH)); + ases.add(new SegmentsBuilder().setCSegment(new CAListBuilder().setAsSequence(numbers).build()).build()); + isSequence = true; + } else { + final List list = AsPathSegmentParser.parseAsSet(count, + ByteArray.subByte(bytes, byteOffset, count * AsPathSegmentParser.AS_NUMBER_LENGTH)); + ases.add(new SegmentsBuilder().setCSegment(new CASetBuilder().setAsSet(list).build()).build()); + + } + byteOffset += count * AsPathSegmentParser.AS_NUMBER_LENGTH; + } + + if (!isSequence && bytes.length != 0) { + throw new BGPDocumentedException("AS_SEQUENCE must be present in AS_PATH attribute.", BGPError.AS_PATH_MALFORMED); + } + return new AsPathBuilder().setSegments(ases).build(); + } + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPDocumentedException, BGPParsingException { + builder.setAsPath(parseAsPath(bytes)); + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AtomicAggregateAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AtomicAggregateAttributeParser.java new file mode 100644 index 0000000000..67f67071fb --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AtomicAggregateAttributeParser.java @@ -0,0 +1,14 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.AtomicAggregateBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; + +final class AtomicAggregateAttributeParser implements AttributeParser { + static final int TYPE = 6; + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { + builder.setAtomicAggregate(new AtomicAggregateBuilder().build()); + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/ClusterIdAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/ClusterIdAttributeParser.java new file mode 100644 index 0000000000..62e3baa39d --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/ClusterIdAttributeParser.java @@ -0,0 +1,26 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import java.util.List; + +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.protocol.util.ByteArray; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier; + +import com.google.common.collect.Lists; + +final class ClusterIdAttributeParser implements AttributeParser { + static final int TYPE = 10; + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { + final List list = Lists.newArrayList(); + int i = 0; + while (i < bytes.length) { + list.add(new ClusterIdentifier(ByteArray.subByte(bytes, i, 4))); + i += 4; + } + + builder.setClusterId(list); + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/CommunitiesAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/CommunitiesAttributeParser.java new file mode 100644 index 0000000000..3ed49eb3d2 --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/CommunitiesAttributeParser.java @@ -0,0 +1,27 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import java.util.List; + +import org.opendaylight.protocol.bgp.parser.BGPDocumentedException; +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.protocol.util.ByteArray; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.Communities; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; + +import com.google.common.collect.Lists; + +final class CommunitiesAttributeParser implements AttributeParser { + static final int TYPE = 8; + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPDocumentedException { + final List set = Lists.newArrayList(); + int i = 0; + while (i < bytes.length) { + set.add((Communities) CommunitiesParser.parseCommunity(ByteArray.subByte(bytes, i, CommunitiesParser.COMMUNITY_LENGTH))); + i += CommunitiesParser.COMMUNITY_LENGTH; + } + + builder.setCommunities(set); + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/CommunitiesParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/CommunitiesParser.java index 9b20326b04..999038d96f 100644 --- a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/CommunitiesParser.java +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/CommunitiesParser.java @@ -59,8 +59,9 @@ public class CommunitiesParser { * @throws BGPDocumentedException */ static Community parseCommunity(final byte[] bytes) throws BGPDocumentedException { - if (bytes.length != COMMUNITY_LENGTH) + if (bytes.length != COMMUNITY_LENGTH) { throw new BGPDocumentedException("Community with wrong length: " + bytes.length, BGPError.OPT_ATTR_ERROR); + } if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x01 })) { return CommunityUtil.NO_EXPORT; } else if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x02 })) { @@ -91,51 +92,54 @@ public class CommunitiesParser { return new CRouteTargetExtendedCommunityBuilder().setRouteTargetExtendedCommunity( new RouteTargetExtendedCommunityBuilder().setGlobalAdministrator( new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator( - ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); + ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); } else if (subType == 3) { return new CRouteOriginExtendedCommunityBuilder().setRouteOriginExtendedCommunity( new RouteOriginExtendedCommunityBuilder().setGlobalAdministrator( new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator( - ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); - } else + ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); + } else { return new CAsSpecificExtendedCommunityBuilder().setAsSpecificExtendedCommunity( new AsSpecificExtendedCommunityBuilder().setTransitive(false).setGlobalAdministrator( new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator( - ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); + ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); + } case 40: // 01000000 return new CAsSpecificExtendedCommunityBuilder().setAsSpecificExtendedCommunity( new AsSpecificExtendedCommunityBuilder().setTransitive(true).setGlobalAdministrator( new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator( - ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); + ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); case 2: if (subType == 2) { return new CRouteTargetExtendedCommunityBuilder().setRouteTargetExtendedCommunity( new RouteTargetExtendedCommunityBuilder().setGlobalAdministrator( new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator( - ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); + ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); } else if (subType == 3) { return new CRouteOriginExtendedCommunityBuilder().setRouteOriginExtendedCommunity( new RouteOriginExtendedCommunityBuilder().setGlobalAdministrator( new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator( - ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); - } else + ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); + } else { throw new BGPDocumentedException("Could not parse Extended Community subtype: " + subType, BGPError.OPT_ATTR_ERROR); + } case 1: if (subType == 2) { return new CRouteTargetExtendedCommunityBuilder().setRouteTargetExtendedCommunity( new RouteTargetExtendedCommunityBuilder().setGlobalAdministrator( new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator( - ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); + ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); } else if (subType == 3) { return new CRouteOriginExtendedCommunityBuilder().setRouteOriginExtendedCommunity( new RouteOriginExtendedCommunityBuilder().setGlobalAdministrator( new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator( - ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); - } else + ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build(); + } else { return new CInet4SpecificExtendedCommunityBuilder().setInet4SpecificExtendedCommunity( new Inet4SpecificExtendedCommunityBuilder().setTransitive(false).setGlobalAdministrator( Ipv4Util.addressForBytes(ByteArray.subByte(value, 0, 4))).setLocalAdministrator( - ByteArray.subByte(value, 4, 2)).build()).build(); + ByteArray.subByte(value, 4, 2)).build()).build(); + } case 41: // 01000001 return new CInet4SpecificExtendedCommunityBuilder().setInet4SpecificExtendedCommunity( new Inet4SpecificExtendedCommunityBuilder().setTransitive(true).setGlobalAdministrator( diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/ExtendedCommunitiesAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/ExtendedCommunitiesAttributeParser.java new file mode 100644 index 0000000000..e928c5c6a3 --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/ExtendedCommunitiesAttributeParser.java @@ -0,0 +1,28 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import java.util.List; + +import org.opendaylight.protocol.bgp.parser.BGPDocumentedException; +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.protocol.util.ByteArray; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.ExtendedCommunities; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; + +import com.google.common.collect.Lists; + +final class ExtendedCommunitiesAttributeParser implements AttributeParser { + static final int TYPE = 16; + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPDocumentedException { + final List set = Lists.newArrayList(); + int i = 0; + while (i < bytes.length) { + set.add((ExtendedCommunities) CommunitiesParser.parseExtendedCommunity(ByteArray.subByte(bytes, i, + CommunitiesParser.EXTENDED_COMMUNITY_LENGTH))); + i += CommunitiesParser.EXTENDED_COMMUNITY_LENGTH; + } + + builder.setExtendedCommunities(set); + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LinkStateParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LinkstateAttributeParser.java similarity index 97% rename from bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LinkStateParser.java rename to bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LinkstateAttributeParser.java index cc1a168b59..2fdbe0e3bd 100644 --- a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LinkStateParser.java +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LinkstateAttributeParser.java @@ -17,6 +17,7 @@ import java.util.Set; import org.opendaylight.protocol.bgp.parser.BGPParsingException; import org.opendaylight.protocol.bgp.parser.impl.ByteList; +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; import org.opendaylight.protocol.concepts.Ipv4Util; import org.opendaylight.protocol.concepts.Ipv6Util; import org.opendaylight.protocol.util.ByteArray; @@ -41,6 +42,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.link import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.NodeIdentifier; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.OspfInterfaceIdentifier; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.OspfRouteType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.PathAttributes1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.PathAttributes1Builder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.ProtocolId; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.RouteDistinguisher; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.RouteTag; @@ -76,6 +79,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.link import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.update.path.attributes.linkstate.path.attribute.link.state.attribute.NodeAttributesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.update.path.attributes.linkstate.path.attribute.link.state.attribute.PrefixAttributes; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.update.path.attributes.linkstate.path.attribute.link.state.attribute.PrefixAttributesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.MplsLabeledVpnSubsequentAddressFamily; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nps.concepts.rev130930.Bandwidth; @@ -96,9 +100,11 @@ import com.google.common.primitives.UnsignedBytes; * * @see BGP-LS draft */ -public class LinkStateParser { +public class LinkstateAttributeParser implements AttributeParser { + // FIXME: update to IANA number once it is known + static final int TYPE = 99; - private static final Logger logger = LoggerFactory.getLogger(LinkStateParser.class); + private static final Logger logger = LoggerFactory.getLogger(LinkstateAttributeParser.class); private static final int TYPE_LENGTH = 2; @@ -117,7 +123,10 @@ public class LinkStateParser { private static final Set prefixTlvs = Sets.newHashSet(1152, 1153, 1154, 1155, 1156, 1157); - private LinkStateParser() { + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPParsingException { + final PathAttributes1 a = new PathAttributes1Builder().setLinkstatePathAttribute(parseLinkState(bytes)).build(); + builder.addAugmentation(PathAttributes1.class, a); } /** @@ -375,8 +384,9 @@ public class LinkStateParser { case 264: final int rt = ByteArray.bytesToInt(value); final OspfRouteType routeType = OspfRouteType.forValue(rt); - if (routeType == null) + if (routeType == null) { throw new BGPParsingException("Unknown OSPF Route Type: " + rt); + } builder.setOspfRouteType(routeType); logger.trace("Parser RouteType: {}", routeType); break; @@ -388,10 +398,11 @@ public class LinkStateParser { logger.debug("Expected length {}, actual length {}.", size, value.length - 1); throw new BGPParsingException("Illegal length of IP reachability TLV: " + (value.length - 1)); } - if (size == 4) + if (size == 4) { prefix = new IpPrefix(Ipv4Util.prefixForBytes(ByteArray.subByte(value, 1, size), prefixLength)); - else + } else { prefix = new IpPrefix(Ipv6Util.prefixForBytes(ByteArray.subByte(value, 1, size), prefixLength)); + } builder.setIpReachabilityInformation(prefix); logger.trace("Parsed IP reachability info: {}", prefix); break; @@ -494,8 +505,9 @@ public class LinkStateParser { break; case 1093: final LinkProtectionType lpt = LinkProtectionType.forValue(UnsignedBytes.toInt(value[0])); - if (lpt == null) + if (lpt == null) { throw new BGPParsingException("Link Protection Type not recognized: " + UnsignedBytes.toInt(value[0])); + } builder.setLinkProtection(lpt); logger.trace("Parsed Link Protection Type {}", lpt); break; diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LocalPreferenceAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LocalPreferenceAttributeParser.java new file mode 100644 index 0000000000..fe9454f070 --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LocalPreferenceAttributeParser.java @@ -0,0 +1,15 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.protocol.util.ByteArray; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.LocalPrefBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; + +final class LocalPreferenceAttributeParser implements AttributeParser { + static final int TYPE = 5; + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { + builder.setLocalPref(new LocalPrefBuilder().setPref(ByteArray.bytesToLong(bytes)).build()); + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPReachAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPReachAttributeParser.java new file mode 100644 index 0000000000..7a4acc25cc --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPReachAttributeParser.java @@ -0,0 +1,24 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import org.opendaylight.protocol.bgp.parser.BGPDocumentedException; +import org.opendaylight.protocol.bgp.parser.BGPError; +import org.opendaylight.protocol.bgp.parser.BGPParsingException; +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes1Builder; + +final class MPReachAttributeParser implements AttributeParser { + static final int TYPE = 14; + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPDocumentedException { + try { + final PathAttributes1 a = new PathAttributes1Builder().setMpReachNlri(MPReachParser.parseMPReach(bytes)).build(); + + builder.addAugmentation(PathAttributes1.class, a); + } catch (final BGPParsingException e) { + throw new BGPDocumentedException("Could not parse MP_REACH_NLRI: " + e.getMessage(), BGPError.OPT_ATTR_ERROR); + } + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPReachParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPReachParser.java index 44a1493aac..9e3b3a353d 100644 --- a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPReachParser.java +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPReachParser.java @@ -131,7 +131,7 @@ public class MPReachParser { final List nlri6 = Ipv6Util.prefixListForBytes(bytes); return new Ipv6Builder().setIpv6Prefixes(nlri6).build(); } else if (afi == LinkstateAddressFamily.class) { - return new LinkstateBuilder().setCLinkstateDestination(LinkStateParser.parseLSNlri(safi, bytes)).build(); + return new LinkstateBuilder().setCLinkstateDestination(LinkstateAttributeParser.parseLSNlri(safi, bytes)).build(); } return null; } diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPUnreachAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPUnreachAttributeParser.java new file mode 100644 index 0000000000..e82ad1805b --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MPUnreachAttributeParser.java @@ -0,0 +1,23 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import org.opendaylight.protocol.bgp.parser.BGPDocumentedException; +import org.opendaylight.protocol.bgp.parser.BGPError; +import org.opendaylight.protocol.bgp.parser.BGPParsingException; +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes2Builder; + +final class MPUnreachAttributeParser implements AttributeParser { + static final int TYPE = 15; + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPDocumentedException { + try { + final PathAttributes2 a = new PathAttributes2Builder().setMpUnreachNlri(MPReachParser.parseMPUnreach(bytes)).build(); + builder.addAugmentation(PathAttributes2.class, a); + } catch (final BGPParsingException e) { + throw new BGPDocumentedException("Could not parse MP_UNREACH_NLRI: " + e.getMessage(), BGPError.OPT_ATTR_ERROR); + } + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MultiExitDiscriminatorAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MultiExitDiscriminatorAttributeParser.java new file mode 100644 index 0000000000..8dd9bc6da1 --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MultiExitDiscriminatorAttributeParser.java @@ -0,0 +1,15 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.protocol.util.ByteArray; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.MultiExitDiscBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; + +final class MultiExitDiscriminatorAttributeParser implements AttributeParser { + static final int TYPE = 4; + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { + builder.setMultiExitDisc(new MultiExitDiscBuilder().setMed(ByteArray.bytesToLong(bytes)).build()); + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/NextHopAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/NextHopAttributeParser.java new file mode 100644 index 0000000000..d97870f55d --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/NextHopAttributeParser.java @@ -0,0 +1,16 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.protocol.concepts.Ipv4Util; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.CIpv4NextHopBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.c.ipv4.next.hop.Ipv4NextHopBuilder; + +final class NextHopAttributeParser implements AttributeParser { + static final int TYPE = 3; + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { + builder.setCNextHop(new CIpv4NextHopBuilder().setIpv4NextHop(new Ipv4NextHopBuilder().setGlobal(Ipv4Util.addressForBytes(bytes)).build()).build()); + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/OriginAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/OriginAttributeParser.java new file mode 100644 index 0000000000..9d478a8e43 --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/OriginAttributeParser.java @@ -0,0 +1,24 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import org.opendaylight.protocol.bgp.parser.BGPDocumentedException; +import org.opendaylight.protocol.bgp.parser.BGPError; +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.OriginBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpOrigin; + +import com.google.common.primitives.UnsignedBytes; + +final class OriginAttributeParser implements AttributeParser { + static final int TYPE = 1; + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPDocumentedException { + final BgpOrigin borigin = BgpOrigin.forValue(UnsignedBytes.toInt(bytes[0])); + if (borigin == null) { + throw new BGPDocumentedException("Unknown Origin type.", BGPError.ORIGIN_ATTR_NOT_VALID, new byte[] { (byte) 0x01, (byte) 0x01, bytes[0] }); + } + + builder.setOrigin(new OriginBuilder().setValue(borigin).build()); + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/OriginatorIdAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/OriginatorIdAttributeParser.java new file mode 100644 index 0000000000..54fe62ed35 --- /dev/null +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/OriginatorIdAttributeParser.java @@ -0,0 +1,17 @@ +package org.opendaylight.protocol.bgp.parser.impl.message.update; + +import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; + +final class OriginatorIdAttributeParser implements AttributeParser { + static final int TYPE = 9; + + @Override + public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { + if (bytes.length != 4) { + throw new IllegalArgumentException("Length of byte array for ORIGINATOR_ID should be 4, but is " + bytes.length); + } + + builder.setOriginatorId(bytes); + } +} \ No newline at end of file diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/PathAttributeParser.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/PathAttributeParser.java deleted file mode 100644 index 3eb0b78d3c..0000000000 --- a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/PathAttributeParser.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.protocol.bgp.parser.impl.message.update; - -import java.util.List; - -import org.opendaylight.protocol.bgp.parser.BGPDocumentedException; -import org.opendaylight.protocol.bgp.parser.BGPError; -import org.opendaylight.protocol.bgp.parser.BGPParsingException; -import org.opendaylight.protocol.bgp.parser.impl.message.update.AsPathSegmentParser.SegmentType; -import org.opendaylight.protocol.bgp.parser.spi.AttributeRegistry; -import org.opendaylight.protocol.concepts.IPv4; -import org.opendaylight.protocol.concepts.Ipv4Util; -import org.opendaylight.protocol.util.ByteArray; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber; -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.linkstate.rev130918.PathAttributes1; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.PathAttributes1Builder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.Aggregator; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.AggregatorBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.AsPath; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.AsPathBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.Communities; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.ExtendedCommunities; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.LocalPref; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.LocalPrefBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.MultiExitDisc; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.MultiExitDiscBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.Origin; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.OriginBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.as.path.Segments; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.as.path.SegmentsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes2; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes2Builder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpOrigin; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.CAListBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.CASetBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.c.a.list.AsSequence; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.CNextHop; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.CIpv4NextHopBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.c.ipv4.next.hop.Ipv4NextHopBuilder; - -import com.google.common.collect.Lists; -import com.google.common.primitives.UnsignedBytes; - -/** - * - * Parser for different Path Attributes. Each attributes has its own method for parsing. - * - */ -public class PathAttributeParser { - - private static final int FLAGS_LENGTH = 1; - - private static final int TYPE_LENGTH = 1; - - private static AttributeRegistry reg = SimpleAttributeRegistry.INSTANCE; - - private PathAttributeParser() { - - } - - /** - * Parse path attribute header (the same for all path attributes) and set type, length and value fields. - * - * @param bytes byte array to be parsed. - * @return generic Path Attribute - * @throws BGPParsingException - * @throws BGPDocumentedException - */ - public static PathAttributes parseAttribute(final byte[] bytes) throws BGPDocumentedException, BGPParsingException { - if (bytes == null || bytes.length == 0) { - throw new BGPParsingException("Insufficient length of byte array: " + bytes.length); - } - int byteOffset = 0; - final PathAttributesBuilder builder = new PathAttributesBuilder(); - while (byteOffset < bytes.length) { - final boolean[] bits = ByteArray.parseBits(bytes[0]); - final boolean optional = bits[0]; - final int attrLength = (bits[3]) ? ByteArray.bytesToInt(ByteArray.subByte(bytes, 2, 2)) : UnsignedBytes.toInt(bytes[2]); - final int hdrLength = FLAGS_LENGTH + TYPE_LENGTH + ((bits[3]) ? 2 : 1); - - final byte[] attrBody = ByteArray.subByte(bytes, hdrLength, attrLength); - - boolean found = reg.parseAttribute(UnsignedBytes.toInt(bytes[1]), attrBody, builder); - if (!optional && !found) { - throw new BGPDocumentedException("Well known attribute not recognized.", BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED); - } - - byteOffset += hdrLength + attrLength; - } - return builder.build(); - } - - /** - * Parses ORIGIN from bytes. - * - * @param bytes byte array to be parsed - * @return {@link Origin} BGP origin value - * @throws BGPDocumentedException - */ - static Origin parseOrigin(final byte[] bytes) throws BGPDocumentedException { - final BgpOrigin borigin = BgpOrigin.forValue(UnsignedBytes.toInt(bytes[0])); - if (borigin == null) { - throw new BGPDocumentedException("Unknown Origin type.", BGPError.ORIGIN_ATTR_NOT_VALID, new byte[] { (byte) 0x01, (byte) 0x01, - bytes[0] }); - } - return new OriginBuilder().setValue(borigin).build(); - } - - /** - * Parses AS_PATH from bytes. - * - * @param bytes byte array to be parsed - * @return new ASPath object - * @throws BGPDocumentedException if there is no AS_SEQUENCE present (mandatory) - * @throws BGPParsingException - */ - static AsPath parseAsPath(final byte[] bytes) throws BGPDocumentedException, BGPParsingException { - int byteOffset = 0; - final List ases = Lists.newArrayList(); - boolean isSequence = false; - while (byteOffset < bytes.length) { - final int type = UnsignedBytes.toInt(bytes[byteOffset]); - final SegmentType segmentType = AsPathSegmentParser.parseType(type); - if (segmentType == null) { - throw new BGPParsingException("AS Path segment type unknown : " + type); - } - byteOffset += AsPathSegmentParser.TYPE_LENGTH; - - final int count = UnsignedBytes.toInt(bytes[byteOffset]); - byteOffset += AsPathSegmentParser.LENGTH_SIZE; - - if (segmentType == SegmentType.AS_SEQUENCE) { - final List numbers = AsPathSegmentParser.parseAsSequence(count, - ByteArray.subByte(bytes, byteOffset, count * AsPathSegmentParser.AS_NUMBER_LENGTH)); - ases.add(new SegmentsBuilder().setCSegment(new CAListBuilder().setAsSequence(numbers).build()).build()); - isSequence = true; - } else { - final List list = AsPathSegmentParser.parseAsSet(count, - ByteArray.subByte(bytes, byteOffset, count * AsPathSegmentParser.AS_NUMBER_LENGTH)); - ases.add(new SegmentsBuilder().setCSegment(new CASetBuilder().setAsSet(list).build()).build()); - - } - byteOffset += count * AsPathSegmentParser.AS_NUMBER_LENGTH; - } - - if (!isSequence && bytes.length != 0) { - throw new BGPDocumentedException("AS_SEQUENCE must be present in AS_PATH attribute.", BGPError.AS_PATH_MALFORMED); - } - return new AsPathBuilder().setSegments(ases).build(); - } - - /** - * Parse NEXT_HOP from bytes - * - * @param bytes byte array to be parsed - * @return new NextHop object, it's always IPv4 (basic BGP-4) - */ - static CNextHop parseNextHop(final byte[] bytes) { - return new CIpv4NextHopBuilder().setIpv4NextHop(new Ipv4NextHopBuilder().setGlobal(Ipv4Util.addressForBytes(bytes)).build()).build(); - } - - /** - * Parse MULTI_EXIT_DISC (integer) from bytes - * - * @param bytes byte array to be parsed - * @return integer representing MULTI_EXIT_DISC path attribute - */ - static MultiExitDisc parseMultiExitDisc(final byte[] bytes) { - return new MultiExitDiscBuilder().setMed(ByteArray.bytesToLong(bytes)).build(); - } - - /** - * Parse LOCAL_PREF (integer) from bytes - * - * @param bytes byte array to be parsed - * @return integer representing LOCAL_PREF path attribute - */ - static LocalPref parseLocalPref(final byte[] bytes) { - return new LocalPrefBuilder().setPref(ByteArray.bytesToLong(bytes)).build(); - } - - /** - * Parse AGGREGATOR from bytes - * - * @param bytes byte array to be parsed - * @return {@link Aggregator} BGP Aggregator - */ - static Aggregator parseAggregator(final byte[] bytes) { - final AsNumber asNumber = new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(bytes, 0, AsPathSegmentParser.AS_NUMBER_LENGTH))); - final Ipv4Address address = new Ipv4Address(IPv4.FAMILY.addressForBytes( - ByteArray.subByte(bytes, AsPathSegmentParser.AS_NUMBER_LENGTH, 4)).toString()); - return new AggregatorBuilder().setAsNumber(asNumber).setNetworkAddress(address).build(); - } - - /** - * Parse MP_REACH_NLRI from bytes - * - * @param bytes byte array to be parsed - * @return new specific MPReach object with reachable flag set to true - * @throws BGPDocumentedException - */ - static void parseMPReach(final PathAttributesBuilder b, final byte[] bytes) throws BGPDocumentedException { - - try { - final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes1 a = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes1Builder().setMpReachNlri( - MPReachParser.parseMPReach(bytes)).build(); - - b.addAugmentation( - org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes1.class, a); - } catch (final BGPParsingException e) { - throw new BGPDocumentedException("Could not parse MP_REACH_NLRI: " + e.getMessage(), BGPError.OPT_ATTR_ERROR); - } - } - - /** - * Parse MP_UNREACH_NLRI from bytes - * - * @param bytes byte array to be parsed - * @return new specific MPReach object with reachable flag set to false - * @throws BGPDocumentedException - */ - static void parseMPUnreach(final PathAttributesBuilder b, final byte[] bytes) throws BGPDocumentedException { - try { - final PathAttributes2 a = new PathAttributes2Builder().setMpUnreachNlri(MPReachParser.parseMPUnreach(bytes)).build(); - - b.addAugmentation(PathAttributes2.class, a); - } catch (final BGPParsingException e) { - throw new BGPDocumentedException("Could not parse MP_UNREACH_NLRI: " + e.getMessage(), BGPError.OPT_ATTR_ERROR); - } - } - - /** - * Parse set of EXTENDED_COMMUNITIES from bytes - * - * @param bytes byte array to be parsed - * @return new specific Extended Community object - * @throws BGPDocumentedException l - */ - static List parseExtendedCommunities(final byte[] bytes) throws BGPDocumentedException { - final List set = Lists.newArrayList(); - int i = 0; - while (i < bytes.length) { - set.add((ExtendedCommunities) CommunitiesParser.parseExtendedCommunity(ByteArray.subByte(bytes, i, - CommunitiesParser.EXTENDED_COMMUNITY_LENGTH))); - i += CommunitiesParser.EXTENDED_COMMUNITY_LENGTH; - } - return set; - } - - /** - * Parse set of COMMUNITIES from bytes - * - * @param bytes byte array to be parsed - * @return new specific Community object - * @throws BGPDocumentedException - */ - static List parseCommunities(final byte[] bytes) throws BGPDocumentedException { - final List set = Lists.newArrayList(); - int i = 0; - while (i < bytes.length) { - set.add((Communities) CommunitiesParser.parseCommunity(ByteArray.subByte(bytes, i, CommunitiesParser.COMMUNITY_LENGTH))); - i += CommunitiesParser.COMMUNITY_LENGTH; - } - return set; - } - - /** - * Parse list of Cluster Identifiers. - * - * @param bytes byte array to be parsed - * @return new List of Cluster Identifiers - */ - static List parseClusterList(final byte[] bytes) { - final List list = Lists.newArrayList(); - int i = 0; - while (i < bytes.length) { - list.add(new ClusterIdentifier(ByteArray.subByte(bytes, i, 4))); - i += 4; - } - return list; - } - - /** - * Parses ORIGINATOR_ID, which is BGP Identifier, which is IP address of the speaker. - * - * @param bytes byte array to be parsed - * @return IP address of the speaker - */ - static byte[] parseOriginatorId(final byte[] bytes) { - if (bytes.length != 4) { - throw new IllegalArgumentException("Length of byte array for ORIGINATOR_ID should be 4, but is " + bytes.length); - } - return bytes; - } - - /** - * Parse LINK_STATE from bytes - * - * @param bytes byte array to be parsed - * @return Map, where the key is the type of a tlv and the value is the value of the tlv - * @throws BGPParsingException - */ - static void parseLinkState(final PathAttributesBuilder builder, final byte[] bytes) throws BGPParsingException { - final PathAttributes1 a = new PathAttributes1Builder().setLinkstatePathAttribute(LinkStateParser.parseLinkState(bytes)).build(); - builder.addAugmentation(PathAttributes1.class, a); - } -} diff --git a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/SimpleAttributeRegistry.java b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/SimpleAttributeRegistry.java index 814c4b52d8..f528e15b8a 100644 --- a/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/SimpleAttributeRegistry.java +++ b/bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/SimpleAttributeRegistry.java @@ -8,17 +8,20 @@ package org.opendaylight.protocol.bgp.parser.impl.message.update; import org.opendaylight.protocol.bgp.parser.BGPDocumentedException; +import org.opendaylight.protocol.bgp.parser.BGPError; import org.opendaylight.protocol.bgp.parser.BGPParsingException; import org.opendaylight.protocol.bgp.parser.spi.AttributeParser; import org.opendaylight.protocol.bgp.parser.spi.AttributeRegistry; import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer; import org.opendaylight.protocol.concepts.HandlerRegistry; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.path.attributes.AtomicAggregateBuilder; +import org.opendaylight.protocol.util.ByteArray; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributes; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; import com.google.common.base.Preconditions; +import com.google.common.primitives.UnsignedBytes; public final class SimpleAttributeRegistry implements AttributeRegistry { public static final AttributeRegistry INSTANCE; @@ -26,106 +29,22 @@ public final class SimpleAttributeRegistry implements AttributeRegistry { static { final AttributeRegistry reg = new SimpleAttributeRegistry(); - reg.registerAttributeParser(1, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPDocumentedException { - builder.setOrigin(PathAttributeParser.parseOrigin(bytes)); - } - }); - reg.registerAttributeParser(2, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPDocumentedException, BGPParsingException { - builder.setAsPath(PathAttributeParser.parseAsPath(bytes)); - } - }); - reg.registerAttributeParser(3, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { - builder.setCNextHop(PathAttributeParser.parseNextHop(bytes)); - } - }); - reg.registerAttributeParser(4, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { - builder.setMultiExitDisc(PathAttributeParser.parseMultiExitDisc(bytes)); - } - }); - reg.registerAttributeParser(5, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { - builder.setLocalPref(PathAttributeParser.parseLocalPref(bytes)); - } - }); - reg.registerAttributeParser(6, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { - builder.setAtomicAggregate(new AtomicAggregateBuilder().build()); - } - }); - reg.registerAttributeParser(7, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { - builder.setAggregator(PathAttributeParser.parseAggregator(bytes)); - } - }); - reg.registerAttributeParser(8, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPDocumentedException { - builder.setCommunities(PathAttributeParser.parseCommunities(bytes)); - } - }); - reg.registerAttributeParser(9, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { - builder.setOriginatorId(PathAttributeParser.parseOriginatorId(bytes)); - } - }); - - reg.registerAttributeParser(10, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { - builder.setClusterId(PathAttributeParser.parseClusterList(bytes)); - } - }); - - reg.registerAttributeParser(14, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPDocumentedException { - PathAttributeParser.parseMPReach(builder, bytes); - } - }); - reg.registerAttributeParser(15, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPDocumentedException { - PathAttributeParser.parseMPUnreach(builder, bytes); - } - }); - reg.registerAttributeParser(16, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPDocumentedException { - builder.setExtendedCommunities(PathAttributeParser.parseExtendedCommunities(bytes)); - } - }); - reg.registerAttributeParser(17, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { - // AS4 Aggregator is ignored - } - }); - reg.registerAttributeParser(18, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) { - // AS4 Path is ignored - } - }); - - // FIXME: update to IANA number once it is known - reg.registerAttributeParser(99, new AttributeParser() { - @Override - public void parseAttribute(final byte[] bytes, final PathAttributesBuilder builder) throws BGPParsingException { - PathAttributeParser.parseLinkState(builder, bytes); - } - }); + reg.registerAttributeParser(OriginAttributeParser.TYPE, new OriginAttributeParser()); + reg.registerAttributeParser(AsPathAttributeParser.TYPE, new AsPathAttributeParser()); + reg.registerAttributeParser(NextHopAttributeParser.TYPE, new NextHopAttributeParser()); + reg.registerAttributeParser(MultiExitDiscriminatorAttributeParser.TYPE, new MultiExitDiscriminatorAttributeParser()); + reg.registerAttributeParser(LocalPreferenceAttributeParser.TYPE, new LocalPreferenceAttributeParser()); + reg.registerAttributeParser(AtomicAggregateAttributeParser.TYPE, new AtomicAggregateAttributeParser()); + reg.registerAttributeParser(AggregatorAttributeParser.TYPE, new AggregatorAttributeParser()); + reg.registerAttributeParser(CommunitiesAttributeParser.TYPE, new CommunitiesAttributeParser()); + reg.registerAttributeParser(OriginatorIdAttributeParser.TYPE, new OriginatorIdAttributeParser()); + reg.registerAttributeParser(ClusterIdAttributeParser.TYPE, new ClusterIdAttributeParser()); + reg.registerAttributeParser(MPReachAttributeParser.TYPE, new MPReachAttributeParser()); + reg.registerAttributeParser(MPUnreachAttributeParser.TYPE, new MPUnreachAttributeParser()); + reg.registerAttributeParser(ExtendedCommunitiesAttributeParser.TYPE, new ExtendedCommunitiesAttributeParser()); + reg.registerAttributeParser(AS4AggregatorAttributeParser.TYPE, new AS4AggregatorAttributeParser()); + reg.registerAttributeParser(AS4PathAttributeParser.TYPE, new AS4PathAttributeParser()); + reg.registerAttributeParser(LinkstateAttributeParser.TYPE, new LinkstateAttributeParser()); INSTANCE = reg; } @@ -133,9 +52,9 @@ public final class SimpleAttributeRegistry implements AttributeRegistry { private final HandlerRegistry handlers = new HandlerRegistry<>(); @Override - public AutoCloseable registerAttributeParser(final int messageType, final AttributeParser parser) { - Preconditions.checkArgument(messageType >= 0 && messageType <= 255); - return handlers.registerParser(messageType, parser); + public AutoCloseable registerAttributeParser(final int attributeType, final AttributeParser parser) { + Preconditions.checkArgument(attributeType >= 0 && attributeType <= 255); + return handlers.registerParser(attributeType, parser); } @Override @@ -143,15 +62,41 @@ public final class SimpleAttributeRegistry implements AttributeRegistry { return handlers.registerSerializer(paramClass, serializer); } - @Override - public boolean parseAttribute(final int attributeType, final byte[] bytes, final PathAttributesBuilder builder) throws BGPDocumentedException, BGPParsingException { - final AttributeParser parser = handlers.getParser(attributeType); + private int parseAttribute( final byte[] bytes, final int offset, final PathAttributesBuilder builder) + throws BGPDocumentedException, BGPParsingException { + // FIXME: validate minimum length + final boolean[] flags = ByteArray.parseBits(bytes[offset]); + final int type = UnsignedBytes.toInt(bytes[offset + 1]); + final int hdrlen; + final int len; + if (flags[3]) { + len = UnsignedBytes.toInt(bytes[offset + 2]) * 256 + UnsignedBytes.toInt(bytes[offset + 3]); + hdrlen = 4; + } else { + len = UnsignedBytes.toInt(bytes[offset + 2]); + hdrlen = 3; + } + + final AttributeParser parser = handlers.getParser(type); if (parser == null) { - return false; + if (!flags[0]) { + throw new BGPDocumentedException("Well known attribute not recognized.", BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED); + } + } else { + parser.parseAttribute(ByteArray.subByte(bytes, offset + hdrlen, len), builder); } - parser.parseAttribute(bytes, builder); - return true; + return hdrlen + len; + } + + @Override + public PathAttributes parseAttributes(final byte[] bytes) throws BGPDocumentedException, BGPParsingException { + int byteOffset = 0; + final PathAttributesBuilder builder = new PathAttributesBuilder(); + while (byteOffset < bytes.length) { + byteOffset += parseAttribute(bytes, byteOffset, builder); + } + return builder.build(); } @Override diff --git a/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/PathAttributeParserTest.java b/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/PathAttributeParserTest.java index 11870ba5af..0ad3e218df 100644 --- a/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/PathAttributeParserTest.java +++ b/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/PathAttributeParserTest.java @@ -14,7 +14,7 @@ import static org.junit.Assert.fail; import org.junit.Test; import org.opendaylight.protocol.bgp.parser.BGPDocumentedException; import org.opendaylight.protocol.bgp.parser.BGPParsingException; -import org.opendaylight.protocol.bgp.parser.impl.message.update.PathAttributeParser; +import org.opendaylight.protocol.bgp.parser.impl.message.update.SimpleAttributeRegistry; /* * To test incorrect values. @@ -24,7 +24,7 @@ public class PathAttributeParserTest { @Test public void testOriginParser() { try { - PathAttributeParser.parseAttribute(new byte[] { 0x40, 0x01, 0x01, 0x04 }); + SimpleAttributeRegistry.INSTANCE.parseAttributes(new byte[] { 0x40, 0x01, 0x01, 0x04 }); fail("This needs to fail."); } catch (final BGPDocumentedException e) { assertEquals("Unknown Origin type.", e.getMessage()); diff --git a/bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/AttributeRegistry.java b/bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/AttributeRegistry.java index ea13945f82..ac47995352 100644 --- a/bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/AttributeRegistry.java +++ b/bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/AttributeRegistry.java @@ -9,13 +9,13 @@ package org.opendaylight.protocol.bgp.parser.spi; 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.rev130918.update.PathAttributesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributes; import org.opendaylight.yangtools.yang.binding.DataObject; public interface AttributeRegistry { public AutoCloseable registerAttributeParser(int attributeType, AttributeParser parser); public AutoCloseable registerAttributeSerializer(Class attributeClass, AttributeSerializer serializer); - public boolean parseAttribute(int attributeType, final byte[] bytes, PathAttributesBuilder builder) throws BGPDocumentedException, BGPParsingException; + public PathAttributes parseAttributes(final byte[] bytes) throws BGPDocumentedException, BGPParsingException; public byte[] serializeAttribute(DataObject attribute); } -- 2.36.6