POF技术分享(二):POF交换机源码结构

一:函数调用关系图

POF交换机先会进行基本配置的初始化、交换机资源初始化等,然后开启交换机与控制器通信进程,建立连接进行通信,最后开启基于流表的数据包匹配与处理的进程(主要位于POF/datapath中)进入正常工作状态。

以上是基本流程,为了对交换机源码的整个脉络有一个清楚了解,特意按照执行流程绘制了函数关系调用图,以供解读源码时候参考对照。

图注:蓝色块为主函数;紫色块是main函数中调用的主要函数,会相应进行不同服务;淡蓝色为被调用的函数;粉色理解为开启的线程,会进行数据包接收、发送等,其中深红色为两个重要线程服务(和控制器交互、数据包匹配处理),之后会着重分析,这里面包括绿色块。蓝色线条上序号标记函数调用顺序,紫色线是逻辑顺序。

二:源码结构

POF源码文件结构较OVS清楚简单许多,主要有五个文件夹目录:common/datapath/include/local_resource/switch_control。根据上图的函数调用关系图,这里基于文件结构对图中涉及到的主要函数分别做简单分析:

1 switch_control目录:包含主函数,并含有与控制器交互的主要文件。

1.1 pof_switch_control.c:一个重要的文件,包含主函数,和各种初始化工作等。 main():主函数

  • pof交换机的配置初始化(pof_set_init_config函数)
  • 资源初始化(pof_localresource_init函数)
  • 建立与控制器的通信(pofsc_init函数)
  • datapath初始化(pof_datapath_init函数)等。

poflr_init():建立与控制器的通信

  • 设置ipport等连接信息
  • 创建给控制器发送消息的发送队列,即待发送的消息都会先写入这个发送队列中(pofbf_queue_create函数)
  • 开启线程,通过状态机来处理OF消息(pofsc_main_task函数)
  • 开启线程,非同步的从发送队列中取出消息发送给controller(pofsc_send_msg_task函数)
  • 开启线程, 在状态下POFCS_CHANNEL_RUN进行echo消息保活

pofsc_main_task(): 根据状态转移与controller保持消息交互

  • conn_desc_ptr维护交换机和控制器交互阶段的状态,根据这些状态不同,while循环会进行不同的处理。
  • POFCS_CHANNEL_INVALID状态时,创建socket客户端,但此时还没开始建立连接,pofsc_create_socket函数)
  • POFCS_CHANNEL_CONNECTING状态会进行尝试建立TCP socket连接(pofsc_connect函数)。建立成功,则设置状态为POFCS_CHANNEL_CONNECTED
  • POFCS_CHANNEL_CONNECTED状态时,交换机则会发送hello消息。发送成功,则设置状态为POFCS _HELLO
  • POFCS_HELLO状态时,则从socket缓存中读取消息。消息类型是控制器发来的hello,则设置状态为POFCS_REQUEST_FEATURE,否则设置状态为POFCS_CHANNEL_INVALID,重新建立连接。
  • 依次经过feature和config等阶段状态,然后进入关键阶段POFCS_CHANNEL_RUN
  • POFCS_CHANNEL_RUN状态时,即进入和控制器正常的交互状态。从socket接收缓存中读取消息内容,根据消息类型进行处理(pofsc_run_process函数)

pofsc_run_process():POFCS_CHANNEL_RUN状态下接收处理controller发来的消息

  • POFT_ECHO_REPLY消息只更新最新echo时间
  • 其他消息类型则进行具体处理,如flowmod处理(pof_parse_msg_from_controller函数)
  • pofsc_send_msg_task():异步取出发送队列消息发送给控制器
  • 检测是否为config/feature/Run状态,是则从发送队列中读取消息进行发送。
  • - 调用和控制器建立的socket接口,通过write函数进行发送。
  • 发送成功则while循环中继续读取发送,发送失败则把消息写回入发送队列,设置连接状态为POFCS_CHANNEL_INVALID,跳出while循环,意味着需要重新和控制器建立连接。
  • pofsc_echo_timer():在POFCS_CHANNEL_RUN状态下进行echo消息发送。

1.2 pof_config.c:一些交换机配置函数

  • pof_set_init_config()
  • 对g_states(pof_state结构体)的默认初始化(pof_set_init_states)
  • 通过pof交换机开启参数进行初始化配置(如设置controller ip,port,pof_set_init_config_by_command函数);
  • 通过文件进行初始化配置(pof_set_init_config_by_file函数)

1.3 pof_parse.c:只含有一个函数,即对controller发送的消息进行类型解析并回复等处理

  • pof_parse_msg_from_controller():对echo消息、flowmod、tablemod等消息进行具体处理。

2 local_resource目录:交换机资源管控,如流表、端口资源等

2.1 pof_local_resource.c:

pof_local_resource_init(): 端口和流表资源的初始化

  • 物理端口信息初始化(poflr_init_port函数)
  • 流表资源(包括组表和meter表等)初始化,如各种表空间分配等操作(poflr_init_table_resource函数)

2.2 剩下的几个文件实现meter表、group表、端口port等相关资源初始化等

3 datapath目录:端口接收packet并进行流表匹配处理

3.1 pof_datapath.c

pof_datapath_init():初始化datapath模块,创建packet的接收与发送队列,创建datapath线程、端口packet接收线程和端口packet发送线程

  • 创建packet的接收队列g_pofdp_recv_q_id
  • 创建packet的发送队列g_pofdp_send_q_id
  • 创建datapath线程(pofdp_main_task函数)
  • 创建端口packet发送线程(pofdp_send_raw_task函数)
  • 创建每个端口的packet接收线程(pofdp_create_port_listen_task函数)
  • 创建端口检测线程,端口改变则上报controller(poflr_port_detect_task函数)

