Linux防止ip首部id字段回绕的策略

 IP首部的id字段用来标识不同的封包(而不是分片,一个封包的所有分片拥有相同的id)

这个字段只占用16位,因此在一个快速的网络上很快就会回绕,这是就可能造成协议栈对ip报文识别混乱。

Linux内核采取了策略来减缓其回绕速度。

 

不使用全局的id变量,而是对每个ip使用一个单独的计数器来计算其id,

但是ip地址是很多的,长时间不清里的话很快会把内存占满,

于是设置一个全局定时器peer_periodic_timer,定时调用peer_check_expire函数,

说是定时,其实也不那么准时,第一次一般设置时间为inet_peer_gc_maxtime(2分钟)再加减一个随机值

UNLI说这是为了防止与开机时启动的其他定时器冲突。

以后重新设置的时间也不是定值,而是要根据inet_peer的数量在10秒到120秒之间变化,

inet_peer数量越多,到期时间越短,这很好理解,负载越重越要频繁清理。

 

在peer_check_expire函数中所做的就是根据负载情况来删除一定数量的peer

如果peer数量大于inet_peer_threshold,那么会删除未用时间超过inet_peer_minttl(120s)的peer

否则根据负载情况删除未用时间在inet_peer_minttl到inet_peer_maxttl(10min)之间的某个值以上的peer

一般也不是全部删除,而是运行1个HZ,删多少算多少,

删除操作是调用cleanup_once完成的,它接受一个参数n表示删除未用时间大于n的peer,它一次只删除一个

超过1HZ之后如果还没有清理完,则设置垃圾收集定时器为最小值10s后再次清理

否则也是设置为10s到120s之间的值

 

有可能添加peer的点:

      1.ip_defrag中创建新inet_frag_queue时会调用constructor,对于ipv4是ip4_frag_init,

这其中会调用inet_getpeer(arg->iph->saddr, 1)。

      2.调用ip_select_ident为外出封包选择id时,如果此封包的目的ip不在peers中,

rt_bind_peer(rt, 1);会调用创建一个peer并且与rtable绑定。

      3.tcp_v4_remember_stamp等几个函数中也会调用rt_bind_peer或者直接调inet_getpeer,

暂时不知道这些是做什么用的

 

 

你可能感兴趣的:(timer,linux,网络,Constructor,linux内核)