The SMBDirect Negotiate Request message is the first message sent by the initiator of a new SMBDirect connection, used to begin establishing an SMBDirect connection with the peer.
        public void SmbdNegotiate_UncompletedMessage()
        {
            const ushort CREDIT_REQUESTED = 10;
            const uint MAX_SEND_SIZE = 1024;
            const uint MAX_RECEIVE_SIZE = 1024;
            const uint MAX_FRAGMENT_SIZE = 131072;

            #region Create a negotiate message, Sends only 19 bytes of negotiate message to peer

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Connect to server over RDMA");
            NtStatus status = smbdAdapter.ConnectToServerOverRDMA();
            BaseTestSite.Assert.AreEqual<NtStatus>(status, NtStatus.STATUS_SUCCESS, "Status of SMBD connection is {0}", status);

            // Create negotiate message
            SmbdNegotiateRequest smbdRequest = new SmbdNegotiateRequest();
            smbdRequest.MinVersion = SmbdVersion.V1;
            smbdRequest.MaxVersion = SmbdVersion.V1;
            smbdRequest.Reserved = 0;
            smbdRequest.CreditsRequested = CREDIT_REQUESTED;
            smbdRequest.PreferredSendSize = MAX_SEND_SIZE;
            smbdRequest.MaxReceiveSize = MAX_RECEIVE_SIZE;
            smbdRequest.MaxFragmentedSize = MAX_FRAGMENT_SIZE;

            byte[] requestBytes = TypeMarshal.ToBytes<SmbdNegotiateRequest>(smbdRequest);
            byte[] uncompletedRequest = new byte[requestBytes.Length - 1];
            Array.Copy(requestBytes, uncompletedRequest, uncompletedRequest.Length);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send SMBD negotiate message with only 19 bytes.");
            status = smbdAdapter.SendDataOverRdma(uncompletedRequest);
            BaseTestSite.Assert.AreEqual<NtStatus>(status, NtStatus.STATUS_SUCCESS, "Status of Send SMBD negotiate {0}", status);

            // wait for connection to be terminated
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify server connection will be terminated.");
            smbdAdapter.WaitRdmaDisconnect();
            BaseTestSite.Assert.IsFalse(smbdAdapter.ClientConnection.Endpoint.IsConnected, "Connection should be terminated.");
            #endregion

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Basic negotiate, sending the whole 20 bytes of SMBD negotiate message to peer, verify server returns STATUS_SUCCESS.");
            SmbdNegotiateResponse response;
            BasicNegotiate(
                CREDIT_REQUESTED,
                MAX_SEND_SIZE,
                MAX_RECEIVE_SIZE,
                MAX_FRAGMENT_SIZE,
                out response);
        }
        public void SmbdNegotiate_Redundancy()
        {
            const ushort CREDIT_REQUESTED = 10;
            const uint MAX_SEND_SIZE = 1024;
            const uint MAX_RECEIVE_SIZE = 1024;
            const uint MAX_FRAGMENT_SIZE = 131072;
            const int NEGOTIATE_SIZE = 512; // it is the size of receive size after server accept the connection

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Connect to server over RDMA.");
            NtStatus status = smbdAdapter.ConnectToServerOverRDMA();
            BaseTestSite.Assert.AreEqual<NtStatus>(status, NtStatus.STATUS_SUCCESS, "Status of SMBD connection is {0}.", status);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Create SMBD Negotiate request.");
            SmbdNegotiateRequest request = new SmbdNegotiateRequest();
            request.MinVersion = SmbdVersion.V1;
            request.MaxVersion = SmbdVersion.V1;
            request.Reserved = 0;
            request.CreditsRequested = CREDIT_REQUESTED;
            request.PreferredSendSize = MAX_SEND_SIZE;
            request.MaxReceiveSize = MAX_RECEIVE_SIZE;
            request.MaxFragmentedSize = MAX_FRAGMENT_SIZE;

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Add 492 redundancy bytes.");
            byte[] requestBytes = TypeMarshal.ToBytes<SmbdNegotiateRequest>(request);
            byte[] allbytes = new byte[NEGOTIATE_SIZE];
            Array.Copy(requestBytes, allbytes, requestBytes.Length);

            // post receive
            status = smbdAdapter.ClientConnection.Endpoint.PostReceive(NEGOTIATE_SIZE);
            BaseTestSite.Assert.AreEqual<NtStatus>(status, NtStatus.STATUS_SUCCESS, "Status of Post Receive is {0}.", status);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send SMBD negotiate request.");
            status = smbdAdapter.SendDataOverRdma(allbytes);
            BaseTestSite.Assert.AreEqual<NtStatus>(status, NtStatus.STATUS_SUCCESS, "Status of Send SMBD negotiate is {0}.", status);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Receive and verify NEGOTIATE response.");
            byte[] responseData;
            smbdAdapter.ReceiveDataOverRdma(
                TimeSpan.FromSeconds(SmbdConnection.ACTIVE_NEGOTIATION_TIMEOUT),
                out responseData);
            SmbdNegotiateResponse response = TypeMarshal.ToStruct<SmbdNegotiateResponse>(responseData);
            smbdAdapter.DisconnectRdma();

            NegotiateBasicChecker(
                response,
                CREDIT_REQUESTED,
                MAX_RECEIVE_SIZE,
                MAX_SEND_SIZE,
                MAX_FRAGMENT_SIZE);
        }
