Linux内核下网卡硬件 MAC 和PHY分析笔记

1 简介

通常CPU自带的以太网接口是MAC控制器,为了实现完整的功能,外围硬件还需要增加一个PHY芯片。

PHY芯片在建立网络连接时负责协商确定网速、全双工 或者 半双工等。在正常通讯时负责在MAC控制器的MII信号 与 网线中的信号之间做转换。

本文的内核代码主要来自kernel-5.4.18

2 PHY芯片 和 MDIO bus

2.1 简介

Most network devices consist of set of registers which provide an interface to a MAC layer, which communicates with the physical connection through a PHY.

The PHY concerns itself with negotiating link parameters with the link partner on the other side of the network connection (typically, an ethernet cable), and provides a register interface to allow drivers to determine what settings were chosen, and to configure what settings are allowed.

                                《Documentation/networking/phy.rst》

2.2 驱动分析

2.2.1 数据结构

struct phy_device;
struct phy_driver;

struct class mdio_bus_class;
struct bus_type mdio_bus_type;
struct mii_bus;
struct mdio_device;
struct mdio_driver;

 

2.2.2 mii_bus、phy_device 和 mdio_device 的初始化

mdiobus_register();
    -> __mdiobus_register();     
        -> mdiobus_scan();       
            -> get_phy_device();
                -> get_phy_id();
                    -> mdiobus_read();
                -> phy_device_create();
            -> phy_device_register();
                -> mdiobus_register_device();

struct mii_bus表示一个mdio bus,mdiobus_register()函数用来向内核注册一个mdio bus。在注册mdio bus时会扫描这个mdio bus上连接的所有phy芯片。

一个mdio bus上最多可以连接32个phy芯片,每个phy芯片都有一个唯一的总线地址。驱动代码会通过唯一的总线地址去读取phy芯片的ID,如果在某个总线地址上读到了ID,就意味着发现了一个phy芯片。

发现phy芯片后,会调用phy_device_create()函数创建struct phy_device和struct mdio_device对象,然后调用phy_device_register() 和 mdiobus_register_device()函数向内核注册device。

在注册phy_device后,会遍历内核中的phy_driver,通过结构体中成员变量phy_id来配对。

2.2.3 通⽤phy驱动

//drivers/net/phy/phy_device.c
static struct phy_driver genphy_driver = {
    .phy_id     = 0xffffffff,
    .phy_id_mask    = 0xffffffff,
    .name       = "Generic PHY",
    .soft_reset = genphy_no_soft_reset,
    .get_features   = genphy_read_abilities,
    .aneg_done  = genphy_aneg_done,
    .suspend    = genphy_suspend,
    .resume     = genphy_resume,
    .set_loopback   = genphy_loopback,
};


2.3 查看系统下的相关信息

2.3.1 查看设备和驱动的信息:/sys/bus/mdio_bus/

# ls /sys/bus/mdio_bus/drivers
'Broadcom BCM84881'  'Generic Clause 45 PHY'  'Generic PHY'

2.3.2 设备类信息:/sys/class/phy/

2.3.3 mdio bus的统计信息:/sys/class/mdio_bus/<bus>/statistics/  (kernel-5.6以后的内核才有)

