2 * Copyright (c) 2014, 2016 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.Collections;
13 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
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.lispflowmapping.mapcache.lisp.LispMapCacheStringifier;
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;
25 * Multi table map-cache that works with 'simple' and SourceDest LCAF addresses (see lisp-proto.yang). It can do longest
26 * prefix matching for IP and SourceDest LCAF addresses. In case of the latter, it uses two tables, one for dst and
27 * another for source, queried and populated in this exact order.
29 * @author Florin Coras
31 public class MultiTableMapCache implements IMapCache {
34 public MultiTableMapCache(ILispDAO dao) {
38 private long getVni(Eid eid) {
39 if (eid.getVirtualNetworkId() == null) {
42 return eid.getVirtualNetworkId().getValue();
46 private ILispDAO getVniTable(Eid eid) {
47 return (ILispDAO) dao.getSpecific(getVni(eid), SubKeys.VNI);
50 private void removeVniTable(Eid eid) {
51 dao.removeSpecific(getVni(eid), SubKeys.VNI);
54 private ILispDAO getOrInstantiateVniTable(Eid eid) {
55 long vni = getVni(eid);
56 ILispDAO table = (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
58 table = dao.putNestedTable(vni, SubKeys.VNI);
63 public void addMapping(Eid key, Object value) {
64 Eid eid = MaskUtil.normalize(key);
65 ILispDAO table = getOrInstantiateVniTable(key);
67 if (eid.getAddress() instanceof SourceDestKey) {
68 Eid srcKey = SourceDestKeyHelper.getSrcBinary(eid);
69 ILispDAO srcDstDao = getOrInstantiateSDInnerDao(eid, table);
70 srcDstDao.put(srcKey, new MappingEntry<>(SubKeys.RECORD, value));
72 table.put(eid, new MappingEntry<>(SubKeys.RECORD, value));
76 // Returns the mapping corresponding to the longest prefix match for eid.
77 // eid must be a simple (maskable or not) address
78 private Object getMappingLpmEid(Eid eid, ILispDAO mappingsDb) {
82 Map<String, ?> daoEntry = mappingsDb.getBest(MaskUtil.normalize(eid));
83 if (daoEntry != null) {
84 return daoEntry.get(SubKeys.RECORD);
90 // Returns a mapping corresponding to either the longest prefix match for both dstEid and srcEid,
91 // if a SourceDest mapping exists, or to dstEid
92 private Object getMappingLpmSD(Eid srcEid, Eid dstEid, ILispDAO mappingsDb) {
93 Map<String, ?> daoEntry = mappingsDb.getBest(MaskUtil.normalize(dstEid));
94 if (daoEntry != null) {
95 // try SrcDst eid lookup
96 ILispDAO srcDstDao = (ILispDAO) daoEntry.get(SubKeys.LCAF_SRCDST);
97 if (srcEid != null && srcDstDao != null) {
98 // make sure that srcEid is a prefix, not an IP and binary
99 Object mapping = getMappingLpmEid(LispAddressUtil.asIpPrefixBinaryEid(srcEid), srcDstDao);
100 if (mapping != null) {
105 // if lookup fails, return whatever is found for dst eid
106 return daoEntry.get(SubKeys.RECORD);
111 public Object getMapping(Eid srcEid, Eid dstEid) {
112 if (dstEid == null) {
116 ILispDAO table = getVniTable(dstEid);
121 // a map-request for an actual SrcDst LCAF, ignore src eid
122 if (dstEid.getAddress() instanceof SourceDestKey) {
123 Eid srcAddr = SourceDestKeyHelper.getSrcBinary(dstEid);
124 Eid dstAddr = SourceDestKeyHelper.getDstBinary(dstEid);
125 return getMappingLpmSD(srcAddr, dstAddr, table);
128 // potential map-request for SrcDst LCAF from non SrcDst capable devices
129 return getMappingLpmSD(srcEid, dstEid, table);
132 // Returns null for positive mappings, and 0/0 for empty cache.
134 public Eid getWidestNegativeMapping(Eid key) {
135 ILispDAO table = getVniTable(key);
137 return MaskUtil.normalize(key, (short) 0);
139 return table.getWidestNegativePrefix(key);
143 public Set<Eid> getSubtree(Eid key) {
144 ILispDAO table = getVniTable(key);
146 return Collections.emptySet();
148 return table.getSubtree(key);
151 public void removeMapping(Eid eid) {
152 Eid key = MaskUtil.normalize(eid);
153 ILispDAO table = getVniTable(key);
158 if (key.getAddress() instanceof SourceDestKey) {
159 ILispDAO db = getSDInnerDao(key, table);
161 db.remove(SourceDestKeyHelper.getSrcBinary(key));
163 removeSDInnerDao(key, table);
169 if (table.isEmpty()) {
174 // SrcDst LCAFs are stored in a 2-tier DAO with dst having priority over src.
175 // This method returns the DAO associated to a dst or creates it if it doesn't exist.
176 private ILispDAO getOrInstantiateSDInnerDao(Eid address, ILispDAO mappingsDb) {
177 Eid dstKey = SourceDestKeyHelper.getDstBinary(address);
178 ILispDAO srcDstDao = (ILispDAO) mappingsDb.getSpecific(dstKey, SubKeys.LCAF_SRCDST);
179 if (srcDstDao == null) {
180 // inserts nested table for source
181 srcDstDao = mappingsDb.putNestedTable(dstKey, SubKeys.LCAF_SRCDST);
186 // SrcDst LCAFs are stored in a 2-tier DAO with dst having priority over src.
187 // This method returns the DAO associated to dst or null if it doesn't exist.
188 private ILispDAO getSDInnerDao(Eid address, ILispDAO mappingsDb) {
189 return (ILispDAO) mappingsDb.getSpecific(SourceDestKeyHelper.getDstBinary(address), SubKeys.LCAF_SRCDST);
192 private void removeSDInnerDao(Eid address, ILispDAO mappingsDb) {
193 mappingsDb.removeSpecific(SourceDestKeyHelper.getDstBinary(address), SubKeys.LCAF_SRCDST);
197 public void addData(Eid eid, String subKey, Object data) {
198 Eid key = MaskUtil.normalize(eid);
199 ILispDAO table = getOrInstantiateVniTable(key);
201 if (key.getAddress() instanceof SourceDestKey) {
202 ILispDAO srcDstDao = getOrInstantiateSDInnerDao(key, table);
203 srcDstDao.put(SourceDestKeyHelper.getSrcBinary(key), new MappingEntry<>(subKey, data));
205 table.put(key, new MappingEntry<>(subKey, data));
210 public Object getData(Eid eid, String subKey) {
211 Eid key = MaskUtil.normalize(eid);
212 ILispDAO table = getVniTable(key);
217 if (key.getAddress() instanceof SourceDestKey) {
218 ILispDAO srcDstDao = getSDInnerDao(key, table);
219 return srcDstDao.getSpecific(SourceDestKeyHelper.getSrcBinary(key), subKey);
221 return table.getSpecific(key, subKey);
226 public void removeData(Eid eid, String subKey) {
227 Eid key = MaskUtil.normalize(eid);
228 ILispDAO table = getVniTable(key);
232 if (key.getAddress() instanceof SourceDestKey) {
233 ILispDAO db = getSDInnerDao(key, table);
235 db.removeSpecific(SourceDestKeyHelper.getSrcBinary(key), subKey);
237 removeSDInnerDao(key, table);
241 table.removeSpecific(key, subKey);
243 if (table.isEmpty()) {
249 public String printMappings() {
250 return LispMapCacheStringifier.printMTMCMappings(dao);
254 public String prettyPrintMappings() {
255 return LispMapCacheStringifier.prettyPrintMTMCMappings(dao);