private void NewTestFile(Smb2FunctionalClient client, string fileName, string content, out uint treeId, out FILEID fileId)
        {
            client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.ShareServerName, TestConfig.ShareServerIP);
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT");
            client.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "NEGOTIATE should succeed.");

                TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response);
            });

            client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.ShareServerName,
                //TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            //string uncSharePath = Smb2Utility.GetUncPath(TestConfig.HvrsSutComputerName, TestConfig.ShareName);
            client.TreeConnect(TestConfig.SharePath, out treeId);
            //string uncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare);
            //client.TreeConnect(uncSharePath, out treeId);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client writes to the file.");
            Smb2CreateContextResponse[] serverCreateContexts;
            client.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts);

            client.Write(treeId, fileId, content);

            // Flush written content to backend storage to avoid cache.
            client.Flush(treeId, fileId);
        }
예제 #2
0
        /// <summary>
        /// Write content before failover
        /// </summary>
        /// <param name="fsType">FileServerType</param>
        /// <param name="server">File Server name.</param>
        /// <param name="serverAccessIp">File Server Access IP.</param>
        /// <param name="uncSharePath">The share path to write the file.</param>
        /// <param name="file">The file name for writing content.</param>
        /// <param name="content">The content to write.</param>
        /// <param name="clientGuid">Smb2 client Guid.</param>
        /// <param name="createGuid">The Guid for smb2 create request.</param>
        /// <returns></returns>
        protected bool WriteContentBeforeFailover(
            FileServerType fsType,
            string server,
            IPAddress serverAccessIp,
            string uncSharePath,
            string file,
            string content,
            Guid clientGuid,
            Guid createGuid)
        {
            uint status = 0;

            beforeFailover = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT to {0}", uncSharePath);

            beforeFailover.ConnectToServer(TestConfig.UnderlyingTransport, server, serverAccessIp);

            Capabilities_Values requestCapabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES;

            status = beforeFailover.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                capabilityValue: requestCapabilities,
                clientGuid: clientGuid,
                checker: (header, response) =>
            {
                TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response);
            });
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "Negotiate failed with {0}.", Smb2Status.GetStatusCode(status));
                return(false);
            }

            status = beforeFailover.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                server,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "SessionSetup failed with {0}.", Smb2Status.GetStatusCode(status));
                return(false);
            }

            uint treeId = 0;
            Share_Capabilities_Values shareCapabilities = Share_Capabilities_Values.NONE;

            status = DoUntilSucceed(
                () => beforeFailover.TreeConnect(uncSharePath, out treeId, (header, response) =>
            {
                shareCapabilities = response.Capabilities;
            }),
                TestConfig.FailoverTimeout,
                "Retry TreeConnect until succeed within timeout span");

            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "TreeConnect failed with {0}.", Smb2Status.GetStatusCode(status));
                return(false);
            }

            BaseTestSite.Assert.IsTrue(shareCapabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY),
                                       "CA Share should have SHARE_CAP_CONTINUOUS_AVAILABILITY bit set for Capabilities in TreeConnect response.");

            if (fsType == FileServerType.ScaleOutFileServer)
            {
                BaseTestSite.Assert.IsTrue(shareCapabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_SCALEOUT),
                                           "ScaleOut FS should have SHARE_CAP_SCALEOUT bit set for Capabilities in TreeConnect response.");
            }

            FILEID fileId;

            Smb2CreateContextResponse[] serverCreateContexts;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request with SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 with PERSISTENT flag set.");
            status = beforeFailover.Create(
                treeId,
                file,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleRequestV2
                {
                    CreateGuid = createGuid,
                    Flags      = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT,
                    Timeout    = 3600000,
                },
            });
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "Create failed with {0}.", Smb2Status.GetStatusCode(status));
                return(false);
            }

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends WRITE request to write content to the file.");
            status = beforeFailover.Write(treeId, fileId, content);
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "Write content failed with {0}.", Smb2Status.GetStatusCode(status));
                return(false);
            }

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends FLUSH request.");
            status = beforeFailover.Flush(treeId, fileId);
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "Flush failed with {0}.", Smb2Status.GetStatusCode(status));
                return(false);
            }

            return(true);
        }
        /// <summary>
        /// Write content before failover
        /// </summary>
        /// <param name="fsType">FileServerType</param>
        /// <param name="server">File Server name.</param>
        /// <param name="serverAccessIp">File Server Access IP.</param>
        /// <param name="uncSharePath">The share path to write the file.</param>
        /// <param name="file">The file name for writing content.</param>
        /// <param name="content">The content to write.</param>
        /// <param name="clientGuid">Smb2 client Guid.</param>
        /// <param name="createGuid">The Guid for smb2 create request.</param>
        /// <returns></returns>
        protected bool WriteContentBeforeFailover(
            FileServerType fsType,
            string server,
            IPAddress serverAccessIp,
            string uncSharePath,
            string file,
            string content,
            Guid clientGuid,
            Guid createGuid)
        {
            uint status = 0;
            beforeFailover = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT to {0}", uncSharePath);

            beforeFailover.ConnectToServer(TestConfig.UnderlyingTransport, server, serverAccessIp);

            Capabilities_Values requestCapabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES;
            status = beforeFailover.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                capabilityValue: requestCapabilities,
                clientGuid: clientGuid,
                checker: (header, response) =>
                {
                    TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response);
                });
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "Negotiate failed with {0}.", Smb2Status.GetStatusCode(status));
                return false;
            }

            status = beforeFailover.SessionSetup(
                    TestConfig.DefaultSecurityPackage,
                    server,
                    TestConfig.AccountCredential,
                    TestConfig.UseServerGssToken);
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "SessionSetup failed with {0}.", Smb2Status.GetStatusCode(status));
                return false;
            }

            uint treeId = 0;
            Share_Capabilities_Values shareCapabilities = Share_Capabilities_Values.NONE;
            status = DoUntilSucceed(
                () => beforeFailover.TreeConnect(uncSharePath, out treeId, (header, response) =>
                {
                    shareCapabilities = response.Capabilities;
                }),
                TestConfig.FailoverTimeout,
                "Retry TreeConnect until succeed within timeout span");

            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "TreeConnect failed with {0}.", Smb2Status.GetStatusCode(status));
                return false;
            }

            BaseTestSite.Assert.IsTrue(shareCapabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY),
                "CA Share should have SHARE_CAP_CONTINUOUS_AVAILABILITY bit set for Capabilities in TreeConnect response.");

            if (fsType == FileServerType.ScaleOutFileServer)
            {
                BaseTestSite.Assert.IsTrue(shareCapabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_SCALEOUT),
                    "ScaleOut FS should have SHARE_CAP_SCALEOUT bit set for Capabilities in TreeConnect response.");
            }

            FILEID fileId;
            Smb2CreateContextResponse[] serverCreateContexts;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request with SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 with PERSISTENT flag set.");
            status = beforeFailover.Create(
                treeId,
                file,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                new Smb2CreateContextRequest[] {
                    new Smb2CreateDurableHandleRequestV2
                    {
                         CreateGuid = createGuid,
                         Flags = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT,
                         Timeout = 3600000,
                    },
                });
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "Create failed with {0}.", Smb2Status.GetStatusCode(status));
                return false;
            }

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends WRITE request to write content to the file.");
            status = beforeFailover.Write(treeId, fileId, content);
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "Write content failed with {0}.", Smb2Status.GetStatusCode(status));
                return false;
            }

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends FLUSH request.");
            status = beforeFailover.Flush(treeId, fileId);
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "Flush failed with {0}.", Smb2Status.GetStatusCode(status));
                return false;
            }

            return true;
        }
        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);

            // The destination file of CopyOffload Write should be equal to or larger than the size of original file
            client.Write(treeId, fileIdDest, Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb));
            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();
        }
