1
2
3
4
5
6
7
8
9 package org.opendaylight.lispflowmapping.implementation.mapcache;
10
11 import java.util.AbstractMap.SimpleImmutableEntry;
12 import java.nio.ByteBuffer;
13 import java.util.ArrayList;
14 import java.util.Date;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19
20 import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
21 import org.opendaylight.lispflowmapping.implementation.util.MappingMergeUtil;
22 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
23 import org.opendaylight.lispflowmapping.interfaces.dao.IRowVisitor;
24 import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
25 import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
26 import org.opendaylight.lispflowmapping.interfaces.mapcache.IMapCache;
27 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Prefix;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6Prefix;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.authkey.container.MappingAuthkey;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37
38
39
40
41
42
43
44
45 public class SimpleMapCache implements IMapCache {
46 private static final Logger LOG = LoggerFactory.getLogger(SimpleMapCache.class);
47 private ILispDAO dao;
48
49 public SimpleMapCache(ILispDAO dao) {
50 this.dao = dao;
51 }
52
53 private ILispDAO getVniTable(Eid eid) {
54 long vni = 0;
55 if (eid.getVirtualNetworkId() == null) {
56 vni = 0;
57 } else {
58 vni = eid.getVirtualNetworkId().getValue();
59 }
60 return (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
61 }
62
63 private ILispDAO getOrInstantiateVniTable(Eid eid) {
64 long vni = 0;
65 if (eid.getVirtualNetworkId() == null) {
66 vni = 0;
67 } else {
68 vni = eid.getVirtualNetworkId().getValue();
69 }
70 ILispDAO table = (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
71 if (table == null) {
72 table = dao.putNestedTable(vni, SubKeys.VNI);
73 }
74 return table;
75 }
76
77 private ILispDAO getXtrIdTable(Eid eid, ILispDAO dao) {
78 return (ILispDAO) dao.getSpecific(eid, SubKeys.XTRID_RECORDS);
79 }
80
81 private ILispDAO getOrInstantiateXtrIdTable(Eid eid, ILispDAO dao) {
82 ILispDAO table = (ILispDAO) dao.getSpecific(eid, SubKeys.XTRID_RECORDS);
83 if (table == null) {
84 table = dao.putNestedTable(eid, SubKeys.XTRID_RECORDS);
85 }
86 return table;
87 }
88
89 public static Object deserializeBytes(byte[] data) {
90 return ByteBuffer.wrap(data);
91 }
92
93 private void removeExpiredXtrIdTableEntries(ILispDAO xtrIdDao, List<byte[]> expiredMappings) {
94 for (byte[] xtrId : expiredMappings) {
95 xtrIdDao.removeSpecific(deserializeBytes(xtrId), SubKeys.RECORD);
96 }
97 }
98
99 public void addMapping(Eid key, Object value, boolean shouldOverwrite) {
100 if (value == null) {
101 LOG.warn("addMapping() called with null 'value', ignoring");
102 return;
103 }
104
105 if (!(value instanceof MappingRecord)) {
106 LOG.warn("addMapping() called with a 'value' that is not a 'MappingRecord', ignoring");
107 return;
108 }
109
110 MappingRecord record = (MappingRecord) value;
111 if (record.getXtrId() == null && !shouldOverwrite && ConfigIni.getInstance().mappingMergeIsSet()) {
112 LOG.warn("addMapping() called will null xTR-ID in MappingRecord, while merge is set, ignoring");
113 return;
114 }
115
116 Date regdate = new Date(record.getTimestamp());
117 Eid eid = MaskUtil.normalize(key);
118 ILispDAO table = getOrInstantiateVniTable(key);
119
120 ILispDAO xtrIdDao = null;
121 if (!shouldOverwrite) {
122 xtrIdDao = getOrInstantiateXtrIdTable(eid, table);
123 xtrIdDao.put(deserializeBytes(record.getXtrId()), new MappingEntry<>(SubKeys.RECORD, value));
124 }
125
126 if (ConfigIni.getInstance().mappingMergeIsSet()) {
127 List<byte[]> expiredMappings = new ArrayList<byte[]>();
128 Set<IpAddress> sourceRlocs = new HashSet<IpAddress>();
129 MappingRecord mergedEntry = MappingMergeUtil.mergeXtrIdMappings(getXtrIdMappingList(xtrIdDao),
130 expiredMappings, sourceRlocs);
131 removeExpiredXtrIdTableEntries(xtrIdDao, expiredMappings);
132 if (mergedEntry == null) {
133 return;
134 }
135 regdate = new Date(mergedEntry.getTimestamp());
136 table.put(eid, new MappingEntry<>(SubKeys.REGDATE, regdate));
137 table.put(eid, new MappingEntry<>(SubKeys.RECORD, mergedEntry));
138 table.put(eid, new MappingEntry<>(SubKeys.SRC_RLOCS, sourceRlocs));
139 } else {
140 table.put(eid, new MappingEntry<>(SubKeys.REGDATE, regdate));
141 table.put(eid, new MappingEntry<>(SubKeys.RECORD, value));
142 }
143 }
144
145
146
147 private Map<String, Object> getDaoEntryBest(Eid eid, ILispDAO dao) {
148 Eid key;
149 if (MaskUtil.isMaskable(eid.getAddress())) {
150 short mask = MaskUtil.getMaskForAddress(eid.getAddress());
151 while (mask > 0) {
152 key = MaskUtil.normalize(eid, mask);
153 mask--;
154 Map<String, Object> entry = dao.get(key);
155 if (entry != null) {
156 return entry;
157 }
158 }
159 return null;
160 } else {
161 key = MaskUtil.normalize(eid);
162 return dao.get(key);
163 }
164 }
165
166
167
168 private SimpleImmutableEntry<Eid, Map<String, ?>> getDaoPairEntryBest(Eid eid, ILispDAO dao) {
169 Eid key;
170 if (MaskUtil.isMaskable(eid.getAddress())) {
171 short mask = MaskUtil.getMaskForAddress(eid.getAddress());
172 while (mask > 0) {
173 key = MaskUtil.normalize(eid, mask);
174 mask--;
175 Map<String, ?> entry = dao.get(key);
176 if (entry != null) {
177 return new SimpleImmutableEntry<Eid, Map<String, ?>>(key, entry);
178 }
179 }
180 return null;
181 } else {
182 key = MaskUtil.normalize(eid);
183 Map<String, ?> entry = dao.get(key);
184 if (entry != null) {
185 return new SimpleImmutableEntry<Eid, Map<String, ?>>(key, entry);
186 } else {
187 return null;
188 }
189 }
190 }
191
192
193 private List<Object> getXtrIdMappingList(ILispDAO dao) {
194 if (dao != null) {
195 final List<Object> records = new ArrayList<Object>();
196 dao.getAll(new IRowVisitor() {
197 public void visitRow(Object keyId, String valueKey, Object value) {
198 if (valueKey.equals(SubKeys.RECORD)) {
199 records.add(value);
200 }
201 }
202 });
203 return records;
204 }
205 return null;
206 }
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 private Object getMappingLpmEid(Eid eid, byte[] xtrId, ILispDAO dao) {
246 SimpleImmutableEntry<Eid, Map<String, ?>> daoEntry = getDaoPairEntryBest(eid, dao);
247 if (daoEntry != null) {
248 if (xtrId != null) {
249 ILispDAO xtrIdTable = getXtrIdTable(eid, (ILispDAO) daoEntry.getValue().get(SubKeys.XTRID_RECORDS));
250 if (xtrIdTable != null) {
251 MappingRecord xtrIdRecord = (MappingRecord) xtrIdTable.getSpecific(xtrId, SubKeys.RECORD);
252 if (xtrIdRecord.getTimestamp() != null &&
253 MappingMergeUtil.timestampIsExpired(xtrIdRecord.getTimestamp())) {
254 xtrIdTable.removeSpecific(xtrId, SubKeys.RECORD);
255 return null;
256 } else {
257 return xtrIdRecord;
258 }
259 } else {
260 return null;
261 }
262 } else {
263 Date timestamp = (Date) daoEntry.getValue().get(SubKeys.REGDATE);
264 if (timestamp != null && MappingMergeUtil.timestampIsExpired(timestamp)) {
265 dao.removeSpecific(daoEntry.getKey(), SubKeys.REGDATE);
266 dao.removeSpecific(daoEntry.getKey(), SubKeys.RECORD);
267 }
268 return daoEntry.getValue().get(SubKeys.RECORD);
269 }
270 } else {
271 return null;
272 }
273 }
274
275 public Object getMapping(Eid srcEid, Eid dstEid, byte[] xtrId) {
276 if (dstEid == null) {
277 return null;
278 }
279
280 ILispDAO table = getVniTable(dstEid);
281 if (table == null) {
282 return null;
283 }
284 return getMappingLpmEid(dstEid, xtrId, table);
285 }
286
287 public Object getMapping(Eid srcEid, Eid dstEid) {
288 return getMapping(srcEid, dstEid, null);
289 }
290
291 public List<Object> getAllXtrIdMappings(Eid eid) {
292 Map<String, ?> daoEntry = getDaoEntryBest(eid, dao);
293 if (daoEntry != null) {
294 ILispDAO xtrIdTable = getXtrIdTable(eid, (ILispDAO) daoEntry.get(SubKeys.XTRID_RECORDS));
295 if (xtrIdTable != null) {
296 return getXtrIdMappingList(xtrIdTable);
297 }
298 }
299 return null;
300 }
301
302 public void removeMapping(Eid eid, boolean overwrite) {
303 Eid key = MaskUtil.normalize(eid);
304 ILispDAO table = getVniTable(key);
305 if (table == null) {
306 return;
307 }
308
309 table.removeSpecific(key, SubKeys.RECORD);
310
311 if (!overwrite) {
312 ILispDAO xtrIdTable = getXtrIdTable(key, table);
313 if (xtrIdTable != null) {
314 xtrIdTable.removeSpecific(key, SubKeys.RECORD);
315 }
316 }
317 }
318
319 public void addAuthenticationKey(Eid eid, MappingAuthkey authKey) {
320 Eid key = MaskUtil.normalize(eid);
321 ILispDAO table = getOrInstantiateVniTable(key);
322 table.put(key, new MappingEntry<>(SubKeys.AUTH_KEY, authKey));
323 }
324
325 private MappingAuthkey getAuthKeyLpm(Eid prefix, ILispDAO db) {
326 short maskLength = MaskUtil.getMaskForAddress(prefix.getAddress());
327 while (maskLength >= 0) {
328 Eid key = MaskUtil.normalize(prefix, maskLength);
329 Object password = db.getSpecific(key, SubKeys.AUTH_KEY);
330 if (password != null && password instanceof MappingAuthkey) {
331 return (MappingAuthkey) password;
332 }
333 maskLength -= 1;
334 }
335 return null;
336 }
337
338 public MappingAuthkey getAuthenticationKey(Eid eid) {
339 ILispDAO table = getVniTable(eid);
340 if (table == null) {
341 return null;
342 }
343 if (eid.getAddress() instanceof Ipv4Prefix || eid.getAddress() instanceof Ipv6Prefix) {
344 return getAuthKeyLpm(eid, table);
345 } else {
346 Eid key = MaskUtil.normalize(eid);
347 Object password = table.getSpecific(key, SubKeys.AUTH_KEY);
348 if (password != null && password instanceof MappingAuthkey) {
349 return (MappingAuthkey) password;
350 } else {
351 LOG.warn("Failed to find password!");
352 return null;
353 }
354 }
355 }
356
357 public void removeAuthenticationKey(Eid eid) {
358 Eid key = MaskUtil.normalize(eid);
359 ILispDAO table = getVniTable(key);
360 if (table == null) {
361 return;
362 }
363 table.removeSpecific(key, SubKeys.AUTH_KEY);
364 }
365
366 public String printMappings() {
367 final StringBuffer sb = new StringBuffer();
368 sb.append("Keys\tValues\n");
369
370 final IRowVisitor innerVisitor = (new IRowVisitor() {
371 String lastKey = "";
372
373 public void visitRow(Object keyId, String valueKey, Object value) {
374 String key = keyId.getClass().getSimpleName() + "#" + keyId;
375 if (!lastKey.equals(key)) {
376 sb.append("\n" + key + "\t");
377 }
378 sb.append(valueKey + "=" + value + "\t");
379 lastKey = key;
380 }
381 });
382
383 dao.getAll(new IRowVisitor() {
384 String lastKey = "";
385
386 public void visitRow(Object keyId, String valueKey, Object value) {
387 String key = keyId.getClass().getSimpleName() + "#" + keyId;
388 if (!lastKey.equals(key)) {
389 sb.append("\n" + key + "\t");
390 }
391 if (valueKey.equals(SubKeys.VNI)) {
392 sb.append(valueKey + "= { ");
393 ((ILispDAO)value).getAll(innerVisitor);
394 sb.append("}\t");
395 } else {
396 sb.append(valueKey + "=" + value + "\t");
397 }
398 lastKey = key;
399 }
400 });
401 sb.append("\n");
402 return sb.toString();
403 }
404
405 @Override
406 public void updateMappingRegistration(Eid eid) {
407 ILispDAO table = getVniTable(eid);
408 if (table == null) {
409 return;
410 }
411 Map<String, Object> daoEntry = getDaoEntryBest(eid, table);
412 if (daoEntry != null) {
413 daoEntry.put(SubKeys.REGDATE, new Date(System.currentTimeMillis()));
414 }
415 }
416
417 @Override
418 public void addData(Eid eid, String subKey, Object data) {
419 Eid key = MaskUtil.normalize(eid);
420 ILispDAO table = getOrInstantiateVniTable(key);
421 table.put(key, new MappingEntry<>(subKey, data));
422 }
423
424 @Override
425 public Object getData(Eid eid, String subKey) {
426 ILispDAO table = getOrInstantiateVniTable(eid);
427 if (table == null) {
428 return null;
429 }
430 Eid key = MaskUtil.normalize(eid);
431 return table.getSpecific(key, subKey);
432 }
433
434 @Override
435 public void removeData(Eid eid, String subKey) {
436 ILispDAO table = getOrInstantiateVniTable(eid);
437 if (table == null) {
438 return;
439 }
440 Eid key = MaskUtil.normalize(eid);
441 table.removeSpecific(key, subKey);
442 }
443 }