ethdev: add common code for different SFF specs
[dpdk.git] / lib / ethdev / sff_telemetry.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2022 Intel Corporation
3  */
4
5 #include <errno.h>
6
7 #include "rte_ethdev.h"
8 #include <rte_common.h>
9 #include "sff_telemetry.h"
10 #include <telemetry_data.h>
11
12 static void
13 sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d)
14 {
15         struct rte_eth_dev_module_info minfo;
16         struct rte_dev_eeprom_info einfo;
17         int ret;
18
19         if (d == NULL) {
20                 RTE_ETHDEV_LOG(ERR, "Dict invalid\n");
21                 return;
22         }
23
24         ret = rte_eth_dev_get_module_info(port_id, &minfo);
25         if (ret != 0) {
26                 switch (ret) {
27                 case -ENODEV:
28                         RTE_ETHDEV_LOG(ERR, "Port index %d invalid\n", port_id);
29                         break;
30                 case -ENOTSUP:
31                         RTE_ETHDEV_LOG(ERR, "Operation not supported by device\n");
32                         break;
33                 case -EIO:
34                         RTE_ETHDEV_LOG(ERR, "Device is removed\n");
35                         break;
36                 default:
37                         RTE_ETHDEV_LOG(ERR, "Unable to get port module info, %d\n", ret);
38                         break;
39                 }
40                 return;
41         }
42
43         einfo.offset = 0;
44         einfo.length = minfo.eeprom_len;
45         einfo.data = calloc(1, minfo.eeprom_len);
46         if (einfo.data == NULL) {
47                 RTE_ETHDEV_LOG(ERR, "Allocation of port %u EEPROM data failed\n", port_id);
48                 return;
49         }
50
51         ret = rte_eth_dev_get_module_eeprom(port_id, &einfo);
52         if (ret != 0) {
53                 switch (ret) {
54                 case -ENODEV:
55                         RTE_ETHDEV_LOG(ERR, "Port index %d invalid\n", port_id);
56                         break;
57                 case -ENOTSUP:
58                         RTE_ETHDEV_LOG(ERR, "Operation not supported by device\n");
59                         break;
60                 case -EIO:
61                         RTE_ETHDEV_LOG(ERR, "Device is removed\n");
62                         break;
63                 default:
64                         RTE_ETHDEV_LOG(ERR, "Unable to get port module EEPROM, %d\n", ret);
65                         break;
66                 }
67                 free(einfo.data);
68                 return;
69         }
70
71         switch (minfo.type) {
72         /* parsing module EEPROM data base on different module type */
73         default:
74                 RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type);
75                 break;
76         }
77
78         free(einfo.data);
79 }
80
81 void
82 ssf_add_dict_string(struct rte_tel_data *d, const char *name_str, const char *value_str)
83 {
84         struct tel_dict_entry *e = &d->data.dict[d->data_len];
85
86         if (d->type != RTE_TEL_DICT)
87                 return;
88         if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES) {
89                 RTE_ETHDEV_LOG(ERR, "data_len has exceeded the maximum number of inserts\n");
90                 return;
91         }
92
93         e->type = RTE_TEL_STRING_VAL;
94         /* append different values for same keys */
95         if (d->data_len > 0) {
96                 struct tel_dict_entry *previous = &d->data.dict[d->data_len - 1];
97                 if (strcmp(previous->name, name_str) == 0) {
98                         strlcat(previous->value.sval, "; ", RTE_TEL_MAX_STRING_LEN);
99                         strlcat(previous->value.sval, value_str, RTE_TEL_MAX_STRING_LEN);
100                         goto end;
101                 }
102         }
103         strlcpy(e->value.sval, value_str, RTE_TEL_MAX_STRING_LEN);
104         strlcpy(e->name, name_str, RTE_TEL_MAX_STRING_LEN);
105         d->data_len++;
106
107 end:
108         return;
109 }
110
111 int
112 eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, const char *params,
113                                   struct rte_tel_data *d)
114 {
115         char *end_param;
116         int port_id;
117
118         if (params == NULL || strlen(params) == 0 || !isdigit(*params))
119                 return -1;
120
121         errno = 0;
122         port_id = strtoul(params, &end_param, 0);
123
124         if (errno != 0) {
125                 RTE_ETHDEV_LOG(ERR, "Invalid argument, %d\n", errno);
126                 return -1;
127         }
128
129         if (*end_param != '\0')
130                 RTE_ETHDEV_LOG(NOTICE,
131                         "Extra parameters [%s] passed to ethdev telemetry command, ignoring\n",
132                                 end_param);
133
134         rte_tel_data_start_dict(d);
135
136         sff_port_module_eeprom_parse(port_id, d);
137
138         return 0;
139 }