diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispInfo.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispInfo.java new file mode 100644 index 0000000000..14cd8842ac --- /dev/null +++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispInfo.java @@ -0,0 +1,230 @@ +/* + * Copyright 2016-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 io.netty.buffer.ByteBuf; +import org.onlab.util.ByteOperator; +import org.onlab.util.ImmutableByteSequence; +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.LispAfiAddress; +import org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter; + +import java.util.Arrays; + +/** + * A class that contains a set of helper methods for LISP info request and reply. + */ +public class DefaultLispInfo implements LispInfo { + + protected final boolean infoReply; + protected final long nonce; + protected final short keyId; + protected final short authDataLength; + protected final byte[] authenticationData; + protected final int ttl; + protected final byte maskLength; + protected final LispAfiAddress eidPrefix; + + private static final int INFO_REPLY_INDEX = 3; + private static final int RESERVED_SKIP_LENGTH_1 = 3; + private static final int RESERVED_SKIP_LENGTH_2 = 1; + + private static final int INFO_REQUEST_SHIFT_BIT = 4; + + private static final int ENABLE_BIT = 1; + private static final int DISABLE_BIT = 0; + + private static final int UNUSED_ZERO = 0; + + /** + * A private constructor that protects object instantiation from external. + * + * @param infoReply info reply flag + * @param nonce nonce + * @param keyId key identifier + * @param authDataLength authentication data length + * @param authenticationData authentication data + * @param ttl Time-To-Live value + * @param maskLength EID prefix mask length + * @param eidPrefix EID prefix + */ + protected DefaultLispInfo(boolean infoReply, long nonce, short keyId, short authDataLength, + byte[] authenticationData, int ttl, byte maskLength, + LispAfiAddress eidPrefix) { + this.infoReply = infoReply; + this.nonce = nonce; + this.keyId = keyId; + this.authDataLength = authDataLength; + this.authenticationData = authenticationData; + this.ttl = ttl; + this.maskLength = maskLength; + this.eidPrefix = eidPrefix; + } + + @Override + public LispType getType() { + return LispType.LISP_INFO; + } + + @Override + public void writeTo(ByteBuf byteBuf) { + // TODO: serialize LispMapRegister message + } + + @Override + public Builder createBuilder() { + return new DefaultLispInfoRequest.DefaultInfoRequestBuilder(); + } + + @Override + public boolean hasInfoReply() { + return infoReply; + } + + @Override + public long getNonce() { + return nonce; + } + + @Override + public short getKeyId() { + return keyId; + } + + @Override + public short getAuthDataLength() { + return authDataLength; + } + + @Override + public byte[] getAuthenticationData() { + if (authenticationData != null && authenticationData.length != 0) { + return ImmutableByteSequence.copyFrom(authenticationData).asArray(); + } else { + return new byte[0]; + } + } + + @Override + public int getTtl() { + return ttl; + } + + @Override + public byte getMaskLength() { + return maskLength; + } + + @Override + public LispAfiAddress getPrefix() { + return eidPrefix; + } + + public static LispInfo deserialize(ByteBuf byteBuf) throws LispParseError, LispReaderException { + + if (byteBuf.readerIndex() != 0) { + return null; + } + + // infoReply -> 1 bit + boolean infoReplyFlag = ByteOperator.getBit(byteBuf.readByte(), INFO_REPLY_INDEX); + + // let's skip the reserved field + byteBuf.skipBytes(RESERVED_SKIP_LENGTH_1); + + // nonce -> 64 bits + long nonce = byteBuf.readLong(); + + // keyId -> 16 bits + short keyId = byteBuf.readShort(); + + // authenticationDataLength -> 16 bits + short authLength = byteBuf.readShort(); + + // authenticationData -> depends on the authenticationDataLength + byte[] authData = new byte[authLength]; + byteBuf.readBytes(authData); + + // ttl -> 32 bits + int ttl = byteBuf.readInt(); + + // let's skip the reserved field + byteBuf.skipBytes(RESERVED_SKIP_LENGTH_2); + + // mask length -> 8 bits + short maskLength = byteBuf.readUnsignedByte(); + + LispAfiAddress prefix = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf); + + return new DefaultLispInfo(infoReplyFlag, nonce, keyId, authLength, + authData, ttl, (byte) maskLength, prefix); + } + + public static void serialize(ByteBuf byteBuf, LispInfo message) throws LispWriterException { + + // specify LISP message type + byte msgType = (byte) (LispType.LISP_INFO.getTypeCode() << INFO_REQUEST_SHIFT_BIT); + + // info reply flag + byte infoReply = DISABLE_BIT; + if (message.hasInfoReply()) { + infoReply = (byte) (ENABLE_BIT << INFO_REPLY_INDEX); + } + + byteBuf.writeByte(msgType + infoReply); + + // fill zero into reserved filed + byteBuf.writeByte((short) UNUSED_ZERO); + byteBuf.writeByte((short) UNUSED_ZERO); + byteBuf.writeByte((short) UNUSED_ZERO); + + // nonce + byteBuf.writeLong(message.getNonce()); + + // keyId + byteBuf.writeShort(message.getKeyId()); + + // authentication data length in octet + byteBuf.writeShort(message.getAuthDataLength()); + + // authentication data + byte[] data = message.getAuthenticationData(); + byte[] clone; + if (data != null) { + clone = data.clone(); + Arrays.fill(clone, (byte) UNUSED_ZERO); + } + + byteBuf.writeBytes(data); + + // TODO: need to implement MAC authentication mechanism + + /// TTL + byteBuf.writeInt(message.getTtl()); + + // fill zero into reserved filed + byteBuf.writeByte((short) UNUSED_ZERO); + + // mask length + byteBuf.writeByte(message.getMaskLength()); + + // EID prefix AFI with EID prefix + AfiAddressWriter afiAddressWriter = new AfiAddressWriter(); + afiAddressWriter.writeTo(byteBuf, message.getPrefix()); + } +} diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoReply.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoReply.java new file mode 100644 index 0000000000..9576deec3b --- /dev/null +++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoReply.java @@ -0,0 +1,219 @@ +/* + * Copyright 2016-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.base.Objects; +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.LispAfiAddress; +import org.onosproject.lisp.msg.types.LispNatLcafAddress; +import org.onosproject.lisp.msg.types.LispNatLcafAddress.NatLcafAddressWriter; + +import java.util.Arrays; + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * Default LISP info reply message class. + */ +public final class DefaultLispInfoReply extends DefaultLispInfo implements LispInfoReply { + + private final LispNatLcafAddress natLcafAddress; + + /** + * A private constructor that protects object instantiation from external. + * + * @param infoReply info reply flag + * @param nonce nonce + * @param keyId key identifier + * @param authDataLength authentication data length + * @param authenticationData authentication data + * @param ttl Time-To-Live value + * @param maskLength EID prefix mask length + * @param eidPrefix EID prefix + * @param natLcafAddress NAT LCAF address + */ + protected DefaultLispInfoReply(boolean infoReply, long nonce, short keyId, short authDataLength, + byte[] authenticationData, int ttl, byte maskLength, + LispAfiAddress eidPrefix, LispNatLcafAddress natLcafAddress) { + super(infoReply, nonce, keyId, authDataLength, authenticationData, ttl, maskLength, eidPrefix); + this.natLcafAddress = natLcafAddress; + } + + @Override + public LispNatLcafAddress getNatLcafAddress() { + return natLcafAddress; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("type", getType()) + .add("nonce", nonce) + .add("keyId", keyId) + .add("authentication data length", authDataLength) + .add("authentication data", authenticationData) + .add("TTL", ttl) + .add("EID mask length", maskLength) + .add("EID prefix", eidPrefix) + .add("NAT LCAF address", natLcafAddress).toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DefaultLispInfoReply that = (DefaultLispInfoReply) o; + return Objects.equal(nonce, that.nonce) && + Objects.equal(keyId, that.keyId) && + Objects.equal(authDataLength, that.authDataLength) && + Arrays.equals(authenticationData, that.authenticationData) && + Objects.equal(ttl, that.ttl) && + Objects.equal(maskLength, that.maskLength) && + Objects.equal(eidPrefix, that.eidPrefix) && + Objects.equal(natLcafAddress, that.natLcafAddress); + } + + @Override + public int hashCode() { + return Objects.hashCode(nonce, keyId, authDataLength, ttl, maskLength, + eidPrefix, natLcafAddress) + Arrays.hashCode(authenticationData); + } + + public static final class DefaultInfoReplyBuilder implements InfoReplyBuilder { + + private boolean infoReply; + private long nonce; + private short keyId; + private short authDataLength; + private byte[] authenticationData = new byte[0]; + private int ttl; + private byte maskLength; + private LispAfiAddress eidPrefix; + private LispNatLcafAddress natLcafAddress; + + @Override + public LispType getType() { + return LispType.LISP_INFO; + } + + + @Override + public InfoReplyBuilder withInfoReply(boolean infoReply) { + this.infoReply = infoReply; + return this; + } + + @Override + public InfoReplyBuilder withNonce(long nonce) { + this.nonce = nonce; + return this; + } + + @Override + public InfoReplyBuilder withAuthDataLength(short authDataLength) { + this.authDataLength = authDataLength; + return this; + } + + @Override + public InfoReplyBuilder withKeyId(short keyId) { + this.keyId = keyId; + return this; + } + + @Override + public InfoReplyBuilder withAuthenticationData(byte[] authenticationData) { + if (authenticationData != null) { + this.authenticationData = authenticationData; + } + return this; + } + + @Override + public InfoReplyBuilder withTtl(int ttl) { + this.ttl = ttl; + return this; + } + + @Override + public InfoReplyBuilder withMaskLength(byte maskLength) { + this.maskLength = maskLength; + return this; + } + + @Override + public InfoReplyBuilder withEidPrefix(LispAfiAddress eidPrefix) { + this.eidPrefix = eidPrefix; + return this; + } + + + @Override + public InfoReplyBuilder withNatLcafAddress(LispNatLcafAddress natLcafAddress) { + this.natLcafAddress = natLcafAddress; + return this; + } + + @Override + public LispInfoReply build() { + return new DefaultLispInfoReply(infoReply, nonce, keyId, authDataLength, + authenticationData, ttl, maskLength, eidPrefix, natLcafAddress); + } + } + + /** + * A LISP message reader for InfoReply message. + */ + public static final class InfoReplyReader implements LispMessageReader { + + @Override + public LispInfoReply readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException { + LispInfo lispInfo = DefaultLispInfo.deserialize(byteBuf); + LispNatLcafAddress natLcafAddress = new LispNatLcafAddress.NatLcafAddressReader().readFrom(byteBuf); + + return new DefaultInfoReplyBuilder() + .withInfoReply(lispInfo.hasInfoReply()) + .withNonce(lispInfo.getNonce()) + .withKeyId(lispInfo.getKeyId()) + .withAuthDataLength(lispInfo.getAuthDataLength()) + .withAuthenticationData(lispInfo.getAuthenticationData()) + .withTtl(lispInfo.getTtl()) + .withMaskLength(lispInfo.getMaskLength()) + .withEidPrefix(lispInfo.getPrefix()) + .withNatLcafAddress(natLcafAddress).build(); + } + } + + public static final class InfoReplyWriter implements LispMessageWriter { + + @Override + public void writeTo(ByteBuf byteBuf, LispInfoReply message) throws LispWriterException { + DefaultLispInfo.serialize(byteBuf, message); + + // NAT LCAF address + NatLcafAddressWriter writer = new NatLcafAddressWriter(); + writer.writeTo(byteBuf, message.getNatLcafAddress()); + } + } +} diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoRequest.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoRequest.java new file mode 100644 index 0000000000..afe473f922 --- /dev/null +++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoRequest.java @@ -0,0 +1,196 @@ +/* + * Copyright 2016-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.base.Objects; +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.LispAfiAddress; + +import java.util.Arrays; + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * Default LISP info request message class. + */ +public class DefaultLispInfoRequest extends DefaultLispInfo implements LispInfoRequest { + + /** + * A private constructor that protects object instantiation from external. + * + * @param infoReply info reply flag + * @param nonce nonce + * @param keyId key identifier + * @param authDataLength authentication data length + * @param authenticationData authentication data + * @param ttl Time-To-Live value + * @param maskLength EID prefix mask length + * @param eidPrefix EID prefix + */ + protected DefaultLispInfoRequest(boolean infoReply, long nonce, short keyId, short authDataLength, + byte[] authenticationData, int ttl, byte maskLength, + LispAfiAddress eidPrefix) { + super(infoReply, nonce, keyId, authDataLength, authenticationData, ttl, maskLength, eidPrefix); + } + + @Override + public String toString() { + return toStringHelper(this) + .add("type", getType()) + .add("nonce", nonce) + .add("keyId", keyId) + .add("authentication data length", authDataLength) + .add("authentication data", authenticationData) + .add("TTL", ttl) + .add("EID mask length", maskLength) + .add("EID prefix", eidPrefix).toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DefaultLispInfoRequest that = (DefaultLispInfoRequest) o; + return Objects.equal(nonce, that.nonce) && + Objects.equal(keyId, that.keyId) && + Objects.equal(authDataLength, that.authDataLength) && + Arrays.equals(authenticationData, that.authenticationData) && + Objects.equal(ttl, that.ttl) && + Objects.equal(maskLength, that.maskLength) && + Objects.equal(eidPrefix, that.eidPrefix); + } + + @Override + public int hashCode() { + return Objects.hashCode(nonce, keyId, authDataLength, ttl, maskLength, + eidPrefix) + Arrays.hashCode(authenticationData); + } + + public static final class DefaultInfoRequestBuilder implements InfoRequestBuilder { + + private boolean infoReply; + private long nonce; + private short keyId; + private short authDataLength; + private byte[] authenticationData = new byte[0]; + private int ttl; + private byte maskLength; + private LispAfiAddress eidPrefix; + + @Override + public LispType getType() { + return LispType.LISP_INFO; + } + + + @Override + public InfoRequestBuilder withInfoReply(boolean infoReply) { + this.infoReply = infoReply; + return this; + } + + @Override + public InfoRequestBuilder withNonce(long nonce) { + this.nonce = nonce; + return this; + } + + @Override + public InfoRequestBuilder withAuthDataLength(short authDataLength) { + this.authDataLength = authDataLength; + return this; + } + + @Override + public InfoRequestBuilder withKeyId(short keyId) { + this.keyId = keyId; + return this; + } + + @Override + public InfoRequestBuilder withAuthenticationData(byte[] authenticationData) { + if (authenticationData != null) { + this.authenticationData = authenticationData; + } + return this; + } + + @Override + public InfoRequestBuilder withTtl(int ttl) { + this.ttl = ttl; + return this; + } + + @Override + public InfoRequestBuilder withMaskLength(byte maskLength) { + this.maskLength = maskLength; + return this; + } + + @Override + public InfoRequestBuilder withEidPrefix(LispAfiAddress eidPrefix) { + this.eidPrefix = eidPrefix; + return this; + } + + @Override + public LispInfoRequest build() { + return new DefaultLispInfoRequest(infoReply, nonce, keyId, + authDataLength, authenticationData, ttl, maskLength, eidPrefix); + } + } + + /** + * A LISP message reader for InfoRequest message. + */ + public static class InfoRequestReader implements LispMessageReader { + + @Override + public LispInfoRequest readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException { + + LispInfo lispInfo = DefaultLispInfo.deserialize(byteBuf); + + return new DefaultInfoRequestBuilder() + .withInfoReply(lispInfo.hasInfoReply()) + .withNonce(lispInfo.getNonce()) + .withKeyId(lispInfo.getKeyId()) + .withAuthDataLength(lispInfo.getAuthDataLength()) + .withAuthenticationData(lispInfo.getAuthenticationData()) + .withTtl(lispInfo.getTtl()) + .withMaskLength(lispInfo.getMaskLength()) + .withEidPrefix(lispInfo.getPrefix()).build(); + } + } + + /** + * A LISP message writer for InfoRequest message. + */ + public static final class InfoRequestWriter implements LispMessageWriter { + + @Override + public void writeTo(ByteBuf byteBuf, LispInfoRequest message) throws LispWriterException { + DefaultLispInfo.serialize(byteBuf, message); + } + } +} diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRegister.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRegister.java index 7ccc7b676a..2d1ff43453 100644 --- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRegister.java +++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRegister.java @@ -51,6 +51,7 @@ public final class DefaultLispMapRegister implements LispMapRegister { * * @param nonce nonce * @param keyId key identifier + * @param authDataLength authentication data length * @param authenticationData authentication data * @param mapRecords a collection of map records * @param proxyMapReply proxy map reply flag diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/InfoBuilder.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/InfoBuilder.java new file mode 100644 index 0000000000..0b6f3811da --- /dev/null +++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/InfoBuilder.java @@ -0,0 +1,89 @@ +/* + * Copyright 2016-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 org.onosproject.lisp.msg.protocols.LispMessage.Builder; +import org.onosproject.lisp.msg.types.LispAfiAddress; + +/** + * LISP info message interface. + */ +public interface InfoBuilder extends Builder { + + /** + * Sets info reply flag value. + * + * @param infoReply info reply + * @return T object + */ + T withInfoReply(boolean infoReply); + + /** + * Sets nonce value. + * + * @param nonce nonce value + * @return T object + */ + T withNonce(long nonce); + + /** + * Sets authentication data length. + * + * @param authDataLength authentication data length + * @return T object + */ + T withAuthDataLength(short authDataLength); + + /** + * Sets key identifier. + * + * @param keyId key identifier + * @return T object + */ + T withKeyId(short keyId); + + /** + * Sets authentication data. + * + * @param authenticationData authentication data + * @return T object + */ + T withAuthenticationData(byte[] authenticationData); + + /** + * Sets Time-To-Live value. + * + * @param ttl Time-To-Live value + * @return T object + */ + T withTtl(int ttl); + + /** + * Sets EID prefix mask length. + * + * @param maskLength EID prefix mask length + * @return T object + */ + T withMaskLength(byte maskLength); + + /** + * Sets EID prefix. + * + * @param eidPrefix EID prefix + * @return T object + */ + T withEidPrefix(LispAfiAddress eidPrefix); +} diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispInfo.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispInfo.java new file mode 100644 index 0000000000..1fd9b46073 --- /dev/null +++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispInfo.java @@ -0,0 +1,80 @@ +/* + * Copyright 2016-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 org.onosproject.lisp.msg.types.LispAfiAddress; + +/** + * LISP info super interface. + */ +public interface LispInfo extends LispMessage { + + /** + * Obtains has info reply flag value. + * + * @return has info reply flag value + */ + boolean hasInfoReply(); + + /** + * Obtains nonce value. + * + * @return nonce value + */ + long getNonce(); + + /** + * Obtains key identifier. + * + * @return key identifier + */ + short getKeyId(); + + /** + * Obtains authentication data length. + * + * @return authentication data length + */ + short getAuthDataLength(); + + /** + * Obtains authentication data. + * + * @return authentication data + */ + byte[] getAuthenticationData(); + + /** + * Obtains TTL value. + * + * @return record TTL value + */ + int getTtl(); + + /** + * Obtains mask length of the EID Record. + * + * @return mask length of the EID Record + */ + byte getMaskLength(); + + /** + * Obtains EID prefix. + * + * @return EID prefix + */ + LispAfiAddress getPrefix(); +} diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispInfoReply.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispInfoReply.java new file mode 100644 index 0000000000..05c642cf9f --- /dev/null +++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispInfoReply.java @@ -0,0 +1,91 @@ +/* + * Copyright 2016-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 org.onosproject.lisp.msg.types.LispNatLcafAddress; + +/** + * LISP info reply message interface. + *

+ * LISP info reply message format is defined in draft-ermagan-lisp-nat-traversal-01. + * https://tools.ietf.org/html/draft-ermagan-lisp-nat-traversal-01#page-8 + * + *

+ * {@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
+ *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *    |Type=7 |R|               Reserved                              |
+ *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *    |                         Nonce . . .                           |
+ *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *    |                      . . . Nonce                              |
+ *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *    |            Key ID             |  Authentication Data Length   |
+ *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *    ~                     Authentication Data                       ~
+ *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *    |                              TTL                              |
+ *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *    |   Reserved    | EID mask-len  |        EID-prefix-AFI         |
+ *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *    |                          EID-prefix                           |
+ * +->+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  |           AFI = 16387         |    Rsvd1      |     Flags     |
+ * |  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  |    Type = 7     |     Rsvd2   |             4 + n             |
+ * |  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * N  |        MS UDP Port Number     |      ETR UDP Port Number      |
+ * A  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * T  |              AFI = x          | Global ETR RLOC Address  ...  |
+ *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * L  |              AFI = x          |       MS RLOC Address  ...    |
+ * C  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * A  |              AFI = x          | Private ETR RLOC Address ...  |
+ * F  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  |              AFI = x          |      RTR RLOC Address 1 ...   |
+ * |  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  |              AFI = x          |       RTR RLOC Address n ...  |
+ * +->+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * }
+ */ +public interface LispInfoReply extends LispInfo { + + /** + * Obtains NAT LCAF address. + * + * @return NAT LCAF address + */ + LispNatLcafAddress getNatLcafAddress(); + + interface InfoReplyBuilder extends InfoBuilder { + + /** + * Sets NAT LCAF address. + * + * @param natLcafAddress NAT LCAF address + * @return InfoReplyBuilder object + */ + InfoReplyBuilder withNatLcafAddress(LispNatLcafAddress natLcafAddress); + + /** + * Builds LISP info reply message. + * + * @return LISP info reply message + */ + LispInfoReply build(); + } +} diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispInfoRequest.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispInfoRequest.java new file mode 100644 index 0000000000..81a9dcff1a --- /dev/null +++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispInfoRequest.java @@ -0,0 +1,60 @@ +/* + * Copyright 2016-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; + +/** + * LISP info request message interface. + *

+ * LISP info request message format is defined in draft-ermagan-lisp-nat-traversal-01. + * https://tools.ietf.org/html/draft-ermagan-lisp-nat-traversal-01#page-7 + * + *

+ * {@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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |Type=7 |R|            Reserved                                 |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         Nonce . . .                           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                      . . . Nonce                              |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |              Key ID           |  Authentication Data Length   |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~                     Authentication Data                       ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                              TTL                              |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |   Reserved    | EID mask-len  |        EID-prefix-AFI         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                          EID-prefix                           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |             AFI = 0           |        |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * }
+ */ +public interface LispInfoRequest extends LispInfo { + + interface InfoRequestBuilder extends InfoBuilder { + + /** + * Builds LISP info request message. + * + * @return LISP info request message + */ + LispInfoRequest build(); + } +} diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispType.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispType.java index 401f10b885..aeacc00b04 100644 --- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispType.java +++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispType.java @@ -27,6 +27,7 @@ public enum LispType { LISP_MAP_REPLY(2), // LISP Map-Reply Message LISP_MAP_REGISTER(3), // LISP Map-Register Message LISP_MAP_NOTIFY(4), // LISP Map-Notify Message + LISP_INFO(7), // LISP Info-Request or Info-Reply Message UNKNOWN(-1); // Other Enums for internal use private final short type; diff --git a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoReplyTest.java b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoReplyTest.java new file mode 100644 index 0000000000..1952a03ea4 --- /dev/null +++ b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoReplyTest.java @@ -0,0 +1,163 @@ +/* + * Copyright 2016-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.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.DefaultLispInfoReply.DefaultInfoReplyBuilder; +import org.onosproject.lisp.msg.protocols.DefaultLispInfoReply.InfoReplyReader; +import org.onosproject.lisp.msg.protocols.DefaultLispInfoReply.InfoReplyWriter; +import org.onosproject.lisp.msg.protocols.LispInfoReply.InfoReplyBuilder; +import org.onosproject.lisp.msg.types.LispIpv4Address; +import org.onosproject.lisp.msg.types.LispNatLcafAddress; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +/** + * Unit tests for DefaultLispInfoReply class. + */ +public final class DefaultLispInfoReplyTest { + + private LispInfoReply reply1; + private LispInfoReply sameAsReply1; + private LispInfoReply reply2; + + @Before + public void setup() { + + InfoReplyBuilder builder1 = new DefaultInfoReplyBuilder(); + + short msUdpPortNumber1 = 80; + short etrUdpPortNumber1 = 100; + LispIpv4Address globalEtrRlocAddress1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.1")); + LispIpv4Address msRlocAddress1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.2")); + LispIpv4Address privateEtrRlocAddress1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.3")); + + LispIpv4Address address1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.4")); + + LispNatLcafAddress natLcafAddress1 = new LispNatLcafAddress.NatAddressBuilder() + .withLength((short) 0) + .withMsUdpPortNumber(msUdpPortNumber1) + .withEtrUdpPortNumber(etrUdpPortNumber1) + .withGlobalEtrRlocAddress(globalEtrRlocAddress1) + .withMsRlocAddress(msRlocAddress1) + .withPrivateEtrRlocAddress(privateEtrRlocAddress1) + .build(); + + reply1 = builder1 + .withNonce(1L) + .withKeyId((short) 1) + .withInfoReply(false) + .withMaskLength((byte) 1) + .withEidPrefix(address1) + .withNatLcafAddress(natLcafAddress1).build(); + + InfoReplyBuilder builder2 = new DefaultInfoReplyBuilder(); + + sameAsReply1 = builder2 + .withNonce(1L) + .withKeyId((short) 1) + .withInfoReply(false) + .withMaskLength((byte) 1) + .withEidPrefix(address1) + .withNatLcafAddress(natLcafAddress1).build(); + + InfoReplyBuilder builder3 = new DefaultInfoReplyBuilder(); + + short msUdpPortNumber2 = 81; + short etrUdpPortNumber2 = 101; + LispIpv4Address globalEtrRlocAddress2 = new LispIpv4Address(IpAddress.valueOf("192.168.2.1")); + LispIpv4Address msRlocAddress2 = new LispIpv4Address(IpAddress.valueOf("192.168.2.2")); + LispIpv4Address privateEtrRlocAddress2 = new LispIpv4Address(IpAddress.valueOf("192.168.2.3")); + + LispIpv4Address address2 = new LispIpv4Address(IpAddress.valueOf("192.168.2.4")); + + LispNatLcafAddress natLcafAddress2 = new LispNatLcafAddress.NatAddressBuilder() + .withLength((short) 0) + .withMsUdpPortNumber(msUdpPortNumber2) + .withEtrUdpPortNumber(etrUdpPortNumber2) + .withGlobalEtrRlocAddress(globalEtrRlocAddress2) + .withMsRlocAddress(msRlocAddress2) + .withPrivateEtrRlocAddress(privateEtrRlocAddress2) + .build(); + + reply2 = builder3 + .withNonce(2L) + .withKeyId((short) 2) + .withInfoReply(true) + .withMaskLength((byte) 1) + .withEidPrefix(address2) + .withNatLcafAddress(natLcafAddress2).build(); + } + + @Test + public void testEquality() { + new EqualsTester() + .addEqualityGroup(reply1, sameAsReply1) + .addEqualityGroup(reply2).testEquals(); + } + + @Test + public void testConstruction() { + DefaultLispInfoReply reply = (DefaultLispInfoReply) reply1; + + LispIpv4Address address = new LispIpv4Address(IpAddress.valueOf("192.168.1.4")); + + short msUdpPortNumber1 = 80; + short etrUdpPortNumber1 = 100; + LispIpv4Address globalEtrRlocAddress1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.1")); + LispIpv4Address msRlocAddress1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.2")); + LispIpv4Address privateEtrRlocAddress1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.3")); + + LispNatLcafAddress natLcafAddress = new LispNatLcafAddress.NatAddressBuilder() + .withLength((short) 0) + .withMsUdpPortNumber(msUdpPortNumber1) + .withEtrUdpPortNumber(etrUdpPortNumber1) + .withGlobalEtrRlocAddress(globalEtrRlocAddress1) + .withMsRlocAddress(msRlocAddress1) + .withPrivateEtrRlocAddress(privateEtrRlocAddress1) + .build(); + + assertThat(reply.hasInfoReply(), is(false)); + assertThat(reply.getNonce(), is(1L)); + assertThat(reply.getKeyId(), is((short) 1)); + assertThat(reply.getMaskLength(), is((byte) 1)); + assertThat(reply.getPrefix(), is(address)); + assertThat(reply.getNatLcafAddress(), is(natLcafAddress)); + } + + @Test + public void testSerialization() throws LispReaderException, LispWriterException, LispParseError { + ByteBuf byteBuf = Unpooled.buffer(); + + InfoReplyWriter writer = new InfoReplyWriter(); + writer.writeTo(byteBuf, reply1); + + InfoReplyReader reader = new InfoReplyReader(); + LispInfoReply deserialized = reader.readFrom(byteBuf); + + new EqualsTester() + .addEqualityGroup(reply1, deserialized).testEquals(); + } +} diff --git a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoRequestTest.java b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoRequestTest.java new file mode 100644 index 0000000000..501b82f3d3 --- /dev/null +++ b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoRequestTest.java @@ -0,0 +1,114 @@ +/* + * Copyright 2016-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.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.DefaultLispInfoRequest.DefaultInfoRequestBuilder; +import org.onosproject.lisp.msg.protocols.DefaultLispInfoRequest.InfoRequestReader; +import org.onosproject.lisp.msg.protocols.DefaultLispInfoRequest.InfoRequestWriter; +import org.onosproject.lisp.msg.protocols.LispInfoRequest.InfoRequestBuilder; +import org.onosproject.lisp.msg.types.LispIpv4Address; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +/** + * Unit tests for DefaultLispInfoRequest class. + */ +public final class DefaultLispInfoRequestTest { + + private LispInfoRequest request1; + private LispInfoRequest sameAsRequest1; + private LispInfoRequest request2; + + @Before + public void setup() { + + InfoRequestBuilder builder1 = new DefaultInfoRequestBuilder(); + + LispIpv4Address address1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.1")); + + request1 = builder1 + .withNonce(1L) + .withKeyId((short) 1) + .withInfoReply(false) + .withMaskLength((byte) 1) + .withEidPrefix(address1).build(); + + InfoRequestBuilder builder2 = new DefaultInfoRequestBuilder(); + + sameAsRequest1 = builder2 + .withNonce(1L) + .withKeyId((short) 1) + .withInfoReply(false) + .withMaskLength((byte) 1) + .withEidPrefix(address1).build(); + + InfoRequestBuilder builder3 = new DefaultInfoRequestBuilder(); + + LispIpv4Address address2 = new LispIpv4Address(IpAddress.valueOf("192.168.2.1")); + + request2 = builder3 + .withNonce(2L) + .withKeyId((short) 2) + .withInfoReply(true) + .withMaskLength((byte) 1) + .withEidPrefix(address2).build(); + } + + @Test + public void testEquality() { + new EqualsTester() + .addEqualityGroup(request1, sameAsRequest1) + .addEqualityGroup(request2).testEquals(); + } + + @Test + public void testConstruction() { + DefaultLispInfoRequest request = (DefaultLispInfoRequest) request1; + + LispIpv4Address address = new LispIpv4Address(IpAddress.valueOf("192.168.1.1")); + + assertThat(request.hasInfoReply(), is(false)); + assertThat(request.getNonce(), is(1L)); + assertThat(request.getKeyId(), is((short) 1)); + assertThat(request.getMaskLength(), is((byte) 1)); + assertThat(request.getPrefix(), is(address)); + } + + + @Test + public void testSerialization() throws LispReaderException, LispWriterException, LispParseError { + ByteBuf byteBuf = Unpooled.buffer(); + + InfoRequestWriter writer = new InfoRequestWriter(); + writer.writeTo(byteBuf, request1); + + InfoRequestReader reader = new InfoRequestReader(); + LispInfoRequest deserialized = reader.readFrom(byteBuf); + + new EqualsTester() + .addEqualityGroup(request1, deserialized).testEquals(); + } +}