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;
};

成员

状态

套接字状态 (SS_CONNECTED 等)

类型

套接字类型 (SOCK_STREAM 等)

标志

套接字标志 (SOCK_NOSPACE 等)

文件

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

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

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

此数据包已被看到,因此已完成其统计,请勿再次执行

head_frag

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

帧是否在 wifi 上被确认

no_fcs

请求 NIC 将最后 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

{unnamed_union}

匿名

执行 skb 分配的 CPU。

csum

{unnamed_struct}

匿名

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

csum_start

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

csum_offset

应存储校验和的从 csum_start 开始的偏移量

priority

数据包排队优先级

skb_iif

我们到达的设备的 ifindex

hash

{unnamed_union}

匿名

数据包哈希

vlan_all

{unnamed_struct}

匿名

vlan 字段(proto & tci)

vlan_proto

vlan 封装协议

vlan_tci

{unnamed_union}

匿名

vlan 标记控制信息

napi_id

此 skb 来自的 NAPI 结构的 ID

sender_cpu

(又名 napi_id)XPS 中的源 CPU

secmark

{unnamed_union}

匿名

安全标记

mark

通用数据包标记

reserved_tailroom

{unnamed_union}

匿名

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

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 是否从 PFMEMALLOC 保留区分配

const struct sk_buff *skb

返回 skb dst_entry

返回

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

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

参数

设置 skb dst

const struct sk_buff *skb

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

const struct sk_buff *skb

struct sk_buff *skb

struct dst_entry *dst

描述

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

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

bool skb_dst_is_noref(const struct sk_buff *skb)

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

const struct sk_buff *skb

测试 skb dst 是否未引用计数

unsigned int skb_napi_id(const struct sk_buff *skb)

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

const struct sk_buff *skb

返回 skb 的 NAPI ID

bool skb_unref(struct sk_buff *skb)

参数

设置 skb dst

const struct sk_buff *skb

返回 skb dst_entry

减少 skb 的引用计数

如果我们能释放 skb,则为 true。

void kfree_skb(struct sk_buff *skb)

参数

设置 skb dst

释放具有“NOT_SPECIFIED”原因的 sk_buff

要释放的缓冲区

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

测试 skb 是否从 PFMEMALLOC 保留区分配

const struct sk_buff *skb

返回 skb dst_entry

套接字

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

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

参数

unsigned int size

分配网络缓冲区

要分配的大小

gfp_t priority

描述

分配掩码

从 fclone 缓存分配网络缓冲区

int skb_pad(struct sk_buff *skb, int pad)

参数

设置 skb dst

将 skb 的尾部填充为零

要填充的缓冲区

int pad

要填充的空间

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

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

int skb_queue_empty(const struct sk_buff_head *list)

参数

检查队列是否为空

队列头

const struct sk_buff_head *list

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

int skb_queue_empty(const struct sk_buff_head *list)

参数

检查队列是否为空

队列头

bool skb_queue_empty_lockless(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 是否从 PFMEMALLOC 保留区分配

const struct sk_buff *skb

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

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

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

参数

检查队列是否为空

队列头

测试 skb 是否从 PFMEMALLOC 保留区分配

const struct sk_buff *skb

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

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

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

参数

检查队列是否为空

队列头

测试 skb 是否从 PFMEMALLOC 保留区分配

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

当前缓冲区

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

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

参数

检查队列是否为空

队列头

测试 skb 是否从 PFMEMALLOC 保留区分配

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

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

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

struct sk_buff *skb_get(struct sk_buff *skb)

参数

设置 skb dst

引用缓冲区

再次引用套接字缓冲区并返回指向该缓冲区的指针。

int skb_cloned(const struct sk_buff *skb)

缓冲区是否为克隆

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要检查的缓冲区

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

int skb_header_cloned(const struct sk_buff *skb)

标头是否为克隆

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要检查的缓冲区

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

void __skb_header_release(struct sk_buff *skb)

允许克隆使用 headroom

参数

设置 skb dst

要操作的缓冲区

描述

参见“DOC: dataref and headerless skbs”。

int skb_shared(const struct sk_buff *skb)

缓冲区是否共享

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要检查的缓冲区

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

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

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

参数

设置 skb dst

要检查的缓冲区

gfp_t pri

内存分配的优先级

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

内存分配失败时返回 NULL。

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

创建共享缓冲区的副本

参数

设置 skb dst

要检查的缓冲区

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

参数

设置 skb dst

从 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 列表,这是为堆栈设计的

参数

检查队列是否为空

要添加的新列表

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 列表,每个列表都是一个队列

参数

检查队列是否为空

要添加的新列表

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 字段

参数

设置 skb dst

要添加 len 的缓冲区

int delta

要添加的字节数

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

在 skb 中初始化一个片段

参数

设置 skb dst

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

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 中初始化分页片段

参数

设置 skb dst

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

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 中初始化分页片段

参数

设置 skb dst

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

int i

要初始化的分页片段索引

struct page *page

用于此片段的页面

int off

使用 page 的数据偏移量

int size

数据的长度

描述

如果页面不属于我们,则 skb_fill_page_desc() 的变体不处理 pfmemalloc。

unsigned int skb_headroom(const struct sk_buff *skb)

缓冲区头部的字节数

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要检查的缓冲区

返回 sk_buff 头部处的空闲空间字节数。

int skb_tailroom(const struct sk_buff *skb)

缓冲区末尾的字节数

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要检查的缓冲区

返回 sk_buff 尾部的空闲空间字节数

int skb_availroom(const struct sk_buff *skb)

缓冲区末尾的字节数

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要检查的缓冲区

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

void skb_reserve(struct sk_buff *skb, int len)

调整 headroom

参数

设置 skb dst

要更改的缓冲区

int len

要移动的字节数

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

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

调整 reserved_tailroom

参数

设置 skb dst

要更改的缓冲区

unsigned int mtu

允许的最大 headlen

unsigned int needed_tailroom

reserved_tailroom 的最小量

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

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

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

参数

设置 skb dst

要更改的缓冲区

unsigned int len

新长度

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

void skb_orphan(struct sk_buff *skb)

孤立缓冲区

参数

设置 skb dst

要孤立的缓冲区

如果缓冲区当前有一个所有者,那么我们调用所有者的析构函数,并使 skb 无所有者。缓冲区继续存在,但不再向其前所有者收费。

int skb_orphan_frags(struct sk_buff *skb, gfp_t gfp_mask)

孤立缓冲区中包含的 frags

参数

设置 skb dst

从中孤立 frags 的缓冲区

gfp_t gfp_mask

替换页面的分配掩码

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

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

要测试的页面

描述

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

返回 skb dst_entry

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

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

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

参数

const struct page *page

从 skb_alloc_page 分配的页面

设置 skb dst

可能需要设置 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

片段

返回 skb dst_entry

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

struct page *skb_frag_page(const skb_frag_t *frag)

检索分页片段引用的页面

参数

const skb_frag_t *frag

分页片段

返回 skb dst_entry

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

netmem_ref skb_frag_netmem(const skb_frag_t *frag)

检索片段引用的 netmem

参数

const skb_frag_t *frag

片段

返回 skb dst_entry

frag 关联的 netmem_ref

void *skb_frag_address(const skb_frag_t *frag)

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

参数

const skb_frag_t *frag

分页片段缓冲区

返回 skb dst_entry

frag 中数据的地址。必须已映射该页面。

void *skb_frag_address_safe(const skb_frag_t *frag)

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

参数

const skb_frag_t *frag

分页片段缓冲区

返回 skb dst_entry

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)

克隆的标头是否可写

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要检查的缓冲区

unsigned int len

要写入的长度

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

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

需要时复制 skb 的标头

参数

设置 skb dst

要 cow 的缓冲区

unsigned int headroom

所需的头部空间

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

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

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

skb_cow 但只使头部可写

参数

设置 skb dst

要 cow 的缓冲区

unsigned int headroom

所需的头部空间

此函数与 skb_cow 相同,只不过我们将 skb_cloned 检查替换为 skb_header_cloned。当您只需要推送一些标头而不需要修改数据时,应使用此函数。

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

将 skbuff 填充到最小大小

参数

设置 skb dst

将 skb 的尾部填充为零

unsigned int len

最小长度

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

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

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

参数

设置 skb dst

将 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 填充到最小大小

参数

设置 skb dst

将 skb 的尾部填充为零

unsigned int len

最小长度

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

int skb_linearize(struct sk_buff *skb)

将分页 skb 转换为线性 skb

参数

设置 skb dst

要线性的缓冲区

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

bool skb_has_shared_frag(const struct sk_buff *skb)

任何片段都可以被覆盖吗?

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要测试的缓冲区

返回 skb dst_entry

如果 skb 至少有一个可能被外部实体修改的片段(如 vmsplice()/sendfile() 中),则为 true

int skb_linearize_cow(struct sk_buff *skb)

确保 skb 是线性和可写的

参数

设置 skb dst

要处理的缓冲区

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

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

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

参数

设置 skb dst

要更新的缓冲区

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 的校验和

参数

设置 skb dst

要更新的缓冲区

const void *start

push 后的数据开始

unsigned int len

push 的数据长度

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

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

push skb 并更新接收校验和

参数

设置 skb dst

要更新的缓冲区

unsigned int len

pull 的数据长度

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

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

trim 接收的 skb 并更新校验和

参数

设置 skb dst

要 trim 的缓冲区

unsigned int len

新长度

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

bool skb_needs_linearize(struct sk_buff *skb, netdev_features_t features)

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

参数

设置 skb dst

要检查的套接字缓冲区

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 获取时间戳

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

从中获取时间戳的 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)

传递带有 tx 时间戳的克隆 skb

参数

设置 skb dst

原始传出数据包的克隆

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)

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

参数

设置 skb dst

一个套接字缓冲区。

描述

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

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

void skb_complete_wifi_ack(struct sk_buff *skb, bool acked)

发送具有 wifi 状态的 skb

参数

设置 skb dst

原始传出数据包

bool acked

确认状态

__sum16 skb_checksum_complete(struct sk_buff *skb)

计算整个数据包的校验和

参数

设置 skb dst

要处理的数据包

此函数计算整个数据包的校验和加上 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 单位存储

缓冲区头

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

注意

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

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

void skb_checksum_none_assert(const struct sk_buff *skb)

确保 skb ip_summed 为 CHECKSUM_NONE

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要检查的 skb

描述

新的 skb 的 ip_summed 设置为 CHECKSUM_NONE。我们可以使用这个助手来记录我们做出此断言的地方,而不是强制 ip_summed 为 CHECKSUM_NONE。

bool skb_head_is_locked(const struct sk_buff *skb)

确定 skb->head 是否已锁定

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要检查的 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

8 字节对齐的 skc_daddr & skc_rcv_saddr 的 __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_BROADCASTSO_KEEPALIVESO_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

此连接的 tx 队列号

skc_rx_queue_mapping

此连接的 rx 队列号

{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;
    union {
        u8 sk_txrehash;
        u8 sk_scm_recv_flags;
        struct {
            u8 sk_scm_credentials : 1,sk_scm_security : 1,sk_scm_pidfd : 1,sk_scm_rights : 1, sk_scm_unused : 4;
        };
    };
    u8 sk_clockid;
    u8 sk_txtime_deadline_mode : 1,sk_txtime_report_errors : 1, sk_txtime_unused : 6;
#define SK_BPF_CB_FLAG_TEST(SK, FLAG) ((SK)->sk_bpf_cb_flags & (FLAG));
    u8 sk_bpf_cb_flags;
    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;
#if IS_ENABLED(CONFIG_PROVE_LOCKING) && IS_ENABLED(CONFIG_MODULES);
    struct module           *sk_owner;
#endif;
};

成员

__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

没有数据时 busy_poll 的微秒数

sk_napi_id

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

sk_busy_poll_budget

busy_polling 时的 napi 处理预算

sk_prefer_busy_poll

首选 busy_polling 而不是 softirq 处理

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

dst_pending_confirm

