linux内核网络相关api

Posted by 婷 on November 5, 2023 本文总阅读量

前言

最近在看gmac驱动代码,发现很多linux内核网络的api,暂时这里先整理出来,先大概知道什么用法,后续再深入了解

netif_rx

 void netif_rx(struct sk_buff *skb);

调用(包括中断期间)这个函数可以通知内核已经收到一个数据包,并封装入一个套接字缓冲区。

netif_rx_schedule

void netif_rx_schedule(dev);

调用该函数通知内核数据包已经存在,并且在接口上启动轮询机制,它只在NAPI驱动程序中使用。

netif_receive_skb与netif_rx_complete

int netif_receive_skb(struct sk_buff *skb)
void netif_rx_complete(dev);

这两函数只在NAPI驱动程序中使用;NAPI中的netif_receive_skb函数与netif_rx等价,它将数据包发送给内核。当NAPI驱动程序耗尽了为接收数据包准备的内存时,则它将重新启动中断,然后调用netif_rx_complete终止轮询函数。

skb_shinfo

通过这个宏来判断数据包是由一个数据片段组成,还是由大量数据片段组成。例如海思的网卡代码

image-20231105103228717

dev_queue_xmit

网络发送函数,最终调用到MAC驱动中的ndo_start_xmit

struct sk_buff

定义在include/linux/skbuff.h,只列举几个比较重要的结构体成员

struct sk_buff {
        union {
                struct {
                        /* These two members must be first. */
                        struct sk_buff          *next;
                        struct sk_buff          *prev;

                        union {
                                struct net_device       *dev;
                                /* Some protocols might use this space to store information,
                                 * while device pointer would be NULL.
                                 * UDP receive path is one user.
                                 */
                                unsigned long           dev_scratch;
                        };
                };
                struct rb_node          rbnode; /* used in netem, ip4 defrag, and tcp stack */
                struct list_head        list;
        };

        union {
                struct sock             *sk;
                int                     ip_defrag_offset;
        };

        union {
                ktime_t         tstamp;
                u64             skb_mstamp_ns; /* earliest departure time */
        };
        /*
         * This is the control buffer. It is free to use for every
         * layer. Please put your private variables there. If you
         * want to keep them across layers you have to do a skb_clone()
         * first. This is owned by whoever has the skb queued ATM.
         */
        char                    cb[48] __aligned(8);
        unsigned int            len,
                                data_len;
        __u16                   mac_len,
                                hdr_len;
        __be16                  protocol;
        __u16                   transport_header;
        __u16                   network_header;
        __u16                   mac_header;

        /* private: */
        __u32                   headers_end[0];
    
       /* These elements must be at the end, see alloc_skb() for details.  */
        sk_buff_data_t          tail;
        sk_buff_data_t          end;
        unsigned char           *head,
                                *data;
};

dev表示当前sk_buff从哪个设备接收到或者发出的。

sk表示当前sk_buff所属的Socket

cb为控制缓冲区,不管哪个层都可以自由使用此缓冲区,用于放置私有数据。

destructor函数,当释放缓冲区的时候可以在此函数里面完成某些动作。

len为实际的数据长度,包括主缓冲区中数据长度和分片中的数据长度。

data_len为数据长度,只计算分片中数据的长度。

protocol协议。

transport_header为传输层头部。

network_header为网络层头部。

mac_header为链接层头部。

tail指向实际数据的尾部,end指向缓冲区的尾部。head指向缓冲区的头部,data指向实际数据的头部。结构如下图所示:

image-20231111202812248

netif_start_queue

ndo_open中,调用这个函数,来激活设备发送队列

netif_stop_queue

ndo_stop中,调用这个函数,停止设备传输包

eth_type_trans

一般用于网络数据接收中,获取该报文的协议类型。

image-20231111202755841

参考链接