ethdev: support SFF-8079 module telemetry
[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         case RTE_ETH_MODULE_SFF_8079:
74                 sff_8079_show_all(einfo.data, d);
75                 break;
76         default:
77                 RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type);
78                 break;
79         }
80
81         free(einfo.data);
82 }
83
84 void
85 ssf_add_dict_string(struct rte_tel_data *d, const char *name_str, const char *value_str)
86 {
87         struct tel_dict_entry *e = &d->data.dict[d->data_len];
88
89         if (d->type != RTE_TEL_DICT)
90                 return;
91         if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES) {
92                 RTE_ETHDEV_LOG(ERR, "data_len has exceeded the maximum number of inserts\n");
93                 return;
94         }
95
96         e->type = RTE_TEL_STRING_VAL;
97         /* append different values for same keys */
98         if (d->data_len > 0) {
99                 struct tel_dict_entry *previous = &d->data.dict[d->data_len - 1];
100                 if (strcmp(previous->name, name_str) == 0) {
101                         strlcat(previous->value.sval, "; ", RTE_TEL_MAX_STRING_LEN);
102                         strlcat(previous->value.sval, value_str, RTE_TEL_MAX_STRING_LEN);
103                         goto end;
104                 }
105         }
106         strlcpy(e->value.sval, value_str, RTE_TEL_MAX_STRING_LEN);
107         strlcpy(e->name, name_str, RTE_TEL_MAX_STRING_LEN);
108         d->data_len++;
109
110 end:
111         return;
112 }
113
114 int
115 eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, const char *params,
116                                   struct rte_tel_data *d)
117 {
118         char *end_param;
119         int port_id;
120
121         if (params == NULL || strlen(params) == 0 || !isdigit(*params))
122                 return -1;
123
124         errno = 0;
125         port_id = strtoul(params, &end_param, 0);
126
127         if (errno != 0) {
128                 RTE_ETHDEV_LOG(ERR, "Invalid argument, %d\n", errno);
129                 return -1;
130         }
131
132         if (*end_param != '\0')
133                 RTE_ETHDEV_LOG(NOTICE,
134                         "Extra parameters [%s] passed to ethdev telemetry command, ignoring\n",
135                                 end_param);
136
137         rte_tel_data_start_dict(d);
138
139         sff_port_module_eeprom_parse(port_id, d);
140
141         return 0;
142 }