--- 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