1
2
3
4
5
6
7
8
9 package org.opendaylight.lispflowmapping.implementation;
10
11 import java.util.ArrayList;
12 import java.util.EnumMap;
13 import java.util.List;
14
15 import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
16 import org.opendaylight.lispflowmapping.implementation.mapcache.FlatMapCache;
17 import org.opendaylight.lispflowmapping.implementation.mapcache.MultiTableMapCache;
18 import org.opendaylight.lispflowmapping.implementation.mapcache.SimpleMapCache;
19 import org.opendaylight.lispflowmapping.implementation.mdsal.DataStoreBackEnd;
20 import org.opendaylight.lispflowmapping.implementation.util.DSBEInputUtil;
21 import org.opendaylight.lispflowmapping.implementation.util.MappingMergeUtil;
22 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
23 import org.opendaylight.lispflowmapping.interfaces.mapcache.IMapCache;
24 import org.opendaylight.lispflowmapping.interfaces.mapcache.IMappingSystem;
25 import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
26 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.SimpleAddress;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ExplicitLocatorPath;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ServicePath;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.explicit.locator.path.explicit.locator.path.Hop;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.SiteId;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.AuthenticationKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.Mapping;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.authkey.container.MappingAuthkey;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47
48
49
50
51
52
53
54 public class MappingSystem implements IMappingSystem {
55 private final static Logger LOG = LoggerFactory.getLogger(MappingSystem.class);
56 private boolean iterateMask;
57 private boolean notificationService;
58 private boolean overwrite;
59 private ILispDAO dao;
60 private IMapCache smc;
61 private IMapCache pmc;
62 private final EnumMap<MappingOrigin, IMapCache> tableMap = new EnumMap<>(MappingOrigin.class);
63 private DataStoreBackEnd dsbe;
64
65 public MappingSystem(ILispDAO dao, boolean iterateMask, boolean notifications, boolean overwrite) {
66 this.dao = dao;
67 this.iterateMask = iterateMask;
68 this.notificationService = notifications;
69 this.overwrite = overwrite;
70 buildMapCaches();
71 }
72
73 public void setDataStoreBackEnd(DataStoreBackEnd dsbe) {
74 this.dsbe = dsbe;
75 }
76
77 @Override
78 public void setOverwritePolicy(boolean overwrite) {
79 this.overwrite = overwrite;
80 }
81
82 @Override
83 public void setIterateMask(boolean iterate) {
84 this.iterateMask = iterate;
85 if (smc != null || pmc != null) {
86 buildMapCaches();
87 }
88 }
89
90 public void initialize() {
91 restoreDaoFromDatastore();
92 }
93
94 private void buildMapCaches() {
95
96
97
98
99 if (iterateMask) {
100 smc = new SimpleMapCache(dao.putTable(MappingOrigin.Southbound.toString()));
101 pmc = new MultiTableMapCache(dao.putTable(MappingOrigin.Northbound.toString()));
102 } else {
103 smc = new FlatMapCache(dao.putTable(MappingOrigin.Southbound.toString()));
104 pmc = new FlatMapCache(dao.putTable(MappingOrigin.Northbound.toString()));
105 }
106 tableMap.put(MappingOrigin.Northbound, pmc);
107 tableMap.put(MappingOrigin.Southbound, smc);
108 }
109
110 public void addMapping(MappingOrigin origin, Eid key, Object value) {
111 tableMap.get(origin).addMapping(key, value, origin == MappingOrigin.Southbound ? overwrite : true);
112 }
113
114 public void updateMappingRegistration(MappingOrigin origin, Eid key) {
115 tableMap.get(origin).updateMappingRegistration(key);
116 }
117
118 private MappingRecord updateServicePathMappingRecord(MappingRecord mapping, Eid eid) {
119
120 MappingRecordBuilder recordBuilder = new MappingRecordBuilder(mapping);
121 recordBuilder.setLocatorRecord(new ArrayList<LocatorRecord>());
122
123
124 if (mapping.getLocatorRecord().size() != 1) {
125 LOG.warn("MappingRecord associated to ServicePath EID has more than one locator!");
126 return mapping;
127 }
128
129 LocatorRecord locatorRecord = mapping.getLocatorRecord().get(0);
130 long serviceIndex = ((ServicePath) eid.getAddress()).getServicePath().getServiceIndex();
131 int index = LispAddressUtil.STARTING_SERVICE_INDEX - (int) serviceIndex;
132 Rloc rloc = locatorRecord.getRloc();
133 if (rloc.getAddress() instanceof Ipv4 || rloc.getAddress() instanceof Ipv6) {
134 if (index != 0) {
135 LOG.warn("Service Index should be 255 for simple IP RLOCs!");
136 }
137 return mapping;
138 } else if (rloc.getAddress() instanceof ExplicitLocatorPath) {
139 ExplicitLocatorPath elp = (ExplicitLocatorPath) rloc.getAddress();
140 List<Hop> hops = elp.getExplicitLocatorPath().getHop();
141
142 if (index < 0 || index > hops.size()) {
143 LOG.warn("Service Index out of bounds!");
144 return mapping;
145 }
146
147 SimpleAddress nextHop = hops.get(index).getAddress();
148 LocatorRecordBuilder lrb = new LocatorRecordBuilder(locatorRecord);
149 lrb.setRloc(LispAddressUtil.toRloc(nextHop));
150 recordBuilder.getLocatorRecord().add(lrb.build());
151 return recordBuilder.build();
152 } else {
153 LOG.warn("Nothing to do with ServicePath mapping record");
154 return mapping;
155 }
156 }
157
158 @Override
159 public Object getMapping(Eid src, Eid dst) {
160
161
162
163 if (ConfigIni.getInstance().getLookupPolicy() == ConfigIni.NB_AND_SB) {
164 return getMappingNbSbIntersection(src, dst);
165 } else {
166 return getMappingNbFirst(src, dst);
167 }
168 }
169
170 private Object getMappingNbFirst(Eid src, Eid dst) {
171
172
173
174
175 Object nbMapping = pmc.getMapping(src, dst);
176
177 if (nbMapping == null) {
178 return getSbMappingWithExpiration(src, dst);
179 }
180 if (dst.getAddress() instanceof ServicePath) {
181 return updateServicePathMappingRecord((MappingRecord) nbMapping, dst);
182 }
183 return nbMapping;
184 }
185
186 private Object getMappingNbSbIntersection(Eid src, Eid dst) {
187
188
189
190 Object nbMapping = pmc.getMapping(src, dst);
191 if (nbMapping == null) {
192 return nbMapping;
193 }
194
195 if (dst.getAddress() instanceof ServicePath) {
196 return updateServicePathMappingRecord((MappingRecord)nbMapping, dst);
197 }
198 Object sbMapping = getSbMappingWithExpiration(src, dst);
199 if (sbMapping == null) {
200 return nbMapping;
201 }
202
203 return MappingMergeUtil.computeNbSbIntersection((MappingRecord)nbMapping, (MappingRecord)sbMapping);
204 }
205
206 private Object getSbMappingWithExpiration(Eid src, Eid dst) {
207 Object mappingObject = smc.getMapping(src, dst);
208 if (mappingObject instanceof MappingRecord) {
209 MappingRecord mapping = (MappingRecord) mappingObject;
210 if (MappingMergeUtil.mappingIsExpired(mapping)) {
211 dsbe.removeMapping(DSBEInputUtil.toMapping(MappingOrigin.Southbound, mapping.getEid(),
212 new SiteId(mapping.getSiteId()), mapping));
213 return null;
214 }
215 }
216 return mappingObject;
217 }
218
219 @Override
220 public Object getMapping(Eid dst) {
221 return getMapping((Eid)null, dst);
222 }
223
224 @Override
225 public Object getMapping(MappingOrigin origin, Eid key) {
226 if (origin.equals(MappingOrigin.Southbound)) {
227 return getSbMappingWithExpiration(null, key);
228 }
229 return tableMap.get(origin).getMapping(null, key);
230 }
231
232 @Override
233 public void removeMapping(MappingOrigin origin, Eid key) {
234 tableMap.get(origin).removeMapping(key, origin == MappingOrigin.Southbound ? overwrite : true);
235 if (notificationService) {
236
237 }
238 }
239
240 @Override
241 public void addAuthenticationKey(Eid key, MappingAuthkey authKey) {
242 LOG.debug("Adding authentication key '{}' with key-ID {} for {}", authKey.getKeyString(), authKey.getKeyType(),
243 LispAddressStringifier.getString(key));
244 smc.addAuthenticationKey(key, authKey);
245 }
246
247 @Override
248 public MappingAuthkey getAuthenticationKey(Eid key) {
249 LOG.debug("Retrieving authentication key for {}", LispAddressStringifier.getString(key));
250 return smc.getAuthenticationKey(key);
251 }
252
253 @Override
254 public void removeAuthenticationKey(Eid key) {
255 LOG.debug("Removing authentication key for {}", LispAddressStringifier.getString(key));
256 smc.removeAuthenticationKey(key);
257 }
258
259 @Override
260 public void addData(MappingOrigin origin, Eid key, String subKey, Object data) {
261 LOG.debug("Add data of class {} for key {} and subkey {}", data.getClass(),
262 LispAddressStringifier.getString(key), subKey);
263 tableMap.get(origin).addData(key, subKey, data);
264 }
265
266 @Override
267 public Object getData(MappingOrigin origin, Eid key, String subKey) {
268 LOG.debug("Retrieving data for key {} and subkey {}", LispAddressStringifier.getString(key), subKey);
269 return tableMap.get(origin).getData(key, subKey);
270 }
271
272 @Override
273 public void removeData(MappingOrigin origin, Eid key, String subKey) {
274 LOG.debug("Removing data for key {} and subkey {}", LispAddressStringifier.getString(key), subKey);
275 tableMap.get(origin).removeData(key, subKey);
276 }
277
278
279
280
281
282 private void restoreDaoFromDatastore() {
283 List<Mapping> mappings = dsbe.getAllMappings();
284 List<AuthenticationKey> authKeys = dsbe.getAllAuthenticationKeys();
285
286 LOG.info("Restoring {} mappings and {} keys from datastore into DAO", mappings.size(), authKeys.size());
287
288 int expiredMappings = 0;
289 for (Mapping mapping : mappings) {
290 if (MappingMergeUtil.mappingIsExpired(mapping.getMappingRecord())) {
291 dsbe.removeMapping(mapping);
292 expiredMappings++;
293 continue;
294 }
295 addMapping(mapping.getOrigin(), mapping.getMappingRecord().getEid(), mapping.getMappingRecord());
296 }
297 LOG.info("{} mappings were expired and were not restored", expiredMappings);
298
299 for (AuthenticationKey authKey : authKeys) {
300 addAuthenticationKey(authKey.getEid(), authKey.getMappingAuthkey());
301 }
302 }
303
304 public void destroy() {
305 LOG.info("Mapping System is being destroyed!");
306 }
307
308 @Override
309 public String printMappings() {
310 final StringBuffer sb = new StringBuffer();
311 sb.append("PolicyMapCache\n--------------\n");
312 sb.append(pmc.printMappings());
313 sb.append("SbMapCache\n----------\n");
314 sb.append(smc.printMappings());
315 return sb.toString();
316 }
317
318 public void cleanCaches() {
319 dao.removeAll();
320 buildMapCaches();
321 }
322 }