# ls /sys/class/mdio_bus/fixed-0/statistics/
errors     errors_18  errors_28  reads     reads_18  reads_28  transfers     transfers_18  transfers_28  writes     writes_18  writes_28
errors_0   errors_19  errors_29  reads_0   reads_19  reads_29  transfers_0   transfers_19  transfers_29  writes_0   writes_19  writes_29
errors_1   errors_2   errors_3   reads_1   reads_2   reads_3   transfers_1   transfers_2   transfers_3   writes_1   writes_2   writes_3
errors_10  errors_20  errors_30  reads_10  reads_20  reads_30  transfers_10  transfers_20  transfers_30  writes_10  writes_20  writes_30
errors_11  errors_21  errors_31  reads_11  reads_21  reads_31  transfers_11  transfers_21  transfers_31  writes_11  writes_21  writes_31
errors_12  errors_22  errors_4   reads_12  reads_22  reads_4   transfers_12  transfers_22  transfers_4   writes_12  writes_22  writes_4
errors_13  errors_23  errors_5   reads_13  reads_23  reads_5   transfers_13  transfers_23  transfers_5   writes_13  writes_23  writes_5
errors_14  errors_24  errors_6   reads_14  reads_24  reads_6   transfers_14  transfers_24  transfers_6   writes_14  writes_24  writes_6
errors_15  errors_25  errors_7   reads_15  reads_25  reads_7   transfers_15  transfers_25  transfers_7   writes_15  writes_25  writes_7
errors_16  errors_26  errors_8   reads_16  reads_26  reads_8   transfers_16  transfers_26  transfers_8   writes_16  writes_26  writes_8
errors_17  errors_27  errors_9   reads_17  reads_27  reads_9   transfers_17  transfers_27  transfers_9   writes_17  writes_27  writes_9

文件内容说明:

                                《Documentation/ABI/testing/sysfs-bus-mdio(kernel-5.6)》

2.4 mdio bus调试:/sys/kernel/debug/tracing/events/mdio/mdio_access

__mdiobus_read();
    -> trace_mdio_access();

__mdiobus_write();
    -> trace_mdio_access();

3 MAC 与 PHY之间的网络数据接口(各种MII)

3.1 数据结构

//include/linux/phy.h
struct phy_device {
    ......
    phy_interface_t interface;
    ......
};
//include/linux/phy.h
/* Interface Mode definitions */
typedef enum {
    PHY_INTERFACE_MODE_NA,
    PHY_INTERFACE_MODE_INTERNAL,
    PHY_INTERFACE_MODE_MII,
    PHY_INTERFACE_MODE_GMII,
    PHY_INTERFACE_MODE_SGMII,
    PHY_INTERFACE_MODE_TBI,
    PHY_INTERFACE_MODE_REVMII,
    PHY_INTERFACE_MODE_RMII,
    PHY_INTERFACE_MODE_RGMII,
    PHY_INTERFACE_MODE_RGMII_ID,
    PHY_INTERFACE_MODE_RGMII_RXID,
    PHY_INTERFACE_MODE_RGMII_TXID,
    PHY_INTERFACE_MODE_RTBI,
    PHY_INTERFACE_MODE_SMII,
    PHY_INTERFACE_MODE_XGMII,
    PHY_INTERFACE_MODE_MOCA,
    PHY_INTERFACE_MODE_QSGMII,
    PHY_INTERFACE_MODE_TRGMII,
    PHY_INTERFACE_MODE_1000BASEX,
    PHY_INTERFACE_MODE_2500BASEX,
    PHY_INTERFACE_MODE_RXAUI,
    PHY_INTERFACE_MODE_XAUI,
    /* 10GBASE-KR, XFI, SFI - single lane 10G Serdes */
    PHY_INTERFACE_MODE_10GKR,
    PHY_INTERFACE_MODE_USXGMII,
    PHY_INTERFACE_MODE_MAX,
} phy_interface_t;

3.2 在设备树中指定使用哪种MII

3.2.1 设备树属性“phy-mode” 和 “phy-connection-type”

可选的属性值

//Documentation/devicetree/bindings/net/ethernet-controller.yaml

      - internal
      - mii
      - gmii
      - sgmii
      - qsgmii
      - tbi
      - rev-mii
      - rmii

      # RX and TX delays are added by the MAC when required
      - rgmii

      # RGMII with internal RX and TX delays provided by the PHY,
      # the MAC should not add the RX or TX delays in this case
      - rgmii-id

      # RGMII with internal RX delay provided by the PHY, the MAC
      # should not add an RX delay in this case
      - rgmii-rxid

      # RGMII with internal TX delay provided by the PHY, the MAC
      # should not add an TX delay in this case
      - rgmii-txid
      - rtbi
      - smii
      - xgmii
      - trgmii
      - 1000base-x
      - 2500base-x
      - rxaui
      - xaui

      # 10GBASE-KR, XFI, SFI
      - 10gbase-kr
      - usxgmii

