/* Assign port to the bridge. */ lagopus_result_t dpmgr_bridge_port_add(struct dpmgr *dpmgr, const char *bridge_name, uint32_t portid, uint32_t port_no) { lagopus_result_t ret; struct port *port; /* Lookup port from the dpmgr. */ port = port_lookup(dpmgr->ports, portid); if (port == NULL) { lagopus_msg_error("Physical port %d is not registered\n", portid); return LAGOPUS_RESULT_NOT_FOUND; } /* Is already part of bridge? */ if (port->bridge != NULL) { lagopus_msg_error("Physical port %d is already assigned\n", portid); return LAGOPUS_RESULT_ALREADY_EXISTS; } port->ofp_port.port_no = port_no; /* Add the port to the bridge. */ ret = bridge_port_add(&dpmgr->bridge_list, bridge_name, port); return ret; }
struct lagopus_packet * alloc_lagopus_packet(void) { struct lagopus_packet *pkt; struct rte_mbuf *mbuf; unsigned sock; mbuf = NULL; if (rawsocket_only_mode != true) { for (sock = 0; sock < APP_MAX_SOCKETS; sock++) { if (app.pools[sock] != NULL) { mbuf = rte_pktmbuf_alloc(app.pools[sock]); break; } } if (mbuf == NULL) { lagopus_msg_error("rte_pktmbuf_alloc failed\n"); return NULL; } } else { /* do not use rte_mempool because it is not initialized. */ mbuf = calloc(1, sizeof(struct rte_mbuf) + APP_DEFAULT_MBUF_SIZE); if (mbuf == NULL) { lagopus_msg_error("memory exhausted\n"); return NULL; } mbuf->buf_addr = (void *)&mbuf[1]; mbuf->buf_len = APP_DEFAULT_MBUF_SIZE; rte_pktmbuf_reset(mbuf); rte_mbuf_refcnt_set(mbuf, 1); } pkt = (struct lagopus_packet *) (mbuf->buf_addr + APP_DEFAULT_MBUF_LOCALDATA_OFFSET); pkt->mbuf = mbuf; return pkt; }
static void s_check_cancelled(lagopus_thread_t *thread, bool require) { bool canceled = !require; lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; if ((ret = lagopus_thread_is_canceled(thread, &canceled)) != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_msg_error("Can't check is_cancelled.\n"); } else if (canceled != require) { lagopus_msg_error( "is_cancelled() required %s, but %s.\n", BOOL_TO_STR(require), BOOL_TO_STR(canceled)); } }
lagopus_result_t lagopus_module_initialize_all(int argc, const char *const argv[]) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; s_lock(); { if (s_n_modules > 0) { size_t i; a_module *mptr; for (ret = LAGOPUS_RESULT_OK, i = 0; ret == LAGOPUS_RESULT_OK && i < s_n_modules; i++) { mptr = &(s_modules[i]); ret = s_initialize_module(mptr, argc, argv); if (ret != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_msg_error("can't initialize module \"%s\".\n", mptr->m_name); } } } else { ret = LAGOPUS_RESULT_OK; } } s_unlock(); return ret; }
lagopus_result_t lagopus_module_start_all(void) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; s_lock(); { if (s_n_modules > 0) { size_t i; a_module *mptr; for (ret = LAGOPUS_RESULT_OK, i = 0; ret == LAGOPUS_RESULT_OK && i < s_n_modules; i++) { mptr = &(s_modules[i]); ret = s_start_module(mptr); if (ret != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_msg_error("can't start module \"%s\".\n", mptr->m_name); } } } else { ret = LAGOPUS_RESULT_OK; } } s_unlock(); return ret; }
static inline void s_shutdown(shutdown_grace_level_t level) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; if ((ret = global_state_request_shutdown(level)) == LAGOPUS_RESULT_OK) { lagopus_msg_info("The shutdown request accepted.\n"); } else { lagopus_perror(ret); lagopus_msg_error("Can't request shutdown.\n"); } }
static int assign_tx_lcore(uint8_t portid, uint8_t n) { struct app_lcore_params *lp; app.nic_tx_port_mask[portid] = 1; lp = &app.lcore_params[lcores[n]]; if (lp->type == e_APP_LCORE_WORKER) { lagopus_msg_error("lcore %d (%dth lcore): already assinged as worker\n", lcores[n], n); return -5; } lp->type = e_APP_LCORE_IO; lp->io.tx.nic_ports[lp->io.tx.n_nic_ports] = portid; lp->io.tx.n_nic_ports++; return 0; }
lagopus_result_t snmpmgr_poll(lagopus_chrono_t nsec) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; (void)lagopus_mutex_lock(&snmp_state_lock); if (state == SNMPMGR_RUNNING) { (void)lagopus_mutex_unlock(&snmp_state_lock); (void)lagopus_mutex_lock(&snmp_lock); ret = internal_snmpmgr_poll(nsec); (void)lagopus_mutex_unlock(&snmp_lock); return ret; } else { (void)lagopus_mutex_unlock(&snmp_state_lock); lagopus_msg_error("SNMP agent is not started.\n"); return LAGOPUS_RESULT_NOT_STARTED; } }
lagopus_result_t lagopus_module_shutdown_all(shutdown_grace_level_t level) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; if (IS_VALID_SHUTDOWN(level) == true) { s_lock(); { if (s_n_modules > 0) { lagopus_result_t first_err = LAGOPUS_RESULT_OK; size_t i; a_module *mptr; /* * Reverse order. */ for (i = 0; i < s_n_modules; i++) { mptr = &(s_modules[s_n_modules - i - 1]); ret = s_shutdown_module(mptr, level); if (ret != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_msg_error("can't shutdown module \"%s\".\n", mptr->m_name); if (first_err == LAGOPUS_RESULT_OK) { first_err = ret; } } /* * Just carry on shutting down no matter what kind of errors * occur. */ } ret = first_err; } else { ret = LAGOPUS_RESULT_OK; } } s_unlock(); } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
void count_ifNumber(int32_t *ifNumber) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; size_t v; if (ifNumber != NULL) { struct port_stat *port_stat; if ((ret = dp_get_port_stat(&port_stat)) == LAGOPUS_RESULT_OK) { dataplane_count_ifNumber(port_stat, &v); *ifNumber = (int32_t)v; port_stat_release(port_stat); free(port_stat); } else { lagopus_msg_error("cannot count ports: %s\n", lagopus_error_get_string(ret)); } } }
void app_init_kni(void) { uint8_t portid; for (portid = 0; portid < rte_eth_dev_count(); portid++) { struct rte_kni *kni; struct rte_kni_ops ops; struct rte_kni_conf conf; struct rte_eth_dev_info dev_info; continue; /* XXX */ /* Clear conf at first */ memset(&conf, 0, sizeof(conf)); memset(&dev_info, 0, sizeof(dev_info)); memset(&ops, 0, sizeof(ops)); snprintf(conf.name, RTE_KNI_NAMESIZE, "vEth%u", portid); conf.group_id = (uint16_t)portid; conf.mbuf_size = MAX_PACKET_SZ; rte_eth_dev_info_get(portid, &dev_info); conf.addr = dev_info.pci_dev->addr; conf.id = dev_info.pci_dev->id; ops.port_id = portid; ops.change_mtu = kni_change_mtu; ops.config_network_if = kni_config_network_interface, /* XXX socket 0 */ kni = rte_kni_alloc(app.pools[0], &conf, &ops); if (kni == NULL) { lagopus_msg_error("Fail to create kni dev for port: %d\n", portid); continue; } lagopus_kni[portid] = kni; printf("KNI: %s is configured.\n", conf.name); printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", (unsigned) portid, lagopus_ports_eth_addr[portid].addr_bytes[0], lagopus_ports_eth_addr[portid].addr_bytes[1], lagopus_ports_eth_addr[portid].addr_bytes[2], lagopus_ports_eth_addr[portid].addr_bytes[3], lagopus_ports_eth_addr[portid].addr_bytes[4], lagopus_ports_eth_addr[portid].addr_bytes[5]); /* initialize port stats */ memset(&port_statistics, 0, sizeof(port_statistics)); } }
static int assign_rx_lcore(uint8_t portid, uint8_t n) { struct app_lcore_params *lp; app.nic_rx_queue_mask[portid][0] = NIC_RX_QUEUE_ENABLED; lp = &app.lcore_params[lcores[n]]; if (lp->type == e_APP_LCORE_WORKER) { lagopus_msg_error("lcore %d (%dth lcore): already assinged as worker\n", lcores[n], n); return -5; } lp->type = e_APP_LCORE_IO; lp->io.rx.nic_queues[lp->io.rx.n_nic_queues].port = portid; lp->io.rx.nic_queues[lp->io.rx.n_nic_queues].queue = 0; lp->io.rx.n_nic_queues++; return 0; }
/** * Copy packet for output. */ struct lagopus_packet * copy_packet(struct lagopus_packet *src_pkt) { struct rte_mbuf *mbuf; struct lagopus_packet *pkt; size_t pktlen; pkt = alloc_lagopus_packet(); if (pkt == NULL) { lagopus_msg_error("alloc_lagopus_packet failed\n"); return NULL; } mbuf = pkt->mbuf; pktlen = OS_M_PKTLEN(src_pkt->mbuf); OS_M_APPEND(mbuf, pktlen); memcpy(OS_MTOD(pkt->mbuf, char *), OS_MTOD(src_pkt->mbuf, char *), pktlen); pkt->in_port = src_pkt->in_port; /* other pkt members are not used in physical output. */ return pkt; }
lagopus_result_t lagopus_module_stop_all(void) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; s_lock(); { if (s_n_modules > 0) { lagopus_result_t first_err = LAGOPUS_RESULT_OK; size_t i; a_module *mptr; /* * Reverse order. */ for (i = 0; i < s_n_modules; i++) { mptr = &(s_modules[s_n_modules - i - 1]); ret = s_stop_module(mptr); if (ret != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_msg_error("can't stop module \"%s\".\n", mptr->m_name); if (first_err == LAGOPUS_RESULT_OK) { first_err = ret; } } /* * Just carry on stopping no matter what kind of errors * occur. */ } ret = first_err; } else { ret = LAGOPUS_RESULT_OK; } } s_unlock(); return ret; }
struct lagopus_packet * alloc_lagopus_packet(void) { struct lagopus_packet *pkt; struct rte_mbuf *mbuf; unsigned sock; mbuf = NULL; for (sock = 0; sock < APP_MAX_SOCKETS; sock++) { if (app.pools[sock] != NULL) { mbuf = rte_pktmbuf_alloc(app.pools[sock]); break; } } if (mbuf == NULL) { lagopus_msg_error("rte_pktmbuf_alloc failed\n"); return NULL; } pkt = (struct lagopus_packet *) (mbuf->buf_addr + APP_DEFAULT_MBUF_LOCALDATA_OFFSET); pkt->mbuf = mbuf; return pkt; }
static inline void s_gen_pidfile(void) { FILE *fd = NULL; if (IS_VALID_STRING(s_pidfile) == true) { snprintf(s_pidfile_buf, sizeof(s_pidfile_buf), "%s", s_pidfile); } else { snprintf(s_pidfile_buf, sizeof(s_pidfile_buf), DEFAULT_PIDFILE_DIR "%s.pid", s_progname); } fd = fopen(s_pidfile_buf, "w"); if (fd != NULL) { fprintf(fd, "%d\n", (int)getpid()); fflush(fd); (void)fclose(fd); } else { lagopus_perror(LAGOPUS_RESULT_POSIX_API_ERROR); lagopus_msg_error("can't create a pidfile \"%s\".\n", s_pidfile_buf); } }
static void s_term_handler(int sig) { lagopus_result_t r = LAGOPUS_RESULT_ANY_FAILURES; global_state_t gs = GLOBAL_STATE_UNKNOWN; if ((r = global_state_get(&gs)) == LAGOPUS_RESULT_OK) { if ((int)gs == (int)GLOBAL_STATE_STARTED) { shutdown_grace_level_t l = SHUTDOWN_UNKNOWN; if (sig == SIGTERM || sig == SIGINT) { l = SHUTDOWN_GRACEFULLY; } else if (sig == SIGQUIT) { l = SHUTDOWN_RIGHT_NOW; } if (IS_VALID_SHUTDOWN(l) == true) { lagopus_msg_info("About to request shutdown(%s)...\n", (l == SHUTDOWN_RIGHT_NOW) ? "RIGHT_NOW" : "GRACEFULLY"); if ((r = global_state_request_shutdown(l)) == LAGOPUS_RESULT_OK) { lagopus_msg_info("The shutdown request accepted.\n"); } else { lagopus_perror(r); lagopus_msg_error("can't request shutdown.\n"); } } } else if ((int)gs < (int)GLOBAL_STATE_STARTED) { if (sig == SIGTERM || sig == SIGINT || sig == SIGQUIT) { s_got_term_sig = true; } } else { lagopus_msg_debug(5, "The system is already shutting down.\n"); } } }
int main(int argc, char const *const argv[]) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; int i; int n = 10000; lagopus_thread_t thread = NULL; pthread_t tid = LAGOPUS_INVALID_THREAD; lagopus_log_set_debug_level(10); if (argc > 1) { int tmp; if (lagopus_str_parse_int32(argv[1], &tmp) == LAGOPUS_RESULT_OK && tmp > 0) { n = tmp; } } /* create, start, wait, destroy */ for (i = 0; i < n; i++) { thread = NULL; if ((ret = lagopus_thread_create( (lagopus_thread_t *)&thread, (lagopus_thread_main_proc_t)s_main_proc, (lagopus_thread_finalize_proc_t)s_finalize_proc, (lagopus_thread_freeup_proc_t)s_freeup_proc, (const char *) "thread", (void *) NULL)) != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_exit_fatal("Can't create a thread.\n"); } else { fprintf(stderr, "create a thread [%d]\n", i); if ((ret = lagopus_thread_get_pthread_id(&thread, &tid)) != LAGOPUS_RESULT_NOT_STARTED) { lagopus_perror(ret); goto done; } } if ((ret = lagopus_thread_start(&thread, false)) != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_exit_fatal("Can't start the thread.\n"); } else { ret = lagopus_thread_get_pthread_id(&thread, &tid); if (ret == LAGOPUS_RESULT_OK || ret == LAGOPUS_RESULT_ALREADY_HALTED) { fprintf(stderr, " start thread: %lu\n", tid); } else { lagopus_perror(ret); goto done; } } s_check_cancelled(&thread, false); if ((ret = lagopus_thread_wait(&thread, 1000LL * 1000LL * 1000LL)) != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_msg_error("Can't wait the thread.\n"); } else { if ((ret = lagopus_thread_get_pthread_id(&thread, &tid)) == LAGOPUS_RESULT_OK) { lagopus_msg_error( "Thread has been completed, but I can get thread ID, %lu\n", tid); } else if (ret != LAGOPUS_RESULT_ALREADY_HALTED) { lagopus_perror(ret); goto done; } } s_check_cancelled(&thread, false); lagopus_thread_destroy(&thread); fprintf(stderr, "destroy the thread [%d]\n", i); fprintf(stderr, "\n"); } /* create, start, cancel, destroy */ for (i = 0; i < n; i++) { thread = NULL; if ((ret = lagopus_thread_create( (lagopus_thread_t *)&thread, (lagopus_thread_main_proc_t)s_main_proc_with_sleep, (lagopus_thread_finalize_proc_t)s_finalize_proc, (lagopus_thread_freeup_proc_t)s_freeup_proc, (const char *) "thread", (void *) NULL)) != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_exit_fatal("Can't create a thread.\n"); } else { fprintf(stderr, "create a thread [%d]\n", i); if ((ret = lagopus_thread_get_pthread_id(&thread, &tid)) != LAGOPUS_RESULT_NOT_STARTED) { lagopus_perror(ret); goto done; } } if ((ret = lagopus_thread_start(&thread, false)) != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_exit_fatal("Can't start the thread.\n"); } else { ret = lagopus_thread_get_pthread_id(&thread, &tid); if (ret == LAGOPUS_RESULT_OK || ret == LAGOPUS_RESULT_ALREADY_HALTED) { fprintf(stderr, " start thread: %lu\n", tid); } else { lagopus_perror(ret); goto done; } } s_check_cancelled(&thread, false); if ((ret = lagopus_thread_cancel(&thread)) != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_msg_error("Can't cancel the thread.\n"); } else { if ((ret = lagopus_thread_get_pthread_id(&thread, &tid)) == LAGOPUS_RESULT_OK) { lagopus_msg_error( "Thread has been canceled, but I can get thread ID, %lu\n", tid); } else if (ret != LAGOPUS_RESULT_NOT_STARTED && ret != LAGOPUS_RESULT_ALREADY_HALTED) { lagopus_perror(ret); goto done; } } s_check_cancelled(&thread, true); lagopus_thread_destroy(&thread); fprintf(stderr, "destroy the thread [%d]\n", i); fprintf(stderr, "\n"); } /* create, start, destroy */ for (i = 0; i < n; i++) { thread = NULL; if ((ret = lagopus_thread_create( (lagopus_thread_t *)&thread, (lagopus_thread_main_proc_t)s_main_proc_with_sleep, (lagopus_thread_finalize_proc_t)s_finalize_proc, (lagopus_thread_freeup_proc_t)s_freeup_proc, (const char *) "thread", (void *) NULL)) != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_exit_fatal("Can't create a thread.\n"); } else { fprintf(stderr, "create a thread [%d]\n", i); if ((ret = lagopus_thread_get_pthread_id(&thread, &tid)) != LAGOPUS_RESULT_NOT_STARTED) { lagopus_perror(ret); goto done; } } if ((ret = lagopus_thread_start(&thread, false)) != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_exit_fatal("Can't start the thread.\n"); } else { ret = lagopus_thread_get_pthread_id(&thread, &tid); if (ret == LAGOPUS_RESULT_OK || ret == LAGOPUS_RESULT_ALREADY_HALTED) { fprintf(stderr, " start thread: %lu\n", tid); } else { lagopus_perror(ret); goto done; } } lagopus_thread_destroy(&thread); fprintf(stderr, "destroy the thread [%d]\n", i); fprintf(stderr, "\n"); } done: return (ret == LAGOPUS_RESULT_OK) ? 0 : 1; }
static inline lagopus_result_t s_start_callout_main_loop(void) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; global_state_t s; shutdown_grace_level_t l; ret = global_state_wait_for(GLOBAL_STATE_STARTED, &s, &l, -1LL); if (likely(ret == LAGOPUS_RESULT_OK)) { if (likely(s == GLOBAL_STATE_STARTED)) { #ifdef CO_MSG_DEBUG lagopus_chrono_t timeout = s_idle_interval; #else lagopus_chrono_t timeout; #endif /* CO_MSG_DEBUG */ lagopus_callout_task_t out_tasks[CALLOUT_TASK_MAX * 3]; size_t n_out_tasks; lagopus_callout_task_t urgent_tasks[CALLOUT_TASK_MAX]; lagopus_result_t sn_urgent_tasks; lagopus_callout_task_t idle_tasks[CALLOUT_TASK_MAX]; lagopus_result_t sn_idle_tasks; lagopus_callout_task_t timed_tasks[CALLOUT_TASK_MAX]; lagopus_result_t sn_timed_tasks; lagopus_result_t r; lagopus_chrono_t now; lagopus_chrono_t next_wakeup; lagopus_chrono_t prev_wakeup; int cstate = 0; WHAT_TIME_IS_IT_NOW_IN_NSEC(prev_wakeup); (void)lagopus_mutex_enter_critical(&s_sched_lck, &cstate); { s_is_stopped = false; mbar(); while (s_do_loop == true) { n_out_tasks = 0; /* * Get the current time. */ WHAT_TIME_IS_IT_NOW_IN_NSEC(now); #ifdef CO_MSG_DEBUG lagopus_msg_debug(3, "now: " PF64(d) "\n", now); lagopus_msg_debug(3, "prv: " PF64(d) "\n", prev_wakeup); lagopus_msg_debug(3, "to: " PF64(d) "\n", timeout); #endif /* CO_MSG_DEBUG */ s_lock_global(); { /* * Acquire the global lock to make the task * submisson/fetch atomic. */ sn_urgent_tasks = lagopus_bbq_get_n(&s_urgent_tsk_q, (void **)urgent_tasks, CALLOUT_TASK_MAX, 1LL, lagopus_callout_task_t, 0LL, NULL); sn_idle_tasks = lagopus_bbq_get_n(&s_idle_tsk_q, (void **)idle_tasks, CALLOUT_TASK_MAX, 1LL, lagopus_callout_task_t, 0LL, NULL); } s_unlock_global(); /* * Pack the tasks into a buffer. */ sn_timed_tasks = s_get_runnable_timed_task(now, timed_tasks, CALLOUT_TASK_MAX, &next_wakeup); if (sn_timed_tasks > 0) { /* * Pack the timed tasks. */ (void)memcpy((void *)(out_tasks + n_out_tasks), timed_tasks, (size_t)(sn_timed_tasks) * sizeof(lagopus_callout_task_t)); n_out_tasks += (size_t)sn_timed_tasks; #ifdef CO_MSG_DEBUG lagopus_msg_debug(3, "timed task " PF64(u) ".\n", sn_timed_tasks); lagopus_msg_debug(3, "nw: " PF64(d) ".\n", next_wakeup); #endif /* CO_MSG_DEBUG */ } else if (sn_timed_tasks < 0) { /* * We can't be treat this as a fatal error. Carry on. */ lagopus_perror(sn_timed_tasks); lagopus_msg_error("timed tasks fetch failed.\n"); } if (sn_urgent_tasks > 0) { /* * Pack the urgent tasks. */ (void)memcpy((void *)(out_tasks + n_out_tasks), urgent_tasks, (size_t)(sn_urgent_tasks) * sizeof(lagopus_callout_task_t)); n_out_tasks += (size_t)sn_urgent_tasks; } else if (sn_urgent_tasks < 0) { /* * We can't be treat this as a fatal error. Carry on. */ lagopus_perror(sn_urgent_tasks); lagopus_msg_error("urgent tasks fetch failed.\n"); } if (sn_idle_tasks > 0) { /* * Pack the idle tasks. */ (void)memcpy((void *)(out_tasks + n_out_tasks), idle_tasks, (size_t)(sn_idle_tasks) * sizeof(lagopus_callout_task_t)); n_out_tasks += (size_t)sn_idle_tasks; } else if (sn_idle_tasks < 0) { /* * We can't be treat this as a fatal error. Carry on. */ lagopus_perror(sn_idle_tasks); lagopus_msg_error("idle tasks fetch failed.\n"); } if (n_out_tasks > 0) { /* * Run/Submit the tasks. */ r = (s_final_task_sched_proc)(out_tasks, now, n_out_tasks); if (unlikely(r <= 0)) { /* * We can't be treat this as a fatal error. Carry on. */ lagopus_perror(r); lagopus_msg_error("failed to submit " PFSZ(u) " urgent/timed tasks.\n", n_out_tasks); } } if (s_idle_proc != NULL && s_next_idle_abstime < (now + CALLOUT_TASK_SCHED_JITTER)) { if (likely(s_idle_proc(s_idle_proc_arg) == LAGOPUS_RESULT_OK)) { s_next_idle_abstime = now + s_idle_interval; } else { /* * Stop the main loop and return (clean finish.) */ s_do_loop = false; goto critical_end; } } /* * fetch the start time of the timed task in the queue head. */ next_wakeup = s_peek_current_wakeup_time(); if (next_wakeup <= 0LL) { /* * Nothing in the timed Q. */ if (s_next_idle_abstime <= 0LL) { s_next_idle_abstime = now + s_idle_interval; } next_wakeup = s_next_idle_abstime; } /* * TODO * * Re-optimize forcible waje up by timed task submission * timing and times. See also * callout_queue.c:s_do_sched(). */ /* * calculate the timeout and sleep. */ timeout = next_wakeup - now; if (likely(timeout > 0LL)) { if (timeout > s_idle_interval) { timeout = s_idle_interval; next_wakeup = now + timeout; } #ifdef CO_MSG_DEBUG lagopus_msg_debug(4, "about to sleep, timeout " PF64(d) " nsec.\n", timeout); #endif /* CO_MSG_DEBUG */ prev_wakeup = next_wakeup; r = lagopus_bbq_wait_gettable(&s_urgent_tsk_q, timeout); if (unlikely(r <= 0 && r != LAGOPUS_RESULT_TIMEDOUT && r != LAGOPUS_RESULT_WAKEUP_REQUESTED)) { lagopus_perror(r); lagopus_msg_error("Event wait failure.\n"); ret = r; goto critical_end; } else { if (r == LAGOPUS_RESULT_WAKEUP_REQUESTED) { #ifdef CO_MSG_DEBUG lagopus_msg_debug(4, "woke up.\n"); #endif /* CO_MSG_DEBUG */ } } } else { WHAT_TIME_IS_IT_NOW_IN_NSEC(next_wakeup); prev_wakeup = next_wakeup; #ifdef CO_MSG_DEBUG lagopus_msg_debug(4, "timeout zero. contiune.\n"); #endif /* CO_MSG_DEBUG */ } /* * The end of the desired potion of the loop. */ } /* while (s_do_loop == true) */ } critical_end: s_is_stopped = true; s_wakeup_sched(); (void)lagopus_mutex_leave_critical(&s_sched_lck, cstate); if (s_do_loop == false) { /* * The clean finish. */ ret = LAGOPUS_RESULT_OK; } } else { /* s == GLOBAL_STATE_STARTED */ s_is_stopped = true; ret = LAGOPUS_RESULT_INVALID_STATE_TRANSITION; } } else { s_is_stopped = true; } return ret; }
int main(int argc, const char *const argv[]) { lagopus_log_destination_t dst = LAGOPUS_LOG_EMIT_TO_UNKNOWN; const char *logarg; char *p; uint16_t cur_debug_level = lagopus_log_get_debug_level(); int ipcfds[2]; ipcfds[0] = -1; ipcfds[1] = -1; s_progname = ((p = strrchr(argv[0], '/')) != NULL) ? ++p : argv[0]; parse_args(argc, argv); if (IS_VALID_STRING(s_logfile) == true) { dst = LAGOPUS_LOG_EMIT_TO_FILE; logarg = s_logfile; } else { dst = LAGOPUS_LOG_EMIT_TO_SYSLOG; logarg = s_progname; } /* * If the cur_debug_level > 0 the debug level is set by the lagopus * runtime so use it as is. */ (void)lagopus_log_initialize(dst, logarg, false, true, (cur_debug_level > 0) ? cur_debug_level : s_debug_level); (void)lagopus_signal(SIGHUP, s_hup_handler, NULL); (void)lagopus_signal(SIGINT, s_term_handler, NULL); (void)lagopus_signal(SIGTERM, s_term_handler, NULL); (void)lagopus_signal(SIGQUIT, s_term_handler, NULL); if (s_debug_level == 0) { pid_t pid = (pid_t)-1; if (pipe(ipcfds) != 0) { lagopus_perror(LAGOPUS_RESULT_POSIX_API_ERROR); return 1; } pid = fork(); if (pid > 0) { int exit_code; ssize_t st; (void)close(ipcfds[1]); if ((st = read(ipcfds[0], (void *)&exit_code, sizeof(int))) != sizeof(int)) { lagopus_perror(LAGOPUS_RESULT_POSIX_API_ERROR); return 1; } return exit_code; } else if (pid == 0) { s_daemonize(ipcfds[1]); if (lagopus_log_get_destination() == LAGOPUS_LOG_EMIT_TO_FILE) { (void)lagopus_log_reinitialize(); } } else { lagopus_perror(LAGOPUS_RESULT_POSIX_API_ERROR); lagopus_msg_error("can' be a daemon.\n"); return 1; } } return s_do_main(argc, argv, ipcfds[1]); }
static inline lagopus_chrono_t s_do_sched(lagopus_callout_task_t t) { lagopus_result_t ret = -1LL; lagopus_result_t r; lagopus_callout_task_t e; s_lock_task_q(); { s_lock_task(t); { if (likely(t->m_is_in_timed_q == false)) { /* * Firstly (re-)compute the next exeution time of this * task. */ if (t->m_is_first == false && t->m_do_repeat == true) { t->m_next_abstime = t->m_last_abstime + t->m_interval_time; } else { WHAT_TIME_IS_IT_NOW_IN_NSEC(t->m_last_abstime); t->m_next_abstime = t->m_last_abstime + t->m_initial_delay_time; } /* * Then insert the task into the Q. */ e = TAILQ_FIRST(&s_chrono_tsk_q); if (e != NULL) { if (e->m_next_abstime > t->m_next_abstime) { TAILQ_INSERT_HEAD(&s_chrono_tsk_q, t, m_entry); } else { for (; e != NULL && e->m_next_abstime <= t->m_next_abstime; e = TAILQ_NEXT(e, m_entry)) { ; } if (e != NULL) { TAILQ_INSERT_BEFORE(e, t, m_entry); } else { TAILQ_INSERT_TAIL(&s_chrono_tsk_q, t, m_entry); } } } else { TAILQ_INSERT_TAIL(&s_chrono_tsk_q, t, m_entry); } (void)s_set_task_state_in_table(t, TASK_STATE_ENQUEUED); t->m_status = TASK_STATE_ENQUEUED; t->m_is_in_timed_q = true; ret = t->m_next_abstime; /* * Fianlly wake the master scheduler. */ lagopus_msg_debug(4, "wake the master scheduler up.\n"); /* * TODO * * Re-optimize forcible wake up by timed task submission * timing and times. See also * callout.c:s_start_callout_main_loop() */ r = lagopus_bbq_wakeup(&s_urgent_tsk_q, 0LL); if (unlikely(r != LAGOPUS_RESULT_OK)) { lagopus_perror(r); lagopus_msg_error("can't wake the callout task master " "scheduler up.\n"); } } } s_unlock_task(t); } s_unlock_task_q(); return ret; }
static void * s_numa_alloc(size_t sz, int cpu) { void *ret = NULL; if (likely(sz > 0)) { if (likely(cpu >= 0)) { if (likely(s_numa_nodes != NULL && s_n_cpus > 0)) { unsigned int node = s_numa_nodes[cpu]; unsigned int allocd_node = UINT_MAX; struct bitmask *bmp; int r; bmp = numa_allocate_nodemask(); numa_bitmask_setbit(bmp, node); errno = 0; r = (int)set_mempolicy(MPOL_BIND, bmp->maskp, bmp->size + 1); if (likely(r == 0)) { errno = 0; ret = numa_alloc_onnode(sz, (int)node); if (likely(ret != NULL)) { lagopus_result_t rl; /* * We need this "first touch" even using the * numa_alloc_onnode(). */ (void)memset(ret, 0, sz); errno = 0; r = (int)get_mempolicy((int *)&allocd_node, NULL, 0, ret, MPOL_F_NODE|MPOL_F_ADDR); if (likely(r == 0)) { if (unlikely(node != allocd_node)) { /* * The memory is not allocated on the node, but it is * still usable. Just return it. */ lagopus_msg_warning("can't allocate " PFSZ(u) " bytes memory " "for CPU %d (NUMA node %d).\n", sz, cpu, node); } } else { lagopus_perror(LAGOPUS_RESULT_POSIX_API_ERROR); lagopus_msg_error("get_mempolicy() returned %d.\n", r); } rl = s_add_addr(ret, sz); if (unlikely(rl != LAGOPUS_RESULT_OK)) { lagopus_perror(rl); lagopus_msg_error("can't register the allocated address.\n"); numa_free(ret, sz); ret = NULL; } } } else { /* r == 0 */ lagopus_perror(LAGOPUS_RESULT_POSIX_API_ERROR); lagopus_msg_error("set_mempolicy() returned %d.\n", r); } numa_free_nodemask(bmp); set_mempolicy(MPOL_DEFAULT, NULL, 0); } else { /* s_numa_nodes != NULL && s_n_cpus > 0 */ /* * Not initialized or initialization failure. */ lagopus_msg_warning("The NUMA related information is not initialized. " "Use malloc(3) instead.\n"); ret = malloc(sz); } } else { /* cpu >= 0 */ /* * Use pure malloc(3). */ ret = malloc(sz); } } return ret; }
/* Parse the argument given in the command line of the application */ int app_parse_args(int argc, const char *argv[]) { int opt, ret; char **argvopt; int option_index; const char *prgname = argv[0]; static const struct option lgopts[] = { {"rx", 1, 0, 0}, {"tx", 1, 0, 0}, {"w", 1, 0, 0}, {"rsz", 1, 0, 0}, {"bsz", 1, 0, 0}, {"no-cache", 0, 0, 0}, {"core-assign", 1, 0, 0}, {"kvstype", 1, 0, 0}, #ifdef __SSE4_2__ {"hashtype", 1, 0, 0}, #endif /* __SSE4_2__ */ {"fifoness", 1, 0, 0}, {"show-core-config", 0, 0, 0}, {NULL, 0, 0, 0} }; uint32_t arg_p = 0; uint32_t arg_w = 0; uint32_t arg_rx = 0; uint32_t arg_tx = 0; uint32_t arg_rsz = 0; uint32_t arg_bsz = 0; uint64_t portmask = 0; char *end = NULL; struct app_lcore_params *lp, *htlp; unsigned lcore, htcore, lcore_count, i, wk_lcore_count = 0; unsigned rx_lcore_start, tx_lcore_start, wk_lcore_start; int rx_lcore_inc, tx_lcore_inc, wk_lcore_inc; uint8_t portid, port_count, count, n; bool show_core_assign = false; argvopt = (char **)argv; while ((opt = getopt_long(argc, argvopt, "p:w:", lgopts, &option_index)) != EOF) { switch (opt) { case 'p': if (optarg[0] == '\0') { printf("Require value for -p argument\n"); return -1; } portmask = (uint64_t)strtoull(optarg, &end, 16); if (end == NULL || *end != '\0') { printf("Non-numerical value for -p argument\n"); return -1; } if (portmask == 0) { printf("Incorrect value for -p argument\n"); return -1; } arg_p = 1; break; case 'w': if (optarg[0] == '\0') { printf("Require value for -w argument\n"); return -1; } wk_lcore_count = (unsigned)strtoul(optarg, &end, 10); if (end == NULL || *end != '\0') { printf("Non-numerical value for -w argument\n"); return -1; } if (wk_lcore_count == 0) { printf("Incorrect value for -w argument\n"); return -1; } break; /* long options */ case 0: if (!strcmp(lgopts[option_index].name, "rx")) { arg_rx = 1; ret = parse_arg_rx(optarg); if (ret) { printf("Incorrect value for --rx argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "tx")) { arg_tx = 1; ret = parse_arg_tx(optarg); if (ret) { printf("Incorrect value for --tx argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "w")) { arg_w = 1; ret = parse_arg_w(optarg); if (ret) { printf("Incorrect value for --w argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "rsz")) { arg_rsz = 1; ret = parse_arg_rsz(optarg); if (ret) { printf("Incorrect value for --rsz argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "bsz")) { arg_bsz = 1; ret = parse_arg_bsz(optarg); if (ret) { printf("Incorrect value for --bsz argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "core-assign")) { ret = parse_arg_core_assign(optarg); if (ret) { printf("Incorrect value for --core-assign argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "no-cache")) { app.no_cache = 1; } if (!strcmp(lgopts[option_index].name, "kvstype")) { ret = parse_arg_kvstype(optarg); if (ret) { printf("Incorrect value for --ksvtype argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "hashtype")) { ret = parse_arg_hashtype(optarg); if (ret) { printf("Incorrect value for --hashtype argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "fifoness")) { ret = parse_arg_fifoness(optarg); if (ret) { printf("Incorrect value for --fifoness argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "show-core-config")) { show_core_assign = true; } break; default: printf("Incorrect option\n"); return -1; } } /* Check that all mandatory arguments are provided */ if ((arg_rx == 0 || arg_tx == 0 || arg_w == 0) && arg_p == 0) { lagopus_exit_error(EXIT_FAILURE, "Not all mandatory arguments are present\n"); } port_count = 0; if (arg_p != 0) { /** * Assign lcore for each thread automatically. */ for (i = 0; i < 32; i++) { if ((portmask & (uint64_t)(1ULL << i)) != 0) { port_count++; } } if (port_count == 0) { lagopus_exit_error(EXIT_FAILURE, "error: port is not specified. use -p HEXNUM or --rx, --tx.\n"); } } for (lcore_count = 0, lcore = 0; lcore < RTE_MAX_LCORE; lcore++) { if (lcore == rte_get_master_lcore()) { continue; } if (!rte_lcore_is_enabled(lcore)) { continue; } lp = &app.lcore_params[lcore]; lp->socket_id = lcore_config[lcore].socket_id; lp->core_id = lcore_config[lcore].core_id; /* add lcore id except for hyper-threading core. */ for (htcore = 0; htcore < lcore; htcore++) { if (!rte_lcore_is_enabled(htcore)) { continue; } htlp = &app.lcore_params[htcore]; if (app.core_assign == CORE_ASSIGN_PERFORMANCE) { if (lp->socket_id == htlp->socket_id && lp->core_id == htlp->core_id) { break; } } } if (htcore == lcore) { lcores[lcore_count++] = lcore; } } if (lcore_count == 0) { lagopus_exit_error( EXIT_FAILURE, "Not enough active core " "(need at least 2 active core%s)\n", app.core_assign == CORE_ASSIGN_PERFORMANCE ? " except for HTT core" : ""); } if (app.core_assign == CORE_ASSIGN_MINIMUM) { lcore_count = 1; } if (lcore_count == 1) { /* * I/O and worker shares single lcore. */ rx_lcore_start = 0; tx_lcore_start = 0; wk_lcore_start = 0; rx_lcore_inc = 0; tx_lcore_inc = 0; wk_lcore_inc = 0; } else if (port_count * 4 <= lcore_count) { /* * each ports rx has own lcore. * each ports tx has own lcore. * all other lcores are assigned as worker. */ rx_lcore_start = 0; tx_lcore_start = rx_lcore_start + port_count; wk_lcore_start = tx_lcore_start + port_count; rx_lcore_inc = 1; tx_lcore_inc = 1; wk_lcore_inc = 1; } else if (port_count * 2 <= lcore_count) { /* * each ports (rx/tx) has own lcore. * all other lcores are assigned as worker. */ rx_lcore_start = 0; tx_lcore_start = 0; wk_lcore_start = rx_lcore_start + port_count; rx_lcore_inc = 1; tx_lcore_inc = 1; wk_lcore_inc = 1; } else if (port_count <= lcore_count) { /* * odd ports and even ports (rx/tx) shared lcore. * all other lcores are assigned as worker. */ rx_lcore_start = 0; tx_lcore_start = 0; wk_lcore_start = rx_lcore_start + (port_count + 1) / 2; rx_lcore_inc = 2; tx_lcore_inc = 2; wk_lcore_inc = 1; } else if (port_count <= lcore_count * 2) { /* * four ports (rx/tx) shared lcore. * all other lcores are assigned as worker. */ rx_lcore_start = 0; tx_lcore_start = 0; wk_lcore_start = rx_lcore_start + (port_count + 3) / 4; rx_lcore_inc = 4; tx_lcore_inc = 4; wk_lcore_inc = 1; } else if (lcore_count >= 4) { /* * rx for all ports has own lcore. * tx for all ports has own lcore. * all other lcores are assigned as worker. */ rx_lcore_start = 0; tx_lcore_start = 1; wk_lcore_start = 2; rx_lcore_inc = 0; tx_lcore_inc = 0; wk_lcore_inc = 1; } else { /* * I/O has own lcore. * all other lcores are assigned as worker. */ rx_lcore_start = 0; tx_lcore_start = 0; wk_lcore_start = 1; rx_lcore_inc = 0; tx_lcore_inc = 0; wk_lcore_inc = 1; } /* assign core automatically */ if (arg_rx == 0) { lcore = rx_lcore_start; count = rx_lcore_inc; for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if ((portmask & (uint64_t)(1ULL << portid)) == 0) { continue; } if (assign_rx_lcore(portid, lcore) != 0) { return -5; } if (--count == 0) { lcore++; count = rx_lcore_inc; } } } if (arg_tx == 0) { lcore = tx_lcore_start; count = tx_lcore_inc; for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if ((portmask & (uint64_t)(1ULL << portid)) == 0) { continue; } if (assign_tx_lcore(portid, lcore) != 0) { return -5; } if (--count == 0) { lcore++; count = tx_lcore_inc; } } } if (arg_w == 0) { if (wk_lcore_count == 0) { wk_lcore_count = lcore_count - wk_lcore_start; } for (lcore = wk_lcore_start; lcore < wk_lcore_start + wk_lcore_count; lcore++) { lp = &app.lcore_params[lcores[lcore]]; if (lp->type == e_APP_LCORE_IO) { /* core is shared by I/O and worker. */ lp->type = e_APP_LCORE_IO_WORKER; } else { lp->type = e_APP_LCORE_WORKER; } if (wk_lcore_inc != 1) { break; } } } /* Assign default values for the optional arguments not provided */ if (arg_rsz == 0) { app.nic_rx_ring_size = APP_DEFAULT_NIC_RX_RING_SIZE; app.nic_tx_ring_size = APP_DEFAULT_NIC_TX_RING_SIZE; app.ring_rx_size = APP_DEFAULT_RING_RX_SIZE; app.ring_tx_size = APP_DEFAULT_RING_TX_SIZE; } if (arg_bsz == 0) { app.burst_size_io_rx_read = APP_DEFAULT_BURST_SIZE_IO_RX_READ; app.burst_size_io_rx_write = APP_DEFAULT_BURST_SIZE_IO_RX_WRITE; app.burst_size_io_tx_read = APP_DEFAULT_BURST_SIZE_IO_TX_READ; app.burst_size_io_tx_write = APP_DEFAULT_BURST_SIZE_IO_TX_WRITE; app.burst_size_worker_read = APP_DEFAULT_BURST_SIZE_WORKER_READ; app.burst_size_worker_write = APP_DEFAULT_BURST_SIZE_WORKER_WRITE; } /* Check cross-consistency of arguments */ if (app_check_every_rx_port_is_tx_enabled() < 0) { lagopus_msg_error("At least one RX port is not enabled for TX.\n"); return -2; } if (show_core_assign == true) { printf("core assign:\n"); for (lcore = 0; lcore < RTE_MAX_LCORE; lcore++) { if (lcore_config[lcore].detected != true) { continue; } lp = &app.lcore_params[lcore]; printf(" lcore %d:\n", lcore); if (lp->type == e_APP_LCORE_IO) { printf(" type: I/O\n"); } else if (lp->type == e_APP_LCORE_WORKER) { printf(" type: WORKER\n"); } else if (lp->type == e_APP_LCORE_IO_WORKER) { printf(" type: I/O WORKER\n"); } else { printf(" type: not used\n"); } for (n = 0; n < lp->io.rx.n_nic_queues; n++) { printf(" RX port %d (queue %d)\n", lp->io.rx.nic_queues[n].port, lp->io.rx.nic_queues[n].queue); } for (n = 0; n < lp->io.tx.n_nic_ports; n++) { printf(" TX port %d\n", lp->io.tx.nic_ports[n]); } } exit(0); } if (optind >= 0) { argv[optind - 1] = prgname; } ret = optind - 1; optind = 0; /* reset getopt lib */ return ret; }
lagopus_result_t lagopus_module_wait_all(lagopus_chrono_t nsec) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; s_lock(); { if (s_n_modules > 0) { lagopus_result_t first_err = LAGOPUS_RESULT_OK; size_t i; a_module *mptr; /* * Reverse order. */ if (nsec < 0LL) { for (i = 0; i < s_n_modules; i++) { mptr = &(s_modules[s_n_modules - i - 1]); ret = s_wait_module(mptr, -1LL); if (ret != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_msg_error("can't wait module \"%s\".\n", mptr->m_name); if (first_err == LAGOPUS_RESULT_OK) { first_err = ret; } } /* * Just carry on wait no matter what kind of errors * occur. */ } } else { lagopus_chrono_t w_begin; lagopus_chrono_t w_end; lagopus_chrono_t w = nsec; for (i = 0; i < s_n_modules; i++) { mptr = &(s_modules[s_n_modules - i - 1]); WHAT_TIME_IS_IT_NOW_IN_NSEC(w_begin); ret = s_wait_module(mptr, w); WHAT_TIME_IS_IT_NOW_IN_NSEC(w_end); if (ret != LAGOPUS_RESULT_OK) { lagopus_perror(ret); lagopus_msg_error("can't wait module \"%s\".\n", mptr->m_name); if (first_err == LAGOPUS_RESULT_OK) { first_err = ret; } } /* * Just carry on wait no matter what kind of errors * occur. */ w = nsec - (w_end - w_begin); if (w < 0LL) { w = 0LL; } } } ret = first_err; } else { ret = LAGOPUS_RESULT_OK; } } s_unlock(); return ret; }