Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 29c2026f authored by Hans Schillstrom's avatar Hans Schillstrom Committed by Simon Horman
Browse files

IPVS: netns awareness to ip_vs_est



All variables moved to struct ipvs,
most external changes fixed (i.e. init_net removed)

*v3
 timer per ns instead of a common timer in estimator.

Signed-off-by: default avatarHans Schillstrom <hans.schillstrom@ericsson.com>
Acked-by: default avatarJulian Anastasov <ja@ssi.bg>
Signed-off-by: default avatarSimon Horman <horms@verge.net.au>
parent ab8a5e84
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1004,8 +1004,8 @@ extern void ip_vs_sync_cleanup(void);
 */
extern int ip_vs_estimator_init(void);
extern void ip_vs_estimator_cleanup(void);
extern void ip_vs_new_estimator(struct ip_vs_stats *stats);
extern void ip_vs_kill_estimator(struct ip_vs_stats *stats);
extern void ip_vs_new_estimator(struct net *net, struct ip_vs_stats *stats);
extern void ip_vs_kill_estimator(struct net *net, struct ip_vs_stats *stats);
extern void ip_vs_zero_estimator(struct ip_vs_stats *stats);

/*
+4 −0
Original line number Diff line number Diff line
@@ -70,6 +70,10 @@ struct netns_ipvs {
	int			sysctl_lblcr_expiration;
	struct ctl_table_header	*lblcr_ctl_header;
	struct ctl_table	*lblcr_ctl_table;
	/* ip_vs_est */
	struct list_head	est_list;	/* estimator list */
	spinlock_t		est_lock;
	struct timer_list	est_timer;	/* Estimation timer */
};

#endif /* IP_VS_H_ */
+10 −10
Original line number Diff line number Diff line
@@ -816,7 +816,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
	spin_unlock(&dest->dst_lock);

	if (add)
		ip_vs_new_estimator(&dest->stats);
		ip_vs_new_estimator(svc->net, &dest->stats);

	write_lock_bh(&__ip_vs_svc_lock);

@@ -1009,9 +1009,9 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
/*
 *	Delete a destination (must be already unlinked from the service)
 */
static void __ip_vs_del_dest(struct ip_vs_dest *dest)
static void __ip_vs_del_dest(struct net *net, struct ip_vs_dest *dest)
{
	ip_vs_kill_estimator(&dest->stats);
	ip_vs_kill_estimator(net, &dest->stats);

	/*
	 *  Remove it from the d-linked list with the real services.
@@ -1080,6 +1080,7 @@ static int
ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
{
	struct ip_vs_dest *dest;
	struct net *net = svc->net;
	__be16 dport = udest->port;

	EnterFunction(2);
@@ -1108,7 +1109,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
	/*
	 *	Delete the destination
	 */
	__ip_vs_del_dest(dest);
	__ip_vs_del_dest(net, dest);

	LeaveFunction(2);

@@ -1197,7 +1198,7 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u,
	else if (svc->port == 0)
		atomic_inc(&ip_vs_nullsvc_counter);

	ip_vs_new_estimator(&svc->stats);
	ip_vs_new_estimator(net, &svc->stats);

	/* Count only IPv4 services for old get/setsockopt interface */
	if (svc->af == AF_INET)
@@ -1345,7 +1346,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc)
	if (svc->af == AF_INET)
		ip_vs_num_services--;

	ip_vs_kill_estimator(&svc->stats);
	ip_vs_kill_estimator(svc->net, &svc->stats);

	/* Unbind scheduler */
	old_sched = svc->scheduler;
@@ -1368,7 +1369,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc)
	 */
	list_for_each_entry_safe(dest, nxt, &svc->destinations, n_list) {
		__ip_vs_unlink_dest(svc, dest, 0);
		__ip_vs_del_dest(dest);
		__ip_vs_del_dest(svc->net, dest);
	}

	/*
@@ -3460,7 +3461,7 @@ int __net_init __ip_vs_control_init(struct net *net)
						  vs_vars);
	if (sysctl_header == NULL)
		goto err_reg;
	ip_vs_new_estimator(&ip_vs_stats);
	ip_vs_new_estimator(net, &ip_vs_stats);
	return 0;

err_reg:
@@ -3472,7 +3473,7 @@ static void __net_exit __ip_vs_control_cleanup(struct net *net)
	if (!net_eq(net, &init_net))	/* netns not enabled yet */
		return;

	ip_vs_kill_estimator(&ip_vs_stats);
	ip_vs_kill_estimator(net, &ip_vs_stats);
	unregister_net_sysctl_table(sysctl_header);
	proc_net_remove(net, "ip_vs_stats");
	proc_net_remove(net, "ip_vs");
@@ -3536,7 +3537,6 @@ void ip_vs_control_cleanup(void)
	ip_vs_trash_cleanup();
	cancel_delayed_work_sync(&defense_work);
	cancel_work_sync(&defense_work.work);
	ip_vs_kill_estimator(&ip_vs_stats);
	unregister_pernet_subsys(&ipvs_control_ops);
	ip_vs_genl_unregister();
	nf_unregister_sockopt(&ip_vs_sockopts);
