2 * Copyright (c) 2014 Contextream, 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.lisp.serializer;
10 import java.net.InetAddress;
11 import java.nio.ByteBuffer;
12 import java.util.ArrayList;
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.LispAddressStringifier;
19 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
20 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
21 import org.opendaylight.lispflowmapping.lisp.util.NumberUtil;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRequest;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MessageType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItem;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItemBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItemKey;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRloc;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRlocBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRlocKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.SourceEidBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequestnotification.MapRequestBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * This class deals with deserializing map request from udp to the java object.
40 public final class MapRequestSerializer {
42 private static final MapRequestSerializer INSTANCE = new MapRequestSerializer();
43 protected static final Logger LOG = LoggerFactory.getLogger(MapRequestSerializer.class);
45 // Private constructor prevents instantiation from other classes
46 private MapRequestSerializer() {
49 public static MapRequestSerializer getInstance() {
53 public ByteBuffer serialize(MapRequest mapRequest) {
54 int size = Length.HEADER_SIZE;
55 if (mapRequest.getSourceEid() != null && mapRequest.getSourceEid().getEid() != null) {
56 size += LispAddressSerializer.getInstance().getAddressSize(mapRequest.getSourceEid().getEid());
60 if (mapRequest.getItrRloc() != null) {
61 for (ItrRloc address : mapRequest.getItrRloc()) {
62 size += LispAddressSerializer.getInstance().getAddressSize(address.getRloc());
65 if (mapRequest.getEidItem() != null) {
66 for (EidItem record : mapRequest.getEidItem()) {
67 size += 2 + LispAddressSerializer.getInstance().getAddressSize(record.getEid());
70 ByteBuffer requestBuffer = ByteBuffer.allocate(size);
71 requestBuffer.put((byte) ((byte) (MessageType.MapRequest.getIntValue() << 4)
72 | ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.isAuthoritative()), Flags.AUTHORITATIVE)
73 | ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.isMapDataPresent()), Flags.MAP_DATA_PRESENT)
74 | ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.isProbe()), Flags.PROBE) | ByteUtil.boolToBit(
75 BooleanUtils.isTrue(mapRequest.isSmr()), Flags.SMR)));
76 requestBuffer.put((byte) (ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.isPitr()), Flags.PITR)
77 | ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.isSmrInvoked()), Flags.SMR_INVOKED)));
78 if (mapRequest.getItrRloc() != null) {
79 int irc = mapRequest.getItrRloc().size();
83 requestBuffer.put((byte) (irc));
85 requestBuffer.put((byte) 0);
88 if (mapRequest.getEidItem() != null) {
89 requestBuffer.put((byte) mapRequest.getEidItem().size());
91 requestBuffer.put((byte) 0);
94 requestBuffer.putLong(NumberUtil.asLong(mapRequest.getNonce()));
95 if (mapRequest.getSourceEid() != null && mapRequest.getSourceEid().getEid() != null) {
96 LispAddressSerializer.getInstance().serialize(requestBuffer, mapRequest.getSourceEid().getEid());
98 requestBuffer.putShort((short) 0);
100 if (mapRequest.getItrRloc() != null) {
101 for (ItrRloc address : mapRequest.getItrRloc()) {
102 LispAddressSerializer.getInstance().serialize(requestBuffer, address.getRloc());
105 if (mapRequest.getEidItem() != null) {
106 for (EidItem record : mapRequest.getEidItem()) {
107 requestBuffer.put((byte) 0);
108 requestBuffer.put((byte) MaskUtil.getMaskForAddress(record.getEid().getAddress()));
109 LispAddressSerializer.getInstance().serialize(requestBuffer, record.getEid());
112 if (mapRequest.getMapReply() != null) {
113 ByteBuffer replyBuffer = ByteBuffer.allocate(MappingRecordSerializer.getInstance()
114 .getSerializationSize(mapRequest.getMapReply().getMappingRecord()));
115 MappingRecordSerializer.getInstance().serialize(replyBuffer, mapRequest.getMapReply().getMappingRecord());
116 ByteBuffer combinedBuffer = ByteBuffer.allocate(requestBuffer.capacity() + replyBuffer.capacity());
117 combinedBuffer.put(requestBuffer.array());
118 combinedBuffer.put(replyBuffer.array());
119 return combinedBuffer;
121 return requestBuffer;
124 @SuppressWarnings("checkstyle:IllegalCatch")
125 public MapRequest deserialize(ByteBuffer requestBuffer, InetAddress sourceRloc) {
127 final byte typeAndFlags = requestBuffer.get();
128 final int type = typeAndFlags >> 4;
129 if (MessageType.forValue(type) != MessageType.MapRequest) {
130 throw new LispSerializationException("Expected Map-Request packet (type 1), but was type " + type);
133 MapRequestBuilder builder = new MapRequestBuilder();
134 builder.setAuthoritative(ByteUtil.extractBit(typeAndFlags, Flags.AUTHORITATIVE));
135 builder.setMapDataPresent(ByteUtil.extractBit(typeAndFlags, Flags.MAP_DATA_PRESENT));
136 builder.setProbe(ByteUtil.extractBit(typeAndFlags, Flags.PROBE));
137 builder.setSmr(ByteUtil.extractBit(typeAndFlags, Flags.SMR));
139 final byte moreFlags = requestBuffer.get();
140 builder.setPitr(ByteUtil.extractBit(moreFlags, Flags.PITR));
141 builder.setSmrInvoked(ByteUtil.extractBit(moreFlags, Flags.SMR_INVOKED));
143 final int itrCount = ByteUtil.getUnsignedByte(requestBuffer) + 1;
144 final int recordCount = ByteUtil.getUnsignedByte(requestBuffer);
145 builder.setNonce(requestBuffer.getLong());
146 LispAddressSerializerContext ctx = new LispAddressSerializerContext(
147 LispAddressSerializerContext.MASK_LEN_MISSING);
148 builder.setSourceEid(new SourceEidBuilder().setEid(
149 LispAddressSerializer.getInstance().deserializeEid(requestBuffer, ctx)).build());
151 if (builder.getItrRloc() == null) {
152 builder.setItrRloc(new ArrayList<ItrRloc>());
154 for (int i = 0; i < itrCount; i++) {
155 Rloc rloc = LispAddressSerializer.getInstance().deserializeRloc(requestBuffer);
156 builder.getItrRloc().add(new ItrRlocBuilder()
157 .withKey(new ItrRlocKey(LispAddressStringifier.getString(rloc)))
158 .setRloc(rloc).build());
161 if (builder.getEidItem() == null) {
162 builder.setEidItem(new ArrayList<EidItem>());
164 for (int i = 0; i < recordCount; i++) {
165 Eid eid = EidRecordSerializer.getInstance().deserialize(requestBuffer);
166 builder.getEidItem().add(new EidItemBuilder()
167 .withKey(new EidItemKey(LispAddressStringifier.getString(eid)))
168 .setEid(eid).build());
170 if (builder.isMapDataPresent() && requestBuffer.hasRemaining()) {
172 builder.setMapReply(new org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105
173 .maprequest.MapReplyBuilder().setMappingRecord(
174 MappingRecordSerializer.getInstance().deserialize(requestBuffer)).build()).build();
175 } catch (RuntimeException re) {
176 LOG.warn("Couldn't deserialize Map-Reply encapsulated in Map-Request", re);
179 builder.setSourceRloc(LispAddressUtil.addressBinaryFromInet(sourceRloc));
180 return builder.build();
181 } catch (RuntimeException re) {
182 throw new LispSerializationException("Couldn't deserialize Map-Request (len="
183 + requestBuffer.capacity() + ")", re);
187 public interface Flags {
188 byte AUTHORITATIVE = 0x08;
189 byte MAP_DATA_PRESENT = 0x04;
193 byte PITR = (byte) 0x80;
194 byte SMR_INVOKED = 0x40;
197 private interface Length {
198 int HEADER_SIZE = 12;