ipvs: add sync_persist_mode flag
authorJulian Anastasov <ja@ssi.bg>
Mon, 24 Jun 2013 19:44:41 +0000 (22:44 +0300)
committerSimon Horman <horms@verge.net.au>
Wed, 26 Jun 2013 09:01:46 +0000 (18:01 +0900)
Add sync_persist_mode flag to reduce sync traffic
by syncing only persistent templates.

Signed-off-by: Julian Anastasov <ja@ssi.bg>
Tested-by: Aleksey Chudov <aleksey.chudov@gmail.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Documentation/networking/ipvs-sysctl.txt
include/net/ip_vs.h
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/ipvs/ip_vs_sync.c

index 9573d0c48c6ea882099edd94ed2dcda94e4fe3dd..7a3c047295914cbc8c4273506a9b6d35246a1750 100644 (file)
@@ -181,6 +181,19 @@ snat_reroute - BOOLEAN
        always be the same as the original route so it is an optimisation
        to disable snat_reroute and avoid the recalculation.
 
+sync_persist_mode - INTEGER
+       default 0
+
+       Controls the synchronisation of connections when using persistence
+
+       0: All types of connections are synchronised
+       1: Attempt to reduce the synchronisation traffic depending on
+       the connection type. For persistent services avoid synchronisation
+       for normal connections, do it only for persistence templates.
+       In such case, for TCP and SCTP it may need enabling sloppy_tcp and
+       sloppy_sctp flags on backup servers. For non-persistent services
+       such optimization is not applied, mode 0 is assumed.
+
 sync_version - INTEGER
        default 1
 
index e667df171003de2d3118646ac5970a10cecc3225..f0d70f066f3ddc59a0c1c7bb5e58daf1c4b3c3a4 100644 (file)
@@ -975,6 +975,7 @@ struct netns_ipvs {
        int                     sysctl_snat_reroute;
        int                     sysctl_sync_ver;
        int                     sysctl_sync_ports;
+       int                     sysctl_sync_persist_mode;
        unsigned long           sysctl_sync_qlen_max;
        int                     sysctl_sync_sock_size;
        int                     sysctl_cache_bypass;
@@ -1076,6 +1077,11 @@ static inline int sysctl_sync_ports(struct netns_ipvs *ipvs)
        return ACCESS_ONCE(ipvs->sysctl_sync_ports);
 }
 
+static inline int sysctl_sync_persist_mode(struct netns_ipvs *ipvs)
+{
+       return ipvs->sysctl_sync_persist_mode;
+}
+
 static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs)
 {
        return ipvs->sysctl_sync_qlen_max;
@@ -1139,6 +1145,11 @@ static inline int sysctl_sync_ports(struct netns_ipvs *ipvs)
        return 1;
 }
 
+static inline int sysctl_sync_persist_mode(struct netns_ipvs *ipvs)
+{
+       return 0;
+}
+
 static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs)
 {
        return IPVS_SYNC_QLEN_MAX;
index da035fc01eb2a104b481b32cd01eb0c231cc91f1..c8148e48738657d63810a1dade924267dc032d01 100644 (file)
@@ -1714,6 +1714,12 @@ static struct ctl_table vs_vars[] = {
                .mode           = 0644,
                .proc_handler   = &proc_do_sync_ports,
        },
+       {
+               .procname       = "sync_persist_mode",
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
        {
                .procname       = "sync_qlen_max",
                .maxlen         = sizeof(unsigned long),
@@ -3729,6 +3735,7 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net)
        tbl[idx++].data = &ipvs->sysctl_sync_ver;
        ipvs->sysctl_sync_ports = 1;
        tbl[idx++].data = &ipvs->sysctl_sync_ports;
+       tbl[idx++].data = &ipvs->sysctl_sync_persist_mode;
        ipvs->sysctl_sync_qlen_max = nr_free_buffer_pages() / 32;
        tbl[idx++].data = &ipvs->sysctl_sync_qlen_max;
        ipvs->sysctl_sync_sock_size = 0;
index 2fc66394d86de8adee26f851fd00b449e7af2c93..f4484719f3e638cc2c6cf10e4d0fa5535990ad6a 100644 (file)
@@ -425,6 +425,16 @@ ip_vs_sync_buff_create_v0(struct netns_ipvs *ipvs)
        return sb;
 }
 
+/* Check if connection is controlled by persistence */
+static inline bool in_persistence(struct ip_vs_conn *cp)
+{
+       for (cp = cp->control; cp; cp = cp->control) {
+               if (cp->flags & IP_VS_CONN_F_TEMPLATE)
+                       return true;
+       }
+       return false;
+}
+
 /* Check if conn should be synced.
  * pkts: conn packets, use sysctl_sync_threshold to avoid packet check
  * - (1) sync_refresh_period: reduce sync rate. Additionally, retry
@@ -447,6 +457,8 @@ static int ip_vs_sync_conn_needed(struct netns_ipvs *ipvs,
        /* Check if we sync in current state */
        if (unlikely(cp->flags & IP_VS_CONN_F_TEMPLATE))
                force = 0;
+       else if (unlikely(sysctl_sync_persist_mode(ipvs) && in_persistence(cp)))
+               return 0;
        else if (likely(cp->protocol == IPPROTO_TCP)) {
                if (!((1 << cp->state) &
                      ((1 << IP_VS_TCP_S_ESTABLISHED) |