support multiple ITR RLOC's TELSDN-188: #close
[lispflowmapping.git] / mappingservice / southbound / src / main / java / org / opendaylight / lispflowmapping / southbound / lisp / LispSouthboundService.java
1 /*
2  * Copyright (c) 2013 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
9 package org.opendaylight.lispflowmapping.southbound.lisp;
10
11 import java.net.DatagramPacket;
12 import java.nio.ByteBuffer;
13
14 import org.opendaylight.lispflowmapping.implementation.serializer.LispMessage;
15 import org.opendaylight.lispflowmapping.implementation.serializer.LispMessageEnum;
16 import org.opendaylight.lispflowmapping.implementation.serializer.MapNotifySerializer;
17 import org.opendaylight.lispflowmapping.implementation.serializer.MapRegisterSerializer;
18 import org.opendaylight.lispflowmapping.implementation.serializer.MapReplySerializer;
19 import org.opendaylight.lispflowmapping.implementation.serializer.MapRequestSerializer;
20 import org.opendaylight.lispflowmapping.implementation.util.ByteUtil;
21 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapResolver;
22 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapServer;
23 import org.opendaylight.lispflowmapping.southbound.lisp.exception.LispMalformedPacketException;
24 import org.opendaylight.lispflowmapping.southbound.lisp.network.PacketHeader;
25 import org.opendaylight.lispflowmapping.type.lisp.MapNotify;
26 import org.opendaylight.lispflowmapping.type.lisp.MapRegister;
27 import org.opendaylight.lispflowmapping.type.lisp.MapReply;
28 import org.opendaylight.lispflowmapping.type.lisp.MapRequest;
29 import org.opendaylight.lispflowmapping.type.lisp.address.LispAddress;
30 import org.opendaylight.lispflowmapping.type.lisp.address.LispIPAddress;
31
32 public class LispSouthboundService implements ILispSouthboundService {
33     private IMapResolver mapResolver;
34     private IMapServer mapServer;
35
36     public LispSouthboundService(IMapResolver mapResolver, IMapServer mapServer) {
37         this.mapResolver = mapResolver;
38         this.mapServer = mapServer;
39     }
40
41     public DatagramPacket handlePacket(DatagramPacket packet) {
42         ByteBuffer inBuffer = ByteBuffer.wrap(packet.getData(), 0, packet.getLength());
43         Object lispType = LispMessageEnum.valueOf((byte) (ByteUtil.getUnsignedByte(inBuffer, LispMessage.Pos.TYPE) >> 4));
44         if (lispType == LispMessageEnum.EncapsulatedControlMessage) {
45             return handleEncapsulatedControlMessage(inBuffer);
46         } else if (lispType == LispMessageEnum.MapRequest) {
47             return handleMapRequest(inBuffer, true);
48         } else if (lispType == LispMessageEnum.MapRegister) {
49             return handleMapRegister(inBuffer);
50         }
51         return null;
52     }
53
54     private DatagramPacket handleEncapsulatedControlMessage(ByteBuffer inBuffer) {
55         try {
56             int encapsulatedSourcePort = extractEncapsulatedSourcePort(inBuffer);
57             DatagramPacket replyPacket = handleMapRequest(inBuffer, false);
58             replyPacket.setPort(encapsulatedSourcePort);
59             return replyPacket;
60         } catch (RuntimeException re) {
61             throw new LispMalformedPacketException("Couldn't deserialize Map-Request (len=" + inBuffer.capacity() + ")", re);
62         }
63     }
64     
65     private DatagramPacket handleMapRequest(ByteBuffer inBuffer, boolean addITRAddress) {
66         try {
67             MapRequest request = MapRequestSerializer.getInstance().deserialize(inBuffer);
68             MapReply mapReply = mapResolver.handleMapRequest(request);
69             ByteBuffer outBuffer = MapReplySerializer.getInstance().serialize(mapReply);
70
71             DatagramPacket replyPacket = new DatagramPacket(outBuffer.array(), outBuffer.capacity());
72             if (!addITRAddress) {
73                 return replyPacket;
74             }
75             replyPacket.setPort(LispMessage.PORT_NUM);
76             for (LispAddress address : request.getItrRlocs()) {
77                 if (address instanceof LispIPAddress) {
78                     replyPacket.setAddress(((LispIPAddress) address).getAddress());
79                     return replyPacket;
80                 }
81             }
82             throw new LispMalformedPacketException("No IP address in the ITR's RLOC's");
83         } catch (RuntimeException re) {
84             throw new LispMalformedPacketException("Couldn't deserialize Map-Request (len=" + inBuffer.capacity() + ")", re);
85         }
86     }
87
88     private int extractEncapsulatedSourcePort(ByteBuffer inBuffer) {
89         try {
90             inBuffer.position(PacketHeader.Length.LISP_ENCAPSULATION);
91             int ipType = (inBuffer.get() >> 4);
92             if (ipType == 4) {
93                 inBuffer.position(inBuffer.position() + PacketHeader.Length.IPV4 - 1);
94             } else {
95                 inBuffer.position(inBuffer.position() + PacketHeader.Length.IPV6_NO_EXT - 1);
96             }
97
98             int encapsulatedSourcePort = inBuffer.getShort() & 0xFFFF;
99             inBuffer.position(inBuffer.position() + PacketHeader.Length.UDP - 2);
100             return encapsulatedSourcePort;
101         } catch (RuntimeException re) {
102             throw new LispMalformedPacketException("Couldn't deserialize Map-Request (len=" + inBuffer.capacity() + ")", re);
103         }
104     }
105
106     private DatagramPacket handleMapRegister(ByteBuffer inBuffer) {
107         try {
108             MapRegister mapRegister = MapRegisterSerializer.getInstance().deserialize(inBuffer);
109             MapNotify mapNotify = mapServer.handleMapRegister(mapRegister);
110
111             if (mapNotify != null) {
112                 ByteBuffer outBuffer = MapNotifySerializer.getInstance().serialize(mapNotify);
113                 DatagramPacket notify = new DatagramPacket(outBuffer.array(), outBuffer.limit());
114                 notify.setPort(LispMessage.PORT_NUM);
115                 return notify;
116             } else {
117                 return null;
118             }
119         } catch (RuntimeException re) {
120             throw new LispMalformedPacketException("Couldn't deserialize Map-Register (len=" + inBuffer.capacity() + ")", re);
121         }
122     }
123 }