基于RYU的拓扑发现

前言

本次实验是一个基于RYU的拓扑发现功能。参考了呈神的实现方式,并加了一些自己实现方式,做了一些数据结构的改动。

数据结构

  • link_to_port 字典

    有两种关系:

    一是记录交换机与交换机之间的链接 (src_dpid, src_port_no) => (dst_dpid, dst_port_no)

    一是记录交换机与控制器之间的链接 (dpid, port_no) =>(mac, ip)

  • host_or_switch 字典

    用来记录交换机连的端口连接的为何种类型的设备 (dpid, port_no) =>

    1:交换机

    2:主机

    其他:没有连接

  • switch_port_table 字段

    用来记录交换机的端口 , (dpid) => [1,2,....]

相关API的使用

API是基于ryu源代码topology/switches下的使用,并使用了三个api

  • get_switch 获取交换机列表
  • get_link 获取链路信息
  • get_host 获取主机信息

实验代码

  1. #-*- coding: UTF-8 -*-
  2. import logging
  3. from ryu.base import app_manager
  4. from ryu.controller import ofp_event
  5. from ryu.controller.handler import MAIN_DISPATCHER, DEAD_DISPATCHER
  6. from ryu.controller.handler import CONFIG_DISPATCHER
  7. from ryu.controller.handler import set_ev_cls
  8. from ryu.ofproto import ofproto_v1_0
  9. from ryu.ofproto import ofproto_v1_2
  10. from ryu.ofproto import ofproto_v1_3
  11. from ryu.lib.packet import packet
  12. from ryu.lib import hub
  13. from ryu.topology import event, switches
  14. from ryu.topology.api import get_switch, get_link, get_host
  15. from ryu import cfg
  16. CONF = cfg.CONF
  17. class test_wpq(app_manager.RyuApp):
  18. OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION,
  19. ofproto_v1_3.OFP_VERSION]
  20. def __init__(self, *args, **kwargs):
  21. super(test_wpq, self).__init__(*args, **kwargs)
  22. self.topology_api_app = self
  23. self.link_to_port = {}
  24. self.host_or_switch = {}
  25. self.switch_port_table = {}
  26. self.name = "wpq"
  27. self.discover_thread = hub.spawn(self._discover_links)
  28. #A thread to output the information of topology
  29. def _discover_links(self):
  30. while True:
  31. self.get_topology(None)
  32. try:
  33. self.show_topology()
  34. except Exception as err:
  35. print "please input pingall in mininet and wait a memment"
  36. hub.sleep(5)
  37. #add entry of table-miss
  38. @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
  39. def switch_feature_handle(self, ev):
  40. msg = ev.msg
  41. print msg
  42. datapath = msg.datapath
  43. ofproto = datapath.ofproto
  44. parser = datapath.ofproto_parser
  45. self.logger.info("switch %s is connected", datapath.id)
  46. match = parser.OFPMatch()
  47. actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER)]
  48. self.add_flow(datapath=datapath, priority=0, actions=actions, match=match)
  49. def add_flow(self, datapath, priority, actions, match, idle_timeout=0, hard_timeout=0):
  50. ofp = datapath.ofproto
  51. parser = datapath.ofproto_parser
  52. inst = [parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
  53. actions)]
  54. mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
  55. idle_timeout=idle_timeout,
  56. hard_timeout=hard_timeout,
  57. match=match, instructions=inst)
  58. datapath.send_msg(mod)
  59. #fill the port of switch imformation
  60. def create_map(self, switch_list):
  61. for sw in switch_list:
  62. dpid = sw.dp.id
  63. self.switch_port_table.setdefault(dpid, set())
  64. for p in sw.ports:
  65. self.switch_port_table[dpid].add(p.port_no)
  66. # print "--------------交换机端口情况---------------"
  67. # print self.switch_port_table
  68. #fill the link information
  69. def create_link_port(self, link_list, host_list):
  70. for link in link_list:
  71. src = link.src
  72. dst = link.dst
  73. self.link_to_port[(src.dpid, src.port_no)] = (dst.dpid, dst.port_no)
  74. self.link_to_port[(dst.dpid, dst.port_no)] = (src.dpid, src.port_no)
  75. self.host_or_switch[(src.dpid, src.port_no)] = 1
  76. self.host_or_switch[(dst.dpid, dst.port_no)] = 1
  77. for host in host_list:
  78. port = host.port
  79. self.link_to_port[(port.dpid, port.port_no)] = (host.mac, host.ipv4)
  80. self.host_or_switch[(port.dpid, port.port_no)] = 2
  81. #packein message handler (it is useless in this function)
  82. @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
  83. def packetin_handler(self, ev):
  84. # print ev.msg
  85. msg = ev.msg
  86. pkt = packet.Packet(msg.data)
  87. # print pkt.get_protocols
  88. dpid = msg.datapath.id
  89. port = msg.match['in_port']
  90. self.get_topology(None)
  91. events = [event.EventSwitchEnter,
  92. event.EventSwitchLeave, event.EventPortAdd,
  93. event.EventPortDelete, event.EventPortModify,
  94. event.EventLinkAdd, event.EventLinkDelete]
  95. #monitor the change in link information
  96. @set_ev_cls(events)
  97. def get_topology(self, ev):
  98. self.create_map(get_switch(self.topology_api_app))
  99. # print get_host(self.topology_api_app)
  100. # print type(get_host(self.topology_api_app))
  101. self.create_link_port(get_link(self.topology_api_app), get_host(self.topology_api_app))
  102. # self.show_topology()
  103. #some command line output typesetting
  104. def show_topology(self):
  105. i = 1
  106. print ""
  107. print ""
  108. print ""
  109. print "----------------" * 2, "physical topology", "----------------" * 6
  110. for dpid in self.switch_port_table.keys():
  111. print "switch%d ----------dpid---------- " % i,
  112. for port_no in self.switch_port_table[dpid]:
  113. print "-----------port %s-----------" % port_no,
  114. print ""
  115. print " ", "%11d" % dpid ,"%12s" % " ",
  116. # # print self.switch_port_table[dpid]
  117. try:
  118. for port_no in self.switch_port_table[dpid]:
  119. if self.host_or_switch[(dpid, port_no)] == 1:
  120. print "%10s" % "switch", "%d" % self.link_to_port[(dpid, port_no)][0], " port %d" % self.link_to_port[(dpid, port_no)][1], " ",
  121. elif self.host_or_switch[(dpid, port_no)] == 2:
  122. print "%s" % "host", "mac: %s" % self.link_to_port[(dpid, port_no)][0],
  123. else:
  124. print "%28s" % "None"
  125. print ""
  126. print " ", "%23s" % " ",
  127. for port_no in self.switch_port_table[dpid]:
  128. if self.host_or_switch[(dpid, port_no)] == 2:
  129. print " ipv4 :", self.link_to_port[(dpid, port_no)][1],
  130. else:
  131. print "%28s" % " ",
  132. print
  133. except Exception as error:
  134. print "please input pingall in mininet and wait a momment until it's finished"
  135. i = i + 1
  136. print "------------------" * 8
  137. print ""
  138. print ""
  139. print ""

