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