From 8db2f898d515b78e0fabf1c0837f9b3064c768e5 Mon Sep 17 00:00:00 2001 From: Alex Wang Date: Sun, 22 Jun 2014 18:08:15 -0700 Subject: [PATCH] ovs-numa: Add support for cpu-mask configuration. This commit adds support in ovs-numa module for reading a user specified cpu mask, which configures the availability of the cores. The cpu mask has the format of a hex string similar to the EAL '-c COREMASK' option input or the 'taskset' mask input. The lowest order bit corresponds to the first CPU core. Bit value '1' means the corresponding core is available. An upcoming patch will allow user to configure the mask via OVSDB. Signed-off-by: Alex Wang Acked-by: Pravin B Shelar --- lib/ovs-numa.c | 93 ++++++++++++++++++++++++++++++++++++++++++-------- lib/ovs-numa.h | 7 ++++ 2 files changed, 86 insertions(+), 14 deletions(-) diff --git a/lib/ovs-numa.c b/lib/ovs-numa.c index 7da14073e..26ab3cf21 100644 --- a/lib/ovs-numa.c +++ b/lib/ovs-numa.c @@ -69,6 +69,7 @@ struct cpu_core { struct list list_node; /* In 'numa_node->cores' list. */ struct numa_node *numa; /* numa node containing the core. */ int core_id; /* Core id. */ + bool available; /* If the core can be pinned. */ bool pinned; /* If a thread has been pinned to the core. */ }; @@ -123,6 +124,7 @@ discover_numa_and_core(void) list_insert(&n->cores, &c->list_node); c->core_id = core_id; c->numa = n; + c->available = true; n_cpus++; } } @@ -222,8 +224,8 @@ ovs_numa_get_n_cores_on_numa(int numa_id) return OVS_CORE_UNSPEC; } -/* Returns the number of unpinned cpu cores on numa node. Returns - * OVS_CORE_UNSPEC if 'numa_id' is invalid. */ +/* Returns the number of cpu cores that are available and unpinned + * on numa node. Returns OVS_CORE_UNSPEC if 'numa_id' is invalid. */ int ovs_numa_get_n_unpinned_cores_on_numa(int numa_id) { @@ -236,7 +238,7 @@ ovs_numa_get_n_unpinned_cores_on_numa(int numa_id) hash_int(numa_id, 0)), struct numa_node, hmap_node); LIST_FOR_EACH(core, list_node, &numa->cores) { - if (!core->pinned) { + if (core->available && !core->pinned) { count++; } } @@ -248,7 +250,8 @@ ovs_numa_get_n_unpinned_cores_on_numa(int numa_id) } /* Given 'core_id', tries to pin that core. Returns true, if succeeds. - * False, if the core has already been pinned or if 'core_id' is invalid. */ + * False, if the core has already been pinned, or if it is invalid or + * not available. */ bool ovs_numa_try_pin_core_specific(int core_id) { @@ -258,7 +261,7 @@ ovs_numa_try_pin_core_specific(int core_id) core = CONTAINER_OF(hmap_first_with_hash(&all_cpu_cores, hash_int(core_id, 0)), struct cpu_core, hmap_node); - if (!core->pinned) { + if (core->available && !core->pinned) { core->pinned = true; return true; } @@ -267,16 +270,16 @@ ovs_numa_try_pin_core_specific(int core_id) return false; } -/* Searches through all cores for an unpinned core. Returns the core_id - * if found and set the 'core->pinned' to true. Otherwise, returns - * OVS_CORE_UNSPEC. */ +/* Searches through all cores for an unpinned and available core. Returns + * the 'core_id' if found and sets the 'core->pinned' to true. Otherwise, + * returns OVS_CORE_UNSPEC. */ int ovs_numa_get_unpinned_core_any(void) { struct cpu_core *core; HMAP_FOR_EACH(core, hmap_node, &all_cpu_cores) { - if (!core->pinned) { + if (core->available && !core->pinned) { core->pinned = true; return core->core_id; } @@ -285,9 +288,9 @@ ovs_numa_get_unpinned_core_any(void) return OVS_CORE_UNSPEC; } -/* Searches through all cores on numa node with 'numa_id' for an unpinned - * core. Returns the core_id if found and sets the 'core->pinned' to true. - * Otherwise, returns OVS_CORE_UNSPEC. */ +/* Searches through all cores on numa node with 'numa_id' for an + * unpinned and available core. Returns the core_id if found and + * sets the 'core->pinned' to true. Otherwise, returns OVS_CORE_UNSPEC. */ int ovs_numa_get_unpinned_core_on_numa(int numa_id) { @@ -299,7 +302,7 @@ ovs_numa_get_unpinned_core_on_numa(int numa_id) hash_int(numa_id, 0)), struct numa_node, hmap_node); LIST_FOR_EACH(core, list_node, &numa->cores) { - if (!core->pinned) { + if (core->available && !core->pinned) { core->pinned = true; return core->core_id; } @@ -309,7 +312,7 @@ ovs_numa_get_unpinned_core_on_numa(int numa_id) return OVS_CORE_UNSPEC; } -/* Resets the 'core->pinned' for the core with 'core_id'. */ +/* Unpins the core with 'core_id'. */ void ovs_numa_unpin_core(int core_id) { @@ -323,4 +326,66 @@ ovs_numa_unpin_core(int core_id) } } +/* Reads the cpu mask configuration from 'cmask' and sets the + * 'available' of corresponding cores. For unspecified cores, + * sets 'available' to false. */ +void +ovs_numa_set_cpu_mask(const char *cmask) +{ + int core_id = 0; + int i; + + if (!found_numa_and_core) { + return; + } + + /* If no mask specified, resets the 'available' to true for all cores. */ + if (!cmask) { + struct cpu_core *core; + + HMAP_FOR_EACH(core, hmap_node, &all_cpu_cores) { + core->available = true; + } + + return; + } + + for (i = strlen(cmask) - 1; i >= 0; i--) { + char hex = toupper(cmask[i]); + int bin, j; + + if (hex >= '0' && hex <= '9') { + bin = hex - '0'; + } else if (hex >= 'A' && hex <= 'F') { + bin = hex - 'A' + 10; + } else { + bin = 0; + VLOG_WARN("Invalid cpu mask: %c", cmask[i]); + } + + for (j = 0; j < 4; j++) { + struct cpu_core *core; + + core = CONTAINER_OF(hmap_first_with_hash(&all_cpu_cores, + hash_int(core_id++, 0)), + struct cpu_core, hmap_node); + core->available = (bin >> j) & 0x1; + + if (core_id >= hmap_count(&all_cpu_cores)) { + return; + } + } + } + + /* For unspecified cores, sets 'available' to false. */ + while (core_id < hmap_count(&all_cpu_cores)) { + struct cpu_core *core; + + core = CONTAINER_OF(hmap_first_with_hash(&all_cpu_cores, + hash_int(core_id++, 0)), + struct cpu_core, hmap_node); + core->available = false; + } +} + #endif /* __linux__ */ diff --git a/lib/ovs-numa.h b/lib/ovs-numa.h index 83732fc68..fab25461d 100644 --- a/lib/ovs-numa.h +++ b/lib/ovs-numa.h @@ -31,6 +31,7 @@ void ovs_numa_init(void); bool ovs_numa_numa_id_is_valid(int numa_id); bool ovs_numa_core_id_is_valid(int core_id); int ovs_numa_get_n_numas(void); +void ovs_numa_set_cpu_mask(const char *cmask); int ovs_numa_get_n_cores(void); int ovs_numa_get_numa_id(int core_id); int ovs_numa_get_n_cores_on_numa(int numa_id); @@ -60,6 +61,12 @@ ovs_numa_core_id_is_valid(int core_id OVS_UNUSED) return false; } +static inline void +ovs_numa_set_cpu_mask(const char *cmask OVS_UNUSED) +{ + /* Nothing */ +} + static inline int ovs_numa_get_n_numas(void) { -- 2.20.1