Esempio n. 1
0
        public void Smb2OverRdma_Smb300_Write_SMB2_CHANNEL_RDMA_V1_INVALIDATE()
        {
            EstablishConnectionAndOpenFile(fileName, Smb300OnlyDialects);

            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_INVALID_PARAMETER,
                status,
                "SMB2 WRITE over RDMA should fail with STATUS_INVALID_PARAMETER if set Channel CHANNEL_RDMA_V1_INVALIDATE on SMB 3.0 dialect.");
        }
Esempio n. 2
0
        private bool CheckSMBDReadWrite(DialectRevision[] dialects, Channel_Values channel)
        {
            try
            {
                using (var client = new SMBDClient(DetectionInfo.ConnectionTimeout))
                {
                    var config = DetectionInfo.SMBDClientCapability;

                    RdmaAdapterInfo rdmaAdapterInfo;

                    client.ConnectOverRDMA(DetectionInfo.DriverRdmaNICIPAddress, DetectionInfo.SUTRdmaNICIPAddress, DetectionInfo.SMBDPort, config.MaxReceiveSize, out rdmaAdapterInfo);

                    client.SMBDNegotiate(
                        config.CreditsRequested,
                        config.ReceiveCreditMax,
                        config.PreferredSendSize,
                        config.MaxReceiveSize,
                        config.MaxFragmentedSize
                        );

                    client.Smb2Negotiate(dialects);

                    client.Smb2SessionSetup(DetectionInfo.Authentication, DetectionInfo.DomainName, DetectionInfo.SUTName, DetectionInfo.UserName, DetectionInfo.Password);

                    string path = Smb2Utility.GetUncPath(DetectionInfo.SUTName, DetectionInfo.ShareFolder);

                    uint treeId;

                    client.Smb2TreeConnect(path, out treeId);

                    FILEID fileId;

                    client.CreateRandomFile(treeId, out fileId);

                    uint length = client.CalculateSMBDMaxReadWriteSize();

                    var buffer = Smb2Utility.CreateRandomByteArray((int)length);

                    client.SMBDWrite(treeId, fileId, channel, buffer, 0, DetectionInfo.Endian);

                    var readBuffer = new byte[length];

                    client.SMBDRead(treeId, fileId, channel, out readBuffer, 0, length, DetectionInfo.Endian);

                    if (!Enumerable.SequenceEqual(buffer, readBuffer))
                    {
                        throw new InvalidOperationException("The data is inconsistent for write and read!");
                    }

                    return(true);
                }
            }
            catch (Exception ex)
            {
                DetectorUtil.WriteLog(String.Format("CheckSMBDReadWrite threw exception: {0}", ex));
                return(false);
            }
        }
Esempio n. 3
0
        public void Smb2OverRdma_Smb300_Read_SMB2_CHANNEL_RDMA_V1_INVALIDATE()
        {
            EstablishConnectionAndOpenFile(fileName, Smb300OnlyDialects);

            uint fileSize = smbdAdapter.Smb2MaxReadSize;

            byte[] fileContent = Smb2Utility.CreateRandomByteArray((int)fileSize);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Register memory and get buffer descriptor for SMB2 WRITE");
            SmbdBufferDescriptorV1 descp;
            NtStatus status = smbdAdapter.SmbdRegisterBuffer(
                fileSize,
                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, "Register memory and get buffer descriptor for SMB2 READ.");
            smbdAdapter.SmbdRegisterBuffer(
                fileSize,
                SmbdBufferReadWrite.RDMA_WRITE_PERMISSION_FOR_READ_FILE,
                out descp);
            byte[] channelInfo = TypeMarshal.ToBytes <SmbdBufferDescriptorV1>(descp);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Read content from file over RDMA.");
            READ_Response readResponse;

            byte[] readData;
            status = (NtStatus)smbdAdapter.Smb2ReadOverRdmaChannel(
                0,
                (uint)fileSize,
                channelInfo,
                out readResponse,
                out readData,
                Channel_Values.CHANNEL_RDMA_V1_INVALIDATE);

            BaseTestSite.Assert.AreEqual <NtStatus>(
                NtStatus.STATUS_INVALID_PARAMETER,
                status,
                "SMB2 READ over RDMA should fail with STATUS_INVALID_PARAMETER if set Channel CHANNEL_RDMA_V1_INVALIDATE on SMB 3.0 dialect.");
        }
