使用NDB调试网络栈
__dhd_sendpkt
为了查看bcmdhd的发送网络包,需要先在`__dhd_sendpkt`处设置断点。
bl
0 e ffffff80`011b45e8 0001 (0001) bcmdhd!__dhd_sendpkt
断点命中后,可以在右侧看到源代码(当然需要.srcpath+ 指定内核源代码的路径)。
具体可以参照下方链接内的文章进行操作。
通过1:kd可以知道,1号CPU正在处理网络包,如果这个时候切到其他CPU(GDK8共有4个CPU),就可以看到它们正在干别的事情。
比如3号CPU这个时候正在处理中断事件,下面是切断3号CPU后的栈回溯。
k
Child-SP RetAddr Call Site
ffffff80`0801bf60 ffffff80`080c0968 lk!ksoftirqd_running+0x24 [kernel/softirq.c @ 92]
ffffff80`0801bf60 ffffff80`08127100 lk!irq_exit+0x90 [kernel/softirq.c @ 362]
ffffff80`0801bf60 ffffff80`080811c0 lk!__handle_domain_irq+0x60 [./include/asm-generic/irq_regs.h @ 33]
ffffff80`0801bf60 ffffff80`08082ee8 lk!gic_handle_irq+0x58 [./arch/arm64/include/asm/io.h @ 90]
ffffff80`0801bf60 ffffff80`08127100 lk!el1_irq+0xe8 [arch/arm64/kernel/entry.S @ 645]
ffffff80`0801bf60 ffffff80`080811c0 lk!__handle_domain_irq+0x60 [./include/asm-generic/irq_regs.h @ 33]
ffffff80`0801bf60 ffffff80`08082ee8 lk!gic_handle_irq+0x58 [./arch/arm64/include/asm/io.h @ 90]
ffffff80`0801bf60 ffffff80`08127100 lk!el1_irq+0xe8 [arch/arm64/kernel/entry.S @ 645]
ffffff80`0801bf60 ffffff80`080811c0 lk!__handle_domain_irq+0x60 [./include/asm-generic/irq_regs.h @ 33]
ffffff80`0801bf60 ffffff80`08082ee8 lk!gic_handle_irq+0x58 [./arch/arm64/include/asm/io.h @ 90]
ffffff80`0801bf60 ffffff80`08127100 lk!el1_irq+0xe8 [arch/arm64/kernel/entry.S @ 645]
ffffff80`0801bf60 ffffff80`080811c0 lk!__handle_domain_irq+0x60 [./include/asm-generic/irq_regs.h @ 33]
ffffff80`0801bf60 ffffff80`08082ee8 lk!gic_handle_irq+0x58 [./arch/arm64/include/asm/io.h @ 90]
ffffff80`0801bf60 ffffff80`08127100 lk!el1_irq+0xe8 [arch/arm64/kernel/entry.S @ 645]
ffffff80`0801bf60 ffffff80`080811c0 lk!__handle_domain_irq+0x60 [./include/asm-generic/irq_regs.h @ 33]
ffffff80`0801bf60 ffffff80`08082ee8 lk!gic_handle_irq+0x58 [./arch/arm64/include/asm/io.h @ 90]
ffffff80`0801bf60 ffffff80`08127100 lk!el1_irq+0xe8 [arch/arm64/kernel/entry.S @ 645]
ffffff80`0801bf60 ffffff80`080811c0 lk!__handle_domain_irq+0x60 [./include/asm-generic/irq_regs.h @ 33]
ffffff80`0801bf60 ffffff80`08082ee8 lk!gic_handle_irq+0x58 [./arch/arm64/include/asm/io.h @ 90]
ffffff80`0801bf60 ffffff80`08127100 lk!el1_irq+0xe8 [arch/arm64/kernel/entry.S @ 645]
先看一下栈回溯,用于k只能看到前20个栈帧,所以用kn 150显示完整的调用栈。
从下面的栈回溯里面可以看到,网络包先经过内核进入到了udp协议栈,然后进入ip层,接着进入链路层,链路层这里是
Linux内核的通用实现,先调用统一实现,之后进入到博通厂商的bcmdhd驱动内,最后开始发生网络包。
kn 150
# Child-SP RetAddr Call Site
00 ffffff80`0b79b640 ffffff80`011bc404 bcmdhd!__dhd_sendpkt [drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c @ 4754]
01 ffffff80`0b79b640 ffffff80`08d838dc bcmdhd!dhd_start_xmit+0x3bc [drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c @ 5366]
02 ffffff80`0b79b640 ffffff80`08dc2e2c lk!dev_hard_start_xmit+0x9c [./include/linux/netdevice.h @ 4390]
03 ffffff80`0b79b640 ffffff80`08dc30b8 lk!sch_direct_xmit+0x1ac [net/sched/sch_generic.c @ 332]
04 ffffff80`0b79b640 ffffff80`08d83e14 lk!__qdisc_run+0x138 [net/sched/sch_generic.c @ 403]
05 ffffff80`0b79b640 ffffff80`08d84478 lk!__dev_queue_xmit+0x254 [./include/linux/seqlock.h @ 234]
06 ffffff80`0b79b640 ffffff80`08d97cd0 lk!dev_queue_xmit+0x10 [net/core/dev.c @ 3872]
07 ffffff80`0b79b640 ffffff80`08eedb58 lk!neigh_resolve_output+0xf0 [net/core/neighbour.c @ 1384]
08 ffffff80`0b79b640 ffffff80`08ef18f4 lk!ip6_finish_output2+0x270 [./include/net/neighbour.h @ 501]
09 ffffff80`0b79b640 ffffff80`08ef1a1c lk!ip6_finish_output+0x1b4 [net/ipv6/ip6_output.c @ 155]
0a ffffff80`0b79b640 ffffff80`08f47974 lk!ip6_output+0x74 [./include/linux/netfilter.h @ 278]
0b ffffff80`0b79b640 ffffff80`08ef21d8 lk!ip6_local_out+0x44 [net/ipv6/output_core.c @ 181]
0c ffffff80`0b79b640 ffffff80`08f13abc lk!ip6_send_skb+0x28 [net/ipv6/ip6_output.c @ 1704]
0d ffffff80`0b79b640 ffffff80`08f1462c lk!udp_v6_send_skb.isra.6+0x164 [net/ipv6/udp.c @ 1115]
0e ffffff80`0b79b640 ffffff80`08ea09ec lk!udpv6_sendmsg+0x76c [net/ipv6/udp.c @ 1411]
0f ffffff80`0b79b640 ffffff80`08d5f598 lk!inet_sendmsg+0x34 [n