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