rk算力集群usb做网卡
rk3568 主机 kernel 4.19
rk3576 从机 kernel 6.1
前四章 都为RK3576配置
一、开启kernel配置
usb 驱动部分自己搞定 ,有adb就OK了 ,再开启下面的配置
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_USBNET=y
CONFIG_USB_ACM=y
CONFIG_USB_CONFIGFS_RNDIS=y
二、修改usbdevice.sh
1、debian
路径在** ${RK3576_SDK}/debian/overlay/etc/profile.d/****usbdevice.sh**
上面导出的变量是在 ** ${RK3576_SDK}/debian/overlay/usr/bin/usbdevice** 使用了 ,内容部分内容截图如下
2、buildroot
查看 **buildroot/package/rockchip/rkscript/rkscript.mk **可以看到下面的配置选项
最后在config文件中加上
BR2_PACKAGE_RKSCRIPT_USB_RNDIS=y
也可以在 common/overlays/rootfs/usb-gadget/install.sh修改默认值
3、查看网卡
输入如下命令
ifconfig -a
三、网卡设置
1、 udev 规则添加
这里需要添加两个文件
(1)、rk3576-net.rules
SUBSYSTEM=="net", ACTION=="add", NAME=="usb0", RUN+="/usr/bin/net_config.sh"
匹配到规则后运行 /usr/bin/net_config.sh
(2)、net_config.sh
#!/bin/shif [ "${INTERFACE}-y" != "usb0-y" ]; thenexit 0
fi#设置macip link set ${INTERFACE} address 02:11:22:33:44:01#开启网卡ip link set "${INTERFACE}" up# 下面可以配置 IP、启动服务等操作ip addr add 172.168.100.102/24 dev usb0
${INTERFACE} 为udev的一个环境变量,直接使用即可
以下是使用adc做ID的脚本 ,需要配合硬件设置
#!/bin/shif [ "${INTERFACE}-y" != "usb0-y" ]; thenexit 0
figet_val() {if [ "$(cat "$1")" -gt 700 ]; thenreturn 1elsereturn 0fi
}pushd '/sys/bus/iio/devices/iio:device0/' || exit 1
power=0
num=0
for f in in_voltage[1-4]_raw; doget_val "$f"val=$?num=$((num + val * 2 ** power))((power++))
donepopd || exit 1ip link set INTERFACE address 02:11:22:33:44:01 #设置mac
ip link set "${INTERFACE}" up #所有网卡都需要启动
ip addr add 172.168.100.$((100 + num))/24 dev "${INTERFACE}"
ip r add default via 172.168.100.1 dev "${INTERFACE}"
gpio版做id
#! /bin/bashif [ "${INTERFACE}-y" != "usb0-y" ]; thenexit 0
fi
# GPIO_RK_PC4 --> 2 * 32 + 8 * (3-1) + 4 = 84
# GPIO_RK_PC3 --> 2 * 32 + 8 * (3-1) + 3 = 83
# GPIO_RK_PC7 --> 2 * 32 + 8 * (3-1) + 7 = 87
# GPIO_RK_PC6 --> 2 * 32 + 8 * (3-1) + 6 = 86
GPIOS=(84 83 87 86)# Configure each GPIO pin as input
for gpio in "${GPIOS[@]}"; doecho "Configuring GPIO $gpio..."echo "$gpio" > /sys/class/gpio/exportecho "in" > /sys/class/gpio/gpio${gpio}/direction
done# Initialize variables
power=0
num=0# Read GPIO values and calculate num
for gpio in "${GPIOS[@]}"; doval=$(cat /sys/class/gpio/gpio${gpio}/value)num=$((num + val * 2 ** power))((power++))
done
num=$((num + 1))
padded_num=$(printf "%02d" "$num")# Output the result
echo "Calculated num: $num"
echo "Padded num: $padded_num"#设置mac
ip link set usb0 down
ip link set ${INTERFACE} address 02:11:22:33:44:$padded_num#开启网卡
ip link set "${INTERFACE}" up# 下面可以配置 IP、启动服务等操作
ip addr add 172.168.100.$((100 + num))/24 dev usb0ip r add default via 172.168.100.1 dev "${INTERFACE}"
(3)、文件拷贝
将上面的两个文件都拷贝到板子的文件系统中
cp rk3576-net.rules /etc/udev/rules.d
cp net_config.sh /usr/bin/
chmod +x /usr/bin/net_config.sh
踩坑点:net_config.sh 必须使用 #! /bin/bash , chmod +x给执行权限 ,777 出现识别不到
2、重启测试
可以看到上面设置的IP
四、Windows上测试网卡
以下测试的前提是 usb没改成网卡之前能检测到adb设备
1、板子设置IP
ip addr add 172.168.100.105/24 dev usb0
2、PC电脑设置ip
我们可以在 “设备管理”中查看网卡是否加载成功了
可以看到成功了 , 最后的 #7 代表 以太网7
设置ip
3、ping测试
关闭电脑防火墙 ,否则板子无法ping通电脑
设备 | IP地址 |
---|---|
PC | 172.168.100.2 |
板子 | 172.168.100.105 |
PC------------------------>板子
板子---------------------->PC
五、Linux USB虚拟网卡多板级联通信
参考: https://blog.csdn.net/qq_33549208/article/details/131520550
把多个开发板通过USB连接,由一块主板通过USB,将AI计算任务分配给多个多块板同时计算,使用USB虚拟成网卡,采用网络通信方式。如下图,
rk3568: 作为主机,有两个网卡 ,通过usb连接usb hub ,这样就可以连接多个设备
rk3576: 作为从机 ,可以有多个,通过将usb虚拟成网卡,从而访问主机和外网
以下是 rk3568 主机的配置 ,从机 rk3576配置看 上面的 “三、网卡设置”
下面的脚本全部放到开机自启即可
1、创建桥接网卡
#!/bin/bashrun() {brctl addbr br_rk3568ip link set br_rk3568 upip addr add 172.168.100.1/24 dev br_rk3568iptables -I INPUT -i br_rk3568 -j ACCEPTecho 1 >/proc/sys/net/ipv4/ip_forwardiptables -t nat -A POSTROUTING -s 172.168.100.0/24 -j MASQUERADE
}case "$1" in
start)run;;
stop):;;
*)echo "Usage: $0 {start|stop}"exit 1;;
esac
报错
修改一下
mv /usr/sbin/iptables /usr/sbin/iptables-nft
ln -s /usr/sbin/iptables-legacy /usr/sbin/iptables
创建成功
2、添加桥接网络
我们将** 从机(rk3576**)的网卡加入
- rk3568_net.sh
#! /bin/shif echo "${INTERFACE}" | grep -q '^usb'; then #只匹配usb开头的echo "Adding ${INTERFACE} to bridge br_rk3568..." > /root/usb_eth_debug_log.txtbrctl addif br_rk3568 "${INTERFACE}"ifconfig "${INTERFACE}" 0.0.0.0 up
elseecho "Interface ${INTERFACE} does not start with usb, skipping." > /root/usb_eth_debug_log.txt
fi
${INTERFACE} : 取的是udev的接口名,是一个环境变量
给上执行权限 文件拷贝到 /usr/bin
可以使用 "brctl show"查看桥接成功没有
- rk3568_net.rules
SUBSYSTEM=="net", \
ACTION=="add", \
ATTRS{idVendor}=="2207", \
ATTRS{idProduct}=="0013", \
RUN+="/usr/bin/rk3568_net.sh"
文件拷贝到 /etc/udev/rules.d/
这里的 ATTRS{idProduct}==“0013”, 这个ID在 从机 RK3576中/usr/bin/usbdevice(debian文件系统)
buildroot 文件在 也可能在 /etc/init.d或者usr/bin/usbdevice下
3、主机<---->从机ping测试
设备 | IP地址 |
---|---|
主机 rk3568 | 172.168.100.1 |
从机 rk3576 | 172.168.100.105 |
主机------------------------>从机
从机---------------------->主机
4、从机访问外网
完成上面的操作从机是无法访问外网的
(1)、rk3568 主机设置
#指定通过end1访问外网
iptables -t nat -A POSTROUTING -s 172.168.100.0/24 -o end1 -j MASQUERADE #所有均可
iptables -t nat -A POSTROUTING -s 172.168.100.0/24 -j MASQUERADE
这个命令是把来自 172.168.100.0/24
的流量伪装为主机 end1
的 IP 地址,这样就可以访问外网了。
-o end1
是通过end1访问外网
(2)、rk3576从机设置
ip route add default via 172.168.100.1 #或者route add default gw 172.168.100.1
主机的网卡地址是 172.168.100.1
把从机的网关设置为主机的ip
(3)、ping测试
这是我的从机,可看到ping百度成功了
(4)、 (可选)清理冲突的 169.254.x.x
地址
如果你在**主机(rk3568)**看到 usb0
/ usb1
有 169.254.x.x
的地址,那是 link-local 地址,是自动分配的,可能干扰你的网络。
手动设置地址时可以先清理掉:
ifconfig usb0 0.0.0.0
ifconfig usb0 172.168.100.1 netmask 255.255.255.0 up
5、从机访问从机
(1)、rk3568 主机设置
执行这个命令允许桥接互通:
iptables -A FORWARD -i br_rk3568 -o br_rk3568 -j ACCEPT
(2)、rk3576 从机设置
如果你是添加整个子网的路由(即所有在 172.168.100.x
范围内的地址),则应该使用 255.255.255.0
作为子网掩码,在从机(RK3576)添加如下
route add -net 172.168.100.0/24 gw 172.168.100.1
(3)、抓包测试
上面测试改完测试不通,所以抓包
tcpdump -i br_rk3568 icmp
抓到包了,还是ping不通
这个文件 不要乱设置** ****resolv.conf**
6、PC ssh访问从机
先按照上面的步骤使从机能访问外网
设备 | IP地址 |
---|---|
主机 rk3568 | 192.168.100.2 end0 |
172.168.100.1 | |
从机 rk3576 | 172.168.100.102 |
PC | 192.168.100.48 |
我的主机 rk3568 有end0(192.168.100.2)这个外网
我现在想通过PC连接到从机的ssh
PC(192.168.100.48) --------->ssh -------------> 从机(172.168.100.103)
思路: 就是通过socat使主机代理从机的ssh端口(22端口),保证从机的ssh是正常的
(1)、安装socat
rk3568 主机安装 socat
apt-get install socat
这个是用来做端口代理的
(2)、端口代理
在这里使用 主机的端口代理从机的端口,即 主机(12202-)—>从机(22),需要指定从机的ip
socat tcp-listen:12202,reuseaddr,fork tcp4:172.168.100.102:22
下面是16个从机的代理脚本
#!/usr/bin/env bashfunction start_exec() {ip=$(printf "%02d" "$1")x-socat "tcp-listen:122${ip},reuseaddr,fork" "tcp4:172.168.100.1${ip}":22 > /dev/null 2>&1 &echo "proxy 172.168.100.1${ip}:22 -> 0.0.0.0:122${ip}"
}function run() {ln -sf /usr/bin/socat /usr/bin/x-socati=0while :; dostart_exec $i((i++))if [ "$i" -gt 15 ]; thenbreakfidoneecho "start ok!"
}function stop() {killall -9 x-socat > /dev/null 2>&1 &echo "stop proxy"
}case "$1" instop)stop;;*)run;;
esac
运行效果
(3)、测试ssh连接
上面已经实现代理了,我们连接从机 172.192.168.102
也就是主机的ip 192.168.100.2:12202
可以看到已经成功连接上了
六、调试命令
1、udev调试命令
udevadm monitor --envudevadm control --reload
udevadm trigger --subsystem-match=net --action=add
2、 ARP 查看
如果ping 命令很久才打印一条,除了检查是不是ip地址重复使用了,还可以看下下面mac地址问题
主机输入
arp -a
可以看到at 后面都是从机的 mac地址,这个地址不能重复,不然网络会出问题
从机(rk3576)可以通过下面的命令来修改网卡mac地址
ip link set usb0 down
ip link set usb0 address 02:11:22:33:44:01
ip link set usb0 up
3、网速测试
(1)、iperf3测试
iperf3
:跨平台网络带宽测试工具,适用于虚拟网卡场景。
我们刚好使用的是usb虚拟网卡
这里我们先安装一下
apt-get install iperf3
- 主机(rk3568)
iperf3 -s #服务端
- 从机(rk3576)
iperf3 -c <服务器IP> -t 30iperf3 -c 172.168.100.1 -t 30
rndis跑到300Mbps的话就已经是天花板级别了
我在最后将rndis网卡改为了**ncm网卡**
主机---->从机能跑到1G了
从机---->主机只能跑到600多(大佬有没有什么优化建议,还请留言)
怎么改为ncm我把教程放到最后了
(2)、 scp测试
新建一个2g的空文件 testfile
dd if=/dev/zero of=testfile bs=1M count=2048
从主机发送给从机
time scp ./testfile root@172.168.100.101:/tmp/
七、debian设置自启服务
**vim /etc/systemd/system/myscript.service **
[Unit]
Description=My Custom Script
After=network.target[Service]
ExecStart=/usr/local/bin/myscript.sh
Type=simple
Restart=on-failure[Install]
WantedBy=multi-user.target
八、usb调试3.0
- 检查当前 USB 运行速率
cat /sys/class/udc/23000000.usb/current_speed
- 检查支持的最大速率设置
cat /sys/class/udc/23000000.usb/maximum_speed
这里的23000000.usb根据你用的芯片可能不一样,这是rk3576的
high-speed
(表示当前运行在 USB2.0 模式)super-speed
(USB3.0,目标状态)super-speed-plus
(USB3.1)
可以看到上面**红色框**是显示我的usb是2.0的 , **黄色框**显示我最大支持3.0的 ,需要修改设备树了 ,修改usb控制器的节点
&usb_drd0_dwc3 {status = "okay";dr_mode = "peripheral";maximum-speed = "super-speed"; #添加自己设备支持最大版本
};
还需要开启如下配置
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_GADGET=y # ✅ 必须开启
#CONFIG_USB_DWC3_DUAL_ROLE=y # 支持 OTG 切换
#CONFIG_USB_DWC3_HOST # host
CONFIG_USB_DWC3_OF_SIMPLE=y
CONFIG_USB_DWC3_ROCKCHIP_INNO=y
可以看到修改成功了
注意:以下选项需要三选一,开启一个,必须先关闭其他两个
CONFIG_USB_DWC3_GADGET=y
#CONFIG_USB_DWC3_DUAL_ROLE=y
#CONFIG_USB_DWC3_HOST
板端配置项检测
zcat /proc/config.gz | grep CONFIG_USB_DWC3
九、部分问题解决
1、USB3.0 HUB频繁断开(挂死)
我在测试带宽的时候出现了 从机老是掉(usb断开),有的时候直接HUB都没了还出现如下报错
解决(不一定完全解决,我是这样解决的)
在主机 rk3568的 usbhost_dwc3节点加入如下配置
snps,parkmode-disable-ss-quirk;
snps,parkmode-disable-ss-quirk
的作用是:
在 USB 3.0 SuperSpeed 模式下,禁用 Park Mode 功能。
这个 quirk 是为了 规避某些硬件平台或芯片在启用 Park Mode 后发生不稳定或兼容性问题。
具体如下
2、kernel-4.19 Failed mapping bounce buffer, not aligning错误
报如下错误
[ 131.802717] xhci-hcd xhci-hcd.7.auto: Failed mapping bounce buffer, not aligning
[ 131.803721] xhci-hcd xhci-hcd.7.auto: Failed mapping bounce buffer, not aligning
[ 131.805069] xhci-hcd xhci-hcd.7.auto: Failed mapping bounce buffer, not aligning
[ 131.805683] xhci-hcd xhci-hcd.7.auto: Failed mapping bounce buffer, not aligning
[ 131.807131] xhci-hcd xhci-hcd.7.auto: Failed mapping bounce buffer, not aligning
解决 加入补丁
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 66d6709eb675..666748a471c4 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -689,7 +689,7 @@ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci,static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,struct xhci_ring *ring, struct xhci_td *td){
- struct device *dev = xhci_to_hcd(xhci)->self.controller;
+ struct device *dev = xhci_to_hcd(xhci)->self.sysdev;struct xhci_segment *seg = td->bounce_seg;struct urb *urb = td->urb;size_t len;
@@ -3194,7 +3194,7 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len,u32 *trb_buff_len, struct xhci_segment *seg){
- struct device *dev = xhci_to_hcd(xhci)->self.controller;
+ struct device *dev = xhci_to_hcd(xhci)->self.sysdev;unsigned int unalign;unsigned int max_pkt;u32 new_buff_len;
--
如图
十、Rndis改为NCM网卡
1、rk3576 从机
(1)、kernel配置
开启ncm
CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_RNDIS=n #我这里是先关闭了rndis的
不管开启adb 还是 uvc 都需要先配置kernel打开这些功能
(2)、修改usbdevice
找到**${RK3576_SDK}/debian/overlay/usr/bin/usbdevice这是我的路径,不同板子可能文件不同,只要有下面的这些,应该就是对的**
- ①、修改usb_pid()函数,添加一个ncm
这两个都是我添加的。只是ecm没有使用,0x0020是一个ID,写一个上面没有使用的
- ②、修改usb_prepare()函数
(3)、修改**usbdevice.sh**
路径 ${RK3576_SDK}/debian/overlay/etc/profile.d/****usbdevice.sh ,根据自己sdk找到路径
改为ncm即可
(4)、验证
cat /sys/kernel/config/usb_gadget/rockchip/idProduct
可以看到这个就是我们上面设置的id 0x0020
或者使用
cat /sys/kernel/config/usb_gadget/rockchip/configs/b.1/strings/0x409/configuration
最后的结果为ncm
2、rk3568 主机
这个只需要修改 udev和桥接的脚本即可 ,因为网卡的名字变了 ,,没有变的可以不修改,我这里反正是变了
3、测速
从机 ----> 主机
主机 ----> 从机
4、各文件路径
根据 SDK版本路径可能发生变化
(1)、rk3588
文件 | buildroot下路径 | debian下路径 |
---|---|---|
usbdevice | ||
usbdevice.sh |
(2)、rk3576
文件 | buildroot下路径 | debian下路径 |
---|---|---|
usbdevice | ${SDK}/external/rkscript/usbdevice | ${SDK}/debian/overlay/usr/bin/usbdevice |
usbdevice.sh | ${SDK}/external/rkscript/S50usbdevice.sh | ${SDK}/debian/overlay/etc/profile.d/usbdevice.sh |
(3)、rk3568
文件 | buildroot下路径 | debian下路径 |
---|---|---|
usbdevice | ${SDK}/external/rkscript/usbdevice | ${SDK}/debian/overlay/usr/bin/usbdevice |
usbdevice.sh | ${SDK}/external/rkscript/S50usbdevice | ${SDK}/debian/overlay/etc/profile.d/usbdevice.sh |
(4)、rv1126
usbdevice、usbdevice.sh 是找不到 可以直接修改文件系统里面的那个
直接find / -name 把这两个文件找出来