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
9 package org.opendaylight.lispflowmapping.implementation;
11 import java.util.ArrayList;
12 import java.util.EnumMap;
13 import java.util.List;
15 import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
16 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
17 import org.opendaylight.lispflowmapping.implementation.mapcache.FlatMapCache;
18 import org.opendaylight.lispflowmapping.implementation.mapcache.MultiTableMapCache;
19 import org.opendaylight.lispflowmapping.implementation.mapcache.SimpleMapCache;
20 import org.opendaylight.lispflowmapping.implementation.mdsal.DataStoreBackEnd;
21 import org.opendaylight.lispflowmapping.implementation.util.DSBEInputUtil;
22 import org.opendaylight.lispflowmapping.implementation.util.MappingMergeUtil;
23 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
24 import org.opendaylight.lispflowmapping.interfaces.mapcache.IMapCache;
25 import org.opendaylight.lispflowmapping.interfaces.mapcache.IMappingSystem;
26 import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
27 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.SimpleAddress;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ExplicitLocatorPath;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ServicePath;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.explicit.locator.path.explicit.locator.path.Hop;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.SiteId;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.AuthenticationKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.Mapping;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.authkey.container.MappingAuthkey;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
49 * The Mapping System coordinates caching of md-sal stored mappings and if so configured enables longest prefix match
52 * @author Florin Coras
55 public class MappingSystem implements IMappingSystem {
56 private final static Logger LOG = LoggerFactory.getLogger(MappingSystem.class);
57 private boolean iterateMask;
58 private boolean notificationService;
59 private boolean overwrite;
61 private IMapCache smc;
62 private IMapCache pmc;
63 private final EnumMap<MappingOrigin, IMapCache> tableMap = new EnumMap<>(MappingOrigin.class);
64 private DataStoreBackEnd dsbe;
65 private BindingAwareBroker bindingAwareBroker;
67 public MappingSystem(ILispDAO dao, boolean iterateMask, boolean notifications, boolean overwrite) {
69 this.iterateMask = iterateMask;
70 this.notificationService = notifications;
71 this.overwrite = overwrite;
75 public void setDataStoreBackEnd(DataStoreBackEnd dsbe) {
80 public void setOverwritePolicy(boolean overwrite) {
81 this.overwrite = overwrite;
85 public void setIterateMask(boolean iterate) {
86 this.iterateMask = iterate;
87 if (smc != null || pmc != null) {
92 public void initialize() {
93 restoreDaoFromDatastore();
96 private void buildMapCaches() {
98 * There exists a direct relationship between MappingOrigins and the tables that are part of the MappingSystem.
99 * Therefore, if a new origin is added, probably a new table should be instantiate here as well.
102 smc = new SimpleMapCache(dao.putTable(MappingOrigin.Southbound.toString()));
103 pmc = new MultiTableMapCache(dao.putTable(MappingOrigin.Northbound.toString()));
105 smc = new FlatMapCache(dao.putTable(MappingOrigin.Southbound.toString()));
106 pmc = new FlatMapCache(dao.putTable(MappingOrigin.Northbound.toString()));
108 tableMap.put(MappingOrigin.Northbound, pmc);
109 tableMap.put(MappingOrigin.Southbound, smc);
112 public void addMapping(MappingOrigin origin, SiteId siteId, Eid key, Object data) {
113 // Store data first in MapCache and only afterwards persist to datastore. This should be used only for SB
115 addMapping(origin, key, data);
116 dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, (MappingRecord) data));
119 public void addMapping(MappingOrigin origin, Eid key, Object value) {
120 tableMap.get(origin).addMapping(key, value, origin == MappingOrigin.Southbound ? overwrite : true);
123 public void updateMappingRegistration(MappingOrigin origin, Eid key) {
124 tableMap.get(origin).updateMappingRegistration(key);
127 private MappingRecord updateServicePathMappingRecord(MappingRecord mapping, Eid eid) {
128 // keep properties of original record
129 MappingRecordBuilder recordBuilder = new MappingRecordBuilder(mapping);
130 recordBuilder.setLocatorRecord(new ArrayList<LocatorRecord>());
132 // there should only be one locator record
133 if (mapping.getLocatorRecord().size() != 1) {
134 LOG.warn("MappingRecord associated to ServicePath EID has more than one locator!");
138 LocatorRecord locatorRecord = mapping.getLocatorRecord().get(0);
139 long serviceIndex = ((ServicePath) eid.getAddress()).getServicePath().getServiceIndex();
140 int index = LispAddressUtil.STARTING_SERVICE_INDEX - (int) serviceIndex;
141 Rloc rloc = locatorRecord.getRloc();
142 if (rloc.getAddress() instanceof Ipv4 || rloc.getAddress() instanceof Ipv6) {
144 LOG.warn("Service Index should be 255 for simple IP RLOCs!");
147 } else if (rloc.getAddress() instanceof ExplicitLocatorPath) {
148 ExplicitLocatorPath elp = (ExplicitLocatorPath) rloc.getAddress();
149 List<Hop> hops = elp.getExplicitLocatorPath().getHop();
151 if (index < 0 || index > hops.size()) {
152 LOG.warn("Service Index out of bounds!");
156 SimpleAddress nextHop = hops.get(index).getAddress();
157 LocatorRecordBuilder lrb = new LocatorRecordBuilder(locatorRecord);
158 lrb.setRloc(LispAddressUtil.toRloc(nextHop));
159 recordBuilder.getLocatorRecord().add(lrb.build());
160 return recordBuilder.build();
162 LOG.warn("Nothing to do with ServicePath mapping record");
168 public Object getMapping(Eid src, Eid dst) {
169 // NOTE: Currently we have two lookup algorithms implemented, which are configurable
170 // using lookupPolicy in ConfigIni.java
172 if (ConfigIni.getInstance().getLookupPolicy() == ConfigIni.NB_AND_SB) {
173 return getMappingNbSbIntersection(src, dst);
175 return getMappingNbFirst(src, dst);
179 private Object getMappingNbFirst(Eid src, Eid dst) {
181 // Default lookup policy is northboundFirst
182 //lookupPolicy == NB_FIRST
184 Object nbMapping = pmc.getMapping(src, dst);
186 if (nbMapping == null) {
187 return smc.getMapping(src, dst);
189 if (dst.getAddress() instanceof ServicePath) {
190 return updateServicePathMappingRecord((MappingRecord) nbMapping, dst);
195 private Object getMappingNbSbIntersection(Eid src, Eid dst) {
196 //lookupPolicy == NB_AND_SB, we return intersection
197 //of NB and SB mappings, or NB mapping if intersection is empty.
199 Object nbMapping = pmc.getMapping(src, dst);
200 if (nbMapping == null) {
203 // no intersection for Service Path mappings
204 if (dst.getAddress() instanceof ServicePath) {
205 return updateServicePathMappingRecord((MappingRecord)nbMapping, dst);
207 Object sbMapping = smc.getMapping(src, dst);
208 if (sbMapping == null) {
211 // both NB and SB mappings exist. Compute intersection of the mappings
212 return MappingMergeUtil.computeNbSbIntersection((MappingRecord)nbMapping, (MappingRecord)sbMapping);
216 public Object getMapping(Eid dst) {
217 return getMapping((Eid)null, dst);
221 public Object getMapping(MappingOrigin origin, Eid key) {
222 return tableMap.get(origin).getMapping(null, key);
226 public void removeMapping(MappingOrigin origin, Eid key) {
227 tableMap.get(origin).removeMapping(key, origin == MappingOrigin.Southbound ? overwrite : true);
228 if (notificationService) {
234 public void addAuthenticationKey(Eid key, MappingAuthkey authKey) {
235 LOG.debug("Adding authentication key '{}' for {}", authKey.getKeyString(),
236 LispAddressStringifier.getString(key));
237 smc.addAuthenticationKey(key, authKey);
241 public MappingAuthkey getAuthenticationKey(Eid key) {
242 LOG.debug("Retrieving authentication key for {}", LispAddressStringifier.getString(key));
243 return smc.getAuthenticationKey(key);
247 public void removeAuthenticationKey(Eid key) {
248 LOG.debug("Removing authentication key for {}", LispAddressStringifier.getString(key));
249 smc.removeAuthenticationKey(key);
253 public void addData(MappingOrigin origin, Eid key, String subKey, Object data) {
254 LOG.debug("Add data of class {} for key {} and subkey {}", data.getClass(),
255 LispAddressStringifier.getString(key), subKey);
256 tableMap.get(origin).addData(key, subKey, data);
260 public Object getData(MappingOrigin origin, Eid key, String subKey) {
261 LOG.debug("Retrieving data for key {} and subkey {}", LispAddressStringifier.getString(key), subKey);
262 return tableMap.get(origin).getData(key, subKey);
266 public void removeData(MappingOrigin origin, Eid key, String subKey) {
267 LOG.debug("Removing data for key {} and subkey {}", LispAddressStringifier.getString(key), subKey);
268 tableMap.get(origin).removeData(key, subKey);
273 * Restore all mappings and keys from mdsal datastore
275 private void restoreDaoFromDatastore() {
276 List<Mapping> mappings = dsbe.getAllMappings();
277 List<AuthenticationKey> authKeys = dsbe.getAllAuthenticationKeys();
279 LOG.info("Restoring {} mappings and {} keys from datastore into DAO", mappings.size(), authKeys.size());
281 for (Mapping mapping : mappings) {
282 addMapping(mapping.getOrigin(), mapping.getMappingRecord().getEid(), mapping.getMappingRecord());
285 for (AuthenticationKey authKey : authKeys) {
286 addAuthenticationKey(authKey.getEid(), authKey.getMappingAuthkey());
290 public void destroy() {
291 LOG.info("Mapping System is being destroyed!");
295 public String printMappings() {
296 final StringBuffer sb = new StringBuffer();
297 sb.append("PolicyMapCache\n--------------\n");
298 sb.append(pmc.printMappings());
299 sb.append("SbMapCache\n----------\n");
300 sb.append(smc.printMappings());
301 return sb.toString();
304 public void cleanCaches() {