TC source code analysis II, the location of flow control code in the kernel

Posted by mysterbx on Thu, 27 Jan 2022 22:27:53 +0100

tc source code analysis II, the location of flow control code in the kernel

Kernel version used

Linux 4.3

Problem exploration

We should study the source code. In addition to being curious about the way the code is written, we are most concerned about the actual logic of the code, so that we can easily understand what is happening inside.
Before studying the flow control code in the Linux kernel, I have two doubts:

  1. How is the flow control code associated with the network card?
  2. When are flow control related codes called?

problem analysis

1. Associated network card device

The first thing to know is that all flow control related operations in the kernel are in the F:\Hert\Studycode\linux-4.9.37\net\sched directory. The flow control subsystem is also Sch under this directory_ api. Registered in C.
Those who have used tc command know that pfifo is the simplest flow control scheme compared with other methods. Then start looking for the registration of this function.
First at / net / sched / Sch_ api. Function register found in C_ qdisc(&pfifo_fast_ops); .

int register_qdisc(struct Qdisc_ops *qops)
{
	struct Qdisc_ops *q, **qp;
	int rc = -EEXIST;

	write_lock(&qdisc_mod_lock);
	for (qp = &qdisc_base; (q = *qp) != NULL; qp = &q->next)
		if (!strcmp(qops->id, q->id))
			goto out;

	if (qops->enqueue == NULL)
		qops->enqueue = noop_qdisc_ops.enqueue;
	if (qops->peek == NULL) {
		if (qops->dequeue == NULL)
			qops->peek = noop_qdisc_ops.peek;
		else
			goto out_einval;
	}
	if (qops->dequeue == NULL)
		qops->dequeue = noop_qdisc_ops.dequeue;

	if (qops->cl_ops) {
		const struct Qdisc_class_ops *cops = qops->cl_ops;

		if (!(cops->get && cops->put && cops->walk && cops->leaf))
			goto out_einval;

		if (cops->tcf_chain && !(cops->bind_tcf && cops->unbind_tcf))
			goto out_einval;
	}

	qops->next = NULL;
	*qp = qops;
	rc = 0;
    ...

In this function, you can know pfifo_fast_ops this structure is added to qdisc_ In case.

Found two clues, one is
qdisc_lookup_ops <- qdisc_create <- qdisc_alloc(dev_queue, ops) <- tc_modify_qdisc <- rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL, NULL);

In qdisc_ In alloc, the parameter dev_queue is the device queue, while ops is via qdisc_ The structure of the flow control operation found inside the base.

In qdisc_alloc can find the following code, which shows that when calling qdisc_ During alloc, the flow control operation will be associated with the equipment.

sch->ops = ops;
sch->enqueue = ops->enqueue;
sch->dequeue = ops->dequeue;
sch->dev_queue = dev_queue;

And then continue to find it. In fact, this method is specified by the way netlink interacts.

Another method is the default flow control method when the equipment is turned on.

In fact, except qdisc_lookup_ops will use qdisc_base table, and a function qdisc_lookup_default also uses this list.

qdisc_ lookup_ default <- qdisc_ set_ default <- set_ default_ Qdisc (there will be the registration of proc file system)
-> qdisc_ set_ Default will use default_qdisc_ops structure, which will be in attach_ one_ default_ The qdisc function is called and further attached_ default_ Qdiscs call - > netdev_ for_ each_ tx_ queue(dev, attach_one_default_qdisc, NULL); Associated with the device.
And its own attachment_ default_ qdiscs <- dev_ activate <- __ dev_ open <- dev_ Open means that the flow control operation will be set when the device is enabled. Forget the description. The default flow control structure is default_ qdisc_ The value of OPS is pfifo_fast_ops, that is, the default flow control operation is pfifo.

2. When is the flow control operation called

Dev in the last part of kernel contracting_ queue_ Flow control will be processed in Xmit function.

txq = netdev_pick_tx(dev, skb, accel_priv);
	q = rcu_dereference_bh(txq->qdisc);

	trace_net_dev_queue(skb);
	if (q->enqueue) {
		rc = __dev_xmit_skb(skb, q, dev, txq);
		goto out;
	}
/*This is mainly to take out txq and qdisc of txq of this netdevice. Qdisc is mainly used for congestion processing. Generally, it is directly
 *The data packet is sent to the driver. If Busy is encountered, congestion processing needs to be carried out, and Qdisc will be used*/

__ dev_xmit_skb this function can see a lot about qdisc operations.

summary

So far, the general position of flow control in the kernel can be relatively clear.
When the device is turned on, the default pfifo flow control will be associated with the network card. After that, if the tc command is used for setting, its default configuration will be modified to the flow control mode set to.

Topics: Linux kernel