sk_pacing_status

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

sk_frag

缓存的页面 frag

sk_timer

套接字清理计时器

sk_pacing_rate

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

sk_zckey

用于对 MSG_ZEROCOPY 通知进行排序的计数器

sk_tskey

用于消除并发 tstamp 请求歧义的计数器

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

如果 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

原始 sock 创建者的 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

在此 sock 上执行的断开连接操作的数量

{unnamed_union}

匿名

sk_txrehash

启用 TX 哈希重新思考

sk_scm_recv_flags

scm_recv() 使用的所有标志

{unnamed_struct}

匿名

sk_scm_credentials

由 SO_PASSCRED 标记以接收 SCM_CREDENTIALS

sk_scm_security

由 SO_PASSSEC 标记以接收 SCM_SECURITY

sk_scm_pidfd

由 SO_PASSPIDFD 标记以接收 SCM_PIDFD

sk_scm_rights

由 SO_PASSRIGHTS 标记以接收 SCM_RIGHTS

sk_scm_unused

scm_recv() 的未使用标志

sk_clockid

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

sk_txtime_deadline_mode

设置 SO_TXTIME 的截止时间模式

sk_txtime_report_errors

设置 SO_TXTIME 的报告错误模式

sk_txtime_unused

未使用的 txtime 标志

sk_bpf_cb_flags

在 bpf_setsockopt() 中使用

sk_user_data

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

sk_security

由安全模块使用

sk_cgrp_data

此 cgroup 的 cgroup 数据

sk_state_change

回调以指示 sock 状态的更改

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。

sk_owner

对调用 sock_lock_init_class_and_name() 的套接字的实际所有者的引用。

bool sk_user_data_is_nocopy(const struct sock *sk)

测试是否不得复制 sk_user_data 指针

参数

检查 fclone 是否繁忙

const struct sock *sk

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

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

参数

检查 fclone 是否繁忙

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

参数

检查 fclone 是否繁忙

const struct sock *sk

uintptr_t flags

标志位

sk_for_each_entry_offset_rcu

sk_for_each_entry_offset_rcu (tpos, pos, head, offset)

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

参数

tpos

用作循环光标的 type *。

pos

用作循环光标的 struct hlist_node

结束指针

列表的 head。

offset

struct 中 hlist_node 的偏移量。

bool lock_sock_fast(struct sock *sk)

lock_sock 的快速版本

参数

struct sock *sk

const 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

const struct sock *sk

bool slow

慢速模式

描述

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

int sk_wmem_alloc_get(const struct sock *sk)

返回写入分配

参数

检查 fclone 是否繁忙

const struct sock *sk

返回 skb dst_entry

sk_wmem_alloc 减去 1 的初始偏移量

int sk_rmem_alloc_get(const struct sock *sk)

返回读取分配

参数

检查 fclone 是否繁忙

const struct sock *sk

返回 skb dst_entry

sk_rmem_alloc

bool sk_has_allocations(const struct sock *sk)

检查是否已进行分配

参数

检查 fclone 是否繁忙

const struct sock *sk

返回 skb dst_entry

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

bool skwq_has_sleeper(struct socket_wq *wq)

检查是否有任何等待进程

参数

struct socket_wq *wq

struct socket_wq

返回 skb dst_entry

如果 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 最终可能会调用计划程序并永远休眠。

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

poll_wait 调用的包装器。

参数

struct file *filp

文件

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

const struct sock *sk

描述

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

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

返回 skb dst_entry

如果上下文允许,则每个任务的 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(不适用于使用 seqno 的 TCP)

注意

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

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

如果不再需要,则释放 skb

参数

struct sock *sk

从中提取此 skb 的套接字

设置 skb dst

要提取的套接字缓冲区

描述

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

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

socket 绑定到 file

参数

struct socket *sock

const struct sock *sk

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

文件

如果失败,则返回 NULL

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

从文件号转到其套接字槽

参数

int fd

文件句柄

int *err

指向错误代码返回的指针

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

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

struct socket *sock_alloc(void)

分配一个套接字

参数

void

无参数

描述

分配一个新的 inode 和 socket 对象。这两个对象绑定在一起并进行初始化。然后返回 socket。如果 inode 不够用,则返回 NULL。此函数在内部使用 GFP_KERNEL。

void sock_release(struct socket *sock)

关闭一个 socket

参数

struct socket *sock

要关闭的 socket

如果 socket 有释放回调函数,则从协议栈中释放该 socket,然后如果 socket 绑定到 inode 而不是文件,则释放该 inode。

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

通过 sock 发送消息

参数

struct socket *sock

const struct sock *sk

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

const struct sock *sk

struct msghdr *msg

消息头

struct kvec *vec

内核 vec

size_t num

vec 数组长度

size_t size

总消息数据大小

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

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

sock 接收消息

参数

struct socket *sock

const struct sock *sk

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)

从 socket 接收消息(内核空间)

参数

struct socket *sock

从中接收消息的 socket

struct msghdr *msg

接收到的消息

struct kvec *vec

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

size_t num

输入 s/g 数组的大小

size_t size

要读取的字节数

int flags

消息标志(MSG_DONTWAIT 等)

在返回时,msg 结构包含 vec 参数中传入的 scatter/gather 数组。修改数组,使其由原始数组的未填充部分组成。

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

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

创建一个 socket

参数

int family

协议族(AF_INET,...)

int type

通信类型(SOCK_STREAM,...)

int protocol

协议(0,...)

struct socket **res

新的 socket

创建一个新的 socket 并将其分配给 res,通过 LSM。新的 socket 初始化尚未完成,请参阅 kernel_accept()。返回 0 或错误。如果失败,则将 res 设置为 NULL。此函数在内部使用 GFP_KERNEL。

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

创建一个 socket

参数

struct net *net

net 命名空间

int family

协议族(AF_INET,...)

int type

通信类型(SOCK_STREAM,...)

int protocol

协议(0,...)

struct socket **res

新的 socket

int kern

用于内核空间 socket 的布尔值

创建一个新的 socket 并将其分配给 res,通过 LSM。返回 0 或错误。如果失败,则将 res 设置为 NULL。如果 socket 位于内核空间中,则 kern 必须设置为 true。此函数在内部使用 GFP_KERNEL。

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

创建一个 socket

参数

int family

协议族(AF_INET,...)

int type

通信类型(SOCK_STREAM,...)

int protocol

协议(0,...)

struct socket **res

新的 socket

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

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

创建一个 socket(内核空间)

参数

struct net *net

net 命名空间

int family

协议族(AF_INET,...)

int type

通信类型(SOCK_STREAM,...)

int protocol

协议(0,...)

struct socket **res

新的 socket

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

int sock_register(const struct net_proto_family *ops)

添加一个 socket 协议处理程序

参数

const struct net_proto_family *ops

协议的描述

协议处理程序调用此函数来声明其地址族,并将其链接到 socket 接口中。值 ops->family 对应于 socket 系统调用协议族。

void sock_unregister(int family)

移除一个协议处理程序

参数

int family

要移除的协议族

协议处理程序调用此函数来移除其地址族,并将其从新的 socket 创建中取消链接。

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

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

将地址绑定到 socket(内核空间)

参数

struct socket *sock

const struct sock *sk

struct sockaddr *addr

地址

int addrlen

地址的长度

返回 0 或错误。

int kernel_listen(struct socket *sock, int backlog)

将 socket 移动到侦听状态(内核空间)

参数

struct socket *sock

const struct sock *sk

int backlog

挂起的连接队列大小

返回 0 或错误。

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

接受连接(内核空间)

参数

struct socket *sock

侦听 socket

struct socket **newsock

新的已连接 socket

int flags

标志

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

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

连接一个 socket(内核空间)

参数

struct socket *sock

const struct sock *sk

struct sockaddr *addr

地址

int addrlen

地址长度

int flags

标志(O_NONBLOCK,...)

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

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

获取 socket 绑定的地址(内核空间)

参数

struct socket *sock

const struct sock *sk

struct sockaddr *addr

地址持有者

用 socket 绑定的地址填充 addr 指针。返回地址的字节长度或错误代码。

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

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

参数

struct socket *sock

const struct sock *sk

struct sockaddr *addr

地址持有者

用 socket 连接的地址填充 addr 指针。返回地址的字节长度或错误代码。

int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd

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

参数

struct socket *sock

const struct sock *sk

enum sock_shutdown_cmd how

连接部分

返回 0 或错误。

u32 kernel_sock_ip_overhead(struct sock *sk)

返回 socket 施加的 IP 开销

参数

struct sock *sk

const struct sock *sk

此例程返回 socket 施加的 IP 开销,即底层 IP 头的长度,具体取决于这是一个 IPv4 还是 IPv6 socket,以及从 socket 上启用的 IP 选项的长度。假设调用方拥有 socket 上的锁。

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() 以确保在返回时没有用户。

u32 napi_skb_cache_get_bulk(void **skbs, u32 n)

从缓存中获取多个零填充的 skb 头部

参数

void **skbs

指向至少 n 大小的数组的指针,用于填充 skb 指针

u32 n

要提供的条目数

描述

尝试从 NAPI percpu 缓存中获取 nsk_buff 条目,并将指针写入提供的数组 skbs 中。如果可用条目较少,则尝试补充缓存,并在需要时从 MM 层批量分配差异。头部将使用 memset()__GFP_ZERO 进行零填充,因此它们已准备好用于 {,__}build_skb_around(),并且没有附加任何数据缓冲区。必须从 BH 上下文中调用。

返回 skb dst_entry

成功分配的 skb 的数量(如果没有实际分配,则为 n

所需,或 kmem_cache_alloc_bulk() 没有失败)。

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

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

参数

设置 skb dst

调用方提供的 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)

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

参数

unsigned int size

分配网络缓冲区

gfp_t gfp_mask

gfp_t priority

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

get_free_pages 掩码,传递给 alloc_skb

分配一个新的 sk_buff 并为其分配一个使用计数。缓冲区具有内置的 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)

私有函数

参数

设置 skb dst

const 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

设置 skb dst

释放具有“NOT_SPECIFIED”原因的 sk_buff

enum skb_drop_reason reason

丢弃此 skb 的原因

减少缓冲区的引用计数,如果使用计数达到零则释放它。同时,将接收套接字和丢弃原因传递给 'kfree_skb' 跟踪点。

void skb_tx_error(struct sk_buff *skb)

报告 sk_buff xmit 错误

参数

设置 skb dst

触发错误的缓冲区

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

void consume_skb(struct sk_buff *skb)

释放 skbuff

参数

设置 skb dst

释放具有“NOT_SPECIFIED”原因的 sk_buff

减少缓冲区的引用计数,如果使用计数达到零则释放它。与 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 变形为另一个

参数

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 缓冲区复制到内核

参数

设置 skb dst

要修改的 skb

gfp_t gfp_mask

分配优先级

必须在带有 SKBFL_ZEROCOPY_ENABLE 的 skb 上调用此函数。它会将所有 frags 复制到内核并删除对用户空间页面的引用。

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

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

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

复制 sk_buff

参数

设置 skb dst

要克隆的缓冲区

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 的私有副本

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要复制的缓冲区

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 副本。

参数

设置 skb dst

要复制的缓冲区

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 的标头

参数

设置 skb dst

要重新分配的缓冲区

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 的标头

参数

设置 skb dst

要重新分配的缓冲区

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

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要复制的缓冲区

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)

int skb_pad(struct sk_buff *skb, int pad)

参数

设置 skb dst

将 skb 的尾部填充为零

要填充的缓冲区

int pad

bool free_on_error

错误时释放缓冲区

要填充的空间

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

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

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

参数

设置 skb dst

要使用的缓冲区的开头

struct sk_buff *tail

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

int len

要添加的数据量

此函数扩展了可能分段的缓冲区的使用数据区域。tail 必须是 skb 的最后一个片段 - 或 skb 本身。如果这会超过总缓冲区大小,内核将会崩溃。返回指向额外数据的第一个字节的指针。

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

