blob: e0591ff4604e424c56bc65577228d9ede7527f59 [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>
49#include <sys/uio.h> /* writev */
50#include <fcntl.h>
51#include <stdio.h> /* for sprintf */
Damjan Marion40f48102023-08-07 01:07:09 +020052#include <limits.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070053
Damjan Mariondae1c7e2020-10-17 13:32:25 +020054__clib_export __thread uword __os_thread_index = 0;
55__clib_export __thread uword __os_numa_index = 0;
Damjan Marionf55f9b82017-05-10 21:06:28 +020056
Dave Barachc3799992016-08-15 11:12:27 -040057clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -040058clib_file_n_bytes (char *file, uword * result)
Ed Warnickecb9cada2015-12-08 15:45:58 -070059{
60 struct stat s;
61
62 if (stat (file, &s) < 0)
63 return clib_error_return_unix (0, "stat `%s'", file);
64
65 if (S_ISREG (s.st_mode))
66 *result = s.st_size;
67 else
68 *result = 0;
69
70 return /* no error */ 0;
71}
72
Dave Barachc3799992016-08-15 11:12:27 -040073clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -040074clib_file_read_contents (char *file, u8 * result, uword n_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -070075{
76 int fd = -1;
77 uword n_done, n_left;
Dave Barachc3799992016-08-15 11:12:27 -040078 clib_error_t *error = 0;
79 u8 *v = result;
Ed Warnickecb9cada2015-12-08 15:45:58 -070080
81 if ((fd = open (file, 0)) < 0)
Dave Barachc3799992016-08-15 11:12:27 -040082 return clib_error_return_unix (0, "open `%s'", file);
Ed Warnickecb9cada2015-12-08 15:45:58 -070083
84 n_left = n_bytes;
85 n_done = 0;
86 while (n_left > 0)
87 {
88 int n_read;
89 if ((n_read = read (fd, v + n_done, n_left)) < 0)
90 {
91 error = clib_error_return_unix (0, "open `%s'", file);
92 goto done;
93 }
94
95 /* End of file. */
96 if (n_read == 0)
97 break;
98
99 n_left -= n_read;
100 n_done += n_read;
101 }
102
103 if (n_left > 0)
104 {
Dave Barachc3799992016-08-15 11:12:27 -0400105 error =
106 clib_error_return (0,
107 " `%s' expected to read %wd bytes; read only %wd",
108 file, n_bytes, n_bytes - n_left);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700109 goto done;
110 }
111
Dave Barachc3799992016-08-15 11:12:27 -0400112done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700113 close (fd);
114 return error;
115}
116
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200117__clib_export clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -0400118clib_file_contents (char *file, u8 ** result)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700119{
120 uword n_bytes;
Dave Barachc3799992016-08-15 11:12:27 -0400121 clib_error_t *error = 0;
122 u8 *v;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700123
Dave Barach59b25652017-09-10 15:04:27 -0400124 if ((error = clib_file_n_bytes (file, &n_bytes)))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700125 return error;
126
127 v = 0;
128 vec_resize (v, n_bytes);
129
Dave Barach59b25652017-09-10 15:04:27 -0400130 error = clib_file_read_contents (file, v, n_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700131
132 if (error)
133 vec_free (v);
134 else
135 *result = v;
136
137 return error;
138}
139
Damjan Marion40f48102023-08-07 01:07:09 +0200140__clib_export u8 *
141clib_file_get_resolved_basename (char *fmt, ...)
142{
143 va_list va;
144 char *p, buffer[PATH_MAX];
145 u8 *link, *s = 0;
146 int r;
147
148 va_start (va, fmt);
149 link = va_format (0, fmt, &va);
150 va_end (va);
151 vec_add1 (link, 0);
152
153 r = readlink ((char *) link, buffer, sizeof (buffer) - 1);
154 vec_free (link);
155
156 if (r < 1)
157 return 0;
158
Dave Wallace05cc62d2023-10-09 18:05:47 -0400159 buffer[r] = 0;
Damjan Marion40f48102023-08-07 01:07:09 +0200160 p = buffer + r - 1;
161 while (p > buffer && p[-1] != '/')
162 p--;
163
164 while (p[0])
165 vec_add1 (s, p++[0]);
166
Damjan Marion08600cc2023-10-04 18:03:18 +0200167 vec_add1 (s, 0);
Damjan Marion40f48102023-08-07 01:07:09 +0200168 return s;
169}
170
Dave Barachc3799992016-08-15 11:12:27 -0400171clib_error_t *
172unix_proc_file_contents (char *file, u8 ** result)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700173{
174 u8 *rv = 0;
175 uword pos;
176 int bytes, fd;
177
178 /* Unfortunately, stat(/proc/XXX) returns zero... */
179 fd = open (file, O_RDONLY);
180
181 if (fd < 0)
182 return clib_error_return_unix (0, "open `%s'", file);
183
Dave Barachc3799992016-08-15 11:12:27 -0400184 vec_validate (rv, 4095);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700185 pos = 0;
Dave Barachc3799992016-08-15 11:12:27 -0400186 while (1)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700187 {
Dave Barachc3799992016-08-15 11:12:27 -0400188 bytes = read (fd, rv + pos, 4096);
189 if (bytes < 0)
190 {
191 close (fd);
192 vec_free (rv);
193 return clib_error_return_unix (0, "read '%s'", file);
194 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700195
Dave Barachc3799992016-08-15 11:12:27 -0400196 if (bytes == 0)
197 {
Damjan Marion8bea5892022-04-04 22:40:45 +0200198 vec_set_len (rv, pos);
Dave Barachc3799992016-08-15 11:12:27 -0400199 break;
200 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700201 pos += bytes;
Dave Barachc3799992016-08-15 11:12:27 -0400202 vec_validate (rv, pos + 4095);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700203 }
204 *result = rv;
205 close (fd);
206 return 0;
207}
208
209void os_panic (void) __attribute__ ((weak));
210
Damjan Marion4a251d02021-05-06 17:28:12 +0200211__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400212os_panic (void)
213{
214 abort ();
215}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700216
217void os_exit (int) __attribute__ ((weak));
218
Dave Barachc3799992016-08-15 11:12:27 -0400219void
220os_exit (int code)
221{
222 exit (code);
223}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700224
225void os_puts (u8 * string, uword string_length, uword is_error)
226 __attribute__ ((weak));
227
Dave Barachc3799992016-08-15 11:12:27 -0400228void
229os_puts (u8 * string, uword string_length, uword is_error)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700230{
Damjan Marionf55f9b82017-05-10 21:06:28 +0200231 int cpu = os_get_thread_index ();
232 int nthreads = os_get_nthreads ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700233 char buf[64];
234 int fd = is_error ? 2 : 1;
235 struct iovec iovs[2];
236 int n_iovs = 0;
237
Damjan Marionf55f9b82017-05-10 21:06:28 +0200238 if (nthreads > 1)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700239 {
Dave Barachc3799992016-08-15 11:12:27 -0400240 snprintf (buf, sizeof (buf), "%d: ", cpu);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241
242 iovs[n_iovs].iov_base = buf;
243 iovs[n_iovs].iov_len = strlen (buf);
244 n_iovs++;
245 }
246
247 iovs[n_iovs].iov_base = string;
248 iovs[n_iovs].iov_len = string_length;
249 n_iovs++;
250
251 if (writev (fd, iovs, n_iovs) < 0)
252 ;
253}
254
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200255__clib_export __clib_weak void
Dave Barachc3799992016-08-15 11:12:27 -0400256os_out_of_memory (void)
257{
258 os_panic ();
259}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700260
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200261__clib_export __clib_weak uword
Damjan Marionf55f9b82017-05-10 21:06:28 +0200262os_get_nthreads (void)
Dave Barachc3799992016-08-15 11:12:27 -0400263{
264 return 1;
265}
266
Damjan Marion4b661402024-02-29 16:14:27 +0100267__clib_export clib_bitmap_t *
268os_get_online_cpu_core_bitmap ()
269{
270#if __linux__
Damjan Marion3eb6cbe2024-02-12 19:44:58 +0000271 return clib_sysfs_read_bitmap ("/sys/devices/system/cpu/online");
Damjan Marion4b661402024-02-29 16:14:27 +0100272#else
273 return 0;
274#endif
275}
276
277__clib_export clib_bitmap_t *
278os_get_online_cpu_node_bitmap ()
279{
280#if __linux__
Damjan Marion3eb6cbe2024-02-12 19:44:58 +0000281 return clib_sysfs_read_bitmap ("/sys/devices/system/node/online");
Damjan Marion4b661402024-02-29 16:14:27 +0100282#else
283 return 0;
284#endif
285}
Damjan Marion3eb6cbe2024-02-12 19:44:58 +0000286__clib_export clib_bitmap_t *
287os_get_cpu_on_node_bitmap (int node)
288{
289#if __linux__
290 return clib_sysfs_read_bitmap ("/sys/devices/system/node/node%u/cpulist",
291 node);
292#else
293 return 0;
294#endif
295}
296
297__clib_export clib_bitmap_t *
298os_get_cpu_with_memory_bitmap ()
299{
300#if __linux__
301 return clib_sysfs_read_bitmap ("/sys/devices/system/node/has_memory");
302#else
303 return 0;
304#endif
305}
306
307__clib_export int
308os_get_cpu_phys_core_id (int cpu_id)
309{
310#if __linux
311 int core_id = -1;
312 clib_error_t *err;
313 u8 *p;
314
315 p =
316 format (0, "/sys/devices/system/cpu/cpu%u/topology/core_id%c", cpu_id, 0);
317 err = clib_sysfs_read ((char *) p, "%d", &core_id);
318 vec_free (p);
319 if (err)
320 {
321 clib_error_free (err);
322 return -1;
323 }
324 return core_id;
325#else
326 return -1;
327#endif
328}
Damjan Marion4b661402024-02-29 16:14:27 +0100329
Dave Barachc3799992016-08-15 11:12:27 -0400330/*
331 * fd.io coding-style-patch-verification: ON
332 *
333 * Local Variables:
334 * eval: (c-set-style "gnu")
335 * End:
336 */