blob: af7fa20531c62f1be48681c06d8f4c3e28df636d [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 Licdbc0872016-12-05 17:23:53 +090018import com.google.common.collect.Lists;
19import org.onosproject.lisp.msg.protocols.DefaultLispEncapsulatedControl.DefaultEcmBuilder;
Jian Li6153eab2016-12-06 00:30:29 +090020import org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.DefaultMapRecordBuilder;
Jian Li5e505c62016-12-05 02:44:24 +090021import org.onosproject.lisp.msg.protocols.DefaultLispMapReply.DefaultReplyBuilder;
Jian Li6153eab2016-12-06 00:30:29 +090022import org.onosproject.lisp.msg.protocols.LispEidRecord;
Jian Li1118c122016-11-01 21:58:15 +090023import org.onosproject.lisp.msg.protocols.LispEncapsulatedControl;
Jian Licdbc0872016-12-05 17:23:53 +090024import org.onosproject.lisp.msg.protocols.LispEncapsulatedControl.EcmBuilder;
25import org.onosproject.lisp.msg.protocols.LispLocatorRecord;
Jian Li1118c122016-11-01 21:58:15 +090026import org.onosproject.lisp.msg.protocols.LispMapRecord;
Jian Li6153eab2016-12-06 00:30:29 +090027import org.onosproject.lisp.msg.protocols.LispMapRecord.MapRecordBuilder;
Jian Li5e505c62016-12-05 02:44:24 +090028import org.onosproject.lisp.msg.protocols.LispMapReply.ReplyBuilder;
Jian Li6153eab2016-12-06 00:30:29 +090029import org.onosproject.lisp.msg.protocols.LispMapReplyAction;
Jian Li5e505c62016-12-05 02:44:24 +090030import org.onosproject.lisp.msg.protocols.LispMapRequest;
Jian Licdbc0872016-12-05 17:23:53 +090031import org.onosproject.lisp.msg.protocols.LispMapReply;
32import org.onosproject.lisp.msg.protocols.LispMessage;
33import org.onosproject.lisp.msg.types.LispAfiAddress;
34import org.onosproject.lisp.msg.types.LispIpAddress;
Jian Li5e505c62016-12-05 02:44:24 +090035
Jian Li1118c122016-11-01 21:58:15 +090036import org.slf4j.Logger;
37import org.slf4j.LoggerFactory;
38
39import java.net.InetSocketAddress;
40import java.util.List;
Jian Li451cea32016-10-04 15:27:50 +090041
42/**
43 * LISP map resolver class.
44 * Handles map-request message and acknowledges with map-reply message.
45 */
Jian Li29986d82016-12-01 03:25:12 +090046public final class LispMapResolver {
Jian Li6322a362016-10-31 00:57:19 +090047
Jian Li1118c122016-11-01 21:58:15 +090048 private static final Logger log = LoggerFactory.getLogger(LispMapResolver.class);
49
Jian Licdbc0872016-12-05 17:23:53 +090050 private static final int ECM_DST_PORT = 4342;
Jian Li6153eab2016-12-06 00:30:29 +090051 private static final int NEGATIVE_REPLY_DST_PORT = 4342;
52 private static final int MAP_REPLY_RECORD_TTL = 15;
53 private static final short MAP_VERSION_NUMBER = 0;
Jian Licdbc0872016-12-05 17:23:53 +090054 private static final String NO_ITR_RLOCS_MSG =
55 "No ITR RLOC is found, cannot respond to ITR.";
56 private static final String NO_ETR_RLOCS_MSG =
57 "No ETR RLOC is found, cannot relay to ETR.";
58 private static final String NO_MAP_INFO_MSG = "Map information is not found.";
59
Jian Li29986d82016-12-01 03:25:12 +090060 private LispMappingDatabase mapDb = LispMappingDatabase.getInstance();
Jian Li1118c122016-11-01 21:58:15 +090061
Jian Li29986d82016-12-01 03:25:12 +090062 // non-instantiable (except for our Singleton)
63 private LispMapResolver() {
64 }
65
Jian Licdbc0872016-12-05 17:23:53 +090066 static LispMapResolver getInstance() {
Jian Li29986d82016-12-01 03:25:12 +090067 return SingletonHelper.INSTANCE;
Jian Li1118c122016-11-01 21:58:15 +090068 }
69
70 /**
71 * Handles encapsulated control message and replies with map-reply message.
72 *
73 * @param message encapsulated control message
74 * @return map-reply message
75 */
Jian Licdbc0872016-12-05 17:23:53 +090076 List<LispMessage> processMapRequest(LispMessage message) {
Jian Li1118c122016-11-01 21:58:15 +090077
78 LispEncapsulatedControl ecm = (LispEncapsulatedControl) message;
79 LispMapRequest request = (LispMapRequest) ecm.getControlMessage();
80
Jian Licdbc0872016-12-05 17:23:53 +090081 List<LispMapRecord> mapReplyRecords =
82 mapDb.getMapRecordByEidRecords(request.getEids(), true);
83
84 List<LispMapRecord> mapRequestRecords =
85 mapDb.getMapRecordByEidRecords(request.getEids(), false);
86
87 if (mapReplyRecords.size() + mapRequestRecords.size() == 0) {
88
Jian Li6153eab2016-12-06 00:30:29 +090089 List<LispMessage> mapReplies = Lists.newArrayList();
90
91 // build natively-forward map reply messages based on map-request from ITR
92 ReplyBuilder replyBuilder = initMapReplyBuilder(request);
93 replyBuilder.withMapRecords(getNegativeMapRecords(request.getEids()));
94 LispMessage mapReply = replyBuilder.build();
95 mapReply.configSender(new InetSocketAddress(ecm.getSender().getAddress(),
96 NEGATIVE_REPLY_DST_PORT));
97 mapReplies.add(mapReply);
98
Jian Licdbc0872016-12-05 17:23:53 +090099 log.warn(NO_MAP_INFO_MSG);
100
101 } else {
102
103 if (mapReplyRecords.size() > 0) {
104
105 List<LispMessage> mapReplies = Lists.newArrayList();
106
107 // build map-reply message based on map-request from ITR
108 ReplyBuilder replyBuilder = initMapReplyBuilder(request);
109 replyBuilder.withMapRecords(mapReplyRecords);
110
111 List<InetSocketAddress> addresses =
112 getItrAddresses(request.getItrRlocs(),
113 ecm.innerUdp().getSourcePort());
114
115 addresses.forEach(address -> {
116 if (address != null) {
117 LispMapReply reply = replyBuilder.build();
118 reply.configSender(address);
119 mapReplies.add(reply);
120 } else {
121 log.warn(NO_ITR_RLOCS_MSG);
122 }
123 });
124
125 return mapReplies;
126 }
127
128 if (mapRequestRecords.size() > 0) {
129
130 List<LispMessage> ecms = Lists.newArrayList();
131
132 // re-encapsulate encapsulated control message from ITR
133 List<InetSocketAddress> addresses =
134 getEtrAddresses(mapRequestRecords, ECM_DST_PORT);
135
136 addresses.forEach(address -> {
137 if (address != null) {
138 LispEncapsulatedControl reencapEcm = cloneEcm(ecm);
139 reencapEcm.configSender(address);
140 ecms.add(reencapEcm);
141 } else {
142 log.warn(NO_ETR_RLOCS_MSG);
143 }
144 });
145
146 return ecms;
147 }
148 }
149 return null;
150 }
151
152 /**
153 * Initializes MapReply builder without specifying map records.
154 *
155 * @param request received map request from ITR
156 * @return initialized MapReply builder
157 */
158 private ReplyBuilder initMapReplyBuilder(LispMapRequest request) {
Jian Li5e505c62016-12-05 02:44:24 +0900159 ReplyBuilder replyBuilder = new DefaultReplyBuilder();
Jian Li1118c122016-11-01 21:58:15 +0900160 replyBuilder.withNonce(request.getNonce());
161 replyBuilder.withIsEtr(false);
162 replyBuilder.withIsSecurity(false);
163 replyBuilder.withIsProbe(request.isProbe());
164
Jian Licdbc0872016-12-05 17:23:53 +0900165 return replyBuilder;
166 }
Jian Li1118c122016-11-01 21:58:15 +0900167
Jian Licdbc0872016-12-05 17:23:53 +0900168 /**
169 * Clones ECM from original ECM.
170 *
171 * @param ecm original ECM
172 * @return cloned ECM
173 */
174 private LispEncapsulatedControl cloneEcm(LispEncapsulatedControl ecm) {
175 EcmBuilder ecmBuilder = new DefaultEcmBuilder();
176 ecmBuilder.innerLispMessage(ecm.getControlMessage());
177 ecmBuilder.isSecurity(ecm.isSecurity());
178 ecmBuilder.innerIpHeader(ecm.innerIpHeader());
179 ecmBuilder.innerUdpHeader(ecm.innerUdp());
180
181 return ecmBuilder.build();
182 }
183
184 /**
Jian Li6153eab2016-12-06 00:30:29 +0900185 * Obtains a collection of map records with natively-forward action.
186 *
187 * @param eids endpoint identifier records
188 * @return a collection of map records with natively-forward action
189 */
190 private List<LispMapRecord> getNegativeMapRecords(List<LispEidRecord> eids) {
191 List<LispMapRecord> mapRecords = Lists.newArrayList();
192
193 MapRecordBuilder recordBuilder = new DefaultMapRecordBuilder();
194 recordBuilder.withRecordTtl(MAP_REPLY_RECORD_TTL);
195 recordBuilder.withLocators(Lists.newArrayList());
196 recordBuilder.withAuthoritative(false);
197 recordBuilder.withMapVersionNumber(MAP_VERSION_NUMBER);
198 recordBuilder.withAction(LispMapReplyAction.NativelyForward);
199
200 eids.forEach(eid -> {
201 recordBuilder.withEidPrefixAfi(eid.getPrefix());
202 recordBuilder.withMaskLength(eid.getMaskLength());
203 mapRecords.add(recordBuilder.build());
204 });
205
206 return mapRecords;
207 }
208
209 /**
Jian Licdbc0872016-12-05 17:23:53 +0900210 * Obtains a collection of valid ITR addresses with a port number specified.
211 * These addresses will be used to acknowledge map-reply to ITR.
212 *
213 * @param itrRlocs a collection of ITR RLOCs
214 * @param port port number
215 * @return a collection of valid ITR addresses with a port number specified
216 */
217 private List<InetSocketAddress> getItrAddresses(List<LispAfiAddress> itrRlocs,
218 int port) {
219 List<InetSocketAddress> addresses = Lists.newArrayList();
220 for (LispAfiAddress itrRloc : itrRlocs) {
221 addresses.add(new InetSocketAddress(((LispIpAddress)
222 itrRloc).getAddress().toInetAddress(), port));
Jian Li1118c122016-11-01 21:58:15 +0900223 }
Jian Licdbc0872016-12-05 17:23:53 +0900224 return addresses;
225 }
Jian Li1118c122016-11-01 21:58:15 +0900226
Jian Licdbc0872016-12-05 17:23:53 +0900227 /**
228 * Obtains a collection of valid ETR addresses with a port number specified.
229 * These addresses will be used to relay map-request to ETR.
230 *
231 * @param mapRecords a collection of map records
232 * @param port port number
233 * @return a collection of valid ETR addresses with a port number specified
234 */
235 private List<InetSocketAddress> getEtrAddresses(List<LispMapRecord> mapRecords,
236 int port) {
237 List<InetSocketAddress> addresses = Lists.newArrayList();
238 for (LispMapRecord mapRecord : mapRecords) {
Jian Li1118c122016-11-01 21:58:15 +0900239
Jian Licdbc0872016-12-05 17:23:53 +0900240 // we only select the first locator record in all cases...
241 LispLocatorRecord locatorRecord = mapRecord.getLocators().get(0);
242 if (locatorRecord != null) {
243 addresses.add(new InetSocketAddress(((LispIpAddress)
244 locatorRecord.getLocatorAfi()).getAddress()
245 .toInetAddress(), port));
246 }
Jian Li1118c122016-11-01 21:58:15 +0900247 }
Jian Licdbc0872016-12-05 17:23:53 +0900248 return addresses;
Jian Li451cea32016-10-04 15:27:50 +0900249 }
Jian Li29986d82016-12-01 03:25:12 +0900250
251 /**
252 * Prevents object instantiation from external.
253 */
254 private static final class SingletonHelper {
255 private static final String ILLEGAL_ACCESS_MSG = "Should not instantiate this class.";
256 private static final LispMapResolver INSTANCE = new LispMapResolver();
257
258 private SingletonHelper() {
259 throw new IllegalAccessError(ILLEGAL_ACCESS_MSG);
260 }
261 }
Jian Li451cea32016-10-04 15:27:50 +0900262}