跟着老王学习stap的使用
最近有一套系统从REDHAT 6.9升级到了7.5,升级后经常出现网络丢包的情况,我们的D-SMART总是发现网络丢包,用户也很疑惑。在分析一个网卡drop包的案例的时候,读到了隔壁老王(火丁大神,https://blog.huoding.com/)的博文,受益匪浅。作为一个DBA来说,在新的形势下,真的需要多掌握一些OS诊断方面的技术。stap在本次分析中发挥了巨大的作用。
分析drop的LINUX工具最常用的是dropwath。首先我们通过dropwatch查看到了丢包发生的位置:
dropwatch -l kas启动后,执行start开始跟踪,然后按ctrl-c中止跟踪。从上面的drop发生的内核调用中,我们发现了一个netif开头的系统调用,netif就是网卡的简称,因此我们就可以进一步分析相关的内容了。当然老白并没有这方面的经验,根据老王的博文的提示,老白查看了相关的LINUX内核版本,并查看了相关函数的源代码:
从源代码中,我们可以看到,走到drop分支的判断条件有两个,一个是pfmemalloc失败,一个是skb_pfmemalloc_protocol(skb)不成功这两个条件之一。第一个条件和我们以前了解的sk buffer不足,导致drop是吻合的,第二个是调用了一个分析协议的函数。
在drop这一节,我们看到只做了一个rx_dropped的计数器增加,然后就执行了释放skb的操作。于是stap该上场了:首先我们编写一个调试脚本xu.stp:
这个脚本的含义是在drop这个位置打印pfmemalloc和skb->protocol的值。
从输出结果我们可以看到,在drop这个位置,Protocal是4。我们继续分析代码,查看返回失败的函数:
可以看出,只有5种情况返回的是true,否则都是false。ETH_P的定义包含在/uapi/linux/if_ether.h中,我们查看相关的定义:
可以看出TYPE=4是一个802.2的包,至此基本上可以看出这是一个802.2协议控制的包,属于系统不处理的包,因此就直接丢弃了。至此为止,一切分析的结果都和隔壁老王的结果十分类似。不过老白刚刚开始忽略了一个问题,就是这个判断drop的条件还有一个pmemalloc的判定条件,这是一个bool类型的值,是函数的参数传进来的。而从前面我们打印的信息来看,在drop这个位置,pmemalloc是0,也就是说这个条件就已经不满足,因此
前半部分就不满足,根本不会走到后面那个函数里去。因此drop产生的位置肯定不在这里。我们继续往下阅读相关的代码:
在后面还有一个条件,如果pt_prev是空值,则还会进入drop这个分支。于是我们修改下stp代码,然后继续跟踪:
从这里可以看出pt_prev是空的。那么我们就要回过头去看看为什么pt_prev是空的。pt_prev是一个函数内定义的指针。并被初始化为NULL。
然后在这段代码里被赋值:
这是一个检索rcu列表的宏,目的是从全局变量ptype_all中查找符合条件的协议,最终比对失败,pt_prev就没有调用deliver_skb,因此最后还是空值。最后的结果和老王的结果类似,也是因为802.2的包不属于OS要处理的,所以被丢弃了。
最后强烈推荐一下隔壁老王的网站,学习网络诊断或者做网络优化的朋友可以当作一个宝库来使用。
本文的分析思路和脚本都来自于以下的博文:https://blog.huoding.com/2020/04/27/814老王的网站主页:
https://blog.huoding.com
《跟着老王学习stap的使用》来自互联网,仅为收藏学习,如侵权请联系删除。本文URL:http://www.bookhoes.com/2187.html