Refactor Packet I/O

This commit is contained in:
luwenpeng
2024-04-10 17:50:51 +08:00
parent 24e109e34f
commit 621a4cf292
13 changed files with 441 additions and 528 deletions

View File

@@ -63,13 +63,13 @@ uint64_t id_generator_alloc()
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts); // must be realtime
uint64_t thread_index = stellar_get_current_thread_index();
uint64_t thr_idx = stellar_get_current_thread_index();
uint64_t global_id = 0;
uint64_t id_per_thread = (global_id_generator.thread_volatile[thread_index]++) % MAX_ID_PER_THREAD;
uint64_t id_per_thread = (global_id_generator.thread_volatile[thr_idx]++) % MAX_ID_PER_THREAD;
uint64_t id_base_time = ts.tv_sec % MAX_ID_BASE_TIME;
global_id = (global_id_generator.device_id << 51) |
(thread_index << 43) |
(thr_idx << 43) |
(id_base_time << 15) |
(id_per_thread);

View File

@@ -1625,18 +1625,18 @@ int packet_get_route_ctx(const struct packet *pkt, char *buff, int size)
return meta->route.len;
}
void packet_set_user_data(struct packet *pkt, void *user_data)
void packet_set_io_ctx(struct packet *pkt, void *ctx)
{
struct metadata *meta = &pkt->meta;
meta->user_data = user_data;
meta->io_ctx = ctx;
}
void *packet_get_user_data(const struct packet *pkt)
void *packet_get_io_ctx(const struct packet *pkt)
{
const struct metadata *meta = &pkt->meta;
return meta->user_data;
return meta->io_ctx;
}
void packet_set_domain(struct packet *pkt, uint64_t domain)
@@ -1749,7 +1749,7 @@ struct packet *packet_dup(const struct packet *pkt)
dup_pkt->need_free = true;
struct metadata *meta = &dup_pkt->meta;
meta->user_data = NULL;
meta->io_ctx = NULL;
// update layers
for (int8_t i = 0; i < pkt->layers_used; i++)

View File

@@ -60,7 +60,7 @@ struct metadata
uint16_t len;
} route;
void *user_data;
void *io_ctx;
uint64_t domain;
uint64_t session_id;
enum packet_direction direction;
@@ -108,8 +108,8 @@ int packet_set_route_ctx(struct packet *pkt, const char *route, int len);
// return len of route ctx
int packet_get_route_ctx(const struct packet *pkt, char *buff, int size);
void packet_set_user_data(struct packet *pkt, void *user_data);
void *packet_get_user_data(const struct packet *pkt);
void packet_set_io_ctx(struct packet *pkt, void *ctx);
void *packet_get_io_ctx(const struct packet *pkt);
void packet_set_domain(struct packet *pkt, uint64_t domain);
uint64_t packet_get_domain(const struct packet *pkt);

View File

@@ -1,4 +1,4 @@
add_library(packet_io packet_io_dumpfile.cpp packet_io_marsio.cpp lock_free_queue.cpp packet_io.cpp)
add_library(packet_io dumpfile_io.cpp marsio_io.cpp lock_free_queue.cpp packet_io.cpp)
target_include_directories(packet_io PUBLIC ${CMAKE_CURRENT_LIST_DIR})
target_include_directories(packet_io PUBLIC ${CMAKE_SOURCE_DIR}/src/stellar)
target_link_libraries(packet_io mrzcpd pcap packet file)

View File

