blob: 5008f82c49375f44713c9810aa64d9cfc4c3cde4 [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 Jonesf4c79962024-04-25 14:25:06 +000045#elif defined(__FreeBSD__)
Tom Jonesab479932024-04-24 10:30:20 +000046#include <sys/sysctl.h>
Tom Jonesf4c79962024-04-25 14:25:06 +000047#include <sys/param.h>
Damjan Marion4b661402024-02-29 16:14:27 +010048#endif
Ed Warnickecb9cada2015-12-08 15:45:58 -070049
50#include <sys/stat.h>
51#include <sys/types.h>
52#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 *
281os_get_online_cpu_node_bitmap ()
282{
283#if __linux__
Damjan Marion3eb6cbe2024-02-12 19:44:58 +0000284 return clib_sysfs_read_bitmap ("/sys/devices/system/node/online");
Damjan Marion4b661402024-02-29 16:14:27 +0100285#else
286 return 0;
287#endif
288}
Damjan Marion3eb6cbe2024-02-12 19:44:58 +0000289__clib_export clib_bitmap_t *
290os_get_cpu_on_node_bitmap (int node)
291{
292#if __linux__
293 return clib_sysfs_read_bitmap ("/sys/devices/system/node/node%u/cpulist",
294 node);
295#else
296 return 0;
297#endif
298}
299
300__clib_export clib_bitmap_t *
301os_get_cpu_with_memory_bitmap ()
302{
303#if __linux__
304 return clib_sysfs_read_bitmap ("/sys/devices/system/node/has_memory");
305#else
306 return 0;
307#endif
308}
309
310__clib_export int
311os_get_cpu_phys_core_id (int cpu_id)
312{
313#if __linux
314 int core_id = -1;
315 clib_error_t *err;
316 u8 *p;
317
318 p =
319 format (0, "/sys/devices/system/cpu/cpu%u/topology/core_id%c", cpu_id, 0);
320 err = clib_sysfs_read ((char *) p, "%d", &core_id);
321 vec_free (p);
322 if (err)
323 {
324 clib_error_free (err);
325 return -1;
326 }
327 return core_id;
328#else
329 return -1;
330#endif
331}
Damjan Marion4b661402024-02-29 16:14:27 +0100332
Tom Jonesab479932024-04-24 10:30:20 +0000333__clib_export u8 *
334os_get_exec_path ()
335{
336 u8 *rv = 0;
337#ifdef __linux__
338 char tmp[PATH_MAX];
339 ssize_t sz = readlink ("/proc/self/exe", tmp, sizeof (tmp));
340
341 if (sz <= 0)
342 return 0;
343#else
344 char tmp[MAXPATHLEN];
345 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
346 size_t sz = MAXPATHLEN;
347
348 if (sysctl (mib, 4, tmp, &sz, NULL, 0) == -1)
349 return 0;
350#endif
351 vec_add (rv, tmp, sz);
352 return rv;
353}
354
Dave Barachc3799992016-08-15 11:12:27 -0400355/*
356 * fd.io coding-style-patch-verification: ON
357 *
358 * Local Variables:
359 * eval: (c-set-style "gnu")
360 * End:
361 */