/// <summary> /// Write file content over RDMA. The file content will be writen with specific number of operations. /// The total size of the write content is SMB2 negotiated MaxWriteize, so content size /// in each SMB2 WRITE request is ( MaxWriteSize / operationCount ) /// </summary> /// <param name="operationCount">count of SMB2 WRITE operation</param> public void WriteOverRdma(uint operationCount = 1) { string fileName = CreateRandomFileName(); InitSmbdConnectionForTestCases(fileName); uint writeSize = smbdAdapter.Smb2MaxWriteSize / operationCount; uint totalSize = writeSize * operationCount; // SMB2 Write file byte[] fileContent = Encoding.ASCII.GetBytes(Smb2Utility.CreateRandomStringInByte((int)writeSize)); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send each write request according SMB2 write file limit."); for (int i = 0; i < operationCount; ++i) { // register memory and get buffer descriptor SmbdBufferDescriptorV1 descp; smbdAdapter.SmbdRegisterBuffer( writeSize, SmbdBufferReadWrite.RDMA_READ_PERMISSION_FOR_WRITE_FILE, out descp ); smbdAdapter.SmbdWriteRegisteredBuffer(fileContent, descp); byte[] channelInfo = TypeMarshal.ToBytes <SmbdBufferDescriptorV1>(descp); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Write content to file over RDMA."); WRITE_Response writeResponse; NtStatus status = (NtStatus)smbdAdapter.Smb2WriteOverRdmaChannel( (UInt64)i * writeSize, channelInfo, writeSize, out writeResponse ); BaseTestSite.Assert.AreEqual <NtStatus>( NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Write File offset {0} is {1}", i * writeSize, status); BaseTestSite.Assert.AreEqual <uint>( (uint)writeSize, writeResponse.Count, "DataLength in WRITE response is {0}", writeResponse.Count); } BaseTestSite.Log.Add(LogEntryKind.TestStep, "Validate file content."); ValidateFileContent(fileContent, totalSize); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Close file."); smbdAdapter.Smb2CloseFile(); }
public void BVT_Smb2OverRdma_Smb302_Write_SMB2_CHANNEL_RDMA_V1_INVALIDATE() { EstablishConnectionAndOpenFile(fileName, Smb302AboveDialects); uint writeSize = smbdAdapter.Smb2MaxWriteSize; byte[] fileContent = Smb2Utility.CreateRandomByteArray((int)writeSize); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Register memory and get buffer descriptor for SMB2 WRITE"); SmbdBufferDescriptorV1 descp; NtStatus status = smbdAdapter.SmbdRegisterBuffer( writeSize, SmbdBufferReadWrite.RDMA_READ_PERMISSION_FOR_WRITE_FILE, out descp); BaseTestSite.Assert.AreEqual( NtStatus.STATUS_SUCCESS, status, "Register buffer should succeed."); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Write content to file over RDMA."); status = Smb2WriteOverRdma(fileName, fileContent, Channel_Values.CHANNEL_RDMA_V1_INVALIDATE, descp); BaseTestSite.Assert.AreEqual <NtStatus>( NtStatus.STATUS_SUCCESS, status, "SMB2 WRITE over RDMA should succeed."); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify file content."); ValidateFileContent(fileContent); try { fileContent = Encoding.ASCII.GetBytes(Smb2Utility.CreateRandomStringInByte((int)writeSize)); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send Smb2 WRITE request using same descriptor which should be invalidated."); status = Smb2WriteOverRdma(fileName, fileContent, Channel_Values.CHANNEL_RDMA_V1_INVALIDATE, descp); } catch { BaseTestSite.Log.Add(LogEntryKind.Debug, "Verify connection is terminated ."); smbdAdapter.WaitRdmaDisconnect(); } BaseTestSite.Assert.IsFalse(smbdAdapter.ClientConnection.Endpoint.IsConnected, "Connection should be terminated when accessing a memory window which is already invalidated."); }
public void Smb2OverRdma_Write_SMB2_CHANNEL_RDMA_V1() { EstablishConnectionAndOpenFile(fileName); uint writeSize = smbdAdapter.Smb2MaxWriteSize; byte[] fileContent = Smb2Utility.CreateRandomByteArray((int)writeSize); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Register memory and get buffer descriptor for SMB2 WRITE"); SmbdBufferDescriptorV1 descp; NtStatus status = smbdAdapter.SmbdRegisterBuffer( writeSize, SmbdBufferReadWrite.RDMA_READ_PERMISSION_FOR_WRITE_FILE, out descp); BaseTestSite.Assert.AreEqual( NtStatus.STATUS_SUCCESS, status, "Register buffer should succeed."); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Write content to file over RDMA."); status = Smb2WriteOverRdma(fileName, fileContent, Channel_Values.CHANNEL_RDMA_V1, descp); BaseTestSite.Assert.AreEqual <NtStatus>( NtStatus.STATUS_SUCCESS, status, "SMB2 WRITE over RDMA should succeed."); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify file content."); ValidateFileContent(fileContent); fileContent = Encoding.ASCII.GetBytes(Smb2Utility.CreateRandomStringInByte((int)writeSize)); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send Smb2 WRITE request using same descriptor."); status = Smb2WriteOverRdma(fileName, fileContent, Channel_Values.CHANNEL_RDMA_V1, descp); BaseTestSite.Assert.AreEqual <NtStatus>( NtStatus.STATUS_SUCCESS, status, "SMB2 WRITE over RDMA should succeed."); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify file content."); ValidateFileContent(fileContent); }
/// <summary> /// Write from Main channel over TCP /// </summary> /// <param name="serverIp">IP Address of Server.</param> /// <param name="clientIp">IP Address of Client.</param> /// <param name="fileName">File name.</param> /// <param name="totalWriteSize">Total Write Size in Bytes.</param> /// <param name="content">Content in the WRITE request.</param> /// <param name="treeId">Tree Connect Id.</param> /// <param name="fileId">File Id.</param> private void WriteFromMainChannel( IPAddress serverIp, IPAddress clientIp, string fileName, uint totalWriteSize, out byte[] content, out uint treeId, out FILEID fileId ) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Write file from Main channel over TCP."); BaseTestSite.Log.Add(LogEntryKind.Debug, "serverIp: " + serverIp.ToString()); BaseTestSite.Log.Add(LogEntryKind.Debug, "clientIp: " + clientIp.ToString()); BaseTestSite.Log.Add(LogEntryKind.Debug, "fileName: " + fileName); BaseTestSite.Log.Add(LogEntryKind.Debug, "Total write size in Bytes: " + totalWriteSize.ToString()); mainChannelClient.ConnectOverTCP(serverIp, clientIp); // SMB2 Negotiate DialectRevision[] negotiatedDialects = new DialectRevision[] { DialectRevision.Smb30, DialectRevision.Smb2002, DialectRevision.Smb21 }; DialectRevision selectedDialect; NtStatus status = (NtStatus)mainChannelClient.Smb2Negotiate(negotiatedDialects, out selectedDialect); BaseTestSite.Assert.AreEqual <NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Negotiate is {0}", status); // SMB2 Session Setup status = (NtStatus)mainChannelClient.Smb2SessionSetup( testConfig.SecurityPackageForSmb2UserAuthentication, testConfig.DomainName, testConfig.UserName, testConfig.Password, testConfig.ServerName ); BaseTestSite.Assert.AreEqual <NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Session Setup is {0}", status); // SMB2 Tree Connect status = (NtStatus)mainChannelClient.Smb2TreeConnect(testConfig.ServerName, testConfig.ShareFolder); BaseTestSite.Assert.AreEqual <NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Tree Connect is {0}", status); // SMB2 Open File status = (NtStatus)mainChannelClient.Smb2Create(fileName); BaseTestSite.Assert.AreEqual <NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Create is {0}", status); uint maxWriteSize = mainChannelClient.Smb2MaxWriteSize; content = Encoding.ASCII.GetBytes(Smb2Utility.CreateRandomStringInByte((int)totalWriteSize)); #region SMB2 Write file // Send each write request according SMB2 write file limit uint offset = 0; while (offset < totalWriteSize) { uint length = maxWriteSize; if (offset + length > content.Length) { length = (uint)content.Length - offset; } WRITE_Response writeResponse; status = (NtStatus)mainChannelClient.Smb2Write((UInt64)offset, content, out writeResponse); BaseTestSite.Assert.AreEqual <NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Write File is {0}", status); BaseTestSite.Assert.AreEqual <uint>((uint)length, writeResponse.Count, "DataLength in WRITE response is {0}", writeResponse.Count); offset += length; } #endregion treeId = mainChannelClient.TreeId; fileId = mainChannelClient.FileId; }
public void BVT_MultiCredit_OneRequestWithMultiCredit() { TestConfig.CheckDialect(DialectRevision.Smb21); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LARGE_MTU); Guid clientGuid = Guid.NewGuid(); string fileName = "MultiCredit_" + clientGuid.ToString() + ".txt"; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: 1. NEGOTIATE; 2. SESSION_SETUP; 3. TREE_CONNECT"); Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite); client.ConnectToServerOverTCP(TestConfig.SutIPAddress); Capabilities_Values clientCapabilities = Capabilities_Values.GLOBAL_CAP_LARGE_MTU; client.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilities); client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); uint treeId; client.TreeConnect(uncSharePath, out treeId); int bufferSize = (int)client.MaxBufferSize; FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts; ushort grantedCredit = 0; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request with {0} credits", client.Credits); client.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out serverCreateContexts, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); BaseTestSite.Log.Add(LogEntryKind.Debug, "The MaxBufferSize of the server is {0}.", client.MaxBufferSize); BaseTestSite.Log.Add(LogEntryKind.Debug, "Server has granted {0} credits to the client.", client.Credits); // Make sure client hold enough credits for test ushort maxBufferSizeInCredit = (ushort)((client.MaxBufferSize - 1) / 65536 + 1); if (client.Credits < maxBufferSizeInCredit) { if (client.Credits < 2) { BaseTestSite.Assert.Inconclusive( "This test case is not applicable when the server only grants {0} credits", client.Credits); } // Test max buffer according to granted credits. bufferSize = (client.Credits - 1) * 65536; } grantedCredit = header.CreditRequestResponse; }); contentWrite = Smb2Utility.CreateRandomStringInByte(bufferSize); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Client attempts to write {0} bytes content to file when server grants {1} credits", client.MaxBufferSize, client.Credits); client.Write( treeId, fileId, contentWrite, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); grantedCredit = header.CreditRequestResponse; }); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Client attempts to read {0} bytes content from file when server grants {1} credit", bufferSize, client.Credits); client.Read(treeId, fileId, 0, (uint)contentWrite.Length, out contentRead); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: 1. CLOSE; 2. TREE_DISCONNECT; 3. LOG_OFF; 4. DISCONNECT"); client.Close(treeId, fileId); client.TreeDisconnect(treeId); client.LogOff(); client.Disconnect(); }
private void CreateFile(string uncShare, string fileName, int lengthInByte) { Site.Log.Add( LogEntryKind.Debug, "Create file {0} in share {1}", fileName, uncShare); Smb2FunctionalClient client = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); client.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress); client.CreditGoal = 32; client.Negotiate( new DialectRevision[] { ModelUtility.GetDialectRevision(config.MaxSmbVersionSupported) }, testConfig.IsSMB1NegotiateEnabled, capabilityValue: Capabilities_Values.GLOBAL_CAP_LARGE_MTU); client.SessionSetup( testConfig.DefaultSecurityPackage, testConfig.SutComputerName, testConfig.AccountCredential, testConfig.UseServerGssToken); uint tId; client.TreeConnect( uncShare, out tId); Smb2CreateContextResponse[] serverCreateContexts; FILEID fId; client.Create( tId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fId, out serverCreateContexts); string content; if (isMultiCreditSupportedOnConnection) { content = Smb2Utility.CreateRandomStringInByte(lengthInByte); client.Write(tId, fId, content); } else { // Write several times if server does not support multi credit int writeTimes = lengthInByte / (64 * 1024); int rest = lengthInByte % (64 * 1024); ulong offset = 0; for (int time = 0; time < writeTimes; time++) { content = Smb2Utility.CreateRandomString(64); client.Write(tId, fId, content, offset); offset += 64 * 1024; } if (rest != 0) { content = Smb2Utility.CreateRandomStringInByte(rest); client.Write(tId, fId, content, offset); } } client.Close(tId, fId); client.TreeDisconnect(tId); client.LogOff(); client.Disconnect(); Site.Log.Add( LogEntryKind.Debug, "Create file {0} in share {1}", fileName, uncShare); }
public void CreditOperationRequest( ModelMidType midType, ModelCreditCharge creditCharge, ModelCreditRequestNum creditRequestNum, ModelPayloadSize payloadSize, ModelPayloadType payloadType) { #region Customize message id ulong smallestAvailableMId = testClient.SequenceWindow.Min; ulong largestAvailableMId = testClient.SequenceWindow.Max; ulong customizedMId = 0; switch (midType) { case ModelMidType.UnavailableMid: { customizedMId = largestAvailableMId + 1; break; } case ModelMidType.UsedMid: { customizedMId = smallestAvailableMId - 1; break; } case ModelMidType.ValidMid: { customizedMId = (ulong)(smallestAvailableMId + largestAvailableMId) / 2; break; } default: throw new ArgumentException("midType"); } testClient.GenerateMessageId = (sequenceWindow) => customizedMId; Site.Log.Add( LogEntryKind.Debug, "*****customizedMId = {0}", customizedMId); #endregion #region Customize credit charge ushort customizedCreditCharge = 0; // Only customize credit charge when midType is valid if (midType == ModelMidType.ValidMid) { switch (creditCharge) { case ModelCreditCharge.CreditChargeWithinBoundary: { customizedCreditCharge = (ushort)((largestAvailableMId - customizedMId + 2) / 2); break; } case ModelCreditCharge.CreditChargeExceedBoundary: { customizedCreditCharge = (ushort)(largestAvailableMId - customizedMId + 2); break; } case ModelCreditCharge.CreditChargeSetZero: { customizedCreditCharge = 0; break; } default: { Site.Assume.Fail("Unexpected creditCharge {0}", creditCharge); break; } } } testClient.GenerateCreditCharge = (size) => customizedCreditCharge; Site.Log.Add( LogEntryKind.Debug, "*****customizedCreditCharge = {0}", customizedCreditCharge); #endregion #region Customize credit request ushort customizedCreditRequest = 0; switch (creditRequestNum) { case ModelCreditRequestNum.CreditRequestSetNonZero: { customizedCreditRequest = (ushort)((1 + testClient.CreditGoal) / 2); break; } case ModelCreditRequestNum.CreditRequestSetZero: { customizedCreditRequest = 0; break; } default: { Site.Assume.Fail("Unexpected creditRequestNum {0}", creditRequestNum); break; } } testClient.GenerateCreditRequest = (sequeceWindow, creditGoal, charge) => customizedCreditRequest; Site.Log.Add( LogEntryKind.Debug, "*****customizedCreditRequest = {0}", customizedCreditRequest); #endregion #region Calculate payload size int dataLengthInByte = 0; switch (payloadSize) { case ModelPayloadSize.PayloadSizeEqualToBoundary: { if (customizedCreditCharge == 0 && isMultiCreditSupportedOnConnection) { dataLengthInByte = 64 * 1024; } else if (!isMultiCreditSupportedOnConnection) { //3.3.5.2: If Connection.SupportsMultiCredit is FALSE and the size of the request is greater than 68*1024 bytes, the server SHOULD<200> terminate the connection //Note 1. 68*1024 byte is total size of Smb2 packet including header, so need to subtract such overhead to calculate payload size // 2. This case is only for WRITE but here does not distiguish READ and WRITE for simplicity uint maxSize = 0; if (testConfig.UnderlyingTransport == Smb2TransportType.NetBios) { maxSize = MaxNetbiosBufferSize; } else { maxSize = 68 * 1024; } dataLengthInByte = (int)(maxSize - Smb2PacketHeaderSizeInByte - Smb2WriteRequestBodySizeInByte); } else { dataLengthInByte = customizedCreditCharge * 64 * 1024; } break; } case ModelPayloadSize.PayloadSizeLargerThanBoundary: { if (customizedCreditCharge == 0 && isMultiCreditSupportedOnConnection) { dataLengthInByte = 64 * 1024 + 1; } else if (!isMultiCreditSupportedOnConnection) { //3.3.5.2: If Connection.SupportsMultiCredit is FALSE and the size of the request is greater than 68*1024 bytes, the server SHOULD<200> terminate the connection //Note 1. 68*1024 byte is total size of Smb2 packet including header, so need to subtract such overhead to calculate payload size // 2. This case is only for WRITE but here does not distiguish READ and WRITE for simplicity uint maxSize = 0; if (testConfig.UnderlyingTransport == Smb2TransportType.NetBios) { maxSize = MaxNetbiosBufferSize; } else { maxSize = 68 * 1024; } dataLengthInByte = (int)(maxSize - Smb2PacketHeaderSizeInByte - Smb2WriteRequestBodySizeInByte + 1); } else { dataLengthInByte = customizedCreditCharge * 64 * 1024 + 1; } break; } case ModelPayloadSize.PayloadSizeLessThanBoundary: { if (customizedCreditCharge == 0 && isMultiCreditSupportedOnConnection) { dataLengthInByte = 32 * 1024; } else if (!isMultiCreditSupportedOnConnection) { dataLengthInByte = 34 * 1024; } else { dataLengthInByte = customizedCreditCharge * 32 * 1024; } break; } default: { Site.Assume.Fail("Unexpected creditRequestNum {0}", creditRequestNum); break; } } Site.Log.Add( LogEntryKind.Debug, "*****dataLengthInByte = {0}", dataLengthInByte); #endregion #region Send request uint status = 0; uint creditResponse = 0; switch (payloadType) { case ModelPayloadType.RequestPayload: { try { string contentToWrite = Smb2Utility.CreateRandomStringInByte(dataLengthInByte); testClient.Write( treeId, fileId, contentToWrite, checker: (header, response) => { status = header.Status; creditResponse = header.CreditRequestResponse; }); if (dataLengthInByte > testClient.MaxBufferSize && config.Platform != Platform.WindowsServer2008) { // The server MUST validate that the length to write is within its configured maximum write size. // If not, it SHOULD<283> fail the request with STATUS_INVALID_PARAMETER. // <283> Section 3.3.5.13: Windows 7 and Windows Server 2008 R2 fail the request with STATUS_BUFFER_OVERFLOW instead of // STATUS_INVALID_PARAMETER if the Length field is greater than Connection.MaxWriteSize. // Windows Vista SP1 and Windows Server 2008 do not validate the Length field in SMB2 Write Request. if (config.Platform == Platform.WindowsServer2008R2) { Site.Assert.AreEqual( ModelSmb2Status.STATUS_BUFFER_OVERFLOW, (ModelSmb2Status)status, "Windows 7, Windows Server 2008 R2 fail the request with STATUS_BUFFER_OVERFLOW if exceeds max write size"); } else { Site.Assert.AreNotEqual( ModelSmb2Status.STATUS_SUCCESS, (ModelSmb2Status)status, "Server SHOULD fail the request with STATUS_INVALID_PARAMETER if exceeds max write data"); } // Bypass the situation when data length exceeds max size that connection allows CreditOperationResponse(ModelSmb2Status.STATUS_SUCCESS, creditResponse, config); } else { if (config.Platform == Platform.WindowsServer2008 && dataLengthInByte > testClient.MaxBufferSize) { Site.Assert.AreEqual( ModelSmb2Status.STATUS_SUCCESS, (ModelSmb2Status)status, "Windows Vista SP1 and Windows Server 2008 do not validate the Length field in SMB2 Write Request."); // Bypass the situation when data length exceeds max size that connection allows CreditOperationResponse(ModelSmb2Status.STATUS_INVALID_PARAMETER, creditResponse, config); } else { CreditOperationResponse((ModelSmb2Status)status, creditResponse, config); } } PostOperation(); } catch (Exception ex) { // Make sure testClient was set to null during disconnection correctly // In case we catch a timeout exception first // Temp fix for test suite bug 6349 as per discussion // For an SMB2 Write request with an invalid MessageId, Windows 8 and Windows Server 2012 will stop processing // the request and any further requests on that connection. // So Smb2Client will throw a timeout exception instead of disconnect event. // The test case should handle the timeout exception the same with disconnect event. if (ex is TimeoutException || testClient.Smb2Client.IsServerDisconnected) { OnServerDisconnected(); } else { throw; } return; } break; } case ModelPayloadType.ResponsePayload: { CreateFile(uncSharePath, fileName, dataLengthInByte); try { string contentToRead = null; testClient.Read( treeId, fileId, 0, (uint)dataLengthInByte, out contentToRead, (header, response) => { status = header.Status; creditResponse = header.CreditRequestResponse; }); if (dataLengthInByte > testClient.MaxBufferSize) { // The server MUST validate that the length to read is within its configured maximum read size. // If not, it SHOULD<277> fail the request with STATUS_INVALID_PARAMETER. // <277> Section 3.3.5.12: Windows 7 and Windows Server 2008 R2 fail the request with STATUS_BUFFER_OVERFLOW if the Length field is greater than Connection.MaxReadSize. // Windows Vista SP1 and Windows Server 2008 will fail the request with STATUS_BUFFER_OVERFLOW if the Length field is greater than 524288(0x80000). if (config.Platform == Platform.WindowsServer2008 || config.Platform == Platform.WindowsServer2008R2) { if (config.Platform == Platform.WindowsServer2008R2) { Site.Assert.AreEqual( ModelSmb2Status.STATUS_BUFFER_OVERFLOW, (ModelSmb2Status)status, "Windows 7, and Windows Server 2008 R2 fail the request with STATUS_BUFFER_OVERFLOW if exceeds max read size"); } else if (dataLengthInByte > 524288) { Site.Assert.AreEqual( ModelSmb2Status.STATUS_BUFFER_OVERFLOW, (ModelSmb2Status)status, "Windows Vista SP1 and Windows Server 2008 will fail the request with STATUS_BUFFER_OVERFLOW if the Length field is greater than 524288"); } } else if (config.Platform == Platform.WindowsServer2012 || config.Platform == Platform.WindowsServer2012R2) { // The server MUST validate that the length to read is within its configured maximum read size. // If not, it SHOULD<277> fail the request with STATUS_INVALID_PARAMETER. Site.Assert.AreEqual( ModelSmb2Status.STATUS_INVALID_PARAMETER, (ModelSmb2Status)status, "The server SHOULD fail the request with STATUS_INVALID_PARAMETER if the length is NOT within its configured maximum size."); } else // NonWindows { Site.Assert.AreNotEqual( ModelSmb2Status.STATUS_SUCCESS, (ModelSmb2Status)status, "Server SHOULD fail the request with STATUS_INVALID_PARAMETER if exceeds max read size"); } // Bypass the situation when data length exceeds max size that connection allows CreditOperationResponse(ModelSmb2Status.STATUS_SUCCESS, creditResponse, config); } else { CreditOperationResponse((ModelSmb2Status)status, creditResponse, config); } PostOperation(); } catch (Exception ex) { // Make sure testClient was set to null during disconnection correctly // In case we catch a timeout exception first // Temp fix for test suite bug 6349 as per discussion // For an SMB2 Write request with an invalid MessageId, Windows 8 and Windows Server 2012 will stop processing // the request and any further requests on that connection. // So Smb2Client will throw a timeout exception instead of disconnect event. // The test case should handle the timeout exception the same with disconnect event. if (ex is TimeoutException || testClient.Smb2Client.IsServerDisconnected) { OnServerDisconnected(); } else { throw; } return; } break; } default: throw new ArgumentException("payloadType"); } #endregion }
public void Smb2OverRdmaChannel_ReadWriteMultipleBufferDescriptorList() { InitSmbdConnectionForTestCases(smbdAdapter.TestConfig.TestFileName_LargeFile); uint size = smbdAdapter.Smb2MaxReadSize; if (size > smbdAdapter.Smb2MaxWriteSize) { size = smbdAdapter.Smb2MaxWriteSize; } int bufferCount = ushort.MaxValue / SmbdBufferDescriptorV1.SIZE; // SMB2 max support channel info size uint bufferLength = (uint)(size / bufferCount + 1); // buffer length of each buffer descriptor byte[] channelInfo = new byte[SmbdBufferDescriptorV1.SIZE * bufferCount]; byte[] writeContent = Encoding.ASCII.GetBytes(Smb2Utility.CreateRandomStringInByte((int)size)); byte[] readContent = new byte[size]; NtStatus status; #region SMB2 Write file BaseTestSite.Log.Add(LogEntryKind.TestStep, "Register memory and get buffer descriptor for SMB2 WRITE"); SmbdBufferDescriptorV1[] writeDescp = new SmbdBufferDescriptorV1[bufferCount]; for (int i = 0; i < bufferCount; ++i) { smbdAdapter.SmbdRegisterBuffer( bufferLength, SmbdBufferReadWrite.RDMA_READ_PERMISSION_FOR_WRITE_FILE, out writeDescp[i]); byte[] channelInfoBlock = TypeMarshal.ToBytes <SmbdBufferDescriptorV1>(writeDescp[i]); Array.Copy( channelInfoBlock, 0, channelInfo, SmbdBufferDescriptorV1.SIZE * i, SmbdBufferDescriptorV1.SIZE); } // copy write content for (int index = 0, writeOffset = 0; index < bufferCount && writeOffset < writeContent.Length; ++index, writeOffset += (int)bufferLength) { int length = (int)bufferLength; if (length + writeOffset > writeContent.Length) { length = writeContent.Length - writeOffset; } byte[] buffer = new byte[length]; Array.Copy(writeContent, writeOffset, buffer, 0, length); smbdAdapter.SmbdWriteRegisteredBuffer(buffer, writeDescp[index]); } BaseTestSite.Log.Add(LogEntryKind.TestStep, "Write content to file over RDMA."); WRITE_Response writeResponse; status = (NtStatus)smbdAdapter.Smb2WriteOverRdmaChannel( 0, channelInfo, size, out writeResponse ); BaseTestSite.Assert.AreEqual <NtStatus>( NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Write File is {0}", status); BaseTestSite.Assert.AreEqual <uint>( (uint)size, writeResponse.Count, "DataLength in WRITE response is {0}", writeResponse.Count); #endregion #region Read file from server BaseTestSite.Log.Add(LogEntryKind.TestStep, "Register memory and get buffer descriptor for SMB2 WRITE"); SmbdBufferDescriptorV1[] readDescp = new SmbdBufferDescriptorV1[bufferCount]; for (int i = 0; i < bufferCount; ++i) { smbdAdapter.SmbdRegisterBuffer( bufferLength, SmbdBufferReadWrite.RDMA_WRITE_PERMISSION_FOR_READ_FILE, out readDescp[i]); byte[] channelInfoBlock = TypeMarshal.ToBytes <SmbdBufferDescriptorV1>(readDescp[i]); Array.Copy( channelInfoBlock, 0, channelInfo, SmbdBufferDescriptorV1.SIZE * i, SmbdBufferDescriptorV1.SIZE); } BaseTestSite.Log.Add(LogEntryKind.TestStep, "Read content from file over RDMA."); READ_Response readResponse; byte[] readData; status = (NtStatus)smbdAdapter.Smb2ReadOverRdmaChannel( 0, size, channelInfo, out readResponse, out readData ); BaseTestSite.Assert.AreEqual <NtStatus>( NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Read File is {0}", status); BaseTestSite.Assert.AreEqual <uint>( 0, readResponse.DataLength, "DataLength in READ response is {0}", readResponse.DataLength); BaseTestSite.Assert.AreEqual <int>( 0, readData.Length, "Data length of content in response is {0}", readData.Length); BaseTestSite.Assert.AreEqual <byte>( 80, readResponse.DataOffset, "DataOffset in response is {0}", readResponse.DataOffset); BaseTestSite.Assert.AreEqual <uint>( size, readResponse.DataRemaining, "DataRemaining in response is {0}", readResponse.DataRemaining); // read content for (int index = 0, readOffset = 0; index < bufferCount && readOffset < readContent.Length; ++index, readOffset += (int)bufferLength) { int length = (int)bufferLength; if (length + readOffset > readContent.Length) { length = writeContent.Length - readOffset; } byte[] buffer = new byte[length]; smbdAdapter.SmbdReadRegisteredBuffer(buffer, readDescp[index]); Array.Copy(buffer, 0, readContent, readOffset, length); } #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "Check the read content is same as the one written into the file."); BaseTestSite.Assert.IsTrue( SmbdUtilities.CompareByteArray(writeContent, readContent), "Check content of file"); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Close file."); smbdAdapter.Smb2CloseFile(); }
public void BVT_CopyOffload() { BaseTestSite.Log.Add(LogEntryKind.TestStep, "1. Create a file with specified length {0} as the source of offload copy.", TestConfig.WriteBufferLengthInKb * 1024); string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb); string fileName = Guid.NewGuid().ToString(); uint treeId; FILEID fileIdSrc; PrepareTestFile(fileName, content, out treeId, out fileIdSrc); BaseTestSite.Log.Add(LogEntryKind.TestStep, "2. Client sends IOCTL request with FSCTL_OFFLOAD_READ to ask server to generate the token of the content for offload copy."); STORAGE_OFFLOAD_TOKEN token; ulong fileOffsetToRead = 0; //FileOffset should be aligned to logical sector boundary on the volume, e.g. 512 bytes ulong copyLengthToRead = (ulong)TestConfig.WriteBufferLengthInKb * 1024; //CopyLength should be aligned to logical sector boundary on the volume, e.g. 512 bytes ulong transferLength; // Request hardware to generate a token that represents a range of file to be copied client.OffloadRead( treeId, fileIdSrc, fileOffsetToRead, copyLengthToRead, out transferLength, out token); BaseTestSite.Log.Add(LogEntryKind.Debug, "Transfer length during OFFLOAD_READ is {0}", transferLength); BaseTestSite.Assert.AreEqual(copyLengthToRead, transferLength, "Transfer length {0} should be equal to copy length {1}", transferLength, copyLengthToRead); BaseTestSite.Log.Add(LogEntryKind.TestStep, "3. Create another file as the destination of offload copy."); FILEID fileIdDest; Smb2CreateContextResponse[] serverCreateContexts; client.Create( treeId, Guid.NewGuid().ToString(), CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdDest, out serverCreateContexts); // Bug 8016334 // The destination file of CopyOffload Write should not be zero, it should be at least 512 bytes, which is the sector size. client.Write(treeId, fileIdDest, Smb2Utility.CreateRandomStringInByte(512)); client.Flush(treeId, fileIdDest); BaseTestSite.Log.Add(LogEntryKind.TestStep, "4. Client sends IOCTL request with FSCTL_OFFLOAD_WRITE to ask server to copy the content from source to destination."); ulong fileOffsetToWrite = 0; //FileOffset should be aligned to logical sector boundary on the volume, e.g. 512 bytes ulong copyLengthToWrite = transferLength; //CopyLength should be aligned to logical sector boundary on the volume, e.g. 512 bytes ulong transferOffset = 0; //TransferOffset should be aligned to logical sector boundary on the volume, e.g. 512 bytes // Request hardware to write a range of file which is represented by the generated token // and length/offset to another place (a different file or different offset of the same file) client.OffloadWrite( treeId, fileIdDest, fileOffsetToWrite, copyLengthToWrite, transferOffset, token); BaseTestSite.Log.Add(LogEntryKind.TestStep, "5. Compare the content of section 1 with the content of section 2."); string readContent; // Read the content that was just offload copied client.Read( treeId, fileIdDest, fileOffsetToWrite, (uint)copyLengthToWrite, out readContent); BaseTestSite.Assert.IsTrue( readContent.Equals(content), "File content read should equal to original"); BaseTestSite.Log.Add(LogEntryKind.TestStep, "6. Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF."); client.Close(treeId, fileIdSrc); client.Close(treeId, fileIdDest); client.TreeDisconnect(treeId); client.LogOff(); }