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