循环中对设备的检查非常有意思:

1 if (!ptype->dev || ptype->dev == skb->dev)

  如果你试图嗅探来自eth0的数据包,但是由于eth0已经是bond的一部分,因而这个检查一定会失败。原因是skb->dev已经被重写为bond设备的dev结构了。

  这是为什么tcpdump和其他的测量工具嗅探bond相关的物理设备时看不到发送的数据包了!

  只要简单地把if语句修改成:

1 if (!ptype->dev || ptype->dev == skb->dev || ptype->dev == orig_dev) {

  因为加入了orig_dev检查,这下pcap能够处理被dev指针被修改过的skb了。

  让我们来测试一下这个修改。

  有意思的现象,第二轮观察

  接下来,重新构建并安装修改后的内核(顺便说一下,这里有一份非常有用的文档),重新ping目标机器并开始嗅探发向物理设备的数据包:
 % sudo tcpdump -i eth0 dst 172.16.209.136 and proto 1
^C
0 packets captured
2 packets received by filter
0 packets dropped by kernel

  什么情况?

  为什么修改以后还是没有看到发送的数据包?

  libpcap

  让我们快速检查一下内核中负责处理AF_PACKET地址家族的libpcap接口。

  AF_PACKET 在内核中是单独实现的一个地址家族,相关的代码位于net/packet/af_packet.c。libpcap通过调用socket系统调用建立一个socket,调用的第一个参数被设置为PACKET。libpcap接下来会使用bind系统调用把这个socket绑定想要嗅探的设备上。