2 * Copyright (c) 2015 Cisco Systems, Inc. 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.implementation;
10 import java.util.ArrayList;
11 import java.util.List;
12 import java.util.concurrent.Future;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
16 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
17 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
18 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
19 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
20 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
21 import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
22 import org.opendaylight.lispflowmapping.implementation.mdsal.AuthenticationKeyDataListener;
23 import org.opendaylight.lispflowmapping.dsbackend.DataStoreBackEnd;
24 import org.opendaylight.lispflowmapping.implementation.mdsal.MappingDataListener;
25 import org.opendaylight.lispflowmapping.implementation.util.DSBEInputUtil;
26 import org.opendaylight.lispflowmapping.implementation.util.RPCInputConvertorUtil;
27 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
28 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
29 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.SiteId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeyInput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeysInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingsInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllKeysOutput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllMappingsOutput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyInput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutputBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeysInput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeysOutput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingInput;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutputBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingsInput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingsOutput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.OdlMappingserviceService;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeyInput;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeysInput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingsInput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeyInput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeysInput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingsInput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.authkey.container.MappingAuthkey;
63 import org.opendaylight.yangtools.yang.common.RpcError;
64 import org.opendaylight.yangtools.yang.common.RpcResult;
65 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
69 import com.google.common.base.Preconditions;
70 import com.google.common.util.concurrent.Futures;
73 * Dispatcher of API calls that implements the RPC and Java APIs in mappingservice.yang and IMappingService
74 * respectively. It also coordinates and acts as container for all objects in charge of
75 * - saving and updating md-sal datastore stored mappings
76 * - monitoring md-sal datastore mapping updates and pushing them to the in memory mapping-system
77 * - in memory mapping-system
79 * @author Lorand Jakab
80 * @author Florin Coras
83 public class MappingService implements OdlMappingserviceService, IMappingService, BindingAwareProvider, AutoCloseable {
84 protected static final Logger LOG = LoggerFactory.getLogger(MappingService.class);
85 private static final String NOT_FOUND_TAG = "data-missing";
86 private static final String DATA_EXISTS_TAG = "data-exists";
88 private MappingSystem mappingSystem;
89 private DataStoreBackEnd dsbe;
90 private RpcRegistration<OdlMappingserviceService> mappingServiceRpc;
91 private AuthenticationKeyDataListener keyListener;
92 private MappingDataListener mappingListener;
95 private DataBroker dataBroker;
96 private RpcProviderRegistry rpcRegistry;
97 private BindingAwareBroker bindingAwareBroker;
98 private NotificationPublishService notificationPublishService;
100 private boolean overwritePolicy = ConfigIni.getInstance().mappingOverwriteIsSet();
101 private boolean notificationPolicy = ConfigIni.getInstance().smrIsSet();
102 private boolean iterateMask = true;
104 public MappingService() {
105 LOG.debug("MappingService created!");
108 public void setDataBroker(DataBroker dataBroker) {
109 this.dataBroker = dataBroker;
112 public void setRpcProviderRegistry(RpcProviderRegistry rpc) {
113 this.rpcRegistry = rpc;
116 public void setBindingAwareBroker(BindingAwareBroker broker) {
117 this.bindingAwareBroker = broker;
120 public void setNotificationPublishService(NotificationPublishService nps) {
121 this.notificationPublishService = nps;
124 public void setDaoService(ILispDAO dao) {
129 public void setMappingOverwrite(boolean overwrite) {
130 this.overwritePolicy = overwrite;
131 if (mappingSystem != null) {
132 mappingSystem.setOverwritePolicy(overwrite);
133 ConfigIni.getInstance().setMappingOverwrite(overwrite);
138 public void setLookupPolicy(IMappingService.LookupPolicy policy) {
139 ConfigIni.getInstance().setLookupPolicy(policy);
142 public void initialize() {
143 bindingAwareBroker.registerProvider(this);
145 mappingServiceRpc = rpcRegistry.addRpcImplementation(OdlMappingserviceService.class, this);
146 dsbe = new DataStoreBackEnd(dataBroker);
148 mappingSystem = new MappingSystem(dao, iterateMask, notificationPolicy, overwritePolicy);
149 mappingSystem.setDataStoreBackEnd(dsbe);
150 mappingSystem.initialize();
152 keyListener = new AuthenticationKeyDataListener(dataBroker, mappingSystem);
153 mappingListener = new MappingDataListener(dataBroker, mappingSystem, notificationPublishService);
157 public Future<RpcResult<Void>> addKey(AddKeyInput input) {
158 Preconditions.checkNotNull(input, "add-key RPC input must be not null!");
159 LOG.trace("RPC received to add the following key: " + input.toString());
161 RpcResultBuilder<Void> rpcResultBuilder;
163 MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
166 String message = "Key already exists! Please use update-key if you want to change it.";
167 rpcResultBuilder = RpcResultBuilder.<Void>failed()
168 .withError(RpcError.ErrorType.PROTOCOL, DATA_EXISTS_TAG, message);
169 return Futures.immediateFuture(rpcResultBuilder.build());
172 dsbe.addAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
173 rpcResultBuilder = RpcResultBuilder.success();
175 return Futures.immediateFuture(rpcResultBuilder.build());
179 public Future<RpcResult<Void>> addMapping(AddMappingInput input) {
180 Preconditions.checkNotNull(input, "add-mapping RPC input must be not null!");
181 LOG.trace("RPC received to add the following mapping: " + input.toString());
183 dsbe.addMapping(RPCInputConvertorUtil.toMapping(input));
185 RpcResultBuilder<Void> rpcResultBuilder;
187 rpcResultBuilder = RpcResultBuilder.success();
189 return Futures.immediateFuture(rpcResultBuilder.build());
193 public Future<RpcResult<GetKeyOutput>> getKey(GetKeyInput input) {
194 Preconditions.checkNotNull(input, "get-key RPC input must be not null!");
195 LOG.trace("RPC received to get the following key: " + input.toString());
197 RpcResultBuilder<GetKeyOutput> rpcResultBuilder;
199 MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
202 String message = "Key was not found in the mapping database";
203 rpcResultBuilder = RpcResultBuilder.<GetKeyOutput>failed()
204 .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
206 rpcResultBuilder = RpcResultBuilder.success(new GetKeyOutputBuilder().setMappingAuthkey(key));
209 return Futures.immediateFuture(rpcResultBuilder.build());
213 public Future<RpcResult<GetMappingOutput>> getMapping(GetMappingInput input) {
214 Preconditions.checkNotNull(input, "get-mapping RPC input must be not null!");
215 LOG.trace("RPC received to get the following mapping: " + input.toString());
217 RpcResultBuilder<GetMappingOutput> rpcResultBuilder;
219 MappingRecord reply = (MappingRecord) mappingSystem.getMapping(convertToBinaryIfNecessary(input.getEid()));
222 String message = "No mapping was found in the mapping database";
223 rpcResultBuilder = RpcResultBuilder.<GetMappingOutput>failed()
224 .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
226 final MappingRecord convertedReply = convertFromBinaryIfNecessary(reply);
227 rpcResultBuilder = RpcResultBuilder.success(new GetMappingOutputBuilder().setMappingRecord(convertedReply));
230 return Futures.immediateFuture(rpcResultBuilder.build());
234 public Future<RpcResult<Void>> removeKey(RemoveKeyInput input) {
235 Preconditions.checkNotNull(input, "remove-key RPC input must be not null!");
236 LOG.trace("RPC received to remove the following key: " + input.toString());
238 RpcResultBuilder<Void> rpcResultBuilder;
240 dsbe.removeAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
242 rpcResultBuilder = RpcResultBuilder.success();
244 return Futures.immediateFuture(rpcResultBuilder.build());
248 public Future<RpcResult<Void>> removeMapping(RemoveMappingInput input) {
249 Preconditions.checkNotNull(input, "remove-mapping RPC input must be not null!");
250 LOG.trace("RPC received to remove the following mapping: " + input.toString());
252 RpcResultBuilder<Void> rpcResultBuilder;
254 dsbe.removeMapping(RPCInputConvertorUtil.toMapping(input));
256 rpcResultBuilder = RpcResultBuilder.success();
258 return Futures.immediateFuture(rpcResultBuilder.build());
262 public Future<RpcResult<Void>> updateKey(UpdateKeyInput input) {
263 Preconditions.checkNotNull(input, "update-key RPC input must be not null!");
264 LOG.trace("RPC received to update the following key: " + input.toString());
266 RpcResultBuilder<Void> rpcResultBuilder;
268 MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
271 String message = "Key doesn't exist! Please use add-key if you want to create a new authentication key.";
272 rpcResultBuilder = RpcResultBuilder.<Void>failed()
273 .withError(RpcError.ErrorType.PROTOCOL, NOT_FOUND_TAG, message);
274 return Futures.immediateFuture(rpcResultBuilder.build());
277 dsbe.updateAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
278 rpcResultBuilder = RpcResultBuilder.success();
280 return Futures.immediateFuture(rpcResultBuilder.build());
284 public Future<RpcResult<Void>> updateMapping(UpdateMappingInput input) {
285 LOG.trace("RPC received to update the following mapping: " + input.toString());
286 Preconditions.checkNotNull(input, "update-mapping RPC input must be not null!");
288 RpcResultBuilder<Void> rpcResultBuilder;
290 dsbe.updateMapping(RPCInputConvertorUtil.toMapping(input));
292 rpcResultBuilder = RpcResultBuilder.success();
294 return Futures.immediateFuture(rpcResultBuilder.build());
298 public Future<RpcResult<Void>> removeKeys(RemoveKeysInput input) {
299 // TODO Auto-generated method stub
304 public Future<RpcResult<Void>> removeMappings(RemoveMappingsInput input) {
305 // TODO Auto-generated method stub
310 public Future<RpcResult<GetKeysOutput>> getKeys(GetKeysInput input) {
311 // TODO Auto-generated method stub
316 public Future<RpcResult<Void>> addMappings(AddMappingsInput input) {
317 // TODO Auto-generated method stub
322 public Future<RpcResult<Void>> updateKeys(UpdateKeysInput input) {
323 // TODO Auto-generated method stub
328 public Future<RpcResult<Void>> removeAllMappings() {
329 // TODO Auto-generated method stub
334 public Future<RpcResult<Void>> removeAllKeys() {
335 // TODO Auto-generated method stub
340 public Future<RpcResult<GetAllKeysOutput>> getAllKeys() {
341 // TODO Auto-generated method stub
346 public Future<RpcResult<Void>> updateMappings(UpdateMappingsInput input) {
347 // TODO Auto-generated method stub
352 public Future<RpcResult<Void>> addKeys(AddKeysInput input) {
353 // TODO Auto-generated method stub
358 public Future<RpcResult<GetAllMappingsOutput>> getAllMappings() {
359 // TODO Auto-generated method stub
364 public Future<RpcResult<GetMappingsOutput>> getMappings(
365 GetMappingsInput input) {
366 // TODO Auto-generated method stub
371 public void addMapping(MappingOrigin origin, Eid key, SiteId siteId, Object data, boolean merge) {
372 // SB registrations are first written to the MappingSystem and only afterwards are persisted to the datastore
373 if (origin.equals(MappingOrigin.Southbound)) {
374 // Store data first in MapCache and only afterwards persist to datastore. This should be used only for SB
376 mappingSystem.addMapping(origin, key, data, merge);
377 dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, (MappingRecord) data));
378 if (((MappingRecord) data).getXtrId() != null) {
379 dsbe.addXtrIdMapping(DSBEInputUtil.toXtrIdMapping((MappingRecord) data));
382 dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, (MappingRecord) data));
387 public void updateMappingRegistration(MappingOrigin origin, Eid key, Long timestamp) {
388 mappingSystem.updateMappingRegistration(origin, key, timestamp);
392 public Object getMapping(MappingOrigin origin, Eid key) {
393 return mappingSystem.getMapping(origin, key);
397 public Object getMapping(Eid key) {
398 return mappingSystem.getMapping(key);
402 public Object getMapping(Eid srcKey, Eid dstKey) {
403 return mappingSystem.getMapping(srcKey, dstKey);
407 public Eid getWidestNegativePrefix(Eid key) {
408 return mappingSystem.getWidestNegativePrefix(key);
412 public void removeMapping(MappingOrigin origin, Eid key) {
413 dsbe.removeMapping(DSBEInputUtil.toMapping(origin, key));
417 public void addAuthenticationKey(Eid key, MappingAuthkey authKey) {
418 dsbe.addAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, authKey));
422 public MappingAuthkey getAuthenticationKey(Eid key) {
423 return mappingSystem.getAuthenticationKey(key);
427 public void removeAuthenticationKey(Eid key) {
428 dsbe.removeAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, null));
432 public void addData(MappingOrigin origin, Eid key, String subKey, Object data) {
433 mappingSystem.addData(origin, key, subKey, data);
437 public Object getData(MappingOrigin origin, Eid key, String subKey) {
438 return mappingSystem.getData(origin, key, subKey);
442 public void removeData(MappingOrigin origin, Eid key, String subKey) {
443 mappingSystem.removeData(origin, key, subKey);
447 public String printMappings() {
448 return mappingSystem.printMappings();
452 public void onSessionInitiated(ProviderContext session) {
453 LOG.info("Mapping Service provider session initializing!");
457 public void close() throws Exception {
458 LOG.info("Mapping Service is being destroyed!");
459 mappingServiceRpc.close();
460 keyListener.closeDataChangeListener();
461 mappingListener.closeDataChangeListener();
465 public void cleanCachedMappings() {
466 mappingSystem.cleanCaches();
467 dsbe.removeAllDatastoreContent();
470 private static Eid convertToBinaryIfNecessary(Eid eid) {
471 if (LispAddressUtil.addressNeedsConversionToBinary(eid.getAddress())) {
472 return LispAddressUtil.convertToBinary(eid);
477 private static MappingRecord convertFromBinaryIfNecessary(MappingRecord originalRecord) {
478 List<LocatorRecord> originalLocators = originalRecord.getLocatorRecord();
480 List<LocatorRecord> convertedLocators = null;
481 if (originalLocators != null) {
482 // If convertedLocators is non-null, while originalLocators is also non-null, conversion has been made
483 convertedLocators = convertFromBinaryIfNecessary(originalLocators);
486 if (LispAddressUtil.addressNeedsConversionFromBinary(originalRecord.getEid().getAddress()) ||
487 (originalLocators != null && convertedLocators != null)) {
488 MappingRecordBuilder mrb = new MappingRecordBuilder(originalRecord);
489 mrb.setEid(LispAddressUtil.convertFromBinary(originalRecord.getEid()));
490 if (convertedLocators != null) {
491 mrb.setLocatorRecord(convertedLocators);
495 return originalRecord;
498 private static List<LocatorRecord> convertFromBinaryIfNecessary(List<LocatorRecord> originalLocators) {
499 List<LocatorRecord> convertedLocators = null;
500 for (LocatorRecord record : originalLocators) {
501 if (LispAddressUtil.addressNeedsConversionFromBinary(record.getRloc().getAddress())) {
502 LocatorRecordBuilder lrb = new LocatorRecordBuilder(record);
503 lrb.setRloc(LispAddressUtil.convertFromBinary(record.getRloc()));
504 if (convertedLocators == null) {
505 convertedLocators = new ArrayList<LocatorRecord>();
507 convertedLocators.add(lrb.build());
510 if (convertedLocators != null) {
511 return convertedLocators;
513 return originalLocators;