bql: Byte queue limits
Networking stack support for byte queue limits, uses dynamic queue
limits library. Byte queue limits are maintained per transmit queue,
and a dql structure has been added to netdev_queue structure for this
purpose.
Configuration of bql is in the tx-<n> sysfs directory for the queue
under the byte_queue_limits directory. Configuration includes:
limit_min, bql minimum limit
limit_max, bql maximum limit
hold_time, bql slack hold time
Also under the directory are:
limit, current byte limit
inflight, current number of bytes on the queue
Signed-off-by: Tom Herbert <therbert@google.com>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9b24cc7..97edb32 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -43,6 +43,7 @@
#include <linux/rculist.h>
#include <linux/dmaengine.h>
#include <linux/workqueue.h>
+#include <linux/dynamic_queue_limits.h>
#include <linux/ethtool.h>
#include <net/net_namespace.h>
@@ -541,7 +542,6 @@
*/
struct net_device *dev;
struct Qdisc *qdisc;
- unsigned long state;
struct Qdisc *qdisc_sleeping;
#ifdef CONFIG_SYSFS
struct kobject kobj;
@@ -564,6 +564,12 @@
* (/sys/class/net/DEV/Q/trans_timeout)
*/
unsigned long trans_timeout;
+
+ unsigned long state;
+
+#ifdef CONFIG_BQL
+ struct dql dql;
+#endif
} ____cacheline_aligned_in_smp;
static inline int netdev_queue_numa_node_read(const struct netdev_queue *q)
@@ -1862,6 +1868,15 @@
static inline void netdev_tx_sent_queue(struct netdev_queue *dev_queue,
unsigned int bytes)
{
+#ifdef CONFIG_BQL
+ dql_queued(&dev_queue->dql, bytes);
+ if (unlikely(dql_avail(&dev_queue->dql) < 0)) {
+ set_bit(__QUEUE_STATE_STACK_XOFF, &dev_queue->state);
+ if (unlikely(dql_avail(&dev_queue->dql) >= 0))
+ clear_bit(__QUEUE_STATE_STACK_XOFF,
+ &dev_queue->state);
+ }
+#endif
}
static inline void netdev_sent_queue(struct net_device *dev, unsigned int bytes)
@@ -1872,6 +1887,18 @@
static inline void netdev_tx_completed_queue(struct netdev_queue *dev_queue,
unsigned pkts, unsigned bytes)
{
+#ifdef CONFIG_BQL
+ if (likely(bytes)) {
+ dql_completed(&dev_queue->dql, bytes);
+ if (unlikely(test_bit(__QUEUE_STATE_STACK_XOFF,
+ &dev_queue->state) &&
+ dql_avail(&dev_queue->dql) >= 0)) {
+ if (test_and_clear_bit(__QUEUE_STATE_STACK_XOFF,
+ &dev_queue->state))
+ netif_schedule_queue(dev_queue);
+ }
+ }
+#endif
}
static inline void netdev_completed_queue(struct net_device *dev,
@@ -1882,6 +1909,9 @@
static inline void netdev_tx_reset_queue(struct netdev_queue *q)
{
+#ifdef CONFIG_BQL
+ dql_reset(&q->dql);
+#endif
}
static inline void netdev_reset_queue(struct net_device *dev_queue)