aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/act_api.h2
-rw-r--r--include/net/gen_stats.h10
-rw-r--r--include/net/netfilter/xt_rateest.h2
-rw-r--r--include/net/sch_generic.h13
-rw-r--r--include/uapi/linux/gen_stats.h11
-rw-r--r--net/core/gen_estimator.c12
-rw-r--r--net/core/gen_stats.c22
-rw-r--r--net/netfilter/xt_rateest.c2
-rw-r--r--net/sched/sch_cbq.c2
-rw-r--r--net/sched/sch_drr.c2
-rw-r--r--net/sched/sch_hfsc.c2
-rw-r--r--net/sched/sch_htb.c2
-rw-r--r--net/sched/sch_qfq.c2
13 files changed, 54 insertions, 30 deletions
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 06ef7e926a66..b8ffac7b6bab 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -18,7 +18,7 @@ struct tcf_common {
18 struct tcf_t tcfc_tm; 18 struct tcf_t tcfc_tm;
19 struct gnet_stats_basic_packed tcfc_bstats; 19 struct gnet_stats_basic_packed tcfc_bstats;
20 struct gnet_stats_queue tcfc_qstats; 20 struct gnet_stats_queue tcfc_qstats;
21 struct gnet_stats_rate_est tcfc_rate_est; 21 struct gnet_stats_rate_est64 tcfc_rate_est;
22 spinlock_t tcfc_lock; 22 spinlock_t tcfc_lock;
23 struct rcu_head tcfc_rcu; 23 struct rcu_head tcfc_rcu;
24}; 24};
diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h
index a79b6cfb02a8..cf8439ba4d11 100644
--- a/include/net/gen_stats.h
+++ b/include/net/gen_stats.h
@@ -30,7 +30,7 @@ extern int gnet_stats_copy_basic(struct gnet_dump *d,
30 struct gnet_stats_basic_packed *b); 30 struct gnet_stats_basic_packed *b);
31extern int gnet_stats_copy_rate_est(struct gnet_dump *d, 31extern int gnet_stats_copy_rate_est(struct gnet_dump *d,
32 const struct gnet_stats_basic_packed *b, 32 const struct gnet_stats_basic_packed *b,
33 struct gnet_stats_rate_est *r); 33 struct gnet_stats_rate_est64 *r);
34extern int gnet_stats_copy_queue(struct gnet_dump *d, 34extern int gnet_stats_copy_queue(struct gnet_dump *d,
35 struct gnet_stats_queue *q); 35 struct gnet_stats_queue *q);
36extern int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len); 36extern int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len);
@@ -38,13 +38,13 @@ extern int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len);
38extern int gnet_stats_finish_copy(struct gnet_dump *d); 38extern int gnet_stats_finish_copy(struct gnet_dump *d);
39 39
40extern int gen_new_estimator(struct gnet_stats_basic_packed *bstats, 40extern int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
41 struct gnet_stats_rate_est *rate_est, 41 struct gnet_stats_rate_est64 *rate_est,
42 spinlock_t *stats_lock, struct nlattr *opt); 42 spinlock_t *stats_lock, struct nlattr *opt);
43extern void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, 43extern void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
44 struct gnet_stats_rate_est *rate_est); 44 struct gnet_stats_rate_est64 *rate_est);
45extern int gen_replace_estimator(struct gnet_stats_basic_packed *bstats, 45extern int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,
46 struct gnet_stats_rate_est *rate_est, 46 struct gnet_stats_rate_est64 *rate_est,
47 spinlock_t *stats_lock, struct nlattr *opt); 47 spinlock_t *stats_lock, struct nlattr *opt);
48extern bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats, 48extern bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
49 const struct gnet_stats_rate_est *rate_est); 49 const struct gnet_stats_rate_est64 *rate_est);
50#endif 50#endif
diff --git a/include/net/netfilter/xt_rateest.h b/include/net/netfilter/xt_rateest.h
index 5a2978d1cb22..495c71f66e7e 100644
--- a/include/net/netfilter/xt_rateest.h
+++ b/include/net/netfilter/xt_rateest.h
@@ -6,7 +6,7 @@ struct xt_rateest {
6 struct gnet_stats_basic_packed bstats; 6 struct gnet_stats_basic_packed bstats;
7 spinlock_t lock; 7 spinlock_t lock;
8 /* keep rstats and lock on same cache line to speedup xt_rateest_mt() */ 8 /* keep rstats and lock on same cache line to speedup xt_rateest_mt() */
9 struct gnet_stats_rate_est rstats; 9 struct gnet_stats_rate_est64 rstats;
10 10
11 /* following fields not accessed in hot path */ 11 /* following fields not accessed in hot path */
12 struct hlist_node list; 12 struct hlist_node list;
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index e7f4e21cc3e1..df5676029827 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -58,14 +58,12 @@ struct Qdisc {
58 * multiqueue device. 58 * multiqueue device.
59 */ 59 */
60#define TCQ_F_WARN_NONWC (1 << 16) 60#define TCQ_F_WARN_NONWC (1 << 16)
61 int padded; 61 u32 limit;
62 const struct Qdisc_ops *ops; 62 const struct Qdisc_ops *ops;
63 struct qdisc_size_table __rcu *stab; 63 struct qdisc_size_table __rcu *stab;
64 struct list_head list; 64 struct list_head list;
65 u32 handle; 65 u32 handle;
66 u32 parent; 66 u32 parent;
67 atomic_t refcnt;
68 struct gnet_stats_rate_est rate_est;
69 int (*reshape_fail)(struct sk_buff *skb, 67 int (*reshape_fail)(struct sk_buff *skb,
70 struct Qdisc *q); 68 struct Qdisc *q);
71 69
@@ -76,8 +74,9 @@ struct Qdisc {
76 */ 74 */
77 struct Qdisc *__parent; 75 struct Qdisc *__parent;
78 struct netdev_queue *dev_queue; 76 struct netdev_queue *dev_queue;
79 struct Qdisc *next_sched;
80 77
78 struct gnet_stats_rate_est64 rate_est;
79 struct Qdisc *next_sched;
81 struct sk_buff *gso_skb; 80 struct sk_buff *gso_skb;
82 /* 81 /*
83 * For performance sake on SMP, we put highly modified fields at the end 82 * For performance sake on SMP, we put highly modified fields at the end
@@ -88,8 +87,10 @@ struct Qdisc {
88 unsigned int __state; 87 unsigned int __state;
89 struct gnet_stats_queue qstats; 88 struct gnet_stats_queue qstats;
90 struct rcu_head rcu_head; 89 struct rcu_head rcu_head;
91 spinlock_t busylock; 90 int padded;
92 u32 limit; 91 atomic_t refcnt;
92
93 spinlock_t busylock ____cacheline_aligned_in_smp;
93}; 94};
94 95
95static inline bool qdisc_is_running(const struct Qdisc *qdisc) 96static inline bool qdisc_is_running(const struct Qdisc *qdisc)
diff --git a/include/uapi/linux/gen_stats.h b/include/uapi/linux/gen_stats.h
index 552c8a0a12d1..6487317ea619 100644
--- a/include/uapi/linux/gen_stats.h
+++ b/include/uapi/linux/gen_stats.h
@@ -9,6 +9,7 @@ enum {
9 TCA_STATS_RATE_EST, 9 TCA_STATS_RATE_EST,
10 TCA_STATS_QUEUE, 10 TCA_STATS_QUEUE,
11 TCA_STATS_APP, 11 TCA_STATS_APP,
12 TCA_STATS_RATE_EST64,
12 __TCA_STATS_MAX, 13 __TCA_STATS_MAX,
13}; 14};
14#define TCA_STATS_MAX (__TCA_STATS_MAX - 1) 15#define TCA_STATS_MAX (__TCA_STATS_MAX - 1)
@@ -38,6 +39,16 @@ struct gnet_stats_rate_est {
38}; 39};
39 40
40/** 41/**
42 * struct gnet_stats_rate_est64 - rate estimator
43 * @bps: current byte rate
44 * @pps: current packet rate
45 */
46struct gnet_stats_rate_est64 {
47 __u64 bps;
48 __u64 pps;
49};
50
51/**
41 * struct gnet_stats_queue - queuing statistics 52 * struct gnet_stats_queue - queuing statistics
42 * @qlen: queue length 53 * @qlen: queue length
43 * @backlog: backlog size of queue 54 * @backlog: backlog size of queue
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index d9d198aa9fed..6b5b6e7013ca 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -82,7 +82,7 @@ struct gen_estimator
82{ 82{
83 struct list_head list; 83 struct list_head list;
84 struct gnet_stats_basic_packed *bstats; 84 struct gnet_stats_basic_packed *bstats;
85 struct gnet_stats_rate_est *rate_est; 85 struct gnet_stats_rate_est64 *rate_est;
86 spinlock_t *stats_lock; 86 spinlock_t *stats_lock;
87 int ewma_log; 87 int ewma_log;
88 u64 last_bytes; 88 u64 last_bytes;
@@ -167,7 +167,7 @@ static void gen_add_node(struct gen_estimator *est)
167 167
168static 168static
169struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats, 169struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats,
170 const struct gnet_stats_rate_est *rate_est) 170 const struct gnet_stats_rate_est64 *rate_est)
171{ 171{
172 struct rb_node *p = est_root.rb_node; 172 struct rb_node *p = est_root.rb_node;
173 173
@@ -203,7 +203,7 @@ struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats
203 * 203 *
204 */ 204 */
205int gen_new_estimator(struct gnet_stats_basic_packed *bstats, 205int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
206 struct gnet_stats_rate_est *rate_est, 206 struct gnet_stats_rate_est64 *rate_est,
207 spinlock_t *stats_lock, 207 spinlock_t *stats_lock,
208 struct nlattr *opt) 208 struct nlattr *opt)
209{ 209{
@@ -258,7 +258,7 @@ EXPORT_SYMBOL(gen_new_estimator);
258 * Note : Caller should respect an RCU grace period before freeing stats_lock 258 * Note : Caller should respect an RCU grace period before freeing stats_lock
259 */ 259 */
260void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, 260void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
261 struct gnet_stats_rate_est *rate_est) 261 struct gnet_stats_rate_est64 *rate_est)
262{ 262{
263 struct gen_estimator *e; 263 struct gen_estimator *e;
264 264
@@ -290,7 +290,7 @@ EXPORT_SYMBOL(gen_kill_estimator);
290 * Returns 0 on success or a negative error code. 290 * Returns 0 on success or a negative error code.
291 */ 291 */
292int gen_replace_estimator(struct gnet_stats_basic_packed *bstats, 292int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,
293 struct gnet_stats_rate_est *rate_est, 293 struct gnet_stats_rate_est64 *rate_est,
294 spinlock_t *stats_lock, struct nlattr *opt) 294 spinlock_t *stats_lock, struct nlattr *opt)
295{ 295{
296 gen_kill_estimator(bstats, rate_est); 296 gen_kill_estimator(bstats, rate_est);
@@ -306,7 +306,7 @@ EXPORT_SYMBOL(gen_replace_estimator);
306 * Returns true if estimator is active, and false if not. 306 * Returns true if estimator is active, and false if not.
307 */ 307 */
308bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats, 308bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
309 const struct gnet_stats_rate_est *rate_est) 309 const struct gnet_stats_rate_est64 *rate_est)
310{ 310{
311 bool res; 311 bool res;
312 312
diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c
index ddedf211e588..9d3d9e78397b 100644
--- a/net/core/gen_stats.c
+++ b/net/core/gen_stats.c
@@ -143,18 +143,30 @@ EXPORT_SYMBOL(gnet_stats_copy_basic);
143int 143int
144gnet_stats_copy_rate_est(struct gnet_dump *d, 144gnet_stats_copy_rate_est(struct gnet_dump *d,
145 const struct gnet_stats_basic_packed *b, 145 const struct gnet_stats_basic_packed *b,
146 struct gnet_stats_rate_est *r) 146 struct gnet_stats_rate_est64 *r)
147{ 147{
148 struct gnet_stats_rate_est est;
149 int res;
150
148 if (b && !gen_estimator_active(b, r)) 151 if (b && !gen_estimator_active(b, r))
149 return 0; 152 return 0;
150 153
154 est.bps = min_t(u64, UINT_MAX, r->bps);
155 /* we have some time before reaching 2^32 packets per second */
156 est.pps = r->pps;
157
151 if (d->compat_tc_stats) { 158 if (d->compat_tc_stats) {
152 d->tc_stats.bps = r->bps; 159 d->tc_stats.bps = est.bps;
153 d->tc_stats.pps = r->pps; 160 d->tc_stats.pps = est.pps;
154 } 161 }
155 162
156 if (d->tail) 163 if (d->tail) {
157 return gnet_stats_copy(d, TCA_STATS_RATE_EST, r, sizeof(*r)); 164 res = gnet_stats_copy(d, TCA_STATS_RATE_EST, &est, sizeof(est));
165 if (res < 0 || est.bps == r->bps)
166 return res;
167 /* emit 64bit stats only if needed */
168 return gnet_stats_copy(d, TCA_STATS_RATE_EST64, r, sizeof(*r));
169 }
158 170
159 return 0; 171 return 0;
160} 172}
diff --git a/net/netfilter/xt_rateest.c b/net/netfilter/xt_rateest.c
index ed0db15ab00e..7720b036d76a 100644
--- a/net/netfilter/xt_rateest.c
+++ b/net/netfilter/xt_rateest.c
@@ -18,7 +18,7 @@ static bool
18xt_rateest_mt(const struct sk_buff *skb, struct xt_action_param *par) 18xt_rateest_mt(const struct sk_buff *skb, struct xt_action_param *par)
19{ 19{
20 const struct xt_rateest_match_info *info = par->matchinfo; 20 const struct xt_rateest_match_info *info = par->matchinfo;
21 struct gnet_stats_rate_est *r; 21 struct gnet_stats_rate_est64 *r;
22 u_int32_t bps1, bps2, pps1, pps2; 22 u_int32_t bps1, bps2, pps1, pps2;
23 bool ret = true; 23 bool ret = true;
24 24
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 1bc210ffcba2..71a568862557 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -130,7 +130,7 @@ struct cbq_class {
130 psched_time_t penalized; 130 psched_time_t penalized;
131 struct gnet_stats_basic_packed bstats; 131 struct gnet_stats_basic_packed bstats;
132 struct gnet_stats_queue qstats; 132 struct gnet_stats_queue qstats;
133 struct gnet_stats_rate_est rate_est; 133 struct gnet_stats_rate_est64 rate_est;
134 struct tc_cbq_xstats xstats; 134 struct tc_cbq_xstats xstats;
135 135
136 struct tcf_proto *filter_list; 136 struct tcf_proto *filter_list;
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index 759b308d1a8d..8302717ea303 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -25,7 +25,7 @@ struct drr_class {
25 25
26 struct gnet_stats_basic_packed bstats; 26 struct gnet_stats_basic_packed bstats;
27 struct gnet_stats_queue qstats; 27 struct gnet_stats_queue qstats;
28 struct gnet_stats_rate_est rate_est; 28 struct gnet_stats_rate_est64 rate_est;
29 struct list_head alist; 29 struct list_head alist;
30 struct Qdisc *qdisc; 30 struct Qdisc *qdisc;
31 31
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 9facea03faeb..c4075610502c 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -114,7 +114,7 @@ struct hfsc_class {
114 114
115 struct gnet_stats_basic_packed bstats; 115 struct gnet_stats_basic_packed bstats;
116 struct gnet_stats_queue qstats; 116 struct gnet_stats_queue qstats;
117 struct gnet_stats_rate_est rate_est; 117 struct gnet_stats_rate_est64 rate_est;
118 unsigned int level; /* class level in hierarchy */ 118 unsigned int level; /* class level in hierarchy */
119 struct tcf_proto *filter_list; /* filter list */ 119 struct tcf_proto *filter_list; /* filter list */
120 unsigned int filter_cnt; /* filter count */ 120 unsigned int filter_cnt; /* filter count */
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index adaedd79389c..162fb800754c 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -78,7 +78,7 @@ struct htb_class {
78 /* general class parameters */ 78 /* general class parameters */
79 struct gnet_stats_basic_packed bstats; 79 struct gnet_stats_basic_packed bstats;
80 struct gnet_stats_queue qstats; 80 struct gnet_stats_queue qstats;
81 struct gnet_stats_rate_est rate_est; 81 struct gnet_stats_rate_est64 rate_est;
82 struct tc_htb_xstats xstats; /* our special stats */ 82 struct tc_htb_xstats xstats; /* our special stats */
83 int refcnt; /* usage count of this class */ 83 int refcnt; /* usage count of this class */
84 84
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index d51852bba01c..7c195d972bf0 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -138,7 +138,7 @@ struct qfq_class {
138 138
139 struct gnet_stats_basic_packed bstats; 139 struct gnet_stats_basic_packed bstats;
140 struct gnet_stats_queue qstats; 140 struct gnet_stats_queue qstats;
141 struct gnet_stats_rate_est rate_est; 141 struct gnet_stats_rate_est64 rate_est;
142 struct Qdisc *qdisc; 142 struct Qdisc *qdisc;
143 struct list_head alist; /* Link for active-classes list. */ 143 struct list_head alist; /* Link for active-classes list. */
144 struct qfq_aggregate *agg; /* Parent aggregate. */ 144 struct qfq_aggregate *agg; /* Parent aggregate. */