+48 −38
Original line number Diff line number Diff line
@@ -8,8 +8,12 @@
 *              as published by the Free Software Foundation; either version
 *              2 of the License, or (at your option) any later version.
 *
 * Changes:
 *
 * Changes:     Hans Schillstrom <hans.schillstrom@ericsson.com>
 *              Network name space (netns) aware.
 *              Global data moved to netns i.e struct netns_ipvs
 *              Affected data: est_list and est_lock.
 *              estimation_timer() runs with timer per netns.
 *              get_stats()) do the per cpu summing.
 */

#define KMSG_COMPONENT "IPVS"
@@ -48,12 +52,6 @@
 */


static void estimation_timer(unsigned long arg);

static LIST_HEAD(est_list);
static DEFINE_SPINLOCK(est_lock);
static DEFINE_TIMER(est_timer, estimation_timer, 0, 0);

static void estimation_timer(unsigned long arg)
{
	struct ip_vs_estimator *e;
@@ -62,9 +60,12 @@ static void estimation_timer(unsigned long arg)
	u32 n_inpkts, n_outpkts;
	u64 n_inbytes, n_outbytes;
	u32 rate;
	struct net *net = (struct net *)arg;
	struct netns_ipvs *ipvs;

	spin_lock(&est_lock);
	list_for_each_entry(e, &est_list, list) {
	ipvs = net_ipvs(net);
	spin_lock(&ipvs->est_lock);
	list_for_each_entry(e, &ipvs->est_list, list) {
		s = container_of(e, struct ip_vs_stats, est);

		spin_lock(&s->lock);
@@ -101,12 +102,13 @@ static void estimation_timer(unsigned long arg)
		s->ustats.outbps = (e->outbps + 0xF) >> 5;
		spin_unlock(&s->lock);
	}
	spin_unlock(&est_lock);
	mod_timer(&est_timer, jiffies + 2*HZ);
	spin_unlock(&ipvs->est_lock);
	mod_timer(&ipvs->est_timer, jiffies + 2*HZ);
}

void ip_vs_new_estimator(struct ip_vs_stats *stats)
void ip_vs_new_estimator(struct net *net, struct ip_vs_stats *stats)
{
	struct netns_ipvs *ipvs = net_ipvs(net);
	struct ip_vs_estimator *est = &stats->est;

	INIT_LIST_HEAD(&est->list);
@@ -126,18 +128,19 @@ void ip_vs_new_estimator(struct ip_vs_stats *stats)
	est->last_outbytes = stats->ustats.outbytes;
	est->outbps = stats->ustats.outbps<<5;

	spin_lock_bh(&est_lock);
	list_add(&est->list, &est_list);
	spin_unlock_bh(&est_lock);
	spin_lock_bh(&ipvs->est_lock);
	list_add(&est->list, &ipvs->est_list);
	spin_unlock_bh(&ipvs->est_lock);
}

void ip_vs_kill_estimator(struct ip_vs_stats *stats)
void ip_vs_kill_estimator(struct net *net, struct ip_vs_stats *stats)
{
	struct netns_ipvs *ipvs = net_ipvs(net);
	struct ip_vs_estimator *est = &stats->est;

	spin_lock_bh(&est_lock);
	spin_lock_bh(&ipvs->est_lock);
	list_del(&est->list);
	spin_unlock_bh(&est_lock);
	spin_unlock_bh(&ipvs->est_lock);
}

void ip_vs_zero_estimator(struct ip_vs_stats *stats)
@@ -159,14 +162,25 @@ void ip_vs_zero_estimator(struct ip_vs_stats *stats)

static int __net_init __ip_vs_estimator_init(struct net *net)
{
	struct netns_ipvs *ipvs = net_ipvs(net);

	if (!net_eq(net, &init_net))	/* netns not enabled yet */
		return -EPERM;

	INIT_LIST_HEAD(&ipvs->est_list);
	spin_lock_init(&ipvs->est_lock);
	setup_timer(&ipvs->est_timer, estimation_timer, (unsigned long)net);
	mod_timer(&ipvs->est_timer, jiffies + 2 * HZ);
	return 0;
}

static void __net_exit __ip_vs_estimator_exit(struct net *net)
{
	del_timer_sync(&net_ipvs(net)->est_timer);
}
static struct pernet_operations ip_vs_app_ops = {
	.init = __ip_vs_estimator_init,
	.exit = __ip_vs_estimator_exit,
};

int __init ip_vs_estimator_init(void)
@@ -174,14 +188,10 @@ int __init ip_vs_estimator_init(void)
	int rv;

	rv = register_pernet_subsys(&ip_vs_app_ops);
	if (rv < 0)
		return rv;
	mod_timer(&est_timer, jiffies + 2 * HZ);
	return rv;
}

void ip_vs_estimator_cleanup(void)
{
	del_timer_sync(&est_timer);
	unregister_pernet_subsys(&ip_vs_app_ops);
}