The implementation of the streaming TC is mentioned in the packet sending section, and is now further studied.
Packet sending is implemented through Dev_queue_xmit,
if (q->enqueue) {
rc = __DEV_XMIT_SKB (SKB, Q, Dev, txq);
Goto out;
}
If there is a enqueue, then the flow control, or send directly.
Reference function __DEV_XMIT_SKB, we can see the enqueue operation of the SKB, and __qdisc_run start to trigger soft interrupts.
struct Qdisc_ops defines QoS-related operations, most notably Enqueue and dequeue.
When a NIC is registered, call int register_netdevice (struct net_device *dev), which is responsible for initializing the NIC TC
void Dev_init_scheduler (struct Net_device*dev)
{
dev->qdisc= &noop_qdisc;
Netdev_for_each_tx_queue (Dev,dev_init_scheduler_queue, &noop_qdisc);
if (Dev_ingress_queue (dev))
dev_init_scheduler_queue (Dev,dev_ingress_queue (Dev), &noop_qdisc);
Setup_timer (&dev->watchdog_timer,dev_watchdog, (unsigned long) dev);
Dev's qdisc was initialized to Noop_qdisc,netdev_for_each_tx_queue responsible for initializing the transport queues in Net_device: Dev->num_tx_queues queue number, dev->_ The TX queue, if there is a ingress queue, is also initialized, where we can see that there is only one queue, called Dev->ingress_queue.
Now look at the Noop_qdisc, initialize the registered QoS, see the code will find that the inside is empty, or simply will call KFREE_SKB will SKB release. This condition will activate the device change after ifconfig up, dev_activate judge, if the discovery is Noop_qdisc, then Attach_default_qdiscs is responsible for assigning the value again.
If the network card is set to a single queue and the queue size is 0, it is noqueue_qdisc;
Single queue, the single queue size is not 0, then pfifo_fast_ops;
Multiple queues, the queue size is 0, then Noqueue_qdisc;
Otherwise, the mq_qdisc_ops is the default policy.
Then, if we write the module to do TC operation, how to do it. Now let's analyze the SCH_RED.C
On the Module_init, Register_qdisc, adding Ops to the qdisc_base, specifically using the TC command at the end of NetLink call Tc_modify_qdisc.
function pointers in the QDISC_OPS structure body are used in the order of invocation is
Ops->init
Ops->attach
Ops->change
Ops->enqueue
Ops->dequeue
Ops->reset
Ops->destroy
The next major analysis
struct Qdisc_ops pfifo_fast_ops __read_mostly = {
. id = "Pfifo_fast",
. priv_size = sizeof (STRUCTPFIFO_FAST_PRIV),
. Enqueue = Pfifo_fast_enqueue,
. dequeue = Pfifo_fast_dequeue,
. Peek = Pfifo_fast_peek,
. init = Pfifo_fast_init,
. reset = Pfifo_fast_reset,
. dump = Pfifo_fast_dump,
. Owner = This_module,
};
This is the default policy under Linux.
Pfifo_fast_init initialization function
Pfifo_fast_enqueue, if the number of frame in the current queue is less than the maximum number in the queue, the band is calculated by Skb->priority, and the queue is finally added to the queue by band the index policy. If the maximum limit is exceeded, the SKB is released.
Pfifo_fast_dequeue are priv->bitmap indexed arrays, and queues are sent out 0 to 21 times, respectively.
Pfifo_fast_peek only extracts data, but not from the queue.
Pfifo_fast_reset finally reset.
Now go back to the Dev_queue_xmit function
1, dev_pick_tx Select Send Queue
2, Q->enqueue pressure queue
3, qdisc_restart,dequeue_skb out the queue
4, Dev_hard_start_xmit send
5, no success is sent, then save SKB to Gso_skb, next time dequeue send this SKB again
There is still one problem, that is the dev_ingress_queue in the ingress flow control is what happened.
The above general introduction of the TC system kernel implementation, TC system is very complex.
http://tldp.org/HOWTO/Traffic-Control-HOWTO/index.html How TC commands are used
Later will continue to further research, the way is to study from the TC command, the kernel implementation, and finally write a module to carry out the flow control.