From a7d86761f9c66eb6fb6d13b77e753d6c42b90e12 Mon Sep 17 00:00:00 2001 From: Zengruan Ye Date: Tue, 16 Jul 2019 00:07:36 +0800 Subject: [PATCH 6/6] feature: irqbalance: Add ability for socket communication This will be used with user interface and also can be used as API for users to create their own scripts on top of. The socket communication can be used for receiving data about IRQs-to-CPUs assignments and setup, as well as setting some options during runtime. Socket address: /var/run/uvp_irqbalance.socket Data to send to socket: settings sleep : set new sleep interval value settings cpus ... : ban listed CPUs from IRQ handling (old values are forgotten, not added to) settings ban irqs ... : ban listed IRQs from balancing (old values are forgotten, not added to) Signed-off-by: Xu Yandong --- Makefile.am | 6 +- classify.c | 20 ++- cputree.c | 5 +- irqbalance.c | 164 ++---------------------- irqbalance.h | 2 + sockapi.c | 400 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sockapi.h | 18 +++ 7 files changed, 452 insertions(+), 163 deletions(-) create mode 100644 sockapi.c create mode 100644 sockapi.h diff --git a/Makefile.am b/Makefile.am index abf1e8d..62ac482 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,7 +30,7 @@ UI_DIR = ui AM_CFLAGS = $(LIBCAP_NG_CFLAGS) $(GLIB2_CFLAGS) AM_CPPFLAGS = -I${top_srcdir} -W -Wall -Wshadow -Wformat -Wundef -D_GNU_SOURCE noinst_HEADERS = bitmap.h constants.h cpumask.h irqbalance.h non-atomic.h \ - types.h $(UI_DIR)/helpers.h $(UI_DIR)/irqbalance-ui.h $(UI_DIR)/ui.h + types.h sockapi.h $(UI_DIR)/helpers.h $(UI_DIR)/irqbalance-ui.h $(UI_DIR)/ui.h sbin_PROGRAMS = irqbalance if IRQBALANCEUI @@ -38,8 +38,8 @@ sbin_PROGRAMS += irqbalance-ui endif irqbalance_SOURCES = activate.c bitmap.c classify.c cputree.c irqbalance.c \ - irqlist.c numa.c placement.c procinterrupts.c -irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS) + irqlist.c numa.c placement.c procinterrupts.c sockapi.c +irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS) -lpthread if IRQBALANCEUI irqbalance_ui_SOURCES = $(UI_DIR)/helpers.c $(UI_DIR)/irqbalance-ui.c \ $(UI_DIR)/ui.c diff --git a/classify.c b/classify.c index 52fd74a..1e277c4 100644 --- a/classify.c +++ b/classify.c @@ -37,7 +37,10 @@ static GList *interrupts_db = NULL; static GList *banned_irqs = NULL; GList *cl_banned_irqs = NULL; static GList *cl_banned_modules = NULL; -static GList *vm_banned_irqs = NULL; +GList *vm_banned_irqs = NULL; + +pthread_mutex_t cl_banned_list_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t vm_banned_list_mutex = PTHREAD_MUTEX_INITIALIZER; #define SYSFS_DIR "/sys" #define SYSPCI_DIR "/sys/bus/pci/devices" @@ -299,12 +302,16 @@ void add_banned_list_irq(int irq) void add_cl_banned_irq(int irq) { + irqbalance_mutex_lock(&cl_banned_list_mutex); add_banned_irq(irq, &cl_banned_irqs, 0); + irqbalance_mutex_unlock(&cl_banned_list_mutex); } void add_vm_banned_irq(int irq) { + irqbalance_mutex_lock(&vm_banned_list_mutex); add_banned_irq(irq, &vm_banned_irqs, IRQ_FLAG_VM_BANNED); + irqbalance_mutex_unlock(&vm_banned_list_mutex); } static int is_banned_irq(int irq) @@ -314,7 +321,9 @@ static int is_banned_irq(int irq) find.irq = irq; + irqbalance_mutex_lock(&vm_banned_list_mutex); entry = g_list_find_custom(vm_banned_irqs, &find, compare_ints); + irqbalance_mutex_unlock(&vm_banned_list_mutex); if (!entry) entry = g_list_find_custom(banned_irqs, &find, compare_ints); @@ -586,7 +595,9 @@ static int check_for_irq_ban(char *path __attribute__((unused)), int irq, GList * Check to see if we banned this irq on the command line */ find.irq = irq; + irqbalance_mutex_lock(&cl_banned_list_mutex); entry = g_list_find_custom(cl_banned_irqs, &find, compare_ints); + irqbalance_mutex_unlock(&cl_banned_list_mutex); if (entry) return 1; @@ -821,9 +832,11 @@ void free_irq_db(void) banned_irqs = NULL; g_list_free(rebalance_irq_list); rebalance_irq_list = NULL; + irqbalance_mutex_lock(&vm_banned_list_mutex); for_each_irq(vm_banned_irqs, free_irq, NULL); g_list_free(vm_banned_irqs); vm_banned_irqs = NULL; + irqbalance_mutex_unlock(&vm_banned_list_mutex); } void free_cl_opts(void) @@ -918,8 +931,11 @@ struct irq_info *get_irq_info(int irq) find.irq = irq; entry = g_list_find_custom(interrupts_db, &find, compare_ints); - if (!entry) + if (!entry) { + irqbalance_mutex_lock(&vm_banned_list_mutex); entry = g_list_find_custom(vm_banned_irqs, &find, compare_ints); + irqbalance_mutex_unlock(&vm_banned_list_mutex); + } if (!entry) entry = g_list_find_custom(banned_irqs, &find, compare_ints); diff --git a/cputree.c b/cputree.c index 5551784..0dbb5c8 100644 --- a/cputree.c +++ b/cputree.c @@ -39,6 +39,7 @@ #include "irqbalance.h" extern char *banned_cpumask_from_ui; +extern int is_set_banned_cpumask_from_ui; GList *cpus; GList *cache_domains; @@ -77,8 +78,8 @@ static void setup_banned_cpus(void) cpus_clear(nohz_full); /* A manually specified cpumask overrides auto-detection. */ - if (banned_cpumask_from_ui != NULL) { - cpulist_parse(banned_cpumask_from_ui, + if (is_set_banned_cpumask_from_ui) { + cpumask_parse_user(banned_cpumask_from_ui, strlen(banned_cpumask_from_ui), banned_cpus); goto out; } diff --git a/irqbalance.c b/irqbalance.c index 27cf2eb..6e9de88 100644 --- a/irqbalance.c +++ b/irqbalance.c @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef HAVE_GETOPT_LONG #include #endif @@ -42,6 +43,7 @@ #include #endif #include "irqbalance.h" +#include "sockapi.h" volatile int keep_going = 1; volatile int ban_pci_assigned_irq = 1; @@ -430,178 +432,6 @@ void get_object_stat(struct topo_obj *object, void *data) } } -gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attribute__((unused))) -{ - char buff[500]; - int sock; - int recv_size = 0; - int valid_user = 0; - - struct iovec iov = { buff, 500 }; - struct msghdr msg = { 0 }; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = malloc(CMSG_SPACE(sizeof(struct ucred))); - msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred)); - - struct cmsghdr *cmsg; - - if (condition == G_IO_IN) { - sock = accept(fd, NULL, NULL); - if (sock < 0) { - log(TO_ALL, LOG_WARNING, "Connection couldn't be accepted.\n"); - goto out; - } - if ((recv_size = recvmsg(sock, &msg, 0)) < 0) { - log(TO_ALL, LOG_WARNING, "Error while receiving data.\n"); - goto out_close; - } - cmsg = CMSG_FIRSTHDR(&msg); - if (!cmsg) { - log(TO_ALL, LOG_WARNING, "Connection no memory.\n"); - goto out_close; - } - if ((cmsg->cmsg_level == SOL_SOCKET) && - (cmsg->cmsg_type == SCM_CREDENTIALS)) { - struct ucred *credentials = (struct ucred *) CMSG_DATA(cmsg); - if (!credentials->uid) { - valid_user = 1; - } - } - if (!valid_user) { - log(TO_ALL, LOG_INFO, "Permission denied for user to connect to socket.\n"); - goto out_close; - } - - if (!strncmp(buff, "stats", strlen("stats"))) { - char *stats = NULL; - for_each_object(numa_nodes, get_object_stat, &stats); - send(sock, stats, strlen(stats), 0); - free(stats); - } - if (!strncmp(buff, "settings ", strlen("settings "))) { - if (!(strncmp(buff + strlen("settings "), "sleep ", - strlen("sleep ")))) { - char *sleep_string = malloc( - sizeof(char) * (recv_size - strlen("settings sleep "))); - if (!sleep_string) - goto out_close; - strncpy(sleep_string, buff + strlen("settings sleep "), - recv_size - strlen("settings sleep ")); - int new_iterval = strtoul(sleep_string, NULL, 10); - if (new_iterval >= 1) { - sleep_interval = new_iterval; - } - free(sleep_string); - } else if (!(strncmp(buff + strlen("settings "), "ban irqs ", - strlen("ban irqs ")))) { - char *end; - char *irq_string = malloc( - sizeof(char) * (recv_size - strlen("settings ban irqs "))); - if (!irq_string) - goto out_close; - strncpy(irq_string, buff + strlen("settings ban irqs "), - recv_size - strlen("settings ban irqs ")); - g_list_free_full(cl_banned_irqs, free); - cl_banned_irqs = NULL; - need_rescan = 1; - if (!strncmp(irq_string, "NONE", strlen("NONE"))) { - free(irq_string); - goto out_close; - } - int irq = strtoul(irq_string, &end, 10); - do { - add_cl_banned_irq(irq); - } while((irq = strtoul(end, &end, 10))); - free(irq_string); - } else if (!(strncmp(buff + strlen("settings "), "cpus ", - strlen("cpus")))) { - char *cpu_ban_string = malloc( - sizeof(char) * (recv_size - strlen("settings cpus "))); - if (!cpu_ban_string) - goto out_close; - strncpy(cpu_ban_string, buff + strlen("settings cpus "), - recv_size - strlen("settings cpus ")); - banned_cpumask_from_ui = strtok(cpu_ban_string, " "); - if (!strncmp(banned_cpumask_from_ui, "NULL", strlen("NULL"))) { - banned_cpumask_from_ui = NULL; - } - need_rescan = 1; - free(cpu_ban_string); - } - } - if (!strncmp(buff, "setup", strlen("setup"))) { - char banned[512]; - char *setup = calloc(strlen("SLEEP ") + 11 + 1, 1); - char *newptr = NULL; - if (!setup) - goto out_close; - snprintf(setup, strlen("SLEEP ") + 11 + 1, "SLEEP %d ", sleep_interval); - if(g_list_length(cl_banned_irqs) > 0) { - for_each_irq(cl_banned_irqs, get_irq_data, &setup); - } - cpumask_scnprintf(banned, 512, banned_cpus); - newptr = realloc(setup, strlen(setup) + strlen(banned) + 7 + 1); - if (!newptr) - goto out_free_setup; - - setup = newptr; - snprintf(setup + strlen(setup), strlen(banned) + 7 + 1, - "BANNED %s", banned); - send(sock, setup, strlen(setup), 0); -out_free_setup: - free(setup); - } - -out_close: - close(sock); - } - -out: - free(msg.msg_control); - return TRUE; -} - -int init_socket() -{ - struct sockaddr_un addr; - memset(&addr, 0, sizeof(struct sockaddr_un)); - - socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0); - if (socket_fd < 0) { - log(TO_ALL, LOG_WARNING, "Socket couldn't be created.\n"); - return 1; - } - - /* - * First try to create a file-based socket in tmpfs. If that doesn't - * succeed, fall back to an abstract socket (non file-based). - */ - addr.sun_family = AF_UNIX; - snprintf(socket_name, 64, "%s/%s%d.sock", SOCKET_TMPFS, SOCKET_PATH, getpid()); - strncpy(addr.sun_path, socket_name, sizeof(addr.sun_path)); - if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the file-based socket.\n"); - - /* Try binding to abstract */ - memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the abstract socket, bailing out.\n"); - return 1; - } - } - - int optval = 1; - if (setsockopt(socket_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) { - log(TO_ALL, LOG_WARNING, "Unable to set socket options.\n"); - return 1; - } - listen(socket_fd, 1); - g_unix_fd_add(socket_fd, G_IO_IN, sock_handle, NULL); - return 0; -} - static int create_lock_pidfile(const char *lockfile) { struct flock lock = { 0 }; @@ -691,7 +519,9 @@ error_close: int main(int argc, char** argv) { - struct sigaction action, hupaction; + int err; + pthread_t socket_tid; + struct sigaction action, hupaction; sigset_t sigset, old_sigset; int ret = EXIT_SUCCESS; @@ -781,7 +631,9 @@ int main(int argc, char** argv) parse_proc_interrupts(); parse_proc_stat(); - if (init_socket()) { + err = pthread_create(&socket_tid, NULL, &handle_socket_api_event, NULL); + if (0 != err) { + log(TO_CONSOLE, LOG_WARNING, "WARNING: Failed to create irqbalance socket thread, return %d.\n", err); ret = EXIT_FAILURE; goto out; } diff --git a/irqbalance.h b/irqbalance.h index 339e2a3..f9b554e 100644 --- a/irqbalance.h +++ b/irqbalance.h @@ -44,6 +44,8 @@ extern void set_msi_interrupt_numa(int number); extern GList *rebalance_irq_list; +void irqbalance_mutex_lock(pthread_mutex_t *lock); +void irqbalance_mutex_unlock(pthread_mutex_t *lock); void update_migration_status(void); void dump_workloads(void); void sort_irq_list(GList **list); diff --git a/sockapi.c b/sockapi.c new file mode 100644 index 0000000..4a0e683 --- /dev/null +++ b/sockapi.c @@ -0,0 +1,415 @@ +/* + * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the MuLan PSL v1. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MuLan PSL v1 for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sockapi.h" +#include "irqbalance.h" + +volatile int is_set_banned_cpumask_from_ui = 0; + +extern char *banned_cpumask_from_ui; +extern int socket_fd; +extern char socket_name[64]; +extern int sleep_interval; +extern pthread_mutex_t cl_banned_list_mutex; +extern GList *cl_banned_irqs; +extern pthread_mutex_t vm_banned_list_mutex; +extern GList *vm_banned_irqs; +extern cpumask_t banned_cpus; +extern int keep_going; + +void irqbalance_mutex_lock(pthread_mutex_t *lock) +{ + int err = 0; + + err = pthread_mutex_lock(lock); + if (err) { + log(TO_ALL, LOG_ERR, "irqbalance: err(%d) irqbalance_mutex_lock failed", err); + exit(-1); + } +} + +void irqbalance_mutex_unlock(pthread_mutex_t *lock) +{ + int err = 0; + + err = pthread_mutex_unlock(lock); + if (err) { + log(TO_ALL, LOG_ERR, "irqbalance: err(%d) irqbalance_mutex_unlock failed", err); + exit(-1); + } +} + +static void fill_banned_cpus(char *cpustr, int length) +{ + (void)snprintf(cpustr, length, "CPU:"); + cpumask_scnprintf(cpustr + strlen(cpustr), length - strlen(cpustr), banned_cpus); +} + +static void fill_banned_irqs(char *irqstr, int length) +{ + GList *entry = NULL; + GList *next = NULL; + struct irq_info *info = NULL; + + (void)snprintf(irqstr, length, "IRQ:"); + + irqbalance_mutex_lock(&cl_banned_list_mutex); + entry = g_list_first(cl_banned_irqs); + if (!entry) + (void)snprintf(irqstr + strlen(irqstr), length - strlen(irqstr), "None "); + while (entry) { + next = g_list_next(entry); + info = entry->data; + (void)snprintf(irqstr + strlen(irqstr), length - strlen(irqstr), + "%d,", info->irq); + entry = next; + } + irqbalance_mutex_unlock(&cl_banned_list_mutex); + + (void)snprintf(irqstr + strlen(irqstr) - 1, length - strlen(irqstr), " PCI:"); + + irqbalance_mutex_lock(&vm_banned_list_mutex); + entry = g_list_first(vm_banned_irqs); + if (!entry) + (void)snprintf(irqstr + strlen(irqstr), length - strlen(irqstr), "None"); + while (entry) { + next = g_list_next(entry); + info = entry->data; + (void)snprintf(irqstr + strlen(irqstr), length - strlen(irqstr), + "%d,", info->irq); + entry = next; + } + irqbalance_mutex_unlock(&vm_banned_list_mutex); +} + +static int send_msg(int fd, char* buf, int len) +{ + int ret = -1; + + do { + ret = send(fd, buf, len, 0); + } while ((ret <= 0) && (errno == EINTR)); + + return ret; +} + +static int setnonblocking(int fd) +{ + if (fcntl(fd, F_SETFL, fcntl(socket_fd, F_GETFD, 0)|O_NONBLOCK) < 0) { + return -1; + } + return 0; +} + +static void prase_banned_irq_string(char *irq_string) +{ + char *end = NULL; + char *last = irq_string; + int irq; + + irqbalance_mutex_lock(&cl_banned_list_mutex); + g_list_free_full(cl_banned_irqs, free); + cl_banned_irqs = NULL; + irqbalance_mutex_unlock(&cl_banned_list_mutex); + + log(TO_ALL, LOG_INFO, "Ban irqs(%s) online.\n", irq_string); + if (!strncmp(irq_string, "NONE", strlen("NONE"))) { + return; + } + + irq = strtoul(irq_string, &end, 10); + while (last != end) { + add_cl_banned_irq(irq); + log(TO_ALL, LOG_INFO, "add banned irq %d from api.\n", irq); + last = end; + irq = strtoul(end, &end, 10); + }; +} + +static void prase_banned_cpu_string(char *cpu_ban_string) +{ + if (strlen(cpu_ban_string) < 1) + return; + if (!is_set_banned_cpumask_from_ui) + is_set_banned_cpumask_from_ui = 1; + + strcpy(banned_cpumask_from_ui, cpu_ban_string); + log(TO_ALL, LOG_INFO, "Ban cpus(%s) online.\n", cpu_ban_string); + if (!strncmp(banned_cpumask_from_ui, "NONE", strlen("NONE"))) { + memset((void*)banned_cpumask_from_ui, 0, NR_CPUS + 1); + } +} + +/* + * recived cmdline format: + * 1: settings sleep + * 2: settings ban irqs " ..." or settings ban irqs "NONE" + * 3: settings ban cpus or settings ban cpus NONE + * */ +int sock_handle(int client_fd) +{ + char buff[FILE_LINE_MAX_NUM] = { 0 }; + int ret = -1; + int recv_size = 0; + int valid_user = 0; + int new_iterval = 0; + + struct cmsghdr *cmsg = NULL; + struct ucred *credentials = NULL; + struct iovec iov = { buff, FILE_LINE_MAX_NUM - 1 }; + struct msghdr msg = { NULL, 0, &iov, 1, NULL, 0, 0 }; + + msg.msg_control = malloc(CMSG_SPACE(sizeof(struct ucred))); + msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred)); + + if ((recv_size = recvmsg(client_fd, &msg, 0)) < 0) { + log(TO_ALL, LOG_WARNING, "Error while receiving data.\n"); + goto cleanup; + } + + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg == NULL) { + log(TO_ALL, LOG_INFO, "There isn't enough space for a cmsghdr in the buffer.\n"); + goto cleanup; + } + + if ((cmsg->cmsg_level == SOL_SOCKET) && + (cmsg->cmsg_type == SCM_CREDENTIALS)) { + credentials = (struct ucred *) CMSG_DATA(cmsg); + if (!credentials->uid) { + valid_user = 1; + } + } + if (!valid_user) { + log(TO_ALL, LOG_INFO, "Permission denied for user to connect to socket.\n"); + goto cleanup; + } + + if (!strncmp(buff, "settings ", strlen("settings "))) { + if (!(strncmp(buff + strlen("settings "), "sleep ", + strlen("sleep ")))) { + new_iterval = strtoul(buff + strlen("settings sleep "), NULL, 10); + if (new_iterval >= 1) { + sleep_interval = new_iterval; + } + } else if (!(strncmp(buff + strlen("settings "), "ban irqs \"", + strlen("ban irqs \""))) + && buff[recv_size - 1] == '\"') { + buff[recv_size - 1] = '\0'; + prase_banned_irq_string(buff + strlen("settings ban irqs \"")); + need_rescan = 1; + } else if (!(strncmp(buff + strlen("settings "), "cpus ", + strlen("cpus")))) { + if (recv_size > (int)(NR_CPUS + strlen("settings cpus "))) { + log(TO_ALL, LOG_WARNING, "Recived error setting cpus string %s, ONLY %d cpus support.\n", buff, NR_CPUS); + goto cleanup; + } + buff[recv_size] = '\0'; + prase_banned_cpu_string(buff + strlen("settings cpus ")); + need_rescan = 1; + } + } else if (!strncmp(buff, "stats ", strlen("stats "))) { + if (!(strncmp(buff + strlen("stats "), "cpu", strlen("cpu")))) { + fill_banned_cpus(buff, FILE_LINE_MAX_NUM - 1); + send_msg(client_fd, buff, strlen(buff)); + } else if (!(strncmp(buff + strlen("stats "), "irq", strlen("irq")))) { + fill_banned_irqs(buff, FILE_LINE_MAX_NUM - 1); + send_msg(client_fd, buff, strlen(buff)); + } + } + + ret = 0; + +cleanup: + free(msg.msg_control); + return ret; +} + +int init_socket() +{ + struct sockaddr_un addr; + int optval = 1; + + (void)unlink(socket_name); + + socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0); + if (socket_fd < 0) { + log(TO_ALL, LOG_WARNING, "Socket couldn't be created.\n"); + goto cleanup; + } + + if (access(SOCKET_TMPFS, F_OK) != 0) { + if (mkdir(SOCKET_TMPFS, 0644) == -1) { + log(TO_ALL, LOG_WARNING, "Daemon couldn't create directory %s.\n", SOCKET_TMPFS); + } + } + + /* + * First try to create a file-based socket in tmpfs. If that doesn't + * succeed, fall back to an abstract socket (non file-based). + */ + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, socket_name, sizeof(addr.sun_path)); + if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the file-based socket.\n"); + /* Try binding to abstract */ + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the abstract socket, bailing out.\n"); + goto cleanup; + } + } + + if (chmod(socket_name, SOCK_RWX_MODE) != 0) { + log(TO_ALL, LOG_WARNING, "socket name : %s, chmod failed\n", socket_name); + goto cleanup; + } + + if (setsockopt(socket_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) { + log(TO_ALL, LOG_WARNING, "Unable to set socket options: %s.\n", strerror(errno)); + goto cleanup; + } + + if (listen(socket_fd, MAX_CLIENT) != 0) { + log(TO_ALL, LOG_WARNING, "Daemon couldn't be listening to the socket: %s.\n", strerror(errno)); + goto cleanup; + } + + if (setnonblocking(socket_fd) < 0) { + log(TO_ALL, LOG_WARNING, "Daemon set connection(listen) nonblocking failed: %s.\n", strerror(errno)); + goto cleanup; + } + + return socket_fd; + +cleanup: + if (socket_fd >= 0) + close(socket_fd); + + return -1; +} + +void *handle_socket_api_event(void *args __attribute__((unused))) +{ + int epoll_fd = -1; + int conn_fd = -1; + int nfds = -1; + int i = 0; + int cur_fd_count = 1; + + struct epoll_event ev; + struct epoll_event *events = NULL; + + snprintf(socket_name, 64, "%s/%s%d.sock", SOCKET_TMPFS, SOCKET_PATH, getpid()); + + memset((void*)&ev, 0, sizeof(ev)); + socket_fd = init_socket(); + if (socket_fd < 0) + exit(-1); + + epoll_fd = epoll_create(MAX_EVENTS); + if (epoll_fd < 0) { + log(TO_ALL, LOG_WARNING, "Unable to create epoll: %s.\n", strerror(errno)); + exit(-1); + } + ev.events = EPOLLIN | EPOLLRDHUP; + ev.data.fd = socket_fd; + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &ev) < 0) { + log(TO_ALL, LOG_WARNING, "Daemon epoll set insertion error: %s.\n", strerror(errno)); + exit(-1); + } + + events = (struct epoll_event *)malloc(sizeof(struct epoll_event) * MAX_EVENTS); + if (NULL == events) { + log(TO_ALL, LOG_WARNING, "Daemon faild to malloc epoll event space.\n"); + exit(-1); + } + memset((void*)events, 0, sizeof(struct epoll_event) * MAX_EVENTS); + + banned_cpumask_from_ui = (char*)malloc(NR_CPUS + 1); + banned_cpumask_from_ui = (char*)malloc(NR_CPUS + 1); + if (!banned_cpumask_from_ui) { + log(TO_ALL, LOG_WARNING, "Daemon faild to malloc banned_cpumask_from_ui space.\n"); + exit(-1); + } + memset((void*)banned_cpumask_from_ui, 0, NR_CPUS + 1); + + while (keep_going) { + nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); + if ( 0 == nfds) { + log(TO_ALL, LOG_WARNING, "Daemon epoll wait failed: %s.\n", strerror(errno)); + (void)usleep(SLEEP_TIME); + continue; + } + for (i = 0; i < nfds; i++) { + if (events[i].data.fd == socket_fd) { + conn_fd = accept(socket_fd, NULL, NULL); + if (conn_fd < 0) { + log(TO_ALL, LOG_WARNING, "Daemon accept failed: %s\n", strerror(errno)); + continue; + } + if (cur_fd_count >= MAX_EVENTS) { + log(TO_ALL, LOG_WARNING, "Daemon support no more than %d connection\n", MAX_EVENTS); + close(conn_fd); + continue; + } + if (setnonblocking(conn_fd) < 0) { + log(TO_ALL, LOG_WARNING, "Daemon set connection nonblocking failed: %s.\n", strerror(errno)); + close(conn_fd); + continue; + } + memset((void*)&ev, 0, sizeof(ev)); + ev.events = EPOLLIN | EPOLLRDHUP; + ev.data.fd = conn_fd; + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_fd, &ev) < 0) { + log(TO_ALL, LOG_WARNING, "Daemonadd socket '%d' to poll failed: %s\n", conn_fd, strerror(errno)); + continue; + } + cur_fd_count++; + continue; + } else if (events[i].events&EPOLLERR || events[i].events&EPOLLHUP ) { + log(TO_ALL, LOG_WARNING, "epoll is error: %u\n", events[i].events); + } else { + /* one socket connection only support send&recv data once */ + sock_handle(events[i].data.fd); + } + epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, &ev); + close(events[i].data.fd); + events[i].data.fd = -1; + cur_fd_count--; + } + } + + free(events); + free(banned_cpumask_from_ui); + banned_cpumask_from_ui = NULL; + if (socket_fd >= 0) + close(socket_fd); + if (socket_name[0]) + unlink(socket_name); + + return 0; +} diff --git a/sockapi.h b/sockapi.h new file mode 100644 index 0000000..254dd3f --- /dev/null +++ b/sockapi.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the MuLan PSL v1. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MuLan PSL v1 for more details. + */ +#ifndef UVP_IRQBALANCE_SOCKAPI_H_ +#define UVP_IRQBALANCE_SOCKAPI_H_ + +#include + +/* set socket file mode to 660 */ +#define SOCK_RWX_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) + +#define SLEEP_TIME (100 * 1000) /* 100ms */ + +#define MAX_CLIENT 512 +#define MAX_EVENTS 1024 + +#define FILE_LINE_MAX_NUM (4096*6) + +void *handle_socket_api_event(void *args); + +#endif -- 1.8.3.1