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