Merge "Add RPC to read per xtrId mappings for an EID."
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / LispMappingService.java
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.implementation;
10
11 import com.google.common.util.concurrent.Futures;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.util.List;
14 import org.apache.commons.lang3.tuple.MutablePair;
15 import org.apache.commons.lang3.tuple.Pair;
16 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
17 import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
18 import org.opendaylight.lispflowmapping.implementation.lisp.MapResolver;
19 import org.opendaylight.lispflowmapping.implementation.lisp.MapServer;
20 import org.opendaylight.lispflowmapping.implementation.util.LispNotificationHelper;
21 import org.opendaylight.lispflowmapping.interfaces.lisp.IFlowMapping;
22 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapNotifyHandler;
23 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapRequestResultHandler;
24 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapResolverAsync;
25 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapServerAsync;
26 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
27 import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
28 import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
29 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
30 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
31 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.AddMapping;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.GotMapNotify;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.GotMapReply;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapNotify;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRegister;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapReply;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRequest;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MappingKeepAlive;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.OdlLispProtoListener;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.RequestMapping;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrReplyMapping;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrRequestMapping;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.metadata.container.MapRegisterCacheMetadata;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.metadata.container.map.register.cache.metadata.EidLispAddress;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapnotifymessage.MapNotifyBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapreplymessage.MapReplyBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequestmessage.MapRequestBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.transport.address.TransportAddress;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.transport.address.TransportAddressBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.OdlLispSbService;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapNotifyInputBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapReplyInputBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapRequestInputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 public class LispMappingService implements IFlowMapping, IMapRequestResultHandler,
63         IMapNotifyHandler, OdlLispProtoListener, AutoCloseable, ClusterSingletonService {
64     public static final String LISPFLOWMAPPING_ENTITY_NAME = "lispflowmapping";
65     public static final ServiceGroupIdentifier SERVICE_GROUP_IDENTIFIER = ServiceGroupIdentifier.create(
66             LISPFLOWMAPPING_ENTITY_NAME);
67
68
69     protected static final Logger LOG = LoggerFactory.getLogger(LispMappingService.class);
70     private final ClusterSingletonServiceProvider clusterSingletonService;
71
72     private volatile boolean smr = ConfigIni.getInstance().smrIsSet();
73     private volatile String elpPolicy = ConfigIni.getInstance().getElpPolicy();
74
75     private ThreadLocal<MapReply> tlsMapReply = new ThreadLocal<MapReply>();
76     private ThreadLocal<Pair<MapNotify, List<TransportAddress>>> tlsMapNotify =
77             new ThreadLocal<Pair<MapNotify, List<TransportAddress>>>();
78     private ThreadLocal<Pair<MapRequest, TransportAddress>> tlsMapRequest =
79             new ThreadLocal<Pair<MapRequest, TransportAddress>>();
80
81     private final OdlLispSbService lispSB;
82     private IMapResolverAsync mapResolver;
83     private IMapServerAsync mapServer;
84
85     private final IMappingService mapService;
86     private final NotificationService notificationService;
87
88     public LispMappingService(final NotificationService notificationService,
89             final IMappingService mappingService,
90             final OdlLispSbService odlLispService, final ClusterSingletonServiceProvider clusterSingletonService) {
91
92         this.notificationService = notificationService;
93         this.mapService = mappingService;
94         this.lispSB = odlLispService;
95         this.clusterSingletonService = clusterSingletonService;
96         LOG.debug("LispMappingService Module constructed!");
97     }
98
99     public boolean shouldUseSmr() {
100         return this.smr;
101     }
102
103     public void setShouldUseSmr(boolean smr) {
104         this.smr = smr;
105         if (mapServer != null) {
106             mapServer.setSubscriptionService(smr);
107         }
108         if (mapResolver != null) {
109             mapResolver.setSubscriptionService(smr);
110         }
111         ConfigIni.getInstance().setSmr(smr);
112     }
113
114     public NotificationService getNotificationService() {
115         return this.notificationService;
116     }
117
118     public void initialize() {
119         mapResolver = new MapResolver(mapService, smr, elpPolicy, this);
120         mapServer = new MapServer(mapService, smr, this, notificationService);
121         this.clusterSingletonService.registerClusterSingletonService(this);
122         LOG.info("LISP (RFC6830) Mapping Service init finished");
123     }
124
125     public void basicInit() {
126         mapResolver = new MapResolver(mapService, smr, elpPolicy, this);
127         mapServer = new MapServer(mapService, smr, this, notificationService);
128     }
129
130     public MapReply handleMapRequest(MapRequest request) {
131         if (LOG.isDebugEnabled()) {
132             LOG.debug("DAO: Retrieving mapping for {}",
133                     LispAddressStringifier.getString(request.getEidItem().get(0).getEid()));
134         }
135
136         tlsMapReply.set(null);
137         tlsMapRequest.set(null);
138         mapResolver.handleMapRequest(request);
139         // After this invocation we assume that the thread local is filled with the reply
140         if (tlsMapRequest.get() != null) {
141             SendMapRequestInputBuilder smrib = new SendMapRequestInputBuilder();
142             smrib.setMapRequest(new MapRequestBuilder(tlsMapRequest.get().getLeft()).build());
143             smrib.setTransportAddress(tlsMapRequest.get().getRight());
144             getLispSB().sendMapRequest(smrib.build());
145             return null;
146         } else {
147             return tlsMapReply.get();
148         }
149     }
150
151     public Pair<MapNotify, List<TransportAddress>> handleMapRegister(MapRegister mapRegister) {
152         if (LOG.isDebugEnabled()) {
153             LOG.debug("DAO: Adding mapping for {}",
154                     LispAddressStringifier.getString(mapRegister.getMappingRecordItem().get(0)
155                             .getMappingRecord().getEid()));
156         }
157
158         tlsMapNotify.set(null);
159         mapServer.handleMapRegister(mapRegister);
160         // After this invocation we assume that the thread local is filled with the reply
161         return tlsMapNotify.get();
162     }
163
164     public void setShouldAuthenticate(boolean shouldAuthenticate) {
165         this.mapResolver.setShouldAuthenticate(shouldAuthenticate);
166     }
167
168     private void sendMapNotify(MapNotify mapNotify, TransportAddress address) {
169         SendMapNotifyInputBuilder smnib = new SendMapNotifyInputBuilder();
170         smnib.setMapNotify(new MapNotifyBuilder(mapNotify).build());
171         smnib.setTransportAddress(address);
172         getLispSB().sendMapNotify(smnib.build());
173     }
174
175     @Override
176     public void onAddMapping(AddMapping mapRegisterNotification) {
177         Pair<MapNotify, List<TransportAddress>> result = handleMapRegister(mapRegisterNotification.getMapRegister());
178         if (result != null && result.getLeft() != null) {
179             MapNotify mapNotify = result.getLeft();
180             List<TransportAddress> rlocs = result.getRight();
181             if (rlocs == null) {
182                 TransportAddressBuilder tab = new TransportAddressBuilder();
183                 tab.setIpAddress(mapRegisterNotification.getTransportAddress().getIpAddress());
184                 tab.setPort(new PortNumber(LispMessage.PORT_NUM));
185                 sendMapNotify(mapNotify, tab.build());
186             } else {
187                 for (TransportAddress ta : rlocs) {
188                     sendMapNotify(mapNotify, ta);
189                 }
190             }
191         } else {
192             LOG.debug("Not sending Map-Notify");
193         }
194     }
195
196     @Override
197     public void onRequestMapping(RequestMapping mapRequestNotification) {
198         MapReply mapReply = handleMapRequest(mapRequestNotification.getMapRequest());
199         if (mapReply != null) {
200             SendMapReplyInputBuilder smrib = new SendMapReplyInputBuilder();
201             smrib.setMapReply((new MapReplyBuilder(mapReply).build()));
202             smrib.setTransportAddress(mapRequestNotification.getTransportAddress());
203             getLispSB().sendMapReply(smrib.build());
204         } else {
205             LOG.debug("handleMapRequest: Got null MapReply");
206         }
207     }
208
209     @Override
210     public void onGotMapReply(GotMapReply notification) {
211         LOG.debug("Received GotMapReply notification, ignoring");
212     }
213
214     @Override
215     public void onGotMapNotify(GotMapNotify notification) {
216         LOG.debug("Received GotMapNotify notification, ignoring");
217     }
218
219     @Override
220     public void onXtrRequestMapping(XtrRequestMapping notification) {
221         LOG.debug("Received XtrRequestMapping notification, ignoring");
222     }
223
224     @Override
225     public void onXtrReplyMapping(XtrReplyMapping notification) {
226         LOG.debug("Received XtrReplyMapping notification, ignoring");
227     }
228
229     @Override
230     public void onMappingKeepAlive(MappingKeepAlive notification) {
231         final MapRegisterCacheMetadata cacheMetadata = notification.getMapRegisterCacheMetadata();
232         for (EidLispAddress eidLispAddress : cacheMetadata.getEidLispAddress()) {
233             final Eid eid = eidLispAddress.getEid();
234             final Long timestamp = cacheMetadata.getTimestamp();
235             LOG.debug("Update map registration for eid {} with timestamp {}", LispAddressStringifier.getString(eid),
236                     timestamp);
237             mapService.updateMappingRegistration(MappingOrigin.Southbound, eid, timestamp);
238         }
239     }
240
241     private OdlLispSbService getLispSB() {
242         return lispSB;
243     }
244
245     @Override
246     public void handleMapReply(MapReply reply) {
247         tlsMapReply.set(reply);
248     }
249
250     @Override
251     public void handleMapNotify(MapNotify notify, List<TransportAddress> rlocs) {
252         tlsMapNotify.set(new MutablePair<MapNotify, List<TransportAddress>>(notify, rlocs));
253     }
254
255     @Override
256     public void handleSMR(MapRequest smr, Rloc subscriber) {
257         if (LOG.isDebugEnabled()) {
258             LOG.debug("Sending SMR to {} with Source-EID {} and EID Record {}",
259                     LispAddressStringifier.getString(subscriber),
260                     LispAddressStringifier.getString(smr.getSourceEid().getEid()),
261                     LispAddressStringifier.getString(smr.getEidItem().get(0).getEid()));
262         }
263         SendMapRequestInputBuilder smrib = new SendMapRequestInputBuilder();
264         smrib.setMapRequest(new MapRequestBuilder(smr).build());
265         smrib.setTransportAddress(LispNotificationHelper.getTransportAddressFromRloc(subscriber));
266         getLispSB().sendMapRequest(smrib.build());
267
268     }
269
270     @Override
271     public void handleNonProxyMapRequest(MapRequest mapRequest, TransportAddress transportAddress) {
272         tlsMapRequest.set(new MutablePair<MapRequest, TransportAddress>(mapRequest, transportAddress));
273     }
274
275     public void destroy() {
276         LOG.info("LISP (RFC6830) Mapping Service is destroyed!");
277         mapResolver = null;
278         mapServer = null;
279     }
280
281     @Override
282     public void close() throws Exception {
283         destroy();
284         clusterSingletonService.close();
285     }
286
287     @Override
288     public void instantiateServiceInstance() {
289         mapService.setIsMaster(true);
290     }
291
292     @Override
293     public ListenableFuture<Void> closeServiceInstance() {
294         if (mapService != null) {
295             mapService.setIsMaster(false);
296         }
297         return Futures.<Void>immediateFuture(null);
298     }
299
300     @Override
301     public ServiceGroupIdentifier getIdentifier() {
302         return SERVICE_GROUP_IDENTIFIER;
303     }
304 }