LINUX协议栈详解 数据包发送


数据包发送和接收有点类似,我们一般都用int dev_queue_xmit(struct sk_buff *skb)来发送数据包,例如我们自己构造完整的数据包,最后调用真正的物理发送函数。

但是我们也知道发送也是有软中断处理的,

open_softirq(NET_TX_SOFTIRQ,net_tx_action);

什么时候会触发这个软中断成为关键呢?其实这个软中断并不是必须的,只是因为传输过程中会出现一些问题,需要后续的软中断来处理。例如我比较关注的TC部分。

如果配置了TC,则调用__dev_xmit_skb,首先会对数据包进行enqueue,接着__qdisc_run进行发送,同时判断是否应该调度了,如果是,则__netif_schedule(q);这里就是进行软中断触发的条件。

进一步说明,其实还是有其他地方进行软中断触发,但是太过于细节,当前没有进一步研究。

排队准则接口

数据包发送过程中最重要的一个部分之一就是TC,也就是排队准则。

struct Qdisc_ops {

         structQdisc_ops *next;

         conststruct Qdisc_class_ops         *cl_ops;

         char                     id[IFNAMSIZ];

         int                        priv_size;

 

         int                      (*enqueue)(structsk_buff *, struct Qdisc *);

         structsk_buff *   (*dequeue)(struct Qdisc *);

         structsk_buff *   (*peek)(struct Qdisc *);

         unsignedint                 (*drop)(struct Qdisc*);

 

         int                        (*init)(struct Qdisc *,struct nlattr *arg);

         void                     (*reset)(struct Qdisc *);

         void                     (*destroy)(struct Qdisc *);

         int                        (*change)(struct Qdisc*, struct nlattr *arg);

         void                     (*attach)(struct Qdisc *);

 

         int                        (*dump)(struct Qdisc *,struct sk_buff *);

         int                        (*dump_stats)(structQdisc *, struct gnet_dump *);

 

         structmodule               *owner;

};

 

         Enqueue将数据包进队列

         Dequeue将数据包出队列

         Requeue将数据包重新进队列

 

void __qdisc_run(struct Qdisc *q)

{

         unsignedlong start_time = jiffies;

 

         while(qdisc_restart(q)) {

                   /*

                    * Postpone processing if

                    * 1. another process needs the CPU;

                    * 2. we've been doing it for too long.

                    */

                   if(need_resched() || jiffies != start_time) {

                            __netif_schedule(q);

                            break;

                   }

         }

 

         qdisc_run_end(q);

}

 

 

qdisc_restart负责发送数据包,后续将专门研究一下TC实现。

总结一下dev_queue_xmit,一是通过QoS层将调用hard_start_xmit发送数据,或者是直接调用hard_start_xmit来发送。

到现在我们只需要知道上层协议最后调用dev_queue_xmit来发送数据,有可能是直接发送出去,也有可能是经过软中断后发送,例如有QoS处理的时候。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值