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   
9   package org.opendaylight.lispflowmapping.southbound.lisp;
10  
11  import io.netty.buffer.ByteBufUtil;
12  import io.netty.channel.ChannelHandlerContext;
13  import io.netty.channel.SimpleChannelInboundHandler;
14  import io.netty.channel.socket.DatagramPacket;
15  
16  import java.net.InetAddress;
17  import java.nio.ByteBuffer;
18  
19  import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
20  import org.opendaylight.lispflowmapping.southbound.util.LispNotificationHelper;
21  import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
22  import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
23  import org.opendaylight.lispflowmapping.lisp.util.MapRequestUtil;
24  import org.opendaylight.lispflowmapping.lisp.serializer.MapReplySerializer;
25  import org.opendaylight.lispflowmapping.lisp.serializer.MapRequestSerializer;
26  import org.opendaylight.lispflowmapping.southbound.lisp.exception.LispMalformedPacketException;
27  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapReply;
28  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRequest;
29  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MessageType;
30  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrReplyMappingBuilder;
31  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrRequestMappingBuilder;
32  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.transport.address.TransportAddressBuilder;
33  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  public class LispXtrSouthboundHandler extends SimpleChannelInboundHandler<DatagramPacket> implements ILispSouthboundService {
38      private NotificationPublishService notificationPublishService;
39      protected static final Logger LOG = LoggerFactory.getLogger(LispXtrSouthboundHandler.class);
40  
41      public void setNotificationProvider(NotificationPublishService nps) {
42          this.notificationPublishService = nps;
43      }
44  
45      public void handlePacket(DatagramPacket packet) {
46          ByteBuffer inBuffer = packet.content().nioBuffer();
47          Object lispType = MessageType.forValue((int) (ByteUtil.getUnsignedByte(inBuffer, LispMessage.Pos.TYPE) >> 4));
48          if (lispType == MessageType.MapRequest) {
49              LOG.trace("Received packet of type MapRequest for xTR");
50              handleMapRequest(inBuffer);
51          } else if (lispType ==  MessageType.MapReply){
52              LOG.trace("Received packet of type MapReply for xTR");
53              handleMapReply(inBuffer);
54          } else {
55              LOG.warn("Received unknown packet type");
56          }
57      }
58  
59      private void handleMapRequest(ByteBuffer inBuffer) {
60          try {
61              MapRequest request = MapRequestSerializer.getInstance().deserialize(inBuffer);
62              InetAddress finalSourceAddress = MapRequestUtil.selectItrRloc(request);
63              if (finalSourceAddress == null) {
64                  throw new LispMalformedPacketException("Couldn't deserialize Map-Request, no ITR Rloc found!");
65              }
66  
67              XtrRequestMappingBuilder requestMappingBuilder = new XtrRequestMappingBuilder();
68              requestMappingBuilder.setMapRequest(LispNotificationHelper.convertMapRequest(request));
69              TransportAddressBuilder transportAddressBuilder = new TransportAddressBuilder();
70              transportAddressBuilder.setIpAddress(LispNotificationHelper.getIpAddressFromInetAddress(finalSourceAddress));
71              transportAddressBuilder.setPort(new PortNumber(LispMessage.PORT_NUM));
72              requestMappingBuilder.setTransportAddress(transportAddressBuilder.build());
73              if (notificationPublishService != null) {
74                  notificationPublishService.putNotification(requestMappingBuilder.build());
75                  LOG.trace("MapRequest was published!");
76              } else {
77                  LOG.warn("Notification Provider is null!");
78              }
79          } catch (RuntimeException re) {
80              throw new LispMalformedPacketException("Couldn't deserialize Map-Request (len=" + inBuffer.capacity() + ")", re);
81          } catch (InterruptedException e) {
82              LOG.warn("Notification publication interrupted!");
83          }
84      }
85  
86      private void handleMapReply(ByteBuffer buffer) {
87          try {
88              MapReply reply = MapReplySerializer.getInstance().deserialize(buffer);
89  
90              XtrReplyMappingBuilder replyMappingBuilder = new XtrReplyMappingBuilder();
91              replyMappingBuilder.setMapReply(LispNotificationHelper.convertMapReply(reply));
92  
93              if (notificationPublishService != null) {
94                  notificationPublishService.putNotification(replyMappingBuilder.build());
95                  LOG.trace("MapReply was published!");
96              } else {
97                  LOG.warn("Notification Provider is null!");
98              }
99          } catch (RuntimeException re) {
100             throw new LispMalformedPacketException("Couldn't deserialize Map-Reply (len=" + buffer.capacity() + ")", re);
101         } catch (InterruptedException e) {
102             LOG.warn("Notification publication interrupted!");
103         }
104     }
105 
106     @Override
107     protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
108         if (LOG.isTraceEnabled()) {
109             LOG.trace("Received UDP packet from {}:{} with content:\n{}", msg.sender().getHostString(),
110                     msg.sender().getPort(), ByteBufUtil.prettyHexDump(msg.content()));
111         }
112         handlePacket(msg);
113     }
114 
115     @Override
116     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
117         ctx.flush();
118     }
119 
120     @Override
121     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
122         LOG.error("Error on channel: " + cause, cause);
123     }
124 }