#pragma once

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdint.h>
#include <limits.h>

#include "utils.h"

struct __attribute__((aligned(64))) packet_io_stat
{
    // device packet
    uint64_t pkts_rx;
    uint64_t bytes_rx;

    uint64_t pkts_tx;
    uint64_t bytes_tx;

    // keep-alive packet
    uint64_t keep_alive_pkts;
    uint64_t keep_alive_bytes;

    // raw packet
    uint64_t raw_pkts_rx;
    uint64_t raw_bytes_rx;

    uint64_t raw_pkts_tx;
    uint64_t raw_bytes_tx;

    // drop packet
    uint64_t pkts_dropped;
    uint64_t bytes_dropped;

    // inject packet
    uint64_t pkts_injected;
    uint64_t bytes_injected;

    // ctrl packet
    uint64_t ctrl_pkts_rx;
    uint64_t ctrl_bytes_rx;

    uint64_t ctrl_pkts_tx;
    uint64_t ctrl_bytes_tx;
};

enum packet_io_mode
{
    PACKET_IO_DUMPFILE = 0,
    PACKET_IO_DUMPFILELIST = 1,
    PACKET_IO_MARSIO = 2,
};

struct packet_io_options
{
    enum packet_io_mode mode;

    // for dumpfile
    char dumpfile_path[PATH_MAX];

    // for marsio
    char app_symbol[64];
    char dev_symbol[64];

    uint16_t nr_threads;
    uint16_t cpu_mask[MAX_THREAD_NUM];
};

struct packet_io;
struct packet_io *packet_io_new(struct packet_io_options *opts);
void packet_io_free(struct packet_io *packet_io);
int packet_io_isbreak(struct packet_io *packet_io); // used for dumpfile mode

int packet_io_init(struct packet_io *packet_io, uint16_t thr_idx);
uint16_t packet_io_input(struct packet_io *packet_io, uint16_t thr_idx, struct packet *pkts, uint16_t nr_pkts);
void packet_io_output(struct packet_io *packet_io, uint16_t thr_idx, struct packet *pkts, uint16_t nr_pkts);
void packet_io_drop(struct packet_io *packet_io, uint16_t thr_idx, struct packet *pkts, uint16_t nr_pkts);
uint16_t packet_io_inject(struct packet_io *packet_io, uint16_t thr_idx, struct packet *pkts, uint16_t nr_pkts);
void packet_io_yield(struct packet_io *packet_io, uint16_t thr_idx, uint64_t timeout_ms);
struct packet_io_stat *packet_io_stat(struct packet_io *packet_io, uint16_t thr_idx);

#ifdef __cplusplus
}
#endif
