2 * Copyright (c) 2014 Contextream, Inc. and others. 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.mapcache;
11 import java.util.Date;
15 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
16 import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
17 import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
18 import org.opendaylight.lispflowmapping.interfaces.dao.SubscriberRLOC;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.eidtolocatorrecords.EidToLocatorRecord;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.eidtolocatorrecords.EidToLocatorRecordBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.lispaddress.LispAddressContainer;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.lispaddress.lispaddresscontainer.address.LcafSourceDest;
23 import org.opendaylight.lispflowmapping.lisp.util.LcafSourceDestHelper;
24 import org.opendaylight.lispflowmapping.lisp.util.LispAFIConvertor;
25 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
29 public class TopologyMapCache {
30 private static final Logger LOG = LoggerFactory.getLogger(TopologyMapCache.class);
32 public static boolean addMapping(EidToLocatorRecord record, boolean checkForChanges, ILispDAO dao,
33 boolean shouldIterate, boolean shouldOverwrite) {
34 LispAddressContainer eid = MaskUtil.normalize(record.getLispAddressContainer());
35 EidToLocatorRecord oldMapping = null;
36 if (eid.getAddress() instanceof LcafSourceDest) {
37 LispAddressContainer srcAddr = LcafSourceDestHelper.getSrc(eid);
38 LispAddressContainer dstAddr = LcafSourceDestHelper.getDst(eid);
40 if (checkForChanges) {
41 oldMapping = getMappingExactSD(srcAddr, dstAddr, dao);
43 ILispDAO srcDstDao = getOrInstantiateSDInnerDao(eid, dao);
44 srcDstDao.put(LcafSourceDestHelper.getSrc(eid),
45 new MappingEntry<>(SubKeys.REGDATE, new Date(System.currentTimeMillis())));
46 srcDstDao.put(LcafSourceDestHelper.getSrc(eid), new MappingEntry<>(SubKeys.RECORD, record));
47 if (checkForChanges && oldMapping != null && eid.equals(oldMapping.getLispAddressContainer())) {
51 if (checkForChanges) {
52 oldMapping = getMappingExactSD(null, eid, dao);
54 dao.put(eid, new MappingEntry<>(SubKeys.REGDATE, new Date(System.currentTimeMillis())));
55 dao.put(eid, new MappingEntry<>(SubKeys.RECORD, record));
56 if (checkForChanges && oldMapping != null && eid.equals(oldMapping.getLispAddressContainer())) {
63 // Method returns the DAO entry (hash) corresponding to either the longest prefix match of eid, if eid is maskable,
64 // or the exact match otherwise. eid must be a 'simple' address
65 private static Map<String, ?> getDaoEntryBest(LispAddressContainer eid, ILispDAO dao) {
66 if (MaskUtil.isMaskable(eid)) {
67 LispAddressContainer key;
68 short mask = MaskUtil.getMaskForAddress(eid);
70 key = MaskUtil.normalize(eid, mask);
72 Map<String, ?> entry = dao.get(key);
79 Map<String, ?> entry = dao.get(eid);
88 private static EidToLocatorRecord getMappingExactSD(LispAddressContainer srcEid, LispAddressContainer dstEid,
90 Map<String, ?> daoEntry = dao.get(dstEid);
91 if (daoEntry != null) {
92 // try SrcDst eid lookup
93 ILispDAO srcDstDao = (ILispDAO) daoEntry.get(SubKeys.LCAF_SRCDST);
94 if (srcEid != null && srcDstDao != null) {
95 EidToLocatorRecord mapping = (EidToLocatorRecord) srcDstDao.getSpecific(srcEid, SubKeys.RECORD);
98 // if lookup fails, return whatever is found for dst eid
99 return (EidToLocatorRecord) daoEntry.get(SubKeys.RECORD);
104 // Returns the mapping corresponding to the longest prefix match for eid. eid must be a simple (maskable or not) address
105 private static EidToLocatorRecord getMappingLpmEid(LispAddressContainer eid, ILispDAO dao) {
106 Map<String, ?> daoEntry = getDaoEntryBest(eid, dao);
107 if (daoEntry != null) {
108 return (EidToLocatorRecord) daoEntry.get(SubKeys.RECORD);
114 // Returns a mapping corresponding to either the longest prefix match for both dstEid and srcEid,
115 // if a SourceDest mapping exists, or to dstEid
116 private static EidToLocatorRecord getMappingLpmSD(LispAddressContainer srcEid, LispAddressContainer dstEid, ILispDAO dao) {
117 Map<String, ?> daoEntry = getDaoEntryBest(dstEid, dao);
118 if (daoEntry != null) {
120 // try SrcDst eid lookup
121 ILispDAO srcDstDao = (ILispDAO) daoEntry.get(SubKeys.LCAF_SRCDST);
122 if (srcDstDao != null) {
123 EidToLocatorRecord mapping = getMappingLpmEid(srcEid, srcDstDao);
124 if (mapping!= null) {
129 // if lookup fails, return whatever is found for dst eid
130 return (EidToLocatorRecord) daoEntry.get(SubKeys.RECORD);
135 public static EidToLocatorRecord getMapping(LispAddressContainer srcEid, LispAddressContainer dstEid,
137 // a map-request for an actual SrcDst LCAF, ignore src eid
138 if (dstEid.getAddress() instanceof LcafSourceDest) {
139 LispAddressContainer srcAddr = LcafSourceDestHelper.getSrc(dstEid);
140 LispAddressContainer dstAddr = LcafSourceDestHelper.getDst(dstEid);
141 return getMappingLpmSD(srcAddr, dstAddr, dao);
144 // potential map-request for SrcDst LCAF from non SrcDst capable devices
145 EidToLocatorRecord mapping = getMappingLpmSD(srcEid, dstEid, dao);
147 if (mapping == null) {
151 // if indeed SrcDst LCAF change the mapping's eid to matched dstEid
152 if (mapping.getLispAddressContainer().getAddress() instanceof LcafSourceDest) {
153 EidToLocatorRecord newMapping = new EidToLocatorRecordBuilder(mapping).setLispAddressContainer(
154 LcafSourceDestHelper.getDst(mapping.getLispAddressContainer())).build();
161 public static void removeMapping(LispAddressContainer address, ILispDAO dao, boolean oerwrite) {
162 if (address.getAddress() instanceof LcafSourceDest) {
163 ILispDAO db = getSDInnerDao(address, dao);
165 db.removeSpecific(LcafSourceDestHelper.getSrc(address),
169 dao.removeSpecific(address, SubKeys.RECORD);
173 public static void addAuthenticationKey(LispAddressContainer address, String key, ILispDAO dao) {
174 if (address.getAddress() instanceof LcafSourceDest) {
175 ILispDAO srcDstDao = getOrInstantiateSDInnerDao(address, dao);
176 srcDstDao.put(LcafSourceDestHelper.getSrc(address), new MappingEntry<String>(SubKeys.PASSWORD, key));
178 dao.put(address, new MappingEntry<String>(SubKeys.PASSWORD, key));
182 private static String getAuthKeyLpm(LispAddressContainer prefix, ILispDAO db) {
183 short maskLength = MaskUtil.getMaskForAddress(prefix);
184 while (maskLength >= 0) {
185 LispAddressContainer key = MaskUtil.normalize(prefix, maskLength);
186 Object password = db.getSpecific(key, SubKeys.PASSWORD);
187 if (password != null && password instanceof String) {
188 return (String) password;
195 public static String getAuthenticationKey(LispAddressContainer eid, ILispDAO dao, boolean iterate) {
196 if (MaskUtil.isMaskable(LispAFIConvertor.toAFI(eid)) && iterate) {
197 return getAuthKeyLpm(eid, dao);
198 } else if (eid.getAddress() instanceof LcafSourceDest && iterate) {
199 // NOTE: this is an exact match, not a longest prefix match
200 ILispDAO srcDstDao = getSDInnerDao(eid, dao);
201 if (srcDstDao != null) {
202 return getAuthKeyLpm(LcafSourceDestHelper.getSrc(eid), srcDstDao);
206 Object password = dao.getSpecific(eid, SubKeys.PASSWORD);
207 if (password != null && password instanceof String) {
208 return (String) password;
210 LOG.warn("Failed to find password!");
216 public static void removeAuthenticationKey(LispAddressContainer eid, ILispDAO dao) {
217 if (eid.getAddress() instanceof LcafSourceDest) {
218 ILispDAO srcDstDao = getSDInnerDao(eid, dao);
219 if (srcDstDao != null) {
220 srcDstDao.removeSpecific(eid, SubKeys.PASSWORD);
223 dao.removeSpecific(eid, SubKeys.PASSWORD);
227 public static void addSubscribers(LispAddressContainer eid, Set<SubscriberRLOC> subscribers,
229 if (eid.getAddress() instanceof LcafSourceDest) {
230 ILispDAO srcDstDao = getOrInstantiateSDInnerDao(eid, dao);
231 srcDstDao.put(LcafSourceDestHelper.getSrc(eid), new MappingEntry<Set<SubscriberRLOC>>(
232 SubKeys.SUBSCRIBERS, subscribers));
234 dao.put(eid, new MappingEntry<Set<SubscriberRLOC>>(SubKeys.SUBSCRIBERS, subscribers));
238 @SuppressWarnings("unchecked")
239 public static Set<SubscriberRLOC> getSubscribers(LispAddressContainer eid, ILispDAO dao) {
241 if (eid.getAddress() instanceof LcafSourceDest) {
242 ILispDAO srcDstDao = getSDInnerDao(eid, dao);
243 subscribers = srcDstDao.getSpecific(LcafSourceDestHelper.getSrc(eid), SubKeys.SUBSCRIBERS);
245 subscribers = dao.getSpecific(eid, SubKeys.SUBSCRIBERS);
248 if (subscribers != null && subscribers instanceof Set<?>) {
249 return (Set<SubscriberRLOC>) subscribers;
254 public static void removeSubscribers(LispAddressContainer address, ILispDAO dao, boolean shouldOverwrite) {
255 if (address.getAddress() instanceof LcafSourceDest) {
256 ILispDAO db = getSDInnerDao(address, dao);
258 db.removeSpecific(LcafSourceDestHelper.getSrc(address), SubKeys.SUBSCRIBERS);
261 dao.removeSpecific(address, SubKeys.SUBSCRIBERS);
265 // SrcDst LCAFs are stored in a 2-tier DAO with dst having priority over src.
266 // This method returns the DAO associated to a dst or creates it if it doesn't exist.
267 public static ILispDAO getOrInstantiateSDInnerDao(LispAddressContainer address, ILispDAO dao) {
268 ILispDAO srcDstDao = (ILispDAO) dao.getSpecific(LcafSourceDestHelper.getDst(address),
269 SubKeys.LCAF_SRCDST);
270 if (srcDstDao == null) {
271 // inserts nested table for source
272 srcDstDao = dao.putNestedTable(LcafSourceDestHelper.getDst(address), SubKeys.LCAF_SRCDST);
277 // SrcDst LCAFs are stored in a 2-tier DAO with dst having priority over src.
278 // This method returns the DAO associated to dst or null if it doesn't exist.
279 public static ILispDAO getSDInnerDao(LispAddressContainer address, ILispDAO dao) {
280 return (ILispDAO) dao.getSpecific(LcafSourceDestHelper.getDst(address), SubKeys.LCAF_SRCDST);