Skip to content

Commit 814512c

Browse files
committed
Perftest: add T10DIF signature offload support
Add T10DIF type 1 data integrity checking with the following characteristics: - Fixed 512 byte blocks size for data integrity checks. - Uses MLX5DV APIs for signature block configuration - Configures CRC-based guard tag, application tag (0x5678), and reference tag (0xabcdef90) for integrity validation - Supports signature verification over wire domain. - Requires MLX5 hardware with signature offload capability. - A symmetric feature: if used, must be enabled on both server and client. - Supported only on RC. Example usage: $ ib_send_bw --sig_offload Signed-off-by: Shmuel Shaul <[email protected]>
1 parent 20e05b9 commit 814512c

File tree

6 files changed

+213
-8
lines changed

6 files changed

+213
-8
lines changed

configure.ac

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,14 @@ if [test $HAVE_AES_XTS = yes] && [test $HAVE_MLX5DV = yes]; then
202202
AC_DEFINE([HAVE_AES_XTS], [1], [Have AES XTS support])
203203
fi
204204

205+
AC_TRY_LINK([
206+
#include <infiniband/mlx5dv.h>],
207+
[int x = MLX5DV_CONTEXT_MASK_SIGNATURE_OFFLOAD;],[HAVE_SIG_OFFLOAD=yes], [HAVE_SIG_OFFLOAD=no])
208+
AM_CONDITIONAL([HAVE_SIG_OFFLOAD],[test "x$HAVE_SIG_OFFLOAD" = "xyes"])
209+
if [test $HAVE_SIG_OFFLOAD = yes] && [test $HAVE_MLX5DV = yes]; then
210+
AC_DEFINE([HAVE_SIG_OFFLOAD], [1], [Have signutre offload support])
211+
fi
212+
205213
AC_TRY_LINK([#include <infiniband/verbs.h>],
206214
[int c = IBV_GID_TYPE_ROCE_V1;],[HAVE_GID_TYPE_DECLARED=yes], [HAVE_GID_TYPE_DECLARED=no])
207215
AM_CONDITIONAL([HAVE_GID_TYPE_DECLARED],[test "x$HAVE_GID_TYPE_DECLARED" = "xyes"])

man/perftest.1

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ many different options and modes.
8080
Not relevant for RawEth and Write latency.
8181
System support required.
8282
.TP
83+
.B --sig_offload
84+
Runs traffic with T10DIF type 1 signature offload feature with 512 bytes block size.
85+
Not relevant for RawEth and Write latency.
86+
System support required.
87+
.TP
8388
.B --aes_block_size=<512,520,4048,4096,4160> (default 512)
8489
Not relevant for RawEth and Write latency.
8590
System support required.

src/perftest_parameters.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,9 @@ static void usage(const char *argv0, VerbType verb, TestType tst, int connection
311311
printf(" --credentials_path path to the credentials file\n");
312312
printf(" --data_enc_key_app_path path to the data encryption key app\n");
313313
#endif
314+
#ifdef HAVE_SIG_OFFLOAD
315+
printf(" --sig_offload Enable T10-DIF signature offload (data integrity) feature\n");
316+
#endif
314317
}
315318

316319
if (tst == LAT) {
@@ -1378,6 +1381,22 @@ static void force_dependecies(struct perftest_parameters *user_param)
13781381
}
13791382
#endif
13801383

1384+
#ifdef HAVE_SIG_OFFLOAD
1385+
if (user_param->sig_offload) {
1386+
if (user_param->connection_type != RC) {
1387+
printf(RESULT_LINE);
1388+
fprintf(stderr, " Signature offload supported only on RC\n");
1389+
exit(1);
1390+
}
1391+
1392+
if (user_param->size % 512 != 0) {
1393+
printf(RESULT_LINE);
1394+
printf(" Signature offload requires message size to be a multiple of 512 bytes.\n");
1395+
exit (1);
1396+
}
1397+
}
1398+
#endif
1399+
13811400
if (user_param->dualport == ON) {
13821401

13831402
user_param->num_of_qps *= 2;
@@ -1737,6 +1756,11 @@ static void force_dependecies(struct perftest_parameters *user_param)
17371756
fprintf(stderr," aes_xts doesn't support Inline messages\n");
17381757
exit(1);
17391758
}
1759+
if(user_param->sig_offload) {
1760+
printf(RESULT_LINE);
1761+
fprintf(stderr," aes_xts cannot be used with signature offload\n");
1762+
exit(1);
1763+
}
17401764
#else
17411765
printf(RESULT_LINE);
17421766
fprintf(stderr," aes_xts not supported\n");
@@ -2645,6 +2669,10 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc)
26452669
static int processing_hints_flag = 0;
26462670
#endif
26472671

2672+
#ifdef HAVE_SIG_OFFLOAD
2673+
static int sig_offload_flag = 0;
2674+
#endif
2675+
26482676
char *server_ip = NULL;
26492677
char *client_ip = NULL;
26502678
char *local_ip = NULL;
@@ -2826,7 +2854,10 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc)
28262854
{ .name = "tph_mem", .has_arg = 1, .flag = &tph_mem_flag, .val = 1},
28272855
{ .name = "cpu_id", .has_arg = 1, .flag = &cpu_id_flag, .val = 1},
28282856
{ .name = "ph", .has_arg = 1, .flag = &processing_hints_flag, .val = 1},
2857+
#endif
28292858
{ .name = "disable_dynamic_polling", .has_arg = 0, .flag = &disable_dynamic_polling_flag, .val = 1},
2859+
#ifdef HAVE_SIG_OFFLOAD
2860+
{.name = "sig_offload", .has_arg = 0, .flag = &sig_offload_flag, .val = 1 },
28302861
#endif
28312862
{0}
28322863
};
@@ -3618,6 +3649,11 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc)
36183649
processing_hints_flag = 0;
36193650
}
36203651
#endif
3652+
#ifdef HAVE_SIG_OFFLOAD
3653+
if (sig_offload_flag) {
3654+
user_param->sig_offload = 1;
3655+
}
3656+
#endif
36213657
break;
36223658
default:
36233659
fprintf(stderr," Invalid Command or flag.\n");

