mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 09:58:01 +00:00
The handler and CPU mapping in upcalls are incorrect, and this is specially noticeable systems with cpu isolation enabled. Say we have a 12 core system where only every even number CPU is enabled C0, C2, C4, C6, C8, C10 This means we will create an array of size 6 that will be sent to kernel that is populated with sockets [S0, S1, S2, S3, S4, S5] The problem is when the kernel does an upcall it checks the socket array via the index of the CPU, effectively adding additional load on some CPUs while leaving no work on other CPUs. e.g. C0 indexes to S0 C2 indexes to S2 (should be S1) C4 indexes to S4 (should be S2) Modulo of 6 (size of socket array) is applied, so we wrap back to S0 C6 indexes to S0 (should be S3) C8 indexes to S2 (should be S4) C10 indexes to S4 (should be S5) Effectively sockets S0, S2, S4 get overloaded while sockets S1, S3, S5 get no work assigned to them This leads to the kernel to throw the following message: "openvswitch: cpu_id mismatch with handler threads" Instead we will send the kernel a corrected array of sockets the size of all CPUs in the system, or the largest core_id on the system, which ever one is greatest. This is to take care of systems with non-continous core cpus. In the above example we would create a corrected array in a round-robin(assuming prime bias) fashion as follows: [S0, S1, S2, S3, S4, S5, S6, S0, S1, S2, S3, S4] Fixes: b1e517bd2f81 ("dpif-netlink: Introduce per-cpu upcall dispatch.") Co-authored-by: Aaron Conole <aconole@redhat.com> Signed-off-by: Aaron Conole <aconole@redhat.com> Signed-off-by: Michael Santana <msantana@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
78 lines
2.4 KiB
C
78 lines
2.4 KiB
C
/*
|
|
* Copyright (c) 2014 Nicira, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef OVS_NUMA_H
|
|
#define OVS_NUMA_H 1
|
|
|
|
#include <limits.h>
|
|
#include <stdbool.h>
|
|
|
|
#include "compiler.h"
|
|
#include "openvswitch/hmap.h"
|
|
|
|
#define OVS_CORE_UNSPEC INT_MAX
|
|
#define OVS_NUMA_UNSPEC INT_MAX
|
|
|
|
#define MAX_NUMA_NODES 128
|
|
|
|
/* Dump of a list of 'struct ovs_numa_info'. */
|
|
struct ovs_numa_dump {
|
|
struct hmap cores;
|
|
struct hmap numas;
|
|
};
|
|
|
|
/* A numa_id - core_id pair. */
|
|
struct ovs_numa_info_core {
|
|
struct hmap_node hmap_node;
|
|
int numa_id;
|
|
unsigned core_id;
|
|
};
|
|
|
|
/* A numa node. */
|
|
struct ovs_numa_info_numa {
|
|
struct hmap_node hmap_node;
|
|
int numa_id;
|
|
size_t n_cores;
|
|
};
|
|
|
|
void ovs_numa_init(void);
|
|
void ovs_numa_set_dummy(const char *config);
|
|
bool ovs_numa_numa_id_is_valid(int numa_id);
|
|
bool ovs_numa_core_id_is_valid(unsigned core_id);
|
|
int ovs_numa_get_n_numas(void);
|
|
int ovs_numa_get_n_cores(void);
|
|
int ovs_numa_get_numa_id(unsigned core_id);
|
|
int ovs_numa_get_n_cores_on_numa(int numa_id);
|
|
unsigned ovs_numa_get_largest_core_id(void);
|
|
struct ovs_numa_dump *ovs_numa_dump_cores_on_numa(int numa_id);
|
|
struct ovs_numa_dump *ovs_numa_dump_cores_with_cmask(const char *cmask);
|
|
struct ovs_numa_dump *ovs_numa_dump_n_cores_per_numa(int n);
|
|
bool ovs_numa_dump_contains_core(const struct ovs_numa_dump *,
|
|
int numa_id, unsigned core_id);
|
|
size_t ovs_numa_dump_count(const struct ovs_numa_dump *);
|
|
struct ovs_numa_dump * ovs_numa_thread_getaffinity_dump(void);
|
|
int ovs_numa_thread_setaffinity_dump(const struct ovs_numa_dump *);
|
|
void ovs_numa_dump_destroy(struct ovs_numa_dump *);
|
|
int ovs_numa_thread_setaffinity_core(unsigned core_id);
|
|
|
|
#define FOR_EACH_CORE_ON_DUMP(ITER, DUMP) \
|
|
HMAP_FOR_EACH (ITER, hmap_node, &(DUMP)->cores)
|
|
|
|
#define FOR_EACH_NUMA_ON_DUMP(ITER, DUMP) \
|
|
HMAP_FOR_EACH (ITER, hmap_node, &(DUMP)->numas)
|
|
|
|
#endif /* ovs-numa.h */
|