当前位置:首页>Linux>Linux 网络子系统源码剖析(十五):网络子系统调试技术 - 问题定位与性能分析

Linux 网络子系统源码剖析(十五):网络子系统调试技术 - 问题定位与性能分析

  • 2026-09-11 09:08:39
Linux 网络子系统源码剖析(十五):网络子系统调试技术 - 问题定位与性能分析

从问题定位到性能调优 - 掌握网络调试的终极武器

系列:Linux 网络子系统源码剖析篇号:第 15 篇 (完结篇)内核版本:Linux 5.10 LTS重点模块:调试工具、性能分析、问题定位、故障排查


📋 本篇导读

你将学到

  • • 网络调试工具的完整使用(tcpdump、ss、netstat、ethtool)
  • • 内核调试技术(ftrace、perf、eBPF)
  • • 网络性能分析方法和工具
  • • 常见网络问题的定位和解决
  • • 数据包跟踪和分析技巧
  • • 内核网络统计信息的解读
  • • 实战调试案例和最佳实践

前置知识

  • • 已阅读第 1-14 篇文章
  • • 了解 Linux 网络协议栈
  • • 熟悉命令行工具
  • • 理解网络协议基础

阅读时间

约 90-100 分钟


🎯 概述

1.1 网络调试的挑战

网络问题的复杂性:

多层次:

多组件:

  • • 网卡硬件
  • • 网卡驱动
  • • 内核协议栈
  • • 防火墙规则
  • • 路由配置
  • • 应用程序

动态性:

  • • 网络状态实时变化
  • • 问题难以复现
  • • 性能问题间歇性出现

1.2 调试工具分类

按层次分类:

按功能分类:

  • • 连通性测试:ping, traceroute, mtr
  • • 流量分析:tcpdump, wireshark, tshark
  • • 状态查看:ss, netstat, ip
  • • 性能分析:iperf3, netperf, perf
  • • 内核跟踪:ftrace, kprobe, eBPF

2. 用户空间调试工具

2.1 连通性测试

ping - ICMP 测试:

# 基本用法ping -c 4 8.8.8.8# 指定包大小ping -s 1400 8.8.8.8# 指定间隔ping -i 0.2 8.8.8.8# 记录路由ping -R 8.8.8.8# 设置 TTLping -t 64 8.8.8.8# 洪水 ping(需要 root)ping -f 8.8.8.8# 统计信息ping -c 100 8.8.8.8 | tail -2

traceroute - 路由跟踪:

# 基本用法traceroute 8.8.8.8# 使用 ICMPtraceroute -I 8.8.8.8# 使用 TCPtraceroute -T -p 80 8.8.8.8# 不解析主机名traceroute -n 8.8.8.8# 设置最大跳数traceroute -m 20 8.8.8.8# 并行探测traceroute -N 16 8.8.8.8

mtr - 持续路由跟踪:

# 交互式模式mtr 8.8.8.8# 报告模式mtr -r -c 100 8.8.8.8# 使用 TCPmtr -T -P 80 8.8.8.8# 显示 AS 号mtr -z 8.8.8.8# JSON 输出mtr -j -c 10 8.8.8.8

2.2 流量分析

tcpdump - 抓包工具:

# ========== 基本用法 ========== ## 抓取所有流量tcpdump -i eth0# 抓取指定数量的包tcpdump -i eth0 -c 100# 保存到文件tcpdump -i eth0 -w capture.pcap# 从文件读取tcpdump -r capture.pcap# ========== 过滤器 ========== ## 主机过滤tcpdump -i eth0 host 192.168.1.1# 网络过滤tcpdump -i eth0 net 192.168.1.0/24# 端口过滤tcpdump -i eth0 port 80# 协议过滤tcpdump -i eth0 tcptcpdump -i eth0 udptcpdump -i eth0 icmp# 组合过滤tcpdump -i eth0 'tcp port 80 and host 192.168.1.1'tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0'# ========== 高级选项 ========== ## 显示详细信息tcpdump -i eth0 -vtcpdump -i eth0 -vvtcpdump -i eth0 -vvv# 显示十六进制和 ASCIItcpdump -i eth0 -X# 不解析主机名和端口tcpdump -i eth0 -nn# 显示绝对时间戳tcpdump -i eth0 -tttt# 抓取完整包(不截断)tcpdump -i eth0 -s 0# ========== 实用示例 ========== ## 抓取 HTTP 请求tcpdump -i eth0 -A 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'# 抓取 SYN 包tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0'# 抓取 DNS 查询tcpdump -i eth0 -n port 53# 抓取大包(>1000 字节)tcpdump -i eth0 'greater 1000'# 抓取特定 MAC 地址tcpdump -i eth0 ether host 00:11:22:33:44:55

Wireshark/tshark - 图形化抓包:

