summaryrefslogtreecommitdiff
path: root/src/packet_io/packet_io_internal.cpp
diff options
context:
space:
mode:
authorliuwentan <[email protected]>2022-08-18 16:26:00 +0800
committerliuwentan <[email protected]>2022-08-31 22:04:05 +0800
commit90b359ed40368f552ae251daaa82a75ff2b86f3e (patch)
tree10a08333fc75b23dacb507885fbd3f7536b63fc2 /src/packet_io/packet_io_internal.cpp
parent90542cec2d50836b2bba8db39900bff9742b9667 (diff)
[PACKET_IO]format api style
Diffstat (limited to 'src/packet_io/packet_io_internal.cpp')
-rw-r--r--src/packet_io/packet_io_internal.cpp461
1 files changed, 461 insertions, 0 deletions
diff --git a/src/packet_io/packet_io_internal.cpp b/src/packet_io/packet_io_internal.cpp
new file mode 100644
index 0000000..0a9e78e
--- /dev/null
+++ b/src/packet_io/packet_io_internal.cpp
@@ -0,0 +1,461 @@
+/*
+**********************************************************************************************
+* File: packet_io_internal.cpp
+* Description:
+* Authors: Liu WenTan <[email protected]>
+* Date: 2022-07-15
+* Copyright: (c) 2018-2022 Geedge Networks, Inc. All rights reserved.
+***********************************************************************************************
+*/
+
+#include <string.h>
+
+#include "logger.h"
+#include "utils.h"
+#include "util_errors.h"
+#include "packet_io.h"
+#include "packet_io_util.h"
+#include "packet_io_internal.h"
+#include "toml/toml.h"
+#include "./pcap_live_mode/pio_pcap_live.h"
+#include "./pcap_file_mode/pio_pcap_file.h"
+#include "./marsio_mode/pio_marsio.h"
+
+struct packet_io_config g_packet_io_config;
+
+struct pio_device_operations pio_device_ops_array[PACKET_IO_RUN_MODE_MAX] =
+{
+ {
+ .open = pio_pcap_file_device_open,
+ .close = pio_pcap_file_device_close,
+ .recv = pio_pcap_file_device_receive,
+ .send = nullptr,
+ .pkt_free = pio_pcap_file_device_pkt_free,
+ .buff_ctrlzone = pio_pcap_file_device_buff_ctrlzone,
+ .buff_mtod = pio_pcap_file_device_buff_mtod,
+ },
+
+ {
+ .open = pio_pcap_live_device_open,
+ .close = pio_pcap_live_device_close,
+ .recv = pio_pcap_live_device_receive,
+ .send = pio_pcap_live_device_send,
+ .pkt_free = pio_pcap_live_device_pkt_free,
+ .buff_ctrlzone = pio_pcap_live_device_buff_ctrlzone,
+ .buff_mtod = pio_pcap_live_device_buff_mtod,
+ },
+
+ {
+ .open = pio_marsio_device_open,
+ .close = pio_marsio_device_close,
+ .recv = pio_marsio_device_receive,
+ .send = pio_marsio_device_send,
+ .pkt_free = pio_marsio_device_pkt_free,
+ .buff_ctrlzone = pio_marsio_device_buff_ctrlzone,
+ .buff_mtod = pio_marsio_device_buff_mtod,
+ }
+};
+
+struct pio_instance_operations pio_instance_ops_array[PACKET_IO_RUN_MODE_MAX] =
+{
+ {
+ .create = pio_pcap_file_instance_create,
+ .destroy = pio_pcap_file_instance_destroy,
+ },
+
+ {
+ .create = pio_pcap_live_instance_create,
+ .destroy = pio_pcap_live_instance_destroy,
+ },
+
+ {
+ .create = pio_marsio_instance_create,
+ .destroy = pio_marsio_instance_destroy,
+ }
+};
+
+struct packet_io_instance *
+packet_io_instance_create(const char *inst_name, const enum packet_io_run_mode mode)
+{
+ if (nullptr == inst_name || mode < PACKET_IO_RUN_MODE_PCAP_FILE || mode >= PACKET_IO_RUN_MODE_MAX) {
+ return nullptr;
+ }
+
+ struct packet_io_instance *pio_instance = CALLOC(struct packet_io_instance, 1);
+ if (nullptr == pio_instance) {
+ log_error(ST_ERR_MEM_ALLOC, "packet_io instance alloc failed.");
+ return nullptr;
+ }
+
+ ssize_t ret = strncpy_safe(pio_instance->inst_name, inst_name, sizeof(pio_instance->inst_name));
+ if (ret < 0) {
+ log_error(ST_ERR_STR_COPY, "packet_io instance name copy failed.");
+ return nullptr;
+ }
+
+ TAILQ_INIT(&pio_instance->device_queue_head);
+ pio_instance->mode = mode;
+ pio_instance->inst_ops = &pio_instance_ops_array[mode];
+
+ ret = pio_instance->inst_ops->create(pio_instance);
+ if (ret < 0) {
+ log_error(ST_ERR_PIO_INSTANCE, "packet_io instance create failed.");
+ return nullptr;
+ }
+
+ return pio_instance;
+}
+
+static ssize_t toml_parse_table(toml_table_t *table, const char *string_key, const char *file_name, toml_table_t **out)
+{
+ *out = toml_table_in(table, string_key);
+ if (nullptr == *out) {
+ log_error(ST_ERR_PIO_CONFIG, "can't find '%s' section in %s", string_key, file_name);
+ return -1;
+ }
+
+ return 0;
+}
+
+static ssize_t toml_parse_string(toml_table_t *table, const char *string_key, const char *file_name, char *out)
+{
+ toml_datum_t string_val = toml_string_in(table, string_key);
+ if (!string_val.ok) {
+ log_error(ST_ERR_PIO_CONFIG, "can't find '%s' configuration iterm in %s", string_key, file_name);
+ return -1;
+ }
+
+ if (strlen(string_val.u.s) <= 0) {
+ log_error(ST_ERR_PIO_CONFIG, "invalid value for '%s' configuration item in %s", string_key, file_name);
+ FREE(string_val.u.s);
+ return -1;
+ }
+
+ strncpy_safe(out, string_val.u.s, strlen(string_val.u.s));
+ FREE(string_val.u.s);
+
+ return 0;
+}
+
+static ssize_t toml_parse_int(toml_table_t *table, const char *int_key, const char *file_name, int *out)
+{
+ toml_datum_t int_val = toml_int_in(table, int_key);
+ if (!int_val.ok) {
+ log_error(ST_ERR_PIO_CONFIG, "can't find '%s' configuration iterm in %s", int_key, file_name);
+ return -1;
+ }
+ *out = int_val.u.i;
+
+ return 0;
+}
+
+enum packet_io_run_mode pio_run_mode_str2int(const char *mode_str)
+{
+ enum packet_io_run_mode mode_int = PACKET_IO_RUN_MODE_MAX;
+ if (strncmp("PCAP_FILE_MODE", mode_str, strlen(mode_str)) == 0) {
+ mode_int = PACKET_IO_RUN_MODE_PCAP_FILE;
+ } else if (strncmp("PCAP_LIVE_MODE", mode_str, strlen(mode_str)) == 0) {
+ mode_int = PACKET_IO_RUN_MODE_PCAP_LIVE;
+ } else if (strncmp("MARSIO_MODE", mode_str, strlen(mode_str)) == 0) {
+ mode_int = PACKET_IO_RUN_MODE_MARSIO;
+ } else {
+ log_error(ST_ERR_RUN_MODE, "unknown run mode '%s'", mode_str);
+ }
+
+ return mode_int;
+}
+
+static ssize_t toml_parse_pcap_file_mode(toml_table_t *tab, struct packet_io_config *config, const char *file_name)
+{
+ if (toml_parse_string(tab, "PCAP_FILE_PATH", file_name, config->pcap.path) < 0) {
+ log_error(ST_ERR_PIO_CONFIG, "can't parse 'PCAP_FILE_PATH' config iterm in 'PACKET_IO' section of %s", file_name);
+ return -1;
+ }
+
+ if (toml_parse_int(tab, "DELETE_WHEN_DONE", file_name, &config->pcap.should_delete) < 0) {
+ log_notice("can't parse 'DELETE_WHEN_DONE' config iterm in 'PACKET_IO' section of %s", file_name);
+ }
+
+ if (toml_parse_string(tab, "BPF_FILTER", file_name, config->pcap.bpf_string) < 0) {
+ log_notice("can't parse 'BPF_FILTER' config iterm in 'PACKET_IO' section of %s", file_name);
+ }
+
+ return 0;
+}
+
+static ssize_t toml_parse_pcap_live_mode(toml_table_t *tab, struct packet_io_config *config, const char *file_name)
+{
+ toml_array_t *interface_array = nullptr;
+ toml_datum_t interface_str;
+
+ interface_array = toml_array_in(tab, "INTERFACE");
+ if (nullptr == interface_array) {
+ log_error(ST_ERR_PIO_CONFIG, "can't find 'INTERFACE' config iterm in 'PACKET_IO' section of %s", file_name);
+ return -1;
+ }
+
+ for (ssize_t i = 0; i < toml_array_nelem(interface_array); i++) {
+ interface_str = toml_string_at(interface_array, i);
+ if (!interface_str.ok) {
+ log_error(ST_ERR_PIO_CONFIG, "can't parse 'INTERFACE' config iterm in 'PACKET_IO' section of %s", file_name);
+ return -1;
+ }
+
+ strncpy_safe(config->common.dev_name[i], interface_str.u.s, sizeof(config->common.dev_name[i]));
+ config->common.dev_cnt++;
+ }
+
+ if (toml_parse_int(tab, "SNAP_LEN", file_name, &config->pcap.snaplen) < 0) {
+ log_notice("can't parse 'SNAP_LEN' config iterm in 'PACKET_IO' section of %s", file_name);
+ }
+
+ if (toml_parse_int(tab, "PROMISC", file_name, &config->pcap.promisc) < 0) {
+ log_notice("can't parse 'PROMISC' config iterm in 'PACKET_IO' section of %s", file_name);
+ }
+
+ if (toml_parse_string(tab, "BPF_FILTER", file_name, config->pcap.bpf_string) < 0) {
+ log_notice("can't parse 'BPF_FILTER' config iterm in 'PACKET_IO' section of %s", file_name);
+ }
+
+ return 0;
+}
+
+static ssize_t toml_parse_marsio_mode(toml_table_t *tab, struct packet_io_config *config, const char *file_name)
+{
+ toml_array_t *interface_array = nullptr;
+ toml_datum_t interface_str;
+
+ interface_array = toml_array_in(tab, "INTERFACE");
+ if (nullptr == interface_array) {
+ log_error(ST_ERR_PIO_CONFIG, "can't find 'INTERFACE' config iterm in 'PACKET_IO' section of %s", file_name);
+ return -1;
+ }
+
+ for (int i = 0; i < toml_array_nelem(interface_array); i++) {
+ interface_str = toml_string_at(interface_array, i);
+ if (!interface_str.ok) {
+ log_error(ST_ERR_PIO_CONFIG, "can't parse 'INTERFACE' config iterm in 'PACKET_IO' section of %s", file_name);
+ return -1;
+ }
+ strncpy_safe(config->common.dev_name[i], interface_str.u.s, sizeof(config->common.dev_name[i]));
+ config->common.dev_cnt++;
+ }
+
+ return 0;
+}
+
+static ssize_t toml_parse_packet_io_section(toml_table_t *root, struct packet_io_config *config, const char *file_name)
+{
+ toml_table_t *packet_io_section = nullptr;
+
+ if (toml_parse_table(root, "PACKET_IO", file_name, &packet_io_section) < 0) {
+ return -1;
+ }
+
+ char run_mode[STR_MAX_LEN] = {0};
+ if (toml_parse_string(packet_io_section, "RUN_MODE", file_name, run_mode) < 0) {
+ return -1;
+ }
+
+ config->common.mode = pio_run_mode_str2int(run_mode);
+ if (config->common.mode == PACKET_IO_RUN_MODE_MAX) {
+ return -1;
+ }
+
+ if (toml_parse_int(packet_io_section, "WORKER_THREAD_NUM", file_name, &config->common.thread_num) < 0) {
+ return -1;
+ }
+
+ if (config->common.mode == PACKET_IO_RUN_MODE_PCAP_FILE) {
+ if (toml_parse_pcap_file_mode(packet_io_section, config, file_name) < 0) {
+ return -1;
+ }
+ } else if (config->common.mode == PACKET_IO_RUN_MODE_PCAP_LIVE) {
+ if (toml_parse_pcap_live_mode(packet_io_section, config, file_name) < 0) {
+ return -1;
+ }
+ } else {
+ if (toml_parse_marsio_mode(packet_io_section, config, file_name) < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+ssize_t packet_io_config_parse(struct packet_io_config *config, const char *file_name)
+{
+ char errbuf[BUFSIZ] = {0};
+
+ FILE *fp = fopen(file_name, "r");
+ if (nullptr == fp) {
+ log_error(ST_ERR_FOPEN, "open packet_io config file failed.");
+ return -1;
+ }
+
+ toml_table_t *root = nullptr;
+ root = toml_parse_file(fp, errbuf, sizeof(errbuf));
+ if (nullptr == root) {
+ goto err;
+ }
+
+ if (toml_parse_packet_io_section(root, config, file_name) < 0) {
+ goto err;
+ }
+
+ toml_free(root);
+ fclose(fp);
+ log_info("packet_io config file '%s' parse success", file_name);
+
+ return 0;
+err:
+ if (root) {
+ toml_free(root);
+ }
+
+ if (fp) {
+ fclose(fp);
+ fp = nullptr;
+ }
+
+ return -1;
+}
+
+struct packet_io_device *
+packet_io_device_open(struct packet_io_instance *pinst, const char *dev_name, size_t nr_rxq, size_t nr_txq)
+{
+ if (nullptr == pinst || nullptr == dev_name) {
+ return nullptr;
+ }
+
+ struct packet_io_device *pdev = CALLOC(struct packet_io_device, 1);
+ if (nullptr == pdev) {
+ log_error(ST_ERR_MEM_ALLOC, "packet_io device alloc failed.");
+ return nullptr;
+ }
+
+ ssize_t ret = strncpy_safe(pdev->dev_name, dev_name, sizeof(pdev->dev_name));
+ if (ret < 0) {
+ log_error(ST_ERR_STR_COPY, "packet_io device name copy failed.");
+ return nullptr;
+ }
+
+ pdev->rxq_num = nr_rxq;
+ pdev->txq_num = nr_txq;
+ pdev->ppio_inst = pinst;
+ pdev->dev_ops = &pio_device_ops_array[pinst->mode];
+
+ TAILQ_INSERT_TAIL(&pinst->device_queue_head, pdev, next);
+ pinst->dev_cnt++;
+
+ ret = pdev->dev_ops->open(pdev);
+ if (ret < 0) {
+ log_error(ST_ERR_PIO_DEVICE, "packet_io device open failed.");
+ return nullptr;
+ }
+
+ return pdev;
+}
+
+void packet_io_device_close(struct packet_io_device *pdev)
+{
+ ssize_t ret = pdev->dev_ops->close(pdev);
+ if (ret < 0) {
+ log_error(ST_ERR_PIO_DEVICE, "packet_io device close failed.");
+ return;
+ }
+
+ struct packet_io_device *node = nullptr;
+ struct packet_io_device *next_node = nullptr;
+ for (node = TAILQ_FIRST(&pdev->ppio_inst->device_queue_head); node != nullptr; node = next_node) {
+ next_node = TAILQ_NEXT(node, next);
+ if (node == pdev) {
+ pdev->ppio_inst->dev_cnt--;
+ /* Remove the item from the tail queue. */
+ TAILQ_REMOVE(&pdev->ppio_inst->device_queue_head, node, next);
+
+ /* Free the item as we don't need it anymore. */
+ FREE(node);
+ break;
+ }
+ }
+}
+
+struct packet_io_instance *
+packet_io_init(const char *instance_name, const char *file_name, struct packet_io_device *devices[], size_t *dev_num)
+{
+ /* parse config file */
+ memset(&g_packet_io_config, 0, sizeof(g_packet_io_config));
+ ssize_t ret = packet_io_config_parse(&g_packet_io_config, file_name);
+ if (ret < 0) {
+ log_error(ST_ERR_PIO_CONFIG, "packet_io config parse failed.");
+ return nullptr;
+ }
+
+ struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", g_packet_io_config.common.mode);
+ if (nullptr == ppio_inst) {
+ log_error(ST_ERR_PIO_INSTANCE, "packet_io instance init failed.");
+ return nullptr;
+ }
+
+ size_t thread_num = g_packet_io_config.common.thread_num;
+ if (g_packet_io_config.common.mode == PACKET_IO_RUN_MODE_PCAP_FILE) {
+ devices[0] = packet_io_device_open(ppio_inst, g_packet_io_config.pcap.path, thread_num, thread_num);
+ if (nullptr == devices[0]) {
+ log_error(ST_ERR_PIO_DEVICE, "packet_io device '%s' open failed.", g_packet_io_config.pcap.path);
+ return nullptr;
+ }
+ *dev_num = 1;
+ } else {
+ *dev_num = g_packet_io_config.common.dev_cnt;
+ for (size_t i = 0; i < *dev_num; i++) {
+ devices[i] = packet_io_device_open(ppio_inst, g_packet_io_config.common.dev_name[i], thread_num, thread_num);
+ if (nullptr == devices[i]) {
+ log_error(ST_ERR_PIO_DEVICE, "packet_io device '%s' open failed.", g_packet_io_config.common.dev_name[i]);
+ return nullptr;
+ }
+ }
+ }
+
+ return ppio_inst;
+}
+
+void packet_io_fini(struct packet_io_instance *pinst)
+{
+ packet_io_instance_destroy(pinst);
+}
+
+void packet_io_instance_destroy(struct packet_io_instance *pinst)
+{
+ if (nullptr == pinst) {
+ return;
+ }
+
+ pinst->inst_ops->destroy(pinst);
+ FREE(pinst);
+}
+
+ssize_t packet_io_device_rx(struct packet_io_device *pdev, uint32_t rxq_id, struct stellar_packet **pkts, size_t nr_pkts)
+{
+ return pdev->dev_ops->recv(pdev, rxq_id, pkts, nr_pkts);
+}
+
+ssize_t packet_io_device_tx(struct packet_io_device *pdev, uint32_t txq_id, struct stellar_packet **pkts, size_t nr_pkts)
+{
+ return pdev->dev_ops->send(pdev, txq_id, pkts, nr_pkts);
+}
+
+void packet_io_pkts_free(struct packet_io_device *pdev, uint32_t qid, struct stellar_packet **pkts, size_t nr_pkts)
+{
+ return pdev->dev_ops->pkt_free(pdev, qid, pkts, nr_pkts);
+}
+
+char *get_stellar_packet_ctrlzone(struct stellar_packet *p, size_t *ctrlzone_len)
+{
+ return pio_device_ops_array[g_packet_io_config.common.mode].buff_ctrlzone(p, ctrlzone_len);
+}
+
+char *get_stellar_packet_data(struct stellar_packet *p, size_t *data_len)
+{
+ return pio_device_ops_array[g_packet_io_config.common.mode].buff_mtod(p, data_len);
+} \ No newline at end of file