前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Libpcap 落地包转发及性能调优

Libpcap 落地包转发及性能调优

作者头像
宋天伦
发布2023-10-18 09:20:26
6070
发布2023-10-18 09:20:26
举报
文章被收录于专栏:frytea

本文 首发于 🌱 煎茶,请注明 来源。

近期接到一个需求,需要使用 libpcap 从某网卡抓包发送到另一张网卡,关于 libpcap 的使用方法在这里不再赘述,网上有很多教程,本文最后会给出一个示例程序。这里记录一个转发效率性能调优的方法。

在写好程序后,发现 Ping 的延时很高,优化了一个参数后得到了极大的改善了。

发现是自己在使用这个函数打开网络设备时的超时时间设定不合理导致的:

代码语言:javascript
复制
函数名称: pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
函数功能:获得用于捕获网络数据包的数据包捕获描述字。
参数说明:device参数为指定打开的网络设备名。snaplen参数定义捕获数据的最大字节数。promisc指定是否将网络接口置于混杂模式。toms参数指*定超时时间(毫秒)。ebuf参数则仅在pcapopen_live()函数出错返回NULL时用于传递错误消息。

我将其中的第四个参数,由之前的 1000 改为 1 ,性能得到极大改善。下面给出示例程序:

代码语言:javascript
复制
/*************************************************************************
        > File Name : pcap_example.c
        > Author : TL Song
        > EMail : songtianlun@frytea.com
        > Created Time : Thu Feb 18 18:57:20 2021
     ************************************************************************/
    #include <stdio.h>
    #include <string.h>
    #include <pthread.h>
    #include <pcap.h>
     
    #define RECV_DEVICE      "ens3"
    #define RECV_DEVICE_SEND "docker0"
    #define RECV_FILTER      "arp or icmp"
     
    #define dPrint(fmt, ...) do{fprintf(stderr, "[%s:%d] " fmt "\r\n", __FUNCTION__, __LINE__, ##__VA_ARGS__);}while(0)
     
    int main()
    {
        char err_buf[PCAP_ERRBUF_SIZE];
        struct bpf_program fp_recv;      /* The compiled filter expression */
        char filter_recv[] = RECV_FILTER;  /* The filter expression (filter 53 port)*/
        pcap_t *handle_recv;
        pcap_t *handle_recv_send;
        bpf_u_int32 mask_recv;       /* The netmask of our sniffing device */
        bpf_u_int32 net_recv;        /* The IP of our sniffing device */
        u_char *pkt_data = NULL;
        int rst;
        struct pcap_pkthdr header;
        struct pcap_pkthdr *p_header = &header;
     
        printf("Recv Device: %s\n", RECV_DEVICE);
     
        /*Step1, Open the session in promiscuous mode*/
        handle_recv = pcap_open_live(RECV_DEVICE, BUFSIZ, 1, 1, err_buf);
        if (handle_recv == NULL) {
            fprintf(stderr, "Couldn't open device %s: %s\n", RECV_DEVICE, err_buf);
            return 0;
        }
     
        handle_recv_send = pcap_open_live(RECV_DEVICE_SEND, BUFSIZ, 1, 1, err_buf);
        if (handle_recv_send == NULL) {
            printf("Couldn't open device %s: %s\n", RECV_DEVICE_SEND, err_buf);
            return 0;
        }
     
        /*Step2, get network mask*/
        if (pcap_lookupnet(RECV_DEVICE, &net_recv, &mask_recv, err_buf) == -1) {
            fprintf(stderr, "Can't get netmask for device %s\n", RECV_DEVICE);
            net_recv = 0;
            mask_recv = 0;
        }
     
        /* Step3, Compile and apply the filter */
        if (pcap_compile(handle_recv, &fp_recv, filter_recv, 0, net_recv) == -1) {
            fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_recv, pcap_geterr(handle_recv));
            return 0;
        }
        if (pcap_setfilter(handle_recv, &fp_recv) == -1) {
            fprintf(stderr, "Couldn't install filter %s: %s\n", filter_recv, pcap_geterr(handle_recv));
            return 0;
        }
     
        /* Step4, get frame. */
        while(1){
            pkt_data = (unsigned char * )pcap_next(handle_recv, p_header);
            rst = pcap_sendpacket(handle_recv_send, pkt_data, p_header->caplen);
            printf("Send to %s ret : %d\n", RECV_DEVICE_SEND, rst);
        }
     
        /* Step5, cleanup */
        pcap_freecode(&fp_recv);
        pcap_close(handle_recv);
        pcap_close(handle_recv_send);
        dPrint("Capture complete.");
        return 0;
    }

参考文献#

注:本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 参考文献#
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档