# tshark 命令行用法# 基本抓包tshark -i eth0# 使用显示过滤器tshark -i eth0 -Y 'tcp.port == 80'# 统计信息tshark -i eth0 -z io,stat,1# 协议层次统计tshark -i eth0 -z io,phs# 会话统计tshark -i eth0 -z conv,tcp# 导出对象tshark -r capture.pcap --export-objects http,./output/# JSON 输出tshark -i eth0 -T json# 字段提取tshark -r capture.pcap -T fields -e ip.src -e ip.dst -e tcp.port

2.3 连接状态查看

ss - Socket 统计:

# ========== 基本用法 ========== ## 显示所有 socketss -a# 显示监听 socketss -l# 显示 TCP socketss -t# 显示 UDP socketss -u# 显示进程信息ss -p# 显示详细信息ss -e# 不解析服务名ss -n# ========== 组合使用 ========== ## 显示所有 TCP 连接ss -tan# 显示监听的 TCP 端口ss -tln# 显示 ESTABLISHED 连接ss -tan state established# 显示 TIME-WAIT 连接ss -tan state time-wait# ========== 过滤 ========== ## 按端口过滤ss -tan sport = :80ss -tan dport = :3306# 按地址过滤ss -tan dst 192.168.1.1# 按状态过滤ss -tan state syn-sentss -tan state fin-wait-1# ========== 统计信息 ========== ## 汇总统计ss -s# 显示内存使用ss -m# 显示定时器ss -o# 显示 TCP 信息ss -ti# ========== 实用示例 ========== ## 查看连接最多的 IPss -tan | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head# 查看各状态的连接数ss -tan | awk '{print $1}' | sort | uniq -c# 查看 ESTABLISHED 连接的 RTTss -ti state established | grep rtt# 查看拥塞窗口ss -ti | grep cwnd

netstat - 网络统计(传统工具):

# 显示所有连接netstat -an# 显示路由表netstat -rn# 显示接口统计netstat -i# 显示协议统计netstat -s# 显示多播组netstat -g# 持续监控netstat -c

2.4 网络配置工具

ip - 网络配置:

# ========== 地址管理 ========== ## 显示所有地址ip addr show# 添加地址ip addr add 192.168.1.100/24 dev eth0# 删除地址ip addr del 192.168.1.100/24 dev eth0# ========== 链路管理 ========== ## 显示链路状态ip link show# 启动/关闭接口ip linkset eth0 upip linkset eth0 down# 设置 MTUip linkset eth0 mtu 9000# 设置 MAC 地址ip linkset eth0 address 00:11:22:33:44:55# ========== 路由管理 ========== ## 显示路由表ip route show# 添加路由ip route add 10.0.0.0/8 via 192.168.1.1# 删除路由ip route del 10.0.0.0/8# 添加默认路由ip route add default via 192.168.1.1# 查看路由ip route get 8.8.8.8# ========== 邻居表 ========== ## 显示 ARP 表ip neigh show# 添加静态 ARPip neigh add 192.168.1.1 lladdr 00:11:22:33:44:55 dev eth0# 删除 ARP 条目ip neigh del 192.168.1.1 dev eth0# ========== 统计信息 ========== ## 显示详细统计ip -s link show eth0# 持续监控ip -s -s link show eth0

ethtool - 网卡配置:

# ========== 基本信息 ========== ## 显示网卡信息ethtool eth0# 显示驱动信息ethtool -i eth0# 显示统计信息ethtool -S eth0# ========== 速度和双工 ========== ## 设置速度和双工ethtool -s eth0 speed 1000 duplex full autoneg off# 自动协商ethtool -s eth0 autoneg on# ========== Offload 特性 ========== ## 显示 offload 特性ethtool -k eth0# 启用/禁用特性ethtool -K eth0 tso onethtool -K eth0 gro onethtool -K eth0 gso on# ========== 队列配置 ========== ## 显示队列数量ethtool -l eth0# 设置队列数量ethtool -L eth0 combined 4# 显示 ring 缓冲区大小ethtool -g eth0# 设置 ring 缓冲区ethtool -G eth0 rx 4096 tx 4096# ========== 中断合并 ========== ## 显示中断合并配置ethtool -c eth0# 设置中断合并ethtool -C eth0 rx-usecs 50 rx-frames 32# 启用自适应中断合并ethtool -C eth0 adaptive-rx on adaptive-tx on# ========== 测试 ========== ## 自检测试ethtool -t eth0# 闪烁 LEDethtool -p eth0 10

🔬 内核调试技术

3.1 ftrace - 函数跟踪

ftrace 基础:

# ========== 启用 ftrace ========== ## 挂载 debugfs(如果未挂载)mount -t debugfs none /sys/kernel/debug# ftrace 目录cd /sys/kernel/debug/tracing# ========== 查看可用跟踪器 ========== #cat available_tracers# 输出:function_graph function nop# ========== 函数跟踪 ========== ## 启用函数跟踪echofunction > current_tracer# 设置过滤器(只跟踪网络相关函数)echo'tcp_*' > set_ftrace_filterecho'ip_*' >> set_ftrace_filter# 开始跟踪echo 1 > tracing_on# 查看跟踪结果cat trace# 停止跟踪echo 0 > tracing_on# 清空跟踪缓冲区echo > trace# ========== 函数图跟踪 ========== ## 启用函数图跟踪echo function_graph > current_tracer# 设置跟踪深度echo 5 > max_graph_depth# 设置图过滤器echo tcp_sendmsg > set_graph_function# 查看结果cat trace# ========== 事件跟踪 ========== ## 查看可用事件cat available_events | grep net# 启用特定事件echo 1 > events/net/netif_rx/enableecho 1 > events/net/net_dev_queue/enable# 启用所有网络事件echo 1 > events/net/enable# 查看事件格式cat events/net/netif_rx/format# ========== 实用脚本 ========== ## 跟踪 TCP 发送路径#!/bin/bashcd /sys/kernel/debug/tracingecho 0 > tracing_onecho > traceecho function_graph > current_tracerecho tcp_sendmsg > set_graph_functionecho 1 > tracing_onsleep 5echo 0 > tracing_oncat trace

3.2 kprobe - 动态探针

kprobe 使用:

# ========== 基本用法 ========== #cd /sys/kernel/debug/tracing# 添加 kprobeecho'p:myprobe tcp_sendmsg' > kprobe_events# 查看 kprobecat kprobe_events# 启用 kprobeecho 1 > events/kprobes/myprobe/enable# 查看结果cat trace# 禁用 kprobeecho 0 > events/kprobes/myprobe/enable# 删除 kprobeecho'-:myprobe' >> kprobe_events# ========== 高级用法 ========== ## 捕获参数echo'p:myprobe tcp_sendmsg size=%dx' > kprobe_events# 捕获返回值echo'r:myretprobe tcp_sendmsg ret=$retval' > kprobe_events# 捕获结构体字段echo'p:myprobe tcp_sendmsg sk=+0(%di):u64' > kprobe_events# 条件过滤echo'p:myprobe tcp_sendmsg size=%dx if size>1000' > kprobe_events

3.3 eBPF 跟踪

bpftrace 脚本:

# ========== 跟踪网络发送 ========== ## 统计发送字节数bpftrace -e 'kprobe:dev_queue_xmit { @bytes = hist(arg0->len); }'# 跟踪 TCP 连接bpftrace -e 'kprobe:tcp_connect {    printf("PID %d connecting to %s\n", pid, str(arg0));}'# 跟踪丢包bpftrace -e 'tracepoint:skb:kfree_skb {    @drop[kstack] = count();}'# ========== 网络延迟分析 ========== ## TCP 发送延迟bpftrace -e 'kprobe:tcp_sendmsg {    @start[tid] = nsecs;}kretprobe:tcp_sendmsg /@start[tid]/ {    @latency = hist(nsecs - @start[tid]);    delete(@start[tid]);}'# ========== 完整脚本示例 ========== ## tcp_life.bt - 跟踪 TCP 连接生命周期#!/usr/bin/env bpftraceBEGIN {printf("Tracing TCP connections... Hit Ctrl-C to end.\n");printf("%-8s %-16s %-6s %-16s %-6s %-8s\n","PID", "COMM", "LPORT", "RADDR", "RPORT", "DURATION");}kprobe:tcp_set_state {$sk = (struct sock *)arg0;$newstate = arg1;if ($newstate == 1) {  /* TCP_ESTABLISHED */        @start[$sk] = nsecs;        @lport[$sk] = $sk->__sk_common.skc_num;        @rport[$sk] = $sk->__sk_common.skc_dport;        @raddr[$sk] = $sk->__sk_common.skc_daddr;    }if ($newstate == 7 && @start[$sk]) {  /* TCP_CLOSE */$duration = (nsecs - @start[$sk]) / 1000000;  /* ms */printf("%-8d %-16s %-6d %-16s %-6d %-8d\n",               pid, comm, @lport[$sk],               ntop(@raddr[$sk]), @rport[$sk], $duration);        delete(@start[$sk]);        delete(@lport[$sk]);        delete(@rport[$sk]);        delete(@raddr[$sk]);    }}END {    clear(@start);    clear(@lport);    clear(@rport);    clear(@raddr);}

3.4 内核日志

dmesg - 内核消息:

# 查看所有消息dmesg# 持续监控dmesg -w# 按级别过滤dmesg -l err,warn# 按设施过滤dmesg -f kern# 显示时间戳dmesg -T# 清空缓冲区dmesg -c# 查看网络相关消息dmesg | grep -i 'eth0\|network\|tcp'

printk 调试:

/* 在内核代码中添加调试信息 */#include<linux/printk.h>/* 不同级别的 printk */pr_emerg("Emergency message\n");pr_alert("Alert message\n");pr_crit("Critical message\n");pr_err("Error message\n");pr_warning("Warning message\n");pr_notice("Notice message\n");pr_info("Info message\n");pr_debug("Debug message\n");/* 网络相关的 printk */netdev_err(dev, "Device error: %d\n", err);netdev_warn(dev, "Device warning\n");netdev_info(dev, "Device info\n");netdev_dbg(dev, "Device debug\n");/* 条件 printk */pr_debug_ratelimited("Rate limited debug\n");pr_info_once("Print only once\n");

