通信网系列实验(二)——基于Kruscal算法的广播通信业务

在Ryu控制器中,使用Kruscal算法计算广播使用的最小生成树,并在Mininet配
置,实现最小生成树的多播通信。

Ryu与Mininet相关安装与配置详见:

https://blog.csdn.net/haimianxiaojie/article/details/50705288

关于本文内所有完整代码详见:

https://github.com/PPPerry/Ryu_projects中的Kruscal部分

本实验所用拓扑结构同系列实验(一)。拓扑代码稍有变化,详见完整代码。

实现内容如下:

  1. 使用Kruscal算法计算广播使用的最小生成树,输入为一个13*13的矩阵,存储着拓扑图中所有的边及相应的权重。输出为一个列表,存储着通过Kruscal算法计算得到的最小生成树中需要的边。
    Kruscal算法代码如下:
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第1张图片
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第2张图片
    算法详解:
    算法总体思想:按照边的从小到大取边;取权重最小的一条边,若该边两个节点均为不同分量,则加入最小生成树;在这个过程中保证并入边后不构成圈;以此类推,直至遍历完所有的边。
    (1)先获取矩阵的节点数nodenum和边数edgenum,创建最小生成树列表result_list;
    (2)进行边界判断:如果点的个数是负数,或者边的数量小于点的数量-1,即不是全连通,直接返回空列表result_list;
    (3)创建存储边的列表edge_list,遍历各个节点,找到连接每个点的边,以[节点i,节点j,权重]的元素形式存储在edge_list中;
    (4)依据权重,利用sort对列表edge_list中的元素(边)升序排序;
    (5)利用列表解析创建节点列表group,判断边两端节点是否相等,若符合不相等(不成环)的条件,则将边添加至最小生成树列表result_list中;
    (6)重复“加边”操作,最后输出最小生成树列表result_list。

  2. 将我们计算出来的边的列表,通过输入根节点,转换成我们配置路径时所需要的格式。此过程中格式经过多种变换。
    首先,将计算出来的包含边和权重的列表转换成一个包含任一节点可到达节点的列表的列表。
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第3张图片
    其次,再根据根节点(发包的主机),将该列表转换成[前节点,该节点,后节点]形式的列表。
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第4张图片
    再其次,将后节点整合成列表:
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第5张图片
    再再其次,将前节点和该节点也整合进列表中:
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第6张图片
    最后,根据发现拓扑时确定的各个交换机之间相连的端口,确定最终配置路径时需要的路径,获得相应格式。

  3. 确定完配置路径后,下一步是将求出来的路径导入到configure_path函数中,完成流表下发。
    与系列实验(一)相比,configure_path()函数需要改动的很少。
    和系列实验(一)不同,系列实验(一)是实现单播,交换机是从一个端口接收数据包,然后向另一个端口转发。
    而本实验是实现多播,交换机从一个端口接收数据包,然后一次性向多个端口转发。系列实验(一)里面洪泛就是这种情况。
    重要部分是:
    在这里插入图片描述
    actions是一个列表。在Python里,列表是可变对象,可以增加里面的元素。只有一个元素时,就意味着向一个端口转发,每增加一个元素,就表示同时向多一个端口转发。通过改变actions,实现我们的多播路径配置。

  4. 编写完相应部分的代码后,我们开始在mininet和ryu平台上进行实验验证。
    ryu连接mininet后,成功发现拓扑,并打印出此时拓扑相关信息。同时生成我们所求的最小生成树。
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第7张图片
    其中,linkList是使用Kruscal算法计算广播使用的最小生成树的边的列表,第三个元素是边的权重。path是计算出来的路径,用于下发流表,其中第三个元素是交换机发送包时对应的相关端口。(此时未加入可视化代码,权重体现不直观,mst拓扑图的可视化请见报告的后一部分)
    在后面的测试中,我们测试时是使用iperf灌udp包进行测试,所以最好再配一条反向的路径。比如以主机4作为起点进行广播,广播时发送的数据包以主机4的ip为源ip,以主机3的ip为目的ip灌包。
    数据包是作为单播进行设计的,但是我们依然需要做成广播。意思是虽然目的ip是主机3的ip,但其他主机也得收到这个包,收到包丢不丢是其他主机的事情,我们要保证把包送过去。
    最后,为了保证iperf能工作,还需要配置流表把主机4 到主机3的路径配通。简单来说,配完流表之后,主机4和主机3之间能够ping通。
    虽然说是iperf udp灌包,但实际上在运行前也是要建立连接的。iperf在正式开始udp灌包之前,会先向目的主机发送一个数据包,并等待对面回应,回应之后就建立连接,然后开始灌包。如果第一个数据包没有收到回应,iperf没法进行udp灌包,会报错网络不可达。然而当建立连接之后,iperf udp灌包就不再需要对面回应了。
    因此,如果不配通主机4到主机3,直接开始从主机4向主机3 灌包,就会显示网络不可达。
    路径配通的操作,我们放在packet_in函数中,在iperf之前,就把两个主机之间的路径给配好。
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第8张图片
    配置好路径后,我们现在mininet平台中进行ping通测试。
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第9张图片
    结果显示,h3和h4之间双向互通,0丢包。
    为了保证在iperf测试中,s3与s4中显示的统计结果更加明显,即不包括开始的这两次ping通测试,我们重新开一次mininet和ryu控制程序。
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第10张图片
    此次生成的mst与上一次不同,是因为我们在给权重中使用的随机函数:
    在这里插入图片描述

  5. 使用iperf命令进行udp灌包:
    Mininet里面启动xterm
    Mininet>xterm h1 h2 s1
    选生成树的起点作客户端灌包,比如h1向其他主机广播,就选h1灌包
    (h1)xxx#iperf –c xx.xx.xx.xx –u –b 1m –p 6001 –t 10000
    中间填的负责接收包的主机的ip
    (h10)xxx#iperf –s –u –p 6001
    h10负责接收处理数据包
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第11张图片
    h4向h3发送了454个包,没有丢包。
    在灌包的同时,我们打开h7进行监测:
    tcpdump –en –i hx-eth0
    (hx表示监控的主机,比如主机2就是h2,eth0表示接交换机的端口,具体可以在mininet里面用net查看)
    当正在灌包时,第三个主机可以看到udp包正在刷屏。
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第12张图片
    灌包灌一会就停了,快捷键ctrl+c强制结束,结束之后会有s3和s4的统计,统计一共发了多少个包。
    进交换机的xterm,输入命令:
    ovs-ofctl -O openflow13 dump-flows sx(x表示那个交换机,比如s1,s2…)查看流表
    在自己配置的流表项目中,里面有一项n_packets,这是流表项匹配到的报文数,每有一个报文根据该流表转发,这个字段就加1.
    其中actions=CONTROLLER:65535的不是我们配置的流表项,这是miss-table项,意思是没找到匹配的流表项就上传控制器。
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第13张图片
    统计结果显示,s4向s3发送了455个包,s3向s4发送了一个包。
    n_packets的值刚好比灌包统计的结果多一个。这是因为iperf udp灌包之前会先发送一个数据包去建立连接,这就是多出来的那一个。
    在那条反向路径的流表中,n_packets刚好为1,这是建立连接时候发送的回应包,之后的udp灌包就不再需要回应了。
    所以,实验结果完美符合我们的预期。

  6. 将广播业务在可视化平台上进行展示
    利用networkx工具包,将带有权重值的拓扑图与mst进行可视化展示:
    因为之前提到,我们每次生成的mst都不一样,因为权重是随机的,所以我们仅以一次生成mst拓扑图的结果为例:
    通信网系列实验(二)——基于Kruscal算法的广播通信业务_第14张图片
    这是以4节点为根节点生成的mst图,经验证,完全符合。

你可能感兴趣的:(SDN,python,算法)