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