This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
stellar-stellar-2022/src/packet_io/pcap_file_mode/pio_pcap_file.cpp

687 lines
23 KiB
C++
Raw Normal View History

2022-07-26 15:05:14 +08:00
/*
**********************************************************************************************
* File: pcap_file.cpp
* Description: pcap file runmode api
* Authors: Liu WenTan <liuwentan@geedgenetworks.com>
* Date: 2022-07-15
* Copyright: (c) 2018-2022 Geedge Networks, Inc. All rights reserved.
***********************************************************************************************
*/
#include <stdio.h>
#include <errno.h>
2022-08-05 11:03:11 +08:00
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/stat.h>
2022-07-26 15:05:14 +08:00
2022-08-11 11:18:14 +08:00
#include "utils.h"
#include "util_errors.h"
#include "logger.h"
#include "time_helper.h"
#include "pio_pcap_file.h"
2022-08-11 11:18:14 +08:00
#include "packet_io.h"
2022-08-05 11:03:11 +08:00
2022-08-10 10:21:07 +08:00
/**
* @brief validate path is a valid plain file or directory
*
* @retval failed (-1) successful (0),
* if success, dir == nullptr <---> means path is plain file
* dir != nullptr <---> means path is directory
2022-08-10 10:21:07 +08:00
*/
2022-08-05 11:03:11 +08:00
static int validate_directory_or_file(const char *path, DIR **dir)
{
DIR *temp_dir = nullptr;
int ret = -1;
temp_dir = opendir(path);
if (nullptr == temp_dir) {
switch (errno) {
case EACCES:
log_error(ST_ERR_FOPEN, "%s: Permission denied", path);
break;
case EBADF:
log_error(ST_ERR_FOPEN, "%s: invalid file descriptor", path);
break;
case ENOTDIR:
log_info("%s: is a plain file, not directory", path);
ret = 0;
break;
default:
log_error(ST_ERR_FOPEN, "%s: errno:%d", path, errno);
}
} else {
*dir = temp_dir;
ret = 0;
}
return ret;
}
2022-08-10 10:21:07 +08:00
/**
2022-08-05 11:03:11 +08:00
* @brief get the timestamp of the first packet and rewind
*
* @retval true(success), false(error)
2022-08-10 10:21:07 +08:00
*/
2022-08-05 11:03:11 +08:00
static bool peek_first_packet_timestamp(struct pcap_plain_file_info *pfile_info)
{
int ret = pcap_next_ex(pfile_info->pcap_handle, &pfile_info->first_pkt_hdr,
&pfile_info->first_pkt_data);
if (ret <= 0 || (nullptr == pfile_info->first_pkt_hdr)) {
log_error(ST_ERR_PCAP_OPEN_OFFLINE, "failed to get first packet timestamp");
return false;
}
pfile_info->first_pkt_ts.tv_sec = pfile_info->first_pkt_hdr->ts.tv_sec;
pfile_info->first_pkt_ts.tv_usec = pfile_info->first_pkt_hdr->ts.tv_usec;
return true;
}
static int init_pcap_file(struct pcap_plain_file_info *pfile_info)
{
char errbuf[PCAP_ERRBUF_SIZE] = "";
if (nullptr == pfile_info || nullptr == pfile_info->file_name) {
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "invalid pfile_info pointer or file_name");
return -1;
}
pfile_info->pcap_handle = pcap_open_offline(pfile_info->file_name, errbuf);
if (nullptr == pfile_info->pcap_handle) {
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "open pcap file:%s failed.", pfile_info->file_name);
return -1;
}
2022-08-11 09:38:38 +08:00
pthread_mutex_init(&pfile_info->handle_mutex, nullptr);
2022-08-05 11:03:11 +08:00
if (pfile_info->shared != nullptr && pfile_info->shared->bpf_string != nullptr) {
if (pcap_compile(pfile_info->pcap_handle, &pfile_info->filter,
pfile_info->shared->bpf_string, 1, 0) < 0) {
log_error(ST_ERR_BPF, "bpf compilation error %s for %s",
pcap_geterr(pfile_info->pcap_handle), pfile_info->file_name);
return -1;
}
if (pcap_setfilter(pfile_info->pcap_handle, &pfile_info->filter) < 0) {
log_error(ST_ERR_BPF, "could not set bpf filter %s for %s",
pcap_geterr(pfile_info->pcap_handle, pfile_info->file_name));
pcap_freecode(&pfile_info->filter);
return -1;
}
pcap_freecode(&pfile_info->filter);
}
pfile_info->data_link = pcap_datalink(pfile_info->pcap_handle);
if (!peek_first_packet_timestamp(pfile_info)) {
return -1;
}
return 0;
}
static int pcap_plain_file_init(struct pio_pcap_file_device_context *pfile_dev_ctx, const char *file_name)
{
if (nullptr == pfile_dev_ctx) {
return -1;
}
struct pcap_plain_file_info *pfile_info = CALLOC(struct pcap_plain_file_info, 1);
if (nullptr == pfile_info) {
2022-08-05 11:03:11 +08:00
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "alloc pcap_plain_file_info failed.");
return -1;
}
2022-08-05 11:03:11 +08:00
/* TODO: get conf and assign pfile_info */
2022-08-11 09:38:38 +08:00
int ret = strncpy_safe(pfile_info->file_name, file_name, sizeof(pfile_info->file_name));
if (ret < 0) {
log_error(ST_ERR_STR_COPY, "pcap plain file name copy failed.");
return -1;
}
2022-08-05 11:03:11 +08:00
pfile_info->shared = &pfile_dev_ctx->shared;
2022-08-11 09:38:38 +08:00
ret = init_pcap_file(pfile_info);
2022-08-05 11:03:11 +08:00
if (ret < 0) {
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "init_pcap_file failed.");
FREE(pfile_info);
return -1;
} else {
pfile_dev_ctx->is_dir = 0;
pfile_dev_ctx->entity.file = pfile_info;
}
return 0;
}
2022-08-05 11:03:11 +08:00
static int pcap_directory_file_init(struct pio_pcap_file_device_context *pfile_dev_ctx, const char *dir_name, DIR *directory)
{
if (nullptr == pfile_dev_ctx) {
return -1;
}
struct pcap_file_directory_info *pdir_info = CALLOC(struct pcap_file_directory_info, 1);
if (nullptr == pdir_info) {
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "alloc pcap_file_directory_info failed.");
return -1;
}
/* TODO: get conf and assign pdir_info */
2022-08-11 09:38:38 +08:00
int ret = strncpy_safe(pdir_info->dir_name, dir_name, sizeof(pdir_info->dir_name));
if (ret < 0) {
log_error(ST_ERR_STR_COPY, "pcap directory name copy failed.");
return -1;
}
2022-08-05 11:03:11 +08:00
//pdir_info->delay = 30;
pdir_info->shared = &pfile_dev_ctx->shared;
pdir_info->directory = directory;
TAILQ_INIT(&pdir_info->file_queue_head);
pfile_dev_ctx->is_dir = 1;
pfile_dev_ctx->entity.dir = pdir_info;
return 0;
}
2022-08-05 11:03:11 +08:00
static int pcap_file_shared_init(struct pio_pcap_file_device_context *pfile_dev_ctx, uint32_t nr_rxq)
{
if (nullptr == pfile_dev_ctx) {
return -1;
}
/* TODO: get conf and assign pfile_dev_ctx->shared */
if ((g_engine_instance.config.packet_io.mode == PACKET_IO_RUN_MODE_PCAP_FILE) &&
g_engine_instance.config.packet_io.bpf_string != nullptr) {
2022-08-11 09:38:38 +08:00
memset(pfile_dev_ctx->shared.bpf_string, 0, sizeof(pfile_dev_ctx->shared.bpf_string));
int ret = strncpy_safe(pfile_dev_ctx->shared.bpf_string, g_engine_instance.config.packet_io.bpf_string,
sizeof(pfile_dev_ctx->shared.bpf_string));
if (ret < 0) {
log_error(ST_ERR_STR_COPY, "pcap file bpf string copy failed.");
return -1;
}
2022-08-05 11:03:11 +08:00
}
pfile_dev_ctx->shared.should_delete = g_engine_instance.config.packet_io.should_delete;
/* init pcap file device packet queue */
memset(pfile_dev_ctx->pkt_queues, 0, sizeof(pfile_dev_ctx->pkt_queues));
for (uint32_t i = 0; i < PKT_QUEUE_MAX_NUM; i++) {
pthread_mutex_init(&pfile_dev_ctx->pkt_queues[i].mutex_q, nullptr);
}
return 0;
}
2022-07-26 15:05:14 +08:00
2022-08-05 11:03:11 +08:00
static void cleanup_pcap_plain_file_info(struct pcap_plain_file_info *pfile_info)
{
if (pfile_info != nullptr) {
if (pfile_info->pcap_handle != nullptr) {
pcap_close(pfile_info->pcap_handle);
pfile_info->pcap_handle = nullptr;
}
if (pfile_info->file_name != nullptr) {
if (pfile_info->shared != nullptr && pfile_info->shared->should_delete) {
log_debug("Deleting pcap file:%s", pfile_info->file_name);
if (unlink(pfile_info->file_name) != 0) {
log_notice(ST_ERR_PCAP_FILE_DELETE_FAILED, "Failed to delete %s",
pfile_info->file_name);
}
}
pfile_info->shared = nullptr;
}
}
}
static void cleanup_pcap_directory_info(struct pcap_file_directory_info *pdir_info)
{
}
int pio_pcap_file_device_open(struct packet_io_device *pdev)
{
int status = -1;
DIR *directory = nullptr;
2022-08-05 11:03:11 +08:00
if (nullptr == pdev) {
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "invalid packet_io_device pointer.");
return -1;
}
pdev->entity.pcap_file_dev_ctx = CALLOC(struct pio_pcap_file_device_context, 1);
if (nullptr == pdev->entity.pcap_file_dev_ctx) {
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "alloc pcap_file_dev_ctx failed.");
return -1;
}
pdev->entity.pcap_file_dev_ctx->pio_dev = pdev;
2022-08-05 11:03:11 +08:00
status = pcap_file_shared_init(pdev->entity.pcap_file_dev_ctx, pdev->rxq_num);
if (status < 0) {
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "pcap file shared init failed.");
return -1;
}
2022-08-05 11:03:11 +08:00
if (validate_directory_or_file(pdev->dev_name, &directory) != 0) {
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "invalid path:%s (not plain file or directory)", pdev->dev_name);
return -1;
}
if (nullptr == directory) {
/* plain file */
2022-08-05 11:03:11 +08:00
status = pcap_plain_file_init(pdev->entity.pcap_file_dev_ctx, pdev->dev_name);
if (status < 0) {
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "pcap plain file init failed.");
return -1;
}
} else {
/* directory */
2022-08-05 11:03:11 +08:00
status = pcap_directory_file_init(pdev->entity.pcap_file_dev_ctx, pdev->dev_name, directory);
if (status < 0) {
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "pcap directory file init failed.");
return -1;
}
}
2022-07-26 15:05:14 +08:00
return 0;
}
int pio_pcap_file_device_close(struct packet_io_device *pdev)
{
if (nullptr == pdev) {
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "invalid pdev pointer so close pcap file device failed!");
return -1;
}
2022-08-05 11:03:11 +08:00
if (pdev->entity.pcap_file_dev_ctx->entity.file != nullptr) {
cleanup_pcap_plain_file_info(pdev->entity.pcap_file_dev_ctx->entity.file);
}
if (pdev->entity.pcap_file_dev_ctx->entity.dir != nullptr) {
cleanup_pcap_directory_info(pdev->entity.pcap_file_dev_ctx->entity.dir);
}
for (uint32_t i = 0; i < PKT_QUEUE_MAX_NUM; i++) {
if (pdev->entity.pcap_file_dev_ctx->pkt_queues[i].len != 0) {
release_pio_packet_queue(&pdev->entity.pcap_file_dev_ctx->pkt_queues[i]);
2022-08-05 11:03:11 +08:00
}
}
FREE(pdev->entity.pcap_file_dev_ctx);
return 0;
}
2022-08-05 18:32:54 +08:00
void pcap_file_pkt_callback_oneshot(char *user, struct pcap_pkthdr *pkt_hdr, u_char *pkt)
2022-08-05 11:03:11 +08:00
{
struct pio_pcap_file_device_context *pfile_dev_ctx = (struct pio_pcap_file_device_context *)user;
struct pio_packet *p = (struct pio_packet *)malloc(SIZE_OF_PIO_PACKET);
2022-08-05 11:03:11 +08:00
if (nullptr == p) {
return;
}
memset(p, 0, SIZE_OF_PIO_PACKET);
2022-08-05 11:03:11 +08:00
p->pkt_hdr = p;
p->pkt_payload = (uint8_t *)p + CUSTOM_ZONE_LEN;
p->pkt_len = pkt_hdr->caplen;
if (packet_copy_data((uint8_t *)p->pkt_payload, (uint8_t *)pkt, pkt_hdr->caplen)) {
2022-08-05 11:03:11 +08:00
FREE(p);
return;
}
2022-08-11 09:38:38 +08:00
//uint32_t nr_rxq = pfile_dev_ctx->pio_dev->rxq_num;
2022-08-05 11:03:11 +08:00
/*
hash to specific queue id and enqueue
hash_id = decode_packet(p) % nr_rxq;
packet_enqueue(&pfile_dev_ctx->pkt_queues[hash_id], p);
*/
int rxq_id = 0;
2022-08-05 11:03:11 +08:00
pthread_mutex_lock(&pfile_dev_ctx->pkt_queues[rxq_id].mutex_q);
pio_packet_enqueue(&pfile_dev_ctx->pkt_queues[rxq_id], p);
pthread_mutex_unlock(&pfile_dev_ctx->pkt_queues[rxq_id].mutex_q);
2022-08-05 11:03:11 +08:00
}
static int pcap_file_dispatch(struct pio_pcap_file_device_context *pfile_dev_ctx, uint32_t rxq_id,
2022-08-11 09:38:38 +08:00
struct stellar_packet **pkts, int nr_pkts)
2022-08-05 11:03:11 +08:00
{
if (pfile_dev_ctx->entity.file->first_pkt_hdr != nullptr) {
pthread_mutex_lock(&pfile_dev_ctx->entity.file->handle_mutex);
if (pfile_dev_ctx->entity.file->first_pkt_hdr != nullptr) {
2022-08-05 18:32:54 +08:00
pcap_file_pkt_callback_oneshot((char *)pfile_dev_ctx, pfile_dev_ctx->entity.file->first_pkt_hdr,
(u_char *)pfile_dev_ctx->entity.file->first_pkt_data);
2022-08-05 11:03:11 +08:00
pfile_dev_ctx->entity.file->first_pkt_hdr = nullptr;
pfile_dev_ctx->entity.file->first_pkt_data = nullptr;
}
pthread_mutex_unlock(&pfile_dev_ctx->entity.file->handle_mutex);
}
int packet_q_len = nr_pkts;
int res = -1;
pthread_mutex_lock(&pfile_dev_ctx->entity.file->handle_mutex);
res = pcap_dispatch(pfile_dev_ctx->entity.file->pcap_handle, packet_q_len,
2022-08-05 18:32:54 +08:00
(pcap_handler)pcap_file_pkt_callback_oneshot, (u_char *)pfile_dev_ctx);
2022-08-05 11:03:11 +08:00
pthread_mutex_unlock(&pfile_dev_ctx->entity.file->handle_mutex);
if (res < 0) {
log_error(ST_ERR_PCAP_DISPATCH, "error code %d %s for %s", res,
pcap_geterr(pfile_dev_ctx->entity.file->pcap_handle), pfile_dev_ctx->entity.file->file_name);
} else if (res == 0) {
log_info("reach end of pcap file %s (error code %d)", pfile_dev_ctx->entity.file->file_name, res);
//TODO: close pcap file
} else {
// success
struct pio_packet *p = nullptr;
2022-08-05 11:03:11 +08:00
int i = 0;
pthread_mutex_lock(&pfile_dev_ctx->pkt_queues[rxq_id].mutex_q);
do {
p = pio_packet_dequeue(&pfile_dev_ctx->pkt_queues[rxq_id]);
2022-08-11 09:38:38 +08:00
pkts[i] = (struct stellar_packet *)p;
2022-08-05 11:03:11 +08:00
i++;
} while (p != nullptr && (i < nr_pkts));
pthread_mutex_unlock(&pfile_dev_ctx->pkt_queues[rxq_id].mutex_q);
if (nullptr == p) {
res = i - 1;
} else {
res = nr_pkts;
}
}
return res;
}
static int pcap_directory_get_modified_time(char *pfile, struct timespec *out)
{
struct stat buf;
int ret = -1;
if (nullptr == pfile) {
return ret;
}
if ((ret = stat(pfile, &buf)) != 0) {
return ret;
}
out->tv_sec = buf.st_mtim.tv_sec;
out->tv_nsec = buf.st_mtim.tv_nsec;
return ret;
}
struct pending_file *
find_pending_file_to_add(struct pio_pcap_file_device_context *pfile_dev_ctx, struct dirent *dir,
struct timespec *deadline)
{
char abs_path[PATH_MAX] = {0};
2022-08-11 09:38:38 +08:00
snprintf(abs_path, sizeof(abs_path), "%s/%s", pfile_dev_ctx->entity.dir->dir_name, dir->d_name);
2022-08-05 11:03:11 +08:00
struct timespec temp_time;
memset(&temp_time, 0, sizeof(struct timespec));
if (pcap_directory_get_modified_time(abs_path, &temp_time) < 0) {
log_debug("unable to get modified time on %s, skipping", abs_path);
return nullptr;
}
/* skip files outside of out time range */
if (compare_timespec(&temp_time, &pfile_dev_ctx->shared.last_processed_ts) <= 0) {
log_debug("skipping old file %s", abs_path);
return nullptr;
} else if (compare_timespec(&temp_time, deadline) >= 0) {
log_debug("skipping new file %s", abs_path);
return nullptr;
}
struct pending_file *file_to_add = CALLOC(struct pending_file, 1);
2022-08-11 09:38:38 +08:00
int ret = strncpy_safe(file_to_add->file_name, abs_path, sizeof(file_to_add->file_name));
if (ret < 0) {
log_error(ST_ERR_STR_COPY, "file_to_add file name copy failed.");
return nullptr;
}
2022-08-05 11:03:11 +08:00
copy_timespec(&temp_time, &file_to_add->modified_time);
log_info("found \"%s\" at %" PRIuMAX, file_to_add->file_name,
(uintmax_t)timespec_to_millisecond(&file_to_add->modified_time));
return file_to_add;
}
static int pcap_directory_insert_file(struct pio_pcap_file_device_context *pfile_dev_ctx, struct pending_file *file_to_add)
{
if (nullptr == pfile_dev_ctx || file_to_add) {
log_error(ST_ERR_PCAP_FILE_COLLECT_FAILED, "invalid directory or file parameters.");
return -1;
}
log_debug("inserting %s into pending file queue", file_to_add->file_name);
if (TAILQ_EMPTY(&pfile_dev_ctx->entity.dir->file_queue_head)) {
TAILQ_INSERT_TAIL(&pfile_dev_ctx->entity.dir->file_queue_head, file_to_add, next);
} else {
struct pending_file *file_to_compare = TAILQ_FIRST(&pfile_dev_ctx->entity.dir->file_queue_head);
while (file_to_compare != nullptr) {
if (compare_timespec(&file_to_add->modified_time, &file_to_compare->modified_time) < 0) {
TAILQ_INSERT_BEFORE(file_to_compare, file_to_add, next);
file_to_compare = nullptr;
} else {
struct pending_file *next_file_to_compare = TAILQ_NEXT(file_to_compare, next);
if (next_file_to_compare == nullptr) {
TAILQ_INSERT_AFTER(&pfile_dev_ctx->entity.dir->file_queue_head, file_to_compare, file_to_add, next);
}
file_to_compare = next_file_to_compare;
}
}
}
2022-07-26 15:05:14 +08:00
return 0;
}
2022-08-05 11:03:11 +08:00
static int pcap_directory_collect_pending_files(struct pio_pcap_file_device_context *pfile_dev_ctx, struct timespec *deadline)
{
if (nullptr == pfile_dev_ctx) {
return -1;
}
if (strlen(pfile_dev_ctx->entity.dir->dir_name) == 0) {
log_error(ST_ERR_PCAP_FILE_COLLECT_FAILED, "invalid directory name.");
return -1;
}
struct dirent *dir = nullptr;
struct pending_file *file_to_add = nullptr;
while ((dir = readdir(pfile_dev_ctx->entity.dir->directory)) != nullptr) {
/* ignore non plain file */
if (dir->d_type != DT_REG) {
continue;
}
/* ignore . and .. */
if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) {
continue;
}
file_to_add = find_pending_file_to_add(pfile_dev_ctx, dir, deadline);
if (nullptr == file_to_add) {
continue;
}
if (pcap_directory_insert_file(pfile_dev_ctx, file_to_add) < 0) {
log_error(ST_ERR_PCAP_FILE_COLLECT_FAILED, "failed to insert file into directory");
FREE(file_to_add);
return -1;
}
}
return 0;
}
static int pcap_directory_dispatch(struct pio_pcap_file_device_context *pfile_dev_ctx, uint32_t rxq_id,
2022-08-11 09:38:38 +08:00
struct stellar_packet **pkts, int nr_pkts)
2022-08-05 11:03:11 +08:00
{
int res = -1;
struct timespec deadline;
memset(&deadline, 0, sizeof(struct timespec));
get_current_timespec(&deadline);
/* the newest file which can be processed */
deadline.tv_sec = deadline.tv_sec - pfile_dev_ctx->entity.dir->delay;
/* collect pending files in current directory */
if (pcap_directory_collect_pending_files(pfile_dev_ctx, &deadline) < 0) {
log_error(ST_ERR_PCAP_FILE_COLLECT_FAILED, "failed to collect pending files in directory.");
return -1;
}
/* file_queue is empty */
if (TAILQ_EMPTY(&pfile_dev_ctx->entity.dir->file_queue_head)) {
log_info("directory %s has no files to process", pfile_dev_ctx->entity.dir->dir_name);
return 0;
}
struct timespec last_time_seen;
memset(&last_time_seen, 0, sizeof(struct timespec));
// file_queue_head has pending files
if (nullptr == pfile_dev_ctx->entity.dir->current_file) {
/* not open file yet */
struct pending_file *current_file = TAILQ_FIRST(&pfile_dev_ctx->entity.dir->file_queue_head);
log_info("processing file %s", current_file->file_name);
struct pcap_plain_file_info *pfile_info = CALLOC(struct pcap_plain_file_info, 1);
if (nullptr == pfile_info) {
log_error(ST_ERR_MEM_ALLOC, "alloc pcap_plain_file_info failed.");
return -1;
}
2022-08-11 09:38:38 +08:00
res = strncpy_safe(pfile_info->file_name, current_file->file_name, sizeof(pfile_info->file_name));
if (res < 0) {
log_error(ST_ERR_STR_COPY, "pfile_info file name copy failed.");
FREE(current_file);
FREE(pfile_info);
return -1;
}
2022-08-05 11:03:11 +08:00
pfile_info->shared = &pfile_dev_ctx->shared;
if (init_pcap_file(pfile_info) < 0) {
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "init_pcap_file failed.");
FREE(current_file);
FREE(pfile_info);
return -1;
} else {
pfile_dev_ctx->entity.dir->current_file = pfile_info;
res = pcap_file_dispatch(pfile_dev_ctx, rxq_id, pkts, nr_pkts);
2022-08-05 11:03:11 +08:00
if (res < 0) {
FREE(current_file);
return -1;
}
log_info("processed file %s, processed up to %" PRIuMAX,
current_file->file_name, (uintmax_t)timespec_to_millisecond(&current_file->modified_time));
if (compare_timespec(&current_file->modified_time, &last_time_seen) > 0) {
copy_timespec(&current_file->modified_time, &last_time_seen);
}
FREE(current_file);
if (res == 0) { // reach the end of the file
pfile_dev_ctx->entity.dir->current_file = nullptr;
}
}
} else {
/* file has been opened */
res = pcap_file_dispatch(pfile_dev_ctx, rxq_id, pkts, nr_pkts);
2022-08-05 11:03:11 +08:00
if (res < 0) {
return -1;
}
}
if (compare_timespec(&last_time_seen, &pfile_dev_ctx->shared.last_processed_ts) > 0) {
log_info("updating processed to %" PRIuMAX, (uintmax_t)timespec_to_millisecond(&last_time_seen));
copy_timespec(&last_time_seen, &pfile_dev_ctx->shared.last_processed_ts);
}
return res;
}
2022-08-11 09:38:38 +08:00
int pio_pcap_file_device_receive(struct packet_io_device *pdev, uint32_t rxq_id, struct stellar_packet **pkts, int nr_pkts)
2022-08-05 11:03:11 +08:00
{
struct pio_pcap_file_device_context *pfile_dev_ctx = pdev->entity.pcap_file_dev_ctx;
if (nullptr == pfile_dev_ctx) {
log_error(ST_ERR_PIO_PCAP_FILE_DEVICE, "invalid pcap_file_dev_ctx pointer.");
return -1;
}
int res = -1;
if (pfile_dev_ctx->is_dir == 0) {
log_info("Start reading file:%s", pfile_dev_ctx->entity.file->file_name);
res = pcap_file_dispatch(pfile_dev_ctx, rxq_id, pkts, nr_pkts);
2022-08-05 11:03:11 +08:00
} else {
log_info("Start reading directory:%s", pfile_dev_ctx->entity.dir->dir_name);
res = pcap_directory_dispatch(pfile_dev_ctx, rxq_id, pkts, nr_pkts);
2022-08-05 11:03:11 +08:00
}
return res;
}
2022-08-11 09:38:38 +08:00
void pio_pcap_file_device_pkt_free(__unused struct packet_io_device *pdev, __unused uint32_t qid, struct stellar_packet **pkts, int nr_pkts)
{
2022-08-11 09:38:38 +08:00
for (int i = 0; i < nr_pkts; i++) {
struct pio_packet *p = (struct pio_packet *)pkts[i];
FREE(p);
}
}
2022-08-10 10:20:12 +08:00
int pio_pcap_file_instance_create(struct packet_io_instance *pinst)
{
2022-08-05 11:03:11 +08:00
if (nullptr == pinst) {
log_error(ST_ERR_PIO_PCAP_FILE_INSTANCE, "invalid pcap file instance pointer.");
return -1;
}
pinst->entity.pcap_file_inst_ctx = CALLOC(struct pio_pcap_file_instance_context, 1);
if (nullptr == pinst->entity.pcap_file_inst_ctx) {
log_error(ST_ERR_PIO_PCAP_FILE_INSTANCE, "alloc pcap_file_inst_ctx failed.");
return -1;
}
2022-07-26 15:05:14 +08:00
return 0;
}
void pio_pcap_file_instance_destroy(struct packet_io_instance *pinst)
{
2022-08-05 18:32:54 +08:00
if (nullptr == pinst) {
return;
}
2022-08-05 11:03:11 +08:00
FREE(pinst->entity.pcap_file_inst_ctx);
for (uint32_t i = 0; i < pinst->dev_cnt; i++) {
pio_pcap_file_device_close(pinst->devices[i]);
FREE(pinst->devices[i]);
}
}
2022-08-11 09:38:38 +08:00
void *pio_pcap_file_device_buff_ctrlzone(struct stellar_packet *p)
{
struct pio_packet *pkt = (struct pio_packet *)p;
return pkt->pkt_hdr;
}
2022-08-11 09:38:38 +08:00
char *pio_pcap_file_device_buff_mtod(struct stellar_packet *p)
{
struct pio_packet *pkt = (struct pio_packet *)p;
return (char *)pkt->pkt_payload;
}
2022-08-11 09:38:38 +08:00
uint32_t pio_pcap_file_device_buff_buflen(struct stellar_packet *p)
{
struct pio_packet *pkt = (struct pio_packet *)p;
return (pkt->pkt_len + CUSTOM_ZONE_LEN);
}
2022-08-11 09:38:38 +08:00
uint32_t pio_pcap_file_device_buff_datalen(struct stellar_packet *p)
{
struct pio_packet *pkt = (struct pio_packet *)p;
return (pkt->pkt_len);
2022-08-11 09:38:38 +08:00
}