日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

​内核调试技巧--systemtap定位丢包原因

發布時間:2024/2/28 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ​内核调试技巧--systemtap定位丢包原因 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:wqiangwang,騰訊 TEG 后臺開發工程師

內核收發包,可能會由于backlog隊列滿、內存不足、包校驗失敗、特性開關如rpf、路由不可達、端口未監聽等等因素將包丟棄。

在內核里面,數據包對應一個叫做skb(sk_buff結構)。當發生如上等原因丟包時,內核會調用***kfree_skb***把這個包釋放(丟掉)。kfree_skb函數中已經埋下了trace點,并且通過__builtin_return_address(0)記錄下了調用kfree_skb的函數地址并傳給location參數,因此可以利用systemtap kernel.trace來跟蹤kfree_skb獲取丟包函數。考慮到該丟包函數可能調用了子函數,子函數繼續調用子子函數,如此遞歸。為了揪出最深層的函數,本文通過舉例幾個丟包場景,來概述一種通用方法,來定位丟包原因及精確行號。

用例1:ospf hello組播報文被drop,導致ospf 鄰居不能建立

方法:saddr是10.10.2.4的skb是我們關心的數據。

1、 drop_watch跟蹤下kfree_skb,定位函數位置:

2、 查看ip_rcv_finish內核源碼,編寫stap腳本,通過pp()行號來跟蹤執行流:

3、 從行號可知ip_route_input_noref返回錯誤,編寫stap腳本,查看ip_route_input_noref的返回值:

返回-22,即-EINVAL。

4、 即ip_route_input_rcu返回錯誤,同樣方法,通過pp()行號來跟蹤執行流:

此路不通,看下原因:原來有些行號$saddr不能訪問。

5、 此時需要碼一碼代碼了,由于ospf的hello報文是組播,所以下圖中紅色方框的ipv4_is_multicast為真:

先看下__in_dev_get_rcu(dev)的返回值是否為null,同時也把dev->priv_flags的值打印出來:

__in_dev_get_rcu(dev)返回不為null,再看ip_check_mc_rcu函數的返回值:

返回值為0,同時通過打印的dev->priv_flags 為0x00029820,可判斷netif_is_l3_slave為假:

另外ospf使用的組播ip為224.0.0.5或224.0.0.6,本例中使用的是224.0.0.5。因此ipv4_is_local_multicast為真:

最終精確定位到了ip_check_mc_rcu:

先看下in_dev->mc_hash是否為null,通過cast強轉來訪問結構體成員mc_hash:

則需要走如下分支:

需要遍歷in_dev->mc_list,有兩種方法,一種是通過crash工具查看,遍歷in_dev->mc_list,輸出im->multiaddr,如下:

既然我們的主題是stap,那么繼續stap,這里通過嵌入c代碼來遍歷mc_list,輸出multiaddr到dmesg:

存在接口加入了224.0.0.5組播組,革命尚未成功,繼續跟蹤下面的代碼:

同樣的方式,編寫stap腳本或者crash通過struct展開im->sources來查看。

至此,一目了然,原來報文接收的接口沒有加入組播組224.0.0.5。google一下:

https://www.cnblogs.com/my_life/articles/6077569.html

綜述:那為什么ens5沒有加入組播組呢,這要從ospf的原理來說起,ospf建立鄰居的時候,是不需要指定接口的,那用于建立鄰居的接口是如何選擇的呢:實際上是根據指定的area network配置來選擇的。當配置area network的時候,會查看系統當前路由,選擇合適的接口加入組播組,進而創建鄰居。

用例2:gre報文的version字段被置位,導致skb被drop。

方法:saddr是10.10.2.2的skb是我們關心的數據。

1、 依然是drop_watch跟蹤下kfree_skb,定位函數位置:

2、 查看gre_rcv的源碼,有兩個內核模塊都存在gre_rcv,由于上面的drop_watch已經定位為ffffffffc099411a,通過crash查看模塊的加載地址,來確定調用的是哪一個模塊的gre_rcv:

3、 依然是pp()行號來跟蹤執行流,和上述不同的是,gre是模塊的形式,使用stap的probe module的方式:

綜述:這里大家要小心,這個存在”寫”skb相關成員,不建議嵌入c代碼的方式,去修改skb,如果真的要怎么做,記得恢復回來。

用例3: overlay報文根據路由找到出的vxlan隧道接口后,沒有從underlay接口出,導致網絡不通:

方法:saddr是172.16.14.2的skb是我們關心的數據。

1、 依然是drop_watch跟蹤下kfree_skb,定位函數位置:

2、 查看vxlan_xmit_one,依然是pp()行號來跟蹤執行流:

綜述:從接口中取到underlay信息后,再去查找路由,由于underlay路由不存在,導致skb被drop。這個問題較簡單,也可直接通過查看ip route定位。但是細心的你一定會發現一個有趣的問題,關鍵字overlay arp,歡迎讀者來撩。

總結,丟包精確定位行的方法:

1、 drop_watch先定位函數。

2、 使用pp()定位行。必要的時候,編寫一些腳本,直接抄寫內核代碼或者調用stap庫就可以了。

3、 遞歸重復步驟1和2。

是不是躍躍欲試的感覺。

最后:

這里”rpf檢查”,”accept_local檢查”留給讀者來嘗試了。實際上systemtap可以做的更多,如內存泄露,系統調用失敗,統計流量等等,github上也有很多實用的腳本。

參考鏈接:

https://cloud.tencent.com/developer/article/1631874

https://www.cnblogs.com/wanpengcoder/p/11768483.html

總結

以上是生活随笔為你收集整理的​内核调试技巧--systemtap定位丢包原因的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。