Esempio n. 4
0
        public bool ConnectToShare(string serverIp, string clientIp)
        {
            try
            {
                using (var client = new SMBDClient(DetectionInfo.ConnectionTimeout))
                {
                    client.Connect(IPAddress.Parse(serverIp), IPAddress.Parse(clientIp));

                    client.Smb2Negotiate(DetectionInfo.SupportedSmbDialects);

                    client.Smb2SessionSetup(DetectionInfo.Authentication, DetectionInfo.DomainName, DetectionInfo.SUTName, DetectionInfo.UserName, DetectionInfo.Password);

                    string path = Smb2Utility.GetUncPath(DetectionInfo.SUTName, DetectionInfo.ShareFolder);

                    uint treeId;

                    client.Smb2TreeConnect(path, out treeId);

                    FILEID fileId;

                    client.CreateRandomFile(treeId, out fileId);

                    uint fileLength = client.CalculateSmb2MaxReadWriteSize();

                    var buffer = Smb2Utility.CreateRandomByteArray((int)fileLength);

                    client.Smb2Write(treeId, fileId, 0, buffer);

                    byte[] output;

                    client.Smb2Read(treeId, fileId, 0, fileLength, out output);

                    bool result = Enumerable.SequenceEqual(buffer, output);

                    if (!result)
                    {
                        DetectorUtil.WriteLog("The content of read and write is inconsistent.");
                    }

                    return(result);
                }
            }
            catch (Exception ex)
            {
                DetectorUtil.WriteLog(String.Format("ConnectToShare threw exception: {0}", ex));
                return(false);
            }
        }
Esempio n. 5
0
        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.");
        }
Esempio n. 6
0
        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);
        }
        private Smb2WriteRequestPacket ConstructRelatedWritePacket()
        {
            var writePacket = new Smb2WriteRequestPacket();

            writePacket.Header.Command = Smb2Command.WRITE;
            // For any subsequent requests the client MUST set SMB2_FLAGS_RELATED_OPERATIONS in the Flags field of the SMB2 header to indicate that
            // it is using the SessionId, TreeId, and FileId supplied in the previous request (or generated by the server in processing that request).
            // The client SHOULD<93> set SessionId to 0xFFFFFFFFFFFFFFFF and TreeId to 0xFFFFFFFF,
            // and SHOULD<94> set FileId to { 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF }.
            writePacket.Header.Flags     = Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS;
            writePacket.Header.SessionId = 0xFFFFFFFFFFFFFFFF;
            writePacket.Header.TreeId    = 0xFFFFFFFF;
            byte[] content = Smb2Utility.CreateRandomByteArray(1); // Write 1 byte to the file.
            writePacket.PayLoad.Length     = (uint)content.Length;
            writePacket.PayLoad.Offset     = 0;
            writePacket.PayLoad.FileId     = FILEID.Invalid;
            writePacket.PayLoad.DataOffset = (ushort)writePacket.BufferOffset;
            writePacket.Buffer             = content;
            return(writePacket);
        }
Esempio n. 8
0
        private Smb2WriteRequestPacket ConstructRelatedWritePacket(ulong sessionId, uint treeId)
        {
            var writePacket = new Smb2WriteRequestPacket();

            writePacket.Header.Command = Smb2Command.WRITE;
            // The client MUST construct the subsequent request as it would do normally.
            // For any subsequent requests the client MUST set SMB2_FLAGS_RELATED_OPERATIONS in the Flags field of the SMB2 header to indicate that it is using the SessionId,
            // TreeId, and FileId supplied in the previous request(or generated by the server in processing that request).
            // For an operation compounded with an SMB2 CREATE request, the FileId field SHOULD be set to { 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF }.
            writePacket.Header.Flags     = Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS;
            writePacket.Header.SessionId = sessionId;
            writePacket.Header.TreeId    = treeId;
            byte[] content = Smb2Utility.CreateRandomByteArray(1); // Write 1 byte to the file.
            writePacket.PayLoad.Length     = (uint)content.Length;
            writePacket.PayLoad.Offset     = 0;
            writePacket.PayLoad.FileId     = FILEID.Invalid;
            writePacket.PayLoad.DataOffset = (ushort)writePacket.BufferOffset;
            writePacket.Buffer             = content;
            return(writePacket);
        }
