news 2026/2/17 9:04:07

记录一次USB虚拟网络问题排查

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
记录一次USB虚拟网络问题排查

背景介绍

项目是用yocto构建的,在升级kernel及yocto后(见https://www.cnblogs.com/ma-yangbiao/p/19149251), 发现某些功能不能正常工作。

问题介绍

目标机是某个不常用的x86平台,该x86 盒子通过USB连接MDM9150, 在该x86盒子上跑某个应用程序过程中,发现没有像预期一样建立和初始化USB虚拟网口custom_usb0。

调试

由于qxdm log在该目标机上受限。加入一些文本打印,重新编译运行,进一步调试发现是因为我们一个管理网络的服务ioctl返回错误,这个ioctl是自己客制化的驱动代码里负责处理的,

于是把相关的驱动编译成模块然后手动加载进内核,其中现象如下

$ sudo insmod ./custom_usb.ko

insmod: ERROR: could not insert module custom_usb.ko: Unknown symbol in module

$ dmesg | tail

[ 183.497776] custom_usb: Unknown symbol usbnet_suspend (err -2)

[ 183.497778] custom_usb: Unknown symbol usbnet_start_xmit (err -2)

[ 183.497793] custom_usb: Unknown symbol usbnet_stop (err -2)

[ 183.497797] custom_usb: Unknown symbol usbnet_disconnect (err -2)

[ 183.497801] custom_usb: Unknown symbol usbnet_probe (err -2)

[ 183.497804] custom_usb: Unknown symbol usbnet_resume (err -2)

这几个符号都来自linux kernel 驱动代码,具体在kernel/drivers/net/usb/usbnet.c,由CONFIG_USB_USBNET决定是否编译,但是在我的自己的defconfig中CONFIG_USB_USBNET已经被显示设置为y了。

于是在我的defconfig把CONFIG_USB_USBNET=m,重新编译后待会手动加载看看是不是报错,

同时该文件中有几处打印用的netdev_dbg,为了方便调试有2种方法运行时看到打印信息,

把netdev_dgb改成netdev_warn

改CONFIG_DYNAMIC_DEBUG=y,这是为了打开编译时动态打印开关,运行时还需要打开运行时调试开关:echo 'file drivers/net/usb/usbnet.c +p' > /sys/kernel/debug/dynamic_debug/control,这样即使是netdev_dbg也能打印到dmesg

我选择方法1,

再次编译完执行insmod usbnet.ko发现没有错误,再手动insmod custom_usb.ko也没有错误.

说明代码没问题,回过头来在usbnet.c-> usbnet_init()里加一句打印 pr_err("usbnet_init called\n");

我的defconfig里再设置CONFIG_USB_USBNET=y,重新编译更新,再次重启发现没有这句打印, 也就是说这个usbnet压根没有自动加载。

于是检查最终的defconfig检查一下,发现最终的.config里CONFIG_USB_USBNET=m

经过检查我的kernel recipe .bbapend代码,有这么一段值得怀疑

do_preconfigure_prepend () {

cat ${WORKDIR}/custom/defconfig >> ${WORKDIR}/defconfig

}

如果我更新后,还有别的部分更新那就会覆盖我的配置。

于是尝试删除上述这三行,同时加入这2行,

SRC_URI += "file://custom/defconfig.cfg"

KERNEL_FEATURES += " custom/defconfig.cfg"

再次编译,查看.config.还是不起作用CONFIG_USB_USBNET=m.

阅读源码,Kconfig并没有提及CONFIG_USB_USBNET是否有依赖项,查看代码CONFIG_USB_USBNET实际是属于CONFIG_USB_NET_DRIVERS的一个子模块,所以尝试也配置

CONFIG_USB_NET_DRIVERS=y

CONFIG_DYNAMIC_DEBUG=y

再次编译,这次可以看到最终的.config里已经成功使能CONFIG_DYNAMIC_DEBUG=y了。说明kernel升级后这些配置项与旧版本里的配置不再一样。

再重新烧image,重新尝试,在解决了其它问题后功能终于正常。

总结

yocto 的内核配置流程是:从 BSP 提供的 defconfig 开始,按顺序合并 KERNEL_FEATURES 和 SRC_URI 中的 .cfg 片段, 运行 merge_config.sh + olddefconfig 生成最终 .config。

kernel升级,伴随的一些配置的依赖项可能会发生变化,需要仔细确认。比如在我们这个case里,CONFIG_USB_USBNET依赖发生了变化,旧kernel里并不依赖CONFIG_USB_NET_DRIVERS,但新kernel版本依赖它。

usbnet的功能

最后分享一下,这次debug过程中加深了对usbnet的功能的认识,

usbnet.c 是一个通用的 USB 网络驱动核心,定义了一个结构体 struct usbnet,它包含struct net_device, struct usb_interface等指针,就像胶水一样把usb操作与网络的操作net_device联系在一起

它实现了一个“USB 网络设备”的抽象:负责处理 USB 传输、数据包队列,以及与内核的 net_device 的集成交互。通过usb虚拟网口收发数据等通用逻辑放在这里。

它被许多小型驱动程序共享:例如 cdc_ether、asix、r8152、rmnet_usb 等都依赖于 usbnet 作为基础,这些特定厂商的驱动只需重写/写少量部分即可。它将通用逻辑与硬件特性分离:核心部分负责收发(TX/RX)管理等通用逻辑,而其它特定的驱动则通过重写钩子函数来实现设备特定的行为。

它还导出了一些辅助函数,供其他驱动调用。

最终效果是:当你插入一个 USB 网卡时,内核可以将其识别为 usb0;而通过少量的驱动特定代码,也可以显示为例如 rmnet_usb0 等。

具体解读

模块初始化/退出

usbnet_init():注册通用的 USB 驱动框架,准备好供子驱动调用。

usbnet_exit():注销驱动,释放资源。

设备探测与移除

usbnet_probe():当匹配的 USB 设备插入时调用,分配并初始化 struct usbnet 和 struct net_device。

usbnet_disconnect():设备拔出时清理资源。

网络设备操作

usbnet_open() / usbnet_stop():启动或停止接口,提交/取消接收 URB。

usbnet_start_xmit():把上层网络栈传下来的数据包封装成 URB,提交给 USB core。

usbnet_change_mtu()、usbnet_set_mac_address():常见的 net_device 操作。

数据收发路径

发送 (TX):start_xmit() → 构造 URB → usb_submit_urb() → 设备。

接收 (RX):URB 完成回调 → rx_complete() → 调用 netif_rx() 把包交给内核协议栈。

提供 rx_fixup() / tx_fixup() 钩子,供子驱动修正报文格式。

电源管理与错误恢复

处理 USB suspend/resume。提供 usbnet_tx_timeout() watchdog,避免传输卡死。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/14 21:05:24

当下的网络安全行业前景到底怎么样?还能入行分蛋糕吗?

常听到很多人不知道学习网络安全能做什么,发展前景好吗?今天我就在这里给大家介绍一下。网络安全作为目前比较火的朝阳行业,人才缺口非常大 先说结论,目前网络安全的前景还是很不错的 作为一个有丰富 Web 安全攻防、渗透领域老工…

作者头像 李华
网站建设 2026/2/10 21:48:57

黑马消息队列-rabbitMQ2-生产者重连机制-生产者确认机制

消息的可靠性问题,保证状态一致性生产者的可靠性 生产者重连生产者连接失败的失败重试连接 生产者确认到达交换机后,路由失败,基本不会出现这种情况;到达交换机后,到达队列;到达交换机后,到达队…

作者头像 李华
网站建设 2026/2/12 19:11:46

AD学习笔记-33 丝印位号的调整

大家好,我们来介绍丝印位号。针对元件装配,一般需要得出PCB的装配图,用于元件定位。1、丝印调整原则和常规尺寸我们先按下l键,把所有层的显示去掉,然后把丝印层打开。在properties中把text打开,避免拖动其他…

作者头像 李华
网站建设 2026/2/16 9:18:46

CAN通讯协议

一、CAN物理层1、电气特性总线结构物理特征(左:闭环;右:开环):​CAN总线由两根信号线组成,使用的是差分信号,是一种异步通讯CAN总线网络的结构有闭环和开环两种,其对应标…

作者头像 李华