Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 133 additions & 67 deletions spdm_emu/spdm_emu_common/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
**/

#include "spdm_emu.h"
#include <linux/mctp.h>
#include <errno.h>

/* hack to add MCTP header for PCAP*/
#include "industry_standard/mctp.h"
Expand All @@ -17,6 +19,8 @@ bool m_send_receive_buffer_acquired = false;
uint8_t m_send_receive_buffer[LIBSPDM_MAX_SENDER_RECEIVER_BUFFER_SIZE];
size_t m_send_receive_buffer_size;

uint8_t m_use_eid = 0;
uint8_t m_send_single_spdm_cmd = 0;
/**
* Read number of bytes data in blocking mode.
*
Expand All @@ -31,8 +35,17 @@ bool read_bytes(const SOCKET socket, uint8_t *buffer,

number_received = 0;
while (number_received < number_of_bytes) {
result = recv(socket, (char *)(buffer + number_received),
number_of_bytes - number_received, 0);
if (m_use_transport_layer == SOCKET_TRANSPORT_TYPE_MCTP_KERNEL) {
struct sockaddr_mctp addr = { 0 };
socklen_t addrlen = sizeof(addr);
result = recvfrom(socket, (char *)(buffer + number_received),
number_of_bytes - number_received, MSG_TRUNC,
(struct sockaddr *)&addr, &addrlen);
}
else {
result = recv(socket, (char *)(buffer + number_received),
number_of_bytes - number_received, 0);
}
if (result == -1) {
printf("Receive error - 0x%x\n",
#ifdef _MSC_VER
Expand Down Expand Up @@ -79,31 +92,51 @@ bool read_multiple_bytes(const SOCKET socket, uint8_t *buffer,
uint32_t length;
bool result;

result = read_data32(socket, &length);
if (!result) {
return result;
}
printf("Platform port Receive size: ");
length = ntohl(length);
dump_data((uint8_t *)&length, sizeof(uint32_t));
printf("\n");
length = ntohl(length);

*bytes_received = length;
if (*bytes_received > max_buffer_length) {
printf("buffer too small (0x%x). Expected - 0x%x\n",
max_buffer_length, *bytes_received);
return false;
}
if (length == 0) {
return true;
}
result = read_bytes(socket, buffer, length);
if (!result) {
return result;
if (m_use_transport_layer != SOCKET_TRANSPORT_TYPE_MCTP_KERNEL) {
result = read_data32(socket, &length);
if (!result) {
return result;
}
printf("Platform port Receive size: ");
length = ntohl(length);
dump_data((uint8_t *)&length, sizeof(uint32_t));
printf("\n");
length = ntohl(length);

*bytes_received = length;
if (*bytes_received > max_buffer_length) {
printf("buffer too small (0x%x). Expected - 0x%x\n",
max_buffer_length, *bytes_received);
return false;
}
if (length == 0) {
return true;
}
result = read_bytes(socket, buffer, length);
if (!result) {
return result;
}
} else {
length = recv(socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
if (length == -1) {
printf("Error: %s\n", strerror(errno));
return false;
}
if (length > max_buffer_length - 1) {
printf("buffer too small (0x%x). Expected - 0x%x\n",
max_buffer_length, length);
return false;
}
result = read_bytes(socket, buffer+1, length);
if (!result)
return result;
// mctp kernel receive payload only.
// So add msg_type byte to receive_message
buffer[0] = MCTP_MESSAGE_TYPE_SPDM;
*bytes_received = length + 1;
}
printf("Platform port Receive buffer:\n ");
dump_data(buffer, length);
dump_data(buffer, length + 1);
printf("\n");

return true;
Expand All @@ -118,30 +151,31 @@ bool receive_platform_data(const SOCKET socket, uint32_t *command,
uint32_t transport_type;
uint32_t bytes_received;

result = read_data32(socket, &response);
if (!result) {
return result;
}
*command = response;
printf("Platform port Receive command: ");
response = ntohl(response);
dump_data((uint8_t *)&response, sizeof(uint32_t));
printf("\n");

result = read_data32(socket, &transport_type);
if (!result) {
return result;
}
printf("Platform port Receive transport_type: ");
transport_type = ntohl(transport_type);
dump_data((uint8_t *)&transport_type, sizeof(uint32_t));
printf("\n");
transport_type = ntohl(transport_type);
if (transport_type != m_use_transport_layer) {
printf("transport_type mismatch\n");
return false;
if (m_use_transport_layer != SOCKET_TRANSPORT_TYPE_MCTP_KERNEL) {
result = read_data32(socket, &response);
if (!result) {
return result;
}
*command = response;
printf("Platform port Receive command: ");
response = ntohl(response);
dump_data((uint8_t *)&response, sizeof(uint32_t));
printf("\n");

result = read_data32(socket, &transport_type);
if (!result) {
return result;
}
printf("Platform port Receive transport_type: ");
transport_type = ntohl(transport_type);
dump_data((uint8_t *)&transport_type, sizeof(uint32_t));
printf("\n");
transport_type = ntohl(transport_type);
if (transport_type != m_use_transport_layer) {
printf("transport_type mismatch\n");
return false;
}
}

bytes_received = 0;
result = read_multiple_bytes(socket, receive_buffer, &bytes_received,
(uint32_t)*bytes_to_receive);
Expand Down Expand Up @@ -193,8 +227,25 @@ bool write_bytes(const SOCKET socket, const uint8_t *buffer,

number_sent = 0;
while (number_sent < number_of_bytes) {
result = send(socket, (char *)(buffer + number_sent),
number_of_bytes - number_sent, 0);
if (m_use_transport_layer == SOCKET_TRANSPORT_TYPE_MCTP_KERNEL) {
/* MCTP kernel approach does not support send() syscall
* sendto() is recommanded to send messages currently
* https://discord.com/channels/775381525260664832/775381525260664836/1161513903319158904 */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we consider using the official Linux man page — such as https://www.man7.org/linux/man-pages/man7/mctp.7.html — instead of the Discord link?

