Linux 网络和网络设备 API

Linux 网络

网络基本类型

enum sock_type

套接字类型

常量

SOCK_STREAM

流(连接)套接字

SOCK_DGRAM

数据报(无连接)套接字

SOCK_RAW

原始套接字

SOCK_RDM

可靠传递的消息

SOCK_SEQPACKET

顺序数据包套接字

SOCK_DCCP

数据报拥塞控制协议套接字

SOCK_PACKET

在设备级别获取数据包的 Linux 特定方式。用于在用户级别编写 rarp 和其他类似的东西。

描述

在添加新的套接字类型时,请 grep ARCH_HAS_SOCKET_TYPE include/asm-* /socket.h,至少 MIPS 为了二进制兼容性而覆盖了这个枚举。

enum sock_shutdown_cmd

关闭类型

常量

SHUT_RD

关闭接收

SHUT_WR

关闭传输

SHUT_RDWR

关闭接收/传输

struct socket

通用 BSD 套接字

定义:

struct socket {
    socket_state state;
    short type;
    unsigned long           flags;
    struct file             *file;
    struct sock             *sk;
    const struct proto_ops  *ops;
    struct socket_wq        wq;
};

成员

state

套接字状态(SS_CONNECTED 等)

type

套接字类型(SOCK_STREAM 等)

flags

套接字标志(SOCK_NOSPACE 等)

file

用于垃圾回收的文件后向指针

sk

内部网络协议不可知套接字表示

ops

协议特定的套接字操作

wq

用于多种用途的等待队列

套接字缓冲区函数

unsigned int skb_frag_size(const skb_frag_t *frag)

返回 skb 片段的大小

参数

const skb_frag_t *frag

skb 片段

void skb_frag_size_set(skb_frag_t *frag, unsigned int size)

设置 skb 片段的大小

参数

skb_frag_t *frag

skb 片段

unsigned int size

片段的大小

void skb_frag_size_add(skb_frag_t *frag, int delta)

将 skb 片段的大小增加 delta

参数

skb_frag_t *frag

skb 片段

int delta

要添加的值

void skb_frag_size_sub(skb_frag_t *frag, int delta)

将 skb 片段的大小减少 delta

参数

skb_frag_t *frag

skb 片段

int delta

要减去的值

bool skb_frag_must_loop(struct page *p)

测试 p 是否为高内存页

参数

struct page *p

片段的页

skb_frag_foreach_page

skb_frag_foreach_page (f, f_off, f_len, p, p_off, p_len, copied)

循环访问片段中的页

参数

f

要操作的 skb 片段

f_off

从 f->netmem 的起始位置开始的偏移量

f_len

从 f_off 开始要循环的长度

p

(临时变量)当前页

p_off

(临时变量)从当前页起始位置开始的偏移量,仅在第一页上为非零。

p_len

(临时变量)当前页的长度,仅在第一页和最后一页上 < PAGE_SIZE。

copied

(临时变量)到目前为止的长度,不包括当前的 p_len。

片段可以保存复合页,在这种情况下,必须为每个常规页调用每页操作,特别是 kmap_atomic。

struct skb_shared_hwtstamps

硬件时间戳

定义:

struct skb_shared_hwtstamps {
    union {
        ktime_t hwtstamp;
        void *netdev_data;
    };
};

成员

{unnamed_union}

匿名

hwtstamp

硬件时间戳,转换为自任意时间点以来的持续时间

netdev_data

网络设备驱动程序的地址/cookie,用作实际硬件时间戳的参考

描述

ktime_get_real() 生成的软件时间戳存储在 skb->tstamp 中。

hwtstamps 只能与来自同一设备的其他 hwtstamps 进行比较。

此结构作为 skb_shared_info 的一部分附加到数据包。使用 skb_hwtstamps() 获取指针。

struct sk_buff

套接字缓冲区

定义:

struct sk_buff {
    union {
        struct {
            struct sk_buff          *next;
            struct sk_buff          *prev;
            union {
                struct net_device       *dev;
                unsigned long           dev_scratch;
            };
        };
        struct rb_node          rbnode;
        struct list_head        list;
        struct llist_node       ll_node;
    };
    struct sock             *sk;
    union {
        ktime_t tstamp;
        u64 skb_mstamp_ns;
    };
    char cb[48] ;
    union {
        struct {
            unsigned long   _skb_refdst;
            void (*destructor)(struct sk_buff *skb);
        };
        struct list_head        tcp_tsorted_anchor;
#ifdef CONFIG_NET_SOCK_MSG;
        unsigned long           _sk_redir;
#endif;
    };
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE);
    unsigned long            _nfct;
#endif;
    unsigned int            len, data_len;
    __u16 mac_len, hdr_len;
    __u16 queue_mapping;
#ifdef __BIG_ENDIAN_BITFIELD;
#define CLONED_MASK     (1 << 7);
#else;
#define CLONED_MASK     1;
#endif;
#define CLONED_OFFSET           offsetof(struct sk_buff, __cloned_offset);
    __u8 cloned:1,nohdr:1,fclone:2,peeked:1,head_frag:1,pfmemalloc:1, pp_recycle:1;
#ifdef CONFIG_SKB_EXTENSIONS;
    __u8 active_extensions;
#endif;
    __u8 pkt_type:3;
    __u8 ignore_df:1;
    __u8 dst_pending_confirm:1;
    __u8 ip_summed:2;
    __u8 ooo_okay:1;
    __u8 tstamp_type:2;
#ifdef CONFIG_NET_XGRESS;
    __u8 tc_at_ingress:1;
    __u8 tc_skip_classify:1;
#endif;
    __u8 remcsum_offload:1;
    __u8 csum_complete_sw:1;
    __u8 csum_level:2;
    __u8 inner_protocol_type:1;
    __u8 l4_hash:1;
    __u8 sw_hash:1;
#ifdef CONFIG_WIRELESS;
    __u8 wifi_acked_valid:1;
    __u8 wifi_acked:1;
#endif;
    __u8 no_fcs:1;
    __u8 encapsulation:1;
    __u8 encap_hdr_csum:1;
    __u8 csum_valid:1;
#ifdef CONFIG_IPV6_NDISC_NODETYPE;
    __u8 ndisc_nodetype:2;
#endif;
#if IS_ENABLED(CONFIG_IP_VS);
    __u8 ipvs_property:1;
#endif;
#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || IS_ENABLED(CONFIG_NF_TABLES);
    __u8 nf_trace:1;
#endif;
#ifdef CONFIG_NET_SWITCHDEV;
    __u8 offload_fwd_mark:1;
    __u8 offload_l3_fwd_mark:1;
#endif;
    __u8 redirected:1;
#ifdef CONFIG_NET_REDIRECT;
    __u8 from_ingress:1;
#endif;
#ifdef CONFIG_NETFILTER_SKIP_EGRESS;
    __u8 nf_skip_egress:1;
#endif;
#ifdef CONFIG_SKB_DECRYPTED;
    __u8 decrypted:1;
#endif;
    __u8 slow_gro:1;
#if IS_ENABLED(CONFIG_IP_SCTP);
    __u8 csum_not_inet:1;
#endif;
    __u8 unreadable:1;
#if defined(CONFIG_NET_SCHED) || defined(CONFIG_NET_XGRESS);
    __u16 tc_index;
#endif;
    u16 alloc_cpu;
    union {
        __wsum csum;
        struct {
            __u16 csum_start;
            __u16 csum_offset;
        };
    };
    __u32 priority;
    int skb_iif;
    __u32 hash;
    union {
        u32 vlan_all;
        struct {
            __be16 vlan_proto;
            __u16 vlan_tci;
        };
    };
#if defined(CONFIG_NET_RX_BUSY_POLL) || defined(CONFIG_XPS);
    union {
        unsigned int    napi_id;
        unsigned int    sender_cpu;
    };
#endif;
#ifdef CONFIG_NETWORK_SECMARK;
    __u32 secmark;
#endif;
    union {
        __u32 mark;
        __u32 reserved_tailroom;
    };
    union {
        __be16 inner_protocol;
        __u8 inner_ipproto;
    };
    __u16 inner_transport_header;
    __u16 inner_network_header;
    __u16 inner_mac_header;
    __be16 protocol;
    __u16 transport_header;
    __u16 network_header;
    __u16 mac_header;
#ifdef CONFIG_KCOV;
    u64 kcov_handle;
#endif;
    sk_buff_data_t tail;
    sk_buff_data_t end;
    unsigned char           *head, *data;
    unsigned int            truesize;
    refcount_t users;
#ifdef CONFIG_SKB_EXTENSIONS;
    struct skb_ext          *extensions;
#endif;
};

成员

{unnamed_union}

匿名

{unnamed_struct}

匿名

next

列表中的下一个缓冲区

prev

列表中的上一个缓冲区

{unnamed_union}

匿名

dev

我们到达/离开的设备

dev_scratch

(又名 dev)当 devNULL 时的 dev 的替代用法

rbnode

RB 树节点,替代 netem/tcp 的 next/prev

list

队列头

ll_node

llist 中的锚点(例如套接字 defer_list)

sk

我们所属的套接字

{unnamed_union}

匿名

tstamp

我们到达/离开的时间

skb_mstamp_ns

(又名 tstamp)最早的离开时间;重传计时器的起始点

cb

控制缓冲区。供每一层使用。将私有变量放在此处

{unnamed_union}

匿名

{unnamed_struct}

匿名

_skb_refdst

目标条目(带有 norefcount 位)

destructor

销毁函数

tcp_tsorted_anchor

TCP 的列表结构 (tp->tsorted_sent_queue)

_sk_redir

skmsg 的套接字重定向信息

_nfct

关联的连接(如果有的话)(带有 nfctinfo 位)

len

实际数据的长度

data_len

数据长度

mac_len

链路层标头的长度

hdr_len

克隆 skb 的可写标头长度

queue_mapping

多队列设备的队列映射

cloned

头可能被克隆(检查 refcnt 以确保)

nohdr

仅有效载荷引用,不得修改标头

fclone

skbuff 克隆状态

peeked

这个数据包已经被处理过了,所以已经对其进行了统计,不要再次处理。

头部片段

skb 是从页面片段分配的,而不是通过 kmalloc() 或 vmalloc() 分配的。

pfmemalloc

skbuff 是从 PFMEMALLOC 预留空间分配的

pp_recycle

标记该数据包用于回收而不是释放(意味着驱动程序支持 page_pool)

active_extensions

活动扩展(skb_ext_id 类型)

pkt_type

数据包类别

ignore_df

允许本地分片

dst_pending_confirm

需要确认邻居

ip_summed

驱动程序提供了 IP 校验和

ooo_okay

允许更改套接字到队列的映射

tstamp_type

设置后,skb->tstamp 具有 skb->tstamp 的 delivery_time 时钟基准。

tc_at_ingress

在 tc_classify 中用于区分入口/出口

tc_skip_classify

不分类数据包。由 IFB 设备设置

remcsum_offload

启用远程校验和卸载

csum_complete_sw

校验和已由软件完成

csum_level

表示数据包中找到的连续校验和数量减一,这些校验和已被验证为 CHECKSUM_UNNECESSARY(最多 3 个)

inner_protocol_type

内部协议是 ENCAP_TYPE_ETHER 还是 ENCAP_TYPE_IPPROTO

l4_hash

表示哈希是传输端口上的规范 4 元组哈希。

sw_hash

表示哈希是在软件堆栈中计算的

wifi_acked_valid

wifi_acked 已设置

wifi_acked

帧是否在 Wi-Fi 上被确认

no_fcs

请求网卡将最后 4 个字节视为以太网 FCS

encapsulation

表示 skbuff 中的内部标头有效

encap_hdr_csum

需要软件校验和

csum_valid

校验和已经有效

ndisc_nodetype

路由器类型(来自链路层)

ipvs_property

skbuff 由 ipvs 拥有

nf_trace

netfilter 数据包跟踪标志

offload_fwd_mark

数据包在硬件中进行了 L2 转发

offload_l3_fwd_mark

数据包在硬件中进行了 L3 转发

redirected

数据包被数据包分类器重定向

from_ingress

数据包从入口路径重定向

nf_skip_egress

数据包应跳过 nf 出口 - 请参阅 netfilter_netdev.h

decrypted

已解密的 SKB

slow_gro

GRO 时存在的状态,需要较慢的准备步骤

csum_not_inet

使用 CRC32c 来解决 CHECKSUM_PARTIAL

unreadable

表示此 skb 中至少有 1 个片段是不可读的。

tc_index

流量控制索引

alloc_cpu

执行 skb 分配的 CPU。

{unnamed_union}

匿名

csum

校验和(必须包括起始/偏移量对)

{unnamed_struct}

匿名

csum_start

从 skb->head 开始,校验和应从此处开始的偏移量

csum_offset

从 csum_start 开始,校验和应存储在此处的偏移量

priority

数据包排队优先级

skb_iif

我们到达的设备的 ifindex

hash

数据包哈希

{unnamed_union}

匿名

vlan_all

vlan 字段(proto & tci)

{unnamed_struct}

匿名

vlan_proto

vlan 封装协议

vlan_tci

vlan 标签控制信息

{unnamed_union}

匿名

napi_id

此 skb 来自的 NAPI 结构的 id

sender_cpu

(又名 napi_id)XPS 中的源 CPU

secmark

安全标记

{unnamed_union}

匿名

mark

通用数据包标记

reserved_tailroom

(又名 mark)sk_buff 尾部可用的可用空间字节数

{unnamed_union}

匿名

inner_protocol

协议(封装)

inner_ipproto

(又名 inner_protocol)当 skb->inner_protocol_type == ENCAP_TYPE_IPPROTO 时存储 ipproto;

inner_transport_header

内部传输层标头(封装)

inner_network_header

网络层标头(封装)

inner_mac_header

链路层标头(封装)

protocol

来自驱动程序的数据包协议

transport_header

传输层标头

network_header

网络层标头

mac_header

链路层标头

kcov_handle

用于远程覆盖收集的 KCOV 远程句柄

tail

尾指针

end

结束指针

head

缓冲区头部

data

数据头指针

truesize

缓冲区大小

users

用户计数 - 请参阅 {datagram,tcp}.c

extensions

已分配的扩展,如果 active_extensions 非零则有效

bool skb_pfmemalloc(const struct sk_buff *skb)

测试 skb 是否从 PFMEMALLOC 预留空间分配的

参数

const struct sk_buff *skb

缓冲区

struct dst_entry *skb_dst(const struct sk_buff *skb)

返回 skb dst_entry

参数

const struct sk_buff *skb

缓冲区

描述

返回 skb dst_entry,无论是否获取了引用。

void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst)

设置 skb dst

参数

struct sk_buff *skb

缓冲区

struct dst_entry *dst

dst 条目

描述

设置 skb dst,假设在 dst 上获取了引用,应该由 skb_dst_drop() 释放

void skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst)

设置 skb dst,希望不获取引用

参数

struct sk_buff *skb

缓冲区

struct dst_entry *dst

dst 条目

描述

设置 skb dst,假设没有在 dst 上获取引用。如果 dst 条目已缓存,我们不获取引用,并且 refdst_drop 会避免 dst_release。如果 dst 条目未缓存,我们会获取引用,以便最后的 dst_release 可以立即销毁 dst。

bool skb_dst_is_noref(const struct sk_buff *skb)

测试 skb dst 是否未进行引用计数

参数

const struct sk_buff *skb

缓冲区

unsigned int skb_napi_id(const struct sk_buff *skb)

返回 skb 的 NAPI id

参数

const struct sk_buff *skb

缓冲区

bool skb_unref(struct sk_buff *skb)

减少 skb 的引用计数

参数

struct sk_buff *skb

缓冲区

描述

如果我们可以释放 skb,则返回 true。

void kfree_skb(struct sk_buff *skb)

以“NOT_SPECIFIED”原因释放 sk_buff

参数

struct sk_buff *skb

要释放的缓冲区

struct sk_buff *alloc_skb(unsigned int size, gfp_t priority)

分配网络缓冲区

参数

unsigned int size

要分配的大小

gfp_t priority

分配掩码

描述

此函数是 __alloc_skb() 的一个便捷封装。

bool skb_fclone_busy(const struct sock *sk, const struct sk_buff *skb)

检查 fclone 是否繁忙

参数

const struct sock *sk

套接字

const struct sk_buff *skb

缓冲区

描述

如果 skb 是快速克隆,且其克隆未被释放,则返回 true。一些驱动程序在其 ndo_start_xmit() 中调用 skb_orphan(),因此我们还要检查是否发生了这种情况。

struct sk_buff *alloc_skb_fclone(unsigned int size, gfp_t priority)

从 fclone 缓存分配网络缓冲区

参数

unsigned int size

要分配的大小

gfp_t priority

分配掩码

描述

此函数是 __alloc_skb() 的一个便捷封装。

int skb_pad(struct sk_buff *skb, int pad)

用零填充 skb 的尾部

参数

struct sk_buff *skb

要填充的缓冲区

int pad

要填充的空间

确保缓冲区后跟一个零填充的填充区域。由网络驱动程序使用,这些驱动程序可能会将数据 DMA 或传输到超出缓冲区末尾的电线上。

在内存不足的情况下可能会返回错误。发生错误时会释放 skb。

int skb_queue_empty(const struct sk_buff_head *list)

检查队列是否为空

参数

const struct sk_buff_head *list

队列头

如果队列为空,则返回 true,否则返回 false。

bool skb_queue_empty_lockless(const struct sk_buff_head *list)

检查队列是否为空

参数

const struct sk_buff_head *list

队列头

如果队列为空,则返回 true,否则返回 false。此变体可以在无锁上下文中使用。

bool skb_queue_is_last(const struct sk_buff_head *list, const struct sk_buff *skb)

检查 skb 是否是队列中的最后一个条目

参数

const struct sk_buff_head *list

队列头

const struct sk_buff *skb

缓冲区

如果 skb 是列表中的最后一个缓冲区,则返回 true。

bool skb_queue_is_first(const struct sk_buff_head *list, const struct sk_buff *skb)

检查 skb 是否是队列中的第一个条目

参数

const struct sk_buff_head *list

队列头

const struct sk_buff *skb

缓冲区

如果 skb 是列表中的第一个缓冲区,则返回 true。

struct sk_buff *skb_queue_next(const struct sk_buff_head *list, const struct sk_buff *skb)

返回队列中的下一个数据包

参数

const struct sk_buff_head *list

队列头

const struct sk_buff *skb

当前缓冲区

返回 skb 之后的 list 中的下一个数据包。仅当 skb_queue_is_last() 的计算结果为 false 时,调用此函数才有效。

struct sk_buff *skb_queue_prev(const struct sk_buff_head *list, const struct sk_buff *skb)

返回队列中的上一个数据包

参数

const struct sk_buff_head *list

队列头

const struct sk_buff *skb

当前缓冲区

返回 skb 之前的 list 中的上一个数据包。仅当 skb_queue_is_first() 的计算结果为 false 时,调用此函数才有效。

struct sk_buff *skb_get(struct sk_buff *skb)

引用缓冲区

参数

struct sk_buff *skb

要引用的缓冲区

对套接字缓冲区进行另一个引用,并返回指向该缓冲区的指针。

int skb_cloned(const struct sk_buff *skb)

缓冲区是否是克隆

参数

const struct sk_buff *skb

要检查的缓冲区

如果缓冲区是通过 skb_clone() 生成的,并且是缓冲区的多个共享副本之一,则返回 true。克隆缓冲区是共享数据,因此在正常情况下不得写入。

int skb_header_cloned(const struct sk_buff *skb)

头部是否是克隆

参数

const struct sk_buff *skb

要检查的缓冲区

如果修改缓冲区的头部需要复制数据,则返回 true。

void __skb_header_release(struct sk_buff *skb)

允许克隆使用预留空间

参数

struct sk_buff *skb

要操作的缓冲区

描述

请参阅“DOC: dataref and headerless skbs”。

int skb_shared(const struct sk_buff *skb)

缓冲区是否被共享

参数

const struct sk_buff *skb

要检查的缓冲区

如果多于一个人引用此缓冲区,则返回 true。

struct sk_buff *skb_share_check(struct sk_buff *skb, gfp_t pri)

检查缓冲区是否被共享,如果是,则克隆它

参数

struct sk_buff *skb

要检查的缓冲区

gfp_t pri

内存分配的优先级

如果缓冲区被共享,则克隆该缓冲区,并且旧副本会减少一个引用计数。返回一个新的、具有单个引用的克隆。如果缓冲区未被共享,则返回原始缓冲区。当从中断状态或持有自旋锁的情况下调用时,pri 必须为 GFP_ATOMIC。

内存分配失败时返回 NULL。

struct sk_buff *skb_unshare(struct sk_buff *skb, gfp_t pri)

创建共享缓冲区的副本

参数

struct sk_buff *skb

要检查的缓冲区

gfp_t pri

内存分配的优先级

如果套接字缓冲区是一个克隆,则此函数创建数据的新副本,减少旧副本的引用计数,并返回引用计数为 1 的新副本。如果缓冲区不是克隆,则返回原始缓冲区。当持有自旋锁或在中断状态下调用时,pri 必须为 GFP_ATOMIC

内存分配失败时返回 NULL

struct sk_buff *skb_peek(const struct sk_buff_head *list_)

查看 sk_buff_head 的头部

参数

const struct sk_buff_head *list_

要查看的列表

查看 sk_buff。与大多数其他操作不同,您必须小心此操作。查看会将缓冲区留在列表中,并且其他人可能会将其取走。您必须持有适当的锁或拥有一个私有队列才能执行此操作。

对于空列表返回 NULL 或指向头部元素的指针。引用计数不会递增,因此引用是易变的。谨慎使用。

struct sk_buff *__skb_peek(const struct sk_buff_head *list_)

查看非空 sk_buff_head 的头部

参数

const struct sk_buff_head *list_

要查看的列表

类似于 skb_peek(),但调用者知道列表不是空的。

struct sk_buff *skb_peek_next(struct sk_buff *skb, const struct sk_buff_head *list_)

从队列中查看给定 skb 后面的 skb

参数

struct sk_buff *skb

要开始的 skb

const struct sk_buff_head *list_

要查看的列表

当到达列表末尾时返回 NULL 或指向下一个元素的指针。引用计数不会递增,因此引用是易变的。谨慎使用。

struct sk_buff *skb_peek_tail(const struct sk_buff_head *list_)

查看 sk_buff_head 的尾部

参数

const struct sk_buff_head *list_

要查看的列表

查看 sk_buff。与大多数其他操作不同,您必须小心此操作。查看会将缓冲区留在列表中,并且其他人可能会将其取走。您必须持有适当的锁或拥有一个私有队列才能执行此操作。

对于空列表返回 NULL 或指向尾部元素的指针。引用计数不会递增,因此引用是易变的。谨慎使用。

__u32 skb_queue_len(const struct sk_buff_head *list_)

获取队列长度

参数

const struct sk_buff_head *list_

要测量的列表

返回 sk_buff 队列的长度。

__u32 skb_queue_len_lockless(const struct sk_buff_head *list_)

获取队列长度

参数

const struct sk_buff_head *list_

要测量的列表

返回 sk_buff 队列的长度。此变体可以在无锁上下文中使用。

void __skb_queue_head_init(struct sk_buff_head *list)

初始化 sk_buff_head 的非自旋锁部分

参数

struct sk_buff_head *list

要初始化的队列

这仅初始化 sk_buff_head 对象的列表和队列长度方面。这允许在不重新初始化自旋锁等内容的情况下初始化 sk_buff_head 的列表方面。它也可以用于已知不使用自旋锁的堆栈上 sk_buff_head 对象。

void skb_queue_splice(const struct sk_buff_head *list, struct sk_buff_head *head)

连接两个 skb 列表,这是为堆栈设计的

参数

const struct sk_buff_head *list

要添加的新列表

struct sk_buff_head *head

要在第一个列表中添加它的位置

void skb_queue_splice_init(struct sk_buff_head *list, struct sk_buff_head *head)

连接两个 skb 列表并重新初始化清空的列表

参数

struct sk_buff_head *list

要添加的新列表

struct sk_buff_head *head

要在第一个列表中添加它的位置

list 中的列表将被重新初始化

void skb_queue_splice_tail(const struct sk_buff_head *list, struct sk_buff_head *head)

连接两个 skb 列表,每个列表都是一个队列。

参数

const struct sk_buff_head *list

要添加的新列表

struct sk_buff_head *head

要在第一个列表中添加它的位置

void skb_queue_splice_tail_init(struct sk_buff_head *list, struct sk_buff_head *head)

连接两个 skb 列表并重新初始化清空的列表

参数

struct sk_buff_head *list

要添加的新列表

struct sk_buff_head *head

要在第一个列表中添加它的位置

每个列表都是一个队列。list 处的列表被重新初始化。

void __skb_queue_after(struct sk_buff_head *list, struct sk_buff *prev, struct sk_buff *newsk)

在列表头部排队一个缓冲区。

参数

struct sk_buff_head *list

要使用的列表。

struct sk_buff *prev

放置在此缓冲区之后。

struct sk_buff *newsk

要排队的缓冲区。

在列表的中间排队一个缓冲区。此函数不获取任何锁,因此在调用它之前,您必须持有所需的锁。

一个缓冲区不能同时放在两个列表中。

void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)

在列表头部排队一个缓冲区。

参数

struct sk_buff_head *list

要使用的列表。

struct sk_buff *newsk

要排队的缓冲区。

在列表的开头排队一个缓冲区。此函数不获取任何锁,因此在调用它之前,您必须持有所需的锁。

一个缓冲区不能同时放在两个列表中。

void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)

在列表尾部排队一个缓冲区。

参数

struct sk_buff_head *list

要使用的列表。

struct sk_buff *newsk

要排队的缓冲区。

在列表末尾排队一个缓冲区。此函数不获取任何锁,因此在调用它之前,您必须持有所需的锁。

一个缓冲区不能同时放在两个列表中。

struct sk_buff *__skb_dequeue(struct sk_buff_head *list)

从队列头部移除。

参数

struct sk_buff_head *list

从中出队的列表。

移除列表的头部。此函数不获取任何锁,因此必须仅在持有适当的锁时使用。返回头部项,如果列表为空,则返回 NULL

struct sk_buff *__skb_dequeue_tail(struct sk_buff_head *list)

从队列尾部移除。

参数

struct sk_buff_head *list

从中出队的列表。

移除列表的尾部。此函数不获取任何锁,因此必须仅在持有适当的锁时使用。返回尾部项,如果列表为空,则返回 NULL

void skb_len_add(struct sk_buff *skb, int delta)

将一个数字添加到 skb 的 len 字段。

参数

struct sk_buff *skb

要添加长度的缓冲区。

int delta

要添加的字节数。

void __skb_fill_netmem_desc(struct sk_buff *skb, int i, netmem_ref netmem, int off, int size)

初始化 skb 中的一个片段。

参数

struct sk_buff *skb

包含要初始化的片段的缓冲区。

int i

要初始化的片段索引。

netmem_ref netmem

此片段要使用的 netmem。

int off

page 中数据偏移量。

int size

数据的长度。

描述

初始化 skb 的第 i 个片段,使其指向 page 内偏移量 off 处的 size 个字节。

不获取片段上的任何其他引用。

void skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size)

初始化 skb 中的一个分页片段。

参数

struct sk_buff *skb

包含要初始化的片段的缓冲区。

int i

要初始化的分页片段索引。

struct page *page

此片段要使用的页。

int off

page 中数据偏移量。

int size

数据的长度。

描述

与 __skb_fill_page_desc() 相同 -- 初始化 skb 的第 i 个片段,使其指向 page 内偏移量 off 处的 size 个字节。此外,更新 skb,使 i 成为最后一个片段。

不获取片段上的任何其他引用。

void skb_fill_page_desc_noacc(struct sk_buff *skb, int i, struct page *page, int off, int size)

初始化 skb 中的一个分页片段。

参数

struct sk_buff *skb

包含要初始化的片段的缓冲区。

int i

要初始化的分页片段索引。

struct page *page

此片段要使用的页。

int off

page 中数据偏移量。

int size

数据的长度。

描述

如果页面不是我们拥有的,则 skb_fill_page_desc() 的变体,它不处理 pfmemalloc。

unsigned int skb_headroom(const struct sk_buff *skb)

缓冲区头部的字节数。

参数

const struct sk_buff *skb

要检查的缓冲区

返回 sk_buff 头部可用空间的字节数。

int skb_tailroom(const struct sk_buff *skb)

缓冲区末尾的字节数。

参数

const struct sk_buff *skb

要检查的缓冲区

返回 sk_buff 尾部可用空间的字节数。

int skb_availroom(const struct sk_buff *skb)

缓冲区末尾的字节数。

参数

const struct sk_buff *skb

要检查的缓冲区

返回由 sk_stream_alloc() 分配的 sk_buff 尾部的可用空间字节数

void skb_reserve(struct sk_buff *skb, int len)

调整头部空间

参数

struct sk_buff *skb

要修改的缓冲区

int len

要移动的字节数

通过减少尾部空间来增加空 sk_buff 的头部空间。 这仅允许用于空缓冲区。

void skb_tailroom_reserve(struct sk_buff *skb, unsigned int mtu, unsigned int needed_tailroom)

调整 reserved_tailroom

参数

struct sk_buff *skb

要修改的缓冲区

unsigned int mtu

允许的最大 headlen 量

unsigned int needed_tailroom

最小的 reserved_tailroom 量

设置 reserved_tailroom,以便 headlen 可以尽可能大,但不大于 mtu,并且 tailroom 不能小于 needed_tailroom。 在使用此函数之前,应已预留所需的头部空间。

void pskb_trim_unique(struct sk_buff *skb, unsigned int len)

从分页的唯一(未克隆)缓冲区中删除末尾

参数

struct sk_buff *skb

要修改的缓冲区

unsigned int len

新长度

这与 pskb_trim 相同,只是调用者知道 skb 没有被克隆,所以我们永远不会因为内存不足而出现错误。

void skb_orphan(struct sk_buff *skb)

孤立一个缓冲区

参数

struct sk_buff *skb

要孤立的缓冲区

如果缓冲区当前有所有者,那么我们调用所有者的析构函数并使 skb 变为无所有者。 该缓冲区继续存在,但不再由其先前所有者负责。

int skb_orphan_frags(struct sk_buff *skb, gfp_t gfp_mask)

孤立缓冲区中包含的片段

参数

struct sk_buff *skb

从中孤立片段的缓冲区

gfp_t gfp_mask

替换页面的分配掩码

对于 SKB 中每个需要析构函数的片段(即有所有者),创建该片段的副本并通过调用析构函数释放原始页面。

void __skb_queue_purge_reason(struct sk_buff_head *list, enum skb_drop_reason reason)

清空列表

参数

struct sk_buff_head *list

要清空的列表

enum skb_drop_reason reason

丢弃原因

删除 sk_buff 列表上的所有缓冲区。 每个缓冲区都将从列表中删除,并且引用计数减 1。 此函数不获取列表锁,调用者必须持有相关的锁才能使用它。

void *netdev_alloc_frag(unsigned int fragsz)

从页面分配一个片段

参数

unsigned int fragsz

片段大小

描述

从页面为接收缓冲区分配一个片段。 使用 GFP_ATOMIC 分配。

struct sk_buff *netdev_alloc_skb(struct net_device *dev, unsigned int length)

在特定设备上为 rx 分配一个 skbuff

参数

struct net_device *dev

要接收的网络设备

unsigned int length

要分配的长度

分配一个新的 sk_buff 并为其分配一个使用计数 1。 该缓冲区具有未指定的内置头部空间。 用户应分配他们认为需要的头部空间,而不考虑内置空间。 内置空间用于优化。

如果没有可用内存,则返回 NULL。 尽管此函数分配内存,但可以从中断中调用它。

struct page *__dev_alloc_pages(gfp_t gfp_mask, unsigned int order)

为网络 Rx 分配页面

参数

gfp_t gfp_mask

分配优先级。 如果不用于网络 Rx,则设置 __GFP_NOMEMALLOC

unsigned int order

分配的大小

描述

分配一个新页面。

如果没有可用内存,则返回 NULL

struct page *__dev_alloc_page(gfp_t gfp_mask)

为网络 Rx 分配一个页面

参数

gfp_t gfp_mask

分配优先级。 如果不用于网络 Rx,则设置 __GFP_NOMEMALLOC

描述

分配一个新页面。

如果没有可用内存,则返回 NULL

bool dev_page_is_reusable(const struct page *page)

检查页面是否可以重复用于网络 Rx

参数

const struct page *page

要测试的页面

描述

如果页面是在内存压力下或在远端内存节点中分配的,则不应考虑重复使用/回收该页面。

如果此页面应返回给页面分配器,则返回 false,否则返回 true。

void skb_propagate_pfmemalloc(const struct page *page, struct sk_buff *skb)

如果 skb 是在 RX 页之后分配的,则传播 pfmemalloc

参数

const struct page *page

从 skb_alloc_page 分配的页

struct sk_buff *skb

可能需要设置 pfmemalloc 的 skb

unsigned int skb_frag_off(const skb_frag_t *frag)

返回 skb 片段的偏移量

参数

const skb_frag_t *frag

分页的片段

void skb_frag_off_add(skb_frag_t *frag, int delta)

将 skb 片段的偏移量增加 delta

参数

skb_frag_t *frag

skb 片段

int delta

要添加的值

void skb_frag_off_set(skb_frag_t *frag, unsigned int offset)

设置 skb 片段的偏移量

参数

skb_frag_t *frag

skb 片段

unsigned int offset

片段的偏移量

void skb_frag_off_copy(skb_frag_t *fragto, const skb_frag_t *fragfrom)

从另一个片段设置 skb 片段的偏移量

参数

skb_frag_t *fragto

设置偏移量的 skb 片段

const skb_frag_t *fragfrom

从中复制偏移量的 skb 片段

struct net_iov *skb_frag_net_iov(const skb_frag_t *frag)

检索片段引用的 net_iov

参数

const skb_frag_t *frag

片段

返回

frag 关联的 struct net_iov。如果此片段没有关联的 net_iov,则返回 NULL。

struct page *skb_frag_page(const skb_frag_t *frag)

检索分页片段引用的页

参数

const skb_frag_t *frag

分页的片段

返回

frag 关联的 struct page。如果此片段没有关联的页,则返回 NULL。

netmem_ref skb_frag_netmem(const skb_frag_t *frag)

检索片段引用的 netmem

参数

const skb_frag_t *frag

片段

返回

frag 关联的 netmem_ref

void *skb_frag_address(const skb_frag_t *frag)

获取分页片段中包含的数据的地址

参数

const skb_frag_t *frag

分页的片段缓冲区

描述

返回 frag 中数据的地址。该页必须已经映射。

void *skb_frag_address_safe(const skb_frag_t *frag)

获取分页片段中包含的数据的地址

参数

const skb_frag_t *frag

分页的片段缓冲区

描述

返回 frag 中数据的地址。检查该页是否已映射,否则返回 NULL

void skb_frag_page_copy(skb_frag_t *fragto, const skb_frag_t *fragfrom)

从另一个片段设置一个片段中的页

参数

skb_frag_t *fragto

设置页面的 skb 片段

const skb_frag_t *fragfrom

从中复制页面的 skb 片段

dma_addr_t skb_frag_dma_map(struct device *dev, const skb_frag_t *frag, size_t offset, size_t size, enum dma_data_direction dir)

通过 DMA API 映射分页的片段

参数

struct device *dev

要将片段映射到的设备

const skb_frag_t *frag

要映射的分页片段

size_t offset

片段内的偏移量(从片段自身的偏移量开始)

size_t size

要映射的字节数

enum dma_data_direction dir

映射的方向 (PCI_DMA_*)

描述

将与 frag 关联的页映射到 device

int skb_clone_writable(const struct sk_buff *skb, unsigned int len)

克隆的头部是否可写

参数

const struct sk_buff *skb

要检查的缓冲区

unsigned int len

写入的最大长度

如果修改克隆缓冲区的头部部分不需要复制数据,则返回 true。

int skb_cow(struct sk_buff *skb, unsigned int headroom)

在需要时复制 skb 的头部

参数

struct sk_buff *skb

要进行写入时复制的缓冲区

unsigned int headroom

需要的头部空间

如果传递的 skb 缺乏足够的头部空间或其数据部分是共享的,则会重新分配数据。如果重新分配失败,则会返回错误,并且不会更改原始 skb。

结果是 skb,其可写区域为 skb->head...skb->tail,并且在头部至少有 headroom 的空间。

int skb_cow_head(struct sk_buff *skb, unsigned int headroom)

skb_cow,但仅使头部可写

参数

struct sk_buff *skb

要进行写入时复制的缓冲区

unsigned int headroom

需要的头部空间

此函数与 skb_cow 相同,只是我们将 skb_cloned 检查替换为 skb_header_cloned。当您只需要在某些头部上推送而不需要修改数据时,应该使用它。

int skb_padto(struct sk_buff *skb, unsigned int len)

将 skbuff 填充到最小大小

参数

struct sk_buff *skb

要填充的缓冲区

unsigned int len

最小长度

填充缓冲区以确保尾部字节存在并且为空白。如果缓冲区已经包含足够的数据,则保持不变。否则,它将被扩展。成功时返回零。发生错误时,skb 将被释放。

int __skb_put_padto(struct sk_buff *skb, unsigned int len, bool free_on_error)

增加大小并将 skbuff 填充到最小大小

参数

struct sk_buff *skb

要填充的缓冲区

unsigned int len

最小长度

bool free_on_error

发生错误时释放缓冲区

填充缓冲区以确保尾部字节存在并且为空白。如果缓冲区已经包含足够的数据,则保持不变。否则,它将被扩展。成功时返回零。如果 free_on_error 为 true,则在发生错误时释放 skb。

int skb_put_padto(struct sk_buff *skb, unsigned int len)

增加大小并将 skbuff 填充到最小大小

参数

struct sk_buff *skb

要填充的缓冲区

unsigned int len

最小长度

填充缓冲区以确保尾部字节存在并且为空白。如果缓冲区已经包含足够的数据,则保持不变。否则,它将被扩展。成功时返回零。发生错误时,skb 将被释放。

int skb_linearize(struct sk_buff *skb)

将分页 skb 转换为线性 skb

参数

struct sk_buff *skb

要线性化的缓冲区

如果没有可用内存,则返回 -ENOMEM,否则返回零并释放旧的 skb 数据。

bool skb_has_shared_frag(const struct sk_buff *skb)

是否可以覆盖任何 frag

参数

const struct sk_buff *skb

要测试的缓冲区

描述

如果 skb 至少有一个可能被外部实体修改的 frag(如 vmsplice()/sendfile() 中),则返回 true。

int skb_linearize_cow(struct sk_buff *skb)

确保 skb 是线性的且可写的

参数

struct sk_buff *skb

要处理的缓冲区

如果没有可用内存,则返回 -ENOMEM,否则返回零并释放旧的 skb 数据。

void skb_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len)

在 pull 后更新接收到的 skb 的校验和

参数

struct sk_buff *skb

要更新的缓冲区

const void *start

pull 之前的数据开始位置

unsigned int len

pull 的数据长度

在对接收到的数据包执行 pull 操作后,您需要调用此函数来更新 CHECKSUM_COMPLETE 校验和,或者将 ip_summed 设置为 CHECKSUM_NONE,以便可以从头重新计算。

void skb_postpush_rcsum(struct sk_buff *skb, const void *start, unsigned int len)

在 push 后更新接收到的 skb 的校验和

参数

struct sk_buff *skb

要更新的缓冲区

const void *start

push 后的数据开始位置

unsigned int len

push 的数据长度

在对接收到的数据包执行 push 操作后,您需要调用此函数来更新 CHECKSUM_COMPLETE 校验和。

void *skb_push_rcsum(struct sk_buff *skb, unsigned int len)

推送 skb 并更新接收校验和

参数

struct sk_buff *skb

要更新的缓冲区

unsigned int len

pull 的数据长度

此函数对数据包执行 skb_push 操作并更新 CHECKSUM_COMPLETE 校验和。它应该在接收路径处理中使用,而不是 skb_push,除非您知道校验和差异为零(例如,有效的 IP 头部),或者您将 ip_summed 设置为 CHECKSUM_NONE。

int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)

修剪接收到的 skb 并更新校验和

参数

struct sk_buff *skb

要修剪的缓冲区

unsigned int len

新长度

这与 pskb_trim 完全相同,只是它确保接收到的数据包的校验和在操作后仍然有效。它可以更改 skb 指针。

bool skb_needs_linearize(struct sk_buff *skb, netdev_features_t features)

检查是否需要根据给定的设备功能线性化给定的 skb。

参数

struct sk_buff *skb

要检查的套接字缓冲区

netdev_features_t features

网络设备功能

如果满足以下任一条件,则返回 true:1. skb 具有 frag_list,并且设备不支持 FRAGLIST,或者 2. skb 是分段的,并且设备不支持 SG。

void skb_get_timestamp(const struct sk_buff *skb, struct __kernel_old_timeval *stamp)

从 skb 获取时间戳

参数

const struct sk_buff *skb

从中获取时间戳的 skb

struct __kernel_old_timeval *stamp

指向 struct __kernel_old_timeval 的指针,用于存储时间戳

时间戳在 skb 中存储为相对于基本时间戳的偏移量。此函数将偏移量转换回 struct timeval 并将其存储在 stamp 中。

void skb_complete_tx_timestamp(struct sk_buff *skb, struct skb_shared_hwtstamps *hwtstamps)

使用发送时间戳传递克隆的 skb

参数

struct sk_buff *skb

原始传出数据包的克隆

struct skb_shared_hwtstamps *hwtstamps

硬件时间戳

描述

PHY 驱动程序可以通过其 phy_driver.txtstamp 方法接受已传输数据包的克隆以进行时间戳记录。这些驱动程序必须调用此函数以将带有时间戳的 skb 返回到堆栈。

void skb_tstamp_tx(struct sk_buff *orig_skb, struct skb_shared_hwtstamps *hwtstamps)

使用发送时间戳将 skb 的克隆排队

参数

struct sk_buff *orig_skb

原始传出数据包

struct skb_shared_hwtstamps *hwtstamps

硬件时间戳,如果不可用,则可能为 NULL

描述

如果 skb 关联了套接字,则此函数会克隆 skb(从而共享实际数据和可选结构),存储可选的硬件时间戳信息(如果非 NULL),或者生成软件时间戳(否则),然后将克隆排队到套接字的错误队列。错误会被静默忽略。

void skb_tx_timestamp(struct sk_buff *skb)

用于传输时间戳的驱动程序钩子

参数

struct sk_buff *skb

套接字缓冲区。

描述

以太网 MAC 驱动程序应在其 hard_xmit() 函数中,在将 sk_buff 提供给 MAC 硬件之前立即调用此函数。

具体来说,应绝对确保在触发此数据包的 TX 完成之前调用此函数。否则,数据包可能已经被释放。

void skb_complete_wifi_ack(struct sk_buff *skb, bool acked)

使用 wifi 状态传递 skb

参数

struct sk_buff *skb

原始传出数据包

bool acked

确认状态

__sum16 skb_checksum_complete(struct sk_buff *skb)

计算整个数据包的校验和

参数

struct sk_buff *skb

要处理的数据包

此函数计算整个数据包的校验和加上 skb->csum 的值。后者可用于提供 TCP/UDP 使用的伪报头的校验和。它返回校验和。

对于包含完整校验和的协议(如 ICMP/TCP/UDP),此函数可用于验证接收数据包上的校验和。在这种情况下,如果校验和正确,该函数应返回零。特别是,如果 skb->ip_summed 为 CHECKSUM_UNNECESSARY,则此函数将返回零,这表示硬件已验证校验和的正确性。

struct skb_ext

sk_buff 扩展

定义:

struct skb_ext {
    refcount_t refcnt;
    u8 offset[SKB_EXT_NUM];
    u8 chunks;
    char data[] ;
};

成员

refcnt

分配时为 1,在 0 时释放

offset

添加到 data 以获得扩展地址的偏移量

chunks

当前分配的大小,以 SKB_EXT_ALIGN_SHIFT 单位存储

data

扩展数据的开始,可变大小

注意

偏移量/长度以 8 字节的块存储,这允许

使用 “u8” 类型,同时允许最多 2kb 的扩展数据。

void skb_checksum_none_assert(const struct sk_buff *skb)

确保 skb ip_summed 为 CHECKSUM_NONE

参数

const struct sk_buff *skb

要检查的 skb

描述

新的 skb 将其 ip_summed 设置为 CHECKSUM_NONE。我们可以使用此助手来记录我们进行此断言的位置,而不是强制 ip_summed 为 CHECKSUM_NONE。

bool skb_head_is_locked(const struct sk_buff *skb)

确定 skb->head 是否已锁定

参数

const struct sk_buff *skb

要检查的 skb

描述

如果未克隆,则可以删除围绕 head frag 构建的 skb 上的 head。如果 skb head 由于通过 kmalloc 分配或由于是具有多个对 head 引用的克隆而锁定,则此函数返回 true。

struct sock_common

套接字的最小网络层表示

定义:

struct sock_common {
    union {
        __addrpair skc_addrpair;
        struct {
            __be32 skc_daddr;
            __be32 skc_rcv_saddr;
        };
    };
    union {
        unsigned int    skc_hash;
        __u16 skc_u16hashes[2];
    };
    union {
        __portpair skc_portpair;
        struct {
            __be16 skc_dport;
            __u16 skc_num;
        };
    };
    unsigned short          skc_family;
    volatile unsigned char  skc_state;
    unsigned char           skc_reuse:4;
    unsigned char           skc_reuseport:1;
    unsigned char           skc_ipv6only:1;
    unsigned char           skc_net_refcnt:1;
    int skc_bound_dev_if;
    union {
        struct hlist_node       skc_bind_node;
        struct hlist_node       skc_portaddr_node;
    };
    struct proto            *skc_prot;
    possible_net_t skc_net;
#if IS_ENABLED(CONFIG_IPV6);
    struct in6_addr         skc_v6_daddr;
    struct in6_addr         skc_v6_rcv_saddr;
#endif;
    atomic64_t skc_cookie;
    union {
        unsigned long   skc_flags;
        struct sock     *skc_listener;
        struct inet_timewait_death_row *skc_tw_dr;
    };
    union {
        struct hlist_node       skc_node;
        struct hlist_nulls_node skc_nulls_node;
    };
    unsigned short          skc_tx_queue_mapping;
#ifdef CONFIG_SOCK_RX_QUEUE_MAPPING;
    unsigned short          skc_rx_queue_mapping;
#endif;
    union {
        int skc_incoming_cpu;
        u32 skc_rcv_wnd;
        u32 skc_tw_rcv_nxt;
    };
    refcount_t skc_refcnt;
};

成员

{unnamed_union}

匿名

skc_addrpair

skc_daddr & skc_rcv_saddr 的 8 字节对齐的 __u64 联合

{unnamed_struct}

匿名

skc_daddr

外部 IPv4 地址

skc_rcv_saddr

绑定的本地 IPv4 地址

{unnamed_union}

匿名

skc_hash

与各种协议查找表一起使用的哈希值

skc_u16hashes

UDP 查找表使用的两个 u16 哈希值

{unnamed_union}

匿名

skc_portpair

skc_dport & skc_num 的 __u32 联合

{unnamed_struct}

匿名

skc_dport

inet_dport/tw_dport 的占位符

skc_num

inet_num/tw_num 的占位符

skc_family

网络地址族

skc_state

连接状态

skc_reuse

SO_REUSEADDR 设置

skc_reuseport

SO_REUSEPORT 设置

skc_ipv6only

套接字仅限 IPV6

skc_net_refcnt

套接字正在使用网络引用计数

skc_bound_dev_if

绑定的设备索引(如果 != 0)

{unnamed_union}

匿名

skc_bind_node

各种协议查找表的绑定哈希链接

skc_portaddr_node

UDP/UDP-Lite 协议的第二个哈希链接

skc_prot

网络系列内部的协议处理程序

skc_net

对此套接字的网络命名空间的引用

skc_v6_daddr

IPV6 目标地址

skc_v6_rcv_saddr

IPV6 源地址

skc_cookie

套接字的 cookie 值

{unnamed_union}

匿名

skc_flags

sk_flags 的占位符 SO_LINGER (l_onoff), SO_BROADCAST, SO_KEEPALIVE, SO_OOBINLINE 设置, SO_TIMESTAMPING 设置

skc_listener

连接请求侦听器套接字(又名 rsk_listener)[与 skc_flags 的联合]

skc_tw_dr

(又名 tw_dr)指向 struct inet_timewait_death_row 的指针 [与 skc_flags 的联合]

{unnamed_union}

匿名

skc_node

各种协议查找表的主哈希链接

skc_nulls_node

TCP/UDP/UDP-Lite 协议的主哈希链接

skc_tx_queue_mapping

此连接的传输队列号

skc_rx_queue_mapping

此连接的接收队列号

{unnamed_union}

匿名

skc_incoming_cpu

记录/匹配处理传入数据包的 CPU

skc_rcv_wnd

(又名 rsk_rcv_wnd)TCP 接收窗口大小(可能已缩放)[与 skc_incoming_cpu 的联合]

skc_tw_rcv_nxt

(又名 tw_rcv_nxt)TCP 窗口下一个预期序列号 [与 skc_incoming_cpu 的联合]

skc_refcnt

引用计数

这是套接字的最小网络层表示,struct sock 和 struct inet_timewait_sock 的标头。

struct sock

套接字的网络层表示

定义:

struct sock {
    struct sock_common      __sk_common;
#define sk_node                 __sk_common.skc_node;
#define sk_nulls_node           __sk_common.skc_nulls_node;
#define sk_refcnt               __sk_common.skc_refcnt;
#define sk_tx_queue_mapping     __sk_common.skc_tx_queue_mapping;
#ifdef CONFIG_SOCK_RX_QUEUE_MAPPING;
#define sk_rx_queue_mapping     __sk_common.skc_rx_queue_mapping;
#endif;
#define sk_dontcopy_begin       __sk_common.skc_dontcopy_begin;
#define sk_dontcopy_end         __sk_common.skc_dontcopy_end;
#define sk_hash                 __sk_common.skc_hash;
#define sk_portpair             __sk_common.skc_portpair;
#define sk_num                  __sk_common.skc_num;
#define sk_dport                __sk_common.skc_dport;
#define sk_addrpair             __sk_common.skc_addrpair;
#define sk_daddr                __sk_common.skc_daddr;
#define sk_rcv_saddr            __sk_common.skc_rcv_saddr;
#define sk_family               __sk_common.skc_family;
#define sk_state                __sk_common.skc_state;
#define sk_reuse                __sk_common.skc_reuse;
#define sk_reuseport            __sk_common.skc_reuseport;
#define sk_ipv6only             __sk_common.skc_ipv6only;
#define sk_net_refcnt           __sk_common.skc_net_refcnt;
#define sk_bound_dev_if         __sk_common.skc_bound_dev_if;
#define sk_bind_node            __sk_common.skc_bind_node;
#define sk_prot                 __sk_common.skc_prot;
#define sk_net                  __sk_common.skc_net;
#define sk_v6_daddr             __sk_common.skc_v6_daddr;
#define sk_v6_rcv_saddr __sk_common.skc_v6_rcv_saddr;
#define sk_cookie               __sk_common.skc_cookie;
#define sk_incoming_cpu         __sk_common.skc_incoming_cpu;
#define sk_flags                __sk_common.skc_flags;
#define sk_rxhash               __sk_common.skc_rxhash;
    __cacheline_group_begin(sock_write_rx);
    atomic_t sk_drops;
    __s32 sk_peek_off;
    struct sk_buff_head     sk_error_queue;
    struct sk_buff_head     sk_receive_queue;
    struct {
        atomic_t rmem_alloc;
        int len;
        struct sk_buff  *head;
        struct sk_buff  *tail;
    } sk_backlog;
#define sk_rmem_alloc sk_backlog.rmem_alloc;
    __cacheline_group_end(sock_write_rx);
    __cacheline_group_begin(sock_read_rx);
    struct dst_entry __rcu  *sk_rx_dst;
    int sk_rx_dst_ifindex;
    u32 sk_rx_dst_cookie;
#ifdef CONFIG_NET_RX_BUSY_POLL;
    unsigned int            sk_ll_usec;
    unsigned int            sk_napi_id;
    u16 sk_busy_poll_budget;
    u8 sk_prefer_busy_poll;
#endif;
    u8 sk_userlocks;
    int sk_rcvbuf;
    struct sk_filter __rcu  *sk_filter;
    union {
        struct socket_wq __rcu  *sk_wq;
    };
    void (*sk_data_ready)(struct sock *sk);
    long sk_rcvtimeo;
    int sk_rcvlowat;
    __cacheline_group_end(sock_read_rx);
    __cacheline_group_begin(sock_read_rxtx);
    int sk_err;
    struct socket           *sk_socket;
    struct mem_cgroup       *sk_memcg;
#ifdef CONFIG_XFRM;
    struct xfrm_policy __rcu *sk_policy[2];
#endif;
    __cacheline_group_end(sock_read_rxtx);
    __cacheline_group_begin(sock_write_rxtx);
    socket_lock_t sk_lock;
    u32 sk_reserved_mem;
    int sk_forward_alloc;
    u32 sk_tsflags;
    __cacheline_group_end(sock_write_rxtx);
    __cacheline_group_begin(sock_write_tx);
    int sk_write_pending;
    atomic_t sk_omem_alloc;
    int sk_sndbuf;
    int sk_wmem_queued;
    refcount_t sk_wmem_alloc;
    unsigned long           sk_tsq_flags;
    union {
        struct sk_buff  *sk_send_head;
        struct rb_root  tcp_rtx_queue;
    };
    struct sk_buff_head     sk_write_queue;
    u32 sk_dst_pending_confirm;
    u32 sk_pacing_status;
    struct page_frag        sk_frag;
    struct timer_list       sk_timer;
    unsigned long           sk_pacing_rate;
    atomic_t sk_zckey;
    atomic_t sk_tskey;
    __cacheline_group_end(sock_write_tx);
    __cacheline_group_begin(sock_read_tx);
    unsigned long           sk_max_pacing_rate;
    long sk_sndtimeo;
    u32 sk_priority;
    u32 sk_mark;
    struct dst_entry __rcu  *sk_dst_cache;
    netdev_features_t sk_route_caps;
#ifdef CONFIG_SOCK_VALIDATE_XMIT;
    struct sk_buff*         (*sk_validate_xmit_skb)(struct sock *sk,struct net_device *dev, struct sk_buff *skb);
#endif;
    u16 sk_gso_type;
    u16 sk_gso_max_segs;
    unsigned int            sk_gso_max_size;
    gfp_t sk_allocation;
    u32 sk_txhash;
    u8 sk_pacing_shift;
    bool sk_use_task_frag;
    __cacheline_group_end(sock_read_tx);
    u8 sk_gso_disabled : 1,sk_kern_sock : 1,sk_no_check_tx : 1, sk_no_check_rx : 1;
    u8 sk_shutdown;
    u16 sk_type;
    u16 sk_protocol;
    unsigned long           sk_lingertime;
    struct proto            *sk_prot_creator;
    rwlock_t sk_callback_lock;
    int sk_err_soft;
    u32 sk_ack_backlog;
    u32 sk_max_ack_backlog;
    kuid_t sk_uid;
    spinlock_t sk_peer_lock;
    int sk_bind_phc;
    struct pid              *sk_peer_pid;
    const struct cred       *sk_peer_cred;
    ktime_t sk_stamp;
#if BITS_PER_LONG==32;
    seqlock_t sk_stamp_seq;
#endif;
    int sk_disconnects;
    u8 sk_txrehash;
    u8 sk_clockid;
    u8 sk_txtime_deadline_mode : 1,sk_txtime_report_errors : 1, sk_txtime_unused : 6;
    void *sk_user_data;
#ifdef CONFIG_SECURITY;
    void *sk_security;
#endif;
    struct sock_cgroup_data sk_cgrp_data;
    void (*sk_state_change)(struct sock *sk);
    void (*sk_write_space)(struct sock *sk);
    void (*sk_error_report)(struct sock *sk);
    int (*sk_backlog_rcv)(struct sock *sk, struct sk_buff *skb);
    void (*sk_destruct)(struct sock *sk);
    struct sock_reuseport __rcu     *sk_reuseport_cb;
#ifdef CONFIG_BPF_SYSCALL;
    struct bpf_local_storage __rcu  *sk_bpf_storage;
#endif;
    struct rcu_head         sk_rcu;
    netns_tracker ns_tracker;
    struct xarray           sk_user_frags;
};

成员

__sk_common

与 inet_timewait_sock 的共享布局

sk_drops

原始/udp 丢弃计数器

sk_peek_off

当前 peek_offset 值

sk_error_queue

很少使用

sk_receive_queue

传入的数据包

sk_backlog

始终与每个套接字自旋锁一起使用

sk_rx_dst

早期解复用使用的接收输入路由

sk_rx_dst_ifindex

sk_rx_dst 的 ifindex

sk_rx_dst_cookie

sk_rx_dst 的 cookie

sk_ll_usec

没有数据时忙轮询的微秒数

sk_napi_id

接收 sk 数据的最后一个 napi 上下文的 ID

sk_busy_poll_budget

忙轮询时的 napi 处理预算

sk_prefer_busy_poll

首选忙轮询而不是软中断处理

sk_userlocks

SO_SNDBUFSO_RCVBUF 设置

sk_rcvbuf

接收缓冲区的字节大小

sk_filter

套接字过滤指令

{unnamed_union}

匿名

sk_wq

套接字等待队列和异步头

sk_data_ready

指示有待处理数据的回调

sk_rcvtimeo

SO_RCVTIMEO 设置

sk_rcvlowat

SO_RCVLOWAT 设置

sk_err

上次错误

sk_socket

Identd 和报告 IO 信号

sk_memcg

此套接字的内存 cgroup 关联

sk_policy

流策略

sk_lock

同步器

sk_reserved_mem

为套接字保留且不可回收的空间

sk_forward_alloc

向前分配的空间

sk_tsflags

SO_TIMESTAMPING 标志

sk_write_pending

对流套接字的写操作等待开始

sk_omem_alloc

“o” 表示“选项”或“其他”

sk_sndbuf

发送缓冲区的大小(以字节为单位)

sk_wmem_queued

持久队列大小

sk_wmem_alloc

已提交的传输队列字节

sk_tsq_flags

TCP 小队列标志

{unnamed_union}

匿名

sk_send_head

要传输内容的前端

tcp_rtx_queue

TCP 重传队列 [与 sk_send_head 联合使用]

sk_write_queue

数据包发送队列

sk_dst_pending_confirm

需要确认邻居

sk_pacing_status

步调状态(请求,由 sch_fq 处理)

sk_frag

缓存的页面片段

sk_timer

套接字清理计时器

sk_pacing_rate

步调速率(如果传输/数据包调度器支持)

sk_zckey

用于排序 MSG_ZEROCOPY 通知的计数器

sk_tskey

用于消除并发时间戳请求的计数器

sk_max_pacing_rate

最大步调速率(SO_MAX_PACING_RATE

sk_sndtimeo

SO_SNDTIMEO 设置

sk_priority

SO_PRIORITY 设置

sk_mark

通用数据包标记

sk_dst_cache

目标缓存

sk_route_caps

路由功能(例如 NETIF_F_TSO

sk_validate_xmit_skb

指向可选验证函数的指针

sk_gso_type

GSO 类型(例如 SKB_GSO_TCPV4

sk_gso_max_segs

最大 GSO 段数

sk_gso_max_size

要构建的最大 GSO 段大小

sk_allocation

分配模式

sk_txhash

为传输计算的流哈希

sk_pacing_shift

TCP 小队列的缩放因子

sk_use_task_frag

允许 sk_page_frag() 使用 current->task_frag。可在内存回收下使用的套接字应将其设置为 false。

sk_gso_disabled

如果设置,则禁止 NETIF_F_GSO_MASK。

sk_kern_sock

如果套接字使用内核锁类,则为 True

sk_no_check_tx

SO_NO_CHECK 设置,在 TX 数据包中设置校验和

sk_no_check_rx

允许在 RX 数据包中使用零校验和

sk_shutdown

SEND_SHUTDOWN 和/或 RCV_SHUTDOWN 的掩码

sk_type

套接字类型(SOCK_STREAM 等)

sk_protocol

此套接字在此网络系列中属于哪个协议

sk_lingertime

SO_LINGER l_linger 设置

sk_prot_creator

原始套接字创建者的 sk_prot(例如,请参阅 ipv6_setsockopt,IPV6_ADDRFORM)

sk_callback_lock

与此结构末尾的回调一起使用

sk_err_soft

不会导致失败但导致持久性失败的错误,而不仅仅是“超时”

sk_ack_backlog

当前侦听积压

sk_max_ack_backlog

在 listen() 中设置的侦听积压

sk_uid

所有者的用户 ID

sk_peer_lock

锁定保护 sk_peer_pidsk_peer_cred

sk_bind_phc

SO_TIMESTAMPING 绑定用于时间戳的 PTP 虚拟时钟的 PHC 索引

sk_peer_pid

此套接字对端的 struct pid

sk_peer_cred

SO_PEERCRED 设置

sk_stamp

上次接收的数据包的时间戳

sk_stamp_seq

仅在 32 位架构上用于访问 sk_stamp 的锁

sk_disconnects

在此套接字上执行的断开连接操作数

sk_txrehash

启用 TX 哈希重新考虑

sk_clockid

基于时间的调度(SO_TXTIME)使用的时钟 ID

sk_txtime_deadline_mode

为 SO_TXTIME 设置截止日期模式

sk_txtime_report_errors

为 SO_TXTIME 设置报告错误模式

sk_txtime_unused

未使用的 txtime 标志

sk_user_data

RPC 层私有数据。受 sk_callback_lock 写保护。

sk_security

由安全模块使用

sk_cgrp_data

此 cgroup 的 cgroup 数据

sk_state_change

指示套接字状态更改的回调

sk_write_space

指示有 bf 发送空间可用的回调

sk_error_report

指示错误的回调(例如 MSG_ERRQUEUE

sk_backlog_rcv

处理积压的回调

sk_destruct

在套接字释放时调用,即当所有 refcnt == 0 时

sk_reuseport_cb

reuseport 组容器

sk_bpf_storage

指向 bpf_sk_storage 的缓存和控件的指针

sk_rcu

在 RCU 宽限期期间使用

ns_tracker

用于 netns 引用的跟踪器

sk_user_frags

用户保持引用的页面 xarray。

bool sk_user_data_is_nocopy(const struct sock *sk)

测试是否不能复制 sk_user_data 指针

参数

const struct sock *sk

套接字

void *__locked_read_sk_user_data_with_flags(const struct sock *sk, uintptr_t flags)

仅当参数标志已全部在 sk_user_data 中设置时才返回指针。否则返回 NULL

参数

const struct sock *sk

套接字

uintptr_t flags

标志位

描述

调用者必须持有 sk->sk_callback_lock。

void *__rcu_dereference_sk_user_data_with_flags(const struct sock *sk, uintptr_t flags)

仅当参数标志已全部在 sk_user_data 中设置时才返回指针。否则返回 NULL

参数

const struct sock *sk

套接字

uintptr_t flags

标志位

sk_for_each_entry_offset_rcu

sk_for_each_entry_offset_rcu (tpos, pos, head, offset)

在给定的结构偏移量处迭代列表

参数

tpos

用作循环光标的类型 *。

pos

用作循环光标的 struct hlist_node

head

列表的头部。

offset

结构中 hlist_node 的偏移量。

bool lock_sock_fast(struct sock *sk)

lock_sock 的快速版本

参数

struct sock *sk

套接字

描述

此版本应用于非常小的部分,其中进程不会阻塞。如果采用快速路径,则返回 false

sk_lock.slock 已锁定,owned = 0,BH 已禁用

如果采用慢速路径,则返回 true

sk_lock.slock 已解锁,owned = 1,BH 已启用

void unlock_sock_fast(struct sock *sk, bool slow)

lock_sock_fast 的补充

参数

struct sock *sk

套接字

bool slow

慢速模式

描述

用户上下文的快速解锁套接字。如果启用慢速模式,我们将调用常规 release_sock()

int sk_wmem_alloc_get(const struct sock *sk)

返回写入分配

参数

const struct sock *sk

套接字

返回

sk_wmem_alloc 减去 1 的初始偏移量

int sk_rmem_alloc_get(const struct sock *sk)

返回读取分配

参数

const struct sock *sk

套接字

返回

sk_rmem_alloc

bool sk_has_allocations(const struct sock *sk)

检查是否存在未完成的分配

参数

const struct sock *sk

套接字

返回

如果套接字有写入或读取分配,则返回 true

bool skwq_has_sleeper(struct socket_wq *wq)

检查是否有等待的进程

参数

struct socket_wq *wq

struct socket_wq

返回

如果 socket_wq 有等待的进程,则返回 true

描述

skwq_has_sleeper 和 sock_poll_wait 的目的是封装内存屏障调用。添加它们是为了解决 tcp 代码中发现的竞争问题。

考虑以下 tcp 代码路径

CPU1                CPU2
sys_select          receive packet
...                 ...
__add_wait_queue    update tp->rcv_nxt
...                 ...
tp->rcv_nxt check   sock_def_readable
...                 {
schedule               rcu_read_lock();
                       wq = rcu_dereference(sk->sk_wq);
                       if (wq && waitqueue_active(&wq->wait))
                           wake_up_interruptible(&wq->wait)
                       ...
                    }

当 CPU1 执行的 __add_wait_queue 更改保留在其缓存中时,以及 CPU2 侧的 tp->rcv_nxt 更新时,tcp 竞争就会触发。如果套接字上没有更多数据,CPU1 可能会最终调用 schedule 并永远休眠。

void sock_poll_wait(struct file *filp, struct socket *sock, poll_table *p)

在 poll_wait 调用后放置内存屏障。

参数

struct file *filp

file

struct socket *sock

要等待的套接字

poll_table *p

poll_table

描述

请参阅 wq_has_sleeper 函数中的注释。

struct page_frag *sk_page_frag(struct sock *sk)

返回适当的 page_frag

参数

struct sock *sk

套接字

描述

当知道我们处于进程上下文中并且拥有与 current 关联的所有内容时,使用每个任务的 page_frag 而不是每个套接字的 page_frag 进行优化。

直接回收和页面错误都可以在其他套接字操作中嵌套,并最终递归到 sk_page_frag(),而它已经在使用中:当用户禁用 sk_use_task_frag 时,显式避免任务 page_frag。

返回

如果上下文允许,则使用每个任务的 page_frag,否则使用每个套接字的 page_frag。

void _sock_tx_timestamp(struct sock *sk, const struct sockcm_cookie *sockc, __u8 *tx_flags, __u32 *tskey)

检查是否要对传出数据包进行时间戳标记

参数

struct sock *sk

发送此数据包的套接字

const struct sockcm_cookie *sockc

指向套接字 cmsg cookie 的指针,用于获取时间戳信息

__u8 *tx_flags

完成时间戳标记的说明

__u32 *tskey

填充下一个 sk_tskey (不适用于 TCP,TCP 使用 seqno)

注意

调用者应注意初始 *tx_flags 值(通常为 0)

void sk_eat_skb(struct sock *sk, struct sk_buff *skb)

如果不再需要 skb,则释放它

参数

struct sock *sk

要从中“吃掉” skb 的套接字

struct sk_buff *skb

要“吃掉”的套接字缓冲区

描述

必须在禁用中断或锁定套接字的情况下调用此例程,以便 sk_buff 队列操作正常。

struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)

socket 绑定到 file

参数

struct socket *sock

套接字

int flags

文件状态标志

const char *dname

协议名称

返回与 sock 绑定的 file,隐式将其存储在 sock->file 中。如果 dname 为 NULL,则设置为 “”。

如果失败,则会释放 sock,并返回 ERR 指针。

此函数在内部使用 GFP_KERNEL。

struct socket *sock_from_file(struct file *file)

返回绑定到 filesocket

参数

struct file *file

file

如果失败,则返回 NULL

struct socket *sockfd_lookup(int fd, int *err)

从文件编号转到其套接字槽

参数

int fd

文件句柄

int *err

指向错误代码返回的指针

传入的文件句柄被锁定,并返回它绑定的套接字。如果发生错误,则 err 指针将被覆盖为负 errno 代码,并返回 NULL。该函数检查无效句柄和传递非套接字的句柄。

如果成功,则返回套接字对象指针。

struct socket *sock_alloc(void)

分配一个套接字

参数

void

无参数

描述

分配一个新的 inode 和套接字对象。两者绑定在一起并进行初始化。然后返回套接字。如果我们没有 inodes,则返回 NULL。此函数在内部使用 GFP_KERNEL。

void sock_release(struct socket *sock)

关闭一个套接字

参数

struct socket *sock

要关闭的套接字

如果套接字有释放回调,则将其从协议栈中释放,如果套接字绑定到 inode 而不是文件,则释放 inode。

int sock_sendmsg(struct socket *sock, struct msghdr *msg)

通过 sock 发送消息。

参数

struct socket *sock

套接字

struct msghdr *msg

要发送的消息。

通过 sock 发送 msg,并传递给 LSM。 返回已发送的字节数,或错误代码。

int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, size_t num, size_t size)

通过 sock 发送消息(内核空间)。

参数

struct socket *sock

套接字

struct msghdr *msg

消息头。

struct kvec *vec

内核向量。

size_t num

向量数组长度。

size_t size

消息数据总大小。

使用 vec 构建消息数据并通过 sock 发送。 返回已发送的字节数,或错误代码。

int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg, struct kvec *vec, size_t num, size_t size)

通过 sock 发送消息(内核空间)。

参数

struct sock *sk

套接字。

struct msghdr *msg

消息头。

struct kvec *vec

输出 s/g 数组。

size_t num

输出 s/g 数组长度。

size_t size

消息数据总大小。

使用 vec 构建消息数据并通过 sock 发送。 返回已发送的字节数,或错误代码。调用者必须持有 sk

int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags)

sock 接收消息。

参数

struct socket *sock

套接字

struct msghdr *msg

要接收的消息。

int flags

消息标志。

sock 接收 msg,并传递给 LSM。 返回接收到的总字节数,或错误。

int kernel_recvmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, size_t num, size_t size, int flags)

从套接字接收消息(内核空间)。

参数

struct socket *sock

要从中接收消息的套接字。

struct msghdr *msg

接收到的消息。

struct kvec *vec

用于消息数据的输入 s/g 数组。

size_t num

输入 s/g 数组的大小。

size_t size

要读取的字节数。

int flags

消息标志(MSG_DONTWAIT 等...)。

返回时,msg 结构包含在 vec 参数中传递的散布/收集数组。该数组被修改,使其由原始数组的未填充部分组成。

返回值是接收到的总字节数,或错误。

int sock_create_lite(int family, int type, int protocol, struct socket **res)

创建套接字。

参数

int family

协议族(AF_INET,...)。

int type

通信类型(SOCK_STREAM,...)。

int protocol

协议 (0, ...)。

struct socket **res

新套接字。

创建一个新套接字并将其分配给 res,并传递给 LSM。新套接字的初始化不完整,请参阅 kernel_accept()。 返回 0 或错误。如果失败,res 将设置为 NULL。 此函数内部使用 GFP_KERNEL。

int __sock_create(struct net *net, int family, int type, int protocol, struct socket **res, int kern)

创建套接字。

参数

struct net *net

网络命名空间。

int family

协议族(AF_INET,...)。

int type

通信类型(SOCK_STREAM,...)。

int protocol

协议 (0, ...)。

struct socket **res

新套接字。

int kern

内核空间套接字的布尔值。

创建一个新套接字并将其分配给 res,并传递给 LSM。返回 0 或错误。如果失败,res 将设置为 NULL。如果套接字驻留在内核空间中,则 kern 必须设置为 true。此函数内部使用 GFP_KERNEL。

int sock_create(int family, int type, int protocol, struct socket **res)

创建套接字。

参数

int family

协议族(AF_INET,...)。

int type

通信类型(SOCK_STREAM,...)。

int protocol

协议 (0, ...)。

struct socket **res

新套接字。

__sock_create() 的一个包装器。返回 0 或错误。此函数内部使用 GFP_KERNEL。

int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)

创建一个套接字(内核空间)

参数

struct net *net

网络命名空间。

int family

协议族(AF_INET,...)。

int type

通信类型(SOCK_STREAM,...)。

int protocol

协议 (0, ...)。

struct socket **res

新套接字。

__sock_create() 的一个包装器。返回 0 或错误。此函数内部使用 GFP_KERNEL。

int sock_register(const struct net_proto_family *ops)

添加一个套接字协议处理程序

参数

const struct net_proto_family *ops

协议描述

此函数由希望声明其地址族的协议处理程序调用,并将其链接到套接字接口。值 ops->family 对应于套接字系统调用协议族。

void sock_unregister(int family)

删除一个协议处理程序

参数

int family

要删除的协议族

此函数由希望删除其地址族的协议处理程序调用,并将其从新的套接字创建中取消链接。

如果协议处理程序是一个模块,则可以使用模块引用计数来防止新的引用。如果协议处理程序不是模块,则需要在 ops->create 例程中提供自己的保护。

int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)

将地址绑定到套接字(内核空间)

参数

struct socket *sock

套接字

struct sockaddr *addr

地址

int addrlen

地址的长度

返回 0 或错误。

int kernel_listen(struct socket *sock, int backlog)

将套接字移动到监听状态(内核空间)

参数

struct socket *sock

套接字

int backlog

待处理的连接队列大小

返回 0 或错误。

int kernel_accept(struct socket *sock, struct socket **newsock, int flags)

接受连接(内核空间)

参数

struct socket *sock

监听套接字

struct socket **newsock

新的已连接套接字

int flags

flags

flags 必须是 SOCK_CLOEXEC、SOCK_NONBLOCK 或 0。如果失败,则保证 newsockNULL。返回 0 或错误。

int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, int flags)

连接套接字(内核空间)

参数

struct socket *sock

套接字

struct sockaddr *addr

地址

int addrlen

地址长度

int flags

标志(O_NONBLOCK,...)

对于数据报套接字,addr 是默认发送数据报的地址,也是接收数据报的唯一地址。对于流套接字,尝试连接到 addr。返回 0 或错误代码。

int kernel_getsockname(struct socket *sock, struct sockaddr *addr)

获取套接字绑定的地址(内核空间)

参数

struct socket *sock

套接字

struct sockaddr *addr

地址持有者

使用套接字绑定的地址填充 addr 指针。返回地址的长度(以字节为单位)或错误代码。

int kernel_getpeername(struct socket *sock, struct sockaddr *addr)

获取套接字连接的地址(内核空间)

参数

struct socket *sock

套接字

struct sockaddr *addr

地址持有者

使用套接字连接的地址填充 addr 指针。返回地址的长度(以字节为单位)或错误代码。

int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)

关闭全双工连接的一部分(内核空间)

参数

struct socket *sock

套接字

enum sock_shutdown_cmd how

连接部分

返回 0 或错误。

u32 kernel_sock_ip_overhead(struct sock *sk)

返回套接字施加的 IP 开销

参数

struct sock *sk

套接字

此例程返回套接字施加的 IP 开销,即底层 IP 标头的长度,具体取决于这是 IPv4 还是 IPv6 套接字,以及套接字上启用的 IP 选项的长度。假设调用者已锁定套接字。

void drop_reasons_register_subsys(enum skb_drop_reason_subsys subsys, const struct drop_reason_list *list)

注册另一个丢弃原因子系统

参数

enum skb_drop_reason_subsys subsys

要注册的子系统,不能是核心

const struct drop_reason_list *list

子系统中的丢弃原因列表,必须指向静态初始化的列表

void drop_reasons_unregister_subsys(enum skb_drop_reason_subsys subsys)

注销丢弃原因子系统

参数

enum skb_drop_reason_subsys subsys

要删除的子系统,不能是核心

注意

这将 synchronize_rcu() 以确保返回时没有用户。

struct sk_buff *build_skb_around(struct sk_buff *skb, void *data, unsigned int frag_size)

围绕提供的 skb 构建一个网络缓冲区。

参数

struct sk_buff *skb

由调用者提供的 sk_buff 必须使用 memset 清零。

void *data

由调用者提供的数据缓冲区。

unsigned int frag_size

数据大小。

struct sk_buff *napi_build_skb(void *data, unsigned int frag_size)

构建一个网络缓冲区。

参数

void *data

由调用者提供的数据缓冲区。

unsigned int frag_size

数据大小。

描述

当数据是页或页片段时,此版本的 __napi_build_skb() 会处理 skb->head_frag 和 skb->pfmemalloc。

成功时返回一个新的 sk_buff,分配失败时返回 NULL

struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, int flags, int node)

分配网络缓冲区

参数

unsigned int size

要分配的大小

gfp_t gfp_mask

分配掩码

int flags

如果设置了 SKB_ALLOC_FCLONE,则从 fclone 缓存而不是头缓存分配,并分配一个克隆的(子)skb。如果设置了 SKB_ALLOC_RX,则在数据需要用于回写的情况下,将使用 __GFP_MEMALLOC 进行分配。

int node

用于分配内存的 numa 节点。

分配一个新的 sk_buff。返回的缓冲区没有前导空间,并且至少有 size 字节的尾部空间。该对象的引用计数为 1。返回值为缓冲区。如果失败,则返回值为 NULL

只能使用 GFP_ATOMICgfp_mask 从中断中分配缓冲区。

struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len, gfp_t gfp_mask)

在特定设备上为 rx 分配一个 skbuff

参数

struct net_device *dev

要接收的网络设备

unsigned int len

要分配的长度

gfp_t gfp_mask

传递给 alloc_skb 的 get_free_pages 掩码。

分配一个新的 sk_buff 并为其分配一个使用计数 1。缓冲区内置了 NET_SKB_PAD 前导空间。用户应分配他们认为需要的前导空间,而无需考虑内置空间。内置空间用于优化。

如果没有可用内存,则返回 NULL

struct sk_buff *napi_alloc_skb(struct napi_struct *napi, unsigned int len)

在特定的 NAPI 实例中为 rx 分配 skbuff。

参数

struct napi_struct *napi

为此缓冲区分配的 napi 实例。

unsigned int len

要分配的长度

分配一个新的 sk_buff,以便在 NAPI 接收中使用。此缓冲区将尝试从仅用于 NAPI Rx 分配的特殊保留区域分配头。通过这样做,我们可以避免禁用和重新启用 IRQ,从而节省几个 CPU 周期。

如果没有可用内存,则返回 NULL

void __kfree_skb(struct sk_buff *skb)

私有函数。

参数

struct sk_buff *skb

缓冲区

释放一个 sk_buff。释放附加到缓冲区的任何内容。清理状态。这是一个内部辅助函数。用户应始终调用 kfree_skb。

void __fix_address sk_skb_reason_drop(struct sock *sk, struct sk_buff *skb, enum skb_drop_reason reason)

释放一个带有特殊原因的 sk_buff。

参数

struct sock *sk

用于接收 skb 的套接字,如果不可用,则为 NULL。

struct sk_buff *skb

要释放的缓冲区

enum skb_drop_reason reason

此 skb 被丢弃的原因。

删除对缓冲区的引用,如果使用计数达到 0,则释放该缓冲区。同时,将接收套接字和丢弃原因传递给“kfree_skb”跟踪点。

void skb_tx_error(struct sk_buff *skb)

报告 sk_buff xmit 错误。

参数

struct sk_buff *skb

触发错误的缓冲区。

如果设备回调正在跟踪此 skb,则报告 xmit 错误。skb 必须在之后释放。

void consume_skb(struct sk_buff *skb)

释放一个 skbuff。

参数

struct sk_buff *skb

要释放的缓冲区

删除对缓冲区的引用,如果使用计数达到 0,则释放该缓冲区。功能与 kfree_skb 相同,但 kfree_skb 假设帧在失败后被丢弃,并会记录该信息。

struct sk_buff *alloc_skb_for_msg(struct sk_buff *first)

分配 sk_buff 以包装形成消息的 frag 列表。

参数

struct sk_buff *first

消息的第一个 sk_buff。

struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src)

将一个 skb 变形为另一个 skb。

参数

struct sk_buff *dst

用于接收内容的 skb。

struct sk_buff *src

提供内容的 skb。

这与 skb_clone 相同,只是目标 skb 由用户提供。

退出时返回目标 skb。

int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)

将用户空间 skb frag 缓冲区复制到内核。

参数

struct sk_buff *skb

要修改的 skb。

gfp_t gfp_mask

分配优先级。

必须在带有 SKBFL_ZEROCOPY_ENABLE 标志的 skb 上调用此函数。它会将所有分片复制到内核,并丢弃对用户空间页面的引用。

如果此函数是从中断调用的,则 gfp_mask() 必须为 GFP_ATOMIC

成功时返回 0,如果无法分配内核内存进行复制,则返回负错误代码。

struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)

复制一个 sk_buff

参数

struct sk_buff *skb

要克隆的缓冲区

gfp_t gfp_mask

分配优先级。

复制一个 sk_buff。新的副本不归套接字所有。两个副本共享相同的包数据,但结构不同。新缓冲区的引用计数为 1。如果分配失败,函数返回 NULL,否则返回新缓冲区。

如果此函数是从中断调用的,则 gfp_mask() 必须为 GFP_ATOMIC

struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)

创建 sk_buff 的私有副本

参数

const struct sk_buff *skb

要复制的缓冲区

gfp_t gfp_mask

分配优先级。

创建 sk_buff 及其数据的副本。当调用者希望修改数据并需要私有数据副本进行更改时,使用此方法。失败时返回 NULL,成功时返回指向缓冲区的指针。返回的缓冲区的引用计数为 1。

作为副产品,此函数将非线性 sk_buff 转换为线性 sk_buff,以便 sk_buff 完全成为私有的,并且允许调用者修改返回缓冲区的所有数据。这意味着当只修改头部时,不建议使用此函数。请改用 pskb_copy()。

struct sk_buff *__pskb_copy_fclone(struct sk_buff *skb, int headroom, gfp_t gfp_mask, bool fclone)

创建带有私有头的 sk_buff 副本。

参数

struct sk_buff *skb

要复制的缓冲区

int headroom

新 skb 的预留空间

gfp_t gfp_mask

分配优先级。

bool fclone

如果为 true,则从 fclone 缓存而不是头缓存分配 skb 的副本;建议在副本很可能被克隆的情况下将其设置为 true

创建 sk_buff 及其部分数据的副本(位于头部)。分片数据保持共享。当调用者希望仅修改 sk_buff 的头部,并且需要头部的私有副本进行更改时,使用此方法。失败时返回 NULL,成功时返回指向缓冲区的指针。返回的缓冲区的引用计数为 1。

int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, gfp_t gfp_mask)

重新分配 sk_buff 的头部

参数

struct sk_buff *skb

要重新分配的缓冲区

int nhead

要在头部添加的空间

int ntail

要在尾部添加的空间

gfp_t gfp_mask

分配优先级。

扩展(如果 nheadntail 为零,则创建相同的副本)skb 的头部。sk_buff 本身不会更改。sk_buff 的引用计数必须为 1。成功时返回零,如果扩展失败,则返回错误。在最后一种情况下,sk_buff 不会更改。

指向 skb 头部的所有指针都可能更改,并且必须在调用此函数后重新加载。

struct sk_buff *skb_expand_head(struct sk_buff *skb, unsigned int headroom)

重新分配 sk_buff 的头部

参数

struct sk_buff *skb

要重新分配的缓冲区

unsigned int headroom

需要的头部空间

与 skb_realloc_headroom 不同,如果可能,此函数不会分配新的 skb;根据需要将 skb->sk 复制到新的 skb,并在失败时释放原始 skb。

它期望增加预留空间,否则会生成警告。

struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom, int newtailroom, gfp_t gfp_mask)

复制并扩展 sk_buff

参数

const struct sk_buff *skb

要复制的缓冲区

int newheadroom

头部的新空闲字节数

int newtailroom

尾部的新空闲字节数

gfp_t gfp_mask

分配优先级。

创建 sk_buff 及其数据的副本,并在执行此操作的同时分配额外的空间。

当调用者希望修改数据并需要私有数据副本进行更改以及更多空间用于新字段时,使用此方法。失败时返回 NULL,成功时返回指向缓冲区的指针。返回的缓冲区的引用计数为 1。

如果此函数是从中断调用的,则必须将 GFP_ATOMIC 作为分配优先级传递。

int __skb_pad(struct sk_buff *skb, int pad, bool free_on_error)

用零填充 skb 的尾部

参数

struct sk_buff *skb

要填充的缓冲区

int pad

要填充的空间

bool free_on_error

发生错误时释放缓冲区

确保缓冲区后跟一个零填充的填充区域。由网络驱动程序使用,这些驱动程序可能会将数据 DMA 或传输到超出缓冲区末尾的电线上。

在内存不足的情况下可能会返回错误。如果 free_on_error 为 true,则会在出错时释放 skb。

void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len)

将数据添加到可能已分片的缓冲区的尾部

参数

struct sk_buff *skb

要使用的缓冲区的开头

struct sk_buff *tail

要使用的缓冲区的尾部分片

int len

要添加的数据量

此函数会扩展可能已分片的缓冲区的使用数据区域。tail 必须是 skb 的最后一个分片,或者 skb 本身。如果超出总缓冲区大小,内核将发生 panic。返回指向额外数据的第一个字节的指针。

void *skb_put(struct sk_buff *skb, unsigned int len)

向缓冲区添加数据

参数

struct sk_buff *skb

要使用的缓冲区

unsigned int len

要添加的数据量

此函数扩展缓冲区已使用的数据区域。如果这将超出缓冲区的总大小,内核将会发生 panic。返回指向额外数据的第一个字节的指针。

void *skb_push(struct sk_buff *skb, unsigned int len)

向缓冲区开头添加数据

参数

struct sk_buff *skb

要使用的缓冲区

unsigned int len

要添加的数据量

此函数扩展缓冲区开头已使用的数据区域。如果这将超出缓冲区的总头部空间,内核将会发生 panic。返回指向额外数据的第一个字节的指针。

void *skb_pull(struct sk_buff *skb, unsigned int len)

从缓冲区开头移除数据

参数

struct sk_buff *skb

要使用的缓冲区

unsigned int len

要移除的数据量

此函数从缓冲区开头移除数据,将内存返回到头部空间。返回指向缓冲区中下一个数据的指针。一旦数据被拉取,未来的推送将覆盖旧数据。

void *skb_pull_data(struct sk_buff *skb, size_t len)

从缓冲区开头移除数据,返回其原始位置。

参数

struct sk_buff *skb

要使用的缓冲区

size_t len

要移除的数据量

此函数从缓冲区开头移除数据,将内存返回到头部空间。在检查是否有足够的数据来拉取后,返回指向缓冲区中原始数据的指针。一旦数据被拉取,未来的推送将覆盖旧数据。

void skb_trim(struct sk_buff *skb, unsigned int len)

从缓冲区移除尾部

参数

struct sk_buff *skb

要修改的缓冲区

unsigned int len

新长度

通过从尾部移除数据来缩减缓冲区的长度。如果缓冲区已小于指定的长度,则不会修改。skb 必须是线性的。

void *__pskb_pull_tail(struct sk_buff *skb, int delta)

推进 skb 头的尾部

参数

struct sk_buff *skb

要重新分配的缓冲区

int delta

要推进尾部的字节数

该函数仅在分片的 sk_buff 上有意义,它通过向前移动尾部并从分片部分复制必要的数据来扩展头部。

sk_buff 必须具有 1 的引用计数。

如果拉取失败,则返回 NULL(且 sk_buff 不会改变),否则返回 skb 的新尾部值。

指向 skb 头部的所有指针都可能更改,并且必须在调用此函数后重新加载。

int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)

将 skb 中的位复制到内核缓冲区

参数

const struct sk_buff *skb

源 skb

int offset

源中的偏移量

void *to

目标缓冲区

int len

要复制的字节数

将指定数量的字节从源 skb 复制到目标缓冲区。

注意!

如果其原型被更改,请检查 arch/{*}/net/{*}.S 文件,因为它是由 BPF 汇编代码调用的。

int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len)

将内核缓冲区中的位存储到 skb

参数

struct sk_buff *skb

目标缓冲区

int offset

目标中的偏移量

const void *from

源缓冲区

int len

要复制的字节数

将指定数量的字节从源缓冲区复制到目标 skb。此函数处理遍历片段列表等所有混乱的位。

int skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen)

将 skb 零复制到 skb

参数

struct sk_buff *to

目标缓冲区

struct sk_buff *from

源缓冲区

int len

要从源缓冲区复制的字节数

int hlen

目标缓冲区中线性头部空间的大小

通过创建对源缓冲区中片段的引用,从 from 复制最多 len 个字节到 to

skb_zerocopy_headlen() 计算出的 hlen 指定 to 缓冲区中的头部空间。

返回值:0:一切正常 -ENOMEM:由于内存不足,无法孤立 **from** 的片段 -EFAULT:skb_copy_bits() 发现 skb 几何结构存在一些问题

struct sk_buff *skb_dequeue(struct sk_buff_head *list)

从队列头部移除。

参数

struct sk_buff_head *list

从中出队的列表。

移除列表的头部。列表锁被获取,因此该函数可以安全地与其他锁定列表函数一起使用。返回头部项,如果列表为空,则返回 NULL

struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list)

从队列尾部移除。

参数

struct sk_buff_head *list

从中出队的列表。

移除列表的尾部。列表锁被获取,因此该函数可以安全地与其他锁定列表函数一起使用。返回尾部项,如果列表为空,则返回 NULL

void skb_queue_purge_reason(struct sk_buff_head *list, enum skb_drop_reason reason)

清空列表

参数

struct sk_buff_head *list

要清空的列表

enum skb_drop_reason reason

丢弃原因

删除 sk_buff 列表上的所有缓冲区。每个缓冲区都会从列表中移除,并减少一个引用计数。此函数会获取列表锁,并且对于其他列表锁定函数是原子的。

void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)

在列表头部排队一个缓冲区。

参数

struct sk_buff_head *list

要使用的列表。

struct sk_buff *newsk

要排队的缓冲区。

将缓冲区排队到列表的开头。此函数会获取列表锁,并且可以安全地与其他锁定 sk_buff 函数一起安全使用。

一个缓冲区不能同时放在两个列表中。

void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)

在列表尾部排队一个缓冲区。

参数

struct sk_buff_head *list

要使用的列表。

struct sk_buff *newsk

要排队的缓冲区。

将缓冲区排队到列表的末尾。此函数会获取列表锁,并且可以安全地与其他锁定 sk_buff 函数一起安全使用。

一个缓冲区不能同时放在两个列表中。

从列表中移除缓冲区

参数

struct sk_buff *skb

要移除的缓冲区

struct sk_buff_head *list

要使用的列表。

从列表中移除数据包。会获取列表锁,并且此函数对于其他列表锁定调用是原子的。

您必须知道 SKB 所在的列表。

void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list)

追加缓冲区

参数

struct sk_buff *old

在其后插入的缓冲区

struct sk_buff *newsk

要插入的缓冲区

struct sk_buff_head *list

要使用的列表。

将数据包放置在列表中给定数据包之后。会获取列表锁,并且此函数对于其他列表锁定调用是原子的。一个缓冲区不能同时放置在两个列表中。

void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len)

在长度 len 处将分片的 skb 分割为两个部分。

参数

struct sk_buff *skb

要分割的缓冲区

struct sk_buff *skb1

用于接收第二部分的缓冲区

const u32 len

skb 的新长度

void skb_prepare_seq_read(struct sk_buff *skb, unsigned int from, unsigned int to, struct skb_seq_state *st)

准备 skb 数据的顺序读取

参数

struct sk_buff *skb

要读取的缓冲区

unsigned int from

要读取的数据的较低偏移量

unsigned int to

要读取的数据的较高偏移量

struct skb_seq_state *st

状态变量

描述

初始化指定的状态变量。必须在第一次调用 skb_seq_read() 之前调用。

unsigned int skb_seq_read(unsigned int consumed, const u8 **data, struct skb_seq_state *st)

按顺序读取 skb 数据

参数

unsigned int consumed

调用者到目前为止已使用的字节数

const u8 **data

要返回的数据的目标指针

struct skb_seq_state *st

状态变量

描述

在相对于 skb_prepare_seq_read() 指定的较低偏移量的 consumed 处读取一个 skb 数据块。将数据块的头部分配给 data,如果到达 skb 数据的末尾或已到达较高偏移量,则返回块的长度或 0。

不需要调用者使用返回的所有数据,即 consumed 通常设置为已使用的字节数,并且下一次调用 skb_seq_read() 将返回该块的剩余部分。

注意 1:返回的每个数据块的大小可以是任意的,

此限制是可能非线性数据的零拷贝顺序读取的代价。

注意 2:当前未实现片段内的片段列表

目前,state->root_skb 可以用作此目的的堆栈。

void skb_abort_seq_read(struct skb_seq_state *st)

中止 skb 数据的顺序读取

参数

struct skb_seq_state *st

状态变量

描述

如果 skb_seq_read() 没有被调用直到它返回 0,则必须调用此函数。

int skb_copy_seq_read(struct skb_seq_state *st, int offset, void *to, int len)

从 skb_seq_state 复制到缓冲区

参数

struct skb_seq_state *st

源 skb_seq_state

int offset

源中的偏移量

void *to

目标缓冲区

int len

要复制的字节数

描述

将源 st 中从 offset 字节开始的 len 个字节复制到目标缓冲区 tooffset 应该在每次后续调用此函数时增加(或保持不变)。如果 offset 需要比上次使用时减小,则应先重置 st

返回

成功返回 0,如果复制提前结束则返回 -EINVAL

unsigned int skb_find_text(struct sk_buff *skb, unsigned int from, unsigned int to, struct ts_config *config)

在 skb 数据中查找文本模式

参数

struct sk_buff *skb

要查找的缓冲区

unsigned int from

搜索偏移量

unsigned int to

搜索限制

struct ts_config *config

文本搜索配置

描述

根据指定的文本搜索配置在 skb 数据中查找模式。使用 textsearch_next() 来检索该模式的后续出现。如果未找到匹配项,则返回第一个匹配项的偏移量或 UINT_MAX。

void *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)

拉取 skb 并更新接收校验和

参数

struct sk_buff *skb

要更新的缓冲区

unsigned int len

pull 的数据长度

此函数对数据包执行 skb_pull 操作并更新 CHECKSUM_COMPLETE 校验和。它应该在接收路径处理中使用,而不是 skb_pull,除非您知道校验和差异为零(例如,有效的 IP 标头)或者您将 ip_summed 设置为 CHECKSUM_NONE。

struct sk_buff *skb_segment(struct sk_buff *head_skb, netdev_features_t features)

在 skb 上执行协议分段。

参数

struct sk_buff *head_skb

要分段的缓冲区

netdev_features_t features

输出路径的功能(请参阅 dev->features)

此函数对给定的 skb 执行分段。它返回指向新 skb 分段列表中第一个 skb 的指针。如果发生错误,则返回 ERR_PTR(err)。

int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)

从套接字缓冲区填充分散-聚集列表

参数

struct sk_buff *skb

包含要映射的缓冲区的套接字缓冲区

struct scatterlist *sg

要映射到的分散-聚集列表

int offset

要开始映射的缓冲区内容偏移量

int len

要映射的缓冲区空间长度

使用指向附加到套接字缓冲区的缓冲区空间的映射/指针填充指定的分散-聚集列表。返回使用的分散列表项数,如果内容无法容纳,则返回 -EMSGSIZE。

int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)

检查套接字缓冲区的数据缓冲区是否可写

参数

struct sk_buff *skb

要检查的套接字缓冲区。

int tailbits

要添加的尾部空间量

struct sk_buff **trailer

返回指向 tailbits 空间开始处的 skb 的指针

确保附加到套接字缓冲区的数据缓冲区是可写的。如果不是,则会创建数据缓冲区的私有副本,并且将套接字缓冲区设置为使用这些副本。

如果给定 tailbits,请确保在套接字缓冲区当前末尾之后有空间写入 tailbits 字节的数据。trailer 将被设置为指向此空间开始处的 skb。

将返回完全映射 COW 扩展套接字缓冲区所需的散列表元素数。

struct sk_buff *skb_clone_sk(struct sk_buff *skb)

创建 skb 的克隆,并获取对套接字的引用

参数

struct sk_buff *skb

要克隆的 skb

描述

此函数创建保存 sk_refcnt 引用的缓冲区克隆。通过此函数创建的缓冲区旨在通过 sock_queue_err_skb 返回,或通过 kfree_skb 释放。

当将使用此函数分配的缓冲区传递给 sock_queue_err_skb 时,必须用 sock_hold/sock_put 包装调用,以防止套接字在排队到 sk_error_queue 之前被释放。

bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off)

为数据包设置并验证部分校验和值

参数

struct sk_buff *skb

要设置的 skb

u16 start

skb->data 后开始计算校验和的字节数。

u16 off

从开始到放置校验和的偏移量。

描述

对于不受信任的部分校验和数据包,我们需要确保 skb->csum_start 和 skb->csum_offset 的值有效,这样我们就不会出错。

此函数检查并设置这些值和 skb->ip_summed:如果返回 false,您应该丢弃该数据包。

int skb_checksum_setup(struct sk_buff *skb, bool recalculate)

设置部分校验和偏移量

参数

struct sk_buff *skb

要设置的 skb

bool recalculate

如果为 true,则将重新计算伪报头校验和

struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb, unsigned int transport_len, __sum16 (*skb_chkf)(struct sk_buff *skb))

验证 skb 的校验和

参数

struct sk_buff *skb

要检查的 skb

unsigned int transport_len

网络标头之外的数据长度

__sum16(*skb_chkf)(struct sk_buff *skb)

要使用的校验和函数

描述

将给定的校验和函数 skb_chkf 应用于提供的 skb。返回经过检查并且可能修剪过的 skb。如果发生错误,则返回 NULL。

如果 skb 的数据超出给定的传输长度,则会检查并返回修剪后的 & 克隆的 skb。

调用者需要设置 skb 传输标头,并释放返回的任何与提供的 skb 不同的 skb。

bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, bool *fragstolen, int *delta_truesize)

尝试将 skb 合并到之前的 skb

参数

struct sk_buff *to

之前的缓冲区

struct sk_buff *from

要添加的缓冲区

bool *fragstolen

指向布尔值的指针

int *delta_truesize

实际分配的比请求的多多少

void skb_scrub_packet(struct sk_buff *skb, bool xnet)

清理 skb

参数

struct sk_buff *skb

要清理的缓冲区

bool xnet

数据包正在跨越 netns

描述

在将数据包封装到隧道或从隧道解封装后可以使用 skb_scrub_packet。在这些操作期间,必须清除一些信息。 skb_scrub_packet 也可以用于在将 skb 注入另一个命名空间之前进行清理(xnet == true)。我们必须清除 skb 中可能影响命名空间隔离的所有信息。

int skb_eth_pop(struct sk_buff *skb)

删除数据包头部中的以太网头部

参数

struct sk_buff *skb

要修改的套接字缓冲区

描述

删除 skb 的以太网头部。

预期 skb->data 指向 mac 头部,并且不存在 VLAN 标签。

成功返回 0,否则返回 -errno。

int skb_eth_push(struct sk_buff *skb, const unsigned char *dst, const unsigned char *src)

在数据包头部添加新的以太网头部

参数

struct sk_buff *skb

要修改的套接字缓冲区

const unsigned char *dst

新头部的目标 MAC 地址

const unsigned char *src

新头部的源 MAC 地址

描述

用新的以太网头部前置 skb

预期 skb->data 指向 mac 头部,该头部必须为空。

成功返回 0,否则返回 -errno。

int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto, int mac_len, bool ethernet)

从数据包起始位置的 mac_len 字节后推送一个新的 MPLS 头部

参数

struct sk_buff *skb

缓冲区

__be32 mpls_lse

要推送的 MPLS 标签栈条目

__be16 mpls_proto

新 MPLS 头部的以太网类型(期望为 0x8847 或 0x8848)

int mac_len

MAC 头部的长度

bool ethernet

标志指示 skb_mpls_push 之后生成的包是否为以太网包

描述

预期 skb->data 位于 mac 头部。

成功返回 0,否则返回 -errno。

int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len, bool ethernet)

弹出最外层的 MPLS 头部

参数

struct sk_buff *skb

缓冲区

__be16 next_proto

弹出 MPLS 头部后的头部以太网类型

int mac_len

MAC 头部的长度

bool ethernet

标志指示数据包是否为以太网包

描述

预期 skb->data 位于 mac 头部。

成功返回 0,否则返回 -errno。

int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse)

修改最外层的 MPLS 头部并更新校验和

参数

struct sk_buff *skb

缓冲区

__be32 mpls_lse

要更新为的新 MPLS 标签栈条目

描述

预期 skb->data 位于 mac 头部。

成功返回 0,否则返回 -errno。

int skb_mpls_dec_ttl(struct sk_buff *skb)

递减最外层 MPLS 头部的 TTL

参数

struct sk_buff *skb

缓冲区

描述

预期 skb->data 位于 mac 头部。

成功返回 0,否则返回 -errno。

struct sk_buff *alloc_skb_with_frags(unsigned long header_len, unsigned long data_len, int order, int *errcode, gfp_t gfp_mask)

使用页面碎片分配 skb

参数

unsigned long header_len

线性部分的大小

unsigned long data_len

碎片中需要的长度

int order

所需的最大页面顺序。

int *errcode

指向错误代码的指针(如果有)

gfp_t gfp_mask

分配掩码

描述

这可以用于分配一个分页的 skb,给定碎片的最大顺序。

void skb_condense(struct sk_buff *skb)

如果可能,尝试摆脱碎片/frag_list

参数

struct sk_buff *skb

缓冲区

描述

可以在将 skb 添加到繁忙队列之前用于节省内存。如果数据包在碎片中有字节,并且 skb->head 中有足够的尾部空间,则拉取所有字节,这样我们就可以立即释放碎片并调整 truesize。

注意

我们不重新分配 skb->head,因此不会失败。如果需要,调用者必须重新评估 skb->truesize。

void *skb_ext_add(struct sk_buff *skb, enum skb_ext_id id)

为给定的扩展分配空间,如果需要则进行写时复制(COW)

参数

struct sk_buff *skb

缓冲区

enum skb_ext_id id

要为其分配空间的扩展

描述

为给定的扩展分配足够的空间。如果扩展已经存在,则返回指向该扩展的指针。

如果 skb 被克隆,则应用 COW,并且返回的内存可以被修改,而不会改变克隆缓冲区的扩展空间。

返回指向扩展的指针,如果分配失败则返回 NULL。

ssize_t skb_splice_from_iter(struct sk_buff *skb, struct iov_iter *iter, ssize_t maxsize, gfp_t gfp)

将页面拼接(或复制)到 skbuff

参数

struct sk_buff *skb

要向其添加页面的缓冲区

struct iov_iter *iter

表示要添加的页面的迭代器

ssize_t maxsize

要添加的最大页面数量

gfp_t gfp

分配标志

描述

这是一个用于支持 MSG_SPLICE_PAGES 的常见辅助函数。它从迭代器中提取页面,并尽可能将它们添加到套接字缓冲区中,如果不可能(例如,如果它们是 slab 页面),则将它们复制到片段中。

返回拼接/复制的数据量,如果缓冲区中没有足够的空间来传输任何内容,则返回 -EMSGSIZE。

bool sk_ns_capable(const struct sock *sk, struct user_namespace *user_ns, int cap)

通用套接字能力测试

参数

const struct sock *sk

要在其上或通过其使用能力的套接字

struct user_namespace *user_ns

要使用的能力的 用户命名空间

int cap

要使用的能力

描述

测试套接字的打开者在创建套接字时是否具有,并且当前进程在用户命名空间 **user_ns** 中是否具有能力 **cap**。

bool sk_capable(const struct sock *sk, int cap)

套接字全局能力测试

参数

const struct sock *sk

要在其上或通过其使用能力的套接字

int cap

要使用的全局能力

描述

测试套接字的打开者在创建套接字时是否具有,并且当前进程在所有用户命名空间中是否都具有能力 **cap**。

bool sk_net_capable(const struct sock *sk, int cap)

网络命名空间套接字能力测试

参数

const struct sock *sk

要在其上或通过其使用能力的套接字

int cap

要使用的能力

描述

测试套接字的打开者在创建套接字时是否具有,并且当前进程是否对套接字所属的网络命名空间具有能力 **cap**。

void sk_set_memalloc(struct sock *sk)

设置 SOCK_MEMALLOC

参数

struct sock *sk

要在其上设置的套接字

描述

在套接字上设置 SOCK_MEMALLOC 以访问紧急预留内存。管理员有责任调整 min_free_kbytes 以满足要求

struct sock *sk_alloc(struct net *net, int family, gfp_t priority, struct proto *prot, int kern)

所有套接字对象都在这里分配

参数

struct net *net

适用的 net 命名空间

int family

协议族

gfp_t priority

用于分配(GFP_KERNELGFP_ATOMIC 等)

struct proto *prot

与这个新套接字实例关联的 struct proto

int kern

这是否是要成为内核套接字?

struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)

克隆一个套接字,并锁定它的克隆

参数

const struct sock *sk

要克隆的套接字

const gfp_t priority

用于分配(GFP_KERNELGFP_ATOMIC 等)

即使在错误路径中,调用者也必须解锁套接字 (bh_unlock_sock(newsk))

bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t gfp)

检查 page_frag 是否包含足够的空间

参数

unsigned int sz

我们想要获取的片段的最小大小

struct page_frag *pfrag

指向 page_frag 的指针

gfp_t gfp

内存分配的优先级

注意

虽然此分配器尝试使用高阶页面,但不保证分配成功。因此,**sz** 必须小于或等于 PAGE_SIZE。

int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb)

等待数据到达 sk_receive_queue

参数

struct sock *sk

要等待的套接字

long *timeo

等待多长时间

const struct sk_buff *skb

在 sk_receive_queue 上看到的最后一个 skb

描述

现在,包括 sk->sk_err 在内的套接字状态仅在锁定下更改,因此我们可以在加入等待队列后省略检查。我们仅在 schedule() 之前检查接收队列,作为优化;release_sock() 很可能添加了新数据。

int __sk_mem_schedule(struct sock *sk, int size, int kind)

增加 sk_forward_alloc 和 memory_allocated

参数

struct sock *sk

套接字

int size

要分配的内存大小

int kind

分配类型

如果 kind 是 SK_MEM_SEND,则表示 wmem 分配。否则表示 rmem 分配。此函数假设具有 memory_pressure 的协议使用 sk_wmem_queued 作为写入缓冲区记账。

void __sk_mem_reclaim(struct sock *sk, int amount)

回收 sk_forward_alloc 和 memory_allocated

参数

struct sock *sk

套接字

int amount

字节数(向下舍入到 PAGE_SIZE 的倍数)

struct sk_buff *__skb_try_recv_datagram(struct sock *sk, struct sk_buff_head *queue, unsigned int flags, int *off, int *err, struct sk_buff **last)

接收一个数据报 skbuff

参数

struct sock *sk

套接字

struct sk_buff_head *queue

要从中接收的套接字队列

unsigned int flags

MSG_ 标志

int *off

从 skb 中窥视的字节偏移量。返回数据实际开始的 skb 中的偏移量

int *err

返回的错误代码

struct sk_buff **last

设置为最后窥视的消息,以告知等待函数在窥视时要查找的内容

获取一个数据报 skbuff,理解窥视、非阻塞唤醒和可能的竞争。这取代了数据包、原始数据和 udp 中的相同代码,以及 IPX AX.25 和 Appletalk。它还最终修复了数据报套接字长期存在的窥视和读取竞争。如果您更改此例程,请记住它必须是可重入的。

如果返回 skb,此函数将锁定套接字,因此调用者需要在这种情况下解锁套接字(通常通过调用 skb_free_datagram)。如果没有任何数据可用,则返回 NULL 并将 err 设置为 -EAGAIN,如果检测到错误,则返回其他值。

  • 从今天开始,它不锁定套接字。此功能是

  • 无竞争条件的。此措施应/可以改善

  • 在高负载下显着提高数据报套接字延迟,

  • 当复制数据到用户空间需要大量时间时。

  • (顺便说一句,我刚刚杀死了 IP/IPv6/core/netlink/packet 中的最后一个 cli())

    1. 大获全胜。)

  • --ANK (980729)

当我们发现没有数据等待时,测试的顺序由 POSIX 1003.1g 明确指定,请不要在没有标准的情况下更改它们。

int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)

强制释放数据报 skbuff

参数

struct sock *sk

套接字

struct sk_buff *skb

数据报 skbuff

unsigned int flags

MSG_ 标志

此函数释放由 skb_recv_datagram 接收的数据报 skbuff。flags 参数必须与 skb_recv_datagram 使用的参数匹配。

如果设置了 MSG_PEEK 标志,并且数据包仍然在套接字的接收队列中,则在释放之前会将其从队列中删除。

此函数当前仅在获取 sk_receive_queue 锁时禁用 BH。因此,它不得在 IRQ 上下文中获取该锁定的上下文中使用。

如果数据包是由我们删除的,则返回 0。

int skb_copy_and_hash_datagram_iter(const struct sk_buff *skb, int offset, struct iov_iter *to, int len, struct ahash_request *hash)

将数据报复制到 iovec 迭代器并更新哈希。

参数

const struct sk_buff *skb

要复制的缓冲区

int offset

要开始复制的缓冲区中的偏移量

struct iov_iter *to

要复制到的 iovec 迭代器

int len

要从缓冲区复制到 iovec 的数据量

struct ahash_request *hash

要更新的哈希请求

int skb_copy_datagram_iter(const struct sk_buff *skb, int offset, struct iov_iter *to, int len)

将数据报复制到 iovec 迭代器。

参数

const struct sk_buff *skb

要复制的缓冲区

int offset

要开始复制的缓冲区中的偏移量

struct iov_iter *to

要复制到的 iovec 迭代器

int len

要从缓冲区复制到 iovec 的数据量

int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset, struct iov_iter *from, int len)

从 iov_iter 复制数据报。

参数

struct sk_buff *skb

要复制的缓冲区

int offset

要开始复制到的缓冲区中的偏移量

struct iov_iter *from

复制源

int len

要从 iovec 复制到缓冲区的数据量

返回 0 或 -EFAULT。

int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *from)

从 iov_iter 构建一个零拷贝数据报

参数

struct sk_buff *skb

要复制的缓冲区

struct iov_iter *from

要复制的源

该函数将首先复制到 headlen,然后固定用户空间页面并通过它们构建 frags。

返回 0、-EFAULT 或 -EMSGSIZE。

int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, int hlen, struct msghdr *msg)

将 skb 复制并校验和到用户 iovec。

参数

struct sk_buff *skb

skbuff

int hlen

硬件长度

struct msghdr *msg

目的地

调用者_必须_检查 skb 是否适合此 iovec。

返回

0 - 成功。

-EINVAL - 校验和失败。 -EFAULT - 复制期间出错。

__poll_t datagram_poll(struct file *file, struct socket *sock, poll_table *wait)

通用数据报轮询

参数

struct file *file

文件结构体

struct socket *sock

套接字

poll_table *wait

轮询表

数据报轮询:再次完全通用。这也处理了序列化的数据包套接字,前提是套接字接收队列始终只保存准备接收的数据。

注意

当你对此协议使用此例程时,

并且你使用了与 sock_writeable() 不同的写入策略,请提供你自己的 write_space 回调函数。

int sk_stream_wait_connect(struct sock *sk, long *timeo_p)

等待套接字进入已连接状态

参数

struct sock *sk

要等待的套接字

long *timeo_p

等待多长时间

描述

必须在套接字锁定的情况下调用。

int sk_stream_wait_memory(struct sock *sk, long *timeo_p)

等待套接字有更多内存可用

参数

struct sock *sk

要等待内存的套接字

long *timeo_p

等待多长时间

套接字过滤器

int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap)

通过套接字过滤器运行数据包

参数

struct sock *sk

sk_buff 关联的套接字

struct sk_buff *skb

要过滤的缓冲区

unsigned int cap

eBPF 程序可以修剪数据包的最小长度限制

描述

运行 eBPF 程序,然后将 skb->data 裁剪为程序返回的正确大小。如果 pkt_len 为 0,则丢弃数据包。如果 skb->len 小于 pkt_len,则保留整个 skb->data。这是 bpf_prog_run 的套接字级包装器。如果应接受数据包,则返回 0,如果应丢弃数据包,则返回 -EPERM。

int bpf_prog_create(struct bpf_prog **pfp, struct sock_fprog_kern *fprog)

创建一个未附加的过滤器

参数

struct bpf_prog **pfp

创建的未附加的过滤器

struct sock_fprog_kern *fprog

过滤器程序

描述

创建独立于任何套接字的过滤器。我们首先对其进行一些健全性检查,以确保它稍后不会崩溃。如果发生错误或过滤器内存不足,则返回负的 errno 代码。成功时返回零。

int bpf_prog_create_from_user(struct bpf_prog **pfp, struct sock_fprog *fprog, bpf_aux_classic_check_t trans, bool save_orig)

从用户缓冲区创建一个未附加的过滤器

参数

struct bpf_prog **pfp

创建的未附加的过滤器

struct sock_fprog *fprog

过滤器程序

bpf_aux_classic_check_t trans

经典后验证器转换处理程序

bool save_orig

保存经典 BPF 程序

描述

此函数实际上与 bpf_prog_create() 相同,只是它从用户空间提供的缓冲区构建其 insns 缓冲区。它还允许传递 bpf_aux_classic_check_t 处理程序。

int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)

附加套接字过滤器

参数

struct sock_fprog *fprog

过滤器程序

struct sock *sk

要使用的套接字

描述

附加用户的过滤器代码。我们首先对其进行一些健全性检查,以确保它稍后不会崩溃。如果发生错误或过滤器内存不足,则返回负的 errno 代码。成功时返回零。

通用网络统计

struct gnet_stats_basic

字节/数据包吞吐量统计

定义:

struct gnet_stats_basic {
    __u64 bytes;
    __u32 packets;
};

成员

字节

已看到的字节数

数据包

已看到的数据包数

struct gnet_stats_rate_est

速率估算器

定义:

struct gnet_stats_rate_est {
    __u32 bps;
    __u32 pps;
};

成员

bps

当前字节速率

pps

当前数据包速率

struct gnet_stats_rate_est64

速率估算器

定义:

struct gnet_stats_rate_est64 {
    __u64 bps;
    __u64 pps;
};

成员

bps

当前字节速率

pps

当前数据包速率

struct gnet_stats_queue

排队统计

定义:

struct gnet_stats_queue {
    __u32 qlen;
    __u32 backlog;
    __u32 drops;
    __u32 requeues;
    __u32 overlimits;
};

成员

qlen

队列长度

积压

队列的积压大小

丢弃

丢弃的数据包数

重新排队

重新排队的次数

超限

超过限制的入队次数

struct gnet_estimator

速率估算器配置

定义:

struct gnet_estimator {
    signed char     interval;
    unsigned char   ewma_log;
};

成员

间隔

采样周期

ewma_log

测量窗口权重的对数

int gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type, int xstats_type, spinlock_t *lock, struct gnet_dump *d, int padattr)

以兼容模式启动转储过程。

参数

struct sk_buff *skb

用于存放统计信息 TLV 的套接字缓冲区。

int type

顶层统计信息 TLV 的 TLV 类型。

int tc_stats_type

用于向后兼容的 struct tc_stats TLV 的 TLV 类型。

int xstats_type

用于向后兼容的 xstats TLV 的 TLV 类型。

spinlock_t *lock

统计信息锁。

struct gnet_dump *d

转储句柄。

int padattr

填充属性。

描述

初始化转储句柄,获取统计信息锁,并将一个空的 TLV 头部附加到套接字缓冲区,以便用作所有其他统计信息 TLV 的容器。

转储句柄被标记为处于向后兼容模式,告知所有 gnet_stats_copy_XXX() 函数填充 struct tc_stats 的本地副本。

成功时返回 0,如果套接字缓冲区中的空间不足,则返回 -1。

int gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock, struct gnet_dump *d, int padattr)

以兼容模式启动转储过程。

参数

struct sk_buff *skb

用于存放统计信息 TLV 的套接字缓冲区。

int type

顶层统计信息 TLV 的 TLV 类型。

spinlock_t *lock

统计信息锁。

struct gnet_dump *d

转储句柄。

int padattr

填充属性。

描述

初始化转储句柄,获取统计信息锁,并将一个空的 TLV 头部附加到套接字缓冲区,以便用作所有其他统计信息 TLV 的容器。

成功时返回 0,如果套接字缓冲区中的空间不足,则返回 -1。

int gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic_sync __percpu *cpu, struct gnet_stats_basic_sync *b, bool running)

将基本统计信息复制到统计信息 TLV 中。

参数

struct gnet_dump *d

转储句柄。

struct gnet_stats_basic_sync __percpu *cpu

复制每个 CPU 的统计信息。

struct gnet_stats_basic_sync *b

基本统计信息。

bool running

如果 b 表示正在运行的 qdisc,则为 true,因此 b 的内部值可能会在基本读取期间发生更改。仅当 cpu 为 NULL 时才使用。

上下文

任务;不得从 IRQ 或 BH 上下文运行。

描述

将基本统计信息附加到 gnet_stats_start_copy() 创建的顶层 TLV。

成功时返回 0,如果套接字缓冲区中的空间不足,则在释放统计信息锁后返回 -1。

int gnet_stats_copy_basic_hw(struct gnet_dump *d, struct gnet_stats_basic_sync __percpu *cpu, struct gnet_stats_basic_sync *b, bool running)

将基本硬件统计信息复制到统计信息 TLV 中。

参数

struct gnet_dump *d

转储句柄。

struct gnet_stats_basic_sync __percpu *cpu

复制每个 CPU 的统计信息。

struct gnet_stats_basic_sync *b

基本统计信息。

bool running

如果 b 表示正在运行的 qdisc,则为 true,因此 b 的内部值可能会在基本读取期间发生更改。仅当 cpu 为 NULL 时才使用。

上下文

任务;不得从 IRQ 或 BH 上下文运行。

描述

将基本统计信息附加到 gnet_stats_start_copy() 创建的顶层 TLV。

成功时返回 0,如果套接字缓冲区中的空间不足,则在释放统计信息锁后返回 -1。

int gnet_stats_copy_rate_est(struct gnet_dump *d, struct net_rate_estimator __rcu **rate_est)

将速率估计器统计信息复制到统计信息 TLV 中。

参数

struct gnet_dump *d

转储句柄。

struct net_rate_estimator __rcu **rate_est

速率估算器

描述

将速率估计器统计信息附加到 gnet_stats_start_copy() 创建的顶层 TLV。

成功时返回 0,如果套接字缓冲区中的空间不足,则在释放统计信息锁后返回 -1。

int gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue __percpu *cpu_q, struct gnet_stats_queue *q, __u32 qlen)

将队列统计信息复制到统计信息 TLV 中。

参数

struct gnet_dump *d

转储句柄。

struct gnet_stats_queue __percpu *cpu_q

每个 CPU 的队列统计信息。

struct gnet_stats_queue *q

队列统计信息。

__u32 qlen

队列长度统计信息。

描述

将队列统计信息附加到 gnet_stats_start_copy() 创建的顶层 TLV。如果每个 CPU 的队列统计信息可用,则使用它们。

成功时返回 0,如果套接字缓冲区中的空间不足,则在释放统计信息锁后返回 -1。

int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len)

将应用程序特定的统计信息复制到统计信息 TLV 中。

参数

struct gnet_dump *d

转储句柄。

void *st

应用程序特定的统计信息数据。

int len

数据的长度。

描述

将应用程序特定的统计信息附加到 gnet_stats_start_copy() 创建的顶层 TLV,并在转储句柄处于向后兼容模式时记住 XSTATS 的数据。

成功时返回 0,如果套接字缓冲区中的空间不足,则在释放统计信息锁后返回 -1。

int gnet_stats_finish_copy(struct gnet_dump *d)

完成转储过程。

参数

struct gnet_dump *d

转储句柄。

描述

更正顶层 TLV 的长度,以包括 gnet_stats_copy_XXX() 调用添加的所有 TLV。如果使用了 gnet_stats_start_copy_compat(),则添加向后兼容的 TLV 并释放统计信息锁。

成功时返回 0,如果套接字缓冲区中的空间不足,则在释放统计信息锁后返回 -1。

int gen_new_estimator(struct gnet_stats_basic_sync *bstats, struct gnet_stats_basic_sync __percpu *cpu_bstats, struct net_rate_estimator __rcu **rate_est, spinlock_t *lock, bool running, struct nlattr *opt)

创建一个新的速率估算器

参数

struct gnet_stats_basic_sync *bstats

基本统计信息。

struct gnet_stats_basic_sync __percpu *cpu_bstats

每个 CPU 的 bstats

struct net_rate_estimator __rcu **rate_est

速率估算器统计信息

spinlock_t *lock

用于统计和控制路径的锁

bool running

如果 bstats 表示正在运行的 qdisc,则为 true,因此 bstats 的内部值可能在基本读取期间发生变化。仅在 bstats_cpu 为 NULL 时使用

struct nlattr *opt

速率估算器配置 TLV

描述

创建一个新的速率估算器,使用 bstats 作为源,rate_est 作为目标。创建一个新的计时器,其间隔在配置 TLV 中指定。在每个间隔时,将从 bstats 读取最新的统计信息,并且在此时段内抓取统计信息锁后,估计的速率将存储在 rate_est 中。

成功时返回 0,或者返回负的错误代码。

void gen_kill_estimator(struct net_rate_estimator __rcu **rate_est)

移除速率估算器

参数

struct net_rate_estimator __rcu **rate_est

速率估算器

描述

移除速率估算器。

int gen_replace_estimator(struct gnet_stats_basic_sync *bstats, struct gnet_stats_basic_sync __percpu *cpu_bstats, struct net_rate_estimator __rcu **rate_est, spinlock_t *lock, bool running, struct nlattr *opt)

替换速率估算器配置

参数

struct gnet_stats_basic_sync *bstats

基本统计信息。

struct gnet_stats_basic_sync __percpu *cpu_bstats

每个 CPU 的 bstats

struct net_rate_estimator __rcu **rate_est

速率估算器统计信息

spinlock_t *lock

用于统计和控制路径的锁

bool running

如果 bstats 表示正在运行的 qdisc,则为 true,因此 bstats 的内部值可能在基本读取期间发生变化。仅在 cpu_bstats 为 NULL 时使用

struct nlattr *opt

速率估算器配置 TLV

描述

通过调用 gen_kill_estimator()gen_new_estimator() 来替换速率估算器的配置。

成功时返回 0,或者返回负的错误代码。

bool gen_estimator_active(struct net_rate_estimator __rcu **rate_est)

测试估算器当前是否正在使用

参数

struct net_rate_estimator __rcu **rate_est

速率估算器

描述

如果估算器处于活动状态,则返回 true,否则返回 false。

SUN RPC 子系统

__be32 *xdr_encode_opaque_fixed(__be32 *p, const void *ptr, unsigned int nbytes)

编码固定长度的不透明数据

参数

__be32 *p

指向 XDR 缓冲区中当前位置的指针。

const void *ptr

指向要编码的数据的指针 (或 NULL)

unsigned int nbytes

数据大小。

描述

将 ptr 处长度为 nbytes 的数据数组复制到位置 p 处的 XDR 缓冲区,然后通过使用零字节填充对齐到下一个 32 位边界(请参阅 RFC1832)。返回更新后的当前 XDR 缓冲区位置

注意

如果 ptr 为 NULL,则仅执行填充。

__be32 *xdr_encode_opaque(__be32 *p, const void *ptr, unsigned int nbytes)

编码可变长度的不透明数据

参数

__be32 *p

指向 XDR 缓冲区中当前位置的指针。

const void *ptr

指向要编码的数据的指针 (或 NULL)

unsigned int nbytes

数据大小。

描述

返回更新后的当前 XDR 缓冲区位置

void xdr_terminate_string(const struct xdr_buf *buf, const u32 len)

以“0”结尾位于 xdr_buf 中的字符串

参数

const struct xdr_buf *buf

字符串所在的 XDR 缓冲区

const u32 len

字符串的长度(以字节为单位)

void xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, struct page **pages, unsigned int base, unsigned int len)

为大型回复准备接收缓冲区

参数

struct xdr_buf *xdr

将放置回复的 xdr_buf

unsigned int offset

数据有效负载的预期起始偏移量(以字节为单位)

struct page **pages

struct page 指针的向量

unsigned int base

应开始接收的第一个页面中的偏移量(以字节为单位)

unsigned int len

上层数据有效负载的预期大小(以字节为单位)

void _copy_from_pages(char *p, struct page **pages, size_t pgbase, size_t len)

参数

char *p

指向目标的指针

struct page **pages

页面数组

size_t pgbase

源数据的偏移量

size_t len

长度

描述

从页面数组中复制数据到任意内存位置。假设复制是不重叠的。

unsigned int xdr_stream_pos(const struct xdr_stream *xdr)

返回 xdr_stream 起始位置的当前偏移量

参数

const struct xdr_stream *xdr

指向 xdr_stream 结构的指针

unsigned int xdr_page_pos(const struct xdr_stream *xdr)

返回 xdr 页起始位置的当前偏移量

参数

const struct xdr_stream *xdr

指向 xdr_stream 结构的指针

void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p, struct rpc_rqst *rqst)

初始化一个用于发送数据的 xdr_stream 结构。

参数

struct xdr_stream *xdr

指向 xdr_stream 结构的指针

struct xdr_buf *buf

指向用于编码数据的 XDR 缓冲区的指针

__be32 *p

XDR 缓冲区内的当前指针

struct rpc_rqst *rqst

指向用于调试的控制 rpc_rqst 的指针

注意

目前,RPC 客户端仅在 xdr_buf 的头部 kvec 中传递我们

暂存缓冲区的长度。以前,这意味着我们需要在编码数据后调用 xdr_adjust_iovec()。使用新方案,xdr_stream 管理缓冲区长度的详细信息,并负责为我们调整 kvec 长度。

void xdr_init_encode_pages(struct xdr_stream *xdr, struct xdr_buf *buf, struct page **pages, struct rpc_rqst *rqst)

初始化一个用于编码到页面的 xdr_stream

参数

struct xdr_stream *xdr

指向 xdr_stream 结构的指针

struct xdr_buf *buf

指向用于编码数据的 XDR 缓冲区的指针

struct page **pages

要解码到的页面列表

struct rpc_rqst *rqst

指向用于调试的控制 rpc_rqst 的指针

void __xdr_commit_encode(struct xdr_stream *xdr)

确保所有数据都写入缓冲区

参数

struct xdr_stream *xdr

指向 xdr_stream 的指针

描述

我们通过给调用者一个临时写入位置来处理跨页面边界的编码,然后将数据复制到位;xdr_commit_encode 执行此复制操作。

通常,调用者不需要直接调用此函数,因为下面的 xdr_reserve_space 将会这样做。但是,在编码结束时或在任何可能读取 xdr_buf 数据的其他时间,可能需要显式调用。

__be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes)

预留用于发送的缓冲区空间

参数

struct xdr_stream *xdr

指向 xdr_stream 的指针

size_t nbytes

要预留的字节数

描述

检查我们是否有足够的缓冲区空间来编码额外的 'nbytes' 字节数据。 如果是,则更新总 xdr_buf 长度,并调整当前 kvec 的长度。

int xdr_reserve_space_vec(struct xdr_stream *xdr, size_t nbytes)

预留大量缓冲区空间用于发送

参数

struct xdr_stream *xdr

指向 xdr_stream 的指针

size_t nbytes

要预留的字节数

描述

传递给 xdr_reserve_space() 的 size 参数是根据当前页面中剩余的字节数确定的,以避免在调用 xdr_commit_encode() 时使 iov_base 指针无效。

返回值

0:成功 -EMSGSIZExdr 中没有足够的可用空间

void xdr_truncate_encode(struct xdr_stream *xdr, size_t len)

截断编码缓冲区

参数

struct xdr_stream *xdr

指向 xdr_stream 的指针

size_t len

缓冲区的新长度

描述

截断 xdr 流,使 xdr->buf->len == len,并且 xdr->p 指向缓冲区起始位置的偏移量 len,并且头部、尾部和页面长度会进行相应调整。

如果这意味着将 xdr->p 移动到不同的缓冲区,我们假设结束指针应设置为当前页面的末尾,但头部缓冲区除外,在这种情况下,我们假设头部缓冲区的当前长度表示可用缓冲区的末尾。

除非在尾部中从一个位置截断到另一个位置的简单情况,否则在已经有内联页面缓存页面的缓冲区(如零拷贝服务器读取回复中)上使用此方法是安全的。

void xdr_truncate_decode(struct xdr_stream *xdr, size_t len)

截断解码流

参数

struct xdr_stream *xdr

指向 xdr_stream 结构的指针

size_t len

要删除的字节数

int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen)

减少可用缓冲区空间

参数

struct xdr_stream *xdr

指向 xdr_stream 的指针

int newbuflen

可用最大字节数的新值

描述

调整我们对缓冲区中可用空间的理解。如果我们已经在缓冲区中使用了过多的空间,则返回 -1。如果可用空间已经小于 newbuflen,则返回 0 并且不执行任何操作。否则,将 xdr->buf->buflen 调整为 newbuflen,并确保 xdr->end 设置为距离缓冲区起始位置最多偏移量 newbuflen 的位置。

void xdr_write_pages(struct xdr_stream *xdr, struct page **pages, unsigned int base, unsigned int len)

将页列表插入到 XDR 缓冲区以进行发送

参数

struct xdr_stream *xdr

指向 xdr_stream 的指针

struct page **pages

要插入的页数组

unsigned int base

pages 中第一个数据字节的起始偏移量

unsigned int len

要插入的 pages 中的数据字节数

描述

添加 pages 后,将实例化指向头部缓冲区末尾的尾部 iovec,并设置流以将后续项编码到尾部。

void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p, struct rpc_rqst *rqst)

初始化用于解码数据的 xdr_stream。

参数

struct xdr_stream *xdr

指向 xdr_stream 结构的指针

struct xdr_buf *buf

指向从中解码数据的 XDR 缓冲区的指针

__be32 *p

XDR 缓冲区内的当前指针

struct rpc_rqst *rqst

指向用于调试的控制 rpc_rqst 的指针

void xdr_init_decode_pages(struct xdr_stream *xdr, struct xdr_buf *buf, struct page **pages, unsigned int len)

初始化用于解码到页面的 xdr_stream

参数

struct xdr_stream *xdr

指向 xdr_stream 结构的指针

struct xdr_buf *buf

指向从中解码数据的 XDR 缓冲区的指针

struct page **pages

要解码到的页面列表

unsigned int len

页面中缓冲区的长度(以字节为单位)

void xdr_finish_decode(struct xdr_stream *xdr)

解码数据后清理 xdr_stream。

参数

struct xdr_stream *xdr

指向 xdr_stream 结构的指针

__be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes)

检索要解码的 XDR 数据

参数

struct xdr_stream *xdr

指向 xdr_stream 结构的指针

size_t nbytes

要解码的数据字节数

描述

检查输入缓冲区是否足够长,以便我们能够从当前位置开始解码更多 ‘nbytes’ 字节的数据。如果足够,则返回当前指针,然后更新当前指针位置。

unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len)

将基于页面的 XDR 数据对齐到当前指针位置

参数

struct xdr_stream *xdr

指向 xdr_stream 结构的指针

unsigned int len

页面数据的字节数

描述

将超出当前指针位置的数据从 XDR head[] 缓冲区移动到页列表。任何超出当前位置 + len 字节的数据都将移动到 XDR tail[]。然后,xdr_stream 当前位置将前进到超出该数据,以与尾部的下一个 XDR 对象对齐。

返回页面中现在包含的 XDR 编码字节数

void xdr_set_pagelen(struct xdr_stream *xdr, unsigned int len)

设置 XDR 页面的长度

参数

struct xdr_stream *xdr

指向 xdr_stream 结构的指针

unsigned int len

XDR 页面数据的新长度

描述

通过将 pagelen 设置为 len 字节来增加或缩小 xdr 页面的长度。缩小长度时,任何额外数据都将移动到 buf->tail,而增大长度时,超出当前指针的任何数据都将移动到尾部。

如果操作成功,则返回 True,否则返回 False。

void xdr_enter_page(struct xdr_stream *xdr, unsigned int len)

从 XDR 页面解码数据

参数

struct xdr_stream *xdr

指向 xdr_stream 结构的指针

unsigned int len

页面数据的字节数

描述

将超出当前指针位置的数据从 XDR head[] 缓冲区移动到页列表。任何超出当前位置 + “len” 字节的数据都将移动到 XDR tail[]。然后,将当前指针重新定位到第一个 XDR 页面的开头。

int xdr_buf_subsegment(const struct xdr_buf *buf, struct xdr_buf *subbuf, unsigned int base, unsigned int len)

将 subbuf 设置为 buf 的一部分

参数

const struct xdr_buf *buf

xdr 缓冲区

struct xdr_buf *subbuf

结果缓冲区

unsigned int base

以字节为单位的范围起始

unsigned int len

以字节为单位的范围长度

描述

subbuf 设置为表示从偏移量 base 开始的长度为 lenbuf 部分的 xdr 缓冲区。

bufsubbuf 可以是指向同一 struct xdr_buf 的指针。

如果 base 或长度超出范围,则返回 -1。

bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf, unsigned int nbytes)

subbuf 设置为 xdr 的一部分

参数

struct xdr_stream *xdr

为解码设置的 xdr_stream

struct xdr_buf *subbuf

结果缓冲区

unsigned int nbytes

要提取的 xdr 的长度(以字节为单位)

描述

设置 subbuf 以表示 xdr 的一部分。该部分从 xdr 中的当前偏移量开始,并延伸 nbytes 的长度。如果成功,xdr 将前进到该部分后面的下一个 XDR 数据项。

返回值

true: 已初始化 subbuf,并且 xdr 已前进。false: 发生了边界错误

unsigned int xdr_stream_move_subsegment(struct xdr_stream *xdr, unsigned int offset, unsigned int target, unsigned int length)

将流的一部分移动到另一个位置

参数

struct xdr_stream *xdr

源 xdr_stream

unsigned int offset

该段的源偏移量

unsigned int target

该段的目标偏移量

unsigned int length

要移动的字节数

描述

将 xdr_stream 中的 length 字节从 offset 移动到 target,覆盖其空间中的任何内容。返回段中的字节数。

unsigned int xdr_stream_zero(struct xdr_stream *xdr, unsigned int offset, unsigned int length)

将 xdr_stream 的一部分清零

参数

struct xdr_stream *xdr

要清零的 xdr_stream

unsigned int offset

流中的起始点

unsigned int length

要清零的字节数

void xdr_buf_trim(struct xdr_buf *buf, unsigned int len)

从“buf”末尾最多删除“len”个字节

参数

struct xdr_buf *buf

要修剪的 buf

unsigned int len

要减少“buf”的字节数

描述

通过修复长度,按给定的字节数修剪 xdr_buf。请注意,如果 xdr_buf 太小,或者(例如)它都在头部并且解析器已经读取得太远,我们可能会修剪得少于该数量。

ssize_t xdr_stream_decode_opaque(struct xdr_stream *xdr, void *ptr, size_t size)

解码可变长度不透明数据

参数

struct xdr_stream *xdr

指向 xdr_stream 的指针

void *ptr

存储不透明数据的位置

size_t size

存储缓冲区 ptr 的大小

描述

返回值

成功时,返回存储在 *ptr 中的对象的大小,XDR 缓冲区溢出时返回 -EBADMSG,存储缓冲区 ptr 溢出时返回 -EMSGSIZE

ssize_t xdr_stream_decode_opaque_dup(struct xdr_stream *xdr, void **ptr, size_t maxlen, gfp_t gfp_flags)

解码并复制可变长度不透明数据

参数

struct xdr_stream *xdr

指向 xdr_stream 的指针

void **ptr

存储指向不透明数据指针的位置

size_t maxlen

最大可接受对象大小

gfp_t gfp_flags

要使用的 GFP 掩码

描述

返回值

成功时,返回存储在 *ptr 中的对象的大小,XDR 缓冲区溢出时返回 -EBADMSG,如果对象的大小超出 maxlen 则返回 -EMSGSIZE,内存分配失败时返回 -ENOMEM

ssize_t xdr_stream_decode_string(struct xdr_stream *xdr, char *str, size_t size)

解码可变长度字符串

参数

struct xdr_stream *xdr

指向 xdr_stream 的指针

char *str

存储字符串的位置

size_t size

存储缓冲区 str 的大小

描述

返回值

成功时,返回存储在 *str 中的以 NULL 结尾的字符串的长度,XDR 缓冲区溢出时返回 -EBADMSG,存储缓冲区 str 溢出时返回 -EMSGSIZE

ssize_t xdr_stream_decode_string_dup(struct xdr_stream *xdr, char **str, size_t maxlen, gfp_t gfp_flags)

解码并复制可变长度字符串

参数

struct xdr_stream *xdr

指向 xdr_stream 的指针

char **str

存储指向字符串的指针的位置

size_t maxlen

最大可接受字符串长度

gfp_t gfp_flags

要使用的 GFP 掩码

描述

返回值

成功时,返回存储在 *ptr 中的以 NULL 结尾的字符串的长度,XDR 缓冲区溢出时返回 -EBADMSG,如果字符串的大小超出 maxlen 则返回 -EMSGSIZE,内存分配失败时返回 -ENOMEM

ssize_t xdr_stream_decode_opaque_auth(struct xdr_stream *xdr, u32 *flavor, void **body, unsigned int *body_len)

解码 struct opaque_auth (RFC5531 S8.2)

参数

struct xdr_stream *xdr

指向 xdr_stream 的指针

u32 *flavor

存储解码后的 flavor 的位置

void **body

存储解码后的 body 的位置

unsigned int *body_len

存储解码后的 body 长度的位置

描述

返回值

成功时,返回消耗的缓冲区字节数,XDR 缓冲区溢出时返回 -EBADMSG,如果 body 字段的解码大小超过 400 个八位字节,则返回 -EMSGSIZE

ssize_t xdr_stream_encode_opaque_auth(struct xdr_stream *xdr, u32 flavor, void *body, unsigned int body_len)

编码 struct opaque_auth (RFC5531 S8.2)

参数

struct xdr_stream *xdr

指向 xdr_stream 的指针

u32 flavor

要编码的验证器 flavor

void *body

要编码的 body 内容

unsigned int body_len

要编码的 body 长度

描述

返回值

成功时,返回消耗的 XDR 缓冲区长度(以字节为单位),XDR 缓冲区溢出时返回 -EBADMSG,如果 body 的大小超过 400 个八位字节,则返回 -EMSGSIZE

int svc_reg_xprt_class(struct svc_xprt_class *xcl)

注册服务器端 RPC 传输类

参数

struct svc_xprt_class *xcl

要注册的新传输类

描述

成功时返回零;否则返回一个负的 errno。

void svc_unreg_xprt_class(struct svc_xprt_class *xcl)

注销服务器端 RPC 传输类

参数

struct svc_xprt_class *xcl

要注销的传输类

void svc_xprt_deferred_close(struct svc_xprt *xprt)

关闭传输

参数

struct svc_xprt *xprt

传输实例

描述

用于需要在将传输关闭工作推迟到 nfsd 线程的上下文中。

void svc_xprt_received(struct svc_xprt *xprt)

启动下一个接收器线程

参数

struct svc_xprt *xprt

控制传输

描述

调用者必须持有 XPT_BUSY 位,并且之后不得触及传输数据。

注意

只有当读取尝试找不到(或不足的)数据时,XPT_DATA 才会清除。

int svc_xprt_create_from_sa(struct svc_serv *serv, const char *xprt_name, struct net *net, struct sockaddr *sap, int flags, const struct cred *cred)

从套接字地址向 serv 添加新的监听器

参数

struct svc_serv *serv

目标 RPC 服务

const char *xprt_name

传输类名称

struct net *net

网络命名空间

struct sockaddr *sap

套接字地址指针

int flags

SVC_SOCK 标志

const struct cred *cred

绑定到此传输的凭据

描述

成功时返回本地 xprt 端口,失败时返回 -EPROTONOSUPPORT

int svc_xprt_create(struct svc_serv *serv, const char *xprt_name, struct net *net, const int family, const unsigned short port, int flags, const struct cred *cred)

serv 添加新的监听器

参数

struct svc_serv *serv

目标 RPC 服务

const char *xprt_name

传输类名称

struct net *net

网络命名空间

const int family

网络地址族

const unsigned short port

监听端口

int flags

SVC_SOCK 标志

const struct cred *cred

绑定到此传输的凭据

描述

成功时返回本地 xprt 端口,失败时返回 -EPROTONOSUPPORT

char *svc_print_addr(struct svc_rqst *rqstp, char *buf, size_t len)

格式化 rq_addr 字段以进行打印

参数

struct svc_rqst *rqstp

包含要打印的地址的 svc_rqst 结构

char *buf

格式化地址的目标缓冲区

size_t len

目标缓冲区的长度

void svc_xprt_enqueue(struct svc_xprt *xprt)

在空闲 nfsd 线程上排队传输

参数

struct svc_xprt *xprt

具有待处理数据的传输

void svc_reserve(struct svc_rqst *rqstp, int space)

更改为请求保留的回复空间。

参数

struct svc_rqst *rqstp

有问题的请求

int space

要保留的新最大空间

描述

每个请求都会在传输的输出队列上保留一些空间,以确保回复适合。此函数将保留空间减少为已使用的空间量,加上 space

void svc_wake_up(struct svc_serv *serv)

唤醒服务线程以进行非传输工作

参数

struct svc_serv *serv

RPC 服务

描述

某些 svc_serv 会有一些偶尔需要做的工作,即使没有 xprt 等待被服务。此函数用于“启动”这些服务之一中的任务,以便它可以唤醒并执行该工作。请注意,我们只关心池 0,因为我们不需要为此唤醒多个线程。

void svc_recv(struct svc_rqst *rqstp)

接收并处理任何传输上的下一个请求

参数

struct svc_rqst *rqstp

空闲 RPC 服务线程

描述

这段代码经过精心组织,不会触及共享 svc_serv 结构中的任何缓存行,只会触及本地 svc_pool 中的缓存行。

void svc_xprt_close(struct svc_xprt *xprt)

关闭客户端连接

参数

struct svc_xprt *xprt

要断开连接的传输

void svc_xprt_destroy_all(struct svc_serv *serv, struct net *net)

销毁与 serv 关联的传输

参数

struct svc_serv *serv

要关闭的 RPC 服务

struct net *net

目标网络命名空间

描述

服务器线程可能仍在运行(特别是在服务仍在其他网络命名空间中运行的情况下)。

因此,我们以与在运行的服务器上相同的方式关闭套接字,通过设置 XPT_CLOSE、排队,并让一个线程选取它来执行关闭操作。如果不存在其他此类线程,则运行线程 svc_clean_up_xprts() 会执行服务器主事件循环的简单版本,如果存在其他线程,我们可能需要等待一段时间,然后再检查它们是否完成。

struct svc_xprt *svc_find_listener(struct svc_serv *serv, const char *xcl_name, struct net *net, const struct sockaddr *sa)

查找 RPC 传输实例

参数

struct svc_serv *serv

要搜索的 svc_serv 指针

const char *xcl_name

包含传输类名称的 C 字符串

struct net *net

所有者 net 指针

const struct sockaddr *sa

包含地址的 sockaddr

描述

返回传输实例指针,该指针指向接受来自指定传输类的连接/对等流量,并与 sockaddr 匹配的端点。

struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, struct net *net, const sa_family_t af, const unsigned short port)

查找 RPC 传输实例

参数

struct svc_serv *serv

要搜索的 svc_serv 指针

const char *xcl_name

包含传输类名称的 C 字符串

struct net *net

所有者 net 指针

const sa_family_t af

传输的本地地址的地址族

const unsigned short port

传输的 IP 端口号

描述

返回传输实例指针,该指针指向接受来自指定传输类、地址族和端口的连接/对等流量的端点。

为地址族或端口指定 0 实际上是通配符,将导致匹配服务列表中第一个具有匹配类名称的传输。

int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen)

格式化一个包含传输名称列表的缓冲区

参数

struct svc_serv *serv

指向 RPC 服务的指针

char *buf

指向要填充的缓冲区的指针

const int buflen

要填充的缓冲区的长度

描述

用包含传输名称列表的字符串填充 buf,每个名称都以 ‘n’ 结尾。

成功时返回填充的字符串的正长度;否则,如果发生错误,则返回负 errno 值。

int xprt_register_transport(struct xprt_class *transport)

注册传输实现

参数

struct xprt_class *transport

要注册的传输

描述

如果传输实现作为内核模块加载,则它可以调用此接口以使 RPC 客户端知道它。

返回

0: 传输注册成功 -EEXIST: 传输已注册 -EINVAL: 传输模块正在卸载

int xprt_unregister_transport(struct xprt_class *transport)

注销传输实现

参数

struct xprt_class *transport

要注销的传输

返回

0: 传输注销成功 -ENOENT: 传输从未注册

int xprt_find_transport_ident(const char *netid)

将 netid 转换为传输标识符

参数

const char *netid

要加载的传输

返回

> 0: 传输标识符 -ENOENT: 传输模块不可用

int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task)

序列化对传输的写入访问

参数

struct rpc_xprt *xprt

指向目标传输的指针

struct rpc_task *task

请求访问传输的任务

描述

这可以防止混合单独请求的有效负载,并防止传输连接与写入冲突。不提供拥塞控制。

void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)

允许其他请求使用传输

参数

struct rpc_xprt *xprt

传输,其中其他任务可能在等待

struct rpc_task *task

释放对传输访问的任务

描述

请注意,“task”可以为 NULL。不提供拥塞控制。

void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task)

允许其他请求使用传输

参数

struct rpc_xprt *xprt

传输,其中其他任务可能在等待

struct rpc_task *task

释放对传输访问的任务

描述

请注意,“task”可以为 NULL。如果传输的拥塞窗口允许,则会唤醒另一个任务以使用该传输。

bool xprt_request_get_cong(struct rpc_xprt *xprt, struct rpc_rqst *req)

请求拥塞控制信用

参数

struct rpc_xprt *xprt

指向传输的指针

struct rpc_rqst *req

指向 RPC 请求的指针

描述

对于需要拥塞控制的传输很有用。

void xprt_release_rqst_cong(struct rpc_task *task)

请求完成时的内务处理

参数

struct rpc_task *task

最近完成的 RPC 请求

描述

对于需要拥塞控制的传输很有用。

void xprt_adjust_cwnd(struct rpc_xprt *xprt, struct rpc_task *task, int result)

调整传输拥塞窗口

参数

struct rpc_xprt *xprt

指向 xprt 的指针

struct rpc_task *task

最近完成的 RPC 请求,用于调整窗口

int result

完成的 RPC 请求的结果代码

描述

传输代码使用 44BSD 中实现的平滑版本的拥塞避免来维护对未完成的 RPC 请求的最大数量的估计。 这基本上是 Van Jacobson 拥塞算法:如果发生重传,则拥塞窗口减半; 否则,当满足以下条件时,它会增加 1/cwnd:

  • 收到回复且

  • 有大量的请求未完成且

  • 拥塞窗口最近未更新。

void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status)

唤醒传输的待处理队列上的所有任务

参数

struct rpc_xprt *xprt

具有等待任务的传输

int status

在唤醒每个任务之前要在其中植入的结果代码

void xprt_wait_for_buffer_space(struct rpc_xprt *xprt)

等待传输输出缓冲区清空。

参数

struct rpc_xprt *xprt

传输

描述

请注意,我们仅在 RPC_IS_SOFT() 的情况下设置定时器,因为通常我们不希望由于不完整的 RPC 调用传输而强制断开套接字连接。

bool xprt_write_space(struct rpc_xprt *xprt)

唤醒等待传输输出缓冲区空间的任务。

参数

struct rpc_xprt *xprt

具有等待任务的传输

描述

可以在软中断上下文中调用,因此 xprt_write_space 永远不会休眠。

void xprt_disconnect_done(struct rpc_xprt *xprt)

将传输标记为已断开连接。

参数

struct rpc_xprt *xprt

要标记为断开连接的传输。

void xprt_force_disconnect(struct rpc_xprt *xprt)

强制传输断开连接。

参数

struct rpc_xprt *xprt

要断开连接的传输

unsigned long xprt_reconnect_delay(const struct rpc_xprt *xprt)

计算计划连接之前的等待时间。

参数

const struct rpc_xprt *xprt

传输实例

void xprt_reconnect_backoff(struct rpc_xprt *xprt, unsigned long init_to)

计算新的重新建立超时。

参数

struct rpc_xprt *xprt

传输实例

unsigned long init_to

初始重新建立超时。

struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid)

查找与 XID 对应的 RPC 请求。

参数

struct rpc_xprt *xprt

在其上传输原始请求的传输。

__be32 xid

传入回复的 RPC XID。

描述

调用者持有 xprt->queue_lock。

void xprt_pin_rqst(struct rpc_rqst *req)

在传输接收列表中固定请求。

参数

struct rpc_rqst *req

要固定的请求。

描述

调用者必须确保这与调用 xprt_lookup_rqst() 是原子操作,因此应该持有 xprt->queue_lock。

void xprt_unpin_rqst(struct rpc_rqst *req)

取消固定传输接收列表中的请求。

参数

struct rpc_rqst *req

要固定的请求。

描述

调用者应持有 xprt->queue_lock。

void xprt_update_rtt(struct rpc_task *task)

更新 RPC RTT 统计信息。

参数

struct rpc_task *task

最近完成的 RPC 请求

描述

调用者持有 xprt->queue_lock。

void xprt_complete_rqst(struct rpc_task *task, int copied)

当回复处理完成时调用。

参数

struct rpc_task *task

最近完成的 RPC 请求

int copied

从传输接收的实际字节数。

描述

调用者持有 xprt->queue_lock。

void xprt_wait_for_reply_request_def(struct rpc_task *task)

等待回复。

参数

struct rpc_task *task

指向 rpc_task 的指针。

描述

根据传输的默认超时参数设置请求的重传超时。由不根据往返时间估计调整重传超时并将任务置于挂起队列的传输使用。

void xprt_wait_for_reply_request_rtt(struct rpc_task *task)

使用 RTT 估算器等待回复。

参数

struct rpc_task *task

指向 rpc_task 的指针。

描述

使用 RTT 估算器设置请求的重传超时,并将任务置于挂起队列中。

struct rpc_xprt *xprt_get(struct rpc_xprt *xprt)

返回对 RPC 传输的引用。

参数

struct rpc_xprt *xprt

指向传输的指针。

void xprt_put(struct rpc_xprt *xprt)

释放对 RPC 传输的引用。

参数

struct rpc_xprt *xprt

指向传输的指针。

void rpc_wake_up(struct rpc_wait_queue *queue)

唤醒所有 rpc_tasks。

参数

struct rpc_wait_queue *queue

任务正在休眠的 rpc_wait_queue。

描述

获取 queue->lock。

void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)

唤醒所有 rpc_tasks 并设置其状态值。

参数

struct rpc_wait_queue *queue

任务正在休眠的 rpc_wait_queue。

int status

要设置的状态值。

描述

获取 queue->lock。

int rpc_malloc(struct rpc_task *task)

分配 RPC 缓冲区资源。

参数

struct rpc_task *task

RPC 任务。

描述

分配单个内存区域,该区域在 RPC 调用和此任务正在使用的 RPC 回复之间分割。当此 RPC 被释放时,内存通过调用 rpc_free 释放。

为了防止 rpciod 挂起,此分配器永远不会休眠,如果无法立即处理请求,则返回 -ENOMEM 并禁止警告。调用者可以安排以对 rpciod 安全的方式休眠。

大多数请求都是“小的”(小于 2KiB),并且可以从内存池中处理,从而确保 NFS 读取和写入始终可以进行,并且这些缓冲区具有良好的引用局部性。

void rpc_free(struct rpc_task *task)

释放通过 rpc_malloc 分配的 RPC 缓冲区资源。

参数

struct rpc_task *task

RPC 任务。

int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)

校验和并复制数据。

参数

struct xdr_buf *xdr

目标 XDR 缓冲区。

struct sk_buff *skb

源 skb

描述

我们已经设置好,这样我们就可以并行执行 UDP 数据包的校验和以及复制到 RPC 客户端 iovec 中。-DaveM

struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt)

分配一个 rpc_iostats 结构体

参数

struct rpc_clnt *clnt

RPC 程序、版本和 xprt

void rpc_free_iostats(struct rpc_iostats *stats)

释放一个 rpc_iostats 结构体

参数

struct rpc_iostats *stats

要释放的 rpc_iostats 结构体

void rpc_count_iostats_metrics(const struct rpc_task *task, struct rpc_iostats *op_metrics)

统计每个任务的统计信息

参数

const struct rpc_task *task

已完成的 rpc_task

struct rpc_iostats *op_metrics

用于操作的统计结构,将从 task 累积统计信息

void rpc_count_iostats(const struct rpc_task *task, struct rpc_iostats *stats)

统计每个任务的统计信息

参数

const struct rpc_task *task

已完成的 rpc_task

struct rpc_iostats *stats

统计结构数组

描述

使用 task 中的 statidx

int rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg)

将一个上行调用消息排队到用户空间

参数

struct rpc_pipe *pipe

要在其上排队给定消息的上行调用管道

struct rpc_pipe_msg *msg

要排队的消息

描述

使用 rpc_mkpipe() 创建的 inode 调用此函数来排队一个上行调用。然后,用户空间进程可以通过对这个 inode 的打开文件执行读取操作来读取上行调用。调用者需要正确初始化 msg 的字段(除了 msg->list)。

struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name, void *private, struct rpc_pipe *pipe)

为内核<->用户空间通信创建一个 rpc_pipefs 文件

参数

struct dentry *parent

要创建新的“管道”的目录的 dentry

const char *name

管道的名称

void *private

与管道关联的私有数据,供调用者使用

struct rpc_pipe *pipe

rpc_pipe 包含输入参数

描述

通过调用 rpc_queue_upcall() 使数据可供用户空间读取。实际的读取将导致调用 ops->upcall,该函数将使用文件指针、消息和要复制到的用户空间缓冲区进行调用。

写入可以随时发生,而不必是对上行调用的响应。它们将导致调用 msg->downcall

此处传递的 private 参数将通过 RPC_I(file_inode(file))->private 从文件指针提供给所有这些方法。

删除一个管道

参数

struct dentry *dentry

管道的 dentry,由 rpc_mkpipe 返回

描述

在此调用之后,查找将不再找到管道,任何尝试使用管道的预先存在的打开来进行读取或写入的操作都将返回 -EPIPE。

void rpc_init_pipe_dir_head(struct rpc_pipe_dir_head *pdh)

初始化一个 struct rpc_pipe_dir_head

参数

struct rpc_pipe_dir_head *pdh

指向 struct rpc_pipe_dir_head 的指针

void rpc_init_pipe_dir_object(struct rpc_pipe_dir_object *pdo, const struct rpc_pipe_dir_object_ops *pdo_ops, void *pdo_data)

初始化一个 struct rpc_pipe_dir_object

参数

struct rpc_pipe_dir_object *pdo

指向 struct rpc_pipe_dir_object 的指针

const struct rpc_pipe_dir_object_ops *pdo_ops

指向 const struct rpc_pipe_dir_object_ops 的指针

void *pdo_data

指向调用者定义的数据的指针

int rpc_add_pipe_dir_object(struct net *net, struct rpc_pipe_dir_head *pdh, struct rpc_pipe_dir_object *pdo)

将 rpc_pipe_dir_object 与目录关联

参数

struct net *net

指向 struct net 的指针

struct rpc_pipe_dir_head *pdh

指向 struct rpc_pipe_dir_head 的指针

struct rpc_pipe_dir_object *pdo

指向 struct rpc_pipe_dir_object 的指针

void rpc_remove_pipe_dir_object(struct net *net, struct rpc_pipe_dir_head *pdh, struct rpc_pipe_dir_object *pdo)

从目录中移除 rpc_pipe_dir_object

参数

struct net *net

指向 struct net 的指针

struct rpc_pipe_dir_head *pdh

指向 struct rpc_pipe_dir_head 的指针

struct rpc_pipe_dir_object *pdo

指向 struct rpc_pipe_dir_object 的指针

struct rpc_pipe_dir_object *rpc_find_or_alloc_pipe_dir_object(struct net *net, struct rpc_pipe_dir_head *pdh, int (*match)(struct rpc_pipe_dir_object*, void*), struct rpc_pipe_dir_object *(*alloc)(void*), void *data)

参数

struct net *net

指向 struct net 的指针

struct rpc_pipe_dir_head *pdh

指向 struct rpc_pipe_dir_head 的指针

int (*match)(struct rpc_pipe_dir_object *, void *)

将 struct rpc_pipe_dir_object 与 data 进行匹配

struct rpc_pipe_dir_object *(*alloc)(void *)

分配一个新的 struct rpc_pipe_dir_object

void *data

用户为 match() 和 alloc() 定义的数据

void rpcb_getport_async(struct rpc_task *task)

获取给定主机上给定 RPC 服务的端口

参数

struct rpc_task *task

正在等待端口映射器请求的任务

描述

这个函数可以为正在进行的 RPC 请求调用,并且可以在异步 (rpciod) 上下文中使用。

struct rpc_clnt *rpc_create(struct rpc_create_args *args)

通过一次调用创建 RPC 客户端和传输

参数

struct rpc_create_args *args

rpc_clnt 创建参数结构

描述

创建并初始化 RPC 传输和 RPC 客户端。

它可以 ping 服务器以确定服务器是否启动,并查看它是否支持此程序和版本。RPC_CLNT_CREATE_NOPING 会禁用此行为,以便异步任务也可以使用 rpc_create。

struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt)

克隆 RPC 客户端结构

参数

struct rpc_clnt *clnt

复制其参数的 RPC 客户端

描述

返回新的 RPC 客户端或 ERR_PTR。

struct rpc_clnt *rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor)

克隆 RPC 客户端结构并设置其身份验证

参数

struct rpc_clnt *clnt

复制其参数的 RPC 客户端

rpc_authflavor_t flavor

新客户端的安全类型

描述

返回新的 RPC 客户端或 ERR_PTR。

int rpc_switch_client_transport(struct rpc_clnt *clnt, struct xprt_create *args, const struct rpc_timeout *timeout)

动态切换 RPC 传输

参数

struct rpc_clnt *clnt

指向 struct rpc_clnt 的指针

struct xprt_create *args

指向新传输参数的指针

const struct rpc_timeout *timeout

指向新超时参数的指针

描述

此函数允许调用者将 rpc_clnt 结构“clnt”的 RPC 传输切换为允许其连接到镜像的 NFS 服务器等。它假定调用者已通过使用某种形式的锁定来确保没有活动的 RPC 任务。

如果“clnt”现在正在使用新的 xprt,则返回零。否则,返回负的 errno,“clnt”继续使用旧的 xprt。

int rpc_clnt_iterate_for_each_xprt(struct rpc_clnt *clnt, int (*fn)(struct rpc_clnt*, struct rpc_xprt*, void*), void *data)

将函数应用于所有传输

参数

struct rpc_clnt *clnt

指向客户端的指针

int (*fn)(struct rpc_clnt *, struct rpc_xprt *, void *)

要应用的函数

void *data

指向函数数据的 void 指针

描述

迭代当前附加到客户端的 RPC 传输列表,并应用函数 fn(clnt, xprt, data)。

如果发生错误,迭代将停止,并且函数返回错误值。

unsigned long rpc_cancel_tasks(struct rpc_clnt *clnt, int error, bool (*fnmatch)(const struct rpc_task*, const void*), const void *data)

尝试取消一组 RPC 任务

参数

struct rpc_clnt *clnt

指向 RPC 客户端的指针

int error

要设置的 RPC 任务错误值

bool (*fnmatch)(const struct rpc_task *, const void *)

指向选择器函数的指针

const void *data

用户数据

描述

使用 fnmatch 定义一组要取消的 RPC 任务。参数 error 必须为负错误值。

struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, const struct rpc_program *program, u32 vers)

将新的 RPC 程序绑定到现有客户端

参数

struct rpc_clnt *old

旧的 rpc_client

const struct rpc_program *program

要设置的 RPC 程序

u32 vers

RPC 程序版本

描述

克隆 RPC 客户端并设置新的 RPC 程序。这主要用于使不同的 RPC 程序共享相同的传输。Sun NFSv2/v3 ACL 协议可以做到这一点。

struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data)

分配新的 RPC 任务,然后针对它运行 rpc_execute

参数

const struct rpc_task_setup *task_setup_data

指向任务初始化数据的指针

int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags)

执行同步 RPC 调用

参数

struct rpc_clnt *clnt

指向 RPC 客户端的指针

const struct rpc_message *msg

RPC 调用参数

int flags

RPC 调用标志

int rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags, const struct rpc_call_ops *tk_ops, void *data)

执行异步 RPC 调用

参数

struct rpc_clnt *clnt

指向 RPC 客户端的指针

const struct rpc_message *msg

RPC 调用参数

int flags

RPC 调用标志

const struct rpc_call_ops *tk_ops

RPC 调用操作

void *data

用户调用数据

void rpc_prepare_reply_pages(struct rpc_rqst *req, struct page **pages, unsigned int base, unsigned int len, unsigned int hdrsize)

准备接收页面中的回复数据负载

参数

struct rpc_rqst *req

要准备的 RPC 请求

struct page **pages

struct page 指针的向量

unsigned int base

应开始接收的第一个页面中的偏移量(以字节为单位)

unsigned int len

上层数据有效负载的预期大小(以字节为单位)

unsigned int hdrsize

上层回复标头的预期大小,以 XDR 字为单位

size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize)

从 clnt 的 xprt 中提取远程对等地址

参数

struct rpc_clnt *clnt

RPC 客户端结构

struct sockaddr *buf

目标缓冲区

size_t bufsize

目标缓冲区的长度

描述

返回存储地址中实际的字节数。

const char *rpc_peeraddr2str(struct rpc_clnt *clnt, enum rpc_display_format_t format)

以可打印格式返回远程对等地址

参数

struct rpc_clnt *clnt

RPC 客户端结构

enum rpc_display_format_t format

地址格式

描述

注意:返回的指针引用的内存的生命周期与 rpc_xprt 本身相同。只要调用者使用此指针,它就必须保持 RCU 读取锁。

int rpc_localaddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t buflen)

为 RPC 客户端发现本地端点地址

参数

struct rpc_clnt *clnt

RPC 客户端结构

struct sockaddr *buf

目标缓冲区

size_t buflen

目标缓冲区的大小,以字节为单位

描述

如果成功,则返回零并填充“buf”和“buflen”;否则,返回负的 errno。

即使底层传输当前未连接,或者上层以前从未提供源地址,此操作也有效。

此函数调用的结果是暂时的:连续多次调用可能会给出不同的结果,具体取决于本地网络配置如何随时间变化。

struct net *rpc_net_ns(struct rpc_clnt *clnt)

获取此 RPC 客户端的网络命名空间

参数

struct rpc_clnt *clnt

要查询的 RPC 客户端

size_t rpc_max_payload(struct rpc_clnt *clnt)

获取传输的最大负载大小,以字节为单位

参数

struct rpc_clnt *clnt

要查询的 RPC 客户端

描述

对于流传输,这是一个 RPC 记录片段(请参阅 RFC 1831),因为我们尚不支持多记录请求。对于数据报传输,这是 IP 数据包的大小减去 IP、UDP 和 RPC 标头的大小。

size_t rpc_max_bc_payload(struct rpc_clnt *clnt)

获取最大反向通道负载大小,以字节为单位

参数

struct rpc_clnt *clnt

要查询的 RPC 客户端

void rpc_force_rebind(struct rpc_clnt *clnt)

强制传输检查远程端口是否未更改

参数

struct rpc_clnt *clnt

客户端重新绑定

int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt, struct rpc_xprt_switch *xps, struct rpc_xprt *xprt, void *in_max_connect)

测试并添加新的传输到 rpc_clnt

参数

struct rpc_clnt *clnt

指向 struct rpc_clnt 的指针

struct rpc_xprt_switch *xps

指向 struct rpc_xprt_switch 的指针,

struct rpc_xprt *xprt

指向 struct rpc_xprt 的指针

void *in_max_connect

指向传入的 xprt 传输的最大连接值的指针

int rpc_clnt_setup_test_and_add_xprt(struct rpc_clnt *clnt, struct rpc_xprt_switch *xps, struct rpc_xprt *xprt, void *data)

参数

struct rpc_clnt *clnt

struct rpc_clnt 以获取新的传输

struct rpc_xprt_switch *xps

用于保存新传输的 rpc_xprt_switch

struct rpc_xprt *xprt

要测试的 rpc_xprt

void *data

一个 struct rpc_add_xprt_test 指针,该指针保存测试函数和测试函数调用数据

描述

这是一个 rpc_clnt_add_xprt setup() 函数,它返回 1,因此

1) 测试函数的调用者必须解引用 rpc_xprt_switch 和 rpc_xprt。 2) 测试函数必须调用 rpc_xprt_switch_add_xprt,通常在 rpc_call_done 例程中。

成功后(返回 1),测试函数将新的传输添加到 rpc_clnt xprt switch

int rpc_clnt_add_xprt(struct rpc_clnt *clnt, struct xprt_create *xprtargs, int (*setup)(struct rpc_clnt*, struct rpc_xprt_switch*, struct rpc_xprt*, void*), void *data)

向 rpc_clnt 添加新的传输

参数

struct rpc_clnt *clnt

指向 struct rpc_clnt 的指针

struct xprt_create *xprtargs

指向 struct xprt_create 的指针

int (*setup)(struct rpc_clnt *, struct rpc_xprt_switch *, struct rpc_xprt *, void *)

用于测试和/或设置连接的回调

void *data

指向设置函数数据的指针

描述

使用 args 中设置的参数创建一个新的传输并将其添加到 clnt。如果设置了 ping,则在添加新的传输之前测试连接是否成功。

网络设备支持

驱动程序支持

void dev_add_pack(struct packet_type *pt)

添加数据包处理程序

参数

struct packet_type *pt

数据包类型声明

向网络堆栈添加协议处理程序。传入的 packet_type 将链接到内核列表,并且在从内核列表中删除之前可能不会被释放。

此调用不会休眠,因此不能保证正在接收数据包的所有 CPU 都会看到新的数据包类型(直到下一个接收的数据包)。

void __dev_remove_pack(struct packet_type *pt)

删除数据包处理程序

参数

struct packet_type *pt

数据包类型声明

删除先前由 dev_add_pack() 添加到内核协议处理程序中的协议处理程序。传递的 packet_type 将从内核列表中删除,并且在此函数返回后可以释放或重用。

数据包类型可能仍被接收器使用,并且在所有 CPU 都经过静止状态之后,不得释放。

void dev_remove_pack(struct packet_type *pt)

删除数据包处理程序

参数

struct packet_type *pt

数据包类型声明

删除先前由 dev_add_pack() 添加到内核协议处理程序中的协议处理程序。传递的 packet_type 将从内核列表中删除,并且在此函数返回后可以释放或重用。

此调用会休眠,以保证在返回后没有 CPU 查看数据包类型。

获取接口的 “iflink” 值

参数

const struct net_device *dev

目标接口

指示接口链接到的 ifindex。物理接口具有相同的“ifindex”和“iflink”值。

int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)

检索隧道出口信息。

参数

struct net_device *dev

目标接口

struct sk_buff *skb

数据包。

为了更好地了解隧道流量,OVS 需要检索数据包的出口隧道信息。以下 API 允许用户获取此信息。

struct net_device *__dev_get_by_name(struct net *net, const char *name)

按名称查找设备

参数

struct net *net

适用的 net 命名空间

const char *name

要查找的名称

按名称查找接口。必须在 RTNL 信号量下调用。如果找到名称,则返回指向该设备的指针。如果找不到名称,则返回 NULL。引用计数器不会递增,因此调用者必须小心使用锁。

struct net_device *dev_get_by_name_rcu(struct net *net, const char *name)

按名称查找设备

参数

struct net *net

适用的 net 命名空间

const char *name

要查找的名称

描述

按名称查找接口。如果找到名称,则返回指向该设备的指针。如果找不到名称,则返回 NULL。引用计数器不会递增,因此调用者必须小心使用锁。调用者必须持有 RCU 锁。

struct net_device *netdev_get_by_name(struct net *net, const char *name, netdevice_tracker *tracker, gfp_t gfp)

按名称查找设备

参数

struct net *net

适用的 net 命名空间

const char *name

要查找的名称

netdevice_tracker *tracker

获取的引用的跟踪对象

gfp_t gfp

跟踪器的分配标志

通过名称查找接口。此函数可以在任何上下文中调用,并执行自己的锁定操作。返回的句柄的使用计数会增加,当不再需要时,调用者必须使用 netdev_put() 来释放它。如果未找到匹配的设备,则返回 NULL

struct net_device *__dev_get_by_index(struct net *net, int ifindex)

通过 ifindex 查找设备

参数

struct net *net

适用的 net 命名空间

int ifindex

设备的索引

通过索引搜索接口。如果未找到设备,则返回 NULL;否则返回指向该设备的指针。该设备的引用计数没有增加,因此调用者必须注意锁定。调用者必须持有 RTNL 信号量。

struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex)

通过 ifindex 查找设备

参数

struct net *net

适用的 net 命名空间

int ifindex

设备的索引

通过索引搜索接口。如果未找到设备,则返回 NULL;否则返回指向该设备的指针。该设备的引用计数没有增加,因此调用者必须注意锁定。调用者必须持有 RCU 锁。

struct net_device *netdev_get_by_index(struct net *net, int ifindex, netdevice_tracker *tracker, gfp_t gfp)

通过 ifindex 查找设备

参数

struct net *net

适用的 net 命名空间

int ifindex

设备的索引

netdevice_tracker *tracker

获取的引用的跟踪对象

gfp_t gfp

跟踪器的分配标志

通过索引搜索接口。如果未找到设备,则返回 NULL;否则返回指向该设备的指针。返回的设备已添加引用,在用户调用 netdev_put() 表明他们已完成对该设备的使用之前,该指针是安全的。

struct net_device *dev_get_by_napi_id(unsigned int napi_id)

通过 napi_id 查找设备

参数

unsigned int napi_id

NAPI 结构的 ID

通过 NAPI ID 搜索接口。如果未找到设备,则返回 NULL;否则返回指向该设备的指针。该设备的引用计数没有增加,因此调用者必须注意锁定。调用者必须持有 RCU 锁。

struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type, const char *ha)

通过硬件地址查找设备

参数

struct net *net

适用的 net 命名空间

unsigned short type

设备的媒体类型

const char *ha

硬件地址

通过 MAC 地址搜索接口。如果未找到设备,则返回 NULL;否则返回指向该设备的指针。调用者必须持有 RCU 或 RTNL。返回的设备没有增加其引用计数,因此调用者必须注意锁定。

struct net_device *__dev_get_by_flags(struct net *net, unsigned short if_flags, unsigned short mask)

查找具有给定标志的任何设备

参数

struct net *net

适用的 net 命名空间

unsigned short if_flags

IFF_* 值

unsigned short mask

要检查的 if_flags 中的位掩码

搜索具有给定标志的任何接口。如果未找到设备,则返回 NULL;否则返回指向该设备的指针。必须在 rtnl_lock() 中调用,并且结果的引用计数不变。

bool dev_valid_name(const char *name)

检查名称对于网络设备是否有效

参数

const char *name

名称字符串

网络设备名称需要是有效的文件名,以允许 sysfs 工作。我们也不允许任何类型的空格。

int dev_alloc_name(struct net_device *dev, const char *name)

为设备分配名称

参数

struct net_device *dev

设备

const char *name

名称格式字符串

传入格式字符串(例如 “lt``d``”),它将尝试查找合适的 ID。它扫描设备列表以构建一个空闲映射,然后选择第一个空闲的插槽。调用者必须持有 dev_base 或 rtnl 锁,同时分配名称并添加设备,以避免重复。限制为 bits_per_byte * 页面大小设备(即大多数平台上的 32K)。返回分配的单元号或负的 errno 代码。

int dev_set_alias(struct net_device *dev, const char *alias, size_t len)

更改设备的 ifalias

参数

struct net_device *dev

设备

const char *alias

名称,最大长度为 IFALIASZ

size_t len

要从 info 复制的字节数限制

为设备设置 ifalias

void netdev_features_change(struct net_device *dev)

设备更改功能

参数

struct net_device *dev

要触发通知的设备

调用此函数以指示设备已更改功能。

void netdev_state_change(struct net_device *dev)

设备状态改变

参数

struct net_device *dev

要触发通知的设备

调用此函数表示设备状态已更改。此函数为 netdev_chain 调用通知链,并向路由套接字发送 NEWLINK 消息。

void __netdev_notify_peers(struct net_device *dev)

通知网络对等方 dev 的存在,当 rtnl 锁已被持有调用此函数。

参数

struct net_device *dev

网络设备

描述

生成流量,使感兴趣的网络对等方了解 dev,例如生成免费 ARP。当设备想要通知网络的其余部分有关某种重新配置时,例如故障转移事件或虚拟机迁移,可以使用此函数。

void netdev_notify_peers(struct net_device *dev)

通知网络对等方 dev 的存在

参数

struct net_device *dev

网络设备

描述

生成流量,使感兴趣的网络对等方了解 dev,例如生成免费 ARP。当设备想要通知网络的其余部分有关某种重新配置时,例如故障转移事件或虚拟机迁移,可以使用此函数。

int dev_open(struct net_device *dev, struct netlink_ext_ack *extack)

准备一个接口以供使用。

参数

struct net_device *dev

要打开的设备

struct netlink_ext_ack *extack

netlink 扩展确认

将设备从关闭状态变为开启状态。调用设备的私有 open 函数,然后加载多播列表。最后,设备移动到开启状态,并将 NETDEV_UP 消息发送到 netdev 通知链。

在活动接口上调用此函数是空操作。如果失败,则返回负 errno 代码。

void dev_close(struct net_device *dev)

关闭一个接口。

参数

struct net_device *dev

要关闭的设备

此函数将活动设备移动到关闭状态。将 NETDEV_GOING_DOWN 发送到 netdev 通知链。然后停用该设备,最后将 NETDEV_DOWN 发送到通知链。

void dev_disable_lro(struct net_device *dev)

禁用设备上的大型接收卸载

参数

struct net_device *dev

设备

禁用网络设备上的大型接收卸载 (LRO)。必须在 RTNL 下调用。如果接收到的数据包可能转发到另一个接口,则需要这样做。

int register_netdevice_notifier(struct notifier_block *nb)

注册一个网络通知程序块

参数

struct notifier_block *nb

通知程序

描述

注册一个通知程序,以便在发生网络设备事件时调用。传递的通知程序链接到内核结构中,在注销之前不得重复使用。如果失败,则返回负 errno 代码。

注册后,所有注册和开启事件都会重新发送到新的通知程序,以允许设备获得网络设备列表的无竞争视图。

int unregister_netdevice_notifier(struct notifier_block *nb)

注销一个网络通知程序块

参数

struct notifier_block *nb

通知程序

描述

注销先前由 register_netdevice_notifier() 注册的通知程序。该通知程序从内核结构中取消链接,然后可以重复使用。如果失败,则返回负 errno 代码。

注销后,将为设备列表中的所有设备向已删除的通知程序合成注销和关闭设备事件,以消除对特殊情况清理代码的需求。

int register_netdevice_notifier_net(struct net *net, struct notifier_block *nb)

注册一个每个 netns 的网络通知程序块

参数

struct net *net

网络命名空间

struct notifier_block *nb

通知程序

描述

注册一个通知程序,以便在发生网络设备事件时调用。传递的通知程序链接到内核结构中,在注销之前不得重复使用。如果失败,则返回负 errno 代码。

注册后,所有注册和开启事件都会重新发送到新的通知程序,以允许设备获得网络设备列表的无竞争视图。

int unregister_netdevice_notifier_net(struct net *net, struct notifier_block *nb)

注销一个每个 netns 的网络通知程序块

参数

struct net *net

网络命名空间

struct notifier_block *nb

通知程序

描述

注销先前由 register_netdevice_notifier_net() 注册的通知程序。该通知程序从内核结构中取消链接,然后可以重复使用。如果失败,则返回负 errno 代码。

注销后,将为设备列表中的所有设备向已删除的通知程序合成注销和关闭设备事件,以消除对特殊情况清理代码的需求。

int call_netdevice_notifiers(unsigned long val, struct net_device *dev)

调用所有网络通知程序块

参数

unsigned long val

未修改传递给通知程序函数的值

struct net_device *dev

未修改传递给通知程序函数的 net_device 指针

调用所有网络通知程序块。参数和返回值与 raw_notifier_call_chain() 相同。

int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)

将 skb 环回另一个网络接口

参数

struct net_device *dev

目标网络设备

struct sk_buff *skb

要转发的缓冲区

描述

返回值

NET_RX_SUCCESS(无拥塞)NET_RX_DROP(数据包被丢弃,但已释放)

dev_forward_skb 可用于将一个设备的 start_xmit 函数中的 skb 注入到另一个设备的接收队列中。

接收设备可能位于另一个命名空间中,因此我们必须清除 skb 中可能影响命名空间隔离的所有信息。

bool dev_nit_active(struct net_device *dev)

如果正在使用任何网络接口 tap,则返回 true

参数

struct net_device *dev

要检查是否存在 tap 的网络设备

int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq)

设置使用的实际 RX 队列数

参数

struct net_device *dev

网络设备

unsigned int rxq

实际 RX 队列数

必须在持有 rtnl_lock 或在注册网络设备之前调用此函数。成功时返回 0,或者返回负错误代码。如果在注册之前调用,则始终成功。

int netif_set_real_num_queues(struct net_device *dev, unsigned int txq, unsigned int rxq)

设置实际使用的 RX 和 TX 队列数量

参数

struct net_device *dev

网络设备

unsigned int txq

实际的 TX 队列数量

unsigned int rxq

实际 RX 队列数

设置实际的 TX 和 RX 队列数量。如果队列数量已经正确,则不执行任何操作。

void netif_set_tso_max_size(struct net_device *dev, unsigned int size)

设置支持的 TSO 帧的最大大小

参数

struct net_device *dev

要更新的网络设备

unsigned int size

TSO 帧的最大 skb->len

描述

设置设备可以处理的 TSO 超帧大小的限制。除非显式设置,否则堆栈将采用 GSO_LEGACY_MAX_SIZE 的值。

void netif_set_tso_max_segs(struct net_device *dev, unsigned int segs)

设置 TSO 支持的最大分段数

参数

struct net_device *dev

要更新的网络设备

unsigned int segs

最大 TCP 分段数

描述

设置设备可以从单个 TSO 超帧生成 TCP 分段的最大数量。除非显式设置,否则堆栈将采用 GSO_MAX_SEGS 的值。

void netif_inherit_tso_max(struct net_device *to, const struct net_device *from)

将所有 TSO 限制从较低的设备复制到较高的设备

参数

struct net_device *to

要更新的网络设备

const struct net_device *from

从中复制限制的网络设备

int netif_get_num_default_rss_queues(void)

默认的 RSS 队列数

参数

void

无参数

描述

如果只有 1 个或 2 个物理核心,则默认值为物理核心数;如果有更多核心,则除以 2。

void netif_device_detach(struct net_device *dev)

将设备标记为已移除

参数

struct net_device *dev

网络设备

描述

将设备标记为已从系统中移除,因此不再可用。

void netif_device_attach(struct net_device *dev)

将设备标记为已附加

参数

struct net_device *dev

网络设备

描述

将设备标记为已从系统中附加,并在需要时重新启动。

int dev_loopback_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)

环回 skb

参数

struct net *net

发生此环回的网络命名空间

struct sock *sk

sk 需要是 netfilter okfn

struct sk_buff *skb

要传输的缓冲区

int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev)

传输缓冲区

参数

struct sk_buff *skb

要传输的缓冲区

struct net_device *sb_dev

用于 L2 转发卸载的子设备

描述

将缓冲区排队以传输到网络设备。调用方必须在调用此函数之前设置设备和优先级并构建缓冲区。该函数可以从中断中调用。

调用此方法时,必须启用中断。这是因为 BH 启用代码必须启用 IRQ,这样它才不会死锁。

无论返回值如何,都会消耗 skb,因此目前很难重试发送到此方法。(如果您小心,可以在发送之前增加引用计数以保留重试的引用。)

返回

  • 0 - 缓冲区已成功传输

  • 正的 qdisc 返回码 - NET_XMIT_DROP 等。

  • 负的 errno - 其他错误

bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index, u32 flow_id, u16 filter_id)

检查是否可以删除 RFS 硬件过滤器

参数

struct net_device *dev

设置过滤器的设备

u16 rxq_index

RX 队列索引

u32 flow_id

传递给 ndo_rx_flow_steer() 的流 ID

u16 filter_id

ndo_rx_flow_steer() 返回的过滤器 ID

描述

实现 ndo_rx_flow_steer() 的驱动程序应定期为每个已安装的过滤器调用此函数,并删除返回 true 的过滤器。

int __netif_rx(struct sk_buff *skb)

netif_rx 的略微优化版本

参数

struct sk_buff *skb

要发布的缓冲区

它的行为与 netif_rx 相同,但它不会禁用下半部分。因此,此函数只能从中断上下文(硬中断或软中断)中调用。

int netif_rx(struct sk_buff *skb)

将缓冲区发布到网络代码

参数

struct sk_buff *skb

要发布的缓冲区

此函数接收来自设备驱动程序的包,并将其排队以供上层(协议)级别通过 backlog NAPI 设备进行处理。它总是成功。缓冲区可能在处理期间因拥塞控制或协议层而被丢弃。网络缓冲区通过 backlog NAPI 设备传递。现代网卡驱动程序应使用 NAPI 和 GRO。此函数可以从中断和进程上下文中调用。来自进程上下文的调用方在调用此函数之前不得禁用中断。

返回值:NET_RX_SUCCESS(无拥塞) NET_RX_DROP(数据包被丢弃)

bool netdev_is_rx_handler_busy(struct net_device *dev)

检查是否已注册接收处理程序

参数

struct net_device *dev

要检查的设备

检查给定设备是否已注册接收处理程序。如果已注册,则返回 true。

调用者必须持有 rtnl_mutex。

int netdev_rx_handler_register(struct net_device *dev, rx_handler_func_t *rx_handler, void *rx_handler_data)

注册接收处理程序

参数

struct net_device *dev

要为其注册处理程序的设备

rx_handler_func_t *rx_handler

要注册的接收处理程序

void *rx_handler_data

接收处理程序使用的数据指针

为设备注册接收处理程序。然后将从 __netif_receive_skb 调用此处理程序。失败时返回负的 errno 代码。

调用者必须持有 rtnl_mutex。

有关 rx_handler 的一般说明,请参阅枚举 rx_handler_result。

void netdev_rx_handler_unregister(struct net_device *dev)

注销接收处理程序

参数

struct net_device *dev

要从中注销处理程序的设备

从设备注销接收处理程序。

调用者必须持有 rtnl_mutex。

int netif_receive_skb_core(struct sk_buff *skb)

netif_receive_skb 的特殊用途版本

参数

struct sk_buff *skb

要处理的缓冲区

更直接的接收版本 netif_receive_skb()。它只应由需要跳过 RPS 和 Generic XDP 的调用者使用。调用者还必须注意处理 (page_is_)pfmemalloc 的情况。

此函数只能从软中断上下文调用,并且应启用中断。

返回值(通常被忽略):NET_RX_SUCCESS:无拥塞 NET_RX_DROP:数据包被丢弃

int netif_receive_skb(struct sk_buff *skb)

处理来自网络的接收缓冲区

参数

struct sk_buff *skb

要处理的缓冲区

netif_receive_skb() 是主要的接收数据处理函数。它总是成功。缓冲区可能会在处理过程中因拥塞控制或协议层而被丢弃。

此函数只能从软中断上下文调用,并且应启用中断。

返回值(通常被忽略):NET_RX_SUCCESS:无拥塞 NET_RX_DROP:数据包被丢弃

void netif_receive_skb_list(struct list_head *head)

处理来自网络的多个接收缓冲区

参数

struct list_head *head

要处理的 skb 列表。

由于 netif_receive_skb() 的返回值通常被忽略,并且对于列表没有意义,因此此函数返回 void。

此函数只能从软中断上下文调用,并且应启用中断。

void __napi_schedule(struct napi_struct *n)

计划接收

参数

struct napi_struct *n

要计划的条目

描述

将计划运行该条目的接收函数。如果已屏蔽硬中断,请考虑使用 __napi_schedule_irqoff()

bool napi_schedule_prep(struct napi_struct *n)

检查是否可以计划 napi

参数

struct napi_struct *n

napi 上下文

描述

测试 NAPI 例程是否已在运行,如果未运行,则将其标记为正在运行。这用作条件变量,以确保仅运行一个 NAPI 轮询实例。我们还确保没有挂起的 NAPI 禁用。

void __napi_schedule_irqoff(struct napi_struct *n)

计划接收

参数

struct napi_struct *n

要计划的条目

描述

__napi_schedule() 的变体,假设已屏蔽硬中断。

在启用 PREEMPT_RT 的内核上,这映射到 __napi_schedule(),因为由于强制线程中断和自旋锁替换,中断禁用的假设可能不成立。

void netif_queue_set_napi(struct net_device *dev, unsigned int queue_index, enum netdev_queue_type type, struct napi_struct *napi)

将队列与 napi 关联

参数

struct net_device *dev

NAPI 和队列所属的设备

unsigned int queue_index

队列的索引

enum netdev_queue_type type

队列类型为 RX 或 TX

struct napi_struct *napi

NAPI 上下文,传递 NULL 以清除先前设置的 NAPI

描述

设置带有其相应 napi 上下文的队列。应在为队列向量注册 NAPI 处理程序,并将队列映射到相应的中断向量后完成此操作。

void napi_enable(struct napi_struct *n)

启用 NAPI 调度

参数

struct napi_struct *n

NAPI 上下文

描述

恢复在此上下文中计划的 NAPI。必须与 napi_disable 配对。

bool netdev_has_upper_dev(struct net_device *dev, struct net_device *upper_dev)

检查设备是否链接到上层设备

参数

struct net_device *dev

设备

struct net_device *upper_dev

要检查的上层设备

描述

查找设备是否链接到指定的上层设备,如果是,则返回 true。请注意,这仅检查直接的上层设备,而不是通过完整的设备堆栈。调用者必须持有 RTNL 锁。

bool netdev_has_upper_dev_all_rcu(struct net_device *dev, struct net_device *upper_dev)

检查设备是否链接到上层设备

参数

struct net_device *dev

设备

struct net_device *upper_dev

要检查的上层设备

描述

查找设备是否链接到指定的上层设备,如果是,则返回 true。请注意,这会检查整个上层设备链。调用者必须持有 rcu 锁。

bool netdev_has_any_upper_dev(struct net_device *dev)

检查设备是否链接到某个设备

参数

struct net_device *dev

设备

描述

查找设备是否链接到上层设备,如果是,则返回 true。调用者必须持有 RTNL 锁。

struct net_device *netdev_master_upper_dev_get(struct net_device *dev)

获取主上层设备

参数

struct net_device *dev

设备

描述

查找主上层设备并返回指向它的指针,如果不存在,则返回 NULL。调用者必须持有 RTNL 锁。

struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, struct list_head **iter)

从上层列表中获取下一个设备

参数

struct net_device *dev

设备

struct list_head **iter

当前位置的 list_head **

描述

从 iter 位置开始,从 dev 的上层列表中获取下一个设备。调用者必须持有 RCU 读取锁。

void *netdev_lower_get_next_private(struct net_device *dev, struct list_head **iter)

从下层邻居列表中获取下一个 ->private

参数

struct net_device *dev

设备

struct list_head **iter

当前位置的 list_head **

描述

从 iter 位置开始,从 dev 的下层邻居列表中获取下一个 netdev_adjacent->private。调用者必须持有 RTNL 锁,或者其自身的锁,以保证邻居下层列表保持不变。

void *netdev_lower_get_next_private_rcu(struct net_device *dev, struct list_head **iter)

从下层邻居列表中获取下一个 ->private,RCU 变体

参数

struct net_device *dev

设备

struct list_head **iter

当前位置的 list_head **

描述

从 iter 位置开始,从 dev 的下层邻居列表中获取下一个 netdev_adjacent->private。调用者必须持有 RCU 读取锁。

void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter)

从下层邻居列表中获取下一个设备

参数

struct net_device *dev

设备

struct list_head **iter

当前位置的 list_head **

描述

从 iter 位置开始,从 dev 的下层邻居列表中获取下一个 netdev_adjacent。调用者必须持有 RTNL 锁,或者其自身的锁,以保证邻居下层列表保持不变。

void *netdev_lower_get_first_private_rcu(struct net_device *dev)

从下层邻居列表中获取第一个 ->private,RCU 变体

参数

struct net_device *dev

设备

描述

从 dev 的下层邻居列表中获取第一个 netdev_adjacent->private。调用者必须持有 RCU 读取锁。

struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)

获取主上层设备

参数

struct net_device *dev

设备

描述

查找主上层设备并返回指向它的指针,如果不存在,则返回 NULL。调用者必须持有 RCU 读取锁。

添加指向上层设备的链接

参数

struct net_device *dev

设备

struct net_device *upper_dev

新的上层设备

struct netlink_ext_ack *extack

netlink 扩展确认

描述

添加一个指向此设备上层的设备的链接。调用者必须持有 RTNL 锁。如果失败,则返回负的 errno 代码。如果成功,则调整引用计数,并且函数返回零。

添加指向上层设备的主链接

参数

struct net_device *dev

设备

struct net_device *upper_dev

新的上层设备

void *upper_priv

上层设备私有数据

void *upper_info

要通过通知器传递的 上层信息

struct netlink_ext_ack *extack

netlink 扩展确认

描述

添加一个指向此设备上层的设备的链接。在这种情况下,只能链接一个主上层设备,尽管也可以链接其他非主设备。调用者必须持有 RTNL 锁。如果失败,则返回负的 errno 代码。如果成功,则调整引用计数,并且函数返回零。

移除到上层设备的链接

参数

struct net_device *dev

设备

struct net_device *upper_dev

新的上层设备

描述

移除到此设备上层设备的链接。调用者必须持有 RTNL 锁。

void netdev_bonding_info_change(struct net_device *dev, struct netdev_bonding_info *bonding_info)

分发关于从设备变更的事件

参数

struct net_device *dev

设备

struct netdev_bonding_info *bonding_info

要分发的信息

描述

发送 NETDEV_BONDING_INFO 到带有信息的 netdev 通知器。调用者必须持有 RTNL 锁。

struct net_device *netdev_get_xmit_slave(struct net_device *dev, struct sk_buff *skb, bool all_slaves)

获取主设备的 xmit 从设备

参数

struct net_device *dev

设备

struct sk_buff *skb

数据包

bool all_slaves

假设所有从设备都处于活动状态

描述

引用计数器不会递增,因此调用者必须小心使用锁。调用者必须持有 RCU 锁。如果没有找到从设备,则返回 NULL

struct net_device *netdev_sk_get_lowest_dev(struct net_device *dev, struct sock *sk)

获取给定设备和套接字链中的最低设备

参数

struct net_device *dev

设备

struct sock *sk

套接字

描述

如果没有找到较低的设备,则返回 NULL

void netdev_lower_state_changed(struct net_device *lower_dev, void *lower_state_info)

分发关于下层设备状态变更的事件

参数

struct net_device *lower_dev

设备

void *lower_state_info

要分发的状态

描述

发送带有信息的 NETDEV_CHANGELOWERSTATE 到 netdev 通知器。调用者必须持有 RTNL 锁。

int dev_set_promiscuity(struct net_device *dev, int inc)

更新设备上的混杂模式计数

参数

struct net_device *dev

设备

int inc

修饰符

在设备上添加或删除混杂模式。当设备中的计数保持在零以上时,接口将保持混杂模式。一旦达到零,设备将恢复为正常的过滤操作。负的 inc 值用于删除设备上的混杂模式。如果成功,则返回 0;如果发生错误,则返回负的 errno 代码。

int dev_set_allmulti(struct net_device *dev, int inc)

更新设备上的 allmulti 计数

参数

struct net_device *dev

设备

int inc

修饰符

在设备上添加或删除接收所有组播帧。当设备中的计数保持在零以上时,接口将保持监听所有接口。一旦达到零,设备将恢复为正常的过滤操作。当释放需要所有组播的资源时,使用负的 inc 值来减少计数器。如果成功,则返回 0;如果发生错误,则返回负的 errno 代码。

unsigned int dev_get_flags(const struct net_device *dev)

获取报告给用户空间的标志

参数

const struct net_device *dev

设备

获取通过 API 导出到用户空间的标志位的组合。

int dev_change_flags(struct net_device *dev, unsigned int flags, struct netlink_ext_ack *extack)

更改设备设置

参数

struct net_device *dev

设备

unsigned int flags

设备状态标志

struct netlink_ext_ack *extack

netlink 扩展确认

基于状态标志更改设备上的设置。这些标志采用用户空间导出的格式。

int dev_pre_changeaddr_notify(struct net_device *dev, const char *addr, struct netlink_ext_ack *extack)

调用 NETDEV_PRE_CHANGEADDR。

参数

struct net_device *dev

设备

const char *addr

新地址

struct netlink_ext_ack *extack

netlink 扩展确认

int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa, struct netlink_ext_ack *extack)

更改媒体访问控制地址

参数

struct net_device *dev

设备

struct sockaddr *sa

新地址

struct netlink_ext_ack *extack

netlink 扩展确认

更改设备的硬件 (MAC) 地址

int dev_get_port_parent_id(struct net_device *dev, struct netdev_phys_item_id *ppid, bool recurse)

获取设备的端口父标识符

参数

struct net_device *dev

网络设备

struct netdev_phys_item_id *ppid

指向端口父标识符存储的指针

bool recurse

允许/禁止递归到较低的设备

获取设备的端口父标识符

bool netdev_port_same_parent_id(struct net_device *a, struct net_device *b)

指示两个网络设备是否具有相同的端口父标识符

参数

struct net_device *a

第一个网络设备

struct net_device *b

第二个网络设备

void netdev_update_features(struct net_device *dev)

重新计算设备特性

参数

struct net_device *dev

要检查的设备

重新计算 dev->features 集合,并在其更改时发送通知。应该在驱动程序或硬件相关条件可能已更改(影响功能)后调用。

void netdev_change_features(struct net_device *dev)

重新计算设备特性

参数

struct net_device *dev

要检查的设备

重新计算 dev->features 集合,并发送通知,即使它们没有更改。如果 dev->vlan_features 也可能已更改,则应调用此函数,而不是 netdev_update_features(),以允许将更改传播到堆叠的 VLAN 设备。

void netif_stacked_transfer_operstate(const struct net_device *rootdev, struct net_device *dev)

转移 operstate

参数

const struct net_device *rootdev

要从中转移状态的根设备或较低级别设备

struct net_device *dev

要将 operstate 转移到的设备

将操作状态从根设备转移到设备。当根设备和设备(叶子设备)之间存在堆叠关系时,通常会调用此函数。

int register_netdevice(struct net_device *dev)

注册网络设备

参数

struct net_device *dev

要注册的设备

描述

获取已准备好的网络设备结构,并使其可从外部访问。 一个 NETDEV_REGISTER 消息被发送到 netdev 通知链。调用者必须持有 rtnl 锁 - 您可能需要 register_netdev() 来代替此函数。

void init_dummy_netdev(struct net_device *dev)

为 NAPI 初始化一个虚拟网络设备

参数

struct net_device *dev

要初始化的设备

此函数获取一个网络设备结构并初始化最少量的字段,以便它可以用于调度 NAPI 轮询,而无需注册完整的接口。这供需要将多个硬件接口绑定到单个 NAPI 轮询调度器的驱动程序使用,原因是硬件限制。

int register_netdev(struct net_device *dev)

注册网络设备

参数

struct net_device *dev

要注册的设备

获取已完成的网络设备结构,并将其添加到内核接口。 一个 NETDEV_REGISTER 消息被发送到 netdev 通知链。成功时返回 0。如果设置设备失败或名称重复,则返回负的 errno 代码。

这是 register_netdevice 的一个包装器,它获取 rtnl 信号量,并在您将格式字符串传递给 alloc_netdev 时展开设备名称。

struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, struct rtnl_link_stats64 *storage)

获取网络设备统计信息

参数

struct net_device *dev

要从中获取统计信息的设备

struct rtnl_link_stats64 *storage

存储统计信息的位置

从设备获取网络统计信息。返回 storage。设备驱动程序可以通过设置 dev->netdev_ops->get_stats64 或 dev->netdev_ops->get_stats 来提供自己的方法;否则,将使用内部统计信息结构。

void dev_fetch_sw_netstats(struct rtnl_link_stats64 *s, const struct pcpu_sw_netstats __percpu *netstats)

获取每个 CPU 的网络设备统计信息

参数

struct rtnl_link_stats64 *s

存储统计信息的位置

const struct pcpu_sw_netstats __percpu *netstats

要从中读取的每个 CPU 的网络统计信息

读取每个 CPU 的网络统计信息,并在 s 中填充相关字段。

void dev_get_tstats64(struct net_device *dev, struct rtnl_link_stats64 *s)

ndo_get_stats64 实现

参数

struct net_device *dev

要从中获取统计信息的设备

struct rtnl_link_stats64 *s

存储统计信息的位置

从 dev->stats 和 dev->tstats 填充 s。可以用作 ndo_get_stats64() 回调。

void netdev_sw_irq_coalesce_default_on(struct net_device *dev)

默认启用 SW IRQ 合并

参数

struct net_device *dev

要在其上启用 IRQ 合并的 netdev

描述

为 SW IRQ 合并设置保守的默认值。用户可以使用 sysfs 属性来覆盖默认值。

struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, unsigned char name_assign_type, void (*setup)(struct net_device*), unsigned int txqs, unsigned int rxqs)

分配网络设备

参数

int sizeof_priv

要为其分配空间的私有数据的大小

const char *name

设备名称格式字符串

unsigned char name_assign_type

设备名称的来源

void (*setup)(struct net_device *)

初始化设备的回调

unsigned int txqs

要分配的 TX 子队列的数量

unsigned int rxqs

要分配的 RX 子队列的数量

描述

分配一个 struct net_device,其中包含供驱动程序使用的私有数据区域,并执行基本初始化。还会为设备上的每个队列分配子队列结构。

void free_netdev(struct net_device *dev)

释放网络设备

参数

struct net_device *dev

设备

描述

此函数执行销毁已分配设备接口的最后阶段。对设备对象的引用会被释放。如果这是最后一个引用,则该对象将被释放。必须在进程上下文中调用。

struct net_device *alloc_netdev_dummy(int sizeof_priv)

分配并初始化一个虚拟网络设备。

参数

int sizeof_priv

要为其分配空间的私有数据的大小

返回

成功时返回分配的 net_device,否则返回 NULL

void synchronize_net(void)

与数据包接收处理同步

参数

void

无参数

描述

等待当前正在接收的数据包处理完成。不会阻止稍后数据包的开始处理。

void unregister_netdevice_queue(struct net_device *dev, struct list_head *head)

从内核中移除设备

参数

struct net_device *dev

设备

struct list_head *head

list

此函数关闭设备接口并将其从内核表中移除。如果 head 不为 NULL,则设备将被放入队列以稍后注销。

调用者必须持有 rtnl 信号量。您可能需要使用 unregister_netdev() 来代替此函数。

void unregister_netdevice_many(struct list_head *head)

注销多个设备

参数

struct list_head *head

设备列表

注意

由于大多数调用者使用堆栈分配的 list_head,

我们强制执行 list_del() 以确保堆栈稍后不会损坏。

void unregister_netdev(struct net_device *dev)

从内核中移除设备

参数

struct net_device *dev

设备

此函数关闭设备接口并将其从内核表中移除。

这只是 unregister_netdevice 的一个包装器,它获取 rtnl 信号量。通常,您需要使用此函数,而不是 unregister_netdevice。

int __dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat, int new_ifindex)

将设备移动到不同的 nethost 命名空间

参数

struct net_device *dev

设备

struct net *net

网络命名空间

const char *pat

如果当前设备名称在目标网络命名空间中已被占用,则尝试的名称模式(如果不为 NULL)。

int new_ifindex

如果不是零,则指定目标命名空间中的设备索引。

此函数关闭设备接口并将其移动到新的网络命名空间。成功时返回 0,失败时返回一个负的 errno 代码。

调用者必须持有 rtnl 信号量。

netdev_features_t netdev_increment_features(netdev_features_t all, netdev_features_t one, netdev_features_t mask)

将功能集增加 1

参数

netdev_features_t all

当前功能集

netdev_features_t one

新的功能集

netdev_features_t mask

掩码功能集

在将具有功能集 **one** 的设备添加到具有当前功能集 **all** 的主设备后,计算新的功能集。不会启用在 **mask** 中关闭的任何功能。返回新的功能集。

int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, const void *saddr, unsigned int len)

创建以太网头部

参数

struct sk_buff *skb

要修改的缓冲区

struct net_device *dev

源设备

unsigned short type

以太网类型字段

const void *daddr

目标地址(NULL 则保留目标地址)

const void *saddr

源地址(NULL 则使用设备源地址)

unsigned int len

数据包长度(<= skb->len)

描述

设置协议类型。对于 ETH_P_802_3/2 类型的数据包,我们将长度放在此处。

u32 eth_get_headlen(const struct net_device *dev, const void *data, u32 len)

确定以太网帧头部的长度

参数

const struct net_device *dev

指向网络设备的指针

const void *data

指向帧开头的指针

u32 len

帧的总长度

描述

尽最大努力尝试在一个线性缓冲区中拉取给定帧的所有头部的长度。

__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)

确定数据包的协议 ID。

参数

struct sk_buff *skb

接收到的套接字数据

struct net_device *dev

接收网络设备

描述

这里的规则是,如果类型字段足够短以表示长度,我们则假设为 802.3。这是正常的实践,并且适用于任何“当前正在使用的”协议。

int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr)

从数据包中提取硬件地址

参数

const struct sk_buff *skb

要从中提取报头的包

unsigned char *haddr

目标缓冲区

int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, __be16 type)

从邻居填充缓存条目

参数

const struct neighbour *neigh

源邻居

struct hh_cache *hh

目标缓存条目

__be16 type

以太网类型字段

描述

从邻居创建一个以太网报头模板。

void eth_header_cache_update(struct hh_cache *hh, const struct net_device *dev, const unsigned char *haddr)

更新缓存条目

参数

struct hh_cache *hh

目标缓存条目

const struct net_device *dev

网络设备

const unsigned char *haddr

新的硬件地址

描述

由地址解析模块调用,以通知地址中的更改。

__be16 eth_header_parse_protocol(const struct sk_buff *skb)

从 L2 报头中提取协议

参数

const struct sk_buff *skb

从中提取协议的数据包

int eth_prepare_mac_addr_change(struct net_device *dev, void *p)

准备进行 MAC 更改

参数

struct net_device *dev

网络设备

void *p

套接字地址

void eth_commit_mac_addr_change(struct net_device *dev, void *p)

提交 MAC 更改

参数

struct net_device *dev

网络设备

void *p

套接字地址

int eth_mac_addr(struct net_device *dev, void *p)

设置新的以太网硬件地址

参数

struct net_device *dev

网络设备

void *p

套接字地址

描述

更改设备的硬件地址。

这不会更改硬件匹配,因此对于大多数实际设备都需要覆盖它。

void ether_setup(struct net_device *dev)

设置以太网网络设备

参数

struct net_device *dev

网络设备

描述

使用以太网通用值填充设备结构的字段。

struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, unsigned int rxqs)

分配并设置一个以太网设备

参数

int sizeof_priv

要为此以太网设备分配的附加驱动程序私有结构的大小

unsigned int txqs

此设备具有的 TX 队列数。

unsigned int rxqs

此设备具有的 RX 队列数。

描述

使用以太网通用值填充设备结构的字段。基本上执行除注册设备之外的所有操作。

构造一个包含大小为 (sizeof_priv) 的私有数据区域的新网络设备。对于此私有数据区域,强制执行 32 字节(非位)对齐。

int platform_get_ethdev_address(struct device *dev, struct net_device *netdev)

从给定设备设置 netdev 的 MAC 地址

参数

struct device *dev

指向设备的指针

struct net_device *netdev

指向要写入地址的 netdev 的指针

描述

eth_platform_get_mac_address() 的包装器,它将地址直接写入 netdev->dev_addr。

int fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr)

从固件节点获取 MAC

参数

struct fwnode_handle *fwnode

指向固件节点的指针

char *addr

用于存储 MAC 的缓冲区地址

描述

在固件节点中搜索要使用的最佳 MAC 地址。 首先检查“mac-address”,因为该地址应该包含“最近”的 MAC 地址。 如果未设置该地址,则接下来检查“local-mac-address”,因为该地址是默认地址。 如果未设置该地址,则检查过时的“address”,以防万一我们使用的是旧的设备树。

请注意,“address”属性应包含寄存器集的虚拟地址,但某些 DTS 文件已将该属性重新定义为 MAC 地址。

拒绝全零 MAC 地址,因为这些地址可能是固件表中存在的属性,但固件未更新。 例如,DTS 可以定义“mac-address”和“local-mac-address”,并使用零 MAC 地址。 一些较旧的 U-Boot 仅初始化“local-mac-address”。 在这种情况下,真正的 MAC 位于“local-mac-address”中,“mac-address”存在但全为零。

int device_get_mac_address(struct device *dev, char *addr)

获取给定设备的 MAC

参数

struct device *dev

指向设备的指针

char *addr

用于存储 MAC 的缓冲区地址

int device_get_ethdev_address(struct device *dev, struct net_device *netdev)

从给定设备设置 netdev 的 MAC 地址

参数

struct device *dev

指向设备的指针

struct net_device *netdev

指向要写入地址的 netdev 的指针

描述

device_get_mac_address() 的包装器,它将地址直接写入 netdev->dev_addr。

void netif_carrier_on(struct net_device *dev)

设置载波

参数

struct net_device *dev

网络设备

描述

设备已检测到载波的获取。

void netif_carrier_off(struct net_device *dev)

清除载波

参数

struct net_device *dev

网络设备

描述

设备已检测到载波丢失。

void netif_carrier_event(struct net_device *dev)

报告载波状态事件

参数

struct net_device *dev

网络设备

描述

设备已检测到载波事件,但载波状态未更改。当异步查询载波状态时,在驱动程序中使用此函数,以避免在查询之前链接恢复时丢失事件(链路抖动)。

确定给定的以太网地址是否为链路本地地址

参数

const u8 *addr

指向包含以太网地址的六字节数组的指针

描述

如果地址是 IEEE 802.1Q 8.6.3 帧过滤中定义的链路本地保留地址 (01:80:c2:00:00:0X),则返回 true。

请注意:addr 必须与 u16 对齐。

bool is_zero_ether_addr(const u8 *addr)

确定给定的以太网地址是否全为零。

参数

const u8 *addr

指向包含以太网地址的六字节数组的指针

描述

如果地址全为零,则返回 true。

请注意:addr 必须与 u16 对齐。

bool is_multicast_ether_addr(const u8 *addr)

确定以太网地址是否为多播地址。

参数

const u8 *addr

指向包含以太网地址的六字节数组的指针

描述

如果地址是多播地址,则返回 true。根据定义,广播地址也是多播地址。

bool is_local_ether_addr(const u8 *addr)

确定以太网地址是否为本地分配的地址 (IEEE 802)。

参数

const u8 *addr

指向包含以太网地址的六字节数组的指针

描述

如果地址是本地地址,则返回 true。

bool is_broadcast_ether_addr(const u8 *addr)

确定以太网地址是否为广播地址

参数

const u8 *addr

指向包含以太网地址的六字节数组的指针

描述

如果地址是广播地址,则返回 true。

请注意:addr 必须与 u16 对齐。

bool is_unicast_ether_addr(const u8 *addr)

确定以太网地址是否为单播地址

参数

const u8 *addr

指向包含以太网地址的六字节数组的指针

描述

如果地址是单播地址,则返回 true。

bool is_valid_ether_addr(const u8 *addr)

确定给定的以太网地址是否有效

参数

const u8 *addr

指向包含以太网地址的六字节数组的指针

描述

检查以太网地址 (MAC) 是否不是 00:00:00:00:00:00,不是多播地址,也不是 FF:FF:FF:FF:FF:FF。

如果地址有效,则返回 true。

请注意:addr 必须与 u16 对齐。

bool eth_proto_is_802_3(__be16 proto)

确定给定的以太网类型/长度是否为协议

参数

__be16 proto

要测试的以太网类型/长度值

描述

检查以太网类型/长度字段中的值是否是有效的以太网类型。

如果该值是 802.3 支持的有效以太网类型,则返回 true。

void eth_random_addr(u8 *addr)

生成软件分配的随机以太网地址

参数

u8 *addr

指向包含以太网地址的六字节数组的指针

描述

生成一个不是多播并且设置了本地分配位的随机以太网地址 (MAC)。

void eth_broadcast_addr(u8 *addr)

分配广播地址

参数

u8 *addr

指向包含以太网地址的六字节数组的指针

描述

将广播地址分配给给定的地址数组。

void eth_zero_addr(u8 *addr)

分配零地址

参数

u8 *addr

指向包含以太网地址的六字节数组的指针

描述

将零地址分配给给定的地址数组。

void eth_hw_addr_random(struct net_device *dev)

生成软件分配的随机以太网地址并设置设备标志

参数

struct net_device *dev

指向 net_device 结构的指针

描述

生成一个随机以太网地址 (MAC),供网络设备使用,并设置 addr_assign_type,以便可以通过 sysfs 读取状态并供用户空间使用。

u32 eth_hw_addr_crc(struct netdev_hw_addr *ha)

从 netdev_hw_addr 计算 CRC

参数

struct netdev_hw_addr *ha

指向硬件地址的指针

描述

从硬件地址计算 CRC,作为筛选哈希的基础。

void ether_addr_copy(u8 *dst, const u8 *src)

复制以太网地址

参数

u8 *dst

指向六字节数组以太网地址目标地址的指针

const u8 *src

指向六字节数组以太网地址源地址的指针

描述

请注意:dst 和 src 都必须与 u16 对齐。

void eth_hw_addr_set(struct net_device *dev, const u8 *addr)

将以太网地址分配给 net_device

参数

struct net_device *dev

指向 net_device 结构的指针

const u8 *addr

要分配的地址

描述

将给定的地址分配给 net_device,addr_assign_type 不会更改。

void eth_hw_addr_inherit(struct net_device *dst, struct net_device *src)

从另一个 net_device 复制 dev_addr

参数

struct net_device *dst

指向要复制 dev_addr 的 net_device 的指针

struct net_device *src

指向要从中复制 dev_addr 的 net_device 的指针

描述

将以太网地址从一个 net_device 复制到另一个,同时复制地址属性 (addr_assign_type)。

bool ether_addr_equal(const u8 *addr1, const u8 *addr2)

比较两个以太网地址

参数

const u8 *addr1

指向包含以太网地址的六字节数组的指针

const u8 *addr2

指向包含以太网地址的六字节数组的指针

描述

比较两个以太网地址,如果相等则返回 true

请注意:addr1 和 addr2 都必须按 u16 对齐。

bool ether_addr_equal_64bits(const u8 *addr1, const u8 *addr2)

比较两个以太网地址

参数

const u8 *addr1

指向一个 8 字节数组的指针

const u8 *addr2

指向另一个 8 字节数组的指针

描述

比较两个以太网地址,如果相等则返回 true,否则返回 false。

该函数不需要任何条件分支,并且可能在 CPU 上使用字内存访问,从而允许廉价的未对齐内存读取。数组 = { byte1, byte2, byte3, byte4, byte5, byte6, pad1, pad2 }

请注意,addr1 和 addr2 的对齐方式仅保证为 16 位。

bool ether_addr_equal_unaligned(const u8 *addr1, const u8 *addr2)

比较两个未按 u16 对齐的以太网地址

参数

const u8 *addr1

指向包含以太网地址的六字节数组的指针

const u8 *addr2

指向包含以太网地址的六字节数组的指针

描述

比较两个以太网地址,如果相等则返回 true

请注意:仅当任何以太网地址可能未按 u16 对齐时才使用。

bool ether_addr_equal_masked(const u8 *addr1, const u8 *addr2, const u8 *mask)

使用掩码比较两个以太网地址

参数

const u8 *addr1

指向包含第一个以太网地址的六字节数组的指针

const u8 *addr2

指向包含第二个以太网地址的六字节数组的指针

const u8 *mask

指向包含以太网地址位掩码的六字节数组的指针

描述

使用掩码比较两个以太网地址,如果位掩码中设置的每个位在以太网地址中的等效位都相等,则返回 true。使用所有位都设置的掩码是速度较慢的 ether_addr_equal。

u64 ether_addr_to_u64(const u8 *addr)

将以太网地址转换为 u64 值。

参数

const u8 *addr

指向包含以太网地址的六字节数组的指针

描述

返回地址的 u64 值

void u64_to_ether_addr(u64 u, u8 *addr)

将 u64 转换为以太网地址。

参数

u64 u

要转换为以太网 MAC 地址的 u64

u8 *addr

指向包含以太网地址的六字节数组的指针

void eth_addr_dec(u8 *addr)

递减给定的 MAC 地址

参数

u8 *addr

指向包含要递减的以太网地址的六字节数组的指针

void eth_addr_inc(u8 *addr)

递增给定的 MAC 地址。

参数

u8 *addr

指向包含要递增的以太网地址的六字节数组的指针。

void eth_addr_add(u8 *addr, long offset)

将偏移量加到给定的 MAC 地址或从中减去偏移量。

参数

u8 *addr

指向包含要递增的以太网地址的六字节数组的指针。

long offset

要添加的偏移量。

bool is_etherdev_addr(const struct net_device *dev, const u8 addr[6 + 2])

判断给定的以太网地址是否属于该设备。

参数

const struct net_device *dev

指向设备结构的指针

const u8 addr[6 + 2]

指向包含以太网地址的六字节数组的指针

描述

将传递的地址与该设备的所有地址进行比较。如果该地址是该设备的地址之一,则返回 true。

请注意,此函数调用 ether_addr_equal_64bits(),因此请注意正确的填充。

unsigned long compare_ether_header(const void *a, const void *b)

比较两个以太网标头

参数

const void *a

指向以太网标头的指针

const void *b

指向以太网标头的指针

描述

比较两个以太网标头,如果相等则返回 0。这假设网络标头(即 IP 标头)是 4 字节对齐的,或者平台可以处理未对齐的访问。对于所有进入 netif_receive_skb 或类似入口点的包,都是这种情况。

void eth_hw_addr_gen(struct net_device *dev, const u8 *base_addr, unsigned int id)

生成以太网地址并将其分配给端口

参数

struct net_device *dev

指向端口的 net_device 结构的指针

const u8 *base_addr

基本以太网地址

unsigned int id

要添加到基本地址的偏移量

描述

使用基本地址和偏移量生成 MAC 地址并将其分配给 net_device。通常由需要为其所有端口计算地址的交换机驱动程序使用。addr_assign_type 不会更改。

void eth_skb_pkt_type(struct sk_buff *skb, const struct net_device *dev)

如果目标地址不匹配,则分配数据包类型

参数

struct sk_buff *skb

如果地址与 dev 地址不匹配,则分配数据包类型

const struct net_device *dev

用于比较数据包地址的网络设备

描述

如果数据包的目标 MAC 地址与网络设备地址不匹配,则分配适当的数据包类型。

int eth_skb_pad(struct sk_buff *skb)

将缓冲区填充到以太网帧的最小字节数

参数

struct sk_buff *skb

要填充的缓冲区

描述

以太网帧的最小大小应为 60 字节。此函数接收短帧并用零填充它们,直到达到 60 字节的限制。

bool napi_is_scheduled(struct napi_struct *n)

测试 NAPI 是否已调度

参数

struct napi_struct *n

NAPI 上下文

描述

此检查是“尽力而为”。在没有实现锁定的情况下,NAPI 可以在此检查之后立即被调度或终止,并产生不精确的结果。

NAPI_STATE_SCHED 是一个内部状态,通常不应使用 napi_is_scheduled,而应使用 napi_schedule。

仅当驱动程序确实需要检查是否已调度 NAPI 时才使用,例如在延迟定时器的上下文中,如果已调度 NAPI,则可以跳过该定时器。

如果 NAPI 已调度,则返回 True,否则返回 False。

bool napi_schedule(struct napi_struct *n)

调度 NAPI 轮询

参数

struct napi_struct *n

NAPI 上下文

描述

如果 NAPI 轮询例程尚未运行,则调度该例程以进行调用。如果我们调度了 NAPI,则返回 true,否则返回 false。有关为什么可能未调度 NAPI 的其他原因,请参阅 napi_schedule_prep()

void napi_schedule_irqoff(struct napi_struct *n)

调度 NAPI 轮询

参数

struct napi_struct *n

NAPI 上下文

描述

napi_schedule() 的变体,假设已屏蔽硬中断。

bool napi_complete_done(struct napi_struct *n, int work_done)

NAPI 处理完成

参数

struct napi_struct *n

NAPI 上下文

int work_done

已处理的数据包数

描述

将 NAPI 处理标记为完成。仅当尚未完全消耗轮询预算时才应调用。优先于 napi_complete()。如果设备应避免重新激活中断,则返回 false。

void napi_disable(struct napi_struct *n)

阻止 NAPI 调度

参数

struct napi_struct *n

NAPI 上下文

描述

阻止在此上下文中调度 NAPI。等待直到任何未完成的处理完成。

void napi_synchronize(const struct napi_struct *n)

等待直到 NAPI 未运行

参数

const struct napi_struct *n

NAPI 上下文

描述

等待直到 NAPI 完成在此上下文中的调度。等待直到任何未完成的处理完成,但不会禁用未来的激活。

bool napi_if_scheduled_mark_missed(struct napi_struct *n)

如果 napi 正在运行,则设置 NAPIF_STATE_MISSED

参数

struct napi_struct *n

NAPI 上下文

描述

如果 napi 正在运行,则设置 NAPIF_STATE_MISSED,如果 NAPI 已调度,则返回 true。

enum netdev_priv_flags

struct net_device priv_flags

常量

IFF_802_1Q_VLAN

802.1Q VLAN 设备

IFF_EBRIDGE

以太网桥接设备

IFF_BONDING

绑定主设备或从设备

IFF_ISATAP

ISATAP 接口 (RFC4214)

IFF_WAN_HDLC

WAN HDLC 设备

IFF_XMIT_DST_RELEASE

允许 dev_hard_start_xmit() 释放 skb->dst

IFF_DONT_BRIDGE

不允许桥接此以太网设备

IFF_DISABLE_NETPOLL

在运行时禁用 netpoll

IFF_MACVLAN_PORT

用作 macvlan 端口的设备

IFF_BRIDGE_PORT

用作网桥端口的设备

IFF_OVS_DATAPATH

用作 Open vSwitch 数据路径端口的设备

IFF_TX_SKB_SHARING

该接口支持在传输时共享 skb

IFF_UNICAST_FLT

支持单播过滤

IFF_TEAM_PORT

用作团队端口的设备

IFF_SUPP_NOFCS

设备支持发送自定义 FCS

IFF_LIVE_ADDR_CHANGE

设备支持在运行时更改硬件地址

IFF_MACVLAN

Macvlan 设备

IFF_XMIT_DST_RELEASE_PERM

IFF_XMIT_DST_RELEASE 未考虑底层堆叠设备

IFF_L3MDEV_MASTER

设备是 L3 主设备

IFF_NO_QUEUE

设备可以在没有附加 qdisc 的情况下运行

IFF_OPENVSWITCH

设备是 Open vSwitch 主设备

IFF_L3MDEV_SLAVE

设备从属于 L3 主设备

IFF_TEAM

设备是团队设备

IFF_RXFH_CONFIGURED

设备已配置 Rx 流重定向表

IFF_PHONY_HEADROOM

头部空间值由外部实体控制(即桥接 veth 的主设备)

IFF_MACSEC

设备是 MACsec 设备

IFF_NO_RX_HANDLER

设备不支持 rx_handler 挂钩

IFF_FAILOVER

设备是故障转移主设备

IFF_FAILOVER_SLAVE

设备是故障转移主设备的较低设备

IFF_L3MDEV_RX_HANDLER

仅调用 L3 主设备的 rx 处理程序

IFF_NO_ADDRCONF

防止 ipv6 地址配置

IFF_TX_SKB_NO_LINEAR

设备/驱动程序能够传输 skb_headlen(skb) == 0 的帧(数据从 frag0 开始)

描述

这些是 struct net_device,它们仅由驱动程序在内部设置,并在内核中使用。这些标志对用户空间不可见;这意味着这些标志的顺序可以在任何内核版本期间更改。

您应该在 net_device::priv_flags(热路径)或 ::threaded(慢路径)之后添加位域布尔值,而不是扩展这些标志。

struct net_device

DEVICE 结构。

定义:

struct net_device {
    __cacheline_group_begin(net_device_read_tx);
    unsigned long           priv_flags:32;
    unsigned long           lltx:1;
    const struct net_device_ops *netdev_ops;
    const struct header_ops *header_ops;
    struct netdev_queue     *_tx;
    netdev_features_t gso_partial_features;
    unsigned int            real_num_tx_queues;
    unsigned int            gso_max_size;
    unsigned int            gso_ipv4_max_size;
    u16 gso_max_segs;
    s16 num_tc;
    unsigned int            mtu;
    unsigned short          needed_headroom;
    struct netdev_tc_txq    tc_to_txq[TC_MAX_QUEUE];
#ifdef CONFIG_XPS;
    struct xps_dev_maps __rcu *xps_maps[XPS_MAPS_MAX];
#endif;
#ifdef CONFIG_NETFILTER_EGRESS;
    struct nf_hook_entries __rcu *nf_hooks_egress;
#endif;
#ifdef CONFIG_NET_XGRESS;
    struct bpf_mprog_entry __rcu *tcx_egress;
#endif;
    __cacheline_group_end(net_device_read_tx);
    __cacheline_group_begin(net_device_read_txrx);
    union {
        struct pcpu_lstats __percpu             *lstats;
        struct pcpu_sw_netstats __percpu        *tstats;
        struct pcpu_dstats __percpu             *dstats;
    };
    unsigned long           state;
    unsigned int            flags;
    unsigned short          hard_header_len;
    netdev_features_t features;
    struct inet6_dev __rcu  *ip6_ptr;
    __cacheline_group_end(net_device_read_txrx);
    __cacheline_group_begin(net_device_read_rx);
    struct bpf_prog __rcu   *xdp_prog;
    struct list_head        ptype_specific;
    int ifindex;
    unsigned int            real_num_rx_queues;
    struct netdev_rx_queue  *_rx;
    unsigned int            gro_max_size;
    unsigned int            gro_ipv4_max_size;
    rx_handler_func_t __rcu *rx_handler;
    void __rcu              *rx_handler_data;
    possible_net_t nd_net;
#ifdef CONFIG_NETPOLL;
    struct netpoll_info __rcu       *npinfo;
#endif;
#ifdef CONFIG_NET_XGRESS;
    struct bpf_mprog_entry __rcu *tcx_ingress;
#endif;
    __cacheline_group_end(net_device_read_rx);
    char name[IFNAMSIZ];
    struct netdev_name_node *name_node;
    struct dev_ifalias      __rcu *ifalias;
    unsigned long           mem_end;
    unsigned long           mem_start;
    unsigned long           base_addr;
    struct list_head        dev_list;
    struct list_head        napi_list;
    struct list_head        unreg_list;
    struct list_head        close_list;
    struct list_head        ptype_all;
    struct {
        struct list_head upper;
        struct list_head lower;
    } adj_list;
    xdp_features_t xdp_features;
    const struct xdp_metadata_ops *xdp_metadata_ops;
    const struct xsk_tx_metadata_ops *xsk_tx_metadata_ops;
    unsigned short          gflags;
    unsigned short          needed_tailroom;
    netdev_features_t hw_features;
    netdev_features_t wanted_features;
    netdev_features_t vlan_features;
    netdev_features_t hw_enc_features;
    netdev_features_t mpls_features;
    unsigned int            min_mtu;
    unsigned int            max_mtu;
    unsigned short          type;
    unsigned char           min_header_len;
    unsigned char           name_assign_type;
    int group;
    struct net_device_stats stats;
    struct net_device_core_stats __percpu *core_stats;
    atomic_t carrier_up_count;
    atomic_t carrier_down_count;
#ifdef CONFIG_WIRELESS_EXT;
    const struct iw_handler_def *wireless_handlers;
#endif;
    const struct ethtool_ops *ethtool_ops;
#ifdef CONFIG_NET_L3_MASTER_DEV;
    const struct l3mdev_ops *l3mdev_ops;
#endif;
#if IS_ENABLED(CONFIG_IPV6);
    const struct ndisc_ops *ndisc_ops;
#endif;
#ifdef CONFIG_XFRM_OFFLOAD;
    const struct xfrmdev_ops *xfrmdev_ops;
#endif;
#if IS_ENABLED(CONFIG_TLS_DEVICE);
    const struct tlsdev_ops *tlsdev_ops;
#endif;
    unsigned int            operstate;
    unsigned char           link_mode;
    unsigned char           if_port;
    unsigned char           dma;
    unsigned char           perm_addr[MAX_ADDR_LEN];
    unsigned char           addr_assign_type;
    unsigned char           addr_len;
    unsigned char           upper_level;
    unsigned char           lower_level;
    unsigned short          neigh_priv_len;
    unsigned short          dev_id;
    unsigned short          dev_port;
    int irq;
    u32 priv_len;
    spinlock_t addr_list_lock;
    struct netdev_hw_addr_list      uc;
    struct netdev_hw_addr_list      mc;
    struct netdev_hw_addr_list      dev_addrs;
#ifdef CONFIG_SYSFS;
    struct kset             *queues_kset;
#endif;
#ifdef CONFIG_LOCKDEP;
    struct list_head        unlink_list;
#endif;
    unsigned int            promiscuity;
    unsigned int            allmulti;
    bool uc_promisc;
#ifdef CONFIG_LOCKDEP;
    unsigned char           nested_level;
#endif;
    struct in_device __rcu  *ip_ptr;
    struct hlist_head       fib_nh_head;
#if IS_ENABLED(CONFIG_VLAN_8021Q);
    struct vlan_info __rcu  *vlan_info;
#endif;
#if IS_ENABLED(CONFIG_NET_DSA);
    struct dsa_port         *dsa_ptr;
#endif;
#if IS_ENABLED(CONFIG_TIPC);
    struct tipc_bearer __rcu *tipc_ptr;
#endif;
#if IS_ENABLED(CONFIG_ATALK);
    void *atalk_ptr;
#endif;
#if IS_ENABLED(CONFIG_AX25);
    void *ax25_ptr;
#endif;
#if IS_ENABLED(CONFIG_CFG80211);
    struct wireless_dev     *ieee80211_ptr;
#endif;
#if IS_ENABLED(CONFIG_IEEE802154) || IS_ENABLED(CONFIG_6LOWPAN);
    struct wpan_dev         *ieee802154_ptr;
#endif;
#if IS_ENABLED(CONFIG_MPLS_ROUTING);
    struct mpls_dev __rcu   *mpls_ptr;
#endif;
#if IS_ENABLED(CONFIG_MCTP);
    struct mctp_dev __rcu   *mctp_ptr;
#endif;
    const unsigned char     *dev_addr;
    unsigned int            num_rx_queues;
#define GRO_LEGACY_MAX_SIZE     65536u;
#define GRO_MAX_SIZE            (8 * 65535u);
    unsigned int            xdp_zc_max_segs;
    struct netdev_queue __rcu *ingress_queue;
#ifdef CONFIG_NETFILTER_INGRESS;
    struct nf_hook_entries __rcu *nf_hooks_ingress;
#endif;
    unsigned char           broadcast[MAX_ADDR_LEN];
#ifdef CONFIG_RFS_ACCEL;
    struct cpu_rmap         *rx_cpu_rmap;
#endif;
    struct hlist_node       index_hlist;
    unsigned int            num_tx_queues;
    struct Qdisc __rcu      *qdisc;
    unsigned int            tx_queue_len;
    spinlock_t tx_global_lock;
    struct xdp_dev_bulk_queue __percpu *xdp_bulkq;
#ifdef CONFIG_NET_SCHED;
    unsigned long qdisc_hash[1 << ((4) - 1)];
#endif;
    struct timer_list       watchdog_timer;
    int watchdog_timeo;
    u32 proto_down_reason;
    struct list_head        todo_list;
#ifdef CONFIG_PCPU_DEV_REFCNT;
    int __percpu            *pcpu_refcnt;
#else;
    refcount_t dev_refcnt;
#endif;
    struct ref_tracker_dir  refcnt_tracker;
    struct list_head        link_watch_list;
    u8 reg_state;
    bool dismantle;
    enum {
        RTNL_LINK_INITIALIZED,
        RTNL_LINK_INITIALIZING,
    } rtnl_link_state:16;
    bool needs_free_netdev;
    void (*priv_destructor)(struct net_device *dev);
    void *ml_priv;
    enum netdev_ml_priv_type        ml_priv_type;
    enum netdev_stat_type           pcpu_stat_type:8;
#if IS_ENABLED(CONFIG_GARP);
    struct garp_port __rcu  *garp_port;
#endif;
#if IS_ENABLED(CONFIG_MRP);
    struct mrp_port __rcu   *mrp_port;
#endif;
#if IS_ENABLED(CONFIG_NET_DROP_MONITOR);
    struct dm_hw_stat_delta __rcu *dm_private;
#endif;
    struct device           dev;
    const struct attribute_group *sysfs_groups[4];
    const struct attribute_group *sysfs_rx_queue_group;
    const struct rtnl_link_ops *rtnl_link_ops;
    const struct netdev_stat_ops *stat_ops;
    const struct netdev_queue_mgmt_ops *queue_mgmt_ops;
#define GSO_MAX_SEGS            65535u;
#define GSO_LEGACY_MAX_SIZE     65536u;
#define GSO_MAX_SIZE            (8 * GSO_MAX_SEGS);
#define TSO_LEGACY_MAX_SIZE     65536;
#define TSO_MAX_SIZE            UINT_MAX;
    unsigned int            tso_max_size;
#define TSO_MAX_SEGS            U16_MAX;
    u16 tso_max_segs;
#ifdef CONFIG_DCB;
    const struct dcbnl_rtnl_ops *dcbnl_ops;
#endif;
    u8 prio_tc_map[TC_BITMASK + 1];
#if IS_ENABLED(CONFIG_FCOE);
    unsigned int            fcoe_ddp_xid;
#endif;
#if IS_ENABLED(CONFIG_CGROUP_NET_PRIO);
    struct netprio_map __rcu *priomap;
#endif;
    struct phy_link_topology        *link_topo;
    struct phy_device       *phydev;
    struct sfp_bus          *sfp_bus;
    struct lock_class_key   *qdisc_tx_busylock;
    bool proto_down;
    bool threaded;
    unsigned long           see_all_hwtstamp_requests:1;
    unsigned long           change_proto_down:1;
    unsigned long           netns_local:1;
    unsigned long           fcoe_mtu:1;
    struct list_head        net_notifier_list;
#if IS_ENABLED(CONFIG_MACSEC);
    const struct macsec_ops *macsec_ops;
#endif;
    const struct udp_tunnel_nic_info        *udp_tunnel_nic_info;
    struct udp_tunnel_nic   *udp_tunnel_nic;
    struct ethtool_netdev_state *ethtool;
    struct bpf_xdp_entity   xdp_state[__MAX_XDP_MODE];
    u8 dev_addr_shadow[MAX_ADDR_LEN];
    netdevice_tracker linkwatch_dev_tracker;
    netdevice_tracker watchdog_dev_tracker;
    netdevice_tracker dev_registered_tracker;
    struct rtnl_hw_stats64  *offload_xstats_l3;
    struct devlink_port     *devlink_port;
#if IS_ENABLED(CONFIG_DPLL);
    struct dpll_pin __rcu   *dpll_pin;
#endif;
#if IS_ENABLED(CONFIG_PAGE_POOL);
    struct hlist_head       page_pools;
#endif;
    struct dim_irq_moder    *irq_moder;
    u64 max_pacing_offload_horizon;
    struct napi_config      *napi_config;
    unsigned long           gro_flush_timeout;
    u32 napi_defer_hard_irqs;
    struct mutex            lock;
#if IS_ENABLED(CONFIG_NET_SHAPER);
    struct net_shaper_hierarchy *net_shaper_hierarchy;
#endif;
    struct hlist_head neighbours[NEIGH_NR_TABLES];
    u8 priv[]  ;
};

成员

priv_flags

对用户空间不可见的标志,定义为位,有关定义,请参阅 enum netdev_priv_flags

lltx

设备支持无锁 Tx。不推荐用于真正的硬件驱动程序。主要用于逻辑接口,例如绑定和隧道

netdev_ops

包括指向回调的多个指针,如果有人想覆盖 ndo_*() 函数

header_ops

包括用于创建、解析、缓存等第 2 层标头的回调。

_tx

TX 队列数组

gso_partial_features

来自 NETIF_F_GSO* 的值

real_num_tx_queues

设备中当前处于活动状态的 TX 队列的数量

gso_max_size

通用分段卸载的最大大小

gso_ipv4_max_size

IPv4 的通用分段卸载的最大大小。

gso_max_segs

可以传递给网卡进行 GSO 的最大分段数

num_tc

网络设备中的流量类别数

mtu

接口 MTU 值

needed_headroom

硬件可能需要的额外头部空间,但并非所有情况下都能保证

tc_to_txq

XXX:需要对此进行注释

xps_maps

XXX:需要对此进行注释

nf_hooks_egress

为出口数据包执行的网络过滤器钩子

tcx_egress

用于出口处理的 BPF 和 clsact qdisc 特定数据

{unnamed_union}

匿名

lstats

环回统计信息:数据包、字节

tstats

隧道统计信息:RX/TX 数据包、RX/TX 字节

dstats

虚拟统计信息:RX/TX/丢弃数据包、RX/TX 字节

state

通用网络排队层状态,请参阅 netdev_state_t

flags

接口标志(类似于 BSD)

hard_header_len

最大硬件标头长度。

features

当前活动的设备功能

ip6_ptr

IPv6 特定数据

xdp_prog

XDP 套接字过滤器程序指针

ptype_specific

设备特定的协议特定数据包处理程序

ifindex

接口索引

real_num_rx_queues

设备中当前活动的 RX 队列数

_rx

RX 队列数组

gro_max_size

通用接收卸载 (GRO) 中聚合数据包的最大大小

gro_ipv4_max_size

IPv4 的通用接收卸载 (GRO) 中聚合数据包的最大大小。

rx_handler

接收数据包的处理程序

rx_handler_data

XXX:需要对此进行注释

nd_net

此网络设备所在的网络命名空间

npinfo

XXX:需要对此进行注释

tcx_ingress

用于入口处理的 BPF 和 clsact qdisc 特定数据

name

这是此结构“可见”部分(即用户在“Space.c”文件中看到的部分)的第一个字段。它是接口的名称。

name_node

名称哈希列表节点

ifalias

SNMP 别名

mem_end

共享内存结束

mem_start

共享内存开始

base_addr

设备 I/O 地址

dev_list

网络设备的全局列表

napi_list

用于轮询 NAPI 设备的列表条目

unreg_list

当我们注销设备时的列表条目;请参阅函数 unregister_netdev

close_list

当关闭设备时使用的列表条目

ptype_all

所有协议的设备特定数据包处理程序

adj_list

直接链接的设备,如用于绑定的从设备

xdp_features

设备支持的 XDP 功能

xdp_metadata_ops

包括指向 XDP 元数据回调的指针。

xsk_tx_metadata_ops

包括指向 AF_XDP TX 元数据回调的指针。

gflags

全局标志(保留为传统标志)

needed_tailroom

硬件可能需要的额外尾部空间,但并非所有情况下都能保证。某些情况下还会使用 LL_MAX_HEADER 来分配 skb

interface address info

hw_features

用户可更改的功能

wanted_features

用户请求的功能

vlan_features

VLAN 设备可继承的功能掩码

hw_enc_features

封装设备继承的功能掩码。此字段指示硬件能够执行哪些封装卸载,驱动程序需要适当地设置它们。

mpls_features

MPLS 可继承的功能掩码

min_mtu

接口最小 MTU 值

max_mtu

接口最大 MTU 值

type

接口硬件类型

min_header_len

最小硬件标头长度

name_assign_type

网络接口名称分配类型

group

设备所属的组

stats

统计信息结构,已作为传统结构保留,请改用 rtnl_link_stats64

core_stats

核心网络计数器,请勿在驱动程序中使用

carrier_up_count

载波已启动的次数

carrier_down_count

载波已关闭的次数

wireless_handlers

处理无线扩展的函数列表,而不是 ioctl,有关详细信息,请参阅 <net/iw_handler.h>。

ethtool_ops

管理操作

l3mdev_ops

第 3 层主设备操作

ndisc_ops

包括用于不同 IPv6 邻居发现处理的回调。例如,6LoWPAN 是必需的。

xfrmdev_ops

转换卸载操作

tlsdev_ops

传输层安全卸载操作

operstate

RFC2863 操作状态

link_mode

操作状态的映射策略

if_port

可选的 AUI、TP 等

dma

DMA 通道

perm_addr

永久硬件地址

addr_assign_type

硬件地址分配类型

addr_len

硬件地址长度

upper_level

上层设备的最大深度级别。

lower_level

下层设备的最大深度级别。

neigh_priv_len

在 neigh_alloc() 中使用

dev_id

用于区分共享同一链路层地址的设备

dev_port

用于区分共享同一功能的设备

irq

设备 IRQ 号

priv_len

->priv 灵活数组的大小

addr_list_lock

XXX:需要对此进行注释

uc

单播 MAC 地址

mc

多播 MAC 地址

dev_addrs

设备硬件地址列表

queues_kset

Tx 和 RX 队列中所有 Kobject 的组

unlink_list

由于可以递归调用 netif_addr_lock(),请保留要删除的接口列表。

promiscuity

NIC 被告知以混杂模式工作的次数;如果变为 0,则 NIC 将退出混杂模式

allmulti

计数器,启用或禁用 allmulticast 模式

uc_promisc

计数器,指示由于需要侦听不支持 ndo_set_rx_mode() 的设备中的其他单播地址而启用了混杂模式

nested_level

用作 dev->addr_list_lock 的 spin_lock_nested() 的参数。

ip_ptr

IPv4 特定数据

fib_nh_head

与此 netdev 关联的下一跳

vlan_info

VLAN 信息

dsa_ptr

dsa 特定数据

tipc_ptr

TIPC 特定数据

atalk_ptr

AppleTalk 链接

ax25_ptr

AX.25 特定数据

ieee80211_ptr

IEEE 802.11 特定数据,在注册之前分配

ieee802154_ptr

IEEE 802.15.4 低速无线个域网设备结构

mpls_ptr

mpls_dev 结构指针

mctp_ptr

MCTP 特定数据

dev_addr

硬件地址(在 bcast 之前,因为大多数数据包是单播)

num_rx_queues

register_netdev() 时分配的 RX 队列数

xdp_zc_max_segs

AF_XDP 零拷贝驱动程序支持的最大分段数

ingress_queue

XXX:需要对此进行注释

nf_hooks_ingress

为入口数据包执行的网络过滤器钩子

broadcast

硬件广播地址

rx_cpu_rmap

RX 完成中断的 CPU 反向映射,按 RX 队列号编制索引。由驱动程序分配。仅当定义了 ndo_rx_flow_steer 操作时,才必须设置此项

index_hlist

设备索引哈希链

num_tx_queues

在 alloc_netdev_mq() 时分配的 TX 队列数

qdisc

从用户空间角度来看的根 qdisc

tx_queue_len

允许的每个队列的最大帧数

tx_global_lock

XXX:需要对此进行注释

xdp_bulkq

XDP 设备批量队列

qdisc_hash

qdisc 哈希表

watchdog_timer

计时器列表

watchdog_timeo

表示看门狗使用的超时(请参阅 dev_watchdog())

proto_down_reason

netdev 接口被保持关闭的原因

todo_list

延迟注册/注销

pcpu_refcnt

对此设备的引用数

dev_refcnt

对此设备的引用数

refcnt_tracker

此设备跟踪引用的跟踪器目录

link_watch_list

XXX:需要对此进行注释

reg_state

注册/注销状态机

dismantle

设备即将被释放

rtnl_link_state

此枚举表示创建新链路的阶段

needs_free_netdev

注销是否应执行 free_netdev?

priv_destructor

从注销调用

ml_priv

中间层私有

ml_priv_type

中间层私有类型

pcpu_stat_type

核心应分配/释放的设备统计信息类型:none、lstats、tstats、dstats。none 表示驱动程序在内部处理统计信息的分配/释放。

garp_port

GARP

mrp_port

MRP

dm_private

丢弃监视器私有

dev

类/网络/名称条目

sysfs_groups

用于可选设备、统计信息和无线 sysfs 组的空间

sysfs_rx_queue_group

用于可选的每个 rx 队列属性的空间

rtnl_link_ops

Rtnl_link_ops

stat_ops

用于队列感知统计信息的可选操作

queue_mgmt_ops

用于队列管理的可选操作

tso_max_size

设备(如硬件)对最大 TSO 请求大小的限制

tso_max_segs

设备(如硬件)对最大 TSO 分段计数的限制

dcbnl_ops

数据中心桥接 netlink 操作

prio_tc_map

XXX:需要对此进行注释

fcoe_ddp_xid

通过 ddp 进行 FCoE LRO 的最大交换 ID

priomap

XXX:需要对此进行注释

link_topo

物理链路拓扑跟踪附加的 PHY

phydev

物理设备可能会自行附加以进行硬件时间戳处理

sfp_bus

附加的 struct sfp_bus 结构。

qdisc_tx_busylock

注释 Qdisc->busylock 自旋锁的 lockdep 类

proto_down

协议端口状态信息可以发送到交换机驱动程序,并用于设置交换机端口的物理状态。

threaded

已启用 NAPI 线程模式

see_all_hwtstamp_requests

设备希望看到对 ndo_hwtstamp_set() 的调用,以处理所有时间戳请求,而不管来源如何,即使这些请求不是 HWTSTAMP_SOURCE_NETDEV

change_proto_down

设备支持通过 IFLA_PROTO_DOWN 设置载波

netns_local

接口无法更改网络命名空间

fcoe_mtu

设备支持的最大 FCoE MTU 为 2158 字节

net_notifier_list

当设备移动到另一个网络命名空间时,跟随该设备的每个网络设备通知器块的列表。

macsec_ops

MACsec 卸载操作

udp_tunnel_nic_info

描述设备的 UDP 隧道卸载功能的静态结构

udp_tunnel_nic

UDP 隧道卸载状态

ethtool

ethtool 相关状态

xdp_state

存储有关附加的 XDP BPF 程序的信息

dev_addr_shadow

dev_addr 的副本,用于捕获直接写入。

linkwatch_dev_tracker

linkwatch 使用的引用计数跟踪器。

watchdog_dev_tracker

watchdog 使用的引用计数跟踪器。

dev_registered_tracker

注册时保持的引用跟踪器

offload_xstats_l3

此网络设备的 L3 硬件统计信息。

devlink_port

指向相关的 devlink 端口结构的指针。在使用 SET_NETDEV_DEVLINK_PORT 宏注册网络设备之前,由驱动程序分配。在网络设备注册期间,此指针是静态的。

dpll_pin

指向 DPLL 子系统的 SyncE 源引脚的指针,时钟在此处恢复。

page_pools

为此网络设备创建的页面池

irq_moder

如果启用了 IS_ENABLED(CONFIG_DIMLIB),则使用 dim 参数。

max_pacing_offload_horizon

最大 EDT 卸载范围,以纳秒为单位。

napi_config

包含每个 NAPI 设置的 napi_config 结构数组。

gro_flush_timeout

NAPI 中 GRO 层的超时时间

napi_defer_hard_irqs

如果非零,则提供一个计数器,该计数器允许避免在繁忙队列上产生 NIC 硬中断。

lock

保护 net_shaper_hierarchy,请随意使用进行其他网络设备范围的保护。顺序:在 rtnl_lock 之后获取。

net_shaper_hierarchy
跟踪当前整形器状态的数据

请参阅 include/net/net_shapers.h

neighbours

指向此设备的邻居 dev_list 的列表头,每个地址族一个。

FIXME:清理 struct net_device,以便网络协议信息移出。

priv

包含私有数据的可变数组

描述

实际上,整个结构是一个大错误。它将 I/O 数据与严格的“高级”数据混合在一起,并且必须了解 INET 模块中使用的几乎每个数据结构。

void *netdev_priv(const struct net_device *dev)

访问网络设备私有数据

参数

const struct net_device *dev

网络设备

描述

获取网络设备私有数据

void netif_napi_add(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct*, int))

初始化 NAPI 上下文

参数

struct net_device *dev

网络设备

struct napi_struct *napi

NAPI 上下文

int (*poll)(struct napi_struct *, int)

轮询函数

描述

必须在调用任何其他 NAPI 相关函数之前使用 netif_napi_add() 来初始化 NAPI 上下文。

void netif_napi_add_config(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct*, int), int index)

使用持久配置初始化 NAPI 上下文

参数

struct net_device *dev

网络设备

struct napi_struct *napi

NAPI 上下文

int (*poll)(struct napi_struct *, int)

轮询函数

int index

NAPI 索引

void netif_napi_add_tx(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct*, int))

初始化一个仅用于 Tx 的 NAPI 上下文

参数

struct net_device *dev

网络设备

struct napi_struct *napi

NAPI 上下文

int (*poll)(struct napi_struct *, int)

轮询函数

描述

对于使用 NAPI 独占轮询 TX 队列的驱动程序,应使用此 netif_napi_add() 变体。这将避免我们将其添加到 napi_hash[] 中,从而污染此哈希表。

void __netif_napi_del(struct napi_struct *napi)

删除 NAPI 上下文

参数

struct napi_struct *napi

NAPI 上下文

描述

警告:调用者必须在释放包含 napi 的内存之前观察 RCU 宽限期。驱动程序可能希望调用此帮助程序,以将所有需要的 RCU 宽限期合并为一个。

void netif_napi_del(struct napi_struct *napi)

删除 NAPI 上下文

参数

struct napi_struct *napi

NAPI 上下文

netif_napi_del() 从网络设备 NAPI 列表中删除 NAPI 上下文

void netif_start_queue(struct net_device *dev)

允许传输

参数

struct net_device *dev

网络设备

允许上层调用设备 hard_start_xmit 例程。

void netif_wake_queue(struct net_device *dev)

重新启动传输

参数

struct net_device *dev

网络设备

允许上层调用设备 hard_start_xmit 例程。当传输资源可用时,用于流量控制。

void netif_stop_queue(struct net_device *dev)

停止传输的数据包

参数

struct net_device *dev

网络设备

阻止上层调用设备 hard_start_xmit 例程。当传输资源不可用时,用于流量控制。

bool netif_queue_stopped(const struct net_device *dev)

测试传输队列是否被阻塞

参数

const struct net_device *dev

网络设备

测试设备上的传输队列当前是否无法发送。

void netdev_queue_set_dql_min_limit(struct netdev_queue *dev_queue, unsigned int min_limit)

设置 dql 最小值

参数

struct netdev_queue *dev_queue

指向传输队列的指针

unsigned int min_limit

dql 最小值

描述

强制 xmit_more() 返回 true,直到达到 min_limit 定义的最小阈值(或直到 tx 队列为空)。警告:请谨慎使用,滥用会影响延迟。

void netdev_txq_bql_enqueue_prefetchw(struct netdev_queue *dev_queue)

预取 bql 数据以进行写入

参数

struct netdev_queue *dev_queue

指向传输队列的指针

描述

启用 BQL 的驱动程序可以在其 ndo_start_xmit() 中使用此辅助函数,以便为 CPU 提供适当的提示。

void netdev_txq_bql_complete_prefetchw(struct netdev_queue *dev_queue)

预取 bql 数据以进行写入

参数

struct netdev_queue *dev_queue

指向传输队列的指针

描述

启用 BQL 的驱动程序可以在其 TX 完成路径中使用此辅助函数,以便为 CPU 提供适当的提示。

void netdev_tx_sent_queue(struct netdev_queue *dev_queue, unsigned int bytes)

报告排队到给定 tx 队列的字节数

参数

struct netdev_queue *dev_queue

网络设备队列

unsigned int bytes

排队到设备队列的字节数

报告排队到网络设备硬件队列以进行发送/完成的字节数。bytes 应该是一个很好的近似值,并且应该与 netdev_completed_queue() 中的 bytes 完全匹配。这通常在每个数据包中调用一次,从 ndo_start_xmit() 中调用。

void netdev_sent_queue(struct net_device *dev, unsigned int bytes)

报告排队到硬件的字节数

参数

struct net_device *dev

网络设备

unsigned int bytes

排队到硬件设备队列的字节数

报告排队到网络设备硬件队列 #0 以进行发送/完成的字节数。bytes 应该是一个很好的近似值,并且应该与 netdev_completed_queue() 中的 bytes 完全匹配。这通常在每个数据包中调用一次,从 ndo_start_xmit() 中调用。

void netdev_tx_completed_queue(struct netdev_queue *dev_queue, unsigned int pkts, unsigned int bytes)

报告 TX 完成时的数据包/字节数。

参数

struct netdev_queue *dev_queue

网络设备队列

unsigned int pkts

数据包数量(当前忽略)

unsigned int bytes

从设备队列中出队的字节数

必须在每次 TX 完成循环中最多调用一次(而不是每个单独的数据包),以便 BQL 可以适当地调整其限制。

void netdev_completed_queue(struct net_device *dev, unsigned int pkts, unsigned int bytes)

报告设备完成的字节和数据包

参数

struct net_device *dev

网络设备

unsigned int pkts

通过介质发送的实际数据包数

unsigned int bytes

通过介质发送的实际字节数

报告网络设备硬件队列通过物理介质传输的字节数和数据包数,bytes 必须与传递给 netdev_sent_queue()bytes 量完全匹配

void netdev_tx_reset_subqueue(const struct net_device *dev, u32 qid)

重置 netdev 队列的 BQL 统计信息和状态

参数

const struct net_device *dev

网络设备

u32 qid

要重置的队列的堆栈索引

void netdev_reset_queue(struct net_device *dev_queue)

重置网络设备的数据包和字节计数

参数

struct net_device *dev_queue

网络设备

重置网络设备的字节和数据包计数,并清除此网络设备的软件流控制 OFF 位

u16 netdev_cap_txqueue(struct net_device *dev, u16 queue_index)

检查所选 tx 队列是否超出设备队列

参数

struct net_device *dev

网络设备

u16 queue_index

给定的 tx 队列索引

如果给定的 tx 队列索引 >= 设备 tx 队列数,则返回 0,否则返回原始传递的 tx 队列索引。

bool netif_running(const struct net_device *dev)

测试是否已启动

参数

const struct net_device *dev

网络设备

测试设备是否已启动。

void netif_start_subqueue(struct net_device *dev, u16 queue_index)

允许在子队列上发送数据包

参数

struct net_device *dev

网络设备

u16 queue_index

子队列索引

描述

启动具有多个传输队列的设备的单个传输队列。

void netif_stop_subqueue(struct net_device *dev, u16 queue_index)

停止在子队列上发送数据包

参数

struct net_device *dev

网络设备

u16 queue_index

子队列索引

描述

停止具有多个传输队列的设备的单个传输队列。

bool __netif_subqueue_stopped(const struct net_device *dev, u16 queue_index)

测试子队列的状态

参数

const struct net_device *dev

网络设备

u16 queue_index

子队列索引

描述

检查具有多个传输队列的设备的单个传输队列。

bool netif_subqueue_stopped(const struct net_device *dev, struct sk_buff *skb)

测试子队列的状态

参数

const struct net_device *dev

网络设备

struct sk_buff *skb

子队列缓冲区指针

描述

检查具有多个传输队列的设备的单个传输队列。

void netif_wake_subqueue(struct net_device *dev, u16 queue_index)

允许在子队列上发送数据包

参数

struct net_device *dev

网络设备

u16 queue_index

子队列索引

描述

恢复具有多个传输队列的设备的单个传输队列。

bool netif_attr_test_mask(unsigned long j, const unsigned long *mask, unsigned int nr_bits)

测试掩码中是否设置了 CPU 或 Rx 队列

参数

unsigned long j

CPU/Rx 队列索引

const unsigned long *mask

所有 CPU/Rx 队列的位掩码

unsigned int nr_bits

位掩码中的位数

描述

测试是否在所有 CPU/Rx 队列的掩码中设置了 CPU 或 Rx 队列索引。

bool netif_attr_test_online(unsigned long j, const unsigned long *online_mask, unsigned int nr_bits)

测试在线 CPU/Rx 队列

参数

unsigned long j

CPU/Rx 队列索引

const unsigned long *online_mask

在线 CPU/Rx 队列的位掩码

unsigned int nr_bits

位掩码中的位数

描述

如果 CPU/Rx 队列在线,则返回 true。

unsigned int netif_attrmask_next(int n, const unsigned long *srcp, unsigned int nr_bits)

获取 CPU/Rx 队列掩码中的下一个 CPU/Rx 队列

参数

int n

CPU/Rx 队列索引

const unsigned long *srcp

cpumask/Rx 队列掩码指针

unsigned int nr_bits

位掩码中的位数

描述

如果没有设置更多 CPU/Rx 队列,则返回 >= nr_bits。

int netif_attrmask_next_and(int n, const unsigned long *src1p, const unsigned long *src2p, unsigned int nr_bits)

获取 *src1p & *src2p 中的下一个 CPU/Rx 队列

参数

int n

CPU/Rx 队列索引

const unsigned long *src1p

第一个 CPU/Rx 队列掩码指针

const unsigned long *src2p

第二个 CPU/Rx 队列掩码指针

unsigned int nr_bits

位掩码中的位数

描述

如果两个掩码中都没有设置更多 CPU/Rx 队列,则返回 >= nr_bits。

bool netif_is_multiqueue(const struct net_device *dev)

测试设备是否具有多个传输队列

参数

const struct net_device *dev

网络设备

描述

检查设备是否具有多个传输队列

void dev_hold(struct net_device *dev)

获取对设备的引用

参数

struct net_device *dev

网络设备

描述

保持对设备的引用,防止它被释放。尝试使用 netdev_hold() 代替。

void dev_put(struct net_device *dev)

释放对设备的引用

参数

struct net_device *dev

网络设备

描述

释放对设备的引用,允许它被释放。尝试使用 netdev_put() 代替。

void linkwatch_sync_dev(struct net_device *dev)

同步给定设备的 linkwatch

参数

struct net_device *dev

要同步 linkwatch 的网络设备

描述

同步给定设备的 linkwatch,将其从待处理工作列表中移除(如果已排队)。

bool netif_carrier_ok(const struct net_device *dev)

测试是否连接载波

参数

const struct net_device *dev

网络设备

描述

检查设备上是否存在载波

void netif_dormant_on(struct net_device *dev)

将设备标记为休眠。

参数

struct net_device *dev

网络设备

描述

根据 RFC2863,将设备标记为休眠。

休眠状态表示相关接口实际上没有处于传递数据包的条件(即,它不是“up”),而是处于“挂起”状态,等待一些外部事件。对于“按需”接口,此新状态标识接口正在等待事件使其进入 up 状态的情况。

void netif_dormant_off(struct net_device *dev)

将设备设置为非休眠状态。

参数

struct net_device *dev

网络设备

描述

设备未处于休眠状态。

bool netif_dormant(const struct net_device *dev)

测试设备是否处于休眠状态

参数

const struct net_device *dev

网络设备

描述

检查设备是否处于休眠状态。

void netif_testing_on(struct net_device *dev)

将设备标记为正在测试中。

参数

struct net_device *dev

网络设备

描述

根据 RFC2863,将设备标记为正在测试中。

测试状态表示必须在接口上执行一些测试。测试完成后,接口状态将根据需要更改为 up、dormant 或 down。

void netif_testing_off(struct net_device *dev)

将设备设置为不在测试中。

参数

struct net_device *dev

网络设备

描述

设备未处于测试状态。

bool netif_testing(const struct net_device *dev)

测试设备是否正在测试中

参数

const struct net_device *dev

网络设备

描述

检查设备是否正在测试中

bool netif_oper_up(const struct net_device *dev)

测试设备是否可操作

参数

const struct net_device *dev

网络设备

描述

检查载波是否可操作

bool netif_device_present(const struct net_device *dev)

设备是否可用或已移除

参数

const struct net_device *dev

网络设备

描述

检查设备是否已从系统中移除。

void netif_tx_lock(struct net_device *dev)

获取网络设备发送锁

参数

struct net_device *dev

网络设备

描述

获取网络设备发送锁

int __dev_uc_sync(struct net_device *dev, int (*sync)(struct net_device*, const unsigned char*), int (*unsync)(struct net_device*, const unsigned char*))

同步设备的单播列表

参数

struct net_device *dev

要同步的设备

int (*sync)(struct net_device *, const unsigned char *)

如果应添加地址,则调用的函数

int (*unsync)(struct net_device *, const unsigned char *)

如果应删除地址,则调用的函数

将新添加的地址添加到接口,并释放已删除的地址。

void __dev_uc_unsync(struct net_device *dev, int (*unsync)(struct net_device*, const unsigned char*))

从设备中删除同步的地址

参数

struct net_device *dev

要同步的设备

int (*unsync)(struct net_device *, const unsigned char *)

如果应删除地址,则调用的函数

删除由 dev_uc_sync() 添加到设备的所有地址。

int __dev_mc_sync(struct net_device *dev, int (*sync)(struct net_device*, const unsigned char*), int (*unsync)(struct net_device*, const unsigned char*))

同步设备的多播列表

参数

struct net_device *dev

要同步的设备

int (*sync)(struct net_device *, const unsigned char *)

如果应添加地址,则调用的函数

int (*unsync)(struct net_device *, const unsigned char *)

如果应删除地址,则调用的函数

将新添加的地址添加到接口,并释放已删除的地址。

void __dev_mc_unsync(struct net_device *dev, int (*unsync)(struct net_device*, const unsigned char*))

从设备中删除同步的地址

参数

struct net_device *dev

要同步的设备

int (*unsync)(struct net_device *, const unsigned char *)

如果应删除地址,则调用的函数

删除由 dev_mc_sync() 添加到设备的所有地址。

struct net_shaper

表示 NIC H/W 上的整形节点,清零的字段被认为未设置。

定义:

struct net_shaper {
    struct net_shaper_handle parent;
    struct net_shaper_handle handle;
    enum net_shaper_metric metric;
    u64 bw_min;
    u64 bw_max;
    u64 burst;
    u32 priority;
    u32 weight;
};

成员

父节点

整形器父节点的唯一标识符,通常是隐式的

句柄

此整形器的唯一标识符

指标

指定速率限制是指 PPS 还是 BPS

bw_min

此整形器的最小保证速率

bw_max

此整形器允许的最大峰值速率

突发

此整形器的峰值速率的最大突发

priority

此整形器的调度优先级

权重

此整形器的调度权重

struct net_shaper_ops

设备 H/W 整形器的操作

定义:

struct net_shaper_ops {
    int (*group)(struct net_shaper_binding *binding, int leaves_count,const struct net_shaper *leaves,const struct net_shaper *node, struct netlink_ext_ack *extack);
    int (*set)(struct net_shaper_binding *binding,const struct net_shaper *shaper, struct netlink_ext_ack *extack);
    int (*delete)(struct net_shaper_binding *binding,const struct net_shaper_handle *handle, struct netlink_ext_ack *extack);
    void (*capabilities)(struct net_shaper_binding *binding, enum net_shaper_scope scope, unsigned long *cap);
};

成员

group

创建指定的整形器调度组

将 * **node** 整形器下标识的 leaves 整形器嵌套。所有整形器都属于由 binding 指定的设备。 leaves 数组的大小由 leaves_count 指定。创建 leavesnode 整形器;或者如果它们已存在,则以所需的方式将它们链接在一起。 leaves 的范围必须为 NET_SHAPER_SCOPE_QUEUE。

设置

更新指定的整形器

更新或创建由 binding 指定的设备上的 shaper

删除

删除指定的整形器

删除由给定 handle 标识的,由 binding 指定的设备上的整形器配置,恢复默认行为。

功能

获取设备支持的整形器功能

scope 和由 binding 指定的设备的受支持功能填充位掩码 cap

描述

这些操作适用于 net_device 和 devlink 对象。设备初始化时的初始整形配置为空:不以任何方式限制速率。网络核心会在 net_device 或 devlink 结构中跟踪已应用的用户配置。操作通过每个设备的锁进行序列化。

不支持任何形式嵌套的设备不应提供分组操作。

每个整形器在设备内都用一个“句柄”唯一标识,该“句柄”包含整形器范围和特定于范围的 ID。

PHY 支持

void phy_print_status(struct phy_device *phydev)

打印当前 phy 状态的便捷函数

参数

struct phy_device *phydev

phy_device 结构

int phy_get_rate_matching(struct phy_device *phydev, phy_interface_t iface)

确定是否支持速率匹配

参数

struct phy_device *phydev

要返回速率匹配的 phy 设备

phy_interface_t iface

要使用的接口模式

描述

这将确定 **phy** 使用 **iface** 支持的速率匹配类型(如果有)。 iface 可以是 PHY_INTERFACE_MODE_NA 来确定是否有任何接口支持速率匹配。

返回

phyiface 支持的速率匹配类型,或

RATE_MATCH_NONE.

int phy_restart_aneg(struct phy_device *phydev)

重新启动自动协商

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

phydev 上重新启动自动协商。成功时返回 >= 0,错误时返回负 errno。

int phy_aneg_done(struct phy_device *phydev)

返回自动协商状态

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

从此 phydev 返回自动协商状态。成功时返回 > 0,错误时返回 < 0。0 表示自动协商仍在进行中。

bool phy_check_valid(int speed, int duplex, unsigned long *features)

检查是否存在与速度、双工和特性掩码匹配的有效 PHY 设置

参数

int speed

要匹配的速度

int duplex

要匹配的双工模式

unsigned long *features

有效设置的掩码

描述

如果存在有效设置,则返回 true,否则返回 false。

int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)

通用的 PHY MII ioctl 接口

参数

struct phy_device *phydev

phy_device 结构

struct ifreq *ifr

用于套接字 ioctl 的 struct ifreq

int cmd

要执行的 ioctl 命令

描述

请注意,此函数当前与 PHYCONTROL 层不兼容。它会更改寄存器,而无需考虑当前状态。使用风险自负。

int phy_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)

通用的 ndo_eth_ioctl 实现

参数

struct net_device *dev

net_device 结构体

struct ifreq *ifr

用于套接字 ioctl 的 struct ifreq

int cmd

要执行的 ioctl 命令

int phy_do_ioctl_running(struct net_device *dev, struct ifreq *ifr, int cmd)

通用的 ndo_eth_ioctl 实现,但首先进行测试

参数

struct net_device *dev

net_device 结构体

struct ifreq *ifr

用于套接字 ioctl 的 struct ifreq

int cmd

要执行的 ioctl 命令

描述

与 phy_do_ioctl 相同,但在处理 ioctl 之前,确保 net_device 正在运行。

void phy_queue_state_machine(struct phy_device *phydev, unsigned long jiffies)

触发状态机尽快运行

参数

struct phy_device *phydev

phy_device 结构

unsigned long jiffies

在这些 jiffies 之后运行状态机

void phy_trigger_machine(struct phy_device *phydev)

触发状态机立即运行

参数

struct phy_device *phydev

phy_device 结构

int phy_ethtool_get_strings(struct phy_device *phydev, u8 *data)

获取统计计数器名称

参数

struct phy_device *phydev

phy_device 结构

u8 *data

将字符串放置在此处

int phy_ethtool_get_sset_count(struct phy_device *phydev)

获取统计计数器的数量

参数

struct phy_device *phydev

phy_device 结构

int phy_ethtool_get_stats(struct phy_device *phydev, struct ethtool_stats *stats, u64 *data)

获取统计计数器

参数

struct phy_device *phydev

phy_device 结构

struct ethtool_stats *stats

要获取哪些计数器

u64 *data

存储计数器的位置

int phy_start_cable_test(struct phy_device *phydev, struct netlink_ext_ack *extack)

启动电缆测试

参数

struct phy_device *phydev

phy_device 结构

struct netlink_ext_ack *extack

extack 用于报告有用的错误消息

int phy_start_cable_test_tdr(struct phy_device *phydev, struct netlink_ext_ack *extack, const struct phy_tdr_config *config)

启动原始 TDR 电缆测试

参数

struct phy_device *phydev

phy_device 结构

struct netlink_ext_ack *extack

extack 用于报告有用的错误消息

const struct phy_tdr_config *config

要运行的测试的配置

int _phy_start_aneg(struct phy_device *phydev)

为此 PHY 设备启动自动协商

参数

struct phy_device *phydev

phy_device 结构

描述

清理设置(如果我们不进行自动协商,则清理设置)

然后调用驱动程序的 config_aneg 函数。如果 PHYCONTROL 层正在运行,我们将更改状态以反映自动协商或强制的开始。

int phy_start_aneg(struct phy_device *phydev)

为此 PHY 设备启动自动协商

参数

struct phy_device *phydev

phy_device 结构

描述

清理设置(如果我们不进行自动协商,则清理设置)

然后调用驱动程序的 config_aneg 函数。如果 PHYCONTROL 层正在运行,我们将更改状态以反映自动协商或强制的开始。

int phy_speed_down(struct phy_device *phydev, bool sync)

将速度设置为链路两端都支持的最低速度

参数

struct phy_device *phydev

phy_device 结构

bool sync

同步执行操作

描述

通常用于在等待网络唤醒 (WoL) 数据包时节省能源

警告:如果 PHY 在完成自动协商时产生中断,则将 sync 设置为 false 可能会导致系统无法挂起。此中断可能会在挂起后立即唤醒系统。因此,仅当您确定对于相应的网络芯片是安全时才使用 sync = false。

int phy_speed_up(struct phy_device *phydev)

(重新)将通告的速度设置为所有支持的速度

参数

struct phy_device *phydev

phy_device 结构

描述

用于恢复 phy_speed_down 的效果

void phy_start_machine(struct phy_device *phydev)

启动 PHY 状态机跟踪

参数

struct phy_device *phydev

phy_device 结构

描述

PHY 基础设施可以运行状态机

该状态机跟踪 PHY 是否正在启动、协商等。此函数启动延迟工作队列,该队列跟踪 PHY 的状态。 如果您想维护自己的状态机,请不要调用此函数。

void phy_error(struct phy_device *phydev)

使此 PHY 设备进入 ERROR 状态

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

响应读取或写入错误,将 PHY 移动到 ERROR 状态,并告知控制器链路已断开。 必须在持有 phydev->lock 的情况下调用。

void phy_request_interrupt(struct phy_device *phydev)

请求并启用 PHY 设备的中断

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

请求并启用给定 PHY 的中断。

如果此操作失败,则我们将 irq 设置为 PHY_POLL。 这应该仅在使用有效的 IRQ 号码时调用。

void phy_free_interrupt(struct phy_device *phydev)

禁用并释放 PHY 设备的中断

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

禁用并释放给定 PHY 的中断。

这应该仅在使用有效的 IRQ 号码时调用。

void phy_stop(struct phy_device *phydev)

关闭 PHY 链路,并停止检查状态

参数

struct phy_device *phydev

目标 phy_device 结构体

void phy_start(struct phy_device *phydev)

启动或重新启动 PHY 设备

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

指示附加的设备已准备好

处理与 PHY 相关的工作。 在启动期间用于启动 PHY,并在调用 phy_stop() 后用于恢复操作。 也用于指示 MDIO 总线已清除错误情况。

void phy_mac_interrupt(struct phy_device *phydev)

MAC 指示链路已更改

参数

struct phy_device *phydev

具有已更改链路的 phy_device 结构

描述

MAC 层能够指示 PHY 链路状态已发生更改。 触发状态机并处理工作队列。

int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)

初始化并检查 EEE 功能

参数

struct phy_device *phydev

目标 phy_device 结构体

bool clk_stop_enable

PHY 可以在 LPI 期间停止时钟

描述

它通过查看 MMD 寄存器 3.20 和 7.60/61 来检查是否支持节能以太网 (EEE),并根据需要对 MMD 寄存器 3.0 进行编程,设置“时钟停止使能”位。

int phy_get_eee_err(struct phy_device *phydev)

报告 EEE 唤醒错误计数

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

用于报告 PHY 未能完成其正常唤醒序列的次数。

int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_keee *data)

获取 EEE 支持和状态

参数

struct phy_device *phydev

目标 phy_device 结构体

struct ethtool_keee *data

ethtool_keee 数据

描述

报告支持/通告/LP 通告功能等。

int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data)

设置 EEE 支持和状态

参数

struct phy_device *phydev

目标 phy_device 结构体

struct ethtool_keee *data

ethtool_keee 数据

描述

用于对通告 EEE 寄存器进行编程。

int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)

配置网络唤醒

参数

struct phy_device *phydev

目标 phy_device 结构体

struct ethtool_wolinfo *wol

请求的配置

void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)

获取当前网络唤醒配置

参数

struct phy_device *phydev

目标 phy_device 结构体

struct ethtool_wolinfo *wol

将当前配置存储在此处

int phy_ethtool_nway_reset(struct net_device *ndev)

重新启动自动协商

参数

struct net_device *ndev

需要重启自动协商的网络设备。

int phy_config_interrupt(struct phy_device *phydev, bool interrupts)

为请求的中断配置 PHY 设备。

参数

struct phy_device *phydev

phy_device 结构

bool interrupts

为这个 phydev 配置的中断标志。

描述

成功返回 0,错误返回 < 0。

const struct phy_setting *phy_find_valid(int speed, int duplex, unsigned long *supported)

查找与请求参数匹配的 PHY 设置。

参数

int speed

期望的速度。

int duplex

期望的双工模式。

unsigned long *supported

支持的链路模式的掩码。

描述

按优先级顺序定位一个受支持的 PHY 设置: - 完全匹配指定速度和双工模式的设置 - 匹配指定速度或更慢速度的设置 - 最慢的支持速度。返回匹配的 phy_setting 条目,如果未找到支持的 PHY 设置,则返回 NULL

unsigned int phy_supported_speeds(struct phy_device *phy, unsigned int *speeds, unsigned int size)

返回 PHY 设备当前支持的所有速度。

参数

struct phy_device *phy

要返回支持速度的 PHY 设备。

unsigned int *speeds

存储支持速度的缓冲区。

unsigned int size

速度缓冲区的大小。

描述

返回支持的速度数,并将支持的速度填充到速度缓冲区中。如果速度缓冲区太小,无法容纳所有当前支持的速度,将返回尽可能多的速度。

void phy_sanitize_settings(struct phy_device *phydev)

确保 PHY 设置为支持的速度和双工模式。

参数

struct phy_device *phydev

目标 phy_device 结构。

描述

确保 PHY 设置为支持的速度和

双工模式。按以下顺序依次降低:1000/FULL、1000/HALF、100/FULL、100/HALF、10/FULL、10/HALF。

int __phy_hwtstamp_get(struct phy_device *phydev, struct kernel_hwtstamp_config *config)

从 PHY 获取硬件时间戳配置。

参数

struct phy_device *phydev

PHY 设备结构。

struct kernel_hwtstamp_config *config

保存时间戳配置的结构。

描述

查询 PHY 设备以获取其当前的硬件时间戳配置。

int __phy_hwtstamp_set(struct phy_device *phydev, struct kernel_hwtstamp_config *config, struct netlink_ext_ack *extack)

修改 PHY 硬件时间戳配置。

参数

struct phy_device *phydev

PHY 设备结构。

struct kernel_hwtstamp_config *config

保存时间戳配置的结构。

struct netlink_ext_ack *extack

netlink 扩展 ACK 结构,用于错误报告。

int phy_ethtool_get_plca_cfg(struct phy_device *phydev, struct phy_plca_cfg *plca_cfg)

获取 PLCA RS 配置。

参数

struct phy_device *phydev

phy_device 结构

struct phy_plca_cfg *plca_cfg

存储检索到的配置的位置。

描述

从 PHY 中检索 PLCA 配置。成功返回 0,如果发生错误,则返回负值。

int plca_check_valid(struct phy_device *phydev, const struct phy_plca_cfg *plca_cfg, struct netlink_ext_ack *extack)

在启用 PLCA 之前检查 PLCA 配置。

参数

struct phy_device *phydev

phy_device 结构

const struct phy_plca_cfg *plca_cfg

当前的 PLCA 配置。

struct netlink_ext_ack *extack

extack 用于报告有用的错误消息

描述

检查 PLCA 和 PHY 配置是否一致,以及启用 PLCA 是否安全。成功返回 0,如果 PLCA 或 PHY 配置不一致,则返回负值。

int phy_ethtool_set_plca_cfg(struct phy_device *phydev, const struct phy_plca_cfg *plca_cfg, struct netlink_ext_ack *extack)

设置 PLCA RS 配置。

参数

struct phy_device *phydev

phy_device 结构

const struct phy_plca_cfg *plca_cfg

要应用的新 PLCA 配置。

struct netlink_ext_ack *extack

extack 用于报告有用的错误消息

描述

在 PHY 中设置 PLCA 配置。成功返回 0,如果发生错误,则返回负值。

int phy_ethtool_get_plca_status(struct phy_device *phydev, struct phy_plca_status *plca_st)

获取 PLCA RS 状态信息。

参数

struct phy_device *phydev

phy_device 结构

struct phy_plca_status *plca_st

存储检索到的状态信息的位置。

描述

从 PHY 中检索 PLCA 状态信息。成功返回 0,如果发生错误,则返回负值。

检查链路状态并相应地设置状态。

参数

struct phy_device *phydev

phy_device 结构

描述

检查链路以及是否触发/正在运行自动协商,并相应地设置状态。

void phy_stop_machine(struct phy_device *phydev)

停止 PHY 状态机跟踪

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

停止状态机延迟工作队列,并将

状态设置为 UP(除非它还未启动)。此函数必须在 phy_detach 之前调用。

int phy_disable_interrupts(struct phy_device *phydev)

从 PHY 端禁用 PHY 中断

参数

struct phy_device *phydev

目标 phy_device 结构体

irqreturn_t phy_interrupt(int irq, void *phy_dat)

PHY 中断处理程序

参数

int irq

中断线

void *phy_dat

phy_device 指针

描述

处理 PHY 中断

int phy_enable_interrupts(struct phy_device *phydev)

从 PHY 端启用中断

参数

struct phy_device *phydev

目标 phy_device 结构体

void phy_state_machine(struct work_struct *work)

处理状态机

参数

struct work_struct *work

描述要完成的工作的 work_struct

void phy_ethtool_set_eee_noneg(struct phy_device *phydev, const struct eee_config *old_cfg)

调整 MAC LPI 配置,无需 PHY 重新协商

参数

struct phy_device *phydev

指向目标 PHY 设备结构的指针

const struct eee_config *old_cfg

指向包含旧 EEE 设置的 eee_config 结构的指针

描述

此函数更新以太网节能 (EEE) 配置,用于仅更改 MAC 的低功耗空闲 (LPI) 配置而无需触发 PHY 重新协商的情况。它通过循环关闭和打开链路来确保 MAC 正确了解新的 LPI 设置,这对于 MAC 采用新配置是必要的。仅当 tx_lpi_enabled 或 tx_lpi_timer 配置发生更改时,才会进行此调整。

const char *phy_speed_to_str(int speed)

返回表示 PHY 链路速度的字符串

参数

int speed

链路速度

const char *phy_duplex_to_str(unsigned int duplex)

返回描述双工的字符串

参数

unsigned int duplex

要描述的双工设置

const char *phy_rate_matching_to_str(int rate_matching)

返回描述速率匹配的字符串

参数

int rate_matching

要描述的速率匹配类型

int phy_interface_num_ports(phy_interface_t interface)

返回给定 MAC-PHY 物理链路可以承载的链路数量。如果未知则返回 0,否则返回链路数量。

参数

phy_interface_t interface

我们要获取端口数量的接口模式

const struct phy_setting *phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact)

查找 PHY 设置

参数

int speed

要匹配的速度

int duplex

要匹配的双工模式

const unsigned long *mask

允许的链路模式

bool exact

需要精确匹配

描述

在设置数组中搜索与速度和双工匹配且受支持的设置。

如果未设置 **exact**,则会返回精确匹配或 NULL (如果未匹配)。

如果设置了 **exact**,则会返回精确匹配、指定速度或更低速度下的最快支持设置、最慢支持设置,或者如果它们都失败,则会返回 NULL

void phy_set_max_speed(struct phy_device *phydev, u32 max_speed)

设置 PHY 应支持的最大速度

参数

struct phy_device *phydev

phy_device 结构

u32 max_speed

最大速度

描述

PHY 的能力可能比 MAC 更强。例如,快速以太网连接到 1G PHY。此函数允许 MAC 指示其最大速度,从而限制 PHY 将通告的内容。

void phy_resolve_aneg_pause(struct phy_device *phydev)

确定暂停自动协商结果

参数

struct phy_device *phydev

phy_device 结构

描述

自动协商完成后,可以解析本地暂停设置。确定 MAC 是否应使用暂停和非对称暂停。

void phy_resolve_aneg_linkmode(struct phy_device *phydev)

将通告解析为 PHY 设置

参数

struct phy_device *phydev

phy_device 结构

描述

将我们和链路伙伴的通告解析为它们对应的速度和双工。如果协商了全双工,则从链路伙伴掩码中提取暂停模式。

void phy_check_downshift(struct phy_device *phydev)

检查是否发生降速

参数

struct phy_device *phydev

phy_device 结构

描述

检查是否发生降速至较低的速度。如果应该发生这种情况,则警告用户。检测降速的前提条件是 PHY 驱动程序实现 read_status 回调并将 phydev->speed 设置为实际链路速度。

int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)

用于从给定 PHY 上的 MMD 读取寄存器的便捷函数。

参数

struct phy_device *phydev

phy_device 结构

int devad

要从中读取的 MMD (0..31)

u32 regnum

要读取的 MMD 上的寄存器 (0..65535)

描述

__phy_read() 相同的规则;

int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)

用于从给定 PHY 上的 MMD 读取寄存器的便捷函数。

参数

struct phy_device *phydev

phy_device 结构

int devad

要从中读取的 MMD

u32 regnum

要读取的 MMD 上的寄存器

描述

phy_read() 相同的规则;

int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)

用于在给定 PHY 上的 MMD 上写入寄存器的便捷函数。

参数

struct phy_device *phydev

phy_device 结构

int devad

要从中读取的 MMD

u32 regnum

要读取的 MMD 上的寄存器

u16 val

要写入 regnum 的值

描述

__phy_write() 相同的规则;

int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)

用于在给定 PHY 上的 MMD 上写入寄存器的便捷函数。

参数

struct phy_device *phydev

phy_device 结构

int devad

要从中读取的 MMD

u32 regnum

要读取的 MMD 上的寄存器

u16 val

要写入 regnum 的值

描述

phy_write() 相同的规则;

int __phy_package_read_mmd(struct phy_device *phydev, unsigned int addr_offset, int devad, u32 regnum)

读取相对于 PHY 封装基址的 MMD 寄存器

参数

struct phy_device *phydev

phy_device 结构

unsigned int addr_offset

要添加到 PHY 封装 base_addr 的偏移量

int devad

要从中读取的 MMD

u32 regnum

要读取的 MMD 上的寄存器

描述

用于使用 PHY 封装基址读取给定 PHY 上 MMD 的寄存器的便捷助手。 基址被添加到 addr_offset 值。

__phy_read() 相同的调用规则;

注意

假设整个 PHY 封装是 C22 或 C45。

int phy_package_read_mmd(struct phy_device *phydev, unsigned int addr_offset, int devad, u32 regnum)

读取相对于 PHY 封装基址的 MMD 寄存器

参数

struct phy_device *phydev

phy_device 结构

unsigned int addr_offset

要添加到 PHY 封装 base_addr 的偏移量

int devad

要从中读取的 MMD

u32 regnum

要读取的 MMD 上的寄存器

描述

用于使用 PHY 封装基址读取给定 PHY 上 MMD 的寄存器的便捷助手。 基址被添加到 addr_offset 值。

phy_read() 相同的调用规则;

注意

假设整个 PHY 封装是 C22 或 C45。

int __phy_package_write_mmd(struct phy_device *phydev, unsigned int addr_offset, int devad, u32 regnum, u16 val)

相对于 PHY 封装基址写入 MMD 寄存器

参数

struct phy_device *phydev

phy_device 结构

unsigned int addr_offset

要添加到 PHY 封装 base_addr 的偏移量

int devad

要写入的 MMD

u32 regnum

要写入的 MMD 上的寄存器

u16 val

要写入 regnum 的值

描述

用于使用 PHY 封装基址在给定 PHY 上写入 MMD 寄存器的便捷助手。 基址被添加到 addr_offset 值。

__phy_write() 相同的调用规则;

注意

假设整个 PHY 封装是 C22 或 C45。

int phy_package_write_mmd(struct phy_device *phydev, unsigned int addr_offset, int devad, u32 regnum, u16 val)

相对于 PHY 封装基址写入 MMD 寄存器

参数

struct phy_device *phydev

phy_device 结构

unsigned int addr_offset

要添加到 PHY 封装 base_addr 的偏移量

int devad

要写入的 MMD

u32 regnum

要写入的 MMD 上的寄存器

u16 val

要写入 regnum 的值

描述

用于使用 PHY 封装基址在给定 PHY 上写入 MMD 寄存器的便捷助手。 基址被添加到 addr_offset 值。

phy_write() 相同的调用规则;

注意

假设整个 PHY 封装是 C22 或 C45。

int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)

用于修改 PHY 寄存器的函数

参数

struct phy_device *phydev

phy_device 结构

u32 regnum

要修改的寄存器号

u16 mask

要清除的位的位掩码

u16 set

mask 中设置的位的新值,以写入 regnum

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

描述

返回负 errno,如果未发生更改则返回 0,如果发生更改则返回 1

int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)

用于修改 PHY 寄存器的便捷函数

参数

struct phy_device *phydev

phy_device 结构

u32 regnum

要修改的寄存器号

u16 mask

要清除的位的位掩码

u16 set

mask 中设置的位的新值,以写入 regnum

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)

用于修改给定 PHY 寄存器的便捷函数

参数

struct phy_device *phydev

phy_device 结构

u32 regnum

要写入的寄存器编号

u16 mask

要清除的位的位掩码

u16 set

mask 中设置的位的新值,以写入 regnum

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, u16 mask, u16 set)

用于修改 MMD 上寄存器的函数

参数

struct phy_device *phydev

phy_device 结构

int devad

包含要修改的寄存器的 MMD

u32 regnum

要修改的寄存器号

u16 mask

要清除的位的位掩码

u16 set

mask 中设置的位的新值,以写入 regnum

描述

未锁定的辅助函数,允许修改 MMD 寄存器,新寄存器值 = (旧寄存器值 & ~mask) | set

返回负 errno,如果未发生更改则返回 0,如果发生更改则返回 1

int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, u16 mask, u16 set)

用于修改 MMD 上寄存器的函数

参数

struct phy_device *phydev

phy_device 结构

int devad

包含要修改的寄存器的 MMD

u32 regnum

要修改的寄存器号

u16 mask

要清除的位的位掩码

u16 set

mask 中设置的位的新值,以写入 regnum

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

描述

返回负 errno,如果未发生更改则返回 0,如果发生更改则返回 1

int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 mask, u16 set)

用于修改 MMD 上寄存器的便捷函数

参数

struct phy_device *phydev

phy_device 结构

int devad

包含要修改的寄存器的 MMD

u32 regnum

要修改的寄存器号

u16 mask

要清除的位的位掩码

u16 set

mask 中设置的位的新值,以写入 regnum

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 mask, u16 set)

用于修改 MMD 上寄存器的便捷函数

参数

struct phy_device *phydev

phy_device 结构

int devad

包含要修改的寄存器的 MMD

u32 regnum

要修改的寄存器号

u16 mask

要清除的位的位掩码

u16 set

mask 中设置的位的新值,以写入 regnum

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int phy_save_page(struct phy_device *phydev)

获取总线锁并保存当前页

参数

struct phy_device *phydev

指向 struct phy_device 的指针

描述

获取 MDIO 总线锁,并返回当前页码。如果出错,返回负 errno。 无论此调用成功或失败,之后都必须始终调用 phy_restore_page()

int phy_select_page(struct phy_device *phydev, int page)

获取总线锁,保存当前页,并设置一个页

参数

struct phy_device *phydev

指向 struct phy_device 的指针

int page

所需的页

描述

获取 MDIO 总线锁以防止并发访问,保存当前的 PHY 页,并设置当前页。 如果出错,返回负 errno,否则返回上一页码。 无论此调用成功或失败,之后都必须始终调用 phy_restore_page()

int phy_restore_page(struct phy_device *phydev, int oldpage, int ret)

恢复页寄存器并释放总线锁

参数

struct phy_device *phydev

指向 struct phy_device 的指针

int oldpage

旧页,来自 phy_save_page()phy_select_page() 的返回值

int ret

操作的返回代码

描述

释放 MDIO 总线锁,如果 oldpage 是有效页,则恢复该页。此函数传播来自操作组的最早的错误代码。

返回

如果 oldpage 为负值,则为 oldpage;如果 ret 为负 errno 值,则为 ret;否则,如果 phy_write_page() 出错,则为其负值,否则为 ret

int phy_read_paged(struct phy_device *phydev, int page, u32 regnum)

用于读取分页寄存器的便捷函数

参数

struct phy_device *phydev

指向 struct phy_device 的指针

int page

phy 的页

u32 regnum

寄存器编号

描述

phy_read() 相同的规则。

int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val)

用于写入分页寄存器的便捷函数

参数

struct phy_device *phydev

指向 struct phy_device 的指针

int page

phy 的页

u32 regnum

寄存器编号

u16 val

要写入的值

描述

phy_write() 相同的规则。

int phy_modify_paged_changed(struct phy_device *phydev, int page, u32 regnum, u16 mask, u16 set)

用于修改分页寄存器的函数

参数

struct phy_device *phydev

指向 struct phy_device 的指针

int page

phy 的页

u32 regnum

寄存器编号

u16 mask

要清除的位的位掩码

u16 set

要设置的位的位掩码

描述

返回负 errno,如果未发生更改则返回 0,如果发生更改则返回 1

int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum, u16 mask, u16 set)

用于修改分页寄存器的便捷函数

参数

struct phy_device *phydev

指向 struct phy_device 的指针

int page

phy 的页

u32 regnum

寄存器编号

u16 mask

要清除的位的位掩码

u16 set

要设置的位的位掩码

描述

phy_read()phy_write() 相同的规则。

int genphy_c45_pma_resume(struct phy_device *phydev)

唤醒 PMA 模块

参数

struct phy_device *phydev

目标 phy_device 结构体

int genphy_c45_pma_suspend(struct phy_device *phydev)

挂起 PMA 模块

参数

struct phy_device *phydev

目标 phy_device 结构体

int genphy_c45_pma_baset1_setup_master_slave(struct phy_device *phydev)

配置 BaseT1 设备的强制主/从角色。

参数

struct phy_device *phydev

目标 phy_device 结构体

int genphy_c45_pma_setup_forced(struct phy_device *phydev)

配置强制速度

参数

struct phy_device *phydev

目标 phy_device 结构体

int genphy_c45_an_config_aneg(struct phy_device *phydev)

配置通告寄存器

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

基于 phydev->advertising 中设置的模式配置通告寄存器

失败时返回负的 errno 代码,如果通告未更改则返回 0,如果通告的模式已更改则返回 1。

int genphy_c45_an_disable_aneg(struct phy_device *phydev)

禁用自动协商

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

在 Clause 45 PHY 中禁用自动协商。链路参数通过 PMA/PMD MMD 寄存器控制。

成功时返回零,失败时返回负的 errno 代码。

int genphy_c45_restart_aneg(struct phy_device *phydev)

启用并重新启动自动协商

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

这假设存在自动协商 MMD。

启用并重新启动自动协商。

int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart)

启用并重新启动自动协商

参数

struct phy_device *phydev

目标 phy_device 结构体

bool restart

是否请求重新启动 aneg

描述

这假设存在自动协商 MMD。

检查并在需要时重新启动自动协商。

int genphy_c45_aneg_done(struct phy_device *phydev)

返回自动协商完成状态

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

这假设存在自动协商 MMD。

从自动协商 MMD 读取状态寄存器,返回: - 如果自动协商完成,则返回正值 - 错误时返回负的 errno 代码 - 否则返回零

从 MMD 读取整体链路状态

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

从指定的 MMD 读取链路状态,如果它们都指示链路已启动,则将 phydev->link 设置为 1。如果遇到错误,则将返回负的 errno,否则返回零。

int genphy_c45_read_lpa(struct phy_device *phydev)

读取链路伙伴通告和暂停

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

读取 Clause 45 定义的基本(7.19)和 10G(7.33)状态寄存器,填充 **phydev** 中的链路伙伴通告、暂停和 asym_pause 成员。 这假设存在自动协商 MMD,并且背板位 (7.48.0) 已清除。 Clause 45 PHY 驱动程序应该从供应商寄存器中填充链路伙伴通告的其余部分。

int genphy_c45_pma_baset1_read_master_slave(struct phy_device *phydev)

读取强制主/从配置

参数

struct phy_device *phydev

目标 phy_device 结构体

int genphy_c45_read_pma(struct phy_device *phydev)

从 PMA 读取链路速度等

参数

struct phy_device *phydev

目标 phy_device 结构体

int genphy_c45_read_mdix(struct phy_device *phydev)

从 PMA 读取 mdix 状态

参数

struct phy_device *phydev

目标 phy_device 结构体

int genphy_c45_read_eee_abilities(struct phy_device *phydev)

读取支持的 EEE 链路模式

参数

struct phy_device *phydev

目标 phy_device 结构体

int genphy_c45_an_config_eee_aneg(struct phy_device *phydev)

配置 EEE 通告

参数

struct phy_device *phydev

目标 phy_device 结构体

int genphy_c45_pma_baset1_read_abilities(struct phy_device *phydev)

从 PMA 读取支持的 baset1 链路模式

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

从扩展的 BASE-T1 能力寄存器读取支持的链路模式

int genphy_c45_pma_read_ext_abilities(struct phy_device *phydev)

从 PMA 读取支持的链路模式

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

从 PMA/PMD 扩展能力寄存器(寄存器 1.11)读取支持的链路模式。

int genphy_c45_pma_read_abilities(struct phy_device *phydev)

从 PMA 读取支持的链路模式

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

从 PMA 状态 2 (1.8) 寄存器读取支持的链路模式。如果设置了位 1.8.9,则使用 PMA 扩展能力(1.11)寄存器中的值构建支持的模式列表,指示 1000BASE-T 和 10G 相关模式。如果设置了位 1.11.14,则该列表还会扩展 2.5G/5G PMA 扩展寄存器(1.21)中的模式,指示是否支持 2.5GBASE-T 和 5GBASE-T。

int genphy_c45_read_status(struct phy_device *phydev)

读取 PHY 状态

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

从 PHY 读取状态并相应地设置 phy_device 成员。

int genphy_c45_config_aneg(struct phy_device *phydev)

重新启动自动协商或强制设置

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

如果启用了自动协商,我们将配置

通告,然后重新启动自动协商。如果未启用,则强制配置。

int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable)

配置快速重训寄存器

参数

struct phy_device *phydev

目标 phy_device 结构体

bool enable

是否启用快速重训

描述

如果启用了快速重训,我们将 PHY 配置为

通告支持快速重训和 THP 旁路请求,然后启用快速重训。如果未启用,我们将配置为禁用快速重训。

int genphy_c45_plca_get_cfg(struct phy_device *phydev, struct phy_plca_cfg *plca_cfg)

从标准寄存器获取 PLCA 配置

参数

struct phy_device *phydev

目标 phy_device 结构体

struct phy_plca_cfg *plca_cfg

用于存储 PLCA 配置的输出结构

描述

如果 PHY 符合开放联盟 TC14 10BASE-T1S PLCA

管理寄存器规范,则可以使用此函数从 MMD 31 中的标准寄存器检索当前 PLCA 配置。

int genphy_c45_plca_set_cfg(struct phy_device *phydev, const struct phy_plca_cfg *plca_cfg)

使用标准寄存器设置 PLCA 配置

参数

struct phy_device *phydev

目标 phy_device 结构体

const struct phy_plca_cfg *plca_cfg

包含 PLCA 配置的结构。设置为 -1 的字段不会被更改。

描述

如果 PHY 符合开放联盟 TC14 10BASE-T1S PLCA

管理寄存器规范,可以使用此函数使用 MMD 31 中的标准寄存器修改 PLCA 配置。

int genphy_c45_plca_get_status(struct phy_device *phydev, struct phy_plca_status *plca_st)

从标准寄存器获取 PLCA 状态

参数

struct phy_device *phydev

目标 phy_device 结构体

struct phy_plca_status *plca_st

用于存储 PLCA 状态的输出结构

描述

如果 PHY 符合开放联盟 TC14 10BASE-T1S PLCA

管理寄存器规范,可以使用此函数从 MMD 31 中的标准寄存器检索当前 PLCA 状态信息。

int genphy_c45_eee_is_active(struct phy_device *phydev, unsigned long *adv, unsigned long *lp, bool *is_enabled)

获取 EEE 状态

参数

struct phy_device *phydev

目标 phy_device 结构体

unsigned long *adv

用于存储通告的链路模式的变量

unsigned long *lp

用于存储 LP 通告的链路模式的变量

bool *is_enabled

用于存储 EEE 启用/禁用配置值的变量

描述

此函数将读取本地和链路伙伴 PHY 通告。比较它们并返回当前的 EEE 状态。

int genphy_c45_ethtool_get_eee(struct phy_device *phydev, struct ethtool_keee *data)

获取 EEE 支持和状态

参数

struct phy_device *phydev

目标 phy_device 结构体

struct ethtool_keee *data

ethtool_keee 数据

描述

它报告支持/通告/LP 通告功能。

int genphy_c45_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data)

设置 EEE 支持和状态

参数

struct phy_device *phydev

目标 phy_device 结构体

struct ethtool_keee *data

ethtool_keee 数据

描述

设置支持/通告/LP 通告功能。如果 eee_enabled 为 false,则不通告任何链路模式,但保留先前通告的链路模式。这允许以非破坏性的方式启用/禁用 EEE。如果未发生更改则返回错误代码或 0,如果发生更改触发了自动协商则返回正值。

enum phy_interface_t

接口模式定义

常量

PHY_INTERFACE_MODE_NA

不适用 - 请勿触碰

PHY_INTERFACE_MODE_INTERNAL

无接口,MAC 和 PHY 组合

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_REVRMII

PHY 角色中的精简媒体独立接口

PHY_INTERFACE_MODE_RGMII

精简千兆媒体独立接口

PHY_INTERFACE_MODE_RGMII_ID

具有内部 RX+TX 延迟的 RGMII

PHY_INTERFACE_MODE_RGMII_RXID

具有内部 RX 延迟的 RGMII

PHY_INTERFACE_MODE_RGMII_TXID

具有内部 RX 延迟的 RGMII

PHY_INTERFACE_MODE_RTBI

精简 TBI

PHY_INTERFACE_MODE_SMII

串行 MII

PHY_INTERFACE_MODE_XGMII

10 千兆媒体独立接口

PHY_INTERFACE_MODE_XLGMII

40 千兆媒体独立接口

PHY_INTERFACE_MODE_MOCA

同轴电缆上的多媒体

PHY_INTERFACE_MODE_PSGMII

五路 SGMII

PHY_INTERFACE_MODE_QSGMII

四路 SGMII

PHY_INTERFACE_MODE_TRGMII

Turbo RGMII

PHY_INTERFACE_MODE_100BASEX

100 BaseX

PHY_INTERFACE_MODE_1000BASEX

1000 BaseX

PHY_INTERFACE_MODE_2500BASEX

2500 BaseX

PHY_INTERFACE_MODE_5GBASER

5G BaseR

PHY_INTERFACE_MODE_RXAUI

精简 XAUI

PHY_INTERFACE_MODE_XAUI

10 千兆连接单元接口

PHY_INTERFACE_MODE_10GBASER

10G BaseR

PHY_INTERFACE_MODE_25GBASER

25G BaseR

PHY_INTERFACE_MODE_USXGMII

通用串行 10GE MII

PHY_INTERFACE_MODE_10GKR

10GBASE-KR - 带 Clause 73 自协商

PHY_INTERFACE_MODE_QUSGMII

四通道通用 SGMII

PHY_INTERFACE_MODE_1000BASEKX

1000Base-KX - 带 Clause 73 自协商

PHY_INTERFACE_MODE_10G_QXGMII

10G-QXGMII - 通过 10G USXGMII 的 4 个端口

PHY_INTERFACE_MODE_MAX

簿记

描述

描述 MAC 和 PHY 之间的接口。

const char *phy_modes(phy_interface_t interface)

将 phy_interface_t 枚举映射到 phy-mode 的设备树绑定

参数

phy_interface_t interface

enum phy_interface_t

描述

将此文件中定义的枚举 phy_interface_t 映射到 ‘phy-mode’ 的设备树绑定,以便以太网设备驱动程序可以从设备树获取 PHY 接口。

struct mdio_bus_stats

MDIO 总线的统计计数器

定义:

struct mdio_bus_stats {
    u64_stats_t transfers;
    u64_stats_t errors;
    u64_stats_t writes;
    u64_stats_t reads;
    struct u64_stats_sync syncp;
};

成员

传输

传输总数,即 写入 + 读取

错误

返回错误的 MDIO 传输次数

写入

写入传输次数

读取

读取传输次数

syncp

用于递增统计数据的同步

struct phy_package_shared

PHY 包中的共享信息

定义:

struct phy_package_shared {
    u8 base_addr;
    struct device_node *np;
    refcount_t refcnt;
    unsigned long flags;
    size_t priv_size;
    void *priv;
};

成员

base_addr

PHY 包的基本 PHY 地址,用于在一个包中组合 PHY 以及用于 phy_package_read/write 的偏移计算

np

如果 PHY 包在 DT 中定义,则指向设备节点的指针

refcnt

连接到此共享数据的 PHY 数量

flags

PHY 包的初始化

priv_size

共享私有数据 priv 的大小

priv

跨 PHY 包共享的驱动程序私有数据

描述

表示同一包中不同 phydev 之间的共享结构,例如四通道 PHY。请参阅 phy_package_join()phy_package_leave()

struct mii_bus

表示 MDIO 总线

定义:

struct mii_bus {
    struct module *owner;
    const char *name;
    char id[MII_BUS_ID_SIZE];
    void *priv;
    int (*read)(struct mii_bus *bus, int addr, int regnum);
    int (*write)(struct mii_bus *bus, int addr, int regnum, u16 val);
    int (*read_c45)(struct mii_bus *bus, int addr, int devnum, int regnum);
    int (*write_c45)(struct mii_bus *bus, int addr, int devnum, int regnum, u16 val);
    int (*reset)(struct mii_bus *bus);
    struct mdio_bus_stats stats[PHY_MAX_ADDR];
    struct mutex mdio_lock;
    struct device *parent;
    enum {
        MDIOBUS_ALLOCATED = 1,
        MDIOBUS_REGISTERED,
        MDIOBUS_UNREGISTERED,
        MDIOBUS_RELEASED,
    } state;
    struct device dev;
    struct mdio_device *mdio_map[PHY_MAX_ADDR];
    u32 phy_mask;
    u32 phy_ignore_ta_mask;
    int irq[PHY_MAX_ADDR];
    int reset_delay_us;
    int reset_post_delay_us;
    struct gpio_desc *reset_gpiod;
    struct mutex shared_lock;
    struct phy_package_shared *shared[PHY_MAX_ADDR];
};

成员

所有者

谁拥有此设备

name

此 MDIO 设备的友好名称或驱动程序名称

id

此总线的唯一标识符,通常来自总线层次结构

priv

驱动程序私有数据

读取

在总线上执行读取传输

写入

在总线上执行写入传输

read_c45

在总线上执行 C45 读取传输

write_c45

在总线上执行 C45 写入传输

重置

执行总线重置

stats

总线上每个设备的统计计数器

mdio_lock

确保一次只有一个东西可以读取/写入 MDIO 总线的锁

父节点

此总线的父设备

state

总线结构的状态

dev

内核设备表示

mdio_map

总线上所有 MDIO 设备的列表

phy_mask

探测时要忽略的 PHY 地址

phy_ignore_ta_mask

忽略 TA/读取失败的 PHY 地址

irq

中断数组,每个 PHY 的中断在其地址匹配的索引处

reset_delay_us

GPIO 重置脉冲宽度,以微秒为单位

reset_post_delay_us

GPIO 重置解除断言延迟,以微秒为单位

reset_gpiod

重置 GPIO 描述符指针

shared_lock

保护对共享元素的访问

shared

不同 PHY 之间的共享状态

描述

PHY 的总线类。提供对 PHY 访问的设备应使用此结构注册

struct mii_bus *mdiobus_alloc(void)

分配 MDIO 总线结构

参数

void

无参数

描述

MDIO 总线的内部状态将设置为 MDIOBUS_ALLOCATED,准备好让驱动程序注册总线。

enum phy_state

PHY 状态机状态

常量

PHY_DOWN

PHY 设备和驱动程序尚未准备好进行任何操作。当且仅当 PHY 处于此状态时,才应调用探测,前提是 PHY 设备存在。- PHY 驱动程序探测函数会将状态设置为 PHY_READY

PHY_READY

PHY 已准备好发送和接收数据包,但控制器尚未准备好。默认情况下,不实现探测的 PHY 将由 phy_probe() 将此状态设置为此状态。 - start 会将状态设置为 UP

PHY_HALTED

PHY 已启动,但不执行轮询或中断。- phy_start 会移动到 PHY_UP

PHY_ERROR

PHY 已启动,但处于错误状态。- phy_stop 会移动到 PHY_HALTED

PHY_UP

PHY 和附加设备已准备好工作。中断应在此处启动。- timer 会移动到 PHY_NOLINKPHY_RUNNING

PHY_RUNNING

PHY 当前已启动、正在运行,并且可能正在发送和/或接收数据包 - 如果链路断开,irq 或 timer 将设置 PHY_NOLINK - phy_stop 会移动到 PHY_HALTED

PHY_NOLINK

PHY 已启动,但当前未插入。- 如果链路恢复,irq 或 timer 将设置 PHY_RUNNING - phy_stop 会移动到 PHY_HALTED

PHY_CABLETEST

PHY 正在执行电缆测试。预计数据包接收/发送将不起作用,载波将指示为断开。PHY 将每秒轮询一次,或根据其中断的当前状态进行轮询。完成后,移动到 UP 以重新启动 PHY。- phy_stop 会中止正在运行的测试并移动到 PHY_HALTED

struct phy_c45_device_ids

802.3-c45 设备标识符

定义:

struct phy_c45_device_ids {
    u32 devices_in_package;
    u32 mmds_present;
    u32 device_ids[MDIO_MMD_NUM];
};

成员

包中的设备

IEEE 802.3 包中设备寄存器值。

mmds_present

存在的 MMD 的位向量。

device_ids

每个存在设备的设备标识符。

struct phy_device

PHY 的实例

定义:

struct phy_device {
    struct mdio_device mdio;
    const struct phy_driver *drv;
    struct device_link *devlink;
    u32 phyindex;
    u32 phy_id;
    struct phy_c45_device_ids c45_ids;
    unsigned is_c45:1;
    unsigned is_internal:1;
    unsigned is_pseudo_fixed_link:1;
    unsigned is_gigabit_capable:1;
    unsigned has_fixups:1;
    unsigned suspended:1;
    unsigned suspended_by_mdio_bus:1;
    unsigned sysfs_links:1;
    unsigned loopback_enabled:1;
    unsigned downshifted_rate:1;
    unsigned is_on_sfp_module:1;
    unsigned mac_managed_pm:1;
    unsigned wol_enabled:1;
    unsigned autoneg:1;
    unsigned link:1;
    unsigned autoneg_complete:1;
    unsigned interrupts:1;
    unsigned irq_suspended:1;
    unsigned irq_rerun:1;
    unsigned default_timestamp:1;
    int rate_matching;
    enum phy_state state;
    u32 dev_flags;
    phy_interface_t interface;
    unsigned long possible_interfaces[BITS_TO_LONGS(PHY_INTERFACE_MODE_MAX)];
    int speed;
    int duplex;
    int port;
    int pause;
    int asym_pause;
    u8 master_slave_get;
    u8 master_slave_set;
    u8 master_slave_state;
    unsigned long supported[BITS_TO_LONGS(__ETHTOOL_LINK_MODE_MASK_NBITS)];
    unsigned long advertising[BITS_TO_LONGS(__ETHTOOL_LINK_MODE_MASK_NBITS)];
    unsigned long lp_advertising[BITS_TO_LONGS(__ETHTOOL_LINK_MODE_MASK_NBITS)];
    unsigned long adv_old[BITS_TO_LONGS(__ETHTOOL_LINK_MODE_MASK_NBITS)];
    unsigned long supported_eee[BITS_TO_LONGS(__ETHTOOL_LINK_MODE_MASK_NBITS)];
    unsigned long advertising_eee[BITS_TO_LONGS(__ETHTOOL_LINK_MODE_MASK_NBITS)];
    unsigned long eee_broken_modes[BITS_TO_LONGS(__ETHTOOL_LINK_MODE_MASK_NBITS)];
    bool enable_tx_lpi;
    bool eee_active;
    struct eee_config eee_cfg;
    unsigned long host_interfaces[BITS_TO_LONGS(PHY_INTERFACE_MODE_MAX)];
#ifdef CONFIG_LED_TRIGGER_PHY;
    struct phy_led_trigger *phy_led_triggers;
    unsigned int phy_num_led_triggers;
    struct phy_led_trigger *last_triggered;
    struct phy_led_trigger *led_link_trigger;
#endif;
    struct list_head leds;
    int irq;
    void *priv;
    struct phy_package_shared *shared;
    struct sk_buff *skb;
    void *ehdr;
    struct nlattr *nest;
    struct delayed_work state_queue;
    struct mutex lock;
    bool sfp_bus_attached;
    struct sfp_bus *sfp_bus;
    struct phylink *phylink;
    struct net_device *attached_dev;
    struct mii_timestamper *mii_ts;
    struct pse_control *psec;
    u8 mdix;
    u8 mdix_ctrl;
    int pma_extable;
    unsigned int link_down_events;
    void (*phy_link_change)(struct phy_device *phydev, bool up);
    void (*adjust_link)(struct net_device *dev);
#if IS_ENABLED(CONFIG_MACSEC);
    const struct macsec_ops *macsec_ops;
#endif;
};

成员

mdio

此 PHY 所在的 MDIO 总线

drv

指向此 PHY 实例的驱动程序的指针

devlink

如果当前 mac 接口使用的外部 phy 由另一个 mac 接口管理,则在 phy dev 和 mac dev 之间创建链接。

phyindex

在 phy 的父级 phy 树中,用于从用户空间寻址 PHY 的唯一 id,类似于 ifindex。索引为零表示尚未为 PHY 分配 id。

phy_id

在发现过程中找到的此设备的 UID

c45_ids

如果 is_c45,则为 802.3-c45 设备标识符。

is_c45

如果此 PHY 使用第 45 条寻址,则设置为 true。

is_internal

如果此 PHY 是 MAC 的内部 PHY,则设置为 true。

is_pseudo_fixed_link

如果此 PHY 是以太网交换机等,则设置为 true。

is_gigabit_capable

如果 PHY 支持 1000Mbps,则设置为 true

has_fixups

如果此 PHY 具有修复/怪癖,则设置为 true。

suspended

如果此 PHY 已成功挂起,则设置为 true。

suspended_by_mdio_bus

如果此 PHY 由 MDIO 总线挂起,则设置为 true。

sysfs_links

跟踪 sysfs 符号链接设置/删除的内部布尔值。

loopback_enabled

如果此 PHY 已成功环回,则设置为 true。

downshifted_rate

如果链路速度已降低,则设置为 true。

is_on_sfp_module

如果 PHY 位于 SFP 模块上,则设置为 true。

mac_managed_pm

如果 MAC 驱动程序负责挂起/恢复 PHY,则设置为 true

wol_enabled

如果 PHY 或附加的 MAC 已启用局域网唤醒,则设置为 true。

autoneg

正在使用自协商的标志

link

当前链路状态

autoneg_complete

链路的自动协商已完成的标志

interrupts

已启用中断的标志

irq_suspended

指示 PHY 已挂起的标志,因此中断处理应推迟到 PHY 恢复后

irq_rerun

指示在 PHY 挂起时发生中断的标志,需要在恢复后重新运行中断处理程序

default_timestamp

指示我们是否使用 phy 时间戳作为默认时间戳的标志

rate_matching

当前速率匹配模式

state

出于管理目的的 PHY 状态

dev_flags

PHY 驱动程序使用的特定于设备的标志。

  • 位 [15:0] 可供 PHY 驱动程序自由使用,以传达驱动程序特定的行为。

  • 位 [23:16] 当前保留供将来使用。

  • 位 [31:24] 保留用于定义通用 PHY 驱动程序行为。

interface

enum phy_interface_t

possible_interfaces

如果连接的 PHY 将根据介质速度在接口模式之间切换,则为位图。

speed

当前链路速度

duplex

当前双工

port

当前端口

pause

当前暂停

asym_pause

当前非对称暂停

master_slave_get

当前主/从通告

master_slave_set

用户请求的主/从配置

master_slave_state

当前主/从配置

已支持

组合 MAC/PHY 支持的链路模式

正在广播

当前广播的链路模式

lp_advertising

当前链路伙伴广播的链路模式

adv_old

为 WoL 节省功耗时保存的广播

supported_eee

支持的 PHY EEE 链路模式

advertising_eee

当前广播的 EEE 链路模式

eee_broken_modes

应禁止的节能以太网模式

enable_tx_lpi

当为 True 时,MAC 应将 LPI 传输到 PHY

eee_active

phylib 私有状态,表示已协商 EEE

eee_cfg

EEE 的用户配置

host_interfaces

主机支持的 PHY 接口模式

phy_led_triggers

LED 触发器数组

phy_num_led_triggers

phy_led_triggers 中的触发器数量

last_triggered

链路速度的最后一个 LED 触发器

led_link_trigger

链路启动/关闭的 LED 触发器

leds

PHY LED 结构列表

irq

PHY 中断的 IRQ 号(如果没有则为 -1)

priv

指向驱动程序私有数据的指针

shared

指向同一封装中 PHY 共享的私有数据的指针

skb

用于电缆诊断的 Netlink 消息

ehdr

用于电缆诊断的 Netlink 标头

nest

用于电缆诊断的 Netlink 嵌套

state_queue

用于状态机的工作队列

lock

用于序列化访问 PHY 的互斥锁

sfp_bus_attached

指示 SFP 总线是否已连接的标志

sfp_bus

连接到此 PHY 光纤端口的 SFP 总线

phylink

指向此 PHY 的 phylink 实例的指针

attached_dev

已连接的 enet 驱动程序的设备实例指针

mii_ts

指向时间戳回调的指针

psec

指向电源供电设备控制结构的指针

mdix

当前交叉

mdix_ctrl

交叉的用户设置

pma_extable

PMA/PMD 扩展功能寄存器的缓存值

link_down_events

链路丢失的次数

phy_link_change

phylink 用于链路更改通知的回调

adjust_link

enet 控制器用于响应链路状态更改的回调。

macsec_ops

MACsec 卸载操作。

描述

中断当前仅支持启用或禁用,但将来可以更改以支持启用和禁用特定中断

包含一些用于轮询和中断处理的基础架构,以及处理 PHY 硬件状态变化的基础架构

struct phy_tdr_config

TDR 原始测试的配置

定义:

struct phy_tdr_config {
    u32 first;
    u32 last;
    u32 step;
    s8 pair;
};

成员

first

第一个数据采集点的距离

last

最后一个数据采集点的距离

step

数据采集点之间的步长

pair

要收集数据的电缆对的位图

描述

一个结构,包含 TDR 电缆测试的可能配置参数。驱动程序不需要实现所有参数,但应报告实际使用的参数。所有距离均以厘米为单位。

struct phy_plca_cfg

PLCA(物理层冲突避免)协调子层的配置。

定义:

struct phy_plca_cfg {
    int version;
    int enabled;
    int node_id;
    int node_cnt;
    int to_tmr;
    int burst_cnt;
    int burst_tmr;
};

成员

version

只读 PLCA 寄存器映射版本。-1 = 不可用。设置配置时忽略。格式与 PLCA IDVER 寄存器 (31.CA00) 报告的格式相同。-1 = 不可用。

enabled

PLCA 配置模式(启用/禁用)。-1 = 不可用/不设置。0 = 禁用,任何其他值 = 启用。

node_id

PLCA 本地节点标识符。-1 = 不可用/不设置。允许的值 [0 .. 254]。255 = 节点禁用。

node_cnt

PLCA 节点计数(具有 TO 的最大节点数)。仅对协调器有意义 (node_id = 0)。-1 = 不可用/不设置。允许的值 [1 .. 255]。

to_tmr

PLCA to_timer 的值,以比特时间为单位,它确定 PLCA 传输机会窗口的打开时间。有关详细信息,请参阅 IEEE802.3 第 148 条。to_timer 在所有节点上应设置为相等的值。-1 = 不可用/不设置。允许的值 [0 .. 255]。

burst_cnt

控制允许一个节点在单个传输机会 (TO) 中发送多少个附加帧。默认值 0 表示允许该节点每个 TO 发送一个帧。值 1 允许每个 TO 发送两个帧,依此类推。-1 = 不可用/不设置。允许的值 [0 .. 255]。

burst_tmr

控制等待 MAC 发送新帧之前中断突发的时间,以比特时间为单位。此值应设置为大于 MAC 帧间间隙(通常为 96 比特)的值。-1 = 不可用/不设置。允许的值 [0 .. 255]。

描述

一个结构,包含用于设置/获取 PLCA RS 配置的配置参数。驱动程序不需要实现所有参数,但应报告实际使用的参数。

struct phy_plca_status

PLCA(物理层冲突避免)协调子层的状态。

定义:

struct phy_plca_status {
    bool pst;
};

成员

pst

PLCA 状态,由 PLCA STATUS 寄存器(31.CA03)中的 PST 位报告,表示信标活动。

描述

一个结构,包含 PLCA RS 配置的状态信息。驱动程序不需要实现所有参数,但应报告实际使用的参数。

struct phy_led

由 PHY 驱动的 LED

定义:

struct phy_led {
    struct list_head list;
    struct phy_device *phydev;
    struct led_classdev led_cdev;
    u8 index;
};

成员

list

LED 列表

phydev

此 LED 连接到的 PHY

led_cdev

标准 LED 类结构

index

LED 的编号

struct phy_driver

特定 PHY 类型的驱动程序结构

定义:

struct phy_driver {
    struct mdio_driver_common mdiodrv;
    u32 phy_id;
    char *name;
    u32 phy_id_mask;
    const unsigned long * const features;
    u32 flags;
    const void *driver_data;
    int (*soft_reset)(struct phy_device *phydev);
    int (*config_init)(struct phy_device *phydev);
    int (*probe)(struct phy_device *phydev);
    int (*get_features)(struct phy_device *phydev);
    int (*get_rate_matching)(struct phy_device *phydev, phy_interface_t iface);
    int (*suspend)(struct phy_device *phydev);
    int (*resume)(struct phy_device *phydev);
    int (*config_aneg)(struct phy_device *phydev);
    int (*aneg_done)(struct phy_device *phydev);
    int (*read_status)(struct phy_device *phydev);
    int (*config_intr)(struct phy_device *phydev);
    irqreturn_t (*handle_interrupt)(struct phy_device *phydev);
    void (*remove)(struct phy_device *phydev);
    int (*match_phy_device)(struct phy_device *phydev);
    int (*set_wol)(struct phy_device *dev, struct ethtool_wolinfo *wol);
    void (*get_wol)(struct phy_device *dev, struct ethtool_wolinfo *wol);
    void (*link_change_notify)(struct phy_device *dev);
    int (*read_mmd)(struct phy_device *dev, int devnum, u16 regnum);
    int (*write_mmd)(struct phy_device *dev, int devnum, u16 regnum, u16 val);
    int (*read_page)(struct phy_device *dev);
    int (*write_page)(struct phy_device *dev, int page);
    int (*module_info)(struct phy_device *dev, struct ethtool_modinfo *modinfo);
    int (*module_eeprom)(struct phy_device *dev, struct ethtool_eeprom *ee, u8 *data);
    int (*cable_test_start)(struct phy_device *dev);
    int (*cable_test_tdr_start)(struct phy_device *dev, const struct phy_tdr_config *config);
    int (*cable_test_get_status)(struct phy_device *dev, bool *finished);
    int (*get_sset_count)(struct phy_device *dev);
    void (*get_strings)(struct phy_device *dev, u8 *data);
    void (*get_stats)(struct phy_device *dev, struct ethtool_stats *stats, u64 *data);
    int (*get_tunable)(struct phy_device *dev, struct ethtool_tunable *tuna, void *data);
    int (*set_tunable)(struct phy_device *dev,struct ethtool_tunable *tuna, const void *data);
    int (*set_loopback)(struct phy_device *dev, bool enable);
    int (*get_sqi)(struct phy_device *dev);
    int (*get_sqi_max)(struct phy_device *dev);
    int (*get_plca_cfg)(struct phy_device *dev, struct phy_plca_cfg *plca_cfg);
    int (*set_plca_cfg)(struct phy_device *dev, const struct phy_plca_cfg *plca_cfg);
    int (*get_plca_status)(struct phy_device *dev, struct phy_plca_status *plca_st);
    int (*led_brightness_set)(struct phy_device *dev, u8 index, enum led_brightness value);
    int (*led_blink_set)(struct phy_device *dev, u8 index,unsigned long *delay_on, unsigned long *delay_off);
    int (*led_hw_is_supported)(struct phy_device *dev, u8 index, unsigned long rules);
    int (*led_hw_control_set)(struct phy_device *dev, u8 index, unsigned long rules);
    int (*led_hw_control_get)(struct phy_device *dev, u8 index, unsigned long *rules);
    int (*led_polarity_set)(struct phy_device *dev, int index, unsigned long modes);
};

成员

mdiodrv

所有 MDIO 设备通用的数据

phy_id

读取此 PHY 类型的 UID 寄存器,并将它们与 phy_id_mask 进行 AND 运算的结果。此驱动程序仅适用于 ID 与此字段匹配的 PHY

name

此 PHY 类型的友好名称

phy_id_mask

定义 phy_id 的重要位

features

此 PHY 支持的强制性功能列表(速度、双工等)

flags

一个位域,定义此 PHY 支持的某些其他功能(如中断)

driver_data

静态驱动程序数据

soft_reset

调用以发出 PHY 软件复位

config_init

调用以初始化 PHY,包括在复位后

probe

在发现期间调用。用于设置特定于设备的结构(如果有)

get_features

探测硬件以确定它具有哪些功能。应仅设置 phydev->supported。

get_rate_matching

获取特定 phy 接口支持的速率匹配类型。phy 使用者使用此方法来确定是否为该接口广播较低速度的模式。假设如果在接口上支持速率匹配模式,则该接口的速率可以适应 phy 支持的所有较慢链路速度。如果不支持该接口,则应返回 RATE_MATCH_NONE

suspend

暂停硬件,并在需要时保存状态

resume

恢复硬件,并在需要时还原状态

config_aneg

配置广播,如果 phydev->autoneg 为 on,则重置自动协商,如果 phydev->autoneg 为 off,则强制速度为 phydev 中的当前设置

aneg_done

确定自动协商结果

read_status

确定协商的速度和双工

config_intr

启用或禁用中断。它还应在启用 IRQ 之前和禁用 IRQ 之后清除任何挂起的中断。

handle_interrupt

覆盖默认的中断处理

remove

在需要时清除任何内存

match_phy_device

如果这是给定 phydev 的合适驱动程序,则返回 true。如果为 NULL,则匹配基于 phy_id 和 phy_id_mask。

set_wol

某些设备(例如,qnap TS-119P II)需要更改 PHY 寄存器才能启用局域网唤醒,因此提供了 set_wol 以便在以太网驱动程序的 set_wol 函数中调用。

get_wol

请参阅 set_wol,但用于检查是否启用了局域网唤醒。

link_change_notify

当核心即将更改链路状态时调用以通知 PHY 设备驱动程序。此回调应该用作需要在此链路状态更改时采取操作的驱动程序的修复挂钩。驱动程序绝不允许在其实现中干扰 PHY 设备结构。

read_mmd

用于读取 MMD 寄存器的特定于 PHY 的驱动程序替代。对于特定于 PHY 的驱动程序,此函数是可选的。如果未提供,默认 MMD 读取函数将由 phy_read_mmd() 使用,该函数将对第 45 条 PHY 使用直接读取,或者对第 22 条 PHY 使用间接读取。devnum 是 PHY 设备中的 MMD 设备编号,regnum 是所选 MMD 设备内的寄存器。

write_mmd

用于写入 MMD 寄存器的特定于 PHY 的驱动程序替代。对于特定于 PHY 的驱动程序,此函数是可选的。如果未提供,默认 MMD 写入函数将由 phy_write_mmd() 使用,该函数将对第 45 条 PHY 使用直接写入,或者对第 22 条 PHY 使用间接写入。devnum 是 PHY 设备中的 MMD 设备编号,regnum 是所选 MMD 设备内的寄存器。val 是要写入的值。

read_page

返回当前 PHY 寄存器页码

write_page

设置当前 PHY 寄存器页码

module_info

获取插件模块中包含的 eeprom 的大小和类型

module_eeprom

从插件模块获取 eeprom 信息

cable_test_start

启动电缆测试

cable_test_tdr_start

启动原始 TDR 电缆测试

cable_test_get_status

每秒一次,或者在中断时,请求测试状态。

get_sset_count

统计计数器的数量

get_strings

统计计数器的名称

get_stats

返回统计计数器值

get_tunable

返回可调参数的值

set_tunable

设置可调参数的值

set_loopback

设置 PHY 的环回模式

get_sqi

获取信号质量指示

get_sqi_max

获取最大信号质量指示

get_plca_cfg

返回当前的PLCA配置

set_plca_cfg

设置PLCA配置

get_plca_status

返回当前的PLCA状态信息

led_brightness_set

设置PHY LED亮度。Index 指示应该设置哪个 PHY 的 LED。Value 遵循标准的 LED 类含义,例如 LED_OFF、LED_HALF、LED_FULL。

led_blink_set

设置 PHY LED 闪烁。Index 指示应该配置哪个 PHY 的 LED 进行闪烁。延迟以毫秒为单位,如果两者都为零,则应选择合理的默认值。该调用应调整时间,如果无法完全匹配指定的值。

led_hw_is_supported

硬件是否支持给定的规则。dev:具有 LED 的 PHY 设备 index:PHY 设备的哪个 LED rules:内核对此规则感兴趣

如果支持,返回 0;如果不支持,返回 -EOPNOTSUPP 或错误代码。

led_hw_control_set

设置硬件控制 LED dev:具有 LED 的 PHY 设备 index:PHY 设备的哪个 LED rules:用于控制 LED 的规则

返回 0 或错误代码。

led_hw_control_get

获取硬件如何控制 LED dev:具有 LED 的 PHY 设备 index:PHY 设备的哪个 LED rules:指向用于控制 LED 的规则的指针

*rules 设置为硬件当前的闪烁方式。成功时返回 0,如果当前闪烁无法用规则表示,则返回错误代码或发生其他错误。

led_polarity_set

设置 LED 极性模式 dev:具有 LED 的 PHY 设备 index:PHY 设备的哪个 LED modes:LED 极性模式的位图

使用 modes 中所有必需的极性模式配置 LED,使其正确打开或关闭。

返回 0 或错误代码。

描述

所有函数都是可选的。如果未实现 config_aneg 或 read_status,则 phy 内核使用 genphy 版本。请注意,这些函数都不应在中断时间调用。目标是总线读/写函数能够在总线事务发生时阻塞,并由中断释放(MPC85xx 具有此能力,但目前驱动程序中不支持)。

bool phy_id_compare(u32 id1, u32 id2, u32 mask)

考虑 mask,比较 id1id2

参数

u32 id1

第一个 PHY ID

u32 id2

第二个 PHY ID

u32 mask

PHY ID 掩码,设置的位在匹配中很重要

描述

如果 id1id2 中由 mask 指定的位相匹配,则返回 true。这使用与 (id & mask) == (phy_id & mask) 等效的测试。

bool phydev_id_compare(struct phy_device *phydev, u32 id)

id 与 PHY 的 Clause 22 ID 进行比较

参数

struct phy_device *phydev

PHY 设备

u32 id

要匹配的 PHY ID

描述

phydev clause 22 ID 与提供的 id 进行比较,并根据是否匹配,使用绑定的驱动程序掩码返回 true 或 false。phydev 必须绑定到驱动程序。

void phy_set_eee_broken(struct phy_device *phydev, u32 link_mode)

将 EEE 模式标记为已损坏,以便不进行通告。

参数

struct phy_device *phydev

phy_device 结构

u32 link_mode

已损坏的 EEE 模式

bool phy_is_started(struct phy_device *phydev)

用于检查 PHY 是否启动的便捷函数

参数

struct phy_device *phydev

phy_device 结构

int phy_read(struct phy_device *phydev, u32 regnum)

用于读取给定 PHY 寄存器的便捷函数

参数

struct phy_device *phydev

phy_device 结构

u32 regnum

要读取的寄存器号

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int __phy_read(struct phy_device *phydev, u32 regnum)

用于读取给定 PHY 寄存器的便捷函数

参数

struct phy_device *phydev

phy_device 结构

u32 regnum

要读取的寄存器号

描述

调用者必须已获得 MDIO 总线锁。

int phy_write(struct phy_device *phydev, u32 regnum, u16 val)

用于写入给定 PHY 寄存器的便捷函数

参数

struct phy_device *phydev

phy_device 结构

u32 regnum

要写入的寄存器编号

u16 val

要写入 regnum 的值

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int __phy_write(struct phy_device *phydev, u32 regnum, u16 val)

用于写入给定 PHY 寄存器的便捷函数

参数

struct phy_device *phydev

phy_device 结构

u32 regnum

要写入的寄存器编号

u16 val

要写入 regnum 的值

描述

调用者必须已获得 MDIO 总线锁。

int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)

用于修改 PHY 寄存器的便捷函数

参数

struct phy_device *phydev

指向 struct phy_device 的指针

u32 regnum

寄存器编号

u16 mask

要清除的位的位掩码

u16 set

要设置的位的位掩码

描述

未锁定的辅助函数,允许修改 PHY 寄存器,新寄存器值 = (旧寄存器值 & ~mask) | set

返回负 errno,如果未发生更改则返回 0,如果发生更改则返回 1

phy_read_mmd_poll_timeout

phy_read_mmd_poll_timeout (phydev, devaddr, regnum, val, cond, sleep_us, timeout_us, sleep_before_read)

定期轮询 PHY 寄存器,直到满足条件或发生超时

参数

phydev

phy_device 结构

devaddr

要从中读取的 MMD

regnum

要读取的 MMD 上的寄存器

val

将寄存器读取到的变量

cond

中断条件(通常涉及 val

sleep_us

两次读取之间休眠的最长时间(以微秒为单位)(0 表示紧循环)。请阅读 usleep_range() 函数说明以了解详细信息和限制。

timeout_us

超时时间(以微秒为单位),0 表示永不超时

sleep_before_read

如果为 true,则在读取之前休眠 sleep_us

返回

成功时为 0,超时时为 -ETIMEDOUT。在这两种情况下,args 处的最后读取值都存储在 val 中。如果使用 sleep_us 或 timeout_us,则不能从原子上下文中调用。

int __phy_set_bits(struct phy_device *phydev, u32 regnum, u16 val)

用于设置 PHY 寄存器中的位的便捷函数

参数

struct phy_device *phydev

phy_device 结构

u32 regnum

要写入的寄存器编号

u16 val

要设置的位

描述

调用者必须已获得 MDIO 总线锁。

int __phy_clear_bits(struct phy_device *phydev, u32 regnum, u16 val)

用于清除 PHY 寄存器中位的便捷函数

参数

struct phy_device *phydev

phy_device 结构

u32 regnum

要写入的寄存器编号

u16 val

要清除的位

描述

调用者必须已获得 MDIO 总线锁。

int phy_set_bits(struct phy_device *phydev, u32 regnum, u16 val)

用于设置 PHY 寄存器中的位的便捷函数

参数

struct phy_device *phydev

phy_device 结构

u32 regnum

要写入的寄存器编号

u16 val

要设置的位

int phy_clear_bits(struct phy_device *phydev, u32 regnum, u16 val)

用于清除 PHY 寄存器中位的便捷函数

参数

struct phy_device *phydev

phy_device 结构

u32 regnum

要写入的寄存器编号

u16 val

要清除的位

int __phy_set_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)

用于设置 MMD 上寄存器中位的便捷函数

参数

struct phy_device *phydev

phy_device 结构

int devad

包含要修改的寄存器的 MMD

u32 regnum

要修改的寄存器号

u16 val

要设置的位

描述

调用者必须已获得 MDIO 总线锁。

int __phy_clear_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)

用于清除 MMD 上寄存器中位的便捷函数

参数

struct phy_device *phydev

phy_device 结构

int devad

包含要修改的寄存器的 MMD

u32 regnum

要修改的寄存器号

u16 val

要清除的位

描述

调用者必须已获得 MDIO 总线锁。

int phy_set_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)

用于设置 MMD 上寄存器中位的便捷函数

参数

struct phy_device *phydev

phy_device 结构

int devad

包含要修改的寄存器的 MMD

u32 regnum

要修改的寄存器号

u16 val

要设置的位

int phy_clear_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)

用于清除 MMD 上寄存器中位的便捷函数

参数

struct phy_device *phydev

phy_device 结构

int devad

包含要修改的寄存器的 MMD

u32 regnum

要修改的寄存器号

u16 val

要清除的位

bool phy_interrupt_is_valid(struct phy_device *phydev)

用于测试给定 PHY 中断的便捷函数

参数

struct phy_device *phydev

phy_device 结构

注意

必须与 PHY_POLL 和 PHY_MAC_INTERRUPT 的添加/删除保持同步

bool phy_polling_mode(struct phy_device *phydev)

用于测试是否使用轮询来检测 PHY 状态更改的便捷函数

参数

struct phy_device *phydev

phy_device 结构

bool phy_has_hwtstamp(struct phy_device *phydev)

测试 PHY 是否具有时间戳配置。

参数

struct phy_device *phydev

phy_device 结构

bool phy_has_rxtstamp(struct phy_device *phydev)

测试 PHY 是否支持接收时间戳。

参数

struct phy_device *phydev

phy_device 结构

bool phy_has_tsinfo(struct phy_device *phydev)

测试 PHY 是否报告时间戳和/或 PTP 硬件时钟功能。

参数

struct phy_device *phydev

phy_device 结构

bool phy_has_txtstamp(struct phy_device *phydev)

测试 PHY 是否支持发送时间戳。

参数

struct phy_device *phydev

phy_device 结构

bool phy_is_default_hwtstamp(struct phy_device *phydev)

PHY hwtstamp 是否为默认时间戳

参数

struct phy_device *phydev

指向 phy_device 的指针

描述

这用于获取默认时间戳设备,考虑到新的 API 选择,如果 phydev 未启用 default_timestamp 标志,则默认从 MAC 选择时间戳。

返回

如果 phy 是默认硬件时间戳,则为 True,否则为 false。

bool phy_is_internal(struct phy_device *phydev)

用于测试 PHY 是否为内部的便捷函数

参数

struct phy_device *phydev

phy_device 结构

bool phy_on_sfp(struct phy_device *phydev)

用于测试 PHY 是否位于 SFP 模块上的便捷函数

参数

struct phy_device *phydev

phy_device 结构

bool phy_interface_mode_is_rgmii(phy_interface_t mode)

用于测试 PHY 接口模式是否为 RGMII(所有变体)的便捷函数

参数

phy_interface_t mode

phy_interface_t 枚举

bool phy_interface_mode_is_8023z(phy_interface_t mode)

PHY 接口模式是否使用 802.3z 协商

参数

phy_interface_t mode

enum phy_interface_t 中的一个

描述

如果 PHY 接口模式使用 802.3z 中定义的 16 位协商字,则返回 true。(请参阅 802.3-2015 37.2.1 Config_Reg 编码)

bool phy_interface_is_rgmii(struct phy_device *phydev)

用于测试 PHY 接口是否为 RGMII(所有变体)的便利函数

参数

struct phy_device *phydev

phy_device 结构

用于测试此 PHY 是否为以太网交换机的面向 CPU 端口侧或类似端口的便利函数。

参数

struct phy_device *phydev

phy_device 结构

phy_module_driver

phy_module_driver (__phy_drivers, __count)

用于注册 PHY 驱动程序的辅助宏

参数

__phy_drivers

要注册的 PHY 驱动程序数组

__count

数组中的成员数量

描述

用于在模块初始化/退出时不做任何特殊处理的 PHY 驱动程序的辅助宏。每个模块只能使用此宏一次,调用此宏会替换 module_init()module_exit()

int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask, int (*run)(struct phy_device*))

创建一个新的 phy_fixup 并将其添加到列表中

参数

const char *bus_id

一个与 phydev->mdio.dev.bus_id(或 PHY_ANY_ID)匹配的字符串

u32 phy_uid

用于与 phydev->phy_id(PHY 的 UID)进行匹配。它也可以是 PHY_ANY_UID

u32 phy_uid_mask

在比较之前应用于 phydev->phy_id 和 fixup->phy_uid

int (*run)(struct phy_device *)

找到匹配的 PHY 时要运行的实际代码

int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask)

从列表中删除 phy_fixup

参数

const char *bus_id

一个字符串匹配 phy_fixup_list 中的 fixup->bus_id(或 PHY_ANY_ID)

u32 phy_uid

一个 phy id 匹配 phy_fixup_list 中的 fixup->phy_id(或 PHY_ANY_UID)

u32 phy_uid_mask

在比较之前应用于 phy_uid 和 fixup->phy_uid

struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)

读取指定的 PHY 设备并返回其 phy_device 结构

参数

struct mii_bus *bus

目标 MII 总线

int addr

MII 总线上的 PHY 地址

bool is_c45

如果为 true,则 PHY 使用 802.3 clause 45 协议

描述

bus 上探测 addr 处的 PHY。

当探测 clause 22 PHY 时,读取 ID 寄存器。如果我们找到有效的 ID,则分配并返回一个 struct phy_device

当探测 clause 45 PHY 时,读取“package 中的设备”寄存器。如果“package 中的设备”看起来有效,则读取每个 MMD 的 ID 寄存器,分配并返回一个 struct phy_device

成功时返回分配的 struct phy_device,如果没有 PHY,则返回 -ENODEV,如果总线访问错误,则返回 -EIO

int phy_device_register(struct phy_device *phydev)

在 MDIO 总线上注册 phy 设备

参数

struct phy_device *phydev

要添加到 MDIO 总线的 phy_device 结构

void phy_device_remove(struct phy_device *phydev)

从 MDIO 总线中删除先前注册的 phy 设备

参数

struct phy_device *phydev

要删除的 phy_device 结构

描述

这不会释放 phy_device 本身,它只是反转 phy_device_register() 的效果。调用此函数后,使用 phy_device_free() 释放设备。

int phy_get_c45_ids(struct phy_device *phydev)

读取 phy 设备的 802.3-c45 ID。

参数

struct phy_device *phydev

要读取 802.3-c45 ID 的 phy_device 结构

描述

成功时返回零,总线访问错误时返回 -EIO,如果“package 中的设备”无效,则返回 -ENODEV

struct phy_device *phy_find_first(struct mii_bus *bus)

查找总线上的第一个 PHY 设备

参数

struct mii_bus *bus

目标 MII 总线

int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, void (*handler)(struct net_device*), phy_interface_t interface)

将以太网设备连接到特定的 phy_device

参数

struct net_device *dev

要连接的网络设备

struct phy_device *phydev

指向 phy 设备的指针

void (*handler)(struct net_device *)

用于状态更改通知的回调函数

phy_interface_t interface

PHY 设备的接口

struct phy_device *phy_connect(struct net_device *dev, const char *bus_id, void (*handler)(struct net_device*), phy_interface_t interface)

将以太网设备连接到 PHY 设备

参数

struct net_device *dev

要连接的网络设备

const char *bus_id

要连接的 PHY 设备的 ID 字符串

void (*handler)(struct net_device *)

用于状态更改通知的回调函数

phy_interface_t interface

PHY 设备的接口

描述

用于连接以太网的便捷函数

设备到 PHY 设备。默认行为是由 PHY 基础架构处理所有事情,并且仅在链路状态更改时通知已连接的驱动程序。如果您不希望或不能使用提供的功能,则可以选择仅调用提供所需功能的功能子集。

void phy_disconnect(struct phy_device *phydev)

禁用中断,停止状态机,并分离 PHY 设备

参数

struct phy_device *phydev

目标 phy_device 结构体

int phy_sfp_connect_phy(void *upstream, struct phy_device *phy)

将 SFP 模块的 PHY 连接到上游 PHY

参数

void *upstream

指向上游 phy 设备的指针

struct phy_device *phy

指向 SFP 模块的 phy 设备的指针

描述

此帮助程序允许跟踪链路上的 PHY 设备。它将 SFP 模块的 phy 添加到上游 phy 的 phy 命名空间

返回

成功时为 0,否则为负错误代码。

void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy)

断开 SFP 模块的 PHY 与上游 PHY 的连接

参数

void *upstream

指向上游 phy 设备的指针

struct phy_device *phy

指向 SFP 模块的 phy 设备的指针

描述

此帮助程序允许跟踪链路上的 PHY 设备。它将 SFP 模块的 phy 移除到上游 phy 的 phy 命名空间。由于模块 phy 将被销毁,因此重新插入同一模块将添加一个具有新索引的新 phy。

void phy_sfp_attach(void *upstream, struct sfp_bus *bus)

将 SFP 总线附加到 PHY 上游网络设备

参数

void *upstream

指向 phy 设备的指针

struct sfp_bus *bus

表示正在附加的插笼的 sfp 总线

描述

这用于填写 sfp_upstream_ops .attach 成员。

void phy_sfp_detach(void *upstream, struct sfp_bus *bus)

从 PHY 上游网络设备分离 SFP 总线

参数

void *upstream

指向 phy 设备的指针

struct sfp_bus *bus

表示正在附加的插笼的 sfp 总线

描述

这用于填写 sfp_upstream_ops .detach 成员。

int phy_sfp_probe(struct phy_device *phydev, const struct sfp_upstream_ops *ops)

探测附加到此 PHY 设备的 SFP 插笼

参数

struct phy_device *phydev

指向 phy_device 的指针

const struct sfp_upstream_ops *ops

SFP 的上游操作

int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, u32 flags, phy_interface_t interface)

将网络设备附加到给定的 PHY 设备指针

参数

struct net_device *dev

要附加的网络设备

struct phy_device *phydev

指向要附加的 phy_device 的指针

u32 flags

PHY 设备的 dev_flags

phy_interface_t interface

PHY 设备的接口

描述

由驱动程序调用以附加到特定的 PHY

设备。找到 phy_device,并将其正确连接到 phy_driver。如果未附加驱动程序,则使用通用驱动程序。为 phy_device 提供指向附加设备的 ptr,并为链路状态更改提供回调。phy_device 将返回给附加的驱动程序。此函数采用对 phy 设备的引用。

struct phy_device *phy_attach(struct net_device *dev, const char *bus_id, phy_interface_t interface)

将网络设备附加到特定的 PHY 设备

参数

struct net_device *dev

要附加的网络设备

const char *bus_id

要附加的 PHY 设备的总线 ID

phy_interface_t interface

PHY 设备的接口

描述

与 phy_attach_direct() 相同,只不过传递的是 PHY bus_id

字符串,而不是指向 struct phy_device 的指针。

int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size)

加入一个公共 PHY 组

参数

struct phy_device *phydev

目标 phy_device 结构体

int base_addr

用于全局寄存器访问的偏移计算的 cookie 和 PHY 包的基址

size_t priv_size

如果非零,则为私有数据分配此数量的字节

描述

这将加入一个 PHY 组,并为此组中的所有 phydev 提供共享存储。这旨在用于包含多个 PHY 的包,例如四路 PHY 收发器。

base_addr 参数用作 cookie,对于同一组的所有成员必须具有相同的值,并且作为 PHY 封装的基址 PHY 地址,用于偏移量计算以访问 PHY 封装的通用寄存器。通常,封装中不同 PHY 的其中一个 PHY 地址提供对这些全局寄存器的访问。此处给出的地址将用在 phy_package_read() 和 phy_package_write() 便利函数中作为基址,并添加到这些函数中传递的偏移量。

这将把 phydev 的共享指针设置为共享存储。如果这是此 cookie 的第一次调用,则将分配共享存储。如果 priv_size 非零,则会为 priv 成员分配给定数量的字节。

错误时返回 < 1,成功时返回 0。特别是,使用相同的 cookie 但不同的 priv_size 调用 phy_package_join() 是错误的。

int of_phy_package_join(struct phy_device *phydev, size_t priv_size)

加入 PHY 封装中的公共 PHY 组

参数

struct phy_device *phydev

目标 phy_device 结构体

size_t priv_size

如果非零,则为私有数据分配此数量的字节

描述

这是为 DT 中定义的 PHY 封装提供的 phy_package_join 的变体。

检查 phydev 的父节点是否为有效的 PHY 封装节点结构(通过匹配节点名称“ethernet-phy-package”),并将 PHY 封装的 base_addr 传递给 phy_package_join。

通过此配置,共享结构还将填充 np 值,以便在 PHY 特定的 probe_once 和 config_init_once PHY 封装 OP 中使用其他 DT 定义的属性。

错误时返回 < 0,成功时返回 0。特别是,使用相同的 cookie 但不同的 priv_size 调用 phy_package_join() 是错误的。或者,未检测到父节点或父节点无效,或者与 PHY 封装的预期节点名称不匹配。

void phy_package_leave(struct phy_device *phydev)

离开公共 PHY 组

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

这将离开由 phy_package_join() 创建的 PHY 组。如果此 phydev 是组之间共享数据的最后一个用户,则将释放此数据。将 phydev->shared 指针重置为 NULL。

int devm_phy_package_join(struct device *dev, struct phy_device *phydev, int base_addr, size_t priv_size)

资源管理 phy_package_join()

参数

struct device *dev

正在注册此 PHY 封装的设备

struct phy_device *phydev

目标 phy_device 结构体

int base_addr

用于全局寄存器访问的偏移计算的 cookie 和 PHY 包的基址

size_t priv_size

如果非零,则为私有数据分配此数量的字节

描述

托管的 phy_package_join()。此函数获取的共享存储,驱动程序分离时会自动调用 phy_package_leave()。有关更多信息,请参见 phy_package_join()

int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev, size_t priv_size)

资源管理 of_phy_package_join()

参数

struct device *dev

正在注册此 PHY 封装的设备

struct phy_device *phydev

目标 phy_device 结构体

size_t priv_size

如果非零,则为私有数据分配此数量的字节

描述

托管的 of_phy_package_join()。此函数获取的共享存储,驱动程序分离时会自动调用 phy_package_leave()。有关更多信息,请参见 of_phy_package_join()

void phy_detach(struct phy_device *phydev)

将 PHY 设备与其网络设备分离

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

这将 PHY 设备与其网络设备和 PHY 驱动程序分离,并删除在 phy_attach_direct() 中获取的引用计数。

int phy_reset_after_clk_enable(struct phy_device *phydev)

在需要时执行 PHY 复位

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

已知某些 PHY 在启用其 refclk 后需要复位

此函数评估标志并在需要时执行复位。错误时返回 < 0,如果未复位 PHY 则返回 0,如果复位了 PHY 则返回 1。

int genphy_setup_forced(struct phy_device *phydev)

phydev 配置/强制速度/双工

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

配置 MII_BMCR 以强制速度/双工

为 phydev 中的值。假设这些值有效。请参见 phy_sanitize_settings()

int genphy_restart_aneg(struct phy_device *phydev)

启用并重新启动自动协商

参数

struct phy_device *phydev

目标 phy_device 结构体

int genphy_check_and_restart_aneg(struct phy_device *phydev, bool restart)

启用并重新启动自动协商

参数

struct phy_device *phydev

目标 phy_device 结构体

bool restart

是否请求重新启动 aneg

描述

检查并在需要时重新启动自动协商。

int __genphy_config_aneg(struct phy_device *phydev, bool changed)

重新启动自动协商或写入 BMCR

参数

struct phy_device *phydev

目标 phy_device 结构体

bool changed

是否请求自动协商

描述

如果启用了自动协商,我们将配置

设置通告,然后重新启动自动协商。如果未启用,则写入 BMCR。

int genphy_c37_config_aneg(struct phy_device *phydev)

重新启动自动协商或写入 BMCR

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

如果启用了自动协商,我们将配置

设置通告,然后重新启动自动协商。如果未启用,则写入 BMCR。此函数旨在用于 Clause 37 1000Base-X 模式。

int genphy_aneg_done(struct phy_device *phydev)

返回自动协商状态

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

读取状态寄存器,如果自动协商未完成,或出现错误,则返回 0。

如果自动协商完成,则返回 BMSR_ANEGCOMPLETE。

更新 phydev 中的链路状态

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

更新 phydev->link 中的值以反映

当前链接值。为此,我们需要读取状态寄存器两次,保留第二个值。

int genphy_read_status_fixed(struct phy_device *phydev)

读取非自动协商模式下的链路参数

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

读取禁用自动协商的 PHY 的当前双工和速度状态。

int genphy_read_status(struct phy_device *phydev)

检查链路状态并更新当前链路状态

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

检查链路,然后通过比较我们声明的与链路伙伴声明的来确定当前状态。首先检查千兆的可能性,然后继续 10/100。

通过比较我们声明的与链路伙伴声明的来确定当前状态。首先检查千兆的可能性,然后继续 10/100。

int genphy_c37_read_status(struct phy_device *phydev, bool *changed)

检查链路状态并更新当前链路状态

参数

struct phy_device *phydev

目标 phy_device 结构体

bool *changed

用于存储链路是否已更改的指针

描述

检查链路,然后通过比较我们声明的与链路伙伴声明的来确定当前状态。首先检查千兆的可能性,然后继续 10/100。

通过比较我们声明的与链路伙伴声明的来确定当前状态。此函数用于 Clause 37 1000Base-X 模式。

如果链路已更改,则 changed 设置为 true,否则为 false。

int genphy_soft_reset(struct phy_device *phydev)

通过 BMCR_RESET 位软件复位 PHY

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

使用标准 BMCR_RESET 位执行软件 PHY 复位,并轮询复位位是否被清除。

返回

成功时返回 0,失败时返回 < 0

int genphy_read_abilities(struct phy_device *phydev)

从 Clause 22 寄存器读取 PHY 功能

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

读取 PHY 的功能并相应地填充 phydev->supported。

返回

成功时返回 0,失败时返回 < 0

删除支持的链路模式

参数

struct phy_device *phydev

要从中删除链路模式的 phy_device 结构

u32 link_mode

要删除的链路模式

描述

一些 MAC 不支持 PHY 支持的所有链路模式。例如,1G MAC 通常不支持 1000Half。添加一个帮助器来删除链路模式。

void phy_advertise_supported(struct phy_device *phydev)

声明所有支持的模式

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

调用此函数以声明所有支持的模式,不接触暂停模式声明。

void phy_advertise_eee_all(struct phy_device *phydev)

声明所有支持的 EEE 模式

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

默认情况下,phylib 在 PHY 探测时保留 EEE 声明,这可能是支持的 EEE 模式的子集。当应声明所有支持的 EEE 模式时,请使用此函数。这不会触发自动协商,因此必须在 phy_start()/ phylink_start() 启动自动协商之前调用。

void phy_support_eee(struct phy_device *phydev)

设置初始 EEE 策略配置

参数

struct phy_device *phydev

目标 phy_device 结构

描述

此函数配置指定 PHY 设备上节能以太网 (EEE) 的初始策略,影响在建立链接之前声明 EEE 功能。如果 MAC 支持 LPI 或 PHY 能够补偿 MAC 缺失的 LPI 功能,则 MAC 驱动程序和/或 PHY 驱动程序(对于 SmartEEE PHY)应在 PHY 注册期间调用此函数。

该函数设置默认的 EEE 策略参数,包括准备 PHY 以声明基于硬件支持的 EEE 功能。

它还在 MAC 驱动程序中设置低功耗空闲 (LPI) 的预期配置。如果 PHY 框架确定本地和远程声明都支持 EEE,并且协商的链路模式与 EEE 兼容,它将设置 enable_tx_lpi = true。如果设置了 enable_tx_lpi,则 MAC 驱动程序应通过启用 LPI 计时器来响应此设置。

void phy_support_sym_pause(struct phy_device *phydev)

启用对称暂停的支持

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

由 MAC 调用,以指示支持对称暂停,但不支持非对称暂停。

void phy_support_asym_pause(struct phy_device *phydev)

启用非对称暂停的支持

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

由 MAC 调用,以指示支持非对称暂停。

void phy_set_sym_pause(struct phy_device *phydev, bool rx, bool tx, bool autoneg)

配置对称暂停

参数

struct phy_device *phydev

目标 phy_device 结构体

bool rx

支持接收器暂停

bool tx

支持传输暂停

bool autoneg

应使用自动协商

描述

根据是否支持接收器暂停和暂停自动协商来配置声明的暂停支持。通常从 set_pauseparam .ndo 调用。

void phy_set_asym_pause(struct phy_device *phydev, bool rx, bool tx)

配置暂停和非对称暂停

参数

struct phy_device *phydev

目标 phy_device 结构体

bool rx

支持接收器暂停

bool tx

支持传输暂停

描述

根据是否支持传输和接收器暂停来配置声明的暂停支持。如果广告已更改,则触发新的自动协商。通常从 set_pauseparam .ndo 调用。

bool phy_validate_pause(struct phy_device *phydev, struct ethtool_pauseparam *pp)

测试 PHY/MAC 是否支持暂停配置

参数

struct phy_device *phydev

phy_device 结构体

struct ethtool_pauseparam *pp

请求的暂停配置

描述

测试 PHY/MAC 组合是否支持用户请求的暂停配置。如果支持,则返回 True,否则返回 false。

void phy_get_pause(struct phy_device *phydev, bool *tx_pause, bool *rx_pause)

解析协商的暂停模式

参数

struct phy_device *phydev

phy_device 结构体

bool *tx_pause

指向 bool 类型的指针,指示是否应启用发送暂停。

bool *rx_pause

指向 bool 类型的指针,指示是否应启用接收暂停。

描述

根据协商结果解析并返回流控制模式。这包括检查我们是否在全双工模式下运行。有关详细信息,请参阅 linkmode_resolve_pause()。

s32 phy_get_internal_delay(struct phy_device *phydev, struct device *dev, const int *delay_values, int size, bool is_rx)

返回内部延迟的索引

参数

struct phy_device *phydev

phy_device 结构体

struct device *dev

指向设备的设备结构体的指针

const int *delay_values

PHY 支持的延迟数组

int size

延迟数组的大小

bool is_rx

布尔值,指示获取接收内部延迟

描述

返回传入的内部延迟数组中的索引。如果设备属性不存在,则检查接口类型,如果接口定义了内部延迟的使用,则返回 1,否则返回 0。该数组必须按升序排列。如果 PHY 没有升序排列的数组,则 size = 0 并返回延迟属性的值。如果延迟无效或找不到,则返回 -EINVAL。

struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode)

给定一个 fwnode,查找 mdio_device

参数

struct fwnode_handle *fwnode

指向 mdio_device 的 fwnode 的指针

描述

如果成功,则返回指向 mdio_device 的指针,并且嵌入的 struct device 引用计数增加 1;如果失败,则返回 NULL。调用者应在使用后在 mdio_device 上调用 put_device()

struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode)

对于提供的 phy_fwnode,查找 phy_device。

参数

struct fwnode_handle *phy_fwnode

指向 PHY 的 fwnode 的指针。

描述

如果成功,则返回指向 phy_device 的指针,并且嵌入的 struct device 引用计数增加 1;如果失败,则返回 NULL。

struct phy_device *device_phy_find_device(struct device *dev)

对于给定的设备,获取 phy_device

参数

struct device *dev

指向给定设备的指针

描述

请参考 fwnode_phy_find_device() 的返回条件。

struct fwnode_handle *fwnode_get_phy_node(const struct fwnode_handle *fwnode)

使用命名引用获取 phy_node。

参数

const struct fwnode_handle *fwnode

指向要从中获取 phy_node 的 fwnode 的指针。

描述

请参考 fwnode_find_reference() 的返回条件。对于 ACPI,仅支持 “phy-handle”。ACPI 中不支持旧的 DT 属性 “phy” 和 “phy-device”。DT 支持所有三种指向 PHY 节点的命名引用。

int phy_driver_register(struct phy_driver *new_driver, struct module *owner)

向 PHY 层注册 phy_driver

参数

struct phy_driver *new_driver

要注册的新 phy_driver

struct module *owner

拥有此 PHY 的模块

int get_phy_c45_ids(struct mii_bus *bus, int addr, struct phy_c45_device_ids *c45_ids)

读取指定地址的 802.3-c45 ID。

参数

struct mii_bus *bus

目标 MII 总线

int addr

MII 总线上的 PHY 地址

struct phy_c45_device_ids *c45_ids

存储 c45 ID 信息的位置。

描述

读取 PHY “封装中的设备”。如果这看起来有效,则读取每个设备的 PHY 标识符。在 c45_ids 中返回“封装中的设备”和标识符。

成功时返回零,总线访问错误时返回 -EIO,或者当“封装中的设备”无效或没有设备响应时返回 -ENODEV

int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)

读取指定地址的 clause 22 ID。

参数

struct mii_bus *bus

目标 MII 总线

int addr

MII 总线上的 PHY 地址

u32 *phy_id

用于存储检索到的 ID。

描述

从 **bus** 上 **addr** 处的 PHY 读取 802.3 clause 22 PHY ID,并将其放置在 **phy_id** 中。成功读取且 ID 有效时返回零,总线访问错误时返回 -EIO,如果设备没有响应或 ID 无效则返回 -ENODEV

准备 PHY 层以监视链路状态

参数

struct phy_device *phydev

目标 phy_device 结构体

void (*handler)(struct net_device *)

用于链路状态更改通知的回调函数

描述

告知 PHY 基础架构处理

监视链路状态的详细信息(通过轮询或中断),并在链路状态更改时回调到连接的设备驱动程序。如果要监视自己的链路状态,请不要调用此函数。

int phy_poll_reset(struct phy_device *phydev)

安全等待,直到 PHY 复位正确完成

参数

struct phy_device *phydev

要轮询的 PHY 设备

描述

根据 IEEE 802.3 第 2 节,22.2.4.1.1 小节(在 2008 年发布),

PHY 复位可能需要长达 0.5 秒。必须轮询 MII BMCR 寄存器,直到 BMCR_RESET 位清除。

此外,在完成此操作之前,任何尝试写入 PHY 寄存器的操作都可能无效,甚至会产生 MDIO 总线错误。

一些 PHY(例如 Marvell 88E1111)并不完全符合标准,并且在设置 BMCR_RESET 位后不会完全复位,甚至可能需要进行软复位才能正确重新启动自动协商。为了支持这种有缺陷的 PHY,此函数与标准的 phy_init_hw() 分开,后者将清除 BMCR 中的所有其他位,并重新应用所有特定于驱动程序和特定于板卡的修复。

int genphy_config_advert(struct phy_device *phydev, const unsigned long *advert)

清理并广播自动协商参数

参数

struct phy_device *phydev

目标 phy_device 结构体

const unsigned long *advert

要广播的自动协商参数

描述

使用适当的值写入 MII_ADVERTISE,

在清理这些值之后,以确保我们只广播支持的内容。如果 PHY 的广播没有更改,则返回 < 0 表示错误,0 表示没有更改,> 0 表示已更改。

int genphy_c37_config_advert(struct phy_device *phydev)

清理并广播自动协商参数

参数

struct phy_device *phydev

目标 phy_device 结构体

描述

使用适当的值写入 MII_ADVERTISE,

在清理这些值之后,以确保我们只广播支持的内容。如果 PHY 的广播没有更改,则返回 < 0 表示错误,0 表示没有更改,> 0 表示已更改。此函数适用于 Clause 37 1000Base-X 模式。

int phy_probe(struct device *dev)

探测并初始化 PHY 设备

参数

struct device *dev

要探测和初始化的设备

描述

负责设置 phy_device 结构,并将状态设置为 READY。

struct mii_bus *mdiobus_alloc_size(size_t size)

分配 mii_bus 结构

参数

size_t size

为私有存储分配的额外内存量。如果非零,则 bus->priv 指向该内存。

描述

由总线驱动程序调用以分配要填充的 mii_bus 结构。

struct mii_bus *mdio_find_bus(const char *mdio_name)

给定 mdiobus 的名称,查找 mii_bus。

参数

const char *mdio_name

mdiobus 的名称。

描述

返回对 mii_bus 的引用,如果未找到则返回 NULL。嵌入的 struct device 的引用计数将递增,并且一旦总线完成,必须 put_deviced。

struct mii_bus *of_mdio_find_bus(struct device_node *mdio_bus_np)

给定一个 mii_bus 节点,查找 mii_bus。

参数

struct device_node *mdio_bus_np

指向 mii_bus 的指针。

描述

返回对 mii_bus 的引用,如果未找到则返回 NULL。嵌入的 struct device 的引用计数将递增,并且一旦总线完成,必须 put。

由于 device_node 和 mii_bus 的关联是通过 of_mdiobus_register() 建立的,因此在向 of_mdiobus_register() 注册之前无法找到 mii_bus。

struct phy_device *mdiobus_scan_c22(struct mii_bus *bus, int addr)

扫描总线上的一个地址以查找 C22 MDIO 设备。

参数

struct mii_bus *bus

要扫描的 mii_bus

int addr

要扫描的总线上的地址

描述

此函数扫描 MDIO 总线上的一个地址,查找可以使用寄存器 2 和 3 中的供应商/产品 ID 识别的设备。并非所有 MDIO 设备都有此类寄存器,但 PHY 设备通常有。因此,此函数假定找到的任何内容都是 PHY,或者可以被视为 PHY。其他 MDIO 设备(如交换机)可能在扫描期间找不到。

int __mdiobus_register(struct mii_bus *bus, struct module *owner)

启动给定总线上的所有 PHY 并将其连接到总线

参数

struct mii_bus *bus

目标 mii_bus

struct module *owner

包含总线访问器函数的模块

描述

由总线驱动程序调用以启动所有 PHY

在给定的总线上,将它们附加到总线上。驱动程序应使用 mdiobus_register() 而不是 __mdiobus_register(),除非它们需要传递特定的所有者模块。此函数不会启动非 PHY 的 MDIO 设备。它们应在 DT 中显式列出,并由 of_mdiobus_register() 实例化。

成功返回 0,错误返回 < 0。

void mdiobus_free(struct mii_bus *bus)

释放 struct mii_bus

参数

struct mii_bus *bus

要释放的 mii_bus

描述

此函数会释放 mii_bus 中对底层设备对象的引用。如果这是最后一个引用,则会释放 mii_bus。

int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)

mdiobus_read 函数的未锁定版本

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

u32 regnum

要读取的寄存器号

描述

读取 MDIO 总线寄存器。调用者必须持有 mdio 总线锁。

注意

不得从中断上下文调用。

int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)

mdiobus_write 函数的未锁定版本

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

u32 regnum

要写入的寄存器编号

u16 val

要写入 regnum 的值

描述

写入 MDIO 总线寄存器。调用者必须持有 mdio 总线锁。

注意

不得从中断上下文调用。

int __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set)

mdiobus_modify 函数的未锁定版本

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

u32 regnum

要修改的寄存器号

u16 mask

要清除的位的位掩码

u16 set

要设置的位的位掩码

描述

读取、修改,如果发生任何更改,则将寄存器值写回设备。任何错误都会返回负数。

注意

不得从中断上下文调用。

int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum)

mdiobus_c45_read 函数的未锁定版本

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

int devad

要读取的设备地址

u32 regnum

要读取的寄存器号

描述

读取 MDIO 总线寄存器。调用者必须持有 mdio 总线锁。

注意

不得从中断上下文调用。

int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, u16 val)

mdiobus_write 函数的未锁定版本

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

int devad

要读取的设备地址

u32 regnum

要写入的寄存器编号

u16 val

要写入 regnum 的值

描述

写入 MDIO 总线寄存器。调用者必须持有 mdio 总线锁。

注意

不得从中断上下文调用。

int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum)

mdiobus_read 函数的嵌套版本

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

u32 regnum

要读取的寄存器号

描述

如果嵌套访问 MDIO 总线,请使用 mutex_lock_nested() 来避免 lockdep 误报。

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)

用于读取给定 MII 管理寄存器的便捷函数

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

u32 regnum

要读取的寄存器号

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum)

用于读取给定 MII 管理寄存器的便捷函数

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

int devad

要读取的设备地址

u32 regnum

要读取的寄存器号

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int mdiobus_c45_read_nested(struct mii_bus *bus, int addr, int devad, u32 regnum)

mdiobus_c45_read 函数的嵌套版本

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

int devad

要读取的设备地址

u32 regnum

要读取的寄存器号

描述

如果嵌套访问 MDIO 总线,请使用 mutex_lock_nested() 来避免 lockdep 误报。

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val)

mdiobus_write 函数的嵌套版本

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

u32 regnum

要写入的寄存器编号

u16 val

要写入 regnum 的值

描述

如果嵌套访问 MDIO 总线,请使用 mutex_lock_nested() 来避免 lockdep 误报。

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)

用于写入给定 MII 管理寄存器的便捷函数

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

u32 regnum

要写入的寄存器编号

u16 val

要写入 regnum 的值

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, u16 val)

用于写入给定 MII 管理寄存器的便捷函数

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

int devad

要读取的设备地址

u32 regnum

要写入的寄存器编号

u16 val

要写入 regnum 的值

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int mdiobus_c45_write_nested(struct mii_bus *bus, int addr, int devad, u32 regnum, u16 val)

mdiobus_c45_write 函数的嵌套版本

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

int devad

要读取的设备地址

u32 regnum

要写入的寄存器编号

u16 val

要写入 regnum 的值

描述

如果嵌套访问 MDIO 总线,请使用 mutex_lock_nested() 来避免 lockdep 误报。

注意

不能从中断上下文调用,因为总线读/写函数可能会等待中断结束操作。

int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set)

用于修改给定 MDIO 设备寄存器的便捷函数

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

u32 regnum

要写入的寄存器编号

u16 mask

要清除的位的位掩码

u16 set

要设置的位的位掩码

int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, u16 mask, u16 set)

用于修改给定 MDIO 设备寄存器的便捷函数

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

int devad

要读取的设备地址

u32 regnum

要写入的寄存器编号

u16 mask

要清除的位的位掩码

u16 set

要设置的位的位掩码

int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set)

用于修改给定 MDIO 设备寄存器并返回是否发生更改的便捷函数

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

u32 regnum

要写入的寄存器编号

u16 mask

要清除的位的位掩码

u16 set

要设置的位的位掩码

int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad, u32 regnum, u16 mask, u16 set)

用于修改给定 MDIO 设备寄存器并返回是否发生更改的便捷函数

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

int devad

要读取的设备地址

u32 regnum

要写入的寄存器编号

u16 mask

要清除的位的位掩码

u16 set

要设置的位的位掩码

void mdiobus_release(struct device *d)

mii_bus 设备释放回调

参数

struct device *d

包含 mii_bus 的目标 struct device

描述

当最后一个对 mii_bus 的引用被删除时调用,以释放底层内存。

int mdiobus_create_device(struct mii_bus *bus, struct mdio_board_info *bi)

给定 mdio_board_info 结构,创建一个完整的 MDIO 设备

参数

struct mii_bus *bus

用于在其上创建设备的 MDIO 总线

struct mdio_board_info *bi

描述设备的 mdio_board_info 结构

描述

成功返回 0,错误返回 < 0。

struct phy_device *mdiobus_scan_c45(struct mii_bus *bus, int addr)

在总线上扫描一个地址以查找 C45 MDIO 设备。

参数

struct mii_bus *bus

要扫描的 mii_bus

int addr

要扫描的总线上的地址

描述

此函数扫描 MDIO 总线上的一个地址,查找可以使用寄存器 2 和 3 中的供应商/产品 ID 识别的设备。并非所有 MDIO 设备都有此类寄存器,但 PHY 设备通常有。因此,此函数假定找到的任何内容都是 PHY,或者可以被视为 PHY。其他 MDIO 设备(如交换机)可能在扫描期间找不到。

int __mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad, u32 regnum, u16 mask, u16 set)

mdiobus_modify 函数的未锁定版本

参数

struct mii_bus *bus

mii_bus 结构体

int addr

phy 地址

int devad

要读取的设备地址

u32 regnum

要修改的寄存器号

u16 mask

要清除的位的位掩码

u16 set

要设置的位的位掩码

描述

读取、修改,如果发生任何更改,则将寄存器值写回设备。任何错误都会返回负数。

注意

不得从中断上下文调用。

int mdio_bus_match(struct device *dev, const struct device_driver *drv)

确定给定的 MDIO 驱动程序是否支持给定的 MDIO 设备

参数

struct device *dev

目标 MDIO 设备

const struct device_driver *drv

给定的 MDIO 驱动程序

描述

给定一个 MDIO 设备和一个 MDIO 驱动程序,如果

该驱动程序支持该设备,则返回 1。否则,返回 0。这可能需要调用设备自己的匹配函数,因为不同类别的 MDIO 设备具有不同的匹配标准。

SFP 支持

struct sfp_bus

sfp 总线的内部表示形式

定义:

struct sfp_bus {
};

成员

struct sfp_eeprom_id

原始 SFP 模块标识信息

定义:

struct sfp_eeprom_id {
    struct sfp_eeprom_base base;
    struct sfp_eeprom_ext ext;
};

成员

base

基本 SFP 模块标识结构

ext

扩展 SFP 模块标识结构

描述

有关这些结构成员的定义,请参阅 SFF-8472 规范及相关文档。可从 https://www.snia.org/technology-communities/sff/specifications 获取。

struct sfp_upstream_ops

上游操作结构

定义:

struct sfp_upstream_ops {
    void (*attach)(void *priv, struct sfp_bus *bus);
    void (*detach)(void *priv, struct sfp_bus *bus);
    int (*module_insert)(void *priv, const struct sfp_eeprom_id *id);
    void (*module_remove)(void *priv);
    int (*module_start)(void *priv);
    void (*module_stop)(void *priv);
    void (*link_down)(void *priv);
    void (*link_up)(void *priv);
    int (*connect_phy)(void *priv, struct phy_device *);
    void (*disconnect_phy)(void *priv, struct phy_device *);
};

成员

attach

当 sfp 套接字驱动程序绑定到上游时调用(强制)。

detach

当 sfp 套接字驱动程序从上游解除绑定时调用(强制)。

module_insert

在检测到模块后调用,以确定上游设备是否支持该模块。

module_remove

在模块移除后调用。

module_start

在 PHY 探测步骤后调用。

module_stop

在移除 PHY 之前调用。

link_down

当链路因任何原因无法运行时调用。

link_up

当链路运行时调用。

connect_phy

当在模块上检测到可通过 I2C 访问的 PHY 时调用。

disconnect_phy

当移除具有可通过 I2C 访问的 PHY 的模块时调用。

int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id, unsigned long *support)

解析 EEPROM 基本 ID,设置端口类型。

参数

struct sfp_bus *bus

指向 sfp 模块的 struct sfp_bus 结构的指针。

const struct sfp_eeprom_id *id

指向模块的 struct sfp_eeprom_id 的指针。

unsigned long *support

指向 ethtool 支持掩码的 unsigned long 数组的可选指针。

描述

解析 id 中给出的 EEPROM 标识,并返回 PORT_TPPORT_FIBREPORT_OTHER 中的一个。如果 supportNULL,则还会设置与连接器类型对应的 ethtool ETHTOOL_LINK_MODE_xxx_BIT

如果端口类型未知,则返回 PORT_OTHER

bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id)

指示模块是否可能具有 PHY

参数

struct sfp_bus *bus

指向 sfp 模块的 struct sfp_bus 结构的指针。

const struct sfp_eeprom_id *id

指向模块的 struct sfp_eeprom_id 的指针。

描述

解析 **id** 中给出的 EEPROM 标识,并返回此模块是否可能具有 PHY。

void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, unsigned long *support, unsigned long *interfaces)

解析 eeprom id 以获取支持的链路模式

参数

struct sfp_bus *bus

指向 sfp 模块的 struct sfp_bus 结构的指针。

const struct sfp_eeprom_id *id

指向模块的 struct sfp_eeprom_id 的指针。

unsigned long *support

指向用于 ethtool 支持掩码的 unsigned long 数组的指针

unsigned long *interfaces

指向用于 phy 接口模式掩码的 unsigned long 数组的指针

描述

解析 EEPROM 标识信息,并为模块推导出支持的 ethtool 链路模式。

phy_interface_t sfp_select_interface(struct sfp_bus *bus, const unsigned long *link_modes)

选择合适的 phy_interface_t 模式

参数

struct sfp_bus *bus

指向 sfp 模块的 struct sfp_bus 结构的指针。

const unsigned long *link_modes

ethtool 链路模式掩码

描述

从链路模式掩码为 SFP 模块推导出 phy_interface_t 模式。

void sfp_bus_put(struct sfp_bus *bus)

struct sfp_bus 上放置一个引用

参数

struct sfp_bus *bus

通过 sfp_bus_find_fwnode() 找到的 struct sfp_bus

描述

struct sfp_bus 上放置一个引用,如果这是最后一个引用,则释放底层结构。

int sfp_get_module_info(struct sfp_bus *bus, struct ethtool_modinfo *modinfo)

获取 SFP 模块的 ethtool_modinfo

参数

struct sfp_bus *bus

指向 sfp 模块的 struct sfp_bus 结构的指针。

struct ethtool_modinfo *modinfo

一个 struct ethtool_modinfo

描述

在 **modinfo** 中填充由 **bus** 指定的 sfp 总线上的模块的类型和 eeprom_len 参数。

成功时返回 0,否则返回负的 errno 值。

int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee, u8 *data)

读取 SFP 模块 EEPROM

参数

struct sfp_bus *bus

指向 sfp 模块的 struct sfp_bus 结构的指针。

struct ethtool_eeprom *ee

一个 struct ethtool_eeprom

u8 *data

包含 EEPROM 数据的缓冲区(必须至少为 **ee->len** 字节)

描述

读取由提供的 **ee** 指定的 EEPROM。有关要读取的区域,请参阅 struct ethtool_eeprom 的文档。

成功时返回 0,否则返回负的 errno 值。

int sfp_get_module_eeprom_by_page(struct sfp_bus *bus, const struct ethtool_module_eeprom *page, struct netlink_ext_ack *extack)

从 SFP 模块 EEPROM 读取一页

参数

struct sfp_bus *bus

指向 sfp 模块的 struct sfp_bus 结构的指针。

const struct ethtool_module_eeprom *page

一个 struct ethtool_module_eeprom

struct netlink_ext_ack *extack

用于报告问题的 extack

描述

读取由提供的 **page** 指定的 EEPROM 页。有关要读取的页,请参阅 struct ethtool_module_eeprom 的文档。

成功时返回 0,否则返回负的 errno 值。可能会通过 extack 提供更多错误信息

void sfp_upstream_start(struct sfp_bus *bus)

通知 SFP 网络设备已启动

参数

struct sfp_bus *bus

指向 sfp 模块的 struct sfp_bus 结构的指针。

描述

通知 SFP 插槽网络设备现在已启动,以便可以通过取消断言 TX_DISABLE 来启用模块。这应该从网络设备驱动程序的 struct net_device_ops ndo_open() 方法中调用。

void sfp_upstream_stop(struct sfp_bus *bus)

通知 SFP 网络设备已关闭

参数

struct sfp_bus *bus

指向 sfp 模块的 struct sfp_bus 结构的指针。

描述

通知 SFP 插槽网络设备现在已启动,以便可以通过断言 TX_DISABLE 来禁用模块,从而禁用光模块中的激光。这应该从网络设备驱动程序的 struct net_device_ops ndo_stop() 方法中调用。

void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd)

设置数据信号速率

参数

struct sfp_bus *bus

指向 sfp 模块的 struct sfp_bus 结构的指针。

unsigned int rate_kbd

以 1000 波特为单位的信号速率

描述

为信号速率(与数据速率不同)配置 SFP 模块上的速率选择设置。

可能持有的锁

Phylink 的 state_mutex rtnl 锁 SFP 的 sm_mutex

struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode)

从 fwnode 解析并定位 SFP 总线

参数

const struct fwnode_handle *fwnode

父设备(MAC 或 PHY)的固件节点

描述

解析父设备的固件节点以查找 SFP 总线,并定位 sfp_bus 结构,递增其引用计数。完成后必须通过 sfp_bus_put() 释放。

返回

  • 成功时,指向 sfp_bus 结构的指针,

  • NULL 如果没有指定 SFP,

  • 失败时,一个错误指针值

  • 对应于 fwnode_property_get_reference_args() 详细说明的错误。

  • -ENOMEM 如果我们无法分配总线。

  • 来自上游的 connect_phy() 方法的错误。

int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream, const struct sfp_upstream_ops *ops)

解析并注册相邻设备

参数

struct sfp_bus *bus

通过 sfp_bus_find_fwnode() 找到的 struct sfp_bus

void *upstream

上游私有数据

const struct sfp_upstream_ops *ops

上游的 struct sfp_upstream_ops

描述

为 SFP 总线添加上游驱动程序,如果总线完整,则使用 sfp_register_upstream() 注册 SFP 总线。 这会在总线上创建一个引用,因此在此调用之后可以安全地释放总线。

返回

  • 成功时,指向 sfp_bus 结构的指针,

  • NULL 如果没有指定 SFP,

  • 失败时,一个错误指针值

  • 对应于 fwnode_property_get_reference_args() 详细说明的错误。

  • -ENOMEM 如果我们无法分配总线。

  • 来自上游的 connect_phy() 方法的错误。

void sfp_bus_del_upstream(struct sfp_bus *bus)

删除 sfp 总线

参数

struct sfp_bus *bus

指向 sfp 模块的 struct sfp_bus 结构的指针。

描述

删除先前为 SFP 模块注册的上游连接。 bus 应该已经通过 sfp_bus_add_upstream() 添加。

const char *sfp_get_name(struct sfp_bus *bus)

获取 SFP 设备名称

参数

struct sfp_bus *bus

指向 sfp 模块的 struct sfp_bus 结构的指针。

描述

获取 SFP 设备的名称,如果 bus 有已注册的套接字。 调用者必须持有 RTNL,并且返回的名称仅在 RTNL 释放之前有效。

返回

  • 使用 sfp_register_socket() 注册的 SFP 设备的名称

  • NULL 如果没有设备在 bus 上注册