package org.opendaylight.lispflowmapping.implementation.mapcache;
import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.ArrayList;
import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
+import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
+import org.opendaylight.lispflowmapping.implementation.util.MappingMergeUtil;
import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
import org.opendaylight.lispflowmapping.interfaces.dao.IRowVisitor;
import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
import org.opendaylight.lispflowmapping.interfaces.mapcache.IMapCache;
import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.authkey.container.MappingAuthkey;
* addresses.
*
* @author Florin Coras
+ * @author Lorand Jakab
*
*/
public class SimpleMapCache implements IMapCache {
return table;
}
+ private void removeExpiredXtrIdTableEntries(ILispDAO xtrIdDao, List<byte[]> expiredMappings) {
+ for (byte[] xtrId : expiredMappings) {
+ xtrIdDao.removeSpecific(xtrId, SubKeys.RECORD);
+ }
+ }
+
public void addMapping(Eid key, Object value, boolean shouldOverwrite) {
+ if (value == null) {
+ LOG.warn("addMapping() called with null 'value', ignoring");
+ return;
+ }
+
+ if (!(value instanceof MappingRecord)) {
+ LOG.warn("addMapping() called with a 'value' that is not a 'MappingRecord', ignoring");
+ return;
+ }
+
+ MappingRecord record = (MappingRecord) value;
+ if (record.getXtrId() == null && !shouldOverwrite && ConfigIni.getInstance().mappingMergeIsSet()) {
+ LOG.warn("addMapping() called will null xTR-ID in MappingRecord, while merge is set, ignoring");
+ return;
+ }
+
+ Date regdate = new Date(record.getTimestamp()); // The serializer always sets it
Eid eid = MaskUtil.normalize(key);
ILispDAO table = getOrInstantiateVniTable(key);
- table.put(eid, new MappingEntry<>(SubKeys.REGDATE, new Date(System.currentTimeMillis())));
- table.put(eid, new MappingEntry<>(SubKeys.RECORD, value));
+ ILispDAO xtrIdDao = null;
+ if (!shouldOverwrite) {
+ xtrIdDao = getOrInstantiateXtrIdTable(eid, table);
+ xtrIdDao.put(record.getXtrId(), new MappingEntry<>(SubKeys.RECORD, value));
+ }
- if (!shouldOverwrite && value instanceof MappingRecord) {
- MappingRecord record = (MappingRecord) value;
- if (record.getXtrId() != null) {
- ILispDAO xtrIdDao = getOrInstantiateXtrIdTable(eid, table);
- xtrIdDao.put(record.getXtrId(), new MappingEntry<>(SubKeys.RECORD, value));
- }
+ if (ConfigIni.getInstance().mappingMergeIsSet()) {
+ List<byte[]> expiredMappings = new ArrayList<byte[]>();
+ Set<IpAddress> sourceRlocs = new HashSet<IpAddress>();
+ MappingRecord mergedEntry = MappingMergeUtil.mergeXtrIdMappings(getXtrIdMappingList(xtrIdDao),
+ expiredMappings, sourceRlocs);
+ removeExpiredXtrIdTableEntries(xtrIdDao, expiredMappings);
+ regdate = new Date(mergedEntry.getTimestamp());
+ table.put(eid, new MappingEntry<>(SubKeys.REGDATE, regdate));
+ table.put(eid, new MappingEntry<>(SubKeys.RECORD, mergedEntry));
+ table.put(eid, new MappingEntry<>(SubKeys.SRC_RLOCS, sourceRlocs));
+ } else {
+ table.put(eid, new MappingEntry<>(SubKeys.REGDATE, regdate));
+ table.put(eid, new MappingEntry<>(SubKeys.RECORD, value));
}
}
// Method returns the DAO entry (hash) corresponding to either the longest prefix match of eid, if eid is maskable,
// or the exact match otherwise. eid must be a 'simple' address
- private SimpleImmutableEntry<Eid, Map<String, ?>> getDaoPairEntryBest(Eid key, ILispDAO dao) {
- if (MaskUtil.isMaskable(key.getAddress())) {
- Eid lookupKey;
- short mask = MaskUtil.getMaskForAddress(key.getAddress());
+ private SimpleImmutableEntry<Eid, Map<String, ?>> getDaoPairEntryBest(Eid eid, ILispDAO dao) {
+ Eid key;
+ if (MaskUtil.isMaskable(eid.getAddress())) {
+ short mask = MaskUtil.getMaskForAddress(eid.getAddress());
while (mask > 0) {
- lookupKey = MaskUtil.normalize(key, mask);
+ key = MaskUtil.normalize(eid, mask);
mask--;
- Map<String, ?> entry = dao.get(lookupKey);
+ Map<String, ?> entry = dao.get(key);
if (entry != null) {
- return new SimpleImmutableEntry<Eid, Map<String, ?>>(lookupKey, entry);
+ return new SimpleImmutableEntry<Eid, Map<String, ?>>(key, entry);
}
}
return null;
} else {
+ key = MaskUtil.normalize(eid);
Map<String, ?> entry = dao.get(key);
if (entry != null) {
return new SimpleImmutableEntry<Eid, Map<String, ?>>(key, entry);
}
}
- // Returns the mapping corresponding to the longest prefix match for eid. eid must be a simple (maskable or not)
- // address
- private Object getMappingLpmEid(Eid eid, ILispDAO dao) {
- Map<String, ?> daoEntry = getDaoEntryBest(eid, dao);
- if (daoEntry != null) {
- return daoEntry.get(SubKeys.RECORD);
- } else {
- return null;
+ // Returns the list of mappings stored in an xTR-ID DAO
+ private List<Object> getXtrIdMappingList(ILispDAO dao) {
+ if (dao != null) {
+ final List<Object> records = new ArrayList<Object>();
+ dao.getAll(new IRowVisitor() {
+ public void visitRow(Object keyId, String valueKey, Object value) {
+ if (valueKey.equals(SubKeys.RECORD)) {
+ records.add(value);
+ }
+ }
+ });
+ return records;
}
+ return null;
}
-
- // Returns the matched key and mapping corresponding to the longest prefix match for eid. eid must be a simple
- // (maskable or not) address
- private SimpleImmutableEntry<Eid, Object> getMappingPairLpmEid(Eid eid, ILispDAO dao) {
+/*
+ private SimpleImmutableEntry<byte[], Long> getXtrIdMinTimeStamp(ILispDAO dao) {
+ if (dao != null) {
+ // We don't actually need a list here, but the external variable we modify inside the IRowVisitor
+ // implementation has to be final. So we use a List, and it's methods, to modify contents
+ final List<SimpleImmutableEntry<byte[], Long>> entries =
+ new ArrayList<SimpleImmutableEntry<byte[], Long>>();
+ entries.set(0, new SimpleImmutableEntry<byte[], Long>(null, System.currentTimeMillis()));
+
+ dao.getAll(new IRowVisitor() {
+ public void visitRow(Object keyId, String valueKey, Object value) {
+ if (valueKey.equals(SubKeys.RECORD)) {
+ byte[] currentXtrId = ((MappingRecord) value).getXtrId();
+ long currentTimestamp = ((MappingRecord) value).getTimestamp();
+ // If one of the timestamps is expired, we signal it to the caller by setting the returned
+ // timestamp to null. The caller will then have to remove that xTR-ID, and do a full merge
+ // (or decrement)
+ if (MappingMergeUtil.timestampIsExpired(currentTimestamp)) {
+ SimpleImmutableEntry<byte[], Long> entry =
+ new SimpleImmutableEntry<byte[], Long>(currentXtrId, null);
+ entries.set(0, entry);
+ return;
+ }
+ if (entries.get(0).getValue() > currentTimestamp) {
+ SimpleImmutableEntry<byte[], Long> entry =
+ new SimpleImmutableEntry<byte[], Long>(currentXtrId, currentTimestamp);
+ entries.set(0, entry);
+ }
+ }
+ }
+ });
+ return entries.get(0);
+ }
+ return null;
+ }
+*/
+ // Returns the mapping corresponding to the longest prefix match for eid. eid must be a simple (maskable or not)
+ // address
+ private Object getMappingLpmEid(Eid eid, byte[] xtrId, ILispDAO dao) {
SimpleImmutableEntry<Eid, Map<String, ?>> daoEntry = getDaoPairEntryBest(eid, dao);
if (daoEntry != null) {
- return new SimpleImmutableEntry<Eid, Object>(daoEntry.getKey(), daoEntry.getValue().get(
- SubKeys.RECORD));
+ if (xtrId != null) {
+ ILispDAO xtrIdTable = getXtrIdTable(eid, (ILispDAO) daoEntry.getValue().get(SubKeys.XTRID_RECORDS));
+ if (xtrIdTable != null) {
+ MappingRecord xtrIdRecord = (MappingRecord) xtrIdTable.getSpecific(xtrId, SubKeys.RECORD);
+ if (xtrIdRecord.getTimestamp() != null &&
+ MappingMergeUtil.timestampIsExpired(xtrIdRecord.getTimestamp())) {
+ xtrIdTable.removeSpecific(xtrId, SubKeys.RECORD);
+ return null;
+ } else {
+ return xtrIdRecord;
+ }
+ } else {
+ return null;
+ }
+ } else {
+ Date timestamp = (Date) daoEntry.getValue().get(SubKeys.REGDATE);
+ if (timestamp != null && MappingMergeUtil.timestampIsExpired(timestamp)) {
+ dao.removeSpecific(daoEntry.getKey(), SubKeys.REGDATE);
+ dao.removeSpecific(daoEntry.getKey(), SubKeys.RECORD);
+ return null;
+ }
+ return daoEntry.getValue().get(SubKeys.RECORD);
+ }
} else {
return null;
}
}
- public Object getMapping(Eid srcEid, Eid dstEid) {
+ public Object getMapping(Eid srcEid, Eid dstEid, byte[] xtrId) {
if (dstEid == null) {
return null;
}
if (table == null) {
return null;
}
- return getMappingLpmEid(dstEid, table);
+ return getMappingLpmEid(dstEid, xtrId, table);
+ }
+
+ public Object getMapping(Eid srcEid, Eid dstEid) {
+ return getMapping(srcEid, dstEid, null);
+ }
+
+ public List<Object> getAllXtrIdMappings(Eid eid) {
+ Map<String, ?> daoEntry = getDaoEntryBest(eid, dao);
+ if (daoEntry != null) {
+ ILispDAO xtrIdTable = getXtrIdTable(eid, (ILispDAO) daoEntry.get(SubKeys.XTRID_RECORDS));
+ if (xtrIdTable != null) {
+ return getXtrIdMappingList(xtrIdTable);
+ }
+ }
+ return null;
}
public void removeMapping(Eid eid, boolean overwrite) {