Merge branch 'master' into topic/ietf_yang
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / mapcache / SimpleMapCache.java
1 /*
2  * Copyright (c) 2015 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.implementation.mapcache;
10
11 import java.util.AbstractMap.SimpleImmutableEntry;
12 import java.util.Date;
13 import java.util.Map;
14
15 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
16 import org.opendaylight.lispflowmapping.interfaces.dao.IRowVisitor;
17 import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
18 import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
19 import org.opendaylight.lispflowmapping.interfaces.mapcache.IMapCache;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.LispAddressContainer;
21 import org.opendaylight.lispflowmapping.lisp.util.LispAFIConvertor;
22 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
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  *
32  */
33 public class SimpleMapCache implements IMapCache {
34     private static final Logger LOG = LoggerFactory.getLogger(SimpleMapCache.class);
35     private ILispDAO dao;
36
37     public SimpleMapCache(ILispDAO dao) {
38         this.dao = dao;
39     }
40
41     public void addMapping(LispAddressContainer key, Object value, boolean shouldOverwrite) {
42         LispAddressContainer eid = MaskUtil.normalize(key);
43         dao.put(eid, new MappingEntry<>(SubKeys.REGDATE, new Date(System.currentTimeMillis())));
44         dao.put(eid, new MappingEntry<>(SubKeys.RECORD, value));
45     }
46
47     // Method returns the DAO entry (hash) corresponding to either the longest prefix match of eid, if eid is maskable,
48     // or the exact match otherwise. eid must be a 'simple' address
49     private  Map<String, ?> getDaoEntryBest(LispAddressContainer key, ILispDAO dao) {
50         if (MaskUtil.isMaskable(key)) {
51             LispAddressContainer lookupKey;
52             short mask = MaskUtil.getMaskForAddress(key);
53             while (mask > 0) {
54                 lookupKey = MaskUtil.normalize(key, mask);
55                 mask--;
56                 Map<String, ?> entry = dao.get(lookupKey);
57                 if (entry != null) {
58                     return entry;
59                 }
60             }
61             return null;
62         } else {
63             return dao.get(key);
64         }
65     }
66
67     // Method returns the DAO entry (hash) corresponding to either the longest prefix match of eid, if eid is maskable,
68     // or the exact match otherwise. eid must be a 'simple' address
69     private SimpleImmutableEntry<LispAddressContainer, Map<String, ?>> getDaoPairEntryBest(LispAddressContainer key, ILispDAO dao) {
70         if (MaskUtil.isMaskable(key)) {
71             LispAddressContainer lookupKey;
72             short mask = MaskUtil.getMaskForAddress(key);
73             while (mask > 0) {
74                 lookupKey = MaskUtil.normalize(key, mask);
75                 mask--;
76                 Map<String, ?> entry = dao.get(lookupKey);
77                 if (entry != null) {
78                     return new SimpleImmutableEntry<LispAddressContainer, Map<String, ?>>(lookupKey, entry);
79                 }
80             }
81             return null;
82         } else {
83             Map<String, ?> entry = dao.get(key);
84             if (entry != null) {
85                 return new SimpleImmutableEntry<LispAddressContainer, Map<String, ?>>(key, entry);
86             } else {
87                 return null;
88             }
89         }
90     }
91
92     // Returns the mapping corresponding to the longest prefix match for eid. eid must be a simple (maskable or not)
93     // address
94     private Object getMappingLpmEid(LispAddressContainer eid, ILispDAO dao) {
95         Map<String, ?> daoEntry = getDaoEntryBest(eid, dao);
96         if (daoEntry != null) {
97             return daoEntry.get(SubKeys.RECORD);
98         } else {
99             return null;
100         }
101     }
102
103     // Returns the matched key and mapping corresponding to the longest prefix match for eid. eid must be a simple
104     // (maskable or not) address
105     private SimpleImmutableEntry<LispAddressContainer, Object> getMappingPairLpmEid(LispAddressContainer eid, ILispDAO dao) {
106         SimpleImmutableEntry<LispAddressContainer, Map<String, ?>> daoEntry = getDaoPairEntryBest(eid, dao);
107         if (daoEntry != null) {
108             return new SimpleImmutableEntry<LispAddressContainer, Object>(daoEntry.getKey(), daoEntry.getValue().get(
109                     SubKeys.RECORD));
110         } else {
111             return null;
112         }
113     }
114
115     public Object getMapping(LispAddressContainer srcEid, LispAddressContainer dstEid) {
116         if (dstEid == null) {
117             return null;
118         }
119         return getMappingLpmEid(dstEid, dao);
120     }
121
122     public void removeMapping(LispAddressContainer eid, boolean overwrite) {
123         eid = MaskUtil.normalize(eid);
124         dao.removeSpecific(eid, SubKeys.RECORD);
125     }
126
127     public void addAuthenticationKey(LispAddressContainer eid, String key) {
128         eid = MaskUtil.normalize(eid);
129         dao.put(eid, new MappingEntry<String>(SubKeys.AUTH_KEY, key));
130     }
131
132     private String getAuthKeyLpm(LispAddressContainer prefix, ILispDAO db) {
133         short maskLength = MaskUtil.getMaskForAddress(prefix);
134         while (maskLength >= 0) {
135             LispAddressContainer key = MaskUtil.normalize(prefix, maskLength);
136             Object password = db.getSpecific(key, SubKeys.AUTH_KEY);
137             if (password != null && password instanceof String) {
138                 return (String) password;
139             }
140             maskLength -= 1;
141         }
142         return null;
143     }
144
145     public String getAuthenticationKey(LispAddressContainer eid) {
146         if (MaskUtil.isMaskable(LispAFIConvertor.toAFI(eid))) {
147             return getAuthKeyLpm(eid, dao);
148         } else {
149             Object password = dao.getSpecific(eid, SubKeys.AUTH_KEY);
150             if (password != null && password instanceof String) {
151                 return (String) password;
152             } else {
153                 LOG.warn("Failed to find password!");
154                 return null;
155             }
156         }
157     }
158
159     public void removeAuthenticationKey(LispAddressContainer eid) {
160         eid = MaskUtil.normalize(eid);
161         dao.removeSpecific(eid, SubKeys.AUTH_KEY);
162     }
163
164     public String printMappings() {
165         final StringBuffer sb = new StringBuffer();
166         sb.append("Keys\tValues\n");
167         dao.getAll(new IRowVisitor() {
168             String lastKey = "";
169
170             public void visitRow(Object keyId, String valueKey, Object value) {
171                 String key = keyId.getClass().getSimpleName() + "#" + keyId;
172                 if (!lastKey.equals(key)) {
173                     sb.append("\n" + key + "\t");
174                 }
175                 sb.append(valueKey + "=" + value + "\t");
176                 lastKey = key;
177             }
178         });
179         sb.append("\n");
180         return sb.toString();
181     }
182
183     @Override
184     public void updateMappingRegistration(LispAddressContainer key) {
185         Map<String, ?> daoEntry = getDaoEntryBest(key, dao);
186         if (daoEntry != null) {
187             dao.put(key, new MappingEntry<>(SubKeys.REGDATE, new Date(System.currentTimeMillis())));
188         }
189     }
190
191     @Override
192     public void addData(LispAddressContainer key, String subKey, Object data) {
193         LispAddressContainer normKey = MaskUtil.normalize(key);
194         dao.put(normKey, new MappingEntry<>(subKey, data));
195     }
196
197     @Override
198     public Object getData(LispAddressContainer key, String subKey) {
199         return dao.getSpecific(key, subKey);
200     }
201
202     @Override
203     public void removeData(LispAddressContainer key, String subKey) {
204         dao.removeSpecific(key, subKey);
205     }
206 }