3.2.2 获取“phy-mode” 和 “phy-connection-type”属性的函数

of_get_phy_mode();
    -> of_property_read_string(np, "phy-mode", &pm);
    -> of_property_read_string(np, "phy-connection-type", &pm);

 3.3 RGMII信号中的 delay

The Reduced Gigabit Medium Independent Interface (RGMII) is a 12-pin
electrical signal interface using a synchronous 125Mhz clock signal and several
data lines. Due to this design decision, a 1.5ns to 2ns delay must be added
between the clock line (RXC or TXC) and the data lines to let the PHY (clock
sink) have enough setup and hold times to sample the data lines correctly. The 
PHY library offers different types of PHY_INTERFACE_MODE_RGMII* values to let 
the PHY driver and optionally the MAC driver, implement the required delay. The 
values of phy_interface_t must be understood from the perspective of the PHY 
device itself, leading to the following:

* PHY_INTERFACE_MODE_RGMII: the PHY is not responsible for inserting any 
  internal delay by itself, it assumes that either the Ethernet MAC (if capable
  or the PCB traces) insert the correct 1.5-2ns delay

* PHY_INTERFACE_MODE_RGMII_TXID: the PHY should insert an internal delay
  for the transmit data lines (TXD[3:0]) processed by the PHY device

* PHY_INTERFACE_MODE_RGMII_RXID: the PHY should insert an internal delay
  for the receive data lines (RXD[3:0]) processed by the PHY device

* PHY_INTERFACE_MODE_RGMII_ID: the PHY should insert internal delays for 
  both transmit AND receive data lines from/to the PHY device

Whenever possible, use the PHY side RGMII delay for these reasons:

* PHY devices may offer sub-nanosecond granularity in how they allow a
  receiver/transmitter side delay (e.g: 0.5, 1.0, 1.5ns) to be specified. Such
  precision may be required to account for differences in PCB trace lengths

* PHY devices are typically qualified for a large range of applications
  (industrial, medical, automotive...), and they provide a constant and 
  reliable delay across temperature/pressure/voltage ranges

* PHY device drivers in PHYLIB being reusable by nature, being able to
  configure correctly a specified delay enables more designs with similar delay
  requirements to be operate correctly

For cases where the PHY is not capable of providing this delay, but the
Ethernet MAC driver is capable of doing so, the correct phy_interface_t value
should be PHY_INTERFACE_MODE_RGMII, and the Ethernet MAC driver should be
configured correctly in order to provide the required transmit and/or receive
side delay from the perspective of the PHY device. Conversely, if the Ethernet
MAC driver looks at the phy_interface_t value, for any other mode but
PHY_INTERFACE_MODE_RGMII, it should make sure that the MAC-level delays are
disabled.

In case neither the Ethernet MAC, nor the PHY are capable of providing the
required delays, as defined per the RGMII standard, several options may be
available:

* Some SoCs may offer a pin pad/mux/controller capable of configuring a given
  set of pins'strength, delays, and voltage; and it may be a suitable
  option to insert the expected 2ns RGMII delay.

* Modifying the PCB design to include a fixed delay (e.g: using a specifically
  designed serpentine), which may not require software configuration at all.

                                《Documentation/networking/phy.rst》

3.4 查看当前系统下MAC和PHY之间正在使用的是哪种MII

/sys/class/mdio_bus/<bus>/<device>/phy_interface

                                《Documentation/ABI/testing/sysfs-class-net-phydev》

3.5 特殊用法:两个MAC控制器通过MII直连,不经过PHY芯片

在这种情况下因为没有PHY芯片,硬件上无法通过协商确定网速、全/半双工等状态信息,需要通过其他方式来获取这些信息,请看下面的“fixed-link”相关的章节。

4 物理链路的状态

4.1 简介

