1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 */ 4 5 #include <rdma/rdma_cma.h> 6 #include <infiniband/verbs.h> 7 #include <infiniband/mlx5dv.h> 8 9 #include "spdk/stdinc.h" 10 #include "spdk/queue.h" 11 #include "spdk/log.h" 12 #include "spdk/likely.h" 13 #include "spdk/util.h" 14 #include "spdk_internal/mlx5.h" 15 #include "spdk_internal/rdma_utils.h" 16 #include "mlx5_ifc.h" 17 #include "mlx5_priv.h" 18 19 /* Plaintext key sizes */ 20 /* 64b keytag */ 21 #define SPDK_MLX5_AES_XTS_KEYTAG_SIZE 8 22 /* key1_128b + key2_128b */ 23 #define SPDK_MLX5_AES_XTS_128_DEK_BYTES 32 24 /* key1_256b + key2_256b */ 25 #define SPDK_MLX5_AES_XTS_256_DEK_BYTES 64 26 /* key1_128b + key2_128b + 64b_keytag */ 27 #define SPDK_MLX5_AES_XTS_128_DEK_BYTES_WITH_KEYTAG (SPDK_MLX5_AES_XTS_128_DEK_BYTES + SPDK_MLX5_AES_XTS_KEYTAG_SIZE) 28 /* key1_256b + key2_256b + 64b_keytag */ 29 #define SPDK_MLX5_AES_XTS_256_DEK_BYTES_WITH_KEYTAG (SPDK_MLX5_AES_XTS_256_DEK_BYTES + SPDK_MLX5_AES_XTS_KEYTAG_SIZE) 30 31 struct mlx5_crypto_dek_init_attr { 32 char *dek; 33 uint64_t opaque; 34 uint32_t key_size_bytes; 35 uint8_t key_size; /* driver representation of \b key_size_bytes */ 36 uint8_t keytag; 37 }; 38 39 struct mlx5_crypto_dek_query_attr { 40 /* state either MLX5_ENCRYPTION_KEY_OBJ_STATE_READY or MLX5_ENCRYPTION_KEY_OBJ_STATE_ERROR */ 41 uint8_t state; 42 uint64_t opaque; 43 }; 44 45 struct mlx5_crypto_dek { 46 struct mlx5dv_devx_obj *devx_obj; 47 struct ibv_pd *pd; 48 struct ibv_context *context; 49 /* Cached dek_obj_id */ 50 uint32_t dek_obj_id; 51 enum spdk_mlx5_crypto_key_tweak_mode tweak_mode; 52 }; 53 54 struct spdk_mlx5_crypto_keytag { 55 struct mlx5_crypto_dek *deks; 56 uint32_t deks_num; 57 bool has_keytag; 58 char keytag[8]; 59 }; 60 61 static char **g_allowed_devices; 62 static size_t g_allowed_devices_count; 63 64 static void 65 mlx5_crypto_devs_free(void) 66 { 67 size_t i; 68 69 if (!g_allowed_devices) { 70 return; 71 } 72 73 for (i = 0; i < g_allowed_devices_count; i++) { 74 free(g_allowed_devices[i]); 75 } 76 free(g_allowed_devices); 77 g_allowed_devices = NULL; 78 g_allowed_devices_count = 0; 79 } 80 81 static bool 82 mlx5_crypto_dev_allowed(const char *dev) 83 { 84 size_t i; 85 86 if (!g_allowed_devices || !g_allowed_devices_count) { 87 return true; 88 } 89 90 for (i = 0; i < g_allowed_devices_count; i++) { 91 if (strcmp(g_allowed_devices[i], dev) == 0) { 92 return true; 93 } 94 } 95 96 return false; 97 } 98 99 int 100 spdk_mlx5_crypto_devs_allow(const char *const dev_names[], size_t devs_count) 101 { 102 size_t i; 103 104 mlx5_crypto_devs_free(); 105 106 if (!dev_names || !devs_count) { 107 return 0; 108 } 109 110 g_allowed_devices = calloc(devs_count, sizeof(char *)); 111 if (!g_allowed_devices) { 112 return -ENOMEM; 113 } 114 for (i = 0; i < devs_count; i++) { 115 g_allowed_devices[i] = strndup(dev_names[i], SPDK_MLX5_DEV_MAX_NAME_LEN); 116 if (!g_allowed_devices[i]) { 117 mlx5_crypto_devs_free(); 118 return -ENOMEM; 119 } 120 g_allowed_devices_count++; 121 } 122 123 return 0; 124 } 125 126 struct ibv_context ** 127 spdk_mlx5_crypto_devs_get(int *dev_num) 128 { 129 struct ibv_context **rdma_devs, **rdma_devs_out = NULL, *dev; 130 struct ibv_device_attr dev_attr; 131 struct ibv_port_attr port_attr; 132 struct spdk_mlx5_device_caps dev_caps; 133 uint8_t in[DEVX_ST_SZ_BYTES(query_nic_vport_context_in)]; 134 uint8_t out[DEVX_ST_SZ_BYTES(query_nic_vport_context_out)]; 135 uint8_t devx_v; 136 int num_rdma_devs = 0, i, rc; 137 int num_crypto_devs = 0; 138 139 /* query all devices, save mlx5 with crypto support */ 140 rdma_devs = rdma_get_devices(&num_rdma_devs); 141 if (!rdma_devs || !num_rdma_devs) { 142 *dev_num = 0; 143 return NULL; 144 } 145 146 rdma_devs_out = calloc(num_rdma_devs + 1, sizeof(*rdma_devs_out)); 147 if (!rdma_devs_out) { 148 SPDK_ERRLOG("Memory allocation failed\n"); 149 return NULL; 150 } 151 152 for (i = 0; i < num_rdma_devs; i++) { 153 dev = rdma_devs[i]; 154 rc = ibv_query_device(dev, &dev_attr); 155 if (rc) { 156 SPDK_ERRLOG("Failed to query dev %s, skipping\n", dev->device->name); 157 continue; 158 } 159 if (dev_attr.vendor_id != SPDK_MLX5_VENDOR_ID_MELLANOX) { 160 SPDK_DEBUGLOG(mlx5, "dev %s is not Mellanox device, skipping\n", dev->device->name); 161 continue; 162 } 163 164 if (!mlx5_crypto_dev_allowed(dev->device->name)) { 165 continue; 166 } 167 168 rc = ibv_query_port(dev, 1, &port_attr); 169 if (rc) { 170 SPDK_ERRLOG("Failed to query port attributes for device %s, rc %d\n", dev->device->name, rc); 171 continue; 172 } 173 174 if (port_attr.link_layer == IBV_LINK_LAYER_ETHERNET) { 175 /* Port may be ethernet but roce is still disabled */ 176 memset(in, 0, sizeof(in)); 177 memset(out, 0, sizeof(out)); 178 DEVX_SET(query_nic_vport_context_in, in, opcode, MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); 179 rc = mlx5dv_devx_general_cmd(dev, in, sizeof(in), out, sizeof(out)); 180 if (rc) { 181 SPDK_ERRLOG("Failed to get VPORT context for device %s. Assuming ROCE is disabled\n", 182 dev->device->name); 183 continue; 184 } 185 186 devx_v = DEVX_GET(query_nic_vport_context_out, out, nic_vport_context.roce_en); 187 if (!devx_v) { 188 SPDK_ERRLOG("Device %s, RoCE disabled\n", dev->device->name); 189 continue; 190 } 191 } 192 193 memset(&dev_caps, 0, sizeof(dev_caps)); 194 rc = spdk_mlx5_device_query_caps(dev, &dev_caps); 195 if (rc) { 196 SPDK_ERRLOG("Failed to query mlx5 dev %s, skipping\n", dev->device->name); 197 continue; 198 } 199 if (!dev_caps.crypto_supported) { 200 SPDK_WARNLOG("dev %s crypto engine doesn't support crypto\n", dev->device->name); 201 continue; 202 } 203 if (!(dev_caps.crypto.single_block_le_tweak || dev_caps.crypto.multi_block_le_tweak || 204 dev_caps.crypto.multi_block_be_tweak)) { 205 SPDK_WARNLOG("dev %s crypto engine doesn't support AES_XTS\n", dev->device->name); 206 continue; 207 } 208 if (dev_caps.crypto.wrapped_import_method_aes_xts) { 209 SPDK_WARNLOG("dev %s uses wrapped import method which is not supported by mlx5 lib\n", 210 dev->device->name); 211 continue; 212 } 213 214 rdma_devs_out[num_crypto_devs++] = dev; 215 } 216 217 if (!num_crypto_devs) { 218 SPDK_DEBUGLOG(mlx5, "Found no mlx5 crypto devices\n"); 219 goto err_out; 220 } 221 222 rdma_free_devices(rdma_devs); 223 *dev_num = num_crypto_devs; 224 225 return rdma_devs_out; 226 227 err_out: 228 free(rdma_devs_out); 229 rdma_free_devices(rdma_devs); 230 *dev_num = 0; 231 return NULL; 232 } 233 234 void 235 spdk_mlx5_crypto_devs_release(struct ibv_context **rdma_devs) 236 { 237 if (rdma_devs) { 238 free(rdma_devs); 239 } 240 } 241 242 int 243 spdk_mlx5_device_query_caps(struct ibv_context *context, struct spdk_mlx5_device_caps *caps) 244 { 245 uint16_t opmod = MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE | 246 HCA_CAP_OPMOD_GET_CUR; 247 uint32_t out[DEVX_ST_SZ_DW(query_hca_cap_out)] = {}; 248 uint32_t in[DEVX_ST_SZ_DW(query_hca_cap_in)] = {}; 249 int rc; 250 251 DEVX_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); 252 DEVX_SET(query_hca_cap_in, in, op_mod, opmod); 253 254 rc = mlx5dv_devx_general_cmd(context, in, sizeof(in), out, sizeof(out)); 255 if (rc) { 256 return rc; 257 } 258 259 caps->crc32c_supported = DEVX_GET(query_hca_cap_out, out, capability.cmd_hca_cap.sho) && 260 DEVX_GET(query_hca_cap_out, out, capability.cmd_hca_cap.sig_crc32c); 261 262 caps->crypto_supported = DEVX_GET(query_hca_cap_out, out, capability.cmd_hca_cap.crypto); 263 if (!caps->crypto_supported) { 264 return 0; 265 } 266 267 caps->crypto.single_block_le_tweak = DEVX_GET(query_hca_cap_out, 268 out, capability.cmd_hca_cap.aes_xts_single_block_le_tweak); 269 caps->crypto.multi_block_be_tweak = DEVX_GET(query_hca_cap_out, out, 270 capability.cmd_hca_cap.aes_xts_multi_block_be_tweak); 271 caps->crypto.multi_block_le_tweak = DEVX_GET(query_hca_cap_out, out, 272 capability.cmd_hca_cap.aes_xts_multi_block_le_tweak); 273 274 opmod = MLX5_SET_HCA_CAP_OP_MOD_CRYPTO | HCA_CAP_OPMOD_GET_CUR; 275 memset(&out, 0, sizeof(out)); 276 memset(&in, 0, sizeof(in)); 277 278 DEVX_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); 279 DEVX_SET(query_hca_cap_in, in, op_mod, opmod); 280 281 rc = mlx5dv_devx_general_cmd(context, in, sizeof(in), out, sizeof(out)); 282 if (rc) { 283 return rc; 284 } 285 286 caps->crypto.wrapped_crypto_operational = DEVX_GET(query_hca_cap_out, out, 287 capability.crypto_caps.wrapped_crypto_operational); 288 caps->crypto.wrapped_crypto_going_to_commissioning = DEVX_GET(query_hca_cap_out, out, 289 capability.crypto_caps .wrapped_crypto_going_to_commissioning); 290 caps->crypto.wrapped_import_method_aes_xts = (DEVX_GET(query_hca_cap_out, out, 291 capability.crypto_caps.wrapped_import_method) & 292 MLX5_CRYPTO_CAPS_WRAPPED_IMPORT_METHOD_AES) != 0; 293 294 return 0; 295 } 296 297 static void 298 mlx5_crypto_dek_deinit(struct mlx5_crypto_dek *dek) 299 { 300 int rc; 301 302 rc = mlx5dv_devx_obj_destroy(dek->devx_obj); 303 if (rc) { 304 SPDK_ERRLOG("Failed to destroy crypto obj:%p, rc %d\n", dek->devx_obj, rc); 305 } 306 } 307 308 void 309 spdk_mlx5_crypto_keytag_destroy(struct spdk_mlx5_crypto_keytag *keytag) 310 { 311 struct mlx5_crypto_dek *dek; 312 uint32_t i; 313 314 if (!keytag) { 315 return; 316 } 317 318 for (i = 0; i < keytag->deks_num; i++) { 319 dek = &keytag->deks[i]; 320 if (dek->devx_obj) { 321 mlx5_crypto_dek_deinit(dek); 322 } 323 if (dek->pd) { 324 spdk_rdma_utils_put_pd(dek->pd); 325 } 326 } 327 spdk_memset_s(keytag->keytag, sizeof(keytag->keytag), 0, sizeof(keytag->keytag)); 328 free(keytag->deks); 329 free(keytag); 330 } 331 332 static int 333 mlx5_crypto_dek_init(struct ibv_pd *pd, struct mlx5_crypto_dek_init_attr *attr, 334 struct mlx5_crypto_dek *dek) 335 { 336 uint32_t in[DEVX_ST_SZ_DW(create_encryption_key_obj_in)] = {}; 337 uint32_t out[DEVX_ST_SZ_DW(general_obj_out_cmd_hdr)] = {}; 338 uint8_t *dek_in; 339 uint32_t pdn; 340 int rc; 341 342 rc = mlx5_get_pd_id(pd, &pdn); 343 if (rc) { 344 return rc; 345 } 346 347 dek_in = DEVX_ADDR_OF(create_encryption_key_obj_in, in, hdr); 348 DEVX_SET(general_obj_in_cmd_hdr, dek_in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 349 DEVX_SET(general_obj_in_cmd_hdr, dek_in, obj_type, MLX5_OBJ_TYPE_DEK); 350 dek_in = DEVX_ADDR_OF(create_encryption_key_obj_in, in, key_obj); 351 DEVX_SET(encryption_key_obj, dek_in, key_size, attr->key_size); 352 DEVX_SET(encryption_key_obj, dek_in, has_keytag, attr->keytag); 353 DEVX_SET(encryption_key_obj, dek_in, key_purpose, MLX5_ENCRYPTION_KEY_OBJ_KEY_PURPOSE_AES_XTS); 354 DEVX_SET(encryption_key_obj, dek_in, pd, pdn); 355 memcpy(DEVX_ADDR_OF(encryption_key_obj, dek_in, opaque), &attr->opaque, sizeof(attr->opaque)); 356 memcpy(DEVX_ADDR_OF(encryption_key_obj, dek_in, key), attr->dek, attr->key_size_bytes); 357 358 dek->devx_obj = mlx5dv_devx_obj_create(pd->context, in, sizeof(in), out, sizeof(out)); 359 spdk_memset_s(DEVX_ADDR_OF(encryption_key_obj, dek_in, key), attr->key_size_bytes, 0, 360 attr->key_size_bytes); 361 if (!dek->devx_obj) { 362 return -errno; 363 } 364 dek->dek_obj_id = DEVX_GET(general_obj_out_cmd_hdr, out, obj_id); 365 366 return 0; 367 } 368 369 static int 370 mlx5_crypto_dek_query(struct mlx5_crypto_dek *dek, struct mlx5_crypto_dek_query_attr *attr) 371 { 372 uint32_t out[DEVX_ST_SZ_DW(query_encryption_key_obj_out)] = {}; 373 uint32_t in[DEVX_ST_SZ_DW(general_obj_in_cmd_hdr)] = {}; 374 uint8_t *dek_out; 375 int rc; 376 377 assert(attr); 378 DEVX_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_QUERY_GENERAL_OBJECT); 379 DEVX_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_OBJ_TYPE_DEK); 380 DEVX_SET(general_obj_in_cmd_hdr, in, obj_id, dek->dek_obj_id); 381 382 rc = mlx5dv_devx_obj_query(dek->devx_obj, in, sizeof(in), out, sizeof(out)); 383 if (rc) { 384 return rc; 385 } 386 387 dek_out = DEVX_ADDR_OF(query_encryption_key_obj_out, out, obj); 388 attr->state = DEVX_GET(encryption_key_obj, dek_out, state); 389 memcpy(&attr->opaque, DEVX_ADDR_OF(encryption_key_obj, dek_out, opaque), sizeof(attr->opaque)); 390 391 return 0; 392 } 393 394 int 395 spdk_mlx5_crypto_keytag_create(struct spdk_mlx5_crypto_dek_create_attr *attr, 396 struct spdk_mlx5_crypto_keytag **out) 397 { 398 struct mlx5_crypto_dek *dek; 399 struct spdk_mlx5_crypto_keytag *keytag; 400 struct ibv_context **devs; 401 struct ibv_pd *pd; 402 struct mlx5_crypto_dek_init_attr dek_attr = {}; 403 struct mlx5_crypto_dek_query_attr query_attr; 404 struct spdk_mlx5_device_caps dev_caps; 405 int num_devs = 0, i, rc; 406 407 dek_attr.dek = attr->dek; 408 dek_attr.key_size_bytes = attr->dek_len; 409 dek_attr.opaque = 0; 410 switch (dek_attr.key_size_bytes) { 411 case SPDK_MLX5_AES_XTS_128_DEK_BYTES_WITH_KEYTAG: 412 dek_attr.key_size = MLX5_ENCRYPTION_KEY_OBJ_KEY_SIZE_SIZE_128; 413 dek_attr.keytag = 1; 414 SPDK_DEBUGLOG(mlx5, "128b AES_XTS with keytag\n"); 415 break; 416 case SPDK_MLX5_AES_XTS_256_DEK_BYTES_WITH_KEYTAG: 417 dek_attr.key_size = MLX5_ENCRYPTION_KEY_OBJ_KEY_SIZE_SIZE_256; 418 dek_attr.keytag = 1; 419 SPDK_DEBUGLOG(mlx5, "256b AES_XTS with keytag\n"); 420 break; 421 case SPDK_MLX5_AES_XTS_128_DEK_BYTES: 422 dek_attr.key_size = MLX5_ENCRYPTION_KEY_OBJ_KEY_SIZE_SIZE_128; 423 dek_attr.keytag = 0; 424 SPDK_DEBUGLOG(mlx5, "128b AES_XTS\n"); 425 break; 426 case SPDK_MLX5_AES_XTS_256_DEK_BYTES: 427 dek_attr.key_size = MLX5_ENCRYPTION_KEY_OBJ_KEY_SIZE_SIZE_256; 428 dek_attr.keytag = 0; 429 SPDK_DEBUGLOG(mlx5, "256b AES_XTS\n"); 430 break; 431 default: 432 SPDK_ERRLOG("Invalid key length %zu. The following keys are supported:\n" 433 "128b key + key2, %u bytes;\n" 434 "256b key + key2, %u bytes\n" 435 "128b key + key2 + keytag, %u bytes\n" 436 "256b lye + key2 + keytag, %u bytes\n", 437 attr->dek_len, SPDK_MLX5_AES_XTS_128_DEK_BYTES, SPDK_MLX5_AES_XTS_256_DEK_BYTES, 438 SPDK_MLX5_AES_XTS_128_DEK_BYTES_WITH_KEYTAG, SPDK_MLX5_AES_XTS_256_DEK_BYTES_WITH_KEYTAG); 439 return -EINVAL; 440 } 441 442 devs = spdk_mlx5_crypto_devs_get(&num_devs); 443 if (!devs || !num_devs) { 444 SPDK_DEBUGLOG(mlx5, "No crypto devices found\n"); 445 return -ENOTSUP; 446 } 447 448 keytag = calloc(1, sizeof(*keytag)); 449 if (!keytag) { 450 SPDK_ERRLOG("Memory allocation failed\n"); 451 spdk_mlx5_crypto_devs_release(devs); 452 return -ENOMEM; 453 } 454 keytag->deks = calloc(num_devs, sizeof(struct mlx5_crypto_dek)); 455 if (!keytag->deks) { 456 SPDK_ERRLOG("Memory allocation failed\n"); 457 spdk_mlx5_crypto_devs_release(devs); 458 free(keytag); 459 return -ENOMEM; 460 } 461 462 for (i = 0; i < num_devs; i++) { 463 keytag->deks_num++; 464 dek = &keytag->deks[i]; 465 pd = spdk_rdma_utils_get_pd(devs[i]); 466 if (!pd) { 467 SPDK_ERRLOG("Failed to get PD on device %s\n", devs[i]->device->name); 468 rc = -EINVAL; 469 goto err_out; 470 } 471 472 memset(&dev_caps, 0, sizeof(dev_caps)); 473 rc = spdk_mlx5_device_query_caps(devs[i], &dev_caps); 474 if (rc) { 475 SPDK_ERRLOG("Failed to get device %s crypto caps\n", devs[i]->device->name); 476 goto err_out; 477 } 478 rc = mlx5_crypto_dek_init(pd, &dek_attr, dek); 479 if (rc) { 480 SPDK_ERRLOG("Failed to create DEK on dev %s, rc %d\n", pd->context->device->name, rc); 481 goto err_out; 482 } 483 memset(&query_attr, 0, sizeof(query_attr)); 484 rc = mlx5_crypto_dek_query(dek, &query_attr); 485 if (rc) { 486 SPDK_ERRLOG("Failed to query DEK on dev %s, rc %d\n", pd->context->device->name, rc); 487 goto err_out; 488 } 489 if (query_attr.opaque != 0 || query_attr.state != MLX5_ENCRYPTION_KEY_OBJ_STATE_READY) { 490 SPDK_ERRLOG("DEK on dev %s in bad state %d, oapque %"PRIu64"\n", pd->context->device->name, 491 query_attr.state, query_attr.opaque); 492 rc = -EINVAL; 493 goto err_out; 494 } 495 496 dek->pd = pd; 497 dek->context = devs[i]; 498 dek->tweak_mode = dev_caps.crypto.multi_block_be_tweak ? 499 SPDK_MLX5_CRYPTO_KEY_TWEAK_MODE_SIMPLE_LBA_BE : SPDK_MLX5_CRYPTO_KEY_TWEAK_MODE_SIMPLE_LBA_LE; 500 } 501 502 if (dek_attr.keytag) { 503 /* Save keytag, it will be used to configure crypto MKEY */ 504 keytag->has_keytag = true; 505 memcpy(keytag->keytag, attr->dek + attr->dek_len - SPDK_MLX5_AES_XTS_KEYTAG_SIZE, 506 SPDK_MLX5_AES_XTS_KEYTAG_SIZE); 507 } 508 509 spdk_mlx5_crypto_devs_release(devs); 510 *out = keytag; 511 512 return 0; 513 514 err_out: 515 spdk_mlx5_crypto_keytag_destroy(keytag); 516 spdk_mlx5_crypto_devs_release(devs); 517 518 return rc; 519 } 520 521 static inline struct mlx5_crypto_dek * 522 mlx5_crypto_get_dek_by_pd(struct spdk_mlx5_crypto_keytag *keytag, struct ibv_pd *pd) 523 { 524 struct mlx5_crypto_dek *dek; 525 uint32_t i; 526 527 for (i = 0; i < keytag->deks_num; i++) { 528 dek = &keytag->deks[i]; 529 if (dek->pd == pd) { 530 return dek; 531 } 532 } 533 534 return NULL; 535 } 536 537 int 538 spdk_mlx5_crypto_get_dek_data(struct spdk_mlx5_crypto_keytag *keytag, struct ibv_pd *pd, 539 struct spdk_mlx5_crypto_dek_data *data) 540 { 541 struct mlx5_crypto_dek *dek; 542 543 dek = mlx5_crypto_get_dek_by_pd(keytag, pd); 544 if (spdk_unlikely(!dek)) { 545 SPDK_ERRLOG("No DEK for pd %p (dev %s)\n", pd, pd->context->device->name); 546 return -EINVAL; 547 } 548 data->dek_obj_id = dek->dek_obj_id; 549 data->tweak_mode = dek->tweak_mode; 550 551 return 0; 552 } 553 554 SPDK_LOG_REGISTER_COMPONENT(mlx5) 555