通过Linux的tc指令实现软路由上的速度控制

通过Linux的tc指令实现软路由上的速度控制

现在很多使用软路由不管是做研究或者家庭使用,大部分基于Linux系统的Hostapd的方案较多,下面通过使用Ubuntu或者RaspOS操作系统为例,在安装了Hostapd的树莓派软路由上实现流量整形的功能。

内容为原创,转载请标注,另外参考自已发表的学术论文,详情见参考文献

Traffic shaping

Traffic shaping 是一种网络流量管理技术,用于控制计算机网络中数据包的传输速度和带宽使用。这种方法可以用于优化、管理或限制网络资源的使用。通过对网络流量进行监控和调整,网络管理员可以确保关键任务的流量优先级最高,同时限制不太重要的数据流量。

在网络中应用的比较多,由于我并不是学习网络工程的,所以就不献丑介绍了。本文主要讲一下如何实际使用shell脚本,在一个局域网中,对不同的设备实现吞吐量控制的功能。

  • 设备列表:
设备描述
树莓派4B作为软路由的本体
Raspbian OS树莓派的Linux操作系统
tc commandtraffic control 指令,在iproute2包里
板载NIC比较垃圾,不建议用
external NIC这里使用的是tp-link的T4UH,除了要装驱动之外没有别的缺点
  • 资料介绍参考网址:
    • tc介绍:https://man7.org/linux/man-pages/man8/tc.8.html
    • RedHat的介绍:https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/8/html-single/configuring_and_managing_networking/index#linux-traffic-control_configuring-and-managing-networking
    • CSDN上找大佬们的帖子

Shell脚本实现TC控制

  • 需要输入的地方:自己想要控制的设备ip地址和想要给吞吐量大小
  • 运行,即可实现

先放一下完整的代码:

#!/bin/bash
#This scripts control incomming and outcomming bandwight in a linux router box

dir=/home/pi/Dual_tc
unit=mbit
# Interface connect to out lan
int1="wlan0"
# Interface virtual for incomming traffic
tin1="ifb0"

totalDatarate=$(< $dir/set_target_throughput24.tmp wc -l)

w=1
while [ $w -le $totalDatarate ]
do
  IP[$w]=$(awk -v var=$w 'FNR==var{print $1}' $dir/set_target_throughput.tmp)
  datarate[$w]=$(awk -v var=$w 'FNR==var{print $2}' $dir/set_target_throughput.tmp)
  w=$(( w+1 ))
done

w=1
total_th=0
while [ $w -le $totalDatarate ]
do
  total_th=$(echo "scale=10; $total_th + ${datarate[$w]};" | bc -l) # add the total datarate for parent class
  w=$(( w+1 ))
done

# It's necessary load this module in the kernel for do it
modprobe ifb numifbs=1
sudo ip link set dev $tin1 up

## Limit incomming traffic ( to localhost)
# Clean interface
sudo tc qdisc del dev $int1 handle ffff: ingress
#modprobe -r ifb
sudo tc qdisc del root dev $tin1
sudo tc qdisc add dev $int1 handle ffff: ingress
# Redirect  ingress wlan0 to egress ifb0
sudo tc filter add dev $int1 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev $tin1
# Add classes per ip
sudo tc qdisc add dev $tin1 root handle 2: htb default 80
sudo tc class add dev $tin1 parent 2: classid 2:1 htb rate $total_th$unit 

# distribute data rate to the host (child class)
w=1
class_id=10
while [ $w -le $totalDatarate ]
do
sudo tc class add dev $tin1 parent 2:1 classid 2:$class_id htb rate ${datarate[$w]}$unit ceil ${datarate[$w]}$unit
w=$(( w+1 ))
class_id=$(( class_id+10 ))
done

# Match ip and put it into the respective class
# host filter
w=1
class_id=10
while [ $w -le $totalDatarate ]
do
sudo tc filter add dev $tin1 parent 2: protocol ip prio 1 u32 match ip src ${IP[$w]} flowid 2:$class_id
w=$(( w+1 ))
class_id=$(( class_id+10 ))
done

简单讲一下上面的脚本内容:

  1. 首先#!/bin/bash这段别忘了加上,因为考虑到不是所有人都熟悉bash或者shell,还是要说一下的。当然这段脚本用的是bash。shell脚本和bash之间类似于包含和被包含的关系,具体的请自己查阅资料吧。#!/bin/bash这行代码出现在脚本文件的第一行,用来指示系统如何执行该文件中的脚本。

  2. 因为需要方便修改ip地址和吞吐量,所以代码中对另外一个文件set_target_throughput.tmp进行了访问,在这文件中可以更加方便的设置,注意,需要修改你自己的文件夹路径和你自己的文件名字,或者你也可以用这个名字。

  3. wlan0是我们需要控制的接口,一般来说wlan0是板载的无线接口,但是如果你的名字不是这个,也没关系,可以修改。例如 wlp3s0 或类似的格式。下面的方法查看你的接口名字:

    • 如果安装了net-tools 包,使用:
    ifconfig
    
    • 如果没安装,建议装一个 : )
    • 一般来说改接口名字没啥问题,但也可能会有问题,如果你想改可以阅读下面的链接中的方法:https://askubuntu.com/questions/1303099/how-to-change-the-name-of-wireless-interface
  4. ifb0 是 Linux 中的一个虚拟网络接口,主要用于处理进入系统的流量(入口流量)。在 Linux 的流量控制(tc)工具中,对出口流量(从本地系统发出的流量)进行限制和控制相对简单,但对入口流量的控制则更为复杂。ifb 接口的引入正是为了解决这个问题。通过将入口流量重定向到 ifb 接口,可以使用 tc 工具对其进行精细控制,就像处理出口流量一样。

  5. outcoming的流量就是控制wlan0接口,进站通过ifb0来实现:

    # 将进站重新定向到ifb0
    sudo tc filter add dev $int1 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev $tin1
    # 在 ifb0上应用HTB(分层令牌桶)流量控制
    sudo tc qdisc add dev $tin1 root handle 2: htb default 80
    sudo tc class add dev $tin1 parent 2: classid 2:1 htb rate $total_th$unit
    
  6. 上述情况适用于:

    • 做实验,不联网,验证拓扑结构或者啥都可以
    • 带宽公平共享,希望确保所有连接到路由器的设备都能公平地共享可用带宽
    • 希望为某些类型的流量设置高优先级,而将其他流量降低优先级

    如果是对于上传速度等需求的控制,入站流量可以选择性忽略。


