summaryrefslogtreecommitdiff
path: root/lib/ethdev/sff_telemetry.c
blob: b3f239d967d907d4d99d974e7e9f18a7a095f743 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright(c) 2022 Intel Corporation
 */

#include <ctype.h>
#include <errno.h>
#include <stdlib.h>

#include "rte_ethdev.h"
#include <rte_common.h>
#include "sff_telemetry.h"
#include <telemetry_data.h>

static void
sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d)
{
	struct rte_eth_dev_module_info minfo;
	struct rte_dev_eeprom_info einfo;
	int ret;

	if (d == NULL) {
		RTE_ETHDEV_LOG_LINE(ERR, "Dict invalid");
		return;
	}

	ret = rte_eth_dev_get_module_info(port_id, &minfo);
	if (ret != 0) {
		switch (ret) {
		case -ENODEV:
			RTE_ETHDEV_LOG_LINE(ERR, "Port index %d invalid", port_id);
			break;
		case -ENOTSUP:
			RTE_ETHDEV_LOG_LINE(ERR, "Operation not supported by device");
			break;
		case -EIO:
			RTE_ETHDEV_LOG_LINE(ERR, "Device is removed");
			break;
		default:
			RTE_ETHDEV_LOG_LINE(ERR, "Unable to get port module info, %d", ret);
			break;
		}
		return;
	}

	einfo.offset = 0;
	einfo.length = minfo.eeprom_len;
	einfo.data = calloc(1, minfo.eeprom_len);
	if (einfo.data == NULL) {
		RTE_ETHDEV_LOG_LINE(ERR, "Allocation of port %u EEPROM data failed", port_id);
		return;
	}

	ret = rte_eth_dev_get_module_eeprom(port_id, &einfo);
	if (ret != 0) {
		switch (ret) {
		case -ENODEV:
			RTE_ETHDEV_LOG_LINE(ERR, "Port index %d invalid", port_id);
			break;
		case -ENOTSUP:
			RTE_ETHDEV_LOG_LINE(ERR, "Operation not supported by device");
			break;
		case -EIO:
			RTE_ETHDEV_LOG_LINE(ERR, "Device is removed");
			break;
		default:
			RTE_ETHDEV_LOG_LINE(ERR, "Unable to get port module EEPROM, %d", ret);
			break;
		}
		free(einfo.data);
		return;
	}

	switch (minfo.type) {
	/* parsing module EEPROM data base on different module type */
	case RTE_ETH_MODULE_SFF_8079:
		sff_8079_show_all(einfo.data, d);
		break;
	case RTE_ETH_MODULE_SFF_8472:
		sff_8079_show_all(einfo.data, d);
		sff_8472_show_all(einfo.data, d);
		break;
	case RTE_ETH_MODULE_SFF_8436:
	case RTE_ETH_MODULE_SFF_8636:
		sff_8636_show_all(einfo.data, einfo.length, d);
		break;
	default:
		RTE_ETHDEV_LOG_LINE(NOTICE, "Unsupported module type: %u", minfo.type);
		break;
	}

	free(einfo.data);
}

void
ssf_add_dict_string(struct rte_tel_data *d, const char *name_str, const char *value_str)
{
	struct tel_dict_entry *e = &d->data.dict[d->data_len];

	if (d->type != TEL_DICT)
		return;
	if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES) {
		RTE_ETHDEV_LOG_LINE(ERR, "data_len has exceeded the maximum number of inserts");
		return;
	}

	e->type = RTE_TEL_STRING_VAL;
	/* append different values for same keys */
	if (d->data_len > 0) {
		struct tel_dict_entry *previous = &d->data.dict[d->data_len - 1];
		if (strcmp(previous->name, name_str) == 0) {
			strlcat(previous->value.sval, "; ", RTE_TEL_MAX_STRING_LEN);
			strlcat(previous->value.sval, value_str, RTE_TEL_MAX_STRING_LEN);
			goto end;
		}
	}
	strlcpy(e->value.sval, value_str, RTE_TEL_MAX_STRING_LEN);
	strlcpy(e->name, name_str, RTE_TEL_MAX_STRING_LEN);
	d->data_len++;

end:
	return;
}

int
eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, const char *params,
				  struct rte_tel_data *d)
{
	char *end_param;
	uint64_t port_id;

	if (params == NULL || strlen(params) == 0 || !isdigit(*params))
		return -1;

	errno = 0;
	port_id = strtoul(params, &end_param, 0);

	if (errno != 0 || port_id >= UINT16_MAX) {
		RTE_ETHDEV_LOG_LINE(ERR, "Invalid argument, %d", errno);
		return -1;
	}

	if (*end_param != '\0')
		RTE_ETHDEV_LOG_LINE(NOTICE,
			"Extra parameters [%s] passed to ethdev telemetry command, ignoring",
				end_param);

	rte_tel_data_start_dict(d);

	sff_port_module_eeprom_parse(port_id, d);

	return 0;
}