1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ 2 3 #include <assert.h> 4 #include <stdlib.h> 5 #include <stdio.h> 6 #include <string.h> 7 8 #include "compiler.h" 9 #include "libmctp.h" 10 #include "test-utils.h" 11 12 #ifndef ARRAY_SIZE 13 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 14 #endif 15 16 struct test_ctx { 17 struct mctp *mctp; 18 struct mctp_binding_test *binding; 19 int rx_count; 20 uint8_t rx_data[4]; 21 size_t rx_len; 22 }; 23 24 static void test_rx(uint8_t eid __unused, bool tag_owner __unused, 25 uint8_t msg_tag __unused, void *data, void *msg, size_t len) 26 { 27 struct test_ctx *ctx = data; 28 29 ctx->rx_count++; 30 31 /* append incoming message data to the existing rx_data */ 32 assert(len <= sizeof(ctx->rx_data)); 33 assert(ctx->rx_len + len <= sizeof(ctx->rx_data)); 34 35 memcpy(ctx->rx_data + ctx->rx_len, msg, len); 36 ctx->rx_len += len; 37 } 38 39 #define SEQ(x) (x << MCTP_HDR_SEQ_SHIFT) 40 41 struct test { 42 int n_packets; 43 uint8_t flags_seq_tags[4]; 44 int exp_rx_count; 45 size_t exp_rx_len; 46 } tests[] = { 47 { 48 /* single packet */ 49 .n_packets = 1, 50 .flags_seq_tags = { 51 SEQ(1) | MCTP_HDR_FLAG_SOM | MCTP_HDR_FLAG_EOM, 52 }, 53 .exp_rx_count = 1, 54 .exp_rx_len = 1, 55 }, 56 { 57 /* two packets: one start, one end */ 58 .n_packets = 2, 59 .flags_seq_tags = { 60 SEQ(1) | MCTP_HDR_FLAG_SOM, 61 SEQ(2) | MCTP_HDR_FLAG_EOM, 62 }, 63 .exp_rx_count = 1, 64 .exp_rx_len = 2, 65 }, 66 { 67 /* three packets: one start, one no flags, one end */ 68 .n_packets = 3, 69 .flags_seq_tags = { 70 SEQ(1) | MCTP_HDR_FLAG_SOM, 71 SEQ(2), 72 SEQ(3) | MCTP_HDR_FLAG_EOM, 73 }, 74 .exp_rx_count = 1, 75 .exp_rx_len = 3, 76 }, 77 { 78 /* two packets, wrapping sequence numbers */ 79 .n_packets = 2, 80 .flags_seq_tags = { 81 SEQ(3) | MCTP_HDR_FLAG_SOM, 82 SEQ(0) | MCTP_HDR_FLAG_EOM, 83 }, 84 .exp_rx_count = 1, 85 .exp_rx_len = 2, 86 }, 87 { 88 /* two packets, invalid sequence number */ 89 .n_packets = 2, 90 .flags_seq_tags = { 91 SEQ(1) | MCTP_HDR_FLAG_SOM, 92 SEQ(3) | MCTP_HDR_FLAG_EOM, 93 }, 94 .exp_rx_count = 0, 95 .exp_rx_len = 0, 96 }, 97 }; 98 99 static void run_one_test(struct test_ctx *ctx, struct test *test) 100 { 101 const mctp_eid_t local_eid = 8; 102 const mctp_eid_t remote_eid = 9; 103 struct { 104 struct mctp_hdr hdr; 105 uint8_t payload[1]; 106 } pktbuf; 107 int i; 108 109 ctx->rx_count = 0; 110 ctx->rx_len = 0; 111 112 mctp_test_stack_init(&ctx->mctp, &ctx->binding, local_eid); 113 114 mctp_set_rx_all(ctx->mctp, test_rx, ctx); 115 116 for (i = 0; i < test->n_packets; i++) { 117 memset(&pktbuf, 0, sizeof(pktbuf)); 118 pktbuf.hdr.dest = local_eid; 119 pktbuf.hdr.src = remote_eid; 120 pktbuf.hdr.flags_seq_tag = test->flags_seq_tags[i]; 121 pktbuf.payload[0] = i; 122 123 mctp_binding_test_rx_raw(ctx->binding, &pktbuf, sizeof(pktbuf)); 124 } 125 126 assert(ctx->rx_count == test->exp_rx_count); 127 assert(ctx->rx_len == test->exp_rx_len); 128 129 /* ensure the payload data was reconstructed correctly */ 130 for (i = 0; i < (int)ctx->rx_len; i++) 131 assert(ctx->rx_data[i] == i); 132 133 mctp_binding_test_destroy(ctx->binding); 134 mctp_destroy(ctx->mctp); 135 } 136 137 int main(void) 138 { 139 struct test_ctx ctx; 140 unsigned int i; 141 142 for (i = 0; i < ARRAY_SIZE(tests); i++) 143 run_one_test(&ctx, &tests[i]); 144 145 return EXIT_SUCCESS; 146 } 147