Add GS Mock Mode feasibility analysis
This commit is contained in:
@@ -0,0 +1,520 @@
|
||||
# GS Mock Mode 模擬模式分析
|
||||
|
||||
## 概述
|
||||
|
||||
為 GS (DtrGuiSrv) 新增 Mock 模擬模式,無需 RAID Driver 即可運行,用於:
|
||||
- 開發測試
|
||||
- CI/CD 自動化測試
|
||||
- 離線 Demo
|
||||
- 功能驗證
|
||||
|
||||
## 需要模擬的關鍵函數
|
||||
|
||||
### 1. Driver I/O 層
|
||||
|
||||
| 函數 | 用途 | 模擬難度 |
|
||||
|------|------|----------|
|
||||
| `DevIoControl()` | I/O Control 與 Driver 通訊 | 高 |
|
||||
| `QuaryDTR()` | 查詢 RAID 控制器資訊 | 中 |
|
||||
| `GetCtlrEvent()` | 取得控制器事件 | 中 |
|
||||
|
||||
### 2. 共享記憶體層
|
||||
|
||||
| 函數 | 用途 | 模擬難度 |
|
||||
|------|------|----------|
|
||||
| `InitialSHMForAllCtlr()` | 初始化共享記憶體 | 高 |
|
||||
| 相關 SHM 函數 | 共享記憶體操作 | 高 |
|
||||
|
||||
## 模擬模式架構
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ GS Mock Mode 架構 │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ GS (DtrGuiSrv) │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Mock Mode 開關 │ │ │
|
||||
│ │ │ #define ENABLE_MOCK_MODE │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ┌──────────────────┼──────────────────┐ │ │
|
||||
│ │ ▼ ▼ ▼ │ │
|
||||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
|
||||
│ │ │ Real Driver │ │ Mock Driver │ │ Mock Data │ │ │
|
||||
│ │ │ (Production)│ │ (Dev/Mock) │ │ (Static) │ │ │
|
||||
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 實現方案
|
||||
|
||||
### 方案 1: 編譯時開關 (推薦)
|
||||
|
||||
```c
|
||||
// hInclude.h
|
||||
#ifdef ENABLE_MOCK_MODE
|
||||
#include "mock_driver.h"
|
||||
#define DevIoControl mock_DevIoControl
|
||||
#define QuaryDTR mock_QuaryDTR
|
||||
#define GetCtlrEvent mock_GetCtlrEvent
|
||||
#endif
|
||||
```
|
||||
|
||||
### 方案 2: 執行時開關
|
||||
|
||||
```c
|
||||
// runtime_config.h
|
||||
extern BOOL g_bMockMode;
|
||||
|
||||
// 初始化時檢查
|
||||
if (g_bMockMode) {
|
||||
initMockDriver();
|
||||
} else {
|
||||
initRealDriver();
|
||||
}
|
||||
```
|
||||
|
||||
### 方案 3: 環境變數
|
||||
|
||||
```bash
|
||||
# 啟動時設定
|
||||
export DTR_GUI_MOCK_MODE=1
|
||||
./DtrGuiSrv01
|
||||
```
|
||||
|
||||
## 需要實現的 Mock 函數
|
||||
|
||||
### 1. mock_driver.h
|
||||
|
||||
```c
|
||||
#ifndef MOCK_DRIVER_H
|
||||
#define MOCK_DRIVER_H
|
||||
|
||||
#include "hInclude.h"
|
||||
|
||||
// Mock 初始化
|
||||
void mock_init(void);
|
||||
void mock_cleanup(void);
|
||||
|
||||
// Mock 控制器數據
|
||||
typedef struct {
|
||||
UCHAR bStatus;
|
||||
UCHAR bCtlrSN[16];
|
||||
UCHAR bModelName[32];
|
||||
UCHAR bPage0Data[1024]; // Controller Info Page
|
||||
UCHAR bPage1Data[1024]; // RAID Snapshot
|
||||
// ...
|
||||
} MOCK_CTRL_INFO;
|
||||
|
||||
// Mock DevIoControl
|
||||
UCHAR mock_DevIoControl(
|
||||
UCHAR bDevNo,
|
||||
ULONG lControlCode,
|
||||
ULONG lInSize,
|
||||
PCHAR pInBuf,
|
||||
ULONG lOutSize,
|
||||
PCHAR pOutBuf,
|
||||
USHORT *pusInBandErrCode
|
||||
);
|
||||
|
||||
// Mock QuaryDTR
|
||||
CHAR mock_QuaryDTR(
|
||||
UCHAR ucCtlrIndex,
|
||||
UCHAR *bPageBuf,
|
||||
UCHAR *pbHeatsink
|
||||
);
|
||||
|
||||
// Mock GetCtlrEvent
|
||||
UCHAR mock_GetCtlrEvent(
|
||||
UCHAR bCtlrNo,
|
||||
PEVENT_INFO pEvent_info
|
||||
);
|
||||
|
||||
// 設定模擬事件
|
||||
void mock_set_event(UCHAR *eventData, int length);
|
||||
void mock_clear_events(void);
|
||||
|
||||
// 控制器狀態控制
|
||||
void mock_set_controller_online(BOOL online);
|
||||
void mock_set_controller_count(int count);
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
### 2. mock_driver.c
|
||||
|
||||
```c
|
||||
#include "mock_driver.h"
|
||||
|
||||
// 單例 Mock 控制器資訊
|
||||
static MOCK_CTRL_INFO g_mockCtrl[MAX_DTR_IN_HOST];
|
||||
static BOOL g_bMockInitialized = FALSE;
|
||||
|
||||
// 模擬的事件佇列
|
||||
static UCHAR g_mockEventQueue[100][512];
|
||||
static int g_mockEventCount = 0;
|
||||
|
||||
void mock_init(void) {
|
||||
if (g_bMockInitialized) return;
|
||||
|
||||
// 初始化 Mock 控制器
|
||||
memset(g_mockCtrl, 0, sizeof(g_mockCtrl));
|
||||
|
||||
// 預設控制器 1 台,狀態上線
|
||||
g_mockCtrl[0].bStatus = CTLR_STATUS_ALIVE;
|
||||
memcpy(g_mockCtrl[0].bCtlrSN, "MOCK00000001", 16);
|
||||
memcpy(g_mockCtrl[0].bModelName, "Accusys Mock RAID", 32);
|
||||
|
||||
// 填充 Page 0 資料 (Controller Info)
|
||||
fill_mock_page0(g_mockCtrl[0].bPage0Data);
|
||||
|
||||
g_bMockInitialized = TRUE;
|
||||
|
||||
printf("[MOCK] Driver initialized\n");
|
||||
}
|
||||
|
||||
UCHAR mock_DevIoControl(...) {
|
||||
if (!g_bMockInitialized) mock_init();
|
||||
|
||||
// 根據 Control Code 處理
|
||||
switch (lControlCode) {
|
||||
case IOCTL_DTR_GET_CONTROLLER_INFO:
|
||||
// 回傳控制器資訊
|
||||
break;
|
||||
|
||||
case IOCTL_DTR_GET_INBAND_EVENT:
|
||||
// 回傳模擬事件
|
||||
break;
|
||||
|
||||
case IOCTL_DTR_SET_INBAND_COMMAND:
|
||||
// 處理命令,回傳成功
|
||||
break;
|
||||
|
||||
default:
|
||||
// 預設回傳成功
|
||||
*pusInBandErrCode = 0;
|
||||
return SYSOK;
|
||||
}
|
||||
|
||||
return SYSOK;
|
||||
}
|
||||
|
||||
CHAR mock_QuaryDTR(UCHAR ucCtlrIndex, UCHAR *bPageBuf, UCHAR *pbHeatsink) {
|
||||
if (!g_bMockInitialized) mock_init();
|
||||
|
||||
if (ucCtlrIndex >= MAX_DTR_IN_HOST) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// 複製 Mock 資料
|
||||
memcpy(bPageBuf, g_mockCtrl[ucCtlrIndex].bPage0Data, 1024);
|
||||
*pbHeatsink = 0x00;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UCHAR mock_GetCtlrEvent(UCHAR bCtlrNo, PEVENT_INFO pEvent_info) {
|
||||
if (!g_bMockInitialized) mock_init();
|
||||
|
||||
// 從佇列取出事件
|
||||
if (g_mockEventCount > 0) {
|
||||
memcpy(pEvent_info->bEventBuf, g_mockEventQueue[0], 512);
|
||||
pEvent_info->bStatus = TRUE;
|
||||
|
||||
// 移除已取出的事件
|
||||
g_mockEventCount--;
|
||||
// ... 佇列搬移
|
||||
|
||||
return SYSOK;
|
||||
}
|
||||
|
||||
pEvent_info->bStatus = FALSE;
|
||||
return SYSFAIL_EVENT_EMPTY;
|
||||
}
|
||||
```
|
||||
|
||||
## 模擬的 Page 資料
|
||||
|
||||
### Page 0: Controller Info
|
||||
|
||||
```c
|
||||
void fill_mock_page0(UCHAR *buf) {
|
||||
// Offset 0-31: Serial Number
|
||||
memcpy(buf + 0, "MOCK00000001", 16);
|
||||
|
||||
// Offset 32-63: Model Name
|
||||
memcpy(buf + 32, "Accusys Mock RAID", 20);
|
||||
|
||||
// Offset 64-95: Firmware Version
|
||||
memcpy(buf + 64, "1.0.0.0", 8);
|
||||
|
||||
// 其他欄位...
|
||||
// 需要完整對應 Java GUI 解析的格式
|
||||
}
|
||||
```
|
||||
|
||||
### 需要的 Page
|
||||
|
||||
| Page | 大小 | 用途 |
|
||||
|------|------|------|
|
||||
| 0x00 | 1024 | Controller Info |
|
||||
| 0x01 | 1024 | RAID Snapshot |
|
||||
| 0x07 | 512 | LUN Map Table |
|
||||
| 0x0A-0x0E | 1024 | RAID Info |
|
||||
| 0x10-0x11 | 512 | Disk/Slice Names |
|
||||
| 0x14 | 512 | Array Info |
|
||||
| 0x1A | 512 | Enclosure Info |
|
||||
| 0x1B | 512 | Disk List |
|
||||
|
||||
## 模擬事件
|
||||
|
||||
### 預設模擬事件
|
||||
|
||||
```c
|
||||
// 初始化時註冊一些模擬事件
|
||||
void mock_register_default_events(void) {
|
||||
// 磁碟上線事件
|
||||
UCHAR diskOnlineEvent[] = {
|
||||
0x01, 0x00, 0x00, 0x00, // Event Type
|
||||
0x00, 0x00, 0x00, 0x00, // Timestamp
|
||||
0x01, 0x02, 0x00, 0x00, // Slot 1, Online
|
||||
// ...
|
||||
};
|
||||
mock_set_event(diskOnlineEvent, 32);
|
||||
|
||||
// RAID 重建完成事件
|
||||
UCHAR rebuildDoneEvent[] = {
|
||||
0x02, 0x00, 0x00, 0x00, // Event Type
|
||||
// ...
|
||||
};
|
||||
mock_set_event(rebuildDoneEvent, 32);
|
||||
}
|
||||
```
|
||||
|
||||
## 配置檔案
|
||||
|
||||
### mock_config.json
|
||||
|
||||
```json
|
||||
{
|
||||
"mock_mode": true,
|
||||
"controller_count": 2,
|
||||
"controllers": [
|
||||
{
|
||||
"serial_number": "MOCK00000001",
|
||||
"model_name": "Accusys GEN2",
|
||||
"firmware_version": "3.8.0",
|
||||
"status": "online",
|
||||
"raid_arrays": [
|
||||
{
|
||||
"id": 0,
|
||||
"level": "RAID5",
|
||||
"disks": [0, 1, 2, 3],
|
||||
"status": "Normal",
|
||||
"capacity": 10000000
|
||||
}
|
||||
],
|
||||
"disks": [
|
||||
{"slot": 0, "status": "Online", "capacity": 4000000},
|
||||
{"slot": 1, "status": "Online", "capacity": 4000000},
|
||||
{"slot": 2, "status": "Online", "capacity": 4000000},
|
||||
{"slot": 3, "status": "Online", "capacity": 4000000},
|
||||
{"slot": 4, "status": "Online", "capacity": 4000000, "spare": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"serial_number": "MOCK00000002",
|
||||
"model_name": "Accusys GEN2",
|
||||
"status": "online"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"type": "DiskOnline",
|
||||
"slot": 2,
|
||||
"timestamp": 1234567890
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 編譯選項
|
||||
|
||||
### Makefile
|
||||
|
||||
```makefile
|
||||
# 一般編譯
|
||||
build:
|
||||
gcc -o DtrGuiSrv01 *.c -lpthread -lm
|
||||
|
||||
# Mock 模式編譯
|
||||
build-mock:
|
||||
gcc -o DtrGuiSrv01_mock *.c -DENABLE_MOCK_MODE -lpthread -lm
|
||||
|
||||
# 兩者區別
|
||||
ifdef ENABLE_MOCK_MODE
|
||||
CFLAGS += -DENABLE_MOCK_MODE
|
||||
SRCS += mock_driver.c
|
||||
endif
|
||||
```
|
||||
|
||||
### CMake
|
||||
|
||||
```cmake
|
||||
option(ENABLE_MOCK "Enable mock mode for testing" OFF)
|
||||
|
||||
if(ENABLE_MOCK)
|
||||
add_definitions(-DENABLE_MOCK_MODE)
|
||||
set(MOCK_SOURCES mock_driver.c)
|
||||
endif()
|
||||
|
||||
add_executable(DtrGuiSrv01 ${SOURCES} ${MOCK_SOURCES})
|
||||
```
|
||||
|
||||
## 執行模式
|
||||
|
||||
### 1. 環境變數
|
||||
|
||||
```bash
|
||||
# 啟用 Mock 模式
|
||||
export DTR_GUI_MOCK_MODE=1
|
||||
./DtrGuiSrv01
|
||||
|
||||
# 指定 Mock 設定檔
|
||||
export DTR_GUI_MOCK_CONFIG=./mock_config.json
|
||||
./DtrGuiSrv01
|
||||
```
|
||||
|
||||
### 2. 命令列參數
|
||||
|
||||
```bash
|
||||
./DtrGuiSrv01 --mock
|
||||
./DtrGuiSrv01 -m
|
||||
./DtrGuiSrv01 --mock-config ./mock_config.json
|
||||
```
|
||||
|
||||
### 3. 設定檔
|
||||
|
||||
```ini
|
||||
# dtr_guiconf.ini
|
||||
[Server]
|
||||
Port=8922
|
||||
MockMode=1
|
||||
MockConfig=./mock_config.json
|
||||
```
|
||||
|
||||
## 測試案例
|
||||
|
||||
### 1. 基本連線測試
|
||||
|
||||
```python
|
||||
import socket
|
||||
|
||||
def test_connection():
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect(('localhost', 8922))
|
||||
|
||||
# 發送 GET_PAGE 請求
|
||||
request = build_get_page_request(page_code=0x00)
|
||||
s.send(request)
|
||||
|
||||
# 驗證回應
|
||||
response = s.recv(4096)
|
||||
assert response[0] == 0x50 # Success
|
||||
|
||||
s.close()
|
||||
```
|
||||
|
||||
### 2. 控制器查詢測試
|
||||
|
||||
```python
|
||||
def test_query_controller():
|
||||
# 查詢控制器資訊
|
||||
response = send_inband_command(opcode=0x01, page=0x00)
|
||||
|
||||
# 驗證資料格式
|
||||
assert response['serial_number'] == 'MOCK00000001'
|
||||
assert response['model_name'] == 'Accusys Mock RAID'
|
||||
```
|
||||
|
||||
### 3. 事件測試
|
||||
|
||||
```python
|
||||
def test_event_polling():
|
||||
# 設定模擬事件
|
||||
mock_set_event(disk_online_event)
|
||||
|
||||
# 取得事件
|
||||
response = send_event_request(opcode=0x02)
|
||||
|
||||
# 驗證事件
|
||||
assert response['event_type'] == 'DiskOnline'
|
||||
```
|
||||
|
||||
## 實作時間評估
|
||||
|
||||
| 工作項目 | 時間 |
|
||||
|----------|------|
|
||||
| 建立 mock_driver.h/c 框架 | 1 天 |
|
||||
| 實作基本 DevIoControl | 2 天 |
|
||||
| 實作 QuaryDTR / GetCtlrEvent | 1 天 |
|
||||
| 實作 Page 0 (Controller Info) | 1 天 |
|
||||
| 實作其他 Page 資料 | 2-3 天 |
|
||||
| 模擬事件系統 | 1 天 |
|
||||
| JSON 設定檔支援 | 1 天 |
|
||||
| 測試與除錯 | 2 天 |
|
||||
| **總計** | **9-10 天** |
|
||||
|
||||
## 風險與限制
|
||||
|
||||
### 已知限制
|
||||
|
||||
1. **不完整模擬**: 無法完全模擬所有 RAID 操作
|
||||
2. **狀態有限**: 只能模擬基本狀態
|
||||
3. **Driver 特定**: 某些低層級錯誤無法模擬
|
||||
|
||||
### 風險控制
|
||||
|
||||
1. **清晰標記**: Mock 模式下顯示明顯標識
|
||||
2. **日誌區分**: Mock 日誌使用不同前綴 `[MOCK]`
|
||||
3. **版本標記**: 回應中包含 Mock 標記
|
||||
|
||||
```c
|
||||
// 回應中加入 Mock 標記
|
||||
UCHAR mock_page0[] = {
|
||||
// ...
|
||||
'M', 'O', 'C', 'K', // 識別碼
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
## 結論
|
||||
|
||||
### 可行性: ✅ 高
|
||||
|
||||
**結論**: 完全可行,預估 9-10 天可完成。
|
||||
|
||||
### 實作策略
|
||||
|
||||
1. **先實現基本框架**: 快速建立可運行的 Mock 骨架
|
||||
2. **逐步完善**: 按需求添加更多 Page 支援
|
||||
3. **測試驅動**: 先寫測試案例,再實作對應 Mock
|
||||
|
||||
### 優點
|
||||
|
||||
- 開發期不需要實際 RAID 硬體
|
||||
- CI/CD 可自動化測試
|
||||
- 容易重現問題
|
||||
- 教學演示方便
|
||||
|
||||
### 產出
|
||||
|
||||
- `mock_driver.h` - Mock 驅動介面
|
||||
- `mock_driver.c` - Mock 驅動實作
|
||||
- `mock_config.json` - 模擬設定檔範例
|
||||
- 編譯腳本更新
|
||||
Reference in New Issue
Block a user