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.mapcache;
11 import java.util.Date;
14 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
15 import org.opendaylight.lispflowmapping.interfaces.dao.IRowVisitor;
16 import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
17 import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
18 import org.opendaylight.lispflowmapping.interfaces.mapcache.IMapCache;
19 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
20 import org.opendaylight.lispflowmapping.lisp.util.SourceDestKeyHelper;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.authkey.container.MappingAuthkey;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * Multi table map-cache that works with 'simple' and SourceDest LCAF addresses (see lisp-proto.yang). It can do longest
29 * prefix matching for IP and SourceDest LCAF addresses. In case of the latter, it uses two tables, one for dst and
30 * another for source, queried and populated in this exact order.
32 * @author Florin Coras
35 public class MultiTableMapCache implements IMapCache {
36 private static final Logger LOG = LoggerFactory.getLogger(MultiTableMapCache.class);
39 public MultiTableMapCache(ILispDAO dao) {
43 private ILispDAO getVniTable(Eid eid) {
45 if (eid.getVirtualNetworkId() == null) {
48 vni = eid.getVirtualNetworkId().getValue();
50 return (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
53 private ILispDAO getOrInstantiateVniTable(Eid eid) {
55 if (eid.getVirtualNetworkId() == null) {
58 vni = eid.getVirtualNetworkId().getValue();
60 ILispDAO table = (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
62 table = dao.putNestedTable(vni, SubKeys.VNI);
67 public void addMapping(Eid key, Object value, boolean shouldOverwrite, boolean shouldMerge) {
68 Eid eid = MaskUtil.normalize(key);
69 ILispDAO table = getOrInstantiateVniTable(key);
71 if (eid.getAddress() instanceof SourceDestKey) {
72 Eid srcKey = SourceDestKeyHelper.getSrcBinary(eid);
73 ILispDAO srcDstDao = getOrInstantiateSDInnerDao(eid, table);
74 srcDstDao.put(srcKey, new MappingEntry<>(SubKeys.REGDATE, new Date(System.currentTimeMillis())));
75 srcDstDao.put(srcKey, new MappingEntry<>(SubKeys.RECORD, value));
77 table.put(eid, new MappingEntry<>(SubKeys.REGDATE, new Date(System.currentTimeMillis())));
78 table.put(eid, new MappingEntry<>(SubKeys.RECORD, value));
82 private Object getMappingExactSD(Eid srcEid, Eid dstEid, ILispDAO dao) {
83 Map<String, ?> daoEntry = dao.get(dstEid);
84 if (daoEntry != null) {
85 // try SrcDst eid lookup
86 ILispDAO srcDstDao = (ILispDAO) daoEntry.get(SubKeys.LCAF_SRCDST);
87 if (srcEid != null && srcDstDao != null) {
88 return srcDstDao.getSpecific(srcEid, SubKeys.RECORD);
90 // if lookup fails, return whatever is found for dst eid
91 return daoEntry.get(SubKeys.RECORD);
96 // Returns the mapping corresponding to the longest prefix match for eid.
97 // eid must be a simple (maskable or not) address
98 private Object getMappingLpmEid(Eid eid, ILispDAO dao) {
102 Map<String, ?> daoEntry = dao.getBest(MaskUtil.normalize(eid));
103 if (daoEntry != null) {
104 return daoEntry.get(SubKeys.RECORD);
110 // Returns a mapping corresponding to either the longest prefix match for both dstEid and srcEid,
111 // if a SourceDest mapping exists, or to dstEid
112 private Object getMappingLpmSD(Eid srcEid, Eid dstEid, ILispDAO dao) {
113 Map<String, ?> daoEntry = dao.getBest(MaskUtil.normalize(dstEid));
114 if (daoEntry != null) {
115 // try SrcDst eid lookup
116 ILispDAO srcDstDao = (ILispDAO) daoEntry.get(SubKeys.LCAF_SRCDST);
117 if (srcDstDao != null) {
118 Object mapping = getMappingLpmEid(srcEid, srcDstDao);
119 if (mapping!= null) {
124 // if lookup fails, return whatever is found for dst eid
125 return daoEntry.get(SubKeys.RECORD);
130 public Object getMapping(Eid srcEid, Eid dstEid) {
131 if (dstEid == null) {
135 ILispDAO table = getVniTable(dstEid);
140 // a map-request for an actual SrcDst LCAF, ignore src eid
141 if (dstEid.getAddress() instanceof SourceDestKey) {
142 Eid srcAddr = SourceDestKeyHelper.getSrcBinary(dstEid);
143 Eid dstAddr = SourceDestKeyHelper.getDstBinary(dstEid);
144 return getMappingLpmSD(srcAddr, dstAddr, table);
147 // potential map-request for SrcDst LCAF from non SrcDst capable devices
148 return getMappingLpmSD(srcEid, dstEid, table);
152 public Eid getWidestNegativeMapping(Eid key) {
153 return dao.getWidestNegativePrefix(key);
156 public void removeMapping(Eid eid, boolean overwrite) {
157 Eid key = MaskUtil.normalize(eid);
158 ILispDAO table = getVniTable(key);
163 if (key.getAddress() instanceof SourceDestKey) {
164 ILispDAO db = getSDInnerDao(key, table);
166 db.removeSpecific(SourceDestKeyHelper.getSrcBinary(key),
170 table.removeSpecific(key, SubKeys.RECORD);
174 public void addAuthenticationKey(Eid eid, MappingAuthkey authKey) {
175 Eid key = MaskUtil.normalize(eid);
176 ILispDAO table = getOrInstantiateVniTable(key);
178 if (key.getAddress() instanceof SourceDestKey) {
179 ILispDAO srcDstDao = getOrInstantiateSDInnerDao(key, table);
180 srcDstDao.put(SourceDestKeyHelper.getSrcBinary(key), new MappingEntry<>(SubKeys.AUTH_KEY, authKey));
182 table.put(key, new MappingEntry<>(SubKeys.AUTH_KEY, authKey));
186 private MappingAuthkey getAuthKeyLpm(Eid prefix, ILispDAO db) {
187 short maskLength = MaskUtil.getMaskForAddress(prefix.getAddress());
188 while (maskLength >= 0) {
189 Eid key = MaskUtil.normalize(prefix, maskLength);
190 Object password = db.getSpecific(key, SubKeys.AUTH_KEY);
191 if (password != null && password instanceof MappingAuthkey) {
192 return (MappingAuthkey) password;
199 public MappingAuthkey getAuthenticationKey(Eid eid) {
200 ILispDAO table = getVniTable(eid);
205 if (MaskUtil.isMaskable(eid.getAddress())) {
206 if (eid.getAddress() instanceof SourceDestKey) {
207 // NOTE: this is an exact match, not a longest prefix match
208 ILispDAO srcDstDao = getSDInnerDao(eid, table);
209 if (srcDstDao != null) {
210 return getAuthKeyLpm(SourceDestKeyHelper.getSrcBinary(eid), srcDstDao);
214 return getAuthKeyLpm(eid, table);
217 Eid key = MaskUtil.normalize(eid);
218 Object password = table.getSpecific(key, SubKeys.AUTH_KEY);
219 if (password != null && password instanceof MappingAuthkey) {
220 return (MappingAuthkey) password;
222 LOG.warn("Failed to find password!");
228 public void removeAuthenticationKey(Eid eid) {
229 Eid key = MaskUtil.normalize(eid);
230 ILispDAO table = getVniTable(key);
235 if (key.getAddress() instanceof SourceDestKey) {
236 ILispDAO srcDstDao = getSDInnerDao(key, table);
237 if (srcDstDao != null) {
238 srcDstDao.removeSpecific(key, SubKeys.AUTH_KEY);
241 table.removeSpecific(key, SubKeys.AUTH_KEY);
245 // SrcDst LCAFs are stored in a 2-tier DAO with dst having priority over src.
246 // This method returns the DAO associated to a dst or creates it if it doesn't exist.
247 private ILispDAO getOrInstantiateSDInnerDao(Eid address, ILispDAO dao) {
248 Eid dstKey = SourceDestKeyHelper.getDstBinary(address);
249 ILispDAO srcDstDao = (ILispDAO) dao.getSpecific(dstKey, SubKeys.LCAF_SRCDST);
250 if (srcDstDao == null) {
251 // inserts nested table for source
252 srcDstDao = dao.putNestedTable(dstKey, SubKeys.LCAF_SRCDST);
257 // SrcDst LCAFs are stored in a 2-tier DAO with dst having priority over src.
258 // This method returns the DAO associated to dst or null if it doesn't exist.
259 private ILispDAO getSDInnerDao(Eid address, ILispDAO dao) {
260 return (ILispDAO) dao.getSpecific(SourceDestKeyHelper.getDstBinary(address), SubKeys.LCAF_SRCDST);
263 public String printMappings() {
264 final StringBuffer sb = new StringBuffer();
265 sb.append("Keys\tValues\n");
266 final IRowVisitor innerVisitor = (new IRowVisitor() {
269 public void visitRow(Object keyId, String valueKey, Object value) {
270 String key = keyId.getClass().getSimpleName() + "#" + keyId;
271 if (!lastKey.equals(key)) {
272 sb.append("\n" + key + "\t");
274 sb.append(valueKey + "=" + value + "\t");
278 final IRowVisitor vniVisitor = (new IRowVisitor() {
281 public void visitRow(Object keyId, String valueKey, Object value) {
282 String key = keyId.getClass().getSimpleName() + "#" + keyId;
283 if (!lastKey.equals(key)) {
284 sb.append(key + "\t");
286 if ((valueKey.equals(SubKeys.LCAF_SRCDST))) {
287 sb.append(valueKey + "= { ");
288 ((ILispDAO)value).getAll(innerVisitor);
291 sb.append(valueKey + "=" + value + "\t");
296 dao.getAll(new IRowVisitor() {
299 public void visitRow(Object keyId, String valueKey, Object value) {
300 String key = keyId.getClass().getSimpleName() + "#" + keyId;
301 if (!lastKey.equals(key)) {
302 sb.append("\n" + key + "\t");
304 if (valueKey.equals(SubKeys.VNI)) {
305 sb.append(valueKey + "= { ");
306 ((ILispDAO)value).getAll(vniVisitor);
309 sb.append(valueKey + "=" + value + "\t");
315 return sb.toString();
319 public void updateMappingRegistration(Eid key, Long timestamp) {
324 public void addData(Eid eid, String subKey, Object data) {
325 Eid key = MaskUtil.normalize(eid);
326 ILispDAO table = getOrInstantiateVniTable(key);
328 if (key.getAddress() instanceof SourceDestKey) {
329 ILispDAO srcDstDao = getOrInstantiateSDInnerDao(key, table);
330 srcDstDao.put(SourceDestKeyHelper.getSrcBinary(key), new MappingEntry<Object>(subKey, data));
332 table.put(key, new MappingEntry<Object>(subKey, data));
337 public Object getData(Eid eid, String subKey) {
338 Eid key = MaskUtil.normalize(eid);
339 ILispDAO table = getVniTable(key);
344 if (key.getAddress() instanceof SourceDestKey) {
345 ILispDAO srcDstDao = getSDInnerDao(key, table);
346 return srcDstDao.getSpecific(SourceDestKeyHelper.getSrcBinary(key), subKey);
348 return table.getSpecific(key, subKey);
353 public void removeData(Eid eid, String subKey) {
354 Eid key = MaskUtil.normalize(eid);
355 ILispDAO table = getVniTable(key);
359 if (key.getAddress() instanceof SourceDestKey) {
360 ILispDAO db = getSDInnerDao(key, table);
362 db.removeSpecific(SourceDestKeyHelper.getSrcBinary(key), subKey);
365 table.removeSpecific(key, subKey);