📊 性能分析方法

4.1 perf - 性能分析

perf 基础:

# ========== 系统级分析 ========== ## 记录系统性能数据perf record -a -g -- sleep 10# 查看报告perf report# 实时监控perf top# 指定事件perf top -e cyclesperf top -e instructionsperf top -e cache-misses# ========== 网络相关分析 ========== ## 记录网络事件perf record -e net:* -a -g -- sleep 10# 跟踪特定函数perf record -e probe:tcp_sendmsg -a -g# 记录调用栈perf record -a -g --call-graph dwarf# ========== 进程级分析 ========== ## 分析特定进程perf record -p <pid> -g -- sleep 10# 分析特定命令perf record -g ./my_program# ========== 统计信息 ========== ## 统计事件perf stat -e cycles,instructions,cache-misses ./program# 网络统计perf stat -e 'net:*' -a -- sleep 10# ========== 火焰图 ========== ## 生成火焰图perf record -F 99 -a -g -- sleep 60perf script | stackcollapse-perf.pl | flamegraph.pl > flame.svg

perf 脚本示例:

#!/bin/bash# network_perf.sh - 网络性能分析脚本echo"Recording network performance for 30 seconds..."# 记录网络相关的性能数据perf record -e 'net:*' \            -e 'skb:*' \            -e 'tcp:*' \            -e 'udp:*' \            -a -g -- sleep 30# 生成报告echo"Generating report..."perf report --stdio > perf_report.txt# 生成火焰图echo"Generating flame graph..."perf script | stackcollapse-perf.pl | flamegraph.pl > network_flame.svgecho"Analysis complete!"echo"Report: perf_report.txt"echo"Flame graph: network_flame.svg"

4.2 SystemTap

SystemTap 脚本示例:

#!/usr/bin/env stap# tcp_connections.stp - 跟踪 TCP 连接probe kernel.function("tcp_connect") {    printf("%s[%d] connecting to %s:%d\n",           execname(), pid(),           ip_ntop($sk->__sk_common.skc_daddr),           $sk->__sk_common.skc_dport);}probe kernel.function("tcp_set_state") {    if ($state == 1) {  /* TCP_ESTABLISHED */        printf("%s[%d] connection established\n",               execname(), pid());    }}probe kernel.function("tcp_done") {    printf("%s[%d] connection closed\n",           execname(), pid());}

4.3 网络性能测试

iperf3 - 吞吐量测试:

# ========== 服务器端 ========== ## 启动服务器iperf3 -s# 指定端口iperf3 -s -p 5201# ========== 客户端 ========== ## TCP 测试iperf3 -c <server_ip># 指定时间iperf3 -c <server_ip> -t 60# 并行连接iperf3 -c <server_ip> -P 4# 反向测试(服务器发送)iperf3 -c <server_ip> -R# UDP 测试iperf3 -c <server_ip> -u -b 1G# 指定窗口大小iperf3 -c <server_ip> -w 256K# JSON 输出iperf3 -c <server_ip> -J > results.json# ========== 高级选项 ========== ## 设置 MSSiperf3 -c <server_ip> -M 1400# 设置 TOSiperf3 -c <server_ip> -S 0x10# 绑定到特定接口iperf3 -c <server_ip> -B eth0# 零拷贝iperf3 -c <server_ip> -Z

5. 问题排查案例

5.1 案例 1:网络丢包排查

问题描述:应用程序报告间歇性丢包。

排查步骤:

# ========== 1. 检查网卡统计 ========== ## 查看网卡错误ethtool -S eth0 | grep -i 'error\|drop\|discard'# 查看 RX/TX 队列丢包ethtool -S eth0 | grep -i 'rx.*drop\|tx.*drop'# 输出示例:# rx_dropped: 1234# tx_dropped: 0# ========== 2. 检查系统丢包 ========== ## 查看协议栈丢包netstat -s | grep -i drop# 查看 softnet 丢包cat /proc/net/softnet_stat# 第二列是丢包数# 查看 backlog 队列sysctl net.core.netdev_max_backlog# ========== 3. 检查防火墙 ========== ## 查看 iptables 丢包iptables -L -v -n | grep DROP# 查看 conntrack 表cat /proc/net/nf_conntrack | wc -lsysctl net.netfilter.nf_conntrack_max# ========== 4. 使用 dropwatch ========== ## 安装 dropwatchapt-get install dropwatch# 运行 dropwatchdropwatch -l kas# 输出会显示丢包的内核函数# ========== 5. 使用 eBPF 跟踪丢包 ========== ## 跟踪 kfree_skbbpftrace -e 'tracepoint:skb:kfree_skb {    @drop[kstack] = count();    @reason[args->reason] = count();}interval:s:10 {    print(@drop);    print(@reason);    clear(@drop);    clear(@reason);}'

