History

ipvs: use 64-bit rates in stats

IPVS stats are limited to 2^(32-10) conns/s and packets/s, 2^(32-5) bytes/s. It is time to use 64 bits: * Change all conn/packet kernel counters to 64-bit and update them in u64_stats_update_{begin,end} section * In kernel use struct ip_vs_kstats instead of the user-space struct ip_vs_stats_user and use new func ip_vs_export_stats_user to export it to sockopt users to preserve compatibility with 32-bit values * Rename cpu counters "ustats" to "cnt" * To netlink users provide additionally 64-bit stats: IPVS_SVC_ATTR_STATS64 and IPVS_DEST_ATTR_STATS64. Old stats remain for old binaries. * We can use ip_vs_copy_stats in ip_vs_stats_percpu_show Thanks to Chris Caputo for providing initial patch for ip_vs_est.c

Julian Anastasov committed 11 years ago

Commit cd67cd51 parent 4c1017a5 files · +226 −143Browse files

Unified · Split

5 files
  1. include/net/ip_vs.h +33 −17
  2. include/uapi/linux/ip_vs.h +6 −1
  3. net/netfilter/ipvs/ip_vs_core.c +21 −15
  4. net/netfilter/ipvs/ip_vs_ctl.c +116 −58
  5. net/netfilter/ipvs/ip_vs_est.c +50 −52