网络物理链路状态在发生改变时,需要确定 UP/DOWN、网速、全双工还是半双工等关键状态信息。

多数时候网络物理链路的状态是通过phy硬件协商确定的,还有另一种方法就是直接指定物理链路的状态。

在某些特殊的硬件设计中,直接将两个MAC控制器的MII信号直连,不使用PHY芯片,这导致硬件无法协商确定物理链路状态,这种情况下也需要直接指定物理链路状态。

4.2 通过phy芯片获取物理链路状态

4.2.1 状态处理工作项

在创建phy_device时会创建工作项,处理函数是phy_state_machine();

phy_device_create();
    -> INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);

 

4.2.2 向内核添加工作项

轮训模式:
        当phydev->irq == PHY_POLL时,采用轮训模式,轮训间隔是1秒,轮训间隔由宏 PHY_STATE_TIME 控制。


中断模式:

phy_request_interrupt();
    -> request_threaded_irq(phydev->irq, NULL, phy_interrupt, ...);

phy_interrupt();
​​​​​​​    -> phy_trigger_machine();

4.3 Fixed MDIO bus

4.3.1 简介

内核配置:CONFIG_FIXED_PHY

MDIO Bus/PHY emulation with fixed speed/link PHYs
Adds the platform "fixed" MDIO Bus to cover the boards that use PHYs that are not connected to the real MDIO bus.

                                drivers/net/phy/Kconfig

4.3.2 初始化

static int __init fixed_mdio_bus_init(void)
{
    struct fixed_mdio_bus *fmb = &platform_fmb;
    int ret;

    pdev = platform_device_register_simple("Fixed MDIO bus", 0, NULL, 0);
    ......
    snprintf(fmb->mii_bus->id, MII_BUS_ID_SIZE, "fixed-0");
    fmb->mii_bus->name = "Fixed MDIO Bus";
    fmb->mii_bus->priv = fmb;
    fmb->mii_bus->parent = &pdev->dev;
    fmb->mii_bus->read = &fixed_mdio_read;
    fmb->mii_bus->write = &fixed_mdio_write;

    ret = mdiobus_register(fmb->mii_bus);
    ......
}
module_init(fixed_mdio_bus_init);

4.3.3 查看系统下的Fixed MDIO bus信息

/sys/class/mdio_bus/fixed-0/
/sys/bus/platform/devices/Fixed\ MDIO\ bus.0/

 

4.4 通过设备树节点“fixed-link”指定物理链路的状态

4.4.1 设备树“fixed-link”节点的属性

"full-duplex"
"speed"
"pause"
"asym-pause"
“link-gpios”

含义如下(Documentation/devicetree/bindings/net/ethernet-controller.yaml)

          properties:
            speed:
              allOf:
                - $ref: /schemas/types.yaml#definitions/uint32
                - enum: [10, 100, 1000]
              description:
                Link speed.

            full-duplex:
              $ref: /schemas/types.yaml#definitions/flag
              description:
                Indicates that full-duplex is used. When absent, half
                duplex is assumed.

            asym-pause:
              $ref: /schemas/types.yaml#definitions/flag
              description:
                Indicates that asym_pause should be enabled.

            link-gpios:
              maxItems: 1
              description:
                GPIO to determine if the link is up

4.4.2 对应的数据结构

struct fixed_phy_status {
    int link;
    int speed;
    int duplex;
    int pause;
    int asym_pause;
};

4.4.3 获取设备树中“fixed-link”内容的代码

of_phy_register_fixed_link();
    -> fixed_phy_register();
        -> __fixed_phy_register();

4.5 通过ethtool命令设置物理链路状态

例如:ethtool -s enp0s31f6 speed 100 duplex full autoneg off

内核中对应的代码:struct ethtool_ops->set_link_ksettings();

4.6 查看网络物理链路的状态信息

方法一、ethtool enp0s31f6

方法二、
                /sys/class/net/<net_dev>/duplex
                /sys/class/net/<net_dev>/speed

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/692329.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Servlet-01

