Utilizing MplsLabel 11/29011/6
authorIveta Halanova <ihalanov@cisco.com>
Thu, 29 Oct 2015 10:59:13 +0000 (11:59 +0100)
committerIveta Halanova <ihalanov@cisco.com>
Tue, 3 Nov 2015 15:33:37 +0000 (16:33 +0100)
Applied in BGP-LU and BGP-LS SR

Change-Id: I0736a96a71a2aca06bf9645df4fdf9b3afa967b9
Signed-off-by: Iveta Halanova <ihalanov@cisco.com>
bgp/labeled-unicast/src/main/java/org/opendaylight/protocol/bgp/labeled/unicast/LUNlriParser.java
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/attribute/sr/SidLabelIndexParser.java
util/src/main/java/org/opendaylight/protocol/util/MplsLabelUtil.java [new file with mode: 0644]
util/src/test/java/org/opendaylight/protocol/util/MplsLabelUtilTest.java [new file with mode: 0644]

index 15c2a094ae09469c630be20a7d2b2f21924b7017..8a0e2e065778ca39bd5de9594c8e7f9611e2d9b9 100644 (file)
@@ -20,6 +20,7 @@ import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
 import org.opendaylight.protocol.util.ByteArray;
 import org.opendaylight.protocol.util.Ipv4Util;
 import org.opendaylight.protocol.util.Ipv6Util;
+import org.opendaylight.protocol.util.MplsLabelUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev150525.labeled.unicast.LabelStack;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev150525.labeled.unicast.LabelStackBuilder;
@@ -40,14 +41,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mult
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv6AddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 
 public class LUNlriParser implements NlriParser, NlriSerializer {
 
     private static final int LABEL_LENGTH = 3;
-    private static final int LABEL_VALUE_OFFSET = 4;
-    private static final byte BOTTOM_LABEL_BIT = 0x1;
 
     @Override
     public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
@@ -83,12 +81,12 @@ public class LUNlriParser implements NlriParser, NlriSerializer {
             // Serialize the label stack entries
             int i = 1;
             for (final LabelStack labelStackEntry : labelStack) {
-                int labelValue = labelStackEntry.getLabelValue().getValue().intValue() << LABEL_VALUE_OFFSET;
                 if (i++ == stackSize) {
                     //mark last label stack entry with bottom-bit
-                    labelValue |= BOTTOM_LABEL_BIT;
+                    nlriByteBuf.writeBytes(MplsLabelUtil.byteBufForMplsLabelWithBottomBit(labelStackEntry.getLabelValue()));
+                } else {
+                    nlriByteBuf.writeBytes(MplsLabelUtil.byteBufForMplsLabel(labelStackEntry.getLabelValue()));
                 }
-                nlriByteBuf.writeMedium(labelValue);
             }
 
             // Serialize the prefix field
@@ -156,14 +154,12 @@ public class LUNlriParser implements NlriParser, NlriSerializer {
             return null;
         }
         final List<LabelStack> labels = new ArrayList<>();
-        long bottomBit = 0;
+        boolean bottomBit = false;
         do {
-            final int label = nlri.readUnsignedMedium();
-            bottomBit = label & BOTTOM_LABEL_BIT;
-            final LabelStackBuilder labelStack = new LabelStackBuilder();
-            labelStack.setLabelValue(new MplsLabel((long) label >> LABEL_VALUE_OFFSET));
-            labels.add(labelStack.build());
-        } while (bottomBit != 1);
+            final ByteBuf slice = nlri.readSlice(LABEL_LENGTH);
+            bottomBit = MplsLabelUtil.getBottomBit(slice);
+            labels.add(new LabelStackBuilder().setLabelValue(MplsLabelUtil.mplsLabelForByteBuf(slice)).build());
+        } while (!bottomBit);
         return labels;
     }
 
index ef3ee0ea173ba75fe77d4578d3d8db14a3dec841..7ac53d663b19b59e005ee14359ca4d66127aa14f 100644 (file)
@@ -12,6 +12,7 @@ import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import java.util.Map;
 import org.opendaylight.protocol.util.Ipv6Util;
+import org.opendaylight.protocol.util.MplsLabelUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.sid.label.index.SidLabelIndex;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.sid.label.index.sid.label.index.Ipv6AddressCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.sid.label.index.sid.label.index.Ipv6AddressCaseBuilder;
@@ -19,7 +20,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segm
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.sid.label.index.sid.label.index.LocalLabelCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.sid.label.index.sid.label.index.SidCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.sid.label.index.sid.label.index.SidCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -51,13 +51,12 @@ public final class SidLabelIndexParser {
     }
 
     static final int SID_TYPE = 1161;