예제 #5
0
        public void BVT_ResilientHandle_LockSequence()
        {
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb21);
            TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_LMR_REQUEST_RESILIENCY);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT);
            #endregion

            Guid clientGuid = Guid.NewGuid();

            #region clientBeforeDisconnection Create a File
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start the first client to create a file by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE.");
            clientBeforeDisconnection.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, clientGuid: clientGuid);
            clientBeforeDisconnection.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false);
            uint treeId;
            clientBeforeDisconnection.TreeConnect(sharePath, out treeId);
            FILEID fileId;
            Smb2CreateContextResponse[] createContextResponse;
            clientBeforeDisconnection.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponse);
            #endregion

            #region Request Resilient Handle
            IOCTL_Response IOCTLResponse;
            byte[]         inputInResponse;
            byte[]         outputInResponse;
            Packet_Header  packetHeader;
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "The first client sends an IOCTL FSCTL_LMR_REQUEST_RESILLIENCY request.");
            clientBeforeDisconnection.ResiliencyRequest(treeId, fileId, TestConfig.MaxResiliencyTimeoutInSecond * 1000,
                                                        NETWORK_RESILIENCY_REQUEST_SIZE, out packetHeader, out IOCTLResponse, out inputInResponse, out outputInResponse);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The first client sends WRITE request.");
            clientBeforeDisconnection.Write(treeId, fileId, "12345678");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The first client sends Flush request.");
            clientBeforeDisconnection.Flush(treeId, fileId);
            #endregion

            //The LockSequence field of the SMB2 lock request MUST be set to (BucketNumber<< 4) + BucketSequence.
            int  bucketNum    = 1;
            int  bucketSeq    = 1;
            uint lockSequence = (uint)bucketNum << 4 + bucketSeq;

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "The first client sends LOCK request with LockSequence set to (BucketNumber<< 4) + BucketSequence");
            clientBeforeDisconnection.Lock(treeId,
                                           lockSequence,
                                           fileId,
                                           new LOCK_ELEMENT[]
            {
                new LOCK_ELEMENT
                {
                    Flags  = LOCK_ELEMENT_Flags_Values.LOCKFLAG_EXCLUSIVE_LOCK | LOCK_ELEMENT_Flags_Values.LOCKFLAG_FAIL_IMMEDIATELY,
                    Offset = 0,
                    Length = 4
                }
            });

            clientBeforeDisconnection.Disconnect();

            #region clientAfterDisconnection Opens the Previously Created File
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start the second client to reconnect to the file created by the first client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE (with SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context).");
            clientAfterDisconnection.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, clientGuid: clientGuid);
            clientAfterDisconnection.ReconnectSessionSetup(clientBeforeDisconnection,
                                                           TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false);
            clientAfterDisconnection.TreeConnect(sharePath, out treeId);
            clientAfterDisconnection.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponse, RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH,
                                            new Smb2CreateContextRequest[]
            {
                new Smb2CreateDurableHandleReconnect
                {
                    Data = fileId
                }
            });
            #endregion

            //If the sequence numbers are equal, the server MUST complete the lock/unlock request with success.
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The second client sends LOCK request with the same LockSequence with the first client.");
            clientAfterDisconnection.Lock(treeId,
                                          lockSequence, //Using same Lock Sequence
                                          fileId,
                                          new LOCK_ELEMENT[]
            {
                new LOCK_ELEMENT
                {
                    Flags  = LOCK_ELEMENT_Flags_Values.LOCKFLAG_EXCLUSIVE_LOCK | LOCK_ELEMENT_Flags_Values.LOCKFLAG_FAIL_IMMEDIATELY,
                    Offset = 0,
                    Length = 4
                }
            });

            clientAfterDisconnection.Lock(treeId,
                                          lockSequence + 1, //Using different Lock Sequence
                                          fileId,
                                          new LOCK_ELEMENT[]
            {
                new LOCK_ELEMENT
                {
                    Flags  = LOCK_ELEMENT_Flags_Values.LOCKFLAG_EXCLUSIVE_LOCK | LOCK_ELEMENT_Flags_Values.LOCKFLAG_FAIL_IMMEDIATELY,
                    Offset = 0,
                    Length = 4
                }
            },
                                          (header, response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_LOCK_NOT_GRANTED,
                    header.Status,
                    "If the range being locked is already locked by another open in a way that does not allow this open to take a lock on the range, " +
                    "and if SMB2_LOCKFLAG_FAIL_IMMEDIATELY is set, the server MUST fail the request with STATUS_LOCK_NOT_GRANTED. " +
                    "Actually server returns {0}.",
                    Smb2Status.GetStatusCode(header.Status));
            });

            #region Tear Down Client
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the second client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            clientAfterDisconnection.Close(treeId, fileId);
            clientAfterDisconnection.TreeDisconnect(treeId);
            clientAfterDisconnection.LogOff();
            #endregion
        }