include/net/ip_vs.h+33−17
@@ -365,15 +365,15 @@ struct ip_vs_seq { · 364 unmodified lines
365 365
366/* counters per cpu */366/* counters per cpu */
367struct ip_vs_counters {367struct ip_vs_counters {
368 __u32 conns; /* connections scheduled */368 __u64 conns; /* connections scheduled */
369 __u32 inpkts; /* incoming packets */369 __u64 inpkts; /* incoming packets */
370 __u32 outpkts; /* outgoing packets */370 __u64 outpkts; /* outgoing packets */
371 __u64 inbytes; /* incoming bytes */371 __u64 inbytes; /* incoming bytes */
372 __u64 outbytes; /* outgoing bytes */372 __u64 outbytes; /* outgoing bytes */
373};373};
374/* Stats per cpu */374/* Stats per cpu */
375struct ip_vs_cpu_stats {375struct ip_vs_cpu_stats {
376 struct ip_vs_counters ustats;376 struct ip_vs_counters cnt;
377 struct u64_stats_sync syncp;377 struct u64_stats_sync syncp;
378};378};
379 379
@@ -383,23 +383,40 @@ struct ip_vs_estimator { · 3 unmodified lines
383 383
384 u64 last_inbytes;384 u64 last_inbytes;
385 u64 last_outbytes;385 u64 last_outbytes;
386 u32 last_conns;386 u64 last_conns;
387 u32 last_inpkts;387 u64 last_inpkts;
388 u32 last_outpkts;388 u64 last_outpkts;
389 389
390 u32 cps;390 u64 cps;
391 u32 inpps;391 u64 inpps;
392 u32 outpps;392 u64 outpps;
393 u32 inbps;393 u64 inbps;
394 u32 outbps;394 u64 outbps;
395};
396
397/*
398 * IPVS statistics object, 64-bit kernel version of struct ip_vs_stats_user
399 */
400struct ip_vs_kstats {
401 u64 conns; /* connections scheduled */
402 u64 inpkts; /* incoming packets */
403 u64 outpkts; /* outgoing packets */
404 u64 inbytes; /* incoming bytes */
405 u64 outbytes; /* outgoing bytes */
406
407 u64 cps; /* current connection rate */
408 u64 inpps; /* current in packet rate */
409 u64 outpps; /* current out packet rate */
410 u64 inbps; /* current in byte rate */
411 u64 outbps; /* current out byte rate */
395};412};
396 413
397struct ip_vs_stats {414struct ip_vs_stats {
398 struct ip_vs_stats_user ustats; /* statistics */415 struct ip_vs_kstats kstats; /* kernel statistics */
399 struct ip_vs_estimator est; /* estimator */416 struct ip_vs_estimator est; /* estimator */
400 struct ip_vs_cpu_stats __percpu *cpustats; /* per cpu counters */417 struct ip_vs_cpu_stats __percpu *cpustats; /* per cpu counters */
401 spinlock_t lock; /* spin lock */418 spinlock_t lock; /* spin lock */
402 struct ip_vs_stats_user ustats0; /* reset values */419 struct ip_vs_kstats kstats0; /* reset values */
403};420};
404 421
405struct dst_entry;422struct dst_entry;
@@ -1388,8 +1405,7 @@ void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp, int pkts); · 982 unmodified lines
1388void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats);1405void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats);
1389void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats);1406void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats);
1390void ip_vs_zero_estimator(struct ip_vs_stats *stats);1407void ip_vs_zero_estimator(struct ip_vs_stats *stats);
1391void ip_vs_read_estimator(struct ip_vs_stats_user *dst,1408void ip_vs_read_estimator(struct ip_vs_kstats *dst, struct ip_vs_stats *stats);
1392 struct ip_vs_stats *stats);
1393 1409
1394/* Various IPVS packet transmitters (from ip_vs_xmit.c) */1410/* Various IPVS packet transmitters (from ip_vs_xmit.c) */
1395int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,1411int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
include/uapi/linux/ip_vs.h+6−1
@@ -358,6 +358,8 @@ enum { · 357 unmodified lines
358 358
359 IPVS_SVC_ATTR_PE_NAME, /* name of ct retriever */359 IPVS_SVC_ATTR_PE_NAME, /* name of ct retriever */
360 360
361 IPVS_SVC_ATTR_STATS64, /* nested attribute for service stats */
362
361 __IPVS_SVC_ATTR_MAX,363 __IPVS_SVC_ATTR_MAX,
362};364};
363 365
@@ -387,6 +389,8 @@ enum { · 23 unmodified lines
387 389
388 IPVS_DEST_ATTR_ADDR_FAMILY, /* Address family of address */390 IPVS_DEST_ATTR_ADDR_FAMILY, /* Address family of address */
389 391
392 IPVS_DEST_ATTR_STATS64, /* nested attribute for dest stats */
393
390 __IPVS_DEST_ATTR_MAX,394 __IPVS_DEST_ATTR_MAX,
391};395};
392 396
@@ -410,7 +414,8 @@ enum { · 17 unmodified lines
410/*414/*
411 * Attributes used to describe service or destination entry statistics415 * Attributes used to describe service or destination entry statistics
412 *416 *
413 * Used inside nested attributes IPVS_SVC_ATTR_STATS and IPVS_DEST_ATTR_STATS417 * Used inside nested attributes IPVS_SVC_ATTR_STATS, IPVS_DEST_ATTR_STATS,
418 * IPVS_SVC_ATTR_STATS64 and IPVS_DEST_ATTR_STATS64.
414 */419 */
415enum {420enum {
416 IPVS_STATS_ATTR_UNSPEC = 0,421 IPVS_STATS_ATTR_UNSPEC = 0,
net/netfilter/ipvs/ip_vs_core.c+21−15
@@ -119,24 +119,24 @@ ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb) · 118 unmodified lines
119 struct ip_vs_service *svc;119 struct ip_vs_service *svc;
120 120
121 s = this_cpu_ptr(dest->stats.cpustats);121 s = this_cpu_ptr(dest->stats.cpustats);
122 s->ustats.inpkts++;
123 u64_stats_update_begin(&s->syncp);122 u64_stats_update_begin(&s->syncp);
124 s->ustats.inbytes += skb->len;123 s->cnt.inpkts++;
124 s->cnt.inbytes += skb->len;
125 u64_stats_update_end(&s->syncp);125 u64_stats_update_end(&s->syncp);
126 126
127 rcu_read_lock();127 rcu_read_lock();
128 svc = rcu_dereference(dest->svc);128 svc = rcu_dereference(dest->svc);
129 s = this_cpu_ptr(svc->stats.cpustats);129 s = this_cpu_ptr(svc->stats.cpustats);
130 s->ustats.inpkts++;
131 u64_stats_update_begin(&s->syncp);130 u64_stats_update_begin(&s->syncp);
132 s->ustats.inbytes += skb->len;131 s->cnt.inpkts++;
132 s->cnt.inbytes += skb->len;
133 u64_stats_update_end(&s->syncp);133 u64_stats_update_end(&s->syncp);
134 rcu_read_unlock();134 rcu_read_unlock();
135 135
136 s = this_cpu_ptr(ipvs->tot_stats.cpustats);136 s = this_cpu_ptr(ipvs->tot_stats.cpustats);
137 s->ustats.inpkts++;
138 u64_stats_update_begin(&s->syncp);137 u64_stats_update_begin(&s->syncp);
139 s->ustats.inbytes += skb->len;138 s->cnt.inpkts++;
139 s->cnt.inbytes += skb->len;
140 u64_stats_update_end(&s->syncp);140 u64_stats_update_end(&s->syncp);
141 }141 }
142}142}
@@ -153,24 +153,24 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb) · 10 unmodified lines
153 struct ip_vs_service *svc;153 struct ip_vs_service *svc;
154 154
155 s = this_cpu_ptr(dest->stats.cpustats);155 s = this_cpu_ptr(dest->stats.cpustats);
156 s->ustats.outpkts++;
157 u64_stats_update_begin(&s->syncp);156 u64_stats_update_begin(&s->syncp);
158 s->ustats.outbytes += skb->len;157 s->cnt.outpkts++;
158 s->cnt.outbytes += skb->len;
159 u64_stats_update_end(&s->syncp);159 u64_stats_update_end(&s->syncp);
160 160
161 rcu_read_lock();161 rcu_read_lock();
162 svc = rcu_dereference(dest->svc);162 svc = rcu_dereference(dest->svc);
163 s = this_cpu_ptr(svc->stats.cpustats);163 s = this_cpu_ptr(svc->stats.cpustats);
164 s->ustats.outpkts++;
165 u64_stats_update_begin(&s->syncp);164 u64_stats_update_begin(&s->syncp);
166 s->ustats.outbytes += skb->len;165 s->cnt.outpkts++;
166 s->cnt.outbytes += skb->len;
167 u64_stats_update_end(&s->syncp);167 u64_stats_update_end(&s->syncp);
168 rcu_read_unlock();168 rcu_read_unlock();
169 169
170 s = this_cpu_ptr(ipvs->tot_stats.cpustats);170 s = this_cpu_ptr(ipvs->tot_stats.cpustats);
171 s->ustats.outpkts++;
172 u64_stats_update_begin(&s->syncp);171 u64_stats_update_begin(&s->syncp);
173 s->ustats.outbytes += skb->len;172 s->cnt.outpkts++;
173 s->cnt.outbytes += skb->len;
174 u64_stats_update_end(&s->syncp);174 u64_stats_update_end(&s->syncp);
175 }175 }
176}176}
@@ -183,13 +183,19 @@ ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc) · 6 unmodified lines
183 struct ip_vs_cpu_stats *s;183 struct ip_vs_cpu_stats *s;
184 184
185 s = this_cpu_ptr(cp->dest->stats.cpustats);185 s = this_cpu_ptr(cp->dest->stats.cpustats);
186 s->ustats.conns++;186 u64_stats_update_begin(&s->syncp);
187 s->cnt.conns++;
188 u64_stats_update_end(&s->syncp);
187 189
188 s = this_cpu_ptr(svc->stats.cpustats);190 s = this_cpu_ptr(svc->stats.cpustats);
189 s->ustats.conns++;191 u64_stats_update_begin(&s->syncp);
192 s->cnt.conns++;
193 u64_stats_update_end(&s->syncp);
190 194
191 s = this_cpu_ptr(ipvs->tot_stats.cpustats);195 s = this_cpu_ptr(ipvs->tot_stats.cpustats);
192 s->ustats.conns++;196 u64_stats_update_begin(&s->syncp);
197 s->cnt.conns++;
198 u64_stats_update_end(&s->syncp);
193}199}
194 200
195 201
net/netfilter/ipvs/ip_vs_ctl.c+116−58
@@ -729,9 +729,9 @@ static void ip_vs_trash_cleanup(struct net *net) · 728 unmodified lines
729}729}
730 730
731static void731static void
732ip_vs_copy_stats(struct ip_vs_stats_user *dst, struct ip_vs_stats *src)732ip_vs_copy_stats(struct ip_vs_kstats *dst, struct ip_vs_stats *src)
733{733{
734#define IP_VS_SHOW_STATS_COUNTER(c) dst->c = src->ustats.c - src->ustats0.c734#define IP_VS_SHOW_STATS_COUNTER(c) dst->c = src->kstats.c - src->kstats0.c
735 735
736 spin_lock_bh(&src->lock);736 spin_lock_bh(&src->lock);
737 737
@@ -746,6 +746,21 @@ ip_vs_copy_stats(struct ip_vs_stats_user *dst, struct ip_vs_stats *src) · 8 unmodified lines
746 spin_unlock_bh(&src->lock);746 spin_unlock_bh(&src->lock);
747}747}
748 748
749static void
750ip_vs_export_stats_user(struct ip_vs_stats_user *dst, struct ip_vs_kstats *src)
751{
752 dst->conns = (u32)src->conns;
753 dst->inpkts = (u32)src->inpkts;
754 dst->outpkts = (u32)src->outpkts;
755 dst->inbytes = src->inbytes;
756 dst->outbytes = src->outbytes;
757 dst->cps = (u32)src->cps;
758 dst->inpps = (u32)src->inpps;
759 dst->outpps = (u32)src->outpps;
760 dst->inbps = (u32)src->inbps;
761 dst->outbps = (u32)src->outbps;
762}
763
749static void764static void
750ip_vs_zero_stats(struct ip_vs_stats *stats)765ip_vs_zero_stats(struct ip_vs_stats *stats)
751{766{
@@ -753,7 +768,7 @@ ip_vs_zero_stats(struct ip_vs_stats *stats) · 1 unmodified line
753 768
754 /* get current counters as zero point, rates are zeroed */769 /* get current counters as zero point, rates are zeroed */
755 770
756#define IP_VS_ZERO_STATS_COUNTER(c) stats->ustats0.c = stats->ustats.c771#define IP_VS_ZERO_STATS_COUNTER(c) stats->kstats0.c = stats->kstats.c
757 772
758 IP_VS_ZERO_STATS_COUNTER(conns);773 IP_VS_ZERO_STATS_COUNTER(conns);
759 IP_VS_ZERO_STATS_COUNTER(inpkts);774 IP_VS_ZERO_STATS_COUNTER(inpkts);
@@ -2044,7 +2059,7 @@ static const struct file_operations ip_vs_info_fops = { · 1284 unmodified lines
2044static int ip_vs_stats_show(struct seq_file *seq, void *v)2059static int ip_vs_stats_show(struct seq_file *seq, void *v)
2045{2060{
2046 struct net *net = seq_file_single_net(seq);2061 struct net *net = seq_file_single_net(seq);
2047 struct ip_vs_stats_user show;2062 struct ip_vs_kstats show;
2048 2063
2049/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */2064/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
2050 seq_puts(seq,2065 seq_puts(seq,
@@ -2053,17 +2068,22 @@ static int ip_vs_stats_show(struct seq_file *seq, void *v) · 2 unmodified lines
2053 " Conns Packets Packets Bytes Bytes\n");2068 " Conns Packets Packets Bytes Bytes\n");
2054 2069
2055 ip_vs_copy_stats(&show, &net_ipvs(net)->tot_stats);2070 ip_vs_copy_stats(&show, &net_ipvs(net)->tot_stats);
2056 seq_printf(seq, "%8X %8X %8X %16LX %16LX\n\n", show.conns,2071 seq_printf(seq, "%8LX %8LX %8LX %16LX %16LX\n\n",
2057 show.inpkts, show.outpkts,2072 (unsigned long long)show.conns,
2058 (unsigned long long) show.inbytes,2073 (unsigned long long)show.inpkts,
2059 (unsigned long long) show.outbytes);2074 (unsigned long long)show.outpkts,
2060 2075 (unsigned long long)show.inbytes,
2061/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */2076 (unsigned long long)show.outbytes);
2077
2078/* 01234567 01234567 01234567 0123456701234567 0123456701234567*/
2062 seq_puts(seq,2079 seq_puts(seq,
2063 " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n");2080 " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n");
2064 seq_printf(seq, "%8X %8X %8X %16X %16X\n",2081 seq_printf(seq, "%8LX %8LX %8LX %16LX %16LX\n",
2065 show.cps, show.inpps, show.outpps,2082 (unsigned long long)show.cps,
2066 show.inbps, show.outbps);2083 (unsigned long long)show.inpps,
2084 (unsigned long long)show.outpps,
2085 (unsigned long long)show.inbps,
2086 (unsigned long long)show.outbps);
2067 2087
2068 return 0;2088 return 0;
2069}2089}
@@ -2086,7 +2106,7 @@ static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v) · 16 unmodified lines
2086 struct net *net = seq_file_single_net(seq);2106 struct net *net = seq_file_single_net(seq);
2087 struct ip_vs_stats *tot_stats = &net_ipvs(net)->tot_stats;2107 struct ip_vs_stats *tot_stats = &net_ipvs(net)->tot_stats;
2088 struct ip_vs_cpu_stats __percpu *cpustats = tot_stats->cpustats;2108 struct ip_vs_cpu_stats __percpu *cpustats = tot_stats->cpustats;
2089 struct ip_vs_stats_user rates;2109 struct ip_vs_kstats kstats;
2090 int i;2110 int i;
2091 2111
2092/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */2112/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
@@ -2098,41 +2118,41 @@ static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v) · 5 unmodified lines
2098 for_each_possible_cpu(i) {2118 for_each_possible_cpu(i) {
2099 struct ip_vs_cpu_stats *u = per_cpu_ptr(cpustats, i);2119 struct ip_vs_cpu_stats *u = per_cpu_ptr(cpustats, i);
2100 unsigned int start;2120 unsigned int start;
2101 __u64 inbytes, outbytes;2121 u64 conns, inpkts, outpkts, inbytes, outbytes;
2102 2122
2103 do {2123 do {
2104 start = u64_stats_fetch_begin_irq(&u->syncp);2124 start = u64_stats_fetch_begin_irq(&u->syncp);
2105 inbytes = u->ustats.inbytes;2125 conns = u->cnt.conns;
2106 outbytes = u->ustats.outbytes;2126 inpkts = u->cnt.inpkts;
2127 outpkts = u->cnt.outpkts;
2128 inbytes = u->cnt.inbytes;
2129 outbytes = u->cnt.outbytes;
2107 } while (u64_stats_fetch_retry_irq(&u->syncp, start));2130 } while (u64_stats_fetch_retry_irq(&u->syncp, start));
2108 2131
2109 seq_printf(seq, "%3X %8X %8X %8X %16LX %16LX\n",2132 seq_printf(seq, "%3X %8LX %8LX %8LX %16LX %16LX\n",
2110 i, u->ustats.conns, u->ustats.inpkts,2133 i, (u64)conns, (u64)inpkts,
2111 u->ustats.outpkts, (__u64)inbytes,2134 (u64)outpkts, (u64)inbytes,
2112 (__u64)outbytes);2135 (u64)outbytes);
2113 }2136 }
2114 2137
2115 spin_lock_bh(&tot_stats->lock);2138 ip_vs_copy_stats(&kstats, tot_stats);
2116
2117 seq_printf(seq, " ~ %8X %8X %8X %16LX %16LX\n\n",
2118 tot_stats->ustats.conns, tot_stats->ustats.inpkts,
2119 tot_stats->ustats.outpkts,
2120 (unsigned long long) tot_stats->ustats.inbytes,
2121 (unsigned long long) tot_stats->ustats.outbytes);
2122
2123 ip_vs_read_estimator(&rates, tot_stats);
2124 2139
2125 spin_unlock_bh(&tot_stats->lock);2140 seq_printf(seq, " ~ %8LX %8LX %8LX %16LX %16LX\n\n",
2141 (unsigned long long)kstats.conns,
2142 (unsigned long long)kstats.inpkts,
2143 (unsigned long long)kstats.outpkts,
2144 (unsigned long long)kstats.inbytes,
2145 (unsigned long long)kstats.outbytes);
2126 2146
2127/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */2147/* ... 01234567 01234567 01234567 0123456701234567 0123456701234567 */
2128 seq_puts(seq,2148 seq_puts(seq,
2129 " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n");2149 " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n");
2130 seq_printf(seq, " %8X %8X %8X %16X %16X\n",2150 seq_printf(seq, " %8LX %8LX %8LX %16LX %16LX\n",
2131 rates.cps,2151 kstats.cps,
2132 rates.inpps,2152 kstats.inpps,
2133 rates.outpps,2153 kstats.outpps,
2134 rates.inbps,2154 kstats.inbps,
2135 rates.outbps);2155 kstats.outbps);
2136 2156
2137 return 0;2157 return 0;
2138}2158}
@@ -2400,6 +2420,7 @@ static void · 261 unmodified lines
2400ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src)2420ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src)
2401{2421{
2402 struct ip_vs_scheduler *sched;2422 struct ip_vs_scheduler *sched;
2423 struct ip_vs_kstats kstats;
2403 2424
2404 sched = rcu_dereference_protected(src->scheduler, 1);2425 sched = rcu_dereference_protected(src->scheduler, 1);
2405 dst->protocol = src->protocol;2426 dst->protocol = src->protocol;
@@ -2411,7 +2432,8 @@ ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src) · 5 unmodified lines
2411 dst->timeout = src->timeout / HZ;2432 dst->timeout = src->timeout / HZ;
2412 dst->netmask = src->netmask;2433 dst->netmask = src->netmask;
2413 dst->num_dests = src->num_dests;2434 dst->num_dests = src->num_dests;
2414 ip_vs_copy_stats(&dst->stats, &src->stats);2435 ip_vs_copy_stats(&kstats, &src->stats);
2436 ip_vs_export_stats_user(&dst->stats, &kstats);
2415}2437}
2416 2438
2417static inline int2439static inline int
@@ -2485,6 +2507,7 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get, · 67 unmodified lines
2485 int count = 0;2507 int count = 0;
2486 struct ip_vs_dest *dest;2508 struct ip_vs_dest *dest;
2487 struct ip_vs_dest_entry entry;2509 struct ip_vs_dest_entry entry;
2510 struct ip_vs_kstats kstats;
2488 2511
2489 memset(&entry, 0, sizeof(entry));2512 memset(&entry, 0, sizeof(entry));
2490 list_for_each_entry(dest, &svc->destinations, n_list) {2513 list_for_each_entry(dest, &svc->destinations, n_list) {
@@ -2506,7 +2529,8 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get, · 15 unmodified lines
2506 entry.activeconns = atomic_read(&dest->activeconns);2529 entry.activeconns = atomic_read(&dest->activeconns);
2507 entry.inactconns = atomic_read(&dest->inactconns);2530 entry.inactconns = atomic_read(&dest->inactconns);
2508 entry.persistconns = atomic_read(&dest->persistconns);2531 entry.persistconns = atomic_read(&dest->persistconns);
2509 ip_vs_copy_stats(&entry.stats, &dest->stats);2532 ip_vs_copy_stats(&kstats, &dest->stats);
2533 ip_vs_export_stats_user(&entry.stats, &kstats);
2510 if (copy_to_user(&uptr->entrytable[count],2534 if (copy_to_user(&uptr->entrytable[count],
2511 &entry, sizeof(entry))) {2535 &entry, sizeof(entry))) {
2512 ret = -EFAULT;2536 ret = -EFAULT;
@@ -2798,25 +2822,51 @@ static const struct nla_policy ip_vs_dest_policy[IPVS_DEST_ATTR_MAX + 1] = { · 285 unmodified lines
2798};2822};
2799 2823
2800static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type,2824static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type,
2801 struct ip_vs_stats *stats)2825 struct ip_vs_kstats *kstats)
2826{
2827 struct nlattr *nl_stats = nla_nest_start(skb, container_type);
2828
2829 if (!nl_stats)
2830 return -EMSGSIZE;
2831
2832 if (nla_put_u32(skb, IPVS_STATS_ATTR_CONNS, (u32)kstats->conns) ||
2833 nla_put_u32(skb, IPVS_STATS_ATTR_INPKTS, (u32)kstats->inpkts) ||
2834 nla_put_u32(skb, IPVS_STATS_ATTR_OUTPKTS, (u32)kstats->outpkts) ||
2835 nla_put_u64(skb, IPVS_STATS_ATTR_INBYTES, kstats->inbytes) ||
2836 nla_put_u64(skb, IPVS_STATS_ATTR_OUTBYTES, kstats->outbytes) ||
2837 nla_put_u32(skb, IPVS_STATS_ATTR_CPS, (u32)kstats->cps) ||
2838 nla_put_u32(skb, IPVS_STATS_ATTR_INPPS, (u32)kstats->inpps) ||
2839 nla_put_u32(skb, IPVS_STATS_ATTR_OUTPPS, (u32)kstats->outpps) ||
2840 nla_put_u32(skb, IPVS_STATS_ATTR_INBPS, (u32)kstats->inbps) ||
2841 nla_put_u32(skb, IPVS_STATS_ATTR_OUTBPS, (u32)kstats->outbps))
2842 goto nla_put_failure;
2843 nla_nest_end(skb, nl_stats);
2844
2845 return 0;
2846
2847nla_put_failure:
2848 nla_nest_cancel(skb, nl_stats);
2849 return -EMSGSIZE;
2850}
2851
2852static int ip_vs_genl_fill_stats64(struct sk_buff *skb, int container_type,
2853 struct ip_vs_kstats *kstats)
2802{2854{
2803 struct ip_vs_stats_user ustats;
2804 struct nlattr *nl_stats = nla_nest_start(skb, container_type);2855 struct nlattr *nl_stats = nla_nest_start(skb, container_type);
2856
2805 if (!nl_stats)2857 if (!nl_stats)
2806 return -EMSGSIZE;2858 return -EMSGSIZE;
2807 2859
2808 ip_vs_copy_stats(&ustats, stats);2860 if (nla_put_u64(skb, IPVS_STATS_ATTR_CONNS, kstats->conns) ||
2809 2861 nla_put_u64(skb, IPVS_STATS_ATTR_INPKTS, kstats->inpkts) ||
2810 if (nla_put_u32(skb, IPVS_STATS_ATTR_CONNS, ustats.conns) ||2862 nla_put_u64(skb, IPVS_STATS_ATTR_OUTPKTS, kstats->outpkts) ||
2811 nla_put_u32(skb, IPVS_STATS_ATTR_INPKTS, ustats.inpkts) ||2863 nla_put_u64(skb, IPVS_STATS_ATTR_INBYTES, kstats->inbytes) ||
2812 nla_put_u32(skb, IPVS_STATS_ATTR_OUTPKTS, ustats.outpkts) ||2864 nla_put_u64(skb, IPVS_STATS_ATTR_OUTBYTES, kstats->outbytes) ||
2813 nla_put_u64(skb, IPVS_STATS_ATTR_INBYTES, ustats.inbytes) ||2865 nla_put_u64(skb, IPVS_STATS_ATTR_CPS, kstats->cps) ||
2814 nla_put_u64(skb, IPVS_STATS_ATTR_OUTBYTES, ustats.outbytes) ||2866 nla_put_u64(skb, IPVS_STATS_ATTR_INPPS, kstats->inpps) ||
2815 nla_put_u32(skb, IPVS_STATS_ATTR_CPS, ustats.cps) ||2867 nla_put_u64(skb, IPVS_STATS_ATTR_OUTPPS, kstats->outpps) ||
2816 nla_put_u32(skb, IPVS_STATS_ATTR_INPPS, ustats.inpps) ||2868 nla_put_u64(skb, IPVS_STATS_ATTR_INBPS, kstats->inbps) ||
2817 nla_put_u32(skb, IPVS_STATS_ATTR_OUTPPS, ustats.outpps) ||2869 nla_put_u64(skb, IPVS_STATS_ATTR_OUTBPS, kstats->outbps))
2818 nla_put_u32(skb, IPVS_STATS_ATTR_INBPS, ustats.inbps) ||
2819 nla_put_u32(skb, IPVS_STATS_ATTR_OUTBPS, ustats.outbps))
2820 goto nla_put_failure;2870 goto nla_put_failure;
2821 nla_nest_end(skb, nl_stats);2871 nla_nest_end(skb, nl_stats);
2822 2872
@@ -2835,6 +2885,7 @@ static int ip_vs_genl_fill_service(struct sk_buff *skb, · 12 unmodified lines
2835 struct nlattr *nl_service;2885 struct nlattr *nl_service;
2836 struct ip_vs_flags flags = { .flags = svc->flags,2886 struct ip_vs_flags flags = { .flags = svc->flags,
2837 .mask = ~0 };2887 .mask = ~0 };
2888 struct ip_vs_kstats kstats;
2838 2889
2839 nl_service = nla_nest_start(skb, IPVS_CMD_ATTR_SERVICE);2890 nl_service = nla_nest_start(skb, IPVS_CMD_ATTR_SERVICE);
2840 if (!nl_service)2891 if (!nl_service)
@@ -2860,7 +2911,10 @@ static int ip_vs_genl_fill_service(struct sk_buff *skb, · 19 unmodified lines
2860 nla_put_u32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ) ||2911 nla_put_u32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ) ||
2861 nla_put_be32(skb, IPVS_SVC_ATTR_NETMASK, svc->netmask))2912 nla_put_be32(skb, IPVS_SVC_ATTR_NETMASK, svc->netmask))
2862 goto nla_put_failure;2913 goto nla_put_failure;
2863 if (ip_vs_genl_fill_stats(skb, IPVS_SVC_ATTR_STATS, &svc->stats))2914 ip_vs_copy_stats(&kstats, &svc->stats);
2915 if (ip_vs_genl_fill_stats(skb, IPVS_SVC_ATTR_STATS, &kstats))
2916 goto nla_put_failure;
2917 if (ip_vs_genl_fill_stats64(skb, IPVS_SVC_ATTR_STATS64, &kstats))
2864 goto nla_put_failure;2918 goto nla_put_failure;
2865 2919
2866 nla_nest_end(skb, nl_service);2920 nla_nest_end(skb, nl_service);
@@ -3032,6 +3086,7 @@ static struct ip_vs_service *ip_vs_genl_find_service(struct net *net, · 165 unmodified lines
3032static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest)3086static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest)
3033{3087{
3034 struct nlattr *nl_dest;3088 struct nlattr *nl_dest;
3089 struct ip_vs_kstats kstats;
3035 3090
3036 nl_dest = nla_nest_start(skb, IPVS_CMD_ATTR_DEST);3091 nl_dest = nla_nest_start(skb, IPVS_CMD_ATTR_DEST);
3037 if (!nl_dest)3092 if (!nl_dest)
@@ -3054,7 +3109,10 @@ static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest) · 16 unmodified lines
3054 atomic_read(&dest->persistconns)) ||3109 atomic_read(&dest->persistconns)) ||
3055 nla_put_u16(skb, IPVS_DEST_ATTR_ADDR_FAMILY, dest->af))3110 nla_put_u16(skb, IPVS_DEST_ATTR_ADDR_FAMILY, dest->af))
3056 goto nla_put_failure;3111 goto nla_put_failure;
3057 if (ip_vs_genl_fill_stats(skb, IPVS_DEST_ATTR_STATS, &dest->stats))3112 ip_vs_copy_stats(&kstats, &dest->stats);
3113 if (ip_vs_genl_fill_stats(skb, IPVS_DEST_ATTR_STATS, &kstats))
3114 goto nla_put_failure;
3115 if (ip_vs_genl_fill_stats64(skb, IPVS_DEST_ATTR_STATS64, &kstats))
3058 goto nla_put_failure;3116 goto nla_put_failure;
3059 3117
3060 nla_nest_end(skb, nl_dest);3118 nla_nest_end(skb, nl_dest);
net/netfilter/ipvs/ip_vs_est.c+50−52
@@ -45,17 +45,19 @@ · 44 unmodified lines
45 45
46 NOTES.46 NOTES.
47 47
48 * The stored value for average bps is scaled by 2^5, so that maximal48 * Average bps is scaled by 2^5, while average pps and cps are scaled by 2^10.
49 rate is ~2.15Gbits/s, average pps and cps are scaled by 2^10.
50 49
51 * A lot code is taken from net/sched/estimator.c50 * Netlink users can see 64-bit values but sockopt users are restricted
51 to 32-bit values for conns, packets, bps, cps and pps.
52
53 * A lot of code is taken from net/core/gen_estimator.c
52 */54 */
53 55
54 56
55/*57/*
56 * Make a summary from each cpu58 * Make a summary from each cpu
57 */59 */
58static void ip_vs_read_cpu_stats(struct ip_vs_stats_user *sum,60static void ip_vs_read_cpu_stats(struct ip_vs_kstats *sum,
59 struct ip_vs_cpu_stats __percpu *stats)61 struct ip_vs_cpu_stats __percpu *stats)
60{62{
61 int i;63 int i;
@@ -64,27 +66,31 @@ static void ip_vs_read_cpu_stats(struct ip_vs_stats_user *sum, · 2 unmodified lines
64 for_each_possible_cpu(i) {66 for_each_possible_cpu(i) {
65 struct ip_vs_cpu_stats *s = per_cpu_ptr(stats, i);67 struct ip_vs_cpu_stats *s = per_cpu_ptr(stats, i);
66 unsigned int start;68 unsigned int start;
67 __u64 inbytes, outbytes;69 u64 conns, inpkts, outpkts, inbytes, outbytes;
70
68 if (add) {71 if (add) {
69 sum->conns += s->ustats.conns;
70 sum->inpkts += s->ustats.inpkts;
71 sum->outpkts += s->ustats.outpkts;
72 do {72 do {
73 start = u64_stats_fetch_begin(&s->syncp);73 start = u64_stats_fetch_begin(&s->syncp);
74 inbytes = s->ustats.inbytes;74 conns = s->cnt.conns;
75 outbytes = s->ustats.outbytes;75 inpkts = s->cnt.inpkts;
76 outpkts = s->cnt.outpkts;
77 inbytes = s->cnt.inbytes;
78 outbytes = s->cnt.outbytes;
76 } while (u64_stats_fetch_retry(&s->syncp, start));79 } while (u64_stats_fetch_retry(&s->syncp, start));
80 sum->conns += conns;
81 sum->inpkts += inpkts;
82 sum->outpkts += outpkts;
77 sum->inbytes += inbytes;83 sum->inbytes += inbytes;
78 sum->outbytes += outbytes;84 sum->outbytes += outbytes;
79 } else {85 } else {
80 add = true;86 add = true;
81 sum->conns = s->ustats.conns;
82 sum->inpkts = s->ustats.inpkts;
83 sum->outpkts = s->ustats.outpkts;
84 do {87 do {
85 start = u64_stats_fetch_begin(&s->syncp);88 start = u64_stats_fetch_begin(&s->syncp);
86 sum->inbytes = s->ustats.inbytes;89 sum->conns = s->cnt.conns;
87 sum->outbytes = s->ustats.outbytes;90 sum->inpkts = s->cnt.inpkts;
91 sum->outpkts = s->cnt.outpkts;
92 sum->inbytes = s->cnt.inbytes;
93 sum->outbytes = s->cnt.outbytes;
88 } while (u64_stats_fetch_retry(&s->syncp, start));94 } while (u64_stats_fetch_retry(&s->syncp, start));
89 }95 }
90 }96 }
@@ -95,10 +101,7 @@ static void estimation_timer(unsigned long arg) · 4 unmodified lines
95{101{
96 struct ip_vs_estimator *e;102 struct ip_vs_estimator *e;
97 struct ip_vs_stats *s;103 struct ip_vs_stats *s;
98 u32 n_conns;104 u64 rate;
99 u32 n_inpkts, n_outpkts;
100 u64 n_inbytes, n_outbytes;
101 u32 rate;
102 struct net *net = (struct net *)arg;105 struct net *net = (struct net *)arg;
103 struct netns_ipvs *ipvs;106 struct netns_ipvs *ipvs;
104 107
@@ -108,33 +111,29 @@ static void estimation_timer(unsigned long arg) · 3 unmodified lines
108 s = container_of(e, struct ip_vs_stats, est);111 s = container_of(e, struct ip_vs_stats, est);
109 112
110 spin_lock(&s->lock);113 spin_lock(&s->lock);
111 ip_vs_read_cpu_stats(&s->ustats, s->cpustats);114 ip_vs_read_cpu_stats(&s->kstats, s->cpustats);
112 n_conns = s->ustats.conns;
113 n_inpkts = s->ustats.inpkts;
114 n_outpkts = s->ustats.outpkts;
115 n_inbytes = s->ustats.inbytes;
116 n_outbytes = s->ustats.outbytes;
117 115
118 /* scaled by 2^10, but divided 2 seconds */116 /* scaled by 2^10, but divided 2 seconds */
119 rate = (n_conns - e->last_conns) << 9;117 rate = (s->kstats.conns - e->last_conns) << 9;
120 e->last_conns = n_conns;118 e->last_conns = s->kstats.conns;
121 e->cps += ((long)rate - (long)e->cps) >> 2;119 e->cps += ((s64)rate - (s64)e->cps) >> 2;
122 120
123 rate = (n_inpkts - e->last_inpkts) << 9;121 rate = (s->kstats.inpkts - e->last_inpkts) << 9;
124 e->last_inpkts = n_inpkts;122 e->last_inpkts = s->kstats.inpkts;
125 e->inpps += ((long)rate - (long)e->inpps) >> 2;123 e->inpps += ((s64)rate - (s64)e->inpps) >> 2;
126 124
127 rate = (n_outpkts - e->last_outpkts) << 9;125 rate = (s->kstats.outpkts - e->last_outpkts) << 9;
128 e->last_outpkts = n_outpkts;126 e->last_outpkts = s->kstats.outpkts;
129 e->outpps += ((long)rate - (long)e->outpps) >> 2;127 e->outpps += ((s64)rate - (s64)e->outpps) >> 2;
130 128
131 rate = (n_inbytes - e->last_inbytes) << 4;129 /* scaled by 2^5, but divided 2 seconds */
132 e->last_inbytes = n_inbytes;130 rate = (s->kstats.inbytes - e->last_inbytes) << 4;
133 e->inbps += ((long)rate - (long)e->inbps) >> 2;131 e->last_inbytes = s->kstats.inbytes;
134 132 e->inbps += ((s64)rate - (s64)e->inbps) >> 2;
135 rate = (n_outbytes - e->last_outbytes) << 4;133
136 e->last_outbytes = n_outbytes;134 rate = (s->kstats.outbytes - e->last_outbytes) << 4;
137 e->outbps += ((long)rate - (long)e->outbps) >> 2;135 e->last_outbytes = s->kstats.outbytes;
136 e->outbps += ((s64)rate - (s64)e->outbps) >> 2;
138 spin_unlock(&s->lock);137 spin_unlock(&s->lock);
139 }138 }
140 spin_unlock(&ipvs->est_lock);139 spin_unlock(&ipvs->est_lock);
@@ -166,14 +165,14 @@ void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats) · 25 unmodified lines
166void ip_vs_zero_estimator(struct ip_vs_stats *stats)165void ip_vs_zero_estimator(struct ip_vs_stats *stats)
167{166{
168 struct ip_vs_estimator *est = &stats->est;167 struct ip_vs_estimator *est = &stats->est;
169 struct ip_vs_stats_user *u = &stats->ustats;168 struct ip_vs_kstats *k = &stats->kstats;
170 169
171 /* reset counters, caller must hold the stats->lock lock */170 /* reset counters, caller must hold the stats->lock lock */
172 est->last_inbytes = u->inbytes;171 est->last_inbytes = k->inbytes;
173 est->last_outbytes = u->outbytes;172 est->last_outbytes = k->outbytes;
174 est->last_conns = u->conns;173 est->last_conns = k->conns;
175 est->last_inpkts = u->inpkts;174 est->last_inpkts = k->inpkts;
176 est->last_outpkts = u->outpkts;175 est->last_outpkts = k->outpkts;
177 est->cps = 0;176 est->cps = 0;
178 est->inpps = 0;177 est->inpps = 0;
179 est->outpps = 0;178 est->outpps = 0;
@@ -182,8 +181,7 @@ void ip_vs_zero_estimator(struct ip_vs_stats *stats) · 2 unmodified lines
182}181}
183 182
184/* Get decoded rates */183/* Get decoded rates */
185void ip_vs_read_estimator(struct ip_vs_stats_user *dst,184void ip_vs_read_estimator(struct ip_vs_kstats *dst, struct ip_vs_stats *stats)
186 struct ip_vs_stats *stats)
187{185{
188 struct ip_vs_estimator *e = &stats->est;186 struct ip_vs_estimator *e = &stats->est;
189 187

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t