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;
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) {
// 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
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;
}
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;
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;
}
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());
}
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:
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+ }
+}