com.ltln.modules.openflow.controller.manager.OFChannelInitializer.java Source code

Java tutorial

Introduction

Here is the source code for com.ltln.modules.openflow.controller.manager.OFChannelInitializer.java

Source

/**
 *    Copyright 2011, Big Switch Networks, Inc.
 *    Originally created by David Erickson, Stanford University
 *
 *    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 com.ltln.modules.openflow.controller.manager;

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.util.Timer;

import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.List;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ltln.modules.openflow.controller.inf.INewOFConnectionListener;
import com.ltln.modules.openflow.controller.inf.IOFSwitchManager;
import com.ltln.modules.openflow.core.protocol.OFFactory;
import com.ltln.modules.openflow.core.types.U32;

/**
 * Creates a ChannelPipeline for a server-side openflow channel
 * @author readams, sovietaced, rizard, andi-bigswitch
 */
public class OFChannelInitializer extends ChannelInitializer<Channel> {
    private static final Logger log = LoggerFactory.getLogger(OFChannelInitializer.class);

    private IOFSwitchManager switchManager;
    private INewOFConnectionListener connectionListener;
    private Timer timer;
    private String keyStore;
    private String keyStorePassword;
    private OFFactory defaultFactory;
    private List<U32> ofBitmaps;

    public OFChannelInitializer(IOFSwitchManager switchManager, INewOFConnectionListener connectionListener,
            Timer timer, List<U32> ofBitmaps, OFFactory defaultFactory, String keyStore, String keyStorePassword) {
        super();
        this.switchManager = switchManager;
        this.connectionListener = connectionListener;
        this.timer = timer;
        this.defaultFactory = defaultFactory;
        this.ofBitmaps = ofBitmaps;
        this.keyStore = keyStore;
        this.keyStorePassword = keyStorePassword;
    }

    @Override
    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        OFChannelHandler handler = new OFChannelHandler(switchManager, connectionListener, pipeline, timer,
                ofBitmaps, defaultFactory);

        if (keyStore != null && keyStorePassword != null) {
            try {
                /* Set up factories and stores. */
                TrustManagerFactory tmFactory = TrustManagerFactory
                        .getInstance(TrustManagerFactory.getDefaultAlgorithm());
                KeyStore tmpKS = null;
                tmFactory.init(tmpKS);

                /* Use keystore/pass defined in properties file. */
                KeyStore ks = KeyStore.getInstance("JKS");
                ks.load(new FileInputStream(keyStore), keyStorePassword.toCharArray());

                KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
                kmf.init(ks, keyStorePassword.toCharArray());

                KeyManager[] km = kmf.getKeyManagers();
                TrustManager[] tm = tmFactory.getTrustManagers();

                /* Set up SSL prereqs for Netty. */
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(km, tm, null);
                SSLEngine sslEngine = sslContext.createSSLEngine();

                /* We are the server and we will create secure sessions. */
                sslEngine.setUseClientMode(false);
                sslEngine.setEnableSessionCreation(true);

                /* These are redundant (default), but for clarity... */
                sslEngine.setEnabledProtocols(sslEngine.getSupportedProtocols());
                sslEngine.setEnabledCipherSuites(sslEngine.getSupportedCipherSuites());

                /* First, decrypt w/handler+engine; then, proceed with rest of handlers. */
                pipeline.addLast(PipelineHandler.SSL_TLS_ENCODER_DECODER, new SslHandler(sslEngine));
                log.info("SSL OpenFlow socket initialized and handler ready for switch.");
            } catch (Exception e) { /* There are lots of possible exceptions to catch, so this should get them all. */
                log.error("Exception initializing SSL OpenFlow socket: {}", e.getMessage());
                throw e; /* If we wanted secure but didn't get it, we should bail. */
            }
        }

        pipeline.addLast(PipelineHandler.OF_MESSAGE_DECODER, new OFMessageDecoder());
        pipeline.addLast(PipelineHandler.OF_MESSAGE_ENCODER, new OFMessageEncoder());
        pipeline.addLast(PipelineHandler.MAIN_IDLE,
                new IdleStateHandler(PipelineIdleReadTimeout.MAIN, PipelineIdleWriteTimeout.MAIN, 0));
        pipeline.addLast(PipelineHandler.READ_TIMEOUT, new ReadTimeoutHandler(30));
        pipeline.addLast(PipelineHandler.CHANNEL_HANDSHAKE_TIMEOUT,
                new HandshakeTimeoutHandler(handler, timer, PipelineHandshakeTimeout.CHANNEL));

        pipeline.addLast(PipelineHandler.CHANNEL_HANDLER, handler);
    }

    public static class PipelineHandler {
        public final static String CHANNEL_HANDSHAKE_TIMEOUT = "channelhandshaketimeout";
        public final static String SWITCH_HANDSHAKE_TIMEOUT = "switchhandshaketimeout";
        public final static String CHANNEL_HANDLER = "channelhandler";
        public final static String MAIN_IDLE = "mainidle";
        public final static String AUX_IDLE = "auxidle";
        public final static String OF_MESSAGE_DECODER = "ofmessagedecoder";
        public final static String OF_MESSAGE_ENCODER = "ofmessageencoder";
        public final static String READ_TIMEOUT = "readtimeout";
        public final static String SSL_TLS_ENCODER_DECODER = "ofsecurechannelencoderdecoder";
    }

    /**
     * Timeouts for parts of the handshake, in seconds
     */
    public static class PipelineHandshakeTimeout {
        final static int CHANNEL = 10;
        public final static int SWITCH = 30;
    }

    /**
     * Timeouts for writes on connections, in seconds
     */
    public static class PipelineIdleWriteTimeout {
        final static int MAIN = 2;
        public final static int AUX = 15;
    }

    /**
     * Timeouts for reads on connections, in seconds
     */
    public static class PipelineIdleReadTimeout {
        final static int MAIN = 3 * PipelineIdleWriteTimeout.MAIN;
        public final static int AUX = 3 * PipelineIdleWriteTimeout.AUX;
    }
}