将数据添加到缓冲区

参数

设置 skb dst

要使用的缓冲区

unsigned int len

要添加的数据量

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

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

将数据添加到缓冲区的开头

参数

设置 skb dst

要使用的缓冲区

unsigned int len

要添加的数据量

此函数在缓冲区开头扩展了缓冲区的使用数据区域。如果这会超过总缓冲区预留空间,内核将会崩溃。返回指向额外数据的第一个字节的指针。

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

从缓冲区的开头删除数据

参数

设置 skb dst

要使用的缓冲区

unsigned int len

要删除的数据量

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

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

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

参数

设置 skb dst

要使用的缓冲区

size_t len

要删除的数据量

此函数从缓冲区的开头删除数据,将内存返回到预留空间。返回指向缓冲区中原始数据的指针,并检查是否有足够的数据可供拉取。拉取数据后,未来的推送将会覆盖旧数据。

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

从缓冲区删除结尾

参数

设置 skb dst

要更改的缓冲区

unsigned int len

新长度

通过从尾部删除数据来缩短缓冲区的长度。如果缓冲区已低于指定的长度,则不会对其进行修改。skb 必须是线性的。

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

推进 skb 标头的尾部

参数

设置 skb dst

要重新分配的缓冲区

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 复制到内核缓冲区

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

源 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

参数

设置 skb dst

目标缓冲区

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

目标缓冲区中线性预留空间的大小

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

由 skb_zerocopy_headlen() 计算的 hlen 指定 to 缓冲区中的预留空间。

返回值:0:一切正常 -ENOMEM:由于内存不足,无法孤立 from 的 frags -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 函数安全地一起使用。

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

从列表中删除缓冲区

参数

设置 skb dst

要删除的缓冲区

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 分成两部分。

参数

设置 skb dst

要拆分的缓冲区

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 数据的顺序读取

参数

设置 skb dst

要读取的缓冲区

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

要复制的字节数

描述

将来自源 stoffset 字节的 len 字节复制到目标缓冲区 to。 对于此函数的每个后续调用,offset 应该增加(或保持不变)。 如果偏移量需要比上次使用时减少,则应首先重置 st

返回 skb dst_entry

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

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

在 skb 数据中查找文本模式

参数

设置 skb dst

要在其中查找的缓冲区

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 并更新接收校验和

参数

设置 skb dst

要更新的缓冲区

unsigned int len

pull 的数据长度

此函数对数据包执行 skb_pull 并更新 CHECKSUM_COMPLETE 校验和。 除非您知道校验和差异为零(例如,有效的 IP 标头),否则应在接收路径处理中使用它而不是 skb_pull,或者您要将 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)

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

参数

设置 skb dst

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

struct scatterlist *sg

要映射到的分散聚集列表

int offset

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

int len

要映射的缓冲区空间长度

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

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

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

参数

设置 skb dst

要检查的套接字缓冲区。

int tailbits

要添加的尾部空间量

struct sk_buff **trailer

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

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

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

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

struct sk_buff *skb_clone_sk(struct sk_buff *skb)

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

参数

设置 skb dst

要克隆的 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)

设置和验证数据包的部分 csum 值

参数

设置 skb dst

要设置的 skb

u16 start

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

u16 off

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

描述

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

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

int skb_checksum_setup(struct sk_buff *skb, bool recalculate)

设置部分校验和偏移量

参数

设置 skb dst

要设置的 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 的校验和

参数

设置 skb dst

要检查的 skb

unsigned int transport_len

网络标头之外的数据长度

__sum16(*skb_chkf)(struct sk_buff *skb)

要使用的校验和函数

描述

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

如果 skb 在给定的传输长度之外有数据,则检查并返回经过修剪和克隆的 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

参数

设置 skb dst

要清理的缓冲区

bool xnet

数据包正在跨越 netns

描述

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

int skb_eth_pop(struct sk_buff *skb)

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

参数

设置 skb dst

要修改的套接字缓冲区

描述

删除 skb 的以太网标头。

期望 skb->data 指向 mac 标头并且不存在 VLAN 标记。

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

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

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

参数

设置 skb dst

要修改的套接字缓冲区

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 标头

参数

设置 skb dst

const struct sk_buff *skb

__be32 mpls_lse

要推送的 MPLS 标签堆栈条目

__be16 mpls_proto

新 MPLS 标头的 ethertype(期望 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 标头

参数

设置 skb dst

const struct sk_buff *skb

__be16 next_proto

弹出 MPLS 标头后的标头的 ethertype

int mac_len

MAC 标头的长度

bool ethernet

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

描述

期望 skb->data 位于 mac 标头处。

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

int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse)

修改最外层的 MPLS 标头并更新 csum

参数

设置 skb dst

const struct sk_buff *skb

__be32 mpls_lse

要更新到的新 MPLS 标签堆栈条目

描述

期望 skb->data 位于 mac 标头处。

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

int skb_mpls_dec_ttl(struct sk_buff *skb)

递减最外层的 MPLS 标头的 TTL

参数

设置 skb dst

const 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

gfp_t priority

描述

这可用于分配分页的 skb,给定片段的最大顺序。

void skb_condense(struct sk_buff *skb)

尝试尽可能地消除碎片/frag_list。

参数

设置 skb dst

const struct sk_buff *skb

描述

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

注意

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

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

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

参数

设置 skb dst

const 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

参数

设置 skb dst

要添加页面的缓冲区

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)

通用套接字能力测试

参数

检查 fclone 是否繁忙

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

struct user_namespace *user_ns

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

int cap

要使用的能力

描述

测试套接字的打开者在创建套接字时是否具有以及当前进程是否在用户名空间 user_ns 中具有能力 cap

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

套接字全局能力测试

参数

检查 fclone 是否繁忙

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

int cap

要使用的全局能力

描述

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

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

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

参数

检查 fclone 是否繁忙

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

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

适用的网络命名空间

int family

协议族

要分配的大小

用于分配(GFP_KERNEL, GFP_ATOMIC 等)

struct proto *prot

与此新 sock 实例关联的 struct proto

int kern

这是否是一个内核套接字?

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

克隆一个套接字,并锁定其克隆

参数

检查 fclone 是否繁忙

要克隆的套接字

const gfp_t priority

用于分配(GFP_KERNEL, GFP_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

要等待的 sock

long *timeo

等待多久

测试 skb 是否从 PFMEMALLOC 保留区分配

在 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

const 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

const 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

const struct sock *sk

struct sk_buff_head *queue

从中接收数据的套接字队列

unsigned int flags

MSG_ 标志

int *off

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

int *err

返回的错误代码

struct sk_buff **last

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

获取一个数据报 skbuff,了解窥视、非阻塞唤醒和可能的竞争。这取代了 packet、raw 和 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

const struct sock *sk

设置 skb dst

数据报 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_crc32c_datagram_iter(const struct sk_buff *skb, int offset, struct iov_iter *to, int len, u32 *crcp)

将数据报复制到 iovec 迭代器并更新 CRC32C 值。

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要复制的缓冲区

int offset

从缓冲区开始复制的偏移量

struct iov_iter *to

要复制到的 iovec 迭代器

int len

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

u32 *crcp

指向要更新的 CRC32C 值的指针

返回 skb dst_entry

成功时返回 0,复制过程中发生故障时返回 -EFAULT。

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

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

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要复制的缓冲区

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 复制数据报。

参数

设置 skb dst

要复制的缓冲区

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 构建零拷贝数据报

参数

设置 skb dst

要复制的缓冲区

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。

参数

设置 skb dst

skbuff

int hlen

硬件长度

struct msghdr *msg

目的地

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

返回 skb dst_entry

0 - 成功。

-EINVAL - 校验和失败。 -EFAULT - 复制期间发生故障。

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

通用数据报轮询

参数

struct file *file

文件结构

struct socket *sock

const struct sock *sk

poll_table *wait

轮询表

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

注意

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

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

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

等待套接字进入连接状态

参数

struct sock *sk

要等待的 sock

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 关联的 sock

设置 skb dst

要过滤的缓冲区

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

队列长度

backlog

队列的 backlog 大小

drops

丢弃的数据包数

requeues

重新排队数

overlimits

超过限制的入队数

struct gnet_estimator

速率估算器配置

定义:

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

成员

interval

采样周期

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)

在兼容模式下启动转储过程

参数

设置 skb dst

套接字缓冲区,用于放入统计信息 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)

在兼容模式下启动转储过程

参数

设置 skb dst

套接字缓冲区,用于放入统计信息 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)

将基本 hw 统计信息复制到统计信息 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

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

unsigned int xdr_buf_to_bvec(struct bio_vec *bvec, unsigned int bvec_size, const struct xdr_buf *xdr)

将 xdr_buf 的组件复制到 bio_vec 数组中

参数

struct bio_vec *bvec

要填充的 bio_vec 数组

unsigned int bvec_size

bio_vec 的元素计数

const struct xdr_buf *xdr

要复制的 xdr_buf

描述

返回 bvec 中消耗的条目数。

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

指向 struct xdr_stream 的指针

unsigned int xdr_page_pos(const struct xdr_stream *xdr)

返回从 xdr 页面的开始的当前偏移量

参数

const struct xdr_stream *xdr

指向 struct xdr_stream 的指针

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

初始化一个 struct 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 的长度。

返回的指针仅在下次调用 xdr_reserve_space() 或 xdr_commit_encode() 在 xdr 上调用之前有效。此 API 的当前实现保证为 4 字节数据项保留的空间在 xdr 被销毁之前仍然有效,但这在未来可能并非总是如此。

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:成功 -EMSGSIZE:在 xdr 中没有足够的可用空间

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

指向 struct 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 设置为距离缓冲区起始位置最多 offset 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 设置为一个 xdr 缓冲区,表示从偏移量 base 开始,长度为 lenbuf 的一部分。

bufsubbuf 可以是指向同一个 struct xdr_buf 的指针。

如果 base 或 length 超出范围,则返回 -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 数据项。

返回值

truesubbuf 已被初始化,并且 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

要移动的字节数

描述

length 个字节从 xdr_stream 中的 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 中的对象的大小 -EBADMSG 在 XDR 缓冲区溢出时 -EMSGSIZE 在存储缓冲区 ptr 溢出时

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 中的对象的大小 -EBADMSG 在 XDR 缓冲区溢出时 -EMSGSIZE 如果对象的大小超过 maxlen -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 中的以 NUL 结尾的字符串的长度 -EBADMSG 在 XDR 缓冲区溢出时 -EMSGSIZE 在存储缓冲区 str 溢出时

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 中的以 NUL 结尾的字符串的长度 -EBADMSG 在 XDR 缓冲区溢出时 -EMSGSIZE 如果字符串的大小超过 maxlen -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 的长度的位置

描述

返回值

成功时,返回消耗的缓冲区字节数 -EBADMSG 在 XDR 缓冲区溢出时 -EMSGSIZE 如果 body 字段的解码大小超过 400 个八位字节

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 缓冲区的长度(以字节为单位) -EBADMSG 在 XDR 缓冲区溢出时 -EMSGSIZE 如果 body 的大小超过 400 个八位字节

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

所有者网络指针

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

所有者网络指针

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 客户端所知。

返回 skb dst_entry

0:传输已成功注册 -EEXIST:传输已注册 -EINVAL:传输模块正在卸载

int xprt_unregister_transport(struct xprt_class *transport)

取消注册传输实现

参数

struct xprt_class *transport

要取消注册的传输

返回 skb dst_entry

0:传输已成功取消注册 -ENOENT:传输从未注册

int xprt_find_transport_ident(const char *netid)

将 netid 转换为传输标识符

参数

const char *netid

要加载的传输

返回 skb dst_entry

> 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 请求的结果代码

描述

传输代码维护对最大未完成 RPC 请求数的估计,使用 44BSD 中实现的拥塞避免的平滑版本。 这基本上是 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

具有等待任务的传输

描述

可以在软 IRQ 上下文中调用,因此 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_task

参数

struct rpc_wait_queue *queue

