From d55111bf58effde7fe88f8899a8be2d41ece0ab3 Mon Sep 17 00:00:00 2001 From: Jian Li Date: Tue, 7 Feb 2017 10:36:40 +0900 Subject: [PATCH] [ONOS-5945] Add de/serailizer for LISP referral with unit tests Change-Id: I2fa06555d56be0a09046f74a570302d2df2b7539 --- .../protocols/DefaultLispReferralRecord.java | 117 ++++++++++++++- .../DefaultLispReferralRecordTest.java | 132 +++++++++++++++++ .../protocols/DefaultLispReferralTest.java | 136 ++++++++++++++++++ 3 files changed, 382 insertions(+), 3 deletions(-) create mode 100644 protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispReferralRecordTest.java create mode 100644 protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispReferralTest.java diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispReferralRecord.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispReferralRecord.java index 976fdd726b..fff91857ca 100644 --- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispReferralRecord.java +++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispReferralRecord.java @@ -20,10 +20,13 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import io.netty.buffer.ByteBuf; import org.onlab.packet.DeserializationException; +import org.onlab.util.ByteOperator; import org.onosproject.lisp.msg.exceptions.LispParseError; import org.onosproject.lisp.msg.exceptions.LispReaderException; import org.onosproject.lisp.msg.exceptions.LispWriterException; +import org.onosproject.lisp.msg.protocols.DefaultLispReferral.ReferralWriter; import org.onosproject.lisp.msg.types.LispAfiAddress; +import org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter; import java.util.List; @@ -180,15 +183,73 @@ public final class DefaultLispReferralRecord extends AbstractLispRecord } } + /** + * A LISP message reader for ReferralRecord portion. + */ public static final class ReferralRecordReader implements LispMessageReader { + private static final int INCOMPLETE_INDEX = 3; + private static final int AUTHORITATIVE_INDEX = 4; + + private static final int REPLY_ACTION_SHIFT_BIT = 5; + private static final int RESERVED_SKIP_LENGTH = 1; + @Override public LispReferralRecord readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException, DeserializationException { - // TODO: need to implement serialization logic - return null; + + // Record TTL -> 32 bits + int recordTtl = byteBuf.readInt(); + + // referral count -> 8 bits + int referralCount = byteBuf.readUnsignedByte(); + + // EID mask length -> 8 bits + byte maskLength = (byte) byteBuf.readUnsignedByte(); + + byte actionWithFlag = (byte) byteBuf.readUnsignedByte(); + + // action -> 3 bits + int actionByte = actionWithFlag >> REPLY_ACTION_SHIFT_BIT; + LispMapReplyAction action = LispMapReplyAction.valueOf(actionByte); + if (action == null) { + action = LispMapReplyAction.NoAction; + } + + // authoritative flag -> 1 bit + boolean authoritative = ByteOperator.getBit((byte) + (actionWithFlag >> AUTHORITATIVE_INDEX), 0); + + // incomplete flag -> 1 bit + boolean incomplete = ByteOperator.getBit((byte) + (actionWithFlag >> INCOMPLETE_INDEX), 0); + + // let's skip the reserved field + byteBuf.skipBytes(RESERVED_SKIP_LENGTH); + + // Map version number -> 12 bits, we treat Rsvd field is all zero + short mapVersionNumber = (short) byteBuf.readUnsignedShort(); + + LispAfiAddress eidPrefixAfi = + new LispAfiAddress.AfiAddressReader().readFrom(byteBuf); + + List referrals = Lists.newArrayList(); + for (int i = 0; i < referralCount; i++) { + referrals.add(new DefaultLispReferral.ReferralReader().readFrom(byteBuf)); + } + + return new DefaultReferralRecordBuilder() + .withRecordTtl(recordTtl) + .withMaskLength(maskLength) + .withAction(action) + .withIsAuthoritative(authoritative) + .withIsIncomplete(incomplete) + .withMapVersionNumber(mapVersionNumber) + .withReferrals(referrals) + .withEidPrefixAfi(eidPrefixAfi) + .build(); } } @@ -198,10 +259,60 @@ public final class DefaultLispReferralRecord extends AbstractLispRecord public static final class ReferralRecordWriter implements LispMessageWriter { + private static final int REPLY_ACTION_SHIFT_BIT = 5; + private static final int INCOMPLETE_SHIFT_BIT = 3; + private static final int AUTHORITATIVE_SHIFT_BIT = 4; + + private static final int ENABLE_BIT = 1; + private static final int DISABLE_BIT = 0; + + private static final int UNUSED_ZERO = 0; + @Override public void writeTo(ByteBuf byteBuf, LispReferralRecord message) throws LispWriterException { - // TODO: need to implement serialization logic + // record TTL + byteBuf.writeInt(message.getRecordTtl()); + + // referral count + byteBuf.writeByte((byte) message.getReferrals().size()); + + // EID mask length + byteBuf.writeByte(message.getMaskLength()); + + // reply action + byte action = (byte) (message.getAction().getAction() << REPLY_ACTION_SHIFT_BIT); + + // authoritative bit + byte authoritative = DISABLE_BIT; + if (message.isAuthoritative()) { + authoritative = ENABLE_BIT << AUTHORITATIVE_SHIFT_BIT; + } + + // incomplete bit + byte incomplete = DISABLE_BIT; + if (message.isIncomplete()) { + incomplete = ENABLE_BIT << INCOMPLETE_SHIFT_BIT; + } + + byteBuf.writeByte((byte) (action + authoritative + incomplete)); + + // fill zero into reserved field + byteBuf.writeByte((short) UNUSED_ZERO); + + // map version number + byteBuf.writeShort(message.getMapVersionNumber()); + + // EID prefix AFI with EID prefix + AfiAddressWriter afiAddressWriter = new AfiAddressWriter(); + afiAddressWriter.writeTo(byteBuf, message.getEidPrefixAfi()); + + // serialize referrals + ReferralWriter referralWriter = new ReferralWriter(); + List referrals = message.getReferrals(); + for (int i = 0; i < referrals.size(); i++) { + referralWriter.writeTo(byteBuf, referrals.get(i)); + } } } } diff --git a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispReferralRecordTest.java b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispReferralRecordTest.java new file mode 100644 index 0000000000..e3deaf5e7d --- /dev/null +++ b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispReferralRecordTest.java @@ -0,0 +1,132 @@ +/* + * Copyright 2017-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.lisp.msg.protocols; + +import com.google.common.testing.EqualsTester; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.DeserializationException; +import org.onlab.packet.IpAddress; +import org.onosproject.lisp.msg.exceptions.LispParseError; +import org.onosproject.lisp.msg.exceptions.LispReaderException; +import org.onosproject.lisp.msg.exceptions.LispWriterException; +import org.onosproject.lisp.msg.protocols.DefaultLispReferralRecord.DefaultReferralRecordBuilder; +import org.onosproject.lisp.msg.protocols.DefaultLispReferralRecord.ReferralRecordReader; +import org.onosproject.lisp.msg.protocols.DefaultLispReferralRecord.ReferralRecordWriter; +import org.onosproject.lisp.msg.protocols.LispReferralRecord.ReferralRecordBuilder; +import org.onosproject.lisp.msg.types.LispIpv4Address; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +/** + * Unit tests for DefaultLispReferralRecord class. + */ +public final class DefaultLispReferralRecordTest { + + private static final String IP_ADDRESS1 = "192.168.1.1"; + private static final String IP_ADDRESS2 = "192.168.1.2"; + + private LispReferralRecord record1; + private LispReferralRecord sameAsRecord1; + private LispReferralRecord record2; + + @Before + public void setup() { + + ReferralRecordBuilder builder1 = new DefaultReferralRecordBuilder(); + + LispIpv4Address ipv4Address1 = + new LispIpv4Address(IpAddress.valueOf(IP_ADDRESS1)); + + record1 = builder1 + .withRecordTtl(100) + .withIsAuthoritative(true) + .withIsIncomplete(false) + .withMapVersionNumber((short) 1) + .withMaskLength((byte) 0x01) + .withAction(LispMapReplyAction.NativelyForward) + .withEidPrefixAfi(ipv4Address1) + .build(); + + ReferralRecordBuilder builder2 = new DefaultReferralRecordBuilder(); + + sameAsRecord1 = builder2 + .withRecordTtl(100) + .withIsAuthoritative(true) + .withIsIncomplete(false) + .withMapVersionNumber((short) 1) + .withMaskLength((byte) 0x01) + .withAction(LispMapReplyAction.NativelyForward) + .withEidPrefixAfi(ipv4Address1) + .build(); + + ReferralRecordBuilder builder3 = new DefaultReferralRecordBuilder(); + + LispIpv4Address ipv4Address2 = + new LispIpv4Address(IpAddress.valueOf(IP_ADDRESS2)); + + record2 = builder3 + .withRecordTtl(200) + .withIsAuthoritative(false) + .withIsIncomplete(true) + .withMapVersionNumber((short) 2) + .withMaskLength((byte) 0x02) + .withAction(LispMapReplyAction.Drop) + .withEidPrefixAfi(ipv4Address2) + .build(); + } + + @Test + public void testEquality() { + new EqualsTester() + .addEqualityGroup(record1, sameAsRecord1) + .addEqualityGroup(record2).testEquals(); + } + + @Test + public void testConstruction() { + LispReferralRecord record = record1; + + LispIpv4Address ipv4Address1 = + new LispIpv4Address(IpAddress.valueOf(IP_ADDRESS1)); + + assertThat(record.getRecordTtl(), is(100)); + assertThat(record.isAuthoritative(), is(true)); + assertThat(record.isIncomplete(), is(false)); + assertThat(record.getMapVersionNumber(), is((short) 1)); + assertThat(record.getMaskLength(), is((byte) 0x01)); + assertThat(record.getAction(), is(LispMapReplyAction.NativelyForward)); + assertThat(record.getEidPrefixAfi(), is(ipv4Address1)); + } + + @Test + public void testSerialization() throws LispReaderException, LispWriterException, + LispParseError, DeserializationException { + ByteBuf byteBuf = Unpooled.buffer(); + + ReferralRecordWriter writer = new ReferralRecordWriter(); + writer.writeTo(byteBuf, record1); + + ReferralRecordReader reader = new ReferralRecordReader(); + LispReferralRecord deserialized = reader.readFrom(byteBuf); + + new EqualsTester() + .addEqualityGroup(record1, deserialized).testEquals(); + } +} diff --git a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispReferralTest.java b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispReferralTest.java new file mode 100644 index 0000000000..dca108797b --- /dev/null +++ b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispReferralTest.java @@ -0,0 +1,136 @@ +/* + * Copyright 2017-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.lisp.msg.protocols; + +import com.google.common.testing.EqualsTester; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.DeserializationException; +import org.onlab.packet.IpAddress; +import org.onosproject.lisp.msg.exceptions.LispParseError; +import org.onosproject.lisp.msg.exceptions.LispReaderException; +import org.onosproject.lisp.msg.exceptions.LispWriterException; +import org.onosproject.lisp.msg.protocols.DefaultLispReferral.DefaultReferralBuilder; +import org.onosproject.lisp.msg.protocols.DefaultLispReferral.ReferralReader; +import org.onosproject.lisp.msg.protocols.DefaultLispReferral.ReferralWriter; +import org.onosproject.lisp.msg.protocols.LispReferral.ReferralBuilder; +import org.onosproject.lisp.msg.types.LispIpv4Address; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +/** + * Unit tests for DefaultLispReferral class. + */ +public final class DefaultLispReferralTest { + + private static final String IP_ADDRESS1 = "192.168.1.1"; + private static final String IP_ADDRESS2 = "192.168.1.2"; + + private LispReferral referral1; + private LispReferral sameAsReferral1; + private LispReferral referral2; + + @Before + public void setup() { + + ReferralBuilder builder1 = new DefaultReferralBuilder(); + + LispIpv4Address ipv4Address1 = + new LispIpv4Address(IpAddress.valueOf(IP_ADDRESS1)); + + referral1 = builder1 + .withPriority((byte) 0x01) + .withWeight((byte) 0x01) + .withMulticastPriority((byte) 0x01) + .withMulticastWeight((byte) 0x01) + .withLocalLocator(true) + .withRlocProbed(false) + .withRouted(true) + .withLocatorAfi(ipv4Address1) + .build(); + + ReferralBuilder builder2 = new DefaultReferralBuilder(); + + sameAsReferral1 = builder2 + .withPriority((byte) 0x01) + .withWeight((byte) 0x01) + .withMulticastPriority((byte) 0x01) + .withMulticastWeight((byte) 0x01) + .withLocalLocator(true) + .withRlocProbed(false) + .withRouted(true) + .withLocatorAfi(ipv4Address1) + .build(); + + ReferralBuilder builder3 = new DefaultReferralBuilder(); + + LispIpv4Address ipv4Address2 = + new LispIpv4Address(IpAddress.valueOf(IP_ADDRESS2)); + + referral2 = builder3 + .withPriority((byte) 0x02) + .withWeight((byte) 0x02) + .withMulticastPriority((byte) 0x02) + .withMulticastWeight((byte) 0x02) + .withLocalLocator(false) + .withRlocProbed(true) + .withRouted(false) + .withLocatorAfi(ipv4Address2) + .build(); + } + + @Test + public void testEquality() { + new EqualsTester() + .addEqualityGroup(referral1, sameAsReferral1) + .addEqualityGroup(referral2).testEquals(); + } + + @Test + public void testConstruction() { + LispReferral referral = referral1; + + LispIpv4Address ipv4Address = + new LispIpv4Address(IpAddress.valueOf(IP_ADDRESS1)); + + assertThat(referral.getPriority(), is((byte) 0x01)); + assertThat(referral.getWeight(), is((byte) 0x01)); + assertThat(referral.getMulticastPriority(), is((byte) 0x01)); + assertThat(referral.getMulticastWeight(), is((byte) 0x01)); + assertThat(referral.isLocalLocator(), is(true)); + assertThat(referral.isRlocProbed(), is(false)); + assertThat(referral.isRouted(), is(true)); + assertThat(referral.getLocatorAfi(), is(ipv4Address)); + } + + @Test + public void testSerialization() throws LispReaderException, LispWriterException, + LispParseError, DeserializationException { + ByteBuf byteBuf = Unpooled.buffer(); + + ReferralWriter writer = new ReferralWriter(); + writer.writeTo(byteBuf, referral1); + + ReferralReader reader = new ReferralReader(); + LispReferral deserialized = reader.readFrom(byteBuf); + + new EqualsTester() + .addEqualityGroup(referral1, deserialized).testEquals(); + } +}