Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduced named network namespace for replayshell #106

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

worenga
Copy link

@worenga worenga commented Nov 27, 2016

this allows the creation of a a custom resolv.conf
which is independent of the mahimahi host resolv.conf, fixes #105

this allows the creation of a a custom resolv.conf
which is independent of the mahimahi host resolv.conf
snprintf(etc_name, sizeof(etc_name), "/etc/%s", entry->d_name);

if ( umount( etc_name ) < 0 ) {
throw runtime_error( string("Unmounting... ") + netns_name + " -> " + etc_name + " failed: " + strerror(errno) + "\n" );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line causes the compile to fail on g++ 6.2. (Can't throw from a destructor.)

network_namespace.cc: In destructor ‘NetworkNamespace::~NetworkNamespace()’: network_namespace.cc:55:135: error: throw will always call terminate() [-Werror=terminate] . ") + netns_name + " -> " + etc_name + " failed: " + strerror(errno) + "\n" ); ^ network_namespace.cc:55:135: note: in C++11 destructors default to noexcept

const string netns_dir = NETNS_ETC_DIR + "/" + name_;
const string resolvconf_path = netns_dir + "/resolv.conf";

SystemCall("mkdir", mkdir( netns_dir.c_str() , S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fails for me on a default Ubuntu 16.10 installation (there's no NETNS_ETC_DIR, aka /etc/netns, so the mkdir fails). We might need more like a mkdir -p, except how do you safely clean that up at the end of the program?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For applications that are aware of network namespaces, the convention
is to look for global network configuration files first in
/etc/netns/NAME/ then in /etc/. For example, if you want a different
version of /etc/resolv.conf for a network namespace used to isolate
your vpn you would name it /etc/netns/myvpn/resolv.conf.

http://man7.org/linux/man-pages/man8/ip-netns.8.html

My bad. It isn't there on Ubuntu 16.04 per default as well. I guess i must have created the /etc/netns folder manually during working on an earlier prototype.
However, the way the code works right now i guess it does not matter where the resolv.conf resides as long as we can mount it later. So the question is adopt that naming pattern from the manpage or create a temporary directory?

Copy link
Collaborator

@keithw keithw Nov 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a tempfile is fine -- as I said on the other thread, I don't know of any "applications that are aware of network namespaces." glibc's resolver doesn't seem to know about this, and that's what most applications use. If we're going to use a bind mount (and a mount namespace) to replace resolv.conf inside the container, then I don't think this convention matters -- we could put it anywhere that can be reliably cleaned up at exit (normal or abnormal).

@keithw
Copy link
Collaborator

keithw commented Nov 27, 2016

Unfortunately this code doesn't seem to be working as intended. It does create a new "mount" namespace (not just a "network" namespace), and then creates a bind mount over /etc/resolv.conf (or whatever that link points to) with a replacement resolv.conf.

But when I run it on Ubuntu 16.10, that replacement resolv.conf is visible systemwide and is not confined to the child of the mm-webreplay. This is changing the nameservers for the entire system, not just those inside replayshell.

Also, some of the mounts seem to be lingering around even after program termination (just check mount).

I think if we're going to adopt something this dramatic (i.e. changing the mahimahi shells to each create both a "network" namespace and a "mount" namespace so we can rewrite resolv.conf), it would need to:

  • actually be confined to the child shell
  • use RAII objects that successfully clean up after themselves when destroyed
  • work in the same way for all of the mahimahi shells (e.g. mm-delay/mm-loss/mm-onoff/mm-link)
  • demonstrate that adding a "mount" namespace doesn't hurt any common use case

still lacks proper raii cleanup for namespace
@worenga
Copy link
Author

worenga commented Nov 29, 2016

@keithw Can you check whether the latest commit works for you on a functional level? Then i can start thinking about RAII. I got rid of the named namespace idea and changed the order in which the network namespace and then the bind namespace are created.

@keithw
Copy link
Collaborator

keithw commented Nov 30, 2016

It's a lot better in that it's no longer affecting the global namespace, but unfortunately it still doesn't seem to actually work for me on Ubuntu 16.10. The permissions on /run/resolvconf/resolv.conf are:

[replay] keithw@pel:~$ ls -l /run/resolvconf/resolv.conf 
-rw------- 1 root keithw 151 Nov 29 22:25 /run/resolvconf/resolv.conf

@worenga
Copy link
Author

worenga commented Nov 30, 2016

Changed the permission of the tempfile to 644.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

DNS response time in delayshell not deterministic
2 participants