文章目录 Servlet创建Servlet探究Servlet的生命周期 HttpServletWebServlet注解详解 重定向与请求转发ServletContextServletContext中的接口 HttpServletRequestHttpServletResponse状态码解释Cookie Servlet Q&#xff1a;它能做什么呢&#xff1f; A&#xff1a;我们可以通…

[office] Excel教学:Excel通配符怎么用? #其他#职场发展

Excel教学&#xff1a;Excel通配符怎么用&#xff1f; 尽管Excel使用了很多年&#xff0c;但很多人都还是忽略了Excel通配符的存在&#xff0c;不知道通配符是什么&#xff0c;不知道如何使用它。今天我就完整地介绍一下通配符&#xff0c;让你彻底地认识通配符。 关于通配符…

SpringBoot2+Vue3开发课程审核流程系统

SpringBoot2Vue3开发课程审核流程系统 简介 此系统实现了课程审核全流程功能并使用了Activiti7工作流技术&#xff0c;功能包含&#xff1a;课程管理、用户管理、流程定义、课程审核&#xff08;我的申请、我的代办、我的已办&#xff09; 功能介绍 课程管理 对课程信息的管…

【JavaScript对象详解】 Day05

JavaScript对象详解 JavaScript 基础 - 第5天对象语法对象属性对象使用属性-查属性-改属性-增属性-删 &#xff08;了解&#xff09; 方法和调用遍历对象遍历数组对象null 内置对象Math属性方法生成任意范围随机数 综合案例随机点名案例猜数字游戏猜数字游戏设定次数生成随机颜…

深入解读Prometheus Adapter:云原生监控的核心组件

一、引言 Prometheus Adapter的背景与重要性 在现代的云原生架构中&#xff0c;微服务和容器化技术得到了广泛的应用。这些技术带来了系统灵活性和扩展性的提升&#xff0c;但同时也增加了系统监控和管理的复杂度。Prometheus作为一款开源的监控系统&#xff0c;因其强大的指标…

微信小程序 导航navigation-bar

属性类型默认值必填说明最低版本titlestring否导航条标题2.9.0loadingbooleanfalse否是否在导航条显示 loading 加载提示2.9.0front-colorstring否导航条前景颜色值&#xff0c;包括按钮、标题、状态栏的颜色&#xff0c;仅支持 #ffffff 和 #0000002.9.0background-colorstring…

javaweb学习(day14-ThreadLocal文件上传下载)

一、线程数据共享和安全 -ThreadLocal 1 什么是 ThreadLocal ThreadLocal 的作用&#xff0c;可以实现在同一个线程数据共享, 从而解决多线程数据安全问题. ThreadLocal 可以给当前线程关联一个数据(普通变量、对象、数组)set 方法 [源码!] ThreadLocal 可以像 Map 一样存取数…

Steam下载游戏很慢?一个设置解决!

博主今天重装系统后&#xff0c;用steam下载发现巨慢 500MB&#xff0c;都要下载半小时。 平时下载软件&#xff0c;一般1分钟就搞定了&#xff0c;于是大致就知道&#xff0c;设置应该出问题了 于是修改了&#xff0c;如下设置之后&#xff0c;速度翻了10倍。 如下&#x…

Mysql使用中的性能优化——单次插入和批量插入的性能差异

一般Mysql的客户端和服务端不在一台机器上&#xff0c;所以它们之间的通信需要通过网络进行。我们本次实验&#xff0c;希望抛开网络的影响&#xff0c;测试不同SQL方案在Mysql服务器上的执行效率的对比。于是我们使用“存储过程”来辅助测试。 结论 先上结论&#xff1a; 批…

windows安装conda

1 Conda简介 Conda 是一个开源的软件包管理系统和环境管理系统&#xff0c;用于安装多个版本的软件包及其依赖关系&#xff0c;并在它们之间轻松切换。Conda 是为 Python 程序创建的&#xff0c;适用于 Linux&#xff0c;OS X 和Windows&#xff0c;也可以打包和分发其他软…