Esempio n. 9
0
        public void BVT_ChangeTracking()
        {
            // The log file used in change tracking request must be an existing file.
            // So create one file before running the case.
            string logFileName = string.Format("log_{0}.txt", System.Guid.NewGuid());

            sutProtocolController.CreateFile(TestConfig.FullPathShareContainingSharedVHD, logFileName, "");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "1.	Client opens a shared virtual disk file and expects success.");
            OpenSharedVHD(TestConfig.NameOfSharedVHDS, RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_2);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "2.	Client sends the tunnel operation SVHDX_CHANGE_TRACKING_START_REQUEST to start change tracking.");
            SVHDX_CHANGE_TRACKING_START_REQUEST request = new SVHDX_CHANGE_TRACKING_START_REQUEST();

            request.TransactionId     = System.Guid.NewGuid();
            request.LogFileId         = System.Guid.NewGuid();
            request.LogFileNameOffset = 56;
            request.LogFileName       = logFileName;
            request.LogFileNameLength = (uint)(request.LogFileName.Length + 1) * 2;
            byte[] payload = client.CreateChangeTrackingStartRequest(request);
            SVHDX_TUNNEL_OPERATION_HEADER?header;
            SVHDX_TUNNEL_OPERATION_HEADER?response;
            //For RSVD_TUNNEL_META_OPERATION_START operation code, the IOCTL code should be FSCTL_SVHDX_ASYNC_TUNNEL_REQUEST
            uint status = client.TunnelOperation <SVHDX_TUNNEL_OPERATION_HEADER>(
                false,//true for Async operation, false for non-async operation
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_CHANGE_TRACKING_START,
                ++RequestIdentifier,
                payload,
                out header,
                out response);

            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Ioctl should succeed, actual status: {0}",
                GetStatus(status));
            VerifyTunnelOperationHeader(header.Value, RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_CHANGE_TRACKING_START, (uint)RsvdStatus.STATUS_SVHDX_SUCCESS, RequestIdentifier);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "3.	Client sends Write request to change the vhds file.");
            payload = Smb2Utility.CreateRandomByteArray(512);
            status  = client.Write(0, payload);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "4.	Client sends the tunnel operation RSVD_TUNNEL_CHANGE_TRACKING_GET_PARAMETERS to get the change tracking status.");
            SVHDX_CHANGE_TRACKING_GET_PARAMETERS_RESPONSE?getParamResponse;

            status = client.TunnelOperation <SVHDX_CHANGE_TRACKING_GET_PARAMETERS_RESPONSE>(
                false,//true for Async operation, false for non-async operation
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_CHANGE_TRACKING_GET_PARAMETERS,
                ++RequestIdentifier,
                null,
                out header,
                out getParamResponse);

            VerifyTunnelOperationHeader(header.Value, RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_CHANGE_TRACKING_GET_PARAMETERS, (uint)RsvdStatus.STATUS_SVHDX_SUCCESS, RequestIdentifier);
            BaseTestSite.Assert.AreEqual(
                RsvdStatus.STATUS_SVHDX_SUCCESS,
                (RsvdStatus)getParamResponse.Value.ChangeTrackingStatus,
                "Status of change tracking should be STATUS_SVHDX_SUCCESS.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "5.	Client sends the tunnel operation SVHDX_CHANGE_TRACKING_STOP_REQUEST to stop change tracking.");
            status = client.TunnelOperation <SVHDX_TUNNEL_OPERATION_HEADER>(
                false,//true for Async operation, false for non-async operation
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_CHANGE_TRACKING_STOP,
                ++RequestIdentifier,
                null,
                out header,
                out response);
            VerifyTunnelOperationHeader(header.Value, RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_CHANGE_TRACKING_STOP, (uint)RsvdStatus.STATUS_SVHDX_SUCCESS, RequestIdentifier);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "6.	Client closes the file.");
            client.CloseSharedVirtualDisk();
        }
