aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-03-02 14:55:05 -0500
committerDavid S. Miller <davem@davemloft.net>2015-03-02 14:55:05 -0500
commit77f0379fa8823e5267509dfff83803a88bb297b0 (patch)
treea1d389e4de30436748236ad9b0f71c9fb016b11c
parent49b31e576a0a264872aa06dbc1ce6cd0cb9db278 (diff)
parent5f15893943bfdc804e8703c5aa2c8dd8bf7ddf3f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Pablo Neira Ayuso says: ==================== Netfilter updates for net-next A small batch with accumulated updates in nf-next, mostly IPVS updates, they are: 1) Add 64-bits stats counters to IPVS, from Julian Anastasov. 2) Move NETFILTER_XT_MATCH_ADDRTYPE out of NETFILTER_ADVANCED as docker seem to require this, from Anton Blanchard. 3) Use boolean instead of numeric value in set_match_v*(), from coccinelle via Fengguang Wu. 4) Allows rescheduling of new connections in IPVS when port reuse is detected, from Marcelo Ricardo Leitner. 5) Add missing bits to support arptables extensions from nft_compat, from Arturo Borrero. Patrick is preparing a large batch to enhance the set infrastructure, named expressions among other things, that should follow up soon after this batch. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/networking/ipvs-sysctl.txt21
-rw-r--r--include/net/ip_vs.h61
-rw-r--r--include/uapi/linux/ip_vs.h7
-rw-r--r--net/netfilter/Kconfig2
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c69
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c182
-rw-r--r--net/netfilter/ipvs/ip_vs_est.c102
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c21
-rw-r--r--net/netfilter/nft_compat.c9
-rw-r--r--net/netfilter/xt_set.c4
10 files changed, 326 insertions, 152 deletions
diff --git a/Documentation/networking/ipvs-sysctl.txt b/Documentation/networking/ipvs-sysctl.txt
index 7a3c04729591..3ba709531adb 100644
--- a/Documentation/networking/ipvs-sysctl.txt
+++ b/Documentation/networking/ipvs-sysctl.txt
@@ -22,6 +22,27 @@ backup_only - BOOLEAN
22 If set, disable the director function while the server is 22 If set, disable the director function while the server is
23 in backup mode to avoid packet loops for DR/TUN methods. 23 in backup mode to avoid packet loops for DR/TUN methods.
24 24
25conn_reuse_mode - INTEGER
26 1 - default
27
28 Controls how ipvs will deal with connections that are detected
29 port reuse. It is a bitmap, with the values being:
30
31 0: disable any special handling on port reuse. The new
32 connection will be delivered to the same real server that was
33 servicing the previous connection. This will effectively
34 disable expire_nodest_conn.
35
36 bit 1: enable rescheduling of new connections when it is safe.
37 That is, whenever expire_nodest_conn and for TCP sockets, when
38 the connection is in TIME_WAIT state (which is only possible if
39 you use NAT mode).
40
41 bit 2: it is bit 1 plus, for TCP connections, when connections
42 are in FIN_WAIT state, as this is the last state seen by load
43 balancer in Direct Routing mode. This bit helps on adding new
44 real servers to a very busy cluster.
45
25conntrack - BOOLEAN 46conntrack - BOOLEAN
26 0 - disabled (default) 47 0 - disabled (default)
27 not 0 - enabled 48 not 0 - enabled
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 615b20b58545..20fd23398537 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -365,15 +365,15 @@ struct ip_vs_seq {
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 {
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;
@@ -924,6 +941,7 @@ struct netns_ipvs {
924 int sysctl_nat_icmp_send; 941 int sysctl_nat_icmp_send;
925 int sysctl_pmtu_disc; 942 int sysctl_pmtu_disc;
926 int sysctl_backup_only; 943 int sysctl_backup_only;
944 int sysctl_conn_reuse_mode;
927 945
928 /* ip_vs_lblc */ 946 /* ip_vs_lblc */
929 int sysctl_lblc_expiration; 947 int sysctl_lblc_expiration;
@@ -1042,6 +1060,11 @@ static inline int sysctl_backup_only(struct netns_ipvs *ipvs)
1042 ipvs->sysctl_backup_only; 1060 ipvs->sysctl_backup_only;
1043} 1061}
1044 1062
1063static inline int sysctl_conn_reuse_mode(struct netns_ipvs *ipvs)
1064{
1065 return ipvs->sysctl_conn_reuse_mode;
1066}
1067
1045#else 1068#else
1046 1069
1047static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs) 1070static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs)
@@ -1109,6 +1132,11 @@ static inline int sysctl_backup_only(struct netns_ipvs *ipvs)
1109 return 0; 1132 return 0;
1110} 1133}
1111 1134
1135static inline int sysctl_conn_reuse_mode(struct netns_ipvs *ipvs)
1136{
1137 return 1;
1138}
1139
1112#endif 1140#endif
1113 1141
1114/* IPVS core functions 1142/* IPVS core functions
@@ -1388,8 +1416,7 @@ void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp, int pkts);
1388void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats); 1416void 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); 1417void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats);
1390void ip_vs_zero_estimator(struct ip_vs_stats *stats); 1418void ip_vs_zero_estimator(struct ip_vs_stats *stats);
1391void ip_vs_read_estimator(struct ip_vs_stats_user *dst, 1419void ip_vs_read_estimator(struct ip_vs_kstats *dst, struct ip_vs_stats *stats);
1392 struct ip_vs_stats *stats);
1393 1420
1394/* Various IPVS packet transmitters (from ip_vs_xmit.c) */ 1421/* Various IPVS packet transmitters (from ip_vs_xmit.c) */
1395int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, 1422int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
diff --git a/include/uapi/linux/ip_vs.h b/include/uapi/linux/ip_vs.h
index cabe95d5b461..3199243f2028 100644
--- a/include/uapi/linux/ip_vs.h
+++ b/include/uapi/linux/ip_vs.h
@@ -358,6 +358,8 @@ enum {
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 {
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 {
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 */
415enum { 420enum {
416 IPVS_STATS_ATTR_UNSPEC = 0, 421 IPVS_STATS_ATTR_UNSPEC = 0,
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index b02660fa9eb0..c68c3b441381 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -951,7 +951,7 @@ comment "Xtables matches"
951 951
952config NETFILTER_XT_MATCH_ADDRTYPE 952config NETFILTER_XT_MATCH_ADDRTYPE
953 tristate '"addrtype" address type match support' 953 tristate '"addrtype" address type match support'
954 depends on NETFILTER_ADVANCED 954 default m if NETFILTER_ADVANCED=n
955 ---help--- 955 ---help---
956 This option allows you to match what routing thinks of an address, 956 This option allows you to match what routing thinks of an address,
957 eg. UNICAST, LOCAL, BROADCAST, ... 957 eg. UNICAST, LOCAL, BROADCAST, ...
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index b87ca32efa0b..04dbd9c7213f 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -119,24 +119,24 @@ ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
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)
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)
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
@@ -1046,6 +1052,26 @@ static inline bool is_new_conn(const struct sk_buff *skb,
1046 } 1052 }
1047} 1053}
1048 1054
1055static inline bool is_new_conn_expected(const struct ip_vs_conn *cp,
1056 int conn_reuse_mode)
1057{
1058 /* Controlled (FTP DATA or persistence)? */
1059 if (cp->control)
1060 return false;
1061
1062 switch (cp->protocol) {
1063 case IPPROTO_TCP:
1064 return (cp->state == IP_VS_TCP_S_TIME_WAIT) ||
1065 ((conn_reuse_mode & 2) &&
1066 (cp->state == IP_VS_TCP_S_FIN_WAIT) &&
1067 (cp->flags & IP_VS_CONN_F_NOOUTPUT));
1068 case IPPROTO_SCTP:
1069 return cp->state == IP_VS_SCTP_S_CLOSED;
1070 default:
1071 return false;
1072 }
1073}
1074
1049/* Handle response packets: rewrite addresses and send away... 1075/* Handle response packets: rewrite addresses and send away...
1050 */ 1076 */
1051static unsigned int 1077static unsigned int
@@ -1585,6 +1611,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
1585 struct ip_vs_conn *cp; 1611 struct ip_vs_conn *cp;
1586 int ret, pkts; 1612 int ret, pkts;
1587 struct netns_ipvs *ipvs; 1613 struct netns_ipvs *ipvs;
1614 int conn_reuse_mode;
1588 1615
1589 /* Already marked as IPVS request or reply? */ 1616 /* Already marked as IPVS request or reply? */
1590 if (skb->ipvs_property) 1617 if (skb->ipvs_property)
@@ -1653,10 +1680,14 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
1653 */ 1680 */
1654 cp = pp->conn_in_get(af, skb, &iph, 0); 1681 cp = pp->conn_in_get(af, skb, &iph, 0);
1655 1682
1656 if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp && cp->dest && 1683 conn_reuse_mode = sysctl_conn_reuse_mode(ipvs);
1657 unlikely(!atomic_read(&cp->dest->weight)) && !iph.fragoffs && 1684 if (conn_reuse_mode && !iph.fragoffs &&
1658 is_new_conn(skb, &iph)) { 1685 is_new_conn(skb, &iph) && cp &&
1659 ip_vs_conn_expire_now(cp); 1686 ((unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest &&
1687 unlikely(!atomic_read(&cp->dest->weight))) ||
1688 unlikely(is_new_conn_expected(cp, conn_reuse_mode)))) {
1689 if (!atomic_read(&cp->n_control))
1690 ip_vs_conn_expire_now(cp);
1660 __ip_vs_conn_put(cp); 1691 __ip_vs_conn_put(cp);
1661 cp = NULL; 1692 cp = NULL;
1662 } 1693 }
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index e55759056361..76cc9ffd87fa 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -729,9 +729,9 @@ static void ip_vs_trash_cleanup(struct net *net)
729} 729}
730 730
731static void 731static 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.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
@@ -747,13 +747,28 @@ ip_vs_copy_stats(struct ip_vs_stats_user *dst, struct ip_vs_stats *src)
747} 747}
748 748
749static void 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
764static void
750ip_vs_zero_stats(struct ip_vs_stats *stats) 765ip_vs_zero_stats(struct ip_vs_stats *stats)
751{ 766{
752 spin_lock_bh(&stats->lock); 767 spin_lock_bh(&stats->lock);
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);
@@ -1808,6 +1823,12 @@ static struct ctl_table vs_vars[] = {
1808 .mode = 0644, 1823 .mode = 0644,
1809 .proc_handler = proc_dointvec, 1824 .proc_handler = proc_dointvec,
1810 }, 1825 },
1826 {
1827 .procname = "conn_reuse_mode",
1828 .maxlen = sizeof(int),
1829 .mode = 0644,
1830 .proc_handler = proc_dointvec,
1831 },
1811#ifdef CONFIG_IP_VS_DEBUG 1832#ifdef CONFIG_IP_VS_DEBUG
1812 { 1833 {
1813 .procname = "debug_level", 1834 .procname = "debug_level",
@@ -2044,7 +2065,7 @@ static const struct file_operations ip_vs_info_fops = {
2044static int ip_vs_stats_show(struct seq_file *seq, void *v) 2065static int ip_vs_stats_show(struct seq_file *seq, void *v)
2045{ 2066{
2046 struct net *net = seq_file_single_net(seq); 2067 struct net *net = seq_file_single_net(seq);
2047 struct ip_vs_stats_user show; 2068 struct ip_vs_kstats show;
2048 2069
2049/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */ 2070/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
2050 seq_puts(seq, 2071 seq_puts(seq,
@@ -2053,17 +2074,22 @@ static int ip_vs_stats_show(struct seq_file *seq, void *v)
2053 " Conns Packets Packets Bytes Bytes\n"); 2074 " Conns Packets Packets Bytes Bytes\n");
2054 2075
2055 ip_vs_copy_stats(&show, &net_ipvs(net)->tot_stats); 2076 ip_vs_copy_stats(&show, &net_ipvs(net)->tot_stats);
2056 seq_printf(seq, "%8X %8X %8X %16LX %16LX\n\n", show.conns, 2077 seq_printf(seq, "%8LX %8LX %8LX %16LX %16LX\n\n",
2057 show.inpkts, show.outpkts, 2078 (unsigned long long)show.conns,
2058 (unsigned long long) show.inbytes, 2079 (unsigned long long)show.inpkts,
2059 (unsigned long long) show.outbytes); 2080 (unsigned long long)show.outpkts,
2060 2081 (unsigned long long)show.inbytes,
2061/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */ 2082 (unsigned long long)show.outbytes);
2083
2084/* 01234567 01234567 01234567 0123456701234567 0123456701234567*/
2062 seq_puts(seq, 2085 seq_puts(seq,
2063 " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n"); 2086 " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n");
2064 seq_printf(seq, "%8X %8X %8X %16X %16X\n", 2087 seq_printf(seq, "%8LX %8LX %8LX %16LX %16LX\n",
2065 show.cps, show.inpps, show.outpps, 2088 (unsigned long long)show.cps,
2066 show.inbps, show.outbps); 2089 (unsigned long long)show.inpps,
2090 (unsigned long long)show.outpps,
2091 (unsigned long long)show.inbps,
2092 (unsigned long long)show.outbps);
2067 2093
2068 return 0; 2094 return 0;
2069} 2095}
@@ -2086,7 +2112,7 @@ static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v)
2086 struct net *net = seq_file_single_net(seq); 2112 struct net *net = seq_file_single_net(seq);
2087 struct ip_vs_stats *tot_stats = &net_ipvs(net)->tot_stats; 2113 struct ip_vs_stats *tot_stats = &net_ipvs(net)->tot_stats;
2088 struct ip_vs_cpu_stats __percpu *cpustats = tot_stats->cpustats; 2114 struct ip_vs_cpu_stats __percpu *cpustats = tot_stats->cpustats;
2089 struct ip_vs_stats_user rates; 2115 struct ip_vs_kstats kstats;
2090 int i; 2116 int i;
2091 2117
2092/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */ 2118/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
@@ -2098,41 +2124,41 @@ static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v)
2098 for_each_possible_cpu(i) { 2124 for_each_possible_cpu(i) {
2099 struct ip_vs_cpu_stats *u = per_cpu_ptr(cpustats, i); 2125 struct ip_vs_cpu_stats *u = per_cpu_ptr(cpustats, i);
2100 unsigned int start; 2126 unsigned int start;
2101 __u64 inbytes, outbytes; 2127 u64 conns, inpkts, outpkts, inbytes, outbytes;
2102 2128
2103 do { 2129 do {
2104 start = u64_stats_fetch_begin_irq(&u->syncp); 2130 start = u64_stats_fetch_begin_irq(&u->syncp);
2105 inbytes = u->ustats.inbytes; 2131 conns = u->cnt.conns;
2106 outbytes = u->ustats.outbytes; 2132 inpkts = u->cnt.inpkts;
2133 outpkts = u->cnt.outpkts;
2134 inbytes = u->cnt.inbytes;
2135 outbytes = u->cnt.outbytes;
2107 } while (u64_stats_fetch_retry_irq(&u->syncp, start)); 2136 } while (u64_stats_fetch_retry_irq(&u->syncp, start));
2108 2137
2109 seq_printf(seq, "%3X %8X %8X %8X %16LX %16LX\n", 2138 seq_printf(seq, "%3X %8LX %8LX %8LX %16LX %16LX\n",
2110 i, u->ustats.conns, u->ustats.inpkts, 2139 i, (u64)conns, (u64)inpkts,
2111 u->ustats.outpkts, (__u64)inbytes, 2140 (u64)outpkts, (u64)inbytes,
2112 (__u64)outbytes); 2141 (u64)outbytes);
2113 } 2142 }
2114 2143
2115 spin_lock_bh(&tot_stats->lock); 2144 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 2145
2125 spin_unlock_bh(&tot_stats->lock); 2146 seq_printf(seq, " ~ %8LX %8LX %8LX %16LX %16LX\n\n",
2147 (unsigned long long)kstats.conns,
2148 (unsigned long long)kstats.inpkts,
2149 (unsigned long long)kstats.outpkts,
2150 (unsigned long long)kstats.inbytes,
2151 (unsigned long long)kstats.outbytes);
2126 2152
2127/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */ 2153/* ... 01234567 01234567 01234567 0123456701234567 0123456701234567 */
2128 seq_puts(seq, 2154 seq_puts(seq,
2129 " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n"); 2155 " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n");
2130 seq_printf(seq, " %8X %8X %8X %16X %16X\n", 2156 seq_printf(seq, " %8LX %8LX %8LX %16LX %16LX\n",
2131 rates.cps, 2157 kstats.cps,
2132 rates.inpps, 2158 kstats.inpps,
2133 rates.outpps, 2159 kstats.outpps,
2134 rates.inbps, 2160 kstats.inbps,
2135 rates.outbps); 2161 kstats.outbps);
2136 2162
2137 return 0; 2163 return 0;
2138} 2164}
@@ -2400,6 +2426,7 @@ static void
2400ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src) 2426ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src)
2401{ 2427{
2402 struct ip_vs_scheduler *sched; 2428 struct ip_vs_scheduler *sched;
2429 struct ip_vs_kstats kstats;
2403 2430
2404 sched = rcu_dereference_protected(src->scheduler, 1); 2431 sched = rcu_dereference_protected(src->scheduler, 1);
2405 dst->protocol = src->protocol; 2432 dst->protocol = src->protocol;
@@ -2411,7 +2438,8 @@ ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src)
2411 dst->timeout = src->timeout / HZ; 2438 dst->timeout = src->timeout / HZ;
2412 dst->netmask = src->netmask; 2439 dst->netmask = src->netmask;
2413 dst->num_dests = src->num_dests; 2440 dst->num_dests = src->num_dests;
2414 ip_vs_copy_stats(&dst->stats, &src->stats); 2441 ip_vs_copy_stats(&kstats, &src->stats);
2442 ip_vs_export_stats_user(&dst->stats, &kstats);
2415} 2443}
2416 2444
2417static inline int 2445static inline int
@@ -2485,6 +2513,7 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get,
2485 int count = 0; 2513 int count = 0;
2486 struct ip_vs_dest *dest; 2514 struct ip_vs_dest *dest;
2487 struct ip_vs_dest_entry entry; 2515 struct ip_vs_dest_entry entry;
2516 struct ip_vs_kstats kstats;
2488 2517
2489 memset(&entry, 0, sizeof(entry)); 2518 memset(&entry, 0, sizeof(entry));
2490 list_for_each_entry(dest, &svc->destinations, n_list) { 2519 list_for_each_entry(dest, &svc->destinations, n_list) {
@@ -2506,7 +2535,8 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get,
2506 entry.activeconns = atomic_read(&dest->activeconns); 2535 entry.activeconns = atomic_read(&dest->activeconns);
2507 entry.inactconns = atomic_read(&dest->inactconns); 2536 entry.inactconns = atomic_read(&dest->inactconns);
2508 entry.persistconns = atomic_read(&dest->persistconns); 2537 entry.persistconns = atomic_read(&dest->persistconns);
2509 ip_vs_copy_stats(&entry.stats, &dest->stats); 2538 ip_vs_copy_stats(&kstats, &dest->stats);
2539 ip_vs_export_stats_user(&entry.stats, &kstats);
2510 if (copy_to_user(&uptr->entrytable[count], 2540 if (copy_to_user(&uptr->entrytable[count],
2511 &entry, sizeof(entry))) { 2541 &entry, sizeof(entry))) {
2512 ret = -EFAULT; 2542 ret = -EFAULT;
@@ -2798,25 +2828,51 @@ static const struct nla_policy ip_vs_dest_policy[IPVS_DEST_ATTR_MAX + 1] = {
2798}; 2828};
2799 2829
2800static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type, 2830static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type,
2801 struct ip_vs_stats *stats) 2831 struct ip_vs_kstats *kstats)
2802{ 2832{
2803 struct ip_vs_stats_user ustats;
2804 struct nlattr *nl_stats = nla_nest_start(skb, container_type); 2833 struct nlattr *nl_stats = nla_nest_start(skb, container_type);
2834
2805 if (!nl_stats) 2835 if (!nl_stats)
2806 return -EMSGSIZE; 2836 return -EMSGSIZE;
2807 2837
2808 ip_vs_copy_stats(&ustats, stats); 2838 if (nla_put_u32(skb, IPVS_STATS_ATTR_CONNS, (u32)kstats->conns) ||
2809 2839 nla_put_u32(skb, IPVS_STATS_ATTR_INPKTS, (u32)kstats->inpkts) ||
2810 if (nla_put_u32(skb, IPVS_STATS_ATTR_CONNS, ustats.conns) || 2840 nla_put_u32(skb, IPVS_STATS_ATTR_OUTPKTS, (u32)kstats->outpkts) ||
2811 nla_put_u32(skb, IPVS_STATS_ATTR_INPKTS, ustats.inpkts) || 2841 nla_put_u64(skb, IPVS_STATS_ATTR_INBYTES, kstats->inbytes) ||
2812 nla_put_u32(skb, IPVS_STATS_ATTR_OUTPKTS, ustats.outpkts) || 2842 nla_put_u64(skb, IPVS_STATS_ATTR_OUTBYTES, kstats->outbytes) ||
2813 nla_put_u64(skb, IPVS_STATS_ATTR_INBYTES, ustats.inbytes) || 2843 nla_put_u32(skb, IPVS_STATS_ATTR_CPS, (u32)kstats->cps) ||
2814 nla_put_u64(skb, IPVS_STATS_ATTR_OUTBYTES, ustats.outbytes) || 2844 nla_put_u32(skb, IPVS_STATS_ATTR_INPPS, (u32)kstats->inpps) ||
2815 nla_put_u32(skb, IPVS_STATS_ATTR_CPS, ustats.cps) || 2845 nla_put_u32(skb, IPVS_STATS_ATTR_OUTPPS, (u32)kstats->outpps) ||
2816 nla_put_u32(skb, IPVS_STATS_ATTR_INPPS, ustats.inpps) || 2846 nla_put_u32(skb, IPVS_STATS_ATTR_INBPS, (u32)kstats->inbps) ||
2817 nla_put_u32(skb, IPVS_STATS_ATTR_OUTPPS, ustats.outpps) || 2847 nla_put_u32(skb, IPVS_STATS_ATTR_OUTBPS, (u32)kstats->outbps))
2818 nla_put_u32(skb, IPVS_STATS_ATTR_INBPS, ustats.inbps) || 2848 goto nla_put_failure;
2819 nla_put_u32(skb, IPVS_STATS_ATTR_OUTBPS, ustats.outbps)) 2849 nla_nest_end(skb, nl_stats);
2850
2851 return 0;
2852
2853nla_put_failure:
2854 nla_nest_cancel(skb, nl_stats);
2855 return -EMSGSIZE;
2856}
2857
2858static int ip_vs_genl_fill_stats64(struct sk_buff *skb, int container_type,
2859 struct ip_vs_kstats *kstats)
2860{
2861 struct nlattr *nl_stats = nla_nest_start(skb, container_type);
2862
2863 if (!nl_stats)
2864 return -EMSGSIZE;
2865
2866 if (nla_put_u64(skb, IPVS_STATS_ATTR_CONNS, kstats->conns) ||
2867 nla_put_u64(skb, IPVS_STATS_ATTR_INPKTS, kstats->inpkts) ||
2868 nla_put_u64(skb, IPVS_STATS_ATTR_OUTPKTS, kstats->outpkts) ||
2869 nla_put_u64(skb, IPVS_STATS_ATTR_INBYTES, kstats->inbytes) ||
2870 nla_put_u64(skb, IPVS_STATS_ATTR_OUTBYTES, kstats->outbytes) ||
2871 nla_put_u64(skb, IPVS_STATS_ATTR_CPS, kstats->cps) ||
2872 nla_put_u64(skb, IPVS_STATS_ATTR_INPPS, kstats->inpps) ||
2873 nla_put_u64(skb, IPVS_STATS_ATTR_OUTPPS, kstats->outpps) ||
2874 nla_put_u64(skb, IPVS_STATS_ATTR_INBPS, kstats->inbps) ||
2875 nla_put_u64(skb, IPVS_STATS_ATTR_OUTBPS, kstats->outbps))
2820 goto nla_put_failure; 2876 goto nla_put_failure;
2821 nla_nest_end(skb, nl_stats); 2877 nla_nest_end(skb, nl_stats);
2822 2878
@@ -2835,6 +2891,7 @@ static int ip_vs_genl_fill_service(struct sk_buff *skb,
2835 struct nlattr *nl_service; 2891 struct nlattr *nl_service;
2836 struct ip_vs_flags flags = { .flags = svc->flags, 2892 struct ip_vs_flags flags = { .flags = svc->flags,
2837 .mask = ~0 }; 2893 .mask = ~0 };
2894 struct ip_vs_kstats kstats;
2838 2895
2839 nl_service = nla_nest_start(skb, IPVS_CMD_ATTR_SERVICE); 2896 nl_service = nla_nest_start(skb, IPVS_CMD_ATTR_SERVICE);
2840 if (!nl_service) 2897 if (!nl_service)
@@ -2860,7 +2917,10 @@ static int ip_vs_genl_fill_service(struct sk_buff *skb,
2860 nla_put_u32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ) || 2917 nla_put_u32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ) ||
2861 nla_put_be32(skb, IPVS_SVC_ATTR_NETMASK, svc->netmask)) 2918 nla_put_be32(skb, IPVS_SVC_ATTR_NETMASK, svc->netmask))
2862 goto nla_put_failure; 2919 goto nla_put_failure;
2863 if (ip_vs_genl_fill_stats(skb, IPVS_SVC_ATTR_STATS, &svc->stats)) 2920 ip_vs_copy_stats(&kstats, &svc->stats);
2921 if (ip_vs_genl_fill_stats(skb, IPVS_SVC_ATTR_STATS, &kstats))
2922 goto nla_put_failure;
2923 if (ip_vs_genl_fill_stats64(skb, IPVS_SVC_ATTR_STATS64, &kstats))
2864 goto nla_put_failure; 2924 goto nla_put_failure;
2865 2925
2866 nla_nest_end(skb, nl_service); 2926 nla_nest_end(skb, nl_service);
@@ -3032,6 +3092,7 @@ static struct ip_vs_service *ip_vs_genl_find_service(struct net *net,
3032static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest) 3092static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest)
3033{ 3093{
3034 struct nlattr *nl_dest; 3094 struct nlattr *nl_dest;
3095 struct ip_vs_kstats kstats;
3035 3096
3036 nl_dest = nla_nest_start(skb, IPVS_CMD_ATTR_DEST); 3097 nl_dest = nla_nest_start(skb, IPVS_CMD_ATTR_DEST);
3037 if (!nl_dest) 3098 if (!nl_dest)
@@ -3054,7 +3115,10 @@ static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest)
3054 atomic_read(&dest->persistconns)) || 3115 atomic_read(&dest->persistconns)) ||
3055 nla_put_u16(skb, IPVS_DEST_ATTR_ADDR_FAMILY, dest->af)) 3116 nla_put_u16(skb, IPVS_DEST_ATTR_ADDR_FAMILY, dest->af))
3056 goto nla_put_failure; 3117 goto nla_put_failure;
3057 if (ip_vs_genl_fill_stats(skb, IPVS_DEST_ATTR_STATS, &dest->stats)) 3118 ip_vs_copy_stats(&kstats, &dest->stats);
3119 if (ip_vs_genl_fill_stats(skb, IPVS_DEST_ATTR_STATS, &kstats))
3120 goto nla_put_failure;
3121 if (ip_vs_genl_fill_stats64(skb, IPVS_DEST_ATTR_STATS64, &kstats))
3058 goto nla_put_failure; 3122 goto nla_put_failure;
3059 3123
3060 nla_nest_end(skb, nl_dest); 3124 nla_nest_end(skb, nl_dest);
@@ -3732,6 +3796,8 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net)
3732 ipvs->sysctl_pmtu_disc = 1; 3796 ipvs->sysctl_pmtu_disc = 1;
3733 tbl[idx++].data = &ipvs->sysctl_pmtu_disc; 3797 tbl[idx++].data = &ipvs->sysctl_pmtu_disc;
3734 tbl[idx++].data = &ipvs->sysctl_backup_only; 3798 tbl[idx++].data = &ipvs->sysctl_backup_only;
3799 ipvs->sysctl_conn_reuse_mode = 1;
3800 tbl[idx++].data = &ipvs->sysctl_conn_reuse_mode;
3735 3801
3736 3802
3737 ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl); 3803 ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl);
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c
index 1425e9a924c4..ef0eb0a8d552 100644
--- a/net/netfilter/ipvs/ip_vs_est.c
+++ b/net/netfilter/ipvs/ip_vs_est.c
@@ -45,17 +45,19 @@
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 */
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,
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)
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)
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)
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)
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
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index c47ffd7a0a70..f96229cdb6e1 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -845,10 +845,27 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param,
845 struct ip_vs_conn *cp; 845 struct ip_vs_conn *cp;
846 struct netns_ipvs *ipvs = net_ipvs(net); 846 struct netns_ipvs *ipvs = net_ipvs(net);
847 847
848 if (!(flags & IP_VS_CONN_F_TEMPLATE)) 848 if (!(flags & IP_VS_CONN_F_TEMPLATE)) {
849 cp = ip_vs_conn_in_get(param); 849 cp = ip_vs_conn_in_get(param);
850 else 850 if (cp && ((cp->dport != dport) ||
851 !ip_vs_addr_equal(cp->daf, &cp->daddr, daddr))) {
852 if (!(flags & IP_VS_CONN_F_INACTIVE)) {
853 ip_vs_conn_expire_now(cp);
854 __ip_vs_conn_put(cp);
855 cp = NULL;
856 } else {
857 /* This is the expiration message for the
858 * connection that was already replaced, so we
859 * just ignore it.
860 */
861 __ip_vs_conn_put(cp);
862 kfree(param->pe_data);
863 return;
864 }
865 }
866 } else {
851 cp = ip_vs_ct_in_get(param); 867 cp = ip_vs_ct_in_get(param);
868 }
852 869
853 if (cp) { 870 if (cp) {
854 /* Free pe_data */ 871 /* Free pe_data */
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index c598f74063a1..a990df2f3f71 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -20,6 +20,7 @@
20#include <linux/netfilter_ipv4/ip_tables.h> 20#include <linux/netfilter_ipv4/ip_tables.h>
21#include <linux/netfilter_ipv6/ip6_tables.h> 21#include <linux/netfilter_ipv6/ip6_tables.h>
22#include <linux/netfilter_bridge/ebtables.h> 22#include <linux/netfilter_bridge/ebtables.h>
23#include <linux/netfilter_arp/arp_tables.h>
23#include <net/netfilter/nf_tables.h> 24#include <net/netfilter/nf_tables.h>
24 25
25static int nft_compat_chain_validate_dependency(const char *tablename, 26static int nft_compat_chain_validate_dependency(const char *tablename,
@@ -42,6 +43,7 @@ union nft_entry {
42 struct ipt_entry e4; 43 struct ipt_entry e4;
43 struct ip6t_entry e6; 44 struct ip6t_entry e6;
44 struct ebt_entry ebt; 45 struct ebt_entry ebt;
46 struct arpt_entry arp;
45}; 47};
46 48
47static inline void 49static inline void
@@ -140,6 +142,8 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
140 entry->ebt.ethproto = proto; 142 entry->ebt.ethproto = proto;
141 entry->ebt.invflags = inv ? EBT_IPROTO : 0; 143 entry->ebt.invflags = inv ? EBT_IPROTO : 0;
142 break; 144 break;
145 case NFPROTO_ARP:
146 break;
143 } 147 }
144 par->entryinfo = entry; 148 par->entryinfo = entry;
145 par->target = target; 149 par->target = target;
@@ -351,6 +355,8 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
351 entry->ebt.ethproto = proto; 355 entry->ebt.ethproto = proto;
352 entry->ebt.invflags = inv ? EBT_IPROTO : 0; 356 entry->ebt.invflags = inv ? EBT_IPROTO : 0;
353 break; 357 break;
358 case NFPROTO_ARP:
359 break;
354 } 360 }
355 par->entryinfo = entry; 361 par->entryinfo = entry;
356 par->match = match; 362 par->match = match;
@@ -537,6 +543,9 @@ nfnl_compat_get(struct sock *nfnl, struct sk_buff *skb,
537 case NFPROTO_BRIDGE: 543 case NFPROTO_BRIDGE:
538 fmt = "ebt_%s"; 544 fmt = "ebt_%s";
539 break; 545 break;
546 case NFPROTO_ARP:
547 fmt = "arpt_%s";
548 break;
540 default: 549 default:
541 pr_err("nft_compat: unsupported protocol %d\n", 550 pr_err("nft_compat: unsupported protocol %d\n",
542 nfmsg->nfgen_family); 551 nfmsg->nfgen_family);
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c
index 0d47afea9682..89045982ec94 100644
--- a/net/netfilter/xt_set.c
+++ b/net/netfilter/xt_set.c
@@ -193,7 +193,7 @@ set_match_v3(const struct sk_buff *skb, struct xt_action_param *par)
193 return ret; 193 return ret;
194 194
195 if (!match_counter0(opt.ext.packets, &info->packets)) 195 if (!match_counter0(opt.ext.packets, &info->packets))
196 return 0; 196 return false;
197 return match_counter0(opt.ext.bytes, &info->bytes); 197 return match_counter0(opt.ext.bytes, &info->bytes);
198} 198}
199 199
@@ -239,7 +239,7 @@ set_match_v4(const struct sk_buff *skb, struct xt_action_param *par)
239 return ret; 239 return ret;
240 240
241 if (!match_counter(opt.ext.packets, &info->packets)) 241 if (!match_counter(opt.ext.packets, &info->packets))
242 return 0; 242 return false;
243 return match_counter(opt.ext.bytes, &info->bytes); 243 return match_counter(opt.ext.bytes, &info->bytes);
244} 244}
245 245