1
2
3
4
5
6
7
8 package org.opendaylight.lispflowmapping.implementation.util;
9
10 import java.net.InetAddress;
11 import java.util.ArrayList;
12 import java.util.Date;
13 import java.util.LinkedHashMap;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.SimpleAddress;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.Address;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.source.dest.key.SourceDestKey;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.source.dest.key.SourceDestKeyBuilder;
27 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
28 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
29 import org.opendaylight.lispflowmapping.lisp.util.SourceDestKeyHelper;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
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.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 import com.google.common.base.Preconditions;
39
40
41
42
43
44
45
46 public final class MappingMergeUtil {
47 protected static final Logger LOG = LoggerFactory.getLogger(MappingMergeUtil.class);
48
49 private static final long REGISTRATION_VALIDITY = 200000L;
50
51
52 private MappingMergeUtil() {
53 }
54
55 private static void mergeCommonMappingRecordFields(MappingRecordBuilder mrb, MappingRecord record) {
56
57 mrb.setXtrId(record.getXtrId());
58 mrb.setSiteId(record.getSiteId());
59
60 mrb.setRecordTtl(Math.min(mrb.getRecordTtl(), record.getRecordTtl()));
61 if (!mrb.getAction().equals(record.getAction())) {
62 LOG.warn("Mapping merge operation: actions are different, which one is used is undefined");
63 }
64 if (mrb.isAuthoritative() != record.isAuthoritative()) {
65 LOG.warn("Mapping merge operation: authoritative status is different, which one is used is undefined");
66 }
67 if (!mrb.getEid().equals(record.getEid())) {
68 LOG.warn("Mapping merge operation: EID records are different, which one is used is undefined");
69 }
70 }
71
72 private static LocatorRecord mergeLocators(LocatorRecord existingLocator, LocatorRecord newLocator) {
73 if (existingLocator.isLocalLocator()) {
74 return existingLocator;
75 }
76 return newLocator;
77 }
78
79 private static int compareLocators(LocatorRecord a, LocatorRecord b) {
80 InetAddress aInet = LispAddressUtil.ipAddressToInet(a.getRloc().getAddress());
81 InetAddress bInet = LispAddressUtil.ipAddressToInet(b.getRloc().getAddress());
82 return LispAddressUtil.compareInetAddresses(aInet, bInet);
83 }
84
85 private static void mergeLocatorRecords(MappingRecordBuilder mrb, MappingRecord newRecord) {
86 List<LocatorRecord> locators = mrb.getLocatorRecord();
87
88
89
90
91 Map<Rloc, LocatorRecord> locatorMap = new LinkedHashMap<Rloc, LocatorRecord>();
92
93
94 List<LocatorRecord> newLocatorList = new ArrayList<LocatorRecord>();
95
96 for (LocatorRecord locator : locators) {
97 locatorMap.put(locator.getRloc(), locator);
98 }
99 for (LocatorRecord newLocator : newRecord.getLocatorRecord()) {
100 Rloc newRloc = newLocator.getRloc();
101 if (locatorMap.containsKey(newRloc)) {
102
103 if (locatorMap.get(newRloc).equals(newLocator)) {
104 continue;
105 } else {
106 LocatorRecord mergedLocator = mergeLocators(locatorMap.get(newRloc), newLocator);
107 newLocatorList.add(mergedLocator);
108 }
109 } else {
110
111 newLocatorList.add(newLocator);
112 }
113 }
114
115
116 if (newLocatorList.size() != 0) {
117 List<LocatorRecord> mergedLocators = new ArrayList<LocatorRecord>();
118
119 int mlIt = 0, lIt = 0;
120 while (mlIt < newLocatorList.size() && lIt < locators.size()) {
121 int cmp = compareLocators(locators.get(lIt), newLocatorList.get(mlIt));
122 if (cmp < 0) {
123 mergedLocators.add(locators.get(lIt));
124 lIt++;
125 } else if (cmp > 0) {
126 mergedLocators.add(newLocatorList.get(mlIt));
127 mlIt++;
128 } else {
129
130 mergedLocators.add(newLocatorList.get(mlIt));
131 mlIt++;
132 lIt++;
133 }
134 }
135 while (lIt < locators.size()) {
136 mergedLocators.add(locators.get(lIt));
137 lIt++;
138 }
139 while (mlIt < newLocatorList.size()) {
140 mergedLocators.add(newLocatorList.get(mlIt));
141 mlIt++;
142 }
143 mrb.setLocatorRecord(mergedLocators);
144 }
145 }
146
147 public static MappingRecord mergeMappings(MappingRecord currentMergedMapping, MappingRecord newMapping,
148 byte[] xtrId, Date regdate) {
149 if (currentMergedMapping == null) {
150 return newMapping;
151 }
152
153 MappingRecordBuilder mrb = new MappingRecordBuilder(currentMergedMapping);
154 mergeCommonMappingRecordFields(mrb, newMapping);
155 mergeLocatorRecords(mrb, newMapping);
156
157 if (xtrId != null) {
158 mrb.setXtrId(xtrId);
159 mrb.setTimestamp(regdate.getTime());
160 }
161
162 return mrb.build();
163 }
164
165 public static MappingRecord mergeXtrIdMappings(List<Object> records, List<byte[]> expiredMappings,
166 Set<IpAddress> sourceRlocs) {
167 MappingRecordBuilder mrb = null;
168 byte[] xtrId = {};
169 Long timestamp = Long.MAX_VALUE;
170
171 for (int i = 0; i < records.size(); i++) {
172 MappingRecord record = (MappingRecord) records.get(i);
173
174
175 if (timestampIsExpired(record.getTimestamp())) {
176 expiredMappings.add(record.getXtrId());
177 continue;
178 }
179
180 if (mrb == null) {
181 mrb = new MappingRecordBuilder((MappingRecord) records.get(i));
182 }
183
184
185 if (record.getTimestamp() < timestamp) {
186 timestamp = record.getTimestamp();
187 xtrId = record.getXtrId();
188 }
189
190
191 mergeCommonMappingRecordFields(mrb, record);
192 mergeLocatorRecords(mrb, record);
193
194
195 sourceRlocs.add(record.getSourceRloc());
196 }
197
198 if (mrb == null) {
199 LOG.warn("All mappings expired when merging! Unexpected!");
200 return null;
201 }
202 mrb.setXtrId(xtrId);
203 mrb.setTimestamp(timestamp);
204
205 return mrb.build();
206 }
207
208 public static boolean mappingIsExpired(MappingRecord mapping) {
209 Preconditions.checkNotNull(mapping, "mapping should not be null!");
210 if (mapping.getTimestamp() != null) {
211 return timestampIsExpired(mapping.getTimestamp());
212 }
213 return false;
214 }
215
216 public static boolean timestampIsExpired(Date timestamp) {
217 Preconditions.checkNotNull(timestamp, "timestamp should not be null!");
218 return timestampIsExpired(timestamp.getTime());
219 }
220
221 public static boolean timestampIsExpired(Long timestamp) {
222 Preconditions.checkNotNull(timestamp, "timestamp should not be null!");
223 if ((System.currentTimeMillis() - timestamp) > REGISTRATION_VALIDITY) {
224 return true;
225 }
226 return false;
227 }
228
229 public static Object computeNbSbIntersection(MappingRecord nbMapping, MappingRecord sbMapping) {
230
231
232
233
234
235 MappingRecordBuilder mrb = new MappingRecordBuilder(nbMapping);
236
237 if (MaskUtil.isMaskable(sbMapping.getEid().getAddress())
238 && MaskUtil.isMaskable(nbMapping.getEid().getAddress())) {
239
240 short sbMask = MaskUtil.getMaskForAddress(sbMapping.getEid().getAddress());
241 short nbMask = MaskUtil.getMaskForAddress(nbMapping.getEid().getAddress());
242
243 if (nbMapping.getEid().getAddress() instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
244 .ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey) {
245 nbMask = SourceDestKeyHelper.getDstMask(nbMapping.getEid());
246 if ( nbMask < sbMask) {
247
248
249
250 SourceDestKey srcDstKey = ((org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp
251 .address.types.rev151105.lisp.address.address.SourceDestKey) nbMapping.getEid()
252 .getAddress()).getSourceDestKey();
253 SourceDestKeyBuilder sdb = new SourceDestKeyBuilder(srcDstKey);
254 sdb.setDest(new SimpleAddress(getIpPrefix(sbMapping.getEid().getAddress())));
255 mrb.setEid(LispAddressUtil.asSrcDstEid(sdb.build(), nbMapping.getEid().getVirtualNetworkId()));
256 }
257 } else if (nbMask < sbMask) {
258
259 mrb.setEid(sbMapping.getEid());
260 mrb.setMaskLength(sbMask);
261 }
262 }
263
264 List<LocatorRecord> commonLocators = getCommonLocatorRecords(nbMapping, sbMapping);
265 if (commonLocators != null && !commonLocators.isEmpty()) {
266 mrb.setLocatorRecord(commonLocators);
267 }
268
269 return mrb.build();
270 }
271
272 private static List<LocatorRecord> getCommonLocatorRecords(MappingRecord nbMapping, MappingRecord sbMapping) {
273
274
275
276
277
278 if (nbMapping.getLocatorRecord() == null || nbMapping.getLocatorRecord().isEmpty()) {
279 return null;
280 }
281
282 List<LocatorRecord> sbLocators = sbMapping.getLocatorRecord();
283
284
285
286 Map<Rloc, LocatorRecord> sbLocatorMap = new HashMap<Rloc, LocatorRecord>();
287 for (LocatorRecord locator : sbLocators) {
288 sbLocatorMap.put(locator.getRloc(), locator);
289 }
290
291
292 List<LocatorRecord> commonLocators = new ArrayList<LocatorRecord>();
293
294 for (LocatorRecord nbLocator : nbMapping.getLocatorRecord()) {
295 Rloc nbRloc = nbLocator.getRloc();
296 if (sbLocatorMap.containsKey(nbRloc)) {
297
298
299 if (sbLocatorMap.get(nbRloc).getPriority() == (short) 255) {
300
301
302 LocatorRecordBuilder lrb = new LocatorRecordBuilder(nbLocator);
303 lrb.setPriority((short) 255);
304 commonLocators.add(lrb.build());
305 } else {
306 commonLocators.add(nbLocator);
307 }
308 }
309 }
310 return commonLocators;
311 }
312
313 private static IpPrefix getIpPrefix(Address address) {
314 IpPrefix ipPrefix = null;
315
316 if (address instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns
317 .yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Prefix) {
318 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp
319 .address.address.Ipv4Prefix lispPrefix = (org.opendaylight.yang.gen.v1.urn.ietf.params
320 .xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Prefix) address;
321
322 Ipv4Prefix inetPrefix = new Ipv4Prefix(lispPrefix.getIpv4Prefix());
323 ipPrefix = new IpPrefix(inetPrefix);
324 } else if (address instanceof org.opendaylight.yang.gen.v1.urn.ietf.params
325 .xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6Prefix) {
326 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp
327 .address.address.Ipv6Prefix lispPrefix = (org.opendaylight.yang.gen.v1.urn.ietf.params
328 .xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6Prefix) address;
329
330 Ipv6Prefix inetPrefix = new Ipv6Prefix(lispPrefix.getIpv6Prefix());
331 ipPrefix = new IpPrefix(inetPrefix);
332 } else {
333 LOG.warn("Southbound mapping address is not an IpPrefix");
334 }
335 return ipPrefix;
336 }
337 }