次のC関数を使用して、単一のプロセスインスタンスから複数のネットワーク名前空間を作成しています。
void create_namespace(const char *ns_name)
{
char ns_path[100];
snprintf(ns_path, 100, "%s/%s", "/var/run/netns", ns_name);
close(open(ns_path, O_RDONLY|O_CREAT|O_EXCL, 0));
unshare(CLONE_NEWNET);
mount("/proc/self/ns/net", ns_path, "none", MS_BIND , NULL);
}
プロセスがすべての名前空間を作成し、1つのネットワーク名前空間のいずれかにタップip link set tap1 netns ns1
インターフェイスを追加した後(コマンドを使用)、実際にはすべての名前空間にこのインターフェイスが表示されます(おそらく、これは実際には異なる名前の単一の名前空間です)。
しかし、複数のプロセスを使用して複数の名前空間を作成すると、すべてが正常に機能します。
ここで何が間違っている可能性がありますか?unshare()
単一のプロセスインスタンスからこれを機能させるには、に追加のフラグを渡す必要がありますか?単一のプロセスインスタンスが複数のネットワーク名前空間を作成できないという制限はありますか?または、実際には複数回マウントされているmount()
ため、呼び出しに問題がありますか?/proc/self/ns/net
更新:unshare()
関数は複数のネットワーク名前空間を正しく作成
しているようですが、すべてのマウントポイントは、/var/run/netns/
実際にはそのディレクトリにマウントされた最初のネットワーク名前空間を参照しています。
Update2: 最善のアプローチは、別のプロセスをfork()して、そこからcreate_namespace()関数を実行することだと思われます。とにかく、fork()呼び出しを含まないより良い解決策を聞いたり、少なくとも単一のプロセスから複数のネットワーク名前空間を作成および管理することが不可能であることを証明する確認を取得したりできれば幸いです。
Update3: 次のコードを使用して、unshare()で複数の名前空間を作成できます。
int main() {
create_namespace("a");
system("ip tuntap add mode tap tapa");
system("ifconfig -a");//shows lo and tapA interface
create_namespace("b");
system("ip tuntap add mode tap tapb");
system("ifconfig -a");//show lo and tapB interface, but does not show tapA. So this is second namespace created.
}
しかし、プロセスが終了して実行ip netns exec a ifconfig -a
した後、ip netns exec b ifconfig -a
両方のコマンドが名前空間aで突然実行されたようです。したがって、実際の問題は、名前空間への参照を保存することです(または、mount()を正しい方法で呼び出します。しかし、これが可能かどうかはわかりません)。