blob: 756e8dffdc68e5108e0d29c3bbf7287b51d34001 [file] [log] [blame] [edit]
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION &
* AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "network-ports.h"
#include <endian.h>
#include <stdio.h>
#include <string.h>
static void htolePortCounterData(struct nsm_port_counter_data *portData)
{
uint32_t htole32_supported_counter_mask;
memcpy(&htole32_supported_counter_mask, &(portData->supported_counter),
sizeof(struct nsm_supported_port_counter));
htole32_supported_counter_mask =
htole32(htole32_supported_counter_mask);
memcpy(&(portData->supported_counter), &htole32_supported_counter_mask,
sizeof(struct nsm_supported_port_counter));
portData->port_rcv_pkts = htole64(portData->port_rcv_pkts);
portData->port_rcv_data = htole64(portData->port_rcv_data);
portData->port_multicast_rcv_pkts =
htole64(portData->port_multicast_rcv_pkts);
portData->port_unicast_rcv_pkts =
htole64(portData->port_unicast_rcv_pkts);
portData->port_malformed_pkts = htole64(portData->port_malformed_pkts);
portData->vl15_dropped = htole64(portData->vl15_dropped);
portData->port_rcv_errors = htole64(portData->port_rcv_errors);
portData->port_xmit_pkts = htole64(portData->port_xmit_pkts);
portData->port_xmit_pkts_vl15 = htole64(portData->port_xmit_pkts_vl15);
portData->port_xmit_data = htole64(portData->port_xmit_data);
portData->port_xmit_data_vl15 = htole64(portData->port_xmit_data_vl15);
portData->port_unicast_xmit_pkts =
htole64(portData->port_unicast_xmit_pkts);
portData->port_multicast_xmit_pkts =
htole64(portData->port_multicast_xmit_pkts);
portData->port_bcast_xmit_pkts =
htole64(portData->port_bcast_xmit_pkts);
portData->port_xmit_discard = htole64(portData->port_xmit_discard);
portData->port_neighbor_mtu_discards =
htole64(portData->port_neighbor_mtu_discards);
portData->port_rcv_ibg2_pkts = htole64(portData->port_rcv_ibg2_pkts);
portData->port_xmit_ibg2_pkts = htole64(portData->port_xmit_ibg2_pkts);
portData->symbol_ber = htole64(portData->symbol_ber);
portData->link_error_recovery_counter =
htole64(portData->link_error_recovery_counter);
portData->link_downed_counter = htole64(portData->link_downed_counter);
portData->port_rcv_remote_physical_errors =
htole64(portData->port_rcv_remote_physical_errors);
portData->port_rcv_switch_relay_errors =
htole64(portData->port_rcv_switch_relay_errors);
portData->QP1_dropped = htole64(portData->QP1_dropped);
portData->xmit_wait = htole64(portData->xmit_wait);
portData->effective_ber = htole64(portData->effective_ber);
portData->total_raw_error = htole64(portData->total_raw_error);
portData->effective_error = htole64(portData->effective_error);
portData->symbol_error = htole64(portData->symbol_error);
portData->total_raw_ber = htole64(portData->total_raw_ber);
portData->unintentional_link_down_count =
htole64(portData->unintentional_link_down_count);
portData->intentional_link_down_count =
htole64(portData->intentional_link_down_count);
}
static void letohPortCounterData(struct nsm_port_counter_data *portData)
{
uint32_t le32toh_supported_counter_mask;
memcpy(&le32toh_supported_counter_mask, &(portData->supported_counter),
sizeof(struct nsm_supported_port_counter));
le32toh_supported_counter_mask =
le32toh(le32toh_supported_counter_mask);
memcpy(&(portData->supported_counter), &le32toh_supported_counter_mask,
sizeof(struct nsm_supported_port_counter));
portData->port_rcv_pkts = le64toh(portData->port_rcv_pkts);
portData->port_rcv_data = le64toh(portData->port_rcv_data);
portData->port_multicast_rcv_pkts =
le64toh(portData->port_multicast_rcv_pkts);
portData->port_unicast_rcv_pkts =
le64toh(portData->port_unicast_rcv_pkts);
portData->port_malformed_pkts = le64toh(portData->port_malformed_pkts);
portData->vl15_dropped = le64toh(portData->vl15_dropped);
portData->port_rcv_errors = le64toh(portData->port_rcv_errors);
portData->port_xmit_pkts = le64toh(portData->port_xmit_pkts);
portData->port_xmit_pkts_vl15 = le64toh(portData->port_xmit_pkts_vl15);
portData->port_xmit_data = le64toh(portData->port_xmit_data);
portData->port_xmit_data_vl15 = le64toh(portData->port_xmit_data_vl15);
portData->port_unicast_xmit_pkts =
le64toh(portData->port_unicast_xmit_pkts);
portData->port_multicast_xmit_pkts =
le64toh(portData->port_multicast_xmit_pkts);
portData->port_bcast_xmit_pkts =
le64toh(portData->port_bcast_xmit_pkts);
portData->port_xmit_discard = le64toh(portData->port_xmit_discard);
portData->port_neighbor_mtu_discards =
le64toh(portData->port_neighbor_mtu_discards);
portData->port_rcv_ibg2_pkts = le64toh(portData->port_rcv_ibg2_pkts);
portData->port_xmit_ibg2_pkts = le64toh(portData->port_xmit_ibg2_pkts);
portData->symbol_ber = le64toh(portData->symbol_ber);
portData->link_error_recovery_counter =
le64toh(portData->link_error_recovery_counter);
portData->link_downed_counter = le64toh(portData->link_downed_counter);
portData->port_rcv_remote_physical_errors =
le64toh(portData->port_rcv_remote_physical_errors);
portData->port_rcv_switch_relay_errors =
le64toh(portData->port_rcv_switch_relay_errors);
portData->QP1_dropped = le64toh(portData->QP1_dropped);
portData->xmit_wait = le64toh(portData->xmit_wait);
portData->effective_ber = le64toh(portData->effective_ber);
portData->total_raw_error = le64toh(portData->total_raw_error);
portData->effective_error = le64toh(portData->effective_error);
portData->symbol_error = le64toh(portData->symbol_error);
portData->total_raw_ber = le64toh(portData->total_raw_ber);
portData->unintentional_link_down_count =
le64toh(portData->unintentional_link_down_count);
portData->intentional_link_down_count =
le64toh(portData->intentional_link_down_count);
}
static void
htolePortCharacteristicsData(struct nsm_port_characteristics_data *data)
{
data->status_lane_info = htole32(data->status_lane_info);
data->nv_port_line_rate_mbps = htole32(data->nv_port_line_rate_mbps);
data->nv_port_data_rate_kbps = htole32(data->nv_port_data_rate_kbps);
uint32_t htole32_port_status;
memcpy(&htole32_port_status, &(data->port_status),
sizeof(struct status));
htole32_port_status = htole32(htole32_port_status);
memcpy(&(data->port_status), &htole32_port_status,
sizeof(struct status));
}
static void
letohPortCharacteristicsData(struct nsm_port_characteristics_data *data)
{
data->status_lane_info = le32toh(data->status_lane_info);
data->nv_port_line_rate_mbps = le32toh(data->nv_port_line_rate_mbps);
data->nv_port_data_rate_kbps = le32toh(data->nv_port_data_rate_kbps);
uint32_t le32toh_port_status;
memcpy(&le32toh_port_status, &(data->port_status),
sizeof(struct status));
le32toh_port_status = le32toh(le32toh_port_status);
memcpy(&(data->port_status), &le32toh_port_status,
sizeof(struct status));
}
#ifdef ENABLE_SYSTEM_GUID
int encode_set_system_guid_req(uint8_t instance_id, struct nsm_msg *msg,
uint8_t *sys_guid, size_t sys_guid_len)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
struct nsm_set_system_guid_req *request =
(struct nsm_set_system_guid_req *)msg->payload;
request->hdr.command = NSM_SET_SYSTEM_GUID;
request->hdr.data_size = 0x08;
if (sys_guid_len != 8) {
return NSM_SW_ERROR_DATA;
}
request->SysGUID_0 = sys_guid[0];
request->SysGUID_1 = sys_guid[1];
request->SysGUID_2 = sys_guid[2];
request->SysGUID_3 = sys_guid[3];
request->SysGUID_4 = sys_guid[4];
request->SysGUID_5 = sys_guid[5];
request->SysGUID_6 = sys_guid[6];
request->SysGUID_7 = sys_guid[7];
return NSM_SW_SUCCESS;
}
int decode_set_system_guid_resp(const struct nsm_msg *msg, size_t msg_len)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_set_system_guid_resp)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_set_system_guid_resp *response =
(struct nsm_set_system_guid_resp *)msg->payload;
if (response->hdr.data_size != 0) {
return NSM_SW_ERROR_DATA;
}
return NSM_SW_SUCCESS;
}
int encode_get_system_guid_req(uint8_t instance_id, struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
struct nsm_get_system_guid_req *request =
(struct nsm_get_system_guid_req *)msg->payload;
request->hdr.command = NSM_GET_SYSTEM_GUID;
request->hdr.data_size = 0x00;
return NSM_SW_SUCCESS;
}
int decode_get_system_guid_resp(const struct nsm_msg *msg, size_t msg_len,
uint8_t *cc, uint16_t *reason_code,
uint8_t *sys_guid, size_t sys_guid_len)
{
if (msg == NULL || sys_guid == NULL) {
return NSM_SW_ERROR_NULL;
}
int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_get_system_guid_resp)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_get_system_guid_resp *response =
(struct nsm_get_system_guid_resp *)msg->payload;
if (response->hdr.data_size < 8 || sys_guid_len != 8) {
return NSM_SW_ERROR_DATA;
}
sys_guid[0] = response->SysGUID_0;
sys_guid[1] = response->SysGUID_1;
sys_guid[2] = response->SysGUID_2;
sys_guid[3] = response->SysGUID_3;
sys_guid[4] = response->SysGUID_4;
sys_guid[5] = response->SysGUID_5;
sys_guid[6] = response->SysGUID_6;
sys_guid[7] = response->SysGUID_7;
return NSM_SW_SUCCESS;
}
#endif
int encode_get_nvlink_agg_led_status_req(uint8_t instance_id,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
struct nsm_get_nvlink_agg_led_status_req *request =
(struct nsm_get_nvlink_agg_led_status_req *)msg->payload;
request->hdr.command = NSM_GET_NVLINK_LED_STATUS;
request->hdr.data_size = 0x00;
return NSM_SW_SUCCESS;
}
int decode_get_nvlink_agg_led_status_resp(const struct nsm_msg *msg,
size_t msg_len, uint8_t *cc,
uint16_t *reason_code,
enum nsm_nvlink_led_state *led_state)
{
// NOTE: Decode reason code function checks pointers passed in
// (msg, msg_len, cc, and reason_code)
// so they are not checked here before use
int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
if (led_state == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_get_nvlink_agg_led_status_resp)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_get_nvlink_agg_led_status_resp *response =
(struct nsm_get_nvlink_agg_led_status_resp *)msg->payload;
if (response->hdr.data_size < 9) {
return NSM_SW_ERROR_DATA;
}
uint8_t led_status_byte = response->LED_State_Aggregate;
// The top bit of the led state byte indicates an invalid state
// so we will check it before reading the value
if ((led_status_byte >> 7) == 1) {
// First 3 bits provide LED state, so we will mask them off
switch (led_status_byte & 0x07) {
case 0:
*led_state = NSM_NVLINK_LED_GREEN;
break;
case 1: // Blinking at 0.5 Hz
case 2: // Blinking at 1 Hz
case 3: // Blinking at 2 Hz
case 4: // Blinking at 4 Hz
*led_state = NSM_NVLINK_LED_GREEN_BLINK;
break;
case 5:
*led_state = NSM_NVLINK_LED_AMBER;
break;
case 6:
*led_state = NSM_NVLINK_LED_OFF;
break;
case 7: // Blinking at 1 Hz
*led_state = NSM_NVLINK_LED_AMBER_BLINK;
break;
default:
*led_state = NSM_NVLINK_LED_ERROR;
break;
}
} else {
*led_state = NSM_NVLINK_LED_ERROR;
return NSM_ERR_INVALID_DATA;
}
return NSM_SW_SUCCESS;
}
int encode_get_port_telemetry_counter_req(uint8_t instance_id,
uint8_t port_number,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
nsm_get_port_telemetry_counter_req *request =
(nsm_get_port_telemetry_counter_req *)msg->payload;
request->hdr.command = NSM_GET_PORT_TELEMETRY_COUNTER;
request->hdr.data_size = sizeof(port_number);
request->port_number = port_number;
return NSM_SW_SUCCESS;
}
int decode_get_port_telemetry_counter_req(const struct nsm_msg *msg,
size_t msg_len, uint8_t *port_number)
{
if (msg == NULL || port_number == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(nsm_get_port_telemetry_counter_req)) {
return NSM_SW_ERROR_LENGTH;
}
nsm_get_port_telemetry_counter_req *request =
(nsm_get_port_telemetry_counter_req *)msg->payload;
if (request->hdr.data_size < sizeof(request->port_number)) {
return NSM_SW_ERROR_DATA;
}
*port_number = request->port_number;
return NSM_SW_SUCCESS;
}
int encode_get_port_telemetry_counter_resp(uint8_t instance_id, uint8_t cc,
uint16_t reason_code,
struct nsm_port_counter_data *data,
struct nsm_msg *msg)
{
if (msg == NULL || data == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_RESPONSE;
header.instance_id = instance_id & INSTANCEID_MASK;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
if (cc != NSM_SUCCESS) {
return encode_reason_code(cc, reason_code,
NSM_GET_PORT_TELEMETRY_COUNTER, msg);
}
struct nsm_get_port_telemetry_counter_resp *response =
(struct nsm_get_port_telemetry_counter_resp *)msg->payload;
response->hdr.command = NSM_GET_PORT_TELEMETRY_COUNTER;
response->hdr.completion_code = cc;
response->hdr.data_size = htole16(sizeof(struct nsm_port_counter_data));
// conversion htole64 for each counter data
htolePortCounterData(data);
memcpy(&(response->data), data, sizeof(struct nsm_port_counter_data));
return NSM_SW_SUCCESS;
}
int decode_get_port_telemetry_counter_resp(const struct nsm_msg *msg,
size_t msg_len, uint8_t *cc,
uint16_t *reason_code,
uint16_t *data_size,
struct nsm_port_counter_data *data)
{
if (data_size == NULL || data == NULL) {
return NSM_SW_ERROR_NULL;
}
int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
if (msg_len <
(sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp) +
PORT_COUNTER_TELEMETRY_MIN_DATA_SIZE)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_get_port_telemetry_counter_resp *resp =
(struct nsm_get_port_telemetry_counter_resp *)msg->payload;
*data_size = le16toh(resp->hdr.data_size);
if (*data_size < PORT_COUNTER_TELEMETRY_MIN_DATA_SIZE) {
return NSM_SW_ERROR_DATA;
}
if (*data_size > sizeof(*data)) {
return NSM_SW_ERROR_LENGTH;
}
memcpy(data, &(resp->data), *data_size);
// conversion le64toh for each counter data
letohPortCounterData(data);
return NSM_SW_SUCCESS;
}
int encode_query_port_status_req(uint8_t instance_id, uint8_t port_number,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
nsm_query_port_status_req *request =
(nsm_query_port_status_req *)msg->payload;
request->hdr.command = NSM_QUERY_PORT_STATUS;
request->hdr.data_size = sizeof(port_number);
request->port_number = port_number;
return NSM_SW_SUCCESS;
}
int decode_query_port_status_req(const struct nsm_msg *msg, size_t msg_len,
uint8_t *port_number)
{
if (msg == NULL || port_number == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len <
sizeof(struct nsm_msg_hdr) + sizeof(nsm_query_port_status_req)) {
return NSM_SW_ERROR_LENGTH;
}
nsm_query_port_status_req *request =
(nsm_query_port_status_req *)msg->payload;
if (request->hdr.data_size < sizeof(request->port_number)) {
return NSM_SW_ERROR_DATA;
}
*port_number = request->port_number;
return NSM_SW_SUCCESS;
}
int encode_query_port_status_resp(uint8_t instance_id, uint8_t cc,
uint16_t reason_code, uint8_t port_state,
uint8_t port_status, struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_RESPONSE;
header.instance_id = instance_id & INSTANCEID_MASK;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
if (cc != NSM_SUCCESS) {
return encode_reason_code(cc, reason_code,
NSM_QUERY_PORT_STATUS, msg);
}
struct nsm_query_port_status_resp *response =
(struct nsm_query_port_status_resp *)msg->payload;
response->hdr.command = NSM_QUERY_PORT_STATUS;
response->hdr.completion_code = cc;
response->hdr.data_size =
htole16(sizeof(port_state) + sizeof(port_status));
response->port_state = port_state;
response->port_status = port_status;
return NSM_SW_SUCCESS;
}
int decode_query_port_status_resp(const struct nsm_msg *msg, size_t msg_len,
uint8_t *cc, uint16_t *reason_code,
uint16_t *data_size, uint8_t *port_state,
uint8_t *port_status)
{
if (data_size == NULL || port_state == NULL || port_status == NULL) {
return NSM_SW_ERROR_NULL;
}
int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
if (msg_len != (sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_query_port_status_resp))) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_query_port_status_resp *resp =
(struct nsm_query_port_status_resp *)msg->payload;
*data_size = le16toh(resp->hdr.data_size);
if (*data_size < (sizeof(*port_state) + sizeof(*port_status))) {
return NSM_SW_ERROR_DATA;
}
*port_state = resp->port_state;
*port_status = resp->port_status;
return NSM_SW_SUCCESS;
}
int encode_query_port_characteristics_req(uint8_t instance_id,
uint8_t port_number,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
nsm_query_port_characteristics_req *request =
(nsm_query_port_characteristics_req *)msg->payload;
request->hdr.command = NSM_QUERY_PORT_CHARACTERISTICS;
request->hdr.data_size = sizeof(port_number);
request->port_number = port_number;
return NSM_SW_SUCCESS;
}
int decode_query_port_characteristics_req(const struct nsm_msg *msg,
size_t msg_len, uint8_t *port_number)
{
if (msg == NULL || port_number == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(nsm_query_port_characteristics_req)) {
return NSM_SW_ERROR_LENGTH;
}
nsm_query_port_characteristics_req *request =
(nsm_query_port_characteristics_req *)msg->payload;
if (request->hdr.data_size < sizeof(request->port_number)) {
return NSM_SW_ERROR_DATA;
}
*port_number = request->port_number;
return NSM_SW_SUCCESS;
}
int encode_query_port_characteristics_resp(
uint8_t instance_id, uint8_t cc, uint16_t reason_code,
struct nsm_port_characteristics_data *data, struct nsm_msg *msg)
{
if (msg == NULL || data == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_RESPONSE;
header.instance_id = instance_id & INSTANCEID_MASK;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
if (cc != NSM_SUCCESS) {
return encode_reason_code(cc, reason_code,
NSM_QUERY_PORT_CHARACTERISTICS, msg);
}
struct nsm_query_port_characteristics_resp *response =
(struct nsm_query_port_characteristics_resp *)msg->payload;
response->hdr.command = NSM_QUERY_PORT_CHARACTERISTICS;
response->hdr.completion_code = cc;
response->hdr.data_size =
htole16(sizeof(struct nsm_port_characteristics_data));
// conversion htole32 for each characteristics data
htolePortCharacteristicsData(data);
memcpy(&(response->data), data,
sizeof(struct nsm_port_characteristics_data));
return NSM_SW_SUCCESS;
}
int decode_query_port_characteristics_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
uint16_t *reason_code, uint16_t *data_size,
struct nsm_port_characteristics_data *data)
{
if (data_size == NULL || data == NULL) {
return NSM_SW_ERROR_NULL;
}
int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
if (msg_len != (sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_query_port_characteristics_resp))) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_query_port_characteristics_resp *resp =
(struct nsm_query_port_characteristics_resp *)msg->payload;
size_t characteristics_data_len =
sizeof(struct nsm_port_characteristics_data);
*data_size = le16toh(resp->hdr.data_size);
if (*data_size < characteristics_data_len) {
return NSM_SW_ERROR_DATA;
}
memcpy(data, &(resp->data), characteristics_data_len);
// conversion le32toh for each characteristics data
letohPortCharacteristicsData(data);
return NSM_SW_SUCCESS;
}
int encode_query_ports_available_req(uint8_t instance_id, struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
nsm_query_ports_available_req *request =
(nsm_query_ports_available_req *)msg->payload;
request->command = NSM_QUERY_PORTS_AVAILABLE;
request->data_size = 0;
return NSM_SW_SUCCESS;
}
int decode_query_ports_available_req(const struct nsm_msg *msg, size_t msg_len)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(nsm_query_ports_available_req)) {
return NSM_SW_ERROR_LENGTH;
}
nsm_query_ports_available_req *request =
(nsm_query_ports_available_req *)msg->payload;
if (request->data_size != 0) {
return NSM_SW_ERROR_DATA;
}
return NSM_SW_SUCCESS;
}
int encode_query_ports_available_resp(uint8_t instance_id, uint8_t cc,
uint16_t reason_code,
uint8_t number_of_ports,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_RESPONSE;
header.instance_id = instance_id & INSTANCEID_MASK;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
if (cc != NSM_SUCCESS) {
return encode_reason_code(cc, reason_code,
NSM_QUERY_PORTS_AVAILABLE, msg);
}
struct nsm_query_ports_available_resp *response =
(struct nsm_query_ports_available_resp *)msg->payload;
response->hdr.command = NSM_QUERY_PORTS_AVAILABLE;
response->hdr.completion_code = cc;
response->hdr.data_size = htole16(sizeof(number_of_ports));
response->number_of_ports = number_of_ports;
return NSM_SW_SUCCESS;
}
int decode_query_ports_available_resp(const struct nsm_msg *msg, size_t msg_len,
uint8_t *cc, uint16_t *reason_code,
uint16_t *data_size,
uint8_t *number_of_ports)
{
if (data_size == NULL || number_of_ports == NULL) {
return NSM_SW_ERROR_NULL;
}
int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
if (msg_len != (sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_query_ports_available_resp))) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_query_ports_available_resp *resp =
(struct nsm_query_ports_available_resp *)msg->payload;
*data_size = le16toh(resp->hdr.data_size);
if (*data_size < sizeof(*number_of_ports)) {
return NSM_SW_ERROR_DATA;
}
*number_of_ports = resp->number_of_ports;
return NSM_SW_SUCCESS;
}
int encode_set_port_disable_future_req(uint8_t instance,
const bitfield8_t *mask,
struct nsm_msg *msg)
{
if (mask == NULL || msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
struct nsm_set_port_disable_future_req *request =
(struct nsm_set_port_disable_future_req *)msg->payload;
request->hdr.command = NSM_SET_PORT_DISABLE_FUTURE;
request->hdr.data_size = PORT_MASK_DATA_SIZE;
memcpy(request->port_mask, mask, PORT_MASK_DATA_SIZE);
return NSM_SW_SUCCESS;
}
int decode_set_port_disable_future_req(const struct nsm_msg *msg,
size_t msg_len,
bitfield8_t mask[PORT_MASK_DATA_SIZE])
{
if (msg == NULL || mask == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_set_port_disable_future_req)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_set_port_disable_future_req *request =
(struct nsm_set_port_disable_future_req *)msg->payload;
if (request->hdr.data_size != PORT_MASK_DATA_SIZE) {
return NSM_SW_ERROR_DATA;
}
memcpy(mask, request->port_mask, PORT_MASK_DATA_SIZE);
return NSM_SW_SUCCESS;
}
int encode_set_port_disable_future_resp(uint8_t instance, uint8_t cc,
uint16_t reason_code,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_RESPONSE;
header.instance_id = instance & INSTANCEID_MASK;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
if (cc != NSM_SUCCESS) {
return encode_reason_code(cc, reason_code,
NSM_SET_PORT_DISABLE_FUTURE, msg);
}
nsm_set_port_disable_future_resp *response =
(nsm_set_port_disable_future_resp *)msg->payload;
response->command = NSM_SET_PORT_DISABLE_FUTURE;
response->completion_code = cc;
response->data_size = 0;
return NSM_SW_SUCCESS;
}
int decode_set_port_disable_future_resp(const struct nsm_msg *msg,
size_t msg_len, uint8_t *cc,
uint16_t *reason_code)
{
int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(nsm_set_port_disable_future_resp)) {
return NSM_SW_ERROR_LENGTH;
}
return NSM_SW_SUCCESS;
}
int encode_get_port_disable_future_req(uint8_t instance_id, struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
nsm_get_port_disable_future_req *request =
(nsm_get_port_disable_future_req *)msg->payload;
request->command = NSM_GET_PORT_DISABLE_FUTURE;
request->data_size = 0;
return NSM_SW_SUCCESS;
}
int decode_get_port_disable_future_req(const struct nsm_msg *msg,
size_t msg_len)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(nsm_get_port_disable_future_req)) {
return NSM_SW_ERROR_LENGTH;
}
nsm_get_port_disable_future_req *request =
(nsm_get_port_disable_future_req *)msg->payload;
if (request->data_size != 0) {
return NSM_SW_ERROR_DATA;
}
return NSM_SW_SUCCESS;
}
int encode_get_port_disable_future_resp(uint8_t instance, uint8_t cc,
uint16_t reason_code,
const bitfield8_t *mask,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_RESPONSE;
header.instance_id = instance & INSTANCEID_MASK;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
if (cc != NSM_SUCCESS) {
return encode_reason_code(cc, reason_code,
NSM_GET_PORT_DISABLE_FUTURE, msg);
}
struct nsm_get_port_disable_future_resp *response =
(struct nsm_get_port_disable_future_resp *)msg->payload;
response->hdr.command = NSM_GET_PORT_DISABLE_FUTURE;
response->hdr.completion_code = cc;
response->hdr.data_size = htole16(PORT_MASK_DATA_SIZE);
memcpy(response->port_mask, mask, PORT_MASK_DATA_SIZE);
return NSM_SW_SUCCESS;
}
int decode_get_port_disable_future_resp(const struct nsm_msg *msg,
size_t msg_len, uint8_t *cc,
uint16_t *reason_code,
bitfield8_t mask[PORT_MASK_DATA_SIZE])
{
if (mask == NULL) {
return NSM_SW_ERROR_NULL;
}
int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_get_port_disable_future_resp)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_get_port_disable_future_resp *resp =
(struct nsm_get_port_disable_future_resp *)msg->payload;
memcpy(mask, resp->port_mask, PORT_MASK_DATA_SIZE);
return NSM_SW_SUCCESS;
}
int encode_get_power_mode_req(uint8_t instance_id, struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id & INSTANCEID_MASK;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
nsm_get_power_mode_req *request =
(nsm_get_power_mode_req *)msg->payload;
request->command = NSM_GET_POWER_MODE;
request->data_size = 0;
return NSM_SW_SUCCESS;
}
int decode_get_power_mode_req(const struct nsm_msg *msg, size_t msg_len)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len <
sizeof(struct nsm_msg_hdr) + sizeof(nsm_get_power_mode_req)) {
return NSM_SW_ERROR_LENGTH;
}
nsm_get_power_mode_req *request =
(nsm_get_power_mode_req *)msg->payload;
if (request->data_size != 0) {
return NSM_SW_ERROR_DATA;
}
return NSM_SW_SUCCESS;
}
int encode_get_power_mode_resp(uint8_t instance_id, uint8_t cc,
uint16_t reason_code,
struct nsm_power_mode_data *data,
struct nsm_msg *msg)
{
if (msg == NULL || data == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_RESPONSE;
header.instance_id = instance_id & INSTANCEID_MASK;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
if (cc != NSM_SUCCESS) {
return encode_reason_code(cc, reason_code, NSM_GET_POWER_MODE,
msg);
}
struct nsm_get_power_mode_resp *response =
(struct nsm_get_power_mode_resp *)msg->payload;
response->hdr.command = NSM_GET_POWER_MODE;
response->hdr.completion_code = cc;
response->hdr.data_size = htole16(sizeof(struct nsm_power_mode_data));
response->data.l1_hw_mode_control = data->l1_hw_mode_control;
response->data.l1_hw_mode_threshold =
htole32(data->l1_hw_mode_threshold);
response->data.l1_fw_throttling_mode = data->l1_fw_throttling_mode;
response->data.l1_prediction_mode = data->l1_prediction_mode;
response->data.l1_hw_active_time = htole16(data->l1_hw_active_time);
response->data.l1_hw_inactive_time = htole16(data->l1_hw_inactive_time);
response->data.l1_prediction_inactive_time =
htole16(data->l1_prediction_inactive_time);
return NSM_SW_SUCCESS;
}
int decode_get_power_mode_resp(const struct nsm_msg *msg, size_t msg_len,
uint8_t *cc, uint16_t *reason_code,
uint16_t *data_size,
struct nsm_power_mode_data *data)
{
if (data_size == NULL || data == NULL) {
return NSM_SW_ERROR_NULL;
}
int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
if (msg_len != (sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_get_power_mode_resp))) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_get_power_mode_resp *resp =
(struct nsm_get_power_mode_resp *)msg->payload;
*data_size = le16toh(resp->hdr.data_size);
if (*data_size < sizeof(struct nsm_power_mode_data)) {
return NSM_SW_ERROR_DATA;
}
data->l1_hw_mode_control = resp->data.l1_hw_mode_control;
data->l1_hw_mode_threshold = le32toh(resp->data.l1_hw_mode_threshold);
data->l1_fw_throttling_mode = resp->data.l1_fw_throttling_mode;
data->l1_prediction_mode = resp->data.l1_prediction_mode;
data->l1_hw_active_time = le16toh(resp->data.l1_hw_active_time);
data->l1_hw_inactive_time = le16toh(resp->data.l1_hw_inactive_time);
data->l1_prediction_inactive_time =
le16toh(resp->data.l1_prediction_inactive_time);
return NSM_SW_SUCCESS;
}
int encode_set_power_mode_req(uint8_t instance_id, struct nsm_msg *msg,
struct nsm_power_mode_data data)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
struct nsm_set_power_mode_req *request =
(struct nsm_set_power_mode_req *)msg->payload;
request->hdr.command = NSM_SET_POWER_MODE;
request->hdr.data_size =
sizeof(struct nsm_power_mode_data) + sizeof(uint8_t);
request->l1_hw_mode_control = data.l1_hw_mode_control;
request->reserved = 0x00; // reserved as per spec
request->l1_hw_mode_threshold = htole32(data.l1_hw_mode_threshold);
request->l1_fw_throttling_mode = data.l1_fw_throttling_mode;
request->l1_prediction_mode = data.l1_prediction_mode;
request->l1_hw_active_time = htole16(data.l1_hw_active_time);
request->l1_hw_inactive_time = htole16(data.l1_hw_inactive_time);
request->l1_prediction_inactive_time =
htole16(data.l1_prediction_inactive_time);
return NSM_SW_SUCCESS;
}
int decode_set_power_mode_req(const struct nsm_msg *msg, size_t msg_len,
struct nsm_power_mode_data *data)
{
if (msg == NULL || data == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len != sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_set_power_mode_req)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_set_power_mode_req *request =
(struct nsm_set_power_mode_req *)msg->payload;
if (request->hdr.data_size !=
(sizeof(struct nsm_power_mode_data) + sizeof(uint8_t))) {
return NSM_SW_ERROR_DATA;
}
data->l1_hw_mode_control = request->l1_hw_mode_control;
data->l1_hw_mode_threshold = le32toh(request->l1_hw_mode_threshold);
data->l1_fw_throttling_mode = request->l1_fw_throttling_mode;
data->l1_prediction_mode = request->l1_prediction_mode;
data->l1_hw_active_time = le16toh(request->l1_hw_active_time);
data->l1_hw_inactive_time = le16toh(request->l1_hw_inactive_time);
data->l1_prediction_inactive_time =
le16toh(request->l1_prediction_inactive_time);
return NSM_SW_SUCCESS;
}
int encode_set_power_mode_resp(uint8_t instance_id, uint16_t reason_code,
struct nsm_msg *msg)
{
return encode_cc_only_resp(instance_id, NSM_TYPE_NETWORK_PORT,
NSM_SET_POWER_MODE, NSM_SUCCESS, reason_code,
msg);
}
int decode_set_power_mode_resp(const struct nsm_msg *msg, size_t msgLen,
uint8_t *cc, uint16_t *reason_code)
{
int rc = decode_reason_code_and_cc(msg, msgLen, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
if (msgLen <
sizeof(struct nsm_msg_hdr) + sizeof(nsm_set_power_mode_resp)) {
return NSM_SW_ERROR_LENGTH;
}
nsm_set_power_mode_resp *resp = (nsm_set_power_mode_resp *)msg->payload;
if (resp->data_size != 0) {
return NSM_SW_ERROR_DATA;
}
return NSM_SW_SUCCESS;
}
int encode_nsm_health_event(uint8_t instance_id, bool ackr,
const struct nsm_health_event_payload *payload,
struct nsm_msg *msg)
{
return encode_nsm_event(instance_id, NSM_TYPE_NETWORK_PORT, ackr,
NSM_EVENT_VERSION, NSM_THRESHOLD_EVENT,
NSM_GENERAL_EVENT_CLASS, 0, sizeof(*payload),
(uint8_t *)(payload), msg);
}
int decode_nsm_health_event(const struct nsm_msg *msg, size_t msg_len,
uint16_t *event_state,
struct nsm_health_event_payload *payload)
{
if (payload == NULL) {
return NSM_SW_ERROR_NULL;
}
uint8_t data_size = 0;
int result = decode_nsm_event_with_data(
msg, msg_len, NSM_THRESHOLD_EVENT, NSM_GENERAL_EVENT_CLASS,
event_state, &data_size, (uint8_t *)payload);
if (result == NSM_SW_SUCCESS &&
data_size != sizeof(struct nsm_health_event_payload)) {
return NSM_SW_ERROR_LENGTH;
}
return result;
}
int encode_get_switch_isolation_mode_req(uint8_t instance, struct nsm_msg *msg)
{
return encode_common_req(instance, NSM_TYPE_NETWORK_PORT,
NSM_GET_SWITCH_ISOLATION_MODE, msg);
}
int decode_get_switch_isolation_mode_req(const struct nsm_msg *msg,
size_t msg_len)
{
return decode_common_req(msg, msg_len);
}
int encode_get_switch_isolation_mode_resp(uint8_t instance, uint8_t cc,
uint16_t reason_code,
uint8_t isolation_mode,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_RESPONSE;
header.instance_id = instance & INSTANCEID_MASK;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
if (cc != NSM_SUCCESS) {
return encode_reason_code(cc, reason_code,
NSM_GET_SWITCH_ISOLATION_MODE, msg);
}
struct nsm_get_switch_isolation_mode_resp *response =
(struct nsm_get_switch_isolation_mode_resp *)msg->payload;
response->hdr.command = NSM_GET_SWITCH_ISOLATION_MODE;
response->hdr.completion_code = cc;
response->hdr.data_size =
htole16(sizeof(struct nsm_get_switch_isolation_mode_resp) -
sizeof(struct nsm_common_resp));
response->isolation_mode = isolation_mode;
return NSM_SW_SUCCESS;
}
int decode_get_switch_isolation_mode_resp(const struct nsm_msg *msg,
size_t msg_len, uint8_t *cc,
uint16_t *reason_code,
uint8_t *isolation_mode)
{
if (isolation_mode == NULL) {
return NSM_SW_ERROR_NULL;
}
int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
if (msg_len != (sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_get_switch_isolation_mode_resp))) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_get_switch_isolation_mode_resp *resp =
(struct nsm_get_switch_isolation_mode_resp *)msg->payload;
uint16_t data_size = le16toh(resp->hdr.data_size);
if (data_size != sizeof(struct nsm_get_switch_isolation_mode_resp) -
sizeof(struct nsm_common_resp)) {
return NSM_SW_ERROR_DATA;
}
*isolation_mode = resp->isolation_mode;
return NSM_SW_SUCCESS;
}
int encode_set_switch_isolation_mode_req(uint8_t instance,
uint8_t isolation_mode,
struct nsm_msg *msg)
{
int rc = encode_common_req(instance, NSM_TYPE_NETWORK_PORT,
NSM_SET_SWITCH_ISOLATION_MODE, msg);
if (rc == NSM_SW_SUCCESS) {
struct nsm_set_switch_isolation_mode_req *req =
(struct nsm_set_switch_isolation_mode_req *)msg->payload;
req->hdr.data_size =
sizeof(struct nsm_set_switch_isolation_mode_req) -
sizeof(struct nsm_common_req);
req->isolation_mode = isolation_mode;
}
return rc;
}
int decode_set_switch_isolation_mode_req(const struct nsm_msg *msg,
size_t msg_len,
uint8_t *isolation_mode)
{
if (msg == NULL || isolation_mode == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
uint8_t rc = unpack_nsm_header(&msg->hdr, &header);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
if (msg_len != sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_set_switch_isolation_mode_req)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_set_switch_isolation_mode_req *req =
(struct nsm_set_switch_isolation_mode_req *)msg->payload;
if (req->hdr.data_size !=
sizeof(struct nsm_set_switch_isolation_mode_req) -
sizeof(struct nsm_common_req)) {
return NSM_SW_ERROR_DATA;
}
*isolation_mode = req->isolation_mode;
return NSM_SW_SUCCESS;
}
int encode_set_switch_isolation_mode_resp(uint8_t instance, uint8_t cc,
uint16_t reason_code,
struct nsm_msg *msg)
{
return encode_common_resp(instance, cc, reason_code,
NSM_TYPE_NETWORK_PORT,
NSM_SET_SWITCH_ISOLATION_MODE, msg);
}
int decode_set_switch_isolation_mode_resp(const struct nsm_msg *msg,
size_t msg_len, uint8_t *cc,
uint16_t *reason_code)
{
uint16_t data_size;
return decode_common_resp(msg, msg_len, cc, &data_size, reason_code);
}
int encode_get_fabric_manager_state_req(uint8_t instance_id,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
nsm_get_fabric_manager_state_req *request =
(nsm_get_fabric_manager_state_req *)msg->payload;
request->command = NSM_GET_FABRIC_MANAGER_STATE;
request->data_size = 0;
return NSM_SW_SUCCESS;
}
int decode_get_fabric_manager_state_req(const struct nsm_msg *msg,
size_t msg_len)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(nsm_get_fabric_manager_state_req)) {
return NSM_SW_ERROR_LENGTH;
}
nsm_get_fabric_manager_state_req *request =
(nsm_get_fabric_manager_state_req *)msg->payload;
if (request->data_size != 0) {
return NSM_SW_ERROR_DATA;
}
return NSM_SW_SUCCESS;
}
int encode_get_fabric_manager_state_resp(
uint8_t instance_id, uint8_t cc, uint16_t reason_code,
struct nsm_fabric_manager_state_data *data, struct nsm_msg *msg)
{
if (msg == NULL || data == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_RESPONSE;
header.instance_id = instance_id & INSTANCEID_MASK;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &msg->hdr);
if (rc != NSM_SW_SUCCESS) {
return rc;
}
if (cc != NSM_SUCCESS) {
return encode_reason_code(cc, reason_code,
NSM_GET_FABRIC_MANAGER_STATE, msg);
}
struct nsm_get_fabric_manager_state_resp *response =
(struct nsm_get_fabric_manager_state_resp *)msg->payload;
response->hdr.command = NSM_GET_FABRIC_MANAGER_STATE;
response->hdr.completion_code = cc;
response->hdr.data_size =
htole16(sizeof(struct nsm_fabric_manager_state_data));
response->data.fm_state = data->fm_state;
response->data.report_status = data->report_status;
response->data.last_restart_timestamp =
htole64(data->last_restart_timestamp);
response->data.duration_since_last_restart_sec =
htole64(data->duration_since_last_restart_sec);
return NSM_SW_SUCCESS;
}
int decode_get_fabric_manager_state_resp(
const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
uint16_t *reason_code, uint16_t *data_size,
struct nsm_fabric_manager_state_data *data)
{
if (data_size == NULL || data == NULL) {
return NSM_SW_ERROR_NULL;
}
int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
return rc;
}
if (msg_len < (sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_get_fabric_manager_state_resp))) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_get_fabric_manager_state_resp *resp =
(struct nsm_get_fabric_manager_state_resp *)msg->payload;
*data_size = le16toh(resp->hdr.data_size);
if (*data_size < sizeof(struct nsm_fabric_manager_state_data)) {
return NSM_SW_ERROR_DATA;
}
data->fm_state = resp->data.fm_state;
data->report_status = resp->data.report_status;
data->last_restart_timestamp =
le64toh(resp->data.last_restart_timestamp);
data->duration_since_last_restart_sec =
le64toh(resp->data.duration_since_last_restart_sec);
return NSM_SW_SUCCESS;
}
int encode_nsm_get_fabric_manager_state_event(
uint8_t instance_id, bool ackr,
nsm_get_fabric_manager_state_event_payload payload, struct nsm_msg *msg)
{
payload.last_restart_timestamp =
htole64(payload.last_restart_timestamp);
payload.duration_since_last_restart_sec =
htole64(payload.duration_since_last_restart_sec);
uint8_t event_data[NSM_EVENT_DATA_MAX_LEN];
memcpy(event_data, &payload, sizeof(payload));
return encode_nsm_event(
instance_id, NSM_TYPE_NETWORK_PORT, ackr, NSM_EVENT_VERSION,
NSM_FABRIC_MANAGER_STATE_EVENT, NSM_GENERAL_EVENT_CLASS, 0,
sizeof(payload), event_data, msg);
}
int decode_nsm_get_fabric_manager_state_event(
const struct nsm_msg *msg, size_t msg_len, uint8_t *event_class,
uint16_t *event_state, nsm_get_fabric_manager_state_event_payload *payload)
{
if (msg == NULL || event_class == NULL || event_state == NULL ||
payload == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_event *event = (struct nsm_event *)msg->payload;
if (event->data_size >
msg_len - sizeof(struct nsm_msg_hdr) - NSM_EVENT_MIN_LEN) {
return NSM_SW_ERROR_DATA;
}
*event_class = event->event_class;
*event_state = le16toh(event->event_state);
if (event->data_size < sizeof(*payload)) {
return NSM_SW_ERROR_DATA;
}
memcpy(payload, event->data, sizeof(*payload));
payload->last_restart_timestamp =
le64toh(payload->last_restart_timestamp);
payload->duration_since_last_restart_sec =
le64toh(payload->duration_since_last_restart_sec);
return NSM_SW_SUCCESS;
}
int encode_get_eth_port_telemetry_counter_req(uint8_t instance_id,
uint16_t port_number,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
struct nsm_get_ethernet_port_telemetry_counter_req *request =
(struct nsm_get_ethernet_port_telemetry_counter_req *)msg->payload;
request->hdr.command = NSM_GET_ETH_PORT_TELEMETRY_COUNTER;
request->hdr.data_size = sizeof(port_number);
request->port_number = htole16(port_number);
return NSM_SW_SUCCESS;
}
int decode_get_eth_port_telemetry_counter_req(const struct nsm_msg *msg,
size_t msg_len,
uint16_t *port_number)
{
if (msg == NULL || port_number == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len <
sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_get_ethernet_port_telemetry_counter_req)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_get_ethernet_port_telemetry_counter_req *request =
(struct nsm_get_ethernet_port_telemetry_counter_req *)msg->payload;
if (request->hdr.data_size < sizeof(request->port_number)) {
return NSM_SW_ERROR_DATA;
}
*port_number = le16toh(request->port_number);
return NSM_SW_SUCCESS;
}
int decode_aggregate_eth_port_telemetry_data(
const uint8_t *data, size_t *data_len, uint8_t tag,
nsm_ethernet_port_counter_data *counter_reading)
{
if (data == NULL || data_len == NULL || counter_reading == NULL) {
return NSM_SW_ERROR_NULL;
}
switch (tag) {
case ETHERNET_PORT_COUNTER_TAG_RX_BYTES:
case ETHERNET_PORT_COUNTER_TAG_TX_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_UNICAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_MULTICAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_BROADCAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_TX_UNICAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_TX_MULTICAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_TX_BROADCAST_BYTES: {
if (*data_len != sizeof(uint64_t)) {
return NSM_SW_ERROR_LENGTH;
}
uint64_t le_reading;
memcpy(&le_reading, data, sizeof(uint64_t));
counter_reading->ethernet_port_counter_data_64bit =
le64toh(le_reading);
break;
}
case ETHERNET_PORT_COUNTER_TAG_RX_FCS_ERRORS:
case ETHERNET_PORT_COUNTER_TAG_RX_ALIGNMENT_ERRORS:
case ETHERNET_PORT_COUNTER_TAG_RX_FALSE_CARRIER_DETECTIONS:
case ETHERNET_PORT_COUNTER_TAG_RX_RUNT_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_JABBER_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_XON_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_XOFF_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_TX_XON_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_TX_XOFF_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_SINGLE_COLLISION_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_MULTIPLE_COLLISION_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_LATE_COLLISION_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_EXCESSIVE_COLLISION_FRAMES: {
if (*data_len != sizeof(uint32_t)) {
return NSM_SW_ERROR_LENGTH;
}
uint32_t le_reading32;
memcpy(&le_reading32, data, sizeof(uint32_t));
counter_reading->ethernet_port_counter_data_32bit =
le32toh(le_reading32);
break;
}
default:
return NSM_SW_ERROR_DATA;
}
return NSM_SW_SUCCESS;
}
int encode_aggregate_eth_port_telemetry_data(
uint8_t tag, nsm_ethernet_port_counter_data *counter_reading, uint8_t *data,
size_t *data_len)
{
if (data == NULL || data_len == NULL || counter_reading == NULL) {
return NSM_SW_ERROR_NULL;
}
switch (tag) {
case ETHERNET_PORT_COUNTER_TAG_RX_BYTES:
case ETHERNET_PORT_COUNTER_TAG_TX_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_UNICAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_MULTICAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_BROADCAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_TX_UNICAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_TX_MULTICAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_TX_BROADCAST_BYTES: {
if (*data_len != sizeof(uint64_t)) {
return NSM_SW_ERROR_LENGTH;
}
uint64_t le_reading =
htole64(counter_reading->ethernet_port_counter_data_64bit);
memcpy(data, &le_reading, sizeof(uint64_t));
*data_len = sizeof(uint64_t);
break;
}
case ETHERNET_PORT_COUNTER_TAG_RX_FCS_ERRORS:
case ETHERNET_PORT_COUNTER_TAG_RX_ALIGNMENT_ERRORS:
case ETHERNET_PORT_COUNTER_TAG_RX_FALSE_CARRIER_DETECTIONS:
case ETHERNET_PORT_COUNTER_TAG_RX_RUNT_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_JABBER_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_XON_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_XOFF_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_TX_XON_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_TX_XOFF_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_SINGLE_COLLISION_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_MULTIPLE_COLLISION_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_LATE_COLLISION_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_EXCESSIVE_COLLISION_FRAMES: {
if (*data_len != sizeof(uint32_t)) {
return NSM_SW_ERROR_LENGTH;
}
uint32_t le_reading32 =
htole32(counter_reading->ethernet_port_counter_data_32bit);
memcpy(data, &le_reading32, sizeof(uint32_t));
*data_len = sizeof(uint32_t);
break;
}
default:
return NSM_SW_ERROR_DATA;
}
return NSM_SW_SUCCESS;
}
int encode_get_network_addresses_req(uint8_t instance_id, uint16_t port_number,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
struct nsm_get_network_addresses_req *request =
(struct nsm_get_network_addresses_req *)msg->payload;
request->hdr.command = NSM_GET_NETWORK_ADDRESSES;
request->hdr.data_size = sizeof(port_number);
request->port_number = htole16(port_number);
return NSM_SW_SUCCESS;
}
int decode_get_network_addresses_req(const struct nsm_msg *msg, size_t msg_len,
uint16_t *port_number)
{
if (msg == NULL || port_number == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_get_network_addresses_req)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_get_network_addresses_req *request =
(struct nsm_get_network_addresses_req *)msg->payload;
if (request->hdr.data_size != sizeof(request->port_number)) {
return NSM_SW_ERROR_DATA;
}
*port_number = le16toh(request->port_number);
return NSM_SW_SUCCESS;
}
int decode_aggregate_network_address_data(uint8_t tag, const uint8_t *data,
size_t data_len,
network_address_sample_data *address)
{
if (data == NULL || address == NULL) {
return NSM_SW_ERROR_NULL;
}
switch (tag) {
case NSM_TAG_LINK_TYPE:
if (data_len != sizeof(uint8_t)) {
return NSM_SW_ERROR_LENGTH;
}
address->link_type = data[0];
break;
case NSM_TAG_MAC_ADDRESS:
case NSM_TAG_PERMANENT_MAC_ADDRESS:
if (data_len != MAC_ADDRESS_LENGTH) {
return NSM_SW_ERROR_LENGTH;
}
memcpy(address->mac_address, data, MAC_ADDRESS_LENGTH);
break;
case NSM_TAG_NODE_GUID:
case NSM_TAG_PORT_GUID:
if (data_len != sizeof(uint64_t)) {
return NSM_SW_ERROR_LENGTH;
}
uint64_t le_reading;
memcpy(&le_reading, data, sizeof(uint64_t));
address->network_identifier_64bit = le64toh(le_reading);
break;
default:
return NSM_SW_ERROR_DATA;
}
return NSM_SW_SUCCESS;
}
int encode_aggregate_network_address_data(
uint8_t tag, const network_address_sample_data *address, uint8_t *data,
size_t *data_len)
{
if (address == NULL || data == NULL || data_len == NULL) {
return NSM_SW_ERROR_NULL;
}
switch (tag) {
case NSM_TAG_LINK_TYPE:
*data_len = sizeof(uint8_t);
data[0] = address->link_type;
break;
case NSM_TAG_MAC_ADDRESS:
case NSM_TAG_PERMANENT_MAC_ADDRESS: {
memcpy(data, address->mac_address, MAC_ADDRESS_LENGTH);
*data_len = MAC_ADDRESS_LENGTH;
break;
}
case NSM_TAG_NODE_GUID:
case NSM_TAG_PORT_GUID: {
uint64_t le_reading =
htole64(address->network_identifier_64bit);
memcpy(data, &le_reading, sizeof(uint64_t));
*data_len = sizeof(uint64_t);
break;
}
default:
return NSM_SW_ERROR_DATA;
}
return NSM_SW_SUCCESS;
}
int encode_get_port_ecc_counters_req(uint8_t instance_id, uint16_t port_number,
struct nsm_msg *msg)
{
if (msg == NULL) {
return NSM_SW_ERROR_NULL;
}
struct nsm_header_info header = {0};
header.nsm_msg_type = NSM_REQUEST;
header.instance_id = instance_id;
header.nvidia_msg_type = NSM_TYPE_NETWORK_PORT;
uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
if (rc != NSM_SW_SUCCESS) {
return rc;
}
struct nsm_get_port_ecc_counters_req *request =
(struct nsm_get_port_ecc_counters_req *)msg->payload;
request->hdr.command = NSM_GET_PORT_ECC_COUNTERS;
request->hdr.data_size = sizeof(port_number);
request->port_number = htole16(port_number);
return NSM_SW_SUCCESS;
}
int decode_get_port_ecc_counters_req(const struct nsm_msg *msg, size_t msg_len,
uint16_t *port_number)
{
if (msg == NULL || port_number == NULL) {
return NSM_SW_ERROR_NULL;
}
if (msg_len < sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_get_port_ecc_counters_req)) {
return NSM_SW_ERROR_LENGTH;
}
struct nsm_get_port_ecc_counters_req *request =
(struct nsm_get_port_ecc_counters_req *)msg->payload;
if (request->hdr.data_size < sizeof(request->port_number)) {
return NSM_SW_ERROR_DATA;
}
*port_number = le16toh(request->port_number);
return NSM_SW_SUCCESS;
}
int decode_aggregate_port_ecc_counter_data(uint8_t tag, const uint8_t *data,
size_t data_len,
uint64_t *counter_value)
{
if (data == NULL || counter_value == NULL) {
return NSM_SW_ERROR_NULL;
}
if (data_len != sizeof(uint64_t)) {
return NSM_SW_ERROR_LENGTH;
}
switch (tag) {
case NSM_TAG_ECC_RX_SYMBOL_ERRORS_BYTES:
case NSM_TAG_ECC_CORRECTED_BITS:
case NSM_TAG_ECC_RAW_ERRORS_LANE_0:
case NSM_TAG_ECC_RAW_ERRORS_LANE_1:
case NSM_TAG_ECC_RAW_ERRORS_LANE_2:
case NSM_TAG_ECC_RAW_ERRORS_LANE_3: {
uint64_t le_reading;
memcpy(&le_reading, data, sizeof(uint64_t));
*counter_value = le64toh(le_reading);
break;
}
default:
return NSM_SW_ERROR_DATA;
}
return NSM_SW_SUCCESS;
}
int encode_aggregate_port_ecc_counter_data(uint8_t tag, uint64_t counter_value,
uint8_t *data, size_t *data_len)
{
if (data == NULL || data_len == NULL) {
return NSM_SW_ERROR_NULL;
}
switch (tag) {
case NSM_TAG_ECC_RX_SYMBOL_ERRORS_BYTES:
case NSM_TAG_ECC_CORRECTED_BITS:
case NSM_TAG_ECC_RAW_ERRORS_LANE_0:
case NSM_TAG_ECC_RAW_ERRORS_LANE_1:
case NSM_TAG_ECC_RAW_ERRORS_LANE_2:
case NSM_TAG_ECC_RAW_ERRORS_LANE_3: {
uint64_t le_value = htole64(counter_value);
memcpy(data, &le_value, sizeof(uint64_t));
*data_len = sizeof(uint64_t);
break;
}
default:
return NSM_SW_ERROR_DATA;
}
return NSM_SW_SUCCESS;
}