Merge "Provide Karaf 4 features"
[lispflowmapping.git] / mappingservice / mapcache / src / main / java / org / opendaylight / lispflowmapping / mapcache / SimpleMapCache.java
1 /*
2  * Copyright (c) 2015, 2017 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.lispflowmapping.mapcache;
10
11 import java.util.AbstractMap.SimpleImmutableEntry;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
17 import org.opendaylight.lispflowmapping.interfaces.dao.IRowVisitor;
18 import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
19 import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
20 import org.opendaylight.lispflowmapping.interfaces.mapcache.ILispMapCache;
21 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.inet.binary.types.rev160303.IpAddressBinary;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
25
26 /**
27  * Simple map-cache that works with 'simple' addresses (see lisp-proto.yang). It can do longest prefix matching for IP
28  * addresses.
29  *
30  * @author Florin Coras
31  * @author Lorand Jakab
32  *
33  */
34 public class SimpleMapCache implements ILispMapCache {
35     private ILispDAO dao;
36
37     public SimpleMapCache(ILispDAO dao) {
38         this.dao = dao;
39     }
40
41     private ILispDAO getVniTable(Eid eid) {
42         long vni = 0;
43         if (eid.getVirtualNetworkId() == null) {
44             vni = 0;
45         } else {
46             vni = eid.getVirtualNetworkId().getValue();
47         }
48         return (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
49     }
50
51     private ILispDAO getOrInstantiateVniTable(Eid eid) {
52         long vni = 0;
53         if (eid.getVirtualNetworkId() == null) {
54             vni = 0;
55         } else {
56             vni = eid.getVirtualNetworkId().getValue();
57         }
58         ILispDAO table = (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
59         if (table == null) {
60             table = dao.putNestedTable(vni, SubKeys.VNI);
61         }
62         return table;
63     }
64
65     private ILispDAO getOrInstantiateXtrIdTable(Eid eid, ILispDAO dao) {
66         ILispDAO table = (ILispDAO) dao.getSpecific(eid, SubKeys.XTRID_RECORDS);
67         if (table == null) {
68             table = dao.putNestedTable(eid, SubKeys.XTRID_RECORDS);
69         }
70         return table;
71     }
72
73     @Override
74     public void addMapping(Eid key, Object value) {
75         addMapping(key, value, null);
76     }
77
78     @Override
79     public void addMapping(Eid key, Object value, Set<IpAddressBinary> sourceRlocs) {
80         Eid eid = MaskUtil.normalize(key);
81         ILispDAO table = getOrInstantiateVniTable(key);
82         table.put(eid, new MappingEntry<>(SubKeys.RECORD, value));
83         if (sourceRlocs != null) {
84             table.put(eid, new MappingEntry<>(SubKeys.SRC_RLOCS, sourceRlocs));
85         }
86     }
87
88     @Override
89     public void addMapping(Eid key, XtrId xtrId, Object value) {
90         Eid eid = MaskUtil.normalize(key);
91         ILispDAO table = getOrInstantiateVniTable(key);
92         ILispDAO xtrIdDao = getOrInstantiateXtrIdTable(eid, table);
93         xtrIdDao.put(xtrId, new MappingEntry<>(SubKeys.RECORD, value));
94     }
95
96     // Returns the mapping corresponding to the longest prefix match for eid. eid must be a simple (maskable or not)
97     // address
98     private Object getMappingLpmEid(Eid eid, XtrId xtrId, ILispDAO dao) {
99         SimpleImmutableEntry<Eid, Map<String, ?>> daoEntry = dao.getBestPair(MaskUtil.normalize(eid));
100         if (daoEntry != null) {
101             if (xtrId != null) {
102                 ILispDAO xtrIdTable = (ILispDAO) daoEntry.getValue().get(SubKeys.XTRID_RECORDS);
103                 if (xtrIdTable != null) {
104                     return xtrIdTable.getSpecific(xtrId, SubKeys.RECORD);
105                 }
106             } else {
107                 return daoEntry.getValue().get(SubKeys.RECORD);
108             }
109         }
110         return null;
111     }
112
113     @Override
114     public Object getMapping(Eid srcEid, Eid dstEid) {
115         final XtrId xtrId = null;
116         return getMapping(dstEid, xtrId);
117     }
118
119     @Override
120     public Object getMapping(Eid eid, XtrId xtrId) {
121         if (eid == null) {
122             return null;
123         }
124
125         ILispDAO table = getVniTable(eid);
126         if (table == null) {
127             return null;
128         }
129         return getMappingLpmEid(eid, xtrId, table);
130     }
131
132     // Returns the list of mappings stored in an xTR-ID DAO
133     private List<Object> getXtrIdMappingList(ILispDAO dao) {
134         if (dao != null) {
135             final List<Object> records = new ArrayList<>();
136             dao.getAll(new IRowVisitor() {
137                 public void visitRow(Object keyId, String valueKey, Object value) {
138                     if (valueKey.equals(SubKeys.RECORD)) {
139                         records.add(value);
140                     }
141                 }
142             });
143             return records;
144         }
145         return null;
146     }
147
148     @Override
149     public List<Object> getAllXtrIdMappings(Eid eid) {
150         ILispDAO table = getVniTable(eid);
151         if (table == null) {
152             return null;
153         }
154         Map<String, ?> daoEntry = table.getBest(MaskUtil.normalize(eid));
155         if (daoEntry != null) {
156             ILispDAO xtrIdTable = (ILispDAO) daoEntry.get(SubKeys.XTRID_RECORDS);
157             if (xtrIdTable != null) {
158                 return getXtrIdMappingList(xtrIdTable);
159             }
160         }
161         return null;
162     }
163
164     public Eid getWidestNegativeMapping(Eid eid) {
165         ILispDAO table = getVniTable(eid);
166         if (table == null) {
167             return null;
168         }
169         return table.getWidestNegativePrefix(MaskUtil.normalize(eid));
170     }
171
172     @Override
173     public Eid getParentPrefix(Eid eid) {
174         ILispDAO table = getVniTable(eid);
175         if (table == null) {
176             return null;
177         }
178         return table.getParentPrefix(MaskUtil.normalize(eid));
179     }
180
181     @Override
182     public Eid getSiblingPrefix(Eid eid) {
183         ILispDAO table = getVniTable(eid);
184         if (table == null) {
185             return null;
186         }
187         return table.getSiblingPrefix(MaskUtil.normalize(eid));
188     }
189
190     @Override
191     public Eid getVirtualParentSiblingPrefix(Eid eid) {
192         ILispDAO table = getVniTable(eid);
193         if (table == null) {
194             return null;
195         }
196         return table.getVirtualParentSiblingPrefix(MaskUtil.normalize(eid));
197     }
198
199     @Override
200     public void removeMapping(Eid eid) {
201         ILispDAO table = getVniTable(eid);
202         if (table == null) {
203             return;
204         }
205
206         Eid key = MaskUtil.normalize(eid);
207         // We intentionally don't remove subscribers, so in case a mapping is re-added, they get notified
208         table.removeSpecific(key, SubKeys.RECORD);
209         table.removeSpecific(key, SubKeys.SRC_RLOCS);
210         table.removeSpecific(key, SubKeys.XTRID_RECORDS);
211         table.removeSpecific(key, SubKeys.TIME_BUCKET_ID);
212     }
213
214     @Override
215     public void removeMapping(Eid eid, XtrId xtrId) {
216         ILispDAO table = getVniTable(eid);
217         if (table == null) {
218             return;
219         }
220         Eid key = MaskUtil.normalize(eid);
221         ILispDAO xtrIdTable = (ILispDAO) table.getSpecific(key, SubKeys.XTRID_RECORDS);
222         if (xtrIdTable == null) {
223             return;
224         }
225         xtrIdTable.removeSpecific(xtrId, SubKeys.RECORD);
226     }
227
228     @Override
229     public void removeXtrIdMappings(Eid eid, List<XtrId> xtrIds) {
230         ILispDAO table = getVniTable(eid);
231         if (table == null) {
232             return;
233         }
234         Eid key = MaskUtil.normalize(eid);
235         ILispDAO xtrIdTable = (ILispDAO) table.getSpecific(key, SubKeys.XTRID_RECORDS);
236         if (xtrIdTable == null) {
237             return;
238         }
239         for (XtrId xtrId : xtrIds) {
240             xtrIdTable.removeSpecific(xtrId, SubKeys.RECORD);
241         }
242     }
243
244     @Override
245     public void addData(Eid eid, String subKey, Object data) {
246         ILispDAO table = getOrInstantiateVniTable(eid);
247         Eid key = MaskUtil.normalize(eid);
248         table.put(key, new MappingEntry<>(subKey, data));
249     }
250
251     @Override
252     public Object getData(Eid eid, String subKey) {
253         ILispDAO table = getOrInstantiateVniTable(eid);
254         if (table == null) {
255             return null;
256         }
257         Eid key = MaskUtil.normalize(eid);
258         return table.getSpecific(key, subKey);
259     }
260
261     @Override
262     public void removeData(Eid eid, String subKey) {
263         ILispDAO table = getOrInstantiateVniTable(eid);
264         if (table == null) {
265             return;
266         }
267         Eid key = MaskUtil.normalize(eid);
268         table.removeSpecific(key, subKey);
269     }
270
271     @Override
272     public String printMappings() {
273         final StringBuffer sb = new StringBuffer();
274         sb.append("Keys\tValues\n");
275
276         final IRowVisitor innerVisitor = (new IRowVisitor() {
277             String lastKey = "";
278
279             public void visitRow(Object keyId, String valueKey, Object value) {
280                 String key = keyId.getClass().getSimpleName() + "#" + keyId;
281                 if (!lastKey.equals(key)) {
282                     sb.append("\n" + key + "\t");
283                 }
284                 sb.append(valueKey + "=" + value + "\t");
285                 lastKey = key;
286             }
287         });
288
289         dao.getAll(new IRowVisitor() {
290             String lastKey = "";
291
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");
296                 }
297                 if (valueKey.equals(SubKeys.VNI)) {
298                     sb.append(valueKey + "= { ");
299                     ((ILispDAO)value).getAll(innerVisitor);
300                     sb.append("}\t");
301                 } else {
302                     sb.append(valueKey + "=" + value + "\t");
303                 }
304                 lastKey = key;
305             }
306         });
307         sb.append("\n");
308         return sb.toString();
309     }
310 }