Ryu:网络时延探测应用

之前,笔者已经发布了网络感知应用和基于跳数的最短路径转发应用。本文将介绍笔者开发的网络时延探测应用。该应用通过LLDP数据包的时延和Echo数据包的时延计算得出链路的时延数据,从而实现网络链路时延的感知。详细原理和实现步骤将在文章中详细介绍。

测试原理

网络时延探测应用利用了Ryu自带的Switches模块的数据,获取到了LLDP数据发送时的时间戳,然后和收到的时间戳进行相减,得到了LLDP数据包从控制器下发到交换机A,然后从交换机A到交换机B,再上报给控制器的时延T1,示例见图1的蓝色箭头。同理反向的时延T2由绿色的箭头组成。此外,控制器到交换机的往返时延由一个蓝色箭头和一个绿色箭头组成,此部分时延由echo报文测试,分别为Ta,Tb。最后链路的前向后向平均时延T=(T1+T2-Ta-Tb)/2。

图1. 测量链路时延原理图

获取LLDP时延

获取T1和T2的逻辑一样,均需要使用到Switches模块的数据。计算LLDP时延的处理逻辑如下代码所示。首先从Packet\_in中解析LLDP数据包,获得源DPID,源端口。然后根据发送端口的数据获取到portdata中的发送时间戳数据,并用当下的系统时间减去发送时间戳,得到时延,最后将其保存到graph数据中。

@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def packet_in_handler(self, ev):
        msg = ev.msg
        try:
            src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
            dpid = msg.datapath.id
            in_port = msg.match['in_port']
            if self.sw_module is None:
                self.sw_module = lookup_service_brick('switches')
            for port in self.sw_module.ports.keys():
                if src_dpid == port.dpid and src_port_no == port.port_no:
                    port_data = self.sw_module.ports[port]
                    timestamp = port_data.timestamp
                    if timestamp:
                        delay = time.time() - timestamp
                        self._save_delay_data(src=src_dpid, dst=dpid,
                                              lldpdelay=delay)
        except LLDPPacket.LLDPUnknownFormat as e:
            return

获取Echo时延

之后,我们还需要测试控制器到交换机之间的echo往返时延。其测量方法是通过在控制器给交换机发送携带有时间戳的echo\_request报文,然后解析交换机返回的echo\_reply,并用当下时间减去data部分解析的发送时间,获得往返时间差。所以我们需要完成echo\_request的定时发送和解析的实现,详细示例代码如下:

def _measure(self):
        while True:
            self._send_echo_request()
            hub.sleep(self.SLEEP_PERIOD)
    def _send_echo_request(self):
        for datapath in self.datapaths.values():
            parser = datapath.ofproto_parser
            data = "%.6f" % time.time()
            echo_req = parser.OFPEchoRequest(datapath, data=data)
            datapath.send_msg(echo_req)
    @set_ev_cls(ofp_event.EventOFPEchoReply, MAIN_DISPATCHER)
    def echo_reply_handler(self, ev):
        try:
            latency = time.time() - eval(ev.msg.data)
            self.echo_latency[ev.msg.datapath.id] = latency
        except:
            return

完成echo时延的计算之后,将其保存到echo\_latency字典中,已备后续计算使用。

计算链路时延

完成时延数据获取之后,还需要基于这些数据,计算出链路的时延,公式就是T=(T1+T2-Ta-Tb)/2。所以编写计算方法,示例代码如下。其中get\_delay方法用于计算对应交换机之间的链路时延,\_save\_delay\_data可以用于计算和存储lldp的时延和链路时延,其功能根据传入参数而定。而calculate\_link\_delay方法则用于调用计算方法,并将时延结果存储到networkx图数据结构中。

def get_dalay(self, src, dst):
        try:
            fwd_delay = self.graph[src][dst]['lldpdelay']
            re_delay = self.graph[dst][src]['lldpdelay']
            src_latency = self.echo_latency[src]
            dst_latency = self.echo_latency[dst]
            delay = (fwd_delay + re_delay - src_latency - dst_latency)/2
            return max(delay, 0)
        except:
            return float('inf')
    def _save_delay_data(self, weight='lldpdelay', src=0, dst=0, lldpdelay=0):
        if self.network_aware is None:
            self.network_aware = lookup_service_brick('network_aware')
            return
        else:
            self.graph = self.network_aware.graph
            if weight == 'delay':
                for src in self.graph:
                    for dst in self.graph[src]:
                        if src == dst:
                            self.graph[src][dst][weight] = 0
                            continue
                        self.graph[src][dst][weight] = self.get_dalay(src, dst)
            elif weight == 'lldpdelay':
                try:
                    self.graph[src][dst][weight] = lldpdelay
                except:
                    return
    def calculate_link_delay(self):
        self._save_delay_data(weight='delay')

