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
Unified · Split
| @@ -365,15 +365,15 @@ struct ip_vs_seq { · 364 unmodified lines | |||
| 365 | 365 | ||
| 366 | /* counters per cpu */ | 366 | /* counters per cpu */ |
| 367 | struct ip_vs_counters { | 367 | struct 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 */ |
| 375 | struct ip_vs_cpu_stats { | 375 | struct 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 | */ | ||
| 400 | struct 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 | ||
| 397 | struct ip_vs_stats { | 414 | struct 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 | ||
| 405 | struct dst_entry; | 422 | struct dst_entry; |
| @@ -1388,8 +1405,7 @@ void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp, int pkts); · 982 unmodified lines | |||
| 1388 | void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats); | 1405 | void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats); |
| 1389 | void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats); | 1406 | void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats); |
| 1390 | void ip_vs_zero_estimator(struct ip_vs_stats *stats); | 1407 | void ip_vs_zero_estimator(struct ip_vs_stats *stats); |
| 1391 | void ip_vs_read_estimator(struct ip_vs_stats_user *dst, | 1408 | void 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) */ |
| 1395 | int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | 1411 | int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, |
| @@ -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 statistics | 415 | * Attributes used to describe service or destination entry statistics |
| 412 | * | 416 | * |
| 413 | * Used inside nested attributes IPVS_SVC_ATTR_STATS and IPVS_DEST_ATTR_STATS | 417 | * Used inside nested attributes IPVS_SVC_ATTR_STATS, IPVS_DEST_ATTR_STATS, |
| 418 | * IPVS_SVC_ATTR_STATS64 and IPVS_DEST_ATTR_STATS64. | ||
| 414 | */ | 419 | */ |
| 415 | enum { | 420 | enum { |
| 416 | IPVS_STATS_ATTR_UNSPEC = 0, | 421 | IPVS_STATS_ATTR_UNSPEC = 0, |
| @@ -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 | ||
| @@ -729,9 +729,9 @@ static void ip_vs_trash_cleanup(struct net *net) · 728 unmodified lines | |||
| 729 | } | 729 | } |
| 730 | 730 | ||
| 731 | static void | 731 | static void |
| 732 | ip_vs_copy_stats(struct ip_vs_stats_user *dst, struct ip_vs_stats *src) | 732 | ip_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.c | 734 | #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 | ||
| 749 | static void | ||
| 750 | ip_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 | |||
| 749 | static void | 764 | static void |
| 750 | ip_vs_zero_stats(struct ip_vs_stats *stats) | 765 | ip_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.c | 771 | #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 | |||
| 2044 | static int ip_vs_stats_show(struct seq_file *seq, void *v) | 2059 | static 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 | |||
| 2400 | ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src) | 2420 | ip_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 | ||
| 2417 | static inline int | 2439 | static 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 | ||
| 2800 | static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type, | 2824 | static 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 | |||
| 2847 | nla_put_failure: | ||
| 2848 | nla_nest_cancel(skb, nl_stats); | ||
| 2849 | return -EMSGSIZE; | ||
| 2850 | } | ||
| 2851 | |||
| 2852 | static 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 | |||
| 3032 | static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest) | 3086 | static 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); |
| @@ -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 maximal | 48 | * 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.c | 50 | * 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 cpu | 58 | * Make a summary from each cpu |
| 57 | */ | 59 | */ |
| 58 | static void ip_vs_read_cpu_stats(struct ip_vs_stats_user *sum, | 60 | static 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 | |||
| 166 | void ip_vs_zero_estimator(struct ip_vs_stats *stats) | 165 | void 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 */ |
| 185 | void ip_vs_read_estimator(struct ip_vs_stats_user *dst, | 184 | void 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 | ||