diff options
author | Hans Schillstrom <hans.schillstrom@ericsson.com> | 2011-01-03 08:44:55 -0500 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2011-01-12 20:30:28 -0500 |
commit | f131315fa272d337dfca7dad2f033ff5296dad65 (patch) | |
tree | 4abe0b8cd421229e27be614e23e3bbc800dff98b | |
parent | 29c2026fd4980c144d9c746dc1565060f08e5796 (diff) |
IPVS: netns awareness to ip_vs_sync
All global variables moved to struct ipvs,
most external changes fixed (i.e. init_net removed)
in sync_buf create + 4 replaced by sizeof(struct..)
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
Acked-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r-- | include/net/ip_vs.h | 14 | ||||
-rw-r--r-- | include/net/netns/ip_vs.h | 16 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 15 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 52 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_sync.c | 334 |
5 files changed, 240 insertions, 191 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index c08927bb1728..4265b5e00c94 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
@@ -958,7 +958,7 @@ extern struct ip_vs_stats ip_vs_stats; | |||
958 | extern const struct ctl_path net_vs_ctl_path[]; | 958 | extern const struct ctl_path net_vs_ctl_path[]; |
959 | extern int sysctl_ip_vs_sync_ver; | 959 | extern int sysctl_ip_vs_sync_ver; |
960 | 960 | ||
961 | extern void ip_vs_sync_switch_mode(int mode); | 961 | extern void ip_vs_sync_switch_mode(struct net *net, int mode); |
962 | extern struct ip_vs_service * | 962 | extern struct ip_vs_service * |
963 | ip_vs_service_get(struct net *net, int af, __u32 fwmark, __u16 protocol, | 963 | ip_vs_service_get(struct net *net, int af, __u32 fwmark, __u16 protocol, |
964 | const union nf_inet_addr *vaddr, __be16 vport); | 964 | const union nf_inet_addr *vaddr, __be16 vport); |
@@ -987,14 +987,10 @@ extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp); | |||
987 | * IPVS sync daemon data and function prototypes | 987 | * IPVS sync daemon data and function prototypes |
988 | * (from ip_vs_sync.c) | 988 | * (from ip_vs_sync.c) |
989 | */ | 989 | */ |
990 | extern volatile int ip_vs_sync_state; | 990 | extern int start_sync_thread(struct net *net, int state, char *mcast_ifn, |
991 | extern volatile int ip_vs_master_syncid; | 991 | __u8 syncid); |
992 | extern volatile int ip_vs_backup_syncid; | 992 | extern int stop_sync_thread(struct net *net, int state); |
993 | extern char ip_vs_master_mcast_ifn[IP_VS_IFNAME_MAXLEN]; | 993 | extern void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp); |
994 | extern char ip_vs_backup_mcast_ifn[IP_VS_IFNAME_MAXLEN]; | ||
995 | extern int start_sync_thread(int state, char *mcast_ifn, __u8 syncid); | ||
996 | extern int stop_sync_thread(int state); | ||
997 | extern void ip_vs_sync_conn(struct ip_vs_conn *cp); | ||
998 | extern int ip_vs_sync_init(void); | 994 | extern int ip_vs_sync_init(void); |
999 | extern void ip_vs_sync_cleanup(void); | 995 | extern void ip_vs_sync_cleanup(void); |
1000 | 996 | ||
diff --git a/include/net/netns/ip_vs.h b/include/net/netns/ip_vs.h index db0240198339..aba78f3c8341 100644 --- a/include/net/netns/ip_vs.h +++ b/include/net/netns/ip_vs.h | |||
@@ -74,6 +74,22 @@ struct netns_ipvs { | |||
74 | struct list_head est_list; /* estimator list */ | 74 | struct list_head est_list; /* estimator list */ |
75 | spinlock_t est_lock; | 75 | spinlock_t est_lock; |
76 | struct timer_list est_timer; /* Estimation timer */ | 76 | struct timer_list est_timer; /* Estimation timer */ |
77 | /* ip_vs_sync */ | ||
78 | struct list_head sync_queue; | ||
79 | spinlock_t sync_lock; | ||
80 | struct ip_vs_sync_buff *sync_buff; | ||
81 | spinlock_t sync_buff_lock; | ||
82 | struct sockaddr_in sync_mcast_addr; | ||
83 | struct task_struct *master_thread; | ||
84 | struct task_struct *backup_thread; | ||
85 | int send_mesg_maxlen; | ||
86 | int recv_mesg_maxlen; | ||
87 | volatile int sync_state; | ||
88 | volatile int master_syncid; | ||
89 | volatile int backup_syncid; | ||
90 | /* multicast interface name */ | ||
91 | char master_mcast_ifn[IP_VS_IFNAME_MAXLEN]; | ||
92 | char backup_mcast_ifn[IP_VS_IFNAME_MAXLEN]; | ||
77 | }; | 93 | }; |
78 | 94 | ||
79 | #endif /* IP_VS_H_ */ | 95 | #endif /* IP_VS_H_ */ |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 9317affc5ea1..5531d569aa5e 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
@@ -1471,12 +1471,13 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1471 | static unsigned int | 1471 | static unsigned int |
1472 | ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | 1472 | ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) |
1473 | { | 1473 | { |
1474 | struct net *net = NULL; | 1474 | struct net *net; |
1475 | struct ip_vs_iphdr iph; | 1475 | struct ip_vs_iphdr iph; |
1476 | struct ip_vs_protocol *pp; | 1476 | struct ip_vs_protocol *pp; |
1477 | struct ip_vs_proto_data *pd; | 1477 | struct ip_vs_proto_data *pd; |
1478 | struct ip_vs_conn *cp; | 1478 | struct ip_vs_conn *cp; |
1479 | int ret, restart, pkts; | 1479 | int ret, restart, pkts; |
1480 | struct netns_ipvs *ipvs; | ||
1480 | 1481 | ||
1481 | /* Already marked as IPVS request or reply? */ | 1482 | /* Already marked as IPVS request or reply? */ |
1482 | if (skb->ipvs_property) | 1483 | if (skb->ipvs_property) |
@@ -1556,7 +1557,8 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1556 | } | 1557 | } |
1557 | 1558 | ||
1558 | IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet"); | 1559 | IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet"); |
1559 | 1560 | net = skb_net(skb); | |
1561 | ipvs = net_ipvs(net); | ||
1560 | /* Check the server status */ | 1562 | /* Check the server status */ |
1561 | if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { | 1563 | if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { |
1562 | /* the destination server is not available */ | 1564 | /* the destination server is not available */ |
@@ -1589,12 +1591,13 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1589 | * | 1591 | * |
1590 | * For ONE_PKT let ip_vs_sync_conn() do the filter work. | 1592 | * For ONE_PKT let ip_vs_sync_conn() do the filter work. |
1591 | */ | 1593 | */ |
1594 | |||
1592 | if (cp->flags & IP_VS_CONN_F_ONE_PACKET) | 1595 | if (cp->flags & IP_VS_CONN_F_ONE_PACKET) |
1593 | pkts = sysctl_ip_vs_sync_threshold[0]; | 1596 | pkts = sysctl_ip_vs_sync_threshold[0]; |
1594 | else | 1597 | else |
1595 | pkts = atomic_add_return(1, &cp->in_pkts); | 1598 | pkts = atomic_add_return(1, &cp->in_pkts); |
1596 | 1599 | ||
1597 | if ((ip_vs_sync_state & IP_VS_STATE_MASTER) && | 1600 | if ((ipvs->sync_state & IP_VS_STATE_MASTER) && |
1598 | cp->protocol == IPPROTO_SCTP) { | 1601 | cp->protocol == IPPROTO_SCTP) { |
1599 | if ((cp->state == IP_VS_SCTP_S_ESTABLISHED && | 1602 | if ((cp->state == IP_VS_SCTP_S_ESTABLISHED && |
1600 | (pkts % sysctl_ip_vs_sync_threshold[1] | 1603 | (pkts % sysctl_ip_vs_sync_threshold[1] |
@@ -1603,13 +1606,13 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1603 | ((cp->state == IP_VS_SCTP_S_CLOSED) || | 1606 | ((cp->state == IP_VS_SCTP_S_CLOSED) || |
1604 | (cp->state == IP_VS_SCTP_S_SHUT_ACK_CLI) || | 1607 | (cp->state == IP_VS_SCTP_S_SHUT_ACK_CLI) || |
1605 | (cp->state == IP_VS_SCTP_S_SHUT_ACK_SER)))) { | 1608 | (cp->state == IP_VS_SCTP_S_SHUT_ACK_SER)))) { |
1606 | ip_vs_sync_conn(cp); | 1609 | ip_vs_sync_conn(net, cp); |
1607 | goto out; | 1610 | goto out; |
1608 | } | 1611 | } |
1609 | } | 1612 | } |
1610 | 1613 | ||
1611 | /* Keep this block last: TCP and others with pp->num_states <= 1 */ | 1614 | /* Keep this block last: TCP and others with pp->num_states <= 1 */ |
1612 | else if ((ip_vs_sync_state & IP_VS_STATE_MASTER) && | 1615 | else if ((ipvs->sync_state & IP_VS_STATE_MASTER) && |
1613 | (((cp->protocol != IPPROTO_TCP || | 1616 | (((cp->protocol != IPPROTO_TCP || |
1614 | cp->state == IP_VS_TCP_S_ESTABLISHED) && | 1617 | cp->state == IP_VS_TCP_S_ESTABLISHED) && |
1615 | (pkts % sysctl_ip_vs_sync_threshold[1] | 1618 | (pkts % sysctl_ip_vs_sync_threshold[1] |
@@ -1619,7 +1622,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1619 | (cp->state == IP_VS_TCP_S_CLOSE) || | 1622 | (cp->state == IP_VS_TCP_S_CLOSE) || |
1620 | (cp->state == IP_VS_TCP_S_CLOSE_WAIT) || | 1623 | (cp->state == IP_VS_TCP_S_CLOSE_WAIT) || |
1621 | (cp->state == IP_VS_TCP_S_TIME_WAIT))))) | 1624 | (cp->state == IP_VS_TCP_S_TIME_WAIT))))) |
1622 | ip_vs_sync_conn(cp); | 1625 | ip_vs_sync_conn(net, cp); |
1623 | out: | 1626 | out: |
1624 | cp->old_state = cp->state; | 1627 | cp->old_state = cp->state; |
1625 | 1628 | ||
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index c89beb8eafbb..03f86312b4bb 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -1559,7 +1559,8 @@ proc_do_sync_mode(ctl_table *table, int write, | |||
1559 | /* Restore the correct value */ | 1559 | /* Restore the correct value */ |
1560 | *valp = val; | 1560 | *valp = val; |
1561 | } else { | 1561 | } else { |
1562 | ip_vs_sync_switch_mode(val); | 1562 | struct net *net = current->nsproxy->net_ns; |
1563 | ip_vs_sync_switch_mode(net, val); | ||
1563 | } | 1564 | } |
1564 | } | 1565 | } |
1565 | return rc; | 1566 | return rc; |
@@ -2174,11 +2175,12 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
2174 | goto out_unlock; | 2175 | goto out_unlock; |
2175 | } else if (cmd == IP_VS_SO_SET_STARTDAEMON) { | 2176 | } else if (cmd == IP_VS_SO_SET_STARTDAEMON) { |
2176 | struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; | 2177 | struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; |
2177 | ret = start_sync_thread(dm->state, dm->mcast_ifn, dm->syncid); | 2178 | ret = start_sync_thread(net, dm->state, dm->mcast_ifn, |
2179 | dm->syncid); | ||
2178 | goto out_unlock; | 2180 | goto out_unlock; |
2179 | } else if (cmd == IP_VS_SO_SET_STOPDAEMON) { | 2181 | } else if (cmd == IP_VS_SO_SET_STOPDAEMON) { |
2180 | struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; | 2182 | struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; |
2181 | ret = stop_sync_thread(dm->state); | 2183 | ret = stop_sync_thread(net, dm->state); |
2182 | goto out_unlock; | 2184 | goto out_unlock; |
2183 | } | 2185 | } |
2184 | 2186 | ||
@@ -2424,6 +2426,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2424 | int ret = 0; | 2426 | int ret = 0; |
2425 | unsigned int copylen; | 2427 | unsigned int copylen; |
2426 | struct net *net = sock_net(sk); | 2428 | struct net *net = sock_net(sk); |
2429 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
2427 | 2430 | ||
2428 | BUG_ON(!net); | 2431 | BUG_ON(!net); |
2429 | if (!capable(CAP_NET_ADMIN)) | 2432 | if (!capable(CAP_NET_ADMIN)) |
@@ -2546,15 +2549,17 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2546 | struct ip_vs_daemon_user d[2]; | 2549 | struct ip_vs_daemon_user d[2]; |
2547 | 2550 | ||
2548 | memset(&d, 0, sizeof(d)); | 2551 | memset(&d, 0, sizeof(d)); |
2549 | if (ip_vs_sync_state & IP_VS_STATE_MASTER) { | 2552 | if (ipvs->sync_state & IP_VS_STATE_MASTER) { |
2550 | d[0].state = IP_VS_STATE_MASTER; | 2553 | d[0].state = IP_VS_STATE_MASTER; |
2551 | strlcpy(d[0].mcast_ifn, ip_vs_master_mcast_ifn, sizeof(d[0].mcast_ifn)); | 2554 | strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn, |
2552 | d[0].syncid = ip_vs_master_syncid; | 2555 | sizeof(d[0].mcast_ifn)); |
2556 | d[0].syncid = ipvs->master_syncid; | ||
2553 | } | 2557 | } |
2554 | if (ip_vs_sync_state & IP_VS_STATE_BACKUP) { | 2558 | if (ipvs->sync_state & IP_VS_STATE_BACKUP) { |
2555 | d[1].state = IP_VS_STATE_BACKUP; | 2559 | d[1].state = IP_VS_STATE_BACKUP; |
2556 | strlcpy(d[1].mcast_ifn, ip_vs_backup_mcast_ifn, sizeof(d[1].mcast_ifn)); | 2560 | strlcpy(d[1].mcast_ifn, ipvs->backup_mcast_ifn, |
2557 | d[1].syncid = ip_vs_backup_syncid; | 2561 | sizeof(d[1].mcast_ifn)); |
2562 | d[1].syncid = ipvs->backup_syncid; | ||
2558 | } | 2563 | } |
2559 | if (copy_to_user(user, &d, sizeof(d)) != 0) | 2564 | if (copy_to_user(user, &d, sizeof(d)) != 0) |
2560 | ret = -EFAULT; | 2565 | ret = -EFAULT; |
@@ -3061,20 +3066,23 @@ nla_put_failure: | |||
3061 | static int ip_vs_genl_dump_daemons(struct sk_buff *skb, | 3066 | static int ip_vs_genl_dump_daemons(struct sk_buff *skb, |
3062 | struct netlink_callback *cb) | 3067 | struct netlink_callback *cb) |
3063 | { | 3068 | { |
3069 | struct net *net = skb_net(skb); | ||
3070 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
3071 | |||
3064 | mutex_lock(&__ip_vs_mutex); | 3072 | mutex_lock(&__ip_vs_mutex); |
3065 | if ((ip_vs_sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) { | 3073 | if ((ipvs->sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) { |
3066 | if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_MASTER, | 3074 | if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_MASTER, |
3067 | ip_vs_master_mcast_ifn, | 3075 | ipvs->master_mcast_ifn, |
3068 | ip_vs_master_syncid, cb) < 0) | 3076 | ipvs->master_syncid, cb) < 0) |
3069 | goto nla_put_failure; | 3077 | goto nla_put_failure; |
3070 | 3078 | ||
3071 | cb->args[0] = 1; | 3079 | cb->args[0] = 1; |
3072 | } | 3080 | } |
3073 | 3081 | ||
3074 | if ((ip_vs_sync_state & IP_VS_STATE_BACKUP) && !cb->args[1]) { | 3082 | if ((ipvs->sync_state & IP_VS_STATE_BACKUP) && !cb->args[1]) { |
3075 | if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_BACKUP, | 3083 | if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_BACKUP, |
3076 | ip_vs_backup_mcast_ifn, | 3084 | ipvs->backup_mcast_ifn, |
3077 | ip_vs_backup_syncid, cb) < 0) | 3085 | ipvs->backup_syncid, cb) < 0) |
3078 | goto nla_put_failure; | 3086 | goto nla_put_failure; |
3079 | 3087 | ||
3080 | cb->args[1] = 1; | 3088 | cb->args[1] = 1; |
@@ -3086,24 +3094,26 @@ nla_put_failure: | |||
3086 | return skb->len; | 3094 | return skb->len; |
3087 | } | 3095 | } |
3088 | 3096 | ||
3089 | static int ip_vs_genl_new_daemon(struct nlattr **attrs) | 3097 | static int ip_vs_genl_new_daemon(struct net *net, struct nlattr **attrs) |
3090 | { | 3098 | { |
3091 | if (!(attrs[IPVS_DAEMON_ATTR_STATE] && | 3099 | if (!(attrs[IPVS_DAEMON_ATTR_STATE] && |
3092 | attrs[IPVS_DAEMON_ATTR_MCAST_IFN] && | 3100 | attrs[IPVS_DAEMON_ATTR_MCAST_IFN] && |
3093 | attrs[IPVS_DAEMON_ATTR_SYNC_ID])) | 3101 | attrs[IPVS_DAEMON_ATTR_SYNC_ID])) |
3094 | return -EINVAL; | 3102 | return -EINVAL; |
3095 | 3103 | ||
3096 | return start_sync_thread(nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]), | 3104 | return start_sync_thread(net, |
3105 | nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]), | ||
3097 | nla_data(attrs[IPVS_DAEMON_ATTR_MCAST_IFN]), | 3106 | nla_data(attrs[IPVS_DAEMON_ATTR_MCAST_IFN]), |
3098 | nla_get_u32(attrs[IPVS_DAEMON_ATTR_SYNC_ID])); | 3107 | nla_get_u32(attrs[IPVS_DAEMON_ATTR_SYNC_ID])); |
3099 | } | 3108 | } |
3100 | 3109 | ||
3101 | static int ip_vs_genl_del_daemon(struct nlattr **attrs) | 3110 | static int ip_vs_genl_del_daemon(struct net *net, struct nlattr **attrs) |
3102 | { | 3111 | { |
3103 | if (!attrs[IPVS_DAEMON_ATTR_STATE]) | 3112 | if (!attrs[IPVS_DAEMON_ATTR_STATE]) |
3104 | return -EINVAL; | 3113 | return -EINVAL; |
3105 | 3114 | ||
3106 | return stop_sync_thread(nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE])); | 3115 | return stop_sync_thread(net, |
3116 | nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE])); | ||
3107 | } | 3117 | } |
3108 | 3118 | ||
3109 | static int ip_vs_genl_set_config(struct net *net, struct nlattr **attrs) | 3119 | static int ip_vs_genl_set_config(struct net *net, struct nlattr **attrs) |
@@ -3159,9 +3169,9 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | |||
3159 | } | 3169 | } |
3160 | 3170 | ||
3161 | if (cmd == IPVS_CMD_NEW_DAEMON) | 3171 | if (cmd == IPVS_CMD_NEW_DAEMON) |
3162 | ret = ip_vs_genl_new_daemon(daemon_attrs); | 3172 | ret = ip_vs_genl_new_daemon(net, daemon_attrs); |
3163 | else | 3173 | else |
3164 | ret = ip_vs_genl_del_daemon(daemon_attrs); | 3174 | ret = ip_vs_genl_del_daemon(net, daemon_attrs); |
3165 | goto out; | 3175 | goto out; |
3166 | } else if (cmd == IPVS_CMD_ZERO && | 3176 | } else if (cmd == IPVS_CMD_ZERO && |
3167 | !info->attrs[IPVS_CMD_ATTR_SERVICE]) { | 3177 | !info->attrs[IPVS_CMD_ATTR_SERVICE]) { |
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 6831e8fac8db..c29e73d686fb 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
@@ -192,6 +192,7 @@ union ip_vs_sync_conn { | |||
192 | #define IPVS_OPT_F_PARAM (1 << (IPVS_OPT_PARAM-1)) | 192 | #define IPVS_OPT_F_PARAM (1 << (IPVS_OPT_PARAM-1)) |
193 | 193 | ||
194 | struct ip_vs_sync_thread_data { | 194 | struct ip_vs_sync_thread_data { |
195 | struct net *net; | ||
195 | struct socket *sock; | 196 | struct socket *sock; |
196 | char *buf; | 197 | char *buf; |
197 | }; | 198 | }; |
@@ -259,10 +260,6 @@ struct ip_vs_sync_mesg { | |||
259 | /* ip_vs_sync_conn entries start here */ | 260 | /* ip_vs_sync_conn entries start here */ |
260 | }; | 261 | }; |
261 | 262 | ||
262 | /* the maximum length of sync (sending/receiving) message */ | ||
263 | static int sync_send_mesg_maxlen; | ||
264 | static int sync_recv_mesg_maxlen; | ||
265 | |||
266 | struct ip_vs_sync_buff { | 263 | struct ip_vs_sync_buff { |
267 | struct list_head list; | 264 | struct list_head list; |
268 | unsigned long firstuse; | 265 | unsigned long firstuse; |
@@ -273,28 +270,6 @@ struct ip_vs_sync_buff { | |||
273 | unsigned char *end; | 270 | unsigned char *end; |
274 | }; | 271 | }; |
275 | 272 | ||
276 | |||
277 | /* the sync_buff list head and the lock */ | ||
278 | static LIST_HEAD(ip_vs_sync_queue); | ||
279 | static DEFINE_SPINLOCK(ip_vs_sync_lock); | ||
280 | |||
281 | /* current sync_buff for accepting new conn entries */ | ||
282 | static struct ip_vs_sync_buff *curr_sb = NULL; | ||
283 | static DEFINE_SPINLOCK(curr_sb_lock); | ||
284 | |||
285 | /* ipvs sync daemon state */ | ||
286 | volatile int ip_vs_sync_state = IP_VS_STATE_NONE; | ||
287 | volatile int ip_vs_master_syncid = 0; | ||
288 | volatile int ip_vs_backup_syncid = 0; | ||
289 | |||
290 | /* multicast interface name */ | ||
291 | char ip_vs_master_mcast_ifn[IP_VS_IFNAME_MAXLEN]; | ||
292 | char ip_vs_backup_mcast_ifn[IP_VS_IFNAME_MAXLEN]; | ||
293 | |||
294 | /* sync daemon tasks */ | ||
295 | static struct task_struct *sync_master_thread; | ||
296 | static struct task_struct *sync_backup_thread; | ||
297 | |||
298 | /* multicast addr */ | 273 | /* multicast addr */ |
299 | static struct sockaddr_in mcast_addr = { | 274 | static struct sockaddr_in mcast_addr = { |
300 | .sin_family = AF_INET, | 275 | .sin_family = AF_INET, |
@@ -324,20 +299,20 @@ static void hton_seq(struct ip_vs_seq *ho, struct ip_vs_seq *no) | |||
324 | put_unaligned_be32(ho->previous_delta, &no->previous_delta); | 299 | put_unaligned_be32(ho->previous_delta, &no->previous_delta); |
325 | } | 300 | } |
326 | 301 | ||
327 | static inline struct ip_vs_sync_buff *sb_dequeue(void) | 302 | static inline struct ip_vs_sync_buff *sb_dequeue(struct netns_ipvs *ipvs) |
328 | { | 303 | { |
329 | struct ip_vs_sync_buff *sb; | 304 | struct ip_vs_sync_buff *sb; |
330 | 305 | ||
331 | spin_lock_bh(&ip_vs_sync_lock); | 306 | spin_lock_bh(&ipvs->sync_lock); |
332 | if (list_empty(&ip_vs_sync_queue)) { | 307 | if (list_empty(&ipvs->sync_queue)) { |
333 | sb = NULL; | 308 | sb = NULL; |
334 | } else { | 309 | } else { |
335 | sb = list_entry(ip_vs_sync_queue.next, | 310 | sb = list_entry(ipvs->sync_queue.next, |
336 | struct ip_vs_sync_buff, | 311 | struct ip_vs_sync_buff, |
337 | list); | 312 | list); |
338 | list_del(&sb->list); | 313 | list_del(&sb->list); |
339 | } | 314 | } |
340 | spin_unlock_bh(&ip_vs_sync_lock); | 315 | spin_unlock_bh(&ipvs->sync_lock); |
341 | 316 | ||
342 | return sb; | 317 | return sb; |
343 | } | 318 | } |
@@ -345,25 +320,27 @@ static inline struct ip_vs_sync_buff *sb_dequeue(void) | |||
345 | /* | 320 | /* |
346 | * Create a new sync buffer for Version 1 proto. | 321 | * Create a new sync buffer for Version 1 proto. |
347 | */ | 322 | */ |
348 | static inline struct ip_vs_sync_buff * ip_vs_sync_buff_create(void) | 323 | static inline struct ip_vs_sync_buff * |
324 | ip_vs_sync_buff_create(struct netns_ipvs *ipvs) | ||
349 | { | 325 | { |
350 | struct ip_vs_sync_buff *sb; | 326 | struct ip_vs_sync_buff *sb; |
351 | 327 | ||
352 | if (!(sb=kmalloc(sizeof(struct ip_vs_sync_buff), GFP_ATOMIC))) | 328 | if (!(sb=kmalloc(sizeof(struct ip_vs_sync_buff), GFP_ATOMIC))) |
353 | return NULL; | 329 | return NULL; |
354 | 330 | ||
355 | if (!(sb->mesg=kmalloc(sync_send_mesg_maxlen, GFP_ATOMIC))) { | 331 | sb->mesg = kmalloc(ipvs->send_mesg_maxlen, GFP_ATOMIC); |
332 | if (!sb->mesg) { | ||
356 | kfree(sb); | 333 | kfree(sb); |
357 | return NULL; | 334 | return NULL; |
358 | } | 335 | } |
359 | sb->mesg->reserved = 0; /* old nr_conns i.e. must be zeo now */ | 336 | sb->mesg->reserved = 0; /* old nr_conns i.e. must be zeo now */ |
360 | sb->mesg->version = SYNC_PROTO_VER; | 337 | sb->mesg->version = SYNC_PROTO_VER; |
361 | sb->mesg->syncid = ip_vs_master_syncid; | 338 | sb->mesg->syncid = ipvs->master_syncid; |
362 | sb->mesg->size = sizeof(struct ip_vs_sync_mesg); | 339 | sb->mesg->size = sizeof(struct ip_vs_sync_mesg); |
363 | sb->mesg->nr_conns = 0; | 340 | sb->mesg->nr_conns = 0; |
364 | sb->mesg->spare = 0; | 341 | sb->mesg->spare = 0; |
365 | sb->head = (unsigned char *)sb->mesg + sizeof(struct ip_vs_sync_mesg); | 342 | sb->head = (unsigned char *)sb->mesg + sizeof(struct ip_vs_sync_mesg); |
366 | sb->end = (unsigned char *)sb->mesg + sync_send_mesg_maxlen; | 343 | sb->end = (unsigned char *)sb->mesg + ipvs->send_mesg_maxlen; |
367 | 344 | ||
368 | sb->firstuse = jiffies; | 345 | sb->firstuse = jiffies; |
369 | return sb; | 346 | return sb; |
@@ -375,14 +352,16 @@ static inline void ip_vs_sync_buff_release(struct ip_vs_sync_buff *sb) | |||
375 | kfree(sb); | 352 | kfree(sb); |
376 | } | 353 | } |
377 | 354 | ||
378 | static inline void sb_queue_tail(struct ip_vs_sync_buff *sb) | 355 | static inline void sb_queue_tail(struct netns_ipvs *ipvs) |
379 | { | 356 | { |
380 | spin_lock(&ip_vs_sync_lock); | 357 | struct ip_vs_sync_buff *sb = ipvs->sync_buff; |
381 | if (ip_vs_sync_state & IP_VS_STATE_MASTER) | 358 | |
382 | list_add_tail(&sb->list, &ip_vs_sync_queue); | 359 | spin_lock(&ipvs->sync_lock); |
360 | if (ipvs->sync_state & IP_VS_STATE_MASTER) | ||
361 | list_add_tail(&sb->list, &ipvs->sync_queue); | ||
383 | else | 362 | else |
384 | ip_vs_sync_buff_release(sb); | 363 | ip_vs_sync_buff_release(sb); |
385 | spin_unlock(&ip_vs_sync_lock); | 364 | spin_unlock(&ipvs->sync_lock); |
386 | } | 365 | } |
387 | 366 | ||
388 | /* | 367 | /* |
@@ -390,18 +369,18 @@ static inline void sb_queue_tail(struct ip_vs_sync_buff *sb) | |||
390 | * than the specified time or the specified time is zero. | 369 | * than the specified time or the specified time is zero. |
391 | */ | 370 | */ |
392 | static inline struct ip_vs_sync_buff * | 371 | static inline struct ip_vs_sync_buff * |
393 | get_curr_sync_buff(unsigned long time) | 372 | get_curr_sync_buff(struct netns_ipvs *ipvs, unsigned long time) |
394 | { | 373 | { |
395 | struct ip_vs_sync_buff *sb; | 374 | struct ip_vs_sync_buff *sb; |
396 | 375 | ||
397 | spin_lock_bh(&curr_sb_lock); | 376 | spin_lock_bh(&ipvs->sync_buff_lock); |
398 | if (curr_sb && (time == 0 || | 377 | if (ipvs->sync_buff && (time == 0 || |
399 | time_before(jiffies - curr_sb->firstuse, time))) { | 378 | time_before(jiffies - ipvs->sync_buff->firstuse, time))) { |
400 | sb = curr_sb; | 379 | sb = ipvs->sync_buff; |
401 | curr_sb = NULL; | 380 | ipvs->sync_buff = NULL; |
402 | } else | 381 | } else |
403 | sb = NULL; | 382 | sb = NULL; |
404 | spin_unlock_bh(&curr_sb_lock); | 383 | spin_unlock_bh(&ipvs->sync_buff_lock); |
405 | return sb; | 384 | return sb; |
406 | } | 385 | } |
407 | 386 | ||
@@ -409,33 +388,37 @@ get_curr_sync_buff(unsigned long time) | |||
409 | * Switch mode from sending version 0 or 1 | 388 | * Switch mode from sending version 0 or 1 |
410 | * - must handle sync_buf | 389 | * - must handle sync_buf |
411 | */ | 390 | */ |
412 | void ip_vs_sync_switch_mode(int mode) { | 391 | void ip_vs_sync_switch_mode(struct net *net, int mode) |
392 | { | ||
393 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
413 | 394 | ||
414 | if (!ip_vs_sync_state & IP_VS_STATE_MASTER) | 395 | if (!ipvs->sync_state & IP_VS_STATE_MASTER) |
415 | return; | 396 | return; |
416 | if (mode == sysctl_ip_vs_sync_ver || !curr_sb) | 397 | if (mode == sysctl_ip_vs_sync_ver || !ipvs->sync_buff) |
417 | return; | 398 | return; |
418 | 399 | ||
419 | spin_lock_bh(&curr_sb_lock); | 400 | spin_lock_bh(&ipvs->sync_buff_lock); |
420 | /* Buffer empty ? then let buf_create do the job */ | 401 | /* Buffer empty ? then let buf_create do the job */ |
421 | if ( curr_sb->mesg->size <= sizeof(struct ip_vs_sync_mesg)) { | 402 | if (ipvs->sync_buff->mesg->size <= sizeof(struct ip_vs_sync_mesg)) { |
422 | kfree(curr_sb); | 403 | kfree(ipvs->sync_buff); |
423 | curr_sb = NULL; | 404 | ipvs->sync_buff = NULL; |
424 | } else { | 405 | } else { |
425 | spin_lock_bh(&ip_vs_sync_lock); | 406 | spin_lock_bh(&ipvs->sync_lock); |
426 | if (ip_vs_sync_state & IP_VS_STATE_MASTER) | 407 | if (ipvs->sync_state & IP_VS_STATE_MASTER) |
427 | list_add_tail(&curr_sb->list, &ip_vs_sync_queue); | 408 | list_add_tail(&ipvs->sync_buff->list, |
409 | &ipvs->sync_queue); | ||
428 | else | 410 | else |
429 | ip_vs_sync_buff_release(curr_sb); | 411 | ip_vs_sync_buff_release(ipvs->sync_buff); |
430 | spin_unlock_bh(&ip_vs_sync_lock); | 412 | spin_unlock_bh(&ipvs->sync_lock); |
431 | } | 413 | } |
432 | spin_unlock_bh(&curr_sb_lock); | 414 | spin_unlock_bh(&ipvs->sync_buff_lock); |
433 | } | 415 | } |
434 | 416 | ||
435 | /* | 417 | /* |
436 | * Create a new sync buffer for Version 0 proto. | 418 | * Create a new sync buffer for Version 0 proto. |
437 | */ | 419 | */ |
438 | static inline struct ip_vs_sync_buff * ip_vs_sync_buff_create_v0(void) | 420 | static inline struct ip_vs_sync_buff * |
421 | ip_vs_sync_buff_create_v0(struct netns_ipvs *ipvs) | ||
439 | { | 422 | { |
440 | struct ip_vs_sync_buff *sb; | 423 | struct ip_vs_sync_buff *sb; |
441 | struct ip_vs_sync_mesg_v0 *mesg; | 424 | struct ip_vs_sync_mesg_v0 *mesg; |
@@ -443,16 +426,17 @@ static inline struct ip_vs_sync_buff * ip_vs_sync_buff_create_v0(void) | |||
443 | if (!(sb=kmalloc(sizeof(struct ip_vs_sync_buff), GFP_ATOMIC))) | 426 | if (!(sb=kmalloc(sizeof(struct ip_vs_sync_buff), GFP_ATOMIC))) |
444 | return NULL; | 427 | return NULL; |
445 | 428 | ||
446 | if (!(sb->mesg=kmalloc(sync_send_mesg_maxlen, GFP_ATOMIC))) { | 429 | sb->mesg = kmalloc(ipvs->send_mesg_maxlen, GFP_ATOMIC); |
430 | if (!sb->mesg) { | ||
447 | kfree(sb); | 431 | kfree(sb); |
448 | return NULL; | 432 | return NULL; |
449 | } | 433 | } |
450 | mesg = (struct ip_vs_sync_mesg_v0 *)sb->mesg; | 434 | mesg = (struct ip_vs_sync_mesg_v0 *)sb->mesg; |
451 | mesg->nr_conns = 0; | 435 | mesg->nr_conns = 0; |
452 | mesg->syncid = ip_vs_master_syncid; | 436 | mesg->syncid = ipvs->master_syncid; |
453 | mesg->size = 4; | 437 | mesg->size = sizeof(struct ip_vs_sync_mesg_v0); |
454 | sb->head = (unsigned char *)mesg + 4; | 438 | sb->head = (unsigned char *)mesg + sizeof(struct ip_vs_sync_mesg_v0); |
455 | sb->end = (unsigned char *)mesg + sync_send_mesg_maxlen; | 439 | sb->end = (unsigned char *)mesg + ipvs->send_mesg_maxlen; |
456 | sb->firstuse = jiffies; | 440 | sb->firstuse = jiffies; |
457 | return sb; | 441 | return sb; |
458 | } | 442 | } |
@@ -461,8 +445,9 @@ static inline struct ip_vs_sync_buff * ip_vs_sync_buff_create_v0(void) | |||
461 | * Version 0 , could be switched in by sys_ctl. | 445 | * Version 0 , could be switched in by sys_ctl. |
462 | * Add an ip_vs_conn information into the current sync_buff. | 446 | * Add an ip_vs_conn information into the current sync_buff. |
463 | */ | 447 | */ |
464 | void ip_vs_sync_conn_v0(struct ip_vs_conn *cp) | 448 | void ip_vs_sync_conn_v0(struct net *net, struct ip_vs_conn *cp) |
465 | { | 449 | { |
450 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
466 | struct ip_vs_sync_mesg_v0 *m; | 451 | struct ip_vs_sync_mesg_v0 *m; |
467 | struct ip_vs_sync_conn_v0 *s; | 452 | struct ip_vs_sync_conn_v0 *s; |
468 | int len; | 453 | int len; |
@@ -473,10 +458,12 @@ void ip_vs_sync_conn_v0(struct ip_vs_conn *cp) | |||
473 | if (cp->flags & IP_VS_CONN_F_ONE_PACKET) | 458 | if (cp->flags & IP_VS_CONN_F_ONE_PACKET) |
474 | return; | 459 | return; |
475 | 460 | ||
476 | spin_lock(&curr_sb_lock); | 461 | spin_lock(&ipvs->sync_buff_lock); |
477 | if (!curr_sb) { | 462 | if (!ipvs->sync_buff) { |
478 | if (!(curr_sb=ip_vs_sync_buff_create_v0())) { | 463 | ipvs->sync_buff = |
479 | spin_unlock(&curr_sb_lock); | 464 | ip_vs_sync_buff_create_v0(ipvs); |
465 | if (!ipvs->sync_buff) { | ||
466 | spin_unlock(&ipvs->sync_buff_lock); | ||
480 | pr_err("ip_vs_sync_buff_create failed.\n"); | 467 | pr_err("ip_vs_sync_buff_create failed.\n"); |
481 | return; | 468 | return; |
482 | } | 469 | } |
@@ -484,8 +471,8 @@ void ip_vs_sync_conn_v0(struct ip_vs_conn *cp) | |||
484 | 471 | ||
485 | len = (cp->flags & IP_VS_CONN_F_SEQ_MASK) ? FULL_CONN_SIZE : | 472 | len = (cp->flags & IP_VS_CONN_F_SEQ_MASK) ? FULL_CONN_SIZE : |
486 | SIMPLE_CONN_SIZE; | 473 | SIMPLE_CONN_SIZE; |
487 | m = (struct ip_vs_sync_mesg_v0 *)curr_sb->mesg; | 474 | m = (struct ip_vs_sync_mesg_v0 *)ipvs->sync_buff->mesg; |
488 | s = (struct ip_vs_sync_conn_v0 *)curr_sb->head; | 475 | s = (struct ip_vs_sync_conn_v0 *)ipvs->sync_buff->head; |
489 | 476 | ||
490 | /* copy members */ | 477 | /* copy members */ |
491 | s->reserved = 0; | 478 | s->reserved = 0; |
@@ -506,18 +493,18 @@ void ip_vs_sync_conn_v0(struct ip_vs_conn *cp) | |||
506 | 493 | ||
507 | m->nr_conns++; | 494 | m->nr_conns++; |
508 | m->size += len; | 495 | m->size += len; |
509 | curr_sb->head += len; | 496 | ipvs->sync_buff->head += len; |
510 | 497 | ||
511 | /* check if there is a space for next one */ | 498 | /* check if there is a space for next one */ |
512 | if (curr_sb->head + FULL_CONN_SIZE > curr_sb->end) { | 499 | if (ipvs->sync_buff->head + FULL_CONN_SIZE > ipvs->sync_buff->end) { |
513 | sb_queue_tail(curr_sb); | 500 | sb_queue_tail(ipvs); |
514 | curr_sb = NULL; | 501 | ipvs->sync_buff = NULL; |
515 | } | 502 | } |
516 | spin_unlock(&curr_sb_lock); | 503 | spin_unlock(&ipvs->sync_buff_lock); |
517 | 504 | ||
518 | /* synchronize its controller if it has */ | 505 | /* synchronize its controller if it has */ |
519 | if (cp->control) | 506 | if (cp->control) |
520 | ip_vs_sync_conn(cp->control); | 507 | ip_vs_sync_conn(net, cp->control); |
521 | } | 508 | } |
522 | 509 | ||
523 | /* | 510 | /* |
@@ -525,8 +512,9 @@ void ip_vs_sync_conn_v0(struct ip_vs_conn *cp) | |||
525 | * Called by ip_vs_in. | 512 | * Called by ip_vs_in. |
526 | * Sending Version 1 messages | 513 | * Sending Version 1 messages |
527 | */ | 514 | */ |
528 | void ip_vs_sync_conn(struct ip_vs_conn *cp) | 515 | void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp) |
529 | { | 516 | { |
517 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
530 | struct ip_vs_sync_mesg *m; | 518 | struct ip_vs_sync_mesg *m; |
531 | union ip_vs_sync_conn *s; | 519 | union ip_vs_sync_conn *s; |
532 | __u8 *p; | 520 | __u8 *p; |
@@ -534,7 +522,7 @@ void ip_vs_sync_conn(struct ip_vs_conn *cp) | |||
534 | 522 | ||
535 | /* Handle old version of the protocol */ | 523 | /* Handle old version of the protocol */ |
536 | if (sysctl_ip_vs_sync_ver == 0) { | 524 | if (sysctl_ip_vs_sync_ver == 0) { |
537 | ip_vs_sync_conn_v0(cp); | 525 | ip_vs_sync_conn_v0(net, cp); |
538 | return; | 526 | return; |
539 | } | 527 | } |
540 | /* Do not sync ONE PACKET */ | 528 | /* Do not sync ONE PACKET */ |
@@ -551,7 +539,7 @@ sloop: | |||
551 | pe_name_len = strnlen(cp->pe->name, IP_VS_PENAME_MAXLEN); | 539 | pe_name_len = strnlen(cp->pe->name, IP_VS_PENAME_MAXLEN); |
552 | } | 540 | } |
553 | 541 | ||
554 | spin_lock(&curr_sb_lock); | 542 | spin_lock(&ipvs->sync_buff_lock); |
555 | 543 | ||
556 | #ifdef CONFIG_IP_VS_IPV6 | 544 | #ifdef CONFIG_IP_VS_IPV6 |
557 | if (cp->af == AF_INET6) | 545 | if (cp->af == AF_INET6) |
@@ -570,26 +558,27 @@ sloop: | |||
570 | 558 | ||
571 | /* check if there is a space for this one */ | 559 | /* check if there is a space for this one */ |
572 | pad = 0; | 560 | pad = 0; |
573 | if (curr_sb) { | 561 | if (ipvs->sync_buff) { |
574 | pad = (4 - (size_t)curr_sb->head) & 3; | 562 | pad = (4 - (size_t)ipvs->sync_buff->head) & 3; |
575 | if (curr_sb->head + len + pad > curr_sb->end) { | 563 | if (ipvs->sync_buff->head + len + pad > ipvs->sync_buff->end) { |
576 | sb_queue_tail(curr_sb); | 564 | sb_queue_tail(ipvs); |
577 | curr_sb = NULL; | 565 | ipvs->sync_buff = NULL; |
578 | pad = 0; | 566 | pad = 0; |
579 | } | 567 | } |
580 | } | 568 | } |
581 | 569 | ||
582 | if (!curr_sb) { | 570 | if (!ipvs->sync_buff) { |
583 | if (!(curr_sb=ip_vs_sync_buff_create())) { | 571 | ipvs->sync_buff = ip_vs_sync_buff_create(ipvs); |
584 | spin_unlock(&curr_sb_lock); | 572 | if (!ipvs->sync_buff) { |
573 | spin_unlock(&ipvs->sync_buff_lock); | ||
585 | pr_err("ip_vs_sync_buff_create failed.\n"); | 574 | pr_err("ip_vs_sync_buff_create failed.\n"); |
586 | return; | 575 | return; |
587 | } | 576 | } |
588 | } | 577 | } |
589 | 578 | ||
590 | m = curr_sb->mesg; | 579 | m = ipvs->sync_buff->mesg; |
591 | p = curr_sb->head; | 580 | p = ipvs->sync_buff->head; |
592 | curr_sb->head += pad + len; | 581 | ipvs->sync_buff->head += pad + len; |
593 | m->size += pad + len; | 582 | m->size += pad + len; |
594 | /* Add ev. padding from prev. sync_conn */ | 583 | /* Add ev. padding from prev. sync_conn */ |
595 | while (pad--) | 584 | while (pad--) |
@@ -647,7 +636,7 @@ sloop: | |||
647 | } | 636 | } |
648 | } | 637 | } |
649 | 638 | ||
650 | spin_unlock(&curr_sb_lock); | 639 | spin_unlock(&ipvs->sync_buff_lock); |
651 | 640 | ||
652 | control: | 641 | control: |
653 | /* synchronize its controller if it has */ | 642 | /* synchronize its controller if it has */ |
@@ -699,7 +688,8 @@ ip_vs_conn_fill_param_sync(int af, union ip_vs_sync_conn *sc, | |||
699 | buff[pe_name_len]=0; | 688 | buff[pe_name_len]=0; |
700 | p->pe = __ip_vs_pe_getbyname(buff); | 689 | p->pe = __ip_vs_pe_getbyname(buff); |
701 | if (!p->pe) { | 690 | if (!p->pe) { |
702 | IP_VS_DBG(3, "BACKUP, no %s engine found/loaded\n", buff); | 691 | IP_VS_DBG(3, "BACKUP, no %s engine found/loaded\n", |
692 | buff); | ||
703 | return 1; | 693 | return 1; |
704 | } | 694 | } |
705 | } else { | 695 | } else { |
@@ -748,7 +738,7 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param, | |||
748 | * If it is not found the connection will remain unbound | 738 | * If it is not found the connection will remain unbound |
749 | * but still handled. | 739 | * but still handled. |
750 | */ | 740 | */ |
751 | dest = ip_vs_find_dest(&init_net, type, daddr, dport, param->vaddr, | 741 | dest = ip_vs_find_dest(net, type, daddr, dport, param->vaddr, |
752 | param->vport, protocol, fwmark); | 742 | param->vport, protocol, fwmark); |
753 | 743 | ||
754 | /* Set the approprite ativity flag */ | 744 | /* Set the approprite ativity flag */ |
@@ -1089,6 +1079,7 @@ out: | |||
1089 | static void ip_vs_process_message(struct net *net, __u8 *buffer, | 1079 | static void ip_vs_process_message(struct net *net, __u8 *buffer, |
1090 | const size_t buflen) | 1080 | const size_t buflen) |
1091 | { | 1081 | { |
1082 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
1092 | struct ip_vs_sync_mesg *m2 = (struct ip_vs_sync_mesg *)buffer; | 1083 | struct ip_vs_sync_mesg *m2 = (struct ip_vs_sync_mesg *)buffer; |
1093 | __u8 *p, *msg_end; | 1084 | __u8 *p, *msg_end; |
1094 | int i, nr_conns; | 1085 | int i, nr_conns; |
@@ -1105,7 +1096,7 @@ static void ip_vs_process_message(struct net *net, __u8 *buffer, | |||
1105 | return; | 1096 | return; |
1106 | } | 1097 | } |
1107 | /* SyncID sanity check */ | 1098 | /* SyncID sanity check */ |
1108 | if (ip_vs_backup_syncid != 0 && m2->syncid != ip_vs_backup_syncid) { | 1099 | if (ipvs->backup_syncid != 0 && m2->syncid != ipvs->backup_syncid) { |
1109 | IP_VS_DBG(7, "BACKUP, Ignoring syncid = %d\n", m2->syncid); | 1100 | IP_VS_DBG(7, "BACKUP, Ignoring syncid = %d\n", m2->syncid); |
1110 | return; | 1101 | return; |
1111 | } | 1102 | } |
@@ -1190,8 +1181,10 @@ static int set_mcast_if(struct sock *sk, char *ifname) | |||
1190 | { | 1181 | { |
1191 | struct net_device *dev; | 1182 | struct net_device *dev; |
1192 | struct inet_sock *inet = inet_sk(sk); | 1183 | struct inet_sock *inet = inet_sk(sk); |
1184 | struct net *net = sock_net(sk); | ||
1193 | 1185 | ||
1194 | if ((dev = __dev_get_by_name(&init_net, ifname)) == NULL) | 1186 | dev = __dev_get_by_name(net, ifname); |
1187 | if (!dev) | ||
1195 | return -ENODEV; | 1188 | return -ENODEV; |
1196 | 1189 | ||
1197 | if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if) | 1190 | if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if) |
@@ -1210,30 +1203,33 @@ static int set_mcast_if(struct sock *sk, char *ifname) | |||
1210 | * Set the maximum length of sync message according to the | 1203 | * Set the maximum length of sync message according to the |
1211 | * specified interface's MTU. | 1204 | * specified interface's MTU. |
1212 | */ | 1205 | */ |
1213 | static int set_sync_mesg_maxlen(int sync_state) | 1206 | static int set_sync_mesg_maxlen(struct net *net, int sync_state) |
1214 | { | 1207 | { |
1208 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
1215 | struct net_device *dev; | 1209 | struct net_device *dev; |
1216 | int num; | 1210 | int num; |
1217 | 1211 | ||
1218 | if (sync_state == IP_VS_STATE_MASTER) { | 1212 | if (sync_state == IP_VS_STATE_MASTER) { |
1219 | if ((dev = __dev_get_by_name(&init_net, ip_vs_master_mcast_ifn)) == NULL) | 1213 | dev = __dev_get_by_name(net, ipvs->master_mcast_ifn); |
1214 | if (!dev) | ||
1220 | return -ENODEV; | 1215 | return -ENODEV; |
1221 | 1216 | ||
1222 | num = (dev->mtu - sizeof(struct iphdr) - | 1217 | num = (dev->mtu - sizeof(struct iphdr) - |
1223 | sizeof(struct udphdr) - | 1218 | sizeof(struct udphdr) - |
1224 | SYNC_MESG_HEADER_LEN - 20) / SIMPLE_CONN_SIZE; | 1219 | SYNC_MESG_HEADER_LEN - 20) / SIMPLE_CONN_SIZE; |
1225 | sync_send_mesg_maxlen = SYNC_MESG_HEADER_LEN + | 1220 | ipvs->send_mesg_maxlen = SYNC_MESG_HEADER_LEN + |
1226 | SIMPLE_CONN_SIZE * min(num, MAX_CONNS_PER_SYNCBUFF); | 1221 | SIMPLE_CONN_SIZE * min(num, MAX_CONNS_PER_SYNCBUFF); |
1227 | IP_VS_DBG(7, "setting the maximum length of sync sending " | 1222 | IP_VS_DBG(7, "setting the maximum length of sync sending " |
1228 | "message %d.\n", sync_send_mesg_maxlen); | 1223 | "message %d.\n", ipvs->send_mesg_maxlen); |
1229 | } else if (sync_state == IP_VS_STATE_BACKUP) { | 1224 | } else if (sync_state == IP_VS_STATE_BACKUP) { |
1230 | if ((dev = __dev_get_by_name(&init_net, ip_vs_backup_mcast_ifn)) == NULL) | 1225 | dev = __dev_get_by_name(net, ipvs->backup_mcast_ifn); |
1226 | if (!dev) | ||
1231 | return -ENODEV; | 1227 | return -ENODEV; |
1232 | 1228 | ||
1233 | sync_recv_mesg_maxlen = dev->mtu - | 1229 | ipvs->recv_mesg_maxlen = dev->mtu - |
1234 | sizeof(struct iphdr) - sizeof(struct udphdr); | 1230 | sizeof(struct iphdr) - sizeof(struct udphdr); |
1235 | IP_VS_DBG(7, "setting the maximum length of sync receiving " | 1231 | IP_VS_DBG(7, "setting the maximum length of sync receiving " |
1236 | "message %d.\n", sync_recv_mesg_maxlen); | 1232 | "message %d.\n", ipvs->recv_mesg_maxlen); |
1237 | } | 1233 | } |
1238 | 1234 | ||
1239 | return 0; | 1235 | return 0; |
@@ -1248,6 +1244,7 @@ static int set_sync_mesg_maxlen(int sync_state) | |||
1248 | static int | 1244 | static int |
1249 | join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname) | 1245 | join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname) |
1250 | { | 1246 | { |
1247 | struct net *net = sock_net(sk); | ||
1251 | struct ip_mreqn mreq; | 1248 | struct ip_mreqn mreq; |
1252 | struct net_device *dev; | 1249 | struct net_device *dev; |
1253 | int ret; | 1250 | int ret; |
@@ -1255,7 +1252,8 @@ join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname) | |||
1255 | memset(&mreq, 0, sizeof(mreq)); | 1252 | memset(&mreq, 0, sizeof(mreq)); |
1256 | memcpy(&mreq.imr_multiaddr, addr, sizeof(struct in_addr)); | 1253 | memcpy(&mreq.imr_multiaddr, addr, sizeof(struct in_addr)); |
1257 | 1254 | ||
1258 | if ((dev = __dev_get_by_name(&init_net, ifname)) == NULL) | 1255 | dev = __dev_get_by_name(net, ifname); |
1256 | if (!dev) | ||
1259 | return -ENODEV; | 1257 | return -ENODEV; |
1260 | if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if) | 1258 | if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if) |
1261 | return -EINVAL; | 1259 | return -EINVAL; |
@@ -1272,11 +1270,13 @@ join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname) | |||
1272 | 1270 | ||
1273 | static int bind_mcastif_addr(struct socket *sock, char *ifname) | 1271 | static int bind_mcastif_addr(struct socket *sock, char *ifname) |
1274 | { | 1272 | { |
1273 | struct net *net = sock_net(sock->sk); | ||
1275 | struct net_device *dev; | 1274 | struct net_device *dev; |
1276 | __be32 addr; | 1275 | __be32 addr; |
1277 | struct sockaddr_in sin; | 1276 | struct sockaddr_in sin; |
1278 | 1277 | ||
1279 | if ((dev = __dev_get_by_name(&init_net, ifname)) == NULL) | 1278 | dev = __dev_get_by_name(net, ifname); |
1279 | if (!dev) | ||
1280 | return -ENODEV; | 1280 | return -ENODEV; |
1281 | 1281 | ||
1282 | addr = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE); | 1282 | addr = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE); |
@@ -1298,8 +1298,9 @@ static int bind_mcastif_addr(struct socket *sock, char *ifname) | |||
1298 | /* | 1298 | /* |
1299 | * Set up sending multicast socket over UDP | 1299 | * Set up sending multicast socket over UDP |
1300 | */ | 1300 | */ |
1301 | static struct socket * make_send_sock(void) | 1301 | static struct socket *make_send_sock(struct net *net) |
1302 | { | 1302 | { |
1303 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
1303 | struct socket *sock; | 1304 | struct socket *sock; |
1304 | int result; | 1305 | int result; |
1305 | 1306 | ||
@@ -1310,7 +1311,7 @@ static struct socket * make_send_sock(void) | |||
1310 | return ERR_PTR(result); | 1311 | return ERR_PTR(result); |
1311 | } | 1312 | } |
1312 | 1313 | ||
1313 | result = set_mcast_if(sock->sk, ip_vs_master_mcast_ifn); | 1314 | result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn); |
1314 | if (result < 0) { | 1315 | if (result < 0) { |
1315 | pr_err("Error setting outbound mcast interface\n"); | 1316 | pr_err("Error setting outbound mcast interface\n"); |
1316 | goto error; | 1317 | goto error; |
@@ -1319,7 +1320,7 @@ static struct socket * make_send_sock(void) | |||
1319 | set_mcast_loop(sock->sk, 0); | 1320 | set_mcast_loop(sock->sk, 0); |
1320 | set_mcast_ttl(sock->sk, 1); | 1321 | set_mcast_ttl(sock->sk, 1); |
1321 | 1322 | ||
1322 | result = bind_mcastif_addr(sock, ip_vs_master_mcast_ifn); | 1323 | result = bind_mcastif_addr(sock, ipvs->master_mcast_ifn); |
1323 | if (result < 0) { | 1324 | if (result < 0) { |
1324 | pr_err("Error binding address of the mcast interface\n"); | 1325 | pr_err("Error binding address of the mcast interface\n"); |
1325 | goto error; | 1326 | goto error; |
@@ -1343,8 +1344,9 @@ static struct socket * make_send_sock(void) | |||
1343 | /* | 1344 | /* |
1344 | * Set up receiving multicast socket over UDP | 1345 | * Set up receiving multicast socket over UDP |
1345 | */ | 1346 | */ |
1346 | static struct socket * make_receive_sock(void) | 1347 | static struct socket *make_receive_sock(struct net *net) |
1347 | { | 1348 | { |
1349 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
1348 | struct socket *sock; | 1350 | struct socket *sock; |
1349 | int result; | 1351 | int result; |
1350 | 1352 | ||
@@ -1368,7 +1370,7 @@ static struct socket * make_receive_sock(void) | |||
1368 | /* join the multicast group */ | 1370 | /* join the multicast group */ |
1369 | result = join_mcast_group(sock->sk, | 1371 | result = join_mcast_group(sock->sk, |
1370 | (struct in_addr *) &mcast_addr.sin_addr, | 1372 | (struct in_addr *) &mcast_addr.sin_addr, |
1371 | ip_vs_backup_mcast_ifn); | 1373 | ipvs->backup_mcast_ifn); |
1372 | if (result < 0) { | 1374 | if (result < 0) { |
1373 | pr_err("Error joining to the multicast group\n"); | 1375 | pr_err("Error joining to the multicast group\n"); |
1374 | goto error; | 1376 | goto error; |
@@ -1439,20 +1441,21 @@ ip_vs_receive(struct socket *sock, char *buffer, const size_t buflen) | |||
1439 | static int sync_thread_master(void *data) | 1441 | static int sync_thread_master(void *data) |
1440 | { | 1442 | { |
1441 | struct ip_vs_sync_thread_data *tinfo = data; | 1443 | struct ip_vs_sync_thread_data *tinfo = data; |
1444 | struct netns_ipvs *ipvs = net_ipvs(tinfo->net); | ||
1442 | struct ip_vs_sync_buff *sb; | 1445 | struct ip_vs_sync_buff *sb; |
1443 | 1446 | ||
1444 | pr_info("sync thread started: state = MASTER, mcast_ifn = %s, " | 1447 | pr_info("sync thread started: state = MASTER, mcast_ifn = %s, " |
1445 | "syncid = %d\n", | 1448 | "syncid = %d\n", |
1446 | ip_vs_master_mcast_ifn, ip_vs_master_syncid); | 1449 | ipvs->master_mcast_ifn, ipvs->master_syncid); |
1447 | 1450 | ||
1448 | while (!kthread_should_stop()) { | 1451 | while (!kthread_should_stop()) { |
1449 | while ((sb = sb_dequeue())) { | 1452 | while ((sb = sb_dequeue(ipvs))) { |
1450 | ip_vs_send_sync_msg(tinfo->sock, sb->mesg); | 1453 | ip_vs_send_sync_msg(tinfo->sock, sb->mesg); |
1451 | ip_vs_sync_buff_release(sb); | 1454 | ip_vs_sync_buff_release(sb); |
1452 | } | 1455 | } |
1453 | 1456 | ||
1454 | /* check if entries stay in curr_sb for 2 seconds */ | 1457 | /* check if entries stay in ipvs->sync_buff for 2 seconds */ |
1455 | sb = get_curr_sync_buff(2 * HZ); | 1458 | sb = get_curr_sync_buff(ipvs, 2 * HZ); |
1456 | if (sb) { | 1459 | if (sb) { |
1457 | ip_vs_send_sync_msg(tinfo->sock, sb->mesg); | 1460 | ip_vs_send_sync_msg(tinfo->sock, sb->mesg); |
1458 | ip_vs_sync_buff_release(sb); | 1461 | ip_vs_sync_buff_release(sb); |
@@ -1462,14 +1465,13 @@ static int sync_thread_master(void *data) | |||
1462 | } | 1465 | } |
1463 | 1466 | ||
1464 | /* clean up the sync_buff queue */ | 1467 | /* clean up the sync_buff queue */ |
1465 | while ((sb=sb_dequeue())) { | 1468 | while ((sb = sb_dequeue(ipvs))) |
1466 | ip_vs_sync_buff_release(sb); | 1469 | ip_vs_sync_buff_release(sb); |
1467 | } | ||
1468 | 1470 | ||
1469 | /* clean up the current sync_buff */ | 1471 | /* clean up the current sync_buff */ |
1470 | if ((sb = get_curr_sync_buff(0))) { | 1472 | sb = get_curr_sync_buff(ipvs, 0); |
1473 | if (sb) | ||
1471 | ip_vs_sync_buff_release(sb); | 1474 | ip_vs_sync_buff_release(sb); |
1472 | } | ||
1473 | 1475 | ||
1474 | /* release the sending multicast socket */ | 1476 | /* release the sending multicast socket */ |
1475 | sock_release(tinfo->sock); | 1477 | sock_release(tinfo->sock); |
@@ -1482,11 +1484,12 @@ static int sync_thread_master(void *data) | |||
1482 | static int sync_thread_backup(void *data) | 1484 | static int sync_thread_backup(void *data) |
1483 | { | 1485 | { |
1484 | struct ip_vs_sync_thread_data *tinfo = data; | 1486 | struct ip_vs_sync_thread_data *tinfo = data; |
1487 | struct netns_ipvs *ipvs = net_ipvs(tinfo->net); | ||
1485 | int len; | 1488 | int len; |
1486 | 1489 | ||
1487 | pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, " | 1490 | pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, " |
1488 | "syncid = %d\n", | 1491 | "syncid = %d\n", |
1489 | ip_vs_backup_mcast_ifn, ip_vs_backup_syncid); | 1492 | ipvs->backup_mcast_ifn, ipvs->backup_syncid); |
1490 | 1493 | ||
1491 | while (!kthread_should_stop()) { | 1494 | while (!kthread_should_stop()) { |
1492 | wait_event_interruptible(*sk_sleep(tinfo->sock->sk), | 1495 | wait_event_interruptible(*sk_sleep(tinfo->sock->sk), |
@@ -1496,7 +1499,7 @@ static int sync_thread_backup(void *data) | |||
1496 | /* do we have data now? */ | 1499 | /* do we have data now? */ |
1497 | while (!skb_queue_empty(&(tinfo->sock->sk->sk_receive_queue))) { | 1500 | while (!skb_queue_empty(&(tinfo->sock->sk->sk_receive_queue))) { |
1498 | len = ip_vs_receive(tinfo->sock, tinfo->buf, | 1501 | len = ip_vs_receive(tinfo->sock, tinfo->buf, |
1499 | sync_recv_mesg_maxlen); | 1502 | ipvs->recv_mesg_maxlen); |
1500 | if (len <= 0) { | 1503 | if (len <= 0) { |
1501 | pr_err("receiving message error\n"); | 1504 | pr_err("receiving message error\n"); |
1502 | break; | 1505 | break; |
@@ -1505,7 +1508,7 @@ static int sync_thread_backup(void *data) | |||
1505 | /* disable bottom half, because it accesses the data | 1508 | /* disable bottom half, because it accesses the data |
1506 | shared by softirq while getting/creating conns */ | 1509 | shared by softirq while getting/creating conns */ |
1507 | local_bh_disable(); | 1510 | local_bh_disable(); |
1508 | ip_vs_process_message(&init_net, tinfo->buf, len); | 1511 | ip_vs_process_message(tinfo->net, tinfo->buf, len); |
1509 | local_bh_enable(); | 1512 | local_bh_enable(); |
1510 | } | 1513 | } |
1511 | } | 1514 | } |
@@ -1519,11 +1522,12 @@ static int sync_thread_backup(void *data) | |||
1519 | } | 1522 | } |
1520 | 1523 | ||
1521 | 1524 | ||
1522 | int start_sync_thread(int state, char *mcast_ifn, __u8 syncid) | 1525 | int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid) |
1523 | { | 1526 | { |
1524 | struct ip_vs_sync_thread_data *tinfo; | 1527 | struct ip_vs_sync_thread_data *tinfo; |
1525 | struct task_struct **realtask, *task; | 1528 | struct task_struct **realtask, *task; |
1526 | struct socket *sock; | 1529 | struct socket *sock; |
1530 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
1527 | char *name, *buf = NULL; | 1531 | char *name, *buf = NULL; |
1528 | int (*threadfn)(void *data); | 1532 | int (*threadfn)(void *data); |
1529 | int result = -ENOMEM; | 1533 | int result = -ENOMEM; |
@@ -1533,27 +1537,27 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid) | |||
1533 | sizeof(struct ip_vs_sync_conn_v0)); | 1537 | sizeof(struct ip_vs_sync_conn_v0)); |
1534 | 1538 | ||
1535 | if (state == IP_VS_STATE_MASTER) { | 1539 | if (state == IP_VS_STATE_MASTER) { |
1536 | if (sync_master_thread) | 1540 | if (ipvs->master_thread) |
1537 | return -EEXIST; | 1541 | return -EEXIST; |
1538 | 1542 | ||
1539 | strlcpy(ip_vs_master_mcast_ifn, mcast_ifn, | 1543 | strlcpy(ipvs->master_mcast_ifn, mcast_ifn, |
1540 | sizeof(ip_vs_master_mcast_ifn)); | 1544 | sizeof(ipvs->master_mcast_ifn)); |
1541 | ip_vs_master_syncid = syncid; | 1545 | ipvs->master_syncid = syncid; |
1542 | realtask = &sync_master_thread; | 1546 | realtask = &ipvs->master_thread; |
1543 | name = "ipvs_syncmaster"; | 1547 | name = "ipvs_master:%d"; |
1544 | threadfn = sync_thread_master; | 1548 | threadfn = sync_thread_master; |
1545 | sock = make_send_sock(); | 1549 | sock = make_send_sock(net); |
1546 | } else if (state == IP_VS_STATE_BACKUP) { | 1550 | } else if (state == IP_VS_STATE_BACKUP) { |
1547 | if (sync_backup_thread) | 1551 | if (ipvs->backup_thread) |
1548 | return -EEXIST; | 1552 | return -EEXIST; |
1549 | 1553 | ||
1550 | strlcpy(ip_vs_backup_mcast_ifn, mcast_ifn, | 1554 | strlcpy(ipvs->backup_mcast_ifn, mcast_ifn, |
1551 | sizeof(ip_vs_backup_mcast_ifn)); | 1555 | sizeof(ipvs->backup_mcast_ifn)); |
1552 | ip_vs_backup_syncid = syncid; | 1556 | ipvs->backup_syncid = syncid; |
1553 | realtask = &sync_backup_thread; | 1557 | realtask = &ipvs->backup_thread; |
1554 | name = "ipvs_syncbackup"; | 1558 | name = "ipvs_backup:%d"; |
1555 | threadfn = sync_thread_backup; | 1559 | threadfn = sync_thread_backup; |
1556 | sock = make_receive_sock(); | 1560 | sock = make_receive_sock(net); |
1557 | } else { | 1561 | } else { |
1558 | return -EINVAL; | 1562 | return -EINVAL; |
1559 | } | 1563 | } |
@@ -1563,9 +1567,9 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid) | |||
1563 | goto out; | 1567 | goto out; |
1564 | } | 1568 | } |
1565 | 1569 | ||
1566 | set_sync_mesg_maxlen(state); | 1570 | set_sync_mesg_maxlen(net, state); |
1567 | if (state == IP_VS_STATE_BACKUP) { | 1571 | if (state == IP_VS_STATE_BACKUP) { |
1568 | buf = kmalloc(sync_recv_mesg_maxlen, GFP_KERNEL); | 1572 | buf = kmalloc(ipvs->recv_mesg_maxlen, GFP_KERNEL); |
1569 | if (!buf) | 1573 | if (!buf) |
1570 | goto outsocket; | 1574 | goto outsocket; |
1571 | } | 1575 | } |
@@ -1574,10 +1578,11 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid) | |||
1574 | if (!tinfo) | 1578 | if (!tinfo) |
1575 | goto outbuf; | 1579 | goto outbuf; |
1576 | 1580 | ||
1581 | tinfo->net = net; | ||
1577 | tinfo->sock = sock; | 1582 | tinfo->sock = sock; |
1578 | tinfo->buf = buf; | 1583 | tinfo->buf = buf; |
1579 | 1584 | ||
1580 | task = kthread_run(threadfn, tinfo, name); | 1585 | task = kthread_run(threadfn, tinfo, name, ipvs->gen); |
1581 | if (IS_ERR(task)) { | 1586 | if (IS_ERR(task)) { |
1582 | result = PTR_ERR(task); | 1587 | result = PTR_ERR(task); |
1583 | goto outtinfo; | 1588 | goto outtinfo; |
@@ -1585,7 +1590,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid) | |||
1585 | 1590 | ||
1586 | /* mark as active */ | 1591 | /* mark as active */ |
1587 | *realtask = task; | 1592 | *realtask = task; |
1588 | ip_vs_sync_state |= state; | 1593 | ipvs->sync_state |= state; |
1589 | 1594 | ||
1590 | /* increase the module use count */ | 1595 | /* increase the module use count */ |
1591 | ip_vs_use_count_inc(); | 1596 | ip_vs_use_count_inc(); |
@@ -1603,16 +1608,18 @@ out: | |||
1603 | } | 1608 | } |
1604 | 1609 | ||
1605 | 1610 | ||
1606 | int stop_sync_thread(int state) | 1611 | int stop_sync_thread(struct net *net, int state) |
1607 | { | 1612 | { |
1613 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
1614 | |||
1608 | IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current)); | 1615 | IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current)); |
1609 | 1616 | ||
1610 | if (state == IP_VS_STATE_MASTER) { | 1617 | if (state == IP_VS_STATE_MASTER) { |
1611 | if (!sync_master_thread) | 1618 | if (!ipvs->master_thread) |
1612 | return -ESRCH; | 1619 | return -ESRCH; |
1613 | 1620 | ||
1614 | pr_info("stopping master sync thread %d ...\n", | 1621 | pr_info("stopping master sync thread %d ...\n", |
1615 | task_pid_nr(sync_master_thread)); | 1622 | task_pid_nr(ipvs->master_thread)); |
1616 | 1623 | ||
1617 | /* | 1624 | /* |
1618 | * The lock synchronizes with sb_queue_tail(), so that we don't | 1625 | * The lock synchronizes with sb_queue_tail(), so that we don't |
@@ -1620,21 +1627,21 @@ int stop_sync_thread(int state) | |||
1620 | * progress of stopping the master sync daemon. | 1627 | * progress of stopping the master sync daemon. |
1621 | */ | 1628 | */ |
1622 | 1629 | ||
1623 | spin_lock_bh(&ip_vs_sync_lock); | 1630 | spin_lock_bh(&ipvs->sync_lock); |
1624 | ip_vs_sync_state &= ~IP_VS_STATE_MASTER; | 1631 | ipvs->sync_state &= ~IP_VS_STATE_MASTER; |
1625 | spin_unlock_bh(&ip_vs_sync_lock); | 1632 | spin_unlock_bh(&ipvs->sync_lock); |
1626 | kthread_stop(sync_master_thread); | 1633 | kthread_stop(ipvs->master_thread); |
1627 | sync_master_thread = NULL; | 1634 | ipvs->master_thread = NULL; |
1628 | } else if (state == IP_VS_STATE_BACKUP) { | 1635 | } else if (state == IP_VS_STATE_BACKUP) { |
1629 | if (!sync_backup_thread) | 1636 | if (!ipvs->backup_thread) |
1630 | return -ESRCH; | 1637 | return -ESRCH; |
1631 | 1638 | ||
1632 | pr_info("stopping backup sync thread %d ...\n", | 1639 | pr_info("stopping backup sync thread %d ...\n", |
1633 | task_pid_nr(sync_backup_thread)); | 1640 | task_pid_nr(ipvs->backup_thread)); |
1634 | 1641 | ||
1635 | ip_vs_sync_state &= ~IP_VS_STATE_BACKUP; | 1642 | ipvs->sync_state &= ~IP_VS_STATE_BACKUP; |
1636 | kthread_stop(sync_backup_thread); | 1643 | kthread_stop(ipvs->backup_thread); |
1637 | sync_backup_thread = NULL; | 1644 | ipvs->backup_thread = NULL; |
1638 | } else { | 1645 | } else { |
1639 | return -EINVAL; | 1646 | return -EINVAL; |
1640 | } | 1647 | } |
@@ -1650,12 +1657,29 @@ int stop_sync_thread(int state) | |||
1650 | */ | 1657 | */ |
1651 | static int __net_init __ip_vs_sync_init(struct net *net) | 1658 | static int __net_init __ip_vs_sync_init(struct net *net) |
1652 | { | 1659 | { |
1660 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
1661 | |||
1662 | if (!net_eq(net, &init_net)) /* netns not enabled yet */ | ||
1663 | return -EPERM; | ||
1664 | |||
1665 | INIT_LIST_HEAD(&ipvs->sync_queue); | ||
1666 | spin_lock_init(&ipvs->sync_lock); | ||
1667 | spin_lock_init(&ipvs->sync_buff_lock); | ||
1668 | |||
1669 | ipvs->sync_mcast_addr.sin_family = AF_INET; | ||
1670 | ipvs->sync_mcast_addr.sin_port = cpu_to_be16(IP_VS_SYNC_PORT); | ||
1671 | ipvs->sync_mcast_addr.sin_addr.s_addr = cpu_to_be32(IP_VS_SYNC_GROUP); | ||
1653 | return 0; | 1672 | return 0; |
1654 | } | 1673 | } |
1655 | 1674 | ||
1656 | static void __ip_vs_sync_cleanup(struct net *net) | 1675 | static void __ip_vs_sync_cleanup(struct net *net) |
1657 | { | 1676 | { |
1677 | if (!net_eq(net, &init_net)) /* netns not enabled yet */ | ||
1678 | return; | ||
1679 | stop_sync_thread(net, IP_VS_STATE_MASTER); | ||
1680 | stop_sync_thread(net, IP_VS_STATE_BACKUP); | ||
1658 | } | 1681 | } |
1682 | |||
1659 | static struct pernet_operations ipvs_sync_ops = { | 1683 | static struct pernet_operations ipvs_sync_ops = { |
1660 | .init = __ip_vs_sync_init, | 1684 | .init = __ip_vs_sync_init, |
1661 | .exit = __ip_vs_sync_cleanup, | 1685 | .exit = __ip_vs_sync_cleanup, |