linux2.6内核网卡数据流过程

原创 2015年07月07日 10:10:15
linux 2.6版的内核,网络数据从网线到应用程序需经过3次copy,分别是:
1. 网线上的电信号经过网卡驱DMA到网卡的环形FIFO里;
2. 从网卡的接收环形FIFO里copy到TCP/IP协议栈的sk_buff里;
3. 应用程序的socket调用recv()函数从协议栈的buffer里copy到用户进程的buffer里。

步骤中的2, sk_buff结构体设计得非常精巧:
C/C++ code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/** 
 *    struct sk_buff - socket buffer
 *    @next: Next buffer in list
 *    @prev: Previous buffer in list
 *    @list: List we are on
 *    @sk: Socket we are owned by
 *    @stamp: Time we arrived
 *    @dev: Device we arrived on/are leaving by
 *    @input_dev: Device we arrived on
 *      @real_dev: The real device we are using
 *    @h: Transport layer header
 *    @nh: Network layer header
 *    @mac: Link layer header
 *    @dst: FIXME: Describe this field
 *    @cb: Control buffer. Free for use by every layer. Put private vars here
 *    @len: Length of actual data
 *    @data_len: Data length
 *    @mac_len: Length of link layer header
 *    @csum: Checksum
 *    @__unused: Dead field, may be reused
 *    @cloned: Head may be cloned (check refcnt to be sure)
 *    @pkt_type: Packet class
 *    @ip_summed: Driver fed us an IP checksum
 *    @priority: Packet queueing priority
 *    @users: User count - see {datagram,tcp}.c
 *    @protocol: Packet protocol from driver
 *    @security: Security level of packet
 *    @truesize: Buffer size 
 *    @head: Head of buffer
 *    @data: Data head pointer
 *    @tail: Tail pointer
 *    @end: End pointer
 *    @destructor: Destruct function
 *    @nfmark: Can be used for communication between hooks
 *    @nfcache: Cache info
 *    @nfct: Associated connection, if any
 *    @nfctinfo: Relationship of this skb to the connection
 *    @nf_debug: Netfilter debugging
 *    @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
 *      @private: Data which is private to the HIPPI implementation
 *    @tc_index: Traffic control index
 */
 
struct sk_buff {
    /* These two members must be first. */
    struct sk_buff        *next;
    struct sk_buff        *prev;
 
    struct sk_buff_head    *list;
    struct sock        *sk;
    struct timeval        stamp;
    struct net_device    *dev;
    struct net_device    *input_dev;
    struct net_device    *real_dev;
 
    union {
        struct tcphdr    *th;
        struct udphdr    *uh;
        struct icmphdr    *icmph;
        struct igmphdr    *igmph;
        struct iphdr    *ipiph;
        struct ipv6hdr    *ipv6h;
        unsigned char    *raw;
    } h;
 
    union {
        struct iphdr    *iph;
        struct ipv6hdr    *ipv6h;
        struct arphdr    *arph;
        unsigned char    *raw;
    } nh;
 
    union {
          unsigned char     *raw;
    } mac;
 
    struct  dst_entry    *dst;
    struct    sec_path    *sp;
 
    /*
     * 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[40];
 
    unsigned int        len,
                data_len,
                mac_len,
                csum;
    unsigned char        local_df,
                cloned,
                pkt_type,
                ip_summed;
    __u32            priority;
    unsigned short        protocol,
                security;
 
    void            (*destructor)(struct sk_buff *skb);
#ifdef CONFIG_NETFILTER
        unsigned long        nfmark;
    __u32            nfcache;
    __u32            nfctinfo;
    struct nf_conntrack    *nfct;
#ifdef CONFIG_NETFILTER_DEBUG
        unsigned int        nf_debug;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
    struct nf_bridge_info    *nf_bridge;
#endif
#endif /* CONFIG_NETFILTER */
#if defined(CONFIG_HIPPI)
    union {
        __u32        ifield;
    private;
#endif
#ifdef CONFIG_NET_SCHED
       __u32            tc_index;        /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
    __u32           tc_verd;               /* traffic control verdict */
    __u32           tc_classid;            /* traffic control classid */
#endif
 
#endif
 
 
    /* These elements must be at the end, see alloc_skb() for details.  */
    unsigned int        truesize;
    atomic_t        users;
    unsigned char        *head,
                *data,
                *tail,
                *end;
};

代码学习-Linux内核网卡收包过程(NAPI)

本文通过学习RealTek8169/8168/8101网卡的驱动代码(drivers/net/r8169.c),梳理一下Linux下网卡的收包过程。 在下水平相当有限,有不当之处,还请大家斧正^_^...

DMA方式的网卡驱动

内核如何从网卡接收数据,传统的过程: 1.数据到达网卡; 2.网卡产生一个中断给内核; 3.内核使用I/O指令,从网卡I/O区域中去读取数据;   我们在许多网卡驱动中(很老那些),...

DMA驱动框架流程编写

本文主要是针对Xilinx DMA驱动流程框架编写 DMA驱动一致性和流式的基本认识 一致性DMA与流式DMA主要是内存的申请方式和访问控制权限不一样 一致性DMA内存申请: void *dm...

Linux内核---网卡驱动的详细分析 让你的网卡飞起来!

Linux内核学习笔记之网卡驱动的详细分析(经典转) 学习应该是一个先把问题简单化,在把问题复杂化的过程。一开始就着手处理复杂的问题,难免让 人有心惊胆颤,捉襟见肘的感觉。读Linux网卡驱动也是一...

学习内核---Linux网卡驱动分析

学习内核---Linux网卡驱动分析 学习应该是一个先把问题简单化,在把问题复杂化的过程。一开始就着手处理复杂的问题,难免让人有心惊胆颤,捉襟见肘的感觉。读Linux网卡驱动也是一样。那长长...

linux网卡数据流 发送与接收

通常在驱动中看见的网卡代码很多,但是都离不开发送与接收,掌握好骨干也就好阅读网卡驱动了。 数据发送 : 发送函数:xxx_start_xmit() 上层封装好了sk_buff丢进kernel后,b...
  • eqwewr
  • eqwewr
  • 2014年09月03日 21:34
  • 1941

NAND芯片的读写及ECC检验软硬件实现

第一节概论 nandflash在对大容量的数据存储中发挥着重要的作用。相对于norflash,它具有一些优势,但它的一个劣势是很容易产生坏块,因此在使用nandflash时,往往要利用校验算法发...

基于linux 2.6内核裁剪过程

  • 2008年12月18日 09:34
  • 21KB
  • 下载

Linux 2.6、4.3内核编译过程的感受与总结

之前编译过2.4.10的内核,很好编译,中间曾经漏下了SCSI low-level drivers下的BusLogic SCSI support选项导致没法启动系统,后来打开该选项后就行了,随手关闭一...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux2.6内核网卡数据流过程
举报原因:
原因补充:

(最多只允许输入30个字)