blob: 29cbe0a557dba523f2d3b8379217e4d030e575ae [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>
Tom Jonesab479932024-04-24 10:30:20 +000045#else
46#include <sys/sysctl.h>
Damjan Marion4b661402024-02-29 16:14:27 +010047#endif
Ed Warnickecb9cada2015-12-08 15:45:58 -070048
49#include <sys/stat.h>
50#include <sys/types.h>
hsandid71c32a82024-03-25 17:51:31 +010051#include <sys/syscall.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070052#include <sys/uio.h> /* writev */
53#include <fcntl.h>
54#include <stdio.h> /* for sprintf */
Damjan Marion40f48102023-08-07 01:07:09 +020055#include <limits.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070056
Damjan Mariondae1c7e2020-10-17 13:32:25 +020057__clib_export __thread uword __os_thread_index = 0;
58__clib_export __thread uword __os_numa_index = 0;
Damjan Marionf55f9b82017-05-10 21:06:28 +020059
Dave Barachc3799992016-08-15 11:12:27 -040060clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -040061clib_file_n_bytes (char *file, uword * result)
Ed Warnickecb9cada2015-12-08 15:45:58 -070062{
63 struct stat s;
64
65 if (stat (file, &s) < 0)
66 return clib_error_return_unix (0, "stat `%s'", file);
67
68 if (S_ISREG (s.st_mode))
69 *result = s.st_size;
70 else
71 *result = 0;
72
73 return /* no error */ 0;
74}
75
Dave Barachc3799992016-08-15 11:12:27 -040076clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -040077clib_file_read_contents (char *file, u8 * result, uword n_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -070078{
79 int fd = -1;
80 uword n_done, n_left;
Dave Barachc3799992016-08-15 11:12:27 -040081 clib_error_t *error = 0;
82 u8 *v = result;
Ed Warnickecb9cada2015-12-08 15:45:58 -070083
84 if ((fd = open (file, 0)) < 0)
Dave Barachc3799992016-08-15 11:12:27 -040085 return clib_error_return_unix (0, "open `%s'", file);
Ed Warnickecb9cada2015-12-08 15:45:58 -070086
87 n_left = n_bytes;
88 n_done = 0;
89 while (n_left > 0)
90 {
91 int n_read;
92 if ((n_read = read (fd, v + n_done, n_left)) < 0)
93 {
94 error = clib_error_return_unix (0, "open `%s'", file);
95 goto done;
96 }
97
98 /* End of file. */
99 if (n_read == 0)
100 break;
101
102 n_left -= n_read;
103 n_done += n_read;
104 }
105
106 if (n_left > 0)
107 {
Dave Barachc3799992016-08-15 11:12:27 -0400108 error =
109 clib_error_return (0,
110 " `%s' expected to read %wd bytes; read only %wd",
111 file, n_bytes, n_bytes - n_left);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700112 goto done;
113 }
114
Dave Barachc3799992016-08-15 11:12:27 -0400115done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700116 close (fd);
117 return error;
118}
119
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200120__clib_export clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -0400121clib_file_contents (char *file, u8 ** result)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700122{
123 uword n_bytes;
Dave Barachc3799992016-08-15 11:12:27 -0400124 clib_error_t *error = 0;
125 u8 *v;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700126
Dave Barach59b25652017-09-10 15:04:27 -0400127 if ((error = clib_file_n_bytes (file, &n_bytes)))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700128 return error;
129
130 v = 0;
131 vec_resize (v, n_bytes);
132
Dave Barach59b25652017-09-10 15:04:27 -0400133 error = clib_file_read_contents (file, v, n_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700134
135 if (error)
136 vec_free (v);
137 else
138 *result = v;
139
140 return error;
141}
142
Damjan Marion40f48102023-08-07 01:07:09 +0200143__clib_export u8 *
144clib_file_get_resolved_basename (char *fmt, ...)
145{
146 va_list va;
147 char *p, buffer[PATH_MAX];
148 u8 *link, *s = 0;
149 int r;
150
151 va_start (va, fmt);
152 link = va_format (0, fmt, &va);
153 va_end (va);
154 vec_add1 (link, 0);
155
156 r = readlink ((char *) link, buffer, sizeof (buffer) - 1);
157 vec_free (link);
158
159 if (r < 1)
160 return 0;
161
Dave Wallace05cc62d2023-10-09 18:05:47 -0400162 buffer[r] = 0;
Damjan Marion40f48102023-08-07 01:07:09 +0200163 p = buffer + r - 1;
164 while (p > buffer && p[-1] != '/')
165 p--;
166
167 while (p[0])
168 vec_add1 (s, p++[0]);
169
Damjan Marion08600cc2023-10-04 18:03:18 +0200170 vec_add1 (s, 0);
Damjan Marion40f48102023-08-07 01:07:09 +0200171 return s;
172}
173
Dave Barachc3799992016-08-15 11:12:27 -0400174clib_error_t *
175unix_proc_file_contents (char *file, u8 ** result)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700176{
177 u8 *rv = 0;
178 uword pos;
179 int bytes, fd;
180
181 /* Unfortunately, stat(/proc/XXX) returns zero... */
182 fd = open (file, O_RDONLY);
183
184 if (fd < 0)
185 return clib_error_return_unix (0, "open `%s'", file);
186
Dave Barachc3799992016-08-15 11:12:27 -0400187 vec_validate (rv, 4095);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700188 pos = 0;
Dave Barachc3799992016-08-15 11:12:27 -0400189 while (1)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700190 {
Dave Barachc3799992016-08-15 11:12:27 -0400191 bytes = read (fd, rv + pos, 4096);
192 if (bytes < 0)
193 {
194 close (fd);
195 vec_free (rv);
196 return clib_error_return_unix (0, "read '%s'", file);
197 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700198
Dave Barachc3799992016-08-15 11:12:27 -0400199 if (bytes == 0)
200 {
Damjan Marion8bea5892022-04-04 22:40:45 +0200201 vec_set_len (rv, pos);
Dave Barachc3799992016-08-15 11:12:27 -0400202 break;
203 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700204 pos += bytes;
Dave Barachc3799992016-08-15 11:12:27 -0400205 vec_validate (rv, pos + 4095);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700206 }
207 *result = rv;
208 close (fd);
209 return 0;
210}
211
212void os_panic (void) __attribute__ ((weak));
213
Damjan Marion4a251d02021-05-06 17:28:12 +0200214__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400215os_panic (void)
216{
217 abort ();
218}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700219
220void os_exit (int) __attribute__ ((weak));
221
Dave Barachc3799992016-08-15 11:12:27 -0400222void
223os_exit (int code)
224{
225 exit (code);
226}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700227
228void os_puts (u8 * string, uword string_length, uword is_error)
229 __attribute__ ((weak));
230
Dave Barachc3799992016-08-15 11:12:27 -0400231void
232os_puts (u8 * string, uword string_length, uword is_error)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700233{
Damjan Marionf55f9b82017-05-10 21:06:28 +0200234 int cpu = os_get_thread_index ();
235 int nthreads = os_get_nthreads ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700236 char buf[64];
237 int fd = is_error ? 2 : 1;
238 struct iovec iovs[2];
239 int n_iovs = 0;
240
Damjan Marionf55f9b82017-05-10 21:06:28 +0200241 if (nthreads > 1)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700242 {
Dave Barachc3799992016-08-15 11:12:27 -0400243 snprintf (buf, sizeof (buf), "%d: ", cpu);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700244
245 iovs[n_iovs].iov_base = buf;
246 iovs[n_iovs].iov_len = strlen (buf);
247 n_iovs++;
248 }
249
250 iovs[n_iovs].iov_base = string;
251 iovs[n_iovs].iov_len = string_length;
252 n_iovs++;
253
254 if (writev (fd, iovs, n_iovs) < 0)
255 ;
256}
257
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200258__clib_export __clib_weak void
Dave Barachc3799992016-08-15 11:12:27 -0400259os_out_of_memory (void)
260{
261 os_panic ();
262}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700263
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200264__clib_export __clib_weak uword
Damjan Marionf55f9b82017-05-10 21:06:28 +0200265os_get_nthreads (void)
Dave Barachc3799992016-08-15 11:12:27 -0400266{
267 return 1;
268}
269
Damjan Marion4b661402024-02-29 16:14:27 +0100270__clib_export clib_bitmap_t *
271os_get_online_cpu_core_bitmap ()
272{
273#if __linux__
Damjan Marion3eb6cbe2024-02-12 19:44:58 +0000274 return clib_sysfs_read_bitmap ("/sys/devices/system/cpu/online");
Damjan Marion4b661402024-02-29 16:14:27 +0100275#else
276 return 0;
277#endif
278}
279
280__clib_export clib_bitmap_t *
hsandid71c32a82024-03-25 17:51:31 +0100281os_get_cpu_affinity_bitmap (int pid)
282{
283#if __linux
284 int index, ret;
285 cpu_set_t cpuset;
286 uword *affinity_cpus;
287
288 clib_bitmap_alloc (affinity_cpus, sizeof (cpu_set_t));
289 clib_bitmap_zero (affinity_cpus);
290
291 __CPU_ZERO_S (sizeof (cpu_set_t), &cpuset);
292
293 ret = syscall (SYS_sched_getaffinity, 0, sizeof (cpu_set_t), &cpuset);
294
295 if (ret < 0)
296 {
297 clib_bitmap_free (affinity_cpus);
298 return 0;
299 }
300
301 for (index = 0; index < sizeof (cpu_set_t); index++)
302 if (__CPU_ISSET_S (index, sizeof (cpu_set_t), &cpuset))
303 clib_bitmap_set (affinity_cpus, index, 1);
304 return affinity_cpus;
305#else
306 return 0;
307#endif
308}
309
310__clib_export clib_bitmap_t *
Damjan Marion4b661402024-02-29 16:14:27 +0100311os_get_online_cpu_node_bitmap ()
312{
313#if __linux__
Damjan Marion3eb6cbe2024-02-12 19:44:58 +0000314 return clib_sysfs_read_bitmap ("/sys/devices/system/node/online");
Damjan Marion4b661402024-02-29 16:14:27 +0100315#else
316 return 0;
317#endif
318}
Damjan Marion3eb6cbe2024-02-12 19:44:58 +0000319__clib_export clib_bitmap_t *
320os_get_cpu_on_node_bitmap (int node)
321{
322#if __linux__
323 return clib_sysfs_read_bitmap ("/sys/devices/system/node/node%u/cpulist",
324 node);
325#else
326 return 0;
327#endif
328}
329
330__clib_export clib_bitmap_t *
331os_get_cpu_with_memory_bitmap ()
332{
333#if __linux__
334 return clib_sysfs_read_bitmap ("/sys/devices/system/node/has_memory");
335#else
336 return 0;
337#endif
338}
339
340__clib_export int
341os_get_cpu_phys_core_id (int cpu_id)
342{
343#if __linux
344 int core_id = -1;
345 clib_error_t *err;
346 u8 *p;
347
348 p =
349 format (0, "/sys/devices/system/cpu/cpu%u/topology/core_id%c", cpu_id, 0);
350 err = clib_sysfs_read ((char *) p, "%d", &core_id);
351 vec_free (p);
352 if (err)
353 {
354 clib_error_free (err);
355 return -1;
356 }
357 return core_id;
358#else
359 return -1;
360#endif
361}
Damjan Marion4b661402024-02-29 16:14:27 +0100362
Tom Jonesab479932024-04-24 10:30:20 +0000363__clib_export u8 *
364os_get_exec_path ()
365{
366 u8 *rv = 0;
367#ifdef __linux__
368 char tmp[PATH_MAX];
369 ssize_t sz = readlink ("/proc/self/exe", tmp, sizeof (tmp));
370
371 if (sz <= 0)
372 return 0;
373#else
374 char tmp[MAXPATHLEN];
375 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
376 size_t sz = MAXPATHLEN;
377
378 if (sysctl (mib, 4, tmp, &sz, NULL, 0) == -1)
379 return 0;
380#endif
381 vec_add (rv, tmp, sz);
382 return rv;
383}
384
Dave Barachc3799992016-08-15 11:12:27 -0400385/*
386 * fd.io coding-style-patch-verification: ON
387 *
388 * Local Variables:
389 * eval: (c-set-style "gnu")
390 * End:
391 */