blob: 29af59632ee9cd50c0fddcbf21515b2cf309e716 [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.lisp.ctl.impl;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.AbstractChannel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollDatagramChannel;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.InetSocketAddress;
import java.util.List;
/**
* Bootstraps LISP netty channel, handles all setup and network listeners.
*/
public class LispControllerBootstrap {
protected static final Logger log = LoggerFactory.getLogger(LispControllerBootstrap.class);
private static final int LISP_DATA_PORT = 4341;
private static final int LISP_CONTROL_PORT = 4342;
// Configuration options
protected List<Integer> lispPorts = ImmutableList.of(LISP_DATA_PORT, LISP_CONTROL_PORT);
private EventLoopGroup eventLoopGroup;
private Class<? extends AbstractChannel> channelClass;
/**
* Stitches all channel handlers into server bootstrap.
*/
private void run() {
try {
final Bootstrap bootstrap = createServerBootstrap();
configBootstrapOptions(bootstrap);
List<ChannelFuture> channelFutures = Lists.newArrayList();
lispPorts.forEach(p -> {
InetSocketAddress sa = new InetSocketAddress(p);
channelFutures.add(bootstrap.bind(sa));
log.info("Listening for LISP router connections on {}", sa);
});
for (ChannelFuture f : channelFutures) {
f.sync();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Initializes server bootstrap with given LISP channel initializer.
*
* @return initialized server bootstrap
*/
private Bootstrap createServerBootstrap() {
Bootstrap bootstrap = new Bootstrap();
initEventLoopGroup();
bootstrap.group(eventLoopGroup)
.channel(channelClass)
.handler(new LispChannelInitializer());
return bootstrap;
}
/**
* Configures bootstrap options to tune the communication performance.
*
* @param bootstrap LISP server bootstrap
*/
private void configBootstrapOptions(Bootstrap bootstrap) {
bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
}
/**
* Closes all open channels.
*
* @param channelFutures a collection of channel futures
*/
private void closeChannels(List<ChannelFuture> channelFutures) {
try {
for (ChannelFuture f : channelFutures) {
f.channel().closeFuture().sync();
}
} catch (InterruptedException e) {
log.warn("Failed to close channels. Reasons: {}.", e.getMessage());
}
}
/**
* Initializes event loop group.
*/
private void initEventLoopGroup() {
// try to use EpollEventLoopGroup if possible,
// if OS does not support native Epoll, fallback to use netty NIO
try {
eventLoopGroup = new EpollEventLoopGroup();
channelClass = EpollDatagramChannel.class;
} catch (Throwable e) {
log.debug("Failed to initialize native (epoll) transport. "
+ "Reason: {}. Proceeding with NIO event group.", e.getMessage());
}
eventLoopGroup = new NioEventLoopGroup();
channelClass = NioDatagramChannel.class;
}
/**
* Launches LISP controller to listen control channel.
*/
public void start() {
log.info("Starting LISP control I/O");
this.run();
}
/**
* Terminates LISP controller and lease all occupied resources.
*/
public void stop() {
log.info("Stopping LISP control I/O");
try {
// try to shutdown all open event groups
eventLoopGroup.shutdownGracefully().sync();
} catch (InterruptedException e) {
log.warn("Failed to stop LISP controller. Reasons: {}.", e.getMessage());
}
}
}