任务在其上睡眠的 rpc_wait_queue

描述

获取 queue->lock

void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)

唤醒所有 rpc_task 并设置其状态值。

参数

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 缓冲区

设置 skb dst

源 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

OP 的统计结构,它将累积来自 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)

将 upcall 消息排队到用户空间

参数

struct rpc_pipe *pipe

在其上排队给定消息的 upcall 管道

struct rpc_pipe_msg *msg

要排队的消息

描述

使用 rpc_mkpipe() 创建的 inode 调用以排队 upcall。然后,用户空间进程可以通过对此 inode 的打开文件执行读取来稍后读取 upcall。调用者有责任适当地初始化 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,它将被调用文件指针、消息和要复制到的用户空间缓冲区。

写入可以随时进行,并且不一定必须是对 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 与数据匹配

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

正在等待 portmapper 请求的任务

描述

可以为正在进行的 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 传输的 max_connect 值的指针

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 指针,它保存测试函数和测试函数调用数据

描述

这是一个返回 1 的 rpc_clnt_add_xprt setup() 函数,因此

1) 测试函数的调用者必须解引用 rpc_xprt_switch 和 rpc_xprt。 2) 测试函数必须调用 rpc_xprt_switch_add_xprt,通常在 rpc_call_done 例程中。

成功后(返回 1),测试函数将新的传输添加到 rpc_clnt xprt 交换机

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

目标接口

设置 skb dst

数据包。

为了更好地了解隧道流量,OVS 需要检索数据包的出口隧道信息。以下 API 允许用户获取此信息。

struct net_device *__dev_get_by_name(struct net *net, const char *name)

按名称查找设备

参数

struct net *net

适用的网络命名空间

const char *name

要查找的名称

按名称查找接口。必须在 RTNL 信号量下调用。如果找到名称,则返回指向设备的指针。如果未找到名称,则返回 NULL。引用计数器不会递增,因此调用者必须小心锁定。

struct net_device *dev_get_by_name_rcu(struct net *net, const char *name)

按名称查找设备

参数

struct 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

适用的网络命名空间

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

适用的网络命名空间

int ifindex

设备索引

按索引搜索接口。如果未找到设备,则返回 NULL 或指向该设备的指针。设备尚未增加其引用计数器,因此调用者必须小心锁定。调用者必须持有 RTNL 信号量。

struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex)

按 ifindex 查找设备

参数

struct 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

适用的网络命名空间

int ifindex

设备索引

netdevice_tracker *tracker

获取的引用的跟踪对象

gfp_t gfp

跟踪器的分配标志

按索引搜索接口。如果未找到设备,则返回 NULL 或指向该设备的指针。返回的设备已添加引用,并且指针是安全的,直到用户调用 netdev_put() 以指示他们已完成使用。

struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type, const char *ha)

按硬件地址查找设备

参数

struct net *net

适用的网络命名空间

unsigned short type

设备媒体类型

const char *ha

硬件地址

按 MAC 地址搜索接口。如果未找到设备,则返回 NULL 或指向该设备的指针。调用者必须持有 RCU。返回的设备尚未增加其引用计数,因此调用者必须小心锁定

struct net_device *dev_getbyhwaddr(struct net *net, unsigned short type, const char *ha)

按硬件地址查找设备

参数

struct net *net

适用的网络命名空间

unsigned short type

设备媒体类型

const char *ha

硬件地址

描述

类似于 dev_getbyhwaddr_rcu(),但所有者需要持有 rtnl_lock。

上下文

必须持有 rtnl_lock()。

返回 skb dst_entry

指向 net_device 的指针,如果未找到,则为 NULL

struct net_device *__dev_get_by_flags(struct net *net, unsigned short if_flags, unsigned short mask)

查找具有给定标志的任何设备

参数

struct net *net

适用的网络命名空间

unsigned short if_flags

IFF_* 值

unsigned short mask

要检查的 if_flags 中位的位掩码

搜索具有给定标志的任何接口。如果未找到设备,则返回 NULL 或指向该设备的指针。必须在 rtnl_lock() 内调用,并且结果 refcount 不变。

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 代码。

void netdev_features_change(struct net_device *dev)

设备更改功能

参数

struct net_device *dev

导致通知的设备

调用以指示设备已更改功能。

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 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 环回到另一个 netif

参数

struct net_device *dev

目标网络设备

设置 skb dst

要转发的缓冲区

描述

返回值

NET_RX_SUCCESS(无拥塞)NET_RX_DROP(数据包已丢弃,但已释放)

dev_forward_skb 可用于将 skb 从一个设备的 start_xmit 函数注入到另一个设备的接收队列中。

接收设备可能位于另一个命名空间中,因此我们必须清除 skb 中可能影响命名空间隔离的所有信息。

bool dev_nit_active_rcu(const struct net_device *dev)

如果正在使用任何网络接口 taps,则返回 true

参数

const struct net_device *dev

要检查是否存在 taps 的网络设备

描述

调用者必须持有 RCU 锁

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

要更新的 netdev

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 支持的最大 segs 数

参数

struct net_device *dev

要更新的 netdev

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

要更新的 netdev

const struct net_device *from

从中复制限制的 netdev

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

设置 skb dst

要传输的缓冲区

int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev)

传输缓冲区

参数

设置 skb dst

要传输的缓冲区

struct net_device *sb_dev

用于 L2 转发卸载的子设备

描述

将缓冲区排队以传输到网络设备。调用者必须在调用此函数之前设置设备和优先级并构建缓冲区。该函数可以从中断中调用。

调用此方法时,必须启用中断。这是因为 BH 启用代码必须启用 IRQ,这样它才不会死锁。

无论返回值如何,skb 都会被消耗,因此目前很难重试向此方法的发送。(如果小心,您可以在发送之前增加引用计数以保留重试的引用。)

返回 skb dst_entry

  • 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() 的 Flow ID

u16 filter_id

ndo_rx_flow_steer() 返回的过滤器 ID

描述

实现 ndo_rx_flow_steer() 的驱动程序应定期为每个已安装的过滤器调用此函数,并删除返回 true 的过滤器。

int __netif_rx(struct sk_buff *skb)

netif_rx 的略微优化版本

参数

设置 skb dst

要发布的缓冲区

此行为与 netif_rx 相同,只是它不禁用下半部。 因此,只能从中断上下文(硬中断或软中断)调用此函数。

int netif_rx(struct sk_buff *skb)

将缓冲区发布到网络代码

参数

设置 skb dst

要发布的缓冲区

此函数从设备驱动程序接收数据包,并将其排队以供上层(协议)级别通过 backlog NAPI 设备进行处理。 它总是成功。 在拥塞控制期间或由协议层可能会丢弃缓冲区。 网络缓冲区通过 backlog NAPI 设备传递。 现代 NIC 驱动程序应使用 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

rx 处理程序使用的数据指针

为设备注册接收处理程序。 然后将从 __netif_receive_skb 调用此处理程序。 如果失败,则返回负 errno 代码。

调用者必须持有 rtnl_mutex。

有关 rx_handler 的一般说明,请参见 enum 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 的特殊用途版本

参数

设置 skb dst

要处理的缓冲区

netif_receive_skb() 的更直接接收版本。 它只应由需要跳过 RPS 和通用 XDP 的调用者使用。 调用者还必须注意处理 (page_is_)pfmemalloc

此函数只能从 softirq 上下文中调用,并且应启用中断。

返回值(通常忽略):NET_RX_SUCCESS:无拥塞 NET_RX_DROP:数据包已丢弃

int netif_receive_skb(struct sk_buff *skb)

处理来自网络的接收缓冲区

参数

设置 skb dst

要处理的缓冲区

netif_receive_skb() 是主要的数据接收处理函数。 它总是成功。 在拥塞控制期间或由协议层可能会丢弃缓冲区。

此函数只能从 softirq 上下文中调用,并且应启用中断。

返回值(通常忽略):NET_RX_SUCCESS:无拥塞 NET_RX_DROP:数据包已丢弃

void netif_receive_skb_list(struct list_head *head)

处理来自网络的许多接收缓冲区

参数

struct list_head *head

要处理的 skb 列表。

由于通常忽略 netif_receive_skb() 的返回值,并且对于列表没有意义,因此此函数返回 void。

此函数只能从 softirq 上下文中调用,并且应启用中断。

void __napi_schedule(struct napi_struct *n)

计划接收

参数

struct napi_struct *n

要计划的条目

描述

该条目的接收函数将被计划运行。 如果硬 irq 被屏蔽,请考虑使用 __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() 的变体,假设硬 irq 被屏蔽。

在启用 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_disable(struct napi_struct *n)

阻止 NAPI 计划

参数

struct napi_struct *n

NAPI 上下文

描述

停止在此上下文中计划 NAPI。 等待任何未完成的处理完成。 为关联的 net_device 获取 netdev_lock()。

void napi_enable(struct napi_struct *n)

启用 NAPI 计划

参数

struct napi_struct *n

NAPI 上下文

描述

启用 NAPI 实例的计划。 必须与 napi_disable() 配对。 为关联的 net_device 获取 netdev_lock()。

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)

从上层列表中获取下一个 dev

参数

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 扩展 ack

描述

添加指向此设备的上层设备的链接。 调用者必须持有 RTNL 锁。 如果失败,则返回负 errno 代码。 成功后,引用计数将调整,该函数将返回零。

添加指向上层设备的主链接

参数

struct net_device *dev

设备

struct net_device *upper_dev

新的上层设备

void *upper_priv

上层设备 private

void *upper_info

要通过通知程序传递的上层信息

struct netlink_ext_ack *extack

netlink 扩展 ack

描述

添加一个链接到此设备之上的设备。在这种情况下,只能链接一个主上层设备,尽管其他非主设备也可能被链接。调用者必须持有 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

要分发的信息

描述

使用 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

设备

设置 skb dst

数据包

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

要分发的状态

描述

使用 info 发送 NETDEV_CHANGELOWERSTATE 到 netdev 通知器。调用者必须持有 RTNL 锁。

unsigned int dev_get_flags(const struct net_device *dev)

获取报告给用户空间的标志

参数

const struct net_device *dev

设备

获取通过 API 导出到用户空间的标志位的组合。

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 扩展 ack

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 传输到的设备

将 operational 状态从 root 传输到 device。这通常在根设备和设备(叶设备)之间存在堆叠关系时调用。

int register_netdevice(struct net_device *dev)

注册一个网络设备

参数

struct net_device *dev

要注册的设备

描述

获取一个已准备好的网络设备结构,并使其可以从外部访问。将一个 NETDEV_REGISTER 消息发送到 netdev 通知器链。调用者必须持有 rtnl 锁 - 您可能需要 register_netdev() 而不是这个。

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

要为其分配空间的的私有数据的大小

返回 skb dst_entry

成功时分配的 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。

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)

创建以太网头部

参数

设置 skb dst

要更改的缓冲区

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。

参数

设置 skb dst

接收到的套接字数据

struct net_device *dev

接收网络设备

描述

这里的规则是,如果类型字段足够短,可以作为长度,那么我们就假设是 802.3。这是一种正常的做法,适用于任何“现在使用的”协议。

int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr)

从数据包中提取硬件地址

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

要从中提取头部的数据包

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 头部提取协议

参数

测试 skb 是否从 PFMEMALLOC 保留区分配

从中提取协议的数据包

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

指向包含以太网地址的六字节数组的指针

返回 skb dst_entry

如果地址是链路本地保留地址 (01:80:c2:00:00:0X),则为 true,按照 IEEE 802.1Q 8.6.3 帧过滤。

描述

请注意:addr 必须与 u16 对齐。

bool is_zero_ether_addr(const u8 *addr)

确定给定的以太网地址是否全为零。

参数

const u8 *addr

指向包含以太网地址的六字节数组的指针

返回 skb dst_entry

如果地址全为零,则为 true。

描述

请注意:addr 必须与 u16 对齐。

bool is_multicast_ether_addr(const u8 *addr)