解决方案:

# 根据排查结果采取措施# 1. 如果是 RX 队列丢包ethtool -G eth0 rx 4096# 2. 如果是 softnet 丢包sysctl -w net.core.netdev_max_backlog=5000sysctl -w net.core.netdev_budget=600# 3. 如果是 conntrack 表满sysctl -w net.netfilter.nf_conntrack_max=1048576# 4. 如果是中断不均衡./set_irq_affinity.sh eth0

5.2 案例 2:TCP 连接慢

问题描述:TCP 连接建立缓慢。

排查步骤:

# ========== 1. 检查 SYN 队列 ========== ## 查看 SYN 队列溢出netstat -s | grep -i 'SYNs to LISTEN'# 查看半连接队列大小sysctl net.ipv4.tcp_max_syn_backlog# 查看全连接队列大小sysctl net.core.somaxconn# ========== 2. 检查 SYN Cookie ========== ## 查看 SYN Cookie 状态sysctl net.ipv4.tcp_syncookies# 查看 SYN Cookie 统计netstat -s | grep -i 'SYN cookies'# ========== 3. 使用 ss 查看队列 ========== ## 查看监听队列ss -ltn# 输出示例:# Recv-Q Send-Q Local Address:Port#   0     128    *:80# Recv-Q: 当前队列中的连接数# Send-Q: 最大队列长度# ========== 4. 跟踪连接建立 ========== ## 使用 tcpdump 抓取 SYN 包tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0' -nn# 使用 bpftrace 跟踪bpftrace -e 'kprobe:tcp_v4_conn_request {    printf("SYN received from %s\n", ntop(arg1));}kprobe:tcp_v4_syn_recv_sock {    printf("Connection established\n");}'# ========== 5. 检查防火墙规则 ========== ## 查看 iptables 规则iptables -L -v -n# 查看 conntrack 连接数cat /proc/sys/net/netfilter/nf_conntrack_countcat /proc/sys/net/netfilter/nf_conntrack_max

解决方案:

# 1. 增大队列sysctl -w net.ipv4.tcp_max_syn_backlog=8192sysctl -w net.core.somaxconn=4096# 2. 启用 SYN Cookiesysctl -w net.ipv4.tcp_syncookies=1# 3. 启用 TCP Fast Opensysctl -w net.ipv4.tcp_fastopen=3# 4. 调整应用程序 listen backlog# 在代码中:listen(sockfd, 4096);

5.3 案例 3:高延迟问题

问题描述:网络延迟突然增高。

排查步骤:

# ========== 1. 基本延迟测试 ========== ## ICMP 延迟ping -c 100 <target> | tail -2# TCP 延迟ss -ti | grep rtt# ========== 2. 检查队列延迟 ========== ## 查看 qdisc 统计tc -s qdisc show dev eth0# 查看队列深度ip -s link show eth0# ========== 3. 检查 CPU 使用率 ========== ## 查看软中断 CPUmpstat -P ALL 1 | grep -E 'CPU|%soft'# 查看网络相关进程top -H -p $(pgrep -d',' ksoftirqd)# ========== 4. 跟踪数据包路径 ========== ## 使用 bpftrace 测量延迟bpftrace -e 'kprobe:netif_receive_skb {    @start[arg0] = nsecs;}kprobe:ip_rcv /@start[arg0]/ {    @latency["netif_rx -> ip_rcv"] = hist(nsecs - @start[arg0]);}kprobe:tcp_v4_rcv /@start[arg0]/ {    @latency["ip_rcv -> tcp_rcv"] = hist(nsecs - @start[arg0]);    delete(@start[arg0]);}'# ========== 5. 检查网卡配置 ========== ## 查看中断合并ethtool -c eth0# 查看队列数量ethtool -l eth0

解决方案:

# 1. 减小中断合并延迟ethtool -C eth0 rx-usecs 10 rx-frames 8# 2. 使用 fq_codel qdisctc qdisc replace dev eth0 root fq_codel# 3. 启用 TCP_NODELAY# 在应用程序中设置# 4. 调整 CPU 亲和性./set_irq_affinity.sh eth0

5.4 案例 4:吞吐量低

问题描述:网络吞吐量远低于预期。

排查步骤:

# ========== 1. 测试基准性能 ========== ## 使用 iperf3 测试iperf3 -c <server> -t 60 -P 4# ========== 2. 检查 TCP 窗口 ========== ## 查看 TCP 窗口大小ss -ti | grep -E 'wscale|rcv_space'# 查看 TCP 缓冲区配置sysctl net.ipv4.tcp_rmemsysctl net.ipv4.tcp_wmem# ========== 3. 检查拥塞控制 ========== ## 查看拥塞控制算法sysctl net.ipv4.tcp_congestion_control# 查看可用算法sysctl net.ipv4.tcp_available_congestion_control# 查看连接的拥塞窗口ss -ti | grep cwnd# ========== 4. 检查 Offload 特性 ========== ## 查看 TSO/GSO/GROethtool -k eth0 | grep -E 'tcp-segmentation|generic-segmentation|generic-receive'# ========== 5. 检查 MTU ========== ## 查看 MTUip link show eth0# 测试路径 MTUtracepath <target># ========== 6. 检查重传 ========== ## 查看重传统计netstat -s | grep -i retrans# 实时监控重传ss -ti | grep -E 'retrans|lost'