Esempio n. 10
0
        public void Smb2OverRdma_Read_SMB2_CHANNEL_RDMA_V1()
        {
            EstablishConnectionAndOpenFile(fileName);

            uint fileSize = smbdAdapter.Smb2MaxReadSize;

            byte[] fileContent = Smb2Utility.CreateRandomByteArray((int)fileSize);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Register memory and get buffer descriptor for SMB2 WRITE");
            SmbdBufferDescriptorV1 descp;
            NtStatus status = smbdAdapter.SmbdRegisterBuffer(
                fileSize,
                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, "Register memory and get buffer descriptor for SMB2 READ.");
            status = smbdAdapter.SmbdRegisterBuffer(
                fileSize,
                SmbdBufferReadWrite.RDMA_WRITE_PERMISSION_FOR_READ_FILE,
                out descp);
            BaseTestSite.Assert.AreEqual(
                NtStatus.STATUS_SUCCESS,
                status,
                "Register buffer should succeed.");

            byte[] channelInfo = TypeMarshal.ToBytes <SmbdBufferDescriptorV1>(descp);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Read content from file over RDMA.");
            READ_Response readResponse;

            byte[] readData;
            status = (NtStatus)smbdAdapter.Smb2ReadOverRdmaChannel(
                0,
                (uint)fileSize,
                channelInfo,
                out readResponse,
                out readData,
                Channel_Values.CHANNEL_RDMA_V1);

            BaseTestSite.Assert.AreEqual <NtStatus>(
                NtStatus.STATUS_SUCCESS,
                status,
                "SMB2 READ over RDMA should succeed.");

            byte[] readContent = new byte[fileSize];
            smbdAdapter.SmbdReadRegisteredBuffer(readContent, descp);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify the read content same as the original one on server.");
            BaseTestSite.Assert.IsTrue(
                SmbdUtilities.CompareByteArray(fileContent, readContent),
                "Content read should be identical with original on server.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send SMB2 READ using same descriptor.");
            status = (NtStatus)smbdAdapter.Smb2ReadOverRdmaChannel(
                0,
                (uint)fileSize,
                channelInfo,
                out readResponse,
                out readData,
                Channel_Values.CHANNEL_RDMA_V1);

            BaseTestSite.Assert.AreEqual <NtStatus>(
                NtStatus.STATUS_SUCCESS,
                status,
                "SMB2 READ over RDMA should succeed.");

            smbdAdapter.SmbdReadRegisteredBuffer(readContent, descp);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify the read content same as the original one on server.");
            BaseTestSite.Assert.IsTrue(
                SmbdUtilities.CompareByteArray(fileContent, readContent),
                "Content read should be identical with original on server.");
        }
