Friday, March 23, 2007

NCTUns Tunnel Architecture PartII

PartI 已經有整個 tunnel 與 NCTUns engine 初步架構說明,至於詳細運作流程與方式,等待 Part IV 再直接從 Code 角度來介紹。

動態配置 Device Major Number
將 nctuns_tun 從原本 tun device driver 獨立出來後,面臨的第一個問題就是 device major number 的指定,每個 major number 都可以有 256 個 minor number,因此之前的作法會佔用 238~253 這區段 16 個 major number,從 PartI 可以瞭解當然不需要佔用這麼多個 number,更何況這些 number 泰半幾乎已經預留給特定的 device driver ,因此我採用 Linux 2.6 所建議,採用 dynamic allocate 的方式由系統於載入時決定 device 使用的 major number,如下:

ret = alloc_chrdev_region(&nctuns_dev_t, 0, MAX_NCTUNS_TUN_MIXORS, DRV_NAME);
...
cdev_init(&nctuns_cdev, &nctuns_tun_fops);
ret = cdev_add(&nctuns_cdev, nctuns_dev_t, MAX_NCTUNS_TUN_MIXORS);

alloc_chrdev_region 必須指定一個 device 所需要使用的 region,在這邊將 MAX_NCTUNS_TUN_MIXORS 指定為 10,主要目的是預留未來使用,但實際上只需藥用到一個 minor number。要 unregister 只要呼叫對應的兩個 API 即可:

cdev_del(&nctuns_cdev);
unregister_chrdev_region(nctuns_dev_t, MAX_NCTUNS_TUN_MIXORS);

將 device number 改以動態配置所面臨的另一個問題就是在 mknod 建立這個 charactor device node 時無法知道真正使用的 major, minor number,雖然從 /proc/device 可以查到 major 但仍舊缺少 minor,這時就必須配合 sysfs 了。

sysfs 新機制
Linux 2.6 另一個重大的改變就是 sysfs 的支援,一個類似於 procfs 的新作法,詳細詳細介紹可以參考相關 Linux 書籍或網路資料,在這邊僅針對 device hot-plug 的支援。

在 Linux 2.6 特有的 sysfs 裡有個 class 的資料夾,裡面分門別類的註冊了眾多 device 的資訊,每個經過標準 API 向 sysfs 註冊的 device driver 都可以在 /sys/class 找到對應 device name 目錄,目錄之下存放了各式各樣跟這 device 相關的檔案提供一些資訊工 user-level 程式使用,其中一個檔名為 dev 的檔案就是存放了這個 device 所使用的 major, minor 資訊,就可以透過這資訊建立 charactor node 了。

整個機制看似複雜,但使用上並不困難,在 class 之下有分門別類區分了各式各樣的 device 各自成為一個 folder,因此我也建立名為 nctuns 的獨立 folder 如下:

nctuns_class = class_create(THIS_MODULE, "nctuns");
...
class_device_create(nctuns_class, NULL, nctuns_dev_t, NULL, DRV_NAME);

先使用 class_create 建立 class 分類 folder,再以 class_device_create 並傳入前面已經建立好的 device number (不管是動態建立或是靜態宣告),就完成了基本動作,重編後載入系統就可以在 /sys/class 看到 nctuns 的目錄,並在之下看到我們所註冊的 nctuns_tun,當然要 unregister 也是使用兩個 API 分別對應上面兩個 create:

class_device_destroy(nctuns_class, nctuns_dev_t);
class_destroy(nctuns_class);


udev 的配合
sysfs 也準備好,最後剩下的就是 user-level 相互搭配 hot-plug 的 daemon: udev,udev 本身也是一個龐大的計畫,他會監看 /sys/class 之下的改變,因此當有任何 device 被載入時就會根據預先設定好的 rule 做出對應的動作甚至執行相對應的 script。

我們只需要為 nctuns_tun 設定一條 rule ,讓 udev daemon 偵測到 nctuns_tun 時可以為我們在 /dev/net 將 charactor device node 建出來,一般 rule 預設路徑都存在 /etc/udev/rules.d 底下,類似於 開機程序 rc.d 的命名方式一般。所以我自己建立一個 55-nctuns.rules 的設定檔,內容如下:

KERNEL=="*", OWNER="root" GROUP="root", MODE="0600"
KERNEL=="nctuns_tun", NAME="net/%k"

指定了當發現 nctuns_tun 就在 /dev/net 建立一個同名的 node(即 nctuns_tun),而第一行就是指定建出來的 node 相關權限的設定。如此既可達到動態配置 device number,避免和系統中已經存在的 device 相衝突(大家搶同樣的 number 時),又可以免去手動 mknod 建立這些 tunnel device node 所衍生的問題,將一切動作交由 device driver 和 udev 去負責,降低安裝中的錯誤發生。



HEMiDEMi Technorati Del.icio.us MyShare個人書籤 Yahoo

0 Comments: