36

以太网驱动流程浅析(一)-ifconfig主要流程

 4 years ago
source link: https://www.tuicool.com/articles/3aArUv6
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
作者简介:
大家好,我叫张昺华,中间那个字和“饼”字一个读音。
2014年我毕业于广东省惠州学院,我从小酷爱理科,当看到陈莉君老师在《Linux内核之旅》上发的学生在课堂上用课本剧的方式来诠释技术时,想到了自己初中的时候老师就是这样锻炼我们的,很喜欢那样的学习氛围,自己大学时和小伙伴们一起创立了科技创新协会,目的就是可以一群人在研究技术,一起做有意思的东西,一起分享技术带给我们的快乐,也希望中国有更多的人热爱技术,喜欢一起研究、分享技术,然后可以一起用我们的技术来做一些好玩的东西,可以为这个社会创造一些东西来改善人们的生活。
eA326jq.png!web

如下是本人调试过程中的一点经验分享,以太网驱动架构毕竟涉及的东西太多,如下仅仅是针对加载流程和围绕这个问题产生的分析过程和驱动加载流程部分,并不涉及以太网协议层的数据流程分析。

fQna2y2.gif

问题描述

机器通过usb方式下载了mac地址后,发现以太网无法正常使用,敲命令 ifconfig eth0 up出现:ifconfig: SIOCSIFFLAGS: No such device,而对于没有下载以太网mac address的机器表现均正常。调试过程中发现在以太网控制器代码中加入一些printk,不正常的机器又正常了,打印的位置不同,机器的以太网有时会正常,有时会异常,十分诡异。

原因分析

reset时序问题导致,phy reset的时间不满足时序要求。如下图,如果硬件接了reset引脚,应满足时序要求在reset保持10ms有效电平后,还必须维持至少150ms才可以访问phy register,也就是reset要在B点之后才可以正常通过MDC/MDIO来访问phy register。如果是不使用硬件reset,使用软件reset方式,那也要至少在A点,也就是在reset维持10ms有效电平后,再维持3.5个clk才能正常访问phy register。

FJvUra7.png!web

那为什么下载了mac地址后才异常呢?不下载的又正常呢?
【原因分析】
freescale控制器获取mac address流程如下:
1)模块化参数设置,如果没有跳到步骤2;
2)device tree中设置,如果没有跳到步骤3;
3)from flash / fuse / via platform data,如果没有跳到步骤4;
4)FEC mac registers set by bootloader===》即靠usb方式下载mac address ,如果没有跳到步骤5;
5)靠kernel算一个随机数mac address出来,然后写入mac
那为什么下载了mac地址后才异常呢?
下了mac后,会执行步骤4,不会执行步骤5,此时目前的代码不满足150ms的时序要求,无法访问phy register,
导致phy_id获取不到,因此phy_device也不会创建
那为什么不下载的又正常呢?
不下载mac address,会执行步骤5 ,步骤5中调用了函数eth_hw_addr_random
刚好满足了150ms的时序要求,所以才可以正常

VRNrMj3.png!web

跟入代码eth_hw_addr_random看下:

R3aiYnq.png!web

继续看

BbyMby7.png!web

终调用了kernel提供的获取随机数的一个函数,这块代码比较多就不继续追下去了。

fAn2A3F.png!web

所以这块步骤五的代码刚刚好好在这个硬件条件下,恰巧满足了150ms的reset时序要求,所以以太网才可以正常。

以太网流程分析跟踪

1 Ifconfig主要流程
回归主题,根据这个ifconfig失败的现象,我们追踪一下code:
ifconfig: SIOCSIFFLAGS: No such device,既然出现了这个问题log,我们就从应用层的log入手,首先我们使用strace命令来追踪下系统调用,以便于我们追踪内核代码实现。
strace ifconfig eth0 up跟踪一下

Jv2Afe2.png!web

可以发现主要是ioctl的操作,SIOCSIFFLAGS,然后我们需要了解下这个宏的意思,说白了就是设置各种flag,靠ioctl第三个参数把所需要的动作flag传入,比如说此时要对eth0进行up动作,那么就传入IFF_UP,例如:

struct ifreq ifr;

6buIbiv.png!web

NBbERfB.png!web

qI7ra2U.png!web

