USB网卡收发数据分析_usb网卡数据传输、-程序员宅基地

技术标签: 网络  sk_buff  # Driver  linux  # Kernel  net  驱动开发  网卡  

前言

网络子系统是 Linux 内核的重中之重。今天,我们从网卡驱动入手,开始网络子系统的探索之路。

硬件环境请添加图片描述

树莓派3B+,搭载千兆网卡 LAN7515,不过其使用的是 USB2.0 通道(最高理论速度为480Mbps),官方给出 300Mbps 的以太网传输速率。

驱动

LAN7515 的驱动为 lan78xx,源码比较简单,就两个文件 ./linux/drivers/net/usb/lan78xx.c/h,编译后产生 lan78xx.ko 驱动文件。

驱动分析

1. USB 驱动注册

static struct usb_driver lan78xx_driver = {
    
	.name			= DRIVER_NAME,
	.id_table		= products,
	.probe			= lan78xx_probe,
	.disconnect		= lan78xx_disconnect,
	.suspend		= lan78xx_suspend,
	.resume			= lan78xx_resume,
	.reset_resume		= lan78xx_reset_resume,
	.supports_autosuspend	= 1,
	.disable_hub_initiated_lpm = 1,
};

module_usb_driver(lan78xx_driver);

LAN7515 是 USB 网卡,和 CPU 交互的接口为 USB,所以它是一个 USB 设备,要在内核注册它的 USB 驱动——lan78xx.ko。
insmod lan78xx.ko 即在 USB 总线上注册 LAN7515 网卡驱动,此时,会遍历 USB 总线上已注册的设备,用总线的 match 方法判断是否有匹配的设备,如果有,则调用驱动的 probe 函数。
具体看一下:
在这里插入图片描述
/sys/bus/usb/ 下有 devices 和 drivers 目录,这两个目录下分别是当前系统中 USB 总线上已注册的设备已注册的驱动
可以看到,在 drivers 目录中目前还没有 lan78xx 驱动,并且我们也不知道 devices 目录中的哪个 USB 设备为 LAN7515 设备。
下面我们安装 lan78xx 驱动
在这里插入图片描述
看到执行了 lan78xx_probe() 函数,这也印证了我们上面的说法(注册驱动,会遍历设备,寻求匹配,匹配成功,触发 probe)。
我们再次查看 /sys/bus/usb/drivers 下的目录情况
在这里插入图片描述
可以看到,已经产生了 lan78xx 目录,说明驱动注册成功了。

2. 驱动和设备绑定

在 lan78xx_probe() 函数中调用了 lan78xx_bind() 方法,正式地将 lan78xx 驱动和 1-1.1.1:1.1 设备绑定了起来。在 lan78xx 目录下也能体现这一点。
在这里插入图片描述
我们也可以手动绑定和解绑

# ifconfig -a
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:42 errors:0 dropped:0 overruns:0 frame:0
          TX packets:42 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:4478 (4.3 KiB)  TX bytes:4478 (4.3 KiB)
# ls
bind       module     new_id     remove_id  uevent     unbind
# echo "1-1.1.1:1.0" > bind 
[37493.831496] lan78xx_probe()
[37494.126379] lan78xx 1-1.1.1:1.0 (unnamed net_device) (uninitialized): No External EEPROM. Setting MAC Speed
[37494.144756] libphy: lan78xx-mdiobus: probed
[37494.264385] lan78xx 1-1.1.1:1.0 (unnamed net_device) (uninitialized): int urb period 64
[37494.276093] lan78xx_phy_init()
# ls
1-1.1.1:1.0  module       remove_id    unbind
bind         new_id       uevent
# ifconfig -a
eth0      Link encap:Ethernet  HWaddr B8:27:EB:8A:BC:F4  
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:42 errors:0 dropped:0 overruns:0 frame:0
          TX packets:42 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:4478 (4.3 KiB)  TX bytes:4478 (4.3 KiB)
# 
# 
# echo "1-1.1.1:1.0" > unbind 
# ls
bind       module     new_id     remove_id  uevent     unbind
# ifconfig -a
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:42 errors:0 dropped:0 overruns:0 frame:0
          TX packets:42 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:4478 (4.3 KiB)  TX bytes:4478 (4.3 KiB)
# 

3. 数据收发

以 PC1 数据链路层发送一个数据包给 PC2 数据链路层为例
请添加图片描述
rx

tasklet_schedule(&dev->bh);	// USB 收到数据时,产生中断,触发该任务
lan78xx_bh()
    lan78xx_rx_bh()
        rx_submit()
            usb_fill_bulk_urb()	// 从 USB 读取数据
            tasklet_schedule(&dev->bh);
                lan78xx_bh()
                    rx_process()
                        lan78xx_rx()
                            lan78xx_skb_return()
-----上面为驱动-------下面为数据链路层-----------------------
                                netif_rx()	// 送入数据链路层

tx

