diff options
author | Alex Shi <alex.shi@linaro.org> | 2016-07-20 16:08:14 +0800 |
---|---|---|
committer | Alex Shi <alex.shi@linaro.org> | 2016-07-20 16:08:14 +0800 |
commit | 1d508e233d21a7848cf54d7d03b40dac2d9ea873 (patch) | |
tree | eec5222580c4bca752ae35d5cef3842166e6f8c8 /net/netfilter/ipvs/ip_vs_core.c | |
parent | 439863d92fda525a8f3b326a24490e91c70f0496 (diff) | |
parent | 5880876e94699ce010554f483ccf0009997955ca (diff) |
Merge remote-tracking branch 'lts/linux-4.1.y' into linux-linaro-lsk-v4.1lsk-v4.1-16.07
Conflicts:
pick up 45d1abd9de arm64: Use PoU cache instr for I/D coherency
in arch/arm64/mm/flush.c
Diffstat (limited to 'net/netfilter/ipvs/ip_vs_core.c')
-rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 38fbc194b9cb..a26bd6532829 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1689,15 +1689,34 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) cp = pp->conn_in_get(af, skb, &iph, 0); conn_reuse_mode = sysctl_conn_reuse_mode(ipvs); - if (conn_reuse_mode && !iph.fragoffs && - is_new_conn(skb, &iph) && cp && - ((unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest && - unlikely(!atomic_read(&cp->dest->weight))) || - unlikely(is_new_conn_expected(cp, conn_reuse_mode)))) { - if (!atomic_read(&cp->n_control)) - ip_vs_conn_expire_now(cp); - __ip_vs_conn_put(cp); - cp = NULL; + if (conn_reuse_mode && !iph.fragoffs && is_new_conn(skb, &iph) && cp) { + bool uses_ct = false, resched = false; + + if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest && + unlikely(!atomic_read(&cp->dest->weight))) { + resched = true; + uses_ct = ip_vs_conn_uses_conntrack(cp, skb); + } else if (is_new_conn_expected(cp, conn_reuse_mode)) { + uses_ct = ip_vs_conn_uses_conntrack(cp, skb); + if (!atomic_read(&cp->n_control)) { + resched = true; + } else { + /* Do not reschedule controlling connection + * that uses conntrack while it is still + * referenced by controlled connection(s). + */ + resched = !uses_ct; + } + } + + if (resched) { + if (!atomic_read(&cp->n_control)) + ip_vs_conn_expire_now(cp); + __ip_vs_conn_put(cp); + if (uses_ct) + return NF_DROP; + cp = NULL; + } } if (unlikely(!cp) && !iph.fragoffs) { |