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 com.google.common.base.Preconditions;
11 import com.google.common.util.concurrent.Futures;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.concurrent.Future;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
17 import org.opendaylight.lispflowmapping.config.ConfigIni;
18 import org.opendaylight.lispflowmapping.dsbackend.DataStoreBackEnd;
19 import org.opendaylight.lispflowmapping.implementation.mdsal.AuthenticationKeyDataListener;
20 import org.opendaylight.lispflowmapping.implementation.mdsal.MappingDataListener;
21 import org.opendaylight.lispflowmapping.implementation.util.DSBEInputUtil;
22 import org.opendaylight.lispflowmapping.implementation.util.RPCInputConvertorUtil;
23 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
24 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
25 import org.opendaylight.lispflowmapping.lisp.type.MappingData;
26 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.SiteId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.authkey.container.MappingAuthkey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeyInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeysInput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingsInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllKeysOutput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllMappingsOutput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutputBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeysInput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeysOutput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingInput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutput;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutputBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingWithXtrIdInput;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingWithXtrIdOutput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingWithXtrIdOutputBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingsInput;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingsOutput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.OdlMappingserviceService;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeyInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeysInput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingInput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingsInput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeyInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeysInput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingsInput;
64 import org.opendaylight.yangtools.yang.common.RpcError;
65 import org.opendaylight.yangtools.yang.common.RpcResult;
66 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
71 * Dispatcher of API calls that implements the RPC and Java APIs in mappingservice.yang and IMappingService
72 * respectively. It also coordinates and acts as container for all objects in charge of
73 * - saving and updating md-sal datastore stored mappings
74 * - monitoring md-sal datastore mapping updates and pushing them to the in memory mapping-system
75 * - in memory mapping-system
77 * @author Lorand Jakab
78 * @author Florin Coras
81 public class MappingService implements OdlMappingserviceService, IMappingService, AutoCloseable {
82 protected static final Logger LOG = LoggerFactory.getLogger(MappingService.class);
83 private static final String NOT_FOUND_TAG = "data-missing";
84 private static final String DATA_EXISTS_TAG = "data-exists";
86 private MappingSystem mappingSystem;
87 private DataStoreBackEnd dsbe;
88 private AuthenticationKeyDataListener keyListener;
89 private MappingDataListener mappingListener;
90 private final ILispDAO dao;
92 private final DataBroker dataBroker;
93 private final NotificationPublishService notificationPublishService;
95 private boolean mappingMergePolicy = ConfigIni.getInstance().mappingMergeIsSet();
96 private boolean notificationPolicy = ConfigIni.getInstance().smrIsSet();
97 private boolean iterateMask = true;
98 private boolean isMaster = false;
100 public MappingService(final DataBroker broker,
101 final NotificationPublishService notificationPublishService,
102 final ILispDAO lispDAO) {
103 this.dataBroker = broker;
104 this.notificationPublishService = notificationPublishService;
107 LOG.debug("MappingService created!");
112 public void setMappingMerge(boolean mergeMapping) {
113 this.mappingMergePolicy = mergeMapping;
114 if (mappingSystem != null) {
115 mappingSystem.setMappingMerge(mergeMapping);
116 ConfigIni.getInstance().setMappingMerge(mappingMergePolicy);
121 public void setLookupPolicy(IMappingService.LookupPolicy policy) {
122 ConfigIni.getInstance().setLookupPolicy(policy);
125 public void initialize() {
126 LOG.info("Mapping Service initializing...");
127 dsbe = new DataStoreBackEnd(dataBroker);
129 mappingSystem = new MappingSystem(dao, iterateMask, notificationPolicy, mappingMergePolicy);
130 mappingSystem.setDataStoreBackEnd(dsbe);
131 mappingSystem.initialize();
133 keyListener = new AuthenticationKeyDataListener(dataBroker, mappingSystem);
134 mappingListener = new MappingDataListener(dataBroker, mappingSystem, notificationPublishService);
135 LOG.info("Mapping Service loaded.");
139 public Future<RpcResult<Void>> addKey(AddKeyInput input) {
140 Preconditions.checkNotNull(input, "add-key RPC input must be not null!");
141 LOG.trace("RPC received to add the following key: " + input.toString());
143 RpcResultBuilder<Void> rpcResultBuilder;
145 MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
148 String message = "Key already exists! Please use update-key if you want to change it.";
149 rpcResultBuilder = RpcResultBuilder.<Void>failed()
150 .withError(RpcError.ErrorType.PROTOCOL, DATA_EXISTS_TAG, message);
151 return Futures.immediateFuture(rpcResultBuilder.build());
154 dsbe.addAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
155 rpcResultBuilder = RpcResultBuilder.success();
157 return Futures.immediateFuture(rpcResultBuilder.build());
161 public Future<RpcResult<Void>> addMapping(AddMappingInput input) {
162 Preconditions.checkNotNull(input, "add-mapping RPC input must be not null!");
163 LOG.trace("RPC received to add the following mapping: " + input.toString());
165 dsbe.addMapping(RPCInputConvertorUtil.toMapping(input));
167 RpcResultBuilder<Void> rpcResultBuilder;
169 rpcResultBuilder = RpcResultBuilder.success();
171 return Futures.immediateFuture(rpcResultBuilder.build());
175 public void addMapping(MappingOrigin origin, Eid key, SiteId siteId, MappingData mappingData) {
176 // SB registrations are first written to the MappingSystem and only afterwards are persisted to the datastore
177 if (origin.equals(MappingOrigin.Southbound)) {
178 // Store data first in MapCache and only afterwards persist to datastore. This should be used only for SB
180 mappingSystem.addMapping(origin, key, mappingData);
181 dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, mappingData));
182 if (mappingData.getXtrId() != null) {
183 dsbe.addXtrIdMapping(DSBEInputUtil.toXtrIdMapping(mappingData));
186 dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, mappingData));
191 public void refreshMappingRegistration(Eid key, XtrId xtrId, Long timestamp) {
192 mappingSystem.refreshMappingRegistration(key, xtrId, timestamp);
196 public Future<RpcResult<GetKeyOutput>> getKey(GetKeyInput input) {
197 Preconditions.checkNotNull(input, "get-key RPC input must be not null!");
198 LOG.trace("RPC received to get the following key: " + input.toString());
200 RpcResultBuilder<GetKeyOutput> rpcResultBuilder;
202 MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
205 String message = "Key was not found in the mapping database";
206 rpcResultBuilder = RpcResultBuilder.<GetKeyOutput>failed()
207 .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
209 rpcResultBuilder = RpcResultBuilder.success(new GetKeyOutputBuilder().setMappingAuthkey(key));
212 return Futures.immediateFuture(rpcResultBuilder.build());
216 public Future<RpcResult<GetMappingOutput>> getMapping(GetMappingInput input) {
217 Preconditions.checkNotNull(input, "get-mapping RPC input must be not null!");
218 LOG.trace("RPC received to get the following mapping: " + input.toString());
220 RpcResultBuilder<GetMappingOutput> rpcResultBuilder;
222 MappingData reply = mappingSystem.getMapping(convertToBinaryIfNecessary(input.getEid()));
225 String message = "No mapping was found in the mapping database";
226 rpcResultBuilder = RpcResultBuilder.<GetMappingOutput>failed()
227 .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
229 final MappingRecord convertedReply = convertFromBinaryIfNecessary(reply.getRecord());
230 rpcResultBuilder = RpcResultBuilder.success(new GetMappingOutputBuilder().setMappingRecord(convertedReply));
233 return Futures.immediateFuture(rpcResultBuilder.build());
237 public MappingData getMapping(MappingOrigin origin, Eid key) {
238 return mappingSystem.getMapping(origin, key);
242 public MappingData getMapping(Eid key) {
243 return mappingSystem.getMapping(key);
247 public MappingData getMapping(Eid srcKey, Eid dstKey) {
248 return mappingSystem.getMapping(srcKey, dstKey);
252 public Future<RpcResult<GetMappingWithXtrIdOutput>> getMappingWithXtrId(GetMappingWithXtrIdInput input) {
253 Preconditions.checkNotNull(input, "get-mapping RPC input must be not null!");
254 LOG.trace("RPC received to get the following mapping: " + input.toString());
256 RpcResultBuilder<GetMappingWithXtrIdOutput> rpcResultBuilder;
258 MappingData reply = mappingSystem.getMapping(null, convertToBinaryIfNecessary(input.getEid()),
262 String message = "No mapping was found in the mapping database";
263 rpcResultBuilder = RpcResultBuilder.<GetMappingWithXtrIdOutput>failed()
264 .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
266 final MappingRecord convertedReply = convertFromBinaryIfNecessary(reply.getRecord());
267 rpcResultBuilder = RpcResultBuilder.success(new GetMappingWithXtrIdOutputBuilder()
268 .setMappingRecord(convertedReply));
271 return Futures.immediateFuture(rpcResultBuilder.build());
275 public Future<RpcResult<Void>> removeKey(RemoveKeyInput input) {
276 Preconditions.checkNotNull(input, "remove-key RPC input must be not null!");
277 LOG.trace("RPC received to remove the following key: " + input.toString());
279 RpcResultBuilder<Void> rpcResultBuilder;
281 dsbe.removeAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
283 rpcResultBuilder = RpcResultBuilder.success();
285 return Futures.immediateFuture(rpcResultBuilder.build());
289 public Future<RpcResult<Void>> removeMapping(RemoveMappingInput input) {
290 Preconditions.checkNotNull(input, "remove-mapping RPC input must be not null!");
291 LOG.trace("RPC received to remove the following mapping: " + input.toString());
293 RpcResultBuilder<Void> rpcResultBuilder;
295 dsbe.removeMapping(RPCInputConvertorUtil.toMapping(input));
297 rpcResultBuilder = RpcResultBuilder.success();
299 return Futures.immediateFuture(rpcResultBuilder.build());
303 public void removeMapping(MappingOrigin origin, Eid key) {
304 dsbe.removeMapping(DSBEInputUtil.toMapping(origin, key));
308 public Future<RpcResult<Void>> updateKey(UpdateKeyInput input) {
309 Preconditions.checkNotNull(input, "update-key RPC input must be not null!");
310 LOG.trace("RPC received to update the following key: " + input.toString());
312 RpcResultBuilder<Void> rpcResultBuilder;
314 MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
317 String message = "Key doesn't exist! Please use add-key if you want to create a new authentication key.";
318 rpcResultBuilder = RpcResultBuilder.<Void>failed()
319 .withError(RpcError.ErrorType.PROTOCOL, NOT_FOUND_TAG, message);
320 return Futures.immediateFuture(rpcResultBuilder.build());
323 dsbe.updateAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
324 rpcResultBuilder = RpcResultBuilder.success();
326 return Futures.immediateFuture(rpcResultBuilder.build());
330 public Future<RpcResult<Void>> updateMapping(UpdateMappingInput input) {
331 LOG.trace("RPC received to update the following mapping: " + input.toString());
332 Preconditions.checkNotNull(input, "update-mapping RPC input must be not null!");
334 RpcResultBuilder<Void> rpcResultBuilder;
336 dsbe.updateMapping(RPCInputConvertorUtil.toMapping(input));
338 rpcResultBuilder = RpcResultBuilder.success();
340 return Futures.immediateFuture(rpcResultBuilder.build());
344 public Future<RpcResult<Void>> removeKeys(RemoveKeysInput input) {
345 // TODO Auto-generated method stub
350 public Future<RpcResult<Void>> removeMappings(RemoveMappingsInput input) {
351 // TODO Auto-generated method stub
356 public Future<RpcResult<GetKeysOutput>> getKeys(GetKeysInput input) {
357 // TODO Auto-generated method stub
362 public Future<RpcResult<Void>> addMappings(AddMappingsInput input) {
363 // TODO Auto-generated method stub
368 public Future<RpcResult<Void>> updateKeys(UpdateKeysInput input) {
369 // TODO Auto-generated method stub
374 public Future<RpcResult<Void>> removeAllMappings() {
375 // TODO Auto-generated method stub
380 public Future<RpcResult<Void>> removeAllKeys() {
381 // TODO Auto-generated method stub
386 public Future<RpcResult<GetAllKeysOutput>> getAllKeys() {
387 // TODO Auto-generated method stub
392 public Future<RpcResult<Void>> updateMappings(UpdateMappingsInput input) {
393 // TODO Auto-generated method stub
398 public Future<RpcResult<Void>> addKeys(AddKeysInput input) {
399 // TODO Auto-generated method stub
404 public Future<RpcResult<GetAllMappingsOutput>> getAllMappings() {
405 // TODO Auto-generated method stub
410 public Future<RpcResult<GetMappingsOutput>> getMappings(
411 GetMappingsInput input) {
412 // TODO Auto-generated method stub
417 public Future<RpcResult<Void>> removeAllOperationalContent() {
418 RpcResultBuilder<Void> rpcResultBuilder;
421 * Since master nodes ignore datastore changes for southbound originated mappings, they need to be removed
425 mappingSystem.cleanSBMappings();
427 dsbe.removeAllOperationalDatastoreContent();
429 rpcResultBuilder = RpcResultBuilder.success();
431 return Futures.immediateFuture(rpcResultBuilder.build());
435 public Eid getWidestNegativePrefix(Eid key) {
436 return mappingSystem.getWidestNegativePrefix(key);
440 public void addAuthenticationKey(Eid key, MappingAuthkey authKey) {
441 dsbe.addAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, authKey));
445 public MappingAuthkey getAuthenticationKey(Eid key) {
446 return mappingSystem.getAuthenticationKey(key);
450 public void removeAuthenticationKey(Eid key) {
451 dsbe.removeAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, null));
455 public void addData(MappingOrigin origin, Eid key, String subKey, Object data) {
456 mappingSystem.addData(origin, key, subKey, data);
460 public Object getData(MappingOrigin origin, Eid key, String subKey) {
461 return mappingSystem.getData(origin, key, subKey);
465 public void removeData(MappingOrigin origin, Eid key, String subKey) {
466 mappingSystem.removeData(origin, key, subKey);
470 public Eid getParentPrefix(Eid key) {
471 return mappingSystem.getParentPrefix(key);
475 public String printMappings() {
476 return mappingSystem.printMappings();
480 public String printKeys() {
481 return mappingSystem.printKeys();
485 public void close() throws Exception {
486 LOG.info("Mapping Service is being destroyed!");
487 keyListener.closeDataChangeListener();
488 mappingListener.closeDataChangeListener();
489 mappingSystem.destroy();
493 public void cleanCachedMappings() {
494 mappingSystem.cleanCaches();
495 dsbe.removeAllDatastoreContent();
498 private static Eid convertToBinaryIfNecessary(Eid eid) {
499 if (LispAddressUtil.addressNeedsConversionToBinary(eid.getAddress())) {
500 return LispAddressUtil.convertToBinary(eid);
505 private static MappingRecord convertFromBinaryIfNecessary(MappingRecord originalRecord) {
506 List<LocatorRecord> originalLocators = originalRecord.getLocatorRecord();
508 List<LocatorRecord> convertedLocators = null;
509 if (originalLocators != null) {
510 // If convertedLocators is non-null, while originalLocators is also non-null, conversion has been made
511 convertedLocators = convertFromBinaryIfNecessary(originalLocators);
514 if (LispAddressUtil.addressNeedsConversionFromBinary(originalRecord.getEid().getAddress())
515 || (originalLocators != null && convertedLocators != null)) {
516 MappingRecordBuilder mrb = new MappingRecordBuilder(originalRecord);
517 mrb.setEid(LispAddressUtil.convertFromBinary(originalRecord.getEid()));
518 if (convertedLocators != null) {
519 mrb.setLocatorRecord(convertedLocators);
523 return originalRecord;
526 private static List<LocatorRecord> convertFromBinaryIfNecessary(List<LocatorRecord> originalLocators) {
527 List<LocatorRecord> convertedLocators = null;
528 for (LocatorRecord record : originalLocators) {
529 if (LispAddressUtil.addressNeedsConversionFromBinary(record.getRloc().getAddress())) {
530 LocatorRecordBuilder lrb = new LocatorRecordBuilder(record);
531 lrb.setRloc(LispAddressUtil.convertFromBinary(record.getRloc()));
532 if (convertedLocators == null) {
533 convertedLocators = new ArrayList<LocatorRecord>();
535 convertedLocators.add(lrb.build());
538 if (convertedLocators != null) {
539 return convertedLocators;
541 return originalLocators;
545 public void setIsMaster(boolean isMaster) {
546 this.isMaster = isMaster;
547 mappingSystem.setIsMaster(isMaster);
551 public boolean isMaster() {