| /* |
| * 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.types; |
| |
| import com.google.common.collect.ImmutableList; |
| 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.LispIpv4Address.Ipv4AddressWriter; |
| import org.onosproject.lisp.msg.types.LispIpv6Address.Ipv6AddressWriter; |
| |
| import java.util.List; |
| import java.util.Objects; |
| |
| import static com.google.common.base.MoreObjects.toStringHelper; |
| import static com.google.common.base.Preconditions.checkArgument; |
| |
| /** |
| * List type LCAF address class. |
| * <p> |
| * List type is defined in draft-ietf-lisp-lcaf-22 |
| * https://tools.ietf.org/html/draft-ietf-lisp-lcaf-22#page-22 |
| * |
| * <pre> |
| * {@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 = 1 | Rsvd2 | Length | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * | AFI = 1 | IPv4 Address ... | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * | ... IPv4 Address | AFI = 2 | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * | IPv6 Address ... | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * | ... IPv6 Address ... | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * | ... IPv6 Address ... | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * | ... IPv6 Address | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * }</pre> |
| */ |
| public final class LispListLcafAddress extends LispLcafAddress { |
| |
| private static final short LENGTH = 24; |
| List<LispAfiAddress> addresses; |
| |
| /** |
| * Initializes list type LCAF address. |
| * |
| * @param addresses a set of IPv4 and IPv6 addresses |
| */ |
| public LispListLcafAddress(List<LispAfiAddress> addresses) { |
| super(LispCanonicalAddressFormatEnum.LIST, LENGTH); |
| |
| checkArgument(checkAddressValidity(addresses), "Malformed addresses, please " + |
| "specify IPv4 address first, and then specify IPv6 address"); |
| |
| this.addresses = addresses; |
| } |
| |
| /** |
| * Initializes list type LCAF address. |
| * |
| * @param reserved1 reserved1 field |
| * @param flag flag |
| * @param reserved2 reserved2 field |
| * @param addresses a set of IPv4 and IPv6 addresses |
| */ |
| public LispListLcafAddress(byte reserved1, byte reserved2, byte flag, |
| List<LispAfiAddress> addresses) { |
| super(LispCanonicalAddressFormatEnum.LIST, reserved1, flag, reserved2, LENGTH); |
| |
| checkArgument(checkAddressValidity(addresses), "Malformed addresses, please " + |
| "specify IPv4 address first, and then specify IPv6 address"); |
| |
| this.addresses = addresses; |
| } |
| |
| /** |
| * Checks the validity of a collection of input addresses. |
| * |
| * @param addresses a collection of addresses |
| * @return validity result |
| */ |
| private boolean checkAddressValidity(List<LispAfiAddress> addresses) { |
| // we need to make sure that the address collection is comprised of |
| // one IPv4 address and one IPv6 address |
| |
| if (addresses == null || addresses.size() != 2) { |
| return false; |
| } |
| |
| LispAfiAddress ipv4 = addresses.get(0); |
| LispAfiAddress ipv6 = addresses.get(1); |
| |
| if (ipv4.getAfi() != AddressFamilyIdentifierEnum.IP4) { |
| return false; |
| } |
| |
| if (ipv6.getAfi() != AddressFamilyIdentifierEnum.IP6) { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Obtains a set of AFI addresses including IPv4 and IPv6. |
| * |
| * @return a set of AFI addresses |
| */ |
| public List<LispAfiAddress> getAddresses() { |
| return ImmutableList.copyOf(addresses); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(addresses); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| |
| if (obj instanceof LispListLcafAddress) { |
| final LispListLcafAddress other = (LispListLcafAddress) obj; |
| return Objects.equals(this.addresses, other.addresses); |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return toStringHelper(this) |
| .add("addresses", addresses) |
| .toString(); |
| } |
| |
| /** |
| * List LCAF address reader class. |
| */ |
| public static class ListLcafAddressReader |
| implements LispAddressReader<LispListLcafAddress> { |
| |
| @Override |
| public LispListLcafAddress readFrom(ByteBuf byteBuf) |
| throws LispParseError, LispReaderException { |
| |
| LispLcafAddress lcafAddress = LispLcafAddress.deserializeCommon(byteBuf); |
| |
| AfiAddressReader reader = new AfiAddressReader(); |
| |
| LispAfiAddress ipv4 = reader.readFrom(byteBuf); |
| LispAfiAddress ipv6 = reader.readFrom(byteBuf); |
| |
| return new LispListLcafAddress(lcafAddress.getReserved1(), |
| lcafAddress.getReserved2(), |
| lcafAddress.getFlag(), |
| ImmutableList.of(ipv4, ipv6)); |
| } |
| } |
| |
| /** |
| * List LCAF address writer class. |
| */ |
| public static class ListLcafAddressWriter |
| implements LispAddressWriter<LispListLcafAddress> { |
| |
| private static final int IPV4_ADDRESS_INDEX = 0; |
| private static final int IPV6_ADDRESS_INDEX = 1; |
| |
| @Override |
| public void writeTo(ByteBuf byteBuf, LispListLcafAddress address) |
| throws LispWriterException { |
| |
| int lcafIndex = byteBuf.writerIndex(); |
| LispLcafAddress.serializeCommon(byteBuf, address); |
| |
| Ipv4AddressWriter v4Writer = new Ipv4AddressWriter(); |
| Ipv6AddressWriter v6Writer = new Ipv6AddressWriter(); |
| |
| LispAfiAddress ipv4 = address.getAddresses().get(IPV4_ADDRESS_INDEX); |
| LispAfiAddress ipv6 = address.getAddresses().get(IPV6_ADDRESS_INDEX); |
| |
| // IPv4 address |
| byteBuf.writeShort(ipv4.getAfi().getIanaCode()); |
| v4Writer.writeTo(byteBuf, (LispIpv4Address) ipv4); |
| |
| // IPv6 address |
| byteBuf.writeShort(ipv6.getAfi().getIanaCode()); |
| v6Writer.writeTo(byteBuf, (LispIpv6Address) ipv6); |
| |
| LispLcafAddress.updateLength(lcafIndex, byteBuf); |
| } |
| } |
| } |