diff options
author | Hans Wippel <hwippel@linux.ibm.com> | 2018-06-28 13:05:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-06-30 07:42:25 -0400 |
commit | c758dfddc1b5b1c9b8c64e5e4bb9bf24b74f4a59 (patch) | |
tree | cb5f055473e2882c0b87b7052394cd1960cb8a3d /net/smc | |
parent | 1619f770589a183af56f248de261534b255122de (diff) |
net/smc: add SMC-D support in CLC messages
There are two types of SMC: SMC-R and SMC-D. These types are signaled
within the CLC messages during the CLC handshake. This patch adds
support for and checks of the SMC type.
Also, SMC-R and SMC-D need to exchange different information during the
CLC handshake. So, this patch extends the current message formats to
support the SMC-D header fields. The Proposal message can contain both
SMC-R and SMC-D information. The Accept and Confirm messages contain
either SMC-R or SMC-D information.
Signed-off-by: Hans Wippel <hwippel@linux.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Suggested-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/smc')
-rw-r--r-- | net/smc/af_smc.c | 9 | ||||
-rw-r--r-- | net/smc/smc_clc.c | 193 | ||||
-rw-r--r-- | net/smc/smc_clc.h | 81 |
3 files changed, 205 insertions, 78 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 8ce48799cf68..20afa94be8bb 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c | |||
@@ -451,14 +451,14 @@ static int smc_check_rdma(struct smc_sock *smc, struct smc_ib_device **ibdev, | |||
451 | } | 451 | } |
452 | 452 | ||
453 | /* CLC handshake during connect */ | 453 | /* CLC handshake during connect */ |
454 | static int smc_connect_clc(struct smc_sock *smc, | 454 | static int smc_connect_clc(struct smc_sock *smc, int smc_type, |
455 | struct smc_clc_msg_accept_confirm *aclc, | 455 | struct smc_clc_msg_accept_confirm *aclc, |
456 | struct smc_ib_device *ibdev, u8 ibport) | 456 | struct smc_ib_device *ibdev, u8 ibport) |
457 | { | 457 | { |
458 | int rc = 0; | 458 | int rc = 0; |
459 | 459 | ||
460 | /* do inband token exchange */ | 460 | /* do inband token exchange */ |
461 | rc = smc_clc_send_proposal(smc, ibdev, ibport); | 461 | rc = smc_clc_send_proposal(smc, smc_type, ibdev, ibport, NULL); |
462 | if (rc) | 462 | if (rc) |
463 | return rc; | 463 | return rc; |
464 | /* receive SMC Accept CLC message */ | 464 | /* receive SMC Accept CLC message */ |
@@ -564,7 +564,7 @@ static int __smc_connect(struct smc_sock *smc) | |||
564 | return smc_connect_decline_fallback(smc, SMC_CLC_DECL_CNFERR); | 564 | return smc_connect_decline_fallback(smc, SMC_CLC_DECL_CNFERR); |
565 | 565 | ||
566 | /* perform CLC handshake */ | 566 | /* perform CLC handshake */ |
567 | rc = smc_connect_clc(smc, &aclc, ibdev, ibport); | 567 | rc = smc_connect_clc(smc, SMC_TYPE_R, &aclc, ibdev, ibport); |
568 | if (rc) | 568 | if (rc) |
569 | return smc_connect_decline_fallback(smc, rc); | 569 | return smc_connect_decline_fallback(smc, rc); |
570 | 570 | ||
@@ -1008,7 +1008,8 @@ static void smc_listen_work(struct work_struct *work) | |||
1008 | smc_tx_init(new_smc); | 1008 | smc_tx_init(new_smc); |
1009 | 1009 | ||
1010 | /* check if RDMA is available */ | 1010 | /* check if RDMA is available */ |
1011 | if (smc_check_rdma(new_smc, &ibdev, &ibport) || | 1011 | if ((pclc->hdr.path != SMC_TYPE_R && pclc->hdr.path != SMC_TYPE_B) || |
1012 | smc_check_rdma(new_smc, &ibdev, &ibport) || | ||
1012 | smc_listen_rdma_check(new_smc, pclc) || | 1013 | smc_listen_rdma_check(new_smc, pclc) || |
1013 | smc_listen_rdma_init(new_smc, pclc, ibdev, ibport, | 1014 | smc_listen_rdma_init(new_smc, pclc, ibdev, ibport, |
1014 | &local_contact) || | 1015 | &local_contact) || |
diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c index 717449b1da0b..038d70ef7892 100644 --- a/net/smc/smc_clc.c +++ b/net/smc/smc_clc.c | |||
@@ -23,9 +23,15 @@ | |||
23 | #include "smc_core.h" | 23 | #include "smc_core.h" |
24 | #include "smc_clc.h" | 24 | #include "smc_clc.h" |
25 | #include "smc_ib.h" | 25 | #include "smc_ib.h" |
26 | #include "smc_ism.h" | ||
27 | |||
28 | #define SMCR_CLC_ACCEPT_CONFIRM_LEN 68 | ||
29 | #define SMCD_CLC_ACCEPT_CONFIRM_LEN 48 | ||
26 | 30 | ||
27 | /* eye catcher "SMCR" EBCDIC for CLC messages */ | 31 | /* eye catcher "SMCR" EBCDIC for CLC messages */ |
28 | static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'}; | 32 | static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'}; |
33 | /* eye catcher "SMCD" EBCDIC for CLC messages */ | ||
34 | static const char SMCD_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xc4'}; | ||
29 | 35 | ||
30 | /* check if received message has a correct header length and contains valid | 36 | /* check if received message has a correct header length and contains valid |
31 | * heading and trailing eyecatchers | 37 | * heading and trailing eyecatchers |
@@ -38,10 +44,14 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm) | |||
38 | struct smc_clc_msg_decline *dclc; | 44 | struct smc_clc_msg_decline *dclc; |
39 | struct smc_clc_msg_trail *trl; | 45 | struct smc_clc_msg_trail *trl; |
40 | 46 | ||
41 | if (memcmp(clcm->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER))) | 47 | if (memcmp(clcm->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) && |
48 | memcmp(clcm->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER))) | ||
42 | return false; | 49 | return false; |
43 | switch (clcm->type) { | 50 | switch (clcm->type) { |
44 | case SMC_CLC_PROPOSAL: | 51 | case SMC_CLC_PROPOSAL: |
52 | if (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D && | ||
53 | clcm->path != SMC_TYPE_B) | ||
54 | return false; | ||
45 | pclc = (struct smc_clc_msg_proposal *)clcm; | 55 | pclc = (struct smc_clc_msg_proposal *)clcm; |
46 | pclc_prfx = smc_clc_proposal_get_prefix(pclc); | 56 | pclc_prfx = smc_clc_proposal_get_prefix(pclc); |
47 | if (ntohs(pclc->hdr.length) != | 57 | if (ntohs(pclc->hdr.length) != |
@@ -56,10 +66,16 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm) | |||
56 | break; | 66 | break; |
57 | case SMC_CLC_ACCEPT: | 67 | case SMC_CLC_ACCEPT: |
58 | case SMC_CLC_CONFIRM: | 68 | case SMC_CLC_CONFIRM: |
69 | if (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D) | ||
70 | return false; | ||
59 | clc = (struct smc_clc_msg_accept_confirm *)clcm; | 71 | clc = (struct smc_clc_msg_accept_confirm *)clcm; |
60 | if (ntohs(clc->hdr.length) != sizeof(*clc)) | 72 | if ((clcm->path == SMC_TYPE_R && |
73 | ntohs(clc->hdr.length) != SMCR_CLC_ACCEPT_CONFIRM_LEN) || | ||
74 | (clcm->path == SMC_TYPE_D && | ||
75 | ntohs(clc->hdr.length) != SMCD_CLC_ACCEPT_CONFIRM_LEN)) | ||
61 | return false; | 76 | return false; |
62 | trl = &clc->trl; | 77 | trl = (struct smc_clc_msg_trail *) |
78 | ((u8 *)clc + ntohs(clc->hdr.length) - sizeof(*trl)); | ||
63 | break; | 79 | break; |
64 | case SMC_CLC_DECLINE: | 80 | case SMC_CLC_DECLINE: |
65 | dclc = (struct smc_clc_msg_decline *)clcm; | 81 | dclc = (struct smc_clc_msg_decline *)clcm; |
@@ -70,7 +86,8 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm) | |||
70 | default: | 86 | default: |
71 | return false; | 87 | return false; |
72 | } | 88 | } |
73 | if (memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER))) | 89 | if (memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) && |
90 | memcmp(trl->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER))) | ||
74 | return false; | 91 | return false; |
75 | return true; | 92 | return true; |
76 | } | 93 | } |
@@ -295,6 +312,9 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, | |||
295 | datlen = ntohs(clcm->length); | 312 | datlen = ntohs(clcm->length); |
296 | if ((len < sizeof(struct smc_clc_msg_hdr)) || | 313 | if ((len < sizeof(struct smc_clc_msg_hdr)) || |
297 | (datlen > buflen) || | 314 | (datlen > buflen) || |
315 | (clcm->version != SMC_CLC_V1) || | ||
316 | (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D && | ||
317 | clcm->path != SMC_TYPE_B) || | ||
298 | ((clcm->type != SMC_CLC_DECLINE) && | 318 | ((clcm->type != SMC_CLC_DECLINE) && |
299 | (clcm->type != expected_type))) { | 319 | (clcm->type != expected_type))) { |
300 | smc->sk.sk_err = EPROTO; | 320 | smc->sk.sk_err = EPROTO; |
@@ -356,17 +376,18 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info) | |||
356 | } | 376 | } |
357 | 377 | ||
358 | /* send CLC PROPOSAL message across internal TCP socket */ | 378 | /* send CLC PROPOSAL message across internal TCP socket */ |
359 | int smc_clc_send_proposal(struct smc_sock *smc, | 379 | int smc_clc_send_proposal(struct smc_sock *smc, int smc_type, |
360 | struct smc_ib_device *smcibdev, | 380 | struct smc_ib_device *ibdev, u8 ibport, |
361 | u8 ibport) | 381 | struct smcd_dev *ismdev) |
362 | { | 382 | { |
363 | struct smc_clc_ipv6_prefix ipv6_prfx[SMC_CLC_MAX_V6_PREFIX]; | 383 | struct smc_clc_ipv6_prefix ipv6_prfx[SMC_CLC_MAX_V6_PREFIX]; |
364 | struct smc_clc_msg_proposal_prefix pclc_prfx; | 384 | struct smc_clc_msg_proposal_prefix pclc_prfx; |
385 | struct smc_clc_msg_smcd pclc_smcd; | ||
365 | struct smc_clc_msg_proposal pclc; | 386 | struct smc_clc_msg_proposal pclc; |
366 | struct smc_clc_msg_trail trl; | 387 | struct smc_clc_msg_trail trl; |
367 | int len, i, plen, rc; | 388 | int len, i, plen, rc; |
368 | int reason_code = 0; | 389 | int reason_code = 0; |
369 | struct kvec vec[4]; | 390 | struct kvec vec[5]; |
370 | struct msghdr msg; | 391 | struct msghdr msg; |
371 | 392 | ||
372 | /* retrieve ip prefixes for CLC proposal msg */ | 393 | /* retrieve ip prefixes for CLC proposal msg */ |
@@ -381,18 +402,34 @@ int smc_clc_send_proposal(struct smc_sock *smc, | |||
381 | memset(&pclc, 0, sizeof(pclc)); | 402 | memset(&pclc, 0, sizeof(pclc)); |
382 | memcpy(pclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); | 403 | memcpy(pclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); |
383 | pclc.hdr.type = SMC_CLC_PROPOSAL; | 404 | pclc.hdr.type = SMC_CLC_PROPOSAL; |
384 | pclc.hdr.length = htons(plen); | ||
385 | pclc.hdr.version = SMC_CLC_V1; /* SMC version */ | 405 | pclc.hdr.version = SMC_CLC_V1; /* SMC version */ |
386 | memcpy(pclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid)); | 406 | pclc.hdr.path = smc_type; |
387 | memcpy(&pclc.lcl.gid, &smcibdev->gid[ibport - 1], SMC_GID_SIZE); | 407 | if (smc_type == SMC_TYPE_R || smc_type == SMC_TYPE_B) { |
388 | memcpy(&pclc.lcl.mac, &smcibdev->mac[ibport - 1], ETH_ALEN); | 408 | /* add SMC-R specifics */ |
389 | pclc.iparea_offset = htons(0); | 409 | memcpy(pclc.lcl.id_for_peer, local_systemid, |
410 | sizeof(local_systemid)); | ||
411 | memcpy(&pclc.lcl.gid, &ibdev->gid[ibport - 1], SMC_GID_SIZE); | ||
412 | memcpy(&pclc.lcl.mac, &ibdev->mac[ibport - 1], ETH_ALEN); | ||
413 | pclc.iparea_offset = htons(0); | ||
414 | } | ||
415 | if (smc_type == SMC_TYPE_D || smc_type == SMC_TYPE_B) { | ||
416 | /* add SMC-D specifics */ | ||
417 | memset(&pclc_smcd, 0, sizeof(pclc_smcd)); | ||
418 | plen += sizeof(pclc_smcd); | ||
419 | pclc.iparea_offset = htons(SMC_CLC_PROPOSAL_MAX_OFFSET); | ||
420 | pclc_smcd.gid = ismdev->local_gid; | ||
421 | } | ||
422 | pclc.hdr.length = htons(plen); | ||
390 | 423 | ||
391 | memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); | 424 | memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); |
392 | memset(&msg, 0, sizeof(msg)); | 425 | memset(&msg, 0, sizeof(msg)); |
393 | i = 0; | 426 | i = 0; |
394 | vec[i].iov_base = &pclc; | 427 | vec[i].iov_base = &pclc; |
395 | vec[i++].iov_len = sizeof(pclc); | 428 | vec[i++].iov_len = sizeof(pclc); |
429 | if (smc_type == SMC_TYPE_D || smc_type == SMC_TYPE_B) { | ||
430 | vec[i].iov_base = &pclc_smcd; | ||
431 | vec[i++].iov_len = sizeof(pclc_smcd); | ||
432 | } | ||
396 | vec[i].iov_base = &pclc_prfx; | 433 | vec[i].iov_base = &pclc_prfx; |
397 | vec[i++].iov_len = sizeof(pclc_prfx); | 434 | vec[i++].iov_len = sizeof(pclc_prfx); |
398 | if (pclc_prfx.ipv6_prefixes_cnt > 0) { | 435 | if (pclc_prfx.ipv6_prefixes_cnt > 0) { |
@@ -428,35 +465,56 @@ int smc_clc_send_confirm(struct smc_sock *smc) | |||
428 | struct kvec vec; | 465 | struct kvec vec; |
429 | int len; | 466 | int len; |
430 | 467 | ||
431 | link = &conn->lgr->lnk[SMC_SINGLE_LINK]; | ||
432 | /* send SMC Confirm CLC msg */ | 468 | /* send SMC Confirm CLC msg */ |
433 | memset(&cclc, 0, sizeof(cclc)); | 469 | memset(&cclc, 0, sizeof(cclc)); |
434 | memcpy(cclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); | ||
435 | cclc.hdr.type = SMC_CLC_CONFIRM; | 470 | cclc.hdr.type = SMC_CLC_CONFIRM; |
436 | cclc.hdr.length = htons(sizeof(cclc)); | ||
437 | cclc.hdr.version = SMC_CLC_V1; /* SMC version */ | 471 | cclc.hdr.version = SMC_CLC_V1; /* SMC version */ |
438 | memcpy(cclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid)); | 472 | if (smc->conn.lgr->is_smcd) { |
439 | memcpy(&cclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1], | 473 | /* SMC-D specific settings */ |
440 | SMC_GID_SIZE); | 474 | memcpy(cclc.hdr.eyecatcher, SMCD_EYECATCHER, |
441 | memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1], ETH_ALEN); | 475 | sizeof(SMCD_EYECATCHER)); |
442 | hton24(cclc.qpn, link->roce_qp->qp_num); | 476 | cclc.hdr.path = SMC_TYPE_D; |
443 | cclc.rmb_rkey = | 477 | cclc.hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN); |
444 | htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey); | 478 | cclc.gid = conn->lgr->smcd->local_gid; |
445 | cclc.rmbe_idx = 1; /* for now: 1 RMB = 1 RMBE */ | 479 | cclc.token = conn->rmb_desc->token; |
446 | cclc.rmbe_alert_token = htonl(conn->alert_token_local); | 480 | cclc.dmbe_size = conn->rmbe_size_short; |
447 | cclc.qp_mtu = min(link->path_mtu, link->peer_mtu); | 481 | cclc.dmbe_idx = 0; |
448 | cclc.rmbe_size = conn->rmbe_size_short; | 482 | memcpy(&cclc.linkid, conn->lgr->id, SMC_LGR_ID_SIZE); |
449 | cclc.rmb_dma_addr = cpu_to_be64( | 483 | memcpy(cclc.smcd_trl.eyecatcher, SMCD_EYECATCHER, |
450 | (u64)sg_dma_address(conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl)); | 484 | sizeof(SMCD_EYECATCHER)); |
451 | hton24(cclc.psn, link->psn_initial); | 485 | } else { |
452 | 486 | /* SMC-R specific settings */ | |
453 | memcpy(cclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); | 487 | link = &conn->lgr->lnk[SMC_SINGLE_LINK]; |
488 | memcpy(cclc.hdr.eyecatcher, SMC_EYECATCHER, | ||
489 | sizeof(SMC_EYECATCHER)); | ||
490 | cclc.hdr.path = SMC_TYPE_R; | ||
491 | cclc.hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN); | ||
492 | memcpy(cclc.lcl.id_for_peer, local_systemid, | ||
493 | sizeof(local_systemid)); | ||
494 | memcpy(&cclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1], | ||
495 | SMC_GID_SIZE); | ||
496 | memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1], | ||
497 | ETH_ALEN); | ||
498 | hton24(cclc.qpn, link->roce_qp->qp_num); | ||
499 | cclc.rmb_rkey = | ||
500 | htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey); | ||
501 | cclc.rmbe_idx = 1; /* for now: 1 RMB = 1 RMBE */ | ||
502 | cclc.rmbe_alert_token = htonl(conn->alert_token_local); | ||
503 | cclc.qp_mtu = min(link->path_mtu, link->peer_mtu); | ||
504 | cclc.rmbe_size = conn->rmbe_size_short; | ||
505 | cclc.rmb_dma_addr = cpu_to_be64((u64)sg_dma_address | ||
506 | (conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl)); | ||
507 | hton24(cclc.psn, link->psn_initial); | ||
508 | memcpy(cclc.smcr_trl.eyecatcher, SMC_EYECATCHER, | ||
509 | sizeof(SMC_EYECATCHER)); | ||
510 | } | ||
454 | 511 | ||
455 | memset(&msg, 0, sizeof(msg)); | 512 | memset(&msg, 0, sizeof(msg)); |
456 | vec.iov_base = &cclc; | 513 | vec.iov_base = &cclc; |
457 | vec.iov_len = sizeof(cclc); | 514 | vec.iov_len = ntohs(cclc.hdr.length); |
458 | len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, sizeof(cclc)); | 515 | len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, |
459 | if (len < sizeof(cclc)) { | 516 | ntohs(cclc.hdr.length)); |
517 | if (len < ntohs(cclc.hdr.length)) { | ||
460 | if (len >= 0) { | 518 | if (len >= 0) { |
461 | reason_code = -ENETUNREACH; | 519 | reason_code = -ENETUNREACH; |
462 | smc->sk.sk_err = -reason_code; | 520 | smc->sk.sk_err = -reason_code; |
@@ -479,35 +537,58 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact) | |||
479 | int rc = 0; | 537 | int rc = 0; |
480 | int len; | 538 | int len; |
481 | 539 | ||
482 | link = &conn->lgr->lnk[SMC_SINGLE_LINK]; | ||
483 | memset(&aclc, 0, sizeof(aclc)); | 540 | memset(&aclc, 0, sizeof(aclc)); |
484 | memcpy(aclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); | ||
485 | aclc.hdr.type = SMC_CLC_ACCEPT; | 541 | aclc.hdr.type = SMC_CLC_ACCEPT; |
486 | aclc.hdr.length = htons(sizeof(aclc)); | ||
487 | aclc.hdr.version = SMC_CLC_V1; /* SMC version */ | 542 | aclc.hdr.version = SMC_CLC_V1; /* SMC version */ |
488 | if (srv_first_contact) | 543 | if (srv_first_contact) |
489 | aclc.hdr.flag = 1; | 544 | aclc.hdr.flag = 1; |
490 | memcpy(aclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid)); | 545 | |
491 | memcpy(&aclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1], | 546 | if (new_smc->conn.lgr->is_smcd) { |
492 | SMC_GID_SIZE); | 547 | /* SMC-D specific settings */ |
493 | memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1], ETH_ALEN); | 548 | aclc.hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN); |
494 | hton24(aclc.qpn, link->roce_qp->qp_num); | 549 | memcpy(aclc.hdr.eyecatcher, SMCD_EYECATCHER, |
495 | aclc.rmb_rkey = | 550 | sizeof(SMCD_EYECATCHER)); |
496 | htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey); | 551 | aclc.hdr.path = SMC_TYPE_D; |
497 | aclc.rmbe_idx = 1; /* as long as 1 RMB = 1 RMBE */ | 552 | aclc.gid = conn->lgr->smcd->local_gid; |
498 | aclc.rmbe_alert_token = htonl(conn->alert_token_local); | 553 | aclc.token = conn->rmb_desc->token; |
499 | aclc.qp_mtu = link->path_mtu; | 554 | aclc.dmbe_size = conn->rmbe_size_short; |
500 | aclc.rmbe_size = conn->rmbe_size_short, | 555 | aclc.dmbe_idx = 0; |
501 | aclc.rmb_dma_addr = cpu_to_be64( | 556 | memcpy(&aclc.linkid, conn->lgr->id, SMC_LGR_ID_SIZE); |
502 | (u64)sg_dma_address(conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl)); | 557 | memcpy(aclc.smcd_trl.eyecatcher, SMCD_EYECATCHER, |
503 | hton24(aclc.psn, link->psn_initial); | 558 | sizeof(SMCD_EYECATCHER)); |
504 | memcpy(aclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); | 559 | } else { |
560 | /* SMC-R specific settings */ | ||
561 | aclc.hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN); | ||
562 | memcpy(aclc.hdr.eyecatcher, SMC_EYECATCHER, | ||
563 | sizeof(SMC_EYECATCHER)); | ||
564 | aclc.hdr.path = SMC_TYPE_R; | ||
565 | link = &conn->lgr->lnk[SMC_SINGLE_LINK]; | ||
566 | memcpy(aclc.lcl.id_for_peer, local_systemid, | ||
567 | sizeof(local_systemid)); | ||
568 | memcpy(&aclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1], | ||
569 | SMC_GID_SIZE); | ||
570 | memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1], | ||
571 | ETH_ALEN); | ||
572 | hton24(aclc.qpn, link->roce_qp->qp_num); | ||
573 | aclc.rmb_rkey = | ||
574 | htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey); | ||
575 | aclc.rmbe_idx = 1; /* as long as 1 RMB = 1 RMBE */ | ||
576 | aclc.rmbe_alert_token = htonl(conn->alert_token_local); | ||
577 | aclc.qp_mtu = link->path_mtu; | ||
578 | aclc.rmbe_size = conn->rmbe_size_short, | ||
579 | aclc.rmb_dma_addr = cpu_to_be64((u64)sg_dma_address | ||
580 | (conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl)); | ||
581 | hton24(aclc.psn, link->psn_initial); | ||
582 | memcpy(aclc.smcr_trl.eyecatcher, SMC_EYECATCHER, | ||
583 | sizeof(SMC_EYECATCHER)); | ||
584 | } | ||
505 | 585 | ||
506 | memset(&msg, 0, sizeof(msg)); | 586 | memset(&msg, 0, sizeof(msg)); |
507 | vec.iov_base = &aclc; | 587 | vec.iov_base = &aclc; |
508 | vec.iov_len = sizeof(aclc); | 588 | vec.iov_len = ntohs(aclc.hdr.length); |
509 | len = kernel_sendmsg(new_smc->clcsock, &msg, &vec, 1, sizeof(aclc)); | 589 | len = kernel_sendmsg(new_smc->clcsock, &msg, &vec, 1, |
510 | if (len < sizeof(aclc)) { | 590 | ntohs(aclc.hdr.length)); |
591 | if (len < ntohs(aclc.hdr.length)) { | ||
511 | if (len >= 0) | 592 | if (len >= 0) |
512 | new_smc->sk.sk_err = EPROTO; | 593 | new_smc->sk.sk_err = EPROTO; |
513 | else | 594 | else |
diff --git a/net/smc/smc_clc.h b/net/smc/smc_clc.h index 41ff9ea96139..100e988ad1a8 100644 --- a/net/smc/smc_clc.h +++ b/net/smc/smc_clc.h | |||
@@ -23,6 +23,9 @@ | |||
23 | #define SMC_CLC_DECLINE 0x04 | 23 | #define SMC_CLC_DECLINE 0x04 |
24 | 24 | ||
25 | #define SMC_CLC_V1 0x1 /* SMC version */ | 25 | #define SMC_CLC_V1 0x1 /* SMC version */ |
26 | #define SMC_TYPE_R 0 /* SMC-R only */ | ||
27 | #define SMC_TYPE_D 1 /* SMC-D only */ | ||
28 | #define SMC_TYPE_B 3 /* SMC-R and SMC-D */ | ||
26 | #define CLC_WAIT_TIME (6 * HZ) /* max. wait time on clcsock */ | 29 | #define CLC_WAIT_TIME (6 * HZ) /* max. wait time on clcsock */ |
27 | #define SMC_CLC_DECL_MEM 0x01010000 /* insufficient memory resources */ | 30 | #define SMC_CLC_DECL_MEM 0x01010000 /* insufficient memory resources */ |
28 | #define SMC_CLC_DECL_TIMEOUT 0x02000000 /* timeout */ | 31 | #define SMC_CLC_DECL_TIMEOUT 0x02000000 /* timeout */ |
@@ -42,9 +45,11 @@ struct smc_clc_msg_hdr { /* header1 of clc messages */ | |||
42 | #if defined(__BIG_ENDIAN_BITFIELD) | 45 | #if defined(__BIG_ENDIAN_BITFIELD) |
43 | u8 version : 4, | 46 | u8 version : 4, |
44 | flag : 1, | 47 | flag : 1, |
45 | rsvd : 3; | 48 | rsvd : 1, |
49 | path : 2; | ||
46 | #elif defined(__LITTLE_ENDIAN_BITFIELD) | 50 | #elif defined(__LITTLE_ENDIAN_BITFIELD) |
47 | u8 rsvd : 3, | 51 | u8 path : 2, |
52 | rsvd : 1, | ||
48 | flag : 1, | 53 | flag : 1, |
49 | version : 4; | 54 | version : 4; |
50 | #endif | 55 | #endif |
@@ -77,6 +82,11 @@ struct smc_clc_msg_proposal_prefix { /* prefix part of clc proposal message*/ | |||
77 | u8 ipv6_prefixes_cnt; /* number of IPv6 prefixes in prefix array */ | 82 | u8 ipv6_prefixes_cnt; /* number of IPv6 prefixes in prefix array */ |
78 | } __aligned(4); | 83 | } __aligned(4); |
79 | 84 | ||
85 | struct smc_clc_msg_smcd { /* SMC-D GID information */ | ||
86 | u64 gid; /* ISM GID of requestor */ | ||
87 | u8 res[32]; | ||
88 | }; | ||
89 | |||
80 | struct smc_clc_msg_proposal { /* clc proposal message sent by Linux */ | 90 | struct smc_clc_msg_proposal { /* clc proposal message sent by Linux */ |
81 | struct smc_clc_msg_hdr hdr; | 91 | struct smc_clc_msg_hdr hdr; |
82 | struct smc_clc_msg_local lcl; | 92 | struct smc_clc_msg_local lcl; |
@@ -94,23 +104,45 @@ struct smc_clc_msg_proposal { /* clc proposal message sent by Linux */ | |||
94 | 104 | ||
95 | struct smc_clc_msg_accept_confirm { /* clc accept / confirm message */ | 105 | struct smc_clc_msg_accept_confirm { /* clc accept / confirm message */ |
96 | struct smc_clc_msg_hdr hdr; | 106 | struct smc_clc_msg_hdr hdr; |
97 | struct smc_clc_msg_local lcl; | 107 | union { |
98 | u8 qpn[3]; /* QP number */ | 108 | struct { /* SMC-R */ |
99 | __be32 rmb_rkey; /* RMB rkey */ | 109 | struct smc_clc_msg_local lcl; |
100 | u8 rmbe_idx; /* Index of RMBE in RMB */ | 110 | u8 qpn[3]; /* QP number */ |
101 | __be32 rmbe_alert_token;/* unique connection id */ | 111 | __be32 rmb_rkey; /* RMB rkey */ |
112 | u8 rmbe_idx; /* Index of RMBE in RMB */ | ||
113 | __be32 rmbe_alert_token;/* unique connection id */ | ||
102 | #if defined(__BIG_ENDIAN_BITFIELD) | 114 | #if defined(__BIG_ENDIAN_BITFIELD) |
103 | u8 rmbe_size : 4, /* RMBE buf size (compressed notation) */ | 115 | u8 rmbe_size : 4, /* buf size (compressed) */ |
104 | qp_mtu : 4; /* QP mtu */ | 116 | qp_mtu : 4; /* QP mtu */ |
105 | #elif defined(__LITTLE_ENDIAN_BITFIELD) | 117 | #elif defined(__LITTLE_ENDIAN_BITFIELD) |
106 | u8 qp_mtu : 4, | 118 | u8 qp_mtu : 4, |
107 | rmbe_size : 4; | 119 | rmbe_size : 4; |
108 | #endif | 120 | #endif |
109 | u8 reserved; | 121 | u8 reserved; |
110 | __be64 rmb_dma_addr; /* RMB virtual address */ | 122 | __be64 rmb_dma_addr; /* RMB virtual address */ |
111 | u8 reserved2; | 123 | u8 reserved2; |
112 | u8 psn[3]; /* initial packet sequence number */ | 124 | u8 psn[3]; /* packet sequence number */ |
113 | struct smc_clc_msg_trail trl; /* eye catcher "SMCR" EBCDIC */ | 125 | struct smc_clc_msg_trail smcr_trl; |
126 | /* eye catcher "SMCR" EBCDIC */ | ||
127 | } __packed; | ||
128 | struct { /* SMC-D */ | ||
129 | u64 gid; /* Sender GID */ | ||
130 | u64 token; /* DMB token */ | ||
131 | u8 dmbe_idx; /* DMBE index */ | ||
132 | #if defined(__BIG_ENDIAN_BITFIELD) | ||
133 | u8 dmbe_size : 4, /* buf size (compressed) */ | ||
134 | reserved3 : 4; | ||
135 | #elif defined(__LITTLE_ENDIAN_BITFIELD) | ||
136 | u8 reserved3 : 4, | ||
137 | dmbe_size : 4; | ||
138 | #endif | ||
139 | u16 reserved4; | ||
140 | u32 linkid; /* Link identifier */ | ||
141 | u32 reserved5[3]; | ||
142 | struct smc_clc_msg_trail smcd_trl; | ||
143 | /* eye catcher "SMCD" EBCDIC */ | ||
144 | } __packed; | ||
145 | }; | ||
114 | } __packed; /* format defined in RFC7609 */ | 146 | } __packed; /* format defined in RFC7609 */ |
115 | 147 | ||
116 | struct smc_clc_msg_decline { /* clc decline message */ | 148 | struct smc_clc_msg_decline { /* clc decline message */ |
@@ -129,13 +161,26 @@ smc_clc_proposal_get_prefix(struct smc_clc_msg_proposal *pclc) | |||
129 | ((u8 *)pclc + sizeof(*pclc) + ntohs(pclc->iparea_offset)); | 161 | ((u8 *)pclc + sizeof(*pclc) + ntohs(pclc->iparea_offset)); |
130 | } | 162 | } |
131 | 163 | ||
164 | /* get SMC-D info from proposal message */ | ||
165 | static inline struct smc_clc_msg_smcd * | ||
166 | smc_get_clc_msg_smcd(struct smc_clc_msg_proposal *prop) | ||
167 | { | ||
168 | if (ntohs(prop->iparea_offset) != sizeof(struct smc_clc_msg_smcd)) | ||
169 | return NULL; | ||
170 | |||
171 | return (struct smc_clc_msg_smcd *)(prop + 1); | ||
172 | } | ||
173 | |||
174 | struct smcd_dev; | ||
175 | |||
132 | int smc_clc_prfx_match(struct socket *clcsock, | 176 | int smc_clc_prfx_match(struct socket *clcsock, |
133 | struct smc_clc_msg_proposal_prefix *prop); | 177 | struct smc_clc_msg_proposal_prefix *prop); |
134 | int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, | 178 | int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, |
135 | u8 expected_type); | 179 | u8 expected_type); |
136 | int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info); | 180 | int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info); |
137 | int smc_clc_send_proposal(struct smc_sock *smc, struct smc_ib_device *smcibdev, | 181 | int smc_clc_send_proposal(struct smc_sock *smc, int smc_type, |
138 | u8 ibport); | 182 | struct smc_ib_device *smcibdev, u8 ibport, |
183 | struct smcd_dev *ismdev); | ||
139 | int smc_clc_send_confirm(struct smc_sock *smc); | 184 | int smc_clc_send_confirm(struct smc_sock *smc); |
140 | int smc_clc_send_accept(struct smc_sock *smc, int srv_first_contact); | 185 | int smc_clc_send_accept(struct smc_sock *smc, int srv_first_contact); |
141 | 186 | ||