[Ethernet]网卡驱动 -- Features

本文解析Linux内核中的网络设备功能集管理,涵盖驱动初始化、用户请求控制、硬软件配置和特性描述。了解如何控制和适配netdev_features,包括校验和计算、分片、VLAN等高级功能。

本文摘自Linux Kernel Documentation/networking/netdev-features.txt文件,附带部分翻译。

原文标题
Netdev features mess and how to get out from it alive

Author:
Michał Mirosław mirq-linux@rere.qmqm.pl

Part I: Feature sets

Long gone are the days when a network card would just take and give packets
verbatim. Today’s devices add multiple features and bugs (read: offloads)
that relieve an OS of various tasks like generating and checking checksums,
splitting packets, classifying them. Those capabilities and their state
are commonly referred to as netdev features in Linux kernel world.

There are currently three sets of features relevant to the driver, and
one used internally by network core:

  1. netdev->hw_features set contains features whose state may possibly
    be changed (enabled or disabled) for a particular device by user’s
    request. This set should be initialized in ndo_init callback and not
    changed later.

    netdev->hw_features集包含的功能,其状态可能会根据用户的要求更改(启用或禁用)特定设备。
    此集应在回调中初始化ndo_init,以后不更改。

  2. netdev->features set contains features which are currently enabled
    for a device. This should be changed only by network core or in
    error paths of ndo_set_features callback.

    netdev->features集合包含当前启用设备的功能。
    这只能通过网络核心或ndo_set_features回调的错误路径来更改。

  3. netdev->vlan_features set contains features whose state is inherited
    by child VLAN devices (limits netdev->features set). This is currently
    used for all VLAN devices whether tags are stripped or inserted in
    hardware or software.

    netdev->vlan_features集包含由子 VLAN 设备继承其状态的功能(限制 netdev->功能集)。
    这当前用于所有 VLAN 设备,无论标签是否被剥离或插入硬件或软件中。

  4. netdev->wanted_features set contains feature set requested by user.
    This set is filtered by ndo_fix_features callback whenever it or
    some device-specific conditions change. This set is internal to
    networking core and should not be referenced in drivers.

    netdev->wanted_features集包含用户要求的功能集。
    每当ndo_fix_features特定设备条件发生变化时,就会通过回调过滤此集。此集是网络核心的内部设置,不应在驱动程序中引用。

Part II: Controlling enabled features

When current feature set (netdev->features) is to be changed, new set
is calculated and filtered by calling ndo_fix_features callback
and netdev_fix_features(). If the resulting set differs from current
set, it is passed to ndo_set_features callback and (if the callback
returns success) replaces value stored in netdev->features.
NETDEV_FEAT_CHANGE notification is issued after that whenever current
set might have changed.

The following events trigger recalculation:

  1. device’s registration, after ndo_init returned success
  2. user requested changes in features state
  3. netdev_update_features() is called

ndo_*_features callbacks are called with rtnl_lock held. Missing callbacks
are treated as always returning success.

A driver that wants to trigger recalculation must do so by calling
netdev_update_features() while holding rtnl_lock. This should not be done
from ndo_*_features callbacks. netdev->features should not be modified by
driver except by means of ndo_fix_features callback.

Part III: Implementation hints

  • ndo_fix_features:

All dependencies between features should be resolved here. The resulting
set can be reduced further by networking core imposed limitations (as coded
in netdev_fix_features()). For this reason it is safer to disable a feature
when its dependencies are not met instead of forcing the dependency on.

This callback should not modify hardware nor driver state (should be
stateless). It can be called multiple times between successive
ndo_set_features calls.

Callback must not alter features contained in NETIF_F_SOFT_FEATURES or
NETIF_F_NEVER_CHANGE sets. The exception is NETIF_F_VLAN_CHALLENGED but
care must be taken as the change won’t affect already configured VLANs.

  • ndo_set_features:

Hardware should be reconfigured to match passed feature set. The set
should not be altered unless some error condition happens that can’t
be reliably detected in ndo_fix_features. In this case, the callback
should update netdev->features to match resulting hardware state.
Errors returned are not (and cannot be) propagated anywhere except dmesg.
(Note: successful return is zero, >0 means silent error.)

Part IV: Features

For current list of features, see include/linux/netdev_features.h.
This section describes semantics of some of them.

  • Transmit checksumming

For complete description, see comments near the top of include/linux/skbuff.h.

Note: NETIF_F_HW_CSUM is a superset of NETIF_F_IP_CSUM + NETIF_F_IPV6_CSUM.
It means that device can fill TCP/UDP-like checksum anywhere in the packets
whatever headers there might be.

  • Transmit TCP segmentation offload

NETIF_F_TSO_ECN means that hardware can properly split packets with CWR bit
set, be it TCPv4 (when NETIF_F_TSO is enabled) or TCPv6 (NETIF_F_TSO6).

  • Transmit UDP segmentation offload

