一、模拟网卡简介

在 Linux 通过 usb 模拟网卡时,有四种方式:

1. 使用 usb gadget rndis
2. 使用 usb gadget ecm
3. 使用 usb gadget ncm
4. 使用 usb gadget eem

rndis:是微软公司制定的协议规范, 不过似乎规范不完整, 引起 rndis host 驱动作者的强烈反对。lichee\linux-4.9\drivers\net\usb\rndis_host.c

ecm:传输的是纯粹的以太网包,一次USB传输只包含一个以太网帧,因此吞吐量较低,实测在 6MB/s 左右,Windows 的驱动不太好找,Ubuntu 可以直接支持。

ncm:ecm 的改进版本,每个NCM报文可以包含多个以太网帧,这种特性称为报文聚合,即调用一次URB可以发送或者接收多个IP报文,实测在 17MB/s 左右,Windows 自带有驱动(本文在 Win10 平台实测通过),Ubuntu 可以直接支持。

eem:了解不多。

二、问题现象

接入 Windows 之后,启用该网卡,会不停的输出 "Wrong NDP SIGN",并且无法相互 ping 通。

检查发现因为 ncm->ndp_sign 的值等于 0,未被正确赋值。(f_ncm.c)

分析发现 ncm->ndp_sign 只有在设置 CRC 模式的时候才会拷贝 ncm->parser_opts,由此可见 Win10 的 ncm 驱动并未主动配置 CRC 模式引起。

经调试发现 USB_CDC_SET_NTB_FORMAT 会被触发,会设置 ncm->parser_opts,那么如果也顺道一同拷贝 ncm->ndp_sign 应该就能解决问题。

实测确实解决了问题,既然 f_ncm.c 驱动有缺陷,那么很有可能最新的内核已经解决了此问题,查看了最新内核的驱动(v5.18),发现已经调整了 ncm->ndp_sign 顺序,在 switch 语句后面进行赋值,同样也能解决问题。

f_ncm.c « function « gadget « usb « drivers - kernel/git/torvalds/linux.git - Linux kernel source tree

三、修复补丁

由于 5.9.y 相对于 4.9 版本改动较大,这里发出一个针对 4.9 版本修复此问题的最小改动补丁。

diff --git a/lichee/linux-4.9/drivers/usb/gadget/function/f_ncm.c b/lichee/linux-4.9/drivers/usb/gadget/function/f_ncm.c
old mode 100644
new mode 100755
index 639603722..278580b5a
--- a/lichee/linux-4.9/drivers/usb/gadget/function/f_ncm.c
+++ b/lichee/linux-4.9/drivers/usb/gadget/function/f_ncm.c
@@ -828,7 +828,7 @@ static int ncm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
default:
goto invalid;
}
- ncm->ndp_sign = ncm->parser_opts->ndp_sign | ndp_hdr_crc;
+ // ncm->ndp_sign = ncm->parser_opts->ndp_sign | ndp_hdr_crc;
value = 0;
break;
}
@@ -846,6 +846,9 @@ static int ncm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
w_value, w_index, w_length);
} + // lmx: fix ncm_unwrap_ntb() --> ncm->ndp_sign to==0, generate "Wrong NDP SIGN" Bug
+ ncm->ndp_sign = ncm->parser_opts->ndp_sign | (ncm->is_crc ? NCM_NDP_HDR_CRC : 0);
+
/* respond with data transfer or status phase? */
if (value >= 0) {
DBG(cdev, "ncm req%02x.%02x v%04x i%04x l%d\n",

实测吞吐量:

最新文章

  1. C#索引器
  2. 短信接口API
  3. Tomcat catalina.out日志使用log4j按天分割
  4. CloudStack系统部署系列教程-KVM
  5. bzoj3991: [SDOI2015]寻宝游戏--DFS序+LCA+set动态维护
  6. android之电话拨号器
  7. 【转】Android中如何使用Bundle传递对象[使用Serializable或者Parcelable] -- 不错
  8. BZOJ 1066: [SCOI2007]蜥蜴( 最大流 )
  9. cocos2d-html5
  10. 【实验室笔记】zedgraph控件属性总结
  11. 基于laravel5.5和vue2开发的个人博客
  12. L1-Day14
  13. <二>ELK-6.5.3学习笔记–使用rsyslog传输管理nginx日志
  14. sublime text下安装插件autoprefixer
  15. Java微信二次开发(十)
  16. Mysql主从同步问题汇总
  17. Oracle EBS 查看双节点是否做了信任
  18. C# 获取文件名、目录、后缀、无后缀文件名、扩展名、根目录等
  19. /etc/ssh/sshd_config 配置(ssh连接)
  20. Java 之单例设计模式

热门文章

  1. vue-axios更改操作
  2. VirtualBox 下 CentOS7 静态 IP 的配置 → 多次踩坑总结,蚌埠住了!
  3. 从小白到架构师(4): Feed 流系统实战
  4. 二叉搜索树 - C++ 实现
  5. 备考CISP-PTE之文件上传
  6. 【红队技巧】Windows存储的密码获取
  7. apt-mirror 制作麒麟桌面版内网源
  8. Go1.20 新版覆盖率方案解读
  9. day30-JQuery03
  10. 【Linux】通过Crontab和shell脚本实现定期备份和删除PG数据库表数据