static void test_pcap(struct ovs_cmdl_context *ctx) { size_t total_count, batch_size_; struct pcap_file *pcap; int err = 0; pcap = ovs_pcap_open(ctx->argv[1], "rb"); if (!pcap) { return; } batch_size_ = 1; if (ctx->argc > 2) { batch_size_ = strtoul(ctx->argv[2], NULL, 0); if (batch_size_ == 0 || batch_size_ > NETDEV_MAX_BURST) { ovs_fatal(0, "batch_size must be between 1 and NETDEV_MAX_BURST(%u)", NETDEV_MAX_BURST); } } fatal_signal_init(); ct = conntrack_init(); total_count = 0; for (;;) { struct dp_packet *packet; struct dp_packet_batch pkt_batch_; struct dp_packet_batch *batch = &pkt_batch_; dp_packet_batch_init(batch); for (int i = 0; i < batch_size_; i++) { err = ovs_pcap_read(pcap, &packet, NULL); if (err) { break; } dp_packet_batch_add(batch, packet); } if (dp_packet_batch_is_empty(batch)) { break; } pcap_batch_execute_conntrack(ct, batch); DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { struct ds ds = DS_EMPTY_INITIALIZER; total_count++; format_flags(&ds, ct_state_to_string, packet->md.ct_state, '|'); printf("%"PRIuSIZE": %s\n", total_count, ds_cstr(&ds)); ds_destroy(&ds); } dp_packet_delete_batch(batch, true); } conntrack_destroy(ct); ovs_pcap_close(pcap); }
/* Check whether a fatal signal has occurred and, if so, call the fatal signal * hooks and exit. * * This function is called automatically by poll_block(), but specialized * programs that may not always call poll_block() on a regular basis should * also call it periodically. (Therefore, any function with "block" in its * name should call fatal_signal_run() each time it is called, either directly * or through poll_block(), because such functions can only used by specialized * programs that can afford to block outside their main loop around * poll_block().) */ void fatal_signal_run(void) { sig_atomic_t sig_nr; fatal_signal_init(); sig_nr = stored_sig_nr; if (sig_nr != SIG_ATOMIC_MAX) { char namebuf[SIGNAL_NAME_BUFSIZE]; ovs_mutex_lock(&mutex); VLOG_WARN("terminating with signal %d (%s)", (int)sig_nr, signal_name(sig_nr, namebuf, sizeof namebuf)); call_hooks(sig_nr); /* Re-raise the signal with the default handling so that the program * termination status reflects that we were killed by this signal */ signal(sig_nr, SIG_DFL); raise(sig_nr); ovs_mutex_unlock(&mutex); OVS_NOT_REACHED(); } }
/* Unregisters 'file' from being unlinked when the program terminates via * exit() or a fatal signal. */ void fatal_signal_remove_file_to_unlink(const char *file) { fatal_signal_init(); ovs_mutex_lock(&mutex); sset_find_and_delete(&files, file); ovs_mutex_unlock(&mutex); }
void fatal_signal_wait(void) { fatal_signal_init(); #ifdef _WIN32 poll_wevent_wait(wevent); #else poll_fd_wait(signal_fds[0], POLLIN); #endif }
/* Registers 'hook_cb' to be called when a process termination signal is * raised. If 'run_at_exit' is true, 'hook_cb' is also called during normal * process termination, e.g. when exit() is called or when main() returns. * * 'hook_cb' is not called immediately from the signal handler but rather the * next time the poll loop iterates, so it is freed from the usual restrictions * on signal handler functions. * * If the current process forks, fatal_signal_fork() may be called to clear the * parent process's fatal signal hooks, so that 'hook_cb' is only called when * the child terminates, not when the parent does. When fatal_signal_fork() is * called, it calls the 'cancel_cb' function if it is nonnull, passing 'aux', * to notify that the hook has been canceled. This allows the hook to free * memory, etc. */ void fatal_signal_add_hook(void (*hook_cb)(void *aux), void (*cancel_cb)(void *aux), void *aux, bool run_at_exit) { fatal_signal_init(); assert(n_hooks < MAX_HOOKS); hooks[n_hooks].hook_cb = hook_cb; hooks[n_hooks].cancel_cb = cancel_cb; hooks[n_hooks].aux = aux; hooks[n_hooks].run_at_exit = run_at_exit; n_hooks++; }
static void test_benchmark(struct ovs_cmdl_context *ctx) { struct thread_aux *threads; long long start; unsigned i; fatal_signal_init(); /* Parse arguments */ n_threads = strtoul(ctx->argv[1], NULL, 0); if (!n_threads) { ovs_fatal(0, "n_threads must be at least one"); } n_pkts = strtoul(ctx->argv[2], NULL, 0); batch_size = strtoul(ctx->argv[3], NULL, 0); if (batch_size == 0 || batch_size > NETDEV_MAX_BURST) { ovs_fatal(0, "batch_size must be between 1 and NETDEV_MAX_BURST(%u)", NETDEV_MAX_BURST); } if (ctx->argc > 4) { change_conn = strtoul(ctx->argv[4], NULL, 0); } threads = xcalloc(n_threads, sizeof *threads); ovs_barrier_init(&barrier, n_threads + 1); ct = conntrack_init(); /* Create threads */ for (i = 0; i < n_threads; i++) { threads[i].tid = i; threads[i].thread = ovs_thread_create("ct_thread", ct_thread_main, &threads[i]); } /* Starts the work inside the threads */ ovs_barrier_block(&barrier); start = time_msec(); /* Wait for the threads to finish the work */ ovs_barrier_block(&barrier); printf("conntrack: %5lld ms\n", time_msec() - start); for (i = 0; i < n_threads; i++) { xpthread_join(threads[i].thread, NULL); } conntrack_destroy(ct); ovs_barrier_destroy(&barrier); free(threads); }
/* Registers 'file' to be unlinked when the program terminates via exit() or a * fatal signal. */ void fatal_signal_add_file_to_unlink(const char *file) { fatal_signal_init(); ovs_mutex_lock(&mutex); if (!added_hook) { added_hook = true; fatal_signal_add_hook(unlink_files, cancel_files, NULL, true); } sset_add(&files, file); ovs_mutex_unlock(&mutex); }
/* Check whether a fatal signal has occurred and, if so, call the fatal signal * hooks and exit. * * This function is called automatically by poll_block(), but specialized * programs that may not always call poll_block() on a regular basis should * also call it periodically. (Therefore, any function with "block" in its * name should call fatal_signal_run() each time it is called, either directly * or through poll_block(), because such functions can only used by specialized * programs that can afford to block outside their main loop around * poll_block().) */ void fatal_signal_run(void) { int sig_nr; fatal_signal_init(); sig_nr = stored_sig_nr; if (sig_nr != SIG_ATOMIC_MAX) { call_hooks(sig_nr); /* Re-raise the signal with the default handling so that the program * termination status reflects that we were killed by this signal */ signal(sig_nr, SIG_DFL); raise(sig_nr); } }
/* Check whether a fatal signal has occurred and, if so, call the fatal signal * hooks and exit. * * This function is called automatically by poll_block(), but specialized * programs that may not always call poll_block() on a regular basis should * also call it periodically. (Therefore, any function with "block" in its * name should call fatal_signal_run() each time it is called, either directly * or through poll_block(), because such functions can only used by specialized * programs that can afford to block outside their main loop around * poll_block().) */ void fatal_signal_run(void) { sig_atomic_t sig_nr; fatal_signal_init(); sig_nr = stored_sig_nr; if (sig_nr != SIG_ATOMIC_MAX) { VLOG_WARN("terminating with signal %d (%s)", (int)sig_nr, signal_name(sig_nr)); call_hooks(sig_nr); /* Re-raise the signal with the default handling so that the program * termination status reflects that we were killed by this signal */ signal(sig_nr, SIG_DFL); raise(sig_nr); } }
/* Like fatal_signal_remove_file_to_unlink(), but also unlinks 'file'. * Returns 0 if successful, otherwise a positive errno value. */ int fatal_signal_unlink_file_now(const char *file) { int error; fatal_signal_init(); ovs_mutex_lock(&mutex); error = unlink(file) ? errno : 0; if (error) { VLOG_WARN("could not unlink \"%s\" (%s)", file, ovs_strerror(error)); } fatal_signal_remove_file_to_unlink(file); ovs_mutex_unlock(&mutex); return error; }
void fatal_signal_wait(void) { fatal_signal_init(); poll_fd_wait(signal_fds[0], POLLIN); }