在 PartII 已經介紹過, nctuns_tun 採用 sysfs 的設計方式,搭配 udev 來實現動態建立 charactor node 的方式增加整體的彈性以及減少不同 linux distribution 不相容因素。源自於 tun 的架構,每個 device 都是透過向 fs 註冊,再用基本的 function 做操作,諸如 open, close, ioctl, read, write 等,因此 nctuns_tun 也不例外,所有一系列的 function,都和原本 tun 是對應的,而為了 NCTUns simulator 需要做調整如下:
Modified function list:
tun_net_xmit
tun_net_init
tun_get_user
tun_chr_aio_read
tun_set_iff
tun_chr_ioctl
tun_get_drvinfo
在上面最重要的莫過於 tun_get_user 及 tun_net_xmit 兩個 function, 另外額外在新增 tun_net_loopback function 用來判斷要經由 tunnel 流進 user-level 的 packet 是否為 loopback packet,如果是就不進 user-level 直接往上送。
tun_net_init
原本的 tun 會根據不同的 device type 判斷為 TUN_DEV 還是 TAP_DEV 而做不同的事情,但在 nctuns_tun 只會有 TUN_DEV mode 因此簡化原本 function,但增加不同 nctuns_tun 的用途判斷,根據 tunnel device name 區分為 event tun 和 data tun,其中 data tun 因需要配合 tcpdump 的解析,因此 net_device type 需指定為 ARPHRD_ETHER 且相關 header length 也需要指定如下:
dev->type = ARPHRD_ETHER;
dev->hard_header_len = ETH_HLEN;
dev->addr_len = 0;
...
...
tun->tid = i;
...
...
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
在這裡我們 hack 原本 tun struct 增加欄位 tid,用來記錄 nctuns_tun 的編號,如此就不用每次得到 maptable 利用 tunnel name 去轉換成 tunnel id,將這動作於初始化就做好。
再者,為了讓 ip input procedure 可以判斷 packet 進來的 net_device 種類,因此我們在 dev->flags 指定刻意將原本的 IFF_MULTICAST 屬性拿掉,就可以搭配 IFF_POINTOPOINT 來檢查 net_device 是否屬於 nctuns_tun。當然可以如此拿掉是因此目前 NCTUns simulator 還沒有一套可以 full support multicast 的機制,因此預設狀態 multicast 的支援都是不會動,因此也不需要為這些功能預留 flags,除非往後設計出一套可以 support 的機制再做調整。
tun_set_iff, tun_get_drvinfo
主要將 tun 原本支援 multi-queue 及 pi header 功能拿掉,因為 nctuns_tun 不需要用到
而 tun_get_drvinfo 則是拿掉不同 device type 的判斷。
tun_chr_ioctl
ioctl 主要增加兩個 command,分別是 TUNSETUD, TUNGETUD 用來取得/設定 tunnel link 的 up/down 狀態如下:
case TUNSETUD: {
...
...
}
case TUNGETUD: {
...
...
}
新增的 command 主要是給 Daemon 使用(如 RIP, OSPF 等),在 NCTUns engine 裡的 phy module 會將 linkfail 設定讀進來後,利用 ioctl 將 flag 設定到 kernel,因此 daemon 可以藉由取得 flags 來判斷 link 是否 fail 了,當然這方法似乎不夠直覺,也許可以利用原本系統的方法來改進這些流程。
tun_chr_aio_read
在 read function 幾乎沒有任何動作,因為該做的事情,我們在 tun_net_xmit 已經完成了,在這裡主要針對 memory mapping 的 tunnel qlen 做校正。
tun_net_xmit, tun_get_user
這兩個 function 就是整個 nctuns_tun 的精神了,其中 tun_net_xmit 這 function 在 上層(Layer 3, 4)要流出 device 時就會間接輾轉的呼叫到這 function,接著 tun_net_xmit 需要做一些 S.S.D.D scheme 轉換之後就 enqueue 到 skb_queue 裡,等待 User-level 的程式來讀取。
而 tun_get_user 就剛好相反,這 function 是 User-level 程式要 write 到 tunnel 時會輾轉呼叫到,同樣我們也需要做一些 S.S.D.D scheme 轉換再往上層送,至於這兩個 function 怎麼做 S.S.D.D 轉換的流程在往後的篇幅會有詳細介紹。
...
Read more.





