blob: 779e6c2e6fe4d4c859d54e0b471dca2bd6b4c7b3 [file] [log] [blame]
Jian Li6322a362016-10-31 00:57:19 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Jian Li6322a362016-10-31 00:57:19 +09003 *
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 Li6322a362016-10-31 00:57:19 +090017
Jian Li834ff722016-12-13 19:43:02 +090018import com.google.common.collect.Maps;
Jian Li712ec052016-11-22 03:23:54 +090019import org.onlab.util.Tools;
20import org.onosproject.cfg.ComponentConfigService;
Jian Li6322a362016-10-31 00:57:19 +090021import org.onosproject.core.CoreService;
Jian Li5e505c62016-12-05 02:44:24 +090022import org.onosproject.lisp.ctl.LispController;
Jian Li7ccc3a82016-12-09 01:30:56 +090023import org.onosproject.lisp.ctl.LispMessageListener;
24import org.onosproject.lisp.ctl.LispRouter;
Jian Li834ff722016-12-13 19:43:02 +090025import org.onosproject.lisp.ctl.LispRouterAgent;
Jian Lib1a8fd02016-12-27 03:55:32 +090026import org.onosproject.lisp.ctl.LispRouterFactory;
Jian Li7ccc3a82016-12-09 01:30:56 +090027import org.onosproject.lisp.ctl.LispRouterId;
28import org.onosproject.lisp.ctl.LispRouterListener;
Jian Li712ec052016-11-22 03:23:54 +090029import org.onosproject.lisp.msg.authentication.LispAuthenticationConfig;
Jian Li834ff722016-12-13 19:43:02 +090030import org.onosproject.lisp.msg.protocols.LispInfoReply;
31import org.onosproject.lisp.msg.protocols.LispInfoRequest;
32import org.onosproject.lisp.msg.protocols.LispMessage;
Jian Li712ec052016-11-22 03:23:54 +090033import org.osgi.service.component.ComponentContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070034import org.osgi.service.component.annotations.Activate;
35import org.osgi.service.component.annotations.Component;
36import org.osgi.service.component.annotations.Deactivate;
37import org.osgi.service.component.annotations.Modified;
38import org.osgi.service.component.annotations.Reference;
39import org.osgi.service.component.annotations.ReferenceCardinality;
Jian Li6322a362016-10-31 00:57:19 +090040import org.slf4j.Logger;
Jian Li6322a362016-10-31 00:57:19 +090041
Jian Li712ec052016-11-22 03:23:54 +090042import java.util.Dictionary;
Jian Li834ff722016-12-13 19:43:02 +090043import java.util.Map;
44import java.util.Set;
45import java.util.concurrent.ConcurrentMap;
46import java.util.concurrent.CopyOnWriteArraySet;
47import java.util.concurrent.ExecutorService;
Jian Li712ec052016-11-22 03:23:54 +090048
Jian Li834ff722016-12-13 19:43:02 +090049import static java.util.concurrent.Executors.newFixedThreadPool;
50import static java.util.stream.Collectors.toConcurrentMap;
Jian Li712ec052016-11-22 03:23:54 +090051import static org.onlab.util.Tools.get;
52import static org.onlab.util.Tools.getIntegerProperty;
Jian Li834ff722016-12-13 19:43:02 +090053import static org.onlab.util.Tools.groupedThreads;
54import static org.slf4j.LoggerFactory.getLogger;
Jian Li712ec052016-11-22 03:23:54 +090055
Jian Li6322a362016-10-31 00:57:19 +090056/**
57 * LISP controller initiation class.
58 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070059@Component(immediate = true, service = LispController.class)
Jian Li6322a362016-10-31 00:57:19 +090060public class LispControllerImpl implements LispController {
61
62 private static final String APP_ID = "org.onosproject.lisp-base";
63
Jian Li834ff722016-12-13 19:43:02 +090064 private static final Logger log = getLogger(LispControllerImpl.class);
Jian Li6322a362016-10-31 00:57:19 +090065
Jian Li712ec052016-11-22 03:23:54 +090066 private static final String DEFAULT_LISP_AUTH_KEY = "onos";
67 private static final short DEFAULT_LISP_AUTH_KEY_ID = 1;
68
Ray Milkeyd84f89b2018-08-17 14:54:17 -070069 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li6322a362016-10-31 00:57:19 +090070 protected CoreService coreService;
71
Ray Milkeyd84f89b2018-08-17 14:54:17 -070072 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li712ec052016-11-22 03:23:54 +090073 protected ComponentConfigService cfgService;
74
Ray Milkeyd84f89b2018-08-17 14:54:17 -070075 //@Property(name = "lispAuthKey", value = DEFAULT_LISP_AUTH_KEY,
76 // label = "Authentication key which is used to calculate authentication " +
77 // "data for LISP control message; default value is onos")
Jian Li834ff722016-12-13 19:43:02 +090078 private String lispAuthKey = DEFAULT_LISP_AUTH_KEY;
Jian Li712ec052016-11-22 03:23:54 +090079
Ray Milkeyd84f89b2018-08-17 14:54:17 -070080 //@Property(name = "lispAuthKeyId", intValue = DEFAULT_LISP_AUTH_KEY_ID,
81 // label = "Authentication key id which denotes the authentication method " +
82 // "that ONOS uses to calculate the authentication data; " +
83 // "1 denotes HMAC SHA1 encryption, 2 denotes HMAC SHA256 encryption; " +
84 // "default value is 1")
Jian Li834ff722016-12-13 19:43:02 +090085 private int lispAuthKeyId = DEFAULT_LISP_AUTH_KEY_ID;
86
Ray Milkeyd84f89b2018-08-17 14:54:17 -070087 //@Property(name = "enableSmr", boolValue = false,
88 // label = "Enable to send SMR(Solicit Map Request) by map server; " +
89 // "By default SMR is not activated")
Jian Lib86d8ad2017-05-03 02:53:44 +090090 private boolean enableSmr = false;
91
Jian Li834ff722016-12-13 19:43:02 +090092 ExecutorService executorMessages =
93 newFixedThreadPool(4, groupedThreads("onos/lisp", "event-stats-%d", log));
94
95 protected LispRouterAgent agent = new DefaultLispRouterAgent();
96
97 ConcurrentMap<LispRouterId, LispRouter> connectedRouters = Maps.newConcurrentMap();
98
Jian Li0dab5962016-12-15 03:44:28 +090099 final LispAuthenticationConfig authConfig = LispAuthenticationConfig.getInstance();
100 LispControllerBootstrap bootstrap = new LispControllerBootstrap();
101
Jian Li834ff722016-12-13 19:43:02 +0900102 private Set<LispRouterListener> lispRouterListeners = new CopyOnWriteArraySet<>();
103 private Set<LispMessageListener> lispMessageListeners = new CopyOnWriteArraySet<>();
Jian Li712ec052016-11-22 03:23:54 +0900104
Jian Lib1a8fd02016-12-27 03:55:32 +0900105 private LispRouterFactory routerFactory = LispRouterFactory.getInstance();
106
Jian Li6322a362016-10-31 00:57:19 +0900107 @Activate
Jian Li712ec052016-11-22 03:23:54 +0900108 public void activate(ComponentContext context) {
Jian Li834ff722016-12-13 19:43:02 +0900109 coreService.registerApplication(APP_ID, this::cleanup);
Jian Li712ec052016-11-22 03:23:54 +0900110 cfgService.registerProperties(getClass());
Jian Li712ec052016-11-22 03:23:54 +0900111 initAuthConfig(context.getProperties());
Jian Lib1a8fd02016-12-27 03:55:32 +0900112 routerFactory.setAgent(agent);
Jian Li6322a362016-10-31 00:57:19 +0900113 bootstrap.start();
114 log.info("Started");
115 }
116
Jian Li834ff722016-12-13 19:43:02 +0900117 /**
118 * Shutdowns all listening channel and all LISP channels.
119 * Clean information about routers before deactivating.
120 */
121 private void cleanup() {
122 bootstrap.stop();
Jian Lib1a8fd02016-12-27 03:55:32 +0900123 routerFactory.cleanAgent();
Jian Li834ff722016-12-13 19:43:02 +0900124 connectedRouters.values().forEach(LispRouter::disconnectRouter);
125 connectedRouters.clear();
126 }
127
Jian Li6322a362016-10-31 00:57:19 +0900128 @Deactivate
129 public void deactivate() {
Jian Li834ff722016-12-13 19:43:02 +0900130 cleanup();
Jian Li712ec052016-11-22 03:23:54 +0900131 cfgService.unregisterProperties(getClass(), false);
Jian Li6322a362016-10-31 00:57:19 +0900132 log.info("Stopped");
133 }
Jian Li712ec052016-11-22 03:23:54 +0900134
135 @Modified
136 public void modified(ComponentContext context) {
137 readComponentConfiguration(context);
Jian Li834ff722016-12-13 19:43:02 +0900138 bootstrap.stop();
139 bootstrap.start();
Jian Li712ec052016-11-22 03:23:54 +0900140 }
141
142 /**
143 * Initializes authentication key and authentication method.
144 *
145 * @param properties a set of properties that contained in component context
146 */
147 private void initAuthConfig(Dictionary<?, ?> properties) {
148 authConfig.updateLispAuthKey(get(properties, "lispAuthKey"));
149 authConfig.updateLispAuthKeyId(getIntegerProperty(properties, "lispAuthKeyId"));
150 }
151
152 /**
153 * Extracts properties from the component configuration context.
154 *
155 * @param context the component context
156 */
157 private void readComponentConfiguration(ComponentContext context) {
158 Dictionary<?, ?> properties = context.getProperties();
159
160 String lispAuthKeyStr = Tools.get(properties, "lispAuthKey");
161 lispAuthKey = lispAuthKeyStr != null ? lispAuthKeyStr : DEFAULT_LISP_AUTH_KEY;
162 authConfig.updateLispAuthKey(lispAuthKey);
163 log.info("Configured. LISP authentication key is {}", lispAuthKey);
164
165 Integer lispAuthMethodInt = Tools.getIntegerProperty(properties, "lispAuthKeyId");
166 if (lispAuthMethodInt == null) {
167 lispAuthKeyId = DEFAULT_LISP_AUTH_KEY_ID;
168 log.info("LISP authentication method is not configured, default value is {}", lispAuthKeyId);
169 } else {
170 lispAuthKeyId = lispAuthMethodInt;
171 log.info("Configured. LISP authentication method is configured to {}", lispAuthKeyId);
172 }
173 authConfig.updateLispAuthKeyId(lispAuthKeyId);
Jian Lib86d8ad2017-05-03 02:53:44 +0900174
175 Boolean enableSmr = Tools.isPropertyEnabled(properties, "enableSmr");
176 if (enableSmr == null) {
177 log.info("Enable SMR is not configured, " +
178 "using current value of {}", this.enableSmr);
179 } else {
180 this.enableSmr = enableSmr;
181 log.info("Configured. Sending SMR through map server is {}",
182 this.enableSmr ? "enabled" : "disabled");
183 }
Jian Li712ec052016-11-22 03:23:54 +0900184 }
Jian Li7ccc3a82016-12-09 01:30:56 +0900185
186 @Override
187 public Iterable<LispRouter> getRouters() {
Jian Li834ff722016-12-13 19:43:02 +0900188 return connectedRouters.values();
189 }
190
191 @Override
192 public Iterable<LispRouter> getSubscribedRouters() {
193 return connectedRouters.entrySet()
194 .stream()
195 .filter(e -> e.getValue().isSubscribed())
196 .collect(toConcurrentMap(Map.Entry::getKey,
197 Map.Entry::getValue)).values();
Jian Li7ccc3a82016-12-09 01:30:56 +0900198 }
199
200 @Override
Jian Li9b1a45b2017-01-19 13:34:31 -0800201 public LispRouter connectRouter(LispRouterId routerId) {
202 if (connectedRouters.containsKey(routerId)) {
203 log.debug("LISP router {} is already existing", routerId);
204 return connectedRouters.get(routerId);
205 } else {
206 // TODO: currently we do not consider to add LISP router from netcfg
207 log.warn("Adding router from netcfg is not supported currently");
208 return null;
209 }
210 }
211
212 @Override
213 public void disconnectRouter(LispRouterId routerId, boolean remove) {
214 if (!connectedRouters.containsKey(routerId)) {
215 log.warn("LISP router {} is not existing", routerId);
216 } else {
217 connectedRouters.get(routerId).disconnectRouter();
218 if (remove) {
219 agent.removeConnectedRouter(routerId);
220 }
221 }
222 }
223
224 @Override
Jian Li7ccc3a82016-12-09 01:30:56 +0900225 public LispRouter getRouter(LispRouterId routerId) {
Jian Li834ff722016-12-13 19:43:02 +0900226 return connectedRouters.get(routerId);
Jian Li7ccc3a82016-12-09 01:30:56 +0900227 }
228
229 @Override
230 public void addRouterListener(LispRouterListener listener) {
Jian Li834ff722016-12-13 19:43:02 +0900231 if (!lispRouterListeners.contains(listener)) {
232 lispRouterListeners.add(listener);
233 }
Jian Li7ccc3a82016-12-09 01:30:56 +0900234 }
235
236 @Override
237 public void removeRouterListener(LispRouterListener listener) {
Jian Li834ff722016-12-13 19:43:02 +0900238 lispRouterListeners.remove(listener);
Jian Li7ccc3a82016-12-09 01:30:56 +0900239 }
240
241 @Override
242 public void addMessageListener(LispMessageListener listener) {
Jian Li834ff722016-12-13 19:43:02 +0900243 if (!lispMessageListeners.contains(listener)) {
244 lispMessageListeners.add(listener);
245 }
Jian Li7ccc3a82016-12-09 01:30:56 +0900246 }
247
248 @Override
249 public void removeMessageListener(LispMessageListener listener) {
Jian Li834ff722016-12-13 19:43:02 +0900250 lispMessageListeners.remove(listener);
251 }
Jian Li7ccc3a82016-12-09 01:30:56 +0900252
Jian Li834ff722016-12-13 19:43:02 +0900253 /**
254 * Implementation of a LISP agent which is responsible for keeping track of
255 * connected LISP routers and the state in which they are in.
256 */
257 public final class DefaultLispRouterAgent implements LispRouterAgent {
258
259 private final Logger log = getLogger(DefaultLispRouterAgent.class);
260
261 /**
262 * Prevents object instantiation from external class.
263 */
264 private DefaultLispRouterAgent() {
265 }
266
267 @Override
268 public boolean addConnectedRouter(LispRouterId routerId, LispRouter router) {
269
270 if (connectedRouters.get(routerId) != null) {
Jian Li07b90202017-04-14 12:03:24 +0900271 log.warn("Trying to add connectedRouter but found a previous " +
Jian Li834ff722016-12-13 19:43:02 +0900272 "value for routerId: {}", routerId);
273 return false;
274 } else {
275 log.info("Added router {}", routerId);
276 connectedRouters.put(routerId, router);
277 for (LispRouterListener listener : lispRouterListeners) {
278 listener.routerAdded(routerId);
279 }
280 return true;
281 }
282 }
283
284 @Override
285 public void removeConnectedRouter(LispRouterId routerId) {
286
287 if (connectedRouters.get(routerId) == null) {
288 log.error("Trying to remove router {} from connectedRouter " +
289 "list but no element was found", routerId);
290 } else {
291 log.info("Removed router {}", routerId);
292 connectedRouters.remove(routerId);
293 for (LispRouterListener listener : lispRouterListeners) {
294 listener.routerRemoved(routerId);
295 }
296 }
297 }
298
299 @Override
300 public void processUpstreamMessage(LispRouterId routerId, LispMessage message) {
301
302 switch (message.getType()) {
303 case LISP_MAP_REGISTER:
304 case LISP_MAP_REQUEST:
305 executorMessages.execute(
306 new LispIncomingMessageHandler(routerId, message));
307 break;
308 case LISP_INFO:
309 if (message instanceof LispInfoRequest) {
310 executorMessages.execute(
311 new LispIncomingMessageHandler(routerId, message));
312 } else {
313 log.warn("Not incoming LISP control message");
314 }
315 break;
316 default:
317 log.warn("Not incoming LISP control message");
318 break;
319 }
320 }
321
322 @Override
323 public void processDownstreamMessage(LispRouterId routerId, LispMessage message) {
324
325 switch (message.getType()) {
326 case LISP_MAP_NOTIFY:
327 case LISP_MAP_REPLY:
328 executorMessages.execute(
329 new LispOutgoingMessageHandler(routerId, message));
330 break;
331 case LISP_INFO:
332 if (message instanceof LispInfoReply) {
333 executorMessages.execute(
334 new LispOutgoingMessageHandler(routerId, message));
335 } else {
336 log.warn("Not outgoing LISP control message");
337 }
338 break;
339 default:
340 log.warn("Not outgoing LISP control message");
341 break;
342 }
343 }
344 }
345
346 /**
347 * LISP message handler.
348 */
349 protected class LispMessageHandler implements Runnable {
350
351 private final LispRouterId routerId;
352 private final LispMessage message;
353 private final boolean isIncoming;
354
355 LispMessageHandler(LispRouterId routerId,
356 LispMessage message, boolean isIncoming) {
357 this.routerId = routerId;
358 this.message = message;
359 this.isIncoming = isIncoming;
360 }
361
362 @Override
363 public void run() {
364 for (LispMessageListener listener : lispMessageListeners) {
365 if (isIncoming) {
366 listener.handleIncomingMessage(routerId, message);
367 } else {
368 listener.handleOutgoingMessage(routerId, message);
369 }
370 }
371 }
372 }
373
374 /**
375 * LISP incoming message handler.
376 */
377 protected final class LispIncomingMessageHandler
378 extends LispMessageHandler implements Runnable {
379
380 LispIncomingMessageHandler(LispRouterId routerId,
381 LispMessage message) {
382 super(routerId, message, true);
383 }
384 }
385
386 /**
387 * LISP outgoing message handler.
388 */
389 protected final class LispOutgoingMessageHandler
390 extends LispMessageHandler implements Runnable {
391
392 LispOutgoingMessageHandler(LispRouterId routerId,
393 LispMessage message) {
394 super(routerId, message, false);
395 }
Jian Li7ccc3a82016-12-09 01:30:56 +0900396 }
Jian Li6322a362016-10-31 00:57:19 +0900397}