struct net_device_ops {
    
	.ndo_start_xmit		= lan78xx_start_xmit,
}
-----上面为数据链路层-------下面为驱动-----------------------
lan78xx_start_xmit()
	skb_queue_tail()	// 插入队列
	tasklet_schedule(&dev->bh);	// 触发任务调度 lan78xx_bh
		lan78xx_bh()
			lan78xx_tx_bh()
				skb_dequeue()	// 取出数据
------上面为驱动网络部分--------下面为驱动 USB 部分-----------
				usb_fill_bulk_urb()	// 填充数据到 USB
				usb_submit_urb()	// USB 发送数据

RX call tree:目前理得有点混乱,大致过程是 USB 硬件产生中断,驱动去捞数据,经过 rx_process() 处理后,最终调用 netif_rx(skb),将数据送入内核网络子系统,进一步处理 skb。
TX call tree:内核网络子系统最终调用 ndo_start_xmit() 发送数据,该接口最终由设备驱动实现,本示例为 lan78xx_start_xmit(),最终将数据通过 USB 发送给 LAN7515 网卡,网卡再经过自己的硬件加工,最终将数据发送到网线。
在这里插入图片描述

打印帧头

static netdev_tx_t
lan78xx_start_xmit(struct sk_buff *skb, struct net_device *net)
{
    
printk("%s()\n", __FUNCTION__);

struct ethhdr *eth = eth_hdr(skb);
printk(KERN_INFO "DEST:" MAC_FMT "\n", MAC_ARG(eth->h_dest));
printk(KERN_INFO "SOURCE:" MAC_FMT "\n", MAC_ARG(eth->h_source));

struct iphdr *ip_header = ip_hdr(skb);
printk("daddr:%x is %d.%d.%d.%d\n", ip_header->daddr, inet_ntoa(ip_header->daddr));
printk("saddr:%x is %d.%d.%d.%d\n\n", ip_header->saddr, inet_ntoa(ip_header->saddr));
...
[44851.676380] lan78xx_start_xmit()
[44851.680906] DEST:08:00:27:38:fc:d0
[44851.685656] SOURCE:b8:27:eb:8a:bc:f4
[44851.690571] daddr:6401a8c0 is 192.168.1.100
[44851.696164] saddr:101a8c0 is 192.168.1.1

打印 TX 方向,驱动送给网卡的数据帧中的目的 MAC、源 MAC、目的 IP、源 IP,即上图中 ① 处的数据帧头。

总结

网卡、网卡驱动、内核网络子系统,它们干的事情核心就是传递数据包,其中 sk_buff 在整个过程中起着穿针引线的作用,这次分析网卡驱动收发的过程中,也尝试打印了 sk_buff 的部分信息,作为一个探索的开始吧。其实 sk_buff 在网络子系统中确实起着非常重要的作用,sk_buff 是 socket buffer 的意思,这又进一步体现了 socket 的重要,连其 buffer 都那么 NB,socket 不更 NB 吗?所以后面的研究路线是:driver --> sk_buff --> socket

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lyndon_li/article/details/122897132

智能推荐

EasyDarwin开源流媒体云平台之EasyRMS录播服务器功能设计_开源录播系统-程序员宅基地

文章浏览阅读3.6k次。需求背景EasyDarwin开发团队维护EasyDarwin开源流媒体服务器也已经很多年了,之前也陆陆续续尝试过很多种服务端录像的方案,有:在EasyDarwin中直接解析收到的RTP包,重新组包录像;也有:在EasyDarwin中新增一个RecordModule,再以RTSPClient的方式请求127.0.0.1自己的直播流录像,但这些始终都没有成气候;我们的想法是能够让整套EasyDarwin_开源录播系统

oracle Plsql 执行update或者delete时卡死问题解决办法_oracle delete update 锁表问题-程序员宅基地

文章浏览阅读1.1w次。今天碰到一个执行语句等了半天没有执行:delete table XXX where ......,但是在select 的时候没问题。后来发现是在执行select * from XXX for update 的时候没有commit,oracle将该记录锁住了。可以通过以下办法解决: 先查询锁定记录 Sql代码 SELECT s.sid, s.seri_oracle delete update 锁表问题

Xcode Undefined symbols 错误_xcode undefined symbols:-程序员宅基地

文章浏览阅读3.4k次。报错信息error:Undefined symbol: typeinfo for sdk::IConfigUndefined symbol: vtable for sdk::IConfig具体信息:Undefined symbols for architecture x86_64: "typeinfo for sdk::IConfig", referenced from: typeinfo for sdk::ConfigImpl in sdk.a(config_impl.o) _xcode undefined symbols:

项目05(Mysql升级07Mysql5.7.32升级到Mysql8.0.22)_mysql8.0.26 升级32-程序员宅基地

文章浏览阅读249次。背景《承接上文,项目05(Mysql升级06Mysql5.6.51升级到Mysql5.7.32)》,写在前面需要(考虑)检查和测试的层面很多,不限于以下内容。参考文档https://dev.mysql.com/doc/refman/8.0/en/upgrade-prerequisites.htmllink推荐阅读以上链接,因为对应以下问题,有详细的建议。官方文档:不得存在以下问题:0.不得有使用过时数据类型或功能的表。不支持就地升级到MySQL 8.0,如果表包含在预5.6.4格_mysql8.0.26 升级32

高通编译8155源码环境搭建_高通8155 qnx 源码-程序员宅基地

文章浏览阅读3.7k次。一.安装基本环境工具:1.安装git工具sudo apt install wget g++ git2.检查并安装java等环境工具2.1、执行下面安装命令#!/bin/bashsudoapt-get-yinstall--upgraderarunrarsudoapt-get-yinstall--upgradepython-pippython3-pip#aliyunsudoapt-get-yinstall--upgradeopenjdk..._高通8155 qnx 源码

firebase 与谷歌_Firebase的好与不好-程序员宅基地

文章浏览阅读461次。firebase 与谷歌 大多数开发人员都听说过Google的Firebase产品。 这就是Google所说的“ 移动平台,可帮助您快速开发高质量的应用程序并发展业务。 ”。 它基本上是大多数开发人员在构建应用程序时所需的一组工具。 在本文中,我将介绍这些工具,并指出您选择使用Firebase时需要了解的所有内容。 在开始之前,我需要说的是,我不会详细介绍Firebase提供的所有工具。 我..._firsebase 与 google

随便推点

k8s挂载目录_kubernetes(k8s)的pod使用统一的配置文件configmap挂载-程序员宅基地

文章浏览阅读1.2k次。在容器化应用中,每个环境都要独立的打一个镜像再给镜像一个特有的tag,这很麻烦,这就要用到k8s原生的配置中心configMap就是用解决这个问题的。使用configMap部署应用。这里使用nginx来做示例,简单粗暴。直接用vim常见nginx的配置文件,用命令导入进去kubectl create cm nginx.conf --from-file=/home/nginx.conf然后查看kub..._pod mount目录会自动创建吗

java计算机毕业设计springcloud+vue基于微服务的分布式新生报到系统_关于spring cloud的参考文献有啥-程序员宅基地

文章浏览阅读169次。随着互联网技术的发发展,计算机技术广泛应用在人们的生活中,逐渐成为日常工作、生活不可或缺的工具,高校各种管理系统层出不穷。高校作为学习知识和技术的高等学府,信息技术更加的成熟,为新生报到管理开发必要的系统,能够有效的提升管理效率。一直以来,新生报到一直没有进行系统化的管理,学生无法准确查询学院信息,高校也无法记录新生报名情况,由此提出开发基于微服务的分布式新生报到系统,管理报名信息,学生可以在线查询报名状态,节省时间,提高效率。_关于spring cloud的参考文献有啥

VB.net学习笔记(十五)继承与多接口练习_vb.net 继承多个接口-程序员宅基地

文章浏览阅读3.2k次。Public MustInherit Class Contact '只能作基类且不能实例化 Private mID As Guid = Guid.NewGuid Private mName As String Public Property ID() As Guid Get Return mID End Get_vb.net 继承多个接口

【Nexus3】使用-Nexus3批量上传jar包 artifact upload_nexus3 批量上传jar包 java代码-程序员宅基地

文章浏览阅读1.7k次。1.美图# 2.概述因为要上传我的所有仓库的包,希望nexus中已有的包,我不覆盖,没有的添加。所以想批量上传jar。3.方案1-脚本批量上传PS:nexus3.x版本只能通过脚本上传3.1 批量放入jar在mac目录下,新建一个文件夹repo,批量放入我们需要的本地库文件夹,并对文件夹授权(base) lcc@lcc nexus-3.22.0-02$ mkdir repo2..._nexus3 批量上传jar包 java代码

关于去隔行的一些概念_mipi去隔行-程序员宅基地

文章浏览阅读6.6k次,点赞6次,收藏30次。本文转自http://blog.csdn.net/charleslei/article/details/486519531、什么是场在介绍Deinterlacer去隔行处理的方法之前,我们有必要提一下关于交错场和去隔行处理的基本知识。那么什么是场呢,场存在于隔行扫描记录的视频中,隔行扫描视频的每帧画面均包含两个场,每一个场又分别含有该帧画面的奇数行扫描线或偶数行扫描线信息,_mipi去隔行

ABAP自定义Search help_abap 自定义 search help-程序员宅基地

文章浏览阅读1.7k次。DATA L_ENDDA TYPE SY-DATUM. IF P_DATE IS INITIAL. CONCATENATE SY-DATUM(4) '1231' INTO L_ENDDA. ELSE. CONCATENATE P_DATE(4) '1231' INTO L_ENDDA. ENDIF. DATA: LV_RESET(1) TY_abap 自定义 search help