* [Qemu-devel] [PATCH] add a command line option to specify the interface to send multicast packets on @ 2010-11-11 1:47 Mike Ryan 2010-11-15 18:54 ` Mike Ryan 2010-11-16 17:54 ` Michael S. Tsirkin 0 siblings, 2 replies; 18+ messages in thread From: Mike Ryan @ 2010-11-11 1:47 UTC (permalink / raw) To: qemu-devel 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 -@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 <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 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] add a command line option to specify the interface to send multicast packets on 2010-11-11 1:47 [Qemu-devel] [PATCH] add a command line option to specify the interface to send multicast packets on Mike Ryan @ 2010-11-15 18:54 ` Mike Ryan 2010-11-15 19:36 ` Anthony Liguori 2010-11-16 17:54 ` Michael S. Tsirkin 1 sibling, 1 reply; 18+ messages in thread From: Mike Ryan @ 2010-11-15 18:54 UTC (permalink / raw) To: qemu-devel Anyone care to comment? 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 > > -@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 <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 > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] add a command line option to specify the interface to send multicast packets on 2010-11-15 18:54 ` Mike Ryan @ 2010-11-15 19:36 ` Anthony Liguori 2010-11-15 19:52 ` Mike Ryan 0 siblings, 1 reply; 18+ messages in thread From: Anthony Liguori @ 2010-11-15 19:36 UTC (permalink / raw) To: Mike Ryan; +Cc: qemu-devel, Michael S. Tsirkin 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 >> >> -@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<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 >> >> > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] add a command line option to specify the interface to send multicast packets on 2010-11-15 19:36 ` Anthony Liguori @ 2010-11-15 19:52 ` Mike Ryan 2010-11-15 21:07 ` Anthony Liguori 0 siblings, 1 reply; 18+ messages in thread From: Mike Ryan @ 2010-11-15 19:52 UTC (permalink / raw) To: qemu-devel 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 > >> > >>-@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<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 > >> > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] add a command line option to specify the interface to send multicast packets on 2010-11-15 19:52 ` Mike Ryan @ 2010-11-15 21:07 ` Anthony Liguori 2010-11-15 21:22 ` Stefan Weil 2010-11-15 21:34 ` Mike Ryan 0 siblings, 2 replies; 18+ messages in thread From: Anthony Liguori @ 2010-11-15 21:07 UTC (permalink / raw) To: Mike Ryan; +Cc: qemu-devel On 11/15/2010 01:52 PM, Mike Ryan wrote: > 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. > Thanks. Second question is how portable is SIOCGIFADDR? I suspect that's very Linux-centric.. Regards, Anthony Liguori > 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 >>>> >>>> -@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<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 >>>> >>>> >> > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] add a command line option to specify the interface to send multicast packets on 2010-11-15 21:07 ` Anthony Liguori @ 2010-11-15 21:22 ` Stefan Weil 2010-11-15 21:34 ` Mike Ryan 1 sibling, 0 replies; 18+ messages in thread From: Stefan Weil @ 2010-11-15 21:22 UTC (permalink / raw) To: Anthony Liguori; +Cc: Mike Ryan, qemu-devel Am 15.11.2010 22:07, schrieb Anthony Liguori: > On 11/15/2010 01:52 PM, Mike Ryan wrote: >> 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. > > Thanks. Second question is how portable is SIOCGIFADDR? I suspect > that's very Linux-centric.. > > Regards, > > Anthony Liguori Yes. It is unavailable for mingw32 (windows). Regards, Stefan Weil ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] add a command line option to specify the interface to send multicast packets on 2010-11-15 21:07 ` Anthony Liguori 2010-11-15 21:22 ` Stefan Weil @ 2010-11-15 21:34 ` Mike Ryan 2010-11-16 9:26 ` [Qemu-devel] " Paolo Bonzini 1 sibling, 1 reply; 18+ messages in thread From: Mike Ryan @ 2010-11-15 21:34 UTC (permalink / raw) To: qemu-devel On Mon, Nov 15, 2010 at 03:07:51PM -0600, Anthony Liguori wrote: <snip> > Thanks. Second question is how portable is SIOCGIFADDR? I suspect > that's very Linux-centric.. It ostensibly exists in FreeBSD, but I can't get master to compile under 7.3-RELEASE or 8.1-STABLE. Given that it is unavailable on at least one platform (mingw32) it sounds like it should be detected in configure. However configure doesn't appear to be generated from autoconf/automake. Is it a custom build system? ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] Re: [PATCH] add a command line option to specify the interface to send multicast packets on 2010-11-15 21:34 ` Mike Ryan @ 2010-11-16 9:26 ` Paolo Bonzini 0 siblings, 0 replies; 18+ messages in thread From: Paolo Bonzini @ 2010-11-16 9:26 UTC (permalink / raw) To: Mike Ryan; +Cc: qemu-devel On 11/15/2010 10:34 PM, Mike Ryan wrote: > Given that it is unavailable on at least one platform (mingw32) it > sounds like it should be detected in configure. However configure > doesn't appear to be generated from autoconf/automake. Is it a custom > build system? Yes, but I think #ifndef _WIN32 is enough in this case, as it is what is used in the rest of QEMU for sys/ioctl.h stuff. In Win32 you would use this: http://msdn.microsoft.com/en-us/library/aa365915%28v=VS.85%29.aspx Paolo ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] Re: [PATCH] add a command line option to specify the interface to send multicast packets on 2010-11-11 1:47 [Qemu-devel] [PATCH] add a command line option to specify the interface to send multicast packets on Mike Ryan 2010-11-15 18:54 ` Mike Ryan @ 2010-11-16 17:54 ` Michael S. Tsirkin 2010-11-16 19:10 ` Mike Ryan 1 sibling, 1 reply; 18+ messages in thread From: Michael S. Tsirkin @ 2010-11-16 17:54 UTC (permalink / raw) To: Mike Ryan; +Cc: qemu-devel 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 <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 > > -@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 <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 > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] Re: [PATCH] add a command line option to specify the interface to send multicast packets on 2010-11-16 17:54 ` Michael S. Tsirkin @ 2010-11-16 19:10 ` Mike Ryan 2010-11-18 1:16 ` [Qemu-devel] [PATCH] add a command line option to specify the IP address to send multicast packets from Mike Ryan 0 siblings, 1 reply; 18+ messages in thread From: Mike Ryan @ 2010-11-16 19:10 UTC (permalink / raw) To: qemu-devel On Tue, Nov 16, 2010 at 07:54:58PM +0200, Michael S. Tsirkin wrote: > > <snip> > > 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? IP address seems like a good alternative and does indeed get rid of the messy platform-specific bits. The multicast code all assumes IPv4. For instance, it uses v4-only parse_host_port to get the multicast destination address. Given that, I'm not going to bother shoehorning in IPV6_MULTICAST_IF. ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] add a command line option to specify the IP address to send multicast packets from 2010-11-16 19:10 ` Mike Ryan @ 2010-11-18 1:16 ` Mike Ryan 2010-11-22 18:48 ` Mike Ryan 2010-11-24 5:32 ` [Qemu-devel] " Michael S. Tsirkin 0 siblings, 2 replies; 18+ messages in thread From: Mike Ryan @ 2010-11-18 1:16 UTC (permalink / raw) To: qemu-devel Add an option to specify the host IP to send multicast packets from when using a multicast socket for networking. The option takes an IP address and sets the IP_MULTICAST_IF socket option, which causes the packets to use that IP's 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 | 46 ++++++++++++++++++++++++++++++++++------------ qemu-options.hx | 11 +++++++++-- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/net.c b/net.c index c5e6063..9ba5be2 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 = "localaddr", + .type = QEMU_OPT_STRING, + .help = "source address for multicast packets", }, { /* end of list */ } }, diff --git a/net/socket.c b/net/socket.c index 1c4e153..d443f4c 100644 --- a/net/socket.c +++ b/net/socket.c @@ -149,7 +149,7 @@ 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, struct in_addr *localaddr) { struct ip_mreq imr; int fd; @@ -201,6 +201,15 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) goto fail; } + /* If a bind address is given, only send packets from that address */ + if (localaddr != NULL) { + ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, localaddr, sizeof(*localaddr)); + if (ret < 0) { + perror("setsockopt(IP_MULTICAST_IF)"); + goto fail; + } + } + socket_set_nonblock(fd); return fd; fail: @@ -248,7 +257,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,17 +477,26 @@ 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 *localaddr_str) { NetSocketState *s; int fd; struct sockaddr_in saddr; + struct in_addr localaddr, *param_localaddr; if (parse_host_port(&saddr, host_str) < 0) return -1; + if (localaddr_str != NULL) { + if (inet_aton(localaddr_str, &localaddr) == 0) + return -1; + param_localaddr = &localaddr; + } else { + param_localaddr = NULL; + } - fd = net_socket_mcast_create(&saddr); + fd = net_socket_mcast_create(&saddr, param_localaddr); if (fd < 0) return -1; @@ -505,8 +523,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, "localaddr")) { + error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=\n"); return -1; } @@ -524,8 +543,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, "localaddr")) { + error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=\n"); return -1; } @@ -539,8 +559,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, "localaddr")) { + error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=\n"); return -1; } @@ -550,7 +571,7 @@ int net_init_socket(QemuOpts *opts, return -1; } } else if (qemu_opt_get(opts, "mcast")) { - const char *mcast; + const char *mcast, *localaddr; if (qemu_opt_get(opts, "fd") || qemu_opt_get(opts, "connect") || @@ -560,8 +581,9 @@ int net_init_socket(QemuOpts *opts, } mcast = qemu_opt_get(opts, "mcast"); + localaddr = qemu_opt_get(opts, "localaddr"); - if (net_socket_mcast_init(vlan, "socket", name, mcast) == -1) { + if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) { return -1; } } else { diff --git a/qemu-options.hx b/qemu-options.hx index 4d99a58..accd16a 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[,localaddr=addr]]\n" " connect the vlan 'n' to multicast maddr and port\n" + " use 'localaddr=addr' to specify the host address to send packets from\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}[,localaddr=@var{addr}]] 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 from host's 1.2.3.4): +@example +qemu linux.img -net nic,macaddr=52:54:00:12:34:56 \ + -net socket,mcast=239.192.168.1:1102,localaddr=1.2.3.4 +@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} -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] add a command line option to specify the IP address to send multicast packets from 2010-11-18 1:16 ` [Qemu-devel] [PATCH] add a command line option to specify the IP address to send multicast packets from Mike Ryan @ 2010-11-22 18:48 ` Mike Ryan 2010-11-23 13:05 ` Michael S. Tsirkin 2010-11-24 5:32 ` [Qemu-devel] " Michael S. Tsirkin 1 sibling, 1 reply; 18+ messages in thread From: Mike Ryan @ 2010-11-22 18:48 UTC (permalink / raw) To: qemu-devel; +Cc: Michael S. Tsirkin Michael, this patch implements the feature with a bind address instead of a bind interface. It should address the cross-platform issues that were raised. Others: any comments? On Wed, Nov 17, 2010 at 05:16:26PM -0800, Mike Ryan wrote: > Add an option to specify the host IP to send multicast packets from when > using a multicast socket for networking. The option takes an IP address > and sets the IP_MULTICAST_IF socket option, which causes the packets to > use that IP's 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 | 46 ++++++++++++++++++++++++++++++++++------------ > qemu-options.hx | 11 +++++++++-- > 3 files changed, 47 insertions(+), 14 deletions(-) > > diff --git a/net.c b/net.c > index c5e6063..9ba5be2 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 = "localaddr", > + .type = QEMU_OPT_STRING, > + .help = "source address for multicast packets", > }, > { /* end of list */ } > }, > diff --git a/net/socket.c b/net/socket.c > index 1c4e153..d443f4c 100644 > --- a/net/socket.c > +++ b/net/socket.c > @@ -149,7 +149,7 @@ 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, struct in_addr *localaddr) > { > struct ip_mreq imr; > int fd; > @@ -201,6 +201,15 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) > goto fail; > } > > + /* If a bind address is given, only send packets from that address */ > + if (localaddr != NULL) { > + ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, localaddr, sizeof(*localaddr)); > + if (ret < 0) { > + perror("setsockopt(IP_MULTICAST_IF)"); > + goto fail; > + } > + } > + > socket_set_nonblock(fd); > return fd; > fail: > @@ -248,7 +257,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,17 +477,26 @@ 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 *localaddr_str) > { > NetSocketState *s; > int fd; > struct sockaddr_in saddr; > + struct in_addr localaddr, *param_localaddr; > > if (parse_host_port(&saddr, host_str) < 0) > return -1; > > + if (localaddr_str != NULL) { > + if (inet_aton(localaddr_str, &localaddr) == 0) > + return -1; > + param_localaddr = &localaddr; > + } else { > + param_localaddr = NULL; > + } > > - fd = net_socket_mcast_create(&saddr); > + fd = net_socket_mcast_create(&saddr, param_localaddr); > if (fd < 0) > return -1; > > @@ -505,8 +523,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, "localaddr")) { > + error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=\n"); > return -1; > } > > @@ -524,8 +543,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, "localaddr")) { > + error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=\n"); > return -1; > } > > @@ -539,8 +559,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, "localaddr")) { > + error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=\n"); > return -1; > } > > @@ -550,7 +571,7 @@ int net_init_socket(QemuOpts *opts, > return -1; > } > } else if (qemu_opt_get(opts, "mcast")) { > - const char *mcast; > + const char *mcast, *localaddr; > > if (qemu_opt_get(opts, "fd") || > qemu_opt_get(opts, "connect") || > @@ -560,8 +581,9 @@ int net_init_socket(QemuOpts *opts, > } > > mcast = qemu_opt_get(opts, "mcast"); > + localaddr = qemu_opt_get(opts, "localaddr"); > > - if (net_socket_mcast_init(vlan, "socket", name, mcast) == -1) { > + if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) { > return -1; > } > } else { > diff --git a/qemu-options.hx b/qemu-options.hx > index 4d99a58..accd16a 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[,localaddr=addr]]\n" > " connect the vlan 'n' to multicast maddr and port\n" > + " use 'localaddr=addr' to specify the host address to send packets from\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}[,localaddr=@var{addr}]] > > 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 from host's 1.2.3.4): > +@example > +qemu linux.img -net nic,macaddr=52:54:00:12:34:56 \ > + -net socket,mcast=239.192.168.1:1102,localaddr=1.2.3.4 > +@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} > -- > 1.7.0.4 > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] add a command line option to specify the IP address to send multicast packets from 2010-11-22 18:48 ` Mike Ryan @ 2010-11-23 13:05 ` Michael S. Tsirkin 2010-11-23 23:49 ` Mike Ryan 0 siblings, 1 reply; 18+ messages in thread From: Michael S. Tsirkin @ 2010-11-23 13:05 UTC (permalink / raw) To: Mike Ryan; +Cc: qemu-devel On Mon, Nov 22, 2010 at 10:48:45AM -0800, Mike Ryan wrote: > Michael, this patch implements the feature with a bind address instead > of a bind interface. It should address the cross-platform issues that > were raised. > > Others: any comments? Looks ok. This does not handle IPv6 but the rest of the code doesn't, either. > On Wed, Nov 17, 2010 at 05:16:26PM -0800, Mike Ryan wrote: > > Add an option to specify the host IP to send multicast packets from when > > using a multicast socket for networking. The option takes an IP address > > and sets the IP_MULTICAST_IF socket option, which causes the packets to > > use that IP's 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 | 46 ++++++++++++++++++++++++++++++++++------------ > > qemu-options.hx | 11 +++++++++-- > > 3 files changed, 47 insertions(+), 14 deletions(-) > > > > diff --git a/net.c b/net.c > > index c5e6063..9ba5be2 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 = "localaddr", > > + .type = QEMU_OPT_STRING, > > + .help = "source address for multicast packets", > > }, > > { /* end of list */ } > > }, > > diff --git a/net/socket.c b/net/socket.c > > index 1c4e153..d443f4c 100644 > > --- a/net/socket.c > > +++ b/net/socket.c > > @@ -149,7 +149,7 @@ 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, struct in_addr *localaddr) > > { > > struct ip_mreq imr; > > int fd; > > @@ -201,6 +201,15 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) > > goto fail; > > } > > > > + /* If a bind address is given, only send packets from that address */ > > + if (localaddr != NULL) { > > + ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, localaddr, sizeof(*localaddr)); > > + if (ret < 0) { > > + perror("setsockopt(IP_MULTICAST_IF)"); > > + goto fail; > > + } > > + } > > + > > socket_set_nonblock(fd); > > return fd; > > fail: > > @@ -248,7 +257,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,17 +477,26 @@ 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 *localaddr_str) > > { > > NetSocketState *s; > > int fd; > > struct sockaddr_in saddr; > > + struct in_addr localaddr, *param_localaddr; > > > > if (parse_host_port(&saddr, host_str) < 0) > > return -1; > > > > + if (localaddr_str != NULL) { > > + if (inet_aton(localaddr_str, &localaddr) == 0) > > + return -1; > > + param_localaddr = &localaddr; > > + } else { > > + param_localaddr = NULL; > > + } > > > > - fd = net_socket_mcast_create(&saddr); > > + fd = net_socket_mcast_create(&saddr, param_localaddr); > > if (fd < 0) > > return -1; > > > > @@ -505,8 +523,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, "localaddr")) { > > + error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=\n"); > > return -1; > > } > > > > @@ -524,8 +543,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, "localaddr")) { > > + error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=\n"); > > return -1; > > } > > > > @@ -539,8 +559,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, "localaddr")) { > > + error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=\n"); > > return -1; > > } > > > > @@ -550,7 +571,7 @@ int net_init_socket(QemuOpts *opts, > > return -1; > > } > > } else if (qemu_opt_get(opts, "mcast")) { > > - const char *mcast; > > + const char *mcast, *localaddr; > > > > if (qemu_opt_get(opts, "fd") || > > qemu_opt_get(opts, "connect") || > > @@ -560,8 +581,9 @@ int net_init_socket(QemuOpts *opts, > > } > > > > mcast = qemu_opt_get(opts, "mcast"); > > + localaddr = qemu_opt_get(opts, "localaddr"); > > > > - if (net_socket_mcast_init(vlan, "socket", name, mcast) == -1) { > > + if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) { > > return -1; > > } > > } else { > > diff --git a/qemu-options.hx b/qemu-options.hx > > index 4d99a58..accd16a 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[,localaddr=addr]]\n" > > " connect the vlan 'n' to multicast maddr and port\n" > > + " use 'localaddr=addr' to specify the host address to send packets from\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}[,localaddr=@var{addr}]] > > > > 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 from host's 1.2.3.4): > > +@example > > +qemu linux.img -net nic,macaddr=52:54:00:12:34:56 \ > > + -net socket,mcast=239.192.168.1:1102,localaddr=1.2.3.4 > > +@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} > > -- > > 1.7.0.4 > > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] add a command line option to specify the IP address to send multicast packets from 2010-11-23 13:05 ` Michael S. Tsirkin @ 2010-11-23 23:49 ` Mike Ryan 0 siblings, 0 replies; 18+ messages in thread From: Mike Ryan @ 2010-11-23 23:49 UTC (permalink / raw) To: Michael S. Tsirkin; +Cc: qemu-devel On Tue, Nov 23, 2010 at 03:05:49PM +0200, Michael S. Tsirkin wrote: > On Mon, Nov 22, 2010 at 10:48:45AM -0800, Mike Ryan wrote: > > Michael, this patch implements the feature with a bind address instead > > of a bind interface. It should address the cross-platform issues that > > were raised. > > > > Others: any comments? > > Looks ok. This does not handle IPv6 but the rest of the code doesn't, > either. Great, is there anything I can do to expedite the process of getting it committed into master? ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] Re: [PATCH] add a command line option to specify the IP address to send multicast packets from 2010-11-18 1:16 ` [Qemu-devel] [PATCH] add a command line option to specify the IP address to send multicast packets from Mike Ryan 2010-11-22 18:48 ` Mike Ryan @ 2010-11-24 5:32 ` Michael S. Tsirkin 2010-11-29 19:12 ` [Qemu-devel] " Mike Ryan 1 sibling, 1 reply; 18+ messages in thread From: Michael S. Tsirkin @ 2010-11-24 5:32 UTC (permalink / raw) To: Mike Ryan; +Cc: qemu-devel On Wed, Nov 17, 2010 at 05:16:26PM -0800, Mike Ryan wrote: > Add an option to specify the host IP to send multicast packets from when > using a multicast socket for networking. The option takes an IP address > and sets the IP_MULTICAST_IF socket option, which causes the packets to > use that IP's interface as an egress. > > This is useful if the host machine has several interfaces with several > virtual networks across disparate interfaces. Please sign your work: ------------------- The sign-off is a simple line at the end of the explanation for the patch, which certifies that you wrote it or otherwise have the right to pass it on as a open-source patch. The rules are pretty simple: if you can certify the below: Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. then you just add a line saying Signed-off-by: Random J Developer <random@developer.example.org> using your real name (sorry, no pseudonyms or anonymous contributions.) Some people also put extra tags at the end. They'll just be ignored for now, but you can do this to mark internal company procedures or just point out some special detail about the sign-off. ------------------- > --- > net.c | 4 ++++ > net/socket.c | 46 ++++++++++++++++++++++++++++++++++------------ > qemu-options.hx | 11 +++++++++-- > 3 files changed, 47 insertions(+), 14 deletions(-) > > diff --git a/net.c b/net.c > index c5e6063..9ba5be2 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 = "localaddr", > + .type = QEMU_OPT_STRING, > + .help = "source address for multicast packets", > }, > { /* end of list */ } > }, > diff --git a/net/socket.c b/net/socket.c > index 1c4e153..d443f4c 100644 > --- a/net/socket.c > +++ b/net/socket.c > @@ -149,7 +149,7 @@ 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, struct in_addr *localaddr) > { > struct ip_mreq imr; > int fd; > @@ -201,6 +201,15 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) > goto fail; > } > > + /* If a bind address is given, only send packets from that address */ > + if (localaddr != NULL) { > + ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, localaddr, sizeof(*localaddr)); > + if (ret < 0) { > + perror("setsockopt(IP_MULTICAST_IF)"); > + goto fail; > + } > + } > + > socket_set_nonblock(fd); > return fd; > fail: > @@ -248,7 +257,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,17 +477,26 @@ 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 *localaddr_str) > { > NetSocketState *s; > int fd; > struct sockaddr_in saddr; > + struct in_addr localaddr, *param_localaddr; > > if (parse_host_port(&saddr, host_str) < 0) > return -1; > > + if (localaddr_str != NULL) { > + if (inet_aton(localaddr_str, &localaddr) == 0) > + return -1; > + param_localaddr = &localaddr; > + } else { > + param_localaddr = NULL; > + } > > - fd = net_socket_mcast_create(&saddr); > + fd = net_socket_mcast_create(&saddr, param_localaddr); > if (fd < 0) > return -1; > > @@ -505,8 +523,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, "localaddr")) { > + error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=\n"); > return -1; > } > > @@ -524,8 +543,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, "localaddr")) { > + error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=\n"); > return -1; > } > > @@ -539,8 +559,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, "localaddr")) { > + error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=\n"); > return -1; > } > > @@ -550,7 +571,7 @@ int net_init_socket(QemuOpts *opts, > return -1; > } > } else if (qemu_opt_get(opts, "mcast")) { > - const char *mcast; > + const char *mcast, *localaddr; > > if (qemu_opt_get(opts, "fd") || > qemu_opt_get(opts, "connect") || > @@ -560,8 +581,9 @@ int net_init_socket(QemuOpts *opts, > } > > mcast = qemu_opt_get(opts, "mcast"); > + localaddr = qemu_opt_get(opts, "localaddr"); > > - if (net_socket_mcast_init(vlan, "socket", name, mcast) == -1) { > + if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) { > return -1; > } > } else { > diff --git a/qemu-options.hx b/qemu-options.hx > index 4d99a58..accd16a 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[,localaddr=addr]]\n" > " connect the vlan 'n' to multicast maddr and port\n" > + " use 'localaddr=addr' to specify the host address to send packets from\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}[,localaddr=@var{addr}]] > > 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 from host's 1.2.3.4): > +@example > +qemu linux.img -net nic,macaddr=52:54:00:12:34:56 \ > + -net socket,mcast=239.192.168.1:1102,localaddr=1.2.3.4 > +@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} > -- > 1.7.0.4 > ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] add a command line option to specify the IP address to send multicast packets from 2010-11-24 5:32 ` [Qemu-devel] " Michael S. Tsirkin @ 2010-11-29 19:12 ` Mike Ryan 2010-12-01 19:16 ` Mike Ryan 0 siblings, 1 reply; 18+ messages in thread From: Mike Ryan @ 2010-11-29 19:12 UTC (permalink / raw) To: Michael S. Tsirkin; +Cc: qemu-devel Add an option to specify the host IP to send multicast packets from when using a multicast socket for networking. The option takes an IP address and sets the IP_MULTICAST_IF socket option, which causes the packets to use that IP's interface as an egress. This is useful if the host machine has several interfaces with several virtual networks across disparate interfaces. Signed-off-by: Mike Ryan <mikeryan@ISI.EDU> --- net.c | 4 ++++ net/socket.c | 46 ++++++++++++++++++++++++++++++++++------------ qemu-options.hx | 11 +++++++++-- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/net.c b/net.c index c5e6063..9ba5be2 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 = "localaddr", + .type = QEMU_OPT_STRING, + .help = "source address for multicast packets", }, { /* end of list */ } }, diff --git a/net/socket.c b/net/socket.c index 1c4e153..d443f4c 100644 --- a/net/socket.c +++ b/net/socket.c @@ -149,7 +149,7 @@ 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, struct in_addr *localaddr) { struct ip_mreq imr; int fd; @@ -201,6 +201,15 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) goto fail; } + /* If a bind address is given, only send packets from that address */ + if (localaddr != NULL) { + ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, localaddr, sizeof(*localaddr)); + if (ret < 0) { + perror("setsockopt(IP_MULTICAST_IF)"); + goto fail; + } + } + socket_set_nonblock(fd); return fd; fail: @@ -248,7 +257,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,17 +477,26 @@ 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 *localaddr_str) { NetSocketState *s; int fd; struct sockaddr_in saddr; + struct in_addr localaddr, *param_localaddr; if (parse_host_port(&saddr, host_str) < 0) return -1; + if (localaddr_str != NULL) { + if (inet_aton(localaddr_str, &localaddr) == 0) + return -1; + param_localaddr = &localaddr; + } else { + param_localaddr = NULL; + } - fd = net_socket_mcast_create(&saddr); + fd = net_socket_mcast_create(&saddr, param_localaddr); if (fd < 0) return -1; @@ -505,8 +523,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, "localaddr")) { + error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=\n"); return -1; } @@ -524,8 +543,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, "localaddr")) { + error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=\n"); return -1; } @@ -539,8 +559,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, "localaddr")) { + error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=\n"); return -1; } @@ -550,7 +571,7 @@ int net_init_socket(QemuOpts *opts, return -1; } } else if (qemu_opt_get(opts, "mcast")) { - const char *mcast; + const char *mcast, *localaddr; if (qemu_opt_get(opts, "fd") || qemu_opt_get(opts, "connect") || @@ -560,8 +581,9 @@ int net_init_socket(QemuOpts *opts, } mcast = qemu_opt_get(opts, "mcast"); + localaddr = qemu_opt_get(opts, "localaddr"); - if (net_socket_mcast_init(vlan, "socket", name, mcast) == -1) { + if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) { return -1; } } else { diff --git a/qemu-options.hx b/qemu-options.hx index 4d99a58..accd16a 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[,localaddr=addr]]\n" " connect the vlan 'n' to multicast maddr and port\n" + " use 'localaddr=addr' to specify the host address to send packets from\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}[,localaddr=@var{addr}]] 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 from host's 1.2.3.4): +@example +qemu linux.img -net nic,macaddr=52:54:00:12:34:56 \ + -net socket,mcast=239.192.168.1:1102,localaddr=1.2.3.4 +@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} -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] add a command line option to specify the IP address to send multicast packets from 2010-11-29 19:12 ` [Qemu-devel] " Mike Ryan @ 2010-12-01 19:16 ` Mike Ryan 2010-12-02 19:19 ` [Qemu-devel] " Michael S. Tsirkin 0 siblings, 1 reply; 18+ messages in thread From: Mike Ryan @ 2010-12-01 19:16 UTC (permalink / raw) To: Michael S. Tsirkin; +Cc: qemu-devel [one more minor change which is needed on older kernels] Add an option to specify the host IP to send multicast packets from when using a multicast socket for networking. The option takes an IP address and sets the IP_MULTICAST_IF socket option, which causes the packets to use that IP's interface as an egress. This is useful if the host machine has several interfaces with several virtual networks across disparate interfaces. Signed-off-by: Mike Ryan <mikeryan@ISI.EDU> --- net.c | 4 ++++ net/socket.c | 51 ++++++++++++++++++++++++++++++++++++++------------- qemu-options.hx | 11 +++++++++-- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/net.c b/net.c index c5e6063..9ba5be2 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 = "localaddr", + .type = QEMU_OPT_STRING, + .help = "source address for multicast packets", }, { /* end of list */ } }, diff --git a/net/socket.c b/net/socket.c index 1c4e153..df777ff 100644 --- a/net/socket.c +++ b/net/socket.c @@ -149,7 +149,7 @@ 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, struct in_addr *localaddr) { struct ip_mreq imr; int fd; @@ -183,7 +183,10 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) /* Add host to multicast group */ imr.imr_multiaddr = mcastaddr->sin_addr; - imr.imr_interface.s_addr = htonl(INADDR_ANY); + if (localaddr != NULL) + imr.imr_interface = *localaddr; + else + imr.imr_interface.s_addr = htonl(INADDR_ANY); ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&imr, sizeof(struct ip_mreq)); @@ -201,6 +204,15 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) goto fail; } + /* If a bind address is given, only send packets from that address */ + if (localaddr != NULL) { + ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, localaddr, sizeof(*localaddr)); + if (ret < 0) { + perror("setsockopt(IP_MULTICAST_IF)"); + goto fail; + } + } + socket_set_nonblock(fd); return fd; fail: @@ -248,7 +260,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,17 +480,26 @@ 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 *localaddr_str) { NetSocketState *s; int fd; struct sockaddr_in saddr; + struct in_addr localaddr, *param_localaddr; if (parse_host_port(&saddr, host_str) < 0) return -1; + if (localaddr_str != NULL) { + if (inet_aton(localaddr_str, &localaddr) == 0) + return -1; + param_localaddr = &localaddr; + } else { + param_localaddr = NULL; + } - fd = net_socket_mcast_create(&saddr); + fd = net_socket_mcast_create(&saddr, param_localaddr); if (fd < 0) return -1; @@ -505,8 +526,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, "localaddr")) { + error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=\n"); return -1; } @@ -524,8 +546,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, "localaddr")) { + error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=\n"); return -1; } @@ -539,8 +562,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, "localaddr")) { + error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=\n"); return -1; } @@ -550,7 +574,7 @@ int net_init_socket(QemuOpts *opts, return -1; } } else if (qemu_opt_get(opts, "mcast")) { - const char *mcast; + const char *mcast, *localaddr; if (qemu_opt_get(opts, "fd") || qemu_opt_get(opts, "connect") || @@ -560,8 +584,9 @@ int net_init_socket(QemuOpts *opts, } mcast = qemu_opt_get(opts, "mcast"); + localaddr = qemu_opt_get(opts, "localaddr"); - if (net_socket_mcast_init(vlan, "socket", name, mcast) == -1) { + if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) { return -1; } } else { diff --git a/qemu-options.hx b/qemu-options.hx index 4d99a58..accd16a 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[,localaddr=addr]]\n" " connect the vlan 'n' to multicast maddr and port\n" + " use 'localaddr=addr' to specify the host address to send packets from\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}[,localaddr=@var{addr}]] 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 from host's 1.2.3.4): +@example +qemu linux.img -net nic,macaddr=52:54:00:12:34:56 \ + -net socket,mcast=239.192.168.1:1102,localaddr=1.2.3.4 +@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} -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] Re: [PATCH] add a command line option to specify the IP address to send multicast packets from 2010-12-01 19:16 ` Mike Ryan @ 2010-12-02 19:19 ` Michael S. Tsirkin 0 siblings, 0 replies; 18+ messages in thread From: Michael S. Tsirkin @ 2010-12-02 19:19 UTC (permalink / raw) To: Mike Ryan; +Cc: qemu-devel On Wed, Dec 01, 2010 at 11:16:47AM -0800, Mike Ryan wrote: > [one more minor change which is needed on older kernels] > > Add an option to specify the host IP to send multicast packets from when > using a multicast socket for networking. The option takes an IP address > and sets the IP_MULTICAST_IF socket option, which causes the packets to > use that IP's interface as an egress. > > This is useful if the host machine has several interfaces with several > virtual networks across disparate interfaces. > > Signed-off-by: Mike Ryan <mikeryan@ISI.EDU> Applied. I tweaked style in one place ({} in if) and the commit message a bit. > --- > net.c | 4 ++++ > net/socket.c | 51 ++++++++++++++++++++++++++++++++++++++------------- > qemu-options.hx | 11 +++++++++-- > 3 files changed, 51 insertions(+), 15 deletions(-) > > diff --git a/net.c b/net.c > index c5e6063..9ba5be2 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 = "localaddr", > + .type = QEMU_OPT_STRING, > + .help = "source address for multicast packets", > }, > { /* end of list */ } > }, > diff --git a/net/socket.c b/net/socket.c > index 1c4e153..df777ff 100644 > --- a/net/socket.c > +++ b/net/socket.c > @@ -149,7 +149,7 @@ 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, struct in_addr *localaddr) > { > struct ip_mreq imr; > int fd; > @@ -183,7 +183,10 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) > > /* Add host to multicast group */ > imr.imr_multiaddr = mcastaddr->sin_addr; > - imr.imr_interface.s_addr = htonl(INADDR_ANY); > + if (localaddr != NULL) > + imr.imr_interface = *localaddr; > + else > + imr.imr_interface.s_addr = htonl(INADDR_ANY); > > ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, > (const char *)&imr, sizeof(struct ip_mreq)); > @@ -201,6 +204,15 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) > goto fail; > } > > + /* If a bind address is given, only send packets from that address */ > + if (localaddr != NULL) { > + ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, localaddr, sizeof(*localaddr)); > + if (ret < 0) { > + perror("setsockopt(IP_MULTICAST_IF)"); > + goto fail; > + } > + } > + > socket_set_nonblock(fd); > return fd; > fail: > @@ -248,7 +260,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,17 +480,26 @@ 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 *localaddr_str) > { > NetSocketState *s; > int fd; > struct sockaddr_in saddr; > + struct in_addr localaddr, *param_localaddr; > > if (parse_host_port(&saddr, host_str) < 0) > return -1; > > + if (localaddr_str != NULL) { > + if (inet_aton(localaddr_str, &localaddr) == 0) > + return -1; > + param_localaddr = &localaddr; > + } else { > + param_localaddr = NULL; > + } > > - fd = net_socket_mcast_create(&saddr); > + fd = net_socket_mcast_create(&saddr, param_localaddr); > if (fd < 0) > return -1; > > @@ -505,8 +526,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, "localaddr")) { > + error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=\n"); > return -1; > } > > @@ -524,8 +546,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, "localaddr")) { > + error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=\n"); > return -1; > } > > @@ -539,8 +562,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, "localaddr")) { > + error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=\n"); > return -1; > } > > @@ -550,7 +574,7 @@ int net_init_socket(QemuOpts *opts, > return -1; > } > } else if (qemu_opt_get(opts, "mcast")) { > - const char *mcast; > + const char *mcast, *localaddr; > > if (qemu_opt_get(opts, "fd") || > qemu_opt_get(opts, "connect") || > @@ -560,8 +584,9 @@ int net_init_socket(QemuOpts *opts, > } > > mcast = qemu_opt_get(opts, "mcast"); > + localaddr = qemu_opt_get(opts, "localaddr"); > > - if (net_socket_mcast_init(vlan, "socket", name, mcast) == -1) { > + if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) { > return -1; > } > } else { > diff --git a/qemu-options.hx b/qemu-options.hx > index 4d99a58..accd16a 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[,localaddr=addr]]\n" > " connect the vlan 'n' to multicast maddr and port\n" > + " use 'localaddr=addr' to specify the host address to send packets from\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}[,localaddr=@var{addr}]] > > 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 from host's 1.2.3.4): > +@example > +qemu linux.img -net nic,macaddr=52:54:00:12:34:56 \ > + -net socket,mcast=239.192.168.1:1102,localaddr=1.2.3.4 > +@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} > -- > 1.7.0.4 ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2010-12-02 19:20 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-11-11 1:47 [Qemu-devel] [PATCH] add a command line option to specify the interface to send multicast packets on Mike Ryan 2010-11-15 18:54 ` Mike Ryan 2010-11-15 19:36 ` Anthony Liguori 2010-11-15 19:52 ` Mike Ryan 2010-11-15 21:07 ` Anthony Liguori 2010-11-15 21:22 ` Stefan Weil 2010-11-15 21:34 ` Mike Ryan 2010-11-16 9:26 ` [Qemu-devel] " Paolo Bonzini 2010-11-16 17:54 ` Michael S. Tsirkin 2010-11-16 19:10 ` Mike Ryan 2010-11-18 1:16 ` [Qemu-devel] [PATCH] add a command line option to specify the IP address to send multicast packets from Mike Ryan 2010-11-22 18:48 ` Mike Ryan 2010-11-23 13:05 ` Michael S. Tsirkin 2010-11-23 23:49 ` Mike Ryan 2010-11-24 5:32 ` [Qemu-devel] " Michael S. Tsirkin 2010-11-29 19:12 ` [Qemu-devel] " Mike Ryan 2010-12-01 19:16 ` Mike Ryan 2010-12-02 19:19 ` [Qemu-devel] " Michael S. Tsirkin
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).