src/perftest_parameters.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,7 @@ struct perftest_parameters {
684684
int cpu_id;
685685
int processing_hints;
686686
int dynamic_cqe_poll;
687+
int sig_offload;
687688
};
688689

689690
struct report_options {

src/perftest_resources.c

Lines changed: 156 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,24 @@ int set_valid_cred(char *dst, struct perftest_parameters *user_param)
223223
}
224224
#endif
225225

226+
#ifdef HAVE_SIG_OFFLOAD
227+
static void set_sig_domain(struct pingpong_context *ctx){
228+
memset(ctx->t10dif_sig, 0, sizeof(struct mlx5dv_sig_t10dif));
229+
ctx->t10dif_sig->bg_type = MLX5DV_SIG_T10DIF_CRC;
230+
ctx->t10dif_sig->bg = 0xffff;
231+
ctx->t10dif_sig->app_tag = 0x5678;
232+
ctx->t10dif_sig->ref_tag = 0xabcdef90;
233+
ctx->t10dif_sig->flags = MLX5DV_SIG_T10DIF_FLAG_REF_REMAP |
234+
MLX5DV_SIG_T10DIF_FLAG_APP_ESCAPE;
235+
236+
memset(ctx->domain, 0, sizeof(struct mlx5dv_sig_block_domain));
237+
ctx->domain->sig.dif = ctx->t10dif_sig;
238+
ctx->domain->sig_type = MLX5DV_SIG_TYPE_T10DIF;
239+
ctx->domain->block_size = MLX5DV_BLOCK_SIZE_512;
240+
}
241+
242+
#endif
243+
226244
static uint32_t perftest_rand(uint32_t *state) {
227245
uint32_t x = *state;
228246
*state = x * 747796405 + 2891336453;
@@ -400,7 +418,42 @@ static inline int _new_post_send(struct pingpong_context *ctx,
400418
}
401419
#endif
402420

421+
#ifdef HAVE_SIG_OFFLOAD
422+
if (user_param->sig_offload){
423+
struct mlx5dv_sig_block_attr sig_attr = {
424+
.mem = NULL,
425+
.wire = ctx->domain,
426+
.check_mask = MLX5DV_SIG_MASK_T10DIF_GUARD |
427+
MLX5DV_SIG_MASK_T10DIF_APPTAG |
428+
MLX5DV_SIG_MASK_T10DIF_REFTAG
429+
};
430+
431+
struct mlx5dv_mkey_conf_attr conf_attr = {};
432+
uint32_t access_flags = IBV_ACCESS_LOCAL_WRITE |
433+
IBV_ACCESS_REMOTE_READ |
434+
IBV_ACCESS_REMOTE_WRITE;
435+
struct ibv_sge sgl;
436+
437+
ibv_wr_start(ctx->qpx[index]);
438+
ctx->qpx[index]->wr_flags = IBV_SEND_INLINE;
439+
440+
mlx5dv_wr_mkey_configure(ctx->dv_qp[index], ctx->mkey[index], 3, &conf_attr);
441+
mlx5dv_wr_set_mkey_access_flags(ctx->dv_qp[index], access_flags);
442+
443+
sgl.addr = (uintptr_t)ctx->mr[index]->addr;
444+
sgl.lkey = ctx->mr[index]->lkey;
445+
sgl.length = user_param->buff_size;
446+
447+
mlx5dv_wr_set_mkey_layout_list(ctx->dv_qp[index], 1, &sgl);
448+
449+
mlx5dv_wr_set_mkey_sig_block(ctx->dv_qp[index], &sig_attr);
403450

451+
if(ibv_wr_complete(ctx->qpx[index])) {
452+
fprintf(stderr, "MKEY T10DIF configuration failed: ibv_wr_complete failed.\n");
453+
return -1;
454+
}
455+
}
456+
#endif
404457

405458
ibv_wr_start(ctx->qpx[index]);
406459
while (wr)
@@ -1119,6 +1172,7 @@ int alloc_ctx(struct pingpong_context *ctx,struct perftest_parameters *user_para
11191172
ALLOC(ctx->qpx, struct ibv_qp_ex*, user_param->num_of_qps);
11201173
#ifdef HAVE_MLX5DV
11211174
ALLOC(ctx->dv_qp, struct mlx5dv_qp_ex*, user_param->num_of_qps);
1175+
ALLOC(ctx->mkey, struct mlx5dv_mkey*, user_param->num_of_qps);
11221176
#endif
11231177
ALLOC(ctx->r_dctn, uint32_t, user_param->num_of_qps);
11241178
#ifdef HAVE_DCS
@@ -1127,7 +1181,10 @@ int alloc_ctx(struct pingpong_context *ctx,struct perftest_parameters *user_para
11271181
#endif
11281182
#ifdef HAVE_AES_XTS
11291183
ALLOC(ctx->dek, struct mlx5dv_dek*, user_param->data_enc_keys_number);
1130-
ALLOC(ctx->mkey, struct mlx5dv_mkey*, user_param->num_of_qps);
1184+
#endif
1185+
#ifdef HAVE_SIG_OFFLOAD
1186+
ALLOC(ctx->domain, struct mlx5dv_sig_block_domain, 1);
1187+
ALLOC(ctx->t10dif_sig, struct mlx5dv_sig_t10dif, 1);
11311188
#endif
11321189
#endif
11331190
ALLOC(ctx->mr, struct ibv_mr*, user_param->num_of_qps);
@@ -1226,6 +1283,8 @@ void dealloc_ctx(struct pingpong_context *ctx,struct perftest_parameters *user_p
12261283
#ifdef HAVE_MLX5DV
12271284
if (ctx->dv_qp != NULL)
12281285
free(ctx->dv_qp);
1286+
if (ctx->mkey != NULL)
1287+
free(ctx->mkey);
12291288
#endif
12301289
if (ctx->r_dctn != NULL)
12311290
free(ctx->r_dctn);
@@ -1236,8 +1295,12 @@ void dealloc_ctx(struct pingpong_context *ctx,struct perftest_parameters *user_p
12361295
#ifdef HAVE_AES_XTS
12371296
if (ctx->dek != NULL)
12381297
free(ctx->dek);
1239-
if (ctx->mkey != NULL)
1240-
free(ctx->mkey);
1298+
#endif
1299+
#ifdef HAVE_SIG_OFFLOAD
1300+
if (ctx->domain != NULL)
1301+
free(ctx->domain);
1302+
if (ctx->t10dif_sig != NULL)
1303+
free(ctx->t10dif_sig);
12411304
#endif
12421305
#endif
12431306
if (ctx->mr != NULL)
@@ -1427,6 +1490,15 @@ int destroy_ctx(struct pingpong_context *ctx,
14271490
}
14281491
#endif
14291492

1493+
#ifdef HAVE_SIG_OFFLOAD
1494+
if(user_param->sig_offload){
1495+
for(i = 0; i < user_param->num_of_qps; i++) {
1496+
if (mlx5dv_destroy_mkey(ctx->mkey[i]))
1497+
fprintf(stderr, "Failed to destroy MKey.\n");
1498+
}
1499+
}
1500+
#endif
1501+
14301502
#ifdef HAVE_TD_API
14311503
if (user_param->no_lock) {
14321504
if (ibv_dealloc_pd(ctx->pad)) {
@@ -1653,6 +1725,32 @@ static uint32_t get_device_vendor(struct ibv_context *context)
16531725
/******************************************************************************
16541726
*
16551727
******************************************************************************/
1728+
static int is_sig_offload_supported(struct ibv_context *ibv_ctx)
1729+
{
1730+
uint32_t is_mlnx_device = get_device_vendor(ibv_ctx) == MLNX_VENDOR_ID;
1731+
1732+
if (!is_mlnx_device)
1733+
return 0;
1734+
1735+
struct mlx5dv_context ctx = {
1736+
.comp_mask = MLX5DV_CONTEXT_MASK_SIGNATURE_OFFLOAD,
1737+
};
1738+
1739+
if (mlx5dv_query_device(ibv_ctx, &ctx)) {
1740+
fprintf(stderr, "Failed to query device capabilities\n");
1741+
return 0;
1742+
}
1743+
1744+
if (!(ctx.sig_caps.t10dif_bg & MLX5DV_SIG_T10DIF_BG_CAP_CRC))
1745+
return 0;
1746+
1747+
return 1;
1748+
}
1749+
1750+
/******************************************************************************
1751+
*
1752+
******************************************************************************/
1753+
16561754
int create_reg_cqs(struct pingpong_context *ctx,
16571755
struct perftest_parameters *user_param,
16581756
int tx_buffer_depth, int need_recv_cq)
@@ -2233,7 +2331,7 @@ static int verify_ooo_settings(struct pingpong_context *ctx,
22332331

22342332
void check_bf_support(struct pingpong_context *ctx)
22352333
{
2236-
if (get_device_vendor(ctx->context) != 0x02c9)
2334+
if (get_device_vendor(ctx->context) != MLNX_VENDOR_ID)
22372335
return;
22382336

22392337
#ifdef HAVE_MLX5DV_BF_FLAG
@@ -2257,7 +2355,7 @@ int ctx_init(struct pingpong_context *ctx, struct perftest_parameters *user_para
22572355
int i;
22582356
int dct_only = (user_param->machine == SERVER && !(user_param->duplex || user_param->tst == LAT));
22592357
int qp_index = 0, dereg_counter;
2260-
#ifdef HAVE_AES_XTS
2358+
#ifdef HAVE_MLX5DV
22612359
int mkey_index = 0, dek_index = 0;
22622360
#endif
22632361

@@ -2367,6 +2465,34 @@ int ctx_init(struct pingpong_context *ctx, struct perftest_parameters *user_para
23672465
}
23682466
#endif
23692467

2468+
#ifdef HAVE_SIG_OFFLOAD
2469+
if(user_param->sig_offload){
2470+
struct mlx5dv_mkey_init_attr mkey_init_attr = {};
2471+
mkey_init_attr.pd = ctx->pd;
2472+
mkey_init_attr.max_entries = 1;
2473+
mkey_init_attr.create_flags = MLX5DV_MKEY_INIT_ATTR_FLAGS_INDIRECT |
2474+
MLX5DV_MKEY_INIT_ATTR_FLAGS_BLOCK_SIGNATURE;
2475+
2476+
if (!is_sig_offload_supported(ctx->context)) {
2477+
fprintf(stderr, "T10DIF signature offload is not supported by the device\n");
2478+
goto mkey;
2479+
}
2480+
2481+
for(i = 0; i < user_param->num_of_qps; i++) {
2482+
ctx->mkey[i] = mlx5dv_create_mkey(&mkey_init_attr);
2483+
2484+
if(!ctx->mkey[i]) {
2485+
fprintf(stderr, "Failed to create mkey\n");
2486+
goto mkey;
2487+
}
2488+
2489+
mkey_index++;
2490+
}
2491+
2492+
set_sig_domain(ctx);
2493+
}
2494+
#endif
2495+
23702496
if (ctx->memory->init(ctx->memory)) {
23712497
fprintf(stderr, "Failed to init memory\n");
23722498
goto mkey;
@@ -2513,12 +2639,19 @@ xrcd: __attribute__((unused))
25132639
if(user_param->aes_xts)
25142640
for (i = 0; i < mkey_index; i++)
25152641
mlx5dv_destroy_mkey(ctx->mkey[i]);
2642+
#endif
2643+
#ifdef HAVE_SIG_OFFLOAD
2644+
if(user_param->sig_offload)
2645+
for (i = 0; i < mkey_index; i++)
2646+
mlx5dv_destroy_mkey(ctx->mkey[i]);
2647+
#endif
25162648

2649+
#ifdef HAVE_AES_XTS
25172650
dek:
25182651
if(user_param->aes_xts)
25192652
for (i = 0; i < dek_index; i++)
25202653
mlx5dv_dek_destroy(ctx->dek[i]);
2521-
#endif
2654+
#endif
25222655

25232656
#ifdef HAVE_TD_API
25242657
if (user_param->no_lock)
@@ -2585,6 +2718,11 @@ int create_reg_qp_main(struct pingpong_context *ctx,
25852718
ctx->dv_qp[i] = mlx5dv_qp_ex_from_ibv_qp_ex(ctx->qpx[i]);
25862719
}
25872720
#endif
2721+
#ifdef HAVE_SIG_OFFLOAD
2722+
if (user_param->sig_offload) {
2723+
ctx->dv_qp[i] = mlx5dv_qp_ex_from_ibv_qp_ex(ctx->qpx[i]);
2724+
}
2725+
#endif
25882726
#endif
25892727
}
25902728
#endif
@@ -2764,7 +2902,7 @@ struct ibv_qp* ctx_qp_create(struct pingpong_context *ctx,
27642902
#ifdef HAVE_MLX5DV
27652903
#ifdef HAVE_OOO_RECV_WRS
27662904
// OOO_RECV_WRS is not supported by non-mlnx devices
2767-
is_mlnx_device = get_device_vendor(ctx->context) == 0x02c9;
2905+
is_mlnx_device = get_device_vendor(ctx->context) == MLNX_VENDOR_ID;
27682906

27692907
if (!user_param->no_enhanced_reorder && is_mlnx_device && user_param->connection_type != UD && user_param->connection_type != UC){
27702908
ctx_dv.comp_mask = MLX5DV_CONTEXT_MASK_OOO_RECV_WRS;
@@ -2825,6 +2963,17 @@ struct ibv_qp* ctx_qp_create(struct pingpong_context *ctx,
28252963
qp = mlx5dv_create_qp(ctx->context, &attr_ex, &attr_dv);
28262964
}
28272965
#endif // HAVE_AES_XTS
2966+
#ifdef HAVE_SIG_OFFLOAD
2967+
else if (user_param->sig_offload) {
2968+
/* 1 RDMA + 1 UMR + 1 SET_PSV */
2969+
attr_ex.cap.max_send_wr = user_param->tx_depth * 3;
2970+
attr_ex.cap.max_inline_data = 512;
2971+
attr_dv.comp_mask = MLX5DV_QP_INIT_ATTR_MASK_SEND_OPS_FLAGS;
2972+
attr_dv.send_ops_flags = MLX5DV_QP_EX_WITH_MKEY_CONFIGURE;
2973+
attr_dv.create_flags |= MLX5DV_QP_CREATE_DISABLE_SCATTER_TO_CQE;
2974+
qp = mlx5dv_create_qp(ctx->context, &attr_ex, &attr_dv);
2975+
}
2976+
#endif // HAVE_AES_XTS
28282977
#ifdef HAVE_OOO_RECV_WRS
28292978
else if (ctx_dv.comp_mask & MLX5DV_CONTEXT_MASK_OOO_RECV_WRS) {
28302979
qp = mlx5dv_create_qp(ctx->context, &attr_ex, &attr_dv);

0 commit comments

Comments
 (0)