core: Add TX/RX API that exposes message tag and tag owner
MCTP received packets can carry a message tag and tag owner bit
which is set by a remote MCTP endpoint. This can be used by the
remote MCTP endpoint to track the responses. Thus, libmctp should
provide a mechanism for the upper layer MCTP applications to
respond with the same message tag.
This patchset extends TX and RX API with message tag and
tag owner bits.
Signed-off-by: Sumanth Bhat <sumanth.bhat@linux.intel.com>
Change-Id: I6d07eafa86c653abdd4313ab7cc77e5a93124477
diff --git a/tests/test_astlpc.c b/tests/test_astlpc.c
index 054eda1..f781fa5 100644
--- a/tests/test_astlpc.c
+++ b/tests/test_astlpc.c
@@ -150,7 +150,8 @@
.lpc_write = mctp_astlpc_mmio_lpc_write,
};
-static void rx_message(uint8_t eid __unused, void *data __unused, void *msg,
+static void rx_message(uint8_t eid __unused, bool tag_owner __unused,
+ uint8_t msg_tag __unused, void *data __unused, void *msg,
size_t len)
{
struct astlpc_test *test = data;
@@ -257,7 +258,8 @@
mctp_set_rx_all(ctx.host.mctp, rx_message, &ctx);
/* BMC sends a message */
- rc = mctp_message_tx(ctx.bmc.mctp, 9, msg, sizeof(msg));
+ rc = mctp_message_tx(ctx.bmc.mctp, 9, MCTP_MESSAGE_TO_SRC, 0, msg,
+ sizeof(msg));
assert(rc == 0);
/* Host receives the first packet */
@@ -284,6 +286,7 @@
{
struct astlpc_test ctx = { 0 };
uint8_t msg[MCTP_BTU];
+ uint8_t tag = 0;
int rc;
/* Test harness initialisation */
@@ -297,7 +300,8 @@
mctp_set_rx_all(ctx.bmc.mctp, rx_message, &ctx);
/* Host sends the single-packet message */
- rc = mctp_message_tx(ctx.host.mctp, 8, msg, sizeof(msg));
+ rc = mctp_message_tx(ctx.host.mctp, 8, MCTP_MESSAGE_TO_DST, tag, msg,
+ sizeof(msg));
assert(rc == 0);
assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
@@ -324,6 +328,7 @@
{
struct astlpc_test ctx = { 0 };
uint8_t msg[MCTP_BTU];
+ uint8_t tag = 0;
int rc;
/* Test harness initialisation */
@@ -337,7 +342,8 @@
mctp_set_rx_all(ctx.host.mctp, rx_message, &ctx);
/* BMC sends the single-packet message */
- rc = mctp_message_tx(ctx.bmc.mctp, 9, msg, sizeof(msg));
+ rc = mctp_message_tx(ctx.bmc.mctp, 9, MCTP_MESSAGE_TO_SRC, tag, msg,
+ sizeof(msg));
assert(rc == 0);
assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
@@ -549,6 +555,7 @@
struct astlpc_test ctx = { 0 };
uint8_t kcs[2] = { 0 };
uint8_t msg[MCTP_BTU];
+ uint8_t tag = 0;
int rc;
ctx.lpc_mem = calloc(1, LPC_WIN_SIZE);
@@ -594,7 +601,8 @@
mctp_set_rx_all(ctx.host.mctp, rx_message, &ctx);
/* BMC sends the single-packet message */
- rc = mctp_message_tx(ctx.bmc.mctp, 9, msg, sizeof(msg));
+ rc = mctp_message_tx(ctx.bmc.mctp, 9, MCTP_MESSAGE_TO_SRC, tag, msg,
+ sizeof(msg));
assert(rc == 0);
/* Host receives the single-packet message */
@@ -615,6 +623,7 @@
struct astlpc_test ctx = { 0 };
uint8_t unwritten[MCTP_BTU];
uint8_t msg[MCTP_BTU];
+ uint8_t tag = 0;
int rc;
/* Test harness initialisation */
@@ -634,7 +643,8 @@
mctp_astlpc_poll(ctx.host.astlpc);
/* Host attempts to send the single-packet message, but is prevented */
- rc = mctp_message_tx(ctx.host.mctp, 8, msg, sizeof(msg));
+ rc = mctp_message_tx(ctx.host.mctp, 8, MCTP_MESSAGE_TO_DST, tag, msg,
+ sizeof(msg));
assert(rc == 0);
assert(!(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF));
astlpc_assert_tx_packet(&ctx.host, &unwritten[0], MCTP_BTU);
@@ -1083,6 +1093,7 @@
struct astlpc_endpoint *bmc, *host;
struct astlpc_test ctx;
uint8_t kcs[2] = { 0 };
+ uint8_t tag = 0;
void *lpc_mem;
int rc;
@@ -1117,7 +1128,8 @@
memset(ctx.msg, 0x5a, 2 * MCTP_BODY_SIZE(8192));
- rc = mctp_message_tx(host->mctp, 8, ctx.msg, 2 * MCTP_BODY_SIZE(8192));
+ rc = mctp_message_tx(host->mctp, 8, MCTP_MESSAGE_TO_DST, tag, ctx.msg,
+ 2 * MCTP_BODY_SIZE(8192));
assert(rc == 0);
rc = mctp_astlpc_poll(bmc->astlpc);
assert(rc == 0);
@@ -1142,6 +1154,7 @@
struct astlpc_test ctx;
uint8_t kcs[2] = { 0 };
uint8_t msg[MCTP_BTU];
+ uint8_t tag = 0;
void *lpc_mem;
int rc;
@@ -1165,7 +1178,8 @@
* terminating after a period long enough to packetise the message.
*/
alarm(1);
- mctp_message_tx(bmc->mctp, 9, msg, sizeof(msg));
+ mctp_message_tx(bmc->mctp, 9, MCTP_MESSAGE_TO_SRC, tag, msg,
+ sizeof(msg));
alarm(0);
endpoint_destroy(bmc);
@@ -1178,6 +1192,7 @@
struct mctp_lpcmap_hdr *hdr;
uint8_t msg[MCTP_BTU];
uint32_t offset;
+ uint8_t tag = 0;
uint32_t code;
uint8_t *tlr;
int rc;
@@ -1193,7 +1208,8 @@
mctp_set_rx_all(ctx.bmc.mctp, rx_message, &ctx);
/* Host sends the single-packet message */
- rc = mctp_message_tx(ctx.host.mctp, 8, msg, sizeof(msg));
+ rc = mctp_message_tx(ctx.host.mctp, 8, MCTP_MESSAGE_TO_DST, tag, msg,
+ sizeof(msg));
assert(rc == 0);
assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
@@ -1230,6 +1246,7 @@
struct mctp_lpcmap_hdr *hdr;
uint8_t msg[MCTP_BTU];
uint32_t offset;
+ uint8_t tag = 0;
uint32_t code;
uint8_t *tlr;
int rc;
@@ -1245,7 +1262,8 @@
mctp_set_rx_all(ctx.host.mctp, rx_message, &ctx);
/* BMC sends the single-packet message */
- rc = mctp_message_tx(ctx.bmc.mctp, 9, msg, sizeof(msg));
+ rc = mctp_message_tx(ctx.bmc.mctp, 9, MCTP_MESSAGE_TO_SRC, tag, msg,
+ sizeof(msg));
assert(rc == 0);
assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
diff --git a/tests/test_cmds.c b/tests/test_cmds.c
index 1b7536a..ca5e838 100644
--- a/tests/test_cmds.c
+++ b/tests/test_cmds.c
@@ -32,6 +32,8 @@
};
static void control_message_transport_callback(mctp_eid_t src __unused,
+ bool tag_owner __unused,
+ uint8_t msg_tag __unused,
void *data, void *buf,
size_t len __unused)
{
diff --git a/tests/test_core.c b/tests/test_core.c
index dacf197..744fe96 100644
--- a/tests/test_core.c
+++ b/tests/test_core.c
@@ -42,17 +42,21 @@
struct test_params {
bool seen;
size_t message_size;
+ uint8_t msg_tag;
+ bool tag_owner;
};
-static void rx_message(uint8_t eid __unused, void *data, void *msg __unused,
- size_t len)
+static void rx_message(uint8_t eid __unused, bool tag_owner, uint8_t msg_tag,
+ void *data, void *msg __unused, size_t len)
{
struct test_params *param = (struct test_params *)data;
- mctp_prdebug("MCTP message received: len %zd", len);
+ mctp_prdebug("MCTP message received: len %zd, tag %u", len, msg_tag);
param->seen = true;
param->message_size = len;
+ param->msg_tag = msg_tag;
+ param->tag_owner = tag_owner;
}
static uint8_t get_sequence()
@@ -441,6 +445,92 @@
mctp_destroy(mctp);
}
+static void mctp_core_test_rx_with_tag()
+{
+ struct mctp *mctp = NULL;
+ struct mctp_binding_test *binding = NULL;
+ struct test_params test_param;
+ static uint8_t test_payload[MCTP_BTU];
+ uint8_t tag = get_tag();
+ struct pktbuf pktbuf;
+ uint8_t flags_seq_tag;
+
+ memset(test_payload, 0, sizeof(test_payload));
+ test_param.seen = false;
+ test_param.message_size = 0;
+ test_param.msg_tag = 0;
+ test_param.tag_owner = false;
+
+ mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
+ mctp_set_rx_all(mctp, rx_message, &test_param);
+ memset(&pktbuf, 0, sizeof(pktbuf));
+ pktbuf.hdr.dest = TEST_DEST_EID;
+ pktbuf.hdr.src = TEST_SRC_EID;
+
+ /* Set tag and tag owner fields for a recieve packet */
+ flags_seq_tag = MCTP_HDR_FLAG_SOM | MCTP_HDR_FLAG_EOM |
+ (1 << MCTP_HDR_TO_SHIFT) | tag;
+ receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
+ &pktbuf);
+
+ assert(test_param.seen);
+ assert(test_param.message_size == (MCTP_BTU));
+ assert(test_param.msg_tag == tag);
+ assert(test_param.tag_owner);
+
+ mctp_binding_test_destroy(binding);
+ mctp_destroy(mctp);
+}
+
+static void mctp_core_test_rx_with_tag_multifragment()
+{
+ struct mctp *mctp = NULL;
+ struct mctp_binding_test *binding = NULL;
+ struct test_params test_param;
+ static uint8_t test_payload[MCTP_BTU];
+ uint8_t tag = get_tag();
+ struct pktbuf pktbuf;
+ uint8_t flags_seq_tag;
+
+ memset(test_payload, 0, sizeof(test_payload));
+ test_param.seen = false;
+ test_param.message_size = 0;
+ test_param.msg_tag = 0;
+ test_param.tag_owner = false;
+
+ mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
+ mctp_set_rx_all(mctp, rx_message, &test_param);
+ memset(&pktbuf, 0, sizeof(pktbuf));
+ pktbuf.hdr.dest = TEST_DEST_EID;
+ pktbuf.hdr.src = TEST_SRC_EID;
+
+ /* Set tag and tag owner fields for a 3 fragment packet */
+ flags_seq_tag = MCTP_HDR_FLAG_SOM |
+ (get_sequence() << MCTP_HDR_SEQ_SHIFT) |
+ (1 << MCTP_HDR_TO_SHIFT) | tag;
+ receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
+ &pktbuf);
+
+ flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) |
+ (1 << MCTP_HDR_TO_SHIFT) | tag;
+ receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
+ &pktbuf);
+
+ flags_seq_tag = MCTP_HDR_FLAG_EOM |
+ (get_sequence() << MCTP_HDR_SEQ_SHIFT) |
+ (1 << MCTP_HDR_TO_SHIFT) | tag;
+ receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
+ &pktbuf);
+
+ assert(test_param.seen);
+ assert(test_param.message_size == (3 * MCTP_BTU));
+ assert(test_param.msg_tag == tag);
+ assert(test_param.tag_owner);
+
+ mctp_binding_test_destroy(binding);
+ mctp_destroy(mctp);
+}
+
/* clang-format off */
#define TEST_CASE(test) { #test, test }
static const struct {
@@ -455,6 +545,8 @@
TEST_CASE(mctp_core_test_receive_bigger_end_fragment),
TEST_CASE(mctp_core_test_drop_large_fragments),
TEST_CASE(mctp_core_test_exhaust_context_buffers),
+ TEST_CASE(mctp_core_test_rx_with_tag),
+ TEST_CASE(mctp_core_test_rx_with_tag_multifragment),
};
/* clang-format on */
diff --git a/tests/test_eid.c b/tests/test_eid.c
index 031d044..5c089ad 100644
--- a/tests/test_eid.c
+++ b/tests/test_eid.c
@@ -16,7 +16,9 @@
mctp_eid_t src_eid;
};
-static void test_rx(uint8_t eid, void *data, void *msg, size_t len)
+static void
+test_rx(uint8_t eid, bool tag_owner __unused, uint8_t msg_tag __unused,
+ void *data, void *msg __unused, size_t len __unused)
{
struct test_ctx *ctx = data;
diff --git a/tests/test_seq.c b/tests/test_seq.c
index 8838acb..e5a8954 100644
--- a/tests/test_seq.c
+++ b/tests/test_seq.c
@@ -19,12 +19,12 @@
size_t rx_len;
};
-static void test_rx(uint8_t eid, void *data, void *msg, size_t len)
+static void
+test_rx(uint8_t eid __unused, bool tag_owner __unused,
+ uint8_t msg_tag __unused, void *data, void *msg, size_t len)
{
struct test_ctx *ctx = data;
- (void)eid;
-
ctx->rx_count++;
/* append incoming message data to the existing rx_data */
diff --git a/tests/test_serial.c b/tests/test_serial.c
index 3c6d147..aa282c9 100644
--- a/tests/test_serial.c
+++ b/tests/test_serial.c
@@ -43,20 +43,25 @@
uint8_t mctp_msg_src[2 * MCTP_BTU];
static bool seen;
+static bool received_tag_owner;
+static uint8_t received_msg_tag;
-static void rx_message(uint8_t eid __unused, void *data __unused, void *msg,
- size_t len)
+static void rx_message(uint8_t eid __unused, bool tag_owner, uint8_t msg_tag,
+ void *data __unused, void *msg, size_t len)
{
uint8_t type;
type = *(uint8_t *)msg;
- mctp_prdebug("MCTP message received: len %zd, type %d", len, type);
+ mctp_prdebug("MCTP message received: len %zd, type %d, tag %d", len,
+ type, msg_tag);
assert(sizeof(mctp_msg_src) == len);
assert(!memcmp(mctp_msg_src, msg, len));
seen = true;
+ received_msg_tag = msg_tag;
+ received_tag_owner = tag_owner;
}
struct serial_test {
@@ -70,6 +75,8 @@
struct mctp_binding_serial_pipe *a;
struct mctp_binding_serial_pipe *b;
+ uint8_t msg_tag = 2;
+ bool tag_owner = false;
int p[2][2];
int rc;
@@ -109,14 +116,19 @@
mctp_serial_set_tx_fn(b->serial, mctp_binding_serial_pipe_tx, a);
mctp_register_bus(scenario[1].mctp, mctp_binding_serial_core(b->serial), 9);
- /* Transmit a message from A to B */
- rc = mctp_message_tx(scenario[0].mctp, 9, mctp_msg_src, sizeof(mctp_msg_src));
+ /* Transmit a message from A to B, with message tag */
+ rc = mctp_message_tx(scenario[0].mctp, 9, tag_owner, msg_tag,
+ mctp_msg_src, sizeof(mctp_msg_src));
assert(rc == 0);
/* Read the message at B from A */
seen = false;
+ received_tag_owner = true;
+ received_msg_tag = 0;
mctp_serial_read(b->serial);
assert(seen);
+ assert(received_tag_owner == tag_owner);
+ assert(received_msg_tag == msg_tag);
mctp_serial_destroy(scenario[1].binding.serial);
mctp_destroy(scenario[1].mctp);