我们看这些主要是想知道为什么会打印这个log:
ifconfig: SIOCSIFFLAGS: No such device
那么内核中又是对ioctl做了什么动作呢?因为strace命令让我们知道了系统调用调用函数,我们可以在kernel中直接搜索SIOCSIFFLAGS,或者去以太网驱动net目录下直接搜索更快。最终我搜到了,路径是:net/ipv4/devinet.c
我们可以看到内核的宏定义:

YZ36J3U.jpg!web

查看devinet.c的代码,我们找到了那个宏,也就是做devinet_ioctl函数中,这也就是应用层的ioctl最终的实现函数,然后我们在里面加一些打印,

zumuaii.png!web

jIn6Bnm.png!web

VV7nIrY.png!web

通过打印结果我们可以确认是这个函数devinet_ioctl为应用层的ioctl的实现函数,因为你在kernel中搜SIOCSIFFLAGS宏的话会有很多地方出现的,所以我们需要确认我们找的函数没问题:

看到这里返回值ret是-19,那么我们继续顺着追踪下去,上代码:

net/core/dev.c

JJZZ3aY.png!web

继续追踪: ne t/core/dev.c

YbMR3ie.jpg!web

muu673j.png!web

因此我们可以看到返回值-19就是如下代码产生的

juYjIrI.png!web

因此我们需要追踪__dev_open函数,继续看代码:

zyIviqR.jpg!web

URnEZzN.png!web

通过调试,比如说加打印,或者是经验我们可以推断出是这里返回的-19,那么这个ndo_open又是在哪里回调的呢?

uIBvUvQ.png!web

我们可以看到ops这个结构的结构体
struct net_device *dev
const struct net_device_ops *ops = dev->netdev_ops;

6fuEva7.png!web

这里熟悉驱动的朋友应该可以猜到这在在freescale的以太网控制器驱动中一定有它的实现
net_device_ops就是kernel提供给drvier操作net_device的一些操作方法,具体实现自然由相应厂商的driver自己去实现。
路径:drivers/net/Ethernet/freescale/fec_main.c

v22qQbE.jpg!web

我们可以在这个fec_enet_open函数中加入dump_stack来看下整个调用情况

我们打出kernel的dump_stack信息来看:

Q3mqmmV.jpg!web

这个调用过程就是应用层ioctl一直到kernel最底层fec_enet_open的过程。

应用代码这样:

bEjAvyj.png!web

总体流程:kill() -> kill.S -> swi陷入内核态 -> 从sys_call_table查看到sys_kill -> ret_fast_syscall -> 回到用户态执行kill()下一行代码
Ioctl<==ret_fast_syscall<==SyS_ioctl<==do_vfs_ioctl<==vfs_ioctl<==sock_ioctl<==devinet_ioctl<==dev_change_flags<==__dev_change_flags<==__dev_open<==fec_enet_open
我附上每个函数的代码:
如果大家想看系统调用流程的话,参考这篇,我就不做这块的说明了:
Linux系统调用(syscall)原理
http://gityuan.com/2016/05/21/syscall/
Arm Linux系统调用流程详细解析
https://www.cnblogs.com/cslunatic/p/3655970.html

网址分享

http://stackoverflow.com/questions/5308090/set-ip-address-using-siocsifaddr-ioctl
 
http://www.ibm.com/support/knowledgecenter/ssw_aix_72/com.ibm.aix.commtrf2/ioctl_socket_control_operations.htm
 
https://lkml.org/lkml/2017/2/3/396
linux PHY驱动
http://www.latelee.org/programming-under-linux/linux-phy-driver.html
Linux PHY几个状态的跟踪
http://www.latelee.org/programming-under-linux/linux-phy-state.html
第十六章PHY -基于Linux3.10
https://blog.csdn.net/shichaog/article/details/44682931
【作者】张昺华
【博客园】 http://www.cnblogs.com/sky-heaven/
【知乎】 http://www.zhihu.com/people/zhang-bing-hua
【我的作品---旋转倒立摆】 
http://v.youku.com/v_show/id_XODM5NDAzNjQw.html?spm=a2hzp.8253869.0.0&from=y1.7-2
【我的作品---自平衡自动循迹车】 
http://v.youku.com/v_show/id_XODM5MzYyNTIw.html?spm=a2hzp.8253869.0.0&from=y1.7-2
【大饼教你学系列】https://edu.csdn.net/course/detail/10393
【twitter】 @sky2030_
【facebook】 张昺华 zhangbinghua
i6beI3i.png!web

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK