内核协议栈数据包转发完全解析

  • 格式:doc
  • 大小:752.00 KB
  • 文档页数:22

下载文档原格式

  / 22
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

内核协议栈数据包转发

目录

1 NAPI流程与非NAPI

1.1NAPI驱动流程

1.2非NAPI流程

1.3NAPI和非NAPI的区别

2内核接受数据

2.1数据接收过程

2.2 采取DMA技术实现

3 e100采用NAPI接收数据过程

3.1 e100_open 启动e100网卡

3.2 e100_rx_alloc_list 建立环形缓冲区

3.3 e100_rx_alloc_skb 分配skb缓存

3.4 e100_poll 轮询函数

3.5 e100_rx_clean 数据包的接收和传输

3.6 e100_rx_indicate

4 队列层

4.1、软中断与下半部

4.2、队列层

5采用非NAPI接收数据过程

5.1netif_rx

5.2轮询与中断调用netif_rx_schedule不同点

5.3 netif_rx_schedule

5.4 net_rx_action

5.5 process_backlog

6数据包进入网络层

6.1 netif_receive_skb():

6.2 ip_rcv():

6.3 ip_rcv_finish():

6.4 dst_input():

6.5本地流程ip_local_deliver:

6.6转发流程ip_forward():

1 NAPI流程与非NAPI

1.1NAPI驱动流程:

中断发生

-->确定中断原因是数据接收完毕(中断原因也可能是发送完毕,DMA完毕,甚至是中断通道上的其他设备中断)

-->通过netif_rx_schedule将驱动自己的napi结构加入softnet_data的poll_list 链表,禁用网卡中断,并发出软中断NET_RX_SOFTIRQ

-->中断返回时触发软中断调用相应的函数net_rx_action,从softnet_data的

poll_list上取下刚挂入的napi结构,并且调用其 poll函数,这个poll函数也是驱动自己提供的,比如e100网卡驱动中的e100_poll等。

-->在poll函数中进行轮询,直到接受完所有的数据或者预算(budget)耗尽。每接收一个报文要分配skb,用eth_type_trans处理并交给netif_receive_skb。

-->如果数据全部接收完(预算没有用完),则重新使能中断并将napi从链表中取下。如果数据没接收完,则什么也不作,等待下一次poll函数被调度。

1.2非NAPI流程:

中断发生

-->确定中断发生的原因是接收完毕。分配skb,读入数据,用eth_type_trans处理并且将skb交给netif_rx

-->在netif_rx中,将packet加入到softnet_data的input_pkt_queue末尾(NAPI 驱动不使用这个 input_pkt_queue),再通过napi_schedule将softnet_data中的backlog(这也是个napi结构)加入 softnet_data的poll_list,最后发出软中断 -->软中断net_rx_action从poll_list上取下softnet_data的backlog,调用其poll 函数,这个poll函数是内核提供的process_backlog

-->函数process_backlog从softnet_data的input_pkt_queue末尾取下skb,并且直接交给netif_receive_skb处理。

-->如果input_pkt_queue中所有skb都处理完则将backlog从队列中除去(注意input_pkt_queue中可能有多个网卡加入的报文,因为它是每cpu公用的)并退出循环;如果预算用完后也跳出循环。最后返回接受到的包数

1.3 NAPI和非NAPI的区别

NAPI和非NAPI的区别

1.NAPI使用中断+轮询的方式,中断产生之后暂时关闭中断然后轮询接收完所有的数据包,接着再开中断。而非NAPI采用纯粹中断的方式,一个中断接收一个数据包

2.NAPI都有自己的struct napi结构,非NAPI没有

3.NAPI有自己的poll函数,而且接收数据都是在软中断调用poll函数时做的,而非NAPI使用公共的process_backlog函数作为其poll函数,接收数据是在硬件中断中做的

4.NAPI在poll函数中接收完数据之后直接把skb发给netif_receive_skb,而非NAPI 在硬件中断中接收了数据通过 netif_rx把skb挂到公共的input_pkt_queue上,最后由软中断调用的process_backlog函数来将其发送给 netif_receive_skb

驱动以及软中断这块对skb仅仅做了以下简单处理:

1.调用skb_reserve预留出2个字节的空间,这是为了让ip首部对齐,因为以太网首部是14字节

2.调用skb_put将tail指向数据末尾

3.调用eth_type_trans进行如下处理:

(1)将skb->dev指向接收设备

(2)将skb->mac_header指向data(此时data就是指向mac起始地址)

(3)调用skb_pull(skb, ETH_HLEN)将skb->data后移14字节指向ip首部

(4)通过比较目的mac地址判断包的类型,并将skb->pkt_type赋值PACKET_BROADCAST或PACKET_MULTICAST或者PACKET_OTHERHOST,因为PACKET_HOST为0,所以是默认值

(5)最后判断协议类型,并返回(大部分情况下直接返回eth首部的protocol 字段的值),这个返回值被存在skb->protocol字段中

总结,结束后,skb->data指向ip首部,skb->mac_header指向 mac首部,skb->protocol 储存L3的协议代码,skb->pkt_type已被设置,skb->len等于接收到的报文长度减去eth 首部长度,也就是整个ip报文的总长。其余字段基本上还是默认值。