qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] add a command line option to specify the interf


From: Mike Ryan
Subject: Re: [Qemu-devel] [PATCH] add a command line option to specify the interface to send multicast packets on
Date: Mon, 15 Nov 2010 11:52:12 -0800
User-agent: Mutt/1.5.20 (2009-06-14)

I'll clarify/elaborate a bit:

When using a multicast socket, the OS chooses a default physical
interface to send packets. The patch I've supplied allows the user to
select the interface.

Suppose you have a setup like so:

BoxA --- BoxB --- BoxC

You wish to run virtual machines on BoxB and BoxC and network them using
a multicast UDP socket.

BoxB has two network interfaces, and the default multicast interface may
be the link between BoxA and BoxB. In this situation, BoxC will not
receive any multicast packets from BoxB and networking between the boxes
is therefore impossible.

The utility of a multicast socket is obviously limited in my simplified
example. Generalize BoxC to a LAN of physical machines all running
virtual machines you wish to network and the use case should become a
bit clearer.

On Mon, Nov 15, 2010 at 01:36:28PM -0600, Anthony Liguori wrote:
> On 11/15/2010 12:54 PM, Mike Ryan wrote:
> >Anyone care to comment?
> 
> I must admit, I don't understand the use-case well enough to really
> give an appropriate amount of review as to whether this is the best
> solution to the problem.
> 
> Michael, do you have any thoughts?
> 
> Regards,
> 
> Anthony Liguori
> 
> >On Wed, Nov 10, 2010 at 05:47:35PM -0800, Mike Ryan wrote:
> >>Add an option to specify the host interface to send multicast packets on
> >>when using a multicast socket for networking. The option takes the name
> >>of a host interface (e.g., eth0) and sets the IP_MULTICAST_IF socket
> >>option, which causes the packets to use that interface as an egress.
> >>
> >>This is useful if the host machine has several interfaces with several
> >>virtual networks across disparate interfaces.
> >>---
> >>  net.c           |    4 ++++
> >>  net/socket.c    |   48 ++++++++++++++++++++++++++++++++++++------------
> >>  qemu-common.h   |    1 +
> >>  qemu-options.hx |   11 +++++++++--
> >>  qemu_socket.h   |    1 +
> >>  5 files changed, 51 insertions(+), 14 deletions(-)
> >>
> >>diff --git a/net.c b/net.c
> >>index c5e6063..ff9eb27 100644
> >>--- a/net.c
> >>+++ b/net.c
> >>@@ -1050,6 +1050,10 @@ static const struct {
> >>                  .name = "mcast",
> >>                  .type = QEMU_OPT_STRING,
> >>                  .help = "UDP multicast address and port number",
> >>+            }, {
> >>+                .name = "interface",
> >>+                .type = QEMU_OPT_STRING,
> >>+                .help = "interface to send multicast packets on",
> >>              },
> >>              { /* end of list */ }
> >>          },
> >>diff --git a/net/socket.c b/net/socket.c
> >>index 1c4e153..ed7cd12 100644
> >>--- a/net/socket.c
> >>+++ b/net/socket.c
> >>@@ -149,11 +149,13 @@ static void net_socket_send_dgram(void *opaque)
> >>      qemu_send_packet(&s->nc, s->buf, size);
> >>  }
> >>
> >>-static int net_socket_mcast_create(struct sockaddr_in *mcastaddr)
> >>+static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, const 
> >>char *interface)
> >>  {
> >>      struct ip_mreq imr;
> >>      int fd;
> >>      int val, ret;
> >>+    struct in_addr maddr;
> >>+    struct ifreq ifr;
> >>      if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
> >>    fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) does 
> >> not contain a multicast address\n",
> >>            inet_ntoa(mcastaddr->sin_addr),
> >>@@ -201,6 +203,23 @@ static int net_socket_mcast_create(struct sockaddr_in 
> >>*mcastaddr)
> >>    goto fail;
> >>      }
> >>
> >>+    /* If an interface name is given, only send packets out that interface 
> >>*/
> >>+    if (interface != NULL) {
> >>+        strncpy(ifr.ifr_name, interface, IFNAMSIZ);
> >>+        ret = ioctl(fd, SIOCGIFADDR,&ifr);
> >>+        if (ret<  0) {
> >>+            fprintf(stderr, "qemu: error: specified interface \"%s\" does 
> >>not exist\n", interface);
> >>+            goto fail;
> >>+        }
> >>+
> >>+        maddr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
> >>+        ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,&maddr, 
> >>sizeof(maddr));
> >>+        if (ret<  0) {
> >>+            perror("setsockopt(IP_MULTICAST_IF)");
> >>+            goto fail;
> >>+        }
> >>+    }
> >>+
> >>      socket_set_nonblock(fd);
> >>      return fd;
> >>  fail:
> >>@@ -248,7 +267,7 @@ static NetSocketState 
> >>*net_socket_fd_init_dgram(VLANState *vlan,
> >>            return NULL;
> >>        }
> >>        /* clone dgram socket */
> >>-       newfd = net_socket_mcast_create(&saddr);
> >>+       newfd = net_socket_mcast_create(&saddr, NULL);
> >>        if (newfd<  0) {
> >>            /* error already reported by net_socket_mcast_create() */
> >>            close(fd);
> >>@@ -468,7 +487,8 @@ static int net_socket_connect_init(VLANState *vlan,
> >>  static int net_socket_mcast_init(VLANState *vlan,
> >>                                   const char *model,
> >>                                   const char *name,
> >>-                                 const char *host_str)
> >>+                                 const char *host_str,
> >>+                                 const char *interface)
> >>  {
> >>      NetSocketState *s;
> >>      int fd;
> >>@@ -478,7 +498,7 @@ static int net_socket_mcast_init(VLANState *vlan,
> >>          return -1;
> >>
> >>
> >>-    fd = net_socket_mcast_create(&saddr);
> >>+    fd = net_socket_mcast_create(&saddr, interface);
> >>      if (fd<  0)
> >>    return -1;
> >>
> >>@@ -505,8 +525,9 @@ int net_init_socket(QemuOpts *opts,
> >>
> >>          if (qemu_opt_get(opts, "listen") ||
> >>              qemu_opt_get(opts, "connect") ||
> >>-            qemu_opt_get(opts, "mcast")) {
> >>-            error_report("listen=, connect= and mcast= is invalid with 
> >>fd=");
> >>+            qemu_opt_get(opts, "mcast") ||
> >>+            qemu_opt_get(opts, "interface")) {
> >>+            error_report("listen=, connect=, mcast= and interface= is 
> >>invalid with fd=\n");
> >>              return -1;
> >>          }
> >>
> >>@@ -524,8 +545,9 @@ int net_init_socket(QemuOpts *opts,
> >>
> >>          if (qemu_opt_get(opts, "fd") ||
> >>              qemu_opt_get(opts, "connect") ||
> >>-            qemu_opt_get(opts, "mcast")) {
> >>-            error_report("fd=, connect= and mcast= is invalid with 
> >>listen=");
> >>+            qemu_opt_get(opts, "mcast") ||
> >>+            qemu_opt_get(opts, "interface")) {
> >>+            error_report("fd=, connect=, mcast= and interface= is invalid 
> >>with listen=\n");
> >>              return -1;
> >>          }
> >>
> >>@@ -539,8 +561,9 @@ int net_init_socket(QemuOpts *opts,
> >>
> >>          if (qemu_opt_get(opts, "fd") ||
> >>              qemu_opt_get(opts, "listen") ||
> >>-            qemu_opt_get(opts, "mcast")) {
> >>-            error_report("fd=, listen= and mcast= is invalid with 
> >>connect=");
> >>+            qemu_opt_get(opts, "mcast") ||
> >>+            qemu_opt_get(opts, "interface")) {
> >>+            error_report("fd=, listen=, mcast= and interface= is invalid 
> >>with connect=\n");
> >>              return -1;
> >>          }
> >>
> >>@@ -550,7 +573,7 @@ int net_init_socket(QemuOpts *opts,
> >>              return -1;
> >>          }
> >>      } else if (qemu_opt_get(opts, "mcast")) {
> >>-        const char *mcast;
> >>+        const char *mcast, *interface;
> >>
> >>          if (qemu_opt_get(opts, "fd") ||
> >>              qemu_opt_get(opts, "connect") ||
> >>@@ -560,8 +583,9 @@ int net_init_socket(QemuOpts *opts,
> >>          }
> >>
> >>          mcast = qemu_opt_get(opts, "mcast");
> >>+        interface = qemu_opt_get(opts, "interface");
> >>
> >>-        if (net_socket_mcast_init(vlan, "socket", name, mcast) == -1) {
> >>+        if (net_socket_mcast_init(vlan, "socket", name, mcast, interface) 
> >>== -1) {
> >>              return -1;
> >>          }
> >>      } else {
> >>diff --git a/qemu-common.h b/qemu-common.h
> >>index b3957f1..e8bc4af 100644
> >>--- a/qemu-common.h
> >>+++ b/qemu-common.h
> >>@@ -34,6 +34,7 @@ typedef struct DeviceState DeviceState;
> >>  #include<fcntl.h>
> >>  #include<sys/stat.h>
> >>  #include<assert.h>
> >>+#include<sys/ioctl.h>
> >>
> >>  #ifndef O_LARGEFILE
> >>  #define O_LARGEFILE 0
> >>diff --git a/qemu-options.hx b/qemu-options.hx
> >>index 4d99a58..e2c4cfa 100644
> >>--- a/qemu-options.hx
> >>+++ b/qemu-options.hx
> >>@@ -1061,8 +1061,9 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
> >>  #endif
> >>      "-net 
> >> socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n"
> >>      "                connect the vlan 'n' to another VLAN using a socket 
> >> connection\n"
> >>-    "-net socket[,vlan=n][,name=str][,fd=h][,mcast=maddr:port]\n"
> >>+    "-net 
> >>socket[,vlan=n][,name=str][,fd=h][,mcast=maddr:port[,interface=ifname]]\n"
> >>      "                connect the vlan 'n' to multicast maddr and port\n"
> >>+    "                use 'interface=ifname' to specify the host interface 
> >>to send packets on\n"
> >>  #ifdef CONFIG_VDE
> >>      "-net 
> >> vde[,vlan=n][,name=str][,sock=socketpath][,port=n][,group=groupname][,mode=octalmode]\n"
> >>      "                connect the vlan 'n' to port 'n' of a vde switch 
> >> running\n"
> >>@@ -1256,7 +1257,7 @@ qemu linux.img -net nic,macaddr=52:54:00:12:34:57 \
> >>                 -net socket,connect=127.0.0.1:1234
> >>  @end example
> >>
> >>address@hidden -net socket[,address@hidden,address@hidden,address@hidden 
> >>[,address@hidden:@var{port}]
> >>address@hidden -net 
> >>socket[,address@hidden,address@hidden,address@hidden,address@hidden:@var{port}[,address@hidden
> >>
> >>  Create a VLAN @var{n} shared with another QEMU virtual
> >>  machines using a UDP multicast socket, effectively making a bus for
> >>@@ -1296,6 +1297,12 @@ qemu linux.img -net nic,macaddr=52:54:00:12:34:56 \
> >>  /path/to/linux ubd0=/path/to/root_fs eth0=mcast
> >>  @end example
> >>
> >>+Example (send packets on host's eth0):
> >>address@hidden
> >>+qemu linux.img -net nic,macaddr=52:54:00:12:34:56 \
> >>+               -net socket,mcast=239.192.168.1:1102,interface=eth0
> >>address@hidden example
> >>+
> >>  @item -net vde[,address@hidden,address@hidden,address@hidden 
> >> [,address@hidden,address@hidden,address@hidden
> >>  Connect VLAN @var{n} to PORT @var{n} of a vde switch running on host and
> >>  listening for incoming connections on @var{socketpath}. Use GROUP 
> >> @var{groupname}
> >>diff --git a/qemu_socket.h b/qemu_socket.h
> >>index 897a8ae..5116e4a 100644
> >>--- a/qemu_socket.h
> >>+++ b/qemu_socket.h
> >>@@ -24,6 +24,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
> >>  #include<arpa/inet.h>
> >>  #include<netdb.h>
> >>  #include<sys/un.h>
> >>+#include<net/if.h>
> >>
> >>  #define socket_error() errno
> >>  #define closesocket(s) close(s)
> >>-- 
> >>1.7.0.4
> >>
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]