Ryu的一些设计方法解读

作为一个业余研究Ryu的软件工程师,一直惊叹于Ryu设计的优雅与简洁。一年多坚持下来,也有自己的一些收获,写出来和大家分享一下。

我们的故事从@set_ev_cls这个被大量使用的装饰器开始。

装饰器的内容已经有小伙伴写到了,这里不再重复。我关心的重点在第一个参数ev_cls上,

比如simple_switch_13.py中@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)

EventOFPPacketIn,类究竟在哪定义,我在\ryu\controller\ofp_event文件中没有找到,甚至搜索完了整个ryu工程都没有搜到。与此类似的ofp_event.EventOFPPortStatus, ofp_event.EventOFPFlowRemoved,ofp_event.EventOFPDescStatsReply等等,他们这些类的定义也没有找到。

某个烈日炎炎的下午,不经意的我在\ryu\controller\ofp_event文件中发现了一点蛛丝马迹:

将ofp的msg名字加上“Event的前缀”,这个有点像。

喔,这个地方creat了一个类,好像就是ev_class(type的用法:创建类的类,元类,以name为类型,以EventOFPMsgBase为父类,并定义了初始化方法,并放到全局字典globals和_OFP_MSG_EVENTS),动态生成需要的类,小样,真有你的。

更进一步从模块名创建ev_class,明确标明了,有'cls_msg_type'属性的才有资格创建类。

终于看到调用的地方了,在同一个文件中的这段代码可不是定义函数,而是直接执行语句哦。其中get_ofp_modules就是获取ofp的版本文件的parser,然后根据这些文件创建对应了msg_ev_class.我们去ryu\ofproto\ofproto_v1_X_parser(X可以为0,1,2,3,你懂的)文件中确认一下。

看,还真是这样。连注释上都写得是一模一样的Example,其他诸如ofp_event.EventOFPPortStatus, ofp_event.EventOFPFlowRemoved,ofp_event.EventOFPDescStatsReply也能找到对应的地方。

这下终于真相大白,我们脑海中有了这样一幅画面,自动去搜索ofp不同版本的模块,找到有cls_msg_type属性的类,然后把它们的名字变换一下,生成对应的类。Ryu的优美与简洁,果然名不虚传。

还有我们的ofp_msg_to_ev,看它的定义是生成类的实例。在Datapath类的_recv_loop中,Ryu从数据流中解析出msg,然后根据msg生成上面msg_ev_class的实例,并通过ofp_brick发送给观察者。send_event_to_observers(ev, self.state)是通过SERVICE_BRICKS(服务实体链表,其实就是所有app的字典)来进行不同模块中的通信的。

在RyuApp的register_handler,register_observer可以看到,观察者和handler的注册都是通过类名。而RyuApp的get_handlers,get_observers方法传入得参数是实例。

这样我们就知道了@set_ev_cls如何用ofp的event类去修饰handler方法,以及如何由具体的报文,得到对应的实例,最后调用到具体的handler方法上。良好的命名规范还真有助于增加代码的可读性。

我们的李呈大神在《RYU源码解读》(http://www.sdnlab.com/6395.html)已经把ryu的启动流程给我们大致讲解了。

不过我本人觉得还不过瘾,有几点在这里补充一下。

1.hanglder.reuster_service是在import的时候被执行的,一般都在app文件的最开头,而不是在使用@set_ev_cls装饰器的时候。

2._Event的使用在\ryu\topology\switches中有如下代码

而在\ryu\base\app_manager文件中有

从这些线索中我们可以看到_EVENTS其实就是上文中动态生成的msg_ev_class的补充,因为不属于OFP模块的内容,自然需要other模块提供。当然Event类的来源还通过import得到,比如\ryu\lib\lacplib.py就定义了大量的Event类,simple_switch_lacp_13.py就是通过from ryu.lib import lacplib来使用的。

3.@set_ev_cls还有个兄弟@set_ev_handler,在\ryu\app\gre_tunnel和\ryu\controller\ofp_handler有使用。两者的区别在set_ev_handler收到对应的事件后自己处理就行了,不需要再通知给observer,而set_ev_cls先通知给observer,再自己处理。原因如下

读完了这些,不得不感叹,RYU实在是太美妙了。它的内部机制的实现,很值得我们学习和借鉴。

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

原文发表时间:2016-10-10

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小程序·云开发专栏

小程序·云开发的云函数路由高级玩法

在掘金开发者大会上,在推荐实践那里,我有提到一种云函数的用法,我们可以将相同的一些操作。

9K130
来自专栏丑胖侠

《Drools 7 规则引擎教程》番外篇-规则条件匹配机制

问题场景 QQ技术群(593177274)中有同学遇到这一个问题场景:在多条规则(比如3条)的when中使用了一个相同的静态方法,并在静态方法中打印相关的日志信...

27680
来自专栏恰童鞋骚年

.NET单元测试的艺术-3.测试代码

开篇:上一篇我们学习单元测试和核心技术:存根、模拟对象和隔离框架,它们是我们进行高质量单元测试的技术基础。本篇会集中在管理和组织单元测试的技术,以及如何确保在真...

9230
来自专栏诸葛青云的专栏

C语言编程实例:清空对方应用程序

今天的文章跟大家讲一下,C语言中的文件操作——遍历文件夹和删除文件,以及如何应用这两个技能来写一个有趣的小程序,这篇文章涉及的知识点很少,也很简单,所以这篇文章...

21000
来自专栏Python入门

这4个Python实战项目,让你瞬间读懂Python!

Python当下真的很火。Python实战项目,也一直尤为关注,接下来,和大家介绍下十个Python练手的实战项目

20640
来自专栏从零开始学自动化测试

python笔记11-多线程之Condition(条件变量)

前言 当小伙伴a在往火锅里面添加鱼丸,这个就是生产者行为;另外一个小伙伴b在吃掉鱼丸就是消费者行为。当火锅里面鱼丸达到一定数量加满后b才能吃,这就是一种条件判断...

40250
来自专栏优启梦

渗透测试中的域名伪装原理

今天在《网络渗透测试--保护网络安全的技术、工具、过程》一书中看到了一个关于对恶意链接进行域名伪装的方法,以前从不知道的一个方法,特此记录下来:

22450
来自专栏java一日一条

Java 元编程及其应用

同样是实现一个投票系统,一个是python程序员,基于django-framework,用了半小时就搭建了一个完整系统,另外一个是标准的SSM(Spring-S...

22610
来自专栏技术记录

谈谈序列化—实体bean一定要实现Serializable接口?

导读:最近在做项目的过程中,发现一个问题,就是我们最开始的时候,传递参数包括返回类型,都有map类型。但是由于map每次都要匹配key值,很麻烦。所以在之后就将...

47680
来自专栏逸鹏说道

04. Web大前端时代之:HTML5+CSS3入门系列~Input新增类型

Web大前端时代之:HTML5+CSS3入门系列:http://www.cnblogs.com/dunitian/p/5121725.html 1.tel:输入...

29070

扫码关注云+社区

领取腾讯云代金券