在研究 net
這個結構的過程中,我注意到了一個特別的欄位 netns_ids
。
// include/net/net_namespace.h
struct net {
...
struct idr netns_ids;
...
}
在我們之前介紹的網路命名空間子系統初始化函數 net_ns_init
中,其實還有一些隱藏掉的部分。
// net/core/net_namespace.c
void __init net_ns_init(void) {
...
if (setup_net(&init_net, &init_user_ns))
panic("Could not setup the initial network namespace");
...
init_net_initialized = true;
...
if (register_pernet_subsys(&net_ns_ops))
panic("Could not register network namespace subsystems");
rtnl_register(PF_UNSPEC, RTM_NEWNSID, rtnl_net_newid, NULL,
RTNL_FLAG_DOIT_UNLOCKED);
rtnl_register(PF_UNSPEC, RTM_GETNSID, rtnl_net_getid, rtnl_net_dumpid,
RTNL_FLAG_DOIT_UNLOCKED);
}
我們可以看到兩個 rtnl_register
函數。這些函數是用來透過 netlink 機制提供 API 給 user space 使用,具體會在後續介紹 netlink 和 rtnetlink 時更深入探討。
總之,這邊網路命名空間子系統提供了 rtnl_net_newid
和 rtnl_net_getid
這兩個函數,其功能是對 net.netns_ids
進行讀寫操作。那么,netns_ids
到底是什麼作用呢?
最後,我在 ip netns
指令的文件中找到了一些線索:
ip netns set NAME NETNSID - assign an id to a peer network namespace
ip netns list-id [target-nsid POSITIVE-INT] [nsid POSITIVE-INT] - list network namespace ids (nsid)
簡單來說,我們可以在當前的 network namespace 中,為另一個 network namespace 指定一個數字 ID (netnsid
),這個 ID 代表另一個 network namespace,並且只在當前的 namespace 有效。接下來舉個例子來說明:
在 init_net
裡面,我們透過 ip
指令建立了另外兩個 namespace,分別是 net2
和 net3
:
ip netns add net2
ip netns add net3
接著,我們在每個 namespace 中設置 net2
和 net3
的 ID:
# In init_net
ip netns set net2 12
ip netns set net3 13
ip -n net2 netns set net2 22
ip -n net2 netns set net3 23
ip -n net3 netns set net2 32
ip -n net3 netns set net3 33
現在,透過 ip netns list-id
指令,我們可以在 init_net
中看到前面設置的 ID:
# In init_net
> ip netns list
net3 (id: 13)
net2 (id: 12)
而在 net2
namespace 裡面,看到的 ID 則是:
> ip netns exec net1 ip netns list-id
nsid 22 (iproute2 netns name: net2)
nsid 23 (iproute2 netns name: net3)
這個id具體有什麼用,筆者目前是看不太出來,可能在開發kernel driver或著其他管理namespace的方式下會有用? 目前我唯一能夠具體觀察到的用途是使用 ip link
指令檢視 veth 介面時,可以看到它指向的 netnsid
。
# In init_net
> ip link add vethnet1 type veth peer name vethnetinit
> ip link set vethnet1 netns net1
> ip link show vethnetinit
12: vethnetinit@if13: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 3a:5f:d1:0b:07:08 brd ff:ff:ff:ff:ff:ff link-netnsid 12
可以看到veth的最後寫著link-netnsid 12
表示他被放到對init_net來說netnsid為12的namespace,也就是net2。
可以看到,在 veth 的最後一行寫著 link-netnsid 12
,表示這個介面被移動到對init_net來說netnsid為12的namespace,也就是 net2
。
在這篇文章中,我們探索了 netns_ids
的用途,這個功能跟本系列文章要介紹的主要脈絡較無關,但因為看到了,所以還是以番外標題的形式放進來了。