USB/IP 协议、PDU 与公共核心
1. 两层协议
用户态管理协议负责DEVLIST和IMPORT,定义在tools/usb/usbip/src/usbip_network.h。导入完成后,socket交给内核,使用usbip_common.h中的URB协议。
默认服务端端口为TCP 3240。用户态在连接后设置TCP_NODELAY,降低小控制传输的Nagle延迟。
2. 四类内核命令
| 命令 | 值 | 方向 | 语义 |
|---|---|---|---|
CMD_SUBMIT |
1 | VHCI→Stub/VUDC | 提交URB |
CMD_UNLINK |
2 | VHCI→Stub/VUDC | 取消指定seqnum |
RET_SUBMIT |
3 | Stub/VUDC→VHCI | URB完成 |
RET_UNLINK |
4 | Stub/VUDC→VHCI | 取消结果 |
数据面usbip_header固定48字节:20字节basic header加28字节最大union。基本头包含command、seqnum、devid、direction、ep。seqnum标识请求;Stub使用(busnum << 16) | devnum形成devid。
3. SUBMIT字段
usbip_header_cmd_submit序列化:
- 可跨网络表达的URB transfer flags;
- transfer buffer length;
- start frame;
- ISO packet数量;
- interval;
- 8字节control setup packet。
并非所有本地URB flag都可直接传输,tweak_transfer_flags()会过滤DMA映射等仅本机有效的标志。
RET_SUBMIT返回status、actual length、frame、ISO packet数和error count。
4. Payload顺序
1 | CMD_SUBMIT OUT: |
非ISO传输可使用线性buffer或scatter-gather。公共层的usbip_recv_xbuff()和发送侧kvec/iov_iter负责数据搬运。
ISO descriptor包含offset、期望length、actual length和status。Stub限制单URB最多1024个ISO packets,并检查负数、越界及长度;VUDC还按endpoint max packet验证packet数。
5. 字节序
usbip_header_correct_endian()对全部32-bit头字段执行CPU与big-endian转换,ISO descriptor同样按网络序处理。Setup packet本身是USB Chapter 9格式,不作为五个普通32-bit字段转换。
解包顺序必须是:
- 完整接收固定头;
- 转为CPU字节序;
- 验证command和长度;
- 分配URB/buffer;
- 接收payload和ISO描述符。
远端给出的有符号长度和packet数量不能在验证前转换为分配大小。
6. usbip_common.c
关键函数:
usbip_pack_pdu():URB和command-specific header互转;usbip_header_correct_endian():网络字节序;usbip_recv():循环接收指定长度,处理EOF和signal;usbip_alloc_iso_desc_pdu():创建ISO descriptor PDU;usbip_recv_iso():接收并验证ISO结果;usbip_recv_xbuff():接收IN/OUT payload;usbip_pad_iso():整理非连续ISO IN数据;- dump/debug函数:输出header和URB字段。
usbip_debug_flag是可写模块参数,同时通过各设备的usbip_debug sysfs暴露位掩码。
7. Event Handler
公共层创建名为usbip_event的单线程workqueue。每个usbip_device以位图记录:
SHUTDOWN:先关闭socket/线程;RESET:恢复到可重连状态;UNUSABLE:永久标记不可用;BYE:对象即将移除。
usbip_event_add()使用全局spinlock把设备去重后加入event list。worker持有该设备sysfs_lock,严格按shutdown→reset→unusable顺序调用前端回调,并唤醒usbip_stop_eh()等待者。
这是全局串行恢复路径:一个设备的慢shutdown会延迟其它USB/IP连接的event处理。
8. 协议边界
内核URB协议没有独立session认证、MAC、加密、重放保护或每PDU长度字段。消息边界依赖command对应的固定头及其中长度。TCP只保证有序字节流,不保证对端可信。
正在加载留言…