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