[PATCH RFC 2/3] Add qdisc_stats_broadcast_interval sysctl parameter, and use it to limit stats broadcast interval.
Toke Høiland-Jørgensen
toke at toke.dk
Mon Jun 10 05:39:48 PDT 2013
---
include/net/netns/ipv4.h | 4 ++++
include/net/sch_generic.h | 4 ++++
net/ipv4/sysctl_net_ipv4.c | 13 +++++++++++++
net/sched/sch_api.c | 7 +++++++
net/sched/sch_generic.c | 18 ++++++++++++++++++
5 files changed, 46 insertions(+)
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 2ba9de8..ff69564 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -64,6 +64,10 @@ struct netns_ipv4 {
int sysctl_tcp_ecn;
+#ifdef CONFIG_NET_SCH_BROADCAST_STATS
+ int sysctl_qdisc_stats_broadcast_interval;
+#endif
+
kgid_t sysctl_ping_group_range[2];
long sysctl_tcp_mem[3];
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index f10818f..92f26cf 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -78,6 +78,10 @@ struct Qdisc {
struct netdev_queue *dev_queue;
struct Qdisc *next_sched;
+#ifdef CONFIG_NET_SCH_BROADCAST_STATS
+ u64 last_stats_broadcast;
+#endif
+
struct sk_buff *gso_skb;
/*
* For performance sake on SMP, we put highly modified fields at the end
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 960fd29..896429c 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -851,6 +851,15 @@ static struct ctl_table ipv4_net_table[] = {
.mode = 0644,
.proc_handler = ipv4_tcp_mem,
},
+#ifdef CONFIG_NET_SCH_BROADCAST_STATS
+ {
+ .procname = "qdisc_stats_broadcast_interval",
+ .data = &init_net.ipv4.sysctl_qdisc_stats_broadcast_interval,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
+#endif
{ }
};
@@ -880,6 +889,10 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
&net->ipv4.sysctl_ping_group_range;
table[7].data =
&net->ipv4.sysctl_tcp_ecn;
+#ifdef CONFIG_NET_SCH_BROADCAST_STATS
+ table[9].data =
+ &net->ipv4.sysctl_qdisc_stats_broadcast_interval;
+#endif
/* Don't export sysctls to unprivileged users */
if (net->user_ns != &init_user_ns)
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index c297e2a..154b316 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1772,6 +1772,10 @@ static int __net_init psched_net_init(struct net *net)
if (e == NULL)
return -ENOMEM;
+#ifdef CONFIG_NET_SCH_BROADCAST_STATS
+ net->ipv4.sysctl_qdisc_stats_broadcast_interval = 200000;
+#endif
+
return 0;
}
@@ -1782,6 +1786,9 @@ static void __net_exit psched_net_exit(struct net *net)
#else
static int __net_init psched_net_init(struct net *net)
{
+#ifdef CONFIG_NET_SCH_BROADCAST_STATS
+ net->ipv4.sysctl_qdisc_stats_broadcast_interval = 200000;
+#endif
return 0;
}
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 56490a1..1b4e16d 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -150,6 +150,13 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
}
#ifdef CONFIG_NET_SCH_BROADCAST_STATS
+static inline u64 qdisc_stats_time(void)
+{
+ u64 ns = ktime_to_ns(ktime_get());
+ do_div(ns, NSEC_PER_USEC);
+ return ns;
+}
+
int qdisc_broadcast_stats(struct Qdisc *q)
{
struct tcmsg *tcm;
@@ -157,10 +164,16 @@ int qdisc_broadcast_stats(struct Qdisc *q)
struct gnet_dump d;
struct sk_buff *skb;
unsigned char *b;
+ u64 time;
if(!q->dev_queue || !q->dev_queue->dev)
return 0;
+ time = qdisc_stats_time();
+ if(time < q->last_stats_broadcast +
+ dev_net(qdisc_dev(q))->ipv4.sysctl_qdisc_stats_broadcast_interval)
+ return 0;
+
printk(KERN_DEBUG "Packet dequeue, ifname %s(%d), qdisc %s, qlen %d\n",
qdisc_dev(q)->name,
qdisc_dev(q)->ifindex,
@@ -205,6 +218,8 @@ int qdisc_broadcast_stats(struct Qdisc *q)
rtnetlink_send(skb, qdisc_dev(q)->nd_net, 0, RTNLGRP_TC_STATS, 0);
+ q->last_stats_broadcast = time;
+
return 0;
nla_put_failure:
@@ -636,6 +651,9 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
sch->enqueue = ops->enqueue;
sch->dequeue = ops->dequeue;
sch->dev_queue = dev_queue;
+#ifdef CONFIG_NET_SCH_BROADCAST_STATS
+ sch->last_stats_broadcast = qdisc_stats_time();
+#endif
dev_hold(dev);
atomic_set(&sch->refcnt, 1);
--
1.8.3
More information about the Bloat-devel
mailing list