这篇文章主要介绍网络层的数据是怎么通过接口层将数据发送出去的,在开始之前我们还是再来看一下softnet_data这个很重要的结构体:
struct softnet_data {
struct list_head poll_list;
struct sk_buff_head process_queue;
/* stats */
unsigned int processed;
unsigned int time_squeeze;
unsigned int received_rps;
#ifdef CONFIG_RPS
struct softnet_data *rps_ipi_list;
#endif
#ifdef CONFIG_NET_FLOW_LIMIT
struct sd_flow_limit __rcu *flow_limit;
#endif
struct Qdisc *output_queue;
struct Qdisc **output_queue_tailp;
struct sk_buff *completion_queue;
...
在数据包输出的时候,其中比较重要的成员是output_queue和completion_queue, 前者是等待发送的队列,后者是完成发送等待释放的队列,比如可能在等待ACK等。
下面我们来了解一下接口处数据包发送的基本流程:
下面这个图是kernel2.6版本dev_queue_xmit()的处理流程,新的kernel已经有很多不一样了,但是可以作为参考
关于接口层数据包的发送,我自己对这一块也不是有太多的兴趣,但是在网上找到几篇介绍的比较清楚的文章,这里就直接贴过来,不浪费口舌了:
Linux网络之设备接口层:发送数据包流程dev_queue_xmit
Linux网络之设备接口层:发送数据包流程dev_queue_xmit(二)新kernel的代码可能刚开始不是那么好看懂,可以先了解一下旧kernel的代码然后看新的代码会容易些。
这篇文章没有详细的介绍发送过程,但是需要记住一个比较重要的函数dev_hard_start_xmit,它是将数据包交给网卡驱动进行发送的接口:
dev_hard_start_xmit
继续看dev_hard_start_xmit,这个函数比较简单,调用xmit_one来发送一个到多个数据包了
对于xmit_one这个来讲比较简单了,下面代码中列出了xmit_one, netdev_start_xmit,__netdev_start_xmit 这个三个函数,其目的就是将封包送到driver的tx函数了..中间在送往driver之前,还会经历抓包的过程,本文不介绍抓包的流程了。
其中ops->ndo_start_xmit就是driver注册的发包函数,这样数据包就交给了驱动处理。
接口层的分析到这里告一段落,如果想要了解更多关于接口层的东西可以访问这里
后面我们将进入广阔的网络层以及传输层的分析: