2a214c4a13136b123d7a9a5d8de56ea1f40f332f
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / lisp / MapResolver.java
1 /*
2  * Copyright (c) 2014 Contextream, 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.lisp;
10
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.Map.Entry;
14 import java.util.Set;
15
16 import org.apache.commons.lang3.exception.ExceptionUtils;
17 import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
18 import org.opendaylight.lispflowmapping.implementation.dao.MappingServiceKeyUtil;
19 import org.opendaylight.lispflowmapping.implementation.util.DAOMappingUtil;
20 import org.opendaylight.lispflowmapping.implementation.util.LispAFIConvertor;
21 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
22 import org.opendaylight.lispflowmapping.interfaces.dao.IMappingServiceKey;
23 import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
24 import org.opendaylight.lispflowmapping.interfaces.dao.MappingServiceRLOCGroup;
25 import org.opendaylight.lispflowmapping.interfaces.dao.MappingServiceSubscriberRLOC;
26 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapRequestResultHandler;
27 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapResolverAsync;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.EidToLocatorRecord.Action;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.LcafTrafficEngineeringAddress;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.LispAFIAddress;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.MapRequest;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.eidrecords.EidRecord;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.eidtolocatorrecords.EidToLocatorRecord;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.eidtolocatorrecords.EidToLocatorRecordBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.lcaftrafficengineeringaddress.Hops;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.lispaddress.LispAddressContainer;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.lispaddress.lispaddresscontainer.address.LcafTrafficEngineering;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.lispaddress.lispaddresscontainer.address.No;
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;
45
46 import com.google.common.collect.Sets;
47
48 public class MapResolver extends AbstractLispComponent implements IMapResolverAsync {
49
50     private static final int TTL_RLOC_TIMED_OUT = 1;
51     private static final int TTL_NO_RLOC_KNOWN = 15;
52     protected static final Logger LOG = LoggerFactory.getLogger(MapResolver.class);
53
54     private static final ConfigIni configIni = new ConfigIni();
55     private static final String elpPolicy = configIni.getElpPolicy();
56
57     public MapResolver(ILispDAO dao) {
58         this(dao, true, true);
59     }
60
61     public MapResolver(ILispDAO dao, boolean authenticate, boolean iterateMask) {
62         super(dao, authenticate, iterateMask);
63     }
64
65     public void handleMapRequest(MapRequest request, boolean smr, IMapRequestResultHandler callback) {
66         if (dao == null) {
67             LOG.warn("handleMapRequest called while dao is uninitialized");
68             return;
69         }
70
71         LispAddressContainer srcEid = null;
72         LispAFIAddress srcEidAfi = null;
73         if (request.getSourceEid() != null) {
74             srcEid = request.getSourceEid().getLispAddressContainer();
75             srcEidAfi = LispAFIConvertor.toAFI(srcEid);
76         }
77         MapReplyBuilder builder = new MapReplyBuilder();
78         builder.setEchoNonceEnabled(false);
79         builder.setProbe(false);
80         builder.setSecurityEnabled(false);
81         builder.setNonce(request.getNonce());
82         builder.setEidToLocatorRecord(new ArrayList<EidToLocatorRecord>());
83         for (EidRecord eid : request.getEidRecord()) {
84             EidToLocatorRecordBuilder recordBuilder = new EidToLocatorRecordBuilder();
85             Entry<IMappingServiceKey, List<MappingServiceRLOCGroup>> mapping =
86                     DAOMappingUtil.getMapping(srcEidAfi, eid, dao);
87             recordBuilder.setRecordTtl(0);
88             recordBuilder.setAction(Action.NoAction);
89             recordBuilder.setAuthoritative(false);
90             recordBuilder.setMapVersion((short) 0);
91             recordBuilder.setMaskLength((short) mapping.getKey().getMask());
92             recordBuilder.setLispAddressContainer(mapping.getKey().getEID());
93             recordBuilder.setLocatorRecord(new ArrayList<LocatorRecord>());
94             List<MappingServiceRLOCGroup> locators = mapping.getValue();
95             if (locators != null && locators.size() > 0) {
96                 List<ItrRloc> itrRlocs = request.getItrRloc();
97                 addLocatorGroups(recordBuilder, locators, itrRlocs);
98                 if (srcEid != null && !(srcEid.getAddress() instanceof No) && itrRlocs != null && itrRlocs.size() > 0) {
99                     LispAddressContainer itrRloc = itrRlocs.get(0).getLispAddressContainer();
100                     MappingServiceSubscriberRLOC subscriberRloc = new MappingServiceSubscriberRLOC(itrRloc, srcEid);
101                     Set<MappingServiceSubscriberRLOC> subscribers = getSubscribers(mapping.getKey().getEID(), mapping.getKey().getMask());
102                     if (subscribers == null) {
103                         subscribers = Sets.newConcurrentHashSet();
104                     } else if (subscribers.contains(subscriberRloc)) {
105                         /*
106                          * If there is an entry already for this
107                          * subscriberRloc, remove it, so that it gets the
108                          * new timestamp
109                          */
110                         subscribers.remove(subscriberRloc);
111                     }
112                     if (smr) {
113                         IMappingServiceKey key = MappingServiceKeyUtil.generateMappingServiceKey(mapping.getKey().getEID(),
114                                 mapping.getKey().getMask());
115                         LOG.trace("Adding new subscriber: " + subscriberRloc.toString());
116                         subscribers.add(subscriberRloc);
117                         dao.put(key, new MappingEntry<Set<MappingServiceSubscriberRLOC>>(SUBSCRIBERS_SUBKEY, subscribers));
118                     }
119                 }
120             } else {
121                 recordBuilder.setAction(Action.NativelyForward);
122                 if (shouldAuthenticate() && getPassword(eid.getLispAddressContainer(), eid.getMask()) != null) {
123                     recordBuilder.setRecordTtl(TTL_RLOC_TIMED_OUT);
124                 } else {
125                     recordBuilder.setRecordTtl(TTL_NO_RLOC_KNOWN);
126
127                 }
128             }
129             builder.getEidToLocatorRecord().add(recordBuilder.build());
130         }
131
132         callback.handleMapReply(builder.build());
133
134     }
135
136     private void addLocatorGroups(EidToLocatorRecordBuilder recordBuilder, List<MappingServiceRLOCGroup> rlocs, List<ItrRloc> itrRlocs) {
137         for (MappingServiceRLOCGroup rloc : rlocs) {
138             addLocators(recordBuilder, rloc, itrRlocs);
139             recordBuilder.setRecordTtl(rloc.getTtl());
140         }
141     }
142
143     private void addLocators(EidToLocatorRecordBuilder recordBuilder, MappingServiceRLOCGroup locatorObject, List<ItrRloc> itrRlocs) {
144         if (locatorObject == null) {
145             return;
146         }
147
148         recordBuilder.setAction(locatorObject.getAction());
149         recordBuilder.setAuthoritative(locatorObject.isAuthoritative());
150         recordBuilder.setRecordTtl(locatorObject.getTtl());
151
152         try {
153             for (LocatorRecord record : locatorObject.getRecords()) {
154                 LispAddressContainer container = record.getLispAddressContainer();
155
156                 // For non-ELP RLOCs, or when ELP policy is default, or itrRlocs is null, just add the locator and be done
157                 if ((!(container.getAddress() instanceof LcafTrafficEngineering)) || elpPolicy.equalsIgnoreCase("default") || itrRlocs == null) {
158                     recordBuilder.getLocatorRecord().add(
159                             new LocatorRecordBuilder().setLocalLocator(record.isLocalLocator()).setRlocProbed(record.isRlocProbed())
160                                     .setWeight(record.getWeight()).setPriority(record.getPriority()).setMulticastWeight(record.getMulticastWeight())
161                                     .setMulticastPriority(record.getMulticastPriority()).setRouted(record.isRouted())
162                                     .setLispAddressContainer(container).setName(record.getName()).build());
163                     continue;
164                 }
165
166                 LcafTrafficEngineeringAddress teAddress = ((LcafTrafficEngineering) container.getAddress()).getLcafTrafficEngineeringAddr();
167                 LispAddressContainer nextHop = getNextELPHop(teAddress, itrRlocs);
168                 if (nextHop != null) {
169                     java.lang.Short priority = record.getPriority();
170                     if (elpPolicy.equalsIgnoreCase("both")) {
171                         recordBuilder.getLocatorRecord().add(
172                                 new LocatorRecordBuilder().setLocalLocator(record.isLocalLocator()).setRlocProbed(record.isRlocProbed())
173                                         .setWeight(record.getWeight()).setPriority(record.getPriority()).setMulticastWeight(record.getMulticastWeight())
174                                         .setMulticastPriority(record.getMulticastPriority()).setRouted(record.isRouted())
175                                         .setLispAddressContainer(container).setName(record.getName()).build());
176                         // Make the priority of the added simple locator lower so that ELP is used by default if
177                         // the xTR understands ELP.  Exclude 255, since that means don't use for unicast forwarding
178                         // XXX Complex cases like several ELPs with different priorities are not handled
179                         if (priority != 254 || priority !=255) {
180                             priority++;
181                         }
182                     }
183                     // Build and add the simple RLOC
184                     recordBuilder.getLocatorRecord().add(
185                             new LocatorRecordBuilder().setLocalLocator(record.isLocalLocator()).setRlocProbed(record.isRlocProbed())
186                             .setWeight(record.getWeight()).setPriority(priority).setMulticastWeight(record.getMulticastWeight())
187                             .setMulticastPriority(record.getMulticastPriority()).setRouted(record.isRouted())
188                             .setLispAddressContainer(nextHop).setName(record.getName()).build());
189                 }
190             }
191         } catch (ClassCastException cce) {
192             LOG.error("Class Cast Exception while building EidToLocatorRecord: {}", ExceptionUtils.getStackTrace(cce));
193         }
194     }
195
196     private LispAddressContainer getNextELPHop(LcafTrafficEngineeringAddress elp, List<ItrRloc> itrRlocs) {
197         LispAddressContainer nextHop = null;
198         List<Hops> hops = elp.getHops();
199
200         if (hops != null && hops.size() > 0) {
201             // By default we return the first hop
202             nextHop = LispAFIConvertor.toContainer(LispAFIConvertor.toAFIfromPrimitive(hops.get(0).getHop().getPrimitiveAddress()));
203             for (Hops hop : hops) {
204                 LispAddressContainer hopContainer = LispAFIConvertor.toContainer(LispAFIConvertor.toAFIfromPrimitive(hop.getHop().getPrimitiveAddress()));
205                 for (ItrRloc itrRloc : itrRlocs) {
206                     if (itrRloc.getLispAddressContainer().equals(hopContainer)) {
207                         int i = hops.indexOf(hop);
208                         if (i < hops.size() - 1) {
209                             nextHop = LispAFIConvertor.toContainer(LispAFIConvertor.toAFIfromPrimitive(hops.get(i+1).getHop().getPrimitiveAddress()));
210                             return nextHop;
211                         }
212                     }
213                 }
214             }
215         }
216
217         return nextHop;
218     }
219
220 }