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-04-30 15:47:45 +08:00
|
|
|
#include <errno.h>
|
|
|
|
|
#include <dirent.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/types.h>
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-06-24 17:07:05 +08:00
|
|
|
#include "tuple.h"
|
2024-08-16 10:43:00 +08:00
|
|
|
#include "utils.h"
|
2024-09-19 16:23:12 +08:00
|
|
|
#include "log_internal.h"
|
2024-08-30 10:21:44 +08:00
|
|
|
#include "pcap_io.h"
|
2024-07-01 15:51:36 +08:00
|
|
|
#include "packet_dump.h"
|
2024-08-23 18:44:17 +08:00
|
|
|
#include "packet_parser.h"
|
2024-09-19 16:10:59 +08:00
|
|
|
#include "packet_internal.h"
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
#define PCAP_IO_LOG_FATAL(format, ...) STELLAR_LOG_FATAL(__thread_local_logger, "pcap io", format, ##__VA_ARGS__)
|
|
|
|
|
#define PCAP_IO_LOG_ERROR(format, ...) STELLAR_LOG_ERROR(__thread_local_logger, "pcap io", format, ##__VA_ARGS__)
|
2024-06-24 17:07:05 +08:00
|
|
|
|
2024-02-28 16:30:03 +08:00
|
|
|
#define MAX_PACKET_QUEUE_SIZE (4096 * 1000)
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
struct pcap_io
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
struct packet_io_config cfg;
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
pcap_t *pcap;
|
2024-08-26 19:01:10 +08:00
|
|
|
struct logger *logger;
|
2024-08-21 14:33:03 +08:00
|
|
|
struct packet_queue *queue[MAX_THREAD_NUM];
|
2024-06-25 14:08:33 +08:00
|
|
|
struct packet_io_stat stat[MAX_THREAD_NUM];
|
2024-02-28 16:30:03 +08:00
|
|
|
uint64_t io_thread_need_exit;
|
|
|
|
|
uint64_t io_thread_is_runing;
|
2024-05-15 11:40:00 +08:00
|
|
|
uint64_t io_thread_wait_exit;
|
2024-08-27 16:19:20 +08:00
|
|
|
|
|
|
|
|
uint64_t read_pcap_files;
|
|
|
|
|
uint64_t read_pcap_pkts;
|
2024-02-28 16:30:03 +08:00
|
|
|
};
|
|
|
|
|
|
2024-03-09 19:28:14 +08:00
|
|
|
struct pcap_pkt
|
|
|
|
|
{
|
|
|
|
|
char *data;
|
|
|
|
|
int len;
|
2024-08-23 16:04:07 +08:00
|
|
|
struct timeval ts;
|
2024-03-09 19:28:14 +08:00
|
|
|
};
|
|
|
|
|
|
2024-02-28 16:30:03 +08:00
|
|
|
/******************************************************************************
|
2024-08-21 14:33:03 +08:00
|
|
|
* Private API -- queue
|
2024-02-28 16:30:03 +08:00
|
|
|
******************************************************************************/
|
|
|
|
|
|
2024-08-21 14:33:03 +08:00
|
|
|
struct packet_queue
|
|
|
|
|
{
|
|
|
|
|
uint64_t *queue;
|
|
|
|
|
uint32_t size;
|
|
|
|
|
uint32_t head;
|
|
|
|
|
uint32_t tail;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct packet_queue *packet_queue_new(uint32_t size)
|
|
|
|
|
{
|
|
|
|
|
struct packet_queue *queue = (struct packet_queue *)calloc(1, sizeof(struct packet_queue));
|
|
|
|
|
if (queue == NULL)
|
|
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_ERROR("unable to new packet queue");
|
2024-08-21 14:33:03 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queue->queue = (uint64_t *)calloc(size, sizeof(uint64_t));
|
|
|
|
|
if (queue->queue == NULL)
|
|
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_ERROR("unable to new packet queue");
|
2024-08-21 14:33:03 +08:00
|
|
|
free(queue);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queue->size = size;
|
|
|
|
|
queue->head = 0;
|
|
|
|
|
queue->tail = 0;
|
|
|
|
|
|
|
|
|
|
return queue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void packet_queue_free(struct packet_queue *queue)
|
|
|
|
|
{
|
|
|
|
|
if (queue == NULL)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (queue->queue)
|
|
|
|
|
{
|
|
|
|
|
free(queue->queue);
|
|
|
|
|
queue->queue = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(queue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int packet_queue_push(struct packet_queue *queue, void *data)
|
|
|
|
|
{
|
|
|
|
|
if (__sync_val_compare_and_swap(&queue->queue[queue->tail], 0, data) != 0)
|
|
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_ERROR("packet queue is full, retry later");
|
2024-08-21 14:33:03 +08:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queue->tail = (queue->tail + 1) % queue->size;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void packet_queue_pop(struct packet_queue *queue, void **data)
|
|
|
|
|
{
|
|
|
|
|
uint64_t read = ATOMIC_READ(&queue->queue[queue->head]);
|
|
|
|
|
if (read == 0)
|
|
|
|
|
{
|
|
|
|
|
*data = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
__sync_val_compare_and_swap(&queue->queue[queue->head], read, 0);
|
|
|
|
|
*data = (void *)read;
|
|
|
|
|
queue->head = (queue->head + 1) % queue->size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
* Private API -- utils
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void pcap_pkt_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
struct pcap_io *handle = (struct pcap_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
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_ERROR("unable to alloc packet");
|
2024-02-28 16:30:03 +08:00
|
|
|
return;
|
|
|
|
|
}
|
2024-03-09 19:28:14 +08:00
|
|
|
pcap_pkt->data = (char *)pcap_pkt + sizeof(struct pcap_pkt);
|
|
|
|
|
pcap_pkt->len = h->caplen;
|
2024-08-23 16:04:07 +08:00
|
|
|
pcap_pkt->ts = h->ts;
|
2024-03-09 19:28:14 +08:00
|
|
|
memcpy((char *)pcap_pkt->data, bytes, h->caplen);
|
2024-08-27 16:19:20 +08:00
|
|
|
ATOMIC_INC(&handle->read_pcap_pkts);
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-03-09 19:28:14 +08:00
|
|
|
// calculate packet hash
|
|
|
|
|
struct packet pkt;
|
2024-06-14 19:24:27 +08:00
|
|
|
memset(&pkt, 0, sizeof(struct packet));
|
2024-03-09 19:28:14 +08:00
|
|
|
packet_parse(&pkt, pcap_pkt->data, pcap_pkt->len);
|
2024-08-16 17:07:52 +08:00
|
|
|
uint64_t hash = packet_ldbc_hash(&pkt, PKT_LDBC_METH_OUTERMOST_INT_EXT_IP, PACKET_DIRECTION_OUTGOING);
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-03-09 19:28:14 +08:00
|
|
|
// push packet to queue
|
2024-08-30 10:21:44 +08:00
|
|
|
struct packet_queue *queue = handle->queue[hash % handle->cfg.nr_worker_thread];
|
2024-08-21 14:33:03 +08:00
|
|
|
while (packet_queue_push(queue, pcap_pkt) == -1)
|
2024-04-11 19:44:02 +08:00
|
|
|
{
|
|
|
|
|
if (ATOMIC_READ(&handle->io_thread_need_exit))
|
|
|
|
|
{
|
|
|
|
|
free(pcap_pkt);
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_FATAL("pcap io thread need exit");
|
2024-04-11 19:44:02 +08:00
|
|
|
pcap_breakloop(handle->pcap);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
usleep(1000);
|
|
|
|
|
}
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
if (ATOMIC_READ(&handle->io_thread_need_exit))
|
|
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_FATAL("pcap io thread need exit");
|
2024-02-28 16:30:03 +08:00
|
|
|
pcap_breakloop(handle->pcap);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
static int pcap_io_handler(struct pcap_io *handle, const char *pcap_file)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-03-26 15:09:03 +08:00
|
|
|
char resolved_path[256];
|
|
|
|
|
char pcap_errbuf[PCAP_ERRBUF_SIZE];
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-08-19 18:40:49 +08:00
|
|
|
realpath(pcap_file, resolved_path);
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_FATAL("pcap %s in-processing", resolved_path)
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-08-19 18:40:49 +08:00
|
|
|
handle->pcap = pcap_open_offline(resolved_path, pcap_errbuf);
|
2024-02-28 16:30:03 +08:00
|
|
|
if (handle->pcap == NULL)
|
|
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_ERROR("unable to open pcap file: %s, %s", resolved_path, pcap_errbuf);
|
2024-02-28 16:30:03 +08:00
|
|
|
return -1;
|
|
|
|
|
}
|
2024-08-27 16:19:20 +08:00
|
|
|
handle->read_pcap_files++;
|
2024-08-21 14:33:03 +08:00
|
|
|
pcap_loop(handle->pcap, -1, pcap_pkt_handler, (u_char *)handle);
|
2024-02-28 16:30:03 +08:00
|
|
|
pcap_close(handle->pcap);
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_FATAL("pcap %s processed", resolved_path)
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
static int all_packet_consumed(struct pcap_io *handle)
|
2024-05-15 11:40:00 +08:00
|
|
|
{
|
2024-08-27 16:19:20 +08:00
|
|
|
uint64_t consumed_pkts = 0;
|
|
|
|
|
uint64_t read_pcap_pkts = ATOMIC_READ(&handle->read_pcap_pkts);
|
2024-08-30 10:21:44 +08:00
|
|
|
for (uint16_t i = 0; i < handle->cfg.nr_worker_thread; i++)
|
2024-05-15 11:40:00 +08:00
|
|
|
{
|
2024-08-27 16:19:20 +08:00
|
|
|
consumed_pkts += ATOMIC_READ(&handle->stat[i].pkts_rx);
|
|
|
|
|
}
|
|
|
|
|
if (consumed_pkts == read_pcap_pkts)
|
|
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
2024-05-15 11:40:00 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
static void *pcap_io_thread(void *arg)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
struct pcap_io *handle = (struct pcap_io *)arg;
|
2024-08-26 19:01:10 +08:00
|
|
|
__thread_local_logger = handle->logger;
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
ATOMIC_SET(&handle->io_thread_is_runing, 1);
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_FATAL("pcap io thread is running");
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
if (handle->cfg.mode == PACKET_IO_PCAPFILE)
|
2024-08-19 18:40:49 +08:00
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
pcap_io_handler(handle, handle->cfg.pcap_path);
|
2024-08-19 18:40:49 +08:00
|
|
|
}
|
2024-08-30 10:21:44 +08:00
|
|
|
else // PACKET_IO_PCAPLIST
|
2024-08-19 18:40:49 +08:00
|
|
|
{
|
2024-08-20 19:29:31 +08:00
|
|
|
FILE *fp = NULL;
|
2024-08-30 10:21:44 +08:00
|
|
|
if (strcmp(handle->cfg.pcap_path, "-") == 0)
|
2024-08-19 18:40:49 +08:00
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_ERROR("pcap path is empty, read from stdin");
|
2024-08-20 19:29:31 +08:00
|
|
|
fp = stdin;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
fp = fopen(handle->cfg.pcap_path, "r");
|
2024-08-20 19:29:31 +08:00
|
|
|
if (fp == NULL)
|
|
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_ERROR("unable to open pcap path: %s", handle->cfg.pcap_path);
|
2024-08-20 19:29:31 +08:00
|
|
|
goto erro_out;
|
|
|
|
|
}
|
2024-08-19 18:40:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char line[PATH_MAX];
|
2024-08-20 19:29:31 +08:00
|
|
|
while (ATOMIC_READ(&handle->io_thread_need_exit) == 0 && fgets(line, sizeof(line), fp))
|
2024-08-19 18:40:49 +08:00
|
|
|
{
|
|
|
|
|
if (line[0] == '#')
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *pos = strchr(line, '\n');
|
|
|
|
|
if (pos)
|
|
|
|
|
{
|
|
|
|
|
*pos = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
pcap_io_handler(handle, line);
|
2024-08-19 18:40:49 +08:00
|
|
|
}
|
2024-08-20 19:29:31 +08:00
|
|
|
if (fp != stdin)
|
|
|
|
|
{
|
|
|
|
|
fclose(fp);
|
|
|
|
|
}
|
2024-08-19 18:40:49 +08:00
|
|
|
}
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_FATAL("pcap io thread read all pcap files");
|
2024-08-19 18:40:49 +08:00
|
|
|
|
|
|
|
|
erro_out:
|
2024-03-27 17:11:38 +08:00
|
|
|
while (ATOMIC_READ(&handle->io_thread_need_exit) == 0)
|
|
|
|
|
{
|
2024-08-27 16:19:20 +08:00
|
|
|
if (all_packet_consumed(handle))
|
2024-05-15 11:40:00 +08:00
|
|
|
{
|
|
|
|
|
ATOMIC_SET(&handle->io_thread_wait_exit, 1);
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-15 19:03:48 +08:00
|
|
|
usleep(1000); // 1ms
|
2024-03-27 17:11:38 +08:00
|
|
|
}
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_FATAL("pcap io thread exit (read_pcap_files: %lu, read_pcap_pkts: %lu)", handle->read_pcap_files, ATOMIC_READ(&handle->read_pcap_pkts));
|
2024-02-28 16:30:03 +08:00
|
|
|
ATOMIC_SET(&handle->io_thread_is_runing, 0);
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
* Public API
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
void *pcap_io_new(const struct packet_io_config *cfg)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
|
|
|
|
pthread_t tid;
|
2024-08-30 10:21:44 +08:00
|
|
|
struct pcap_io *handle = (struct pcap_io *)calloc(1, sizeof(struct pcap_io));
|
2024-02-28 16:30:03 +08:00
|
|
|
if (handle == NULL)
|
|
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_ERROR("unable to allocate memory for pcap_io");
|
2024-02-28 16:30:03 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-26 19:01:10 +08:00
|
|
|
handle->logger = __thread_local_logger;
|
2024-08-30 10:21:44 +08:00
|
|
|
memcpy(&handle->cfg, cfg, sizeof(struct packet_io_config));
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
for (uint16_t i = 0; i < handle->cfg.nr_worker_thread; i++)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-08-21 14:33:03 +08:00
|
|
|
handle->queue[i] = packet_queue_new(MAX_PACKET_QUEUE_SIZE);
|
2024-02-28 16:30:03 +08:00
|
|
|
if (handle->queue[i] == NULL)
|
|
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_ERROR("unable to create packet queue");
|
2024-02-28 16:30:03 +08:00
|
|
|
goto error_out;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-08-30 10:21:44 +08:00
|
|
|
if (pthread_create(&tid, NULL, pcap_io_thread, (void *)handle) != 0)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_ERROR("unable to create pcap io thread");
|
2024-02-28 16:30:03 +08:00
|
|
|
goto error_out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
|
|
|
|
|
|
error_out:
|
2024-08-30 10:21:44 +08:00
|
|
|
pcap_io_free(handle);
|
2024-02-28 16:30:03 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
void pcap_io_free(void *handle)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)handle;
|
|
|
|
|
if (pcap_io)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
ATOMIC_SET(&pcap_io->io_thread_need_exit, 1);
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
while (ATOMIC_READ(&pcap_io->io_thread_is_runing))
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
|
|
|
|
usleep(1000);
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-11 19:44:02 +08:00
|
|
|
struct pcap_pkt *pcap_pkt = NULL;
|
2024-08-30 10:21:44 +08:00
|
|
|
for (uint16_t i = 0; i < pcap_io->cfg.nr_worker_thread; i++)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-04-11 19:44:02 +08:00
|
|
|
while (1)
|
|
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
packet_queue_pop(pcap_io->queue[i], (void **)&pcap_pkt);
|
2024-04-11 19:44:02 +08:00
|
|
|
if (pcap_pkt)
|
|
|
|
|
{
|
|
|
|
|
free(pcap_pkt);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
packet_queue_free(pcap_io->queue[i]);
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|
2024-08-30 10:21:44 +08:00
|
|
|
free(pcap_io);
|
|
|
|
|
pcap_io = NULL;
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
int pcap_io_isbreak(void *handle)
|
2024-05-15 11:40:00 +08:00
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)handle;
|
|
|
|
|
|
|
|
|
|
return ATOMIC_READ(&pcap_io->io_thread_wait_exit);
|
2024-05-15 11:40:00 +08:00
|
|
|
}
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
int pcap_io_init(void *handle __attribute__((unused)), uint16_t thr_idx __attribute__((unused)))
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-19 16:29:17 +08:00
|
|
|
uint16_t pcap_io_ingress(void *handle, uint16_t thr_idx, struct packet *pkts, uint16_t nr_pkts)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
uint16_t nr_packet_parsed = 0;
|
|
|
|
|
struct packet *pkt = NULL;
|
2024-03-09 19:28:14 +08:00
|
|
|
struct pcap_pkt *pcap_pkt = NULL;
|
2024-08-30 10:21:44 +08:00
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)handle;
|
|
|
|
|
struct packet_queue *queue = pcap_io->queue[thr_idx];
|
|
|
|
|
struct packet_io_stat *stat = &pcap_io->stat[thr_idx];
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-08-21 14:33:03 +08:00
|
|
|
for (uint16_t i = 0; i < nr_pkts; i++)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-08-21 14:33:03 +08:00
|
|
|
packet_queue_pop(queue, (void **)&pcap_pkt);
|
2024-03-09 19:28:14 +08:00
|
|
|
if (pcap_pkt == NULL)
|
2024-03-08 18:10:38 +08:00
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-08-27 16:19:20 +08:00
|
|
|
ATOMIC_INC(&stat->pkts_rx);
|
2024-08-16 17:44:23 +08:00
|
|
|
stat->bytes_rx += pcap_pkt->len;
|
2024-04-10 17:50:51 +08:00
|
|
|
|
2024-08-16 17:44:23 +08:00
|
|
|
stat->raw_pkts_rx++;
|
|
|
|
|
stat->raw_bytes_rx += pcap_pkt->len;
|
2024-03-09 19:28:14 +08:00
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
pkt = &pkts[nr_packet_parsed];
|
2024-03-09 19:28:14 +08:00
|
|
|
packet_parse(pkt, pcap_pkt->data, pcap_pkt->len);
|
2024-08-14 10:50:33 +08:00
|
|
|
memset(&pkt->meta, 0, sizeof(pkt->meta));
|
2024-05-08 18:24:26 +08:00
|
|
|
packet_set_origin_ctx(pkt, pcap_pkt);
|
2024-05-09 14:57:12 +08:00
|
|
|
packet_set_action(pkt, PACKET_ACTION_FORWARD);
|
2024-08-23 16:04:07 +08:00
|
|
|
packet_set_timeval(pkt, &pcap_pkt->ts);
|
2024-08-30 10:21:44 +08:00
|
|
|
nr_packet_parsed++;
|
2024-03-08 18:10:38 +08:00
|
|
|
}
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|
2024-03-08 18:10:38 +08:00
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
return nr_packet_parsed;
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|
|
|
|
|
|
2024-09-19 16:29:17 +08:00
|
|
|
void pcap_io_egress(void *handle, uint16_t thr_idx, struct packet *pkts, uint16_t 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;
|
2024-08-30 10:21:44 +08:00
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)handle;
|
|
|
|
|
struct packet_io_stat *stat = &pcap_io->stat[thr_idx];
|
2024-04-18 14:20:28 +08:00
|
|
|
|
2024-08-21 14:33:03 +08:00
|
|
|
for (uint16_t 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-06-14 19:24:27 +08:00
|
|
|
len = packet_get_raw_len(pkt);
|
2024-03-08 18:10:38 +08:00
|
|
|
|
2024-08-16 17:44:23 +08:00
|
|
|
stat->pkts_tx++;
|
|
|
|
|
stat->bytes_tx += len;
|
2024-03-09 19:28:14 +08:00
|
|
|
|
2024-08-16 17:44:23 +08:00
|
|
|
stat->raw_pkts_tx++;
|
|
|
|
|
stat->raw_bytes_tx += len;
|
2024-03-09 19:28:14 +08:00
|
|
|
|
2024-05-08 18:24:26 +08:00
|
|
|
struct pcap_pkt *pcap_pkt = (struct pcap_pkt *)packet_get_origin_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-08-30 10:21:44 +08:00
|
|
|
void pcap_io_drop(void *handle, uint16_t thr_idx, struct packet *pkts, uint16_t nr_pkts)
|
2024-03-09 19:28:14 +08:00
|
|
|
{
|
|
|
|
|
struct packet *pkt = NULL;
|
2024-08-30 10:21:44 +08:00
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)handle;
|
|
|
|
|
struct packet_io_stat *stat = &pcap_io->stat[thr_idx];
|
2024-04-30 15:25:34 +08:00
|
|
|
|
2024-08-21 14:33:03 +08:00
|
|
|
for (uint16_t i = 0; i < nr_pkts; i++)
|
2024-03-09 19:28:14 +08:00
|
|
|
{
|
|
|
|
|
pkt = &pkts[i];
|
2024-05-08 18:24:26 +08:00
|
|
|
struct pcap_pkt *pcap_pkt = (struct pcap_pkt *)packet_get_origin_ctx(pkt);
|
2024-04-10 11:40:26 +08:00
|
|
|
if (pcap_pkt)
|
|
|
|
|
{
|
2024-08-16 17:44:23 +08:00
|
|
|
stat->pkts_dropped++;
|
|
|
|
|
stat->bytes_dropped += packet_get_raw_len(pkt);
|
2024-04-10 11:40:26 +08:00
|
|
|
free(pcap_pkt);
|
|
|
|
|
}
|
2024-03-08 18:10:38 +08:00
|
|
|
packet_free(pkt);
|
|
|
|
|
}
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|
2024-04-18 14:20:28 +08:00
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
uint16_t pcap_io_inject(void *handle, uint16_t thr_idx, struct packet *pkts, uint16_t nr_pkts)
|
2024-04-25 15:34:46 +08:00
|
|
|
{
|
2024-07-01 15:51:36 +08:00
|
|
|
uint16_t len;
|
|
|
|
|
struct tuple6 tuple;
|
2024-08-30 10:21:44 +08:00
|
|
|
struct packet *pkt = NULL;
|
|
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)handle;
|
|
|
|
|
struct packet_io_stat *stat = &pcap_io->stat[thr_idx];
|
2024-07-01 15:51:36 +08:00
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
char file[PATH_MAX] = {0};
|
2024-07-01 15:51:36 +08:00
|
|
|
char src_addr[INET6_ADDRSTRLEN] = {0};
|
|
|
|
|
char dst_addr[INET6_ADDRSTRLEN] = {0};
|
2024-04-25 15:34:46 +08:00
|
|
|
|
2024-08-21 14:33:03 +08:00
|
|
|
for (uint16_t i = 0; i < nr_pkts; i++)
|
2024-04-25 15:34:46 +08:00
|
|
|
{
|
|
|
|
|
pkt = &pkts[i];
|
2024-06-14 19:24:27 +08:00
|
|
|
len = packet_get_raw_len(pkt);
|
2024-04-25 15:34:46 +08:00
|
|
|
|
2024-08-16 17:44:23 +08:00
|
|
|
stat->pkts_injected++;
|
|
|
|
|
stat->bytes_injected += len;
|
2024-04-25 15:34:46 +08:00
|
|
|
|
2024-08-16 17:44:23 +08:00
|
|
|
stat->raw_pkts_tx++;
|
|
|
|
|
stat->raw_bytes_tx += len;
|
2024-04-25 15:34:46 +08:00
|
|
|
|
2024-08-16 17:44:23 +08:00
|
|
|
stat->pkts_tx++;
|
|
|
|
|
stat->bytes_tx += len;
|
2024-04-25 15:34:46 +08:00
|
|
|
|
2024-07-01 15:51:36 +08:00
|
|
|
memset(&tuple, 0, sizeof(struct tuple6));
|
|
|
|
|
packet_get_innermost_tuple6(pkt, &tuple);
|
2024-05-15 11:40:00 +08:00
|
|
|
|
2024-07-25 18:29:57 +08:00
|
|
|
if (tuple.addr_family == AF_INET)
|
2024-07-01 15:51:36 +08:00
|
|
|
{
|
|
|
|
|
inet_ntop(AF_INET, &tuple.src_addr.v4, src_addr, INET6_ADDRSTRLEN);
|
|
|
|
|
inet_ntop(AF_INET, &tuple.dst_addr.v4, dst_addr, INET6_ADDRSTRLEN);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
inet_ntop(AF_INET6, &tuple.src_addr.v6, src_addr, INET6_ADDRSTRLEN);
|
|
|
|
|
inet_ntop(AF_INET6, &tuple.dst_addr.v6, dst_addr, INET6_ADDRSTRLEN);
|
|
|
|
|
}
|
2024-08-19 18:40:49 +08:00
|
|
|
snprintf(file, sizeof(file), "inject-%s:%u-%s:%u-%lu.pcap", src_addr, ntohs(tuple.src_port), dst_addr, ntohs(tuple.dst_port), stat->pkts_injected);
|
2024-07-01 15:51:36 +08:00
|
|
|
|
2024-07-02 17:55:55 +08:00
|
|
|
if (packet_dump_pcap(pkt, file) == -1)
|
2024-07-01 15:51:36 +08:00
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_ERROR("unable to dump pcap file: %s", file);
|
2024-07-01 15:51:36 +08:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
PCAP_IO_LOG_FATAL("dump inject packet: %s", file);
|
2024-07-01 15:51:36 +08:00
|
|
|
}
|
2024-04-25 15:34:46 +08:00
|
|
|
packet_free(pkt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nr_pkts;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
void pcap_io_yield(void *handle __attribute__((unused)), uint16_t thr_idx __attribute__((unused)))
|
2024-04-18 14:20:28 +08:00
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
struct packet_io_stat *pcap_io_stat(void *handle, uint16_t thr_idx)
|
2024-04-18 14:20:28 +08:00
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)handle;
|
|
|
|
|
|
|
|
|
|
return &pcap_io->stat[thr_idx];
|
2024-04-18 14:20:28 +08:00
|
|
|
}
|