xref: /dpdk/lib/telemetry/telemetry_data.c (revision 87d396163c005deb8d9f72ec0977f19e5edd8f47)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020 Intel Corporation
3  */
4 
5 #include <errno.h>
6 #include <stdlib.h>
7 
8 #undef RTE_USE_LIBBSD
9 #include <stdbool.h>
10 
11 #include <rte_string_fns.h>
12 
13 #include "telemetry_data.h"
14 
15 int
16 rte_tel_data_start_array(struct rte_tel_data *d, enum rte_tel_value_type type)
17 {
18 	enum tel_container_types array_types[] = {
19 			RTE_TEL_ARRAY_STRING, /* RTE_TEL_STRING_VAL = 0 */
20 			RTE_TEL_ARRAY_INT,    /* RTE_TEL_INT_VAL = 1 */
21 			RTE_TEL_ARRAY_U64,    /* RTE_TEL_u64_VAL = 2 */
22 			RTE_TEL_ARRAY_CONTAINER, /* RTE_TEL_CONTAINER = 3 */
23 	};
24 	d->type = array_types[type];
25 	d->data_len = 0;
26 	return 0;
27 }
28 
29 int
30 rte_tel_data_start_dict(struct rte_tel_data *d)
31 {
32 	d->type = RTE_TEL_DICT;
33 	d->data_len = 0;
34 	return 0;
35 }
36 
37 int
38 rte_tel_data_string(struct rte_tel_data *d, const char *str)
39 {
40 	d->type = RTE_TEL_STRING;
41 	d->data_len = strlcpy(d->data.str, str, sizeof(d->data.str));
42 	if (d->data_len >= RTE_TEL_MAX_SINGLE_STRING_LEN) {
43 		d->data_len = RTE_TEL_MAX_SINGLE_STRING_LEN - 1;
44 		return E2BIG; /* not necessarily and error, just truncation */
45 	}
46 	return 0;
47 }
48 
49 int
50 rte_tel_data_add_array_string(struct rte_tel_data *d, const char *str)
51 {
52 	if (d->type != RTE_TEL_ARRAY_STRING)
53 		return -EINVAL;
54 	if (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)
55 		return -ENOSPC;
56 	const size_t bytes = strlcpy(d->data.array[d->data_len++].sval,
57 			str, RTE_TEL_MAX_STRING_LEN);
58 	return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;
59 }
60 
61 int
62 rte_tel_data_add_array_int(struct rte_tel_data *d, int x)
63 {
64 	if (d->type != RTE_TEL_ARRAY_INT)
65 		return -EINVAL;
66 	if (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)
67 		return -ENOSPC;
68 	d->data.array[d->data_len++].ival = x;
69 	return 0;
70 }
71 
72 int
73 rte_tel_data_add_array_u64(struct rte_tel_data *d, uint64_t x)
74 {
75 	if (d->type != RTE_TEL_ARRAY_U64)
76 		return -EINVAL;
77 	if (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)
78 		return -ENOSPC;
79 	d->data.array[d->data_len++].u64val = x;
80 	return 0;
81 }
82 
83 int
84 rte_tel_data_add_array_container(struct rte_tel_data *d,
85 		struct rte_tel_data *val, int keep)
86 {
87 	if (d->type != RTE_TEL_ARRAY_CONTAINER ||
88 			(val->type != RTE_TEL_ARRAY_U64
89 			&& val->type != RTE_TEL_ARRAY_INT
90 			&& val->type != RTE_TEL_ARRAY_STRING))
91 		return -EINVAL;
92 	if (d->data_len >= RTE_TEL_MAX_ARRAY_ENTRIES)
93 		return -ENOSPC;
94 
95 	d->data.array[d->data_len].container.data = val;
96 	d->data.array[d->data_len++].container.keep = !!keep;
97 	return 0;
98 }
99 
100 static bool
101 valid_name(const char *name)
102 {
103 	char allowed[128] = {
104 			['0' ... '9'] = 1,
105 			['A' ... 'Z'] = 1,
106 			['a' ... 'z'] = 1,
107 			['_'] = 1,
108 			['/'] = 1,
109 	};
110 	while (*name != '\0') {
111 		if ((size_t)*name >= RTE_DIM(allowed) || allowed[(int)*name] == 0)
112 			return false;
113 		name++;
114 	}
115 	return true;
116 }
117 
118 int
119 rte_tel_data_add_dict_string(struct rte_tel_data *d, const char *name,
120 		const char *val)
121 {
122 	struct tel_dict_entry *e = &d->data.dict[d->data_len];
123 	size_t nbytes, vbytes;
124 
125 	if (d->type != RTE_TEL_DICT)
126 		return -EINVAL;
127 	if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES)
128 		return -ENOSPC;
129 
130 	if (!valid_name(name))
131 		return -EINVAL;
132 
133 	d->data_len++;
134 	e->type = RTE_TEL_STRING_VAL;
135 	vbytes = strlcpy(e->value.sval, val, RTE_TEL_MAX_STRING_LEN);
136 	nbytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN);
137 	if (vbytes >= RTE_TEL_MAX_STRING_LEN ||
138 			nbytes >= RTE_TEL_MAX_STRING_LEN)
139 		return E2BIG;
140 	return 0;
141 }
142 
143 int
144 rte_tel_data_add_dict_int(struct rte_tel_data *d, const char *name, int val)
145 {
146 	struct tel_dict_entry *e = &d->data.dict[d->data_len];
147 	if (d->type != RTE_TEL_DICT)
148 		return -EINVAL;
149 	if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES)
150 		return -ENOSPC;
151 
152 	if (!valid_name(name))
153 		return -EINVAL;
154 
155 	d->data_len++;
156 	e->type = RTE_TEL_INT_VAL;
157 	e->value.ival = val;
158 	const size_t bytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN);
159 	return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;
160 }
161 
162 int
163 rte_tel_data_add_dict_u64(struct rte_tel_data *d,
164 		const char *name, uint64_t val)
165 {
166 	struct tel_dict_entry *e = &d->data.dict[d->data_len];
167 	if (d->type != RTE_TEL_DICT)
168 		return -EINVAL;
169 	if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES)
170 		return -ENOSPC;
171 
172 	if (!valid_name(name))
173 		return -EINVAL;
174 
175 	d->data_len++;
176 	e->type = RTE_TEL_U64_VAL;
177 	e->value.u64val = val;
178 	const size_t bytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN);
179 	return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;
180 }
181 
182 int
183 rte_tel_data_add_dict_container(struct rte_tel_data *d, const char *name,
184 		struct rte_tel_data *val, int keep)
185 {
186 	struct tel_dict_entry *e = &d->data.dict[d->data_len];
187 
188 	if (d->type != RTE_TEL_DICT || (val->type != RTE_TEL_ARRAY_U64
189 			&& val->type != RTE_TEL_ARRAY_INT
190 			&& val->type != RTE_TEL_ARRAY_STRING
191 			&& val->type != RTE_TEL_DICT))
192 		return -EINVAL;
193 	if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES)
194 		return -ENOSPC;
195 
196 	if (!valid_name(name))
197 		return -EINVAL;
198 
199 	d->data_len++;
200 	e->type = RTE_TEL_CONTAINER;
201 	e->value.container.data = val;
202 	e->value.container.keep = !!keep;
203 	const size_t bytes = strlcpy(e->name, name, RTE_TEL_MAX_STRING_LEN);
204 	return bytes < RTE_TEL_MAX_STRING_LEN ? 0 : E2BIG;
205 }
206 
207 struct rte_tel_data *
208 rte_tel_data_alloc(void)
209 {
210 	return malloc(sizeof(struct rte_tel_data));
211 }
212 
213 void
214 rte_tel_data_free(struct rte_tel_data *data)
215 {
216 	free(data);
217 }
218