mptcp联合拥塞控制算法 balia代码总结

static int rate_scale_limit = 25;
static int alpha_scale = 10;
static int scale_num = 5;//这里static修饰的都是全局变量,而且不允许其他文件引用

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

这里表示一个结构体(相当于java中的类)实现了一个拥塞控制接口,里面有私有的成员变量

//static inline表示这是一个内嵌函数,不用调用即可使用,注意这里是static修饰,外来文件不许调用
static inline int mptcp_balia_sk_can_send(const struct sock *sk)//表示此套接字是否可以发送数据
{
	return mptcp_sk_can_send(sk) && tcp_sk(sk)->srtt_us;
}
//获取meta(主套接字的)耦合因子
static inline u64 mptcp_get_ai(const struct sock *meta_sk)
{
	return ((struct mptcp_balia *)inet_csk_ca(meta_sk))->ai;
	//注意inet_csk_ca(主套接字)强制转化为本结构体类型才能使用成员变量
}
//设置meta(主套接字的)耦合因子
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;
}
//对值放大  val=val*2^scale
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); //常量强制转换为tcp_sock
	const struct mptcp_cb *mpcb = tp->mpcb; //常量多路径控制块
	struct mptcp_tcp_sock *mptcp;//声明此变量为了遍历mptcp连接中的所有子流
	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;

	/* Find max_rate first 首先寻找最大速率*/
	mptcp_for_each_sub(mpcb, mptcp)//这里是mpcb相当于一个链表
	{
		const struct sock *sub_sk = mptcp_to_sock(mptcp); //取出子sock
		struct tcp_sock *sub_tp = tcp_sk(sub_sk) //转为tcp_sock
			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))//这里unlikely()属于一个宏定义函数,主要是对整形变量进行判断是否为0
		goto exit;

	alpha = div64_u64(max_rate, rate); //计算alpha

	/* Scale down max_rate if it is too high (e.g., >2^25) 如果max_rate太高,则按比例缩小*/
	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_sub(mpcb, mptcp)
		{
			const struct sock *sub_sk = mptcp_to_sock(mptcp);
			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()用来判断参数是否配置了mptcp
		mptcp_set_forced(sk, 0);//成员变量设为0
		mptcp_set_ai(sk, 0);//因子都设为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);
}
//实现的拥塞避免算法  ack:表示拥塞窗口大小 acked:表示已确认的数据包数量
static void mptcp_balia_cong_avoid(struct sock *sk, u32 ack, u32 acked)
{
	struct tcp_sock *tp = tcp_sk(sk);
	int snd_cwnd;
	//判断有没有配置mptcp
	if (!mptcp(tp)) {
		tcp_reno_cong_avoid(sk, ack, acked);
		return;
	}

	if (!tcp_is_cwnd_limited(sk))
		return;
	//判断tcp是否处于慢启动阶段
	if (tcp_in_slow_start(tp)) {
		/* 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);
	}
	//
	snd_cwnd = (int)mptcp_get_ai(sk);
	//这一部分与lia一样
	if (tp->snd_cwnd_cnt >= snd_cwnd) {
		if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
			tp->snd_cwnd++;
			mptcp_balia_recalc_ai(
				sk); //每次收到一个ack,都要计算一次alpha
		}

		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);

	if (unlikely(!mptcp(tp)))
		return tcp_reno_ssthresh(sk);
	else
		return max((u32)(tp->snd_cwnd - mptcp_get_md(sk)), 1U);//阈值至少为1
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值