ODL openflowjava和openflowplugin的启动流程,代码详解。
来源:互联网 发布:w7电脑网络出现感叹号 编辑:程序博客网 时间:2024/06/17 06:57
我们从南向北开始分析,首先看openflowjava工程,重点关注openflow-protocol-impl bundle。
首先查看该工程\src\main\yang目录下的yang文件,该文件指定了这个bundle启动的一些配置。
重点关注下面这段代码:
augment "/config:modules/config:module/config:configuration" {
case openflow-switch-connection-provider-impl {
when "/config:modules/config:module/config:type = 'openflow-switch-connection-provider-impl'";
leaf port { //openflow协议使用的端口,(of1.0 6633) (of1.3 6653)
description "local listening port";
type uint16;
mandatory true;
}
leaf address {//监听的ip
description "address of local listening interface";
type ietf-inet:ip-address;
}
leaf transport-protocol {//传输协议一般是tcp
description "Transport protocol used for communication.";
type of-config:transport-protocol;
mandatory true;
}
leaf switch-idle-timeout {//设备超时时间
description "idle timeout in [ms]";
type uint32;
mandatory true;
}
container tls {//安全传输层协议
leaf keystore {
description "keystore location";
type string;
}
leaf keystore-type {
description "keystore type (JKS or PKCS12)";
type of-config:keystore-type;
}
leaf keystore-path-type {
description "keystore path type (CLASSPATH or PATH)";
type of-config:path-type;
}
leaf keystore-password {
description "password protecting keystore";
type string;
}
leaf certificate-password {
description "password protecting certificate";
type string;
}
leaf truststore {
description "truststore location";
type string;
}
leaf truststore-type {
description "truststore type (JKS or PKCS12)";
type of-config:keystore-type;
}
leaf truststore-path-type {
description "truststore path type (CLASSPATH or PATH)";
type of-config:path-type;
}
leaf truststore-password {
description "password protecting truststore";
type string;
}
}
container threads {
leaf boss-threads {
type uint16;
}
leaf worker-threads {
type uint16;
}
}
leaf outbound-queue-size {
description "Sets size of ChannelOutboundQueue";
type uint16;
default 1024;
}
}
}
SwitchConnectionProviderModule为该bundle的启动类,关注creatInstance()方法:
public java.lang.AutoCloseable createInstance() {可见其首先实例化了一个SwitchConnectionProviderImpl对象,该对象的构造方法如下:
LOG.info("SwitchConnectionProvider started.");
SwitchConnectionProviderImpl switchConnectionProviderImpl = new SwitchConnectionProviderImpl();
try {
ConnectionConfiguration connConfiguration = createConnectionConfiguration();
switchConnectionProviderImpl.setConfiguration(connConfiguration);
} catch (UnknownHostException e) {
throw new IllegalArgumentException(e.getMessage(), e);
}
return switchConnectionProviderImpl;
}
/** Constructor */在该构造方法里主要完成,注册openflow消息的编解码工厂
public SwitchConnectionProviderImpl() {
serializerRegistry = new SerializerRegistryImpl();
serializerRegistry.init();
serializationFactory = new SerializationFactory();
serializationFactory.setSerializerTable(serializerRegistry);
deserializerRegistry = new DeserializerRegistryImpl();
deserializerRegistry.init();
deserializationFactory = new DeserializationFactory();
deserializationFactory.setRegistry(deserializerRegistry);
}
例如:
version = EncodeConstants.OF13_VERSION_ID;到此,openflow-protocol-impl启动完毕。
registryHelper = new CommonMessageRegistryHelper(version, serializerRegistry);
registryHelper.registerSerializer(BarrierInput.class, new BarrierInputMessageFactory());
registryHelper.registerSerializer(EchoInput.class, new EchoInputMessageFactory());
registryHelper.registerSerializer(EchoReplyInput.class, new EchoReplyInputMessageFactory());
registryHelper.registerSerializer(FlowModInput.class, new FlowModInputMessageFactory());
这时大家可能有疑问,这好像什么也没干啊,但通过查看openflow-protocol-spi中的yang文件发现,接口SwitchConnectionProvider作为一个服务被导出,而这个接口的实现正是前文实例化的SwitchConnectionProviderImpl对象,所以大胆猜测,引入接口SwitchConnectionProvider的bundle会继续调用接口SwitchConnectionProviderImpl实例。
而唯一可能调用该实例的bundle,应该位于openfllowplugin工程中。
查看openflowplugin工程的openflowplugin bundle中的yang文件openflow-plugin-cfg-impl.yang,可见其确实引入了SwitchConnectionProvider接口。
import openflow-switch-connection-provider
还要注意该yang文件中的这段定义:
augment "/config:modules/config:module/config:configuration" {标黄的语句表明,openfllowplugin应该会使用多个SwitchConnectionProvider实例,通过分析openflowplugin-controller-config中的42-openflowplugin.xml文件可以得知,运行时会存在两个SwitchConnectionProvider实例分别监听6633和6653端口。
case openflow-provider-impl {
when "/config:modules/config:module/config:type = 'openflow-provider-impl'";
container binding-aware-broker {
uses config:service-ref {
refine type {
mandatory true;
config:required-identity md-sal-binding:binding-broker-osgi-registry;
}
}
}
list openflow-switch-connection-provider {
uses config:service-ref {
refine type {
mandatory true;
config:required-identity openflow-switch-connection-provider:openflow-switch-connection-provider;
}
}
}
}
@Override
public java.lang.AutoCloseable createInstance() {
pluginProvider = new OpenflowPluginProvider();
pluginProvider.setBroker(getBindingAwareBrokerDependency());
pluginProvider.setSwitchConnectionProviders(getOpenflowSwitchConnectionProviderDependency());
pluginProvider.initialization();
return pluginProvider;
}
这里面的getOpenflowSwitchConnectionProviderDependency()需要注意下,返回的是Collection<SwitchConnectionProvider> ,该Collection应该只有两个元素。
可见SwitchConnectionProvider的集合被set到了OpenflowPluginProvider的实例中。然后调用了OpenflowPluginProvider的初始化方法,如下:public void initialization() {在执行this.registerProvider()时,会调用OpenflowPluginProvider中的onSessionInitiated()方法
messageCountProvider = new MessageSpyCounterImpl();
extensionConverterManager = new ExtensionConverterManagerImpl();
this.registerProvider();
}
@Override这段代码主要实现了:
public void onSessionInitiated(ProviderContext session) {
LOG.debug("onSessionInitiated");
registrationManager = new SalRegistrationManager();
registrationManager.onSessionInitiated(session);
mdController = new MDController();
mdController.setSwitchConnectionProviders(switchConnectionProviders);
mdController.setMessageSpyCounter(messageCountProvider);
mdController.setExtensionConverterProvider(extensionConverterManager);
mdController.init();
mdController.start();
}
获取notification服务,databroker服务,注册了session观察者SalRegistrationManager,
在MDController中注册openflow消息的translator,translate之后消息的poplistener(用于向md-sal发送notification)
最后调用的MDController的start()方法,是整个启动流程的关键,我们一步一步分析:
public void start() {首先,实例化了SwitchConnectionHandlerImpl,其构造方法如下:
LOG.debug("starting ..");
LOG.debug("switchConnectionProvider: " + switchConnectionProviders);
// setup handler
SwitchConnectionHandlerImpl switchConnectionHandler = new SwitchConnectionHandlerImpl();
switchConnectionHandler.setMessageSpy(messageSpyCounter);
errorHandler = new ErrorHandlerSimpleImpl();
switchConnectionHandler.setErrorHandler(errorHandler);
switchConnectionHandler.init();
List<ListenableFuture<Boolean>> starterChain = new ArrayList<>(switchConnectionProviders.size());
for (SwitchConnectionProvider switchConnectionPrv : switchConnectionProviders) {
switchConnectionPrv.setSwitchConnectionHandler(switchConnectionHandler);
ListenableFuture<Boolean> isOnlineFuture = switchConnectionPrv.startup();
starterChain.add(isOnlineFuture);
}
Future<List<Boolean>> srvStarted = Futures.allAsList(starterChain);
}
实例化了QueueProcessorLightImpl对象,该对象是以后处理openfllow消息的重要类,在此先不展开讲。public SwitchConnectionHandlerImpl() {
queueProcessor = new QueueProcessorLightImpl();
//TODO: implement shutdown invocation upon service stop event
spyPool = new ScheduledThreadPoolExecutor(1);
}
创建了一个ScheduledThreadPoolExecutor实例,这个实例是一个可以实现定时,延迟,重复执行任务的线程池,该线程池大小是1。
然后,在set了messageSpy和errorHandler之后调用了SwitchConnectionHandlerImpl的init()方法。
/**这里面的queueProcessor就是上一步实例化的QueueProcessorLightImpl对象,然后调用了QueueProcessorLightImpl的init()方法:
* wire all up
*/
public void init() {
queueProcessor.setTranslatorMapping(OFSessionUtil.getTranslatorMap());
queueProcessor.setPopListenersMapping(OFSessionUtil.getPopListenerMapping());
queueProcessor.setMessageSpy(messageSpy);
queueProcessor.init();
spyPool.scheduleAtFixedRate(messageSpy, spyRate, spyRate, TimeUnit.SECONDS);
}
/**在这个方法里实例化了3个线程池,ThreadPoolExecutor中各个参数的含义可以参考下面的帖子
* prepare queue
*/
public void init() {
int ticketQueueCapacity = 1500;
ticketQueue = new ArrayBlockingQueue<>(ticketQueueCapacity);
/*
* TODO FIXME - DOES THIS REALLY NEED TO BE CONCURRENT? Can we figure out
* a better lifecycle? Why does this have to be a Set?
*/
messageSources = new CopyOnWriteArraySet<>();
processorPool = new ThreadPoolLoggingExecutor(processingPoolSize, processingPoolSize, 0,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(ticketQueueCapacity),
"OFmsgProcessor");
// force blocking when pool queue is full
processorPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException(e);
}
}
});
harvesterPool = new ThreadPoolLoggingExecutor(1, 1, 0,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), "OFmsgHarvester");
finisherPool = new ThreadPoolLoggingExecutor(1, 1, 0,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), "OFmsgFinisher");
finisher = new TicketFinisherImpl(
ticketQueue, popListenersMapping);
finisherPool.execute(finisher);
harvester = new QueueKeeperHarvester<OfHeader>(this, messageSources);
harvesterPool.execute(harvester);
ticketProcessorFactory = new TicketProcessorFactoryImpl();
ticketProcessorFactory.setTranslatorMapping(translatorMapping);
ticketProcessorFactory.setSpy(messageSpy);
ticketProcessorFactory.setTicketFinisher(finisher);
}
http://www.cnblogs.com/dolphin0520/p/3932921.html
第一个processorPool,用来处理(主要是translate)收到的openflow消息
第二个harvesterPool ,用来处理openfllow的消息队列
第三个finisherPool, 用来发送处理后(translate之后)的openfllow消息
这三个的关系以后再说,接着回到之前的MDController的start()方法,应该运行到for循环这一步了
for (SwitchConnectionProvider switchConnectionPrv : switchConnectionProviders) {在这终于使用openflow-protocol-impl这个bundle中的SwitchConnectionProvider对象了。重点看一下SwitchConnectionProvider的startup()方法:
switchConnectionPrv.setSwitchConnectionHandler(switchConnectionHandler);
ListenableFuture<Boolean> isOnlineFuture = switchConnectionPrv.startup();
starterChain.add(isOnlineFuture);
}
@Override这个方法的功能简单来说就是创建一个Tcp或Udp的server来监听指定的端口,从目前的配置文件来看,创建的都是Tcp的Server端。
public ListenableFuture<Boolean> startup() {
LOGGER.debug("Startup summoned");
serverFacade = createAndConfigureServer();
LOGGER.debug("Starting ..");
ListenableFuture<Boolean> result = null;
try {
if (serverFacade == null) {
throw new IllegalStateException("No server configured");
}
if (serverFacade.getIsOnlineFuture().isDone()) {
throw new IllegalStateException("Server already running");
}
if (switchConnectionHandler == null) {
throw new IllegalStateException("switchConnectionHandler is not set");
}
new Thread(serverFacade).start();
result = serverFacade.getIsOnlineFuture();
} catch (Exception e) {
SettableFuture<Boolean> exResult = SettableFuture.create();
exResult.setException(e);
result = exResult;
}
return result;
}
/**
* @return
*/
private ServerFacade createAndConfigureServer() {
LOGGER.debug("Configuring ..");
ServerFacade server = null;
ChannelInitializerFactory factory = new ChannelInitializerFactory();
factory.setSwitchConnectionHandler(switchConnectionHandler);
factory.setSwitchIdleTimeout(connConfig.getSwitchIdleTimeout());
factory.setTlsConfig(connConfig.getTlsConfiguration());
factory.setSerializationFactory(serializationFactory);
factory.setDeserializationFactory(deserializationFactory);
factory.setOutboundQueueSize(connConfig.getOutboundQueueSize());
TransportProtocol transportProtocol = (TransportProtocol) connConfig.getTransferProtocol();
if (transportProtocol.equals(TransportProtocol.TCP) || transportProtocol.equals(TransportProtocol.TLS)) {
server = new TcpHandler(connConfig.getAddress(), connConfig.getPort());
((TcpHandler) server).setChannelInitializer(factory.createPublishingChannelInitializer());
} else {
server = new UdpHandler(connConfig.getAddress(), connConfig.getPort());
((UdpHandler) server).setChannelInitializer(factory.createUdpChannelInitializer());
}
server.setThreadConfig(connConfig.getThreadConfiguration());
return server;
}
到此整个openflow协议栈完全启动,controller与设备如何建立连接,以及如何接收和发送openflow消息,请听下回分解吧。
我们从南向北开始分析,首先看openflowjava工程,重点关注openflow-protocol-impl bundle。
首先查看该工程\src\main\yang目录下的yang文件,该文件指定了这个bundle启动的一些配置。
重点关注下面这段代码:
augment "/config:modules/config:module/config:configuration" {
case openflow-switch-connection-provider-impl {
when "/config:modules/config:module/config:type = 'openflow-switch-connection-provider-impl'";
leaf port { //openflow协议使用的端口,(of1.0 6633) (of1.3 6653)
description "local listening port";
type uint16;
mandatory true;
}
leaf address {//监听的ip
description "address of local listening interface";
type ietf-inet:ip-address;
}
leaf transport-protocol {//传输协议一般是tcp
description "Transport protocol used for communication.";
type of-config:transport-protocol;
mandatory true;
}
leaf switch-idle-timeout {//设备超时时间
description "idle timeout in [ms]";
type uint32;
mandatory true;
}
container tls {//安全传输层协议
leaf keystore {
description "keystore location";
type string;
}
leaf keystore-type {
description "keystore type (JKS or PKCS12)";
type of-config:keystore-type;
}
leaf keystore-path-type {
description "keystore path type (CLASSPATH or PATH)";
type of-config:path-type;
}
leaf keystore-password {
description "password protecting keystore";
type string;
}
leaf certificate-password {
description "password protecting certificate";
type string;
}
leaf truststore {
description "truststore location";
type string;
}
leaf truststore-type {
description "truststore type (JKS or PKCS12)";
type of-config:keystore-type;
}
leaf truststore-path-type {
description "truststore path type (CLASSPATH or PATH)";
type of-config:path-type;
}
leaf truststore-password {
description "password protecting truststore";
type string;
}
}
container threads {
leaf boss-threads {
type uint16;
}
leaf worker-threads {
type uint16;
}
}
leaf outbound-queue-size {
description "Sets size of ChannelOutboundQueue";
type uint16;
default 1024;
}
}
}
SwitchConnectionProviderModule为该bundle的启动类,关注creatInstance()方法:
public java.lang.AutoCloseable createInstance() {可见其首先实例化了一个SwitchConnectionProviderImpl对象,该对象的构造方法如下:
LOG.info("SwitchConnectionProvider started.");
SwitchConnectionProviderImpl switchConnectionProviderImpl = new SwitchConnectionProviderImpl();
try {
ConnectionConfiguration connConfiguration = createConnectionConfiguration();
switchConnectionProviderImpl.setConfiguration(connConfiguration);
} catch (UnknownHostException e) {
throw new IllegalArgumentException(e.getMessage(), e);
}
return switchConnectionProviderImpl;
}
/** Constructor */在该构造方法里主要完成,注册openflow消息的编解码工厂
public SwitchConnectionProviderImpl() {
serializerRegistry = new SerializerRegistryImpl();
serializerRegistry.init();
serializationFactory = new SerializationFactory();
serializationFactory.setSerializerTable(serializerRegistry);
deserializerRegistry = new DeserializerRegistryImpl();
deserializerRegistry.init();
deserializationFactory = new DeserializationFactory();
deserializationFactory.setRegistry(deserializerRegistry);
}
例如:
version = EncodeConstants.OF13_VERSION_ID;到此,openflow-protocol-impl启动完毕。
registryHelper = new CommonMessageRegistryHelper(version, serializerRegistry);
registryHelper.registerSerializer(BarrierInput.class, new BarrierInputMessageFactory());
registryHelper.registerSerializer(EchoInput.class, new EchoInputMessageFactory());
registryHelper.registerSerializer(EchoReplyInput.class, new EchoReplyInputMessageFactory());
registryHelper.registerSerializer(FlowModInput.class, new FlowModInputMessageFactory());
这时大家可能有疑问,这好像什么也没干啊,但通过查看openflow-protocol-spi中的yang文件发现,接口SwitchConnectionProvider作为一个服务被导出,而这个接口的实现正是前文实例化的SwitchConnectionProviderImpl对象,所以大胆猜测,引入接口SwitchConnectionProvider的bundle会继续调用接口SwitchConnectionProviderImpl实例。
而唯一可能调用该实例的bundle,应该位于openfllowplugin工程中。
查看openflowplugin工程的openflowplugin bundle中的yang文件openflow-plugin-cfg-impl.yang,可见其确实引入了SwitchConnectionProvider接口。
import openflow-switch-connection-provider
还要注意该yang文件中的这段定义:
augment "/config:modules/config:module/config:configuration" {标黄的语句表明,openfllowplugin应该会使用多个SwitchConnectionProvider实例,通过分析openflowplugin-controller-config中的42-openflowplugin.xml文件可以得知,运行时会存在两个SwitchConnectionProvider实例分别监听6633和6653端口。
case openflow-provider-impl {
when "/config:modules/config:module/config:type = 'openflow-provider-impl'";
container binding-aware-broker {
uses config:service-ref {
refine type {
mandatory true;
config:required-identity md-sal-binding:binding-broker-osgi-registry;
}
}
}
list openflow-switch-connection-provider {
uses config:service-ref {
refine type {
mandatory true;
config:required-identity openflow-switch-connection-provider:openflow-switch-connection-provider;
}
}
}
}
@Override
public java.lang.AutoCloseable createInstance() {
pluginProvider = new OpenflowPluginProvider();
pluginProvider.setBroker(getBindingAwareBrokerDependency());
pluginProvider.setSwitchConnectionProviders(getOpenflowSwitchConnectionProviderDependency());
pluginProvider.initialization();
return pluginProvider;
}
这里面的getOpenflowSwitchConnectionProviderDependency()需要注意下,返回的是Collection<SwitchConnectionProvider> ,该Collection应该只有两个元素。
可见SwitchConnectionProvider的集合被set到了OpenflowPluginProvider的实例中。然后调用了OpenflowPluginProvider的初始化方法,如下:public void initialization() {在执行this.registerProvider()时,会调用OpenflowPluginProvider中的onSessionInitiated()方法
messageCountProvider = new MessageSpyCounterImpl();
extensionConverterManager = new ExtensionConverterManagerImpl();
this.registerProvider();
}
@Override这段代码主要实现了:
public void onSessionInitiated(ProviderContext session) {
LOG.debug("onSessionInitiated");
registrationManager = new SalRegistrationManager();
registrationManager.onSessionInitiated(session);
mdController = new MDController();
mdController.setSwitchConnectionProviders(switchConnectionProviders);
mdController.setMessageSpyCounter(messageCountProvider);
mdController.setExtensionConverterProvider(extensionConverterManager);
mdController.init();
mdController.start();
}
获取notification服务,databroker服务,注册了session观察者SalRegistrationManager,
在MDController中注册openflow消息的translator,translate之后消息的poplistener(用于向md-sal发送notification)
最后调用的MDController的start()方法,是整个启动流程的关键,我们一步一步分析:
public void start() {首先,实例化了SwitchConnectionHandlerImpl,其构造方法如下:
LOG.debug("starting ..");
LOG.debug("switchConnectionProvider: " + switchConnectionProviders);
// setup handler
SwitchConnectionHandlerImpl switchConnectionHandler = new SwitchConnectionHandlerImpl();
switchConnectionHandler.setMessageSpy(messageSpyCounter);
errorHandler = new ErrorHandlerSimpleImpl();
switchConnectionHandler.setErrorHandler(errorHandler);
switchConnectionHandler.init();
List<ListenableFuture<Boolean>> starterChain = new ArrayList<>(switchConnectionProviders.size());
for (SwitchConnectionProvider switchConnectionPrv : switchConnectionProviders) {
switchConnectionPrv.setSwitchConnectionHandler(switchConnectionHandler);
ListenableFuture<Boolean> isOnlineFuture = switchConnectionPrv.startup();
starterChain.add(isOnlineFuture);
}
Future<List<Boolean>> srvStarted = Futures.allAsList(starterChain);
}
实例化了QueueProcessorLightImpl对象,该对象是以后处理openfllow消息的重要类,在此先不展开讲。public SwitchConnectionHandlerImpl() {
queueProcessor = new QueueProcessorLightImpl();
//TODO: implement shutdown invocation upon service stop event
spyPool = new ScheduledThreadPoolExecutor(1);
}
创建了一个ScheduledThreadPoolExecutor实例,这个实例是一个可以实现定时,延迟,重复执行任务的线程池,该线程池大小是1。
然后,在set了messageSpy和errorHandler之后调用了SwitchConnectionHandlerImpl的init()方法。
/**这里面的queueProcessor就是上一步实例化的QueueProcessorLightImpl对象,然后调用了QueueProcessorLightImpl的init()方法:
* wire all up
*/
public void init() {
queueProcessor.setTranslatorMapping(OFSessionUtil.getTranslatorMap());
queueProcessor.setPopListenersMapping(OFSessionUtil.getPopListenerMapping());
queueProcessor.setMessageSpy(messageSpy);
queueProcessor.init();
spyPool.scheduleAtFixedRate(messageSpy, spyRate, spyRate, TimeUnit.SECONDS);
}
/**在这个方法里实例化了3个线程池,ThreadPoolExecutor中各个参数的含义可以参考下面的帖子
* prepare queue
*/
public void init() {
int ticketQueueCapacity = 1500;
ticketQueue = new ArrayBlockingQueue<>(ticketQueueCapacity);
/*
* TODO FIXME - DOES THIS REALLY NEED TO BE CONCURRENT? Can we figure out
* a better lifecycle? Why does this have to be a Set?
*/
messageSources = new CopyOnWriteArraySet<>();
processorPool = new ThreadPoolLoggingExecutor(processingPoolSize, processingPoolSize, 0,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(ticketQueueCapacity),
"OFmsgProcessor");
// force blocking when pool queue is full
processorPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException(e);
}
}
});
harvesterPool = new ThreadPoolLoggingExecutor(1, 1, 0,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), "OFmsgHarvester");
finisherPool = new ThreadPoolLoggingExecutor(1, 1, 0,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), "OFmsgFinisher");
finisher = new TicketFinisherImpl(
ticketQueue, popListenersMapping);
finisherPool.execute(finisher);
harvester = new QueueKeeperHarvester<OfHeader>(this, messageSources);
harvesterPool.execute(harvester);
ticketProcessorFactory = new TicketProcessorFactoryImpl();
ticketProcessorFactory.setTranslatorMapping(translatorMapping);
ticketProcessorFactory.setSpy(messageSpy);
ticketProcessorFactory.setTicketFinisher(finisher);
}
http://www.cnblogs.com/dolphin0520/p/3932921.html
第一个processorPool,用来处理(主要是translate)收到的openflow消息
第二个harvesterPool ,用来处理openfllow的消息队列
第三个finisherPool, 用来发送处理后(translate之后)的openfllow消息
这三个的关系以后再说,接着回到之前的MDController的start()方法,应该运行到for循环这一步了
for (SwitchConnectionProvider switchConnectionPrv : switchConnectionProviders) {在这终于使用openflow-protocol-impl这个bundle中的SwitchConnectionProvider对象了。重点看一下SwitchConnectionProvider的startup()方法:
switchConnectionPrv.setSwitchConnectionHandler(switchConnectionHandler);
ListenableFuture<Boolean> isOnlineFuture = switchConnectionPrv.startup();
starterChain.add(isOnlineFuture);
}
@Override这个方法的功能简单来说就是创建一个Tcp或Udp的server来监听指定的端口,从目前的配置文件来看,创建的都是Tcp的Server端。
public ListenableFuture<Boolean> startup() {
LOGGER.debug("Startup summoned");
serverFacade = createAndConfigureServer();
LOGGER.debug("Starting ..");
ListenableFuture<Boolean> result = null;
try {
if (serverFacade == null) {
throw new IllegalStateException("No server configured");
}
if (serverFacade.getIsOnlineFuture().isDone()) {
throw new IllegalStateException("Server already running");
}
if (switchConnectionHandler == null) {
throw new IllegalStateException("switchConnectionHandler is not set");
}
new Thread(serverFacade).start();
result = serverFacade.getIsOnlineFuture();
} catch (Exception e) {
SettableFuture<Boolean> exResult = SettableFuture.create();
exResult.setException(e);
result = exResult;
}
return result;
}
/**
* @return
*/
private ServerFacade createAndConfigureServer() {
LOGGER.debug("Configuring ..");
ServerFacade server = null;
ChannelInitializerFactory factory = new ChannelInitializerFactory();
factory.setSwitchConnectionHandler(switchConnectionHandler);
factory.setSwitchIdleTimeout(connConfig.getSwitchIdleTimeout());
factory.setTlsConfig(connConfig.getTlsConfiguration());
factory.setSerializationFactory(serializationFactory);
factory.setDeserializationFactory(deserializationFactory);
factory.setOutboundQueueSize(connConfig.getOutboundQueueSize());
TransportProtocol transportProtocol = (TransportProtocol) connConfig.getTransferProtocol();
if (transportProtocol.equals(TransportProtocol.TCP) || transportProtocol.equals(TransportProtocol.TLS)) {
server = new TcpHandler(connConfig.getAddress(), connConfig.getPort());
((TcpHandler) server).setChannelInitializer(factory.createPublishingChannelInitializer());
} else {
server = new UdpHandler(connConfig.getAddress(), connConfig.getPort());
((UdpHandler) server).setChannelInitializer(factory.createUdpChannelInitializer());
}
server.setThreadConfig(connConfig.getThreadConfiguration());
return server;
}
到此整个openflow协议栈完全启动,controller与设备如何建立连接,以及如何接收和发送openflow消息,请听下回分解吧。
0 0
- ODL openflowjava和openflowplugin的启动流程,代码详解。
- openflowjava的hello消息
- 关于安装opendaylight feature:install odl-openflowplugin-all发生错误解决办法
- Linux的启动流程详解
- Linux 的启动流程详解
- Linux 的启动流程详解
- nginx的启动流程和接客流程
- app的启动流程和打包流程
- 一步一步分析odl【第二弹】openflow协议栈的运行流程之建立tcp连接
- 详解ARM-linux的启动流程[转帖]
- 详解ARM-linux的启动流程[转帖]
- Linux 的启动流程详解
- Linux 的启动流程详解
- Linux 的开机启动流程详解
- Linux 的开机启动流程详解
- 计算机的开机启动流程详解!
- Linux的启动流程以及GRUB详解
- 代码启动Windchill流程
- 国内 程序员的十个等级 你属于哪个等级
- Linux命令备忘实例(13)——文件操作
- 国外 程序员的十个等级,看看你是那个等级?
- RST复位报文段
- 【我的故事】写在一万(怀带着谴责激励自己)
- ODL openflowjava和openflowplugin的启动流程,代码详解。
- freopen后重新控制台读入
- JAVA基础学习(十四)--集合一List和HashSet
- 进程上下文和中断上下文、原子上下文的区别
- 掌握JS中的“this” (一)
- 计算字符串的一个子串出现的次数
- iOS-Core-Animation-Advanced-Techniques(一)
- 讲述程序员的发展方向
- D3D11无双(0):DirectX11学习第一篇