确定以太网地址是否为多播地址。

参数

const u8 *addr

指向包含以太网地址的六字节数组的指针

返回 skb dst_entry

如果地址是多播地址,则为 true。 根据定义,广播地址也是多播地址。

bool is_local_ether_addr(const u8 *addr)

确定以太网地址是否为本地分配的地址 (IEEE 802)。

参数

const u8 *addr

指向包含以太网地址的六字节数组的指针

返回 skb dst_entry

如果地址是本地地址,则为 true。

bool is_broadcast_ether_addr(const u8 *addr)

确定以太网地址是否为广播地址

参数

const u8 *addr

指向包含以太网地址的六字节数组的指针

返回 skb dst_entry

如果地址是广播地址,则为 true。

描述

请注意:addr 必须与 u16 对齐。

bool is_unicast_ether_addr(const u8 *addr)

确定以太网地址是否为单播地址

参数

const u8 *addr

指向包含以太网地址的六字节数组的指针

返回 skb dst_entry

如果地址是单播地址,则为 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。

请注意:addr 必须与 u16 对齐。

返回 skb dst_entry

如果地址有效,则为 true。

bool eth_proto_is_802_3(__be16 proto)

确定给定的 Ethertype/长度是否为协议

参数

__be16 proto

要测试的 Ethertype/长度值

描述

检查 Ethertype/长度字段中的值是否为有效的 Ethertype。

返回 skb dst_entry

如果有效值为 802.3 支持的 Ethertype,则为 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 复制到另一个 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

指向包含以太网地址的六字节数组的指针

返回 skb dst_entry

地址的 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)

如果目标地址不匹配,则分配数据包类型

参数

设置 skb dst

如果地址与 dev 地址不匹配,则分配数据包类型

const struct net_device *dev

用于比较数据包地址的网络设备

描述

如果数据包的目标 MAC 地址与网络设备地址不匹配,则分配适当的数据包类型。

int eth_skb_pad(struct sk_buff *skb)

将缓冲区填充到以太网帧的最小八位字节数

参数

设置 skb dst

要填充的缓冲区

描述

以太网帧的最小大小应为 60 字节。 此函数接受短帧,并用零填充它们,直到达到 60 字节的限制。

struct gro_node

支持通用接收卸载的结构

定义:

struct gro_node {
    unsigned long           bitmask;
    struct gro_list         hash[GRO_HASH_BUCKETS];
    struct list_head        rx_list;
    u32 rx_count;
    u32 cached_napi_id;
};

成员

位掩码

位掩码,用于指示 hash 中使用的存储桶

我们到达的设备的 ifindex

待处理聚合 skb 的哈希表,按流分隔

rx_list

待处理的 GRO_NORMAL skb 列表

rx_count

缓存的 rx_list 当前长度

cached_napi_id

为热路径缓存的 napi_struct::napi_id,独立使用时为 0

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 已调度,则可以跳过该定时器。

返回 skb dst_entry

如果 NAPI 已调度,则为 True,否则为 False。

bool napi_schedule(struct napi_struct *n)

调度 NAPI 轮询

参数

struct napi_struct *n

NAPI 上下文

描述

如果 NAPI 轮询例程尚未运行,则调度它以被调用。

返回 skb dst_entry

如果我们调度了 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()。

返回 skb dst_entry

如果设备应避免重新激活中断,则为 false。

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

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

用作 team 端口的设备

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

设备是一个 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 addrconf

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;
    unsigned long           netmem_tx: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);
    struct ax25_dev __rcu   *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;
    bool moving_ns;
    bool rtnl_link_initializing;
    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;
    bool irq_affinity_auto;
    bool rx_cpu_rmap_auto;
    unsigned long           see_all_hwtstamp_requests:1;
    unsigned long           change_proto_down:1;
    unsigned long           netns_immutable: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 netdev_config    *cfg;
    struct netdev_config    *cfg_pending;
    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;
    bool up;
    bool request_ops_lock;
    struct mutex            lock;
#if IS_ENABLED(CONFIG_NET_SHAPER);
    struct net_shaper_hierarchy *net_shaper_hierarchy;
#endif;
    struct hlist_head neighbours[NEIGH_NR_TABLES];
    struct hwtstamp_provider __rcu  *hwprov;
    u8 priv[]  ;
};

成员

priv_flags

对用户空间不可见的标志,定义为位,有关定义,请参阅 enum netdev_priv_flags

lltx

设备支持无锁 Tx。已弃用真正的 HW 驱动程序。主要由逻辑接口使用,例如 bonding 和隧道

netmem_tx

设备支持 netmem_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

可以传递到 NIC 进行 GSO 的最大段数

num_tc

网络设备中的流量类别数

mtu

接口 MTU 值

needed_headroom

硬件可能需要的额外头空间,但在所有情况下都不能保证这一点

tc_to_txq

XXX:需要对此进行注释

xps_maps

XXX:需要对此进行注释

nf_hooks_egress

为出口数据包执行的 netfilter 钩子

tcx_egress

用于出口处理的 BPF & clsact qdisc 特定数据

{unnamed_union}

匿名

lstats

环回统计信息:数据包、字节

tstats

隧道统计信息:RX/TX 数据包、RX/TX 字节

dstats

虚拟统计信息:RX/TX/丢弃数据包、RX/TX 字节

状态

通用网络排队层状态,请参阅 netdev_state_t

标志

接口标志 (a la 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

此网络设备所在的网络命名空间,受 lock 保护

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

直接链接的设备,例如 bonding 的从设备

xdp_features

设备支持的 XDP 功能

xdp_metadata_ops

包括指向 XDP 元数据回调的指针。

xsk_tx_metadata_ops

包括指向 AF_XDP TX 元数据回调的指针。

gflags

全局标志(保留为旧版)

needed_tailroom

硬件可能需要的额外尾部空间,但在所有情况下都不能保证这一点。某些情况下也使用 LL_MAX_HEADER 来分配 skb

接口地址信息

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 operstate

link_mode

策略到 operstate 的映射

if_port

可选的 AUI、TP、...

dma

DMA 通道

perm_addr

永久 hw 地址

addr_assign_type

Hw 地址分配类型

addr_len

硬件地址长度

upper_level

上层设备的最大深度级别。

lower_level

下层设备的最大深度级别。

neigh_priv_len

在 neigh_alloc() 中使用

dev_id

用于区分共享相同链路层地址的设备

dev_port

用于区分共享相同功能的设备

irq

设备 IRQ 编号

priv_len

->priv 灵活数组的大小

XXX:需要对此进行注释

addr_list_lock

uc

单播 mac 地址

mc

多播 mac 地址

dev_addrs

设备 hw 地址列表

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

Hw 地址(在 bcast 之前,因为大多数数据包都是单播)

num_rx_queues

register_netdev() 时分配的 RX 队列数

xdp_zc_max_segs

AF_XDP 零复制驱动程序支持的最大段数

XXX:需要对此进行注释

ingress_queue

nf_hooks_ingress

为入口数据包执行的 netfilter 钩子

broadcast

hw 广播地址

rx_cpu_rmap

RX 完成中断的 CPU 反向映射,按 RX 队列编号索引。由驱动程序分配。只有在定义了 ndo_rx_flow_steer 操作时才必须设置此值

index_hlist

设备索引哈希链

num_tx_queues

在 alloc_netdev_mq() 时分配的 TX 队列数

qdisc

从用户空间角度来看的根 qdisc

tx_queue_len

允许的每个队列的最大帧数

XXX:需要对此进行注释

tx_global_lock

xdp_bulkq

XDP 设备批量队列

qdisc_hash

qdisc 哈希表

watchdog_timer

计时器列表

watchdog_timeo

表示 watchdog 使用的超时(请参阅 dev_watchdog())

proto_down_reason

netdev 接口被禁用的原因

todo_list

延迟注册/注销

pcpu_refcnt

对此设备的引用数

pcpu_refcnt

dev_refcnt

refcnt_tracker

用于跟踪此设备的跟踪引用的跟踪器目录

XXX:需要对此进行注释

link_watch_list

reg_state

注册/注销状态机

dismantle

设备将被释放

moving_ns

设备正在更改 netns,受 lock 保护

rtnl_link_initializing

正在创建设备,禁止事件

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

丢弃监视器私有

Class/net/name 条目

sysfs_groups

用于可选设备、统计信息和无线 sysfs 组的空间

sysfs_rx_queue_group

用于可选的每个 rx 队列属性的空间

rtnl_link_ops

Rtnl_link_ops

stat_ops

用于队列感知统计信息的可选操作

queue_mgmt_ops

用于队列管理的可选操作

tso_max_size

设备(如 HW)对最大 TSO 请求大小的限制

tso_max_segs

设备(如 HW)对最大 TSO 段数的限制

dcbnl_ops

数据中心桥接 netlink 操作

XXX:需要对此进行注释

prio_tc_map

fcoe_ddp_xid

用于 FCoE LRO by ddp 的最大交换 ID

XXX:需要对此进行注释

priomap

link_topo

物理链路拓扑跟踪连接的 PHY

phydev

物理设备可以自行附加以进行硬件时间戳

sfp_bus

附加的 struct sfp_bus 结构。

qdisc_tx_busylock

注释 Qdisc->busylock 自旋锁的 lockdep 类

proto_down

协议端口状态信息可以发送到交换机驱动程序,并用于设置交换机端口的 phys 状态。

threaded

已启用 napi 线程模式

irq_affinity_auto

驱动程序希望核心存储并重新分配 IRQ 亲和性。由 netif_enable_irq_affinity() 设置,然后驱动程序必须通过 netif_napi_add_config() 创建持久 napi,最后将 napi 绑定到 IRQ(通过 netif_napi_set_irq())。

rx_cpu_rmap_auto

驱动程序希望核心管理 ARFS rmap。通过调用 netif_enable_cpu_rmap() 设置。

see_all_hwtstamp_requests

设备希望查看对 ndo_hwtstamp_set() 的调用,以获取所有时间戳请求,无论来源如何,即使这些请求不是 HWTSTAMP_SOURCE_NETDEV

change_proto_down

设备支持通过 IFLA_PROTO_DOWN 设置载波

netns_immutable

接口无法更改网络命名空间

fcoe_mtu

设备支持最大 FCoE MTU,2158 字节

net_notifier_list

当设备移动到另一个网络命名空间时,遵循此设备的每个网络 netdev 通知程序块的列表。

macsec_ops

MACsec 卸载操作

udp_tunnel_nic_info

描述设备的 UDP 隧道卸载功能的静态结构

udp_tunnel_nic

UDP 隧道卸载状态

cfg

net_device 队列相关配置
cfg_pending

cfg 相同,但当设备处于活动状态时

重新配置包括用户请求的对配置的任何更改,但这些更改可能会被拒绝。

ethtool

ethtool 相关状态

xdp_state

存储有关附加的 XDP BPF 程序的信息

dev_addr_shadow

dev_addr 的副本,用于捕获直接写入。

linkwatch_dev_tracker

linkwatch 使用的 refcount 跟踪器。

watchdog_dev_tracker

watchdog 使用的 refcount 跟踪器。

dev_registered_tracker

用于在注册时保存引用的跟踪器

offload_xstats_l3

此 netdevice 的 L3 HW 统计信息。

devlink_port

指向相关 devlink 端口结构的指针。在 netdev 注册之前由驱动程序使用 SET_NETDEV_DEVLINK_PORT 宏分配。此指针在 netdevice 注册期间是静态的。

dpll_pin

指向 DPLL 子系统的 SyncE 源引脚的指针,其中时钟已恢复。

page_pools

为此 netdevice 创建的页面池

irq_moder

如果 IS_ENABLED(CONFIG_DIMLIB),则使用 dim 参数。

max_pacing_offload_horizon

最大 EDT 卸载范围,单位为 nsec。

napi_config

napi_config 结构的数组,包含每个 NAPI 的设置。

gro_flush_timeout

NAPI 中 GRO 层的超时

napi_defer_hard_irqs

如果非零,则提供一个计数器,该计数器可以在繁忙的队列上避免 NIC 硬中断。
up

state 的 IFF_UP 的副本,但可以安全读取,只需 lock

在打开或关闭设备时可能会报告假阴性(lock 不保护 .ndo_open 或 .ndo_close)。

request_ops_lock

请求核心在 lock 下运行所有 netdev_opsethtool_ops

lock

netdev 范围的锁,保护少量字段。应始终使用 netdev_lock() / netdev_unlock() 帮助程序获取。驱动程序可以自由地使用它进行其他保护。

对于实现整形器或队列 API 的驱动程序,此锁的范围已扩展为涵盖大多数 ndo/queue/ethtool/sysfs 操作。驱动程序可以通过设置 request_ops_lock 来选择此行为。

  • lock 保护以多种方式与 rtnl_lock 混合,字段可以是

  • 仅由实例 lock 保护;

  • 双重保护 - 写入者同时持有两个锁,读取者持有其中一个;

  • ops 保护 - 受围绕 NDO 和其他回调持有的锁保护,对于 netdev_need_ops_lock() 返回 true 的设备,它是实例锁,否则由 rtnl_lock 保护;

双重 ops 保护 - 始终由 rtnl_lock 保护,但对于 netdev_need_ops_lock() 返回 true 的设备 - 也由实例锁保护。

简单地保护

gro_flush_timeoutnapi_defer_hard_irqsnapi_listnet_shaper_hierarchyreg_statethreaded

双重保护

upmoving_nsnd_netxdp_features

双重 ops 保护

real_num_rx_queuesreal_num_tx_queues

还保护一些字段

struct napi_struct、struct netdev_queue、struct netdev_rx_queue

排序:在 rtnl_lock 之后获取。
net_shaper_hierarchy

跟踪当前整形器状态的数据

请参阅 include/net/net_shapers.h

neighbours

指向此设备的邻居的 dev_list 的列表头,每个地址族一个。

hwprov

跟踪哪个 PTP 执行硬件数据包时间戳。

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))

