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.net.Inet4Address;
11  import java.net.InetAddress;
12  import java.nio.ByteBuffer;
13  import java.util.ArrayList;
14  import java.util.List;
15  
16  import org.apache.commons.lang3.BooleanUtils;
17  import org.opendaylight.lispflowmapping.lisp.serializer.exception.LispSerializationException;
18  import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
19  import org.opendaylight.lispflowmapping.lisp.util.NumberUtil;
20  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
21  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
22  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
23  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRegister;
24  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MessageType;
25  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
26  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItem;
27  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItemBuilder;
28  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapregisternotification.MapRegisterBuilder;
29  
30  /**
31   * This class deals with deserializing map register from udp to the java object.
32   */
33  public final class MapRegisterSerializer {
34  
35      private static final MapRegisterSerializer INSTANCE = new MapRegisterSerializer();
36  
37      // Private constructor prevents instantiation from other classes
38      private MapRegisterSerializer() {
39      }
40  
41      public static MapRegisterSerializer getInstance() {
42          return INSTANCE;
43      }
44  
45      public ByteBuffer serialize(MapRegister mapRegister) {
46          int size = Length.HEADER_SIZE;
47          if (mapRegister.getAuthenticationData() != null) {
48              size += mapRegister.getAuthenticationData().length;
49          }
50          if (mapRegister.isXtrSiteIdPresent() != null && mapRegister.isXtrSiteIdPresent()) {
51              size += Length.XTRID_SIZE + Length.SITEID_SIZE;
52          }
53          for (MappingRecordItem eidToLocatorRecord : mapRegister.getMappingRecordItem()) {
54              size += MappingRecordSerializer.getInstance().getSerializationSize(eidToLocatorRecord.getMappingRecord());
55          }
56  
57          ByteBuffer registerBuffer = ByteBuffer.allocate(size);
58          registerBuffer.put((byte) ((byte) (MessageType.MapRegister.getIntValue() << 4) |
59                  ByteUtil.boolToBit(BooleanUtils.isTrue(mapRegister.isProxyMapReply()), Flags.PROXY) |
60                  ByteUtil.boolToBit(BooleanUtils.isTrue(mapRegister.isXtrSiteIdPresent()), Flags.XTRSITEID)));
61          registerBuffer.position(registerBuffer.position() + Length.RES);
62          registerBuffer.put((byte)
63                  (ByteUtil.boolToBit(BooleanUtils.isTrue(mapRegister.isMergeEnabled()), Flags.MERGE_ENABLED) |
64                  ByteUtil.boolToBit(BooleanUtils.isTrue(mapRegister.isWantMapNotify()), Flags.WANT_MAP_NOTIFY)));
65          registerBuffer.put((byte) mapRegister.getMappingRecordItem().size());
66          registerBuffer.putLong(NumberUtil.asLong(mapRegister.getNonce()));
67          registerBuffer.putShort(NumberUtil.asShort(mapRegister.getKeyId()));
68  
69          if (mapRegister.getAuthenticationData() != null) {
70              registerBuffer.putShort((short) mapRegister.getAuthenticationData().length);
71              registerBuffer.put(mapRegister.getAuthenticationData());
72          } else {
73              registerBuffer.putShort((short) 0);
74          }
75          for (MappingRecordItem eidToLocatorRecord : mapRegister.getMappingRecordItem()) {
76              MappingRecordSerializer.getInstance().serialize(registerBuffer, eidToLocatorRecord.getMappingRecord());
77          }
78  
79          if (mapRegister.isXtrSiteIdPresent() != null && mapRegister.isXtrSiteIdPresent()) {
80              registerBuffer.put(mapRegister.getXtrId());
81              registerBuffer.put(mapRegister.getSiteId());
82          }
83          registerBuffer.clear();
84          return registerBuffer;
85      }
86  
87      public MapRegister deserialize(ByteBuffer registerBuffer, InetAddress sourceRloc) {
88          try {
89              MapRegisterBuilder builder = new MapRegisterBuilder();
90              builder.setMappingRecordItem(new ArrayList<MappingRecordItem>());
91  
92              byte typeAndFlags = registerBuffer.get();
93              boolean xtrSiteIdPresent = ByteUtil.extractBit(typeAndFlags, Flags.XTRSITEID);
94              builder.setProxyMapReply(ByteUtil.extractBit(typeAndFlags, Flags.PROXY));
95              builder.setXtrSiteIdPresent(xtrSiteIdPresent);
96  
97              registerBuffer.position(registerBuffer.position() + Length.RES);
98              byte mergeAndMapReply = registerBuffer.get();
99              builder.setWantMapNotify(ByteUtil.extractBit(mergeAndMapReply, Flags.WANT_MAP_NOTIFY));
100             builder.setMergeEnabled(ByteUtil.extractBit(mergeAndMapReply, Flags.MERGE_ENABLED));
101             byte recordCount = (byte) ByteUtil.getUnsignedByte(registerBuffer);
102             builder.setNonce(registerBuffer.getLong());
103             builder.setKeyId(registerBuffer.getShort());
104             short authenticationLength = registerBuffer.getShort();
105             byte[] authenticationData = new byte[authenticationLength];
106             registerBuffer.get(authenticationData);
107             builder.setAuthenticationData(authenticationData);
108 
109             if (xtrSiteIdPresent) {
110                 List<MappingRecordBuilder> mrbs = new ArrayList<MappingRecordBuilder>();
111                 for (int i = 0; i < recordCount; i++) {
112                     mrbs.add(MappingRecordSerializer.getInstance().deserializeToBuilder(registerBuffer));
113                 }
114                 byte[] xtrId  = new byte[Length.XTRID_SIZE];
115                 registerBuffer.get(xtrId);
116                 byte[] siteId = new byte[Length.SITEID_SIZE];
117                 registerBuffer.get(siteId);
118                 builder.setXtrId(xtrId);
119                 builder.setSiteId(siteId);
120                 for (MappingRecordBuilder mrb : mrbs) {
121                     mrb.setXtrId(xtrId);
122                     mrb.setSiteId(siteId);
123                     mrb.setSourceRloc(getSourceRloc(sourceRloc));
124                     builder.getMappingRecordItem().add(new MappingRecordItemBuilder().setMappingRecord(
125                             mrb.build()).build());
126                 }
127             } else {
128                 for (int i = 0; i < recordCount; i++) {
129                     builder.getMappingRecordItem().add(new MappingRecordItemBuilder().setMappingRecord(
130                             MappingRecordSerializer.getInstance().deserialize(registerBuffer)).build());
131                 }
132             }
133 
134             registerBuffer.limit(registerBuffer.position());
135             byte[] mapRegisterBytes = new byte[registerBuffer.position()];
136             registerBuffer.position(0);
137             registerBuffer.get(mapRegisterBytes);
138             return builder.build();
139         } catch (RuntimeException re) {
140             throw new LispSerializationException("Couldn't deserialize Map-Register (len=" + registerBuffer.capacity() + ")", re);
141         }
142 
143     }
144 
145     private static IpAddress getSourceRloc(InetAddress sourceRloc) {
146         if (sourceRloc == null) {
147             sourceRloc = InetAddress.getLoopbackAddress();
148         }
149 
150         if (sourceRloc instanceof Inet4Address) {
151             return new IpAddress(new Ipv4Address(sourceRloc.getHostAddress()));
152         } else {
153             return new IpAddress(new Ipv6Address(sourceRloc.getHostAddress()));
154         }
155     }
156 
157     private interface Flags {
158         byte PROXY = 0x08;
159         byte XTRSITEID = 0x02;
160         byte MERGE_ENABLED = 0x04;
161         byte WANT_MAP_NOTIFY = 0x01;
162     }
163 
164     public interface Length {
165         int HEADER_SIZE = 16;
166         int XTRID_SIZE = 16;
167         int SITEID_SIZE = 8;
168         int RES = 1;
169     }
170 }