文章目录
https://blog.youkuaiyun.com/qq_45880533/article/details/112230039
https://blog.youkuaiyun.com/asddasads/article/details/110678627
https://blog.youkuaiyun.com/asddasads/article/details/110678705
https://blog.youkuaiyun.com/u010643777/article/details/81352481
前言
在网络领域,大多数情况下做的实验都是基于ns2、ns3等仿真软件。这些软件是在应用层上模拟了一套网络协议,算是在应用层实现的,而mininet使用的网络协议是基于内核的,更关注网络拓扑本身,要想修改协议进行网络测试,直接到内核级别进行更改,更有现实意义
一、mininet简单使用
在Linux平台上安装好mininet之后,可以通过终端使用,官方也支持python API,更方便的进行编码。
使用mininet创建一个拓扑结构
# 创建一个简单拓扑,h1--s1--h2
sudo mn --topo=minimal
# 测试网络性能
# h1开启iperf,-s:服务端,-p 端口号 -i
# 令主机h1为服务器,使用端口为5566,并且每隔一秒监视一次,在后台运行
h1 iperf -s -p 5566 -i 1 &
# 令主机h2为客户端,使用端口5566,并且每隔一秒监视一次,共持续15s,我们可以看见每隔一秒钟,会报告一次当前的网络状况,同时会在最后统计15秒内的网络情况
h2 iperf -c 10.0.0.1 -p 5566 -t 15 -i 1
二、关于系统变量控制的相关命令
# 设置系统控制变量(sysctl): -w 临时改变
sysctl -w net.mptcp.[name of the wariable]=[value]
# 当前内核可以使用的tcp拥塞控制算法
sysctl net.ipv4.tcp_available_congestion_control
# 当前内核正在使用的tcp拥塞控制算法
sysctl net.ipv4.tcp_congestion_control
# 更改tcp拥塞控制算法(更改为reno)
sysctl net.ipv4.tcp_congestion_control=reno
# 检查是否内核有没有开启mptcp协议
sudo sysctl -a | grep mptcp
# 确认mptcp内核版本号
dmesg | grep MPTCP
三、基于mininet的实验
1、小试牛刀——使用mininal拓扑
关闭mptcp选项,测试tcp协议的一些性能参数
sudo sysctl -a | grep mptcp
sudo sysctl net.mptcp.mptcp_enabled=0
查看当前tcp拥塞控制协议
sudo sysctl net.ipv4.tcp_congestion_control
⬆️当前tcp协议的拥塞控制算法为balia
使用mininet创建minimal网络拓扑,并测试(依次输入以下命令)
sudo mn --topo=minimal
h1 iperf -s -p 5566 -i 1 &
h2 iperf -c 10.0.0.1 -p 5566 -t 15 -i 1
⬆️由上图课件,当前校园网下网络拓扑为minimal,拥塞控制协议为balia,15s传输了74.4GBytes的数据。
更换拥塞控制协议,继续测量。
查看当前系统可以使用的tcp拥塞控制算法
sysctl net.ipv4.tcp_available_congestion_control
⬆️reno bbr cubic lia olia wvegas balia mctcpdesync
更改拥塞控制算法为cubic,测量方式如上
⬆️由上图可见,当前校园网下网络拓扑为minimal,拥塞控制协议为cubic,15s传输了77.3GBytes的数据。
一次测量数据具有偶然性,可以测量多次取平均值。(我实际测量,相同算法每次测量结果基本一致)
按照上述方法,可以设置拥塞控制算法,设计拓扑图,测量数据传输的效果。
2、自定义拓扑
拓扑1
mininet除了使用terminal进行控制之外,还支持python API,对于相对复杂的拓扑结构,我们使用python编程设计,然后执行更方便。
MPTCP协议在mininet中的性能测试
拓扑结构如下:
编写拓补脚本,mptcp-example1.py,启动iperf软件,可以测量节点间的带宽。(以下代码是python2的代码)
#!/usr/bin/env python
from mininet.net import Mininet
from mininet.cli import CLI
from mininet.link import Link, TCLink,Intf
from subprocess import Popen, PIPE
from mininet.log import setLogLevel
if '__main__' == __name__:
setLogLevel('info')
net = Mininet(link=TCLink)
key = "net.mptcp.mptcp_enabled"
value = 1
p = Popen("sysctl -w %s=%s" % (key, value), shell=True, stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()
print "stdout=",stdout,"stderr=", stderr
h1 = net.addHost('h1')
h2 = net.addHost('h2')
r1 = net.addHost('r1')
linkopt={'bw':10}
net.addLink(r1,h1,cls=TCLink, **linkopt)
net.addLink(r1,h1,cls=TCLink, **linkopt)
net.addLink(r1,h2,cls=TCLink, **linkopt)
net.addLink(r1,h2,cls=TCLink, **linkopt)
net.build()
r1.cmd("ifconfig r1-eth0 0")
r1.cmd("ifconfig r1-eth1 0")
r1.cmd("ifconfig r1-eth2 0")
r1.cmd("ifconfig r1-eth3 0")
h1.cmd("ifconfig h1-eth0 0")
h1.cmd("ifconfig h1-eth1 0")
h2.cmd("ifconfig h2-eth0 0")
h2.cmd("ifconfig h2-eth1 0")
r1.cmd("echo 1 > /proc/sys/net/ipv4/ip_forward")
r1.cmd("ifconfig r1-eth0 10.0.0.1 netmask 255.255.255.0")
r1.cmd("ifconfig r1-eth1 10.0.1.1 netmask 255.255.255.0")
r1.cmd("ifconfig r1-eth2 10.0.2.1 netmask 255.255.255.0")
r1.cmd("ifconfig r1-eth3 10.0.3.1 netmask 255.255.255.0")
h1.cmd("ifconfig h1-eth0 10.0.0.2 netmask 255.255.255.0")
h1.cmd("ifconfig h1-eth1 10.0.1.2 netmask 255.255.255.0")
h2.cmd("ifconfig h2-eth0 10.0.2.2 netmask 255.255.255.0")
h2.cmd("ifconfig h2-eth1 10.0.3.2 netmask 255.255.255.0")
h1.cmd("ip rule add from 10.0.0.2 table 1")
h1.cmd("ip rule add from 10.0.1.2 table 2")
h1.cmd("ip route add 10.0.0.0/24 dev h1-eth0 scope link table 1")
h1.cmd("ip route add default via 10.0.0.1 dev h1-eth0 table 1")
h1.cmd("ip route add 10.0.1.0/24 dev h1-eth1 scope link table 2")
h1.cmd("ip route add default via 10.0.1.1 dev h1-eth1 table 2")
h1.cmd("ip route add default scope global nexthop via 10.0.0.1 dev h1-eth0")
h2.cmd("ip rule add from 10.0.2.2 table 1")
h2.cmd("ip rule add from 10.0.3.2 table 2")
h2.cmd("ip route add 10.0.2.0/24 dev h2-eth0 scope link table 1")
h2.cmd("ip route add default via 10.0.2.1 dev h2-eth0 table 1")
h2.cmd("ip route add 10.0.3.0/24 dev h2-eth1 scope link table 2")
h2.cmd("ip route add default via 10.0.3.1 dev h2-eth1 table 2")
h2.cmd("ip route add default scope global nexthop via 10.0.2.1 dev h2-eth0")
CLI(net)
net.stop()
执行命令
sudo python mptcp-example1.py
启动h1,h2两个终端窗口
mininet>xterm h1 h2
首先在h2中输入:
iperf -s -i 1
接着在h1中输入:
iperf -c 10.0.2.2 -t 10 -i 1
代码中value的值控制mptcp的开启和关闭,1为开启,0为关闭。效果图如下:
拓扑2
python代码:
#!/usr/bin/env python
from mininet.net import Mininet
from mininet.cli import CLI
from mininet.link import Link, TCLink, Intf
from subprocess import Popen, PIPE
from mininet.log import setLogLevel
import sys
if '__main__' == __name__:
# 处理命令行参数
value = 1
if len(sys.argv) > 2:
value = int(sys.argv[1])
setLogLevel('info')
net = Mininet(link=TCLink)
key = "net.mptcp.mptcp_enabled"
p = Popen("sysctl -w %s=%s" % (key, value), shell=True, stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()
print("stdout=", stdout, "stderr=", stderr)
h1 = net.addHost('h1')
h2 = net.addHost('h2')
h3 = net.addHost('h3')
r1 = net.addHost('r1')
r2 = net.addHost('r2')
# 设置链路带宽
linkopt = {'bw': 10}
# 总共有五条链路
# r1
# h1 h2
# r2
#
# h3
net.addLink(r1, h1, cls=TCLink, **linkopt)
net.addLink(r1, h2, cls=TCLink, **linkopt)
net.addLink(r2, h1, cls=TCLink, **linkopt)
net.addLink(r2, h2, cls=TCLink, **linkopt)
net.addLink(r2, h3, cls=TCLink, **linkopt)
net.build()
# 配置路由器r1两个端口
r1.cmd("ifconfig r1-eth0 0")
r1.cmd("ifconfig r1-eth1 0")
# 配置路由器r2三个端口
r2.cmd("ifconfig r2-eth0 0")
r2.cmd("ifconfig r2-eth1 0")
r2.cmd("ifconfig r2-eth2 0")
h1.cmd("ifconfig h1-eth0 0")
h1.cmd("ifconfig h1-eth1 0")
h2.cmd("ifconfig h2-eth0 0")
h2.cmd("ifconfig h2-eth1 0")
h3.cmd("ifconfig h3-eth0 0")
r1.cmd("echo 1 > /proc/sys/net/ipv4/ip_forward")
r2.cmd("echo 1 > /proc/sys/net/ipv4/ip_forward")
r1.cmd("ifconfig r1-eth0 10.0.0.1 netmask 255.255.255.0")
r1.cmd("ifconfig r1-eth1 10.0.1.1 netmask 255.255.255.0")
r2.cmd("ifconfig r2-eth0 10.0.2.1 netmask 255.255.255.0")
r2.cmd("ifconfig r2-eth1 10.0.3.1 netmask 255.255.255.0")
r2.cmd("ifconfig r2-eth2 10.0.4.1 netmask 255.255.255.0")
h1.cmd("ifconfig h1-eth0 10.0.0.2 netmask 255.255.255.0")
h1.cmd("ifconfig h1-eth1 10.0.2.2 netmask 255.255.255.0")
h2.cmd("ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0")
h2.cmd("ifconfig h2-eth1 10.0.3.2 netmask 255.255.255.0")
h3.cmd("ifconfig h3-eth0 10.0.4.2 netmask 255.255.255.0")
h1.cmd("ip rule add from 10.0.0.2 table 1")
h1.cmd("ip rule add from 10.0.2.2 table 2")
h1.cmd("ip route add 10.0.0.0/24 dev h1-eth0 scope link table 1")
h1.cmd("ip route add default via 10.0.0.1 dev h1-eth0 table 1")
h1.cmd("ip route add 10.0.2.0/24 dev h1-eth1 scope link table 2")
h1.cmd("ip route add default via 10.0.2.1 dev h1-eth1 table 2")
h1.cmd("ip route add default scope global nexthop via 10.0.0.1 dev h1-eth0")
h2.cmd("ip rule add from 10.0.1.2 table 1")
h2.cmd("ip rule add from 10.0.3.2 table 2")
h2.cmd("ip route add 10.0.1.0/24 dev h2-eth0 scope link table 1")
h2.cmd("ip route add default via 10.0.2.1 dev h2-eth0 table 1")
h2.cmd("ip route add 10.0.3.0/24 dev h2-eth1 scope link table 2")
h2.cmd("ip route add default via 10.0.3.1 dev h2-eth1 table 2")
h2.cmd("ip route add default scope global nexthop via 10.0.1.1 dev h2-eth0")
h3.cmd("ip rule add from 10.0.4.2 table 1")
h3.cmd("ip route add 10.0.4.0/24 dev h3-eth0 scope link table 1")
h3.cmd("ip route add default via 10.0.4.1 dev h3-eth0 table 1")
h3.cmd("ip route add default scope global nexthop via 10.0.4.1 dev h3-eth0")
CLI(net)
net.stop()
测试的话,自己随便尝试吧!
四、自定义内核
以上我们使用系统中的内核进行了tcp性能的简单测试,我们可以做的不止这些,可以设计一个tcp拥塞控制算法,然后编译到内核里面,运行并测量效果。
1、设计源代码
我的内核的名字为mptcp,一般情况下Linux内核源代码的名字叫linux5.10.60-9.al8.x86_64这样的名字。
进入内核源码文件夹
cd /usr/src/mptcp
进入tcp协议中拥塞控制算法源码的目录(/net/ipv4)
:/usr/src/mptcp
cd net/ipv4
:/usr/src/mptcp/net/ipv4
我想在cubic的基础上修改实现一个我自己的拥塞控制算法,取名叫tcp_bupt,就是我们学校的名字,哈哈哈!
可以找到tcp cubic算法的源文件为tcp_cubic.c
可以打开查看一下:
gedit tcp_cubic.c
文件内部有简单介绍该算法。
在文件中搜索.name,可以找到如下信息,“cubic”
复制tcp_cubic.c为tcp_bupt.c
sudo cp tcp_cubic.c tcp_bupt.c
(需要注意的是,如果拥塞控制算法不止在一个c文件中实现,注意要复制所有的文件,判断的方式为
a. 文件名前缀相同
b. 看c文件中是否包含双引号的头文件
更改一下里面的内容:
更改的一行为
delta = (cube_rtt_scale * offs * offs * offs) >> (10+3*BICTCP_HZ)
⬇️
delta = (cube_rtt_scale * offs * offs * offs) >> (20+4*BICTCP_HZ)
更改文件最后的.name中的"cubic"为"bupt"
2、编译信息配置
Linux模块文件如何编译到内核和独立编译成模块?
修改Makefile
sudo vim Makefile
比葫芦画葫芦
c文件经过编译生成o文件
增加一行内容:
obj_$(CONFIG_TCP_CONG_BUPT) += tcp_bupt.o
修改Kconfig
sudo gedit Kconfig
还是比葫芦画葫芦,需要注意的一点是有一行内容为
default m
default y
default n
m,y,n分别代表的意思为编译为模块、编译进内核、不编译。
我选择y
下面的choice也要将信息添加进来
回退到目录/usr/src/mptcp
cd ..
cd ..
执行命令
sudo make menuconfig
出现如下配置界面
依次进入
>Networking support>Networking options>TCP: advanced congestion control
界面内容为:
可以发现,最后一行TCP Bupt ( NEW ),前面的<*>表示编译到内核。因此不需要任何配置,直接退出吧!
3、编译
执行make命令,注意在Linux源文件目录下执行该命令
:/usr/src/mptcp$ sudo make
让我们选择编译TCP Bupt的选项,Y是大写表示默认,可以直接回车,也可以输入y,这里我输入y
编译中,请耐心等待,喝杯咖啡放松一下!!!!
编译完成后。
可能还需要执行(如果编译的是模块的话,需要install,直接编译到内核不需要这一行代码)
其实执行一下也无所谓,这总是稳妥的。
sudo make install
重新启动Linux
查看拥塞控制算法
sudo sysctl net.ipv4.tcp_avaliable_congestion_control
可以发现已经有了bupt这样一个算法,这个名字是.name控制的,tcp_bupt.c里面的.name是什么,你的算法就叫什么名字。
4、测试新的拥塞控制算法bupt
终于到了测试的环节了,因为bupt是经过cubic改良过来的(改了一行代码),所以我将这两个拥塞控制算法的性能进行比较。
# 关闭mptcp
sudo sysctl net.mptcp_enabled=0
1、cubic
sudo sysctl net.ipv4.tcp_congestion_control=cubic
在mininet下使用minimal拓扑测试
sudo mn --topo=minimal
h1 iperf -s -p 5566 -i 1 &
h2 iperf -c 10.0.0.1 -p 5566 -t 15 -i 1
2、bupt
sudo sysctl net.ipv4.tcp_congestion_control=bupt
sudo mn --topo=minimal
h1 iperf -s -p 5566 -i 1 &
h2 iperf -c 10.0.0.1 -p 5566 -t 15 -i 1
从两个实验的对比,发现好像差距不大,毕竟我只改了一行代码,如果想获得更加明显的对比(随意修改的算法参数,一般情况都会性能下降),需要更多的更改才行。
你可以尝试一下!
总结
通过上述内容,你可以了解mininet的简单实用,系统变量的查看与控制,已经修改内核编译内核,真的是收获满满了。对于想从事网络研究的人来说,相信一定对你有很大的帮助!