参数

struct net_device *dev

网络设备

struct napi_struct *napi

NAPI 上下文

初始化 NAPI 上下文

int (*poll)(struct napi_struct *, int)

描述

轮询函数

必须使用 netif_napi_add() 来初始化 NAPI 上下文,然后才能调用任何其他 NAPI 相关函数。

void netif_napi_add_config(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct*, int), int index)

参数

struct net_device *dev

网络设备

struct napi_struct *napi

NAPI 上下文

初始化 NAPI 上下文

int (*poll)(struct napi_struct *, int)

使用持久配置初始化 NAPI 上下文

int index

NAPI 索引

void netif_napi_add_tx(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct*, int))

参数

struct net_device *dev

网络设备

struct napi_struct *napi

NAPI 上下文

初始化 NAPI 上下文

int (*poll)(struct napi_struct *, int)

描述

初始化 NAPI 上下文,仅用于 Tx

netif_napi_add() 的此变体应由使用 NAPI 专门轮询 TX 队列的驱动程序使用。这将避免我们将其添加到 napi_hash[] 中,从而污染此哈希表。

void __netif_napi_del(struct napi_struct *napi)

参数

struct napi_struct *napi

NAPI 上下文

描述

删除 NAPI 上下文

void netif_napi_del(struct napi_struct *napi)

void __netif_napi_del(struct napi_struct *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

网络设备

设置 skb dst

子队列缓冲区指针

描述

检查具有多个发送队列的设备的单个发送队列。

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

位掩码中的位数

返回 skb dst_entry

如果 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

位掩码中的位数

返回 skb dst_entry

掩码中的下一个(在 n 之后)CPU/Rx 队列索引; 如果没有设置更多的 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

第一个 CPUs/Rx 队列掩码指针

const unsigned long *src2p

第二个 CPUs/Rx 队列掩码指针

unsigned int nr_bits

位掩码中的位数

返回 skb dst_entry

两个掩码中设置的下一个(在 n 之后)CPU/Rx 队列索引; 如果两个中都没有设置更多的 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)。

休眠状态表示相关接口实际上并未处于传递数据包的条件(即,它未“启动”),而是处于“挂起”状态,等待某些外部事件。 对于“按需”接口,这种新状态标识了接口正在等待事件将其置于启动状态的情况。

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)。

测试状态表示必须在接口上执行一些测试。 完成测试后,接口状态将根据需要更改为启动、休眠或关闭。

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

此整形器允许的最大峰值速率

突发

此整形器的峰值速率的最大突发

应存储校验和的从 csum_start 开始的偏移量

此整形器的调度优先级

权重

此整形器的调度权重

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);
};

成员

网络接口名称分配类型

创建指定的整形器调度组

leaves 整形器(由 node 整形器标识)嵌套。所有整形器都属于 binding 指定的设备。leaves 数组的大小由 leaves_count 指定。创建 leavesnode 整形器;或者,如果它们已经存在,则以期望的方式将它们链接在一起。leaves 的作用域必须是 NET_SHAPER_SCOPE_QUEUE。

设置

更新指定的整形器

更新或创建 shaperbinding 指定的设备上。

删除

移除指定的整形器

移除由给定的 handle 标识的整形器配置,该配置在 binding 指定的设备上,恢复默认行为。

功能

获取设备支持的整形器特性

使用 binding 指定的设备的指定 scope 的支持功能填充位掩码 cap

描述

这些操作适用于 net_device 和 devlink 对象。设备初始化时的初始整形配置为空:不以任何方式约束速率。网络核心在 net_device 或 devlink 结构中跟踪应用的用户配置。这些操作通过每个设备的锁进行序列化。

不支持任何嵌套的设备不应提供组操作。

每个整形器在设备中都使用 “handle” 唯一标识,该 “handle” 包括整形器作用域和特定于作用域的 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,以确定任何接口是否支持速率匹配。

返回 skb dst_entry

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

struct ifreq 用于套接字 ioctl

int cmd

要执行的 ioctl cmd

描述

请注意,此函数当前与 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

struct ifreq 用于套接字 ioctl

int cmd

要执行的 ioctl cmd

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

struct ifreq 用于套接字 ioctl

int cmd

要执行的 ioctl cmd

描述

与 phy_do_ioctl 相同,但在处理 ioctl 之前确保 net_device 正在运行。

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

要运行的测试的配置

unsigned int phy_inband_caps(struct phy_device *phydev, phy_interface_t interface)

查询支持哪些带内信令模式

参数

struct phy_device *phydev

指向 struct phy_device 的指针

phy_interface_t interface

PHY 的接口模式

描述

如果不知道 PHY 支持哪些带内信令(例如,因为 PHY 驱动程序未实现该方法),则返回零。 否则,返回 enum link_inband_signalling 中的 LINK_INBAND_* 值的位掩码,以描述 PHY 在此接口模式下支持哪些带内模式。

int phy_config_inband(struct phy_device *phydev, unsigned int modes)

配置所需的 PHY 带内模式

参数

struct phy_device *phydev

phy_device 结构

unsigned int modes

要配置的带内模式

描述

禁用、启用或启用带旁路的带内信令

在 PHY 和主机系统之间。

返回 skb dst_entry

成功返回零,或返回负 errno 值。

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 数据包时节省能源

警告:如果将 sync 设置为 false,则在 PHY 完成自动协商时生成中断的情况下,可能会导致系统无法挂起。此中断可能会在挂起后立即唤醒系统。因此,仅当您确定对于相应的网络芯片是安全的情况下,才使用 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 设备的 interrupts

参数

struct phy_device *phydev

目标 phy_device 结构

描述

请求并启用给定 PHY 的 interrupts。

如果失败,则我们将 irq 设置为 PHY_POLL。 仅应使用有效的 IRQ 号调用此方法。

void phy_free_interrupt(struct phy_device *phydev)

禁用并释放 PHY 设备的 interrupts

参数

struct phy_device *phydev

目标 phy_device 结构

描述

禁用并释放给定 PHY 的 interrupts。

仅应使用有效的 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_loopback(struct phy_device *phydev, bool enable, int speed)

配置 PHY 的环回模式

参数

struct phy_device *phydev

目标 phy_device 结构

bool enable

启用或禁用环回模式

int speed

使用速度启用环回模式

描述

配置 PHY 的环回模式,并在速度更改时发出链路断开和链路连接信号。

返回 skb dst_entry

成功时返回 0,失败时返回负错误代码。

int phy_eee_tx_clock_stop_capable(struct phy_device *phydev)

指示 MAC 是否可以停止 tx 时钟

参数

struct phy_device *phydev

目标 phy_device 结构

描述

指示 MAC 是否可以在 LPI 状态下禁用传输 xMII 时钟。如果 MAC 可以停止传输时钟,则返回 1,如果 MAC 必须不停止传输时钟,则返回 0,或返回负错误。

int phy_eee_rx_clock_stop(struct phy_device *phydev, bool clk_stop_enable)

在 LPI 中配置 PHY 接收时钟

参数

struct phy_device *phydev

目标 phy_device 结构

bool clk_stop_enable

标志,指示是否可以停止时钟

描述

配置 PHY 是否可以在 LPI 模式下禁用其接收时钟。请参见 IEEE 802.3 Sections 22.2.2.2、35.2.2.10 和 45.2.3.1.4。

返回 skb dst_entry

0 或负错误。

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),并且如果需要,它会通过设置 “Clock stop enable” 位来编程 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 数据

描述

获取当前的EEE设置,填充 **data** 的所有成员。

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 数据

描述

用于编程Advertisement 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。

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

speeds缓冲区的大小。

描述

返回支持的速度数,并使用支持的速度填充speeds缓冲区。如果speeds缓冲区太小而无法容纳所有当前支持的速度,将返回尽可能多的速度。

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扩展确认结构,用于错误报告

void phy_queue_state_machine(struct phy_device *phydev, unsigned long jiffies)

触发状态机立即运行

参数

struct phy_device *phydev

phy_device 结构

unsigned long jiffies

在这些jiffies之后运行状态机

void __phy_ethtool_get_phy_stats(struct phy_device *phydev, struct ethtool_eth_phy_stats *phy_stats, struct ethtool_phy_stats *phydev_stats)

检索标准化的PHY统计信息

参数

struct phy_device *phydev

指向PHY设备的指针

struct ethtool_eth_phy_stats *phy_stats

指向ethtool_eth_phy_stats结构的指针

struct ethtool_phy_stats *phydev_stats

指向ethtool_phy_stats结构的指针

描述

使用内核定义的接口获取PHY统计信息,以实现一致的诊断。与phy_ethtool_get_stats()不同,后者允许自定义统计信息,此函数强制使用标准化格式,以实现更好的互操作性。

检索PHY的扩展链路统计信息

参数

struct phy_device *phydev

指向PHY设备的指针

struct ethtool_link_ext_stats *link_stats

指向用于存储扩展链路统计信息的结构的指针

描述

使用链路断开事件计数和其他特定于驱动程序的链路统计信息(如果可用)填充ethtool_link_ext_stats结构。

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配置

参数

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 结构

int phy_update_stats(struct phy_device *phydev)

如果支持,则更新PHY设备统计信息。

参数

struct phy_device *phydev

指向PHY设备结构的指针。

描述

如果PHY驱动程序提供了update_stats回调,则此函数会调用它来更新PHY统计信息。如果不是,则返回0。

返回 skb dst_entry

成功时返回0,如果回调失败,则返回负错误代码。

unsigned int phy_get_next_update_time(struct phy_device *phydev)

确定下一个PHY更新时间

参数

struct phy_device *phydev

指向phy_device结构的指针

描述

此函数查询PHY驱动程序以获取下一次轮询事件的时间。如果驱动程序未实现回调,则使用默认值。

返回 skb dst_entry

下一次轮询事件的时间(以jiffies为单位)

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)

在不进行PHY重新协商的情况下调整MAC LPI配置

参数

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

我们要获取端口数的接口模式

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 结构

描述