Esempio n. 3
0
        /// <summary>
        /// SMBDirect Negotiate
        /// </summary>
        /// <param name="minVersion">The minimum SMBDirect Protocol version supported by the sender</param>
        /// <param name="maxVersion">The maximum SMBDirect Protocol version supported by the sender</param>
        /// <param name="creditsRequested">The number of Send Credits requested of the receiver</param>
        /// <param name="receiveCreditMax">Maximum of receive credits</param>
        /// <param name="preferredSendSize">The maximum number of bytes that the sender requests to transmit in a single message</param>
        /// <param name="maxReceiveSize">The maximum number of bytes that the sender can receive in a single message</param>
        /// <param name="maxFragmentedSize">The maximum number of upper-layer bytes that the sender can receive as the result of a sequence of fragmented Send operations</param>
        /// <param name="smbdNegotiateResponse">SMBDirect Negotiate response</param>
        /// <param name="reserved">The sender SHOULD set this field to 0 and the receiver MUST ignore it on receipt</param>
        /// <returns></returns>
        public NtStatus Negotiate(
            SmbdVersion minVersion,
            SmbdVersion maxVersion,
            ushort creditsRequested,
            ushort receiveCreditMax,
            uint preferredSendSize,
            uint maxReceiveSize,
            uint maxFragmentedSize,
            out SmbdNegotiateResponse smbdNegotiateResponse,
            ushort reserved = 0
            )
        {
            #region set SMBD connection

            Connection.ReceiveCreditMax  = receiveCreditMax;
            Connection.SendCreditTarget  = creditsRequested;
            Connection.MaxSendSize       = preferredSendSize;
            Connection.MaxFragmentedSize = maxFragmentedSize;
            Connection.MaxReceiveSize    = maxReceiveSize;
            #endregion

            smbdNegotiateResponse = new SmbdNegotiateResponse();

            // send negotiate message
            SmbdNegotiateRequest smbdRequest = new SmbdNegotiateRequest();
            smbdRequest.MinVersion        = minVersion;
            smbdRequest.MaxVersion        = maxVersion;
            smbdRequest.Reserved          = reserved;
            smbdRequest.CreditsRequested  = creditsRequested;
            smbdRequest.PreferredSendSize = preferredSendSize;
            smbdRequest.MaxReceiveSize    = maxReceiveSize;
            smbdRequest.MaxFragmentedSize = maxFragmentedSize;


            byte[] requestBytes = TypeMarshal.ToBytes <SmbdNegotiateRequest>(smbdRequest);

            // post receive
            NtStatus ret = Connection.Endpoint.PostReceive((uint)SmbdNegotiateResponse.SIZE);
            if (ret != NtStatus.STATUS_SUCCESS)
            {
                LogEvent(string.Format("Connection.Endpoint.PostReceive with error {0}", ret));
                return(ret);
            }

            // send message
            ret = (NtStatus)Connection.Endpoint.SendData(requestBytes);
            if (ret != NtStatus.STATUS_SUCCESS)
            {
                LogEvent(string.Format("Connection.Endpoint.SendData with error {0}", ret));
                return(ret);
            }

            byte[] responseBytes;
            try
            {
                ret = Connection.Endpoint.ReceiveData(
                    TimeSpan.FromSeconds(SmbdConnection.ACTIVE_NEGOTIATION_TIMEOUT),
                    out responseBytes);
                if (ret != NtStatus.STATUS_SUCCESS)
                {
                    LogEvent(string.Format("Connection.Endpoint.ReceiveData with error {0}", ret));
                    return(ret);
                }
            }
            catch (TimeoutException e)
            {
                LogEvent(string.Format("Do not get the SMBD negotiate response within {0} seconds", SmbdConnection.ACTIVE_NEGOTIATION_TIMEOUT));
                throw new TimeoutException(e.Message);
            }

            smbdNegotiateResponse = TypeMarshal.ToStruct <SmbdNegotiateResponse>(responseBytes);
            if ((NtStatus)smbdNegotiateResponse.Status != NtStatus.STATUS_SUCCESS)
            {
                LogEvent(string.Format("SMBDirect Negotiate response with status {0}", (NtStatus)smbdNegotiateResponse.Status));
                return((NtStatus)smbdNegotiateResponse.Status);
            }

            #region set connection parameters
            Connection.Protocol            = SmbdVersion.V1;
            Connection.ReceiveCreditTarget = smbdNegotiateResponse.CreditsRequested;
            Connection.MaxReceiveSize      = Smaller(Connection.MaxReceiveSize, smbdNegotiateResponse.PreferredSendSize);
            Connection.MaxSendSize         = Smaller(Connection.MaxSendSize, smbdNegotiateResponse.MaxReceiveSize);
            Connection.MaxReadWriteSize    = Smaller(smbdNegotiateResponse.MaxReadWriteSize, SmbdConnection.FLOOR_MAX_READ_WRITE_SIZE);
            Connection.SendCredits         = smbdNegotiateResponse.CreditsGranted;
            #endregion

            Connection.Role = SmbdRole.ESTABLISHED;
            try
            {
                Connection.FragmentReassemblyBuffer = new byte[Connection.MaxFragmentedSize];
            }
            catch (OverflowException)
            {
                Connection.MaxFragmentedSize        = smbdNegotiateResponse.MaxFragmentedSize;
                Connection.FragmentReassemblyBuffer = new byte[Connection.MaxFragmentedSize];
            }
            return((NtStatus)smbdNegotiateResponse.Status);
        }
        public void NegativeNegotiate(
            ushort creditsRequested,
            uint preferredSendSize,
            uint maxReceiveSize,
            uint maxFragmentSize)
        {
            // Connect to server over RDMA, and negotiate
            NtStatus status = smbdAdapter.ConnectToServerOverRDMA();
            BaseTestSite.Assert.AreEqual<NtStatus>(status, NtStatus.STATUS_SUCCESS, "Status of SMBD connection is {0}", status);

            // send negotiate message
            SmbdNegotiateRequest smbdRequest = new SmbdNegotiateRequest();
            smbdRequest.MinVersion = SmbdVersion.V1;
            smbdRequest.MaxVersion = SmbdVersion.V1;
            smbdRequest.Reserved = 0;
            smbdRequest.CreditsRequested = creditsRequested;
            smbdRequest.PreferredSendSize = preferredSendSize;
            smbdRequest.MaxReceiveSize = maxReceiveSize;
            smbdRequest.MaxFragmentedSize = maxFragmentSize;

            byte[] requestBytes = TypeMarshal.ToBytes<SmbdNegotiateRequest>(smbdRequest);

            BaseTestSite.Log.Add(LogEntryKind.Debug,
                        @"Send Negotiate request with parameters:
                        MinVersion: {0},
                        MaxVersion: {1},
                        CreditsRequested: {2},
                        PreferredSendSize: {3},
                        MaxReceiveSize: {4},
                        MaxFragmentedSize: {5}
                        ",
                        smbdRequest.MinVersion,
                        smbdRequest.MaxVersion,
                        smbdRequest.CreditsRequested,
                        smbdRequest.PreferredSendSize,
                        smbdRequest.MaxReceiveSize,
                        smbdRequest.MaxFragmentedSize);
            // send message
            status = smbdAdapter.SendDataOverRdma(requestBytes);
            BaseTestSite.Assert.AreEqual<NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of Send SMBD negotiate {0}", status);

            // wait for connection to be terminated
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify server connection will be terminated.");
            smbdAdapter.WaitRdmaDisconnect();
            BaseTestSite.Assert.IsFalse(smbdAdapter.ClientConnection.Endpoint.IsConnected, "Connection MUST be terminated, but it is not terminated.");
        }
        /// <summary>
        /// SMBDirect Negotiate
        /// </summary>
        /// <param name="minVersion">The minimum SMBDirect Protocol version supported by the sender</param>
        /// <param name="maxVersion">The maximum SMBDirect Protocol version supported by the sender</param>
        /// <param name="creditsRequested">The number of Send Credits requested of the receiver</param>
        /// <param name="receiveCreditMax">Maximum of receive credits</param>
        /// <param name="preferredSendSize">The maximum number of bytes that the sender requests to transmit in a single message</param>
        /// <param name="maxReceiveSize">The maximum number of bytes that the sender can receive in a single message</param>
        /// <param name="maxFragmentedSize">The maximum number of upper-layer bytes that the sender can receive as the result of a sequence of fragmented Send operations</param>
        /// <param name="smbdNegotiateResponse">SMBDirect Negotiate response</param>
        /// <param name="reserved">The sender SHOULD set this field to 0 and the receiver MUST ignore it on receipt</param>
        /// <returns></returns>
        public NtStatus Negotiate(
            SmbdVersion minVersion,
            SmbdVersion maxVersion,
            ushort creditsRequested,
            ushort receiveCreditMax,
            uint preferredSendSize,
            uint maxReceiveSize,
            uint maxFragmentedSize,
            out SmbdNegotiateResponse smbdNegotiateResponse,
            ushort reserved = 0
            )
        {
            #region set SMBD connection

            Connection.ReceiveCreditMax = receiveCreditMax;
            Connection.SendCreditTarget = creditsRequested;
            Connection.MaxSendSize = preferredSendSize;
            Connection.MaxFragmentedSize = maxFragmentedSize;
            Connection.MaxReceiveSize = maxReceiveSize;
            #endregion

            smbdNegotiateResponse = new SmbdNegotiateResponse();

            // send negotiate message
            SmbdNegotiateRequest smbdRequest = new SmbdNegotiateRequest();
            smbdRequest.MinVersion = minVersion;
            smbdRequest.MaxVersion = maxVersion;
            smbdRequest.Reserved = reserved;
            smbdRequest.CreditsRequested = creditsRequested;
            smbdRequest.PreferredSendSize = preferredSendSize;
            smbdRequest.MaxReceiveSize = maxReceiveSize;
            smbdRequest.MaxFragmentedSize = maxFragmentedSize;

            byte[] requestBytes = TypeMarshal.ToBytes<SmbdNegotiateRequest>(smbdRequest);

            // post receive
            NtStatus ret = Connection.Endpoint.PostReceive((uint)SmbdNegotiateResponse.SIZE);
            if (ret != NtStatus.STATUS_SUCCESS)
            {
                LogEvent(string.Format("Connection.Endpoint.PostReceive with error {0}", ret));
                return ret;
            }

            // send message
            ret = (NtStatus)Connection.Endpoint.SendData(requestBytes);
            if (ret != NtStatus.STATUS_SUCCESS)
            {
                LogEvent(string.Format("Connection.Endpoint.SendData with error {0}", ret));
                return ret;
            }

            byte[] responseBytes;
            try
            {
                ret = Connection.Endpoint.ReceiveData(
                    TimeSpan.FromSeconds(SmbdConnection.ACTIVE_NEGOTIATION_TIMEOUT),
                    out responseBytes);
                if (ret != NtStatus.STATUS_SUCCESS)
                {
                    LogEvent(string.Format("Connection.Endpoint.ReceiveData with error {0}", ret));
                    return ret;
                }
            }
            catch (TimeoutException e)
            {
                LogEvent(string.Format("Do not get the SMBD negotiate response within {0} seconds", SmbdConnection.ACTIVE_NEGOTIATION_TIMEOUT));
                throw new TimeoutException(e.Message);
            }

            smbdNegotiateResponse = TypeMarshal.ToStruct<SmbdNegotiateResponse>(responseBytes);
            if ((NtStatus)smbdNegotiateResponse.Status != NtStatus.STATUS_SUCCESS)
            {
                LogEvent(string.Format("SMBDirect Negotiate response with status {0}", (NtStatus)smbdNegotiateResponse.Status));
                return (NtStatus)smbdNegotiateResponse.Status;
            }

            #region set connection parameters
            Connection.Protocol = SmbdVersion.V1;
            Connection.ReceiveCreditTarget = smbdNegotiateResponse.CreditsRequested;
            Connection.MaxReceiveSize = Smaller(Connection.MaxReceiveSize, smbdNegotiateResponse.PreferredSendSize);
            Connection.MaxSendSize = Smaller(Connection.MaxSendSize, smbdNegotiateResponse.MaxReceiveSize);
            Connection.MaxReadWriteSize = Smaller(smbdNegotiateResponse.MaxReadWriteSize, SmbdConnection.FLOOR_MAX_READ_WRITE_SIZE);
            Connection.SendCredits = smbdNegotiateResponse.CreditsGranted;
            #endregion

            Connection.Role = SmbdRole.ESTABLISHED;
            try
            {
                Connection.FragmentReassemblyBuffer = new byte[Connection.MaxFragmentedSize];
            }
            catch (OverflowException)
            {
                Connection.MaxFragmentedSize = smbdNegotiateResponse.MaxFragmentedSize;
                Connection.FragmentReassemblyBuffer = new byte[Connection.MaxFragmentedSize];
            }
            return (NtStatus)smbdNegotiateResponse.Status;
        }