2 * Copyright (c) 2015, 2017 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;
15 import java.util.concurrent.Future;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
18 import org.opendaylight.lispflowmapping.config.ConfigIni;
19 import org.opendaylight.lispflowmapping.dsbackend.DataStoreBackEnd;
20 import org.opendaylight.lispflowmapping.implementation.mdsal.AuthenticationKeyDataListener;
21 import org.opendaylight.lispflowmapping.implementation.mdsal.MappingDataListener;
22 import org.opendaylight.lispflowmapping.implementation.util.DSBEInputUtil;
23 import org.opendaylight.lispflowmapping.implementation.util.RPCInputConvertorUtil;
24 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
25 import org.opendaylight.lispflowmapping.interfaces.dao.Subscriber;
26 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
27 import org.opendaylight.lispflowmapping.lisp.type.MappingData;
28 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.SiteId;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
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.authkey.container.MappingAuthkey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeyInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeysInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingsInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllKeysOutput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetAllMappingsOutput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyInput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutputBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeysInput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeysOutput;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingInput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutput;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutputBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingWithXtrIdInput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingWithXtrIdOutput;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingWithXtrIdOutputBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingsInput;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingsOutput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.OdlMappingserviceService;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeyInput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeysInput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingsInput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeyInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeysInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingInput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingsInput;
66 import org.opendaylight.yangtools.yang.common.RpcError;
67 import org.opendaylight.yangtools.yang.common.RpcResult;
68 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
69 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory;
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, AutoCloseable {
84 private 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 AuthenticationKeyDataListener keyListener;
91 private MappingDataListener mappingListener;
92 private final ILispDAO dao;
94 private final DataBroker dataBroker;
95 private final NotificationPublishService notificationPublishService;
97 private boolean mappingMergePolicy = ConfigIni.getInstance().mappingMergeIsSet();
98 private boolean notificationPolicy = ConfigIni.getInstance().smrIsSet();
99 private boolean iterateMask = true;
100 private boolean isMaster = false;
102 public MappingService(final DataBroker broker,
103 final NotificationPublishService notificationPublishService,
104 final ILispDAO lispDAO) {
105 this.dataBroker = broker;
106 this.notificationPublishService = notificationPublishService;
109 LOG.debug("MappingService created!");
114 public void setMappingMerge(boolean mergeMapping) {
115 this.mappingMergePolicy = mergeMapping;
116 if (mappingSystem != null) {
117 mappingSystem.setMappingMerge(mergeMapping);
118 ConfigIni.getInstance().setMappingMerge(mappingMergePolicy);
123 public void setLookupPolicy(IMappingService.LookupPolicy policy) {
124 ConfigIni.getInstance().setLookupPolicy(policy);
127 public void initialize() {
128 LOG.info("Mapping Service initializing...");
129 dsbe = new DataStoreBackEnd(dataBroker);
131 mappingSystem = new MappingSystem(dao, iterateMask, notificationPublishService, mappingMergePolicy);
132 mappingSystem.setDataStoreBackEnd(dsbe);
133 mappingSystem.initialize();
135 keyListener = new AuthenticationKeyDataListener(dataBroker, mappingSystem);
136 mappingListener = new MappingDataListener(dataBroker, mappingSystem, notificationPublishService);
137 LOG.info("Mapping Service loaded.");
141 public Future<RpcResult<Void>> addKey(AddKeyInput input) {
142 Preconditions.checkNotNull(input, "add-key RPC input must be not null!");
143 LOG.trace("RPC received to add the following key: " + input.toString());
145 RpcResultBuilder<Void> rpcResultBuilder;
147 MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
150 String message = "Key already exists! Please use update-key if you want to change it.";
151 rpcResultBuilder = RpcResultBuilder.<Void>failed()
152 .withError(RpcError.ErrorType.PROTOCOL, DATA_EXISTS_TAG, message);
153 return Futures.immediateFuture(rpcResultBuilder.build());
156 dsbe.addAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
157 rpcResultBuilder = RpcResultBuilder.success();
159 return Futures.immediateFuture(rpcResultBuilder.build());
163 public Future<RpcResult<Void>> addMapping(AddMappingInput input) {
164 Preconditions.checkNotNull(input, "add-mapping RPC input must be not null!");
165 LOG.trace("RPC received to add the following mapping: " + input.toString());
167 dsbe.addMapping(RPCInputConvertorUtil.toMapping(input));
169 RpcResultBuilder<Void> rpcResultBuilder;
171 rpcResultBuilder = RpcResultBuilder.success();
173 return Futures.immediateFuture(rpcResultBuilder.build());
177 public void addMapping(MappingOrigin origin, Eid key, SiteId siteId, MappingData mappingData) {
178 // SB registrations are first written to the MappingSystem and only afterwards are persisted to the datastore
179 if (origin.equals(MappingOrigin.Southbound)) {
180 // Store data first in MapCache and only afterwards persist to datastore. This should be used only for SB
182 mappingSystem.addMapping(origin, key, mappingData);
183 dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, mappingData));
184 if (mappingData.getXtrId() != null) {
185 dsbe.addXtrIdMapping(DSBEInputUtil.toXtrIdMapping(mappingData));
188 dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, mappingData));
193 public MappingData addNegativeMapping(Eid key) {
194 return mappingSystem.addNegativeMapping(key);
198 public void refreshMappingRegistration(Eid key, XtrId xtrId, Long timestamp) {
199 mappingSystem.refreshMappingRegistration(key, xtrId, timestamp);
203 public Future<RpcResult<GetKeyOutput>> getKey(GetKeyInput input) {
204 Preconditions.checkNotNull(input, "get-key RPC input must be not null!");
205 LOG.trace("RPC received to get the following key: " + input.toString());
207 RpcResultBuilder<GetKeyOutput> rpcResultBuilder;
209 MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
212 String message = "Key was not found in the mapping database";
213 rpcResultBuilder = RpcResultBuilder.<GetKeyOutput>failed()
214 .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
216 rpcResultBuilder = RpcResultBuilder.success(new GetKeyOutputBuilder().setMappingAuthkey(key));
219 return Futures.immediateFuture(rpcResultBuilder.build());
223 public Future<RpcResult<GetMappingOutput>> getMapping(GetMappingInput input) {
224 Preconditions.checkNotNull(input, "get-mapping RPC input must be not null!");
225 LOG.trace("RPC received to get the following mapping: " + input.toString());
227 RpcResultBuilder<GetMappingOutput> rpcResultBuilder;
229 MappingData reply = mappingSystem.getMapping(convertToBinaryIfNecessary(input.getEid()));
232 String message = "No mapping was found in the mapping database";
233 rpcResultBuilder = RpcResultBuilder.<GetMappingOutput>failed()
234 .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
236 final MappingRecord convertedReply = convertFromBinaryIfNecessary(reply.getRecord());
237 rpcResultBuilder = RpcResultBuilder.success(new GetMappingOutputBuilder().setMappingRecord(convertedReply));
240 return Futures.immediateFuture(rpcResultBuilder.build());
244 public MappingData getMapping(MappingOrigin origin, Eid key) {
245 return mappingSystem.getMapping(origin, key);
249 public MappingData getMapping(Eid key) {
250 return mappingSystem.getMapping(key);
254 public MappingData getMapping(Eid srcKey, Eid dstKey) {
255 return mappingSystem.getMapping(srcKey, dstKey);
259 public void subscribe(Subscriber subscriber, Eid subscribedEid) {
260 mappingSystem.subscribe(subscriber, subscribedEid);
264 public Set<Subscriber> getSubscribers(Eid eid) {
265 return mappingSystem.getSubscribers(eid);
269 public Future<RpcResult<GetMappingWithXtrIdOutput>> getMappingWithXtrId(GetMappingWithXtrIdInput input) {
270 Preconditions.checkNotNull(input, "get-mapping RPC input must be not null!");
271 LOG.trace("RPC received to get the following mapping: " + input.toString());
273 RpcResultBuilder<GetMappingWithXtrIdOutput> rpcResultBuilder;
275 MappingData reply = mappingSystem.getMapping(null, convertToBinaryIfNecessary(input.getEid()),
279 String message = "No mapping was found in the mapping database";
280 rpcResultBuilder = RpcResultBuilder.<GetMappingWithXtrIdOutput>failed()
281 .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
283 final MappingRecord convertedReply = convertFromBinaryIfNecessary(reply.getRecord());
284 rpcResultBuilder = RpcResultBuilder.success(new GetMappingWithXtrIdOutputBuilder()
285 .setMappingRecord(convertedReply));
288 return Futures.immediateFuture(rpcResultBuilder.build());
292 public Future<RpcResult<Void>> removeKey(RemoveKeyInput input) {
293 Preconditions.checkNotNull(input, "remove-key RPC input must be not null!");
294 LOG.trace("RPC received to remove the following key: " + input.toString());
296 RpcResultBuilder<Void> rpcResultBuilder;
298 dsbe.removeAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
300 rpcResultBuilder = RpcResultBuilder.success();
302 return Futures.immediateFuture(rpcResultBuilder.build());
306 public Future<RpcResult<Void>> removeMapping(RemoveMappingInput input) {
307 Preconditions.checkNotNull(input, "remove-mapping RPC input must be not null!");
308 LOG.trace("RPC received to remove the following mapping: " + input.toString());
310 RpcResultBuilder<Void> rpcResultBuilder;
312 dsbe.removeMapping(RPCInputConvertorUtil.toMapping(input));
314 rpcResultBuilder = RpcResultBuilder.success();
316 return Futures.immediateFuture(rpcResultBuilder.build());
320 public void removeMapping(MappingOrigin origin, Eid key) {
321 if (origin.equals(MappingOrigin.Southbound)) {
322 mappingSystem.removeMapping(origin, key);
324 dsbe.removeMapping(DSBEInputUtil.toMapping(origin, key));
328 public Future<RpcResult<Void>> updateKey(UpdateKeyInput input) {
329 Preconditions.checkNotNull(input, "update-key RPC input must be not null!");
330 LOG.trace("RPC received to update the following key: " + input.toString());
332 RpcResultBuilder<Void> rpcResultBuilder;
334 MappingAuthkey key = mappingSystem.getAuthenticationKey(convertToBinaryIfNecessary(input.getEid()));
337 String message = "Key doesn't exist! Please use add-key if you want to create a new authentication key.";
338 rpcResultBuilder = RpcResultBuilder.<Void>failed()
339 .withError(RpcError.ErrorType.PROTOCOL, NOT_FOUND_TAG, message);
340 return Futures.immediateFuture(rpcResultBuilder.build());
343 dsbe.updateAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
344 rpcResultBuilder = RpcResultBuilder.success();
346 return Futures.immediateFuture(rpcResultBuilder.build());
350 public Future<RpcResult<Void>> updateMapping(UpdateMappingInput input) {
351 LOG.trace("RPC received to update the following mapping: " + input.toString());
352 Preconditions.checkNotNull(input, "update-mapping RPC input must be not null!");
354 RpcResultBuilder<Void> rpcResultBuilder;
356 dsbe.updateMapping(RPCInputConvertorUtil.toMapping(input));
358 rpcResultBuilder = RpcResultBuilder.success();
360 return Futures.immediateFuture(rpcResultBuilder.build());
364 public Future<RpcResult<Void>> removeKeys(RemoveKeysInput input) {
365 // TODO Auto-generated method stub
370 public Future<RpcResult<Void>> removeMappings(RemoveMappingsInput input) {
371 // TODO Auto-generated method stub
376 public Future<RpcResult<GetKeysOutput>> getKeys(GetKeysInput input) {
377 // TODO Auto-generated method stub
382 public Future<RpcResult<Void>> addMappings(AddMappingsInput input) {
383 // TODO Auto-generated method stub
388 public Future<RpcResult<Void>> updateKeys(UpdateKeysInput input) {
389 // TODO Auto-generated method stub
394 public Future<RpcResult<Void>> removeAllMappings() {
395 // TODO Auto-generated method stub
400 public Future<RpcResult<Void>> removeAllKeys() {
401 // TODO Auto-generated method stub
406 public Future<RpcResult<GetAllKeysOutput>> getAllKeys() {
407 // TODO Auto-generated method stub
412 public Future<RpcResult<Void>> updateMappings(UpdateMappingsInput input) {
413 // TODO Auto-generated method stub
418 public Future<RpcResult<Void>> addKeys(AddKeysInput input) {
419 // TODO Auto-generated method stub
424 public Future<RpcResult<GetAllMappingsOutput>> getAllMappings() {
425 // TODO Auto-generated method stub
430 public Future<RpcResult<GetMappingsOutput>> getMappings(
431 GetMappingsInput input) {
432 // TODO Auto-generated method stub
437 public Future<RpcResult<Void>> removeAllOperationalContent() {
438 RpcResultBuilder<Void> rpcResultBuilder;
441 * Since master nodes ignore datastore changes for southbound originated mappings, they need to be removed
445 mappingSystem.cleanSBMappings();
447 dsbe.removeAllOperationalDatastoreContent();
449 rpcResultBuilder = RpcResultBuilder.success();
451 return Futures.immediateFuture(rpcResultBuilder.build());
455 public Eid getWidestNegativePrefix(Eid key) {
456 return mappingSystem.getWidestNegativePrefix(key);
460 public Set<Eid> getSubtree(MappingOrigin origin, Eid key) {
461 return mappingSystem.getSubtree(origin, key);
465 public void addAuthenticationKey(Eid key, MappingAuthkey authKey) {
466 dsbe.addAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, authKey));
470 public MappingAuthkey getAuthenticationKey(Eid key) {
471 return mappingSystem.getAuthenticationKey(key);
475 public void removeAuthenticationKey(Eid key) {
476 dsbe.removeAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, null));
480 public void addData(MappingOrigin origin, Eid key, String subKey, Object data) {
481 mappingSystem.addData(origin, key, subKey, data);
485 public Object getData(MappingOrigin origin, Eid key, String subKey) {
486 return mappingSystem.getData(origin, key, subKey);
490 public void removeData(MappingOrigin origin, Eid key, String subKey) {
491 mappingSystem.removeData(origin, key, subKey);
495 public Eid getParentPrefix(Eid key) {
496 return mappingSystem.getParentPrefix(key);
500 public String printMappings() {
501 return mappingSystem.printMappings();
505 public String prettyPrintMappings() {
506 return mappingSystem.prettyPrintMappings();
510 public String printKeys() {
511 return mappingSystem.printKeys();
515 public String prettyPrintKeys() {
516 return mappingSystem.prettyPrintKeys();
520 public void close() throws Exception {
521 LOG.info("Mapping Service is being destroyed!");
522 keyListener.closeDataChangeListener();
523 mappingListener.closeDataChangeListener();
524 mappingSystem.destroy();
528 public void cleanCachedMappings() {
529 mappingSystem.cleanCaches();
530 dsbe.removeAllDatastoreContent();
533 private static Eid convertToBinaryIfNecessary(Eid eid) {
534 if (LispAddressUtil.addressNeedsConversionToBinary(eid.getAddress())) {
535 return LispAddressUtil.convertToBinary(eid);
540 private static MappingRecord convertFromBinaryIfNecessary(MappingRecord originalRecord) {
541 List<LocatorRecord> originalLocators = originalRecord.getLocatorRecord();
543 List<LocatorRecord> convertedLocators = null;
544 if (originalLocators != null) {
545 // If convertedLocators is non-null, while originalLocators is also non-null, conversion has been made
546 convertedLocators = convertFromBinaryIfNecessary(originalLocators);
549 if (LispAddressUtil.addressNeedsConversionFromBinary(originalRecord.getEid().getAddress())
550 || (originalLocators != null && convertedLocators != null)) {
551 MappingRecordBuilder mrb = new MappingRecordBuilder(originalRecord);
552 mrb.setEid(LispAddressUtil.convertFromBinary(originalRecord.getEid()));
553 if (convertedLocators != null) {
554 mrb.setLocatorRecord(convertedLocators);
558 return originalRecord;
561 private static List<LocatorRecord> convertFromBinaryIfNecessary(List<LocatorRecord> originalLocators) {
562 List<LocatorRecord> convertedLocators = null;
563 for (LocatorRecord record : originalLocators) {
564 if (LispAddressUtil.addressNeedsConversionFromBinary(record.getRloc().getAddress())) {
565 LocatorRecordBuilder lrb = new LocatorRecordBuilder(record);
566 lrb.setRloc(LispAddressUtil.convertFromBinary(record.getRloc()));
567 if (convertedLocators == null) {
568 convertedLocators = new ArrayList<LocatorRecord>();
570 convertedLocators.add(lrb.build());
573 if (convertedLocators != null) {
574 return convertedLocators;
576 return originalLocators;
580 public void setIsMaster(boolean isMaster) {
581 this.isMaster = isMaster;
582 mappingSystem.setIsMaster(isMaster);
586 public boolean isMaster() {