2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.lispflowmapping.southbound.lisp.cache;
10 import java.net.InetAddress;
11 import java.nio.ByteBuffer;
12 import java.util.HashMap;
14 import java.util.Optional;
15 import org.opendaylight.lispflowmapping.lisp.serializer.MapRegisterSerializer;
16 import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana.afn.safi.rev130704.AddressFamily;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.key.container.MapRegisterCacheKey;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.key.container.MapRegisterCacheKeyBuilder;
21 public final class MapRegisterPartialDeserializer {
34 private static final int PAYLOAD1_LEN = 4;
40 private static final int SKIP1_LEN = 8;
46 private static final int PAYLOAD2_LEN = 2;
48 private static final int NUM_OF_BYTES_FROM_START_TO_AUTH_DATA_LENGTH_POS = PAYLOAD1_LEN + SKIP1_LEN + PAYLOAD2_LEN;
49 private static final int NUM_OF_BYTES_AUTHENTICATION_DATA_LENGTH = 2;
54 * - 8bits Locator Count
55 * - 8bits EID mask-len
60 * - 12bits Map-Version Number
62 private static final int NUM_OF_BYTES_FROM_AUTH_DATA_TO_EID_PREFIX_AFI = 10;
63 private static final int NUM_OF_BYTES_EID_PREFIX_AFI = 2;
64 private static final int NUM_OF_BYTES_IPV4 = 4;
65 private static final int NUM_OF_BYTES_IPV6 = 16;
66 private static final int NUM_OF_BYTES_MAC48 = 6;
67 private static final byte XTR_SITE_ID = 0x02;
68 private static final byte MERGE_ENABLED_BIT_POSITION = 0x04;
69 private static final int NUM_OF_BYTES_FROM_EID_PREFIX_AFI_TO_LCAF_LENGTH = 6;
70 private static final int NUM_OF_BYTES_FROM_LCAF_RSVD1_TO_LCAF_LENGTH = 6;
73 private MapRegisterPartialDeserializer() {
74 throw new UnsupportedOperationException("Trying to instantiate util class.");
77 public static Map.Entry<MapRegisterCacheKey, byte[]> deserializePartially(final ByteBuffer buffer,
78 final InetAddress sourceRloc) {
80 final byte thirdByte = buffer.get(2);
81 //if merge bit is set to 1, not store to cache.
82 final boolean isMergeBitSet = ByteUtil.extractBit(thirdByte, MERGE_ENABLED_BIT_POSITION);
87 final int authDataLength = ByteUtil.getUnsignedShort(buffer, NUM_OF_BYTES_FROM_START_TO_AUTH_DATA_LENGTH_POS);
89 MapRegisterCacheKey mapRegisterCacheKey = createKeyFromBytes(buffer, authDataLength);
90 if (mapRegisterCacheKey == null) {
93 final byte[] relevantPayloadData = createValueFromBytes(buffer, authDataLength);
96 return new HashMap.SimpleEntry<>(mapRegisterCacheKey, relevantPayloadData);
100 * Extract from buffer the data which doesn't change.
102 * It means that nonce and authentication items are ommited (skipped).
104 * payload1 - <Type;RecordCount>
107 * skip2 - <Authentication Data Length; Authentication Data>
108 * payload3 - <Record TTL; end of message>
113 private static byte[] createValueFromBytes(ByteBuffer buffer, final int authDataLength) {
115 final int bufferLength = buffer.remaining();
117 final int skip2Length = authDataLength + NUM_OF_BYTES_AUTHENTICATION_DATA_LENGTH;
118 final int totalNewPayloadLength = bufferLength - SKIP1_LEN - skip2Length;
119 final byte[] newPayload = new byte[totalNewPayloadLength];
121 buffer.get(newPayload, 0, PAYLOAD1_LEN);
122 buffer.position(PAYLOAD1_LEN + SKIP1_LEN);
123 buffer.get(newPayload, PAYLOAD1_LEN, PAYLOAD2_LEN);
124 buffer.position(PAYLOAD1_LEN + SKIP1_LEN + PAYLOAD2_LEN + skip2Length);
125 int payload3Len = totalNewPayloadLength - PAYLOAD1_LEN - PAYLOAD2_LEN;
126 buffer.get(newPayload, PAYLOAD1_LEN + PAYLOAD2_LEN, payload3Len);
131 private static MapRegisterCacheKey createKeyFromBytes(final ByteBuffer buffer, int authDataLength) {
133 byte typeAndFlags = buffer.get();
135 boolean xtrSiteIdPresent = ByteUtil.extractBit(typeAndFlags, XTR_SITE_ID);
136 if (!xtrSiteIdPresent) {
139 final MapRegisterCacheKeyBuilder mapRegisterCacheKeyBuilder = new MapRegisterCacheKeyBuilder();
140 final byte[] eidPrefix = extractEidPrefix(buffer, authDataLength);
141 if (eidPrefix == null) {
144 mapRegisterCacheKeyBuilder.setEidPrefix(eidPrefix);
145 if (xtrSiteIdPresent) {
147 final int bufferLength = buffer.remaining();
148 buffer.position(bufferLength - MapRegisterSerializer.Length.XTRID_SIZE - MapRegisterSerializer.Length
151 byte[] xtrId = new byte[MapRegisterSerializer.Length.XTRID_SIZE];
153 mapRegisterCacheKeyBuilder.setXtrId(xtrId);
155 byte[] siteId = new byte[MapRegisterSerializer.Length.SITEID_SIZE];
157 mapRegisterCacheKeyBuilder.setSiteId(siteId);
159 return mapRegisterCacheKeyBuilder.build();
162 private static byte[] extractEidPrefix(final ByteBuffer buffer, int authDataLength) {
163 final int startPositionOfEidPrefixAFI = NUM_OF_BYTES_FROM_START_TO_AUTH_DATA_LENGTH_POS
164 + NUM_OF_BYTES_AUTHENTICATION_DATA_LENGTH + authDataLength
165 + NUM_OF_BYTES_FROM_AUTH_DATA_TO_EID_PREFIX_AFI;
166 buffer.position(startPositionOfEidPrefixAFI);
167 final int eidPrefixAfi = ByteUtil.getUnsignedShort(buffer, startPositionOfEidPrefixAFI);
168 Optional<Integer> eidPrefixLengthOpt = resolveEidPrefixAfi(eidPrefixAfi, buffer);
169 if (eidPrefixLengthOpt.isPresent()) {
170 final byte[] eidPrefix = new byte[eidPrefixLengthOpt.get()];
171 final int startPositionOfEidPrefix = startPositionOfEidPrefixAFI + NUM_OF_BYTES_EID_PREFIX_AFI;
172 buffer.position(startPositionOfEidPrefix);
173 buffer.get(eidPrefix);
179 private static Optional<Integer> resolveEidPrefixAfi(final int eidPrefixAfi, final ByteBuffer buffer) {
180 switch (AddressFamily.forValue(eidPrefixAfi)) {
182 return Optional.of(NUM_OF_BYTES_IPV4);
184 return Optional.of(NUM_OF_BYTES_IPV6);
186 return Optional.of(NUM_OF_BYTES_MAC48);
187 case LispCanonicalAddressFormat:
188 buffer.position(buffer.position() + NUM_OF_BYTES_FROM_EID_PREFIX_AFI_TO_LCAF_LENGTH);
189 final short lengthRawValue = buffer.getShort();
190 final int length = lengthRawValue & 0xFFFF;
192 return Optional.of(NUM_OF_BYTES_FROM_LCAF_RSVD1_TO_LCAF_LENGTH + length);
194 return Optional.empty();