---
lang: ja
breaks: false
---
<style>
.ui-infobar, #doc.markdown-body { max-width: 1100px; }
</style>
# 2020-10-08 kernel network stack reading - network namespace -
- 参加者: hayakawa, kawakami, taguchi, saito
- kernel: `5.6.6`
- ドライバー: hayakawa
- 今回のテーマ
- network nemespaceの実態を知る
- どんなリソースがnamespacingされているのか
- どうやってnamespaceを識別するのか
- ip netns addすると何が起こるのか?
- ip link set netnsはなにをするのか?
- ip netns execは何をするのか?
- etc...
## 使用マシン
- 早川のローカルマシンのVagrant
- fedora/32-cloud-base
- Vagrant環境の構築方法は9/4に記載されている通り
- https://hackmd.io/iMc0OpUESIWCNSr9DBC_sg?both#tinet%E3%81%A8ipftrace2%E7%92%B0%E5%A2%83%E3%81%AE%E6%A7%8B%E7%AF%89
## 現状わかっていること
- `struct net` が実質的なnetnsの実体らしい
- namespacingされるリソース
- routing table
- netfilter
- procfs?
- sysfs?
- unshare(2)
## メモ
- struct net
- http://elixir-referencer.dev.linecorp.com/linux/latest/source/include/net/net_namespace.h#L56
- namespacingされているリソース
- mib知らなかった
- Unix network namespaceとは?
- netns_ipv4/v6みたいなのがアドレスファミリーごとにある?
- sysctlの設定もここに入ってる
- http://elixir-referencer.dev.linecorp.com/linux/latest/source/include/net/netns/ipv4.h#L43
- http://elixir-referencer.dev.linecorp.com/linux/latest/source/include/net/netns/ipv6.h#L56
- struct pernet_operations
- init_net => root namespace?
- per-process namespace => nsproxy
- struct proc_ns_operations
- unshareとsetnsの違い
- unshareはnamespaceを作成して移動
- setnsは指定されたnamespaceに移動
## ip netns addのstrace
```
getuid() = 0
socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE) = 3
setsockopt(3, SOL_SOCKET, SO_SNDBUF, [32768], 4) = 0
setsockopt(3, SOL_SOCKET, SO_RCVBUF, [1048576], 4) = 0
setsockopt(3, SOL_NETLINK, NETLINK_EXT_ACK, [1], 4) = 0
bind(3, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 0
getsockname(3, {sa_family=AF_NETLINK, nl_pid=3937, nl_groups=00000000}, [12]) = 0
setsockopt(3, SOL_NETLINK, NETLINK_DUMP_STRICT_CHK, [1], 4) = 0
openat(AT_FDCWD, "/proc/self/ns/net", O_RDONLY) = 4
sendto(3, {{len=28, type=RTM_GETNSID, flags=NLM_F_REQUEST, seq=0, pid=0}, {rtgen_family=AF_UNSPEC}, {{nla_len=8, nla_type=NETNSA_FD}, 4}}, 28, 0, NULL, 0) = 28
recvmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=28, type=RTM_NEWNSID, flags=0, seq=0, pid=3937}, {rtgen_family=AF_UNSPEC}, {{nla_len=8, nla_type=NETNSA_NSID}, -1}}, iov_len=16384}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 28
close(4) = 0
socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE) = 4
setsockopt(4, SOL_SOCKET, SO_SNDBUF, [32768], 4) = 0
setsockopt(4, SOL_SOCKET, SO_RCVBUF, [1048576], 4) = 0
setsockopt(4, SOL_NETLINK, NETLINK_EXT_ACK, [1], 4) = 0
bind(4, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 0
getsockname(4, {sa_family=AF_NETLINK, nl_pid=-57337353, nl_groups=00000000}, [12]) = 0
mkdir("/var/run/netns", 0755) = -1 EEXIST (File exists)
mount("", "/var/run/netns", 0x5566641d767f, MS_REC|MS_SHARED, NULL) = 0
openat(AT_FDCWD, "/var/run/netns/bazbaz", O_RDONLY|O_CREAT|O_EXCL, 000) = 5
close(5) = 0
openat(AT_FDCWD, "/proc/self/ns/net", O_RDONLY|O_CLOEXEC) = 5 <= 現在のnamepaceを保持 fd=5
unshare(CLONE_NEWNET) = 0 <= 新しいnamespaceを作成し,新しいnamespaceに移動
mount("/proc/self/ns/net", "/var/run/netns/bazbaz", 0x5566641d767f, MS_BIND, NULL) = 0 <= 作成したnamespaceをmountし固定
setns(5, CLONE_NEWNET) = 0 <= 元のnamespaceに復帰 fd=5
close(5) = 0
exit_group(0) = ?
+++ exited with 0 +++
```
## ip link set netnsの中身
- dev_change_net_namespaceが大事
- ifindexは可能な限り元のnamespaceでのifindexと同じにしようとする
## ip netns exec
- setns -> close -> unshare
- sysfsをマウントし直してくれる
- /etc/netns/NAME 以下にファイルを作るとマウントしてくれたりする
## nsenter
- setns
## /etc/netns/NETNS_NAME
- このディレクトリに配置したファイルは、netns毎の`/etc`にマウントされる (bind mount)
- resolv.confをnetns毎に配置するのに使える
## 参考
- https://man7.org/linux/man-pages/man8/ip-netns.8.html
- https://www.man7.org/linux/man-pages/man2/unshare.2.html
- https://man7.org/linux/man-pages/man2/setns.2.html