Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'iff_no_queue'

Phil Sutter says:

====================
net: introduce IFF_NO_QUEUE as successor of zero tx_queue_len

This series adds a new private net_device flag indicating that a device may
(and probably should) be used without a queueing discipline attached to it.
This is already common practice for many virtual device types like e.g.
loopback, VLAN (802.1Q) or bridges (802.1D). The reason for this is that these
devices lack an underlying layer which could impose back pressure and therefore
making a TX queue necessary to not slow down senders.

Up to now, drivers being aware of the above applying to them set
dev->tx_queue_len to zero to indicate no qdisc should be attached to the
interface they drive and the kernel reacts upon this by assigning the noop
qdisc instead of the default pfifo_fast. This implicit agreement though leads
to an inconvenient situation once a user tries to attach a real qdisc to these
devices, as the formerly special tx_queue_len value becomes a regular one,
limiting the queue to zero packets and thus prevents any TX from happening. To
overcome this, practically all qdisc implementations intercept and sanitize the
malicious value.

With this series applied, drivers may signal the lack of need for a qdisc
without having to tamper with tx_queue_len, making fallbacks in qdiscs and
caveats in userspace unnecessary.

Upon upstream acceptance, this series will be followed up by a set of patches
converting device drivers, adding a warning so out-of-tree driver authors get
aware of this change and dropping all special handling of tx_queue_len in
net/sched/.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+7 -2
+3
include/linux/netdevice.h
··· 1262 1262 * @IFF_LIVE_ADDR_CHANGE: device supports hardware address 1263 1263 * change when it's running 1264 1264 * @IFF_MACVLAN: Macvlan device 1265 + * @IFF_NO_QUEUE: device can run without qdisc attached 1265 1266 */ 1266 1267 enum netdev_priv_flags { 1267 1268 IFF_802_1Q_VLAN = 1<<0, ··· 1291 1290 IFF_IPVLAN_MASTER = 1<<23, 1292 1291 IFF_IPVLAN_SLAVE = 1<<24, 1293 1292 IFF_VRF_MASTER = 1<<25, 1293 + IFF_NO_QUEUE = 1<<26, 1294 1294 }; 1295 1295 1296 1296 #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN ··· 1320 1318 #define IFF_IPVLAN_MASTER IFF_IPVLAN_MASTER 1321 1319 #define IFF_IPVLAN_SLAVE IFF_IPVLAN_SLAVE 1322 1320 #define IFF_VRF_MASTER IFF_VRF_MASTER 1321 + #define IFF_NO_QUEUE IFF_NO_QUEUE 1323 1322 1324 1323 /** 1325 1324 * struct net_device - The DEVICE structure.
+4 -2
net/sched/sch_generic.c
··· 735 735 { 736 736 struct Qdisc *qdisc = &noqueue_qdisc; 737 737 738 - if (dev->tx_queue_len) { 738 + if (dev->tx_queue_len && !(dev->priv_flags & IFF_NO_QUEUE)) { 739 739 qdisc = qdisc_create_dflt(dev_queue, 740 740 default_qdisc_ops, TC_H_ROOT); 741 741 if (!qdisc) { ··· 755 755 756 756 txq = netdev_get_tx_queue(dev, 0); 757 757 758 - if (!netif_is_multiqueue(dev) || dev->tx_queue_len == 0) { 758 + if (!netif_is_multiqueue(dev) || 759 + dev->tx_queue_len == 0 || 760 + dev->priv_flags & IFF_NO_QUEUE) { 759 761 netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL); 760 762 dev->qdisc = txq->qdisc_sleeping; 761 763 atomic_inc(&dev->qdisc->refcnt);