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