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.dsbackend.DataStoreBackEnd;
18 import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
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.util.LispAddressUtil;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.SiteId;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.authkey.container.MappingAuthkey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeyInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeysInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingsInput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllKeysOutput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllMappingsOutput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeysInput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeysOutput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingInput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutputBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingWithXtrIdInput;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingWithXtrIdOutput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingWithXtrIdOutputBuilder;
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.yangtools.yang.common.RpcError;
63 import org.opendaylight.yangtools.yang.common.RpcResult;
64 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
69 * Dispatcher of API calls that implements the RPC and Java APIs in mappingservice.yang and IMappingService
70 * respectively. It also coordinates and acts as container for all objects in charge of
71 * - saving and updating md-sal datastore stored mappings
72 * - monitoring md-sal datastore mapping updates and pushing them to the in memory mapping-system
73 * - in memory mapping-system
75 * @author Lorand Jakab
76 * @author Florin Coras
79 public class MappingService implements OdlMappingserviceService, IMappingService, AutoCloseable {
80 protected static final Logger LOG = LoggerFactory.getLogger(MappingService.class);
81 private static final String NOT_FOUND_TAG = "data-missing";
82 private static final String DATA_EXISTS_TAG = "data-exists";
84 private MappingSystem mappingSystem;
85 private DataStoreBackEnd dsbe;
86 private AuthenticationKeyDataListener keyListener;
87 private MappingDataListener mappingListener;
88 private final ILispDAO dao;
90 private final DataBroker dataBroker;
91 private final NotificationPublishService notificationPublishService;
93 private boolean overwritePolicy = ConfigIni.getInstance().mappingOverwriteIsSet();
94 private boolean notificationPolicy = ConfigIni.getInstance().smrIsSet();
95 private boolean iterateMask = true;
96 private boolean isMaster = false;
98 public MappingService(final DataBroker broker,
99 final NotificationPublishService notificationPublishService,
100 final ILispDAO lispDAO) {
101 this.dataBroker = broker;
102 this.notificationPublishService = notificationPublishService;
105 LOG.debug("MappingService created!");
110 public void setMappingOverwrite(boolean overwrite) {
111 this.overwritePolicy = overwrite;
112 if (mappingSystem != null) {
113 mappingSystem.setOverwritePolicy(overwrite);
114 ConfigIni.getInstance().setMappingOverwrite(overwrite);
119 public void setLookupPolicy(IMappingService.LookupPolicy policy) {
120 ConfigIni.getInstance().setLookupPolicy(policy);
123 public void initialize() {
124 LOG.info("Mapping Service initializing...");
125 dsbe = new DataStoreBackEnd(dataBroker);
127 mappingSystem = new MappingSystem(dao, iterateMask, notificationPolicy, overwritePolicy);
128 mappingSystem.setDataStoreBackEnd(dsbe);
129 mappingSystem.initialize();
131 keyListener = new AuthenticationKeyDataListener(dataBroker, mappingSystem);
132 mappingListener = new MappingDataListener(dataBroker, mappingSystem, notificationPublishService);
133 LOG.info("Mapping Service loaded.");
137 public Future<RpcResult<Void>> addKey(AddKeyInput input) {
138 Preconditions.checkNotNull(input, "add-key RPC input must be not null!");
139 LOG.trace("RPC received to add the following key: " + input.toString());
141 RpcResultBuilder<Void> rpcResultBuilder;
143 MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
146 String message = "Key already exists! Please use update-key if you want to change it.";
147 rpcResultBuilder = RpcResultBuilder.<Void>failed()
148 .withError(RpcError.ErrorType.PROTOCOL, DATA_EXISTS_TAG, message);
149 return Futures.immediateFuture(rpcResultBuilder.build());
152 dsbe.addAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
153 rpcResultBuilder = RpcResultBuilder.success();
155 return Futures.immediateFuture(rpcResultBuilder.build());
159 public Future<RpcResult<Void>> addMapping(AddMappingInput input) {
160 Preconditions.checkNotNull(input, "add-mapping RPC input must be not null!");
161 LOG.trace("RPC received to add the following mapping: " + input.toString());
163 dsbe.addMapping(RPCInputConvertorUtil.toMapping(input));
165 RpcResultBuilder<Void> rpcResultBuilder;
167 rpcResultBuilder = RpcResultBuilder.success();
169 return Futures.immediateFuture(rpcResultBuilder.build());
173 public void addMapping(MappingOrigin origin, Eid key, SiteId siteId, Object data, boolean merge) {
174 // SB registrations are first written to the MappingSystem and only afterwards are persisted to the datastore
175 if (origin.equals(MappingOrigin.Southbound)) {
176 // Store data first in MapCache and only afterwards persist to datastore. This should be used only for SB
178 mappingSystem.addMapping(origin, key, data, merge);
179 dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, (MappingRecord) data));
180 if (((MappingRecord) data).getXtrId() != null) {
181 dsbe.addXtrIdMapping(DSBEInputUtil.toXtrIdMapping((MappingRecord) data));
184 dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, (MappingRecord) data));
189 public void updateMappingRegistration(MappingOrigin origin, Eid key, Long timestamp) {
190 mappingSystem.updateMappingRegistration(origin, key, timestamp);
194 public Future<RpcResult<GetKeyOutput>> getKey(GetKeyInput input) {
195 Preconditions.checkNotNull(input, "get-key RPC input must be not null!");
196 LOG.trace("RPC received to get the following key: " + input.toString());
198 RpcResultBuilder<GetKeyOutput> rpcResultBuilder;
200 MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
203 String message = "Key was not found in the mapping database";
204 rpcResultBuilder = RpcResultBuilder.<GetKeyOutput>failed()
205 .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
207 rpcResultBuilder = RpcResultBuilder.success(new GetKeyOutputBuilder().setMappingAuthkey(key));
210 return Futures.immediateFuture(rpcResultBuilder.build());
214 public Future<RpcResult<GetMappingOutput>> getMapping(GetMappingInput input) {
215 Preconditions.checkNotNull(input, "get-mapping RPC input must be not null!");
216 LOG.trace("RPC received to get the following mapping: " + input.toString());
218 RpcResultBuilder<GetMappingOutput> rpcResultBuilder;
220 MappingRecord reply = (MappingRecord) mappingSystem.getMapping(convertToBinaryIfNecessary(input.getEid()));
223 String message = "No mapping was found in the mapping database";
224 rpcResultBuilder = RpcResultBuilder.<GetMappingOutput>failed()
225 .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
227 final MappingRecord convertedReply = convertFromBinaryIfNecessary(reply);
228 rpcResultBuilder = RpcResultBuilder.success(new GetMappingOutputBuilder().setMappingRecord(convertedReply));
231 return Futures.immediateFuture(rpcResultBuilder.build());
235 public Object getMapping(MappingOrigin origin, Eid key) {
236 return mappingSystem.getMapping(origin, key);
240 public Object getMapping(Eid key) {
241 return mappingSystem.getMapping(key);
245 public Object getMapping(Eid srcKey, Eid dstKey) {
246 return mappingSystem.getMapping(srcKey, dstKey);
250 public Future<RpcResult<GetMappingWithXtrIdOutput>> getMappingWithXtrId(GetMappingWithXtrIdInput input) {
251 Preconditions.checkNotNull(input, "get-mapping RPC input must be not null!");
252 LOG.trace("RPC received to get the following mapping: " + input.toString());
254 RpcResultBuilder<GetMappingWithXtrIdOutput> rpcResultBuilder;
256 MappingRecord reply = (MappingRecord) mappingSystem.getMapping(null, convertToBinaryIfNecessary(input.getEid()),
260 String message = "No mapping was found in the mapping database";
261 rpcResultBuilder = RpcResultBuilder.<GetMappingWithXtrIdOutput>failed()
262 .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
264 final MappingRecord convertedReply = convertFromBinaryIfNecessary(reply);
265 rpcResultBuilder = RpcResultBuilder.success(new GetMappingWithXtrIdOutputBuilder()
266 .setMappingRecord(convertedReply));
269 return Futures.immediateFuture(rpcResultBuilder.build());
273 public Future<RpcResult<Void>> removeKey(RemoveKeyInput input) {
274 Preconditions.checkNotNull(input, "remove-key RPC input must be not null!");
275 LOG.trace("RPC received to remove the following key: " + input.toString());
277 RpcResultBuilder<Void> rpcResultBuilder;
279 dsbe.removeAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
281 rpcResultBuilder = RpcResultBuilder.success();
283 return Futures.immediateFuture(rpcResultBuilder.build());
287 public Future<RpcResult<Void>> removeMapping(RemoveMappingInput input) {
288 Preconditions.checkNotNull(input, "remove-mapping RPC input must be not null!");
289 LOG.trace("RPC received to remove the following mapping: " + input.toString());
291 RpcResultBuilder<Void> rpcResultBuilder;
293 dsbe.removeMapping(RPCInputConvertorUtil.toMapping(input));
295 rpcResultBuilder = RpcResultBuilder.success();
297 return Futures.immediateFuture(rpcResultBuilder.build());
301 public void removeMapping(MappingOrigin origin, Eid key) {
302 dsbe.removeMapping(DSBEInputUtil.toMapping(origin, key));
306 public Future<RpcResult<Void>> updateKey(UpdateKeyInput input) {
307 Preconditions.checkNotNull(input, "update-key RPC input must be not null!");
308 LOG.trace("RPC received to update the following key: " + input.toString());
310 RpcResultBuilder<Void> rpcResultBuilder;
312 MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
315 String message = "Key doesn't exist! Please use add-key if you want to create a new authentication key.";
316 rpcResultBuilder = RpcResultBuilder.<Void>failed()
317 .withError(RpcError.ErrorType.PROTOCOL, NOT_FOUND_TAG, message);
318 return Futures.immediateFuture(rpcResultBuilder.build());
321 dsbe.updateAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
322 rpcResultBuilder = RpcResultBuilder.success();
324 return Futures.immediateFuture(rpcResultBuilder.build());
328 public Future<RpcResult<Void>> updateMapping(UpdateMappingInput input) {
329 LOG.trace("RPC received to update the following mapping: " + input.toString());
330 Preconditions.checkNotNull(input, "update-mapping RPC input must be not null!");
332 RpcResultBuilder<Void> rpcResultBuilder;
334 dsbe.updateMapping(RPCInputConvertorUtil.toMapping(input));
336 rpcResultBuilder = RpcResultBuilder.success();
338 return Futures.immediateFuture(rpcResultBuilder.build());
342 public Future<RpcResult<Void>> removeKeys(RemoveKeysInput input) {
343 // TODO Auto-generated method stub
348 public Future<RpcResult<Void>> removeMappings(RemoveMappingsInput input) {
349 // TODO Auto-generated method stub
354 public Future<RpcResult<GetKeysOutput>> getKeys(GetKeysInput input) {
355 // TODO Auto-generated method stub
360 public Future<RpcResult<Void>> addMappings(AddMappingsInput input) {
361 // TODO Auto-generated method stub
366 public Future<RpcResult<Void>> updateKeys(UpdateKeysInput input) {
367 // TODO Auto-generated method stub
372 public Future<RpcResult<Void>> removeAllMappings() {
373 // TODO Auto-generated method stub
378 public Future<RpcResult<Void>> removeAllKeys() {
379 // TODO Auto-generated method stub
384 public Future<RpcResult<GetAllKeysOutput>> getAllKeys() {
385 // TODO Auto-generated method stub
390 public Future<RpcResult<Void>> updateMappings(UpdateMappingsInput input) {
391 // TODO Auto-generated method stub
396 public Future<RpcResult<Void>> addKeys(AddKeysInput input) {
397 // TODO Auto-generated method stub
402 public Future<RpcResult<GetAllMappingsOutput>> getAllMappings() {
403 // TODO Auto-generated method stub
408 public Future<RpcResult<GetMappingsOutput>> getMappings(
409 GetMappingsInput input) {
410 // TODO Auto-generated method stub
415 public Eid getWidestNegativePrefix(Eid key) {
416 return mappingSystem.getWidestNegativePrefix(key);
420 public void addAuthenticationKey(Eid key, MappingAuthkey authKey) {
421 dsbe.addAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, authKey));
425 public MappingAuthkey getAuthenticationKey(Eid key) {
426 return mappingSystem.getAuthenticationKey(key);
430 public void removeAuthenticationKey(Eid key) {
431 dsbe.removeAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, null));
435 public void addData(MappingOrigin origin, Eid key, String subKey, Object data) {
436 mappingSystem.addData(origin, key, subKey, data);
440 public Object getData(MappingOrigin origin, Eid key, String subKey) {
441 return mappingSystem.getData(origin, key, subKey);
445 public void removeData(MappingOrigin origin, Eid key, String subKey) {
446 mappingSystem.removeData(origin, key, subKey);
450 public String printMappings() {
451 return mappingSystem.printMappings();
455 public void close() throws Exception {
456 LOG.info("Mapping Service is being destroyed!");
457 keyListener.closeDataChangeListener();
458 mappingListener.closeDataChangeListener();
462 public void cleanCachedMappings() {
463 mappingSystem.cleanCaches();
464 dsbe.removeAllDatastoreContent();
467 private static Eid convertToBinaryIfNecessary(Eid eid) {
468 if (LispAddressUtil.addressNeedsConversionToBinary(eid.getAddress())) {
469 return LispAddressUtil.convertToBinary(eid);
474 private static MappingRecord convertFromBinaryIfNecessary(MappingRecord originalRecord) {
475 List<LocatorRecord> originalLocators = originalRecord.getLocatorRecord();
477 List<LocatorRecord> convertedLocators = null;
478 if (originalLocators != null) {
479 // If convertedLocators is non-null, while originalLocators is also non-null, conversion has been made
480 convertedLocators = convertFromBinaryIfNecessary(originalLocators);
483 if (LispAddressUtil.addressNeedsConversionFromBinary(originalRecord.getEid().getAddress())
484 || (originalLocators != null && convertedLocators != null)) {
485 MappingRecordBuilder mrb = new MappingRecordBuilder(originalRecord);
486 mrb.setEid(LispAddressUtil.convertFromBinary(originalRecord.getEid()));
487 if (convertedLocators != null) {
488 mrb.setLocatorRecord(convertedLocators);
492 return originalRecord;
495 private static List<LocatorRecord> convertFromBinaryIfNecessary(List<LocatorRecord> originalLocators) {
496 List<LocatorRecord> convertedLocators = null;
497 for (LocatorRecord record : originalLocators) {
498 if (LispAddressUtil.addressNeedsConversionFromBinary(record.getRloc().getAddress())) {
499 LocatorRecordBuilder lrb = new LocatorRecordBuilder(record);
500 lrb.setRloc(LispAddressUtil.convertFromBinary(record.getRloc()));
501 if (convertedLocators == null) {
502 convertedLocators = new ArrayList<LocatorRecord>();
504 convertedLocators.add(lrb.build());
507 if (convertedLocators != null) {
508 return convertedLocators;
510 return originalLocators;
514 public void setIsMaster(boolean isMaster) {
515 this.isMaster = isMaster;
516 mappingSystem.setIsMaster(isMaster);
520 public boolean isMaster() {