Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2020 Intel Corporation
3 : : */
4 : :
5 : : #include <ctype.h>
6 : : #include <errno.h>
7 : : #include <stdlib.h>
8 : : #include <inttypes.h>
9 : :
10 : : #undef RTE_USE_LIBBSD
11 : : #include <stdbool.h>
12 : :
13 : : #include <eal_export.h>
14 : : #include <rte_string_fns.h>
15 : :
16 : : #include "telemetry_data.h"
17 : :
18 : : #define RTE_TEL_UINT_HEX_STR_BUF_LEN 64
19 : :
20 : : RTE_EXPORT_SYMBOL(rte_tel_data_start_array)
21 : : int
22 : 33 : rte_tel_data_start_array(struct rte_tel_data *d, enum rte_tel_value_type type)
23 : : {
24 : 33 : enum tel_container_types array_types[] = {
25 : : [RTE_TEL_STRING_VAL] = TEL_ARRAY_STRING,
26 : : [RTE_TEL_INT_VAL] = TEL_ARRAY_INT,
27 : : [RTE_TEL_UINT_VAL] = TEL_ARRAY_UINT,
28 : : [RTE_TEL_CONTAINER] = TEL_ARRAY_CONTAINER,
29 : : };
30 : 33 : d->type = array_types[type];
31 : 33 : d->data_len = 0;
32 : 33 : return 0;
33 : : }
34 : :
35 : : RTE_EXPORT_SYMBOL(rte_tel_data_start_dict)
36 : : int
37 : 13 : rte_tel_data_start_dict(struct rte_tel_data *d)
38 : : {
39 : 13 : d->type = TEL_DICT;
40 : 13 : d->data_len = 0;
41 : 13 : return 0;
42 : : }
43 : :
44 : : RTE_EXPORT_SYMBOL(rte_tel_data_string)
45 : : int
46 : 2 : rte_tel_data_string(struct rte_tel_data *d, const char *str)
47 : : {
48 : 2 : d->type = TEL_STRING;
49 [ - + ]: 2 : d->data_len = strlcpy(d->data.str, str, sizeof(d->data.str));
50 [ - + ]: 2 : if (d->data_len >= RTE_TEL_MAX_SINGLE_STRING_LEN) {
51 : 0 : d->data_len = RTE_TEL_MAX_SINGLE_STRING_LEN - 1;
52 : 0 : return E2BIG; /* not necessarily and error, just truncation */
53 : : }
54 : : return 0;
55 : : }
56 : :
57 : : RTE_EXPORT_SYMBOL(rte_tel_data_add_array_string)
58 : : int
59 : 29 : rte_tel_data_add_array_string(struct rte_tel_data *d, const char *str)
60 : : {
61 [ + - ]: 29 : if (d->type != TEL_ARRAY_STRING)
62 : : return -EINVAL;
63 [ + - ]: 29 : if (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)
64 : : return -ENOSPC;
65 [ - + ]: 29 : const size_t bytes = strlcpy(d->data.array[d->data_len++].sval,
66 : : str, RTE_TEL_MAX_STRING_LEN);
67 [ - + ]: 29 : return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;
68 : : }
69 : :
70 : : RTE_EXPORT_SYMBOL(rte_tel_data_add_array_int)
71 : : int
72 : 25 : rte_tel_data_add_array_int(struct rte_tel_data *d, int64_t x)
73 : : {
74 [ + - ]: 25 : if (d->type != TEL_ARRAY_INT)
75 : : return -EINVAL;
76 [ + - ]: 25 : if (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)
77 : : return -ENOSPC;
78 : 25 : d->data.array[d->data_len++].ival = x;
79 : 25 : return 0;
80 : : }
81 : :
82 : : RTE_EXPORT_SYMBOL(rte_tel_data_add_array_uint)
83 : : int
84 : 35 : rte_tel_data_add_array_uint(struct rte_tel_data *d, uint64_t x)
85 : : {
86 [ + - ]: 35 : if (d->type != TEL_ARRAY_UINT)
87 : : return -EINVAL;
88 [ + - ]: 35 : if (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)
89 : : return -ENOSPC;
90 : 35 : d->data.array[d->data_len++].uval = x;
91 : 35 : return 0;
92 : : }
93 : :
94 : : RTE_EXPORT_SYMBOL(rte_tel_data_add_array_u64)
95 : : int
96 : 0 : rte_tel_data_add_array_u64(struct rte_tel_data *d, uint64_t x)
97 : : {
98 : 0 : return rte_tel_data_add_array_uint(d, x);
99 : : }
100 : :
101 : : RTE_EXPORT_SYMBOL(rte_tel_data_add_array_container)
102 : : int
103 : 10 : rte_tel_data_add_array_container(struct rte_tel_data *d,
104 : : struct rte_tel_data *val, int keep)
105 : : {
106 [ + - ]: 10 : if (d->type != TEL_ARRAY_CONTAINER ||
107 : 10 : (val->type != TEL_ARRAY_UINT
108 : : && val->type != TEL_ARRAY_INT
109 [ + - ]: 10 : && val->type != TEL_ARRAY_STRING))
110 : : return -EINVAL;
111 [ + - ]: 10 : if (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)
112 : : return -ENOSPC;
113 : :
114 : 10 : d->data.array[d->data_len].container.data = val;
115 : 10 : d->data.array[d->data_len++].container.keep = !!keep;
116 : 10 : return 0;
117 : : }
118 : :
119 : : static int
120 : 24 : rte_tel_uint_to_hex_encoded_str(char *buf, size_t buf_len, uint64_t val,
121 : : uint8_t display_bitwidth)
122 : : {
123 : 24 : int spec_hex_width = (display_bitwidth + 3) / 4;
124 : : int len;
125 : :
126 [ + + ]: 24 : if (display_bitwidth != 0)
127 : : len = snprintf(buf, buf_len, "0x%0*" PRIx64, spec_hex_width, val);
128 : : else
129 : : len = snprintf(buf, buf_len, "0x%" PRIx64, val);
130 : :
131 [ - + ]: 24 : return len < (int)buf_len ? 0 : -EINVAL;
132 : : }
133 : :
134 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_tel_data_add_array_uint_hex, 23.03)
135 : : int
136 : 16 : rte_tel_data_add_array_uint_hex(struct rte_tel_data *d, uint64_t val,
137 : : uint8_t display_bitwidth)
138 : : {
139 : : char hex_str[RTE_TEL_UINT_HEX_STR_BUF_LEN];
140 : : int ret;
141 : :
142 : 16 : ret = rte_tel_uint_to_hex_encoded_str(hex_str,
143 : : RTE_TEL_UINT_HEX_STR_BUF_LEN, val, display_bitwidth);
144 [ + - ]: 16 : if (ret != 0)
145 : : return ret;
146 : :
147 : 16 : return rte_tel_data_add_array_string(d, hex_str);
148 : : }
149 : :
150 : : static bool
151 : 36 : valid_name(const char *name)
152 : : {
153 : : /* non-alphanumeric characters allowed in names */
154 : : static const char allowed[128] = { ['_'] = 1, ['/'] = 1 };
155 : :
156 [ + + ]: 257 : for (; *name != '\0'; name++) {
157 [ + + ]: 221 : if (isalnum(*name))
158 : 185 : continue;
159 [ + - + - ]: 36 : if ((size_t)*name >= RTE_DIM(allowed) || allowed[(int)*name] == 0)
160 : : return false;
161 : : }
162 : : return true;
163 : : }
164 : :
165 : : RTE_EXPORT_SYMBOL(rte_tel_data_add_dict_string)
166 : : int
167 : 13 : rte_tel_data_add_dict_string(struct rte_tel_data *d, const char *name,
168 : : const char *val)
169 : : {
170 : 13 : struct tel_dict_entry *e = &d->data.dict[d->data_len];
171 : : size_t nbytes, vbytes;
172 : :
173 [ + - ]: 13 : if (d->type != TEL_DICT)
174 : : return -EINVAL;
175 [ + - ]: 13 : if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES)
176 : : return -ENOSPC;
177 : :
178 [ + - ]: 13 : if (!valid_name(name))
179 : : return -EINVAL;
180 : :
181 : 13 : d->data_len++;
182 : 13 : e->type = RTE_TEL_STRING_VAL;
183 [ - + ]: 13 : vbytes = strlcpy(e->value.sval, val, RTE_TEL_MAX_STRING_LEN);
184 : 13 : nbytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN);
185 : 13 : if (vbytes >= RTE_TEL_MAX_STRING_LEN ||
186 [ - + ]: 13 : nbytes >= RTE_TEL_MAX_STRING_LEN)
187 : 0 : return E2BIG;
188 : : return 0;
189 : : }
190 : :
191 : : RTE_EXPORT_SYMBOL(rte_tel_data_add_dict_int)
192 : : int
193 : 5 : rte_tel_data_add_dict_int(struct rte_tel_data *d, const char *name, int64_t val)
194 : : {
195 : 5 : struct tel_dict_entry *e = &d->data.dict[d->data_len];
196 [ + - ]: 5 : if (d->type != TEL_DICT)
197 : : return -EINVAL;
198 [ + - ]: 5 : if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES)
199 : : return -ENOSPC;
200 : :
201 [ + - ]: 5 : if (!valid_name(name))
202 : : return -EINVAL;
203 : :
204 : 5 : d->data_len++;
205 : 5 : e->type = RTE_TEL_INT_VAL;
206 : 5 : e->value.ival = val;
207 [ - + ]: 5 : const size_t bytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN);
208 [ - + ]: 5 : return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;
209 : : }
210 : :
211 : : RTE_EXPORT_SYMBOL(rte_tel_data_add_dict_uint)
212 : : int
213 : 5 : rte_tel_data_add_dict_uint(struct rte_tel_data *d,
214 : : const char *name, uint64_t val)
215 : : {
216 : 5 : struct tel_dict_entry *e = &d->data.dict[d->data_len];
217 [ + - ]: 5 : if (d->type != TEL_DICT)
218 : : return -EINVAL;
219 [ + - ]: 5 : if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES)
220 : : return -ENOSPC;
221 : :
222 [ + - ]: 5 : if (!valid_name(name))
223 : : return -EINVAL;
224 : :
225 : 5 : d->data_len++;
226 : 5 : e->type = RTE_TEL_UINT_VAL;
227 : 5 : e->value.uval = val;
228 [ - + ]: 5 : const size_t bytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN);
229 [ - + ]: 5 : return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;
230 : : }
231 : :
232 : : RTE_EXPORT_SYMBOL(rte_tel_data_add_dict_u64)
233 : : int
234 : 0 : rte_tel_data_add_dict_u64(struct rte_tel_data *d, const char *name, uint64_t val)
235 : : {
236 : 0 : return rte_tel_data_add_dict_uint(d, name, val);
237 : : }
238 : :
239 : : RTE_EXPORT_SYMBOL(rte_tel_data_add_dict_container)
240 : : int
241 : 13 : rte_tel_data_add_dict_container(struct rte_tel_data *d, const char *name,
242 : : struct rte_tel_data *val, int keep)
243 : : {
244 : 13 : struct tel_dict_entry *e = &d->data.dict[d->data_len];
245 : :
246 [ + - ]: 13 : if (d->type != TEL_DICT || (val->type != TEL_ARRAY_UINT
247 : : && val->type != TEL_ARRAY_INT
248 : : && val->type != TEL_ARRAY_STRING
249 [ + - ]: 13 : && val->type != TEL_DICT))
250 : : return -EINVAL;
251 [ + - ]: 13 : if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES)
252 : : return -ENOSPC;
253 : :
254 [ + - ]: 13 : if (!valid_name(name))
255 : : return -EINVAL;
256 : :
257 : 13 : d->data_len++;
258 : 13 : e->type = RTE_TEL_CONTAINER;
259 : 13 : e->value.container.data = val;
260 : 13 : e->value.container.keep = !!keep;
261 [ - + ]: 13 : const size_t bytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN);
262 [ - + ]: 13 : return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;
263 : : }
264 : :
265 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_tel_data_add_dict_uint_hex, 23.03)
266 : : int
267 : 8 : rte_tel_data_add_dict_uint_hex(struct rte_tel_data *d, const char *name,
268 : : uint64_t val, uint8_t display_bitwidth)
269 : : {
270 : : char hex_str[RTE_TEL_UINT_HEX_STR_BUF_LEN];
271 : : int ret;
272 : :
273 : 8 : ret = rte_tel_uint_to_hex_encoded_str(hex_str,
274 : : RTE_TEL_UINT_HEX_STR_BUF_LEN, val, display_bitwidth);
275 [ + - ]: 8 : if (ret != 0)
276 : : return ret;
277 : :
278 : :
279 : 8 : return rte_tel_data_add_dict_string(d, name, hex_str);
280 : : }
281 : :
282 : : RTE_EXPORT_SYMBOL(rte_tel_data_alloc)
283 : : struct rte_tel_data *
284 : 23 : rte_tel_data_alloc(void)
285 : : {
286 : 23 : return malloc(sizeof(struct rte_tel_data));
287 : : }
288 : :
289 : : RTE_EXPORT_SYMBOL(rte_tel_data_free)
290 : : void
291 : 23 : rte_tel_data_free(struct rte_tel_data *data)
292 : : {
293 : 23 : free(data);
294 : 23 : }
|