I’m unable to access Discord within the company network, and the man page provides a more reliable, standardized, and accessible reference for technical documentation.

struct sockaddr_mctp addr = { 0 };
addr.smctp_family = AF_MCTP;
if (m_use_eid != 0)
addr.smctp_addr.s_addr = m_use_eid;
addr.smctp_type = MCTP_MESSAGE_TYPE_SPDM;
addr.smctp_tag = MCTP_TAG_OWNER;
/* we own the tag, and so the kernel will allocate one for us */
result = sendto(socket, (char *)(buffer + number_sent),
number_of_bytes - number_sent, 0,
(struct sockaddr *)&addr, sizeof(addr));
}
else {
result = send(socket, (char *)(buffer + number_sent),
number_of_bytes - number_sent, 0);
}
if (result == -1) {
#ifdef _MSC_VER
if (WSAGetLastError() == 0x2745) {
Expand All @@ -208,6 +259,7 @@ bool write_bytes(const SOCKET socket, const uint8_t *buffer,
errno
#endif
);
printf("Something went wrong, cannot send()! errno = %s\n", strerror(errno));
#ifdef _MSC_VER
}
#endif
Expand Down Expand Up @@ -235,17 +287,25 @@ bool write_multiple_bytes(const SOCKET socket, const uint8_t *buffer,
{
bool result;

result = write_data32(socket, bytes_to_send);
if (!result) {
return result;
if (m_use_transport_layer != SOCKET_TRANSPORT_TYPE_MCTP_KERNEL)
{
result = write_data32(socket, bytes_to_send);
if (!result) {
return result;
}
}
printf("Platform port Transmit size: ");
bytes_to_send = htonl(bytes_to_send);
dump_data((uint8_t *)&bytes_to_send, sizeof(uint32_t));
printf("\n");
bytes_to_send = htonl(bytes_to_send);

result = write_bytes(socket, buffer, bytes_to_send);
if (m_use_transport_layer != SOCKET_TRANSPORT_TYPE_MCTP_KERNEL)
result = write_bytes(socket, buffer, bytes_to_send);
else {
//mctp kernel do not need to send message type in the payload
result = write_bytes(socket, buffer+1, bytes_to_send-1);
}
if (!result) {
return result;
}
Expand All @@ -262,19 +322,25 @@ bool send_platform_data(const SOCKET socket, uint32_t command,
uint32_t request;
uint32_t transport_type;

request = command;
result = write_data32(socket, request);
if (!result) {
return result;
}
printf("Platform port Transmit command: ");
request = htonl(request);
dump_data((uint8_t *)&request, sizeof(uint32_t));
printf("\n");

result = write_data32(socket, m_use_transport_layer);
if (!result) {
return result;
if(m_use_transport_layer != SOCKET_TRANSPORT_TYPE_MCTP_KERNEL)
{
request = command;
result = write_data32(socket, request);
if (!result) {
return result;
}
printf("Platform port Transmit command: ");
request = htonl(request);
dump_data((uint8_t *)&request, sizeof(uint32_t));
printf("\n");
result = write_data32(socket, m_use_transport_layer);
if (!result) {
return result;
}
printf("Platform port Transmit transport_type: ");
transport_type = ntohl(m_use_transport_layer);
dump_data((uint8_t *)&transport_type, sizeof(uint32_t));
printf("\n");
}
printf("Platform port Transmit transport_type: ");
transport_type = ntohl(m_use_transport_layer);
Expand Down
2 changes: 2 additions & 0 deletions spdm_emu/spdm_emu_common/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#define SOCKET_TRANSPORT_TYPE_MCTP 0x01
#define SOCKET_TRANSPORT_TYPE_PCI_DOE 0x02
#define SOCKET_TRANSPORT_TYPE_TCP 0x03
/* Support mctp kernel */
#define SOCKET_TRANSPORT_TYPE_MCTP_KERNEL 0x05
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clearly distinguish the Linux kernel’s MCTP stack, would it be better to rename SOCKET_TRANSPORT_TYPE_MCTP_KERNEL to SOCKET_TRANSPORT_TYPE_MCTP_LINUX_KERNEL?

Additionally, since other transport layers may be added in the future, it would be advisable to use platform-specific qualifiers in all MCTP transport type definitions. For example:

Suggested change
#define SOCKET_TRANSPORT_TYPE_MCTP_KERNEL 0x05
#define SOCKET_TRANSPORT_TYPE_MCTP_LINUX_KERNEL 0x0101 // MCTP transport via Linux kernel stack,

This approach ensures clarity, and supports scalable extension for new transport backends.


#define SOCKET_TCP_NO_HANDSHAKE 0x00
#define SOCKET_TCP_HANDSHAKE 0x01
Expand Down
Loading