NETIF_F_GSO_UDP_L4 accepts a single UDP header with a payload that exceeds
gso_size. On segmentation, it segments the payload on gso_size boundaries and
replicates the network and UDP headers (fixing up the last one if less than
gso_size).

  • Transmit DMA from high memory

On platforms where this is relevant, NETIF_F_HIGHDMA signals that
ndo_start_xmit can handle skbs with frags in high memory.

  • Transmit scatter-gather

Those features say that ndo_start_xmit can handle fragmented skbs:
NETIF_F_SG — paged skbs (skb_shinfo()->frags)
NETIF_F_FRAGLIST — chained skbs (skb->next/prev list).

  • Software features

Features contained in NETIF_F_SOFT_FEATURES are features of networking
stack. Driver should not change behaviour based on them.

  • LLTX driver (deprecated for hardware drivers)

NETIF_F_LLTX is meant to be used by drivers that don’t need locking at all,
e.g. software tunnels.

This is also used in a few legacy drivers that implement their
own locking, don’t use it for new (hardware) drivers.

  • netns-local device

NETIF_F_NETNS_LOCAL is set for devices that are not allowed to move between
network namespaces (e.g. loopback).

Don’t use it in drivers.

  • VLAN challenged

NETIF_F_VLAN_CHALLENGED should be set for devices which can’t cope with VLAN
headers. Some drivers set this because the cards can’t handle the bigger MTU.
[FIXME: Those cases could be fixed in VLAN code by allowing only reduced-MTU
VLANs. This may be not useful, though.]

  • rx-fcs

This requests that the NIC append the Ethernet Frame Checksum (FCS)
to the end of the skb data. This allows sniffers and other tools to
read the CRC recorded by the NIC on receipt of the packet.

  • rx-all

This requests that the NIC receive all possible frames, including errored
frames (such as bad FCS, etc). This can be helpful when sniffing a link with
bad packets on it. Some NICs may receive more packets if also put into normal
PROMISC mode.

  • rx-gro-hw

This requests that the NIC enables Hardware GRO (generic receive offload).
Hardware GRO is basically the exact reverse of TSO, and is generally
stricter than Hardware LRO. A packet stream merged by Hardware GRO must
be re-segmentable by GSO or TSO back to the exact original packet stream.
Hardware GRO is dependent on RXCSUM since every packet successfully merged
by hardware must also have the checksum verified by hardware.

### U-Boot 中网卡 PHY 的移植 在 U-Boot 中进行网卡 PHY 的移植是一项复杂的工作,涉及多个层面的配置和实现。以下是关于如何完成这一任务的具体细节: #### 1. 理解 PHY 芯片及其驱动框架 PHY 是物理层收发器 (Physical Layer Transceiver),负责以太网数据链路层与物理介质之间的通信。U-Boot 提供了一个通用的 PHY 框架来支持不同类型的 PHY 芯片[^2]。 对于特定型号的 PHY(如裕太微电子 YT8511),通常需要确认该芯片是否已被纳入到主流 U-Boot 版本的支持列表中。如果未被支持,则需手动添加其驱动程序并适配至现有框架。 #### 2. 修改设备树文件 设备树描述了硬件资源分配情况,在现代嵌入式系统开发过程中占据重要地位。为了使新加入的 PHY 正常工作,可能需要更新对应的 `.dts` 文件,定义必要的参数比如地址、中断线号以及连接方式等信息[^4]: ```dts &ethernet { phy-handle = <&phy0>; phy-mode = "rmii"; /* 或者 mii */ }; &mdio { #address-cells = <1>; #size-cells = <0>; phy0: ethernet-phy@0 { compatible = "yutai,yt8511"; }; }; ``` 上述代码片段展示了如何通过设备树指定所使用的 PHY 类型及模式设置。 #### 3. 添加或调整 PHY 驱动代码 当目标平台上的 PHY 不受当前版本 U-Boot 支持时,开发者应依据官方文档编写专属驱动模块。此过程大致分为以下几个方面: - **注册新的 PHY 设备**: 将自定义的 PHY 描述符添加进 `drivers/net/phy/Kconfig` 和相应的 Makefile 当中。 - **实现核心功能函数**: 编写初始化、读取状态寄存器等功能接口,确保它们遵循既定 API 定义[^3]。 下面是一个简单的例子展示如何扩展已有的 PHY 表格结构体: ```c static struct phy_driver yt8511_phy __phy_table_ptr = { .uid = 0x001cc916, .name = "yt8511", .features = PHY_GBIT_FEATURES, // 实现其他成员变量... }; mii_register_phy(&yt8511_phy); ``` 注意这里假设了YT8511具有千兆能力,并设置了相应特性标志位;实际应用当中还需要仔细查阅具体器件手册以便正确填充这些字段值。 #### 4. 测试验证 最后一步就是进行全面的功能测试,包括但不限于连通性检测(ping命令)、速度协商状况观察等等。任何异常现象都应该追溯根源直至彻底解决为止。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值