细节点

这也是我调了半天的一个bug,使用hub.spawnhub.sleep配合的函数,应该可以达到停几秒休息一次的作用,尝试很多无果,后来自己随便建了一个没有消息处理机制的函数进行测试,发现其却能正常运行。究其原因,后面原来是自己没有异常处理。异常处理很重要!!!

实验效果图

实验缺陷

对于不同的终端可能适配不一样,尽量放大到全屏看的比较直观,如果设备多了,这个显示依然是一片模糊,后期将加入一个做成json,做成web可视化

实验总结

这个程序有一大部分得感谢呈神的参考,还有其他部分也是自己对python的一些类似循环,字典的一些应用,懂得去debug,对python不会那么陌生。

基于RYU的拓扑发现的更多相关文章

  1. 基于SNMP的路由拓扑发现算法收集

    一.三层(网络层)发现 算法来源:王娟娟.基于SNMP的网络拓扑发现算法研究.武汉科技大学硕士学位论文,2008 数据结构: 待检路由设备网关链表:存放指定深度内待检路由设备的网关信息,处理后删除. ...

  2. OpenFlow 1.3 控制器与交换机的交互,以及拓扑发现

    前言 最近纠结于控制器如何发现拓扑,于是就翻起了OpenFlow 1.3进行查看,以及一些相关协议 OF 1.3 安全通道,即交互消息 OpenFlow Switch Specification 1. ...

  3. 提高SDN控制器拓扑发现性能

    原文由我发表在sdnlab.com.原文链接:http://www.sdnlab.com/15425.html SDN网络的一大特点就是资源由控制器集中管理,控制器管理网络,最基本的当然需要知道网络的 ...

  4. 基于Ryu REST API的VLAN实现

    目录 0.预备知识 1.实验内容 2.编写脚本addflow.sh一步实现流表下发 3.使用api查看流表 4.实验结果 0.预备知识 ryu控制器的API文档:ryu.app.ofctl_rest ...

  5. 两款商业拓扑发现软件siteview和ElementSentry的比较

    今天在公司试用了一下两款商业拓扑发现软件游龙科技的siteview和速方软件ElementSentry. 条目/产品 速方软件ElementSentryv5.0 游龙科技Siteview NNM v3 ...

  6. prometheus 基于DNS的目标发现

    prometheus 基于DNS的目标发现 DNS服务发现依赖于查询A.AAAA或SRV DNS记录. 1.基于 SRV 记录发现 scrape_configs: - job_name: 'webap ...

  7. prometheus — 基于文件的服务发现

    基于文件的服务发现方式不需要依赖其他平台与第三方服务,用户只需将要新的target信息以yaml或json文件格式添加到target文件中 ,prometheus会定期从指定文件中读取target信息 ...

  8. prometheus 基于文件的目标发现

    prometheus 基于文件的目标发现 1.创建目录 cd /usr/local/prometheus/conf mkdir -pv targets/{nodes,docker} 2.修改prome ...

  9. 基于Ryu的服务器实现及相关请求访问处理

    基于Ryu的服务器实现及相关请求访问处理 前言及问题描述 近期又遇到了一个非常棘手的问题,由于Ryu是通过Python语言开发的,通过Ryu的wsgi的方式建立服务器,无法解析PHP,通过多次方法解决 ...

