aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/ipvs-sysctl.txt7
-rw-r--r--include/net/ip_vs.h12
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c12
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c7
4 files changed, 34 insertions, 4 deletions
diff --git a/Documentation/networking/ipvs-sysctl.txt b/Documentation/networking/ipvs-sysctl.txt
index f2a2488f1bf3..9573d0c48c6e 100644
--- a/Documentation/networking/ipvs-sysctl.txt
+++ b/Documentation/networking/ipvs-sysctl.txt
@@ -15,6 +15,13 @@ amemthresh - INTEGER
15 enabled and the variable is automatically set to 2, otherwise 15 enabled and the variable is automatically set to 2, otherwise
16 the strategy is disabled and the variable is set to 1. 16 the strategy is disabled and the variable is set to 1.
17 17
18backup_only - BOOLEAN
19 0 - disabled (default)
20 not 0 - enabled
21
22 If set, disable the director function while the server is
23 in backup mode to avoid packet loops for DR/TUN methods.
24
18conntrack - BOOLEAN 25conntrack - BOOLEAN
19 0 - disabled (default) 26 0 - disabled (default)
20 not 0 - enabled 27 not 0 - enabled
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 68c69d54d392..fce8e6b66d55 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -976,6 +976,7 @@ struct netns_ipvs {
976 int sysctl_sync_retries; 976 int sysctl_sync_retries;
977 int sysctl_nat_icmp_send; 977 int sysctl_nat_icmp_send;
978 int sysctl_pmtu_disc; 978 int sysctl_pmtu_disc;
979 int sysctl_backup_only;
979 980
980 /* ip_vs_lblc */ 981 /* ip_vs_lblc */
981 int sysctl_lblc_expiration; 982 int sysctl_lblc_expiration;
@@ -1067,6 +1068,12 @@ static inline int sysctl_pmtu_disc(struct netns_ipvs *ipvs)
1067 return ipvs->sysctl_pmtu_disc; 1068 return ipvs->sysctl_pmtu_disc;
1068} 1069}
1069 1070
1071static inline int sysctl_backup_only(struct netns_ipvs *ipvs)
1072{
1073 return ipvs->sync_state & IP_VS_STATE_BACKUP &&
1074 ipvs->sysctl_backup_only;
1075}
1076
1070#else 1077#else
1071 1078
1072static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs) 1079static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs)
@@ -1114,6 +1121,11 @@ static inline int sysctl_pmtu_disc(struct netns_ipvs *ipvs)
1114 return 1; 1121 return 1;
1115} 1122}
1116 1123
1124static inline int sysctl_backup_only(struct netns_ipvs *ipvs)
1125{
1126 return 0;
1127}
1128
1117#endif 1129#endif
1118 1130
1119/* 1131/*
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 47edf5a40a59..18b4bc55fa3d 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1577,7 +1577,8 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
1577 } 1577 }
1578 /* ipvs enabled in this netns ? */ 1578 /* ipvs enabled in this netns ? */
1579 net = skb_net(skb); 1579 net = skb_net(skb);
1580 if (!net_ipvs(net)->enable) 1580 ipvs = net_ipvs(net);
1581 if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable))
1581 return NF_ACCEPT; 1582 return NF_ACCEPT;
1582 1583
1583 ip_vs_fill_iph_skb(af, skb, &iph); 1584 ip_vs_fill_iph_skb(af, skb, &iph);
@@ -1654,7 +1655,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
1654 } 1655 }
1655 1656
1656 IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet"); 1657 IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet");
1657 ipvs = net_ipvs(net);
1658 /* Check the server status */ 1658 /* Check the server status */
1659 if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { 1659 if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
1660 /* the destination server is not available */ 1660 /* the destination server is not available */
@@ -1815,13 +1815,15 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb,
1815{ 1815{
1816 int r; 1816 int r;
1817 struct net *net; 1817 struct net *net;
1818 struct netns_ipvs *ipvs;
1818 1819
1819 if (ip_hdr(skb)->protocol != IPPROTO_ICMP) 1820 if (ip_hdr(skb)->protocol != IPPROTO_ICMP)
1820 return NF_ACCEPT; 1821 return NF_ACCEPT;
1821 1822
1822 /* ipvs enabled in this netns ? */ 1823 /* ipvs enabled in this netns ? */
1823 net = skb_net(skb); 1824 net = skb_net(skb);
1824 if (!net_ipvs(net)->enable) 1825 ipvs = net_ipvs(net);
1826 if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable))
1825 return NF_ACCEPT; 1827 return NF_ACCEPT;
1826 1828
1827 return ip_vs_in_icmp(skb, &r, hooknum); 1829 return ip_vs_in_icmp(skb, &r, hooknum);
@@ -1835,6 +1837,7 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb,
1835{ 1837{
1836 int r; 1838 int r;
1837 struct net *net; 1839 struct net *net;
1840 struct netns_ipvs *ipvs;
1838 struct ip_vs_iphdr iphdr; 1841 struct ip_vs_iphdr iphdr;
1839 1842
1840 ip_vs_fill_iph_skb(AF_INET6, skb, &iphdr); 1843 ip_vs_fill_iph_skb(AF_INET6, skb, &iphdr);
@@ -1843,7 +1846,8 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb,
1843 1846
1844 /* ipvs enabled in this netns ? */ 1847 /* ipvs enabled in this netns ? */
1845 net = skb_net(skb); 1848 net = skb_net(skb);
1846 if (!net_ipvs(net)->enable) 1849 ipvs = net_ipvs(net);
1850 if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable))
1847 return NF_ACCEPT; 1851 return NF_ACCEPT;
1848 1852
1849 return ip_vs_in_icmp_v6(skb, &r, hooknum, &iphdr); 1853 return ip_vs_in_icmp_v6(skb, &r, hooknum, &iphdr);
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index c68198bf9128..9e2d1cccd1eb 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1808,6 +1808,12 @@ static struct ctl_table vs_vars[] = {
1808 .mode = 0644, 1808 .mode = 0644,
1809 .proc_handler = proc_dointvec, 1809 .proc_handler = proc_dointvec,
1810 }, 1810 },
1811 {
1812 .procname = "backup_only",
1813 .maxlen = sizeof(int),
1814 .mode = 0644,
1815 .proc_handler = proc_dointvec,
1816 },
1811#ifdef CONFIG_IP_VS_DEBUG 1817#ifdef CONFIG_IP_VS_DEBUG
1812 { 1818 {
1813 .procname = "debug_level", 1819 .procname = "debug_level",
@@ -3741,6 +3747,7 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net)
3741 tbl[idx++].data = &ipvs->sysctl_nat_icmp_send; 3747 tbl[idx++].data = &ipvs->sysctl_nat_icmp_send;
3742 ipvs->sysctl_pmtu_disc = 1; 3748 ipvs->sysctl_pmtu_disc = 1;
3743 tbl[idx++].data = &ipvs->sysctl_pmtu_disc; 3749 tbl[idx++].data = &ipvs->sysctl_pmtu_disc;
3750 tbl[idx++].data = &ipvs->sysctl_backup_only;
3744 3751
3745 3752
3746 ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl); 3753 ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl);