概述
每个CPU有一个单独的softnet_data实例,用来存储与网络中断处理相关的报文输出和输出队列。在输出过程中会用到softnet_data中的output_queue和completion_queue队列。
/*
* Incoming packets are placed on per-cpu queues so that
* no locking is needed.
*/
struct softnet_data
{
struct Qdisc *output_queue;
struct sk_buff_head input_pkt_queue;
struct list_head poll_list;
struct sk_buff *completion_queue;
struct napi_struct backlog;
};
struct Qdisc
{
int (*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
struct sk_buff * (*dequeue)(struct Qdisc *dev);
unsigned flags;
...
int padded;
struct Qdisc_ops *ops;
struct qdisc_size_table *stab;
struct list_head list;
u32 handle;
u32 parent;
atomic_t refcnt;
struct gnet_stats_rate_est rate_est;
int (*reshape_fail)(struct sk_buff *skb,
struct Qdisc *q);
void *u32_node;
...
struct sk_buff_head q;
struct gnet_stats_basic_packed bstats;
struct gnet_stats_queue qstats;
};
softnet与接口层和网络层的关系
如果支持流量控制,则将待输出的数据包根据规则加入到输出网络设备队列中排队,并在合适的实际激活网络输出软中断,依次将报文从队列中取出通过网络设备输出。若不支持流量控制,则直接将数据包通过网络设备输出调用dev_queue_xmit()函数输出数据包,前提是必须启用中断,只有启用中断之后才能激活下半部分
dev_queue_xmit->dev_hard_start_xmit->ops->ndo_start_xmit
e100_xmit_frame()为e100网络设备的ndo_start_xmit接口实现,最终将数据包输出到硬件。
网络输出软中断
激活数据包输出软中断有多个接口,__netif_schedule()是最常用的几个
如果输出网络设备没有处于流量控制的调度中,则将该网络设备链接到softnet_data中的output_queue队列上,然后激活网络输出软中断对该队列进行处理
net_tx_action()
net_tx_action()是数据包输出软中断例程,一旦被激活便会遍历output_queue队列待处理的输出网络设备,然后调用qdisc_run()在合适的时机发送数据包。