Skip to content

Commit 16ecbfe

Browse files
committed
Perftest: correct rdma_cm header output and enforce --ib-dev
When using --rdma_cm, perftest printed the user-requested device, GID index, and local GID rather than what rdma_cm actually resolved. Additionally, --ib-dev was silently ignored since rdma_cm relies on kernel IP routing to pick the device. - Bind rdma_cm to a source IP from the --ib-dev device so route resolution goes through the correct interface - After connection, update user_param with the actual device, port, and GID index from the resolved cm_id Signed-off-by: Shmuel Shaul <sshaul@nvidia.com>
1 parent 4ff43ea commit 16ecbfe

2 files changed

Lines changed: 179 additions & 1 deletion

File tree

src/perftest_communication.c

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3097,6 +3097,100 @@ int rdma_cm_client_connection(struct pingpong_context *ctx,
30973097
return error_handler(error_message);
30983098
}
30993099

3100+
/******************************************************************************
3101+
* Convert a sockaddr (IPv4 or IPv6) to a 16-byte GID suitable for
3102+
* comparison against the device's GID table. Returns 0 on success.
3103+
******************************************************************************/
3104+
static int sockaddr_to_gid(const struct sockaddr *addr, union ibv_gid *gid)
3105+
{
3106+
memset(gid, 0, sizeof(*gid));
3107+
3108+
if (addr->sa_family == AF_INET) {
3109+
const struct sockaddr_in *s4 = (const struct sockaddr_in *)addr;
3110+
gid->raw[10] = 0xff;
3111+
gid->raw[11] = 0xff;
3112+
memcpy(&gid->raw[12], &s4->sin_addr, 4);
3113+
return 0;
3114+
}
3115+
3116+
if (addr->sa_family == AF_INET6) {
3117+
const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *)addr;
3118+
memcpy(gid->raw, &s6->sin6_addr, 16);
3119+
return 0;
3120+
}
3121+
3122+
return -1;
3123+
}
3124+
3125+
/******************************************************************************
3126+
* Scan the GID table on the given device/port and return the index whose
3127+
* entry matches 'target'. Returns the index (>= 0) or -1 if not found.
3128+
******************************************************************************/
3129+
static int find_gid_index(struct ibv_context *context, uint8_t port,
3130+
const union ibv_gid *target)
3131+
{
3132+
struct ibv_port_attr port_attr;
3133+
union ibv_gid entry;
3134+
int i;
3135+
3136+
if (ibv_query_port(context, port, &port_attr))
3137+
return -1;
3138+
3139+
for (i = 0; i < port_attr.gid_tbl_len; i++) {
3140+
if (ibv_query_gid(context, port, i, &entry))
3141+
continue;
3142+
if (!memcmp(entry.raw, target->raw, sizeof(entry.raw)))
3143+
return i;
3144+
}
3145+
3146+
return -1;
3147+
}
3148+
3149+
/******************************************************************************
3150+
* After rdma_cm connection is established, the actual device, port, and GID
3151+
* may differ from what the user requested via --ib-dev / -x. Refresh
3152+
* user_param so that subsequent header prints reflect reality.
3153+
******************************************************************************/
3154+
static void update_rdma_cm_params(struct pingpong_context *ctx,
3155+
struct perftest_parameters *user_param,
3156+
struct perftest_comm *comm)
3157+
{
3158+
struct rdma_cm_id *cm_id;
3159+
struct sockaddr *src_addr;
3160+
union ibv_gid src_gid;
3161+
int idx;
3162+
3163+
cm_id = ctx->cma_master.nodes[0].cma_id;
3164+
if (!cm_id || !cm_id->verbs)
3165+
return;
3166+
3167+
free(user_param->ib_devname);
3168+
user_param->ib_devname = strdup(ibv_get_device_name(cm_id->verbs->device));
3169+
3170+
/* Similarly, the physical port may differ from what the user assumed. */
3171+
user_param->ib_port = cm_id->port_num;
3172+
3173+
/* Find the GID index that matches the source address rdma_cm actually
3174+
* used: convert the resolved local sockaddr to a GID, then look it up
3175+
* in the device's GID table. */
3176+
src_addr = rdma_get_local_addr(cm_id);
3177+
if (!src_addr)
3178+
return;
3179+
3180+
if (sockaddr_to_gid(src_addr, &src_gid))
3181+
return;
3182+
3183+
idx = find_gid_index(ctx->context, user_param->ib_port, &src_gid);
3184+
if (idx >= 0) {
3185+
user_param->gid_index = idx;
3186+
user_param->use_gid_user = 1;
3187+
/* comm->rdma_params is a separate copy used by
3188+
* ctx_print_pingpong_data() — keep it in sync. */
3189+
if (comm && comm->rdma_params)
3190+
comm->rdma_params->gid_index = idx;
3191+
}
3192+
}
3193+
31003194
/******************************************************************************
31013195
*
31023196
******************************************************************************/
@@ -3138,7 +3232,6 @@ int create_rdma_cm_connection(struct pingpong_context *ctx,
31383232

31393233
if (rc) {
31403234
error_message = "Failed to create RDMA CM connection.";
3141-
free(hints.ai_src_addr);
31423235
goto destroy_rdma_id;
31433236
}
31443237

@@ -3151,6 +3244,8 @@ int create_rdma_cm_connection(struct pingpong_context *ctx,
31513244

31523245
free(hints.ai_src_addr);
31533246

3247+
update_rdma_cm_params(ctx, user_param, comm);
3248+
31543249
return rc;
31553250

31563251

src/perftest_resources.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6803,6 +6803,65 @@ int run_iter_fs(struct pingpong_context *ctx, struct perftest_parameters *user_p
68036803
}
68046804

68056805

6806+
/******************************************************************************
6807+
*
6808+
******************************************************************************/
6809+
static int gid_is_v4mapped(const union ibv_gid *gid)
6810+
{
6811+
return (gid->raw[10] == 0xff && gid->raw[11] == 0xff &&
6812+
!gid->raw[0] && !gid->raw[1] && !gid->raw[2] &&
6813+
!gid->raw[3] && !gid->raw[4] && !gid->raw[5] &&
6814+
!gid->raw[6] && !gid->raw[7] && !gid->raw[8] &&
6815+
!gid->raw[9]);
6816+
}
6817+
6818+
/******************************************************************************
6819+
*
6820+
******************************************************************************/
6821+
static int gid_to_sockaddr(const union ibv_gid *gid, int ai_family,
6822+
struct sockaddr **addr, socklen_t *len)
6823+
{
6824+
if (ai_family == AF_INET && gid_is_v4mapped(gid)) {
6825+
struct sockaddr_in *s4;
6826+
6827+
/* Skip 0.0.0.0 */
6828+
if (!gid->raw[12] && !gid->raw[13] &&
6829+
!gid->raw[14] && !gid->raw[15])
6830+
return -1;
6831+
6832+
s4 = (struct sockaddr_in *)calloc(1, sizeof(*s4));
6833+
s4->sin_family = AF_INET;
6834+
memcpy(&s4->sin_addr, &gid->raw[12], 4);
6835+
*addr = (struct sockaddr *)s4;
6836+
*len = sizeof(*s4);
6837+
return 0;
6838+
}
6839+
6840+
if (ai_family == AF_INET6 && !gid_is_v4mapped(gid)) {
6841+
struct sockaddr_in6 *s6;
6842+
int j, all_zero = 1;
6843+
6844+
for (j = 0; j < 16; j++) {
6845+
if (gid->raw[j]) { all_zero = 0; break; }
6846+
}
6847+
if (all_zero)
6848+
return -1;
6849+
6850+
/* Skip link-local (fe80::/10) — not routable across subnets */
6851+
if (gid->raw[0] == 0xfe && (gid->raw[1] & 0xc0) == 0x80)
6852+
return -1;
6853+
6854+
s6 = (struct sockaddr_in6 *)calloc(1, sizeof(*s6));
6855+
s6->sin6_family = AF_INET6;
6856+
memcpy(&s6->sin6_addr, gid->raw, 16);
6857+
*addr = (struct sockaddr *)s6;
6858+
*len = sizeof(*s6);
6859+
return 0;
6860+
}
6861+
6862+
return -1;
6863+
}
6864+
68066865
/******************************************************************************
68076866
*
68086867
******************************************************************************/
@@ -6881,6 +6940,30 @@ int rdma_cm_allocate_nodes(struct pingpong_context *ctx,
68816940
hints->ai_src_addr = (struct sockaddr *)(source_addr);
68826941
hints->ai_src_len = sizeof(*source_addr);
68836942
}
6943+
} else if (user_param->ib_devname) {
6944+
/* No --bind_source_ip, but --ib-dev was specified.
6945+
* rdma_cm ignores --ib-dev when resolving routes, so find an IP
6946+
* on that device and pass it as the source address to bind the interface. */
6947+
struct ibv_port_attr port_attr;
6948+
union ibv_gid gid;
6949+
6950+
if (!ibv_query_port(ctx->context, user_param->ib_port,
6951+
&port_attr)) {
6952+
int idx;
6953+
6954+
for (idx = 0; idx < port_attr.gid_tbl_len; idx++) {
6955+
if (ibv_query_gid(ctx->context,
6956+
user_param->ib_port,
6957+
idx, &gid))
6958+
continue;
6959+
6960+
if (!gid_to_sockaddr(&gid,
6961+
user_param->ai_family,
6962+
&hints->ai_src_addr,
6963+
&hints->ai_src_len))
6964+
break;
6965+
}
6966+
}
68846967
}
68856968

68866969
return rc;

0 commit comments

Comments
 (0)