ntop / PF_RING

High-speed packet processing framework
http://www.ntop.org
GNU Lesser General Public License v2.1
2.68k stars 353 forks source link

PF_RING integration fail #942

Closed utoni closed 4 months ago

utoni commented 4 months ago

I am trying to integrate PF_RING in nDPId, but it's crashing right after the first call to pfring_recv().

Does PF_RING by the way support having multiple threads which are calling pfring_recv() whereas all threads have their own pfring* context previously opened with pfring_open ?

gdb backtrace (not really helpful :/):

__memcpy_avx_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:279
279 ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S: No such file or directory.
(gdb) bt
#0  __memcpy_avx_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:279
#1  0x0000555555ce6cb4 in pfring_mod_recv ()
#2  0x0000555555ce4f88 in pfring_recv ()
#3  0x0000555555b0a9e6 in npfring_recv (npf=0x631000014800, pcap_hdr=0x7ffff2cf4ce0) at /home/toni/git/nDPId/npfring.c:95
#4  0x0000555555b01c1f in run_pfring_loop (reader_thread=0x5555565862a0 <reader_threads>) at /home/toni/git/nDPId/nDPId.c:4454
#5  0x0000555555b04099 in processing_thread (ndpi_thread_arg=0x5555565862a0 <reader_threads>) at /home/toni/git/nDPId/nDPId.c:4688
#6  0x00007ffff6ea8134 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#7  0x00007ffff6f287dc in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
(gdb)

My minimalist implementation:

#include <pfring.h>
#include <sched.h>

#include "npfring.h"
#include "utils.h"

void npfring_print_version(FILE * const out)
{
    uint32_t pfring_version;

    pfring_version_noring(&pfring_version);
    fprintf(out,
            "PF_RING version: %d.%d.%d\n",
            (pfring_version & 0xFFFF0000) >> 16,
            (pfring_version & 0x0000FF00) >> 8,
            (pfring_version & 0x000000FF));
}

int npfring_init(char const * device_name, uint32_t caplen, struct npfring * result)
{
    pfring * pd = pfring_open(device_name, caplen, PF_RING_REENTRANT | PF_RING_PROMISC);

    if (pd == NULL)
    {
        return -1;
    }

    pfring_set_application_name(pd, "nDPId");
    logger_early(0, "PF_RING RX channels: %d", pfring_get_num_rx_channels(pd));
    result->pfring_desc = pd;

    int rc;
    if ((rc = pfring_set_socket_mode(pd, recv_only_mode)) != 0)
    {
        logger_early(1, "pfring_set_sock_moode returned: %d", rc);
    }

    return 0;
}

void npfring_close(struct npfring * npf)
{
    if (npf->pfring_desc != NULL)
    {
        pfring_close(npf->pfring_desc);
        npf->pfring_desc = NULL;
    }
}

int npfring_set_bpf(struct npfring * npf, char const * bpf_filter)
{
    char buf[BUFSIZ];

    if (npf->pfring_desc == NULL)
    {
        return -1;
    }

    // pfring_set_bpf_filter expects a char*
    snprintf(buf, sizeof(buf), "%s", bpf_filter);
    return pfring_set_bpf_filter(npf->pfring_desc, buf);
}

int npfring_datalink(struct npfring * npf)
{
    if (npf->pfring_desc != NULL)
    {
        pfring_get_link_type(npf->pfring_desc);
    }

    return -1;
}

int npfring_enable(struct npfring * npf)
{
    if (npf->pfring_desc == NULL)
    {
        return -1;
    }

    return pfring_enable_ring(npf->pfring_desc);
}

int npfring_recv(struct npfring * npf, struct pcap_pkthdr * pcap_hdr)
{
    int rc;

    if (npf->pfring_desc == NULL || pcap_hdr == NULL)
    {
        return -1;
    }

    unsigned char ** const buf = (unsigned char **)&npf->pfring_buffer;
    struct pfring_pkthdr pfring_pkthdr;
    rc = pfring_recv(npf->pfring_desc, buf, PFRING_BUFFER_SIZE, &pfring_pkthdr, 1);
    if (rc > 0)
    {
        pcap_hdr->ts = pfring_pkthdr.ts;
        pcap_hdr->caplen = pfring_pkthdr.caplen;
        pcap_hdr->len = pfring_pkthdr.len;
    }
    else
    {
        sched_yield();
    }

    return rc;
}
utoni commented 4 months ago

Nvm, I failed...