2024-03-09 19:28:14 +08:00
|
|
|
#include <assert.h>
|
2024-10-23 10:01:20 +08:00
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <limits.h>
|
|
|
|
|
#include <pthread.h>
|
|
|
|
|
#include <pcap/pcap.h>
|
2024-02-28 16:30:03 +08:00
|
|
|
|
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-10-23 10:01:20 +08:00
|
|
|
#include "packet_pool.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-10-23 10:01:20 +08:00
|
|
|
#include "utils_internal.h"
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
#define RING_BUFFER_MAX_SIZE (4096 * 1000)
|
|
|
|
|
|
|
|
|
|
struct pcap_pkt
|
|
|
|
|
{
|
|
|
|
|
char *data;
|
|
|
|
|
int len;
|
|
|
|
|
struct timeval ts;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct pcap_io_cfg
|
|
|
|
|
{
|
|
|
|
|
char mode[16]; // pcapfile, pcaplist
|
|
|
|
|
char pcap_path[PATH_MAX];
|
2024-10-31 16:25:37 +08:00
|
|
|
uint64_t pcap_done_exit; // range [0, 1]
|
|
|
|
|
uint64_t thread_num; // range [1, MAX_THREAD_NUM]
|
2024-10-23 10:01:20 +08:00
|
|
|
|
|
|
|
|
// packet pool
|
|
|
|
|
uint64_t capacity; // range: [1, 4294967295]
|
|
|
|
|
};
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-08-30 10:21:44 +08:00
|
|
|
struct pcap_io
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
struct pcap_io_cfg *cfg;
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
pcap_t *pcap;
|
2024-08-26 19:01:10 +08:00
|
|
|
struct logger *logger;
|
2024-10-23 10:01:20 +08:00
|
|
|
struct ring_buffer *ring[MAX_THREAD_NUM];
|
|
|
|
|
struct packet_pool *pool[MAX_THREAD_NUM];
|
2024-06-25 14:08:33 +08:00
|
|
|
struct packet_io_stat stat[MAX_THREAD_NUM];
|
2024-10-23 10:01:20 +08:00
|
|
|
|
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-10-23 10:01:20 +08:00
|
|
|
* Private API -- ring
|
2024-02-28 16:30:03 +08:00
|
|
|
******************************************************************************/
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
struct ring_buffer
|
2024-08-21 14:33:03 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
uint64_t *buff;
|
2024-08-21 14:33:03 +08:00
|
|
|
uint32_t size;
|
|
|
|
|
uint32_t head;
|
|
|
|
|
uint32_t tail;
|
|
|
|
|
};
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
static struct ring_buffer *ring_buffer_new(uint32_t size)
|
2024-08-21 14:33:03 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
struct ring_buffer *ring = (struct ring_buffer *)calloc(1, sizeof(struct ring_buffer));
|
|
|
|
|
if (ring == NULL)
|
2024-08-21 14:33:03 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_ERROR("unable to new ring buffer");
|
2024-08-21 14:33:03 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
ring->buff = (uint64_t *)calloc(size, sizeof(uint64_t));
|
|
|
|
|
if (ring->buff == NULL)
|
2024-08-21 14:33:03 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_ERROR("unable to new ring buffer");
|
2024-10-23 10:01:20 +08:00
|
|
|
free(ring);
|
2024-08-21 14:33:03 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
ring->size = size;
|
|
|
|
|
ring->head = 0;
|
|
|
|
|
ring->tail = 0;
|
2024-08-21 14:33:03 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
return ring;
|
2024-08-21 14:33:03 +08:00
|
|
|
}
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
static void ring_buffer_free(struct ring_buffer *ring)
|
2024-08-21 14:33:03 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
if (ring)
|
2024-08-21 14:33:03 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
if (ring->buff)
|
|
|
|
|
{
|
|
|
|
|
free(ring->buff);
|
|
|
|
|
ring->buff = NULL;
|
|
|
|
|
}
|
|
|
|
|
free(ring);
|
|
|
|
|
ring = NULL;
|
2024-08-21 14:33:03 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
static int ring_buffer_push(struct ring_buffer *ring, void *data)
|
2024-08-21 14:33:03 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
if (__sync_val_compare_and_swap(&ring->buff[ring->tail], 0, data) != 0)
|
2024-08-21 14:33:03 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_ERROR("ring buffer is full, retry later");
|
2024-08-21 14:33:03 +08:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
ring->tail = (ring->tail + 1) % ring->size;
|
2024-08-21 14:33:03 +08:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
static void ring_buffer_pop(struct ring_buffer *ring, void **data)
|
2024-08-21 14:33:03 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
uint64_t read = ATOMIC_READ(&ring->buff[ring->head]);
|
2024-08-21 14:33:03 +08:00
|
|
|
if (read == 0)
|
|
|
|
|
{
|
|
|
|
|
*data = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-10-23 10:01:20 +08:00
|
|
|
__sync_val_compare_and_swap(&ring->buff[ring->head], read, 0);
|
2024-08-21 14:33:03 +08:00
|
|
|
*data = (void *)read;
|
2024-10-23 10:01:20 +08:00
|
|
|
ring->head = (ring->head + 1) % ring->size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
* Private API -- config
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
static struct pcap_io_cfg *pcap_io_cfg_new(const char *toml_file)
|
|
|
|
|
{
|
|
|
|
|
struct pcap_io_cfg *cfg = (struct pcap_io_cfg *)calloc(1, sizeof(struct pcap_io_cfg));
|
|
|
|
|
if (cfg == NULL)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ret = 0;
|
|
|
|
|
ret += load_toml_str_config(toml_file, "packet_io.mode", cfg->mode);
|
|
|
|
|
ret += load_toml_str_config(toml_file, "packet_io.pcap_path", cfg->pcap_path);
|
2024-10-31 16:25:37 +08:00
|
|
|
ret += load_toml_integer_config(toml_file, "packet_io.pcap_done_exit", &cfg->pcap_done_exit, 0, 1);
|
|
|
|
|
ret += load_toml_integer_config(toml_file, "packet_io.thread_num", &cfg->thread_num, 1, MAX_THREAD_NUM);
|
2024-10-23 10:01:20 +08:00
|
|
|
ret += load_toml_integer_config(toml_file, "packet_io.packet_pool.capacity", &cfg->capacity, 1, 4294967295);
|
|
|
|
|
if (strcmp(cfg->mode, "pcapfile") != 0 && strcmp(cfg->mode, "pcaplist") != 0)
|
|
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_ERROR("config file invalid packet_io.mode %s", cfg->mode);
|
2024-10-23 10:01:20 +08:00
|
|
|
ret = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret != 0)
|
|
|
|
|
{
|
|
|
|
|
free(cfg);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return cfg;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void pcap_io_cfg_free(struct pcap_io_cfg *cfg)
|
|
|
|
|
{
|
|
|
|
|
if (cfg)
|
|
|
|
|
{
|
|
|
|
|
free(cfg);
|
|
|
|
|
cfg = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void pcap_io_cfg_print(const struct pcap_io_cfg *cfg)
|
|
|
|
|
{
|
|
|
|
|
if (cfg)
|
|
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_INFO("packet_io.pcap_path : %s", cfg->pcap_path);
|
|
|
|
|
PACKET_IO_LOG_INFO("packet_io.pcap_done_exit : %lu", cfg->pcap_done_exit);
|
|
|
|
|
PACKET_IO_LOG_INFO("packet_io.packet_pool.capacity : %lu", cfg->capacity);
|
2024-10-23 10:01:20 +08:00
|
|
|
}
|
2024-08-21 14:33:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
2024-10-23 10:01:20 +08:00
|
|
|
* Private API -- pcap
|
2024-08-21 14:33:03 +08:00
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
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-10-23 10:01:20 +08:00
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)user;
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-10-31 16:25:37 +08:00
|
|
|
struct pcap_pkt *pcap = (struct pcap_pkt *)calloc(1, sizeof(struct pcap_pkt) + h->caplen);
|
|
|
|
|
if (pcap == NULL)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_ERROR("unable to alloc packet");
|
2024-02-28 16:30:03 +08:00
|
|
|
return;
|
|
|
|
|
}
|
2024-10-31 16:25:37 +08:00
|
|
|
pcap->data = (char *)pcap + sizeof(struct pcap_pkt);
|
|
|
|
|
pcap->len = h->caplen;
|
|
|
|
|
pcap->ts = h->ts;
|
|
|
|
|
memcpy((char *)pcap->data, bytes, h->caplen);
|
2024-10-23 10:01:20 +08:00
|
|
|
ATOMIC_INC(&pcap_io->read_pcap_pkts);
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-03-09 19:28:14 +08:00
|
|
|
struct packet pkt;
|
2024-06-14 19:24:27 +08:00
|
|
|
memset(&pkt, 0, sizeof(struct packet));
|
2024-10-31 16:25:37 +08:00
|
|
|
packet_parse(&pkt, pcap->data, pcap->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-10-23 10:01:20 +08:00
|
|
|
struct ring_buffer *ring = pcap_io->ring[hash % pcap_io->cfg->thread_num];
|
2024-10-31 16:25:37 +08:00
|
|
|
while (ring_buffer_push(ring, pcap) == -1)
|
2024-04-11 19:44:02 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
if (ATOMIC_READ(&pcap_io->io_thread_need_exit))
|
2024-04-11 19:44:02 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
free(pcap);
|
|
|
|
|
PACKET_IO_LOG_FATAL("pcap io thread need exit");
|
2024-10-23 10:01:20 +08:00
|
|
|
pcap_breakloop(pcap_io->pcap);
|
2024-04-11 19:44:02 +08:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
usleep(1000);
|
|
|
|
|
}
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
if (ATOMIC_READ(&pcap_io->io_thread_need_exit))
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_FATAL("pcap io thread need exit");
|
2024-10-23 10:01:20 +08:00
|
|
|
pcap_breakloop(pcap_io->pcap);
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
static int pcap_io_handler(struct pcap_io *pcap_io, 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-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_FATAL("pcap %s in-processing", resolved_path)
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
pcap_io->pcap = pcap_open_offline(resolved_path, pcap_errbuf);
|
|
|
|
|
if (pcap_io->pcap == NULL)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +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;
|
|
|
|
|
}
|
2024-10-23 10:01:20 +08:00
|
|
|
pcap_io->read_pcap_files++;
|
|
|
|
|
pcap_loop(pcap_io->pcap, -1, pcap_pkt_handler, (u_char *)pcap_io);
|
|
|
|
|
pcap_close(pcap_io->pcap);
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_FATAL("pcap %s processed", resolved_path)
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
static int all_packet_consumed(struct pcap_io *pcap_io)
|
2024-05-15 11:40:00 +08:00
|
|
|
{
|
2024-08-27 16:19:20 +08:00
|
|
|
uint64_t consumed_pkts = 0;
|
2024-10-23 10:01:20 +08:00
|
|
|
uint64_t read_pcap_pkts = ATOMIC_READ(&pcap_io->read_pcap_pkts);
|
|
|
|
|
for (uint16_t i = 0; i < pcap_io->cfg->thread_num; i++)
|
2024-05-15 11:40:00 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
consumed_pkts += ATOMIC_READ(&pcap_io->stat[i].pkts_rx);
|
2024-08-27 16:19:20 +08:00
|
|
|
}
|
|
|
|
|
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-10-23 10:01:20 +08:00
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)arg;
|
|
|
|
|
__thread_local_logger = pcap_io->logger;
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
ATOMIC_SET(&pcap_io->io_thread_is_runing, 1);
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_FATAL("pcap io thread is running");
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
if (strcmp(pcap_io->cfg->mode, "pcapfile") == 0)
|
2024-08-19 18:40:49 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
pcap_io_handler(pcap_io, pcap_io->cfg->pcap_path);
|
2024-08-19 18:40:49 +08:00
|
|
|
}
|
2024-10-23 10:01:20 +08:00
|
|
|
else
|
2024-08-19 18:40:49 +08:00
|
|
|
{
|
2024-08-20 19:29:31 +08:00
|
|
|
FILE *fp = NULL;
|
2024-10-23 10:01:20 +08:00
|
|
|
if (strcmp(pcap_io->cfg->pcap_path, "-") == 0)
|
2024-08-19 18:40:49 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_ERROR("pcap path is empty, read from stdin");
|
2024-08-20 19:29:31 +08:00
|
|
|
fp = stdin;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
fp = fopen(pcap_io->cfg->pcap_path, "r");
|
2024-08-20 19:29:31 +08:00
|
|
|
if (fp == NULL)
|
|
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_ERROR("unable to open pcap path: %s", pcap_io->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-10-23 10:01:20 +08:00
|
|
|
while (ATOMIC_READ(&pcap_io->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-10-23 10:01:20 +08:00
|
|
|
pcap_io_handler(pcap_io, 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-10-30 17:00:20 +08:00
|
|
|
PACKET_IO_LOG_FATAL("pcap io thread read all pcap files (files: %lu, pkts: %lu)", pcap_io->read_pcap_files, ATOMIC_READ(&pcap_io->read_pcap_pkts));
|
2024-08-19 18:40:49 +08:00
|
|
|
|
|
|
|
|
erro_out:
|
2024-10-23 10:01:20 +08:00
|
|
|
while (ATOMIC_READ(&pcap_io->io_thread_need_exit) == 0)
|
2024-03-27 17:11:38 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
if (all_packet_consumed(pcap_io))
|
2024-05-15 11:40:00 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
ATOMIC_SET(&pcap_io->io_thread_wait_exit, 1);
|
2024-05-15 11:40:00 +08:00
|
|
|
}
|
|
|
|
|
|
2024-08-15 19:03:48 +08:00
|
|
|
usleep(1000); // 1ms
|
2024-03-27 17:11:38 +08:00
|
|
|
}
|
|
|
|
|
|
2024-10-30 17:00:20 +08:00
|
|
|
PACKET_IO_LOG_FATAL("pcap io thread exit");
|
2024-10-23 10:01:20 +08:00
|
|
|
ATOMIC_SET(&pcap_io->io_thread_is_runing, 0);
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
static void origin_free_cb(struct packet *pkt, void *args)
|
|
|
|
|
{
|
|
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)args;
|
|
|
|
|
struct packet_origin *origin = packet_get_origin(pkt);
|
2024-10-31 16:25:37 +08:00
|
|
|
struct pcap_pkt *pcap = origin->ctx;
|
2024-10-23 10:01:20 +08:00
|
|
|
struct packet_io_stat *stat = &pcap_io->stat[origin->thr_idx];
|
2024-10-23 10:10:20 +08:00
|
|
|
struct packet_pool *pool = pcap_io->pool[origin->thr_idx];
|
2024-10-23 10:01:20 +08:00
|
|
|
|
|
|
|
|
stat->pkts_user_freed++;
|
|
|
|
|
stat->bytes_user_freed += packet_get_raw_len(pkt);
|
|
|
|
|
|
2024-10-31 16:25:37 +08:00
|
|
|
free(pcap);
|
2024-11-08 19:16:06 +08:00
|
|
|
packet_pool_release_packet(pool, pkt);
|
2024-10-23 10:01:20 +08:00
|
|
|
}
|
|
|
|
|
|
2024-02-28 16:30:03 +08:00
|
|
|
/******************************************************************************
|
|
|
|
|
* Public API
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
void *pcap_io_new(const char *toml_file)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
|
|
|
|
pthread_t tid;
|
2024-10-23 10:01:20 +08:00
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)calloc(1, sizeof(struct pcap_io));
|
|
|
|
|
if (pcap_io == NULL)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_ERROR("unable to allocate memory for pcap_io");
|
2024-02-28 16:30:03 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
pcap_io->cfg = pcap_io_cfg_new(toml_file);
|
|
|
|
|
if (pcap_io->cfg == NULL)
|
|
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_ERROR("unable to create pcap_io_cfg");
|
2024-10-23 10:01:20 +08:00
|
|
|
goto error_out;
|
|
|
|
|
}
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
pcap_io_cfg_print(pcap_io->cfg);
|
|
|
|
|
pcap_io->logger = __thread_local_logger;
|
2024-10-31 16:25:37 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
for (uint16_t i = 0; i < pcap_io->cfg->thread_num; i++)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
pcap_io->ring[i] = ring_buffer_new(RING_BUFFER_MAX_SIZE);
|
|
|
|
|
if (pcap_io->ring[i] == NULL)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_ERROR("unable to create ring buffer");
|
2024-10-23 10:01:20 +08:00
|
|
|
goto error_out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pcap_io->pool[i] = packet_pool_new(pcap_io->cfg->capacity);
|
|
|
|
|
if (pcap_io->pool[i] == NULL)
|
|
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_ERROR("unable to create packet pool");
|
2024-02-28 16:30:03 +08:00
|
|
|
goto error_out;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-23 10:01:20 +08:00
|
|
|
if (pthread_create(&tid, NULL, pcap_io_thread, (void *)pcap_io) != 0)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
PACKET_IO_LOG_ERROR("unable to create pcap io thread");
|
2024-02-28 16:30:03 +08:00
|
|
|
goto error_out;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
return pcap_io;
|
2024-02-28 16:30:03 +08:00
|
|
|
|
|
|
|
|
error_out:
|
2024-10-23 10:01:20 +08:00
|
|
|
pcap_io_free(pcap_io);
|
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-10-31 16:25:37 +08:00
|
|
|
struct pcap_pkt *pcap = NULL;
|
2024-10-23 10:01:20 +08:00
|
|
|
for (uint16_t i = 0; i < pcap_io->cfg->thread_num; i++)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-04-11 19:44:02 +08:00
|
|
|
while (1)
|
|
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
ring_buffer_pop(pcap_io->ring[i], (void **)&pcap);
|
|
|
|
|
if (pcap)
|
2024-04-11 19:44:02 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
free(pcap);
|
2024-04-11 19:44:02 +08:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-23 10:01:20 +08:00
|
|
|
packet_pool_free(pcap_io->pool[i]);
|
|
|
|
|
ring_buffer_free(pcap_io->ring[i]);
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|
2024-10-23 10:01:20 +08:00
|
|
|
pcap_io_cfg_free(pcap_io->cfg);
|
2024-08-30 10:21:44 +08:00
|
|
|
free(pcap_io);
|
|
|
|
|
pcap_io = NULL;
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-31 16:25:37 +08:00
|
|
|
int pcap_io_is_done(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;
|
|
|
|
|
|
2024-10-31 16:25:37 +08:00
|
|
|
if (pcap_io->cfg->pcap_done_exit)
|
|
|
|
|
{
|
|
|
|
|
return ATOMIC_READ(&pcap_io->io_thread_wait_exit);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
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-10-23 10:01:20 +08:00
|
|
|
int pcap_io_recv(void *handle, uint16_t thr_idx, struct packet *pkts[], int nr_pkts)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-08-30 10:21:44 +08:00
|
|
|
struct packet *pkt = NULL;
|
2024-10-31 16:25:37 +08:00
|
|
|
struct pcap_pkt *pcap = NULL;
|
2024-08-30 10:21:44 +08:00
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)handle;
|
2024-10-23 10:01:20 +08:00
|
|
|
struct ring_buffer *ring = pcap_io->ring[thr_idx];
|
2024-10-31 16:25:37 +08:00
|
|
|
struct packet_pool *pool = pcap_io->pool[thr_idx];
|
|
|
|
|
struct packet_io_stat *stat = &pcap_io->stat[thr_idx];
|
2024-02-28 16:30:03 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
int ret = 0;
|
|
|
|
|
for (int i = 0; i < nr_pkts; i++)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
ring_buffer_pop(ring, (void **)&pcap);
|
|
|
|
|
if (pcap == NULL)
|
2024-03-08 18:10:38 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
break;
|
2024-03-08 18:10:38 +08:00
|
|
|
}
|
2024-10-31 16:25:37 +08:00
|
|
|
|
|
|
|
|
stat->pkts_rx++;
|
|
|
|
|
stat->bytes_rx += pcap->len;
|
|
|
|
|
|
2024-11-08 19:16:06 +08:00
|
|
|
pkt = packet_pool_acquire_packet(pool);
|
2024-10-31 16:25:37 +08:00
|
|
|
assert(pkt != NULL);
|
|
|
|
|
struct packet_origin origin = {
|
|
|
|
|
.type = ORIGIN_TYPE_PCAP,
|
|
|
|
|
.ctx = pcap,
|
|
|
|
|
.cb = origin_free_cb,
|
|
|
|
|
.args = pcap_io,
|
|
|
|
|
.thr_idx = thr_idx,
|
|
|
|
|
};
|
|
|
|
|
packet_parse(pkt, pcap->data, pcap->len);
|
|
|
|
|
memset(&pkt->meta, 0, sizeof(pkt->meta));
|
|
|
|
|
packet_set_action(pkt, PACKET_ACTION_FORWARD);
|
|
|
|
|
packet_set_timeval(pkt, &pcap->ts);
|
|
|
|
|
packet_set_origin(pkt, &origin);
|
|
|
|
|
|
|
|
|
|
pkts[ret++] = pkt;
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|
2024-03-08 18:10:38 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
return ret;
|
2024-02-28 16:30:03 +08:00
|
|
|
}
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
void pcap_io_send(void *handle, uint16_t thr_idx, struct packet *pkts[], int nr_pkts)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
int len = 0;
|
|
|
|
|
struct tuple6 tuple;
|
|
|
|
|
char file[PATH_MAX] = {0};
|
2024-03-08 18:10:38 +08:00
|
|
|
struct packet *pkt = NULL;
|
2024-10-31 16:25:37 +08:00
|
|
|
struct pcap_pkt *pcap = NULL;
|
|
|
|
|
struct packet_origin *origin = NULL;
|
|
|
|
|
char src_addr_str[INET6_ADDRSTRLEN] = {0};
|
|
|
|
|
char dst_addr_str[INET6_ADDRSTRLEN] = {0};
|
2024-08-30 10:21:44 +08:00
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)handle;
|
2024-10-31 16:25:37 +08:00
|
|
|
struct packet_io_stat *stat = &pcap_io->stat[thr_idx];
|
2024-10-09 11:46:53 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
for (int i = 0; i < nr_pkts; i++)
|
2024-02-28 16:30:03 +08:00
|
|
|
{
|
2024-10-23 10:01:20 +08:00
|
|
|
pkt = pkts[i];
|
2024-03-08 18:10:38 +08:00
|
|
|
|
2024-10-31 16:25:37 +08:00
|
|
|
len = packet_get_raw_len(pkt);
|
|
|
|
|
origin = packet_get_origin(pkt);
|
|
|
|
|
|
|
|
|
|
stat->pkts_tx++;
|
|
|
|
|
stat->bytes_tx += len;
|
|
|
|
|
|
|
|
|
|
if (origin->type == ORIGIN_TYPE_PCAP)
|
2024-10-09 11:46:53 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
pcap = (struct pcap_pkt *)origin->ctx;
|
|
|
|
|
free(pcap);
|
2024-11-08 19:16:06 +08:00
|
|
|
packet_pool_release_packet(pcap_io->pool[thr_idx], pkt);
|
2024-10-09 11:46:53 +08:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
stat->pkts_injected++;
|
|
|
|
|
stat->bytes_injected += len;
|
|
|
|
|
|
|
|
|
|
memset(&tuple, 0, sizeof(struct tuple6));
|
|
|
|
|
packet_get_innermost_tuple6(pkt, &tuple);
|
|
|
|
|
if (tuple.addr_family == AF_INET)
|
|
|
|
|
{
|
|
|
|
|
inet_ntop(AF_INET, &tuple.src_addr.v4, src_addr_str, INET6_ADDRSTRLEN);
|
|
|
|
|
inet_ntop(AF_INET, &tuple.dst_addr.v4, dst_addr_str, INET6_ADDRSTRLEN);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
inet_ntop(AF_INET6, &tuple.src_addr.v6, src_addr_str, INET6_ADDRSTRLEN);
|
|
|
|
|
inet_ntop(AF_INET6, &tuple.dst_addr.v6, dst_addr_str, INET6_ADDRSTRLEN);
|
|
|
|
|
}
|
|
|
|
|
snprintf(file, sizeof(file), "inject-%s:%u-%s:%u-%lu.pcap", src_addr_str, ntohs(tuple.src_port), dst_addr_str, ntohs(tuple.dst_port), stat->pkts_injected);
|
|
|
|
|
if (packet_dump_pcap(pkt, file) == -1)
|
|
|
|
|
{
|
|
|
|
|
PACKET_IO_LOG_ERROR("unable to dump pcap file: %s", file);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
PACKET_IO_LOG_FATAL("dump inject packet: %s", file);
|
|
|
|
|
}
|
|
|
|
|
packet_free(pkt);
|
2024-10-09 11:46:53 +08:00
|
|
|
}
|
2024-10-31 16:25:37 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
pkts[i] = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-03-09 19:28:14 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
void pcap_io_drop(void *handle, uint16_t thr_idx, struct packet *pkts[], int nr_pkts)
|
|
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
int len = 0;
|
2024-10-23 10:01:20 +08:00
|
|
|
struct packet *pkt = NULL;
|
2024-10-31 16:25:37 +08:00
|
|
|
struct pcap_pkt *pcap = NULL;
|
|
|
|
|
struct packet_origin *origin = NULL;
|
2024-10-23 10:01:20 +08:00
|
|
|
struct pcap_io *pcap_io = (struct pcap_io *)handle;
|
2024-10-31 16:25:37 +08:00
|
|
|
struct packet_io_stat *stat = &pcap_io->stat[thr_idx];
|
2024-10-09 11:46:53 +08:00
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
for (int i = 0; i < nr_pkts; i++)
|
|
|
|
|
{
|
|
|
|
|
pkt = pkts[i];
|
2024-10-09 11:46:53 +08:00
|
|
|
|
2024-10-31 16:25:37 +08:00
|
|
|
len = packet_get_raw_len(pkt);
|
|
|
|
|
origin = packet_get_origin(pkt);
|
|
|
|
|
|
|
|
|
|
stat->pkts_dropped++;
|
|
|
|
|
stat->bytes_dropped += len;
|
|
|
|
|
|
|
|
|
|
if (origin->type == ORIGIN_TYPE_PCAP)
|
2024-10-23 10:01:20 +08:00
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
pcap = (struct pcap_pkt *)origin->ctx;
|
|
|
|
|
free(pcap);
|
2024-11-08 19:16:06 +08:00
|
|
|
packet_pool_release_packet(pcap_io->pool[thr_idx], pkt);
|
2024-10-23 10:01:20 +08:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-10-31 16:25:37 +08:00
|
|
|
packet_free(pkt);
|
2024-10-09 11:46:53 +08:00
|
|
|
}
|
2024-10-23 10:01:20 +08:00
|
|
|
pkts[i] = NULL;
|
2024-03-09 19:28:14 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 10:01:20 +08:00
|
|
|
void pcap_io_yield(void *handle __attribute__((unused)), uint16_t thr_idx __attribute__((unused)))
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
}
|