blob: fc22f8072749088f994b46381a514f1b2ca77b3d [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 Li5e505c62016-12-05 02:44:24 +090020import org.onosproject.lisp.msg.protocols.DefaultLispMapReply.DefaultReplyBuilder;
Jian Li1118c122016-11-01 21:58:15 +090021import org.onosproject.lisp.msg.protocols.LispEncapsulatedControl;
Jian Licdbc0872016-12-05 17:23:53 +090022import org.onosproject.lisp.msg.protocols.LispEncapsulatedControl.EcmBuilder;
23import org.onosproject.lisp.msg.protocols.LispLocatorRecord;
Jian Li1118c122016-11-01 21:58:15 +090024import org.onosproject.lisp.msg.protocols.LispMapRecord;
Jian Li5e505c62016-12-05 02:44:24 +090025import org.onosproject.lisp.msg.protocols.LispMapReply.ReplyBuilder;
Jian Li5e505c62016-12-05 02:44:24 +090026import org.onosproject.lisp.msg.protocols.LispMapRequest;
Jian Licdbc0872016-12-05 17:23:53 +090027import org.onosproject.lisp.msg.protocols.LispMapReply;
28import org.onosproject.lisp.msg.protocols.LispMessage;
29import org.onosproject.lisp.msg.types.LispAfiAddress;
30import org.onosproject.lisp.msg.types.LispIpAddress;
Jian Li5e505c62016-12-05 02:44:24 +090031
Jian Li1118c122016-11-01 21:58:15 +090032import org.slf4j.Logger;
33import org.slf4j.LoggerFactory;
34
35import java.net.InetSocketAddress;
36import java.util.List;
Jian Li451cea32016-10-04 15:27:50 +090037
38/**
39 * LISP map resolver class.
40 * Handles map-request message and acknowledges with map-reply message.
41 */
Jian Li29986d82016-12-01 03:25:12 +090042public final class LispMapResolver {
Jian Li6322a362016-10-31 00:57:19 +090043
Jian Li1118c122016-11-01 21:58:15 +090044 private static final Logger log = LoggerFactory.getLogger(LispMapResolver.class);
45
Jian Licdbc0872016-12-05 17:23:53 +090046 private static final int ECM_DST_PORT = 4342;
47 private static final String NO_ITR_RLOCS_MSG =
48 "No ITR RLOC is found, cannot respond to ITR.";
49 private static final String NO_ETR_RLOCS_MSG =
50 "No ETR RLOC is found, cannot relay to ETR.";
51 private static final String NO_MAP_INFO_MSG = "Map information is not found.";
52
Jian Li29986d82016-12-01 03:25:12 +090053 private LispMappingDatabase mapDb = LispMappingDatabase.getInstance();
Jian Li1118c122016-11-01 21:58:15 +090054
Jian Li29986d82016-12-01 03:25:12 +090055 // non-instantiable (except for our Singleton)
56 private LispMapResolver() {
57 }
58
Jian Licdbc0872016-12-05 17:23:53 +090059 static LispMapResolver getInstance() {
Jian Li29986d82016-12-01 03:25:12 +090060 return SingletonHelper.INSTANCE;
Jian Li1118c122016-11-01 21:58:15 +090061 }
62
63 /**
64 * Handles encapsulated control message and replies with map-reply message.
65 *
66 * @param message encapsulated control message
67 * @return map-reply message
68 */
Jian Licdbc0872016-12-05 17:23:53 +090069 List<LispMessage> processMapRequest(LispMessage message) {
Jian Li1118c122016-11-01 21:58:15 +090070
71 LispEncapsulatedControl ecm = (LispEncapsulatedControl) message;
72 LispMapRequest request = (LispMapRequest) ecm.getControlMessage();
73
Jian Licdbc0872016-12-05 17:23:53 +090074 List<LispMapRecord> mapReplyRecords =
75 mapDb.getMapRecordByEidRecords(request.getEids(), true);
76
77 List<LispMapRecord> mapRequestRecords =
78 mapDb.getMapRecordByEidRecords(request.getEids(), false);
79
80 if (mapReplyRecords.size() + mapRequestRecords.size() == 0) {
81
82 // TODO: need to generate map-reply with configured native-forward action
83 log.warn(NO_MAP_INFO_MSG);
84
85 } else {
86
87 if (mapReplyRecords.size() > 0) {
88
89 List<LispMessage> mapReplies = Lists.newArrayList();
90
91 // build map-reply message based on map-request from ITR
92 ReplyBuilder replyBuilder = initMapReplyBuilder(request);
93 replyBuilder.withMapRecords(mapReplyRecords);
94
95 List<InetSocketAddress> addresses =
96 getItrAddresses(request.getItrRlocs(),
97 ecm.innerUdp().getSourcePort());
98
99 addresses.forEach(address -> {
100 if (address != null) {
101 LispMapReply reply = replyBuilder.build();
102 reply.configSender(address);
103 mapReplies.add(reply);
104 } else {
105 log.warn(NO_ITR_RLOCS_MSG);
106 }
107 });
108
109 return mapReplies;
110 }
111
112 if (mapRequestRecords.size() > 0) {
113
114 List<LispMessage> ecms = Lists.newArrayList();
115
116 // re-encapsulate encapsulated control message from ITR
117 List<InetSocketAddress> addresses =
118 getEtrAddresses(mapRequestRecords, ECM_DST_PORT);
119
120 addresses.forEach(address -> {
121 if (address != null) {
122 LispEncapsulatedControl reencapEcm = cloneEcm(ecm);
123 reencapEcm.configSender(address);
124 ecms.add(reencapEcm);
125 } else {
126 log.warn(NO_ETR_RLOCS_MSG);
127 }
128 });
129
130 return ecms;
131 }
132 }
133 return null;
134 }
135
136 /**
137 * Initializes MapReply builder without specifying map records.
138 *
139 * @param request received map request from ITR
140 * @return initialized MapReply builder
141 */
142 private ReplyBuilder initMapReplyBuilder(LispMapRequest request) {
Jian Li5e505c62016-12-05 02:44:24 +0900143 ReplyBuilder replyBuilder = new DefaultReplyBuilder();
Jian Li1118c122016-11-01 21:58:15 +0900144 replyBuilder.withNonce(request.getNonce());
145 replyBuilder.withIsEtr(false);
146 replyBuilder.withIsSecurity(false);
147 replyBuilder.withIsProbe(request.isProbe());
148
Jian Licdbc0872016-12-05 17:23:53 +0900149 return replyBuilder;
150 }
Jian Li1118c122016-11-01 21:58:15 +0900151
Jian Licdbc0872016-12-05 17:23:53 +0900152 /**
153 * Clones ECM from original ECM.
154 *
155 * @param ecm original ECM
156 * @return cloned ECM
157 */
158 private LispEncapsulatedControl cloneEcm(LispEncapsulatedControl ecm) {
159 EcmBuilder ecmBuilder = new DefaultEcmBuilder();
160 ecmBuilder.innerLispMessage(ecm.getControlMessage());
161 ecmBuilder.isSecurity(ecm.isSecurity());
162 ecmBuilder.innerIpHeader(ecm.innerIpHeader());
163 ecmBuilder.innerUdpHeader(ecm.innerUdp());
164
165 return ecmBuilder.build();
166 }
167
168 /**
169 * Obtains a collection of valid ITR addresses with a port number specified.
170 * These addresses will be used to acknowledge map-reply to ITR.
171 *
172 * @param itrRlocs a collection of ITR RLOCs
173 * @param port port number
174 * @return a collection of valid ITR addresses with a port number specified
175 */
176 private List<InetSocketAddress> getItrAddresses(List<LispAfiAddress> itrRlocs,
177 int port) {
178 List<InetSocketAddress> addresses = Lists.newArrayList();
179 for (LispAfiAddress itrRloc : itrRlocs) {
180 addresses.add(new InetSocketAddress(((LispIpAddress)
181 itrRloc).getAddress().toInetAddress(), port));
Jian Li1118c122016-11-01 21:58:15 +0900182 }
Jian Licdbc0872016-12-05 17:23:53 +0900183 return addresses;
184 }
Jian Li1118c122016-11-01 21:58:15 +0900185
Jian Licdbc0872016-12-05 17:23:53 +0900186 /**
187 * Obtains a collection of valid ETR addresses with a port number specified.
188 * These addresses will be used to relay map-request to ETR.
189 *
190 * @param mapRecords a collection of map records
191 * @param port port number
192 * @return a collection of valid ETR addresses with a port number specified
193 */
194 private List<InetSocketAddress> getEtrAddresses(List<LispMapRecord> mapRecords,
195 int port) {
196 List<InetSocketAddress> addresses = Lists.newArrayList();
197 for (LispMapRecord mapRecord : mapRecords) {
Jian Li1118c122016-11-01 21:58:15 +0900198
Jian Licdbc0872016-12-05 17:23:53 +0900199 // we only select the first locator record in all cases...
200 LispLocatorRecord locatorRecord = mapRecord.getLocators().get(0);
201 if (locatorRecord != null) {
202 addresses.add(new InetSocketAddress(((LispIpAddress)
203 locatorRecord.getLocatorAfi()).getAddress()
204 .toInetAddress(), port));
205 }
Jian Li1118c122016-11-01 21:58:15 +0900206 }
Jian Licdbc0872016-12-05 17:23:53 +0900207 return addresses;
Jian Li451cea32016-10-04 15:27:50 +0900208 }
Jian Li29986d82016-12-01 03:25:12 +0900209
210 /**
211 * Prevents object instantiation from external.
212 */
213 private static final class SingletonHelper {
214 private static final String ILLEGAL_ACCESS_MSG = "Should not instantiate this class.";
215 private static final LispMapResolver INSTANCE = new LispMapResolver();
216
217 private SingletonHelper() {
218 throw new IllegalAccessError(ILLEGAL_ACCESS_MSG);
219 }
220 }
Jian Li451cea32016-10-04 15:27:50 +0900221}