Bug 611 - serialization of path attributes 17/7517/20
authorMartin Bobak <mbobak@cisco.com>
Thu, 29 May 2014 14:23:32 +0000 (16:23 +0200)
committerMartin Bobak <mbobak@cisco.com>
Thu, 19 Jun 2014 11:42:03 +0000 (13:42 +0200)
- added Nlri,originatorId and clusterId serialization to BGPUPdateMessageParser
- added Ipv4NextHopCase Ipv6NextHopCase serialization
- added serialization methods to attribute objects
- attribute_flags and attribute_type added to all attribute serializers
- attribute descriptors <attribute type, attribute length, attribute
  value> unified by AttributeDescriptor interface
- added tests for Update message serialization

Change-Id: I49e6bb6c0883f125a24fa2a058f0f0bf0e404261
Signed-off-by: Martin Bobak <mbobak@cisco.com>
17 files changed:
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/AttributeFlags.java [new file with mode: 0644]
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPUpdateMessageParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AggregatorAttributeParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AsPathAttributeParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/AtomicAggregateAttributeParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/ClusterIdAttributeParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/CommunitiesAttributeParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/ExtendedCommunitiesAttributeParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/Ipv4NlriParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/LocalPreferenceAttributeParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/MultiExitDiscriminatorAttributeParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/NextHopAttributeParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/OriginAttributeParser.java
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/update/OriginatorIdAttributeParser.java
bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/BGPUpdateAttributesSerializationTest.java [new file with mode: 0644]
bgp/parser-spi/src/main/java/org/opendaylight/protocol/bgp/parser/spi/NlriSerializer.java
concepts/src/main/java/org/opendaylight/protocol/concepts/Ipv4Util.java

diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/AttributeFlags.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/AttributeFlags.java
new file mode 100644 (file)
index 0000000..67b0eb5
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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;
+}
index 94209f23538f8469186b579f98d00946e1609353..ebdf468258c15d02e24229a5e993425d4f916690 100644 (file)
@@ -1,25 +1,24 @@
 /*
- * 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;
@@ -29,8 +28,10 @@ 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;
 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;
@@ -102,7 +103,7 @@ public class BGPUpdateMessageParser implements MessageParser, MessageSerializer
     }
 
     @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");
         }
@@ -110,13 +111,48 @@ public class BGPUpdateMessageParser implements MessageParser, MessageSerializer
         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)));
     }
 }
index d02ef7d2e0180a63920fc9b00ede0b922b9eef3e..8d5a430eec6692a34fcc6ba773dfd9d0ea2041a4 100644 (file)
@@ -8,9 +8,9 @@
 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;
@@ -22,6 +22,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 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 {
@@ -55,7 +56,13 @@ public final class AggregatorAttributeParser implements AttributeParser, Attribu
             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);
     }
 }
index 02831bef795ec5373142ffcd514e15dfb21e0f56..da9e2a123bb70d330ec37608b78dae45635cdcd4 100644 (file)
@@ -12,9 +12,9 @@ import com.google.common.collect.Lists;
 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;
@@ -55,8 +55,7 @@ public final class AsPathAttributeParser implements AttributeParser, AttributeSe
     /**
      * 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
      */
@@ -100,20 +99,29 @@ public final class AsPathAttributeParser implements AttributeParser, AttributeSe
     @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);
     }
 }
index 520a39bec08abc0896a264264794fff00f731e99..d912c29bcc053354e2e13b78112a32e707dfe08c 100644 (file)
@@ -8,9 +8,10 @@
 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;
@@ -18,6 +19,7 @@ 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) {
@@ -26,7 +28,12 @@ public final class AtomicAggregateAttributeParser implements AttributeParser,Att
 
     @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);
     }
 }
index 99c0f5834d69fa662794cfcb44e54c37d0618e06..ee785f410bd72aed5c39f39beca0d1562f5b78bc 100644 (file)
@@ -10,13 +10,16 @@ package org.opendaylight.protocol.bgp.parser.impl.message.update;
 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;
@@ -24,20 +27,30 @@ 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);
     }
 }
index fd0347339850156ba6659073c4c74d2ef2f6b3a2..a233ca96e8e2d7b379132e92d1d74047ba3675b1 100644 (file)
@@ -9,11 +9,10 @@ package org.opendaylight.protocol.bgp.parser.impl.message.update;
 
 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;
