FeatureRequest: Async support for ```send/receive``` payload
Currently in SPDM Requester case libspdm triggers send callback registered when it has payload to send.
Based on return value of the callback the receive callback registered is called subsequently.
In many applications(example: OpenBMC etc) async way of request/response is implemented at transport layer(mctp) where request is sent and once response is received it is handled.
The current implementation of libspdm requires response to be received before returning from send callback.
Can we have async way of handling in SPDM Requester case ?
- libspdm will trigger send callback
- Once the application receives the response
application will call for example:
process_received_messageprovided by libspdm to process the response for all the SPDM Request message
Thanks, Prithvi A Pai
See #1049 and #2406.
I checked the provided links. I see the support only for VCA. However, other APIs are still require support is that correct ? what is the plan for supporting all the APIs ?
We need some one validate and confirm that split is working, before we move too far.
@PrithviAPai , can you help to try the new API?
We need some one validate and confirm that split is working, before we move too far.
@PrithviAPai , can you help to try the new API?
Hi @jyao1, I did test the APIs provided in the PR.
About my setup: I have my device acting as SPDM Requester and a i2c simulator acting as SPDM Responder(which internally uses spdm-emu) The transport used is MCTP over SMBUS.
Findings:
- Transport layer
encode/decodeis NOT supported with the APIs provided. (The integrator has to add/remove Message Type SPMD(5) in case of MCTP). - GET VERSION Requester and Response is obtained --->
Works Fine. - GET CAP Request is sent but Response validation
FAILS. The reason is:
if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_process_response_capabilities header request version %02x\n",spdm_request->header.spdm_version));
status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
goto receive_done;
}
Prints: 0x00
- Once Request packet is formed
libspdm_send_spdm_requestis called where before adding transport specific header the request is stored in last_message_context. We might need to do that in our case
/* backup it to last_spdm_request, because the caller wants to compare it with response */
if (((const spdm_message_header_t *)request)->request_response_code != SPDM_RESPOND_IF_READY
&& ((const spdm_message_header_t *)request)->request_response_code != SPDM_CHUNK_GET
&& ((const spdm_message_header_t*) request)->request_response_code != SPDM_CHUNK_SEND) {
libspdm_copy_mem (context->last_spdm_request,
libspdm_get_scratch_buffer_last_spdm_request_capacity(context),
request,
request_size
);
context->last_spdm_request_size = request_size;
}
@steven-bellock @jyao1 can this be supported ? The PR added is NOT helping as transport encoding is not done and Receive part is NOT correctly handled. BMC is designed to work in asynchronous manner but libspdm requires synchronous approach. Please provide your feedback
I think what you want is a library that completely removes the transport portion. So in this case the Integrator
- Calls libspdm to generate a request that is stored in some buffer. This request may be encrypted.
- Sends the request to the Responder.
- Receives the response from the Responder and puts it in some buffer. This response may be encrypted.
- Calls libspdm to parse the Response.
In particular the Integrator has full ownership over 2 and 3. If so then yes, that's doable. @JakubLedworowski does that work for you as well?
yes, existing library can work as it is till encode/decode transport messages. Post which we can make sure the integrator takes care of sending and receiving the API. This helps in allowing integrator send and receive response in async way.
@steven-bellock yes, that approach works for me as long as the integrator has the option to use the transport layer methods directly (eg. libspdm_transport_mctp_encode_message) to avoid code duplication as it is already implemented in libspdm.
So, in case the integrator wants to use the new approach while reusing transport layer the flow would look like this:
- Calls libspdm to generate a request that is stored in some buffer. This request may be encrypted.
- [Optional] Calls libspdm to encode the request
- Sends the request to the Responder.
- Receives the response from the Responder and puts it in some buffer. This response may be encrypted.
- [Optional] Calls libspdm to decode the response
- Calls libspdm to parse the Response.
@steven-bellock up to transport layer encoding/decoding can be as we have currently. But, integrator need option to send/receive without having callbacks called for the same.
@steven-bellock can you please tell us some rough timelines when this will be available so that we can plan our deliverables accordingly ? Thanks a lot for your support and quick reply.
If it's at the normal pace of things maybe a year. We are focused on SPDM 1.3 features right now and it's taking a (long) while. That can obviously be accelerated if you, or someone else, implements the feature.
@steven-bellock please suggest if this looks good.
SEND PART
- Integrator to acquire
SenderBuffer. - Integrator to call
libspdm_build_spdm_request -
libspdm_build_spdm_requestto build spdm request + add transport encoding - Integrator gets the SPDM payload to be sent to spdm endpoint
- Integrator to release the
SenderBuffer
Questions
-
In libspdm_handle_large_requestwe have a looping logic which requires callback to triggered How should that be handled when we split the APIs ? Please shed some light
I'm interested in this feature as well.