blob: 4dbc5ce98cee8b22d3b3741c6d9f48fe4faa0ca0 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/*
16 Copyright (c) 2005 Eliot Dresselhaus
17
18 Permission is hereby granted, free of charge, to any person obtaining
19 a copy of this software and associated documentation files (the
20 "Software"), to deal in the Software without restriction, including
21 without limitation the rights to use, copy, modify, merge, publish,
22 distribute, sublicense, and/or sell copies of the Software, and to
23 permit persons to whom the Software is furnished to do so, subject to
24 the following conditions:
25
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
28
29 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36*/
37
38#include <vppinfra/error.h>
39#include <vppinfra/os.h>
Damjan Marion4b661402024-02-29 16:14:27 +010040#include <vppinfra/bitmap.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070041#include <vppinfra/unix.h>
Damjan Marion40f48102023-08-07 01:07:09 +020042#include <vppinfra/format.h>
Damjan Marion4b661402024-02-29 16:14:27 +010043#ifdef __linux__
44#include <vppinfra/linux/sysfs.h>
45#endif
Ed Warnickecb9cada2015-12-08 15:45:58 -070046
47#include <sys/stat.h>
48#include <sys/types.h>
hsandid71c32a82024-03-25 17:51:31 +010049#include <sys/syscall.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070050#include <sys/uio.h> /* writev */
51#include <fcntl.h>
52#include <stdio.h> /* for sprintf */
Damjan Marion40f48102023-08-07 01:07:09 +020053#include <limits.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070054
Damjan Mariondae1c7e2020-10-17 13:32:25 +020055__clib_export __thread uword __os_thread_index = 0;
56__clib_export __thread uword __os_numa_index = 0;
Damjan Marionf55f9b82017-05-10 21:06:28 +020057
Dave Barachc3799992016-08-15 11:12:27 -040058clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -040059clib_file_n_bytes (char *file, uword * result)
Ed Warnickecb9cada2015-12-08 15:45:58 -070060{
61 struct stat s;
62
63 if (stat (file, &s) < 0)
64 return clib_error_return_unix (0, "stat `%s'", file);
65
66 if (S_ISREG (s.st_mode))
67 *result = s.st_size;
68 else
69 *result = 0;
70
71 return /* no error */ 0;
72}
73
Dave Barachc3799992016-08-15 11:12:27 -040074clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -040075clib_file_read_contents (char *file, u8 * result, uword n_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -070076{
77 int fd = -1;
78 uword n_done, n_left;
Dave Barachc3799992016-08-15 11:12:27 -040079 clib_error_t *error = 0;
80 u8 *v = result;
Ed Warnickecb9cada2015-12-08 15:45:58 -070081
82 if ((fd = open (file, 0)) < 0)
Dave Barachc3799992016-08-15 11:12:27 -040083 return clib_error_return_unix (0, "open `%s'", file);
Ed Warnickecb9cada2015-12-08 15:45:58 -070084
85 n_left = n_bytes;
86 n_done = 0;
87 while (n_left > 0)
88 {
89 int n_read;
90 if ((n_read = read (fd, v + n_done, n_left)) < 0)
91 {
92 error = clib_error_return_unix (0, "open `%s'", file);
93 goto done;
94 }
95
96 /* End of file. */
97 if (n_read == 0)
98 break;
99
100 n_left -= n_read;
101 n_done += n_read;
102 }
103
104 if (n_left > 0)
105 {
Dave Barachc3799992016-08-15 11:12:27 -0400106 error =
107 clib_error_return (0,
108 " `%s' expected to read %wd bytes; read only %wd",
109 file, n_bytes, n_bytes - n_left);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700110 goto done;
111 }
112
Dave Barachc3799992016-08-15 11:12:27 -0400113done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700114 close (fd);
115 return error;
116}
117
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200118__clib_export clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -0400119clib_file_contents (char *file, u8 ** result)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700120{
121 uword n_bytes;
Dave Barachc3799992016-08-15 11:12:27 -0400122 clib_error_t *error = 0;
123 u8 *v;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700124
Dave Barach59b25652017-09-10 15:04:27 -0400125 if ((error = clib_file_n_bytes (file, &n_bytes)))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700126 return error;
127
128 v = 0;
129 vec_resize (v, n_bytes);
130
Dave Barach59b25652017-09-10 15:04:27 -0400131 error = clib_file_read_contents (file, v, n_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700132
133 if (error)
134 vec_free (v);
135 else
136 *result = v;
137
138 return error;
139}
140
Damjan Marion40f48102023-08-07 01:07:09 +0200141__clib_export u8 *
142clib_file_get_resolved_basename (char *fmt, ...)
143{
144 va_list va;
145 char *p, buffer[PATH_MAX];
146 u8 *link, *s = 0;
147 int r;
148
149 va_start (va, fmt);
150 link = va_format (0, fmt, &va);
151 va_end (va);
152 vec_add1 (link, 0);
153
154 r = readlink ((char *) link, buffer, sizeof (buffer) - 1);
155 vec_free (link);
156
157 if (r < 1)
158 return 0;
159
Dave Wallace05cc62d2023-10-09 18:05:47 -0400160 buffer[r] = 0;
Damjan Marion40f48102023-08-07 01:07:09 +0200161 p = buffer + r - 1;
162 while (p > buffer && p[-1] != '/')
163 p--;
164
165 while (p[0])
166 vec_add1 (s, p++[0]);
167
Damjan Marion08600cc2023-10-04 18:03:18 +0200168 vec_add1 (s, 0);
Damjan Marion40f48102023-08-07 01:07:09 +0200169 return s;
170}
171
Dave Barachc3799992016-08-15 11:12:27 -0400172clib_error_t *
173unix_proc_file_contents (char *file, u8 ** result)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700174{
175 u8 *rv = 0;
176 uword pos;
177 int bytes, fd;
178
179 /* Unfortunately, stat(/proc/XXX) returns zero... */
180 fd = open (file, O_RDONLY);
181
182 if (fd < 0)
183 return clib_error_return_unix (0, "open `%s'", file);
184
Dave Barachc3799992016-08-15 11:12:27 -0400185 vec_validate (rv, 4095);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700186 pos = 0;
Dave Barachc3799992016-08-15 11:12:27 -0400187 while (1)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700188 {
Dave Barachc3799992016-08-15 11:12:27 -0400189 bytes = read (fd, rv + pos, 4096);
190 if (bytes < 0)
191 {
192 close (fd);
193 vec_free (rv);
194 return clib_error_return_unix (0, "read '%s'", file);
195 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196
Dave Barachc3799992016-08-15 11:12:27 -0400197 if (bytes == 0)
198 {
Damjan Marion8bea5892022-04-04 22:40:45 +0200199 vec_set_len (rv, pos);
Dave Barachc3799992016-08-15 11:12:27 -0400200 break;
201 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700202 pos += bytes;
Dave Barachc3799992016-08-15 11:12:27 -0400203 vec_validate (rv, pos + 4095);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700204 }
205 *result = rv;
206 close (fd);
207 return 0;
208}
209
210void os_panic (void) __attribute__ ((weak));
211
Damjan Marion4a251d02021-05-06 17:28:12 +0200212__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400213os_panic (void)
214{
215 abort ();
216}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700217
218void os_exit (int) __attribute__ ((weak));
219
Dave Barachc3799992016-08-15 11:12:27 -0400220void
221os_exit (int code)
222{
223 exit (code);
224}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700225
226void os_puts (u8 * string, uword string_length, uword is_error)
227 __attribute__ ((weak));
228
Dave Barachc3799992016-08-15 11:12:27 -0400229void
230os_puts (u8 * string, uword string_length, uword is_error)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700231{
Damjan Marionf55f9b82017-05-10 21:06:28 +0200232 int cpu = os_get_thread_index ();
233 int nthreads = os_get_nthreads ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700234 char buf[64];
235 int fd = is_error ? 2 : 1;
236 struct iovec iovs[2];
237 int n_iovs = 0;
238
Damjan Marionf55f9b82017-05-10 21:06:28 +0200239 if (nthreads > 1)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700240 {
Dave Barachc3799992016-08-15 11:12:27 -0400241 snprintf (buf, sizeof (buf), "%d: ", cpu);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700242
243 iovs[n_iovs].iov_base = buf;
244 iovs[n_iovs].iov_len = strlen (buf);
245 n_iovs++;
246 }
247
248 iovs[n_iovs].iov_base = string;
249 iovs[n_iovs].iov_len = string_length;
250 n_iovs++;
251
252 if (writev (fd, iovs, n_iovs) < 0)
253 ;
254}
255
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200256__clib_export __clib_weak void
Dave Barachc3799992016-08-15 11:12:27 -0400257os_out_of_memory (void)
258{
259 os_panic ();
260}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700261
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200262__clib_export __clib_weak uword
Damjan Marionf55f9b82017-05-10 21:06:28 +0200263os_get_nthreads (void)
Dave Barachc3799992016-08-15 11:12:27 -0400264{
265 return 1;
266}
267
Damjan Marion4b661402024-02-29 16:14:27 +0100268__clib_export clib_bitmap_t *
269os_get_online_cpu_core_bitmap ()
270{
271#if __linux__
Damjan Marion3eb6cbe2024-02-12 19:44:58 +0000272 return clib_sysfs_read_bitmap ("/sys/devices/system/cpu/online");
Damjan Marion4b661402024-02-29 16:14:27 +0100273#else
274 return 0;
275#endif
276}
277
278__clib_export clib_bitmap_t *
hsandid71c32a82024-03-25 17:51:31 +0100279os_get_cpu_affinity_bitmap (int pid)
280{
281#if __linux
282 int index, ret;
283 cpu_set_t cpuset;
284 uword *affinity_cpus;
285
286 clib_bitmap_alloc (affinity_cpus, sizeof (cpu_set_t));
287 clib_bitmap_zero (affinity_cpus);
288
289 __CPU_ZERO_S (sizeof (cpu_set_t), &cpuset);
290
291 ret = syscall (SYS_sched_getaffinity, 0, sizeof (cpu_set_t), &cpuset);
292
293 if (ret < 0)
294 {
295 clib_bitmap_free (affinity_cpus);
296 return 0;
297 }
298
299 for (index = 0; index < sizeof (cpu_set_t); index++)
300 if (__CPU_ISSET_S (index, sizeof (cpu_set_t), &cpuset))
301 clib_bitmap_set (affinity_cpus, index, 1);
302 return affinity_cpus;
303#else
304 return 0;
305#endif
306}
307
308__clib_export clib_bitmap_t *
Damjan Marion4b661402024-02-29 16:14:27 +0100309os_get_online_cpu_node_bitmap ()
310{
311#if __linux__
Damjan Marion3eb6cbe2024-02-12 19:44:58 +0000312 return clib_sysfs_read_bitmap ("/sys/devices/system/node/online");
Damjan Marion4b661402024-02-29 16:14:27 +0100313#else
314 return 0;
315#endif
316}
Damjan Marion3eb6cbe2024-02-12 19:44:58 +0000317__clib_export clib_bitmap_t *
318os_get_cpu_on_node_bitmap (int node)
319{
320#if __linux__
321 return clib_sysfs_read_bitmap ("/sys/devices/system/node/node%u/cpulist",
322 node);
323#else
324 return 0;
325#endif
326}
327
328__clib_export clib_bitmap_t *
329os_get_cpu_with_memory_bitmap ()
330{
331#if __linux__
332 return clib_sysfs_read_bitmap ("/sys/devices/system/node/has_memory");
333#else
334 return 0;
335#endif
336}
337
338__clib_export int
339os_get_cpu_phys_core_id (int cpu_id)
340{
341#if __linux
342 int core_id = -1;
343 clib_error_t *err;
344 u8 *p;
345
346 p =
347 format (0, "/sys/devices/system/cpu/cpu%u/topology/core_id%c", cpu_id, 0);
348 err = clib_sysfs_read ((char *) p, "%d", &core_id);
349 vec_free (p);
350 if (err)
351 {
352 clib_error_free (err);
353 return -1;
354 }
355 return core_id;
356#else
357 return -1;
358#endif
359}
Damjan Marion4b661402024-02-29 16:14:27 +0100360
Dave Barachc3799992016-08-15 11:12:27 -0400361/*
362 * fd.io coding-style-patch-verification: ON
363 *
364 * Local Variables:
365 * eval: (c-set-style "gnu")
366 * End:
367 */