diff options
-rw-r--r-- | lib/dpif-netlink.c | 75 | ||||
-rw-r--r-- | lib/ovs-thread.c | 17 | ||||
-rw-r--r-- | lib/ovs-thread.h | 1 |
3 files changed, 91 insertions, 2 deletions
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 89e1d4325..51eaf7aef 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -2506,6 +2506,77 @@ dpif_netlink_handler_uninit(struct dpif_handler *handler) } #endif +/* Returns true if num is a prime number, + * otherwise, return false. + */ +static bool +is_prime(uint32_t num) +{ + if (num == 2) { + return true; + } + + if (num < 2) { + return false; + } + + if (num % 2 == 0) { + return false; + } + + for (uint64_t i = 3; i * i <= num; i += 2) { + if (num % i == 0) { + return false; + } + } + + return true; +} + +/* Returns start if start is a prime number. Otherwise returns the next + * prime greater than start. Search is limited by UINT32_MAX. + * + * Returns 0 if no prime has been found between start and UINT32_MAX. + */ +static uint32_t +next_prime(uint32_t start) +{ + if (start <= 2) { + return 2; + } + + for (uint32_t i = start; i < UINT32_MAX; i++) { + if (is_prime(i)) { + return i; + } + } + + return 0; +} + +/* Calculates and returns the number of handler threads needed based + * the following formula: + * + * handlers_n = min(next_prime(active_cores + 1), total_cores) + */ +static uint32_t +dpif_netlink_calculate_n_handlers(void) +{ + uint32_t total_cores = count_total_cores(); + uint32_t n_handlers = count_cpu_cores(); + uint32_t next_prime_num; + + /* If not all cores are available to OVS, create additional handler + * threads to ensure more fair distribution of load between them. + */ + if (n_handlers < total_cores && total_cores > 2) { + next_prime_num = next_prime(n_handlers + 1); + n_handlers = MIN(next_prime_num, total_cores); + } + + return n_handlers; +} + static int dpif_netlink_refresh_handlers_cpu_dispatch(struct dpif_netlink *dpif) OVS_REQ_WRLOCK(dpif->upcall_lock) @@ -2515,7 +2586,7 @@ dpif_netlink_refresh_handlers_cpu_dispatch(struct dpif_netlink *dpif) uint32_t n_handlers; uint32_t *upcall_pids; - n_handlers = count_cpu_cores(); + n_handlers = dpif_netlink_calculate_n_handlers(); if (dpif->n_handlers != n_handlers) { VLOG_DBG("Dispatch mode(per-cpu): initializing %d handlers", n_handlers); @@ -2755,7 +2826,7 @@ dpif_netlink_number_handlers_required(struct dpif *dpif_, uint32_t *n_handlers) struct dpif_netlink *dpif = dpif_netlink_cast(dpif_); if (dpif_netlink_upcall_per_cpu(dpif)) { - *n_handlers = count_cpu_cores(); + *n_handlers = dpif_netlink_calculate_n_handlers(); return true; } diff --git a/lib/ovs-thread.c b/lib/ovs-thread.c index 805cba622..78ed3e970 100644 --- a/lib/ovs-thread.c +++ b/lib/ovs-thread.c @@ -663,6 +663,23 @@ count_cpu_cores(void) return n_cores > 0 ? n_cores : 0; } +/* Returns the total number of cores on the system, or 0 if the + * number cannot be determined. */ +int +count_total_cores(void) +{ + long int n_cores; + +#ifndef _WIN32 + n_cores = sysconf(_SC_NPROCESSORS_CONF); +#else + n_cores = 0; + errno = ENOTSUP; +#endif + + return n_cores > 0 ? n_cores : 0; +} + /* Returns 'true' if current thread is PMD thread. */ bool thread_is_pmd(void) diff --git a/lib/ovs-thread.h b/lib/ovs-thread.h index 3b444ccdc..aac5e19c9 100644 --- a/lib/ovs-thread.h +++ b/lib/ovs-thread.h @@ -522,6 +522,7 @@ bool may_fork(void); /* Useful functions related to threading. */ int count_cpu_cores(void); +int count_total_cores(void); bool thread_is_pmd(void); #endif /* ovs-thread.h */ |