可能有些绕,但是让我们慢慢来详细说明一下:
现在,有一个linux系统的设备,开启这Hostapd作为软路由,eth0也就是设备的网线口连着你家光猫或者什么都可以,总之就是连着互联网。然后你的这个软路由上有一个无线接口wlan0,这个接口作为wifi共享给你的设备。

你有一台手机,连着这个软路由的wifi,想要下载一部电影,通过控制软路由上的ifb0实际上就是控制下载电影的速度。

当然,除了控制流量之外还可以设置优先级,上面的脚本中只用了HTB来控制流量,并没有涉及到优先级排序。

实际操作

下面来讲一下实际的操作。

  • 首先,检查你的网络接口。

    # 查看网络接口名称
    ifconfig
    

    出现错误,例如这样:

    Command 'ifconfig' not found, but can be installed with:
    sudo apt install net-tools
    # 速速下载net-tools
    

    你需要按照他的提示运行:

    sudo apt install net-tools
    # 然后再次运行
    ifconfig
    

    出现的信息大概是下面这样:(我演示用的是wsl所以可能信息不一样,按照你自己的情况去找)

    eth2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.73.1  netmask 255.255.255.0  broadcast 192.168.73.255
            inet6 fe80::dc3f:9673:5809:7c97  prefixlen 64  scopeid 0xfd<compat,link,site,host>
            ether 00:50:56:c0:00:01  (Ethernet)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    eth3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.136.1  netmask 255.255.255.0  broadcast 192.168.136.255
            inet6 fe80::6091:2a00:3739:ff14  prefixlen 64  scopeid 0xfd<compat,link,site,host>
            ether 00:50:56:c0:00:08  (Ethernet)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    eth4: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 172.29.96.1  netmask 255.255.240.0  broadcast 172.29.111.255
            inet6 fe80::c148:abe:7a41:1e43  prefixlen 64  scopeid 0xfd<compat,link,site,host>
            ether 00:15:5d:64:2d:90  (Ethernet)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 1500
            inet 127.0.0.1  netmask 255.0.0.0
            inet6 ::1  prefixlen 128  scopeid 0xfe<compat,link,site,host>
            loop  (Local Loopback)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    # !!!这里,找到你的wifi接口名字
    wifi0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.10.112  netmask 255.255.255.0  broadcast 192.168.10.255
            inet6 fe80::4800:f260:8634:78ba  prefixlen 64  scopeid 0xfd<compat,link,site,host>
            ether a8:64:f1:d6:08:67  (Ethernet)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
  • 在你想要的位置创建你的脚本和用于控制ip和速率的文件:

    • 例如/path to/home/your name/,在你的home文件夹中创建一个例如名为traffic_control.sh的脚本文件,里面粘贴上面的代码

    • 在同一路径(推荐)创建一个名为set_target_throughput.tmp的文件,里面内容如下:

      # 你想要控制的设备ip | 以及速率(单位mbit)
      192.168.10.1 50
      
    • 修改代码中的路径:

      # 这里放上你的set_target_throughput.tmp所在位置
      dir=/home/pi/Dual_tc
      # 这里修改速率单位
      unit=mbit
      # 这里修改你的无线接口名称
      # 注意,如果使用的是Hostapd的话,注意和你Hostapd的conf文件中配置的软路由接口名字一致
      # Interface connect to out lan
      int1="wlan0"
      
    • 检查ifb模块是否加载:

      # 通过ifconfig检查
      ifconfig
      
      # 如果ifconfig找不到,运行
      sudo modprobe ifb
      # 然后运行
      sudo ip link add name ifb0 type ifb
      sudo ip link set dev ifb0 up
      
      # 再次检查
      ifconfig
      # 或者使用
      ip link show ifb0
      

      拓展一下,如果你的软路由是双接口,比如现在常见的2.4Ghz和5Ghz的那种,一个80211n一个80211ac,你想控制双接口的流量的话,就需要两个ifb接口:

      sudo modprobe ifb numifbs=2
      
      sudo ip link add name ifb0 type ifb
      sudo ip link add name ifb1 type ifb
      
      sudo ip link set dev ifb0 up
      sudo ip link set dev ifb1 up
      
  • 运行刚刚创建的脚本文件:

    sudo ./traffic_control.sh
    

实用工具

可以使用iperf或者iftop等网络监测工具去查看目前的流量控制是否成功。

参考文献

  • Rahman, M.M.; Funabiki, N.; Munene, K.I.; Roy, S.C.; Kuribayashi, M.; Gulo, M.M.; Kao, W.-C. A Throughput Request Satisfaction Method for Concurrently Communicating Multiple Hosts in Wireless Local Area Network. Sensors 2022, 22, 8823. https://doi.org/10.3390/s22228823
  • Rahman M M, Funabiki N, Munene K I, et al. A Throughput Fairness Control Method for Concurrent Communications in Wireless Local-Area Network with Multiple Access-Points[J]. J. Commun., 2022, 17(8): 592-599.
  • 30
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卜卜123a

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值