一个关于组播的网络问题--暂没有时间确定真实原因
2011-01-11 20:35
381 查看
操作系统:Debian 3(内核2.6.8-2-686-smp)
网卡:四块网卡,驱动程序为e1000(e1000.ko)
应用程序:在其中一块或者多块网卡上启动heartbeat(向组播地址发包)
现象:heartbeat绑在ethx发送组播,然而ethx没有插网线,网卡口本身状态up,此时modprobe ip_conntrack,然后rmmod ip_conntrack,rmmod将会阻塞,通过ps查看它是running状态,发送SIGKILL给它也不行,此时只需要在ethx插上网线或者ifdown ethx,rmmod方可返回(此中ethx可以代表多个网卡口,若代表多个网卡,那么必须这几个网卡都插上线或者都ifdown了才可以);
分析过程:使用别的网卡是没有这个现象的,我的意思是说在别的不使用e1000驱动的网卡的机器上是没有这个问题的,另外不启动组播也是没有问题的,因此问题肯定在网卡驱动和组播。
内核代码情况:在ip_conntrack_core.c中有ip_conntrack_cleanup函数,肯定是在该函数中死循环了,因为/proc/net/ip_conntrack文件已经没有了,故而proc_net_remove("ip_conntrack")调用是成功的,按照下面的序列:
cleanup_proc:
proc_net_remove("ip_conntrack");
cleanup_init:
ip_conntrack_cleanup();
cleanup_nothing:
return ret;
则肯定是ip_conntrack_cleanup的问题:
void ip_conntrack_cleanup(void)
{
ip_ct_attach = NULL;
synchronize_net();
i_see_dead_people:
ip_ct_selective_cleanup(kill_all, NULL);
if (atomic_read(&ip_conntrack_count) != 0) { //1
schedule();
goto i_see_dead_people;
}
while (atomic_read(&ip_conntrack_untracked.ct_general.use) > 1) //2
schedule();
kmem_cache_destroy(ip_conntrack_cachep);
vfree(ip_conntrack_hash);
nf_unregister_sockopt(&so_getorigdst);
}
该函数中有两个循环,一个是1处,一个是2处,经调试是1处死循环了,结果是ip_conntrack_count这个计数器一直是1,然而ip_ct_selective_cleanup中的:
while ((h = get_next_corpse(kill, data, &bucket)) != NULL)
其h返回却是NULL,进一步跟踪发现get_next_corpse是从ip_conntrack_hash中找数据的,而ip_conntrack_hash中的数据是在ip_confirm被加入的,也就是说在一个数据包必须离开内核的时候才会将其ip_conntrack加入到ip_conntrack_hash,然而ip_conntrack_count计数器却是在init_conntrack中被递增的,也就是在数据包刚进入内核的时候被递增的,这就在ip_conntrack_hash的更新和ip_conntrack_count的更新之间留下了一个时间段,不过这个时间段不要紧,内核并不保证ip_ct_selective_cleanup中的ip_conntrack_hash遍历的数目一定要和ip_conntrack_count完全一致,也就是说,一个ip_conntrack可以已经由于它的存在递增了ip_conntrack_count,但是它可以不加入ip_conntrack_hash哈希表,这样不会有任何问题,这是因为在ip_ct_selective_cleanup中遍历ip_conntrack_hash表,然后依次调用ip_conntrack_put来降之destroy掉,如果哈希表中没有的ip_conntrack则可以在别的内核路径调用ip_conntrack_put来destroy掉,进而在destroy中递减ip_conntrack_count这个计数器,最终肯定在ip_conntrack_cleanup中会得到计数器ip_conntrack_count成为0的信息,最终从i_see_dead_people这个不吉利的循环中出来。
现在的问题就是为何在使用e1000驱动并且没有插网线发送组播的情况下(数据肯定发不出去),卸载ip_conntrack模块的时候没有任何内核路径调用ip_conntrack_put来释放这个游离的ip_conntrack,另外为何会有一个游离的ip_conntrack没有加入到ip_conntrack_hash哈希表却已经存在了,也即是它还没有准备从内核出去!此时,只要一插网线(在组播相关的所有网卡上插一下网线,哪怕插一下再拔下也行)或者ifdown所有的组播相关的网卡,一个ip_conntrack_put将被调用释放掉最后的那个游离ip_conntrack结构,递减掉最后的那个1,最终卸载ip_conntrack模块完成。
目前没有时间来调试e1000的驱动,我觉得问题十有八九出在这个驱动里面,可能需要网卡工具对网卡设置一下什么的。
本文出自 “我来,我看,我征服” 博客,请务必保留此出处http://dog250.blog.51cto.com/2466061/1271145
网卡:四块网卡,驱动程序为e1000(e1000.ko)
应用程序:在其中一块或者多块网卡上启动heartbeat(向组播地址发包)
现象:heartbeat绑在ethx发送组播,然而ethx没有插网线,网卡口本身状态up,此时modprobe ip_conntrack,然后rmmod ip_conntrack,rmmod将会阻塞,通过ps查看它是running状态,发送SIGKILL给它也不行,此时只需要在ethx插上网线或者ifdown ethx,rmmod方可返回(此中ethx可以代表多个网卡口,若代表多个网卡,那么必须这几个网卡都插上线或者都ifdown了才可以);
分析过程:使用别的网卡是没有这个现象的,我的意思是说在别的不使用e1000驱动的网卡的机器上是没有这个问题的,另外不启动组播也是没有问题的,因此问题肯定在网卡驱动和组播。
内核代码情况:在ip_conntrack_core.c中有ip_conntrack_cleanup函数,肯定是在该函数中死循环了,因为/proc/net/ip_conntrack文件已经没有了,故而proc_net_remove("ip_conntrack")调用是成功的,按照下面的序列:
cleanup_proc:
proc_net_remove("ip_conntrack");
cleanup_init:
ip_conntrack_cleanup();
cleanup_nothing:
return ret;
则肯定是ip_conntrack_cleanup的问题:
void ip_conntrack_cleanup(void)
{
ip_ct_attach = NULL;
synchronize_net();
i_see_dead_people:
ip_ct_selective_cleanup(kill_all, NULL);
if (atomic_read(&ip_conntrack_count) != 0) { //1
schedule();
goto i_see_dead_people;
}
while (atomic_read(&ip_conntrack_untracked.ct_general.use) > 1) //2
schedule();
kmem_cache_destroy(ip_conntrack_cachep);
vfree(ip_conntrack_hash);
nf_unregister_sockopt(&so_getorigdst);
}
该函数中有两个循环,一个是1处,一个是2处,经调试是1处死循环了,结果是ip_conntrack_count这个计数器一直是1,然而ip_ct_selective_cleanup中的:
while ((h = get_next_corpse(kill, data, &bucket)) != NULL)
其h返回却是NULL,进一步跟踪发现get_next_corpse是从ip_conntrack_hash中找数据的,而ip_conntrack_hash中的数据是在ip_confirm被加入的,也就是说在一个数据包必须离开内核的时候才会将其ip_conntrack加入到ip_conntrack_hash,然而ip_conntrack_count计数器却是在init_conntrack中被递增的,也就是在数据包刚进入内核的时候被递增的,这就在ip_conntrack_hash的更新和ip_conntrack_count的更新之间留下了一个时间段,不过这个时间段不要紧,内核并不保证ip_ct_selective_cleanup中的ip_conntrack_hash遍历的数目一定要和ip_conntrack_count完全一致,也就是说,一个ip_conntrack可以已经由于它的存在递增了ip_conntrack_count,但是它可以不加入ip_conntrack_hash哈希表,这样不会有任何问题,这是因为在ip_ct_selective_cleanup中遍历ip_conntrack_hash表,然后依次调用ip_conntrack_put来降之destroy掉,如果哈希表中没有的ip_conntrack则可以在别的内核路径调用ip_conntrack_put来destroy掉,进而在destroy中递减ip_conntrack_count这个计数器,最终肯定在ip_conntrack_cleanup中会得到计数器ip_conntrack_count成为0的信息,最终从i_see_dead_people这个不吉利的循环中出来。
现在的问题就是为何在使用e1000驱动并且没有插网线发送组播的情况下(数据肯定发不出去),卸载ip_conntrack模块的时候没有任何内核路径调用ip_conntrack_put来释放这个游离的ip_conntrack,另外为何会有一个游离的ip_conntrack没有加入到ip_conntrack_hash哈希表却已经存在了,也即是它还没有准备从内核出去!此时,只要一插网线(在组播相关的所有网卡上插一下网线,哪怕插一下再拔下也行)或者ifdown所有的组播相关的网卡,一个ip_conntrack_put将被调用释放掉最后的那个游离ip_conntrack结构,递减掉最后的那个1,最终卸载ip_conntrack模块完成。
目前没有时间来调试e1000的驱动,我觉得问题十有八九出在这个驱动里面,可能需要网卡工具对网卡设置一下什么的。
本文出自 “我来,我看,我征服” 博客,请务必保留此出处http://dog250.blog.51cto.com/2466061/1271145
相关文章推荐
- 一个关于组播的网络问题--暂没有时间确定真实原因
- 关于Windows 7启动后网络一直转的问题的一个解决方法
- 关于没有登录wifi的网络连接问题
- “在使用Samba进行建立Wisamba无法访问,你可能没有权限使用网络”的一种问题原因及解决
- 关于socket网络的一个小问题
- 一个我很长时间才解决的关于xp与2000共享的网络问题
- 今天遇到一个问题:在程序中加入的定时触发器,当时出现这样一个问题,触发器定时2秒,程序从后台查询数据经过复杂处理后时间超过了2秒,我查阅好些网络上说有可能触发器等待程序执行完毕后,在触发下一次,也有说
- 没有网络,NTP更新时间问题
- 关于C#更新Access数据库时发现的一个没有任何技术含量的问题,给大家分享,希望能给大家帮助
- 关于向Mysql数据库中插入时间只有日期没有时分秒的问题
- 一个关于时间的故事(通过历史分析解决程序问题)
- 一个关于Oracle更新语句引发的时间字段类型的问题
- 一个我很长时间才解决的关于xp与2000共享的网络问题
- 学习Java的第一步是安装好JDK,写一个Hello World, 其实JDK的学习没有那么简单,关于JDK有两个问题是很容易一直困扰Java程序员的地方:一个是CLASSPATH的问题,其实从原理上来说,是要搞清楚JRE的ClassLoader是如何加
- 一个关于时间的SQL分组排序问题
- 关于一个时间的转换问题。由一个RFC3339时间格式的字符串转为本地时间
- 一个小问题——关于linux重启网络需重设DNS的问题
- 铁通网络没有一个真实的公网IP,NAT转换能不能解决?
- 关于网络连接问题前期一直失败的原因
- 【selenium】python+selenium+unittest,关于每次执行完一个测试用例都关闭浏览器等时间较长的问题之解决方案