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
8 package org.opendaylight.lispflowmapping.mapcache;
10 import java.util.Date;
12 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
13 import org.opendaylight.lispflowmapping.interfaces.dao.IRowVisitor;
14 import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
15 import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
16 import org.opendaylight.lispflowmapping.interfaces.mapcache.IMapCache;
17 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
18 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
19 import org.opendaylight.lispflowmapping.lisp.util.SourceDestKeyHelper;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.authkey.container.MappingAuthkey;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
27 * Multi table map-cache that works with 'simple' and SourceDest LCAF addresses (see lisp-proto.yang). It can do longest
28 * prefix matching for IP and SourceDest LCAF addresses. In case of the latter, it uses two tables, one for dst and
29 * another for source, queried and populated in this exact order.
31 * @author Florin Coras
33 public class MultiTableMapCache implements IMapCache {
34 private static final Logger LOG = LoggerFactory.getLogger(MultiTableMapCache.class);
38 public MultiTableMapCache(ILispDAO dao) {
42 private ILispDAO getVniTable(Eid eid) {
44 if (eid.getVirtualNetworkId() == null) {
47 vni = eid.getVirtualNetworkId().getValue();
49 return (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
52 private ILispDAO getOrInstantiateVniTable(Eid eid) {
54 if (eid.getVirtualNetworkId() == null) {
57 vni = eid.getVirtualNetworkId().getValue();
59 ILispDAO table = (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
61 table = dao.putNestedTable(vni, SubKeys.VNI);
66 public void addMapping(Eid key, Object value, boolean shouldOverwrite, boolean shouldMerge) {
67 Eid eid = MaskUtil.normalize(key);
68 ILispDAO table = getOrInstantiateVniTable(key);
70 if (eid.getAddress() instanceof SourceDestKey) {
71 Eid srcKey = SourceDestKeyHelper.getSrcBinary(eid);
72 ILispDAO srcDstDao = getOrInstantiateSDInnerDao(eid, table);
73 srcDstDao.put(srcKey, new MappingEntry<>(SubKeys.REGDATE, new Date(System.currentTimeMillis())));
74 srcDstDao.put(srcKey, new MappingEntry<>(SubKeys.RECORD, value));
76 table.put(eid, new MappingEntry<>(SubKeys.REGDATE, new Date(System.currentTimeMillis())));
77 table.put(eid, new MappingEntry<>(SubKeys.RECORD, value));
81 // Returns the mapping corresponding to the longest prefix match for eid.
82 // eid must be a simple (maskable or not) address
83 private Object getMappingLpmEid(Eid eid, ILispDAO mappingsDb) {
87 Map<String, ?> daoEntry = mappingsDb.getBest(MaskUtil.normalize(eid));
88 if (daoEntry != null) {
89 return daoEntry.get(SubKeys.RECORD);
95 // Returns a mapping corresponding to either the longest prefix match for both dstEid and srcEid,
96 // if a SourceDest mapping exists, or to dstEid
97 private Object getMappingLpmSD(Eid srcEid, Eid dstEid, ILispDAO mappingsDb) {
98 Map<String, ?> daoEntry = mappingsDb.getBest(MaskUtil.normalize(dstEid));
99 if (daoEntry != null) {
100 // try SrcDst eid lookup
101 ILispDAO srcDstDao = (ILispDAO) daoEntry.get(SubKeys.LCAF_SRCDST);
102 if (srcEid != null && srcDstDao != null) {
103 // make sure that srcEid is a prefix, not an IP and binary
104 Object mapping = getMappingLpmEid(LispAddressUtil.asIpPrefixBinaryEid(srcEid), srcDstDao);
105 if (mapping != null) {
110 // if lookup fails, return whatever is found for dst eid
111 return daoEntry.get(SubKeys.RECORD);
116 public Object getMapping(Eid srcEid, Eid dstEid) {
117 if (dstEid == null) {
121 ILispDAO table = getVniTable(dstEid);
126 // a map-request for an actual SrcDst LCAF, ignore src eid
127 if (dstEid.getAddress() instanceof SourceDestKey) {
128 Eid srcAddr = SourceDestKeyHelper.getSrcBinary(dstEid);
129 Eid dstAddr = SourceDestKeyHelper.getDstBinary(dstEid);
130 return getMappingLpmSD(srcAddr, dstAddr, table);
133 // potential map-request for SrcDst LCAF from non SrcDst capable devices
134 return getMappingLpmSD(srcEid, dstEid, table);
138 public Eid getWidestNegativeMapping(Eid key) {
139 ILispDAO table = getVniTable(key);
143 return table.getWidestNegativePrefix(key);
146 public void removeMapping(Eid eid, boolean overwrite) {
147 Eid key = MaskUtil.normalize(eid);
148 ILispDAO table = getVniTable(key);
153 if (key.getAddress() instanceof SourceDestKey) {
154 ILispDAO db = getSDInnerDao(key, table);
156 db.removeSpecific(SourceDestKeyHelper.getSrcBinary(key),
158 db.removeSpecific(SourceDestKeyHelper.getSrcBinary(key),
162 table.removeSpecific(key, SubKeys.RECORD);
163 table.removeSpecific(key, SubKeys.REGDATE);
167 public void addAuthenticationKey(Eid eid, MappingAuthkey authKey) {
168 Eid key = MaskUtil.normalize(eid);
169 ILispDAO table = getOrInstantiateVniTable(key);
171 if (key.getAddress() instanceof SourceDestKey) {
172 ILispDAO srcDstDao = getOrInstantiateSDInnerDao(key, table);
173 srcDstDao.put(SourceDestKeyHelper.getSrcBinary(key), new MappingEntry<>(SubKeys.AUTH_KEY, authKey));
175 table.put(key, new MappingEntry<>(SubKeys.AUTH_KEY, authKey));
179 private MappingAuthkey getAuthKeyLpm(Eid prefix, ILispDAO db) {
180 short maskLength = MaskUtil.getMaskForAddress(prefix.getAddress());
181 while (maskLength >= 0) {
182 Eid key = MaskUtil.normalize(prefix, maskLength);
183 Object password = db.getSpecific(key, SubKeys.AUTH_KEY);
184 if (password != null && password instanceof MappingAuthkey) {
185 return (MappingAuthkey) password;
192 public MappingAuthkey getAuthenticationKey(Eid eid) {
193 ILispDAO table = getVniTable(eid);
198 if (MaskUtil.isMaskable(eid.getAddress())) {
199 if (eid.getAddress() instanceof SourceDestKey) {
200 // NOTE: this is an exact match, not a longest prefix match
201 ILispDAO srcDstDao = getSDInnerDao(eid, table);
202 if (srcDstDao != null) {
203 return getAuthKeyLpm(SourceDestKeyHelper.getSrcBinary(eid), srcDstDao);
207 return getAuthKeyLpm(eid, table);
210 Eid key = MaskUtil.normalize(eid);
211 Object password = table.getSpecific(key, SubKeys.AUTH_KEY);
212 if (password != null && password instanceof MappingAuthkey) {
213 return (MappingAuthkey) password;
215 LOG.warn("Failed to find password!");
221 public void removeAuthenticationKey(Eid eid) {
222 Eid key = MaskUtil.normalize(eid);
223 ILispDAO table = getVniTable(key);
228 if (key.getAddress() instanceof SourceDestKey) {
229 ILispDAO srcDstDao = getSDInnerDao(key, table);
230 if (srcDstDao != null) {
231 srcDstDao.removeSpecific(key, SubKeys.AUTH_KEY);
234 table.removeSpecific(key, SubKeys.AUTH_KEY);
238 // SrcDst LCAFs are stored in a 2-tier DAO with dst having priority over src.
239 // This method returns the DAO associated to a dst or creates it if it doesn't exist.
240 private ILispDAO getOrInstantiateSDInnerDao(Eid address, ILispDAO mappingsDb) {
241 Eid dstKey = SourceDestKeyHelper.getDstBinary(address);
242 ILispDAO srcDstDao = (ILispDAO) mappingsDb.getSpecific(dstKey, SubKeys.LCAF_SRCDST);
243 if (srcDstDao == null) {
244 // inserts nested table for source
245 srcDstDao = mappingsDb.putNestedTable(dstKey, SubKeys.LCAF_SRCDST);
250 // SrcDst LCAFs are stored in a 2-tier DAO with dst having priority over src.
251 // This method returns the DAO associated to dst or null if it doesn't exist.
252 private ILispDAO getSDInnerDao(Eid address, ILispDAO mappingsDb) {
253 return (ILispDAO) mappingsDb.getSpecific(SourceDestKeyHelper.getDstBinary(address), SubKeys.LCAF_SRCDST);
256 public String printMappings() {
257 final StringBuffer sb = new StringBuffer();
258 sb.append("Keys\tValues\n");
259 final IRowVisitor innerVisitor = (new IRowVisitor() {
262 public void visitRow(Object keyId, String valueKey, Object value) {
263 String key = keyId.getClass().getSimpleName() + "#" + keyId;
264 if (!lastKey.equals(key)) {
265 sb.append("\n" + key + "\t");
267 sb.append(valueKey + "=" + value + "\t");
271 final IRowVisitor vniVisitor = (new IRowVisitor() {
274 public void visitRow(Object keyId, String valueKey, Object value) {
275 String key = keyId.getClass().getSimpleName() + "#" + keyId;
276 if (!lastKey.equals(key)) {
277 sb.append(key + "\t");
279 if ((valueKey.equals(SubKeys.LCAF_SRCDST))) {
280 sb.append(valueKey + "= { ");
281 ((ILispDAO)value).getAll(innerVisitor);
284 sb.append(valueKey + "=" + value + "\t");
289 dao.getAll(new IRowVisitor() {
292 public void visitRow(Object keyId, String valueKey, Object value) {
293 String key = keyId.getClass().getSimpleName() + "#" + keyId;
294 if (!lastKey.equals(key)) {
295 sb.append("\n" + key + "\t");
297 if (valueKey.equals(SubKeys.VNI)) {
298 sb.append(valueKey + "= { ");
299 ((ILispDAO)value).getAll(vniVisitor);
302 sb.append(valueKey + "=" + value + "\t");
308 return sb.toString();
312 public void updateMappingRegistration(Eid key, Long timestamp) {
317 public void addData(Eid eid, String subKey, Object data) {
318 Eid key = MaskUtil.normalize(eid);
319 ILispDAO table = getOrInstantiateVniTable(key);
321 if (key.getAddress() instanceof SourceDestKey) {
322 ILispDAO srcDstDao = getOrInstantiateSDInnerDao(key, table);
323 srcDstDao.put(SourceDestKeyHelper.getSrcBinary(key), new MappingEntry<>(subKey, data));
325 table.put(key, new MappingEntry<>(subKey, data));
330 public Object getData(Eid eid, String subKey) {
331 Eid key = MaskUtil.normalize(eid);
332 ILispDAO table = getVniTable(key);
337 if (key.getAddress() instanceof SourceDestKey) {
338 ILispDAO srcDstDao = getSDInnerDao(key, table);
339 return srcDstDao.getSpecific(SourceDestKeyHelper.getSrcBinary(key), subKey);
341 return table.getSpecific(key, subKey);
346 public void removeData(Eid eid, String subKey) {
347 Eid key = MaskUtil.normalize(eid);
348 ILispDAO table = getVniTable(key);
352 if (key.getAddress() instanceof SourceDestKey) {
353 ILispDAO db = getSDInnerDao(key, table);
355 db.removeSpecific(SourceDestKeyHelper.getSrcBinary(key), subKey);
358 table.removeSpecific(key, subKey);