@@ -7,20 +7,20 @@
#include "stellar.h"
#include "file_scan.h"
#include "packet_io.h"
#include "packet_private.h"
#include "lock_free_queue.h"
#include "packet_io_dumpfile.h"
#include "dumpfile_io.h"
#define MAX_PACKET_QUEUE_SIZE (4096 * 1000)
struct packet_io_dumpfile
struct dumpfile_io
{
uint8_t nr_threads;
char dumpfile_dir[256];
char directory[256];
pcap_t *pcap;
struct lock_free_queue *queue[MAX_THREAD_NUM];
struct packet_io_stat stat;
struct packet_stat stat;
uint64_t io_thread_need_exit;
uint64_t io_thread_is_runing;
};
@@ -37,7 +37,7 @@ struct pcap_pkt
static void pcap_handle(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
{
struct packet_io_dumpfile *handle = (struct packet_io_dumpfile *)user;
struct dumpfile_io *handle = (struct dumpfile_io *)user;
// copy packet data to new memory
struct pcap_pkt *pcap_pkt = (struct pcap_pkt *)calloc(1, sizeof(struct pcap_pkt) + h->caplen);
@@ -70,7 +70,7 @@ static int dumpfile_handle(const char *file, void *arg)
{
char resolved_path[256];
char pcap_errbuf[PCAP_ERRBUF_SIZE];
struct packet_io_dumpfile *handle = (struct packet_io_dumpfile *)arg;
struct dumpfile_io *handle = (struct dumpfile_io *)arg;
realpath(file, resolved_path);
PACKET_IO_LOG_STATE("dumpfile %s in-processing", resolved_path)
@@ -91,12 +91,12 @@ static int dumpfile_handle(const char *file, void *arg)
static void *dumpfile_thread_cycle(void *arg)
{
struct packet_io_dumpfile *handle = (struct packet_io_dumpfile *)arg;
struct dumpfile_io *handle = (struct dumpfile_io *)arg;
ATOMIC_SET(&handle->io_thread_is_runing, 1);
PACKET_IO_LOG_STATE("dumpfile io thread is running");
file_scan(handle->dumpfile_dir, dumpfile_handle, arg);
file_scan(handle->directory, dumpfile_handle, arg);
while (ATOMIC_READ(&handle->io_thread_need_exit) == 0)
{
@@ -114,18 +114,18 @@ static void *dumpfile_thread_cycle(void *arg)
* Public API
******************************************************************************/
struct packet_io_dumpfile *packet_io_dumpfile_new(struct packet_io_dumpfile_options *opts)
struct dumpfile_io *dumpfile_io_new(const char *directory, uint8_t nr_threads)
{
pthread_t tid;
struct packet_io_dumpfile *handle = (struct packet_io_dumpfile *)calloc(1, sizeof(struct packet_io_dumpfile));
struct dumpfile_io *handle = (struct dumpfile_io *)calloc(1, sizeof(struct dumpfile_io));
if (handle == NULL)
{
PACKET_IO_LOG_ERROR("unable to allocate memory for packet_io_dumpfile");
PACKET_IO_LOG_ERROR("unable to allocate memory for dumpfile_io");
return NULL;
}
handle->nr_threads = opts->nr_threads;
strncpy(handle->dumpfile_dir, opts->dumpfile_dir, sizeof(handle->dumpfile_dir));
handle->nr_threads = nr_threads;
strncpy(handle->directory, directory, strlen(directory));
for (uint16_t i = 0; i < handle->nr_threads; i++)
{
@@ -136,7 +136,6 @@ struct packet_io_dumpfile *packet_io_dumpfile_new(struct packet_io_dumpfile_opti
goto error_out;
}
}
if (pthread_create(&tid, NULL, dumpfile_thread_cycle, (void *)handle) != 0)
{
PACKET_IO_LOG_ERROR("unable to create packet io thread");
@@ -146,11 +145,11 @@ struct packet_io_dumpfile *packet_io_dumpfile_new(struct packet_io_dumpfile_opti
return handle;
error_out:
packet_io_dumpfile_free(handle);
dumpfile_io_free(handle);
return NULL;
}
void packet_io_dumpfile_free(struct packet_io_dumpfile *handle)
void dumpfile_io_free(struct dumpfile_io *handle)
{
if (handle)
{
@@ -170,19 +169,19 @@ void packet_io_dumpfile_free(struct packet_io_dumpfile *handle)
}
}
struct packet_io_stat *packet_io_dumpfile_get_stat(struct packet_io_dumpfile *handle)
struct packet_stat *dumpfile_io_stat(struct dumpfile_io *handle)
{
return &handle->stat;
}
int packet_io_dumpfile_init(struct packet_io_dumpfile *handle, uint16_t thread_id)
int dumpfile_io_init(struct dumpfile_io *handle, uint16_t thr_idx)
{
return 0;
}
int packet_io_dumpfile_ingress(struct packet_io_dumpfile *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts)
int dumpfile_io_ingress(struct dumpfile_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts)
{
struct lock_free_queue *queue = handle->queue[thread_id];
struct lock_free_queue *queue = handle->queue[thr_idx];
struct pcap_pkt *pcap_pkt = NULL;
int nr_parsed = 0;
@@ -195,13 +194,16 @@ int packet_io_dumpfile_ingress(struct packet_io_dumpfile *handle, uint16_t threa
}
else
{
ATOMIC_ADD(&handle->stat.rx_pkts, 1);
ATOMIC_ADD(&handle->stat.rx_bytes, pcap_pkt->len);
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);
struct packet *pkt = &pkts[nr_parsed++];
memset(pkt, 0, sizeof(struct packet));
packet_parse(pkt, pcap_pkt->data, pcap_pkt->len);
packet_set_user_data(pkt, pcap_pkt);
packet_set_io_ctx(pkt, pcap_pkt);
packet_set_type(pkt, PACKET_TYPE_DATA);
packet_set_action(pkt, PACKET_ACTION_FORWARD);
}
@@ -210,17 +212,22 @@ int packet_io_dumpfile_ingress(struct packet_io_dumpfile *handle, uint16_t threa
return nr_parsed;
}
void packet_io_dumpfile_egress(struct packet_io_dumpfile *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts)
void dumpfile_io_egress(struct dumpfile_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts)
{
int len;
struct packet *pkt = NULL;
for (int i = 0; i < nr_pkts; i++)
{
pkt = &pkts[i];
len = packet_get_len(pkt);
ATOMIC_ADD(&handle->stat.tx_pkts, 1);
ATOMIC_ADD(&handle->stat.tx_bytes, packet_get_len(pkt));
ATOMIC_ADD(&handle->stat.dev_tx_pkts, 1);
ATOMIC_ADD(&handle->stat.dev_tx_bytes, len);
struct pcap_pkt *pcap_pkt = (struct pcap_pkt *)packet_get_user_data(pkt);
ATOMIC_ADD(&handle->stat.raw_tx_pkts, 1);
ATOMIC_ADD(&handle->stat.raw_tx_bytes, len);
struct pcap_pkt *pcap_pkt = (struct pcap_pkt *)packet_get_io_ctx(pkt);
if (pcap_pkt)
{
free(pcap_pkt);
@@ -229,36 +236,13 @@ void packet_io_dumpfile_egress(struct packet_io_dumpfile *handle, uint16_t threa
}
}
void packet_io_dumpfile_drop(struct packet_io_dumpfile *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts)
void dumpfile_io_drop(struct dumpfile_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts)
{
struct packet *pkt = NULL;
for (int i = 0; i < nr_pkts; i++)
{
pkt = &pkts[i];
ATOMIC_ADD(&handle->stat.drop_pkts, 1);
ATOMIC_ADD(&handle->stat.drop_bytes, packet_get_len(pkt));
struct pcap_pkt *pcap_pkt = (struct pcap_pkt *)packet_get_user_data(pkt);
if (pcap_pkt)
{
free(pcap_pkt);
}
packet_free(pkt);
}
}
void packet_io_dumpfile_inject(struct packet_io_dumpfile *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts)
{
struct packet *pkt = NULL;
for (int i = 0; i < nr_pkts; i++)
{
pkt = &pkts[i];
ATOMIC_ADD(&handle->stat.inject_pkts, 1);
ATOMIC_ADD(&handle->stat.inject_bytes, packet_get_len(pkt));
struct pcap_pkt *pcap_pkt = (struct pcap_pkt *)packet_get_user_data(pkt);
struct pcap_pkt *pcap_pkt = (struct pcap_pkt *)packet_get_io_ctx(pkt);
if (pcap_pkt)
{
free(pcap_pkt);

View File

@@ -0,0 +1,25 @@
#ifndef _DUMPFILE_IO_H
#define _DUMPFILE_IO_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include "packet_io.h"
struct dumpfile_io;
struct dumpfile_io *dumpfile_io_new(const char *directory, uint8_t nr_threads);
void dumpfile_io_free(struct dumpfile_io *handle);
struct packet_stat *dumpfile_io_stat(struct dumpfile_io *handle);
int dumpfile_io_init(struct dumpfile_io *handle, uint16_t thr_idx);
int dumpfile_io_ingress(struct dumpfile_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts);
void dumpfile_io_egress(struct dumpfile_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts);
void dumpfile_io_drop(struct dumpfile_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts);
#ifdef __cpluscplus
}
#endif
#endif

243
src/packet_io/marsio_io.cpp Normal file
View File

@@ -0,0 +1,243 @@
#include <sched.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <netinet/ether.h>
#include "stellar.h"
#include "marsio.h"
#include "packet_private.h"
#include "marsio_io.h"
struct marsio_io
{
struct mr_instance *mr_ins;
struct mr_vdev *mr_dev;
struct mr_sendpath *mr_path;
struct packet_stat stat;
};
/******************************************************************************
* Private API
******************************************************************************/
static int is_keepalive_packet(const char *data, int len)
{
if (data == NULL || len < (int)(sizeof(struct ethhdr)))
{
return 0;
}
struct ethhdr *eth_hdr = (struct ethhdr *)data;
if (eth_hdr->h_proto == 0xAAAA)
{
return 1;
}
else
{
return 0;
}
}
/******************************************************************************
* Public API
******************************************************************************/
struct marsio_io *marsio_io_new(const char *app_symbol, const char *dev_symbol, uint16_t *cpu_mask, uint8_t nr_threads)
{
int opt = 1;
cpu_set_t coremask;
CPU_ZERO(&coremask);
for (uint8_t i = 0; i < nr_threads; i++)
{
CPU_SET(cpu_mask[i], &coremask);
}
struct marsio_io *handle = (struct marsio_io *)calloc(1, sizeof(struct marsio_io));
if (handle == NULL)
{
PACKET_IO_LOG_ERROR("unable to allocate memory for marsio_io");
return NULL;
}
handle->mr_ins = marsio_create();
if (handle->mr_ins == NULL)
{
PACKET_IO_LOG_ERROR("unable to create marsio instance");
goto error_out;
}
marsio_option_set(handle->mr_ins, MARSIO_OPT_THREAD_MASK_IN_CPUSET, &coremask, sizeof(cpu_set_t));
marsio_option_set(handle->mr_ins, MARSIO_OPT_EXIT_WHEN_ERR, &opt, sizeof(opt));
if (marsio_init(handle->mr_ins, app_symbol) != 0)
{
PACKET_IO_LOG_ERROR("unable to init marsio instance");
goto error_out;
}
handle->mr_dev = marsio_open_device(handle->mr_ins, dev_symbol, nr_threads, nr_threads);
if (handle->mr_dev == NULL)
{
PACKET_IO_LOG_ERROR("unable to open marsio device");
goto error_out;
}
handle->mr_path = marsio_sendpath_create_by_vdev(handle->mr_dev);
if (handle->mr_path == NULL)
{
PACKET_IO_LOG_ERROR("unable to create marsio sendpath");
goto error_out;
}
return handle;
error_out:
marsio_io_free(handle);
return NULL;
}
void marsio_io_free(struct marsio_io *handle)
{
if (handle)
{
if (handle->mr_path)
{
marsio_sendpath_destory(handle->mr_path);
handle->mr_path = NULL;
}
if (handle->mr_dev)
{
marsio_close_device(handle->mr_dev);
handle->mr_dev = NULL;
}
if (handle->mr_ins)
{
marsio_destory(handle->mr_ins);
handle->mr_ins = NULL;
}
free(handle);
handle = NULL;
}
}
struct packet_stat *marsio_io_stat(struct marsio_io *handle)
{
return &handle->stat;
}
int marsio_io_init(struct marsio_io *handle, uint16_t thr_idx)
{
if (marsio_thread_init(handle->mr_ins) != 0)
{
PACKET_IO_LOG_ERROR("unable to init marsio thread");
return -1;
}
return 0;
}
int marsio_io_ingress(struct marsio_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts)
{
struct packet *pkt;
marsio_buff_t *mbuff;
marsio_buff_t *rx_buffs[RX_BURST_MAX];
int nr_recv;
int nr_parsed = 0;
int len;
char *data;
nr_recv = marsio_recv_burst(handle->mr_dev, thr_idx, rx_buffs, MIN(RX_BURST_MAX, nr_pkts));
if (nr_recv <= 0)
{
return 0;
}
for (int i = 0; i < nr_recv; i++)
{
mbuff = rx_buffs[i];
data = marsio_buff_mtod(mbuff);
len = marsio_buff_datalen(mbuff);
ATOMIC_ADD(&handle->stat.dev_rx_pkts, 1);
ATOMIC_ADD(&handle->stat.dev_rx_bytes, len);
if (is_keepalive_packet(data, len))
{
ATOMIC_ADD(&handle->stat.keep_alive_pkts, 1);
ATOMIC_ADD(&handle->stat.keep_alive_bytes, len);
ATOMIC_ADD(&handle->stat.dev_tx_pkts, 1);
ATOMIC_ADD(&handle->stat.dev_tx_bytes, len);
marsio_send_burst(handle->mr_path, thr_idx, &mbuff, 1);
continue;
}
if (marsio_buff_is_ctrlbuf(mbuff))
{
ATOMIC_ADD(&handle->stat.ctrl_rx_pkts, 1);
ATOMIC_ADD(&handle->stat.ctrl_rx_bytes, len);
}
else
{
ATOMIC_ADD(&handle->stat.raw_rx_pkts, 1);
ATOMIC_ADD(&handle->stat.raw_rx_bytes, len);
}
pkt = &pkts[nr_parsed];
packet_parse(pkt, data, len);
packet_set_io_ctx(pkt, mbuff);
packet_set_action(pkt, PACKET_ACTION_FORWARD);
nr_parsed++;
}
return nr_parsed;
}
void marsio_io_egress(struct marsio_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts)
{
struct packet *pkt;
marsio_buff_t *mbuff;
int len;
for (int i = 0; i < nr_pkts; i++)
{
pkt = &pkts[i];
len = packet_get_len(pkt);
ATOMIC_ADD(&handle->stat.dev_tx_pkts, 1);
ATOMIC_ADD(&handle->stat.dev_tx_bytes, len);
mbuff = (marsio_buff_t *)packet_get_io_ctx(pkt);
assert(mbuff != NULL);
if (marsio_buff_is_ctrlbuf(mbuff))
{
ATOMIC_ADD(&handle->stat.ctrl_tx_pkts, 1);
ATOMIC_ADD(&handle->stat.ctrl_tx_bytes, len);
}
else
{
ATOMIC_ADD(&handle->stat.raw_tx_pkts, 1);
ATOMIC_ADD(&handle->stat.raw_tx_bytes, len);
}
marsio_send_burst(handle->mr_path, thr_idx, &mbuff, 1);
packet_free(pkt);
}
}
void marsio_io_drop(struct marsio_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts)
{
struct packet *pkt;
marsio_buff_t *mbuff;
for (int i = 0; i < nr_pkts; i++)
{
pkt = &pkts[i];
mbuff = (marsio_buff_t *)packet_get_io_ctx(pkt);
if (mbuff)
{
marsio_buff_free(handle->mr_ins, &mbuff, 1, 0, thr_idx);
}
packet_free(pkt);
}
}

25
src/packet_io/marsio_io.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef _MARSIO_IO_H
#define _MARSIO_IO_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include "packet_io.h"
struct marsio_io;
struct marsio_io *marsio_io_new(const char *app_symbol, const char *dev_symbol, uint16_t *cpu_mask, uint8_t nr_threads);
void marsio_io_free(struct marsio_io *handle);
struct packet_stat *marsio_io_stat(struct marsio_io *handle);
int marsio_io_init(struct marsio_io *handle, uint16_t thr_idx);
int marsio_io_ingress(struct marsio_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts);
void marsio_io_egress(struct marsio_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts);
void marsio_io_drop(struct marsio_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts);
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -1,129 +1,119 @@
#include <stdlib.h>
#include <string.h>
#include "packet_io.h"
#include "packet_io_marsio.h"
#include "packet_io_dumpfile.h"
typedef void *on_new(void *options);
typedef void on_free(void *handle);
typedef void *on_stat(void *handle);
typedef int on_init(void *handle, uint16_t thread_id);
typedef int on_recv(void *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
typedef void on_send(void *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
typedef void on_drop(void *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
typedef void on_inject(void *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
#include "marsio_io.h"
#include "dumpfile_io.h"
struct packet_io
{
void *handle;
on_new *new_func;
on_free *free_func;
on_stat *stat_func;
on_init *init_func;
on_recv *recv_func;
on_send *send_func;
on_drop *drop_func;
on_inject *inject_func;
enum packet_io_mode mode;
struct marsio_io *marsio;
struct dumpfile_io *dumpfile;
};
struct packet_io *packet_io_new(struct packet_io_options *opts)
{
struct packet_io *handle = (struct packet_io *)calloc(1, sizeof(struct packet_io));
if (handle == NULL)
struct packet_io *packet_io = (struct packet_io *)calloc(1, sizeof(struct packet_io));
if (packet_io == NULL)
{
PACKET_IO_LOG_ERROR("unable to alloc packet io");
return NULL;
}
struct packet_io_marsio_options opts_marsio;
struct packet_io_dumpfile_options opts_dumpfile;
void *opts_ptr = NULL;
packet_io->mode = opts->mode;
if (opts->mode == PACKET_IO_MARSIO)
{
strncpy(opts_marsio.app_symbol, opts->app_symbol, sizeof(opts_marsio.app_symbol));
strncpy(opts_marsio.dev_symbol, opts->dev_symbol, sizeof(opts_marsio.dev_symbol));
memcpy(opts_marsio.cpu_mask, opts->cpu_mask, sizeof(opts_marsio.cpu_mask));
opts_marsio.nr_threads = opts->nr_threads;
opts_ptr = &opts_marsio;
handle->new_func = (on_new *)packet_io_marsio_new;
handle->free_func = (on_free *)packet_io_marsio_free;
handle->stat_func = (on_stat *)packet_io_marsio_get_stat;
handle->init_func = (on_init *)packet_io_marsio_init;
handle->recv_func = (on_recv *)packet_io_marsio_ingress;
handle->send_func = (on_send *)packet_io_marsio_egress;
handle->drop_func = (on_drop *)packet_io_marsio_drop;
handle->inject_func = (on_inject *)packet_io_marsio_inject;
packet_io->marsio = marsio_io_new(opts->app_symbol, opts->dev_symbol, opts->cpu_mask, opts->nr_threads);
}
else
{
strncpy(opts_dumpfile.dumpfile_dir, opts->dumpfile_dir, sizeof(opts_dumpfile.dumpfile_dir));
opts_dumpfile.nr_threads = opts->nr_threads;
opts_ptr = &opts_dumpfile;
handle->new_func = (on_new *)packet_io_dumpfile_new;
handle->free_func = (on_free *)packet_io_dumpfile_free;
handle->stat_func = (on_stat *)packet_io_dumpfile_get_stat;
handle->init_func = (on_init *)packet_io_dumpfile_init;
handle->recv_func = (on_recv *)packet_io_dumpfile_ingress;
handle->send_func = (on_send *)packet_io_dumpfile_egress;
handle->drop_func = (on_drop *)packet_io_dumpfile_drop;
handle->inject_func = (on_inject *)packet_io_dumpfile_inject;
packet_io->dumpfile = dumpfile_io_new(opts->dumpfile_dir, opts->nr_threads);
}
handle->handle = handle->new_func(opts_ptr);
if (handle->handle == NULL)
if (packet_io->marsio == NULL && packet_io->dumpfile == NULL)
{
goto error_out;
}
return handle;
return packet_io;
error_out:
packet_io_free(handle);
packet_io_free(packet_io);
return NULL;
}
void packet_io_free(struct packet_io *handle)
void packet_io_free(struct packet_io *packet_io)
{
if (handle)
if (packet_io)
{
handle->free_func(handle->handle);
free(handle);
handle = NULL;
if (packet_io->mode == PACKET_IO_MARSIO)
{
marsio_io_free(packet_io->marsio);
}
else
{
dumpfile_io_free(packet_io->dumpfile);
}
free(packet_io);
packet_io = NULL;
}
}
struct packet_io_stat *packet_io_get_stat(struct packet_io *handle)
struct packet_stat *packet_io_stat(struct packet_io *packet_io)
{
return (struct packet_io_stat *)handle->stat_func(handle->handle);
if (packet_io->mode == PACKET_IO_MARSIO)
{
return marsio_io_stat(packet_io->marsio);
}
else
{
return dumpfile_io_stat(packet_io->dumpfile);
}
}
// return 0: success
// return -1: failed
int packet_io_init(struct packet_io *handle, uint16_t thread_id)
int packet_io_init(struct packet_io *packet_io, uint16_t thr_idx)
{
return handle->init_func(handle->handle, thread_id);
if (packet_io->mode == PACKET_IO_MARSIO)
{
return marsio_io_init(packet_io->marsio, thr_idx);
}
else
{
return dumpfile_io_init(packet_io->dumpfile, thr_idx);
}
}
// return number of packets received
int packet_io_ingress(struct packet_io *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts)
int packet_io_ingress(struct packet_io *packet_io, uint16_t thr_idx, struct packet *pkts, int nr_pkts)
{
return handle->recv_func(handle->handle, thread_id, pkts, nr_pkts);
if (packet_io->mode == PACKET_IO_MARSIO)
{
return marsio_io_ingress(packet_io->marsio, thr_idx, pkts, nr_pkts);
}
else
{
return dumpfile_io_ingress(packet_io->dumpfile, thr_idx, pkts, nr_pkts);
}
}
void packet_io_egress(struct packet_io *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts)
void packet_io_egress(struct packet_io *packet_io, uint16_t thr_idx, struct packet *pkts, int nr_pkts)
{
handle->send_func(handle->handle, thread_id, pkts, nr_pkts);
if (packet_io->mode == PACKET_IO_MARSIO)
{
marsio_io_egress(packet_io->marsio, thr_idx, pkts, nr_pkts);
}
else
{
dumpfile_io_egress(packet_io->dumpfile, thr_idx, pkts, nr_pkts);
}
}
void packet_io_drop(struct packet_io *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts)
void packet_io_drop(struct packet_io *packet_io, uint16_t thr_idx, struct packet *pkts, int nr_pkts)
{
handle->drop_func(handle->handle, thread_id, pkts, nr_pkts);
}
void packet_io_inject(struct packet_io *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts)
{
handle->inject_func(handle->handle, thread_id, pkts, nr_pkts);
if (packet_io->mode == PACKET_IO_MARSIO)
{
marsio_io_drop(packet_io->marsio, thr_idx, pkts, nr_pkts);
}
else
{
dumpfile_io_drop(packet_io->dumpfile, thr_idx, pkts, nr_pkts);
}
}

View File

@@ -6,29 +6,40 @@ extern "C"
{
#endif
#include "packet_private.h"
#include "log.h"
#include "packet.h"
#include "stellar.h"
#define PACKET_IO_LOG_STATE(format, ...) LOG_STATE("packet_io", format, ##__VA_ARGS__)
#define PACKET_IO_LOG_ERROR(format, ...) LOG_ERROR("packet_io", format, ##__VA_ARGS__)
#define PACKET_IO_LOG_DEBUG(format, ...) LOG_DEBUG("packet_io", format, ##__VA_ARGS__)
struct packet_io_stat
struct packet_stat
{
uint64_t rx_pkts;
uint64_t tx_pkts;
// device packet
uint64_t dev_rx_pkts;
uint64_t dev_rx_bytes;
uint64_t rx_bytes;
uint64_t tx_bytes;
uint64_t dev_tx_pkts;
uint64_t dev_tx_bytes;
uint64_t keepalive_pkts;
uint64_t keepalive_bytes;
// keep-alive packet
uint64_t keep_alive_pkts;
uint64_t keep_alive_bytes;
uint64_t drop_pkts;
uint64_t drop_bytes;
// raw packet
uint64_t raw_rx_pkts;
uint64_t raw_rx_bytes;
uint64_t inject_pkts;
uint64_t inject_bytes;
uint64_t raw_tx_pkts;
uint64_t raw_tx_bytes;
// ctrl packet
uint64_t ctrl_rx_pkts;
uint64_t ctrl_rx_bytes;
uint64_t ctrl_tx_pkts;
uint64_t ctrl_tx_bytes;
};
enum packet_io_mode
@@ -54,19 +65,13 @@ struct packet_io_options
struct packet_io;
struct packet_io *packet_io_new(struct packet_io_options *opts);
void packet_io_free(struct packet_io *handle);
struct packet_io_stat *packet_io_get_stat(struct packet_io *handle);
void packet_io_free(struct packet_io *packet_io);
struct packet_stat *packet_io_stat(struct packet_io *packet_io);
// TODO performance optimization egress for multi-packet
// return 0: success
// return -1: failed
int packet_io_init(struct packet_io *handle, uint16_t thread_id);
// return number of packets received
int packet_io_ingress(struct packet_io *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
void packet_io_egress(struct packet_io *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
void packet_io_drop(struct packet_io *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
void packet_io_inject(struct packet_io *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
int packet_io_init(struct packet_io *packet_io, uint16_t thr_idx);
int packet_io_ingress(struct packet_io *packet_io, uint16_t thr_idx, struct packet *pkts, int nr_pkts);
void packet_io_egress(struct packet_io *packet_io, uint16_t thr_idx, struct packet *pkts, int nr_pkts);
void packet_io_drop(struct packet_io *packet_io, uint16_t thr_idx, struct packet *pkts, int nr_pkts);
#ifdef __cpluscplus
}

View File

@@ -1,36 +0,0 @@
#ifndef _PACKET_IO_DUMPFILE_H
#define _PACKET_IO_DUMPFILE_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include "packet_private.h"
struct packet_io_dumpfile_options
{
char dumpfile_dir[256];
uint8_t nr_threads;
};
struct packet_io_dumpfile;
struct packet_io_dumpfile *packet_io_dumpfile_new(struct packet_io_dumpfile_options *opts);
void packet_io_dumpfile_free(struct packet_io_dumpfile *handle);
struct packet_io_stat *packet_io_dumpfile_get_stat(struct packet_io_dumpfile *handle);
// return 0: success
// return -1: failed
int packet_io_dumpfile_init(struct packet_io_dumpfile *handle, uint16_t thread_id);
// return number of packets received
int packet_io_dumpfile_ingress(struct packet_io_dumpfile *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
void packet_io_dumpfile_egress(struct packet_io_dumpfile *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
void packet_io_dumpfile_drop(struct packet_io_dumpfile *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
void packet_io_dumpfile_inject(struct packet_io_dumpfile *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -1,285 +0,0 @@
#include <sched.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <netinet/ether.h>
#include "stellar.h"
#include "marsio.h"
#include "packet_private.h"
#include "packet_io.h"
#include "packet_io_marsio.h"
struct packet_io_marsio
{
struct mr_instance *mr_ins;
struct mr_vdev *mr_dev;
struct mr_sendpath *mr_path;
struct packet_io_stat stat;
};
/******************************************************************************
* Private API
******************************************************************************/
static void metadata_to_packet(marsio_buff_t *mbuff, struct packet *pkt)
{
struct metadata *meta = &pkt->meta;
packet_set_user_data(pkt, mbuff);
meta->sid.used = marsio_buff_get_sid_list(mbuff, meta->sid.list, MAX_SID_NUM);
meta->route.len = marsio_buff_get_metadata(mbuff, MR_BUFF_ROUTE_CTX, meta->route.data, MAX_ROUTE_LEN);
marsio_buff_get_metadata(mbuff, MR_BUFF_SESSION_ID, &(meta->session_id), sizeof(meta->session_id));
marsio_buff_get_metadata(mbuff, MR_BUFF_DIR, &(meta->direction), sizeof(meta->direction));
packet_set_type(pkt, marsio_buff_is_ctrlbuf(mbuff) ? PACKET_TYPE_CTRL : PACKET_TYPE_DATA);
packet_set_action(pkt, PACKET_ACTION_FORWARD);
}
static void metadata_to_mbuff(marsio_buff_t *mbuff, struct packet *pkt)
{
struct metadata *meta = &pkt->meta;
marsio_buff_set_sid_list(mbuff, meta->sid.list, meta->sid.used);
marsio_buff_set_metadata(mbuff, MR_BUFF_ROUTE_CTX, meta->route.data, meta->route.len);
marsio_buff_set_metadata(mbuff, MR_BUFF_SESSION_ID, &(meta->session_id), sizeof(meta->session_id));
marsio_buff_set_metadata(mbuff, MR_BUFF_DIR, &(meta->direction), sizeof(meta->direction));
if (packet_get_type(pkt) == PACKET_TYPE_CTRL)
{
marsio_buff_set_ctrlbuf(mbuff);
}
}
static int is_keepalive_packet(const char *data, int len)
{
if (data == NULL || len < (int)(sizeof(struct ethhdr)))
{
return 0;
}
struct ethhdr *eth_hdr = (struct ethhdr *)data;
if (eth_hdr->h_proto == 0xAAAA)
{
return 1;
}
else
{
return 0;
}
}
/******************************************************************************
* Public API
******************************************************************************/
struct packet_io_marsio *packet_io_marsio_new(struct packet_io_marsio_options *opts)
{
int opt = 1;
cpu_set_t coremask;
CPU_ZERO(&coremask);
for (uint8_t i = 0; i < opts->nr_threads; i++)
{
CPU_SET(opts->cpu_mask[i], &coremask);
}
struct packet_io_marsio *handle = (struct packet_io_marsio *)calloc(1, sizeof(struct packet_io_marsio));
if (handle == NULL)
{
PACKET_IO_LOG_ERROR("unable to allocate memory for packet_io_marsio");
return NULL;
}
handle->mr_ins = marsio_create();
if (handle->mr_ins == NULL)
{
PACKET_IO_LOG_ERROR("unable to create marsio instance");
goto error_out;
}
marsio_option_set(handle->mr_ins, MARSIO_OPT_THREAD_MASK_IN_CPUSET, &coremask, sizeof(coremask));
marsio_option_set(handle->mr_ins, MARSIO_OPT_EXIT_WHEN_ERR, &opt, sizeof(opt));
if (marsio_init(handle->mr_ins, opts->app_symbol) != 0)
{
PACKET_IO_LOG_ERROR("unable to init marsio instance");
goto error_out;
}
handle->mr_dev = marsio_open_device(handle->mr_ins, opts->dev_symbol, opts->nr_threads, opts->nr_threads);
if (handle->mr_dev == NULL)
{
PACKET_IO_LOG_ERROR("unable to open marsio device");
goto error_out;
}
handle->mr_path = marsio_sendpath_create_by_vdev(handle->mr_dev);
if (handle->mr_path == NULL)
{
PACKET_IO_LOG_ERROR("unable to create marsio sendpath");
goto error_out;
}
return handle;
error_out:
packet_io_marsio_free(handle);
return NULL;
}
void packet_io_marsio_free(struct packet_io_marsio *handle)
{
if (handle)
{
if (handle->mr_path)
{
marsio_sendpath_destory(handle->mr_path);
handle->mr_path = NULL;
}
if (handle->mr_dev)
{
marsio_close_device(handle->mr_dev);
handle->mr_dev = NULL;
}
if (handle->mr_ins)
{
marsio_destory(handle->mr_ins);
handle->mr_ins = NULL;
}
free(handle);
handle = NULL;
}
}
struct packet_io_stat *packet_io_marsio_get_stat(struct packet_io_marsio *handle)
{
return &handle->stat;
}
int packet_io_marsio_init(struct packet_io_marsio *handle, uint16_t thread_id)
{
if (marsio_thread_init(handle->mr_ins) != 0)
{
PACKET_IO_LOG_ERROR("unable to init marsio thread");
return -1;
}
return 0;
}
int packet_io_marsio_ingress(struct packet_io_marsio *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts)
{
marsio_buff_t *rx_buff;
marsio_buff_t *rx_buffs[RX_BURST_MAX];
int nr_recv;
int nr_parsed = 0;
int raw_len;
char *raw_data;
nr_recv = marsio_recv_burst(handle->mr_dev, thread_id, rx_buffs, MIN(RX_BURST_MAX, nr_pkts));
if (nr_recv <= 0)
{
return 0;
}
for (int i = 0; i < nr_recv; i++)
{
rx_buff = rx_buffs[i];
raw_data = marsio_buff_mtod(rx_buff);
raw_len = marsio_buff_datalen(rx_buff);
ATOMIC_ADD(&handle->stat.rx_pkts, 1);
ATOMIC_ADD(&handle->stat.rx_bytes, raw_len);
if (is_keepalive_packet(raw_data, raw_len))
{
ATOMIC_ADD(&handle->stat.keepalive_pkts, 1);
ATOMIC_ADD(&handle->stat.keepalive_bytes, raw_len);
ATOMIC_ADD(&handle->stat.tx_pkts, 1);
ATOMIC_ADD(&handle->stat.tx_bytes, raw_len);
marsio_send_burst(handle->mr_path, thread_id, &rx_buff, 1);
continue;
}
packet_parse(&pkts[nr_parsed], raw_data, raw_len);
metadata_to_packet(rx_buff, &pkts[nr_parsed++]);
}
return nr_parsed;
}
void packet_io_marsio_egress(struct packet_io_marsio *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts)
{
struct packet *pkt;
struct metadata *meta;
marsio_buff_t *tx_buff;
for (int i = 0; i < nr_pkts; i++)
{
pkt = &pkts[i];
ATOMIC_ADD(&handle->stat.tx_pkts, 1);
ATOMIC_ADD(&handle->stat.tx_bytes, packet_get_len(pkt));
// update sid list
tx_buff = (marsio_buff_t *)packet_get_user_data(pkt);
assert(tx_buff != NULL);
meta = &pkt->meta;
marsio_buff_set_sid_list(tx_buff, meta->sid.list, meta->sid.used);
marsio_send_burst(handle->mr_path, thread_id, &tx_buff, 1);
packet_free(pkt);
}
}
void packet_io_marsio_drop(struct packet_io_marsio *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts)
{
struct packet *pkt;
marsio_buff_t *tx_buff;
for (int i = 0; i < nr_pkts; i++)
{
pkt = &pkts[i];
tx_buff = (marsio_buff_t *)packet_get_user_data(pkt);
ATOMIC_ADD(&handle->stat.drop_pkts, 1);
ATOMIC_ADD(&handle->stat.drop_bytes, packet_get_len(pkt));
if (tx_buff)
{
marsio_buff_free(handle->mr_ins, &tx_buff, 1, 0, thread_id);
}
packet_free(pkt);
}
}
void packet_io_marsio_inject(struct packet_io_marsio *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts)
{
struct packet *pkt;
marsio_buff_t *tx_buff;
for (int i = 0; i < nr_pkts; i++)
{
pkt = &pkts[i];
tx_buff = (marsio_buff_t *)packet_get_user_data(pkt);
assert(tx_buff == NULL);
if (marsio_buff_malloc_global(handle->mr_ins, &tx_buff, 1, MARSIO_SOCKET_ID_ANY, MARSIO_LCORE_ID_ANY) < 0)
{
PACKET_IO_LOG_ERROR("unable to alloc tx buffer");
continue;
}
ATOMIC_ADD(&handle->stat.inject_pkts, 1);
ATOMIC_ADD(&handle->stat.inject_bytes, packet_get_len(pkt));
char *dst = marsio_buff_append(tx_buff, packet_get_len(pkt));
memcpy(dst, packet_get_data(pkt), packet_get_len(pkt));
ATOMIC_ADD(&handle->stat.tx_pkts, 1);
ATOMIC_ADD(&handle->stat.tx_bytes, packet_get_len(pkt));
metadata_to_mbuff(tx_buff, pkt);
marsio_send_burst(handle->mr_path, thread_id, &tx_buff, 1);
packet_free(pkt);
}
}

View File

@@ -1,38 +0,0 @@
#ifndef _PACKET_IO_MARSIO_H
#define _PACKET_IO_MARSIO_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include "packet_private.h"
struct packet_io_marsio_options
{
char app_symbol[64];
char dev_symbol[64];
uint8_t nr_threads;
uint16_t cpu_mask[MAX_THREAD_NUM];
};
struct packet_io_marsio;
struct packet_io_marsio *packet_io_marsio_new(struct packet_io_marsio_options *opts);
void packet_io_marsio_free(struct packet_io_marsio *handle);
struct packet_io_stat *packet_io_marsio_get_stat(struct packet_io_marsio *handle);
// return 0: success
// return -1: failed
int packet_io_marsio_init(struct packet_io_marsio *handle, uint16_t thread_id);
// return number of packets received
int packet_io_marsio_ingress(struct packet_io_marsio *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
void packet_io_marsio_egress(struct packet_io_marsio *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
void packet_io_marsio_drop(struct packet_io_marsio *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
void packet_io_marsio_inject(struct packet_io_marsio *handle, uint16_t thread_id, struct packet *pkts, int nr_pkts);
#ifdef __cpluscplus
}
#endif
#endif