Re: [libvirt] [PATCH] virNetDevVethCreate: assign names based on mac address by default

2013-08-29 Thread Michal Privoznik
On 28.08.2013 23:05, Oskari Saarenmaa wrote:
 Interface names do not have to be numerical (or veth + number) and trying to
 assign them to that format is susceptible to race conditions.  Instead,
 assign the parent interface name according to the mac address (the last
 three bytes) if no name was given by the caller and use the parent interface
 name plus 'p' for the container name.
 
 Signed-off-by: Oskari Saarenmaa o...@ohmu.fi
 
 ---
  src/lxc/lxc_process.c|  2 +-
  src/util/virnetdevveth.c | 81 
 +---
  src/util/virnetdevveth.h |  6 ++--
  3 files changed, 19 insertions(+), 70 deletions(-)
 
 diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
 index 4835bd5..956bbdb 100644
 --- a/src/lxc/lxc_process.c
 +++ b/src/lxc/lxc_process.c
 @@ -243,7 +243,7 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr 
 conn,
  
  VIR_DEBUG(calling vethCreate());
  parentVeth = net-ifname;
 -if (virNetDevVethCreate(parentVeth, containerVeth)  0)
 +if (virNetDevVethCreate(parentVeth, containerVeth, net-mac)  0)
  goto cleanup;
  VIR_DEBUG(parentVeth: %s, containerVeth: %s, parentVeth, 
 containerVeth);
  
 diff --git a/src/util/virnetdevveth.c b/src/util/virnetdevveth.c
 index 039767f..c0e3e93 100644
 --- a/src/util/virnetdevveth.c
 +++ b/src/util/virnetdevveth.c
 @@ -38,96 +38,46 @@
  
  /* Functions */
  /**
 - * virNetDevVethGetFreeName:
 - * @veth: pointer to store returned name for veth device
 - * @startDev: device number to start at (x in vethx)
 - *
 - * Looks in /sys/class/net/ to find the first available veth device
 - * name.
 - *
 - * Returns non-negative device number on success or -1 in case of error
 - */
 -static int virNetDevVethGetFreeName(char **veth, int startDev)
 -{
 -int devNum = startDev-1;
 -char *path = NULL;
 -
 -VIR_DEBUG(Find free from veth%d, startDev);
 -do {
 -VIR_FREE(path);
 -++devNum;
 -if (virAsprintf(path, /sys/class/net/veth%d/, devNum)  0)
 -return -1;
 -VIR_DEBUG(Probe %s, path);
 -} while (virFileExists(path));
 -VIR_FREE(path);
 -
 -if (virAsprintf(veth, veth%d, devNum)  0)
 -return -1;
 -
 -return devNum;
 -}
 -
 -/**
   * virNetDevVethCreate:
   * @veth1: pointer to name for parent end of veth pair
   * @veth2: pointer to return name for container end of veth pair
 + * @mac: mac address of the device
   *
   * Creates a veth device pair using the ip command:
   * ip link add veth1 type veth peer name veth2
 - * If veth1 points to NULL on entry, it will be a valid interface on
 - * return.  veth2 should point to NULL on entry.
   *
 - * NOTE: If veth1 and veth2 names are not specified, ip will auto assign
 - *   names.  There seems to be two problems here -
 - *   1) There doesn't seem to be a way to determine the names of the
 - *  devices that it creates.  They show up in ip link show and
 - *  under /sys/class/net/ however there is no guarantee that they
 - *  are the devices that this process just created.
 - *   2) Once one of the veth devices is moved to another namespace, it
 - *  is no longer visible in the parent namespace.  This seems to
 - *  confuse the name assignment causing it to fail with File exists.
 - *   Because of these issues, this function currently allocates names
 - *   prior to using the ip command, and returns any allocated names
 - *   to the caller.
 + * If veth1 or veth2 points to NULL on entry, they will be a valid interface
 + * on return.  The name is generated based on the mac address given.
   *
   * Returns 0 on success or -1 in case of error
   */
 -int virNetDevVethCreate(char** veth1, char** veth2)
 +int virNetDevVethCreate(char** veth1, char** veth2, const virMacAddrPtr mac)
  {
 -int rc = -1;
  const char *argv[] = {
  ip, link, add, NULL, type, veth, peer, name, NULL, NULL
  };
 -int vethDev = 0;
  bool veth1_alloc = false;
  bool veth2_alloc = false;
  
  VIR_DEBUG(Host: %s guest: %s, NULLSTR(*veth1), NULLSTR(*veth2));
  
  if (*veth1 == NULL) {
 -if ((vethDev = virNetDevVethGetFreeName(veth1, vethDev))  0)
 -goto cleanup;
 +/* Use the last three bytes of the mac address as our if name */
 +if (virAsprintf(veth1, veth%02x%02x%02x,
 +mac-addr[3], mac-addr[4], mac-addr[5])  0)

I don't think it is a good idea. What it user defines MAC addresses in a
way that the last three bytes are the same? E.g.

00:11:22:33:44:55
00:22:11:33:44:55

(there are plenty of possibilities). With your code we would create
veth334455 for the first domain and there's nothing left for the other
one but eyes to cry.

Moreover, there's no race now, as we use global lock to mutually exclude
call to virNetDevVethCreate. Although, I must admit it's only within a
single driver, I think. So if there are two domains starting (one in
qemu 

Re: [libvirt] [PATCH] virNetDevVethCreate: assign names based on mac address by default

2013-08-29 Thread Oskari Saarenmaa
On Thu, Aug 29, 2013 at 10:10:36AM +0200, Michal Privoznik wrote:
 On 28.08.2013 23:05, Oskari Saarenmaa wrote:
  Interface names do not have to be numerical (or veth + number) and trying to
  assign them to that format is susceptible to race conditions.  Instead,
  assign the parent interface name according to the mac address (the last
  three bytes) if no name was given by the caller and use the parent interface
  name plus 'p' for the container name.
 I don't think it is a good idea. What it user defines MAC addresses in a
 way that the last three bytes are the same? E.g.
 
 00:11:22:33:44:55
 00:22:11:33:44:55
 
 (there are plenty of possibilities). With your code we would create
 veth334455 for the first domain and there's nothing left for the other
 one but eyes to cry.

Sure, it's possible for the user to assign addresses like this, but I
believe most mac addresses are assigned randomly, that's what libvirt does
by default, no?  Also, it's possible for the user to override the interface
name if they want to.  Currently it's only possible to set the first
interface name, but there's no way to set the name of the second interface
which causes failures because of races.  In any case it makes sense to set
the second interface's name based on the first interface's name so we don't
have to try to come up with two different unique names.

 Moreover, there's no race now, as we use global lock to mutually exclude
 call to virNetDevVethCreate. Although, I must admit it's only within a
 single driver, I think. So if there are two domains starting (one in
 qemu driver the other one in lxc, for instance) there can be race. But
 this should be solved in a different way then. The virNetDevVethCreate
 should be turned into virObjectLockable and a veth should be allocated
 by calling a method.

I ran into this issue repeatedly when I tried to start multiple LXC domains
simultaneously from my application (https://github.com/melor/poni) which
runs libvirt operations in their own threads.

/ Oskari

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] virNetDevVethCreate: assign names based on mac address by default

2013-08-29 Thread Gao feng
On 08/29/2013 04:20 PM, Oskari Saarenmaa wrote:
 On Thu, Aug 29, 2013 at 10:10:36AM +0200, Michal Privoznik wrote:
 On 28.08.2013 23:05, Oskari Saarenmaa wrote:
 Interface names do not have to be numerical (or veth + number) and trying to
 assign them to that format is susceptible to race conditions.  Instead,
 assign the parent interface name according to the mac address (the last
 three bytes) if no name was given by the caller and use the parent interface
 name plus 'p' for the container name.
 I don't think it is a good idea. What it user defines MAC addresses in a
 way that the last three bytes are the same? E.g.

 00:11:22:33:44:55
 00:22:11:33:44:55

 (there are plenty of possibilities). With your code we would create
 veth334455 for the first domain and there's nothing left for the other
 one but eyes to cry.
 
 Sure, it's possible for the user to assign addresses like this, but I
 believe most mac addresses are assigned randomly, that's what libvirt does
 by default, no?  Also, it's possible for the user to override the interface
 name if they want to.  Currently it's only possible to set the first
 interface name, but there's no way to set the name of the second interface
 which causes failures because of races.  In any case it makes sense to set
 the second interface's name based on the first interface's name so we don't
 have to try to come up with two different unique names.
 
 Moreover, there's no race now, as we use global lock to mutually exclude
 call to virNetDevVethCreate. Although, I must admit it's only within a
 single driver, I think. So if there are two domains starting (one in
 qemu driver the other one in lxc, for instance) there can be race. But
 this should be solved in a different way then. The virNetDevVethCreate
 should be turned into virObjectLockable and a veth should be allocated
 by calling a method.
 
 I ran into this issue repeatedly when I tried to start multiple LXC domains
 simultaneously from my application (https://github.com/melor/poni) which
 runs libvirt operations in their own threads.
 

It's easy to be resolved. give the parentVeth and containerVeth a name by 
default.

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] virNetDevVethCreate: assign names based on mac address by default

2013-08-29 Thread Oskari Saarenmaa
29.08.2013 11:36, Gao feng kirjoitti:
 On 08/29/2013 04:20 PM, Oskari Saarenmaa wrote:
 On Thu, Aug 29, 2013 at 10:10:36AM +0200, Michal Privoznik wrote:
 On 28.08.2013 23:05, Oskari Saarenmaa wrote:
 Interface names do not have to be numerical (or veth + number) and trying 
 to
 assign them to that format is susceptible to race conditions.  Instead,
 assign the parent interface name according to the mac address (the last
 three bytes) if no name was given by the caller and use the parent 
 interface
 name plus 'p' for the container name.
 I don't think it is a good idea. What it user defines MAC addresses in a
 way that the last three bytes are the same? E.g.

 00:11:22:33:44:55
 00:22:11:33:44:55

 (there are plenty of possibilities). With your code we would create
 veth334455 for the first domain and there's nothing left for the other
 one but eyes to cry.

 Sure, it's possible for the user to assign addresses like this, but I
 believe most mac addresses are assigned randomly, that's what libvirt does
 by default, no?  Also, it's possible for the user to override the interface
 name if they want to.  Currently it's only possible to set the first
 interface name, but there's no way to set the name of the second interface
 which causes failures because of races.  In any case it makes sense to set
 the second interface's name based on the first interface's name so we don't
 have to try to come up with two different unique names.

 Moreover, there's no race now, as we use global lock to mutually exclude
 call to virNetDevVethCreate. Although, I must admit it's only within a
 single driver, I think. So if there are two domains starting (one in
 qemu driver the other one in lxc, for instance) there can be race. But
 this should be solved in a different way then. The virNetDevVethCreate
 should be turned into virObjectLockable and a veth should be allocated
 by calling a method.

 I ran into this issue repeatedly when I tried to start multiple LXC domains
 simultaneously from my application (https://github.com/melor/poni) which
 runs libvirt operations in their own threads.

 
 It's easy to be resolved. give the parentVeth and containerVeth a name by 
 default.

At the moment virLXCProcessSetupInterfaceBridged always passes a NULL
for the container interface name and while it would be possible to make
it configurable like the parent interface name, I believe it makes more
sense to just do the right thing by default.

The suggested patch also greatly simplifies name selection by removing
the loops trying to find a supposedly unused interface name.  If you
don't like using mac address in the interface name we could just replace
it with a random string with a loop checking that the selected name
wasn't in use when it was selected.  The current approach of trying to
use a name with a low number just doesn't work in an environment where
another process does the same thing.

/ Oskari

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] virNetDevVethCreate: assign names based on mac address by default

2013-08-29 Thread Gao feng
On 08/29/2013 04:52 PM, Oskari Saarenmaa wrote:
 29.08.2013 11:36, Gao feng kirjoitti:
 On 08/29/2013 04:20 PM, Oskari Saarenmaa wrote:
 On Thu, Aug 29, 2013 at 10:10:36AM +0200, Michal Privoznik wrote:
 On 28.08.2013 23:05, Oskari Saarenmaa wrote:
 Interface names do not have to be numerical (or veth + number) and trying 
 to
 assign them to that format is susceptible to race conditions.  Instead,
 assign the parent interface name according to the mac address (the last
 three bytes) if no name was given by the caller and use the parent 
 interface
 name plus 'p' for the container name.
 I don't think it is a good idea. What it user defines MAC addresses in a
 way that the last three bytes are the same? E.g.

 00:11:22:33:44:55
 00:22:11:33:44:55

 (there are plenty of possibilities). With your code we would create
 veth334455 for the first domain and there's nothing left for the other
 one but eyes to cry.

 Sure, it's possible for the user to assign addresses like this, but I
 believe most mac addresses are assigned randomly, that's what libvirt does
 by default, no?  Also, it's possible for the user to override the interface
 name if they want to.  Currently it's only possible to set the first
 interface name, but there's no way to set the name of the second interface
 which causes failures because of races.  In any case it makes sense to set
 the second interface's name based on the first interface's name so we don't
 have to try to come up with two different unique names.

 Moreover, there's no race now, as we use global lock to mutually exclude
 call to virNetDevVethCreate. Although, I must admit it's only within a
 single driver, I think. So if there are two domains starting (one in
 qemu driver the other one in lxc, for instance) there can be race. But
 this should be solved in a different way then. The virNetDevVethCreate
 should be turned into virObjectLockable and a veth should be allocated
 by calling a method.

 I ran into this issue repeatedly when I tried to start multiple LXC domains
 simultaneously from my application (https://github.com/melor/poni) which
 runs libvirt operations in their own threads.


 It's easy to be resolved. give the parentVeth and containerVeth a name by 
 default.
 
 At the moment virLXCProcessSetupInterfaceBridged always passes a NULL
 for the container interface name and while it would be possible to make
 it configurable like the parent interface name, I believe it makes more
 sense to just do the right thing by default.
 

Agree.

 The suggested patch also greatly simplifies name selection by removing
 the loops trying to find a supposedly unused interface name.  If you
 don't like using mac address in the interface name we could just replace
 it with a random string with a loop checking that the selected name
 wasn't in use when it was selected.  The current approach of trying to
 use a name with a low number just doesn't work in an environment where
 another process does the same thing.
 

Use mac address to create an unique name is not a good idea,
I suggest you pass an index to virLXCProcessSetupInterfaceBridged.
use this index and domain_name to create an unique name.

Such as, for the first net interface for domain fedora19
parentVeth's name is fedora19-host-1, containerVeth is fedora19-container-1
for the second interface,
parentVeth's name is fedora19-host-2, containerVeth is fedora19-container-2
...

find out a proper name for these veth device :)

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] virNetDevVethCreate: assign names based on mac address by default

2013-08-29 Thread Oskari Saarenmaa
29.08.2013 12:11, Gao feng kirjoitti:
 The suggested patch also greatly simplifies name selection by removing
 the loops trying to find a supposedly unused interface name.  If you
 don't like using mac address in the interface name we could just replace
 it with a random string with a loop checking that the selected name
 wasn't in use when it was selected.  The current approach of trying to
 use a name with a low number just doesn't work in an environment where
 another process does the same thing.

 
 Use mac address to create an unique name is not a good idea,
 I suggest you pass an index to virLXCProcessSetupInterfaceBridged.
 use this index and domain_name to create an unique name.
 
 Such as, for the first net interface for domain fedora19
 parentVeth's name is fedora19-host-1, containerVeth is 
 fedora19-container-1
 for the second interface,
 parentVeth's name is fedora19-host-2, containerVeth is 
 fedora19-container-2
 ...
 
 find out a proper name for these veth device :)

Interface names are limited to 16 characters, so we can't really use the
full domain name there and I suppose it makes sense to prefix them with
veth.  That leaves 12 characters for the which is enough for a random
name that will effectively never collide with anything else, but I'd
still prefer naming them according to the mac address.  The randomly
generated address with 3 random bytes is unique enough to be used as a
mac address in a network - it should be unique enough to be used as an
interface name on a single host (and you can still override it in domain
configuration if you want to.)

/ Oskari

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] virNetDevVethCreate: assign names based on mac address by default

2013-08-29 Thread Daniel P. Berrange
On Thu, Aug 29, 2013 at 12:05:49AM +0300, Oskari Saarenmaa wrote:
 Interface names do not have to be numerical (or veth + number) and trying to
 assign them to that format is susceptible to race conditions.  Instead,
 assign the parent interface name according to the mac address (the last
 three bytes) if no name was given by the caller and use the parent interface
 name plus 'p' for the container name.
 
 Signed-off-by: Oskari Saarenmaa o...@ohmu.fi

NACK, I really don't like this proposed naming scheme. If there is a rac
with our current code we should be fixing that race.

Daniel
-- 
|: http://berrange.com  -o-http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org  -o- http://virt-manager.org :|
|: http://autobuild.org   -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org   -o-   http://live.gnome.org/gtk-vnc :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list