aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Herbert <therbert@google.com>2011-11-28 11:33:09 -0500
committerDavid S. Miller <davem@davemloft.net>2011-11-29 12:46:19 -0500
commit114cf5802165ee93e3ab461c9c505cd94a08b800 (patch)
tree88208dddd7c1e90f5e1a840ad0ad7afcea991050
parent927fbec13e40648d3c87cbb1daaac5b1fb9c8775 (diff)
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>
-rw-r--r--include/linux/netdevice.h32
-rw-r--r--net/Kconfig6
-rw-r--r--net/core/dev.c3
-rw-r--r--net/core/net-sysfs.c140
4 files changed, 172 insertions, 9 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9b24cc7a54d..97edb3215a5 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -43,6 +43,7 @@
43#include <linux/rculist.h> 43#include <linux/rculist.h>
44#include <linux/dmaengine.h> 44#include <linux/dmaengine.h>
45#include <linux/workqueue.h> 45#include <linux/workqueue.h>
46#include <linux/dynamic_queue_limits.h>
46 47
47#include <linux/ethtool.h> 48#include <linux/ethtool.h>
48#include <net/net_namespace.h> 49#include <net/net_namespace.h>
@@ -541,7 +542,6 @@ struct netdev_queue {
541 */ 542 */
542 struct net_device *dev; 543 struct net_device *dev;
543 struct Qdisc *qdisc; 544 struct Qdisc *qdisc;
544 unsigned long state;
545 struct Qdisc *qdisc_sleeping; 545 struct Qdisc *qdisc_sleeping;
546#ifdef CONFIG_SYSFS 546#ifdef CONFIG_SYSFS
547 struct kobject kobj; 547 struct kobject kobj;
@@ -564,6 +564,12 @@ struct netdev_queue {
564 * (/sys/class/net/DEV/Q/trans_timeout) 564 * (/sys/class/net/DEV/Q/trans_timeout)
565 */ 565 */
566 unsigned long trans_timeout; 566 unsigned long trans_timeout;
567
568 unsigned long state;
569
570#ifdef CONFIG_BQL
571 struct dql dql;
572#endif
567} ____cacheline_aligned_in_smp; 573} ____cacheline_aligned_in_smp;
568 574
569static inline int netdev_queue_numa_node_read(const struct netdev_queue *q) 575static inline int netdev_queue_numa_node_read(const struct netdev_queue *q)
@@ -1862,6 +1868,15 @@ static inline int netif_xmit_frozen_or_stopped(const struct netdev_queue *dev_qu
1862static inline void netdev_tx_sent_queue(struct netdev_queue *dev_queue, 1868static inline void netdev_tx_sent_queue(struct netdev_queue *dev_queue,
1863 unsigned int bytes) 1869 unsigned int bytes)
1864{ 1870{
1871#ifdef CONFIG_BQL
1872 dql_queued(&dev_queue->dql, bytes);
1873 if (unlikely(dql_avail(&dev_queue->dql) < 0)) {
1874 set_bit(__QUEUE_STATE_STACK_XOFF, &dev_queue->state);
1875 if (unlikely(dql_avail(&dev_queue->dql) >= 0))
1876 clear_bit(__QUEUE_STATE_STACK_XOFF,
1877 &dev_queue->state);
1878 }
1879#endif
1865} 1880}
1866 1881
1867static inline void netdev_sent_queue(struct net_device *dev, unsigned int bytes) 1882static inline void netdev_sent_queue(struct net_device *dev, unsigned int bytes)
@@ -1872,6 +1887,18 @@ static inline void netdev_sent_queue(struct net_device *dev, unsigned int bytes)
1872static inline void netdev_tx_completed_queue(struct netdev_queue *dev_queue, 1887static inline void netdev_tx_completed_queue(struct netdev_queue *dev_queue,
1873 unsigned pkts, unsigned bytes) 1888 unsigned pkts, unsigned bytes)
1874{ 1889{
1890#ifdef CONFIG_BQL
1891 if (likely(bytes)) {
1892 dql_completed(&dev_queue->dql, bytes);
1893 if (unlikely(test_bit(__QUEUE_STATE_STACK_XOFF,
1894 &dev_queue->state) &&
1895 dql_avail(&dev_queue->dql) >= 0)) {
1896 if (test_and_clear_bit(__QUEUE_STATE_STACK_XOFF,
1897 &dev_queue->state))
1898 netif_schedule_queue(dev_queue);
1899 }
1900 }
1901#endif
1875} 1902}
1876 1903
1877static inline void netdev_completed_queue(struct net_device *dev, 1904static inline void netdev_completed_queue(struct net_device *dev,
@@ -1882,6 +1909,9 @@ static inline void netdev_completed_queue(struct net_device *dev,
1882 1909
1883static inline void netdev_tx_reset_queue(struct netdev_queue *q) 1910static inline void netdev_tx_reset_queue(struct netdev_queue *q)
1884{ 1911{
1912#ifdef CONFIG_BQL
1913 dql_reset(&q->dql);
1914#endif
1885} 1915}
1886 1916
1887static inline void netdev_reset_queue(struct net_device *dev_queue) 1917static inline void netdev_reset_queue(struct net_device *dev_queue)
diff --git a/net/Kconfig b/net/Kconfig
index 63d2c5dc36f..2d998735c4d 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -239,6 +239,12 @@ config NETPRIO_CGROUP
239 Cgroup subsystem for use in assigning processes to network priorities on 239 Cgroup subsystem for use in assigning processes to network priorities on
240 a per-interface basis 240 a per-interface basis
241 241
242config BQL
243 boolean
244 depends on SYSFS
245 select DQL
246 default y
247
242config HAVE_BPF_JIT 248config HAVE_BPF_JIT
243 bool 249 bool
244 250
diff --git a/net/core/dev.c b/net/core/dev.c
index cb8f753b423..91a59912207 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5470,6 +5470,9 @@ static void netdev_init_one_queue(struct net_device *dev,
5470 queue->xmit_lock_owner = -1; 5470 queue->xmit_lock_owner = -1;
5471 netdev_queue_numa_node_write(queue, NUMA_NO_NODE); 5471 netdev_queue_numa_node_write(queue, NUMA_NO_NODE);
5472 queue->dev = dev; 5472 queue->dev = dev;
5473#ifdef CONFIG_BQL
5474 dql_init(&queue->dql, HZ);
5475#endif
5473} 5476}
5474 5477
5475static int netif_alloc_netdev_queues(struct net_device *dev) 5478static int netif_alloc_netdev_queues(struct net_device *dev)
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index b17c14a0fce..3bf72b638d3 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -21,6 +21,7 @@
21#include <linux/wireless.h> 21#include <linux/wireless.h>
22#include <linux/vmalloc.h> 22#include <linux/vmalloc.h>
23#include <linux/export.h> 23#include <linux/export.h>
24#include <linux/jiffies.h>
24#include <net/wext.h> 25#include <net/wext.h>
25 26
26#include "net-sysfs.h" 27#include "net-sysfs.h"
@@ -845,6 +846,116 @@ static ssize_t show_trans_timeout(struct netdev_queue *queue,
845static struct netdev_queue_attribute queue_trans_timeout = 846static struct netdev_queue_attribute queue_trans_timeout =
846 __ATTR(tx_timeout, S_IRUGO, show_trans_timeout, NULL); 847 __ATTR(tx_timeout, S_IRUGO, show_trans_timeout, NULL);
847 848
849#ifdef CONFIG_BQL
850/*
851 * Byte queue limits sysfs structures and functions.
852 */
853static ssize_t bql_show(char *buf, unsigned int value)
854{
855 return sprintf(buf, "%u\n", value);
856}
857
858static ssize_t bql_set(const char *buf, const size_t count,
859 unsigned int *pvalue)
860{
861 unsigned int value;
862 int err;
863
864 if (!strcmp(buf, "max") || !strcmp(buf, "max\n"))
865 value = DQL_MAX_LIMIT;
866 else {
867 err = kstrtouint(buf, 10, &value);
868 if (err < 0)
869 return err;
870 if (value > DQL_MAX_LIMIT)
871 return -EINVAL;
872 }
873
874 *pvalue = value;
875
876 return count;
877}
878
879static ssize_t bql_show_hold_time(struct netdev_queue *queue,
880 struct netdev_queue_attribute *attr,
881 char *buf)
882{
883 struct dql *dql = &queue->dql;
884
885 return sprintf(buf, "%u\n", jiffies_to_msecs(dql->slack_hold_time));
886}
887
888static ssize_t bql_set_hold_time(struct netdev_queue *queue,
889 struct netdev_queue_attribute *attribute,
890 const char *buf, size_t len)
891{
892 struct dql *dql = &queue->dql;
893 unsigned value;
894 int err;
895
896 err = kstrtouint(buf, 10, &value);
897 if (err < 0)
898 return err;
899
900 dql->slack_hold_time = msecs_to_jiffies(value);
901
902 return len;
903}
904
905static struct netdev_queue_attribute bql_hold_time_attribute =
906 __ATTR(hold_time, S_IRUGO | S_IWUSR, bql_show_hold_time,
907 bql_set_hold_time);
908
909static ssize_t bql_show_inflight(struct netdev_queue *queue,
910 struct netdev_queue_attribute *attr,
911 char *buf)
912{
913 struct dql *dql = &queue->dql;
914
915 return sprintf(buf, "%u\n", dql->num_queued - dql->num_completed);
916}
917
918static struct netdev_queue_attribute bql_inflight_attribute =
919 __ATTR(inflight, S_IRUGO | S_IWUSR, bql_show_inflight, NULL);
920
921#define BQL_ATTR(NAME, FIELD) \
922static ssize_t bql_show_ ## NAME(struct netdev_queue *queue, \
923 struct netdev_queue_attribute *attr, \
924 char *buf) \
925{ \
926 return bql_show(buf, queue->dql.FIELD); \
927} \
928 \
929static ssize_t bql_set_ ## NAME(struct netdev_queue *queue, \
930 struct netdev_queue_attribute *attr, \
931 const char *buf, size_t len) \
932{ \
933 return bql_set(buf, len, &queue->dql.FIELD); \
934} \
935 \
936static struct netdev_queue_attribute bql_ ## NAME ## _attribute = \
937 __ATTR(NAME, S_IRUGO | S_IWUSR, bql_show_ ## NAME, \
938 bql_set_ ## NAME);
939
940BQL_ATTR(limit, limit)
941BQL_ATTR(limit_max, max_limit)
942BQL_ATTR(limit_min, min_limit)
943
944static struct attribute *dql_attrs[] = {
945 &bql_limit_attribute.attr,
946 &bql_limit_max_attribute.attr,
947 &bql_limit_min_attribute.attr,
948 &bql_hold_time_attribute.attr,
949 &bql_inflight_attribute.attr,
950 NULL
951};
952
953static struct attribute_group dql_group = {
954 .name = "byte_queue_limits",
955 .attrs = dql_attrs,
956};
957#endif /* CONFIG_BQL */
958
848#ifdef CONFIG_XPS 959#ifdef CONFIG_XPS
849static inline unsigned int get_netdev_queue_index(struct netdev_queue *queue) 960static inline unsigned int get_netdev_queue_index(struct netdev_queue *queue)
850{ 961{
@@ -1096,17 +1207,17 @@ static struct attribute *netdev_queue_default_attrs[] = {
1096 NULL 1207 NULL
1097}; 1208};
1098 1209
1099#ifdef CONFIG_XPS
1100static void netdev_queue_release(struct kobject *kobj) 1210static void netdev_queue_release(struct kobject *kobj)
1101{ 1211{
1102 struct netdev_queue *queue = to_netdev_queue(kobj); 1212 struct netdev_queue *queue = to_netdev_queue(kobj);
1103 1213
1214#ifdef CONFIG_XPS
1104 xps_queue_release(queue); 1215 xps_queue_release(queue);
1216#endif
1105 1217
1106 memset(kobj, 0, sizeof(*kobj)); 1218 memset(kobj, 0, sizeof(*kobj));
1107 dev_put(queue->dev); 1219 dev_put(queue->dev);
1108} 1220}
1109#endif /* CONFIG_XPS */
1110 1221
1111static struct kobj_type netdev_queue_ktype = { 1222static struct kobj_type netdev_queue_ktype = {
1112 .sysfs_ops = &netdev_queue_sysfs_ops, 1223 .sysfs_ops = &netdev_queue_sysfs_ops,
@@ -1125,14 +1236,21 @@ static int netdev_queue_add_kobject(struct net_device *net, int index)
1125 kobj->kset = net->queues_kset; 1236 kobj->kset = net->queues_kset;
1126 error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL, 1237 error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL,
1127 "tx-%u", index); 1238 "tx-%u", index);
1128 if (error) { 1239 if (error)
1129 kobject_put(kobj); 1240 goto exit;
1130 return error; 1241
1131 } 1242#ifdef CONFIG_BQL
1243 error = sysfs_create_group(kobj, &dql_group);
1244 if (error)
1245 goto exit;
1246#endif
1132 1247
1133 kobject_uevent(kobj, KOBJ_ADD); 1248 kobject_uevent(kobj, KOBJ_ADD);
1134 dev_hold(queue->dev); 1249 dev_hold(queue->dev);
1135 1250
1251 return 0;
1252exit:
1253 kobject_put(kobj);
1136 return error; 1254 return error;
1137} 1255}
1138#endif /* CONFIG_SYSFS */ 1256#endif /* CONFIG_SYSFS */
@@ -1152,8 +1270,14 @@ netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num)
1152 } 1270 }
1153 } 1271 }
1154 1272
1155 while (--i >= new_num) 1273 while (--i >= new_num) {
1156 kobject_put(&net->_tx[i].kobj); 1274 struct netdev_queue *queue = net->_tx + i;
1275
1276#ifdef CONFIG_BQL
1277 sysfs_remove_group(&queue->kobj, &dql_group);
1278#endif
1279 kobject_put(&queue->kobj);
1280 }
1157 1281
1158 return error; 1282 return error;
1159#else 1283#else