Checkstyle: fix issues and enforce on implementation
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / util / MappingMergeUtil.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc.  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 package org.opendaylight.lispflowmapping.implementation.util;
9
10 import com.google.common.base.Preconditions;
11 import java.util.ArrayList;
12 import java.util.Date;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16 import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
17 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
18 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
19 import org.opendaylight.lispflowmapping.lisp.util.SourceDestKeyHelper;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.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.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 /**
36  * Utility class to implement merging of locator sets.
37  *
38  * @author Lorand Jakab
39  *
40  */
41 public final class MappingMergeUtil {
42     protected static final Logger LOG = LoggerFactory.getLogger(MappingMergeUtil.class);
43
44     // Utility class, should not be instantiated
45     private MappingMergeUtil() {
46     }
47
48     public static boolean mappingIsExpired(MappingRecord mapping) {
49         Preconditions.checkNotNull(mapping, "mapping should not be null!");
50         if (mapping.getTimestamp() != null) {
51             return timestampIsExpired(mapping.getTimestamp());
52         }
53         return false;
54     }
55
56     public static boolean timestampIsExpired(Date timestamp) {
57         Preconditions.checkNotNull(timestamp, "timestamp should not be null!");
58         return timestampIsExpired(timestamp.getTime());
59     }
60
61     public static boolean timestampIsExpired(Long timestamp) {
62         Preconditions.checkNotNull(timestamp, "timestamp should not be null!");
63         if ((System.currentTimeMillis() - timestamp) > ConfigIni.getInstance().getRegistrationValiditySb() ) {
64             return true;
65         }
66         return false;
67     }
68
69     public static Object computeNbSbIntersection(MappingRecord nbMapping, MappingRecord sbMapping) {
70         // returns a MappingRecord which has the more specific EID, and intersection of locator records.
71         // If locators intersection is empty, original NB mapping is returned.
72         // The intersection is only computed for mappings with maskable EIDs.
73         // Supports both maskable and non-maskable EIDs
74
75         MappingRecordBuilder mrb = new MappingRecordBuilder(nbMapping);
76
77         if (MaskUtil.isMaskable(sbMapping.getEid().getAddress())
78                 && MaskUtil.isMaskable(nbMapping.getEid().getAddress())) {
79
80             short sbMask = MaskUtil.getMaskForAddress(sbMapping.getEid().getAddress());
81             short nbMask = MaskUtil.getMaskForAddress(nbMapping.getEid().getAddress());
82
83             if (nbMapping.getEid().getAddress() instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
84                     .ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey) {
85                 nbMask = SourceDestKeyHelper.getDstMask(nbMapping.getEid());
86                 if ( nbMask < sbMask) {
87                     // We have to create a new SourceDest EID, where the source is same as the
88                     // one in NB record, and dest EID is the more specific from SB mapping record.
89
90                     SourceDestKey srcDstKey = ((org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp
91                             .address.types.rev151105.lisp.address.address.SourceDestKey) nbMapping.getEid()
92                             .getAddress()).getSourceDestKey();
93                     SourceDestKeyBuilder sdb = new SourceDestKeyBuilder(srcDstKey);
94                     sdb.setDest(new SimpleAddress(getIpPrefix(sbMapping.getEid().getAddress())));
95                     mrb.setEid(LispAddressUtil.asSrcDstEid(sdb.build(), nbMapping.getEid().getVirtualNetworkId()));
96                 }
97             } else if (nbMask < sbMask) {
98                 // Both EIDs are IP prefixes. SB mapping is a subprefix so we have to update EID intersection
99                 mrb.setEid(sbMapping.getEid());
100             }
101         }
102         // find and update locators intersection if not empty
103         List<LocatorRecord> commonLocators = getCommonLocatorRecords(nbMapping, sbMapping);
104         if (commonLocators != null && !commonLocators.isEmpty()) {
105             mrb.setLocatorRecord(commonLocators);
106         }
107
108         return mrb.build();
109     }
110
111     private static List<LocatorRecord> getCommonLocatorRecords(MappingRecord nbMapping, MappingRecord sbMapping) {
112         // This method updates the MappingRecord builder with the intersection of the locator records
113         // from the two mappings. NB mapping records fields have precedence, only Priority is updated
114         // from SB mapping if p is 255.
115
116         // Return null when NB is a negative mapping
117         if (nbMapping.getLocatorRecord() == null || nbMapping.getLocatorRecord().isEmpty()) {
118             return null;
119         }
120
121         List<LocatorRecord> sbLocators = sbMapping.getLocatorRecord();
122
123         // We assume locators are unique and don't show up several times (with different or identical p/w/mp/mw),
124         // so we create a HashMap of the locators from the SB mapping record, keyed by the Rloc
125         Map<Rloc, LocatorRecord> sbLocatorMap = new HashMap<Rloc, LocatorRecord>();
126         for (LocatorRecord locator : sbLocators) {
127             sbLocatorMap.put(locator.getRloc(), locator);
128         }
129
130         // Gradually building final list of common locators, in order that they appear in NB Mapping
131         List<LocatorRecord> commonLocators = new ArrayList<LocatorRecord>();
132
133         for (LocatorRecord nbLocator : nbMapping.getLocatorRecord()) {
134             Rloc nbRloc = nbLocator.getRloc();
135             if (sbLocatorMap.containsKey(nbRloc)) {
136                 // common locator found. use the NB record as the common locator.
137
138                 if (sbLocatorMap.get(nbRloc).getPriority() == (short) 255) {
139                     // if SB locator has p == 255 then common locator takes all NB fields except for p
140                     // which must be set to 255
141                     LocatorRecordBuilder lrb = new LocatorRecordBuilder(nbLocator);
142                     lrb.setPriority((short) 255);
143                     commonLocators.add(lrb.build());
144                 } else {
145                     commonLocators.add(nbLocator);
146                 }
147             }
148         }
149         return commonLocators;
150     }
151
152     private static IpPrefix getIpPrefix(Address address) {
153         IpPrefix ipPrefix = null;
154
155         if (address instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns
156                 .yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Prefix) {
157             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp
158                     .address.address.Ipv4Prefix lispPrefix = (org.opendaylight.yang.gen.v1.urn.ietf.params
159                     .xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Prefix) address;
160
161             Ipv4Prefix inetPrefix = new Ipv4Prefix(lispPrefix.getIpv4Prefix());
162             ipPrefix = new IpPrefix(inetPrefix);
163         } else if (address instanceof org.opendaylight.yang.gen.v1.urn.ietf.params
164                 .xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6Prefix) {
165             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp
166                     .address.address.Ipv6Prefix lispPrefix = (org.opendaylight.yang.gen.v1.urn.ietf.params
167                     .xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6Prefix) address;
168
169             Ipv6Prefix inetPrefix = new Ipv6Prefix(lispPrefix.getIpv6Prefix());
170             ipPrefix = new IpPrefix(inetPrefix);
171         } else {
172             LOG.warn("Southbound mapping address is not an IpPrefix");
173         }
174         return ipPrefix;
175     }
176 }