mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 13:23:02 -04:00
ipvs: add totalconns for dest
Replace the inactconns dest counter with totalconns, now
inactconns can be obtained from totalconns - activeconns.
This reduces the atomic inc/dec ops for TCP/SCTP from
6 to 4 if the connection is established and then closed.
Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
committed by
Pablo Neira Ayuso
parent
d45cc8020d
commit
04d2feaed8
@@ -987,7 +987,7 @@ struct ip_vs_dest {
|
||||
|
||||
/* connection counters and thresholds */
|
||||
atomic_t activeconns; /* active connections */
|
||||
atomic_t inactconns; /* inactive connections */
|
||||
atomic_t totalconns; /* total connections */
|
||||
atomic_t persistconns; /* persistent connections */
|
||||
__u32 u_threshold; /* upper threshold */
|
||||
__u32 l_threshold; /* lower threshold */
|
||||
@@ -2220,14 +2220,21 @@ void ip_vs_unregister_hooks(struct netns_ipvs *ipvs, unsigned int af);
|
||||
static inline int
|
||||
ip_vs_dest_conn_overhead(struct ip_vs_dest *dest)
|
||||
{
|
||||
/* We think the overhead of processing active connections is 256
|
||||
/* We think the overhead of processing active connections is 257
|
||||
* times higher than that of inactive connections in average. (This
|
||||
* 256 times might not be accurate, we will change it later) We
|
||||
* 257 times might not be accurate, we will change it later) We
|
||||
* use the following formula to estimate the overhead now:
|
||||
* dest->activeconns*256 + dest->inactconns
|
||||
* dest->activeconns*256 + dest->totalconns
|
||||
*/
|
||||
return (atomic_read(&dest->activeconns) << 8) +
|
||||
atomic_read(&dest->inactconns);
|
||||
atomic_read(&dest->totalconns);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ip_vs_dest_inactconns(const struct ip_vs_dest *dest)
|
||||
{
|
||||
return max(atomic_read(&dest->totalconns) -
|
||||
atomic_read(&dest->activeconns), 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IP_VS_PROTO_TCP
|
||||
|
||||
@@ -1081,12 +1081,6 @@ static inline void ip_vs_bind_xmit_v6(struct ip_vs_conn *cp)
|
||||
#endif
|
||||
|
||||
|
||||
static inline int ip_vs_dest_totalconns(struct ip_vs_dest *dest)
|
||||
{
|
||||
return atomic_read(&dest->activeconns)
|
||||
+ atomic_read(&dest->inactconns);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bind a connection entry with a virtual service destination
|
||||
* Called just after a new connection entry is created.
|
||||
@@ -1153,8 +1147,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)
|
||||
*/
|
||||
if (!(flags & IP_VS_CONN_F_INACTIVE))
|
||||
atomic_inc(&dest->activeconns);
|
||||
else
|
||||
atomic_inc(&dest->inactconns);
|
||||
atomic_inc(&dest->totalconns);
|
||||
} else {
|
||||
/* It is a persistent connection/template, so increase
|
||||
the persistent connection counter */
|
||||
@@ -1162,7 +1155,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)
|
||||
}
|
||||
|
||||
if (dest->u_threshold != 0 &&
|
||||
ip_vs_dest_totalconns(dest) >= dest->u_threshold)
|
||||
atomic_read(&dest->totalconns) >= dest->u_threshold)
|
||||
dest->flags |= IP_VS_DEST_F_OVERLOAD;
|
||||
}
|
||||
|
||||
@@ -1244,13 +1237,10 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp)
|
||||
|
||||
/* Update the connection counters */
|
||||
if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) {
|
||||
/* It is a normal connection, so decrease the inactconns
|
||||
or activeconns counter */
|
||||
if (cp->flags & IP_VS_CONN_F_INACTIVE) {
|
||||
atomic_dec(&dest->inactconns);
|
||||
} else {
|
||||
/* It is a normal connection, so decrease the counters */
|
||||
if (!(cp->flags & IP_VS_CONN_F_INACTIVE))
|
||||
atomic_dec(&dest->activeconns);
|
||||
}
|
||||
atomic_dec(&dest->totalconns);
|
||||
} else {
|
||||
/* It is a persistent connection/template, so decrease
|
||||
the persistent connection counter */
|
||||
@@ -1258,10 +1248,10 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp)
|
||||
}
|
||||
|
||||
if (dest->l_threshold != 0) {
|
||||
if (ip_vs_dest_totalconns(dest) < dest->l_threshold)
|
||||
if (atomic_read(&dest->totalconns) < dest->l_threshold)
|
||||
dest->flags &= ~IP_VS_DEST_F_OVERLOAD;
|
||||
} else if (dest->u_threshold != 0) {
|
||||
if (ip_vs_dest_totalconns(dest) * 4 < dest->u_threshold * 3)
|
||||
if (atomic_read(&dest->totalconns) * 4 < dest->u_threshold * 3)
|
||||
dest->flags &= ~IP_VS_DEST_F_OVERLOAD;
|
||||
} else {
|
||||
if (dest->flags & IP_VS_DEST_F_OVERLOAD)
|
||||
|
||||
@@ -1445,7 +1445,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
|
||||
dest->port = udest->port;
|
||||
|
||||
atomic_set(&dest->activeconns, 0);
|
||||
atomic_set(&dest->inactconns, 0);
|
||||
atomic_set(&dest->totalconns, 0);
|
||||
atomic_set(&dest->persistconns, 0);
|
||||
refcount_set(&dest->refcnt, 1);
|
||||
|
||||
@@ -3031,7 +3031,7 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v)
|
||||
ip_vs_fwd_name(atomic_read(&dest->conn_flags)),
|
||||
atomic_read(&dest->weight),
|
||||
atomic_read(&dest->activeconns),
|
||||
atomic_read(&dest->inactconns));
|
||||
ip_vs_dest_inactconns(dest));
|
||||
else
|
||||
#endif
|
||||
seq_printf(seq,
|
||||
@@ -3042,7 +3042,7 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v)
|
||||
ip_vs_fwd_name(atomic_read(&dest->conn_flags)),
|
||||
atomic_read(&dest->weight),
|
||||
atomic_read(&dest->activeconns),
|
||||
atomic_read(&dest->inactconns));
|
||||
ip_vs_dest_inactconns(dest));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3670,7 +3670,7 @@ __ip_vs_get_dest_entries(struct netns_ipvs *ipvs, const struct ip_vs_get_dests *
|
||||
entry.u_threshold = dest->u_threshold;
|
||||
entry.l_threshold = dest->l_threshold;
|
||||
entry.activeconns = atomic_read(&dest->activeconns);
|
||||
entry.inactconns = atomic_read(&dest->inactconns);
|
||||
entry.inactconns = ip_vs_dest_inactconns(dest);
|
||||
entry.persistconns = atomic_read(&dest->persistconns);
|
||||
ip_vs_copy_stats(&kstats, &dest->stats);
|
||||
ip_vs_export_stats_user(&entry.stats, &kstats);
|
||||
@@ -4282,7 +4282,7 @@ static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest)
|
||||
nla_put_u32(skb, IPVS_DEST_ATTR_ACTIVE_CONNS,
|
||||
atomic_read(&dest->activeconns)) ||
|
||||
nla_put_u32(skb, IPVS_DEST_ATTR_INACT_CONNS,
|
||||
atomic_read(&dest->inactconns)) ||
|
||||
ip_vs_dest_inactconns(dest)) ||
|
||||
nla_put_u32(skb, IPVS_DEST_ATTR_PERSIST_CONNS,
|
||||
atomic_read(&dest->persistconns)) ||
|
||||
nla_put_u16(skb, IPVS_DEST_ATTR_ADDR_FAMILY, dest->af))
|
||||
|
||||
@@ -30,7 +30,7 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
|
||||
|
||||
/*
|
||||
* Simply select the server with the least number of
|
||||
* (activeconns<<5) + inactconns
|
||||
* (activeconns*256) + totalconns
|
||||
* Except whose weight is equal to zero.
|
||||
* If the weight is equal to zero, it means that the server is
|
||||
* quiesced, the existing connections to the server still get
|
||||
@@ -56,7 +56,7 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
|
||||
IP_VS_DBG_ADDR(least->af, &least->addr),
|
||||
ntohs(least->port),
|
||||
atomic_read(&least->activeconns),
|
||||
atomic_read(&least->inactconns));
|
||||
ip_vs_dest_inactconns(least));
|
||||
|
||||
return least;
|
||||
}
|
||||
|
||||
@@ -446,12 +446,10 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
|
||||
if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
|
||||
(next_state != IP_VS_SCTP_S_ESTABLISHED)) {
|
||||
atomic_dec(&dest->activeconns);
|
||||
atomic_inc(&dest->inactconns);
|
||||
cp->flags |= IP_VS_CONN_F_INACTIVE;
|
||||
} else if ((cp->flags & IP_VS_CONN_F_INACTIVE) &&
|
||||
(next_state == IP_VS_SCTP_S_ESTABLISHED)) {
|
||||
atomic_inc(&dest->activeconns);
|
||||
atomic_dec(&dest->inactconns);
|
||||
cp->flags &= ~IP_VS_CONN_F_INACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,12 +526,10 @@ set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
|
||||
if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
|
||||
!tcp_state_active(new_state)) {
|
||||
atomic_dec(&dest->activeconns);
|
||||
atomic_inc(&dest->inactconns);
|
||||
cp->flags |= IP_VS_CONN_F_INACTIVE;
|
||||
} else if ((cp->flags & IP_VS_CONN_F_INACTIVE) &&
|
||||
tcp_state_active(new_state)) {
|
||||
atomic_inc(&dest->activeconns);
|
||||
atomic_dec(&dest->inactconns);
|
||||
cp->flags &= ~IP_VS_CONN_F_INACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -878,13 +878,10 @@ static void ip_vs_proc_conn(struct netns_ipvs *ipvs, struct ip_vs_conn_param *pa
|
||||
spin_lock_bh(&cp->lock);
|
||||
if ((cp->flags ^ flags) & IP_VS_CONN_F_INACTIVE &&
|
||||
!(flags & IP_VS_CONN_F_TEMPLATE) && dest) {
|
||||
if (flags & IP_VS_CONN_F_INACTIVE) {
|
||||
if (flags & IP_VS_CONN_F_INACTIVE)
|
||||
atomic_dec(&dest->activeconns);
|
||||
atomic_inc(&dest->inactconns);
|
||||
} else {
|
||||
else
|
||||
atomic_inc(&dest->activeconns);
|
||||
atomic_dec(&dest->inactconns);
|
||||
}
|
||||
}
|
||||
flags &= IP_VS_CONN_F_BACKUP_UPD_MASK;
|
||||
flags |= cp->flags & ~IP_VS_CONN_F_BACKUP_UPD_MASK;
|
||||
|
||||
Reference in New Issue
Block a user