diff options
-rw-r--r-- | include/linux/ip_vs.h | 3 | ||||
-rw-r--r-- | include/net/ip_vs.h | 1 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_conn.c | 3 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 3 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_proto_tcp.c | 10 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_sync.c | 4 |
6 files changed, 22 insertions, 2 deletions
diff --git a/include/linux/ip_vs.h b/include/linux/ip_vs.h index 9708de265bb1..4fe656575073 100644 --- a/include/linux/ip_vs.h +++ b/include/linux/ip_vs.h @@ -87,6 +87,7 @@ #define IP_VS_CONN_F_NO_CPORT 0x0800 /* no client port set yet */ #define IP_VS_CONN_F_TEMPLATE 0x1000 /* template, not connection */ #define IP_VS_CONN_F_ONE_PACKET 0x2000 /* forward only one packet */ +#define IP_VS_CONN_F_BACKLOG 0x4000 /* backlog connection */ #define IP_VS_SCHEDNAME_MAXLEN 16 #define IP_VS_IFNAME_MAXLEN 16 @@ -350,6 +351,8 @@ enum { IPVS_DEST_ATTR_PERSIST_CONNS, /* persistent connections */ IPVS_DEST_ATTR_STATS, /* nested attribute for dest stats */ + + IPVS_DEST_ATTR_BACKLOG_CONNS, /* backlog connections */ __IPVS_DEST_ATTR_MAX, }; diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index a4747a0f7303..c39dee674e35 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -499,6 +499,7 @@ struct ip_vs_dest { /* connection counters and thresholds */ atomic_t activeconns; /* active connections */ atomic_t inactconns; /* inactive connections */ + atomic_t backlogconns; /* backlog connections */ atomic_t persistconns; /* persistent connections */ __u32 u_threshold; /* upper threshold */ __u32 l_threshold; /* lower threshold */ diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index b71c69a2db13..486dd489d9cc 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -607,6 +607,9 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp) } else { atomic_dec(&dest->activeconns); } + + if (cp->flags & IP_VS_CONN_F_BACKLOG) + atomic_dec(&dest->backlogconns); } else { /* It is a persistent connection/template, so decrease the peristent connection counter */ diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 0f0c079c422a..1933e60067d9 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2579,6 +2579,7 @@ static const struct nla_policy ip_vs_dest_policy[IPVS_DEST_ATTR_MAX + 1] = { [IPVS_DEST_ATTR_INACT_CONNS] = { .type = NLA_U32 }, [IPVS_DEST_ATTR_PERSIST_CONNS] = { .type = NLA_U32 }, [IPVS_DEST_ATTR_STATS] = { .type = NLA_NESTED }, + [IPVS_DEST_ATTR_BACKLOG_CONNS] = { .type = NLA_U32 }, }; static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type, @@ -2826,6 +2827,8 @@ static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest) atomic_read(&dest->activeconns)); NLA_PUT_U32(skb, IPVS_DEST_ATTR_INACT_CONNS, atomic_read(&dest->inactconns)); + NLA_PUT_U32(skb, IPVS_DEST_ATTR_BACKLOG_CONNS, + atomic_read(&dest->backlogconns)); NLA_PUT_U32(skb, IPVS_DEST_ATTR_PERSIST_CONNS, atomic_read(&dest->persistconns)); diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c index 282d24de8592..c92cbab6d6c0 100644 --- a/net/netfilter/ipvs/ip_vs_proto_tcp.c +++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c @@ -510,6 +510,16 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp, atomic_dec(&dest->inactconns); cp->flags &= ~IP_VS_CONN_F_INACTIVE; } + + if (new_state == IP_VS_TCP_S_SYN_RECV && + !(cp->flags & IP_VS_CONN_F_BACKLOG)) { + atomic_inc(&dest->backlogconns); + cp->flags |= IP_VS_CONN_F_BACKLOG; + } else if (new_state == IP_VS_TCP_S_ESTABLISHED && + cp->flags & IP_VS_CONN_F_BACKLOG) { + atomic_dec(&dest->backlogconns); + cp->flags &= ~IP_VS_CONN_F_BACKLOG; + } } } diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 7ba06939829f..ceb1cd9c5976 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c @@ -264,7 +264,7 @@ void ip_vs_sync_conn(struct ip_vs_conn *cp) s->caddr = cp->caddr.ip; s->vaddr = cp->vaddr.ip; s->daddr = cp->daddr.ip; - s->flags = htons(cp->flags & ~IP_VS_CONN_F_HASHED); + s->flags = htons(cp->flags & ~(IP_VS_CONN_F_HASHED | IP_VS_CONN_F_BACKLOG)); s->state = htons(cp->state); if (cp->flags & IP_VS_CONN_F_SEQ_MASK) { struct ip_vs_sync_conn_options *opt = @@ -334,7 +334,7 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) } s = (struct ip_vs_sync_conn *) p; flags = ntohs(s->flags) | IP_VS_CONN_F_SYNC; - flags &= ~IP_VS_CONN_F_HASHED; + flags &= ~(IP_VS_CONN_F_HASHED | IP_VS_CONN_F_BACKLOG); if (flags & IP_VS_CONN_F_SEQ_MASK) { opt = (struct ip_vs_sync_conn_options *)&s[1]; p += FULL_CONN_SIZE; |