blob: 1db6559e0c731b25957f8021b1ee6fca9dee74ac [file] [log] [blame]
Jian Li451cea32016-10-04 15:27:50 +09001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Jian Li5e505c62016-12-05 02:44:24 +090016package org.onosproject.lisp.ctl.impl;
Jian Li451cea32016-10-04 15:27:50 +090017
Jian Li347c51e2017-01-18 14:08:50 -080018import com.google.common.collect.ImmutableList;
Jian Licdbc0872016-12-05 17:23:53 +090019import com.google.common.collect.Lists;
20import org.onosproject.lisp.msg.protocols.DefaultLispEncapsulatedControl.DefaultEcmBuilder;
Jian Li6153eab2016-12-06 00:30:29 +090021import org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.DefaultMapRecordBuilder;
Jian Li5e505c62016-12-05 02:44:24 +090022import org.onosproject.lisp.msg.protocols.DefaultLispMapReply.DefaultReplyBuilder;
Jian Li6153eab2016-12-06 00:30:29 +090023import org.onosproject.lisp.msg.protocols.LispEidRecord;
Jian Li1118c122016-11-01 21:58:15 +090024import org.onosproject.lisp.msg.protocols.LispEncapsulatedControl;
Jian Licdbc0872016-12-05 17:23:53 +090025import org.onosproject.lisp.msg.protocols.LispEncapsulatedControl.EcmBuilder;
Jian Li672ebda2017-02-06 20:21:04 +090026import org.onosproject.lisp.msg.protocols.LispLocator;
Jian Li1118c122016-11-01 21:58:15 +090027import org.onosproject.lisp.msg.protocols.LispMapRecord;
Jian Li6153eab2016-12-06 00:30:29 +090028import org.onosproject.lisp.msg.protocols.LispMapRecord.MapRecordBuilder;
Jian Li5e505c62016-12-05 02:44:24 +090029import org.onosproject.lisp.msg.protocols.LispMapReply.ReplyBuilder;
Jian Li6153eab2016-12-06 00:30:29 +090030import org.onosproject.lisp.msg.protocols.LispMapReplyAction;
Jian Li5e505c62016-12-05 02:44:24 +090031import org.onosproject.lisp.msg.protocols.LispMapRequest;
Jian Licdbc0872016-12-05 17:23:53 +090032import org.onosproject.lisp.msg.protocols.LispMapReply;
33import org.onosproject.lisp.msg.protocols.LispMessage;
34import org.onosproject.lisp.msg.types.LispAfiAddress;
35import org.onosproject.lisp.msg.types.LispIpAddress;
Jian Li5e505c62016-12-05 02:44:24 +090036
Jian Li1118c122016-11-01 21:58:15 +090037import org.slf4j.Logger;
38import org.slf4j.LoggerFactory;
39
40import java.net.InetSocketAddress;
41import java.util.List;
Jian Li451cea32016-10-04 15:27:50 +090042
43/**
44 * LISP map resolver class.
45 * Handles map-request message and acknowledges with map-reply message.
46 */
Jian Li29986d82016-12-01 03:25:12 +090047public final class LispMapResolver {
Jian Li6322a362016-10-31 00:57:19 +090048
Jian Li1118c122016-11-01 21:58:15 +090049 private static final Logger log = LoggerFactory.getLogger(LispMapResolver.class);
50
Jian Licdbc0872016-12-05 17:23:53 +090051 private static final int ECM_DST_PORT = 4342;
Jian Li6153eab2016-12-06 00:30:29 +090052 private static final int NEGATIVE_REPLY_DST_PORT = 4342;
53 private static final int MAP_REPLY_RECORD_TTL = 15;
54 private static final short MAP_VERSION_NUMBER = 0;
Jian Licdbc0872016-12-05 17:23:53 +090055 private static final String NO_ITR_RLOCS_MSG =
56 "No ITR RLOC is found, cannot respond to ITR.";
57 private static final String NO_ETR_RLOCS_MSG =
58 "No ETR RLOC is found, cannot relay to ETR.";
59 private static final String NO_MAP_INFO_MSG = "Map information is not found.";
60
Jian Li29986d82016-12-01 03:25:12 +090061 private LispMappingDatabase mapDb = LispMappingDatabase.getInstance();
Jian Li1118c122016-11-01 21:58:15 +090062
Jian Li29986d82016-12-01 03:25:12 +090063 // non-instantiable (except for our Singleton)
64 private LispMapResolver() {
65 }
66
Jian Licdbc0872016-12-05 17:23:53 +090067 static LispMapResolver getInstance() {
Jian Li29986d82016-12-01 03:25:12 +090068 return SingletonHelper.INSTANCE;
Jian Li1118c122016-11-01 21:58:15 +090069 }
70
71 /**
72 * Handles encapsulated control message and replies with map-reply message.
73 *
74 * @param message encapsulated control message
75 * @return map-reply message
76 */
Jian Licdbc0872016-12-05 17:23:53 +090077 List<LispMessage> processMapRequest(LispMessage message) {
Jian Li1118c122016-11-01 21:58:15 +090078
79 LispEncapsulatedControl ecm = (LispEncapsulatedControl) message;
80 LispMapRequest request = (LispMapRequest) ecm.getControlMessage();
81
Jian Licdbc0872016-12-05 17:23:53 +090082 List<LispMapRecord> mapReplyRecords =
83 mapDb.getMapRecordByEidRecords(request.getEids(), true);
84
85 List<LispMapRecord> mapRequestRecords =
86 mapDb.getMapRecordByEidRecords(request.getEids(), false);
87
88 if (mapReplyRecords.size() + mapRequestRecords.size() == 0) {
89
Jian Li6153eab2016-12-06 00:30:29 +090090 List<LispMessage> mapReplies = Lists.newArrayList();
91
92 // build natively-forward map reply messages based on map-request from ITR
93 ReplyBuilder replyBuilder = initMapReplyBuilder(request);
94 replyBuilder.withMapRecords(getNegativeMapRecords(request.getEids()));
95 LispMessage mapReply = replyBuilder.build();
96 mapReply.configSender(new InetSocketAddress(ecm.getSender().getAddress(),
97 NEGATIVE_REPLY_DST_PORT));
98 mapReplies.add(mapReply);
99
Jian Licdbc0872016-12-05 17:23:53 +0900100 log.warn(NO_MAP_INFO_MSG);
101
102 } else {
103
Jian Li347c51e2017-01-18 14:08:50 -0800104 if (!mapReplyRecords.isEmpty()) {
Jian Licdbc0872016-12-05 17:23:53 +0900105
106 List<LispMessage> mapReplies = Lists.newArrayList();
107
108 // build map-reply message based on map-request from ITR
109 ReplyBuilder replyBuilder = initMapReplyBuilder(request);
110 replyBuilder.withMapRecords(mapReplyRecords);
111
112 List<InetSocketAddress> addresses =
113 getItrAddresses(request.getItrRlocs(),
114 ecm.innerUdp().getSourcePort());
115
116 addresses.forEach(address -> {
117 if (address != null) {
118 LispMapReply reply = replyBuilder.build();
119 reply.configSender(address);
120 mapReplies.add(reply);
121 } else {
122 log.warn(NO_ITR_RLOCS_MSG);
123 }
124 });
125
126 return mapReplies;
127 }
128
Jian Li347c51e2017-01-18 14:08:50 -0800129 if (!mapRequestRecords.isEmpty()) {
Jian Licdbc0872016-12-05 17:23:53 +0900130
131 List<LispMessage> ecms = Lists.newArrayList();
132
133 // re-encapsulate encapsulated control message from ITR
134 List<InetSocketAddress> addresses =
135 getEtrAddresses(mapRequestRecords, ECM_DST_PORT);
136
137 addresses.forEach(address -> {
138 if (address != null) {
139 LispEncapsulatedControl reencapEcm = cloneEcm(ecm);
140 reencapEcm.configSender(address);
141 ecms.add(reencapEcm);
142 } else {
143 log.warn(NO_ETR_RLOCS_MSG);
144 }
145 });
146
147 return ecms;
148 }
149 }
Jian Li347c51e2017-01-18 14:08:50 -0800150 return ImmutableList.of();
Jian Licdbc0872016-12-05 17:23:53 +0900151 }
152
153 /**
154 * Initializes MapReply builder without specifying map records.
155 *
156 * @param request received map request from ITR
157 * @return initialized MapReply builder
158 */
159 private ReplyBuilder initMapReplyBuilder(LispMapRequest request) {
Jian Li5e505c62016-12-05 02:44:24 +0900160 ReplyBuilder replyBuilder = new DefaultReplyBuilder();
Jian Li1118c122016-11-01 21:58:15 +0900161 replyBuilder.withNonce(request.getNonce());
162 replyBuilder.withIsEtr(false);
163 replyBuilder.withIsSecurity(false);
164 replyBuilder.withIsProbe(request.isProbe());
165
Jian Licdbc0872016-12-05 17:23:53 +0900166 return replyBuilder;
167 }
Jian Li1118c122016-11-01 21:58:15 +0900168
Jian Licdbc0872016-12-05 17:23:53 +0900169 /**
170 * Clones ECM from original ECM.
171 *
172 * @param ecm original ECM
173 * @return cloned ECM
174 */
175 private LispEncapsulatedControl cloneEcm(LispEncapsulatedControl ecm) {
176 EcmBuilder ecmBuilder = new DefaultEcmBuilder();
177 ecmBuilder.innerLispMessage(ecm.getControlMessage());
178 ecmBuilder.isSecurity(ecm.isSecurity());
179 ecmBuilder.innerIpHeader(ecm.innerIpHeader());
180 ecmBuilder.innerUdpHeader(ecm.innerUdp());
181
182 return ecmBuilder.build();
183 }
184
185 /**
Jian Li6153eab2016-12-06 00:30:29 +0900186 * Obtains a collection of map records with natively-forward action.
187 *
188 * @param eids endpoint identifier records
189 * @return a collection of map records with natively-forward action
190 */
191 private List<LispMapRecord> getNegativeMapRecords(List<LispEidRecord> eids) {
192 List<LispMapRecord> mapRecords = Lists.newArrayList();
193
194 MapRecordBuilder recordBuilder = new DefaultMapRecordBuilder();
195 recordBuilder.withRecordTtl(MAP_REPLY_RECORD_TTL);
196 recordBuilder.withLocators(Lists.newArrayList());
Jian Li672ebda2017-02-06 20:21:04 +0900197 recordBuilder.withIsAuthoritative(false);
Jian Li6153eab2016-12-06 00:30:29 +0900198 recordBuilder.withMapVersionNumber(MAP_VERSION_NUMBER);
199 recordBuilder.withAction(LispMapReplyAction.NativelyForward);
200
201 eids.forEach(eid -> {
202 recordBuilder.withEidPrefixAfi(eid.getPrefix());
203 recordBuilder.withMaskLength(eid.getMaskLength());
204 mapRecords.add(recordBuilder.build());
205 });
206
207 return mapRecords;
208 }
209
210 /**
Jian Licdbc0872016-12-05 17:23:53 +0900211 * Obtains a collection of valid ITR addresses with a port number specified.
212 * These addresses will be used to acknowledge map-reply to ITR.
213 *
214 * @param itrRlocs a collection of ITR RLOCs
215 * @param port port number
216 * @return a collection of valid ITR addresses with a port number specified
217 */
218 private List<InetSocketAddress> getItrAddresses(List<LispAfiAddress> itrRlocs,
219 int port) {
220 List<InetSocketAddress> addresses = Lists.newArrayList();
221 for (LispAfiAddress itrRloc : itrRlocs) {
222 addresses.add(new InetSocketAddress(((LispIpAddress)
223 itrRloc).getAddress().toInetAddress(), port));
Jian Li1118c122016-11-01 21:58:15 +0900224 }
Jian Licdbc0872016-12-05 17:23:53 +0900225 return addresses;
226 }
Jian Li1118c122016-11-01 21:58:15 +0900227
Jian Licdbc0872016-12-05 17:23:53 +0900228 /**
229 * Obtains a collection of valid ETR addresses with a port number specified.
230 * These addresses will be used to relay map-request to ETR.
231 *
232 * @param mapRecords a collection of map records
233 * @param port port number
234 * @return a collection of valid ETR addresses with a port number specified
235 */
236 private List<InetSocketAddress> getEtrAddresses(List<LispMapRecord> mapRecords,
237 int port) {
238 List<InetSocketAddress> addresses = Lists.newArrayList();
239 for (LispMapRecord mapRecord : mapRecords) {
Jian Li1118c122016-11-01 21:58:15 +0900240
Jian Licdbc0872016-12-05 17:23:53 +0900241 // we only select the first locator record in all cases...
Jian Li672ebda2017-02-06 20:21:04 +0900242 LispLocator locatorRecord = mapRecord.getLocators().get(0);
Jian Licdbc0872016-12-05 17:23:53 +0900243 if (locatorRecord != null) {
244 addresses.add(new InetSocketAddress(((LispIpAddress)
245 locatorRecord.getLocatorAfi()).getAddress()
246 .toInetAddress(), port));
247 }
Jian Li1118c122016-11-01 21:58:15 +0900248 }
Jian Licdbc0872016-12-05 17:23:53 +0900249 return addresses;
Jian Li451cea32016-10-04 15:27:50 +0900250 }
Jian Li29986d82016-12-01 03:25:12 +0900251
252 /**
253 * Prevents object instantiation from external.
254 */
255 private static final class SingletonHelper {
256 private static final String ILLEGAL_ACCESS_MSG = "Should not instantiate this class.";
257 private static final LispMapResolver INSTANCE = new LispMapResolver();
258
259 private SingletonHelper() {
260 throw new IllegalAccessError(ILLEGAL_ACCESS_MSG);
261 }
262 }
Jian Li451cea32016-10-04 15:27:50 +0900263}