Hello, On Tue, 30 Dec 2014, Marcelo Ricardo Leitner wrote: > What if we make the backup server purge the old entry, just like the active server does, and ignore old updates if needed? Please note the new hunk on ip_vs_sync.c. This is the patch I'm using so far, and I'm seeing good results with even with master/backup. Backup server successfully purges the old and creates a new entry when it detects such update: > > [ 344.971673] IPVS: Bind-dest TCP c:192.168.122.1:22222 v:192.168.122.200:80 d:192.168.122.67:80 fwd:R s:0 conn->flags:A3 conn->refcnt:1 dest->refcnt:2 > [ 344.972071] IPVS: Unbind-dest TCP c:192.168.122.1:22222 v:192.168.122.200:80 d:192.168.122.95:80 fwd:R s:4 conn->flags:1A3 conn->refcnt:0 dest->refcnt:2 Good idea > -- 8< -- > > /* IPVS core functions > diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c > index 990decba1fe418e36e59a1f081fcf0e47188da29..da2760496314d49a5b4f6f588de7cb565a28e223 100644 > --- a/net/netfilter/ipvs/ip_vs_core.c > +++ b/net/netfilter/ipvs/ip_vs_core.c > @@ -1036,6 +1036,20 @@ static inline bool is_new_conn(const struct sk_buff *skb, > } > } > > +static inline bool is_new_conn_expected(const struct ip_vs_conn *cp, > + int conn_reuse_mode) > +{ > + if ((cp->protocol != IPPROTO_TCP) && (cp->protocol != IPPROTO_SCTP)) > + return false; If we want SCTP support may be we have to check cp->state for IP_VS_SCTP_S_CLOSED, it is analog to our IP_VS_TCP_S_TIME_WAIT state. But cp->state checks should be per protocol, eg: /* Controlled (FTP DATA or persistence)? */ if (cp->control) return false; switch (cp->protocol) { case IPPROTO_TCP: return ... case IPPROTO_SCTP: return cp->state == IP_VS_SCTP_S_CLOSED; default: return false; } > + /* Controlled (FTP DATA or persistence)? */ > + if (cp->control) > + return false; > + return (cp->state == IP_VS_TCP_S_TIME_WAIT) || > + ((conn_reuse_mode & 2) && > + (cp->state == IP_VS_TCP_S_FIN_WAIT) && > + (cp->flags & IP_VS_CONN_F_NOOUTPUT)); > +} > + > /* Handle response packets: rewrite addresses and send away... > */ > static unsigned int > @@ -1574,6 +1588,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) > struct ip_vs_conn *cp; > int ret, pkts; > struct netns_ipvs *ipvs; > + int conn_reuse_mode; > > /* Already marked as IPVS request or reply? */ > if (skb->ipvs_property) > @@ -1642,9 +1657,13 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) > */ > cp = pp->conn_in_get(af, skb, &iph, 0); > > - if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp && cp->dest && > - unlikely(!atomic_read(&cp->dest->weight)) && !iph.fragoffs && > - is_new_conn(skb, &iph)) { > + conn_reuse_mode = sysctl_conn_reuse_mode(ipvs); > + if (conn_reuse_mode && !iph.fragoffs && > + is_new_conn(skb, &iph) && cp && > + !atomic_read(&cp->n_control) && Above n_control check will prevent FTP:21 connections to be replaced when expire_nodest_conn=1. May be the n_control check should be moved below to avoid ip_vs_conn_expire_now? Like this: if (!atomic_read(&cp->n_control)) ip_vs_conn_expire_now(cp); __ip_vs_conn_put(cp); cp = NULL; I.e. old connection will not be tried for expiration but we still create new connection. The old will not be visible to packets. > + ((unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest && > + unlikely(!atomic_read(&cp->dest->weight))) || > + unlikely(is_new_conn_expected(cp, conn_reuse_mode)))) { > ip_vs_conn_expire_now(cp); > __ip_vs_conn_put(cp); > cp = NULL; > diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c > index c47ffd7a0a709cb73834c84652f251960f25db79..7ed4484c2c93e0aed89be55c773c94f3c80cc09e 100644 > --- a/net/netfilter/ipvs/ip_vs_sync.c > +++ b/net/netfilter/ipvs/ip_vs_sync.c > @@ -850,6 +850,21 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param, > else > cp = ip_vs_ct_in_get(param); > > + if (cp && ((cp->dport != dport) || > + !ip_vs_addr_equal(cp->af, &cp->daddr, daddr))) { Better to use here the new cp->daf field instead of cp->af. > + if (!(flags & IP_VS_CONN_F_INACTIVE)) { I guess, we here try to avoid old sync message to expire new connection. The problem is that UDP conns and templates are always IP_VS_CONN_F_INACTIVE, may be a TCP+SCTP protocol check is needed. > + ip_vs_conn_expire_now(cp); > + __ip_vs_conn_put(cp); > + cp = NULL; > + } else { > + /* This is the expiration message for the > + * connection that was already replaced, so we > + * just ignore it. > + */ > + goto out; > + } > + } > + > if (cp) { > /* Free pe_data */ > kfree(param->pe_data); > @@ -925,6 +940,8 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param, > else > cp->timeout = (3*60*HZ); > } > + > +out: > ip_vs_conn_put(cp); > } > Regards -- Julian Anastasov <ja@xxxxxx> -- To unsubscribe from this list: send the line "unsubscribe lvs-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html