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
365365
366366 /* counters per cpu */
367367 struct ip_vs_counters {
368− __u32 conns; /* connections scheduled */
369− __u32 inpkts; /* incoming packets */
370− __u32 outpkts; /* outgoing packets */
368+ __u64 conns; /* connections scheduled */
369+ __u64 inpkts; /* incoming packets */
370+ __u64 outpkts; /* outgoing packets */
371371 __u64 inbytes; /* incoming bytes */
372372 __u64 outbytes; /* outgoing bytes */
373373 };
374374 /* Stats per cpu */
375375 struct ip_vs_cpu_stats {
376− struct ip_vs_counters ustats;
376+ struct ip_vs_counters cnt;
377377 struct u64_stats_sync syncp;
378378 };
379379
@@ -383,23 +383,40 @@ struct ip_vs_estimator { · 3 unmodified lines
383383
384384 u64 last_inbytes;
385385 u64 last_outbytes;
386− u32 last_conns;
387− u32 last_inpkts;
388− u32 last_outpkts;
389−
390− u32 cps;
391− u32 inpps;
392− u32 outpps;
393− u32 inbps;
394− u32 outbps;
386+ u64 last_conns;
387+ u64 last_inpkts;
388+ u64 last_outpkts;
389+
390+ u64 cps;
391+ u64 inpps;
392+ u64 outpps;
393+ u64 inbps;
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 */
395412 };
396413
397414 struct ip_vs_stats {
398− struct ip_vs_stats_user ustats; /* statistics */
415+ struct ip_vs_kstats kstats; /* kernel statistics */
399416 struct ip_vs_estimator est; /* estimator */
400417 struct ip_vs_cpu_stats __percpu *cpustats; /* per cpu counters */
401418 spinlock_t lock; /* spin lock */
402− struct ip_vs_stats_user ustats0; /* reset values */
419+ struct ip_vs_kstats kstats0; /* reset values */
403420 };
404421
405422 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
13881405 void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats);
13891406 void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats);
13901407 void ip_vs_zero_estimator(struct ip_vs_stats *stats);
1391−void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
1392− struct ip_vs_stats *stats);
1408+void ip_vs_read_estimator(struct ip_vs_kstats *dst, struct ip_vs_stats *stats);
13931409
13941410 /* Various IPVS packet transmitters (from ip_vs_xmit.c) */
13951411 int 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
358358
359359 IPVS_SVC_ATTR_PE_NAME, /* name of ct retriever */
360360
361+ IPVS_SVC_ATTR_STATS64, /* nested attribute for service stats */
362+
361363 __IPVS_SVC_ATTR_MAX,
362364 };
363365
@@ -387,6 +389,8 @@ enum { · 23 unmodified lines
387389
388390 IPVS_DEST_ATTR_ADDR_FAMILY, /* Address family of address */
389391
392+ IPVS_DEST_ATTR_STATS64, /* nested attribute for dest stats */
393+
390394 __IPVS_DEST_ATTR_MAX,
391395 };
392396
@@ -410,7 +414,8 @@ enum { · 17 unmodified lines
410414 /*
411415 * Attributes used to describe service or destination entry statistics
412416 *
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.
414419 */
415420 enum {
416421 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
119119 struct ip_vs_service *svc;
120120
121121 s = this_cpu_ptr(dest->stats.cpustats);
122− s->ustats.inpkts++;
123122 u64_stats_update_begin(&s->syncp);
124− s->ustats.inbytes += skb->len;
123+ s->cnt.inpkts++;
124+ s->cnt.inbytes += skb->len;
125125 u64_stats_update_end(&s->syncp);
126126
127127 rcu_read_lock();
128128 svc = rcu_dereference(dest->svc);
129129 s = this_cpu_ptr(svc->stats.cpustats);
130− s->ustats.inpkts++;
131130 u64_stats_update_begin(&s->syncp);
132− s->ustats.inbytes += skb->len;
131+ s->cnt.inpkts++;
132+ s->cnt.inbytes += skb->len;
133133 u64_stats_update_end(&s->syncp);
134134 rcu_read_unlock();
135135
136136 s = this_cpu_ptr(ipvs->tot_stats.cpustats);
137− s->ustats.inpkts++;
138137 u64_stats_update_begin(&s->syncp);
139− s->ustats.inbytes += skb->len;
138+ s->cnt.inpkts++;
139+ s->cnt.inbytes += skb->len;
140140 u64_stats_update_end(&s->syncp);
141141 }
142142 }
@@ -153,24 +153,24 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb) · 10 unmodified lines
153153 struct ip_vs_service *svc;
154154
155155 s = this_cpu_ptr(dest->stats.cpustats);
156− s->ustats.outpkts++;
157156 u64_stats_update_begin(&s->syncp);
158− s->ustats.outbytes += skb->len;
157+ s->cnt.outpkts++;
158+ s->cnt.outbytes += skb->len;
159159 u64_stats_update_end(&s->syncp);
160160
161161 rcu_read_lock();
162162 svc = rcu_dereference(dest->svc);
163163 s = this_cpu_ptr(svc->stats.cpustats);
164− s->ustats.outpkts++;
165164 u64_stats_update_begin(&s->syncp);
166− s->ustats.outbytes += skb->len;
165+ s->cnt.outpkts++;
166+ s->cnt.outbytes += skb->len;
167167 u64_stats_update_end(&s->syncp);
168168 rcu_read_unlock();
169169
170170 s = this_cpu_ptr(ipvs->tot_stats.cpustats);
171− s->ustats.outpkts++;
172171 u64_stats_update_begin(&s->syncp);
173− s->ustats.outbytes += skb->len;
172+ s->cnt.outpkts++;
173+ s->cnt.outbytes += skb->len;
174174 u64_stats_update_end(&s->syncp);
175175 }
176176 }
@@ -183,13 +183,19 @@ ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc) · 6 unmodified lines
183183 struct ip_vs_cpu_stats *s;
184184
185185 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);
187189
188190 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);
190194
191195 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);
193199 }
194200
195201
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
729729 }
730730
731731 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)
733733 {
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
735735
736736 spin_lock_bh(&src->lock);
737737
@@ -746,6 +746,21 @@ ip_vs_copy_stats(struct ip_vs_stats_user *dst, struct ip_vs_stats *src) · 8 unmodified lines
746746 spin_unlock_bh(&src->lock);
747747 }
748748
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+
749764 static void
750765 ip_vs_zero_stats(struct ip_vs_stats *stats)
751766 {
@@ -753,7 +768,7 @@ ip_vs_zero_stats(struct ip_vs_stats *stats) · 1 unmodified line
753768
754769 /* get current counters as zero point, rates are zeroed */
755770
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
757772
758773 IP_VS_ZERO_STATS_COUNTER(conns);
759774 IP_VS_ZERO_STATS_COUNTER(inpkts);
@@ -2044,7 +2059,7 @@ static const struct file_operations ip_vs_info_fops = { · 1284 unmodified lines
20442059 static int ip_vs_stats_show(struct seq_file *seq, void *v)
20452060 {
20462061 struct net *net = seq_file_single_net(seq);
2047− struct ip_vs_stats_user show;
2062+ struct ip_vs_kstats show;
20482063
20492064 /* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
20502065 seq_puts(seq,
@@ -2053,17 +2068,22 @@ static int ip_vs_stats_show(struct seq_file *seq, void *v) · 2 unmodified lines
20532068 " Conns Packets Packets Bytes Bytes\n");
20542069
20552070 ip_vs_copy_stats(&show, &net_ipvs(net)->tot_stats);
2056− seq_printf(seq, "%8X %8X %8X %16LX %16LX\n\n", show.conns,
2057− show.inpkts, show.outpkts,
2058− (unsigned long long) show.inbytes,
2059− (unsigned long long) show.outbytes);
2060−
2061−/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
2071+ seq_printf(seq, "%8LX %8LX %8LX %16LX %16LX\n\n",
2072+ (unsigned long long)show.conns,
2073+ (unsigned long long)show.inpkts,
2074+ (unsigned long long)show.outpkts,
2075+ (unsigned long long)show.inbytes,
2076+ (unsigned long long)show.outbytes);
2077+
2078+/* 01234567 01234567 01234567 0123456701234567 0123456701234567*/
20622079 seq_puts(seq,
2063− " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n");
2064− seq_printf(seq, "%8X %8X %8X %16X %16X\n",
2065− show.cps, show.inpps, show.outpps,
2066− show.inbps, show.outbps);
2080+ " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n");
2081+ seq_printf(seq, "%8LX %8LX %8LX %16LX %16LX\n",
2082+ (unsigned long long)show.cps,
2083+ (unsigned long long)show.inpps,
2084+ (unsigned long long)show.outpps,
2085+ (unsigned long long)show.inbps,
2086+ (unsigned long long)show.outbps);
20672087
20682088 return 0;
20692089 }
@@ -2086,7 +2106,7 @@ static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v) · 16 unmodified lines
20862106 struct net *net = seq_file_single_net(seq);
20872107 struct ip_vs_stats *tot_stats = &net_ipvs(net)->tot_stats;
20882108 struct ip_vs_cpu_stats __percpu *cpustats = tot_stats->cpustats;
2089− struct ip_vs_stats_user rates;
2109+ struct ip_vs_kstats kstats;
20902110 int i;
20912111
20922112 /* 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
20982118 for_each_possible_cpu(i) {
20992119 struct ip_vs_cpu_stats *u = per_cpu_ptr(cpustats, i);
21002120 unsigned int start;
2101− __u64 inbytes, outbytes;
2121+ u64 conns, inpkts, outpkts, inbytes, outbytes;
21022122
21032123 do {
21042124 start = u64_stats_fetch_begin_irq(&u->syncp);
2105− inbytes = u->ustats.inbytes;
2106− outbytes = u->ustats.outbytes;
2125+ conns = u->cnt.conns;
2126+ inpkts = u->cnt.inpkts;
2127+ outpkts = u->cnt.outpkts;
2128+ inbytes = u->cnt.inbytes;
2129+ outbytes = u->cnt.outbytes;
21072130 } while (u64_stats_fetch_retry_irq(&u->syncp, start));
21082131
2109− seq_printf(seq, "%3X %8X %8X %8X %16LX %16LX\n",
2110− i, u->ustats.conns, u->ustats.inpkts,
2111− u->ustats.outpkts, (__u64)inbytes,
2112− (__u64)outbytes);
2132+ seq_printf(seq, "%3X %8LX %8LX %8LX %16LX %16LX\n",
2133+ i, (u64)conns, (u64)inpkts,
2134+ (u64)outpkts, (u64)inbytes,
2135+ (u64)outbytes);
21132136 }
21142137
2115− spin_lock_bh(&tot_stats->lock);
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);
2138+ ip_vs_copy_stats(&kstats, tot_stats);
21242139
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);
21262146
2127−/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
2147+/* ... 01234567 01234567 01234567 0123456701234567 0123456701234567 */
21282148 seq_puts(seq,
2129− " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n");
2130− seq_printf(seq, " %8X %8X %8X %16X %16X\n",
2131− rates.cps,
2132− rates.inpps,
2133− rates.outpps,
2134− rates.inbps,
2135− rates.outbps);
2149+ " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n");
2150+ seq_printf(seq, " %8LX %8LX %8LX %16LX %16LX\n",
2151+ kstats.cps,
2152+ kstats.inpps,
2153+ kstats.outpps,
2154+ kstats.inbps,
2155+ kstats.outbps);
21362156
21372157 return 0;
21382158 }
@@ -2400,6 +2420,7 @@ static void · 261 unmodified lines
24002420 ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src)
24012421 {
24022422 struct ip_vs_scheduler *sched;
2423+ struct ip_vs_kstats kstats;
24032424
24042425 sched = rcu_dereference_protected(src->scheduler, 1);
24052426 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
24112432 dst->timeout = src->timeout / HZ;
24122433 dst->netmask = src->netmask;
24132434 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);
24152437 }
24162438
24172439 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
24852507 int count = 0;
24862508 struct ip_vs_dest *dest;
24872509 struct ip_vs_dest_entry entry;
2510+ struct ip_vs_kstats kstats;
24882511
24892512 memset(&entry, 0, sizeof(entry));
24902513 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
25062529 entry.activeconns = atomic_read(&dest->activeconns);
25072530 entry.inactconns = atomic_read(&dest->inactconns);
25082531 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);
25102534 if (copy_to_user(&uptr->entrytable[count],
25112535 &entry, sizeof(entry))) {
25122536 ret = -EFAULT;
@@ -2798,25 +2822,51 @@ static const struct nla_policy ip_vs_dest_policy[IPVS_DEST_ATTR_MAX + 1] = { · 285 unmodified lines
27982822 };
27992823
28002824 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)
28022854 {
2803− struct ip_vs_stats_user ustats;
28042855 struct nlattr *nl_stats = nla_nest_start(skb, container_type);
2856+
28052857 if (!nl_stats)
28062858 return -EMSGSIZE;
28072859
2808− ip_vs_copy_stats(&ustats, stats);
2809−
2810− if (nla_put_u32(skb, IPVS_STATS_ATTR_CONNS, ustats.conns) ||
2811− nla_put_u32(skb, IPVS_STATS_ATTR_INPKTS, ustats.inpkts) ||
2812− nla_put_u32(skb, IPVS_STATS_ATTR_OUTPKTS, ustats.outpkts) ||
2813− nla_put_u64(skb, IPVS_STATS_ATTR_INBYTES, ustats.inbytes) ||
2814− nla_put_u64(skb, IPVS_STATS_ATTR_OUTBYTES, ustats.outbytes) ||
2815− nla_put_u32(skb, IPVS_STATS_ATTR_CPS, ustats.cps) ||
2816− nla_put_u32(skb, IPVS_STATS_ATTR_INPPS, ustats.inpps) ||
2817− nla_put_u32(skb, IPVS_STATS_ATTR_OUTPPS, ustats.outpps) ||
2818− nla_put_u32(skb, IPVS_STATS_ATTR_INBPS, ustats.inbps) ||
2819− nla_put_u32(skb, IPVS_STATS_ATTR_OUTBPS, ustats.outbps))
2860+ if (nla_put_u64(skb, IPVS_STATS_ATTR_CONNS, kstats->conns) ||
2861+ nla_put_u64(skb, IPVS_STATS_ATTR_INPKTS, kstats->inpkts) ||
2862+ nla_put_u64(skb, IPVS_STATS_ATTR_OUTPKTS, kstats->outpkts) ||
2863+ nla_put_u64(skb, IPVS_STATS_ATTR_INBYTES, kstats->inbytes) ||
2864+ nla_put_u64(skb, IPVS_STATS_ATTR_OUTBYTES, kstats->outbytes) ||
2865+ nla_put_u64(skb, IPVS_STATS_ATTR_CPS, kstats->cps) ||
2866+ nla_put_u64(skb, IPVS_STATS_ATTR_INPPS, kstats->inpps) ||
2867+ nla_put_u64(skb, IPVS_STATS_ATTR_OUTPPS, kstats->outpps) ||
2868+ nla_put_u64(skb, IPVS_STATS_ATTR_INBPS, kstats->inbps) ||
2869+ nla_put_u64(skb, IPVS_STATS_ATTR_OUTBPS, kstats->outbps))
28202870 goto nla_put_failure;
28212871 nla_nest_end(skb, nl_stats);
28222872
@@ -2835,6 +2885,7 @@ static int ip_vs_genl_fill_service(struct sk_buff *skb, · 12 unmodified lines
28352885 struct nlattr *nl_service;
28362886 struct ip_vs_flags flags = { .flags = svc->flags,
28372887 .mask = ~0 };
2888+ struct ip_vs_kstats kstats;
28382889
28392890 nl_service = nla_nest_start(skb, IPVS_CMD_ATTR_SERVICE);
28402891 if (!nl_service)
@@ -2860,7 +2911,10 @@ static int ip_vs_genl_fill_service(struct sk_buff *skb, · 19 unmodified lines
28602911 nla_put_u32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ) ||
28612912 nla_put_be32(skb, IPVS_SVC_ATTR_NETMASK, svc->netmask))
28622913 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))
28642918 goto nla_put_failure;
28652919
28662920 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
30323086 static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest)
30333087 {
30343088 struct nlattr *nl_dest;
3089+ struct ip_vs_kstats kstats;
30353090
30363091 nl_dest = nla_nest_start(skb, IPVS_CMD_ATTR_DEST);
30373092 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
30543109 atomic_read(&dest->persistconns)) ||
30553110 nla_put_u16(skb, IPVS_DEST_ATTR_ADDR_FAMILY, dest->af))
30563111 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))
30583116 goto nla_put_failure;
30593117
30603118 nla_nest_end(skb, nl_dest);
net/netfilter/ipvs/ip_vs_est.c+50−52
@@ -45,17 +45,19 @@ · 44 unmodified lines
4545
4646 NOTES.
4747
48− * The stored value for average bps is scaled by 2^5, so that maximal
49− rate is ~2.15Gbits/s, average pps and cps are scaled by 2^10.
48+ * Average bps is scaled by 2^5, while average pps and cps are scaled by 2^10.
5049
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
5254 */
5355
5456
5557 /*
5658 * Make a summary from each cpu
5759 */
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,
5961 struct ip_vs_cpu_stats __percpu *stats)
6062 {
6163 int i;
@@ -64,27 +66,31 @@ static void ip_vs_read_cpu_stats(struct ip_vs_stats_user *sum, · 2 unmodified lines
6466 for_each_possible_cpu(i) {
6567 struct ip_vs_cpu_stats *s = per_cpu_ptr(stats, i);
6668 unsigned int start;
67− __u64 inbytes, outbytes;
69+ u64 conns, inpkts, outpkts, inbytes, outbytes;
70+
6871 if (add) {
69− sum->conns += s->ustats.conns;
70− sum->inpkts += s->ustats.inpkts;
71− sum->outpkts += s->ustats.outpkts;
7272 do {
7373 start = u64_stats_fetch_begin(&s->syncp);
74− inbytes = s->ustats.inbytes;
75− outbytes = s->ustats.outbytes;
74+ conns = s->cnt.conns;
75+ inpkts = s->cnt.inpkts;
76+ outpkts = s->cnt.outpkts;
77+ inbytes = s->cnt.inbytes;
78+ outbytes = s->cnt.outbytes;
7679 } while (u64_stats_fetch_retry(&s->syncp, start));
80+ sum->conns += conns;
81+ sum->inpkts += inpkts;
82+ sum->outpkts += outpkts;
7783 sum->inbytes += inbytes;
7884 sum->outbytes += outbytes;
7985 } else {
8086 add = true;
81− sum->conns = s->ustats.conns;
82− sum->inpkts = s->ustats.inpkts;
83− sum->outpkts = s->ustats.outpkts;
8487 do {
8588 start = u64_stats_fetch_begin(&s->syncp);
86− sum->inbytes = s->ustats.inbytes;
87− sum->outbytes = s->ustats.outbytes;
89+ sum->conns = s->cnt.conns;
90+ sum->inpkts = s->cnt.inpkts;
91+ sum->outpkts = s->cnt.outpkts;
92+ sum->inbytes = s->cnt.inbytes;
93+ sum->outbytes = s->cnt.outbytes;
8894 } while (u64_stats_fetch_retry(&s->syncp, start));
8995 }
9096 }
@@ -95,10 +101,7 @@ static void estimation_timer(unsigned long arg) · 4 unmodified lines
95101 {
96102 struct ip_vs_estimator *e;
97103 struct ip_vs_stats *s;
98− u32 n_conns;
99− u32 n_inpkts, n_outpkts;
100− u64 n_inbytes, n_outbytes;
101− u32 rate;
104+ u64 rate;
102105 struct net *net = (struct net *)arg;
103106 struct netns_ipvs *ipvs;
104107
@@ -108,33 +111,29 @@ static void estimation_timer(unsigned long arg) · 3 unmodified lines
108111 s = container_of(e, struct ip_vs_stats, est);
109112
110113 spin_lock(&s->lock);
111− ip_vs_read_cpu_stats(&s->ustats, 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;
114+ ip_vs_read_cpu_stats(&s->kstats, s->cpustats);
117115
118116 /* scaled by 2^10, but divided 2 seconds */
119− rate = (n_conns - e->last_conns) << 9;
120− e->last_conns = n_conns;
121− e->cps += ((long)rate - (long)e->cps) >> 2;
122−
123− rate = (n_inpkts - e->last_inpkts) << 9;
124− e->last_inpkts = n_inpkts;
125− e->inpps += ((long)rate - (long)e->inpps) >> 2;
126−
127− rate = (n_outpkts - e->last_outpkts) << 9;
128− e->last_outpkts = n_outpkts;
129− e->outpps += ((long)rate - (long)e->outpps) >> 2;
130−
131− rate = (n_inbytes - e->last_inbytes) << 4;
132− e->last_inbytes = n_inbytes;
133− e->inbps += ((long)rate - (long)e->inbps) >> 2;
134−
135− rate = (n_outbytes - e->last_outbytes) << 4;
136− e->last_outbytes = n_outbytes;
137− e->outbps += ((long)rate - (long)e->outbps) >> 2;
117+ rate = (s->kstats.conns - e->last_conns) << 9;
118+ e->last_conns = s->kstats.conns;
119+ e->cps += ((s64)rate - (s64)e->cps) >> 2;
120+
121+ rate = (s->kstats.inpkts - e->last_inpkts) << 9;
122+ e->last_inpkts = s->kstats.inpkts;
123+ e->inpps += ((s64)rate - (s64)e->inpps) >> 2;
124+
125+ rate = (s->kstats.outpkts - e->last_outpkts) << 9;
126+ e->last_outpkts = s->kstats.outpkts;
127+ e->outpps += ((s64)rate - (s64)e->outpps) >> 2;
128+
129+ /* scaled by 2^5, but divided 2 seconds */
130+ rate = (s->kstats.inbytes - e->last_inbytes) << 4;
131+ e->last_inbytes = s->kstats.inbytes;
132+ e->inbps += ((s64)rate - (s64)e->inbps) >> 2;
133+
134+ rate = (s->kstats.outbytes - e->last_outbytes) << 4;
135+ e->last_outbytes = s->kstats.outbytes;
136+ e->outbps += ((s64)rate - (s64)e->outbps) >> 2;
138137 spin_unlock(&s->lock);
139138 }
140139 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
166165 void ip_vs_zero_estimator(struct ip_vs_stats *stats)
167166 {
168167 struct ip_vs_estimator *est = &stats->est;
169− struct ip_vs_stats_user *u = &stats->ustats;
168+ struct ip_vs_kstats *k = &stats->kstats;
170169
171170 /* reset counters, caller must hold the stats->lock lock */
172− est->last_inbytes = u->inbytes;
173− est->last_outbytes = u->outbytes;
174− est->last_conns = u->conns;
175− est->last_inpkts = u->inpkts;
176− est->last_outpkts = u->outpkts;
171+ est->last_inbytes = k->inbytes;
172+ est->last_outbytes = k->outbytes;
173+ est->last_conns = k->conns;
174+ est->last_inpkts = k->inpkts;
175+ est->last_outpkts = k->outpkts;
177176 est->cps = 0;
178177 est->inpps = 0;
179178 est->outpps = 0;
@@ -182,8 +181,7 @@ void ip_vs_zero_estimator(struct ip_vs_stats *stats) · 2 unmodified lines
182181 }
183182
184183 /* Get decoded rates */
185−void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
186− struct ip_vs_stats *stats)
184+void ip_vs_read_estimator(struct ip_vs_kstats *dst, struct ip_vs_stats *stats)
187185 {
188186 struct ip_vs_estimator *e = &stats->est;
189187

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