Libnet是一个用于构建和注入网络数据包的便携式框架。它提供了在IP层和链路层创建数据包的功能,以及一系列辅助和补充功能。Libnet非常适合编写网络工具和网络测试代码。一些使用libnet的项目包括arping、ettercap、ipguard、isic、nemesis、packit、tcptraceroute和yersinia。
通常使用c语言编写网络数据报文的程序时,会选择libnet这个成熟的第三方库,其源码地址如下
GitHub - libnet/libnet: A portable framework for low-level network packet construction
网上有很多的教程教授如何使用libnet库,我就不再这里赘述了,这篇文章主要来分析使用libnet库造成的性能下降问题。
使用libnet库,在网口带宽不高的时候,看不出来其对性能会造成影响。但一旦全速跑带宽时,就会发现,libnet库会造成至少10%的性能下降。
那么是什么原因造成的性能下降呢?让我们从探索过程中找寻问题的答案。
开始时,我发现了性能下降的问题,由此,先从我们自己的代码入手来分析。经过添加断点,我发现,当我初始化libnet后,性能立马会下降,即执行libnet_init函数。
然后我就进入源码查看libnet_init做了什么工作。经过分析,我发现libnet_open_link是罪魁祸首的函数。以下是其具体的源码。
这里面,唯一可能出现问题的,就是socket语句。socket语句中最后可能出问题的就是最后的参数,那么我们来看一下最后的参数是什么含义。
基于上述的描述,我们可以发现,除了不指定(即设置0)外,其他的设置方式,都会造成socket既接收报文又发送报文,而原始套接字的接收报文,是要进行一次额外的内存拷贝的。
所以问题的原因就定位清除了,是因为原始套接字的最后的参数,造成了额外的内存拷贝,所以影响了机器的性能。如果你是用的libnet仅仅只是用于构造报文并发送,并且需要较高的性能,那可以将源码中的ETH_P_ALL改成0,重新编译自己的libnet库。