将我们和链路合作伙伴的通告解析为其相应的速度和双工。如果协商了全双工,请从链路合作伙伴掩码中提取暂停模式。

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_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

在掩码中设置的位的新值,用于写入 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

在掩码中设置的位的新值,用于写入 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

在掩码中设置的位的新值,用于写入 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

在掩码中设置的位的新值,用于写入 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

在掩码中设置的位的新值,用于写入 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

在掩码中设置的位的新值,用于写入 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

在掩码中设置的位的新值,用于写入 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 是有效的页面,则恢复该页面。此函数会传递操作组中最早的错误代码。

返回 skb dst_entry

如果 oldpage 是负值,则为 oldpage,否则,如果 ret 是负 errno 值,则为 ret,否则,如果 phy_write_page() 出错,则为 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) 寄存器中的值构建支持的模式列表,指示 1000BASET 和 10G 相关模式。如果设置了位 1.11.14,则该列表也会使用 2.5G/5G PMA 扩展寄存器 (1.21) 中的模式进行扩展,指示是否支持 2.5GBASET 和 5GBASET。

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 Bypass 请求,然后启用快速重训练。如果未启用,则配置为禁用快速重训练。

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 *lp)

获取 EEE 状态

参数

struct phy_device *phydev

目标 phy_device 结构

unsigned long *lp

用于存储 LP 通告的链路模式的变量

描述

此函数将读取链路伙伴 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

具有内部 TX 延迟的 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 AN

PHY_INTERFACE_MODE_QUSGMII

四路通用 SGMII

PHY_INTERFACE_MODE_1000BASEKX

1000Base-KX - 带有 Clause 73 AN

PHY_INTERFACE_MODE_10G_QXGMII

10G-QXGMII - 4 个端口通过 10G USXGMII

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 接口。

long rgmii_clock(int speed)

将链路速度映射到时钟频率

参数

int speed

链路速度值

描述

将 RGMII 支持的链路速度映射到时钟频率。

返回 skb dst_entry

时钟频率或负 errno

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 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

此总线的唯一标识符,通常来自总线层次结构

FIXME:清理 struct net_device,以便网络协议信息移出。

驱动程序私有数据

读取

在总线上执行读取传输

写入

在总线上执行写入传输

read_c45

在总线上执行 C45 读取传输

write_c45

在总线上执行 C45 写入传输

重置

执行总线重置

设备所属的组

总线上每个设备的统计计数器

mdio_lock

用于确保一次只有一个事物可以读取/写入 MDIO 总线的锁

父节点

此总线的父设备

状态

总线结构的状态

dev

内核设备表示

mdio_map

总线上所有 MDIO 设备的列表

phy_mask

探测时要忽略的 PHY 地址

phy_ignore_ta_mask

忽略 TA/读取失败的 PHY 地址

用于区分共享相同功能的设备

中断数组,每个 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() 设置为此状态。- 启动会将状态设置为 UP

PHY_HALTED

PHY 已启动,但不执行轮询或中断。- phy_start 移动到 PHY_UP

PHY_ERROR

PHY 已启动,但处于错误状态。- phy_stop 移动到 PHY_HALTED

PHY_UP

PHY 和连接的设备已准备好工作。中断应在此处启动。- 计时器移动到 PHY_NOLINKPHY_RUNNING

PHY_RUNNING

PHY 当前已启动、正在运行,并且可能正在发送和/或接收数据包 - 如果链路断开,则 irq 或计时器将设置 PHY_NOLINK - phy_stop 移动到 PHY_HALTED

PHY_NOLINK

PHY 已启动,但当前未插入。- 如果链路恢复,则 irq 或计时器将设置 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];
};

成员

devices_in_package

包寄存器值中的 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_disabled_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 的父树的唯一 id,用于从用户空间寻址 PHY,类似于 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 启用了 Wake-on-LAN,则设置为 true。

autoneg

正在使用的标志自动协商

link

当前链路状态

autoneg_complete

链路自动协商已完成的标志

interrupts

已启用标志中断

irq_suspended

指示 PHY 已挂起的标志,因此中断处理应推迟到 PHY 恢复为止

irq_rerun

指示 PHY 挂起时发生中断的标志,需要在恢复后重新运行中断处理程序

default_timestamp

指示我们是否使用 phy 时间戳作为默认时间戳的标志

rate_matching

当前速率匹配模式

状态

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

当前主/从配置

supported

组合 MAC/PHY 支持的链路模式

advertising

当前通告的链路模式

lp_advertising

当前链路伙伴通告的链路模式

adv_old

为 WoL 节电时保存的通告

supported_eee

支持的 PHY EEE 链路模式

advertising_eee

当前通告的 EEE 链路模式

eee_disabled_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 结构列表

用于区分共享相同功能的设备

PHY 中断的 IRQ 号 (-1 如果没有)

FIXME:清理 struct net_device,以便网络协议信息移出。

指向驱动程序私有数据的指针

shared

指向一个包中 phy 共享的私有数据的指针

skb

用于电缆诊断的 Netlink 消息

ehdr

用于电缆诊断的 nNtlink 标头

nest

用于电缆诊断的 Netlink nest

state_queue

用于状态机的工作队列

请求核心在 lock 下运行所有 netdev_opsethtool_ops

用于序列化访问 PHY 的互斥锁

sfp_bus_attached

指示 SFP 总线是否已连接的标志

物理设备可以自行附加以进行硬件时间戳

连接到此 PHY 光纤端口的 SFP 总线

phylink

指向此 PHY 的 phylink 实例的指针

attached_dev

连接的 enet 驱动程序的设备实例 ptr

mii_ts

指向时间戳回调的指针

psec

指向电源设备控制结构的指针

mdix

当前交叉

mdix_ctrl

用户交叉设置

pma_extable

PMA/PMD 扩展能力寄存器的缓存值

link_down_events

链路丢失的次数

phy_link_change

用于 phylink 的回调,用于通知链路更改

adjust_link

用于 enet 控制器响应更改的回调:在链路状态中。

当设备移动到另一个网络命名空间时,遵循此设备的每个网络 netdev 通知程序块的列表。

MACsec 卸载操作。

描述

中断当前仅支持启用或禁用,但将来可能会更改为支持启用和禁用特定中断

包含用于轮询和中断处理的一些基础结构,以及处理 PHY 硬件状态的转变

struct phy_tdr_config

TDR 原始测试的配置

定义:

struct phy_tdr_config {
    u32 first;
    u32 last;
    u32 step;
    s8 pair;
};

成员

first

第一个数据收集点的距离

last

最后一个数据收集点的距离

step

数据收集点之间的步长

pair

要收集数据的电缆对的位图

描述

一个结构,包含 TDR 电缆测试的可能配置参数。驱动程序不需要实现所有参数,但应报告实际使用的参数。所有距离都以厘米为单位。

支持的带内信令模式

常量

LINK_INBAND_DISABLE

可以禁用带内信令

LINK_INBAND_ENABLE

可以在不绕过的情况下启用带内信令

LINK_INBAND_BYPASS

可以在绕过的情况下启用带内信令

描述

仅当设置了有效位时,才能使用可能的和必需的位。如果可能位已清除,则表示无法使用带内信令。仅当设置了可能位时,必需位才有效,并且表示必须使用带内信令。

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 Clause 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 位报告,指示 BEACON 活动。

描述

一个结构,包含 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 列表

物理链路拓扑跟踪连接的 PHY

此 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);
    unsigned int (*inband_caps)(struct phy_device *phydev, phy_interface_t interface);
    int (*config_inband)(struct phy_device *phydev, unsigned int modes);
    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, const struct phy_driver *phydrv);
    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);
    void (*get_phy_stats)(struct phy_device *dev,struct ethtool_eth_phy_stats *eth_stats, struct ethtool_phy_stats *stats);
    void (*get_link_stats)(struct phy_device *dev, struct ethtool_link_ext_stats *link_stats);
    int (*update_stats)(struct phy_device *dev);
    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 speed);
    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);
    unsigned int (*get_next_update_time)(struct phy_device *dev);
};

成员

mdiodrv

所有 MDIO 设备共有的数据

phy_id

读取此 PHY 类型的 UID 寄存器的结果,并将其与 phy_id_mask 进行 AND 运算。此驱动程序仅适用于 ID 与此字段匹配的 PHY

name

此 PHY 类型的友好名称

phy_id_mask

定义 phy_id 的重要位

features

此 PHY 支持的强制功能列表(速度、双工等)

标志

一个位字段,定义此 PHY 支持的某些其他功能(例如中断)

driver_data

静态驱动程序数据

soft_reset

调用以发出 PHY 软件重置

config_init

调用以初始化 PHY,包括在重置之后

probe

在发现期间调用。用于设置特定于设备的结构(如果有)

get_features

探测硬件以确定其具有哪些能力。应仅设置 phydev->supported。

inband_caps

查询给定 PHY 接口模式是否支持带内。返回由 enum link_inband_signalling 定义的位的位掩码。

config_inband

配置 PHY 的带内模式

get_rate_matching

获取特定 phy 接口支持的速率匹配类型。phy 使用者使用它来确定是否为该接口通告较低速度的模式。假设如果在接口上支持速率匹配模式,则可以使该接口的速率适应 phy 支持的所有较慢链路速度。如果不支持该接口,则应返回 RATE_MATCH_NONE

suspend

挂起硬件,如果需要,则保存状态

resume

恢复硬件,如果需要,则恢复状态

config_aneg

配置通告,如果 phydev->autoneg 已开启,则重置自动协商,如果 phydev->autoneg 已关闭,则强制速度为 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 寄存器才能启用 Wake on LAN,因此提供了 set_wol 以便在以太网驱动程序的 set_wol 函数中调用。

get_wol

请参阅 set_wol,但用于检查是否启用了 Wake on LAN。

link_change_notify

在核心即将更改链路状态时,调用以通知 PHY 设备驱动程序。此回调应被用作修复程序挂钩,用于需要在链路状态更改时采取措施的驱动程序。驱动程序绝不允许在其实现中干扰 PHY 设备结构。

read_mmd

读取 MMD 寄存器的 PHY 特定驱动程序覆盖。对于 PHY 特定驱动程序,此函数是可选的。如果未提供,phy_read_mmd() 将使用默认的 MMD 读取函数,该函数将对 Clause 45 PHY 使用直接读取,或对 Clause 22 PHY 使用间接读取。devnum 是 PHY 设备中的 MMD 设备编号,regnum 是所选 MMD 设备中的寄存器。

write_mmd

写入 MMD 寄存器的 PHY 特定驱动程序覆盖。对于 PHY 特定驱动程序,此函数是可选的。如果未提供,phy_write_mmd() 将使用默认的 MMD 写入函数,该函数将对 Clause 45 PHY 使用直接写入,或对 Clause 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_phy_stats

检索 PHY 统计信息。dev:为其检索统计信息的 PHY 设备。eth_stats:将存储以太网 PHY 统计信息的结构。stats:将存储其他特定于 PHY 的统计信息的结构。

检索支持的 PHY 统计信息并填充提供的结构。输入结构使用 ETHTOOL_STAT_NOT_SET 进行预初始化,驱动程序必须仅修改与支持的统计信息对应的成员。未修改的成员将保持设置为 ETHTOOL_STAT_NOT_SET,并且不会返回到用户空间。

get_link_stats

检索链路统计信息。dev:为其检索统计信息的 PHY 设备。link_stats:将存储特定于链路的统计信息的结构。

检索给定 PHY 设备的链路相关统计信息。输入结构使用 ETHTOOL_STAT_NOT_SET 进行预初始化,驱动程序必须仅修改与支持的统计信息对应的成员。未修改的成员将保持设置为 ETHTOOL_STAT_NOT_SET,并且不会返回到用户空间。

update_stats

触发定期统计信息更新。dev:为其触发统计信息更新的 PHY 设备。