Esempio n. 11
0
        public void BVT_Smb2OverRdma_Smb302_Read_SMB2_CHANNEL_RDMA_V1_INVALIDATE()
        {
            EstablishConnectionAndOpenFile(fileName, Smb302AboveDialects);

            uint fileSize = smbdAdapter.Smb2MaxReadSize;

            byte[] fileContent = Smb2Utility.CreateRandomByteArray((int)fileSize);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Register memory and get buffer descriptor for SMB2 WRITE");
            SmbdBufferDescriptorV1 descp;
            NtStatus status = smbdAdapter.SmbdRegisterBuffer(
                fileSize,
                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, "Register memory and get buffer descriptor for SMB2 READ.");
            status = smbdAdapter.SmbdRegisterBuffer(
                fileSize,
                SmbdBufferReadWrite.RDMA_WRITE_PERMISSION_FOR_READ_FILE,
                out descp);
            BaseTestSite.Assert.AreEqual(
                NtStatus.STATUS_SUCCESS,
                status,
                "Register buffer should succeed.");
            byte[] channelInfo = TypeMarshal.ToBytes <SmbdBufferDescriptorV1>(descp);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Read content from file over RDMA.");
            READ_Response readResponse;

            byte[] readData;
            status = (NtStatus)smbdAdapter.Smb2ReadOverRdmaChannel(
                0,
                (uint)fileSize,
                channelInfo,
                out readResponse,
                out readData,
                Channel_Values.CHANNEL_RDMA_V1_INVALIDATE);

            BaseTestSite.Assert.AreEqual <NtStatus>(
                NtStatus.STATUS_SUCCESS,
                status,
                "SMB2 READ over RDMA should succeed.");

            byte[] readContent = new byte[fileSize];
            smbdAdapter.SmbdReadRegisteredBuffer(readContent, descp);

            BaseTestSite.Assert.IsTrue(
                SmbdUtilities.CompareByteArray(fileContent, readContent),
                "Content read should be identical with original on server.");

            try
            {
                status = (NtStatus)smbdAdapter.Smb2ReadOverRdmaChannel(
                    0,
                    (uint)fileSize,
                    channelInfo,
                    out readResponse,
                    out readData,
                    Channel_Values.CHANNEL_RDMA_V1_INVALIDATE);
            }
            catch
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Wait for connection to be 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 BVT_QueryVirtualDiskChanges()
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "1.	Client opens a shared virtual disk file and expects success.");
            OpenSharedVHD(TestConfig.NameOfSharedVHDS, RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_2);

            Guid snapshotId = Guid.NewGuid();

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "2.	Client sends the first tunnel operation SVHDX_META_OPERATION_START_REQUEST to create a snapshot.");
            CreateSnapshot(snapshotId);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "3.	Client closes the open.");
            client.CloseSharedVirtualDisk();

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "4.	Client reopens the shared virtual disk file and expects success.");

            RequestIdentifier = 0;
            OpenSharedVHD(TestConfig.NameOfSharedVHDS, RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_2);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "5.	Client sends Write request and expects success.");
            byte[] payload = Smb2Utility.CreateRandomByteArray(512);
            uint   status  = client.Write(0, payload);

            BaseTestSite.Assert.AreEqual(
                (uint)0,
                status,
                "Write Status should be {0}, actual is {1}", GetStatus(0), GetStatus(status));

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "6.	Client creates another snapshot.");
            Guid snapshotId2 = Guid.NewGuid();

            CreateSnapshot(snapshotId2);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "7.	Client sends the tunnel operation SVHDX_TUNNEL_QUERY_VIRTUAL_DISK_CHANGES_REQUEST to query the changes since the first snapshot.");

            SVHDX_TUNNEL_QUERY_VIRTUAL_DISK_CHANGES_REQUEST queryRequest = new SVHDX_TUNNEL_QUERY_VIRTUAL_DISK_CHANGES_REQUEST();

            queryRequest.TargetSnapshotId = snapshotId2;
            queryRequest.LimitSnapshotId  = snapshotId;
            queryRequest.SnapshotType     = Snapshot_Type.SvhdxSnapshotTypeVM;
            queryRequest.ByteOffset       = 0;
            queryRequest.ByteLength       = 1024;

            SVHDX_TUNNEL_OPERATION_HEADER?header;
            SVHDX_TUNNEL_QUERY_VIRTUAL_DISK_CHANGES_REPLY?response;

            //For RSVD_TUNNEL_META_OPERATION_START operation code, the IOCTL code should be FSCTL_SVHDX_ASYNC_TUNNEL_REQUEST
            status = client.TunnelOperation <SVHDX_TUNNEL_QUERY_VIRTUAL_DISK_CHANGES_REPLY>(
                false,//true for Async operation, false for non-async operation
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_QUERY_VIRTUAL_DISK_CHANGES,
                ++RequestIdentifier,
                client.CreateQueryVirtualDiskChangeRequest(queryRequest),
                out header,
                out response);
            VerifyTunnelOperationHeader(header.Value, RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_QUERY_VIRTUAL_DISK_CHANGES, (uint)RsvdStatus.STATUS_SVHDX_SUCCESS, RequestIdentifier);

            BaseTestSite.Assert.AreEqual((uint)1, response.Value.RangeCount, "RangeCount should be 1");
            BaseTestSite.Assert.AreEqual((ulong)0, response.Value.Ranges[0].ByteOffset, "ByteOffset should be 0");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "8.	Client deletes the two snapshots.");

            DeleteSnapshot(snapshotId);
            DeleteSnapshot(snapshotId2);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "9.	Client closes the file.");
            client.CloseSharedVirtualDisk();
        }
        public void BVT_ApplySnapshot()
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "1.	Client opens a shared virtual disk file and expects success.");
            OpenSharedVHD(TestConfig.NameOfSharedVHDS, RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_2);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "2. Client reads 512 bytes and saves it for later comparation.");
            byte[] byteBeforeChanged = null;
            uint   status            = client.Read(0, 512, out byteBeforeChanged);

            BaseTestSite.Assert.AreEqual(
                (uint)0,
                status,
                "Read Status should be {0}, actual is {1}", GetStatus(0), GetStatus(status));

            Guid snapshotId = Guid.NewGuid();

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "3.	Client creates a snapshot.");
            CreateSnapshot(snapshotId);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "4.	Client closes the file.");
            client.CloseSharedVirtualDisk();

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "5.	Client reopens the shared virtual disk file and expects success.");

            RequestIdentifier = 0;
            OpenSharedVHD(TestConfig.NameOfSharedVHDS, RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_2);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "6.	Client sends Write request to change the file and expects success.");
            byte[] payload = Smb2Utility.CreateRandomByteArray(512);
            status = client.Write(0, payload);
            BaseTestSite.Assert.AreEqual(
                (uint)0,
                status,
                "Write Status should be {0}, actual is {1}", GetStatus(0), GetStatus(status));

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "7.	Client sends Apply Snapshot request to apply the previous snapshot.");

            SVHDX_APPLY_SNAPSHOT_PARAMS applySnapshot = new SVHDX_APPLY_SNAPSHOT_PARAMS();

            applySnapshot.SnapshotID   = snapshotId;
            applySnapshot.SnapshotType = Snapshot_Type.SvhdxSnapshotTypeVM;
            SVHDX_META_OPERATION_START_REQUEST startRequest = new SVHDX_META_OPERATION_START_REQUEST();

            startRequest.TransactionId = Guid.NewGuid();
            startRequest.OperationType = Operation_Type.SvhdxMetaOperationTypeApplySnapshot;
            payload = client.CreateTunnelMetaOperationStartApplySnapshotRequest(startRequest, applySnapshot);
            SVHDX_TUNNEL_OPERATION_HEADER?header;
            SVHDX_TUNNEL_OPERATION_HEADER?response;

            status = client.TunnelOperation <SVHDX_TUNNEL_OPERATION_HEADER>(
                true,            //true for Async operation, false for non-async operation
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_META_OPERATION_START,
                ++RequestIdentifier,
                payload,
                out header,
                out response);
            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Ioctl should succeed, actual status: {0}",
                GetStatus(status));
            VerifyTunnelOperationHeader(header.Value, RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_META_OPERATION_START, (uint)RsvdStatus.STATUS_SVHDX_SUCCESS, RequestIdentifier);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "8.	Client rereads 512 bytes and compares it with the previously saved bytes.");
            byte[] byteAfterApplied = null;
            status = client.Read(0, 512, out byteAfterApplied);
            BaseTestSite.Assert.AreEqual(
                (uint)0,
                status,
                "Read Status should be {0}, actual is {1}", GetStatus(0), GetStatus(status));

            bool equal = ArrayUtility.CompareArrays(byteBeforeChanged, byteAfterApplied);

            BaseTestSite.Assert.AreEqual(
                true,
                equal,
                "The bytes after snapshot applied should be the same with the original.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "9.	Client deletes the snapshot.");
            DeleteSnapshot(snapshotId);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "10. Client closes the file.");
            client.CloseSharedVirtualDisk();
        }