From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=55950 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PIQKg-0001IR-21 for qemu-devel@nongnu.org; Tue, 16 Nov 2010 13:32:43 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PIQKe-0000s9-E8 for qemu-devel@nongnu.org; Tue, 16 Nov 2010 13:32:41 -0500 Received: from mx1.redhat.com ([209.132.183.28]:31784) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PIQKe-0000ry-1K for qemu-devel@nongnu.org; Tue, 16 Nov 2010 13:32:40 -0500 Date: Tue, 16 Nov 2010 19:54:58 +0200 From: "Michael S. Tsirkin" Message-ID: <20101116175458.GD4077@redhat.com> References: <20101111014735.GQ2211@zzz.isi.edu> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20101111014735.GQ2211@zzz.isi.edu> Subject: [Qemu-devel] Re: [PATCH] add a command line option to specify the interface to send multicast packets on List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Mike Ryan Cc: qemu-devel@nongnu.org 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. > @@ -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; > + } Let's let the user pass in the IP address? That would solve the portability issue. Further, we could be doing IPv6, right? So you'd need IPV6_MULTICAST_IF? Also - you might also want to control IP_MULTICAST_LOOP/IPV6_MULTICAST_LOOP? > + } > + > 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 > #include > #include > +#include > > #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 > > -@item -net socket[,vlan=@var{n}][,name=@var{name}][,fd=@var{h}] [,mcast=@var{maddr}:@var{port}] > +@item -net socket[,vlan=@var{n}][,name=@var{name}][,fd=@var{h}][,mcast=@var{maddr}:@var{port}[,interface=@var{ifname}]] > > 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): > +@example > +qemu linux.img -net nic,macaddr=52:54:00:12:34:56 \ > + -net socket,mcast=239.192.168.1:1102,interface=eth0 > +@end example > + > @item -net vde[,vlan=@var{n}][,name=@var{name}][,sock=@var{socketpath}] [,port=@var{n}][,group=@var{groupname}][,mode=@var{octalmode}] > 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 > #include > #include > +#include > > #define socket_error() errno > #define closesocket(s) close(s) > -- > 1.7.0.4 >