Openflow Plugin学习笔记3
MDController.java 中的start方法,创建了SwitchConnectionHandlerImpl实例
SwitchConnectionHandlerImpl switchConnectionHandler = new SwitchConnectionHandlerImpl();
在SwitchConnectionHandlerImpl从命名理解即为交换机连接处理,在其构造方法中创建了QueueProcessorLightImpl实例。随后在start方法中调用了init方法对SwitchConnectionHandlerImpl进行初始化,该过程中传递给OF协议消息处理的上下行处理器,同时调用了QueueProcessorLightImpl的init方法,该方法创建了3个线程池,分别是processorPool,harvesterPool,finisherPool,用来处理消息,传递消息及处理消息处理结果。
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); // OF消息处理结果将从ticketQueue中获取,目前由于为空,因此处于阻塞状态
finisherPool.execute(finisher);
harvester = new QueueKeeperHarvester<OfHeader>(this, messageSources);
harvesterPool.execute(harvester);
ticketProcessorFactory = new TicketProcessorFactoryImpl(); // OF消息处理工厂
ticketProcessorFactory.setTranslatorMapping(translatorMapping);
ticketProcessorFactory.setSpy(messageSpy);
ticketProcessorFactory.setTicketFinisher(finisher);
}
其中harvester是串联起前后消息传递的重要手段,如下
harvester = new QueueKeeperHarvester<OfHeader>(this, messageSources);
创建给harvest时,传入的参数分别是QueueProcessorLightImpl实例本身与一个装载OF消息的集合,harsvert从集合中取出单个消息进入QueueProcessorLightImpl实例的ticket处理流程中。如下:
boolean starving = true;
for (QueueKeeper<IN> source : messageSources) {
QueueItem<IN> qItem = source.poll();
if (qItem != null) {
starving = false;
enqueuer.enqueueQueueItem(qItem); // 调用即为QueueProcessorLightImpl中的enqueueQueueItem方法
}
}
QueueProcessorLightImpl中enqueueQueueItem方法如下:
@Override
public void enqueueQueueItem(QueueItem<OfHeader> queueItem) {
messageSpy.spyMessage(queueItem.getMessage(), STATISTIC_GROUP.FROM_SWITCH_ENQUEUED);
TicketImpl<OfHeader, DataObject> ticket = new TicketImpl<>(); // 输入为OF消息,输出为MD-SAL消息
ticket.setConductor(queueItem.getConnectionConductor());
ticket.setMessage(queueItem.getMessage());
ticket.setQueueType(queueItem.getQueueType());
LOG.trace("ticket scheduling: {}, ticket: {}",
queueItem.getMessage().getImplementedInterface().getSimpleName(),
System.identityHashCode(queueItem));
scheduleTicket(ticket); // 进入线程处理
}
scheduleTicket方法将根据queue类型来选择线程,关于queue类型可参见《OpenDaylight OpenFlow Plugin 过载保护》,如下:
private void scheduleTicket(Ticket<OfHeader, DataObject> ticket) {
switch (ticket.getQueueType()) {
case DEFAULT: // 处理非pktin消息
Runnable ticketProcessor = ticketProcessorFactory.createProcessor(ticket); // 创建消息处理任务
processorPool.execute(ticketProcessor); // 放入处理线程池
try {
ticketQueue.put(ticket); // 结果放入队列
} catch (InterruptedException e) {
LOG.warn("enqeueue of unordered message ticket failed", e);
}
break;
case UNORDERED: // 处理pktin消息
Runnable ticketProcessorSync = ticketProcessorFactory.createSyncProcessor(ticket);
processorPool.execute(ticketProcessorSync);
break;
default:
LOG.warn("unsupported enqueue type: {}", ticket.getQueueType());
}
}
消息处理如下:
Runnable ticketProcessor = new Runnable() {
@Override
public void run() {
LOG.debug("message received, type: {}", ticket.getMessage().getImplementedInterface().getSimpleName());
List<DataObject> translate;
try {
translate = translate(ticket); // 翻译OF消息
ticket.getResult().set(translate); // 异步结果
ticket.setDirectResult(translate); // 直接返回结果
// spying on result
if (spy != null) {
spy.spyIn(ticket.getMessage());
for (DataObject outMessage : translate) {
spy.spyOut(outMessage);
}
}
} catch (Exception e) {
LOG.warn("translation problem: {}", e.getMessage());
ticket.getResult().setException(e);
}
LOG.debug("message processing done (type: {}, ticket: {})",
ticket.getMessage().getImplementedInterface().getSimpleName(),
System.identityHashCode(ticket));
}
};
Openflow Plugin学习笔记3的更多相关文章
- Openflow Plugin学习笔记2
OpenDaylight OpenFlow Plugin 过载保护 过载保护 OF Plugin中的过载保护按如下流程工作: ConnectionConductor将消息送入队列,是最靠近OFJava ...
- Openflow Plugin学习笔记1
主入口 ConfigurableOpenFlowProviderModule是OpenFlowPlugin中启动加载的入口,如下: @Override public java.lang.AutoClo ...
- OpenFlow Switch学习笔记(五)——Group Table、Meter Table及Counters
本文主要详述OpenFlow Switch的另外两个主要组件——Group Table和Meter Table,它们在整个OpenFlow Swtich Processing中也起到了重要作用. 1. ...
- OpenFlow Switch学习笔记(四)——Matching
这次我们着重详述来自于网络中的数据包在OpenFlow Switch中与Flow Entries的具体匹配过程,以及当出现Table Miss时的处理方式,下面就将从这两方面说起. 1.Matchin ...
- OpenFlow Switch学习笔记(一)——基础概念
OpenFlow Switch v1.4.0规范是在2013年10月14号发布,规范涵盖了OpenFlow Switch各个组件的功能定义.Controller与Switch之间的通信协议Open F ...
- OpenFlow Switch学习笔记(七)——Matching Fields
Matching Fields in_port=port Matches OpenFlow port port dl_vlan=vlan Matches IEEE 802.1q Virtual LAN ...
- OpenFlow Switch学习笔记(六)——Instructions和Actions
本文主要重点讨论OpenFlow Switch规范的指令集,它们深刻影响着数据包在Switch中的处理行为,下面开始从以下几个部分谈起. 1.Instructions 每一个Flow Entry里都包 ...
- OpenFlow Switch学习笔记(三)——Flow Tables
这次我们主要讨论下OpenFlow Switch的核心组件之一——Flow Tables,以了解其内部的 matching 以及 action handling 机制.下文将会分为几个部分来逐步详述O ...
- OpenFlow Switch学习笔记(二)——OpenFlow Ports
OpenFlow Ports是OpenFlow Switch与剩余网络之间传递Packet的网络接口.OpenFlow Switches之间通过OpenFlow Ports彼此相互逻辑连接.一个Ope ...
随机推荐
- php in_array()优化
开年首篇文章,后天上班了,正在调整状态.年前室友问我一段程序效率问题,刚好来研究下!该函数是关于判断域名字符串是否是单拼域名.双拼域名.三拼域名...多拼域名问题: //原始程序function pi ...
- 程序集里包含多个版本dll引用 ,强制低版本到制定版本dll引用
在 config 的 <configuration> 节点内加入以下 类似信息 以下是以Newtonsoft.Json 为例子 <runtime> <assemblyBi ...
- Springboot 和 Mybatis集成开发
Springboot 和 Mybatis集成开发 本项目使用的环境: 开发工具:Intellij IDEA 2017.1.3 jdk:1.7.0_79 maven:3.3.9 额外功能 PageHel ...
- pyCharm最新2019激活码
破解补丁激活优点:到期时间为2099年,基本为永久啦 缺点:相对服务器激活麻烦些,但是一共只需要3个步骤,其实并不麻烦 一.下载 https://pan.baidu.com/s/1mcQM8CLUnw ...
- 【CF438E】小朋友和二叉树 解题报告
[CF438E]小朋友和二叉树 Description 我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树. 考虑一个含有\(n\)个互异正整数的序列\(c_1,c_2,\dots,c_n\). ...
- 《Linux内核设计与实现》学习总结 Chap3
第三章 进程管理 进程是Unix操作系统抽象概念中最基本的一种.我们拥有操作系统就是为了运行用户程序,因此,进程管理就是所有操作系统的心脏所在. 3.1进程 概念: 进程:处于执行期的程序.但不仅局限 ...
- (转)java getResourceAsStream的使用方法
背景:对于java项目中配置文件加载时候的绝对路径和相对路径做一个清晰的认识! 1 分析路径 在Java项目中会经常用到getResourceAsStream这个函数获取一些配置文件,但是怎样正确使用 ...
- Codeforces Round #426 (Div. 2) D 线段树优化dp
D. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...
- CDOJ--1141
原题链接:http://acm.uestc.edu.cn/problem.php?pid=1141 分析:运用欧拉函数可解此题. #include <iostream> #include ...
- linux查看当前文件夹的大小
1.(方法一)ls -lht会列出当前目录下每个文件的大小,同时也会给出当前目录下所有文件大小总和 [查看谬个文件的大小,] 2.(方法二)du -sh *也会列出当前文件夹下所有文件对应的大小 [把 ...