/*
 *	MPTCP implementation - Balia Congestion Control
 *	(Balanced Linked Adaptation Algorithm)
 *
 *	Analysis, Design and Implementation:
 *	Qiuyu Peng <qpeng@caltech.edu>
 *	Anwar Walid <anwar@research.bell-labs.com>
 *	Jaehyun Hwang <jhyun.hwang@samsung.com>
 *	Steven H. Low <slow@caltech.edu>
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License
 *	as published by the Free Software Foundation; either version
 *	2 of the License, or (at your option) any later version.
 */

#include <net/tcp.h>
#include <net/mptcp.h>

#include <linux/module.h>

/* The variable 'rate' (i.e., x_r) will be scaled
 * e.g., from B/s to KB/s, MB/s, or GB/s
 * if max_rate > 2^rate_scale_limit
 */

static int rate_scale_limit = 25;
static int alpha_scale = 10;
static int scale_num = 5;

struct mptcp_balia {
	u64	ai;
	u64	md;
	bool	forced_update;
};

static inline int mptcp_balia_sk_can_send(const struct sock *sk)
{
	return mptcp_sk_can_send(sk) && tcp_sk(sk)->srtt_us;
}

static inline u64 mptcp_get_ai(const struct sock *meta_sk)
{
	return ((struct mptcp_balia *)inet_csk_ca(meta_sk))->ai;
}

static inline void mptcp_set_ai(const struct sock *meta_sk, u64 ai)
{
	((struct mptcp_balia *)inet_csk_ca(meta_sk))->ai = ai;
}

static inline u64 mptcp_get_md(const struct sock *meta_sk)
{
	return ((struct mptcp_balia *)inet_csk_ca(meta_sk))->md;
}

static inline void mptcp_set_md(const struct sock *meta_sk, u64 md)
{
	((struct mptcp_balia *)inet_csk_ca(meta_sk))->md = md;
}

static inline u64 mptcp_balia_scale(u64 val, int scale)
{
	return (u64) val << scale;
}

static inline bool mptcp_get_forced(const struct sock *meta_sk)
{
	return ((struct mptcp_balia *)inet_csk_ca(meta_sk))->forced_update;
}

static inline void mptcp_set_forced(const struct sock *meta_sk, bool force)
{
	((struct mptcp_balia *)inet_csk_ca(meta_sk))->forced_update = force;
}

static void mptcp_balia_recalc_ai(const struct sock *sk)
{
	const struct tcp_sock *tp = tcp_sk(sk);
	const struct mptcp_cb *mpcb = tp->mpcb;
	const struct sock *sub_sk;
	u64 max_rate = 0, rate = 0, sum_rate = 0;
	u64 alpha, ai = tp->snd_cwnd, md = (tp->snd_cwnd >> 1);
	int num_scale_down = 0;

	if (!mpcb)
		return;

	/* Only one subflow left - fall back to normal reno-behavior */
	if (mpcb->cnt_established <= 1)
		goto exit;

	/* Find max_rate first */
	mptcp_for_each_sk(mpcb, sub_sk) {
		struct tcp_sock *sub_tp = tcp_sk(sub_sk);
		u64 tmp;

		if (!mptcp_balia_sk_can_send(sub_sk))
			continue;

		tmp = div_u64((u64)tp->mss_cache * sub_tp->snd_cwnd
				* (USEC_PER_SEC << 3), sub_tp->srtt_us);
		sum_rate += tmp;

		if (tp == sub_tp)
			rate = tmp;

		if (tmp >= max_rate)
			max_rate = tmp;
	}

	/* At least, the current subflow should be able to send */
	if (unlikely(!rate))
		goto exit;

	alpha = div64_u64(max_rate, rate);

	/* Scale down max_rate if it is too high (e.g., >2^25) */
	while (max_rate > mptcp_balia_scale(1, rate_scale_limit)) {
		max_rate >>= scale_num;
		num_scale_down++;
	}

	if (num_scale_down) {
		sum_rate = 0;
		mptcp_for_each_sk(mpcb, sub_sk) {
			struct tcp_sock *sub_tp = tcp_sk(sub_sk);
			u64 tmp;

			if (!mptcp_balia_sk_can_send(sub_sk))
				continue;

			tmp = div_u64((u64)tp->mss_cache * sub_tp->snd_cwnd
				* (USEC_PER_SEC << 3), sub_tp->srtt_us);
			tmp >>= (scale_num * num_scale_down);

			sum_rate += tmp;
		}
		rate >>= (scale_num * num_scale_down);
	}

	/*	(sum_rate)^2 * 10 * w_r
	 * ai = ------------------------------------
	 *	(x_r + max_rate) * (4x_r + max_rate)
	 */
	sum_rate *= sum_rate;

	ai = div64_u64(sum_rate * 10, rate + max_rate);
	ai = div64_u64(ai * tp->snd_cwnd, (rate << 2) + max_rate);

	if (unlikely(!ai))
		ai = tp->snd_cwnd;

	md = ((tp->snd_cwnd >> 1) * min(mptcp_balia_scale(alpha, alpha_scale),
					mptcp_balia_scale(3, alpha_scale) >> 1))
					>> alpha_scale;

exit:
	mptcp_set_ai(sk, ai);
	mptcp_set_md(sk, md);
}

