Packet sending and receiving is somewhat similar, we generally use int dev_queue_xmit (struct sk_buff *skb) to send packets, such as we construct the complete packet ourselves, and finally call the real physical send function.
But we also know that the delivery is also a soft interrupt processing,
OPEN_SOFTIRQ (net_tx_softirq,net_tx_action);
When will this soft interrupt be triggered? In fact, this soft interrupt is not necessary, only because there are some problems in the transmission process, the need for subsequent soft interrupts to deal with. For example, I am more concerned about the TC section.
If the TC is configured, then call __DEV_XMIT_SKB, first the packet will be enqueue, then __qdisc_run to send, at the same time judge whether should be scheduled, if yes, then __netif_schedule (q); Here is the condition for the soft interrupt trigger.
Further, there are other places where soft interrupts are triggered, but they are too detailed to be studied at the moment.
Queuing Criteria Interface
One of the most important parts of the packet delivery process is TC, which is the queuing criterion.
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 packets into the queue
Dequeue packets out of the queue
Requeue the packet back into the queue
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 is responsible for sending packets, followed by a dedicated study of TC implementation.
Summing up the Dev_queue_xmit, one is through the QoS layer will call Hard_start_xmit send data, or directly call Hard_start_xmit to send.
Now we just need to know that the upper layer protocol finally calls Dev_queue_xmit to send the data, either directly or through a soft interrupt, for example, when QoS is processed.