2024-02-28 16:30:03 +08:00
|
|
|
#include <pcap/pcap.h>
|
|
|
|
|
#include <pthread.h>
|
|
|
|
|
#include <unistd.h>
|
2024-03-09 19:28:14 +08:00
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <assert.h>
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
#include "stellar.h"
|
|
|
|
|
#include "file_scan.h"
|
2024-04-10 17:50:51 +08:00
|
|
|
#include "packet_private.h"
|
2024-03-09 19:28:14 +08:00
|
|
|
#include "lock_free_queue.h"
|
2024-04-10 17:50:51 +08:00
|
|
|
#include "dumpfile_io.h"
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
#define MAX_PACKET_QUEUE_SIZE (4096 * 1000)
|
|
|
|
|
|
2024-04-10 17:50:51 +08:00
|
|
|
struct dumpfile_io
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
|
|
|
|
uint8_t nr_threads;
|
2024-04-10 17:50:51 +08:00
|
|
|
char directory[256];
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
pcap_t *pcap;
|
2024-03-09 19:28:14 +08:00
|
|
|
struct lock_free_queue *queue[MAX_THREAD_NUM];
|
2024-04-10 17:50:51 +08:00
|
|
|
struct packet_stat stat;
|
2024-02-28 16:30:03 +08:00
|
|
|
uint64_t io_thread_need_exit;
|
|
|
|
|
uint64_t io_thread_is_runing;
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-09 19:28:14 +08:00
|
|
|
struct pcap_pkt
|
|
|
|
|
{
|
|
|
|
|
char *data;
|
|
|
|
|
int len;
|
|
|
|
|
};
|
|
|
|
|
|
2024-02-28 16:30:03 +08:00
|
|
|
/******************************************************************************
|
|
|
|
|
* Private API
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void pcap_handle(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
|
|
|
|
|
{
|
2024-04-10 17:50:51 +08:00
|
|
|
struct dumpfile_io *handle = (struct dumpfile_io *)user;
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-03-09 19:28:14 +08:00
|
|
|
// copy packet data to new memory
|
|
|
|
|
struct pcap_pkt *pcap_pkt = (struct pcap_pkt *)calloc(1, sizeof(struct pcap_pkt) + h->caplen);
|
|
|
|
|
if (pcap_pkt == NULL)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
|
|
|
|
PACKET_IO_LOG_ERROR("unable to alloc packet");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-03-09 19:28:14 +08:00
|
|
|
pcap_pkt->data = (char *)pcap_pkt + sizeof(struct pcap_pkt);
|
|
|
|
|
pcap_pkt->len = h->caplen;
|
|
|
|
|
memcpy((char *)pcap_pkt->data, bytes, h->caplen);
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-03-09 19:28:14 +08:00
|
|
|
// calculate packet hash
|
|
|
|
|
struct packet pkt;
|
|
|
|
|
packet_parse(&pkt, pcap_pkt->data, pcap_pkt->len);
|
|
|
|
|
uint64_t hash = packet_get_hash(&pkt, LDBC_METHOD_HASH_INT_IP_AND_EXT_IP, 0);
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-03-09 19:28:14 +08:00
|
|
|
// push packet to queue
|
|
|
|
|
struct lock_free_queue *queue = handle->queue[hash % handle->nr_threads];
|
|
|
|
|
lock_free_queue_push(queue, pcap_pkt);
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
if (ATOMIC_READ(&handle->io_thread_need_exit))
|
|
|
|
|
{
|
|
|
|
|
PACKET_IO_LOG_STATE("dumpfile io thread need exit");
|
|
|
|
|
pcap_breakloop(handle->pcap);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int dumpfile_handle(const char *file, void *arg)
|
|
|
|
|
{
|
2024-03-26 15:09:03 +08:00
|
|
|
char resolved_path[256];
|
|
|
|
|
char pcap_errbuf[PCAP_ERRBUF_SIZE];
|
2024-04-10 17:50:51 +08:00
|
|
|
struct dumpfile_io *handle = (struct dumpfile_io *)arg;
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-03-26 15:09:03 +08:00
|
|
|
realpath(file, resolved_path);
|
|
|
|
|
PACKET_IO_LOG_STATE("dumpfile %s in-processing", resolved_path)
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-03-26 15:09:03 +08:00
|
|
|
handle->pcap = pcap_open_offline(file, pcap_errbuf);
|
2024-02-28 16:30:03 +08:00
|
|
|
if (handle->pcap == NULL)
|
|
|
|
|
{
|
2024-03-26 15:09:03 +08:00
|
|
|
PACKET_IO_LOG_ERROR("unable to open pcap file: %s, %s", resolved_path, pcap_errbuf);
|
2024-02-28 16:30:03 +08:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
pcap_loop(handle->pcap, -1, pcap_handle, (u_char *)handle);
|
|
|
|
|
pcap_close(handle->pcap);
|
|
|
|
|
|
2024-03-26 15:09:03 +08:00
|
|
|
PACKET_IO_LOG_STATE("dumpfile %s processed", resolved_path)
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *dumpfile_thread_cycle(void *arg)
|
|
|
|
|
{
|
2024-04-10 17:50:51 +08:00
|
|
|
struct dumpfile_io *handle = (struct dumpfile_io *)arg;
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
ATOMIC_SET(&handle->io_thread_is_runing, 1);
|
|
|
|
|
PACKET_IO_LOG_STATE("dumpfile io thread is running");
|
|
|
|
|
|
2024-04-10 17:50:51 +08:00
|
|
|
file_scan(handle->directory, dumpfile_handle, arg);
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-03-27 17:11:38 +08:00
|
|
|
while (ATOMIC_READ(&handle->io_thread_need_exit) == 0)
|
|
|
|
|
{
|
|
|
|
|
PACKET_IO_LOG_STATE("dumpfile io thread waiting");
|
|
|
|
|
sleep(1);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-28 16:30:03 +08:00
|
|
|
PACKET_IO_LOG_STATE("dumpfile io thread is exiting");
|
|
|
|
|
ATOMIC_SET(&handle->io_thread_is_runing, 0);
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
* Public API
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
2024-04-10 17:50:51 +08:00
|
|
|
struct dumpfile_io *dumpfile_io_new(const char *directory, uint8_t nr_threads)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
|
|
|
|
pthread_t tid;
|
2024-04-10 17:50:51 +08:00
|
|
|
struct dumpfile_io *handle = (struct dumpfile_io *)calloc(1, sizeof(struct dumpfile_io));
|
2024-02-28 16:30:03 +08:00
|
|
|
if (handle == NULL)
|
|
|
|
|
{
|
2024-04-10 17:50:51 +08:00
|
|
|
PACKET_IO_LOG_ERROR("unable to allocate memory for dumpfile_io");
|
2024-02-28 16:30:03 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-10 17:50:51 +08:00
|
|
|
handle->nr_threads = nr_threads;
|
|
|
|
|
strncpy(handle->directory, directory, strlen(directory));
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
for (uint16_t i = 0; i < handle->nr_threads; i++)
|
|
|
|
|
{
|
2024-03-09 19:28:14 +08:00
|
|
|
handle->queue[i] = lock_free_queue_new(MAX_PACKET_QUEUE_SIZE);
|
2024-02-28 16:30:03 +08:00
|
|
|
if (handle->queue[i] == NULL)
|
|
|
|
|
{
|
|
|
|
|
PACKET_IO_LOG_ERROR("unable to create packet queue");
|
|
|
|
|
goto error_out;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (pthread_create(&tid, NULL, dumpfile_thread_cycle, (void *)handle) != 0)
|
|
|
|
|
{
|
|
|
|
|
PACKET_IO_LOG_ERROR("unable to create packet io thread");
|
|
|
|
|
goto error_out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
|
|
|
|
|
|
error_out:
|
2024-04-10 17:50:51 +08:00
|
|
|
dumpfile_io_free(handle);
|
2024-02-28 16:30:03 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-10 17:50:51 +08:00
|
|
|
void dumpfile_io_free(struct dumpfile_io *handle)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
|
|
|
|
if (handle)
|
|
|
|
|
{
|
|
|
|
|
ATOMIC_SET(&handle->io_thread_need_exit, 1);
|
|
|
|
|
|
|
|
|
|
while (ATOMIC_READ(&handle->io_thread_is_runing))
|
|
|
|
|
{
|
|
|
|
|
usleep(1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (uint16_t i = 0; i < handle->nr_threads; i++)
|
|
|
|
|
{
|
2024-03-09 19:28:14 +08:00
|
|
|
lock_free_queue_free(handle->queue[i]);
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|
|
|
|
|
free(handle);
|
|
|
|
|
handle = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-10 17:50:51 +08:00
|
|
|
struct packet_stat *dumpfile_io_stat(struct dumpfile_io *handle)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
|
|
|
|
return &handle->stat;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-10 17:50:51 +08:00
|
|
|
int dumpfile_io_init(struct dumpfile_io *handle, uint16_t thr_idx)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-10 17:50:51 +08:00
|
|
|
int dumpfile_io_ingress(struct dumpfile_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-04-10 17:50:51 +08:00
|
|
|
struct lock_free_queue *queue = handle->queue[thr_idx];
|
2024-03-09 19:28:14 +08:00
|
|
|
struct pcap_pkt *pcap_pkt = NULL;
|
2024-03-08 18:10:38 +08:00
|
|
|
int nr_parsed = 0;
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-03-08 18:10:38 +08:00
|
|
|
for (int i = 0; i < nr_pkts; i++)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-03-09 19:28:14 +08:00
|
|
|
lock_free_queue_pop(queue, (void **)&pcap_pkt);
|
|
|
|
|
if (pcap_pkt == NULL)
|
2024-03-08 18:10:38 +08:00
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-04-10 17:50:51 +08:00
|
|
|
ATOMIC_ADD(&handle->stat.dev_rx_pkts, 1);
|
|
|
|
|
ATOMIC_ADD(&handle->stat.dev_rx_bytes, pcap_pkt->len);
|
|
|
|
|
|
|
|
|
|
ATOMIC_ADD(&handle->stat.raw_rx_pkts, 1);
|
|
|
|
|
ATOMIC_ADD(&handle->stat.raw_rx_bytes, pcap_pkt->len);
|
2024-03-09 19:28:14 +08:00
|
|
|
|
|
|
|
|
struct packet *pkt = &pkts[nr_parsed++];
|
|
|
|
|
memset(pkt, 0, sizeof(struct packet));
|
|
|
|
|
packet_parse(pkt, pcap_pkt->data, pcap_pkt->len);
|
2024-04-10 17:50:51 +08:00
|
|
|
packet_set_io_ctx(pkt, pcap_pkt);
|
2024-03-09 19:28:14 +08:00
|
|
|
packet_set_type(pkt, PACKET_TYPE_DATA);
|
|
|
|
|
packet_set_action(pkt, PACKET_ACTION_FORWARD);
|
2024-03-08 18:10:38 +08:00
|
|
|
}
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|
2024-03-08 18:10:38 +08:00
|
|
|
|
|
|
|
|
return nr_parsed;
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|
|
|
|
|
|
2024-04-10 17:50:51 +08:00
|
|
|
void dumpfile_io_egress(struct dumpfile_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-04-10 17:50:51 +08:00
|
|
|
int len;
|
2024-03-08 18:10:38 +08:00
|
|
|
struct packet *pkt = NULL;
|
|
|
|
|
for (int i = 0; i < nr_pkts; i++)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-03-08 18:10:38 +08:00
|
|
|
pkt = &pkts[i];
|
2024-04-10 17:50:51 +08:00
|
|
|
len = packet_get_len(pkt);
|
2024-03-08 18:10:38 +08:00
|
|
|
|
2024-04-10 17:50:51 +08:00
|
|
|
ATOMIC_ADD(&handle->stat.dev_tx_pkts, 1);
|
|
|
|
|
ATOMIC_ADD(&handle->stat.dev_tx_bytes, len);
|
2024-03-09 19:28:14 +08:00
|
|
|
|
2024-04-10 17:50:51 +08:00
|
|
|
ATOMIC_ADD(&handle->stat.raw_tx_pkts, 1);
|
|
|
|
|
ATOMIC_ADD(&handle->stat.raw_tx_bytes, len);
|
2024-03-09 19:28:14 +08:00
|
|
|
|
2024-04-10 17:50:51 +08:00
|
|
|
struct pcap_pkt *pcap_pkt = (struct pcap_pkt *)packet_get_io_ctx(pkt);
|
2024-04-10 11:40:26 +08:00
|
|
|
if (pcap_pkt)
|
|
|
|
|
{
|
|
|
|
|
free(pcap_pkt);
|
|
|
|
|
}
|
|
|
|
|
packet_free(pkt);
|
2024-03-09 19:28:14 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-10 17:50:51 +08:00
|
|
|
void dumpfile_io_drop(struct dumpfile_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts)
|
2024-03-09 19:28:14 +08:00
|
|
|
{
|
|
|
|
|
struct packet *pkt = NULL;
|
|
|
|
|
for (int i = 0; i < nr_pkts; i++)
|
|
|
|
|
{
|
|
|
|
|
pkt = &pkts[i];
|
2024-04-10 17:50:51 +08:00
|
|
|
struct pcap_pkt *pcap_pkt = (struct pcap_pkt *)packet_get_io_ctx(pkt);
|
2024-04-10 11:40:26 +08:00
|
|
|
if (pcap_pkt)
|
|
|
|
|
{
|
|
|
|
|
free(pcap_pkt);
|
|
|
|
|
}
|
2024-03-08 18:10:38 +08:00
|
|
|
packet_free(pkt);
|
|
|
|
|
}
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|