解决方案:

# 1. 增大 TCP 缓冲区sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"# 2. 启用 TCP 窗口缩放sysctl -w net.ipv4.tcp_window_scaling=1# 3. 切换拥塞控制算法sysctl -w net.ipv4.tcp_congestion_control=bbr# 4. 启用所有 Offloadethtool -K eth0 tso on gso on gro on# 5. 增大 MTU(如果支持)ip linkset eth0 mtu 9000

6. 调试最佳实践

6.1 系统化排查方法

自顶向下方法:

1. 应用层   ├─ 检查应用日志   ├─ 使用 strace 跟踪系统调用   └─ 检查 socket 选项2. 传输层   ├─ 使用 ss/netstat 查看连接状态   ├─ 检查 TCP 参数   └─ 分析重传和丢包3. 网络层   ├─ 检查路由表   ├─ 检查 iptables 规则   └─ 分析 IP 分片4. 链路层   ├─ 检查网卡状态   ├─ 查看网卡统计   └─ 检查 MTU5. 物理层   ├─ 检查链路状态   ├─ 检查错误计数   └─ 测试线缆

6.2 常用调试组合

连通性问题:

# 1. 基本连通性ping <target># 2. 路由跟踪traceroute <target># 3. DNS 解析nslookup <hostname>dig <hostname># 4. 端口测试telnet <target> <port>nc -zv <target> <port># 5. 抓包分析tcpdump -i eth0 host <target> -w capture.pcap

性能问题:

# 1. 系统资源topmpstat -P ALL 1vmstat 1# 2. 网络统计ss -snetstat -s# 3. 网卡统计ethtool -S eth0ip -s link show eth0# 4. 性能测试iperf3 -c <server># 5. 性能分析perf record -a -gperf report

6.3 调试脚本模板

网络诊断脚本:

#!/bin/bash# network_diag.sh - 网络诊断脚本OUTPUT_DIR="network_diag_$(date +%Y%m%d_%H%M%S)"mkdir -p "$OUTPUT_DIR"echo"Starting network diagnostics..."# ========== 1. 基本信息 ========== #echo"Collecting basic information..."uname -a > "$OUTPUT_DIR/system_info.txt"ip addr show > "$OUTPUT_DIR/ip_addr.txt"ip route show > "$OUTPUT_DIR/ip_route.txt"ip neigh show > "$OUTPUT_DIR/ip_neigh.txt"# ========== 2. 网卡信息 ========== #echo"Collecting interface information..."for iface in $(ls /sys/class/net/); doif [ "$iface" != "lo" ]; then        ethtool "$iface" > "$OUTPUT_DIR/ethtool_${iface}.txt" 2>&1        ethtool -S "$iface" > "$OUTPUT_DIR/ethtool_stats_${iface}.txt" 2>&1        ethtool -k "$iface" > "$OUTPUT_DIR/ethtool_features_${iface}.txt" 2>&1fidone# ========== 3. 连接状态 ========== #echo"Collecting connection information..."ss -tan > "$OUTPUT_DIR/ss_tcp.txt"ss -uan > "$OUTPUT_DIR/ss_udp.txt"ss -s > "$OUTPUT_DIR/ss_summary.txt"# ========== 4. 统计信息 ========== #echo"Collecting statistics..."netstat -s > "$OUTPUT_DIR/netstat_stats.txt"cat /proc/net/softnet_stat > "$OUTPUT_DIR/softnet_stat.txt"cat /proc/net/sockstat > "$OUTPUT_DIR/sockstat.txt"# ========== 5. 防火墙规则 ========== #echo"Collecting firewall rules..."iptables -L -v -n > "$OUTPUT_DIR/iptables.txt" 2>&1iptables -t nat -L -v -n > "$OUTPUT_DIR/iptables_nat.txt" 2>&1# ========== 6. 系统参数 ========== #echo"Collecting sysctl parameters..."sysctl -a | grep -E 'net\.' > "$OUTPUT_DIR/sysctl_net.txt" 2>&1# ========== 7. 内核日志 ========== #echo"Collecting kernel logs..."dmesg | grep -i 'network\|eth\|tcp\|udp' > "$OUTPUT_DIR/dmesg_network.txt"# ========== 8. 进程信息 ========== #echo"Collecting process information..."ps aux | grep -E 'network|tcp|udp' > "$OUTPUT_DIR/processes.txt"# ========== 9. 创建摘要 ========== #echo"Creating summary..."cat > "$OUTPUT_DIR/summary.txt" << EOFNetwork Diagnostics SummaryGenerated: $(date)System: $(uname -a)Network Interfaces:$(ip -br addr show)Active Connections:$(ss -s)Top Network Processes:$(ps aux --sort=-%cpu | grep -E 'network|tcp|udp' | head -10)Recent Network Errors:$(dmesg | grep -i 'error\|fail' | grep -i 'network\|eth' | tail -20)EOFecho"Diagnostics complete! Results saved to: $OUTPUT_DIR"