至此关于网络拓扑中链路时延的获取应用开发完成。需要注意的是,本应用需要依赖Ryu的topology/switches.py模块,所以如果单独使用时,需要配套启动switches.py。另外,与前面发表的应用相互结合,此应用中的graph是之前的network\_aware模块感知的网络拓扑数据graph。

时延探测应用运行结果截图如图2所示。

图2.时延监控应用运行结果

总结

网络时延数据是网络重要数据,是许多网络决策的重要依据,所以网络时延数据测量非常重要。本文介绍了如何在Ryu中开发时延探测应用,并粘贴了关键的代码,希望对读者的学习提供一定的帮助。此外,还需要注意两点:(1)此时延探测模块十分初级,并没有精确性方面的考虑,比如需要将其放在核心层实现,在发送的最后时刻才添加时间戳,收到数据包的第一时刻马上解析时间戳等等,所以精确性不足。在Mininet模拟场景下,最开始的几组数据将会异常,但很快就可以恢复正常。(2)此处的拓扑数据均基于两个交换机之间仅有单链路存在的假设。若存在多链路,则数据会被最后获取的链路覆盖。解决这一问题的办法就是采用Neworkx的MultiGraph图结构来存储数据。最后希望本文能给读者带来一定的帮助,完整代码将于6月发布,敬请期待。

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

原文发表时间:2016-05-19

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏听雨堂

连续打印问题的解决

主要是纸张的高度无法控制! 情况如下:     打印一个窄行的自定义单据,通过设置自定义纸张,可以控制打印机每次严格按照自定义的大小进行打印只打单张的情况下,没...

23290
来自专栏Vamei实验室

协议森林07 傀儡 (UDP协议)

作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁任何形式转载。 我们已经讲解了物理层、连接层和网络层。最开始的连接层协议种...

23660
来自专栏同步博客

OSI七层模型学习笔记

  OSI模型全名Open System InterConnect 即开放式系统互联,是国际标准化组织(ISO)提出的一个试图使各种计算机在世界范围内互连为网络...

12350
来自专栏吴伟祥

OSI七层模型 原

模型把网络通信的工作分为7层。1至4层被认为是低层,这些层与数据移动密切相关。5至7层是高层,包含应用程序级的数据。每一层负责一项具体的工作,然后把数据传送到下...

22370
来自专栏网络

TCP/IP四层模型讲解笔记整理通俗易懂版

OSI七层模型和TCP/IP四层模型,以前总觉得这些纯理论层面的东西对实战没有什么意义,现在回头看看还是非常有意义的,不过放在当时我也懒得学这么枯燥的东西。 接...

280100
来自专栏xcywt

IP协议和网络传输中的封装与分用。

关于七层模型和四层模型可以参考这个:http://www.cnblogs.com/xcywt/p/5027277.html 因为四层模型用的比较多,这里只拿四层...

23060
来自专栏JetpropelledSnake

Python Web学习笔记之图解TCP/IP协议和浅析算法

21240
来自专栏zhisheng

那些不能遗忘的知识点回顾——计算机网络系列(笔试面试高频题)

前两天发表了“那些不能遗忘的知识点回顾——操作系统系列(笔试面试高频题)”和“那些不能遗忘的知识点回顾——C/C++系列(笔试面试高频题)”文章,没看的赶紧在公...

42360
来自专栏运维小白

TCP/IP三次握手四次挥手

背景 和女朋友异地恋一年多,为了保持感情我提议每天晚上视频聊天一次。 从好上开始,到现在,一年多也算坚持下来了。 问题 有时候聊天的过程中,我的网络或者她的网...

27950
来自专栏土豆专栏

计算机网络基础知识整理--数据链路层

小编最近在复习计算机网络基础,整理出来一些我认为比较重要的知识。希望能帮到大家哈,后续会更新~

827120

扫码关注云+社区

领取腾讯云代金券