2 * Copyright (c) 2014 Contextream, Inc. and others. All rights reserved.
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
9 package org.opendaylight.lispflowmapping.implementation.lisp;
11 import java.util.ArrayList;
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Map.Entry;
16 import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
17 import org.opendaylight.lispflowmapping.implementation.dao.MappingServiceKeyUtil;
18 import org.opendaylight.lispflowmapping.implementation.util.DAOMappingUtil;
19 import org.opendaylight.lispflowmapping.implementation.util.LispAFIConvertor;
20 import org.opendaylight.lispflowmapping.implementation.util.LispAddressStringifier;
21 import org.opendaylight.lispflowmapping.implementation.util.LispNotificationHelper;
22 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
23 import org.opendaylight.lispflowmapping.interfaces.dao.IMappingServiceKey;
24 import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
25 import org.opendaylight.lispflowmapping.interfaces.dao.MappingServiceRLOCGroup;
26 import org.opendaylight.lispflowmapping.interfaces.dao.MappingServiceSubscriberRLOC;
27 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapRequestResultHandler;
28 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapResolverAsync;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.EidToLocatorRecord.Action;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.LcafTrafficEngineeringAddress;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.LispAFIAddress;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.MapRequest;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.eidrecords.EidRecord;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.eidtolocatorrecords.EidToLocatorRecord;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.eidtolocatorrecords.EidToLocatorRecordBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.lcaftrafficengineeringaddress.Hops;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.lispaddress.LispAddressContainer;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.lispaddress.lispaddresscontainer.address.LcafTrafficEngineering;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.locatorrecords.LocatorRecord;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.locatorrecords.LocatorRecordBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.mapreplymessage.MapReplyBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.maprequest.ItrRloc;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
46 public class MapResolver extends AbstractLispComponent implements IMapResolverAsync {
48 private static final int TTL_RLOC_TIMED_OUT = 1;
49 private static final int TTL_NO_RLOC_KNOWN = 15;
50 protected static final Logger LOG = LoggerFactory.getLogger(MapResolver.class);
52 private static final ConfigIni configIni = new ConfigIni();
53 private static final String elpPolicy = configIni.getElpPolicy();
55 public MapResolver(ILispDAO dao) {
56 this(dao, true, true);
59 public MapResolver(ILispDAO dao, boolean authenticate, boolean iterateMask) {
60 super(dao, authenticate, iterateMask);
63 public void handleMapRequest(MapRequest request, boolean smr, IMapRequestResultHandler callback) {
65 LOG.warn("handleMapRequest called while dao is uninitialized");
68 if (request.isPitr()) {
69 if (request.getEidRecord().size() > 0) {
70 EidRecord eid = request.getEidRecord().get(0);
71 Object result = DAOMappingUtil.getLocatorsSpecificByEidRecord(eid, dao, ADDRESS_SUBKEY, shouldIterateMask());
72 if (result != null && result instanceof MappingServiceRLOCGroup) {
73 MappingServiceRLOCGroup locatorsGroup = (MappingServiceRLOCGroup) result;
74 if (locatorsGroup != null && locatorsGroup.getRecords().size() > 0) {
75 callback.handleNonProxyMapRequest(request,
76 LispNotificationHelper.getTransportAddressFromContainer(locatorsGroup.getRecords().get(0).getLispAddressContainer()));
82 LispAFIAddress srcEid = null;
83 if (request.getSourceEid() != null) {
84 srcEid = LispAFIConvertor.toAFI(request.getSourceEid().getLispAddressContainer());
86 MapReplyBuilder builder = new MapReplyBuilder();
87 builder.setEchoNonceEnabled(false);
88 builder.setProbe(false);
89 builder.setSecurityEnabled(false);
90 builder.setNonce(request.getNonce());
91 builder.setEidToLocatorRecord(new ArrayList<EidToLocatorRecord>());
92 for (EidRecord eid : request.getEidRecord()) {
93 EidToLocatorRecordBuilder recordBuilder = new EidToLocatorRecordBuilder();
94 Entry<IMappingServiceKey, List<MappingServiceRLOCGroup>> mapping = DAOMappingUtil.getMapping(srcEid, eid, dao);
95 recordBuilder.setRecordTtl(0);
96 recordBuilder.setAction(Action.NoAction);
97 recordBuilder.setAuthoritative(false);
98 recordBuilder.setMapVersion((short) 0);
99 recordBuilder.setMaskLength((short) mapping.getKey().getMask());
100 recordBuilder.setLispAddressContainer(mapping.getKey().getEID());
101 recordBuilder.setLocatorRecord(new ArrayList<LocatorRecord>());
102 List<MappingServiceRLOCGroup> locators = mapping.getValue();
103 if (locators != null && locators.size() > 0) {
104 List<ItrRloc> itrRlocs = request.getItrRloc();
105 addLocatorGroups(recordBuilder, locators, itrRlocs);
106 if (itrRlocs != null && itrRlocs.size() > 0) {
107 LispAddressContainer itrRloc = itrRlocs.get(0).getLispAddressContainer();
108 MappingServiceSubscriberRLOC subscriberRloc = new MappingServiceSubscriberRLOC(itrRloc);
109 HashSet<MappingServiceSubscriberRLOC> subscribers = getSubscribers(mapping.getKey().getEID(), mapping.getKey().getMask());
110 if (subscribers == null) {
111 subscribers = new HashSet<MappingServiceSubscriberRLOC>();
112 } else if (subscribers.contains(subscriberRloc)) {
114 * If there is an entry already for this
115 * subscriberRloc, remove it, so that it gets the
118 subscribers.remove(subscriberRloc);
121 IMappingServiceKey key = MappingServiceKeyUtil.generateMappingServiceKey(mapping.getKey().getEID(),
122 mapping.getKey().getMask());
123 LOG.trace("Adding new subscriber: " + subscriberRloc.toString());
124 subscribers.add(subscriberRloc);
125 dao.put(key, new MappingEntry<HashSet<MappingServiceSubscriberRLOC>>(SUBSCRIBERS_SUBKEY, subscribers));
129 recordBuilder.setAction(Action.NativelyForward);
130 if (shouldAuthenticate() && getPassword(eid.getLispAddressContainer(), eid.getMask()) != null) {
131 recordBuilder.setRecordTtl(TTL_RLOC_TIMED_OUT);
133 recordBuilder.setRecordTtl(TTL_NO_RLOC_KNOWN);
137 builder.getEidToLocatorRecord().add(recordBuilder.build());
140 callback.handleMapReply(builder.build());
144 private void addLocatorGroups(EidToLocatorRecordBuilder recordBuilder, List<MappingServiceRLOCGroup> rlocs, List<ItrRloc> itrRlocs) {
145 for (MappingServiceRLOCGroup rloc : rlocs) {
146 addLocators(recordBuilder, rloc, itrRlocs);
147 recordBuilder.setRecordTtl(rloc.getTtl());
151 private void addLocators(EidToLocatorRecordBuilder recordBuilder, MappingServiceRLOCGroup locatorObject, List<ItrRloc> itrRlocs) {
152 if (locatorObject == null) {
156 recordBuilder.setAction(locatorObject.getAction());
157 recordBuilder.setAuthoritative(locatorObject.isAuthoritative());
158 recordBuilder.setRecordTtl(locatorObject.getTtl());
161 for (LocatorRecord record : locatorObject.getRecords()) {
162 LispAddressContainer container = record.getLispAddressContainer();
164 // For non-ELP RLOCs, or when ELP policy is default, just add the locator and be done
165 if ((!(container.getAddress() instanceof LcafTrafficEngineering)) || elpPolicy.equalsIgnoreCase("default")) {
166 recordBuilder.getLocatorRecord().add(
167 new LocatorRecordBuilder().setLocalLocator(record.isLocalLocator()).setRlocProbed(record.isRlocProbed())
168 .setWeight(record.getWeight()).setPriority(record.getPriority()).setMulticastWeight(record.getMulticastWeight())
169 .setMulticastPriority(record.getMulticastPriority()).setRouted(true)
170 .setLispAddressContainer(container).setName(LispAddressStringifier.getString(container)).build());
171 // TODO HACK ^^^^^^^^^^^^^
175 LcafTrafficEngineeringAddress teAddress = ((LcafTrafficEngineering) container.getAddress()).getLcafTrafficEngineeringAddr();
176 LispAddressContainer nextHop = getNextELPHop(teAddress, itrRlocs);
177 if (nextHop != null) {
178 java.lang.Short priority = record.getPriority();
179 if (elpPolicy.equalsIgnoreCase("both")) {
180 recordBuilder.getLocatorRecord().add(
181 new LocatorRecordBuilder().setLocalLocator(record.isLocalLocator()).setRlocProbed(record.isRlocProbed())
182 .setWeight(record.getWeight()).setPriority(record.getPriority()).setMulticastWeight(record.getMulticastWeight())
183 .setMulticastPriority(record.getMulticastPriority()).setRouted(true)
184 .setLispAddressContainer(container).build());
185 // Make the priority of the added simple locator lower so that ELP is used by default if
186 // the xTR understands ELP. Exclude 255, since that means don't use for unicast forwarding
187 // XXX Complex cases like several ELPs with different priorities are not handled
188 if (priority != 254 || priority !=255) {
192 // Build and add the simple RLOC
193 recordBuilder.getLocatorRecord().add(
194 new LocatorRecordBuilder().setLocalLocator(record.isLocalLocator()).setRlocProbed(record.isRlocProbed())
195 .setWeight(record.getWeight()).setPriority(priority).setMulticastWeight(record.getMulticastWeight())
196 .setMulticastPriority(record.getMulticastPriority()).setRouted(true)
197 .setLispAddressContainer(nextHop).build());
200 } catch (ClassCastException cce) {
201 LOG.error("Class Cast Exception while building EidToLocatorRecord: {}", cce);
205 private LispAddressContainer getNextELPHop(LcafTrafficEngineeringAddress elp, List<ItrRloc> itrRlocs) {
206 LispAddressContainer nextHop = null;
207 List<Hops> hops = elp.getHops();
209 if (hops != null && hops.size() > 0) {
210 // By default we return the first hop
211 nextHop = LispAFIConvertor.toContainer(LispAFIConvertor.toAFIfromPrimitive(hops.get(0).getHop().getPrimitiveAddress()));
212 for (Hops hop : hops) {
213 LispAddressContainer hopContainer = LispAFIConvertor.toContainer(LispAFIConvertor.toAFIfromPrimitive(hop.getHop().getPrimitiveAddress()));
214 for (ItrRloc itrRloc : itrRlocs) {
215 if (itrRloc.getLispAddressContainer().equals(hopContainer)) {
216 int i = hops.indexOf(hop);
217 if (i < hops.size() - 1) {
218 nextHop = LispAFIConvertor.toContainer(LispAFIConvertor.toAFIfromPrimitive(hops.get(i+1).getHop().getPrimitiveAddress()));