FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
sysfs.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 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 #include <vppinfra/clib.h>
17 #include <vppinfra/clib_error.h>
18 #include <vppinfra/format.h>
19 #include <vppinfra/bitmap.h>
20 
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <dirent.h>
25 
26 __clib_export clib_error_t *
27 clib_sysfs_write (char *file_name, char *fmt, ...)
28 {
29  u8 *s;
30  int fd;
31  clib_error_t *error = 0;
32 
33  fd = open (file_name, O_WRONLY);
34  if (fd < 0)
35  return clib_error_return_unix (0, "open `%s'", file_name);
36 
37  va_list va;
38  va_start (va, fmt);
39  s = va_format (0, fmt, &va);
40  va_end (va);
41 
42  if (write (fd, s, vec_len (s)) < 0)
43  error = clib_error_return_unix (0, "write `%s'", file_name);
44 
45  vec_free (s);
46  close (fd);
47  return error;
48 }
49 
50 __clib_export clib_error_t *
51 clib_sysfs_read (char *file_name, char *fmt, ...)
52 {
53  unformat_input_t input;
54  u8 *s = 0;
55  int fd;
56  ssize_t sz;
57  uword result;
58 
59  fd = open (file_name, O_RDONLY);
60  if (fd < 0)
61  return clib_error_return_unix (0, "open `%s'", file_name);
62 
63  vec_validate (s, 4095);
64 
65  sz = read (fd, s, vec_len (s));
66  if (sz < 0)
67  {
68  close (fd);
69  vec_free (s);
70  return clib_error_return_unix (0, "read `%s'", file_name);
71  }
72 
73  _vec_len (s) = sz;
74  unformat_init_vector (&input, s);
75 
76  va_list va;
77  va_start (va, fmt);
78  result = va_unformat (&input, fmt, &va);
79  va_end (va);
80 
81  vec_free (s);
82  close (fd);
83 
84  if (result == 0)
85  return clib_error_return (0, "unformat error");
86 
87  return 0;
88 }
89 
90 __clib_export u8 *
92 {
93  char *p, buffer[64];
95  u8 *s = 0;
96  int r;
97 
98  r = readlink (link, buffer, sizeof (buffer) - 1);
99 
100  if (r < 0)
101  return 0;
102 
103  buffer[r] = 0;
104  p = strrchr (buffer, '/');
105 
106  if (!p)
107  return 0;
108 
109  unformat_init_string (&in, p + 1, strlen (p + 1));
110  if (unformat (&in, "%s", &s) != 1)
111  clib_unix_warning ("no string?");
112  unformat_free (&in);
113 
114  return s;
115 }
116 
117 clib_error_t *
118 clib_sysfs_set_nr_hugepages (int numa_node, int log2_page_size, int nr)
119 {
120  clib_error_t *error = 0;
121  struct stat sb;
122  u8 *p = 0;
123  uword page_size;
124 
125  if (log2_page_size == 0)
126  log2_page_size = min_log2 (clib_mem_get_default_hugepage_size ());
127 
128  page_size = 1ULL << (log2_page_size - 10);
129 
130  p = format (p, "/sys/devices/system/node/node%u%c", numa_node, 0);
131 
132  if (stat ((char *) p, &sb) == 0)
133  {
134  if (S_ISDIR (sb.st_mode) == 0)
135  {
136  error = clib_error_return (0, "'%s' is not directory", p);
137  goto done;
138  }
139  }
140  else if (numa_node == 0)
141  {
142  vec_reset_length (p);
143  p = format (p, "/sys/kernel/mm%c", 0);
144  if (stat ((char *) p, &sb) < 0 || S_ISDIR (sb.st_mode) == 0)
145  {
146  error = clib_error_return (0, "'%s' does not exist or it is not "
147  "directory", p);
148  goto done;
149  }
150  }
151  else
152  {
153  error = clib_error_return (0, "'%s' does not exist", p);
154  goto done;
155  }
156 
157  _vec_len (p) -= 1;
158  p = format (p, "/hugepages/hugepages-%ukB/nr_hugepages%c", page_size, 0);
159  clib_sysfs_write ((char *) p, "%d", nr);
160 
161 done:
162  vec_free (p);
163  return error;
164 }
165 
166 
167 static clib_error_t *
168 clib_sysfs_get_xxx_hugepages (char *type, int numa_node,
169  int log2_page_size, int *val)
170 {
171  clib_error_t *error = 0;
172  struct stat sb;
173  u8 *p = 0;
174 
175  uword page_size;
176 
177  if (log2_page_size == 0)
178  log2_page_size = min_log2 (clib_mem_get_default_hugepage_size ());
179 
180  page_size = 1ULL << (log2_page_size - 10);
181 
182 
183  p = format (p, "/sys/devices/system/node/node%u%c", numa_node, 0);
184 
185  if (stat ((char *) p, &sb) == 0)
186  {
187  if (S_ISDIR (sb.st_mode) == 0)
188  {
189  error = clib_error_return (0, "'%s' is not directory", p);
190  goto done;
191  }
192  }
193  else if (numa_node == 0)
194  {
195  vec_reset_length (p);
196  p = format (p, "/sys/kernel/mm%c", 0);
197  if (stat ((char *) p, &sb) < 0 || S_ISDIR (sb.st_mode) == 0)
198  {
199  error = clib_error_return (0, "'%s' does not exist or it is not "
200  "directory", p);
201  goto done;
202  }
203  }
204  else
205  {
206  error = clib_error_return (0, "'%s' does not exist", p);
207  goto done;
208  }
209 
210  _vec_len (p) -= 1;
211  p = format (p, "/hugepages/hugepages-%ukB/%s_hugepages%c", page_size,
212  type, 0);
213  error = clib_sysfs_read ((char *) p, "%d", val);
214 
215 done:
216  vec_free (p);
217  return error;
218 }
219 
220 clib_error_t *
221 clib_sysfs_get_free_hugepages (int numa_node, int log2_page_size, int *v)
222 {
223  return clib_sysfs_get_xxx_hugepages ("free", numa_node, log2_page_size, v);
224 }
225 
226 clib_error_t *
227 clib_sysfs_get_nr_hugepages (int numa_node, int log2_page_size, int *v)
228 {
229  return clib_sysfs_get_xxx_hugepages ("nr", numa_node, log2_page_size, v);
230 }
231 
232 clib_error_t *
233 clib_sysfs_get_surplus_hugepages (int numa_node, int log2_page_size, int *v)
234 {
235  return clib_sysfs_get_xxx_hugepages ("surplus", numa_node, log2_page_size,
236  v);
237 }
238 
239 clib_error_t *
240 clib_sysfs_prealloc_hugepages (int numa_node, int log2_page_size, int nr)
241 {
242  clib_error_t *error = 0;
243  int n, needed;
244  uword page_size;
245 
246  if (log2_page_size == 0)
247  log2_page_size = min_log2 (clib_mem_get_default_hugepage_size ());
248 
249  page_size = 1ULL << (log2_page_size - 10);
250 
251  error = clib_sysfs_get_free_hugepages (numa_node, log2_page_size, &n);
252  if (error)
253  return error;
254  needed = nr - n;
255  if (needed <= 0)
256  return 0;
257 
258  error = clib_sysfs_get_nr_hugepages (numa_node, log2_page_size, &n);
259  if (error)
260  return error;
261  clib_warning ("pre-allocating %u additional %uK hugepages on numa node %u",
262  needed, page_size, numa_node);
263  return clib_sysfs_set_nr_hugepages (numa_node, log2_page_size, n + needed);
264 }
265 
266 __clib_export uword *
268 {
269  FILE *fp;
270  uword *r = 0;
271 
272  fp = fopen (filename, "r");
273 
274  if (fp != NULL)
275  {
276  u8 *buffer = 0;
277  vec_validate (buffer, 256 - 1);
278  if (fgets ((char *) buffer, 256, fp))
279  {
280  unformat_input_t in;
281  unformat_init_string (&in, (char *) buffer,
282  strlen ((char *) buffer));
283  if (unformat (&in, "%U", unformat_bitmap_list, &r) != 1)
284  clib_warning ("unformat_bitmap_list failed");
285  unformat_free (&in);
286  }
287  vec_free (buffer);
288  fclose (fp);
289  }
290  return r;
291 }
292 
293 /*
294  * fd.io coding-style-patch-verification: ON
295  *
296  * Local Variables:
297  * eval: (c-set-style "gnu")
298  * End:
299  */
vec_reset_length
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
Definition: vec_bootstrap.h:194
clib_sysfs_link_to_name
__clib_export u8 * clib_sysfs_link_to_name(char *link)
Definition: sysfs.c:91
unformat_init_vector
void unformat_init_vector(unformat_input_t *input, u8 *vector_string)
Definition: unformat.c:1037
buffer
char * buffer
Definition: cJSON.h:163
bitmap.h
clib.h
clib_mem_get_default_hugepage_size
static_always_inline uword clib_mem_get_default_hugepage_size(void)
Definition: mem.h:489
clib_error_return
#define clib_error_return(e, args...)
Definition: error.h:99
clib_sysfs_set_nr_hugepages
clib_error_t * clib_sysfs_set_nr_hugepages(int numa_node, int log2_page_size, int nr)
Definition: sysfs.c:118
clib_sysfs_prealloc_hugepages
clib_error_t * clib_sysfs_prealloc_hugepages(int numa_node, int log2_page_size, int nr)
Definition: sysfs.c:240
va_format
__clib_export u8 * va_format(u8 *s, const char *fmt, va_list *va)
Definition: format.c:391
unformat_input_t
struct _unformat_input_t unformat_input_t
clib_sysfs_get_xxx_hugepages
static clib_error_t * clib_sysfs_get_xxx_hugepages(char *type, int numa_node, int log2_page_size, int *val)
Definition: sysfs.c:168
r
vnet_hw_if_output_node_runtime_t * r
Definition: interface_output.c:1089
clib_unix_warning
#define clib_unix_warning(format, args...)
Definition: error.h:68
error
Definition: cJSON.c:88
clib_sysfs_write
__clib_export clib_error_t * clib_sysfs_write(char *file_name, char *fmt,...)
Definition: sysfs.c:27
clib_sysfs_get_free_hugepages
clib_error_t * clib_sysfs_get_free_hugepages(int numa_node, int log2_page_size, int *v)
Definition: sysfs.c:221
unformat
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
clib_sysfs_read
__clib_export clib_error_t * clib_sysfs_read(char *file_name, char *fmt,...)
Definition: sysfs.c:51
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
unformat_free
static void unformat_free(unformat_input_t *i)
Definition: format.h:155
clib_sysfs_get_nr_hugepages
clib_error_t * clib_sysfs_get_nr_hugepages(int numa_node, int log2_page_size, int *v)
Definition: sysfs.c:227
uword
u64 uword
Definition: types.h:112
va_unformat
uword va_unformat(unformat_input_t *i, const char *fmt, va_list *args)
Definition: unformat.c:839
vec_validate
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment)
Definition: vec.h:523
format.h
fmt
int cJSON_bool fmt
Definition: cJSON.h:160
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
unformat_init_string
void unformat_init_string(unformat_input_t *input, char *string, int string_len)
Definition: unformat.c:1029
format
description fragment has unexpected format
Definition: map.api:433
clib_error_return_unix
#define clib_error_return_unix(e, args...)
Definition: error.h:102
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
clib_error.h
clib_warning
#define clib_warning(format, args...)
Definition: error.h:59
clib_sysfs_get_surplus_hugepages
clib_error_t * clib_sysfs_get_surplus_hugepages(int numa_node, int log2_page_size, int *v)
Definition: sysfs.c:233
min_log2
static uword min_log2(uword x)
Definition: clib.h:176
unformat_bitmap_list
__clib_export uword unformat_bitmap_list(unformat_input_t *input, va_list *va)
unformat a list of bit ranges into a bitmap (eg "0-3,5-7,11" )
Definition: bitmap.c:55
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
clib_sysfs_list_to_bitmap
__clib_export uword * clib_sysfs_list_to_bitmap(char *filename)
Definition: sysfs.c:267