DM8168芯片运行Linux操作系统,有两个物理网口。在某项目中需要绕过协议栈直接收发以太网帧,本文总结调试过程中的几处注意事项。
收发以太网帧
有两种原始套接字可以处理底层数据。一种是处理IP层及其上的数据,通过指定socket第一个参数为AF_INET来创建这种套接字。另一种是处理数据链路层及其上的数据,通过指定socket第一个参数为PF_PACKET来创建这种套接字。我们需要使用第二种原始套接字来直接收发以太网帧:
sd = socket (PF_PACKET, SOCK_RAW, htons (protocol))
其中protocol对应TCP/IP协议中链路层以太网帧的类型字段,如0x0800代表IP包,0x0806代表ARP包。在<include/linux/if_ether.h>
中有详细定义。用户也可以定义自己的非标准类型,用在自组网中。
这样创建的socket与具体网络接口并没有关系,多网卡上任意一个网卡收到的符合protocol类型的数据包都会被传递到这个socket中。如果想指定从某个网卡上接收数据包,则要对接收数据过滤目的MAC地址。
首先通过ioctl()
获取该网卡的MAC地址。interface是接口名,如”eth0”:
struct ifreq ifr;