最近很多SDN研究人员问起如何安装RYU的GUI,网上也有一些教程。但是由于RYU版本问题,导致安装没有成功。本篇博文将介绍RYU3.16版本下如何安装GUI,以及对RYU拓扑模块进行简单分析。
安装GUI
Linton的博客已经有详细介绍,我在这里将一些可能出现问题的地方再提醒一次。
第一步:依赖安装及修改代码
建议查看Linton的博客,比较简单,不赘述。
第二步:运行相关组建
- 运行RYU相关APP
1 |
ryu-manager --verbose --observe-links app/simple_switch_13.py ryu.topology.switches ryu.app.rest_topology ryu.app.ofctl_rest |
运行截图如下:
- 运行controller.py文件
进入到gui目录,运行controller.py文件。
1 |
python controller.py |
- 访问页面
打开浏览器,访问http://127.0.0.1:8000页面。查看到connected to 127.0.0.1:8080信息则为连接成功。
Note that: 如果没有显示connected to 127.0.0.1:8000等信息,而显示Disconnected, 那么需要重新启动RYU的相关APP,再刷新网页,重新链接。运行controller.py的终端不需要动。
若连接成功,启动mininet与控制器连接,则可发现网页逐步在显示网络拓扑,点击交换机图标可查看详细信息。
众多网友表示3.19+版本无法成功使用GUI,可参考:RYU3.20 GUI DOC 进行安装使用。
TOPOLOGY源码分析
有一个小伙伴已经在我之前发布了详细的代码介绍,我不再赘述,大家有兴趣的可以前往查看:Ryu拓扑发现原理分析
在topology目录中,switches.py最重要。在switches.py文件中,核心的类是class Switches。
在Switches类中,我们仅仅需要关注几个重要的函数即可将大体的拓扑发现逻辑理清。
- __init__()
初始化函数初始化了一些重要的内容,如dps,ports,links等。并将lldp_loop和link_loop这两个函数加入线程(协程)。
- packet_in_handler()
此函数用于解析LLDP报文,从而提取出对应的信息,得到link信息。
- lldp_loop()
调用了send_lldp_packet()函数,循环发送LLDP报文的函数。
- link_loop()
实时检测link事件,及时发现拓扑变化,生产对应的event,并通过send_event_to_observers提供和观察者。
使用Switches模块
在实验过程中,实验人员往往需要得到网络拓扑的信息,不仅仅是dpid,link,port这些零散的元素,而是一张图。这张图往往由邻接矩阵或关联矩阵。所以一下的内容将介绍如何将dpid,link等信息转化成邻接矩阵和关联矩阵,以便后续的算路算法使用。
在你开发的模块中,将Switches作为context加载,并在__init__函数中将其赋值给某一变量。
1 2 3 4 5 6 7 8 9 |
_CONTEXTS = {'switches': switches.Switches } def __init__(self, *args, **kwargs): super(yourapp, self).__init__(*args, **kwargs) self.switches = kwargs['switches'] self.threads = [] self.threads.extend([hub.spawn(self._link_monitor),]) |
self.threads用于保存线程。将_link_monitor函数作为执行体,加入线程执行。函数简单定义如下:
1 2 3 4 5 6 |
def _link_monitor(self): while(self.is_active): if self.links != self.dp_tracker.links.keys(): self.dps = self.dp_tracker.dps self.links = self.dp_tracker.links.keys() hub.sleep(1) |
从_link_monitor函数中可以获取到dps,links等数据。这些数据需要整理存储,以便使用,get_graph函数就是用于将数据存储在图中的函数:定义函数get_graph,函数返回值是两张图,其中图graph_cap记录两个交换机之间的链路能力,图graph_port则记录的是从src到dst的源端口,目的端口信息保存在图的对称节点上。详细代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def get_graph(self): graph_cap = {} graph_port = {} for dpid in self.dps.keys(): for link in self.links: if link.src.dpid == dpid: graph_cap.setdefault(dpid, {}) graph_port.setdefault(dpid, {}) neighbor = link.dst.dpid capacity = link.dst.curr_speed graph_cap[dpid][neighbor] = capacity graph_port[dpid][neighbor] = link.src.port_no return graph_cap, graph_port |
至此,网络拓扑图生成完毕。在运行最短路径或者其他的路径计算算法时,可使用get_graph返回的数据。
总结
一直以来做实验并不需要可视化拓扑界面,直到最近发现许多研究者频繁提问,才想起来尝试这个实验。但事实上,我觉得Switches模块的使用是一个更重要的内容。很多情况下,我们需要的是原始的数据,而不是展示出来的界面。本文内容比较简单,希望能帮助到一些SDN学习者。
作者简介:
李呈,2014/09-至今,北京邮电大学信息与通信工程学院未来网络理论与应用实验室(FNL实验室)攻读硕士研究生。