blob: 56695a46d5e07ffd3ceb37ba1ded95af4c48649a [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
18import com.google.common.collect.ImmutableList;
19import com.google.common.collect.Lists;
Jian Li6322a362016-10-31 00:57:19 +090020import io.netty.bootstrap.Bootstrap;
21import io.netty.buffer.PooledByteBufAllocator;
Jian Li5ba6ec12016-11-18 02:38:58 +090022import io.netty.channel.AbstractChannel;
Jian Li451cea32016-10-04 15:27:50 +090023import io.netty.channel.ChannelFuture;
24import io.netty.channel.ChannelOption;
25import io.netty.channel.EventLoopGroup;
Jian Li5ba6ec12016-11-18 02:38:58 +090026import io.netty.channel.epoll.EpollDatagramChannel;
27import io.netty.channel.epoll.EpollEventLoopGroup;
Jian Li451cea32016-10-04 15:27:50 +090028import io.netty.channel.nio.NioEventLoopGroup;
Jian Li6322a362016-10-31 00:57:19 +090029import io.netty.channel.socket.nio.NioDatagramChannel;
Jian Li451cea32016-10-04 15:27:50 +090030import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
33import java.net.InetSocketAddress;
34import java.util.List;
35
36/**
Jian Li451cea32016-10-04 15:27:50 +090037 * Bootstraps LISP netty channel, handles all setup and network listeners.
38 */
Jian Li6322a362016-10-31 00:57:19 +090039public class LispControllerBootstrap {
Jian Li451cea32016-10-04 15:27:50 +090040
Jian Li6322a362016-10-31 00:57:19 +090041 protected static final Logger log = LoggerFactory.getLogger(LispControllerBootstrap.class);
Jian Li451cea32016-10-04 15:27:50 +090042
43 private static final int LISP_DATA_PORT = 4341;
44 private static final int LISP_CONTROL_PORT = 4342;
45
46 // Configuration options
47 protected List<Integer> lispPorts = ImmutableList.of(LISP_DATA_PORT, LISP_CONTROL_PORT);
48
Jian Li6322a362016-10-31 00:57:19 +090049 private EventLoopGroup eventLoopGroup;
Jian Li5ba6ec12016-11-18 02:38:58 +090050 private Class<? extends AbstractChannel> channelClass;
Jian Li834ff722016-12-13 19:43:02 +090051 private List<ChannelFuture> channelFutures = Lists.newArrayList();
Jian Li451cea32016-10-04 15:27:50 +090052
53 /**
54 * Stitches all channel handlers into server bootstrap.
55 */
Jian Li5ba6ec12016-11-18 02:38:58 +090056 private void run() {
Jian Li451cea32016-10-04 15:27:50 +090057
58 try {
Jian Li6322a362016-10-31 00:57:19 +090059 final Bootstrap bootstrap = createServerBootstrap();
Jian Li451cea32016-10-04 15:27:50 +090060
61 configBootstrapOptions(bootstrap);
62
Jian Li451cea32016-10-04 15:27:50 +090063 lispPorts.forEach(p -> {
64 InetSocketAddress sa = new InetSocketAddress(p);
65 channelFutures.add(bootstrap.bind(sa));
66 log.info("Listening for LISP router connections on {}", sa);
67 });
68
69 for (ChannelFuture f : channelFutures) {
70 f.sync();
71 }
72
73 } catch (Exception e) {
74 throw new RuntimeException(e);
75 }
76 }
77
78 /**
79 * Initializes server bootstrap with given LISP channel initializer.
80 *
81 * @return initialized server bootstrap
82 */
Jian Li6322a362016-10-31 00:57:19 +090083 private Bootstrap createServerBootstrap() {
84 Bootstrap bootstrap = new Bootstrap();
Jian Li5ba6ec12016-11-18 02:38:58 +090085
86 initEventLoopGroup();
Jian Li6322a362016-10-31 00:57:19 +090087 bootstrap.group(eventLoopGroup)
Jian Li5ba6ec12016-11-18 02:38:58 +090088 .channel(channelClass)
Jian Li6322a362016-10-31 00:57:19 +090089 .handler(new LispChannelInitializer());
Jian Li451cea32016-10-04 15:27:50 +090090
91 return bootstrap;
92 }
93
94 /**
95 * Configures bootstrap options to tune the communication performance.
96 *
97 * @param bootstrap LISP server bootstrap
98 */
Jian Li6322a362016-10-31 00:57:19 +090099 private void configBootstrapOptions(Bootstrap bootstrap) {
100 bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
Jian Li451cea32016-10-04 15:27:50 +0900101 }
102
103 /**
104 * Closes all open channels.
105 *
106 * @param channelFutures a collection of channel futures
107 */
108 private void closeChannels(List<ChannelFuture> channelFutures) {
109 try {
110 for (ChannelFuture f : channelFutures) {
111 f.channel().closeFuture().sync();
112 }
113 } catch (InterruptedException e) {
Jian Li5ba6ec12016-11-18 02:38:58 +0900114 log.warn("Failed to close channels. Reasons: {}.", e.getMessage());
Jian Li451cea32016-10-04 15:27:50 +0900115 }
116 }
117
118 /**
Jian Li5ba6ec12016-11-18 02:38:58 +0900119 * Initializes event loop group.
120 */
121 private void initEventLoopGroup() {
122
123 // try to use EpollEventLoopGroup if possible,
124 // if OS does not support native Epoll, fallback to use netty NIO
125 try {
126 eventLoopGroup = new EpollEventLoopGroup();
127 channelClass = EpollDatagramChannel.class;
Jian Li47828a72017-02-14 20:56:31 +0900128 } catch (NoClassDefFoundError e) {
Jian Li5ba6ec12016-11-18 02:38:58 +0900129 log.debug("Failed to initialize native (epoll) transport. "
Jian Li347c51e2017-01-18 14:08:50 -0800130 + "Reason: {}. Proceeding with NIO event group.", e);
Jian Li5ba6ec12016-11-18 02:38:58 +0900131 }
132 eventLoopGroup = new NioEventLoopGroup();
133 channelClass = NioDatagramChannel.class;
134 }
135
136 /**
Jian Li451cea32016-10-04 15:27:50 +0900137 * Launches LISP controller to listen control channel.
138 */
139 public void start() {
140 log.info("Starting LISP control I/O");
141
142 this.run();
143 }
144
145 /**
146 * Terminates LISP controller and lease all occupied resources.
147 */
148 public void stop() {
149 log.info("Stopping LISP control I/O");
150
151 try {
152 // try to shutdown all open event groups
Jian Li6322a362016-10-31 00:57:19 +0900153 eventLoopGroup.shutdownGracefully().sync();
Jian Li834ff722016-12-13 19:43:02 +0900154 closeChannels(channelFutures);
Jian Li451cea32016-10-04 15:27:50 +0900155 } catch (InterruptedException e) {
Jian Li5ba6ec12016-11-18 02:38:58 +0900156 log.warn("Failed to stop LISP controller. Reasons: {}.", e.getMessage());
Jian Li451cea32016-10-04 15:27:50 +0900157 }
158 }
159}