qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [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

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).