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