diff options
| author | liuwentan <[email protected]> | 2022-08-18 16:26:00 +0800 |
|---|---|---|
| committer | liuwentan <[email protected]> | 2022-08-31 22:04:05 +0800 |
| commit | 90b359ed40368f552ae251daaa82a75ff2b86f3e (patch) | |
| tree | 10a08333fc75b23dacb507885fbd3f7536b63fc2 /src/packet_io/packet_io_internal.cpp | |
| parent | 90542cec2d50836b2bba8db39900bff9742b9667 (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.cpp | 461 |
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 |
