Skip to content

Commit f73181c

Browse files
committed
ipvs: add support for sync threads
Allow master and backup servers to use many threads for sync traffic. Add sysctl var "sync_ports" to define the number of threads. Every thread will use single UDP port, thread 0 will use the default port 8848 while last thread will use port 8848+sync_ports-1. The sync traffic for connections is scheduled to many master threads based on the cp address but one connection is always assigned to same thread to avoid reordering of the sync messages. Remove ip_vs_sync_switch_mode because this check for sync mode change is still risky. Instead, check for mode change under sync_buff_lock. Make sure the backup socks do not block on reading. Special thanks to Aleksey Chudov for helping in all tests. Signed-off-by: Julian Anastasov <[email protected]> Tested-by: Aleksey Chudov <[email protected]> Signed-off-by: Simon Horman <[email protected]>
1 parent 749c42b commit f73181c

File tree

4 files changed

+305
-166
lines changed

4 files changed

+305
-166
lines changed

include/net/ip_vs.h

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,16 @@ struct ip_vs_app {
784784
void (*timeout_change)(struct ip_vs_app *app, int flags);
785785
};
786786

787+
struct ipvs_master_sync_state {
788+
struct list_head sync_queue;
789+
struct ip_vs_sync_buff *sync_buff;
790+
int sync_queue_len;
791+
unsigned int sync_queue_delay;
792+
struct task_struct *master_thread;
793+
struct delayed_work master_wakeup_work;
794+
struct netns_ipvs *ipvs;
795+
};
796+
787797
/* IPVS in network namespace */
788798
struct netns_ipvs {
789799
int gen; /* Generation */
@@ -870,6 +880,7 @@ struct netns_ipvs {
870880
#endif
871881
int sysctl_snat_reroute;
872882
int sysctl_sync_ver;
883+
int sysctl_sync_ports;
873884
int sysctl_sync_qlen_max;
874885
int sysctl_sync_sock_size;
875886
int sysctl_cache_bypass;
@@ -893,16 +904,11 @@ struct netns_ipvs {
893904
spinlock_t est_lock;
894905
struct timer_list est_timer; /* Estimation timer */
895906
/* ip_vs_sync */
896-
struct list_head sync_queue;
897-
int sync_queue_len;
898-
unsigned int sync_queue_delay;
899-
struct delayed_work master_wakeup_work;
900907
spinlock_t sync_lock;
901-
struct ip_vs_sync_buff *sync_buff;
908+
struct ipvs_master_sync_state *ms;
902909
spinlock_t sync_buff_lock;
903-
struct sockaddr_in sync_mcast_addr;
904-
struct task_struct *master_thread;
905-
struct task_struct *backup_thread;
910+
struct task_struct **backup_threads;
911+
int threads_mask;
906912
int send_mesg_maxlen;
907913
int recv_mesg_maxlen;
908914
volatile int sync_state;
@@ -926,6 +932,7 @@ struct netns_ipvs {
926932
#define IPVS_SYNC_SEND_DELAY (HZ / 50)
927933
#define IPVS_SYNC_CHECK_PERIOD HZ
928934
#define IPVS_SYNC_FLUSH_TIME (HZ * 2)
935+
#define IPVS_SYNC_PORTS_MAX (1 << 6)
929936

930937
#ifdef CONFIG_SYSCTL
931938

@@ -954,6 +961,11 @@ static inline int sysctl_sync_ver(struct netns_ipvs *ipvs)
954961
return ipvs->sysctl_sync_ver;
955962
}
956963

964+
static inline int sysctl_sync_ports(struct netns_ipvs *ipvs)
965+
{
966+
return ACCESS_ONCE(ipvs->sysctl_sync_ports);
967+
}
968+
957969
static inline int sysctl_sync_qlen_max(struct netns_ipvs *ipvs)
958970
{
959971
return ipvs->sysctl_sync_qlen_max;
@@ -991,6 +1003,11 @@ static inline int sysctl_sync_ver(struct netns_ipvs *ipvs)
9911003
return DEFAULT_SYNC_VER;
9921004
}
9931005

1006+
static inline int sysctl_sync_ports(struct netns_ipvs *ipvs)
1007+
{
1008+
return 1;
1009+
}
1010+
9941011
static inline int sysctl_sync_qlen_max(struct netns_ipvs *ipvs)
9951012
{
9961013
return IPVS_SYNC_QLEN_MAX;
@@ -1240,7 +1257,6 @@ extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
12401257
extern struct ip_vs_stats ip_vs_stats;
12411258
extern int sysctl_ip_vs_sync_ver;
12421259

1243-
extern void ip_vs_sync_switch_mode(struct net *net, int mode);
12441260
extern struct ip_vs_service *
12451261
ip_vs_service_get(struct net *net, int af, __u32 fwmark, __u16 protocol,
12461262
const union nf_inet_addr *vaddr, __be16 vport);

net/netfilter/ipvs/ip_vs_conn.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,12 +619,19 @@ struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp)
619619
if (dest) {
620620
struct ip_vs_proto_data *pd;
621621

622+
spin_lock(&cp->lock);
623+
if (cp->dest) {
624+
spin_unlock(&cp->lock);
625+
return dest;
626+
}
627+
622628
/* Applications work depending on the forwarding method
623629
* but better to reassign them always when binding dest */
624630
if (cp->app)
625631
ip_vs_unbind_app(cp);
626632

627633
ip_vs_bind_dest(cp, dest);
634+
spin_unlock(&cp->lock);
628635

629636
/* Update its packet transmitter */
630637
cp->packet_xmit = NULL;

net/netfilter/ipvs/ip_vs_ctl.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,9 +1657,24 @@ proc_do_sync_mode(ctl_table *table, int write,
16571657
if ((*valp < 0) || (*valp > 1)) {
16581658
/* Restore the correct value */
16591659
*valp = val;
1660-
} else {
1661-
struct net *net = current->nsproxy->net_ns;
1662-
ip_vs_sync_switch_mode(net, val);
1660+
}
1661+
}
1662+
return rc;
1663+
}
1664+
1665+
static int
1666+
proc_do_sync_ports(ctl_table *table, int write,
1667+
void __user *buffer, size_t *lenp, loff_t *ppos)
1668+
{
1669+
int *valp = table->data;
1670+
int val = *valp;
1671+
int rc;
1672+
1673+
rc = proc_dointvec(table, write, buffer, lenp, ppos);
1674+
if (write && (*valp != val)) {
1675+
if (*valp < 1 || !is_power_of_2(*valp)) {
1676+
/* Restore the correct value */
1677+
*valp = val;
16631678
}
16641679
}
16651680
return rc;
@@ -1722,6 +1737,12 @@ static struct ctl_table vs_vars[] = {
17221737
.mode = 0644,
17231738
.proc_handler = &proc_do_sync_mode,
17241739
},
1740+
{
1741+
.procname = "sync_ports",
1742+
.maxlen = sizeof(int),
1743+
.mode = 0644,
1744+
.proc_handler = &proc_do_sync_ports,
1745+
},
17251746
{
17261747
.procname = "sync_qlen_max",
17271748
.maxlen = sizeof(int),
@@ -3686,6 +3707,8 @@ int __net_init ip_vs_control_net_init_sysctl(struct net *net)
36863707
tbl[idx++].data = &ipvs->sysctl_snat_reroute;
36873708
ipvs->sysctl_sync_ver = 1;
36883709
tbl[idx++].data = &ipvs->sysctl_sync_ver;
3710+
ipvs->sysctl_sync_ports = 1;
3711+
tbl[idx++].data = &ipvs->sysctl_sync_ports;
36893712
ipvs->sysctl_sync_qlen_max = nr_free_buffer_pages() / 32;
36903713
tbl[idx++].data = &ipvs->sysctl_sync_qlen_max;
36913714
ipvs->sysctl_sync_sock_size = 0;

0 commit comments

Comments
 (0)