随机推荐

  1. Angular2学习笔记(1)——Hello World

    1. 写在前面 之前基于Electron写过一个Markdown编辑器.就其功能而言,主要功能已经实现,一些小的不影响使用的功能由于时间关系还没有完成:但就代码而言,之前主要使用的是jQuery,由于 ...

  2. Please select Android SDK解决办法

    项目不能运行,提示如下  打开项目local.properties文件,查看sdk地址是否正确,注意区分大小写  如果sdk地址正确,那么点击File-Sync Project with gradle ...

  3. Linux之Vim学习

    Linux之Vim学习 一般模式 光标移动 按键 作用 j或down方向键 向下移动一个字符 k或up方向键 向上移动一个字符 h或left方向键 向左移动一个字符 l或right方向键 向右移动一个 ...

  4. Android学习笔记--通过wifi向服务器端发送数据

    (转自http://www.cnblogs.com/zhxiang/archive/2011/07/21/2112825.html) 客户端程序: 1 2 3 4 5 6 7 8 9 10 11 12 ...

  5. IntelliJ IDEA 2018.3发布

    本文转自:https://www.linuxprobe.com/intellij-idea-2018-3-java-12.html

  6. Python2.7-fractions

    fractions 模块,提供分数格式存储数据,没多大用处,除了模块里的最大公约数函数 gcd(a,b) 模块类和方法: fractions.Fraction(numerator=0, denomin ...

  7. Android给拼接好的Bitmap加上个性化边框

    在上一节中将到将若干张图片拼接成为一张图片.但是这种简单的操作往往不能满足实际的需求,有时我们会需要给图片添加上个性化的边框,来更好的展示图片. 下面就讲一下在图片拼接后如何给bitmap添加边框. ...

  8. 20155204 王昊《网络对抗技术》EXP4

    20155204 王昊<网络对抗技术>EXP4 一.实验后回答问题 (1)如果在工作中怀疑一台主机上有恶意代码,但只是猜想,所有想监控下系统一天天的到底在干些什么.请设计下你想监控的操作有 ...

  9. 20155217《网络对抗》Exp04 恶意代码分析

    20155217<网络对抗>Exp04 恶意代码分析 实践内容 使用schtasks指令监控系统运行 使用sysmon工具监控系统运行 使用virscan分析恶意软件 使用systrace ...

  10. 20155233 《网络对抗》Exp4 恶意代码分析

    使用schtasks指令监控系统运行 先在C盘目录下建立一个netstatlog.bat文件,用来将记录的联网结果格式化输出到netstatlog.txt文件中,netstatlog.bat内容为: ...