diff options
Diffstat (limited to 'platform/src/packet_adapter.cpp')
| -rw-r--r-- | platform/src/packet_adapter.cpp | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/platform/src/packet_adapter.cpp b/platform/src/packet_adapter.cpp new file mode 100644 index 0000000..6fa94f0 --- /dev/null +++ b/platform/src/packet_adapter.cpp @@ -0,0 +1,240 @@ +#include <errno.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <pthread.h> +#include <sys/prctl.h> + +#include "log.h" +#include "system.h" +#include "packet_io.h" +#include "packet_stat.h" +#include "packet_handle.h" + +#define LOG_MAIN "PacketAdapter" + +#ifdef GIT_VERSION +static __attribute__((__used__)) const char *Packet_Adapter_Version = GIT_VERSION; +#else +static __attribute__((__used__)) const char *Packet_Adapter_Version = "Unknown"; +#endif + +/****************************************************************************** + * Struct + ******************************************************************************/ + +struct thread +{ + int index; + pthread_t tid; + struct runtime_ctx *runtime; +}; + +struct runtime_ctx +{ + int enable_debug; + int need_stop; + + struct metrics metrics; + struct packet_io *handle; + struct packet_stat *stat; + struct thread threads[MAX_THREAD_NUM]; +}; + +/****************************************************************************** + * Static + ******************************************************************************/ + +struct runtime_ctx static_runtime_ctx = {0}; +struct runtime_ctx *runtime = &static_runtime_ctx; + +/****************************************************************************** + * API + ******************************************************************************/ + +static enum action packet_handle_callback(const char *data, int len, void *args) +{ + struct metrics *metrics = (struct metrics *)args; + packet_handle(data, len, metrics); + + return ACTION_BYPASS; +} + +static void *worker_thread_cycle(void *arg) +{ + struct thread *thread = (struct thread *)arg; + struct runtime_ctx *runtime = thread->runtime; + struct packet_io *handle = runtime->handle; + + char thread_name[16]; + snprintf(thread_name, sizeof(thread_name), "pkt-adapter:%d", thread->index); + prctl(PR_SET_NAME, (unsigned long long)thread_name, NULL, NULL, NULL); + + if (packet_io_thread_init(handle, thread->index) != 0) + { + goto error_out; + } + + LOG_INFO("%s: worker thread %d is running", LOG_MAIN, thread->index); + while (!runtime->need_stop) + { + if (packet_io_thread_polling(handle, thread->index) == 0) + { + packet_io_thread_wait(handle, thread->index, -1); + } + } + +error_out: + LOG_ERROR("%s: worker thread %d exiting", LOG_MAIN, thread->index); + return (void *)NULL; +} + +static void signal_handler(int signo) +{ + if (signo == SIGUSR1) + { + runtime->enable_debug = 1; + LOG_ERROR("%s: received SIGUSR1, enable debug", LOG_MAIN); + } + if (signo == SIGUSR2) + { + runtime->enable_debug = 0; + LOG_ERROR("%s: received SIGUSR2, disable debug", LOG_MAIN); + } + if (signo == SIGHUP) + { + LOG_RELOAD(); + LOG_ERROR("%s: received SIGHUP, reload zlog.conf", LOG_MAIN); + } + if (signo == SIGINT) + { + runtime->need_stop = 1; + LOG_ERROR("%s: received SIGINT, exit !!!", LOG_MAIN); + } + if (signo == SIGQUIT) + { + runtime->need_stop = 1; + LOG_ERROR("%s: received SIGQUIT, exit !!!", LOG_MAIN); + } + if (signo == SIGTERM) + { + runtime->need_stop = 1; + LOG_ERROR("%s: received SIGTERM, exit !!!", LOG_MAIN); + } +} + +static void usage(char *cmd) +{ + fprintf(stderr, "USAGE: %s [OPTIONS]\n", cmd); + fprintf(stderr, " -v -- show version\n"); + fprintf(stderr, " -d -- run daemon\n"); + fprintf(stderr, " -h -- show help\n"); + fprintf(stderr, "Signal: \n"); + fprintf(stderr, " kill -s SIGUSR1 `pidof %s` -- enable debug\n", cmd); + fprintf(stderr, " kill -s SIGUSR2 `pidof %s` -- disable debug\n", cmd); +} + +int main(int argc, char **argv) +{ + int opt; + const char *profile = "./conf/packet_adapter.conf"; + + if (LOG_INIT("./conf/zlog.conf") == -1) + { + return -1; + } + + while ((opt = getopt(argc, argv, "vdh")) != -1) + { + switch (opt) + { + case 'v': + fprintf(stderr, "Packet Adapter Version: %s\n", Packet_Adapter_Version); + return 0; + case 'd': + run_daemon(); + break; + case 'h': /* fall through */ + default: + usage(argv[0]); + return 0; + } + } + + LOG_ERROR("%s: TSG Packet Adapter Engine, Version: %s Start ...", LOG_MAIN, Packet_Adapter_Version); + + if (signal(SIGUSR1, signal_handler) == SIG_ERR) + { + LOG_ERROR("%s: failed at signal(SIGUSR1), %d: %s", LOG_MAIN, errno, strerror(errno)); + goto error; + } + if (signal(SIGUSR2, signal_handler) == SIG_ERR) + { + LOG_ERROR("%s: failed at signal(SIGUSR2), %d: %s", LOG_MAIN, errno, strerror(errno)); + goto error; + } + if (signal(SIGHUP, signal_handler) == SIG_ERR) + { + LOG_ERROR("%s: failed at signal(SIGHUP), %d: %s", LOG_MAIN, errno, strerror(errno)); + goto error; + } + if (signal(SIGINT, signal_handler) == SIG_ERR) + { + LOG_ERROR("%s: failed at signal(SIGINT), %d: %s", LOG_MAIN, errno, strerror(errno)); + goto error; + } + if (signal(SIGQUIT, signal_handler) == SIG_ERR) + { + LOG_ERROR("%s: failed at signal(SIGQUIT), %d: %s", LOG_MAIN, errno, strerror(errno)); + goto error; + } + + if (signal(SIGTERM, signal_handler) == SIG_ERR) + { + LOG_ERROR("%s: failed at signal(SIGTERM), %d: %s", LOG_MAIN, errno, strerror(errno)); + goto error; + } + + runtime->stat = packet_stat_create(profile); + if (runtime->stat == NULL) + { + goto error; + } + + runtime->handle = packet_io_create(profile); + if (runtime->handle == NULL) + { + goto error; + } + + packet_io_set_callback(runtime->handle, packet_handle_callback, &runtime->metrics); + for (int i = 0; i < packet_io_thread_number(runtime->handle); i++) + { + runtime->threads[i].tid = 0; + runtime->threads[i].index = i; + runtime->threads[i].runtime = runtime; + } + + for (int i = 0; i < packet_io_thread_number(runtime->handle); i++) + { + struct thread *thread = &runtime->threads[i]; + if (pthread_create(&thread->tid, NULL, worker_thread_cycle, (void *)thread) < 0) + { + LOG_ERROR("%s: unable to create worker thread %d, error %d: %s", LOG_MAIN, i, errno, strerror(errno)); + runtime->need_stop = 1; + } + } + + while (!runtime->need_stop) + { + packet_stat_output(runtime->stat, &runtime->metrics); + sleep(packet_stat_cycle(runtime->stat)); + } + +error: + packet_stat_destory(runtime->stat); + packet_io_destory(runtime->handle); + LOG_CLOSE(); + + return 0; +}
\ No newline at end of file |
