记一次有惊无险的丢包调试经历
发布时间 - 2025-06-26 00:00:00 点击率:次在将服务器从 centos 5 升级到 centos 7(内核版本 3.10.0-693)后,我在服务器上偶然发现了一个重大问题:网卡 eth0 在接收(rx)数据时存在规律性丢包,每一两秒丢一个包。
我首先怀疑可能是网卡的 ring buffer 容量不足,于是使用「ethtool」工具进行检查:
shell> ethtool -g eth0 Ring parameters for eth0: Pre-set maximums: RX: 256 RX Mini: 0 RX Jumbo: 0 TX: 256 Current hardware settings: RX: 256 RX Mini: 0 RX Jumbo: 0 TX: 256
虽然 ring buffer 确实显得较小,但当前硬件设置已达到预设的最大值,无法进一步扩大。为了进一步确认网卡是否存在丢包问题,我继续使用「ethtool」进行检查:
shell> ethtool -S eth0 no stats available shell> ethtool -i eth0 driver: virtio_net version: 1.0.0 firmware-version: expansion-rom-version: bus-info: 0000:00:04.0 supports-statistics: no supports-test: no supports-eeprom-access: no supports-register-dump: no supports-priv-flags: no
结果显示,kvm 的 virtio_net 驱动不支持统计数据,好在还有其他方法来获取信息:
shell> find /sys -name eth0 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth0 /sys/class/net/eth0 shell> cd /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth0 shell> cd statistics shell> grep . * | grep rx rx_bytes:633037730314 rx_compressed:0 rx_crc_errors:0 rx_dropped:206975 rx_errors:0 rx_fifo_errors:0 rx_frame_errors:0 rx_length_errors:0 rx_missed_errors:0 rx_nohandler:0 rx_over_errors:0 rx_packets:4717658080
虽然 rx_dropped 值不为零,但 rx_errors 等错误计数器都为零,这表明 ring buffer 没有溢出,否则 rx_fifo_errors 等错误计数器不可能为零。因此可以推断:网卡已经将数据完整地传递给了操作系统,丢包问题出在操作系统层面。
为了确定操作系统在哪里丢包,我使用了 dropwatch 工具:
shell> dropwatch -l kas Initializing kallsyms db dropwatch> start Enabling monitoring... Kernel monitoring activated. Issue Ctrl-C to stop monitoring 6 drops at ip_rcv+cf (0xffffffff815ca47f) 11 drops at ipv6_rcv+3ad (0xffffffff81643d7d) 75 drops at tcp_v4_rcv+87 (0xffffffff815f0197) 426 drops at sk_stream_kill_queues+50 (0xffffffff8157a740) 235 drops at tcp_rcv_state_process+1b0 (0xffffffff815e4fb0) 137 drops at tcp_v4_rcv+87 (0xffffffff815f0197) 11 drops at ipv6_rcv+3ad (0xffffffff81643d7d) 1 drops at __netif_receive_skb_core+3d2 (0xffffffff81586d82) shell> grep -w -A 10 __netif_receive_skb_core /proc/kallsyms ffffffff815869b0 t __netif_receive_skb_core ffffffff81587170 t __netif_receive_skb ffffffff815871d0 t netif_receive_skb_internal ffffffff81587290 T netif_receive_skb ffffffff81587300 t napi_gro_complete ffffffff81587400 T napi_gro_flush ffffffff81587490 T napi_complete_done ffffffff81587550 T napi_complete ffffffff81587570 T sk_busy_loop ffffffff81587830 t net_rx_action ffffffff81587bb0 t dev_gro_receive
dropwatch 通过监控 kfree_skb 的调用来监控操作系统可能的丢包行为。我们的问题是每一两秒丢一个包,因此我们将关注点放在了 __netif_receive_skb_core 函数上(丢包地址 0xffffffff81586d82 位于 ffffffff815869b0 和 ffffffff81587170 之间)。
查阅 Linux 源代码中的 __netif_receive_skb_core 函数定义,确认丢包原因:
static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
{
...
if (pfmemalloc && !skb_pfmemalloc_protocol(skb))
g
oto drop;
...
drop:
atomic_long_inc(&skb->dev->rx_dropped);
kfree_skb(skb);
/* Jamal, now you will not able to escape explaining
* me how you were going to use this. :-)
*/
ret = NET_RX_DROP;
...
}
static bool skb_pfmemalloc_protocol(struct sk_buff *skb)
{
switch (skb->protocol) {
case __constant_htons(ETH_P_ARP):
case __constant_htons(ETH_P_IP):
case __constant_htons(ETH_P_IPV6):
case __constant_htons(ETH_P_8021Q):
case __constant_htons(ETH_P_8021AD):
return true;
default:
return false;
}
}当 pfmemalloc 为真,且 skb_pfmemalloc_protocol 函数判断包协议不支持时,就会丢包。此外,代码中调用了 kfree_skb,这也验证了 dropwatch 的工作原理。
为了确定我们问题中丢包的协议类型,我使用了 systemtap 工具:
#! /usr/bin/env stap
probe kernel.function("__netif_receive_skb_core").label("drop") {
printf("0x%04X\n", ntohs($skb->protocol))
}
// output
0x0004systemtap 几乎可以为所欲为,甚至可以替换前面提到的 dropwatch。
根据我们对 Linux 源代码的分析,skb_pfmemalloc_protocol 函数支持的包 protocol 如下:
#define ETH_P_ARP 0x0806 /* Address Resolution packet */ #define ETH_P_IP 0x0800 /* Internet Protocol packet */ #define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ #define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ #define ETH_P_8021AD 0x88A8 /* 802.1ad Service VLAN */
而 systemtap 脚本检测到的包 protocol 为 0x0004,也就是路由器发出的 802.3 包:
#define ETHERTYPE_8023 0x0004 /* IEEE 802.3 packet */
因为这是系统不支持的包,所以被丢弃了。
其实,只要了解了问题的根源,使用 tcpdump 也可以捕获被系统丢弃的包,只需打印出包的 ether type,然后过滤掉操作系统支持的协议包,剩下的就是丢掉的包:
shell> tcpdump -i eth0 -e | grep -v -E 'ARP|IP|802.1Q|802.1AD' 802.3,length 105: LLC,dsap STP (0x42) Individual,ssap STP (0x42) Command,ctrl 0x03: STP 802.1s,Rapid STP,CIST Flags [Learn, Forward, Agreement],length 102
需要说明的是,CentOS 的新旧版本在处理此类问题上的行为有所不同:面对不支持协议的包,虽然 CentOS 的新旧版本都会丢弃它,但旧版不会更新丢包计数器(rx_dropped),新版却会更新丢包计数器(rx_dropped),具体细节就不展开讨论了,有兴趣的可以自行查阅。
# centos
# linux
# 操作系统
# access
# 工具
# ai
# switch
# tcpdump
# 不支持
# 为零
# 源代码
# 的是
# 这是
# 就会
# 使用了
# 我在
# 放在
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件
HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】
lovemo网页版地址 lovemo官网手机登录
悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤
C语言设计一个闪闪的圣诞树
如何挑选高效建站主机与优质域名?
,在苏州找工作,上哪个网站比较好?
Laravel Eloquent:优雅地将关联模型字段扁平化到主模型中
Laravel的辅助函数有哪些_Laravel常用Helpers函数提高开发效率
如何在IIS服务器上快速部署高效网站?
Laravel如何配置和使用缓存?(Redis代码示例)
如何在新浪SAE免费搭建个人博客?
laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法
iOS UIView常见属性方法小结
Android Socket接口实现即时通讯实例代码
javascript中的try catch异常捕获机制用法分析
Laravel N+1查询问题如何解决_Eloquent预加载(Eager Loading)优化数据库查询
Microsoft Edge如何解决网页加载问题 Edge浏览器加载问题修复
无锡营销型网站制作公司,无锡网选车牌流程?
Laravel 419 page expired怎么解决_Laravel CSRF令牌过期处理
香港服务器建站指南:免备案优势与SEO优化技巧全解析
高防服务器租用如何选择配置与防御等级?
如何快速生成可下载的建站源码工具?
阿里云高弹*务器配置方案|支持分布式架构与多节点部署
Laravel Eloquent性能优化技巧_Laravel N+1查询问题解决
使用PHP下载CSS文件中的所有图片【几行代码即可实现】
javascript事件捕获机制【深入分析IE和DOM中的事件模型】
简单实现jsp分页
Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】
如何在 React 中条件性地遍历数组并渲染元素
网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?
Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】
QQ浏览器网页版登录入口 个人中心在线进入
HTML5空格和nbsp有啥关系_nbsp的作用及使用场景【说明】
Laravel如何理解并使用服务容器(Service Container)_Laravel依赖注入与容器绑定说明
Laravel怎么集成Log日志记录_Laravel单文件与每日日志配置及自定义通道【详解】
利用 Google AI 进行 YouTube 视频 SEO 描述优化
如何在阿里云虚拟主机上快速搭建个人网站?
Android滚轮选择时间控件使用详解
b2c电商网站制作流程,b2c水平综合的电商平台?
jimdo怎样用html5做选项卡_jimdo选项卡html5实现与切换效果【指南】
如何快速搭建高效WAP手机网站吸引移动用户?
Laravel Artisan命令怎么自定义_创建自己的Laravel命令行工具完全指南
Google浏览器为什么这么卡 Google浏览器提速优化设置步骤【方法】
Claude怎样写结构化提示词_Claude结构化提示词写法【教程】
网站建设保证美观性,需要考虑的几点问题!
标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?
今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】
浏览器如何快速切换搜索引擎_在地址栏使用不同搜索引擎【搜索】
成都品牌网站制作公司,成都营业执照年报网上怎么办理?


oto drop;
...
drop:
atomic_long_inc(&skb->dev->rx_dropped);
kfree_skb(skb);
/* Jamal, now you will not able to escape explaining
* me how you were going to use this. :-)
*/
ret = NET_RX_DROP;
...
}
static bool skb_pfmemalloc_protocol(struct sk_buff *skb)
{
switch (skb->protocol) {
case __constant_htons(ETH_P_ARP):
case __constant_htons(ETH_P_IP):
case __constant_htons(ETH_P_IPV6):
case __constant_htons(ETH_P_8021Q):
case __constant_htons(ETH_P_8021AD):
return true;
default:
return false;
}
}