pofdp_main_task():循环接收端口的packet进行转发处理,前一个包结束转发处理后才处理下一个包

  • 设定第一个默认instruction,即goto第一个表(set_goto_first_table_instruction),然后进入循环处理
  • 从端口packet接收队列中读取packet数据(pofdp_recv_raw)
  • packet长度检测、第一个表存在性检测,检测出错则释放此packet缓存
  • packet转发处理(pofdp_forward函数)

pofdp_forward():对packet进行流表匹配查找,并进行instruction处理,直到发送或是丢弃。

  • 初始化元数据(init_packet_metadata函数)
  • 第一个instruction的执行,即goto表1,然后继续流表匹配处理(pofdp_instruction_execute函数)

pofdp_send_raw_task():创建线程,循环读取端口发送队列的packet,进行发送

  • 创建发送socket,进入while循环
  • 从端口发送队列中读取packet内容(pofbf_queue_read函数)
  • 通过与物理端口绑定的socket进行packet发送(sendto函数)

pofdp_create_port_listen_task():设置端口的packet接收线程

pofdp_recv_raw_task():创建线程,循环读取端口packet,并放入端口接收队列中

  • 创建并绑定端口的socket,保持实时监听状态(socket,bind)。然后进入循环处理
  • 通过socket接收端口消息,存入buf
  • 检测端口的openflow使能、包长度,并根据规则过滤包
  • 将当前端口接受的packet放入端口接收队列中(pofbf_queue_write函数)

3.2 pof_instruction.c

pofdp_instruction_execute():循环读取packet的instructions,逐一执行。

  • while检测packet的instruction是否执行完
  • 对packet执行instruction(excute_##INSTRUCTIONS_NAME()函数)

excute_##INSTRUCTIONS_NAME():一些instruction的执行函数

  • execute_METER():速率限制
  • execute_WRITE_METADATA():将instruction中value字段数据写入matadata中。
  • excute_WRITE_METADATA():将packet中相应字段数据写入matadata中。
  • execute_GOTO_DIRECT_TABLE():根据全局table_id跳转到指定表,并且不需要匹配,直接得到跳转表中的指定的相应表项,执行表项动作。
  • execute_GOTO_TABLE():跳转表前先通过packet计算出key,跳转后直接用key进行匹配。
  • execute_APPLY_ACTIONS():包含不同action,如OUTPUT、ADD字段等。
  • execute_WRITE_ACTIONS(): 目前无,待开发。
  • execute_CLEAR_ACTIONS():待开发
  • execute_EXPERIMENTER():待开发

4 include目录:存放POF交换机的全部自定义的头文件,供其他文件调用。

5 common目录:最主要是action和Instruction相关的函数定义在这里。

  • pof_byte_trans:主要存放一些action和Instruction相关的函数等。
  • pof_log_print:和log打印相关函数。

后记

本文对POF交换机源码执行的主要流程进行总结,并绘制成函数关系调用图,可以供大家分析源码时候参考,此外,基于文件结构,对调用图中涉及到的主要函数进行简单的功能分析。有了以上代码了解,后文将会对POF交换机如何与控制器通信、数据包如何根据POF进行匹配与action处理等做进一步学习分析。

原文发布于微信公众号 - SDNLAB(SDNLAB)

原文发表时间:2016-01-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏PHP在线

PHP的错误机制总结

PHP的错误机制也是非常复杂的,做了几年php,也没有仔细总结过,现在就补上这一课。

2145
来自专栏用户2442861的专栏

tinyhttpd 剖析

http://blog.csdn.net/jcjc918/article/details/42129311

1852
来自专栏解Bug之路

MySql-Binlog协议详解-报文篇

#MySql-Binlog协议详解-报文篇 紧接上篇流程篇,本篇主要将binlog的event报文。 ##Event报文分层 event报文主要分三层。 (1...

1493
来自专栏大内老A

WCF技术剖析(卷1)之目录

第1章  WCF简介 (WCF Overview)     1.1  SOA基本概念的和设计思想        1.2  WCF是对现有Windows平台下...

2298
来自专栏草根专栏

用ASP.NET Core 2.0 建立规范的 REST API -- GET 和 POST

本文所需的一些预备知识可以看这里: http://www.cnblogs.com/cgzl/p/9010978.html 和 http://www.cnblog...

1361
来自专栏Python中文社区

Python网络编程中的套接字名和DNS解析

这一次要讲的是套接字名和DNS,并且还会涉及到网络数据的发送接受和网络错误的发生和处理。下面说套接字名,在创建和部署每个套接字对象时总共需要做5个主要的决定,主...

4057
来自专栏丑胖侠

Zookeeper开源客户端Curator之Master/Leader选举

在实际生产中,特别是分布式系统中,我们经常遇到这样的场景:一个复杂的任务,近需要从分布式机器中选出一台机器来执行。诸如此类的问题,我们统称为“Master选举”...

40610
来自专栏架构师之路

一分钟实现分布式锁

一、缘起 分布式环境下,多台机器上多个进程对一个数据进行操作,如果不做互斥,就有可能出现“余额扣成负数”,或者“商品超卖”的情况,如何实现简易分布式锁,对分布式...

4106
来自专栏闵开慧

tomcat6.0下找不到jasper-runtime.jar

今天有点需求,需要用jasper-runtime.jar包。但是我在我的\apache-tomcat-6.0.16\lib目录下,怎么也找不到这个jar包。结果...

3305
来自专栏黑泽君的专栏

day56_BOS项目_08

  注意1:权限数据属于比较特殊的数据,系统在上线之后,必须先把权限数据给它初始化到数据库中去,然后这个系统才可以跑起来。如果不初始化权限数据的话,那么登录上系...

1092

扫码关注云+社区

领取腾讯云代金券