View Javadoc

1   /*
2    * Copyright (c) 2014 Contextream, 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.lisp.serializer;
9   
10  import java.nio.ByteBuffer;
11  import java.util.ArrayList;
12  
13  import org.apache.commons.lang3.BooleanUtils;
14  import org.opendaylight.lispflowmapping.lisp.serializer.address.LispAddressSerializer;
15  import org.opendaylight.lispflowmapping.lisp.serializer.address.LispAddressSerializerContext;
16  import org.opendaylight.lispflowmapping.lisp.serializer.exception.LispSerializationException;
17  import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
18  import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
19  import org.opendaylight.lispflowmapping.lisp.util.NumberUtil;
20  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRequest;
21  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MessageType;
22  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItem;
23  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItemBuilder;
24  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRloc;
25  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRlocBuilder;
26  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.SourceEidBuilder;
27  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequestnotification.MapRequestBuilder;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  /**
32   * This class deals with deserializing map request from udp to the java object.
33   */
34  public final class MapRequestSerializer {
35  
36      private static final MapRequestSerializer INSTANCE = new MapRequestSerializer();
37      protected static final Logger LOG = LoggerFactory.getLogger(MapRequestSerializer.class);
38  
39      // Private constructor prevents instantiation from other classes
40      private MapRequestSerializer() {
41      }
42  
43      public static MapRequestSerializer getInstance() {
44          return INSTANCE;
45      }
46  
47      public ByteBuffer serialize(MapRequest mapRequest) {
48          int size = Length.HEADER_SIZE;
49          if (mapRequest.getSourceEid() != null && mapRequest.getSourceEid().getEid() != null) {
50              size += LispAddressSerializer.getInstance().getAddressSize(mapRequest.getSourceEid().getEid());
51          } else {
52              size += 2;
53          }
54          if (mapRequest.getItrRloc() != null) {
55              for (ItrRloc address : mapRequest.getItrRloc()) {
56                  size += LispAddressSerializer.getInstance().getAddressSize(address.getRloc());
57              }
58          }
59          if (mapRequest.getEidItem() != null) {
60              for (EidItem record : mapRequest.getEidItem()) {
61                  size += 2 + LispAddressSerializer.getInstance().getAddressSize(record.getEid());
62              }
63          }
64          ByteBuffer requestBuffer = ByteBuffer.allocate(size);
65          requestBuffer.put((byte) ((byte) (MessageType.MapRequest.getIntValue() << 4)
66                  | ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.isAuthoritative()), Flags.AUTHORITATIVE)
67                  | ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.isMapDataPresent()), Flags.MAP_DATA_PRESENT)
68                  | ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.isProbe()), Flags.PROBE) | ByteUtil.boolToBit(
69                  BooleanUtils.isTrue(mapRequest.isSmr()), Flags.SMR)));
70          requestBuffer.put((byte) (ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.isPitr()), Flags.PITR) | ByteUtil.boolToBit(
71                  BooleanUtils.isTrue(mapRequest.isSmrInvoked()), Flags.SMR_INVOKED)));
72          if (mapRequest.getItrRloc() != null) {
73              int IRC = mapRequest.getItrRloc().size();
74              if (IRC > 0) {
75                  IRC--;
76              }
77              requestBuffer.put((byte) (IRC));
78          } else {
79              requestBuffer.put((byte) 0);
80  
81          }
82          if (mapRequest.getEidItem() != null) {
83              requestBuffer.put((byte) mapRequest.getEidItem().size());
84          } else {
85              requestBuffer.put((byte) 0);
86  
87          }
88          requestBuffer.putLong(NumberUtil.asLong(mapRequest.getNonce()));
89          if (mapRequest.getSourceEid() != null && mapRequest.getSourceEid().getEid() != null) {
90              LispAddressSerializer.getInstance().serialize(requestBuffer, mapRequest.getSourceEid().getEid());
91          } else {
92              requestBuffer.putShort((short) 0);
93          }
94          if (mapRequest.getItrRloc() != null) {
95              for (ItrRloc address : mapRequest.getItrRloc()) {
96                  LispAddressSerializer.getInstance().serialize(requestBuffer, address.getRloc());
97              }
98          }
99          if (mapRequest.getEidItem() != null) {
100             for (EidItem record : mapRequest.getEidItem()) {
101                 requestBuffer.put((byte) 0);
102                 requestBuffer.put((byte) MaskUtil.getMaskForAddress(record.getEid().getAddress()));
103                 LispAddressSerializer.getInstance().serialize(requestBuffer, record.getEid());
104             }
105         }
106         if (mapRequest.getMapReply() != null) {
107             ByteBuffer replyBuffer = ByteBuffer.allocate(MappingRecordSerializer.getInstance()
108                     .getSerializationSize(mapRequest.getMapReply().getMappingRecord()));
109             MappingRecordSerializer.getInstance().serialize(replyBuffer, mapRequest.getMapReply().getMappingRecord());
110             ByteBuffer combinedBuffer = ByteBuffer.allocate(requestBuffer.capacity() + replyBuffer.capacity());
111             combinedBuffer.put(requestBuffer.array());
112             combinedBuffer.put(replyBuffer.array());
113             return combinedBuffer;
114         }
115         return requestBuffer;
116     }
117 
118     public MapRequest deserialize(ByteBuffer requestBuffer) {
119         try {
120             MapRequestBuilder builder = new MapRequestBuilder();
121 
122             byte typeAndFlags = requestBuffer.get();
123             builder.setAuthoritative(ByteUtil.extractBit(typeAndFlags, Flags.AUTHORITATIVE));
124             builder.setMapDataPresent(ByteUtil.extractBit(typeAndFlags, Flags.MAP_DATA_PRESENT));
125             builder.setProbe(ByteUtil.extractBit(typeAndFlags, Flags.PROBE));
126             builder.setSmr(ByteUtil.extractBit(typeAndFlags, Flags.SMR));
127 
128             byte moreFlags = requestBuffer.get();
129             builder.setPitr(ByteUtil.extractBit(moreFlags, Flags.PITR));
130             builder.setSmrInvoked(ByteUtil.extractBit(moreFlags, Flags.SMR_INVOKED));
131 
132             int itrCount = ByteUtil.getUnsignedByte(requestBuffer) + 1;
133             int recordCount = ByteUtil.getUnsignedByte(requestBuffer);
134             builder.setNonce(requestBuffer.getLong());
135             LispAddressSerializerContext ctx = new LispAddressSerializerContext(
136                     LispAddressSerializerContext.MASK_LEN_MISSING);
137             builder.setSourceEid(new SourceEidBuilder().setEid(
138                     LispAddressSerializer.getInstance().deserializeEid(requestBuffer, ctx)).build());
139 
140             if (builder.getItrRloc() == null) {
141                 builder.setItrRloc(new ArrayList<ItrRloc>());
142             }
143             for (int i = 0; i < itrCount; i++) {
144                 builder.getItrRloc().add(new ItrRlocBuilder().setRloc(
145                         LispAddressSerializer.getInstance().deserializeRloc(requestBuffer)).build());
146             }
147 
148             if (builder.getEidItem() == null) {
149                 builder.setEidItem(new ArrayList<EidItem>());
150             }
151             for (int i = 0; i < recordCount; i++) {
152                 builder.getEidItem().add(new EidItemBuilder().setEid(
153                         EidRecordSerializer.getInstance().deserialize(requestBuffer)).build());
154             }
155             if (builder.isMapDataPresent() && requestBuffer.hasRemaining()) {
156                 try {
157                     builder.setMapReply(new org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.MapReplyBuilder().setMappingRecord(
158                             MappingRecordSerializer.getInstance().deserialize(requestBuffer)).build()).build();
159                 } catch (RuntimeException re) {
160                     LOG.warn("Couldn't deserialize Map-Reply encapsulated in Map-Request", re);
161                 }
162             }
163             return builder.build();
164         } catch (RuntimeException re) {
165             throw new LispSerializationException("Couldn't deserialize Map-Request (len=" + requestBuffer.capacity() + ")", re);
166         }
167     }
168 
169     public interface Flags {
170         byte AUTHORITATIVE = 0x08;
171         byte MAP_DATA_PRESENT = 0x04;
172         byte PROBE = 0x02;
173         byte SMR = 0x01;
174 
175         byte PITR = (byte) 0x80;
176         byte SMR_INVOKED = 0x40;
177     }
178 
179     private interface Length {
180         int HEADER_SIZE = 12;
181     }
182 
183 }