1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
|
/// CPU Information Auto-Detection
/// Author : Qiuwen Lu<[email protected]>
/// Date : 2016-08-08
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <strings.h>
#include <assert.h>
#include <unistd.h>
#include <rte_malloc.h>
#include <rte_config.h>
#include <common.h>
#include <sc_common.h>
struct hwinfo_core
{
unsigned int enable;
unsigned int cpu_id;
unsigned int physical_cpu_id;
unsigned int socket_id;
};
struct hwinfo_main
{
/* logical cpus, including hardware-thread cpus */
unsigned int nr_total_cpus;
/* counts of numa nodes */
unsigned int nr_total_sockets;
/* detailed info of logical cpus */
struct hwinfo_core coreinfo[RTE_MAX_LCORE];
};
#define __FILE_LINUX_CPUS "/sys/devices/system/cpu/present"
#define __FILE_LINUX_PCPU_ID "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/core_id"
#define __FILE_LINUX_SOCKET_ID "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/physical_package_id"
#define SYS_CPU_DIR "/sys/devices/system/cpu/cpu%u"
#define CORE_ID_FILE "topology/core_id"
#define NUMA_NODE_PATH "/sys/devices/system/node"
/* parse a sysfs (or other) file containing one integer value */
static int eal_parse_sysfs_value(const char *filename, unsigned long *val)
{
FILE *f;
char buf[BUFSIZ];
char *end = NULL;
if ((f = fopen(filename, "r")) == NULL) {
RTE_LOG(ERR, EAL, "%s(): cannot open sysfs value %s\n",
__func__, filename);
return -1;
}
if (fgets(buf, sizeof(buf), f) == NULL) {
RTE_LOG(ERR, EAL, "%s(): cannot read sysfs value %s\n",
__func__, filename);
fclose(f);
return -1;
}
*val = strtoul(buf, &end, 0);
if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {
RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs value %s\n",
__func__, filename);
fclose(f);
return -1;
}
fclose(f);
return 0;
}
static int linux_get_nr_total_cpus(void)
{
char buffer[MR_STRING_MAX], *string;
FILE *fd;
fd = fopen(__FILE_LINUX_CPUS, "r");
if (fd == NULL)
return -1;
if (fgets(buffer, sizeof(buffer), fd) == NULL)
{
fclose(fd);
return -1;
}
fclose(fd);
string = index(buffer, '-');
if (string == NULL)
return -1;
return (atoi(++string) + 1);
}
static int linux_get_physical_cpu_id(int lcore_id)
{
char path[PATH_MAX];
unsigned long id;
int len = snprintf(path, sizeof(path), SYS_CPU_DIR "/%s", lcore_id, CORE_ID_FILE);
if (len <= 0 || (unsigned)len >= sizeof(path))
goto err;
if (eal_parse_sysfs_value(path, &id) != 0)
goto err;
return (unsigned)id;
err:
MR_ERROR("Error reading core id value from %s "
"for lcore %u - assuming core 0\n", SYS_CPU_DIR, lcore_id);
return 0;
}
static int linux_get_socket_id(int lcore_id)
{
unsigned socket;
for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) {
char path[PATH_MAX];
snprintf(path, sizeof(path), "%s/node%u/cpu%u", NUMA_NODE_PATH,
socket, lcore_id);
if (access(path, F_OK) == 0)
return socket;
}
return 0;
}
static int hwinfo_cpu_scan(struct hwinfo_main * ctx)
{
int nr_cpus = linux_get_nr_total_cpus();
if (nr_cpus < 0)
{
MR_ERROR("Cannot get count of total cpus");
return nr_cpus;
}
int bitmap_socket[RTE_MAX_NUMA_NODES] = { 0 };
int count_sockets = 0;
int count_cpus = 0;
// 计算CPU信息
for (int cpu_id = 0; cpu_id < nr_cpus; cpu_id++)
{
int pcpu_id = linux_get_physical_cpu_id(cpu_id);
int socket_id = linux_get_socket_id(cpu_id);
if (pcpu_id < 0)
{
MR_ERROR("Cannot get physical id of cpu %d\n", cpu_id);
continue;
}
if (socket_id < 0)
{
MR_ERROR("Cannot get socket id for cpu %d\n", cpu_id);
continue;
}
ctx->coreinfo[cpu_id].enable = 1;
ctx->coreinfo[cpu_id].cpu_id = cpu_id;
ctx->coreinfo[cpu_id].physical_cpu_id = pcpu_id;
ctx->coreinfo[cpu_id].socket_id = socket_id;
count_cpus++;
bitmap_socket[socket_id] = 1;
}
// 根据Socket的标志位,计算Socket的数量。
for (int socket_id = 0; socket_id < RTE_MAX_NUMA_NODES; socket_id++)
{
count_sockets += bitmap_socket[socket_id] > 0 ? 1 : 0;
}
assert(count_cpus > 0);
assert(count_sockets > 0);
ctx->nr_total_cpus = count_cpus;
ctx->nr_total_sockets = count_sockets;
return 0;
}
int hwinfo_deinit(struct hwinfo_main * object)
{
return 0;
}
int hwinfo_init(struct sc_main * sc)
{
struct hwinfo_main * hwinfo_main;
// 分配存储空间
hwinfo_main = ZMALLOC(sizeof(struct hwinfo_main));
MR_VERIFY_MALLOC(hwinfo_main);
// 检测处理器信息
int retval = hwinfo_cpu_scan(hwinfo_main);
if (retval < 0) goto errout;
sc->hwinfo_main = hwinfo_main;
return RT_SUCCESS;
errout:
if (hwinfo_main != NULL) hwinfo_deinit(hwinfo_main);
return RT_ERR;
}
int hwinfo_nr_sockets(struct hwinfo_main * object)
{
return object->nr_total_sockets;
}
int hwinfo_nr_cpus(struct hwinfo_main * object)
{
return object->nr_total_cpus;
}
int hwinfo_physical_cpu_id(struct hwinfo_main * object, int cpu_id)
{
if (!object->coreinfo[cpu_id].enable) return -1;
return object->coreinfo[cpu_id].physical_cpu_id;
}
int hwinfo_socket_id(struct hwinfo_main * object, int cpu_id)
{
if (!object->coreinfo[cpu_id].enable) return -1;
return object->coreinfo[cpu_id].socket_id;
}
|