1
2
3
4
5
6
7
8
9 package org.opendaylight.lispflowmapping.implementation.lisp;
10
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.Set;
14
15 import org.apache.commons.lang3.exception.ExceptionUtils;
16 import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
17 import org.opendaylight.lispflowmapping.interfaces.dao.SubscriberRLOC;
18 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapRequestResultHandler;
19 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapResolverAsync;
20 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
21 import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
22 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
23 import org.opendaylight.lispflowmapping.lisp.util.SourceDestKeyHelper;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.SimpleAddress;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.SourceDestKeyLcaf;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.Address;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ExplicitLocatorPath;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey;
29 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;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRequest;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItem;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord.Action;
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.mapping.record.list.MappingRecordItem;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItemBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapreplymessage.MapReplyBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRloc;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 import com.google.common.base.Preconditions;
48 import com.google.common.collect.Sets;
49
50 public class MapResolver implements IMapResolverAsync {
51 protected static final Logger LOG = LoggerFactory.getLogger(MapResolver.class);
52
53 private static final int TTL_RLOC_TIMED_OUT = 1;
54 private static final int TTL_NO_RLOC_KNOWN = 15;
55
56 private IMappingService mapService;
57 private boolean subscriptionService;
58 private String elpPolicy;
59 private IMapRequestResultHandler requestHandler;
60 private boolean authenticate = true;
61
62 public MapResolver(IMappingService mapService, boolean smr, String elpPolicy,
63 IMapRequestResultHandler requestHandler) {
64 Preconditions.checkNotNull(mapService);
65 this.subscriptionService = smr;
66 this.mapService = mapService;
67 this.elpPolicy = elpPolicy;
68 this.requestHandler = requestHandler;
69 }
70
71 public void handleMapRequest(MapRequest request) {
72 Eid srcEid = null;
73 if (request.getSourceEid() != null) {
74 srcEid = request.getSourceEid().getEid();
75 }
76 MapReplyBuilder replyBuilder = new MapReplyBuilder();
77 replyBuilder.setEchoNonceEnabled(false);
78 replyBuilder.setProbe(false);
79 replyBuilder.setSecurityEnabled(false);
80 replyBuilder.setNonce(request.getNonce());
81 replyBuilder.setMappingRecordItem(new ArrayList<MappingRecordItem>());
82 for (EidItem eidRecord : request.getEidItem()) {
83 MappingRecord mapping = (MappingRecord) mapService.getMapping(srcEid,
84 eidRecord.getEid());
85 if (mapping != null) {
86 List<ItrRloc> itrRlocs = request.getItrRloc();
87 if (itrRlocs != null && itrRlocs.size() != 0) {
88 if (subscriptionService) {
89 updateSubscribers(itrRlocs.get(0).getRloc(), eidRecord.getEid(), mapping.getEid(), srcEid);
90 }
91 mapping = updateLocators(mapping, itrRlocs);
92 }
93 mapping = fixIfNotSDRequest(mapping, eidRecord.getEid());
94 } else {
95 mapping = getNegativeMapping(eidRecord.getEid());
96 }
97 replyBuilder.getMappingRecordItem().add(new MappingRecordItemBuilder().setMappingRecord(mapping).build());
98 }
99 requestHandler.handleMapReply(replyBuilder.build());
100 }
101
102 private MappingRecord getNegativeMapping(Eid eid) {
103 MappingRecordBuilder recordBuilder = new MappingRecordBuilder();
104 recordBuilder.setAuthoritative(false);
105 recordBuilder.setMapVersion((short) 0);
106 recordBuilder.setEid(eid);
107 recordBuilder.setAction(Action.NativelyForward);
108 if (authenticate && mapService.getAuthenticationKey(eid) != null) {
109 recordBuilder.setRecordTtl(TTL_RLOC_TIMED_OUT);
110 } else {
111 recordBuilder.setRecordTtl(TTL_NO_RLOC_KNOWN);
112 }
113 return recordBuilder.build();
114 }
115
116 private void updateSubscribers(Rloc itrRloc, Eid reqEid, Eid mapEid, Eid srcEid) {
117 SubscriberRLOC subscriberRloc = new SubscriberRLOC(itrRloc, srcEid);
118 Eid subscribedEid = mapEid;
119
120
121
122
123 if (mapEid.getAddressType().equals(SourceDestKeyLcaf.class)
124 && !reqEid.getAddressType().equals(SourceDestKeyLcaf.class)) {
125 subscribedEid = SourceDestKeyHelper.getDst(mapEid);
126 }
127
128 Set<SubscriberRLOC> subscribers = getSubscribers(subscribedEid);
129 if (subscribers == null) {
130 subscribers = Sets.newConcurrentHashSet();
131 } else if (subscribers.contains(subscriberRloc)) {
132
133
134 subscribers.remove(subscriberRloc);
135 }
136 if (LOG.isTraceEnabled()) {
137 LOG.trace("Adding new subscriber: " + LispAddressStringifier.getString(subscriberRloc.getSrcRloc()));
138 }
139 subscribers.add(subscriberRloc);
140 addSubscribers(subscribedEid, subscribers);
141 }
142
143
144 private MappingRecord fixIfNotSDRequest(MappingRecord mapping, Eid dstEid) {
145 if (mapping.getEid().getAddress() instanceof SourceDestKey
146 && !(dstEid.getAddress() instanceof SourceDestKey)) {
147 return new MappingRecordBuilder(mapping).setEid(
148 SourceDestKeyHelper.getDst(mapping.getEid())).build();
149 }
150 return mapping;
151 }
152
153 private boolean locatorsNeedFixing(List<LocatorRecord> locatorRecords) {
154 for (LocatorRecord record : locatorRecords) {
155 if (record.getRloc().getAddress() instanceof ExplicitLocatorPath) {
156 return true;
157 }
158 }
159 return false;
160 }
161
162
163 private MappingRecord updateLocators(MappingRecord mapping, List<ItrRloc> itrRlocs) {
164
165 if (elpPolicy.equalsIgnoreCase("default")) {
166 return mapping;
167 }
168
169 List<LocatorRecord> locatorRecords = mapping.getLocatorRecord();
170
171
172 if (!locatorsNeedFixing(locatorRecords)) {
173 return mapping;
174 }
175
176 MappingRecordBuilder recordBuilder = new MappingRecordBuilder(mapping);
177 recordBuilder.setLocatorRecord(new ArrayList<LocatorRecord>());
178 try {
179 for (LocatorRecord record : locatorRecords) {
180 Rloc container = record.getRloc();
181
182
183
184 if ((!(container.getAddress() instanceof ExplicitLocatorPath))
185 || elpPolicy.equalsIgnoreCase("default") || itrRlocs == null) {
186 recordBuilder.getLocatorRecord().add(
187 new LocatorRecordBuilder().setLocalLocator(record.isLocalLocator())
188 .setRlocProbed(record.isRlocProbed()).setWeight(record.getWeight())
189 .setPriority(record.getPriority()).setMulticastWeight(record.getMulticastWeight())
190 .setMulticastPriority(record.getMulticastPriority()).setRouted(record.isRouted())
191 .setRloc(container).setLocatorId(record.getLocatorId()).build());
192 continue;
193 }
194
195 ExplicitLocatorPath teAddress = ((ExplicitLocatorPath) container.getAddress());
196 SimpleAddress nextHop = getNextELPHop(teAddress, itrRlocs);
197 if (nextHop != null) {
198 java.lang.Short priority = record.getPriority();
199 if (elpPolicy.equalsIgnoreCase("both")) {
200 recordBuilder.getLocatorRecord().add(
201 new LocatorRecordBuilder().setLocalLocator(record.isLocalLocator())
202 .setRlocProbed(record.isRlocProbed()).setWeight(record.getWeight())
203 .setPriority(record.getPriority())
204 .setMulticastWeight(record.getMulticastWeight())
205 .setMulticastPriority(record.getMulticastPriority())
206 .setRouted(record.isRouted()).setRloc(container)
207 .setLocatorId(record.getLocatorId()).build());
208
209
210
211 if (priority != 254 || priority != 255) {
212 priority++;
213 }
214 }
215
216 recordBuilder.getLocatorRecord().add(
217 new LocatorRecordBuilder().setLocalLocator(record.isLocalLocator())
218 .setRlocProbed(record.isRlocProbed()).setWeight(record.getWeight())
219 .setPriority(priority).setMulticastWeight(record.getMulticastWeight())
220 .setMulticastPriority(record.getMulticastPriority()).setRouted(record.isRouted())
221 .setRloc(LispAddressUtil.toRloc(nextHop)).setLocatorId(record.getLocatorId()).build());
222 }
223 }
224 } catch (ClassCastException cce) {
225 LOG.error("Class Cast Exception while building EidToLocatorRecord: {}", ExceptionUtils.getStackTrace(cce));
226 }
227
228 return recordBuilder.build();
229 }
230
231 private SimpleAddress getNextELPHop(ExplicitLocatorPath elp, List<ItrRloc> itrRlocs) {
232 SimpleAddress nextHop = null;
233 List<Hop> hops = elp.getExplicitLocatorPath().getHop();
234
235 if (hops != null && hops.size() > 0) {
236
237 nextHop = hops.get(0).getAddress();
238 for (Hop hop : hops) {
239 Address hopAddress = LispAddressUtil.addressFromSimpleAddress(hop.getAddress());
240 for (ItrRloc itrRloc : itrRlocs) {
241 if (itrRloc.getRloc().getAddress().equals(hopAddress)) {
242 int i = hops.indexOf(hop);
243 if (i < hops.size() - 1) {
244 nextHop = hops.get(i + 1).getAddress();
245 return nextHop;
246 }
247 }
248 }
249 }
250 }
251
252 return nextHop;
253 }
254
255 @SuppressWarnings("unchecked")
256 private Set<SubscriberRLOC> getSubscribers(Eid address) {
257 return (Set<SubscriberRLOC>) mapService.getData(MappingOrigin.Southbound, address, SubKeys.SUBSCRIBERS);
258 }
259
260 private void addSubscribers(Eid address, Set<SubscriberRLOC> subscribers) {
261 mapService.addData(MappingOrigin.Southbound, address, SubKeys.SUBSCRIBERS, subscribers);
262 }
263
264 @Override
265 public void setSubscriptionService(boolean smr) {
266 subscriptionService = smr;
267 }
268
269 @Override
270 public void setElpPolicy(String elpPolicy) {
271 this.elpPolicy = elpPolicy;
272 }
273
274 @Override
275 public void setShouldAuthenticate(boolean shouldAuthenticate) {
276 this.authenticate = shouldAuthenticate;
277 }
278 }