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
}