这几年面对成倍增长的带宽需求,各种硬件加速转发手段层出不穷。其中智能网卡又是我比较感兴趣的一个方向。但是我们能买到的都是已经做好的成品,定制起来比较麻烦。再加上价格比较贵,不适合个人折腾。渐渐的萌生了低价造智能网卡的想法。我决定将折腾的过程记录一个系列流水账,毕竟人老了。本篇就是系列流水账的第一篇。

我的想法是借用linux内核的USB Gadget能力,构建出一个usb网卡。这个网卡实际上就是Android网络共享的网卡。大多数的操作系统都已经内置了驱动,是不是看起来和virtio-net很像?

选型的话比较随意,但是既然称之为网卡,还是要选一个带网口带otg的开发板。最终选了rpi4(总算带otg了)。

一些配置

/boot/config.txt中加入dtoverlay=dwc2
我喜欢在[pi4]标签下面设置,因为这张tf卡还要用来启动其他开发版。

[pi4]
# Enable DRM VC4 V3D driver on top of the dispmanx display stack
dtoverlay=vc4-fkms-v3d
max_framebuffers=2
dtoverlay=dwc2

还需要两个内核模块:

  • dwc2:usb芯片的驱动。
  • libcomposite:Linux Gadget的操作框架。插入它会在configfs中生成usb_gadget目录。

偷个懒少写点脚本,直接写到/boot/cmdline.txt里吧:modules-load=dwc2,libcomposite

最后,要把之后会生成的接口的DHCP关掉,免得乱申请地址:
编辑/etc/dhcpcd.conf,最后一行加入denyinterfaces usb0

全部搞定以后,重启一次。(还是懒)

简单测试

简单改造一下大师的脚本:
https://www.hardill.me.uk/wordpress/2019/11/02/pi4-usb-c-gadget/

#!/bin/bash
cd /sys/kernel/config/usb_gadget/
mkdir -p pi4
cd pi4
echo 0x1d6b > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB2
echo 0xEF > bDeviceClass
echo 0x02 > bDeviceSubClass
echo 0x01 > bDeviceProtocol
mkdir -p strings/0x409
echo "fedcba9876543211" > strings/0x409/serialnumber
echo "Ben Hardill" > strings/0x409/manufacturer
echo "PI4 USB Device" > strings/0x409/product
mkdir -p configs/c.1/strings/0x409
echo "Config 1: ECM network" > configs/c.1/strings/0x409/configuration
echo 250 > configs/c.1/MaxPower
# Add functions here
# see gadget configurations below
# End functions
mkdir -p functions/ecm.usb0
HOST="00:dc:c8:f7:75:14" # "HostPC"
SELF="00:dd:dc:eb:6d:a1" # "BadUSB"
echo $HOST > functions/ecm.usb0/host_addr
echo $SELF > functions/ecm.usb0/dev_addr
ln -s functions/ecm.usb0 configs/c.1/
udevadm settle -t 5 || :
ls /sys/class/udc > UDC
ifup usb0

先不管里边的原理。如果在pi上出现了usb0,并且电脑上出现了一张网卡,这个阶段的目标就达成了。

在我的环境上是这样的:

root@raspberrypi:/sys/kernel/config/usb_gadget/pi4# ifconfig -a
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::2dd:dcff:feeb:6da1  prefixlen 64  scopeid 0x20<link>
        ether 00:dd:dc:eb:6d:a1  txqueuelen 1000  (Ethernet)
        RX packets 88  bytes 29324 (28.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 20  bytes 2402 (2.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

为了能达到当作网卡使用的目的,接下来需要将usb0和eth0桥接起来:

ip link add br0 type bridge
ip link set dev eth0 promisc on
ip link set dev usb0 promisc on
ip link set dev eth0 master br0
ip link set dev usb0 master br0
ip link set dev br0 up

有一说一iproute2里边的命令是真的不直观。

最后查看一下网桥状态:

bridge link show
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 master br0 state disabled priority 32 cost 100
4: usb0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 100

激动人心的时刻到了:接线试试:

效果不错,正常上个百度一点问题都没有。


0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据