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