@@ -27,6 +26,7 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 public final class CommunitiesAttributeParser implements AttributeParser, AttributeSerializer {
 
     public static final int TYPE = 8;
+    public static final int ATTR_LENGTH = 4;
 
     private final ReferenceCache refCache;
 
@@ -52,8 +52,14 @@ public final class CommunitiesAttributeParser implements AttributeParser, Attrib
         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);
     }
 }
index 267d51ea7c026a0ca765abee8422d67d0651410b..2cb3782ac9552de4285f6a7213e5795b3237e6cc 100644 (file)
@@ -12,8 +12,10 @@ 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;
@@ -57,55 +59,60 @@ public final class ExtendedCommunitiesAttributeParser implements AttributeParser
         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);
         }
     }
 }
index 61b13c50dac2f2638a8f412bbcccc810f0e1771b..a19341f5d3db52c65fb00f168ad02b841a5d4da9 100644 (file)
@@ -9,16 +9,29 @@ package org.opendaylight.protocol.bgp.parser.impl.message.update;
 
 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
index 5b46f3c0b0a091897ec92425c245478193f742d7..d66b1b365253bc7cf7dfadd114369df688096265 100644 (file)
@@ -8,7 +8,7 @@
 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;
@@ -20,6 +20,7 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 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) {
@@ -33,6 +34,10 @@ public final class LocalPreferenceAttributeParser implements AttributeParser,Att
         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());
     }
 }
index 6b2e0f4ed7555246b717003f5bb05dfd7bdb2567..201490a9776f2fa37f412672b9e843315101207f 100644 (file)
@@ -8,7 +8,7 @@
 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;
@@ -20,6 +20,7 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 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) {
@@ -33,6 +34,9 @@ public final class MultiExitDiscriminatorAttributeParser implements AttributePar
         if (multiExitDisc == null) {
             return;
         }
+        byteAggregator.writeByte(AttributeFlags.OPTIONAL);
+        byteAggregator.writeByte(TYPE);
+        byteAggregator.writeByte(ATTR_LENGTH);
         byteAggregator.writeInt(multiExitDisc.getMed().intValue());
     }
 }
index e6c713677a395db4f8ffe28475c4eea9aa0eeec7..506661eeffef9f64b0ce25c6c11b895f867cbce3 100644 (file)
@@ -8,9 +8,9 @@
 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;
@@ -43,17 +43,27 @@ public final class NextHopAttributeParser implements AttributeParser, AttributeS
         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);
         }
+
     }
 }
index 7d45bd88fff7f3c64f92b53cc93134403cdc6d4a..845b44aaf64952bb2d7c3f7c467ed58ac3e12b31 100644 (file)
@@ -11,6 +11,7 @@ import com.google.common.primitives.UnsignedBytes;
 
 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;
@@ -25,6 +26,7 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 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 {
@@ -40,9 +42,11 @@ public final class OriginAttributeParser implements AttributeParser, AttributeSe
     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());
     }
 }
index 77499dc527d7bfa6d8ad254dd47dd1af037a6f9a..b6318a993d8a5406a8becb12f4a3d4a7fa4d4c59 100644 (file)
@@ -10,28 +10,41 @@ 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.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);
+
     }
 }
diff --git a/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/BGPUpdateAttributesSerializationTest.java b/bgp/parser-impl/src/test/java/org/opendaylight/protocol/bgp/parser/impl/BGPUpdateAttributesSerializationTest.java
new file mode 100644 (file)
index 0000000..ad271aa
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * 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());
+            }
+        }
+    }
+}
index 972e0e96e9ead085351d39c89d5faeee447eeba2..d604d694d75f32e7ce5e30d194c5bb489ac54d9c 100644 (file)
@@ -7,8 +7,12 @@
  */
 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);
+
 }
index 435fad881a4edffe1da8e63cc84912078d71c90f..eeae25905bdb052cd78c4e3b0efa73f051752359 100644 (file)
@@ -72,6 +72,20 @@ public final class Ipv4Util {
         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.
      *
@@ -90,7 +104,7 @@ public final class Ipv4Util {
     /**
      * Creates an Ipv4Prefix object from given byte array.
      *
-     * @param bytes IPv4 address
+     * @param bytes  IPv4 address
      * @param length prefix length
      * @return Ipv4Prefix object
      */