From 3ff578de254c2121eda81e2cdeb7fbd603f09a0b Mon Sep 17 00:00:00 2001 From: Jian Li Date: Sun, 5 Feb 2017 15:34:37 +0900 Subject: [PATCH] [ONOS-5943] Add LISP nonce LCAF address type Change-Id: I6200ca4ea3432a982b8c1ba10551e2a4b501c1d5 --- .../lcaf/LispCanonicalAddressFormatEnum.java | 1 + .../lisp/msg/types/lcaf/LispLcafAddress.java | 9 + .../msg/types/lcaf/LispNonceLcafAddress.java | 216 ++++++++++++++++++ .../types/lcaf/LispNonceLcafAddressTest.java | 112 +++++++++ 4 files changed, 338 insertions(+) create mode 100644 protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/lcaf/LispNonceLcafAddress.java create mode 100644 protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/lcaf/LispNonceLcafAddressTest.java diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/lcaf/LispCanonicalAddressFormatEnum.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/lcaf/LispCanonicalAddressFormatEnum.java index 6a0492fef4..b6cfa7195c 100644 --- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/lcaf/LispCanonicalAddressFormatEnum.java +++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/lcaf/LispCanonicalAddressFormatEnum.java @@ -30,6 +30,7 @@ public enum LispCanonicalAddressFormatEnum { AS(3), // AS Number Type APPLICATION_DATA(4), // Application Data Type NAT(7), // NAT Traversal Type + NONCE(8), // Nonce Locator Type MULTICAST(9), // Multi-cast Info Type TRAFFIC_ENGINEERING(10), // Explicit Locator Path Type SECURITY(11), // Security Key Type diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/lcaf/LispLcafAddress.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/lcaf/LispLcafAddress.java index 5aff3b9200..920d356400 100644 --- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/lcaf/LispLcafAddress.java +++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/lcaf/LispLcafAddress.java @@ -33,6 +33,7 @@ import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.LIST; import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.MULTICAST; import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.NAT; +import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.NONCE; import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.SEGMENT; import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.SOURCE_DEST; import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.TRAFFIC_ENGINEERING; @@ -412,6 +413,10 @@ public class LispLcafAddress extends LispAfiAddress { return new LispSegmentLcafAddress.SegmentLcafAddressReader().readFrom(byteBuf); } + if (lcafType == NONCE.getLispCode()) { + return new LispNonceLcafAddress.NonceLcafAddressReader().readFrom(byteBuf); + } + if (lcafType == MULTICAST.getLispCode()) { return new LispMulticastLcafAddress.MulticastLcafAddressReader().readFrom(byteBuf); } @@ -456,6 +461,10 @@ public class LispLcafAddress extends LispAfiAddress { new LispSegmentLcafAddress.SegmentLcafAddressWriter().writeTo(byteBuf, (LispSegmentLcafAddress) address); break; + case NONCE: + new LispNonceLcafAddress.NonceLcafAddressWriter().writeTo(byteBuf, + (LispNonceLcafAddress) address); + break; case MULTICAST: new LispMulticastLcafAddress.MulticastLcafAddressWriter().writeTo(byteBuf, (LispMulticastLcafAddress) address); diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/lcaf/LispNonceLcafAddress.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/lcaf/LispNonceLcafAddress.java new file mode 100644 index 0000000000..0930539764 --- /dev/null +++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/lcaf/LispNonceLcafAddress.java @@ -0,0 +1,216 @@ +/* + * 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.types.lcaf; + +import io.netty.buffer.ByteBuf; +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.types.LispAddressReader; +import org.onosproject.lisp.msg.types.LispAddressWriter; +import org.onosproject.lisp.msg.types.LispAfiAddress; + +import java.util.Objects; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Nonce locator data type LCAF address class. + *

+ * Nonce locator data type is defined in draft-ietf-lisp-lcaf-22 + * https://tools.ietf.org/html/draft-ietf-lisp-lcaf-22#page-30 + *

+ *

+ * {@literal
+ *  0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           AFI = 16387         |     Rsvd1     |     Flags     |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |   Type = 8    |     Rsvd2     |             Length            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |   Reserved    |                  Nonce                        |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |              AFI = x          |         Address  ...          |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * }
+ */ +public final class LispNonceLcafAddress extends LispLcafAddress { + + private final int nonce; + private final LispAfiAddress address; + + /** + * Initializes nonce locator data type LCAF address. + * + * @param nonce nonce + * @param address address + */ + private LispNonceLcafAddress(int nonce, LispAfiAddress address) { + super(LispCanonicalAddressFormatEnum.NONCE); + this.nonce = nonce; + this.address = address; + } + + /** + * Obtains nonce. + * + * @return nonce + */ + public int getNonce() { + return nonce; + } + + /** + * Obtains address. + * + * @return address + */ + public LispAfiAddress getAddress() { + return address; + } + + @Override + public int hashCode() { + return Objects.hash(nonce, address); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof LispNonceLcafAddress) { + final LispNonceLcafAddress other = (LispNonceLcafAddress) obj; + return Objects.equals(this.nonce, other.nonce) && + Objects.equals(this.address, other.address); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("nonce", nonce) + .add("address", address) + .toString(); + } + + public static final class NonceAddressBuilder + extends LcafAddressBuilder { + private int nonce; + private LispAfiAddress address; + + /** + * Sets nonce. + * + * @param nonce nonce + * @return NonceAddressBuilder object + */ + public NonceAddressBuilder withNonce(int nonce) { + this.nonce = nonce; + return this; + } + + /** + * Sets address. + * + * @param address address + * @return NonceAddressBuilder object + */ + public NonceAddressBuilder withAddress(LispAfiAddress address) { + this.address = address; + return this; + } + + /** + * Builds LispNonceLcafAddress instance. + * + * @return LispNonceLcafAddress instance + */ + public LispNonceLcafAddress build() { + + checkNotNull(address, "Must specify an address"); + + return new LispNonceLcafAddress(nonce, address); + } + } + + /** + * Nonce LCAF address reader class. + */ + public static class NonceLcafAddressReader + implements LispAddressReader { + + private static final int NONCE_SHIFT_BIT = 16; + private static final int RESERVED_SKIP_LENGTH = 1; + + @Override + public LispNonceLcafAddress readFrom(ByteBuf byteBuf) + throws LispParseError, LispReaderException { + + deserializeCommon(byteBuf); + + byteBuf.skipBytes(RESERVED_SKIP_LENGTH); + + // nonce -> 24 bits + int nonceFirst = byteBuf.readShort() << NONCE_SHIFT_BIT; + int nonceSecond = byteBuf.readInt(); + int nonce = nonceFirst + nonceSecond; + + LispAfiAddress address = new AfiAddressReader().readFrom(byteBuf); + + return new NonceAddressBuilder() + .withNonce(nonce) + .withAddress(address) + .build(); + } + } + + /** + * Nonce LCAF address writer class. + */ + public static class NonceLcafAddressWriter + implements LispAddressWriter { + + private static final int UNUSED_ZERO = 0; + private static final int NONCE_SHIFT_BIT = 16; + + @Override + public void writeTo(ByteBuf byteBuf, LispNonceLcafAddress address) + throws LispWriterException { + int lcafIndex = byteBuf.writerIndex(); + LispLcafAddress.serializeCommon(byteBuf, address); + + // reserved field + byteBuf.writeByte(UNUSED_ZERO); + + // nonce field + int nonceFirst = address.getNonce() >> NONCE_SHIFT_BIT; + byteBuf.writeShort((short) nonceFirst); + int nonceSecond = address.getNonce() - (nonceFirst << NONCE_SHIFT_BIT); + byteBuf.writeInt(nonceSecond); + + // address + AfiAddressWriter writer = new AfiAddressWriter(); + writer.writeTo(byteBuf, address.getAddress()); + + LispLcafAddress.updateLength(lcafIndex, byteBuf); + } + } +} diff --git a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/lcaf/LispNonceLcafAddressTest.java b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/lcaf/LispNonceLcafAddressTest.java new file mode 100644 index 0000000000..378d169bac --- /dev/null +++ b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/lcaf/LispNonceLcafAddressTest.java @@ -0,0 +1,112 @@ +/* + * 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.types.lcaf; + +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.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.types.LispIpv4Address; +import org.onosproject.lisp.msg.types.lcaf.LispNonceLcafAddress.NonceAddressBuilder; +import org.onosproject.lisp.msg.types.lcaf.LispNonceLcafAddress.NonceLcafAddressReader; +import org.onosproject.lisp.msg.types.lcaf.LispNonceLcafAddress.NonceLcafAddressWriter; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +/** + * Unit tests for LispNonceLcafAddress class. + */ +public class LispNonceLcafAddressTest { + + private static final String IP_ADDRESS_1 = "192.168.1.1"; + private static final String IP_ADDRESS_2 = "192.168.1.2"; + + private static final int NONCE_1 = 1048576; + private static final int NONCE_2 = 1; + + private LispNonceLcafAddress address1; + private LispNonceLcafAddress sameAsAddress1; + private LispNonceLcafAddress address2; + + @Before + public void setup() { + + NonceAddressBuilder builder1 = new NonceAddressBuilder(); + + LispIpv4Address ipv4Address1 = + new LispIpv4Address(IpAddress.valueOf(IP_ADDRESS_1)); + + address1 = builder1 + .withNonce(NONCE_1) + .withAddress(ipv4Address1) + .build(); + + NonceAddressBuilder builder2 = new NonceAddressBuilder(); + + sameAsAddress1 = builder2 + .withNonce(NONCE_1) + .withAddress(ipv4Address1) + .build(); + + NonceAddressBuilder builder3 = new NonceAddressBuilder(); + + LispIpv4Address ipv4Address2 = + new LispIpv4Address(IpAddress.valueOf(IP_ADDRESS_2)); + + address2 = builder3 + .withNonce(NONCE_2) + .withAddress(ipv4Address2) + .build(); + } + + @Test + public void testEquality() { + new EqualsTester() + .addEqualityGroup(address1, sameAsAddress1) + .addEqualityGroup(address2).testEquals(); + } + + @Test + public void testConstruction() { + LispNonceLcafAddress nonceLcafAddress = address1; + + LispIpv4Address ipv4Address = + new LispIpv4Address(IpAddress.valueOf(IP_ADDRESS_1)); + + assertThat(nonceLcafAddress.getNonce(), is(NONCE_1)); + assertThat(nonceLcafAddress.getAddress(), is(ipv4Address)); + } + + @Test + public void testSerialization() throws LispWriterException, LispParseError, + LispReaderException { + ByteBuf byteBuf = Unpooled.buffer(); + + NonceLcafAddressWriter writer = new NonceLcafAddressWriter(); + writer.writeTo(byteBuf, address1); + + NonceLcafAddressReader reader = new NonceLcafAddressReader(); + LispNonceLcafAddress deserialized = reader.readFrom(byteBuf); + + new EqualsTester().addEqualityGroup(address1, deserialized).testEquals(); + } +}