TCP rwnd自适应
Posted dog250
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TCP rwnd自适应相关的知识,希望对你有一定的参考价值。
紧接着前面的继续说。
填满TCP长肥管道
socket与Linux TCP
TCP rwnd算法挖坟
找到了RFC675这个宝贝,值得一读再读。本文对rwnd的计算做个简单侵入hook,并且做个模拟。
将rwnd替换成自己计算出来的值,需要修改 __tcp_select_window 的返回值,而它的计算过程可以在 __tcp_select_window 之前进行:
下面是代码:
#!/usr/local/bin/stap -g
%
#include <net/tcp.h>
%
function get_rwnd(skk:long)
%
struct sock *sk = (struct sock *)STAP_ARG_skk;
if (inet_sk(sk)->inet_num == 5001)
// loss_buff统计比较麻烦,用计数器比较好,干脆全部只统计包量,不统计包长。
unsigned long ret = sk->sk_rcvbuf /*+ loss_buff*/;
ret *= ret;
do_div(ret, sock_net(sk)->ipv4.sysctl_tcp_rmem[2]);
ret *= 315724928;
do_div(ret, sock_net(sk)->ipv4.sysctl_tcp_rmem[2]);
STAP_RETVALUE = ret;
else
STAP_RETVALUE = 0;
%
global win = 0
probe kernel.function("__tcp_select_window")
win = get_rwnd($sk);
probe kernel.function("__tcp_select_window").return
if (win != 0)
$return = win;
这段逻辑事实上应该替换 __tcp_select_window 逻辑的,并且free space应该减去由于应用读取不畅造成的丢包总量。大致是个意思。
下面是一个模拟程序:
#define _GNU_SOURCE
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include <math.h>
#include <sched.h>
pthread_t tid_sender, tid_receiver, tid_reader, tid_log;
unsigned long seq_front = 0, seq_end = 0;
unsigned int rwnd = 10, logwnd = 0;
unsigned int rate;
void* logger(void *arg)
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(4, &set);
while(1)
printf ("front:%d end:%d rwnd:%d rate:%d\\n", seq_front, seq_end, logwnd, rate);
void* sender(void *arg)
unsigned long tmp;
unsigned int wnd;
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(5, &set);
while(1)
wnd = __sync_fetch_and_or(&rwnd, 0);
if (wnd == 0)
continue;
__sync_fetch_and_and(&rwnd, 0);
logwnd = wnd;
while (wnd)
__sync_fetch_and_add(&seq_front, 1);
wnd --;
usleep(10000);
void* receiver(void *arg)
unsigned long tmp_front, tmp_end, i, newwnd;
unsigned int wnd;
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(6, &set);
wnd = rwnd;
while (1)
while (wnd)
tmp_front = __sync_fetch_and_sub(&seq_front, 0);
if (tmp_front == 0)
continue;
__sync_fetch_and_sub(&seq_front, 1);
tmp_end = __sync_fetch_and_add(&seq_end, 1);
wnd --;
newwnd = 1000*pow(1 - ((double)tmp_end)/((double)0xfffff), 3.5);
wnd = __sync_or_and_fetch(&rwnd, newwnd);
void* reader(void *arg)
unsigned long tmp;
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(7, &set);
while (1)
tmp = __sync_fetch_and_sub(&seq_end, 0);
if (tmp == 0)
continue;
__sync_fetch_and_sub(&seq_end, 1);
usleep(rate);
int main(int argc, char **argv)
rate = 10000;
pthread_create(&tid_sender, NULL, &sender, NULL);
pthread_create(&tid_receiver, NULL, &receiver, NULL);
pthread_create(&tid_reader, NULL, &reader, NULL);
pthread_create(&tid_log, NULL, &logger, NULL);
while (getchar() != 'e')
scanf("%d", &rate);
看懂这个代码,如有bug修复它,运行这个程序,输入微调reader速度,就可以观察到自适应的过程了。
买小龙虾前,把昨晚的代码写了一下,运行一下还是有趣的。但还是要喷Linux。Linux内核里不好做分数乘除这种浮点运算是很多TCP优化落不了地的根源!u64都装不住一个分数三次方,不得不写一个大数运算函数,为了折腾一个1000000量级这么小的数的屡次平方和除法,竟然要搞“大数”,真tmd讽刺!垃圾linus,sb。搞不懂Linux内核如今还不支持浮点数的根本原因,当然,你要是解释它为什么不支持,总有1000个原因,反正Linux什么都是对的,宗教般的正确。
浙江温州皮鞋湿,下雨进水不会胖。
以上是关于TCP rwnd自适应的主要内容,如果未能解决你的问题,请参考以下文章
计算机网络之TCP协议流量拥塞控制算法原理:滑动窗口cwnd与rwnd