-    private static final int OFFSET = 4;
 
     static ByteBuf serializeSidValue(final SidLabelIndex tlv) {
         if (tlv instanceof Ipv6AddressCase) {
             return Ipv6Util.byteBufForAddress(((Ipv6AddressCase) tlv).getIpv6Address());
         } else if (tlv instanceof LocalLabelCase) {
-            return Unpooled.copyMedium(((LocalLabelCase) tlv).getLocalLabel().getValue().intValue() << OFFSET);
+            return MplsLabelUtil.byteBufForMplsLabel(((LocalLabelCase) tlv).getLocalLabel());
         } else if (tlv instanceof SidCase) {
             return Unpooled.copyInt(((SidCase) tlv).getSid().intValue());
         }
@@ -77,7 +76,7 @@ public final class SidLabelIndexParser {
     static SidLabelIndex parseSidLabelIndex(final Size length, final ByteBuf buffer) {
         switch (length) {
         case LABEL:
-            return new LocalLabelCaseBuilder().setLocalLabel(new MplsLabel((long) buffer.readUnsignedMedium() >> OFFSET)).build();
+            return new LocalLabelCaseBuilder().setLocalLabel(MplsLabelUtil.mplsLabelForByteBuf(buffer)).build();
         case SID:
             return new SidCaseBuilder().setSid(buffer.readUnsignedInt()).build();
         case IPV6_ADD:
diff --git a/util/src/main/java/org/opendaylight/protocol/util/MplsLabelUtil.java b/util/src/main/java/org/opendaylight/protocol/util/MplsLabelUtil.java
new file mode 100644 (file)
index 0000000..018f6d7
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015 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.util;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
+
+/**
+ * Util class for encoding/decoding 20bit leftmost value.
+ */
+public final class MplsLabelUtil {
+
+    private static final int LABEL_OFFSET = 4;
+    private static final byte BOTTOM_LABEL_BIT = 0x1;
+
+    private MplsLabelUtil() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Creates and returns MplsLabel object from 20 leftmost bits in the incoming buffer.
+     * Moves reader index by 3.
+     * @param buffer expecting 3 bytes with 20 leftmost bits as label
+     * @return MplsLabel object
+     */
+    public static MplsLabel mplsLabelForByteBuf(final ByteBuf buffer) {
+        return new MplsLabel(new Long(buffer.readUnsignedMedium() >> LABEL_OFFSET));
+    }
+
+    /**
+     * Serializes incoming MplsLabel without bottom bit
+     * @param label MplsLabel object
+     * @return
+     */
+    public static ByteBuf byteBufForMplsLabel(final MplsLabel label) {
+        return Unpooled.copyMedium(intForMplsLabel(label));
+    }
+
+    /**
+     * Serializes incoming MplsLabel with bottom bit
+     * @param label MplsLabel object
+     * @return
+     */
+    public static ByteBuf byteBufForMplsLabelWithBottomBit(final MplsLabel label) {
+        return Unpooled.copyMedium(intForMplsLabelWithBottomBit(label));
+    }
+
+    /**
+     * Makes a value of incoming label 20 leftmost bits in 24bit number
+     * @param label object
+     * @return shifted value
+     */
+    private static int intForMplsLabel(final MplsLabel label) {
+        return label.getValue().intValue() << LABEL_OFFSET;
+    }
+
+    /**
+     * Makes a value of incoming label 20 leftmost bits in 24bit number and sets bottom bit
+     * @param label object
+     * @return value with bottom bit
+     */
+    private static int intForMplsLabelWithBottomBit(final MplsLabel label) {
+        final int value = intForMplsLabel(label);
+        return setBottomBit(value);
+    }
+
+    /**
+     * Sets bottom bit of 3 byte value
+     * @param value where 20 leftmost bits are label
+     * @return value with set bottom bit
+     */
+    private static int setBottomBit(final int value) {
+        return value | BOTTOM_LABEL_BIT;
+    }
+
+    /**
+     * @param slice with 20 leftmost bits as label
+     * @return value of bottom bit
+     */
+    public static boolean getBottomBit(final ByteBuf slice) {
+        return (slice.getUnsignedMedium(slice.readerIndex()) & BOTTOM_LABEL_BIT) == 1;
+    }
+}
diff --git a/util/src/test/java/org/opendaylight/protocol/util/MplsLabelUtilTest.java b/util/src/test/java/org/opendaylight/protocol/util/MplsLabelUtilTest.java
new file mode 100644 (file)
index 0000000..319fa21
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 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.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import io.netty.buffer.Unpooled;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
+
+public class MplsLabelUtilTest {
+
+    private static final long VAL1 = 5;
+    private static final byte[] VAL1_LEFT_BYTES = new byte[] { 0, 0, 0x50 };
+    private static final byte[] VAL1_LEFT_BYTES_BOTTOM = new byte[] { 0, 0, 0x51 };
+
+    @Test
+    public void testCreateLabel() {
+        assertEquals(new MplsLabel(VAL1), MplsLabelUtil.mplsLabelForByteBuf(Unpooled.copiedBuffer(VAL1_LEFT_BYTES_BOTTOM)));
+    }
+
+    @Test
+    public void testBottomBit() {
+        assertFalse(MplsLabelUtil.getBottomBit(Unpooled.copiedBuffer(VAL1_LEFT_BYTES)));
+        assertTrue(MplsLabelUtil.getBottomBit(Unpooled.copiedBuffer(VAL1_LEFT_BYTES_BOTTOM)));
+    }
+
+    @Test
+    public void testSerialization() {
+        final MplsLabel label = new MplsLabel(VAL1);
+        assertEquals(Unpooled.copiedBuffer(VAL1_LEFT_BYTES), MplsLabelUtil.byteBufForMplsLabel(label));
+        assertEquals(Unpooled.copiedBuffer(VAL1_LEFT_BYTES_BOTTOM), MplsLabelUtil.byteBufForMplsLabelWithBottomBit(label));
+    }
+
+    @Test(expected=UnsupportedOperationException.class)
+    public void testPrivateConstructor() throws Throwable {
+        final Constructor<MplsLabelUtil> c = MplsLabelUtil.class.getDeclaredConstructor();
+        c.setAccessible(true);
+        try {
+            c.newInstance();
+        } catch (final InvocationTargetException e) {
+            throw e.getCause();
+        }
+    }
+}