7. 总结

7.1 核心要点

调试工具分类:

  • • 连通性:ping, traceroute, mtr
  • • 流量分析:tcpdump, wireshark
  • • 状态查看:ss, netstat, ip
  • • 性能分析:perf, iperf3, bpftrace
  • • 内核跟踪:ftrace, kprobe, eBPF

排查方法:

  • • 自顶向下:从应用层到物理层
  • • 分层诊断:每层独立验证
  • • 对比分析:正常 vs 异常
  • • 数据驱动:基于统计数据

常见问题:

  • • 丢包:检查队列、防火墙、硬件
  • • 延迟:检查队列、中断、拥塞控制
  • • 吞吐量:检查窗口、MTU、Offload
  • • 连接慢:检查队列、SYN Cookie

7.2 调试检查清单

基础检查:

# 1. 网卡状态ip link showethtool eth0# 2. IP 配置ip addr showip route show# 3. 连接状态ss -tanss -s# 4. 统计信息netstat -sethtool -S eth0# 5. 系统参数sysctl -a | grep net.

性能检查:

# 1. CPU 使用率mpstat -P ALL 1# 2. 中断分布cat /proc/interrupts | grep eth0# 3. 队列状态tc -s qdisc show# 4. Offload 特性ethtool -k eth0# 5. 缓冲区大小sysctl net.ipv4.tcp_rmemsysctl net.ipv4.tcp_wmem

7.3 推荐工具组合

日常监控:

  • • ss: 连接状态
  • • ip: 网络配置
  • • ethtool: 网卡状态
  • • dmesg: 内核日志

问题排查:

  • • tcpdump: 抓包分析
  • • perf: 性能分析
  • • bpftrace: 内核跟踪
  • • iperf3: 性能测试

深度调试:

  • • ftrace: 函数跟踪
  • • kprobe: 动态探针
  • • SystemTap: 脚本跟踪
  • • crash: 内核崩溃分析

8. 常见问题(FAQ)

8.1 如何快速定位网络问题?

快速诊断流程:

# 1. 检查连通性(10 秒)ping -c 4 <target># 2. 检查路由(10 秒)traceroute -n <target># 3. 检查端口(5 秒)nc -zv <target> <port># 4. 检查本地状态(5 秒)ss -tan | grep <target># 5. 抓包分析(30 秒)tcpdump -i eth0 host <target> -c 100# 总计:约 1 分钟

8.2 tcpdump 和 Wireshark 如何选择?

tcpdump:

  • • 命令行工具
  • • 适合服务器环境
  • • 适合自动化脚本
  • • 资源占用小

Wireshark:

  • • 图形界面
  • • 适合详细分析
  • • 强大的过滤和统计
  • • 适合本地分析

推荐组合:

# 服务器上用 tcpdump 抓包tcpdump -i eth0 -w capture.pcap# 下载到本地用 Wireshark 分析scp user@server:capture.pcap .wireshark capture.pcap

8.3 如何分析网络延迟?

延迟分析方法:

# 1. ICMP 延迟ping -c 100 <target> | tail -2# 2. TCP 延迟ss -ti | grep rtt# 3. 应用层延迟curl -w "@curl-format.txt" -o /dev/null -s <url># curl-format.txt:time_namelookup:  %{time_namelookup}\ntime_connect:     %{time_connect}\ntime_starttransfer: %{time_starttransfer}\ntime_total:       %{time_total}\n# 4. 使用 bpftrace 测量内核延迟bpftrace -e 'kprobe:tcp_sendmsg {    @start[tid] = nsecs;}kretprobe:tcp_sendmsg /@start[tid]/ {    @latency = hist(nsecs - @start[tid]);    delete(@start[tid]);}'

8.4 如何监控网络丢包?

丢包监控方法:

# 1. 网卡丢包watch -n 1 'ethtool -S eth0 | grep drop'# 2. 协议栈丢包watch -n 1 'netstat -s | grep -i drop'# 3. 队列丢包watch -n 1 'cat /proc/net/softnet_stat'# 4. 使用 dropwatchdropwatch -l kas# 5. 使用 eBPF 实时监控bpftrace -e 'tracepoint:skb:kfree_skb {    @drop[kstack] = count();}interval:s:5 {    print(@drop);    clear(@drop);}'

8.5 如何调试内核网络代码?

内核调试方法:

# 1. 添加 printk# 在内核代码中添加:pr_info("Debug: value=%d\n", value);# 重新编译内核make -j$(nproc)make modules_installmake install# 查看输出dmesg | tail# 2. 使用 ftraceecho function_graph > /sys/kernel/debug/tracing/current_tracerecho tcp_sendmsg > /sys/kernel/debug/tracing/set_graph_functionecho 1 > /sys/kernel/debug/tracing/tracing_on# 3. 使用 kprobeecho'p:myprobe tcp_sendmsg' > /sys/kernel/debug/tracing/kprobe_eventsecho 1 > /sys/kernel/debug/tracing/events/kprobes/myprobe/enable# 4. 使用 crash 分析崩溃crash /usr/lib/debug/vmlinux /var/crash/vmcore

9. 参考资料

9.1 官方文档

内核文档:

  • • Linux Kernel Documentation: https://www.kernel.org/doc/html/latest/
  • • Networking Documentation: https://www.kernel.org/doc/html/latest/networking/

工具文档:

  • • tcpdump: https://www.tcpdump.org/
  • • Wireshark: https://www.wireshark.org/docs/
  • • perf: https://perf.wiki.kernel.org/

9.2 经典书籍

  1. 1. 《Systems Performance: Enterprise and the Cloud》- Brendan Gregg
  2. 2. 《BPF Performance Tools》- Brendan Gregg
  3. 3. 《TCP/IP Illustrated》- W. Richard Stevens
  4. 4. 《Linux Observability with BPF》

9.3 在线资源

技术博客:

  • • Brendan Gregg's Blog: http://www.brendangregg.com/
  • • Julia Evans' Blog: https://jvns.ca/
  • • PackageCloud Blog: https://blog.packagecloud.io/

工具集合:

  • • perf-tools: https://github.com/brendangregg/perf-tools
  • • bcc-tools: https://github.com/iovisor/bcc
  • • bpftrace: https://github.com/iovisor/bpftrace

9.4 调试工具速查

连通性测试:

ping, traceroute, mtr, nc, telnet

流量分析:

tcpdump, wireshark, tshark, ngrep

状态查看:

ss, netstat, ip, ethtool, ifconfig

性能分析:

perf, iperf3, netperf, sar, vmstat

内核跟踪:

ftrace, kprobe, bpftrace, SystemTap

10. 系列回顾

10.1 系列文章总览

本系列共 15 篇文章,全面剖析了 Linux 网络子系统:

第一部分:基础架构(3 篇)

  1. 1. 网络子系统总览与初始化
  2. 2. sk_buff 深度解析
  3. 3. 网络设备驱动框架

第二部分:协议栈实现(5 篇)4. 二层处理与网桥5. IP 层实现(上)- 接收与路由6. IP 层实现(下)- 发送与分片7. TCP 协议实现(上)- 连接管理8. TCP 协议实现(下)- 数据传输与拥塞控制

第三部分:高级特性(4 篇)9. Netfilter 与 iptables 源码解析10. 流量控制(QoS)源码解析11. 套接字层实现12. 网络命名空间(Network Namespace)

第四部分:性能优化(3 篇)13. 网络性能优化技术14. eBPF/XDP 网络加速15. 网络子系统调试技术

10.2 核心知识点

数据结构:

  • • sk_buff: 网络数据包的核心结构
  • • net_device: 网络设备抽象
  • • sock: socket 的内核表示
  • • net: 网络命名空间

关键流程:

  • • 数据包接收:网卡 → 驱动 → 协议栈 → 应用
  • • 数据包发送:应用 → 协议栈 → 驱动 → 网卡
  • • TCP 连接:三次握手、数据传输、四次挥手
  • • 路由查找:FIB trie 最长前缀匹配

性能优化:

  • • 零拷贝:sendfile, splice, MSG_ZEROCOPY
  • • 硬件 Offload:TSO/GSO, GRO/LRO, RSS
  • • 多队列:RPS, RFS, XPS
  • • eBPF/XDP:可编程数据平面

10.3 学习建议

初学者:

  1. 1. 从第 1-3 篇开始,理解基础架构
  2. 2. 动手实践,编译和调试内核
  3. 3. 使用 tcpdump 分析数据包
  4. 4. 阅读简单的驱动代码

进阶者:

  1. 1. 深入学习第 4-8 篇,理解协议栈
  2. 2. 分析 TCP 状态机和拥塞控制
  3. 3. 使用 perf 和 ftrace 分析性能
  4. 4. 尝试修改内核代码

高级用户:

  1. 1. 研究第 9-15 篇,掌握高级特性
  2. 2. 开发 eBPF/XDP 程序
  3. 3. 优化网络性能
  4. 4. 参与内核社区贡献

系列完结

感谢您阅读《Linux 网络子系统源码剖析系列》!

本系列涵盖了从基础到高级的所有重要主题。希望这些内容能帮助您深入理解 Linux 网络子系统,在实际工作中解决问题,并激发您对内核开发的兴趣。

作者:肇中内核版本:Linux 5.10 LTS

勘误和建议:欢迎提出勘误和改进建议。

致谢:

  • • Linux 内核社区
  • • 所有开源贡献者
  • • 读者的支持和反馈

祝您在 Linux 内核网络的学习和研究中取得成功!

最新文章

随机文章