【Vue】如何提供访问vuex的数据

文章目录 一、提供数据二、访问Vuex中的数据通过$store访问的语法1&#xff09;模板中使用2&#xff09;组件逻辑中使用3&#xff09;js文件中使用 三、通过辅助函数 - mapState获取 state中的数据 一、提供数据 State提供唯一的公共数据源&#xff0c;所有共享的数据都要统一…

Redis进阶知识个人汇总

持久化 三种方式实现它的持久化&#xff1a; RDB持久化 全称Redis数据备份文件&#xff0c;又称Redis数据快照 这种就是将Redis内存中所有数据记录到磁盘中&#xff0c;当实例出故障后&#xff0c;从磁盘中读快照文件进行恢复数据。 一般使用bgsave指令实现 复制主线程得到一…

NVeloDocx一个基于NVelocity的word模版引擎

NVeloDocx是一个基于NVelocity的Word模版引擎&#xff0c;目前主要是用于E6低代码开发平台供用户轻松制作各种Word报告模版。 有以下优点&#xff1a; 1、完全的NVelocity语法&#xff1b; 2、直接在Word中写NVelocity脚本&#xff0c;使用非常非常方便&#xff1b; 3、完全兼…

值类型和引用类型在使用和存储上的区别

使用上的区别 //值类型 int a 10; //引用类型 int[] arr new int[] { 1, 2, 3, 4, 5 };//声明了一个b让其等于之前的a int b a; //声明了一个arr2让其等于之前的arr int[] arr2 arr; Console.WriteLine("a{0},b{1}", a, b); Console.WriteLine("arr[0]{0},…

【SQLAlChemy】如何连接数据库?

使用SQLAlChemy连接数据库 导入包 首先&#xff0c;导入创建数据库引擎的包。 from sqlalchemy import create_engine编写数据库配置 SQLALCHEMY_DATABASE_URL "mysql://root:123456789127.0.0.1:3306/tortoise"字段解释&#xff1a; mysql:&#xff1a;这是数…

关于python中的列表和元组

变量就是一块内存空间&#xff0c;用来表示/存储数据 如果表示的数据较少&#xff0c;直接定义几个变量就行了 但是也有的时候&#xff0c;要表示的数据就比较多&#xff0c;如果只是通过定义一个变量来表示一个数据的话&#xff0c;这样的工作效率太低&#xff0c; 所以在p…

QT学习之标签+鼠标/定时器

标签鼠标 QEvent 需求鼠标进入控件范围会进行相关操作 在QEnterEvent类中 [virtual protected] void QWidget::enterEvent(QEnterEvent *event)虚成员函数可以进行重写 实现鼠标进入或离开Lable会打印输出 新建一个父类为QWidget的名字为mylable的C类文件 先声明在.h文件这…

[HGAME 2023 week4]shellcode

看题目&#xff0c;将base64解密&#xff0c;然后dump下来&#xff0c;再拉进ida里&#xff0c;发现为tea加密 在tea加密中得到key 密文就是另外的一个文件 exp import re from ctypes import *import libnumdef decrypt(v, k):v0, v1 c_uint32(v[0]), c_uint32(v[1])delta…

HTML做成一个炫酷跳动爱心的页面

大家好&#xff0c;今天制作制作一个炫酷跳动爱心的页面&#xff01; 先看具体效果&#xff1a; 要创建一个炫酷跳动爱心的HTML页面&#xff0c;你可以使用HTML、CSS和JavaScript的组合。以下是一个简单的示例&#xff0c;它使用CSS动画和JavaScript来实现跳动效果。 首先&…

【NetTopologySuite类库】C#生成带约束(线、面)的Delaunay三角网

介绍 API地址&#xff1a;https://nettopologysuite.github.io/NetTopologySuite/api/NetTopologySuite.Triangulate.ConformingDelaunayTriangulationBuilder.html#NetTopologySuite_Triangulate_ConformingDelaunayTriangulationBuilder_Constraints 约束为线 效果图 红色…