--- /dev/null
+/*
+ * Copyright (c) 2014 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;
+
+public final class AttributeFlags {
+
+ private AttributeFlags(){
+
+ }
+
+ public static final int OPTIONAL = 128;
+ public static final int TRANSITIVE = 64;
+ public static final int PARTIAL = 32;
+ public static final int EXTENDED = 16;
+ public static final int UNUSED_8 = 8;
+ public static final int UNUSED_4 = 4;
+ public static final int UNUSED_2 = 2;
+ public static final int UNUSED_1 = 1;
+}
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * * 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;
-import com.google.common.base.Preconditions;
+import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
-
import java.util.Arrays;
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.ClusterIdAttributeParser;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.OriginatorIdAttributeParser;
import org.opendaylight.protocol.bgp.parser.spi.AttributeRegistry;
import org.opendaylight.protocol.bgp.parser.spi.MessageParser;
import org.opendaylight.protocol.bgp.parser.spi.MessageSerializer;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.UpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.Nlri;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.NlriBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.WithdrawnRoutes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.WithdrawnRoutesBuilder;
import org.opendaylight.yangtools.yang.binding.Notification;
import org.slf4j.Logger;
}
@Override
- public void serializeMessage(Notification message,ByteBuf bytes) {
+ public void serializeMessage(Notification message, ByteBuf bytes) {
if (message == null) {
throw new IllegalArgumentException("BGPUpdate message cannot be null");
}
final Update update = (Update) message;
ByteBuf messageBody = Unpooled.buffer();
+ WithdrawnRoutes withdrawnRoutes = update.getWithdrawnRoutes();
+ if (withdrawnRoutes != null) {
+ ByteBuf withdrawnRoutesBuf = Unpooled.buffer();
+ for (Ipv4Prefix withdrawnRoutePrefix : withdrawnRoutes.getWithdrawnRoutes()) {
+ int prefixBits = Ipv4Util.getPrefixLength(withdrawnRoutePrefix.getValue());
+ byte[] prefixBytes = ByteArray.subByte(Ipv4Util.bytesForPrefix(withdrawnRoutePrefix), 0,
+ Ipv4Util.getPrefixLengthBytes(withdrawnRoutePrefix.getValue()));
+ withdrawnRoutesBuf.writeByte(prefixBits);
+ withdrawnRoutesBuf.writeBytes(prefixBytes);
+ }
+ messageBody.writeShort(withdrawnRoutesBuf.writerIndex());
+ messageBody.writeBytes(withdrawnRoutesBuf);
+ } else {
+ messageBody.writeZero(2);
+ }
if (update.getPathAttributes() != null) {
- this.reg.serializeAttribute(update.getPathAttributes(), messageBody);
+ ByteBuf pathAttributesBuf = Unpooled.buffer();
+ this.reg.serializeAttribute(update.getPathAttributes(), pathAttributesBuf);
+ ClusterIdAttributeParser clusterIdAttributeParser = new ClusterIdAttributeParser();
+ clusterIdAttributeParser.serializeAttribute(update.getPathAttributes(), pathAttributesBuf);
+
+ OriginatorIdAttributeParser originatorIdAttributeParser = new OriginatorIdAttributeParser();
+ originatorIdAttributeParser.serializeAttribute(update.getPathAttributes(), pathAttributesBuf);
+
+ messageBody.writeShort(pathAttributesBuf.writerIndex());
+ messageBody.writeBytes(pathAttributesBuf);
+ } else {
+ messageBody.writeZero(2);
+ }
+ Nlri nlri = update.getNlri();
+ if (nlri != null) {
+ for (Ipv4Prefix ipv4Prefix : nlri.getNlri()) {
+ int prefixBits = Ipv4Util.getPrefixLength(ipv4Prefix.getValue());
+ byte[] prefixBytes = ByteArray.subByte(Ipv4Util.bytesForPrefix(ipv4Prefix), 0,
+ Ipv4Util.getPrefixLengthBytes(ipv4Prefix.getValue()));
+ messageBody.writeByte(prefixBits);
+ messageBody.writeBytes(prefixBytes);
+ }
}
-
LOG.trace("Update message serialized to {}", ByteBufUtil.hexDump(messageBody));
//FIXME: switch to ByteBuf
- bytes.writeBytes(MessageUtil.formatMessage(TYPE,ByteArray.getAllBytes(messageBody)));
+ bytes.writeBytes(MessageUtil.formatMessage(TYPE, ByteArray.getAllBytes(messageBody)));
}
}
package org.opendaylight.protocol.bgp.parser.impl.message.update;
import com.google.common.base.Preconditions;
-
import io.netty.buffer.ByteBuf;
-
+import io.netty.buffer.Unpooled;
+import org.opendaylight.protocol.bgp.parser.AttributeFlags;
import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
import org.opendaylight.protocol.concepts.Ipv4Util;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Aggregator;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AggregatorBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ShortAsNumber;
import org.opendaylight.yangtools.yang.binding.DataObject;
public final class AggregatorAttributeParser implements AttributeParser, AttributeSerializer {
return;
}
Preconditions.checkArgument(aggregator.getAsNumber() != null, "Missing AS number that formed the aggregate route (encoded as 2 octets).");
- byteAggregator.writeInt(aggregator.getAsNumber().getValue().shortValue());
- byteAggregator.writeBytes(Ipv4Util.bytesForAddress(aggregator.getNetworkAddress()));
+ ShortAsNumber shortAsNumber = new ShortAsNumber(aggregator.getAsNumber());
+ byteAggregator.writeByte(AttributeFlags.OPTIONAL | AttributeFlags.TRANSITIVE);
+ byteAggregator.writeByte(TYPE);
+ ByteBuf aggregatorBuffer = Unpooled.buffer();
+ aggregatorBuffer.writeInt(shortAsNumber.getValue().intValue());
+ aggregatorBuffer.writeBytes(Ipv4Util.bytesForAddress(aggregator.getNetworkAddress()));
+ byteAggregator.writeByte(aggregatorBuffer.writerIndex());
+ byteAggregator.writeBytes(aggregatorBuffer);
}
}
import com.google.common.primitives.UnsignedBytes;
import io.netty.buffer.ByteBuf;
-
+import io.netty.buffer.Unpooled;
import java.util.List;
-
+import org.opendaylight.protocol.bgp.parser.AttributeFlags;
import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
import org.opendaylight.protocol.bgp.parser.BGPError;
import org.opendaylight.protocol.bgp.parser.BGPParsingException;
/**
* Parses AS_PATH from bytes.
*
- * @param buffer bytes to be parsed
- * @return new ASPath object
+ * @param buffer bytes to be parsed @return new ASPath object
* @throws BGPDocumentedException if there is no AS_SEQUENCE present (mandatory)
* @throws BGPParsingException
*/
@Override
public void serializeAttribute(DataObject attribute, ByteBuf byteAggregator) {
PathAttributes pathAttributes = (PathAttributes) attribute;
- if (pathAttributes.getAsPath() == null) {
+ AsPath asPath = pathAttributes.getAsPath();
+ if (asPath == null) {
return;
}
- AsPath asPath = pathAttributes.getAsPath();
- for (Segments segments : asPath.getSegments()) {
- if (segments.getCSegment() instanceof AListCase) {
- AListCase listCase = (AListCase) segments.getCSegment();
- AsPathSegmentParser.serializeAsSequence(listCase, byteAggregator);
- } else if (segments.getCSegment() instanceof ASetCase) {
- ASetCase set = (ASetCase) segments.getCSegment();
- AsPathSegmentParser.serializeAsSet(set, byteAggregator);
- } else {
- LOG.warn("CSegment class is neither AListCase nor ASetCase.");
+
+ byteAggregator.writeByte(AttributeFlags.TRANSITIVE);
+ byteAggregator.writeByte(TYPE);
+
+ ByteBuf segmentsBuffer = Unpooled.buffer();
+ if (asPath.getSegments().size()>0) {
+ for (Segments segments : asPath.getSegments()) {
+ if (segments.getCSegment() instanceof AListCase) {
+ AListCase listCase = (AListCase) segments.getCSegment();
+ AsPathSegmentParser.serializeAsSequence(listCase, segmentsBuffer);
+ } else if (segments.getCSegment() instanceof ASetCase) {
+ ASetCase set = (ASetCase) segments.getCSegment();
+ AsPathSegmentParser.serializeAsSet(set, segmentsBuffer);
+ } else {
+ LOG.warn("Segment class is neither AListCase nor ASetCase.");
+ }
}
}
+ byteAggregator.writeByte(segmentsBuffer.writerIndex());
+ byteAggregator.writeBytes(segmentsBuffer);
}
}
package org.opendaylight.protocol.bgp.parser.impl.message.update;
import io.netty.buffer.ByteBuf;
-
+import org.opendaylight.protocol.bgp.parser.AttributeFlags;
import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathAttributes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AtomicAggregateBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributesBuilder;
import org.opendaylight.yangtools.yang.binding.DataObject;
public final class AtomicAggregateAttributeParser implements AttributeParser,AttributeSerializer {
public static final int TYPE = 6;
+ public static final int ATTR_LENGTH = 0;
@Override
public void parseAttribute(final ByteBuf buffer, final PathAttributesBuilder builder) {
@Override
public void serializeAttribute(DataObject attribute, ByteBuf byteAggregator) {
- // FIXME: add attribute type/length, does not contain any value by definition
- return;
+ PathAttributes pathAttributes = (PathAttributes) attribute;
+ if (pathAttributes.getAtomicAggregate() == null) {
+ return;
+ }
+ byteAggregator.writeByte(AttributeFlags.TRANSITIVE | AttributeFlags.PARTIAL);
+ byteAggregator.writeByte(TYPE);
+ byteAggregator.writeByte(ATTR_LENGTH);
}
}
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
import java.util.List;
+import org.opendaylight.protocol.bgp.parser.AttributeFlags;
import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
import org.opendaylight.protocol.concepts.Ipv4Util;
import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathAttributes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
import org.opendaylight.yangtools.yang.binding.DataObject;
public final class ClusterIdAttributeParser implements AttributeParser, AttributeSerializer {
public static final int TYPE = 10;
-
- private static final int CLUSTER_LENGTH = 4;
+ public static final int ATTR_LENGTH = 4;
@Override
public void parseAttribute(final ByteBuf buffer, final PathAttributesBuilder builder) {
final List<ClusterIdentifier> list = Lists.newArrayList();
while (buffer.isReadable()) {
- list.add(new ClusterIdentifier(Ipv4Util.addressForBytes(ByteArray.readBytes(buffer, CLUSTER_LENGTH))));
+ list.add(new ClusterIdentifier(Ipv4Util.addressForBytes(ByteArray.readBytes(buffer, ATTR_LENGTH))));
}
builder.setClusterId(list);
}
@Override
public void serializeAttribute(DataObject attribute, ByteBuf byteAggregator) {
- //TODO implement this
+ PathAttributes pathAttributes = (PathAttributes) attribute;
+ if (pathAttributes.getClusterId() == null) {
+ return;
+ }
+ ByteBuf clusterIdBuffer = Unpooled.buffer();
+ for (ClusterIdentifier clusterIdentifier : pathAttributes.getClusterId()) {
+ clusterIdBuffer.writeBytes(Ipv4Util.bytesForAddress(clusterIdentifier));
+ }
+ byteAggregator.writeByte(AttributeFlags.OPTIONAL);
+ byteAggregator.writeByte(TYPE);
+ byteAggregator.writeByte(clusterIdBuffer.writerIndex());
+ byteAggregator.writeBytes(clusterIdBuffer);
}
}
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
-
import io.netty.buffer.ByteBuf;
-
+import io.netty.buffer.Unpooled;
import java.util.List;
-
+import org.opendaylight.protocol.bgp.parser.AttributeFlags;
import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
public final class CommunitiesAttributeParser implements AttributeParser, AttributeSerializer {
public static final int TYPE = 8;
+ public static final int ATTR_LENGTH = 4;
private final ReferenceCache refCache;
if (communities == null) {
return;
}
+ ByteBuf communitiesBuffer = Unpooled.buffer();
for (Community community : communities) {
- byteAggregator.writeInt(community.getAsNumber().getValue().intValue());
+ communitiesBuffer.writeShort(community.getAsNumber().getValue().shortValue());
+ communitiesBuffer.writeShort(community.getSemantics().shortValue());
}
+ byteAggregator.writeByte(AttributeFlags.TRANSITIVE | AttributeFlags.PARTIAL);
+ byteAggregator.writeByte(CommunitiesAttributeParser.TYPE);
+ byteAggregator.writeByte(communitiesBuffer.writerIndex());
+ byteAggregator.writeBytes(communitiesBuffer);
}
}
import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
import java.util.List;
+import org.opendaylight.protocol.bgp.parser.AttributeFlags;
import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
if (communitiesList == null) {
return;
}
+ ByteBuf extendedCommunitiesBuffer = Unpooled.buffer();
for (ExtendedCommunities extendedCommunities : communitiesList) {
if (extendedCommunities.getCommSubType() != null) {
- byteAggregator.writeShort(extendedCommunities.getCommSubType());
+ extendedCommunitiesBuffer.writeShort(extendedCommunities.getCommSubType());
}
if (extendedCommunities.getExtendedCommunity() instanceof AsSpecificExtendedCommunityCase) {
AsSpecificExtendedCommunityCase asSpecificExtendedCommunity = (AsSpecificExtendedCommunityCase) extendedCommunities.getExtendedCommunity();
//TODO resolve types correctly
- byteAggregator.writeByte(0);
- byteAggregator.writeByte(1);
+ extendedCommunitiesBuffer.writeByte(0);
+ extendedCommunitiesBuffer.writeByte(1);
- byteAggregator.writeShort(asSpecificExtendedCommunity.getAsSpecificExtendedCommunity().getGlobalAdministrator().getValue().shortValue());
- byteAggregator.writeBytes(asSpecificExtendedCommunity.getAsSpecificExtendedCommunity().getLocalAdministrator());
+ extendedCommunitiesBuffer.writeShort(asSpecificExtendedCommunity.getAsSpecificExtendedCommunity().getGlobalAdministrator().getValue().shortValue());
+ extendedCommunitiesBuffer.writeBytes(asSpecificExtendedCommunity.getAsSpecificExtendedCommunity().getLocalAdministrator());
}
if (extendedCommunities.getExtendedCommunity() instanceof Inet4SpecificExtendedCommunityCase) {
Inet4SpecificExtendedCommunityCase inet4SpecificExtendedCommunity = (Inet4SpecificExtendedCommunityCase) extendedCommunities.getExtendedCommunity();
//TODO resolve types correctly
- byteAggregator.writeByte(1);
- byteAggregator.writeByte(4);
+ extendedCommunitiesBuffer.writeByte(1);
+ extendedCommunitiesBuffer.writeByte(4);
- byteAggregator.writeBytes(Ipv4Util.bytesForAddress(inet4SpecificExtendedCommunity.getInet4SpecificExtendedCommunity().getGlobalAdministrator()));
- byteAggregator.writeBytes(inet4SpecificExtendedCommunity.getInet4SpecificExtendedCommunity().getLocalAdministrator());
+ extendedCommunitiesBuffer.writeBytes(Ipv4Util.bytesForAddress(inet4SpecificExtendedCommunity.getInet4SpecificExtendedCommunity().getGlobalAdministrator()));
+ extendedCommunitiesBuffer.writeBytes(inet4SpecificExtendedCommunity.getInet4SpecificExtendedCommunity().getLocalAdministrator());
}
if (extendedCommunities.getExtendedCommunity() instanceof OpaqueExtendedCommunityCase) {
OpaqueExtendedCommunityCase opaqueExtendedCommunity = (OpaqueExtendedCommunityCase) extendedCommunities.getExtendedCommunity();
//TODO resolve types correctly
- byteAggregator.writeByte(3);
- byteAggregator.writeByte(4);
+ extendedCommunitiesBuffer.writeByte(3);
+ extendedCommunitiesBuffer.writeByte(4);
- byteAggregator.writeBytes(opaqueExtendedCommunity.getOpaqueExtendedCommunity().getValue());
+ extendedCommunitiesBuffer.writeBytes(opaqueExtendedCommunity.getOpaqueExtendedCommunity().getValue());
}
if (extendedCommunities.getExtendedCommunity() instanceof RouteTargetExtendedCommunityCase) {
RouteTargetExtendedCommunityCase routeTargetExtendedCommunity = (RouteTargetExtendedCommunityCase) extendedCommunities.getExtendedCommunity();
//TODO how to determine, which numbering space global administrator number is originated from
- byteAggregator.writeByte(0);
- byteAggregator.writeByte(2);
+ extendedCommunitiesBuffer.writeByte(0);
+ extendedCommunitiesBuffer.writeByte(2);
- byteAggregator.writeShort(routeTargetExtendedCommunity.getRouteTargetExtendedCommunity().getGlobalAdministrator().getValue().shortValue());
- byteAggregator.writeBytes(routeTargetExtendedCommunity.getRouteTargetExtendedCommunity().getLocalAdministrator());
+ extendedCommunitiesBuffer.writeShort(routeTargetExtendedCommunity.getRouteTargetExtendedCommunity().getGlobalAdministrator().getValue().shortValue());
+ extendedCommunitiesBuffer.writeBytes(routeTargetExtendedCommunity.getRouteTargetExtendedCommunity().getLocalAdministrator());
}
if (extendedCommunities.getExtendedCommunity() instanceof RouteOriginExtendedCommunityCase) {
RouteOriginExtendedCommunityCase routeOriginExtendedCommunity = (RouteOriginExtendedCommunityCase) extendedCommunities.getExtendedCommunity();
//TODO how to determine, which numbering space global administrator number is originated from
- byteAggregator.writeByte(2);
- byteAggregator.writeByte(3);
- byteAggregator.writeShort(routeOriginExtendedCommunity.getRouteOriginExtendedCommunity().getGlobalAdministrator().getValue().shortValue());
- byteAggregator.writeBytes(routeOriginExtendedCommunity.getRouteOriginExtendedCommunity().getLocalAdministrator());
+ extendedCommunitiesBuffer.writeByte(2);
+ extendedCommunitiesBuffer.writeByte(3);
+ extendedCommunitiesBuffer.writeShort(routeOriginExtendedCommunity.getRouteOriginExtendedCommunity().getGlobalAdministrator().getValue().shortValue());
+ extendedCommunitiesBuffer.writeBytes(routeOriginExtendedCommunity.getRouteOriginExtendedCommunity().getLocalAdministrator());
}
+ byteAggregator.writeByte(AttributeFlags.OPTIONAL);
+ byteAggregator.writeByte(TYPE);
+ byteAggregator.writeByte(extendedCommunitiesBuffer.writerIndex());
+ byteAggregator.writeBytes(extendedCommunitiesBuffer);
}
}
}
import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
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.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.Nlri;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.destination.destination.type.DestinationIpv4Case;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.destination.destination.type.DestinationIpv4CaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.destination.destination.type.destination.ipv4._case.DestinationIpv4Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+public final class Ipv4NlriParser extends IpNlriParser implements NlriSerializer {
-public final class Ipv4NlriParser extends IpNlriParser {
@Override
protected DestinationIpv4Case parseNlri(final ByteBuf nlri) {
return new DestinationIpv4CaseBuilder().setDestinationIpv4(
new DestinationIpv4Builder().setIpv4Prefixes(Ipv4Util.prefixListForBytes(ByteArray.readAllBytes(nlri))).build()).build();
}
+
+ @Override
+ public void serializeAttribute(DataObject attribute, ByteBuf byteAggregator) {
+ Nlri nlri = (Nlri) attribute;
+ for (Ipv4Prefix ipv4Prefix : nlri.getNlri()) {
+ byteAggregator.writeBytes(Ipv4Util.bytesForPrefix(ipv4Prefix));
+ }
+ }
}
\ No newline at end of file
package org.opendaylight.protocol.bgp.parser.impl.message.update;
import io.netty.buffer.ByteBuf;
-
+import org.opendaylight.protocol.bgp.parser.AttributeFlags;
import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathAttributes;
public final class LocalPreferenceAttributeParser implements AttributeParser,AttributeSerializer {
public static final int TYPE = 5;
+ public static final int LOCAL_PREFS_LENGTH = 4;
@Override
public void parseAttribute(final ByteBuf buffer, final PathAttributesBuilder builder) {
if (lp == null) {
return;
}
- byteAggregator.writeInt(lp.getPref().shortValue());
+
+ byteAggregator.writeByte(AttributeFlags.TRANSITIVE);
+ byteAggregator.writeByte(TYPE);
+ byteAggregator.writeByte(LOCAL_PREFS_LENGTH);
+ byteAggregator.writeInt(lp.getPref().intValue());
}
}
package org.opendaylight.protocol.bgp.parser.impl.message.update;
import io.netty.buffer.ByteBuf;
-
+import org.opendaylight.protocol.bgp.parser.AttributeFlags;
import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathAttributes;
public final class MultiExitDiscriminatorAttributeParser implements AttributeParser, AttributeSerializer {
public static final int TYPE = 4;
+ public static final int ATTR_LENGTH = 4;
@Override
public void parseAttribute(final ByteBuf buffer, final PathAttributesBuilder builder) {
if (multiExitDisc == null) {
return;
}
+ byteAggregator.writeByte(AttributeFlags.OPTIONAL);
+ byteAggregator.writeByte(TYPE);
+ byteAggregator.writeByte(ATTR_LENGTH);
byteAggregator.writeInt(multiExitDisc.getMed().intValue());
}
}
package org.opendaylight.protocol.bgp.parser.impl.message.update;
import com.google.common.base.Preconditions;
-
import io.netty.buffer.ByteBuf;
-
+import io.netty.buffer.Unpooled;
+import org.opendaylight.protocol.bgp.parser.AttributeFlags;
import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
import org.opendaylight.protocol.concepts.Ipv4Util;
if (cNextHop == null) {
return;
}
+ ByteBuf nextHopBuffer = Unpooled.buffer();
if (cNextHop instanceof Ipv4NextHopCase) {
+ byteAggregator.writeByte(AttributeFlags.TRANSITIVE);
+ byteAggregator.writeByte(TYPE);
Ipv4NextHopCase nextHop = (Ipv4NextHopCase) cNextHop;
- byteAggregator.writeBytes(Ipv4Util.bytesForAddress(nextHop.getIpv4NextHop().getGlobal()));
+ nextHopBuffer.writeBytes(Ipv4Util.bytesForAddress(nextHop.getIpv4NextHop().getGlobal()));
+ byteAggregator.writeByte(nextHopBuffer.writerIndex());
+ byteAggregator.writeBytes(nextHopBuffer);
} else if (cNextHop instanceof Ipv6NextHopCase) {
+ byteAggregator.writeByte(AttributeFlags.TRANSITIVE);
+ byteAggregator.writeByte(TYPE);
Ipv6NextHopCase nextHop = (Ipv6NextHopCase) cNextHop;
if (nextHop.getIpv6NextHop().getGlobal() != null) {
- byteAggregator.writeBytes(Ipv6Util.bytesForAddress(nextHop.getIpv6NextHop().getGlobal()));
+ nextHopBuffer.writeBytes(Ipv6Util.bytesForAddress(nextHop.getIpv6NextHop().getGlobal()));
}
if (nextHop.getIpv6NextHop().getLinkLocal() != null) {
- byteAggregator.writeBytes(Ipv6Util.bytesForAddress(nextHop.getIpv6NextHop().getLinkLocal()));
+ nextHopBuffer.writeBytes(Ipv6Util.bytesForAddress(nextHop.getIpv6NextHop().getLinkLocal()));
}
+ byteAggregator.writeByte(nextHopBuffer.writerIndex());
+ byteAggregator.writeBytes(nextHopBuffer);
}
+
}
}
import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.parser.AttributeFlags;
import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
import org.opendaylight.protocol.bgp.parser.BGPError;
import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
public final class OriginAttributeParser implements AttributeParser, AttributeSerializer {
public static final int TYPE = 1;
+ public static final int ATTR_LENGTH = 1;
@Override
public void parseAttribute(final ByteBuf buffer, final PathAttributesBuilder builder) throws BGPDocumentedException {
public void serializeAttribute(DataObject attribute, ByteBuf byteAggregator) {
PathAttributes pathAttributes = (PathAttributes) attribute;
Origin origin = pathAttributes.getOrigin();
- if (origin == null) {
- return;
+ if (origin != null) {
+ byteAggregator.writeByte(AttributeFlags.TRANSITIVE);
+ byteAggregator.writeByte(TYPE);
+ byteAggregator.writeByte(ATTR_LENGTH);
+ byteAggregator.writeByte(origin.getValue().getIntValue());
}
- byteAggregator.writeByte(origin.getValue().getIntValue());
}
}
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.opendaylight.protocol.bgp.parser.AttributeFlags;
import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
import org.opendaylight.protocol.concepts.Ipv4Util;
import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathAttributes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributesBuilder;
import org.opendaylight.yangtools.yang.binding.DataObject;
-public final class OriginatorIdAttributeParser implements AttributeParser, AttributeSerializer {
- public static final int TYPE = 9;
+public final class OriginatorIdAttributeParser implements AttributeParser,AttributeSerializer {
- private static final int ORIGINATOR_LENGTH = 4;
+ public static final int TYPE = 9;
+ public static final int ATTR_LENGTH = 4;
@Override
public void parseAttribute(final ByteBuf buffer, final PathAttributesBuilder builder) {
- Preconditions.checkArgument(buffer.readableBytes() == ORIGINATOR_LENGTH, "Length of byte array for ORIGINATOR_ID should be %s, but is %s", ORIGINATOR_LENGTH, buffer.readableBytes());
- builder.setOriginatorId(Ipv4Util.addressForBytes(ByteArray.readBytes(buffer, ORIGINATOR_LENGTH)));
+ Preconditions.checkArgument(buffer.readableBytes() == ATTR_LENGTH, "Length of byte array for ORIGINATOR_ID should be %s, but is %s", ATTR_LENGTH, buffer.readableBytes());
+ builder.setOriginatorId(Ipv4Util.addressForBytes(ByteArray.readBytes(buffer, ATTR_LENGTH)));
}
@Override
public void serializeAttribute(DataObject attribute, ByteBuf byteAggregator) {
- //FIXME: implement this
+ PathAttributes pathAttributes = (PathAttributes) attribute;
+ if (pathAttributes.getOriginatorId() == null) {
+ return;
+ }
+ ByteBuf originatorIdBuf = Unpooled.buffer();
+ originatorIdBuf.writeBytes(Ipv4Util.bytesForAddress(pathAttributes.getOriginatorId()));
+ byteAggregator.writeByte(AttributeFlags.OPTIONAL);
+ byteAggregator.writeByte(TYPE);
+ byteAggregator.writeByte(originatorIdBuf.writerIndex());
+ byteAggregator.writeBytes(originatorIdBuf);
+
}
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPUpdateMessageParser;
+import org.opendaylight.protocol.bgp.parser.spi.MessageUtil;
+import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AsPath;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Communities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.ExtendedCommunities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.as.path.Segments;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.Nlri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.WithdrawnRoutes;
+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.ExtendedCommunity;
+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.Ipv4NextHopCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.Ipv6NextHopCase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BGPUpdateAttributesSerializationTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BGPUpdateAttributesSerializationTest.class);
+ static final List<byte[]> inputBytes = new ArrayList<byte[]>();
+ private static BGPUpdateMessageParser updateParser = new BGPUpdateMessageParser(ServiceLoaderBGPExtensionProviderContext.getSingletonInstance().getAttributeRegistry());
+
+ private static int COUNTER = 9;//17;
+ private static int MAX_SIZE = 300;
+
+ @Before
+ public void setupUpdateMessage() throws Exception {
+
+ for (int i = 1; i <= COUNTER; i++) {
+ final String name = "/up" + i + ".bin";
+ final InputStream is = BGPParserTest.class.getResourceAsStream(name);
+ if (is == null) {
+ throw new IOException("Failed to get resource " + name);
+ }
+
+ final ByteArrayOutputStream bis = new ByteArrayOutputStream();
+ final byte[] data = new byte[MAX_SIZE];
+ int nRead = 0;
+ while ((nRead = is.read(data, 0, data.length)) != -1) {
+ bis.write(data, 0, nRead);
+ }
+ bis.flush();
+
+ inputBytes.add(bis.toByteArray());
+ }
+
+
+ }
+
+ private Update readUpdateMessageFromList(int listIndex) throws BGPDocumentedException {
+ return readUpdateMessageBytes(Unpooled.copiedBuffer(inputBytes.get(listIndex)));
+ }
+
+ private Update readUpdateMessageBytes(ByteBuf messageBytes) throws BGPDocumentedException {
+ final byte[] body = ByteArray.cutBytes(ByteArray.getAllBytes(messageBytes), MessageUtil.COMMON_HEADER_LENGTH);
+ final int messageLength = ByteArray.bytesToInt(ByteArray.subByte(ByteArray.getAllBytes(messageBytes), MessageUtil.MARKER_LENGTH,
+ MessageUtil.LENGTH_FIELD_LENGTH));
+ return BGPUpdateAttributesSerializationTest.updateParser.parseMessageBody(Unpooled.copiedBuffer(body), messageLength);
+ }
+
+ private void assertEqualsPathAttributes(PathAttributes left, PathAttributes right) {
+ if (left.getCNextHop() != null) {
+ assertEqualsNextHop(left.getCNextHop(), right.getCNextHop());
+ }
+ if (left.getAsPath() != null) {
+ assertEqualsAsPath(left.getAsPath(), right.getAsPath());
+ }
+ if (left.getExtendedCommunities() != null) {
+ assertEqualsExtendedCommunities(left.getExtendedCommunities(), right.getExtendedCommunities());
+ }
+ if (left.getCommunities() != null) {
+ assertEqualsCommunities(left.getCommunities(), right.getCommunities());
+ }
+ if (left.getAggregator() != null) {
+ assertEquals(left.getAggregator().getAsNumber().getValue(), right.getAggregator().getAsNumber().getValue());
+ assertEquals(left.getAggregator().getNetworkAddress().getValue(), right.getAggregator().getNetworkAddress().getValue());
+ }
+ if (left.getAtomicAggregate() != null) {
+ assertEquals(left.getAtomicAggregate() != null, right.getAtomicAggregate() != null);
+ }
+ if (left.getClusterId() != null) {
+ assertEqualsClusterId(left.getClusterId(), right.getClusterId());
+ }
+ if (left.getLocalPref() != null) {
+ assertEquals(left.getLocalPref().getPref(), right.getLocalPref().getPref());
+ }
+ if (left.getMultiExitDisc() != null) {
+ assertEquals(left.getMultiExitDisc().getMed(), right.getMultiExitDisc().getMed());
+ }
+ if (left.getOrigin() != null) {
+ assertEquals(left.getOrigin().getValue().getIntValue(), right.getOrigin().getValue().getIntValue());
+ }
+ if (left.getOriginatorId() != null) {
+ assertEquals(left.getOriginatorId().getValue(), right.getOriginatorId().getValue());
+ }
+ }
+
+ private void assertEqualsClusterId(List<ClusterIdentifier> left, List<ClusterIdentifier> right) {
+ assertEquals(left.size(), right.size());
+ for (ClusterIdentifier clusterIdentifier : left) {
+ right.remove(clusterIdentifier);
+ }
+ assertEquals(right.size(), 0);
+ }
+
+ private void assertEqualsCommunities(List<Communities> left, List<Communities> right) {
+ assertEquals(left.size(), right.size());
+ for (Communities communities : left) {
+ right.remove(communities);
+ }
+ assertEquals(right.size(), 0);
+ }
+
+ private void assertEqualsExtendedCommunities(List<ExtendedCommunities> left, List<ExtendedCommunities> right) {
+ assertEquals(left.size(), right.size());
+ for (ExtendedCommunity extendedCommunity : left) {
+ right.remove(extendedCommunity);
+ }
+ assertEquals(right.size(), 0);
+ }
+
+ private void assertEqualsAsPath(AsPath left, AsPath right) {
+ for (Segments segments : left.getSegments()) {
+ right.getSegments().remove(segments);
+ }
+ assertTrue(right.getSegments().size() == 0);
+ }
+
+ private void assertEqualsNextHop(CNextHop left, CNextHop right) {
+ if (left instanceof Ipv4NextHopCase) {
+ assertTrue(left instanceof Ipv4NextHopCase && right instanceof Ipv4NextHopCase);
+ Ipv4NextHopCase leftIpv4NextHopCase = (Ipv4NextHopCase) left;
+ Ipv4NextHopCase rightIpv4NextHopCase = (Ipv4NextHopCase) right;
+ assertEquals(leftIpv4NextHopCase.getIpv4NextHop().getGlobal().getValue(), rightIpv4NextHopCase.getIpv4NextHop().getGlobal().getValue());
+ }
+ if (left instanceof Ipv6NextHopCase) {
+ assertTrue(left instanceof Ipv6NextHopCase && right instanceof Ipv6NextHopCase);
+ Ipv6NextHopCase leftIpv6NextHopCase = (Ipv6NextHopCase) left;
+ Ipv6NextHopCase rightIpv6NextHopCase = (Ipv6NextHopCase) right;
+ assertEquals(leftIpv6NextHopCase.getIpv6NextHop().getGlobal().getValue(), rightIpv6NextHopCase.getIpv6NextHop().getGlobal().getValue());
+ assertEquals(leftIpv6NextHopCase.getIpv6NextHop().getLinkLocal().getValue(), rightIpv6NextHopCase.getIpv6NextHop().getLinkLocal().getValue());
+ }
+ }
+
+ private void assertEqualsNlri(Nlri left, Nlri right) {
+ assertEquals(left.getNlri().size(), right.getNlri().size());
+ for (Ipv4Prefix ipv4Prefix : left.getNlri()) {
+ right.getNlri().remove(ipv4Prefix);
+ }
+ assertEquals(right.getNlri().size(), 0);
+ }
+
+ private void assertWithdrawnRoutes(WithdrawnRoutes left, WithdrawnRoutes right) {
+ assertEquals(left.getWithdrawnRoutes().size(), right.getWithdrawnRoutes().size());
+ for (Ipv4Prefix ipv4Prefix : left.getWithdrawnRoutes()) {
+ right.getWithdrawnRoutes().remove(ipv4Prefix);
+ }
+ assertEquals(right.getWithdrawnRoutes().size(), 0);
+ }
+
+ @Test
+ public void testUpdateMessageSerialization() throws BGPDocumentedException {
+ for (int i = 0; i < COUNTER; i++) {
+ ByteBuf byteAggregator = Unpooled.buffer();
+ Update originalMessage = readUpdateMessageFromList(i);
+ updateParser.serializeMessage(originalMessage, byteAggregator);
+ ByteBuf reconstructed = Unpooled.buffer();
+ BGPUpdateAttributesSerializationTest.updateParser.serializeMessage(originalMessage, reconstructed);
+ Update serializedMessage = readUpdateMessageBytes(reconstructed);
+ if (originalMessage.getNlri() != null) {
+ assertEqualsNlri(originalMessage.getNlri(), serializedMessage.getNlri());
+ }
+ if (originalMessage.getPathAttributes() != null) {
+ assertEqualsPathAttributes(originalMessage.getPathAttributes(), serializedMessage.getPathAttributes());
+ }
+ if (originalMessage.getWithdrawnRoutes() != null) {
+ assertWithdrawnRoutes(originalMessage.getWithdrawnRoutes(), serializedMessage.getWithdrawnRoutes());
+ }
+ }
+ }
+}
*/
package org.opendaylight.protocol.bgp.parser.spi;
+import io.netty.buffer.ByteBuf;
+
import org.opendaylight.yangtools.yang.binding.DataObject;
public interface NlriSerializer {
- byte[] serializeAttribute(DataObject attribute);
+
+ void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator);
+
}
return a.getAddress();
}
+ /**
+ * Returns number of minimum bytes needed to cover all bits of prefix.
+ *
+ * @param prefix
+ * @return
+ */
+ public static int getPrefixLengthBytes(final String prefix) {
+ int bits = Ipv4Util.getPrefixLength(prefix);
+ if (bits % 8 != 0) {
+ return (bits / 8) + 1;
+ }
+ return bits / 8;
+ }
+
/**
* Converts Ipv4Prefix to byte array.
*
/**
* Creates an Ipv4Prefix object from given byte array.
*
- * @param bytes IPv4 address
+ * @param bytes IPv4 address
* @param length prefix length
* @return Ipv4Prefix object
*/