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的更多相关文章

  1. Openflow Plugin学习笔记2

    OpenDaylight OpenFlow Plugin 过载保护 过载保护 OF Plugin中的过载保护按如下流程工作: ConnectionConductor将消息送入队列,是最靠近OFJava ...

  2. Openflow Plugin学习笔记1

    主入口 ConfigurableOpenFlowProviderModule是OpenFlowPlugin中启动加载的入口,如下: @Override public java.lang.AutoClo ...

  3. OpenFlow Switch学习笔记(五)——Group Table、Meter Table及Counters

    本文主要详述OpenFlow Switch的另外两个主要组件——Group Table和Meter Table,它们在整个OpenFlow Swtich Processing中也起到了重要作用. 1. ...

  4. OpenFlow Switch学习笔记(四)——Matching

    这次我们着重详述来自于网络中的数据包在OpenFlow Switch中与Flow Entries的具体匹配过程,以及当出现Table Miss时的处理方式,下面就将从这两方面说起. 1.Matchin ...

  5. OpenFlow Switch学习笔记(一)——基础概念

    OpenFlow Switch v1.4.0规范是在2013年10月14号发布,规范涵盖了OpenFlow Switch各个组件的功能定义.Controller与Switch之间的通信协议Open F ...

  6. OpenFlow Switch学习笔记(七)——Matching Fields

    Matching Fields in_port=port Matches OpenFlow port port dl_vlan=vlan Matches IEEE 802.1q Virtual LAN ...

  7. OpenFlow Switch学习笔记(六)——Instructions和Actions

    本文主要重点讨论OpenFlow Switch规范的指令集,它们深刻影响着数据包在Switch中的处理行为,下面开始从以下几个部分谈起. 1.Instructions 每一个Flow Entry里都包 ...

  8. OpenFlow Switch学习笔记(三)——Flow Tables

    这次我们主要讨论下OpenFlow Switch的核心组件之一——Flow Tables,以了解其内部的 matching 以及 action handling 机制.下文将会分为几个部分来逐步详述O ...

  9. OpenFlow Switch学习笔记(二)——OpenFlow Ports

    OpenFlow Ports是OpenFlow Switch与剩余网络之间传递Packet的网络接口.OpenFlow Switches之间通过OpenFlow Ports彼此相互逻辑连接.一个Ope ...

随机推荐

  1. kafka重新启动时出现:found a corrupted index file due to requirement failed问题解决方法

    问题如下: 解决方法: 删除kafka目录下的日志文件即可解决

  2. 调用webservice超时问题的解决[转]

    1.web.config配置,<system.web></system.web>里面增加:<httpRuntime maxRequestLength="1024 ...

  3. C#实体对象序列化成Json,并让字段的首字母小写

    引言:最近在工作中遇到与某些API对接的post的数据需要将对象的字段首字母小写.解决办法有两种:第一种:使用对象的字段属性设置JsonProperty来实现(不推荐,因为需要手动的修改每个字段的属性 ...

  4. THUWC2017颓废记

    2.9翘掉Wc闭幕式,和石家庄大爷们坐一辆车去杭州…路上日常orz gzz.2.10早上来报到,拍照.宿舍里另外四个人都是GD大爷.开幕式是喜闻乐见的thu日常黑pku(“在中国,世界一流大学有两所, ...

  5. hdu6446 Tree and Permutation

    没啥好说的,拆一下贡献就完事了.记dis(x,y)为树上x到y的最短路径,设长度为n的排列中有f(n)个里面x和y相邻(不考虑x和y的顺序),那么f(n)=(n-2)! (n-1) 2,显然这个f(n ...

  6. python对excel操作

    学习一下:原文链接:http://www.cnblogs.com/lhj588/archive/2012/01/06/2314181.html 一.安装xlrd模块 到python官网下载http:/ ...

  7. MT【128】不动点指路

    已知数列\(\{a_n\}\)满足\(2a_{n+1}=1-a_n^2\),且\(0<a_1<1\).求证:当\(n\geqslant 3\) 时,\(\left|\dfrac{1}{a_ ...

  8. 【BZOJ4774】修路(动态规划,斯坦纳树)

    [BZOJ4774]修路(动态规划,斯坦纳树) 题面 BZOJ 题解 先讲怎么求解最小斯坦纳树. 先明白什么是斯坦纳树. 斯坦纳树可以认为是最小生成树的一般情况.最小生成树是把所有给定点都要加入到联通 ...

  9. bzoj 1856: [Scoi2010]字符串 卡特兰数

    1856: [Scoi2010]字符串 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1458  Solved: 814[Submit][Status][ ...

  10. 题解【bzoj2002 [Hnoi2010]Bounce 弹飞绵羊】

    Description 给 \(n\) 个点以及它们的弹力系数 \(k_i\) ,含义为 可以弹到 \(i + k_i\) 的位置. 支持两个东西,修改一个点的弹力系数:求一个点要弹多少次弹出 \(n ...