SDN实验(四):测定链路时延
当一个 SDN 网络建立时,Ryu 控制器通过 LLDP 数据包与交换机通信,获取网络的各种信息。借助 LLDP 数据包上的时间戳,控制器可以测定两个交换机之间的传输时延,用于寻找数据传输的最短路径等。
在 Ryu 中维护端口时延
Ryu 维护的端口信息在ryu/ryu/topology/switch.py
中定义为PortData
类,可以修改其__init__
来增加属性。当 LLDP 数据包规划从某个端口发送时,对应实例就会更新时间戳timestamp = time.time()
。
这里再加上一个时延属性
用于记录根据该端口转发出的 LLDP 包计算的时延。听来有些拗口,若用图示转发过程
则 LLDP 包的生命周期是:(以绿色箭头所示为例)
- 由 Ryu 控制器构造,发送时对应 S2 交换机上某个端口的
PortData
实例更新时间戳。 - 被 S2 交换机转发给 S1 交换机。
- 被 S1 交换机发送给控制器,触发 Packet-In ,控制器收到后,可以解析出这个 LLDP 包的源端口是 S2 上的某个端口。
RyuApp 是运行于控制器的程序,维护的PortData
也都在控制器端。第一步的时间戳是控制器发送 LLDP 包的时间,第三步的“当前时间”是控制器收到包的时间。因此,用当前时间减去时间戳,得到的就是 LLDP 数据包经过三步所用的总时延。这个时延维护在PortData
实例的delay
属性里。
为了用上述方法更新delay
属性,还需要改动ryu/ryu/topology/switch.py
中的Switches
类,在它的lldp_packet_in_handler
方法中更新self.ports
[1]维护的所有端口。
用类似的方法可以得到反方向(红色箭头所示)的时延。
估计往返时延 RTT
网络链路的时延是实时变化的,只能进行估计式的测量。
LLDP 数据包被控制器发给交换机后,转发一次(一跳)就会被再次发回控制器。在上方图示的过程中,往返两次转发的总时延可以表示为 ,另一方面,这也是如下两项的和:
- 交换机 S1 和 S2 之间的往返时延
- 控制器到两台交换机的往返时延
由此得到 ,可以用这个式子估计往返时延[2](忽略了构造、解析、转发数据包的时间)。
OpenFlow 的 Echo Request/Reply 消息可以用于测量 两个时延,具体方法是:周期性发送以时间戳作为数据的 Echo Request ,时间戳会被 Echo Reply 回送,与当前时间相减即得时延。
网络同步对数据的影响
应用运行在控制器上,但数据需要等待网络传输。LLDP 时延和 Echo 往返时延都需要等待数据包传回,任何一个为空都不能计算 RTT ;即使这些数据都就位,也未必正确。
控制器端调用dp.send_msg
,会把相应数据包送入消息队列。如果大量数据包同时发送,有些数据包可能等待一段时间,但附加在数据包中的时间戳是送入队列的时间,并非实际发出的时间。于是 Echo 往返时延有可能异常地长——例如数十毫秒——甚至比测出的 LLDP 时延还要长。依此计算,网络的拓扑图中将出现负权边,即到达在发送之前,这显然不可能。
那么,一方面需要让 Echo Request 较为均匀地发送,避免集中;另一方面需要检查算出的链路往返时延是否为负,避免构造出负权边。
协程调度问题
实验是在 ARPANET 网络拓扑上进行,一共有三个协程:
- 消息处理协程(由 App Manager 启动的主协程)
- 更新拓扑并下发生成树的协程(解决 ARP 广播风暴)
- 发送 Echo Request 获取时延的协程
每个协程都要等待其他协程主动让出 CPU 才能执行,因此任何一个协程必须控制自己的执行时间,否则其他协程可能不能正常执行[3]。对于发送 Echo Request 的协程,每发送一轮之后应该hub.sleep
主动休眠足够长的时间,所以最后的_send_echo_request
是这样:
说明
SDN 课内实验共有四次,第一次的“自学习交换机”参考资料多如牛毛,我自不必赘述;最后一次实验介绍的 VeriFlow 工具,精华在于论文[4],对此我只有献丑之技,没有剖析之能,亦不再记录。
这几篇文章大多来自作业和实验报告,以提取思路、增进理解为主,增删过一些内容。时间所限,我并没有太多时间将实验的内容和相关技术资料认真整理成笔记,只借此简单提取、留档;也希望可以作为日后同学粗疏的参考。若有所助力,不胜荣幸。
Ryu 的资料主要有两个来源,均为官方维护人员编写:
-
Read The Docs 文档,介绍 Ryu 中关于应用、协议 API ,但对于源码结构、协程调度没有讲解。
-
Ryu Book ,讲解 Ryu 如何使用、如何工作,详尽全面,只是不太方便查。
注释
[1]^这是一个键为Port
实例,值为PortData
实例的字典。
[3]^我的程序因此出现了各种奇怪的 Bug ,包括但不限于:时而正常工作时而卡在发送 Echo Request 的过程中、根据 Echo Reply 计算的时延很大(很小)、始终不能向所有的交换机发出 Echo Request ,等等。不外乎是影响了消息处理和更新拓扑的协程正常工作。
[4]^Ahmed Khurshid, Xuan Zou, Wenxuan Zhou, Matthew Caesar, P. Brighten Godfrey. VeriFlow: Verifying Network-Wide Invariants in Real Time. In NSDI