static void mptcp_balia_init(struct sock *sk)
{
	if (mptcp(tcp_sk(sk))) {
		mptcp_set_forced(sk, 0);
		mptcp_set_ai(sk, 0);
		mptcp_set_md(sk, 0);
	}
}

static void mptcp_balia_cwnd_event(struct sock *sk, enum tcp_ca_event event)
{
	if (event == CA_EVENT_COMPLETE_CWR || event == CA_EVENT_LOSS)
		mptcp_balia_recalc_ai(sk);
}

static void mptcp_balia_set_state(struct sock *sk, u8 ca_state)
{
	if (!mptcp(tcp_sk(sk)))
		return;

	mptcp_set_forced(sk, 1);
}

static void mptcp_balia_cong_avoid(struct sock *sk, u32 ack, u32 acked)
{
	struct tcp_sock *tp = tcp_sk(sk);
	const struct mptcp_cb *mpcb = tp->mpcb;
	int snd_cwnd;

	if (!mptcp(tp)) {
		tcp_reno_cong_avoid(sk, ack, acked);
		return;
	}

	if (!tcp_is_cwnd_limited(sk))
		return;

	if (tp->snd_cwnd <= tp->snd_ssthresh) {
		/* In "safe" area, increase. */
		tcp_slow_start(tp, acked);
		mptcp_balia_recalc_ai(sk);
		return;
	}

	if (mptcp_get_forced(mptcp_meta_sk(sk))) {
		mptcp_balia_recalc_ai(sk);
		mptcp_set_forced(sk, 0);
	}

	if (mpcb->cnt_established > 1)
		snd_cwnd = (int) mptcp_get_ai(sk);
	else
		snd_cwnd = tp->snd_cwnd;

	if (tp->snd_cwnd_cnt >= snd_cwnd) {
		if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
			tp->snd_cwnd++;
			mptcp_balia_recalc_ai(sk);
		}

		tp->snd_cwnd_cnt = 0;
	} else {
		tp->snd_cwnd_cnt++;
	}
}

static u32 mptcp_balia_ssthresh(struct sock *sk)
{
	const struct tcp_sock *tp = tcp_sk(sk);
	const struct mptcp_cb *mpcb = tp->mpcb;

	if (unlikely(!mptcp(tp) || mpcb->cnt_established <= 1))
		return tcp_reno_ssthresh(sk);
	else
		return max((u32)(tp->snd_cwnd - mptcp_get_md(sk)), 1U);
}

static struct tcp_congestion_ops mptcp_balia = {
	.init		= mptcp_balia_init,
	.ssthresh	= mptcp_balia_ssthresh,
	.cong_avoid	= mptcp_balia_cong_avoid,
	.cwnd_event	= mptcp_balia_cwnd_event,
	.set_state	= mptcp_balia_set_state,
	.owner		= THIS_MODULE,
	.name		= "balia",
};

static int __init mptcp_balia_register(void)
{
	BUILD_BUG_ON(sizeof(struct mptcp_balia) > ICSK_CA_PRIV_SIZE);
	return tcp_register_congestion_control(&mptcp_balia);
}

static void __exit mptcp_balia_unregister(void)
{
	tcp_unregister_congestion_control(&mptcp_balia);
}

module_init(mptcp_balia_register);
module_exit(mptcp_balia_unregister);

MODULE_AUTHOR("Jaehyun Hwang, Anwar Walid, Qiuyu Peng, Steven H. Low");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MPTCP BALIA CONGESTION CONTROL ALGORITHM");
MODULE_VERSION("0.1");
