| 536 | } |
| 537 | } |
| 538 | void ParseWelcomePacket(ibv_wc* wc) { |
| 539 | TIBRecvPacketProcess pkt(BP, *wc); |
| 540 | |
| 541 | char cmdId = *(const char*)pkt.GetUDData(); |
| 542 | switch (cmdId) { |
| 543 | case CMD_HANDSHAKE: { |
| 544 | //printf("got handshake\n"); |
| 545 | const TCmdHandshake& handshake = *(TCmdHandshake*)pkt.GetUDData(); |
| 546 | if (handshake.SocketId != ConnectInfo.SocketId) { |
| 547 | // connection attempt from wrong IB subnet |
| 548 | break; |
| 549 | } |
| 550 | TIntrusivePtr<TRCQueuePair> rcQP; |
| 551 | rcQP = new TRCQueuePair(Port->GetCtx(), CQ, BP.GetSRQ(), QP_SEND_QUEUE_SIZE); |
| 552 | |
| 553 | int qpn = rcQP->GetQPN(); |
| 554 | Y_ASSERT(Channels.find(qpn) == Channels.end()); |
| 555 | TIntrusivePtr<TIBPeer>& peer = Channels[qpn]; |
| 556 | peer = new TIBPeer(handshake.MyAddress, rcQP); |
| 557 | |
| 558 | ibv_ah_attr peerAddr; |
| 559 | TIntrusivePtr<TAddressHandle> ahPeer; |
| 560 | Port->GetAHAttr(wc, pkt.GetGRH(), &peerAddr); |
| 561 | ahPeer = new TAddressHandle(Port->GetCtx(), &peerAddr); |
| 562 | |
| 563 | peerAddr.sl = TRAFFIC_SL; |
| 564 | rcQP->Init(peerAddr, handshake.QPN, handshake.PSN); |
| 565 | |
| 566 | TCmdHandshakeAck handshakeAck; |
| 567 | handshakeAck.Command = CMD_HANDSHAKE_ACK; |
| 568 | handshakeAck.PSN = rcQP->GetPSN(); |
| 569 | handshakeAck.QPN = rcQP->GetQPN(); |
| 570 | handshakeAck.YourQPN = handshake.QPN; |
| 571 | // if ack gets lost we'll create new Peer Channel |
| 572 | // and this one will be erased in Step() by timeout counted from LastRecv |
| 573 | BP.PostSend(WelcomeQP, ahPeer, wc->src_qp, WELCOME_QKEY, &handshakeAck, sizeof(handshakeAck)); |
| 574 | //printf("send handshake_ack\n"); |
| 575 | } break; |
| 576 | case CMD_HANDSHAKE_ACK: { |
| 577 | //printf("got handshake_ack\n"); |
| 578 | const TCmdHandshakeAck& handshakeAck = *(TCmdHandshakeAck*)pkt.GetUDData(); |
| 579 | TIBPeer* peer = GetChannelByQPN(handshakeAck.YourQPN); |
| 580 | if (peer) { |
| 581 | ibv_ah_attr peerAddr; |
| 582 | Port->GetAHAttr(wc, pkt.GetGRH(), &peerAddr); |
| 583 | |
| 584 | peerAddr.sl = TRAFFIC_SL; |
| 585 | peer->QP->Init(peerAddr, handshakeAck.QPN, handshakeAck.PSN); |
| 586 | |
| 587 | peer->State = IIBPeer::OK; |
| 588 | |
| 589 | TCmdConfirm confirm; |
| 590 | confirm.Command = CMD_CONFIRM; |
| 591 | peer->PostSend(BP, &confirm, sizeof(confirm), TCompleteInfo::CI_IGNORE, 0); |
| 592 | //printf("send confirm\n"); |
| 593 | } else { |
| 594 | // respective QPN was deleted or never existed |
| 595 | // silently ignore and peer channel on remote side |