be6cfe6c91174e46338db07c6440ef1a167566c9
[lispflowmapping.git] / mappingservice / southbound / src / main / java / org / opendaylight / lispflowmapping / southbound / lisp / cache / MapRegisterPartialDeserializer.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.lispflowmapping.southbound.lisp.cache;
9
10 import java.net.InetAddress;
11 import java.nio.ByteBuffer;
12 import java.util.HashMap;
13 import java.util.Map;
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;
20
21 public final class MapRegisterPartialDeserializer {
22
23     /*
24      * Consists of:
25      * - 4bits Type,
26      * - 1bit  P,
27      * - 1bit  Reserved,
28      * - 1bit  I,
29      * - 1bit  R,
30      * - 15bit Reserved,
31      * - 1bit  M,
32      * - 8bits RecordCount
33      */
34     private static final int PAYLOAD1_LEN = 4;
35
36     /*
37      * Consists of:
38      * - 64bits  Nonce
39      */
40     private static final int SKIP1_LEN = 8;
41
42     /*
43      * Consists of:
44      * - 16bits - Key ID
45      */
46     private static final int PAYLOAD2_LEN = 2;
47
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;
50
51     /*
52      * Consists of:
53      * - 32bits  Record TTL
54      * -  8bits  Locator Count
55      * -  8bits  EID mask-len
56      * -  3bits  ACT
57      * -  1bit   A
58      * - 12bits  Reserved
59      * -  4bits  Reserved
60      * - 12bits  Map-Version Number
61      */
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;
71
72
73     private MapRegisterPartialDeserializer() {
74         throw new UnsupportedOperationException("Trying to instantiate util class.");
75     }
76
77     public static Map.Entry<MapRegisterCacheKey, byte[]> deserializePartially(final ByteBuffer buffer,
78                                                                                       final InetAddress sourceRloc) {
79
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);
83         if (isMergeBitSet) {
84             return null;
85         }
86
87         final int authDataLength = ByteUtil.getUnsignedShort(buffer, NUM_OF_BYTES_FROM_START_TO_AUTH_DATA_LENGTH_POS);
88
89         MapRegisterCacheKey mapRegisterCacheKey = createKeyFromBytes(buffer, authDataLength);
90         if (mapRegisterCacheKey == null) {
91             return null;
92         }
93         final byte[] relevantPayloadData = createValueFromBytes(buffer, authDataLength);
94
95         buffer.position(0);
96         return new HashMap.SimpleEntry<>(mapRegisterCacheKey, relevantPayloadData);
97     }
98
99     /*
100      * Extract from buffer the data which doesn't change.
101      *
102      * It means that nonce and authentication items are ommited (skipped).
103      *
104      * payload1 - <Type;RecordCount>
105      * skip1    - Nonce
106      * payload2 - KeyId
107      * skip2    - <Authentication Data Length; Authentication Data>
108      * payload3 - <Record TTL; end of message>
109      *
110      * @param buffer
111      * @return
112      */
113     private static byte[] createValueFromBytes(ByteBuffer buffer, final int authDataLength) {
114         buffer.position(0);
115         final int bufferLength = buffer.remaining();
116
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];
120
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);
127
128         return newPayload;
129     }
130
131     private static MapRegisterCacheKey createKeyFromBytes(final ByteBuffer buffer, int authDataLength) {
132
133         byte typeAndFlags = buffer.get();
134         buffer.position(0);
135         boolean xtrSiteIdPresent = ByteUtil.extractBit(typeAndFlags, XTR_SITE_ID);
136         if (!xtrSiteIdPresent) {
137             return null;
138         }
139         final MapRegisterCacheKeyBuilder mapRegisterCacheKeyBuilder = new MapRegisterCacheKeyBuilder();
140         final byte[] eidPrefix = extractEidPrefix(buffer, authDataLength);
141         if (eidPrefix == null) {
142             return null;
143         }
144         mapRegisterCacheKeyBuilder.setEidPrefix(eidPrefix);
145         if (xtrSiteIdPresent) {
146             buffer.position(0);
147             final int bufferLength = buffer.remaining();
148             buffer.position(bufferLength - MapRegisterSerializer.Length.XTRID_SIZE - MapRegisterSerializer.Length
149                     .SITEID_SIZE);
150
151             byte[] xtrId  = new byte[MapRegisterSerializer.Length.XTRID_SIZE];
152             buffer.get(xtrId);
153             mapRegisterCacheKeyBuilder.setXtrId(xtrId);
154
155             byte[] siteId = new byte[MapRegisterSerializer.Length.SITEID_SIZE];
156             buffer.get(siteId);
157             mapRegisterCacheKeyBuilder.setSiteId(siteId);
158         }
159         return mapRegisterCacheKeyBuilder.build();
160     }
161
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);
174             return eidPrefix;
175         }
176         return null;
177     }
178
179     private static Optional<Integer> resolveEidPrefixAfi(final int eidPrefixAfi, final ByteBuffer buffer) {
180         switch (AddressFamily.forValue(eidPrefixAfi)) {
181             case IpV4:
182                 return Optional.of(NUM_OF_BYTES_IPV4);
183             case IpV6:
184                 return Optional.of(NUM_OF_BYTES_IPV6);
185             case _48BitMac:
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;
191                 buffer.position(0);
192                 return Optional.of(NUM_OF_BYTES_FROM_LCAF_RSVD1_TO_LCAF_LENGTH + length);
193             default:
194                 return Optional.empty();
195         }
196     }
197
198
199 }