定期从 PHY 设备收集统计信息,以更新本地维护的 64 位计数器。这对于实现缩减宽度计数器(例如 16 位或 32 位)的 PHY 是必需的,这些计数器与 64 位计数器相比,可以更频繁地溢出。通过调用此回调,驱动程序可以获取当前计数器值、处理溢出检测并将结果累积到本地 64 位计数器中,以便通过 get_phy_statsget_link_stats 接口进行准确报告。

返回值:成功时返回 0,失败时返回负错误代码。

get_sset_count

统计计数器数量

get_strings

统计计数器的名称

get_stats

返回统计计数器值

get_tunable

返回可调值

set_tunable

设置可调值

set_loopback

PHY的回环模式使能选择是否启用回环模式。如果启用回环模式,则可以使用 speed 参数请求回环模式的速度。如果 speed 参数为零,则可以选择任何速度。如果 speed 参数 > 0,则应为回环模式选择此速度,如果不支持速度选择,则应返回 EOPNOTSUPP。

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,或一个错误代码。

get_next_update_time

获取直到下一次更新事件的时间 dev: PHY 设备

回调以确定 PHY 状态机的下一次更新事件的时间(以节拍为单位)。允许 PHY 驱动程序根据链路状态或其他条件动态调整轮询间隔。

返回直到下一次更新事件的时间(以节拍为单位)。

描述

所有函数都是可选的。如果 config_aneg 或 read_status 没有实现,则 phy 核心使用 genphy 版本。请注意,这些函数都不应该从中断时间调用。目标是总线读取/写入函数能够在总线事务发生时阻塞,并被中断释放(MPC85xx 具有此能力,尽管目前在驱动程序中不支持)。

bool phy_id_compare(u32 id1, u32 id2, u32 mask)

比较 id1id2,考虑 mask

参数

u32 id1

第一个 PHY ID

u32 id2

第二个 PHY ID

u32 mask

PHY ID 掩码,设置的位在匹配中很重要

描述

如果 mask 指定的 id1id2 的位匹配,则返回 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 必须绑定到驱动程序。

bool phy_is_started(struct phy_device *phydev)

方便函数,用于检查 PHY 是否已启动

参数

struct phy_device *phydev

phy_device 结构

void phy_disable_eee_mode(struct phy_device *phydev, u32 link_mode)

不通告 EEE 模式。

参数

struct phy_device *phydev

phy_device 结构

u32 link_mode

要禁用的 EEE 模式

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 寄存器,直到满足条件或发生超时

参数

物理链路拓扑跟踪连接的 PHY

phy_device 结构

devaddr

要从中读取的MMD

regnum

要读取的MMD上的寄存器

val

将寄存器读入的变量

cond

中断条件(通常涉及 val

sleep_us

读取之间休眠的最长时间,以微秒为单位(0 为紧密循环)。请阅读 usleep_range() 函数描述,了解详细信息和限制。

timeout_us

超时时间,以微秒为单位,0 表示从不超时

sleep_before_read

如果为 true,则在读取之前休眠 sleep_us

返回 skb dst_entry

成功时为 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 irq

参数

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 中选择时间戳。

返回 skb dst_entry

如果 phy 是默认 hw 时间戳,则为 True,否则为 false。

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_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,然后再进行比较

int genphy_match_phy_device(struct phy_device *phydev, const struct phy_driver *phydrv)

将 PHY 设备与 PHY 驱动程序匹配

参数

struct phy_device *phydev

目标 phy_device 结构

const struct phy_driver *phydrv

目标 phy_driver 结构

描述

检查给定的 PHY 设备是否与指定的 PHY 驱动程序匹配。对于 Clause 45 PHY,它会迭代可用的设备标识符,并将它们与驱动程序的预期 PHY ID 进行比较,并应用提供的掩码。对于 Clause 22 PHY,将执行直接 ID 比较。

返回 skb dst_entry

如果 PHY 设备与驱动程序匹配,则为 1,否则为 0。

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 时,读取“封装中的设备”寄存器。如果“封装中的设备”看起来有效,则读取每个 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,如果“封装中的设备”无效则返回 -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 命名空间

返回 skb dst_entry

成功时返回 0,否则返回一个负错误代码。

void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy)

从上游 PHY 断开 SFP 模块的 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

表示正在连接的 cage 的 sfp 总线

描述

这用于填充 sfp_upstream_ops .attach 成员。

void phy_sfp_detach(void *upstream, struct sfp_bus *bus)

从 PHY 上游网络设备分离 SFP 总线

参数

void *upstream

指向 phy 设备的指针

struct sfp_bus *bus

表示正在连接的 cage 的 sfp 总线

描述

这用于填充 sfp_upstream_ops .detach 成员。

int phy_sfp_probe(struct phy_device *phydev, const struct sfp_upstream_ops *ops)

探测连接到此 PHY 设备的 SFP cage

参数

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 提供指向附加设备的指针,并提供链路状态更改的回调。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 的指针。

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)

读取 !aneg 模式的链路参数

参数

struct phy_device *phydev

目标 phy_device 结构

描述

读取禁用了自动协商的 PHY 的当前双工和速度状态。

int genphy_read_status(struct phy_device *phydev)

检查链路状态并更新当前链路状态

参数

struct phy_device *phydev

目标 phy_device 结构

描述

检查链路,然后确定当前状态

通过比较我们广播的内容与链路伙伴广播的内容。首先检查千兆的可能性,然后继续检查 10/100。

int genphy_c37_read_status(struct phy_device *phydev, bool *changed)

检查链路状态并更新当前链路状态

参数

struct phy_device *phydev

目标 phy_device 结构

bool *changed

指向存储链路是否已更改的位置的指针

描述

检查链路,然后确定当前状态

通过比较我们广播的内容与链路伙伴广播的内容。此函数用于 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 复位,并轮询复位位是否已清除。

返回 skb dst_entry

成功时返回 0,失败时返回 < 0

int genphy_read_abilities(struct phy_device *phydev)

从 Clause 22 寄存器读取 PHY 功能

参数

struct phy_device *phydev

目标 phy_device 结构

描述

读取 PHY 的功能并相应地填充 phydev->supported。

返回 skb dst_entry

成功时返回 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。MAC 驱动程序应通过在设置 enable_tx_lpi 时启用 LPI 计时器来对此设置执行操作。

void phy_disable_eee(struct phy_device *phydev)

禁用 PHY 的 EEE

参数

struct phy_device *phydev

目标 phy_device 结构

描述

MAC 驱动程序使用此函数来处理不支持 EEE 的 MAC。它禁用 PHY 层的 EEE。

void phy_support_sym_pause(struct phy_device *phydev)

启用对称暂停的支持

参数

struct phy_device *phydev

目标 phy_device 结构

描述

由 MAC 调用以指示它支持对称暂停,但不作为 asym 暂停。

void phy_support_asym_pause(struct phy_device *phydev)

启用 asym 暂停的支持

参数

struct phy_device *phydev

目标 phy_device 结构

描述

由 MAC 调用以指示它支持 Asym 暂停。

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 *rx_pause

指向布尔值的指针,指示是否应启用接收暂停。

描述

根据协商结果解析并返回流控制模式。 这包括检查我们是否在全双工模式下运行。 有关更多详细信息,请参阅 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

用于指示获取 rx 内部延迟的布尔值

描述

返回传入的内部延迟数组中的索引。 如果设备属性不存在,则检查接口类型,如果接口定义使用内部延迟,则返回 1,否则返回 0。 数组必须按升序排列。 如果 PHY 没有升序数组,则 size = 0,并返回延迟属性的值。 如果延迟无效或找不到,则返回 -EINVAL。

int phy_get_tx_amplitude_gain(struct phy_device *phydev, struct device *dev, enum ethtool_link_mode_bit_indices linkmode, u32 *val)

将 tx 幅度增益存储在 val

参数

struct phy_device *phydev

phy_device 结构体

struct device *dev

指向设备设备结构的指针

enum ethtool_link_mode_bit_indices linkmode

应检索 tx 幅度增益的 linkmode

u32 *val

tx 幅度增益

返回 skb dst_entry

成功时返回 0,失败时返回 < 0

int phy_get_mac_termination(struct phy_device *phydev, struct device *dev, u32 *val)

将 MAC 终端存储在 val

参数

struct phy_device *phydev

phy_device 结构体

struct device *dev

指向设备设备结构的指针

u32 *val

MAC 终端

返回 skb dst_entry

成功时返回 0,失败时返回 < 0

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 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 的模块

bool phy_uses_state_machine(struct phy_device *phydev)

测试消费者驱动程序是否使用 PAL 状态机

参数

struct phy_device *phydev

目标 PHY 设备结构

描述

最终,这旨在通过调用 phy_start()phy_stop() 来间接确定 PHY 是否连接到使用状态机的消费者。

当 PHY 驱动程序消费者使用 phylib 时,它必须先前调用 phy_connect_direct() 或其派生项之一,以便 phy_prepare_link() 已设置一个用于监视状态更改的挂钩。

当 PHY 驱动程序由通过 phylink 的 MAC 驱动程序消费者使用时(phy_link_change() 方法的唯一其他提供程序),使用 PHY 状态机不是可选的。

返回 skb dst_entry

如果消费者调用 phy_start()phy_stop(),则为 true;否则为 false。

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 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,

在清理值以确保我们只通告支持的内容之后。 错误时返回 < 0,如果 PHY 的通告没有更改,则返回 0,如果已更改,则返回 > 0。

int genphy_c37_config_advert(struct phy_device *phydev)

清理和通告自动协商参数

参数

struct phy_device *phydev

目标 phy_device 结构

描述

使用适当的值写入 MII_ADVERTISE,

在清理值以确保我们只通告支持的内容之后。 错误时返回 < 0,如果 PHY 的通告没有更改,则返回 0,如果已更改,则返回 > 0。 此函数适用于 Clause 37 1000Base-X 模式。

int phy_probe(struct device *dev)

探测和初始化 PHY 设备

参数

struct device *dev

要探测和初始化的设备

描述

注意设置 phy_device 结构,并将状态设置为 READY。

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’ed。

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。

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() 避免锁依赖误报。

注意

不得从中断上下文中调用,因为总线读取/写入函数可能会等待中断完成操作。

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() 避免锁依赖误报。

注意

不得从中断上下文中调用,因为总线读取/写入函数可能会等待中断完成操作。

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() 避免锁依赖误报。

注意

不得从中断上下文中调用,因为总线读取/写入函数可能会等待中断完成操作。

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() 避免锁依赖误报。

注意

不得从中断上下文中调用,因为总线读取/写入函数可能会等待中断完成操作。

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_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 支持掩码的无符号长整型数组的可选指针

描述

解析 id 中给出的 EEPROM 标识,并返回 PORT_TPPORT_FIBREPORT_OTHER 之一。如果 support 不是 NULL,则还设置与连接器类型对应的 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 *interfaces

指向 phy 接口模式掩码的无符号长整型数组的指针

描述

解析 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 中填写类型和 eeprom_len 参数,用于 bus 指定的 sfp 总线上的模块。

成功时返回 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() 放置。

返回 skb dst_entry

  • 成功时,指向 sfp_bus 结构的指针,

  • 如果未指定 SFP,则为 NULL

  • 失败时,错误指针值

  • 对应于 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 总线。 这将在总线上放置引用,因此在此调用之后放置总线是安全的。

返回 skb dst_entry

  • 成功时,指向 sfp_bus 结构的指针,

  • 如果未指定 SFP,则为 NULL

  • 失败时,错误指针值

  • 对应于 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 模块的先前注册的上游连接。 应该通过 sfp_bus_add_upstream() 添加 bus

const char *sfp_get_name(struct sfp_bus *bus)

获取 SFP 设备名称

参数

struct sfp_bus *bus

指向 sfp 模块的 struct sfp_bus 结构的指针

描述

获取 SFP 设备的名称,如果 bus 具有已注册的套接字。 调用者必须持有 RTNL,并且返回的名称仅在释放 RTNL 之前有效。

返回 skb dst_entry

  • 使用 sfp_register_socket() 注册的 SFP 设备的名称

  • 如果 bus 上未注册任何设备,则为 NULL