Wireshark工具
WireShark是非常流行的网络封包分析工具,可以截取各种网络数据包,并显示数据包详细信息 ,软件还能够实时监测到各种网络数据的通讯情况,可以快速的获取其里面的信息抓取各种有用的东西,软件还自带强大的过滤工具,让用户能够进一步筛选自己想要的信息文件包,删除掉不需要的内容。
Wireshark使用
工具可以在官网wireshark.org下载。
选择最新稳定版本后开始下载安装
1.1 tcpdump抓包
tcpdump 的常用参数如下:
-i : 选择要捕获的接口,通常是以太网卡或无线网卡,也可以是 vlan 或其他特殊接口。如果该系统上只有一个网络接口,则无需指定。
-nn : 单个 n 表示不解析域名,直接显示 IP;两个 n 表示不解析域名和端口。这样不仅方便查看 IP 和端口号,而且在抓取大量数据时非常高效,因为域名解析会降低抓取速度。
-s0 : tcpdump 默认只会截取前 96 字节的内容,要想截取所有的报文内容,可以使用 -s number, number 就是你要截取的报文字节数,如果是 0 的话,表示截取报文全部内容。
-v : 使用 -v,-vv 和 -vvv 来显示更多的详细信息,通常会显示更多与特定协议相关的信息。
port 80 : 这是一个常见的端口过滤器,表示仅抓取 80 端口上的流量,通常是 HTTP。
-w : 选项用来把数据报文输出到文件,以便后面使用其他图形工具(比如 wireshark,Snort)来分析。
1.2 Host过滤器
Host 过滤器用来过滤某个主机的数据报文。例如:
该命令会抓取所有发往主机 1.2.3.4 或者从主机 1.2.3.4 发出的流量。如果想只抓取从该主机发出的流量,可以使用下面的命令:
1.3 NetWork过滤器
抓取所有发往网段 192.168.1.x 或从网段 192.168.1.x 发出的流量:
抓取所有发往网段 10.x.x.x 或从网段 10.x.x.x 发出的流量:
和 Host 过滤器一样,这里也可以指定源和目的:
dropwatch
dropwatch工具用来定位网络丢包问题。
dropwatch使用
在openEuler系统上,可以直接使用yum安装dropwatch
以下案例基于cenots7.6环境。
Dropwatch 本身有一个交互命令行,命令中的 kas 指的是加载对应的符号表:
在本例子中,Dropwatch 显示在 init_dummy_netdev 附近存在大量丢包现象,提示信息格式的大致说明是:丢包数量 drops at 函数名+偏移量 (地址)。 下面让我们看看为什么会提示丢包,直接在符号表里搜索:
可见 init_dummy_netdev 的地址是 ffffffff81459cc0,加上偏移量 50 等于 ffffffff81459d10,正好是 net_tx_action 的地址(注:如果计算后的地址在两个函数之间,那么取前者),于是我们得出结论,实际丢包是发生在 net_tx_action 函数中。
搞清楚了案发地,接下来可以通过 kernel-debuginfo-common 包来获取源代码路径,在本例子中,安装对应的包后执行命令显示源代码位于 usr/src/debug 目录。 前面提到过系统通过跟踪 kfree_skb 来确认丢包的,那么看看 kfree_skb 的定义:
实际上起作用的是 trace_kfree_skb,所以直接或间接调用 trace_kfree_skb 和 kfree_skb 的地方就意味着有丢包,不过需要说明的是 __kfree_skb 不表示丢包,可以无视。
有了如上的准备工作,下面开始搜索 net_tx_action 的源代码:
shell> grep -wr net_tx_action usr/src/debug 终于可以看到庐山真面目了,2.6.32 版本的 net_tx_action 源代码如下:
根据之前的分析,我们可以推断出就是在 trace_kfree_skb(skb, net_tx_action); 这一行丢的包。通常找到代码中丢包的具体位置后,我们需要做的就是代码前后看看是否触发了什么限制,比如说队列太小了,缓冲不够之类的,不过在本例子中,看上去是清除完成队列里的数据,这并没有什么问题。以 dropwatch + net_tx_action 为关键字去搜索后找到一篇文章:net_tx_action: Call trace_consume_skb() instead of trace_kfree_skb(),似乎验证了我们之前的猜测,带着疑惑查看最新版本代码中 net_tx_action 的源代码:
在新版本的源代码中区分了 trace_consume_skb 和 trace_kfree_skb 的使用,而我们知道 trace_kfree_skb 表示丢包,而trace_consume_skb是无害的,至此我们可以基本确定:在本例子中所谓的丢包是旧版本内核的误判。虽然这次纠错过程最终被证实为虚惊一场,但是相信大家在过程中已经学会了如何使用 Dropwatch。
Wireshark工具
WireShark是非常流行的网络封包分析工具,可以截取各种网络数据包,并显示数据包详细信息 ,软件还能够实时监测到各种网络数据的通讯情况,可以快速的获取其里面的信息抓取各种有用的东西,软件还自带强大的过滤工具,让用户能够进一步筛选自己想要的信息文件包,删除掉不需要的内容。
Wireshark使用
工具可以在官网wireshark.org下载。
选择最新稳定版本后开始下载安装
1.1 tcpdump抓包
tcpdump 的常用参数如下:
-i : 选择要捕获的接口,通常是以太网卡或无线网卡,也可以是 vlan 或其他特殊接口。如果该系统上只有一个网络接口,则无需指定。
-nn : 单个 n 表示不解析域名,直接显示 IP;两个 n 表示不解析域名和端口。这样不仅方便查看 IP 和端口号,而且在抓取大量数据时非常高效,因为域名解析会降低抓取速度。
-s0 : tcpdump 默认只会截取前 96 字节的内容,要想截取所有的报文内容,可以使用 -s number, number 就是你要截取的报文字节数,如果是 0 的话,表示截取报文全部内容。
-v : 使用 -v,-vv 和 -vvv 来显示更多的详细信息,通常会显示更多与特定协议相关的信息。
port 80 : 这是一个常见的端口过滤器,表示仅抓取 80 端口上的流量,通常是 HTTP。
-w : 选项用来把数据报文输出到文件,以便后面使用其他图形工具(比如 wireshark,Snort)来分析。
1.2 Host过滤器
Host 过滤器用来过滤某个主机的数据报文。例如:
该命令会抓取所有发往主机 1.2.3.4 或者从主机 1.2.3.4 发出的流量。如果想只抓取从该主机发出的流量,可以使用下面的命令:
1.3 NetWork过滤器
抓取所有发往网段 192.168.1.x 或从网段 192.168.1.x 发出的流量:
抓取所有发往网段 10.x.x.x 或从网段 10.x.x.x 发出的流量:
和 Host 过滤器一样,这里也可以指定源和目的:
dropwatch
dropwatch工具用来定位网络丢包问题。
dropwatch使用
在openEuler系统上,可以直接使用yum安装dropwatch
以下案例基于cenots7.6环境。
Dropwatch 本身有一个交互命令行,命令中的 kas 指的是加载对应的符号表:
在本例子中,Dropwatch 显示在 init_dummy_netdev 附近存在大量丢包现象,提示信息格式的大致说明是:丢包数量 drops at 函数名+偏移量 (地址)。 下面让我们看看为什么会提示丢包,直接在符号表里搜索:
可见 init_dummy_netdev 的地址是 ffffffff81459cc0,加上偏移量 50 等于 ffffffff81459d10,正好是 net_tx_action 的地址(注:如果计算后的地址在两个函数之间,那么取前者),于是我们得出结论,实际丢包是发生在 net_tx_action 函数中。
搞清楚了案发地,接下来可以通过 kernel-debuginfo-common 包来获取源代码路径,在本例子中,安装对应的包后执行命令显示源代码位于 usr/src/debug 目录。 前面提到过系统通过跟踪 kfree_skb 来确认丢包的,那么看看 kfree_skb 的定义:
void __kfree_skb(struct sk_buff *skb) { skb_release_all(skb); kfree_skbmem(skb); } EXPORT_SYMBOL(__kfree_skb); void kfree_skb(struct sk_buff *skb) { if (unlikely(!skb)) return; if (likely(atomic_read(&skb->users) == 1)) smp_rmb(); else if (likely(!atomic_dec_and_test(&skb->users))) return; trace_kfree_skb(skb, __builtin_return_address(0)); __kfree_skb(skb); } EXPORT_SYMBOL(kfree_skb);实际上起作用的是 trace_kfree_skb,所以直接或间接调用 trace_kfree_skb 和 kfree_skb 的地方就意味着有丢包,不过需要说明的是 __kfree_skb 不表示丢包,可以无视。
有了如上的准备工作,下面开始搜索 net_tx_action 的源代码:
shell> grep -wr net_tx_action usr/src/debug 终于可以看到庐山真面目了,2.6.32 版本的 net_tx_action 源代码如下:
static void net_tx_action(struct softirq_action *h) { struct softnet_data *sd = &__get_cpu_var(softnet_data); if (sd->completion_queue) { struct sk_buff *clist; local_irq_disable(); clist = sd->completion_queue; sd->completion_queue = NULL; local_irq_enable(); while (clist) { struct sk_buff *skb = clist; clist = clist->next; WARN_ON(atomic_read(&skb->users)); trace_kfree_skb(skb, net_tx_action); __kfree_skb(skb); } }根据之前的分析,我们可以推断出就是在 trace_kfree_skb(skb, net_tx_action); 这一行丢的包。通常找到代码中丢包的具体位置后,我们需要做的就是代码前后看看是否触发了什么限制,比如说队列太小了,缓冲不够之类的,不过在本例子中,看上去是清除完成队列里的数据,这并没有什么问题。以 dropwatch + net_tx_action 为关键字去搜索后找到一篇文章:net_tx_action: Call trace_consume_skb() instead of trace_kfree_skb(),似乎验证了我们之前的猜测,带着疑惑查看最新版本代码中 net_tx_action 的源代码:
static __latent_entropy void net_tx_action(struct softirq_action *h) { struct softnet_data *sd = this_cpu_ptr(&softnet_data); if (sd->completion_queue) { struct sk_buff *clist; local_irq_disable(); clist = sd->completion_queue; sd->completion_queue = NULL; local_irq_enable(); while (clist) { struct sk_buff *skb = clist; clist = clist->next; WARN_ON(atomic_read(&skb->users)); if (likely(get_kfree_skb_cb(skb)->reason == SKB_REASON_CONSUMED)) trace_consume_skb(skb); else trace_kfree_skb(skb, net_tx_action); if (skb->fclone != SKB_FCLONE_UNAVAILABLE) __kfree_skb(skb); else __kfree_skb_defer(skb); } __kfree_skb_flush(); } ...在新版本的源代码中区分了 trace_consume_skb 和 trace_kfree_skb 的使用,而我们知道 trace_kfree_skb 表示丢包,而trace_consume_skb是无害的,至此我们可以基本确定:在本例子中所谓的丢包是旧版本内核的误判。虽然这次纠错过程最终被证实为虚惊一场,但是相信大家在过程中已经学会了如何使用 Dropwatch。