2 * Copyright (c) 2015 Cisco Systems, 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.AbstractMap.SimpleImmutableEntry;
12 import java.util.ArrayList;
13 import java.util.Date;
14 import java.util.HashSet;
15 import java.util.List;
18 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
19 import org.opendaylight.lispflowmapping.interfaces.dao.IRowVisitor;
20 import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
21 import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
22 import org.opendaylight.lispflowmapping.interfaces.mapcache.IMapCache;
23 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.inet.binary.types.rev160303.IpAddressBinary;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.authkey.container.MappingAuthkey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
34 * Simple map-cache that works with 'simple' addresses (see lisp-proto.yang). It can do longest prefix matching for IP
37 * @author Florin Coras
38 * @author Lorand Jakab
41 public class SimpleMapCache implements IMapCache {
42 private static final Logger LOG = LoggerFactory.getLogger(SimpleMapCache.class);
45 public SimpleMapCache(ILispDAO dao) {
49 private ILispDAO getVniTable(Eid eid) {
51 if (eid.getVirtualNetworkId() == null) {
54 vni = eid.getVirtualNetworkId().getValue();
56 return (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
59 private ILispDAO getOrInstantiateVniTable(Eid eid) {
61 if (eid.getVirtualNetworkId() == null) {
64 vni = eid.getVirtualNetworkId().getValue();
66 ILispDAO table = (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
68 table = dao.putNestedTable(vni, SubKeys.VNI);
73 private ILispDAO getXtrIdTable(Eid eid, ILispDAO dao) {
74 return (ILispDAO) dao.getSpecific(eid, SubKeys.XTRID_RECORDS);
77 private ILispDAO getOrInstantiateXtrIdTable(Eid eid, ILispDAO dao) {
78 ILispDAO table = (ILispDAO) dao.getSpecific(eid, SubKeys.XTRID_RECORDS);
80 table = dao.putNestedTable(eid, SubKeys.XTRID_RECORDS);
85 private void removeExpiredXtrIdTableEntries(ILispDAO xtrIdDao, List<XtrId> expiredMappings) {
86 for (XtrId xtrId : expiredMappings) {
87 xtrIdDao.removeSpecific(xtrId, SubKeys.RECORD);
91 public void addMapping(Eid key, Object value, boolean shouldOverwrite, boolean shouldMerge) {
93 LOG.warn("addMapping() called with null 'value', ignoring");
97 if (!(value instanceof MappingRecord)) {
98 LOG.warn("addMapping() called with a 'value' that is not a 'MappingRecord', ignoring");
102 MappingRecord record = (MappingRecord) value;
103 if (record.getXtrId() == null && !shouldOverwrite && shouldMerge) {
104 LOG.warn("addMapping() called will null xTR-ID in MappingRecord, while merge is set, ignoring");
108 Date regdate = new Date(record.getTimestamp()); // The serializer always sets it
109 Eid eid = MaskUtil.normalize(key);
110 ILispDAO table = getOrInstantiateVniTable(key);
112 ILispDAO xtrIdDao = null;
113 if (!shouldOverwrite && record.getXtrId() != null) {
114 xtrIdDao = getOrInstantiateXtrIdTable(eid, table);
115 xtrIdDao.put(record.getXtrId(), new MappingEntry<>(SubKeys.RECORD, value));
119 List<XtrId> expiredMappings = new ArrayList<>();
120 Set<IpAddressBinary> sourceRlocs = new HashSet<>();
121 MappingRecord mergedEntry = MappingMergeUtil.mergeXtrIdMappings(getXtrIdMappingList(xtrIdDao),
122 expiredMappings, sourceRlocs);
123 removeExpiredXtrIdTableEntries(xtrIdDao, expiredMappings);
124 if (mergedEntry == null) {
127 regdate = new Date(mergedEntry.getTimestamp());
128 table.put(eid, new MappingEntry<>(SubKeys.REGDATE, regdate));
129 table.put(eid, new MappingEntry<>(SubKeys.RECORD, mergedEntry));
130 table.put(eid, new MappingEntry<>(SubKeys.SRC_RLOCS, sourceRlocs));
132 table.put(eid, new MappingEntry<>(SubKeys.REGDATE, regdate));
133 table.put(eid, new MappingEntry<>(SubKeys.RECORD, value));
137 // Returns the list of mappings stored in an xTR-ID DAO
138 private List<Object> getXtrIdMappingList(ILispDAO dao) {
140 final List<Object> records = new ArrayList<>();
141 dao.getAll(new IRowVisitor() {
142 public void visitRow(Object keyId, String valueKey, Object value) {
143 if (valueKey.equals(SubKeys.RECORD)) {
153 // Returns the mapping corresponding to the longest prefix match for eid. eid must be a simple (maskable or not)
155 private Object getMappingLpmEid(Eid eid, byte[] xtrId, ILispDAO dao) {
156 SimpleImmutableEntry<Eid, Map<String, ?>> daoEntry = dao.getBestPair(MaskUtil.normalize(eid));
157 if (daoEntry != null) {
159 ILispDAO xtrIdTable = getXtrIdTable(eid, (ILispDAO) daoEntry.getValue().get(SubKeys.XTRID_RECORDS));
160 if (xtrIdTable != null) {
161 MappingRecord xtrIdRecord = (MappingRecord) xtrIdTable.getSpecific(xtrId, SubKeys.RECORD);
162 if (xtrIdRecord.getTimestamp() != null
163 && MappingMergeUtil.timestampIsExpired(xtrIdRecord.getTimestamp())) {
164 xtrIdTable.removeSpecific(xtrId, SubKeys.RECORD);
173 Date timestamp = (Date) daoEntry.getValue().get(SubKeys.REGDATE);
174 if (timestamp != null && MappingMergeUtil.timestampIsExpired(timestamp)) {
175 dao.removeSpecific(daoEntry.getKey(), SubKeys.REGDATE);
176 dao.removeSpecific(daoEntry.getKey(), SubKeys.RECORD);
178 return daoEntry.getValue().get(SubKeys.RECORD);
185 public Object getMapping(Eid srcEid, Eid dstEid, byte[] xtrId) {
186 if (dstEid == null) {
190 ILispDAO table = getVniTable(dstEid);
194 return getMappingLpmEid(dstEid, xtrId, table);
197 public Object getMapping(Eid srcEid, Eid dstEid) {
198 return getMapping(srcEid, dstEid, null);
201 public List<Object> getAllXtrIdMappings(Eid eid) {
202 Map<String, ?> daoEntry = dao.getBest(MaskUtil.normalize(eid));
203 if (daoEntry != null) {
204 ILispDAO xtrIdTable = getXtrIdTable(eid, (ILispDAO) daoEntry.get(SubKeys.XTRID_RECORDS));
205 if (xtrIdTable != null) {
206 return getXtrIdMappingList(xtrIdTable);
212 public Eid getWidestNegativeMapping(Eid key) {
213 ILispDAO table = getVniTable(key);
217 return table.getWidestNegativePrefix(MaskUtil.normalize(key));
220 public void removeMapping(Eid eid, boolean overwrite) {
221 Eid key = MaskUtil.normalize(eid);
222 ILispDAO table = getVniTable(key);
227 table.removeSpecific(key, SubKeys.RECORD);
230 ILispDAO xtrIdTable = getXtrIdTable(key, table);
231 if (xtrIdTable != null) {
232 xtrIdTable.removeSpecific(key, SubKeys.RECORD);
237 public void addAuthenticationKey(Eid eid, MappingAuthkey authKey) {
238 Eid key = MaskUtil.normalize(eid);
239 ILispDAO table = getOrInstantiateVniTable(key);
240 table.put(key, new MappingEntry<>(SubKeys.AUTH_KEY, authKey));
243 private MappingAuthkey getAuthKeyLpm(Eid prefix, ILispDAO db) {
244 short maskLength = MaskUtil.getMaskForAddress(prefix.getAddress());
245 while (maskLength >= 0) {
246 Eid key = MaskUtil.normalize(prefix, maskLength);
247 Object password = db.getSpecific(key, SubKeys.AUTH_KEY);
248 if (password != null && password instanceof MappingAuthkey) {
249 return (MappingAuthkey) password;
256 public MappingAuthkey getAuthenticationKey(Eid eid) {
257 ILispDAO table = getVniTable(eid);
261 if (MaskUtil.isMaskable(eid.getAddress()) && !(eid.getAddress() instanceof SourceDestKey)) {
262 return getAuthKeyLpm(eid, table);
264 Eid key = MaskUtil.normalize(eid);
265 Object password = table.getSpecific(key, SubKeys.AUTH_KEY);
266 if (password != null && password instanceof MappingAuthkey) {
267 return (MappingAuthkey) password;
269 LOG.warn("Failed to find password!");
275 public void removeAuthenticationKey(Eid eid) {
276 Eid key = MaskUtil.normalize(eid);
277 ILispDAO table = getVniTable(key);
281 table.removeSpecific(key, SubKeys.AUTH_KEY);
284 public String printMappings() {
285 final StringBuffer sb = new StringBuffer();
286 sb.append("Keys\tValues\n");
288 final IRowVisitor innerVisitor = (new IRowVisitor() {
291 public void visitRow(Object keyId, String valueKey, Object value) {
292 String key = keyId.getClass().getSimpleName() + "#" + keyId;
293 if (!lastKey.equals(key)) {
294 sb.append("\n" + key + "\t");
296 sb.append(valueKey + "=" + value + "\t");
301 dao.getAll(new IRowVisitor() {
304 public void visitRow(Object keyId, String valueKey, Object value) {
305 String key = keyId.getClass().getSimpleName() + "#" + keyId;
306 if (!lastKey.equals(key)) {
307 sb.append("\n" + key + "\t");
309 if (valueKey.equals(SubKeys.VNI)) {
310 sb.append(valueKey + "= { ");
311 ((ILispDAO)value).getAll(innerVisitor);
314 sb.append(valueKey + "=" + value + "\t");
320 return sb.toString();
324 public void updateMappingRegistration(Eid eid, Long timestamp) {
325 ILispDAO table = getVniTable(eid);
329 if (timestamp == null) {
330 timestamp = System.currentTimeMillis();
332 Map<String, Object> daoEntry = table.getBest(MaskUtil.normalize(eid));
333 if (daoEntry != null) {
334 daoEntry.put(SubKeys.REGDATE, new Date(timestamp));
339 public void addData(Eid eid, String subKey, Object data) {
340 Eid key = MaskUtil.normalize(eid);
341 ILispDAO table = getOrInstantiateVniTable(key);
342 table.put(key, new MappingEntry<>(subKey, data));
346 public Object getData(Eid eid, String subKey) {
347 ILispDAO table = getOrInstantiateVniTable(eid);
351 Eid key = MaskUtil.normalize(eid);
352 return table.getSpecific(key, subKey);
356 public void removeData(Eid eid, String subKey) {
357 ILispDAO table = getOrInstantiateVniTable(eid);
361 Eid key = MaskUtil.normalize(eid);
362 table.removeSpecific(key, subKey);