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