aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2007-10-16 04:26:48 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:05 -0400
commitad43c3565bebada7e5a13288e37542fd940369e8 (patch)
tree0946d7e5fc8f4bfa9ce5932d2cd1a921946e7c86
parent6d536e4b59f77c34a0e5a414dfa934db373c85c2 (diff)
uml: add VDE networking support
Added vde network backend in uml to introduce native Virtual Distributed Ethernet support (using libvdeplug). Signed-off-by: Luca Bigliardi <shammash@artha.org> Signed-off-by: Jeff Dike <jdike@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/um/Kconfig.net22
-rw-r--r--arch/um/drivers/Makefile11
-rw-r--r--arch/um/drivers/vde.h32
-rw-r--r--arch/um/drivers/vde_kern.c136
-rw-r--r--arch/um/drivers/vde_user.c136
5 files changed, 335 insertions, 2 deletions
diff --git a/arch/um/Kconfig.net b/arch/um/Kconfig.net
index 14a04ebdeae9..66e50026ade9 100644
--- a/arch/um/Kconfig.net
+++ b/arch/um/Kconfig.net
@@ -108,6 +108,28 @@ config UML_NET_DAEMON
108 more than one without conflict. If you don't need UML networking, 108 more than one without conflict. If you don't need UML networking,
109 say N. 109 say N.
110 110
111config UML_NET_VDE
112 bool "VDE transport"
113 depends on UML_NET
114 help
115 This User-Mode Linux network transport allows one or more running
116 UMLs on a single host to communicate with each other and also
117 with the rest of the world using Virtual Distributed Ethernet,
118 an improved fork of uml_switch.
119
120 You must have libvdeplug installed in order to build the vde
121 transport into UML.
122
123 To use this form of networking, you will need to run vde_switch
124 on the host.
125
126 For more information, see <http://wiki.virtualsquare.org/>
127 That site has a good overview of what VDE is and also examples
128 of the UML command line to use to enable VDE networking.
129
130 If you need UML networking with VDE,
131 say Y.
132
111config UML_NET_MCAST 133config UML_NET_MCAST
112 bool "Multicast transport" 134 bool "Multicast transport"
113 depends on UML_NET 135 depends on UML_NET
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index de17d4c6e02d..634968150bd6 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -19,10 +19,16 @@ harddog-objs := harddog_kern.o harddog_user.o
19 19
20LDFLAGS_pcap.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libpcap.a) 20LDFLAGS_pcap.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libpcap.a)
21 21
22targets := pcap_kern.o pcap_user.o 22LDFLAGS_vde.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libvdeplug.a)
23
24targets := pcap_kern.o pcap_user.o vde_kern.o vde_user.o
23 25
24$(obj)/pcap.o: $(obj)/pcap_kern.o $(obj)/pcap_user.o 26$(obj)/pcap.o: $(obj)/pcap_kern.o $(obj)/pcap_user.o
25 $(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_pcap.o) 27 $(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_pcap.o)
28
29$(obj)/vde.o: $(obj)/vde_kern.o $(obj)/vde_user.o
30 $(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_vde.o)
31
26#XXX: The call below does not work because the flags are added before the 32#XXX: The call below does not work because the flags are added before the
27# object name, so nothing from the library gets linked. 33# object name, so nothing from the library gets linked.
28#$(call if_changed,ld) 34#$(call if_changed,ld)
@@ -37,6 +43,7 @@ obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o
37obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o 43obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o
38obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o 44obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o
39obj-$(CONFIG_UML_NET_DAEMON) += daemon.o 45obj-$(CONFIG_UML_NET_DAEMON) += daemon.o
46obj-$(CONFIG_UML_NET_VDE) += vde.o
40obj-$(CONFIG_UML_NET_MCAST) += mcast.o 47obj-$(CONFIG_UML_NET_MCAST) += mcast.o
41obj-$(CONFIG_UML_NET_PCAP) += pcap.o 48obj-$(CONFIG_UML_NET_PCAP) += pcap.o
42obj-$(CONFIG_UML_NET) += net.o 49obj-$(CONFIG_UML_NET) += net.o
@@ -54,6 +61,6 @@ obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
54obj-$(CONFIG_UML_RANDOM) += random.o 61obj-$(CONFIG_UML_RANDOM) += random.o
55 62
56# pcap_user.o must be added explicitly. 63# pcap_user.o must be added explicitly.
57USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o 64USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o vde_user.o
58 65
59include arch/um/scripts/Makefile.rules 66include arch/um/scripts/Makefile.rules
diff --git a/arch/um/drivers/vde.h b/arch/um/drivers/vde.h
new file mode 100644
index 000000000000..fc3a05902ba1
--- /dev/null
+++ b/arch/um/drivers/vde.h
@@ -0,0 +1,32 @@
1/*
2 * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org).
3 * Licensed under the GPL.
4 */
5
6#ifndef __UM_VDE_H__
7#define __UM_VDE_H__
8
9struct vde_data {
10 char *vde_switch;
11 char *descr;
12 void *args;
13 void *conn;
14 void *dev;
15};
16
17struct vde_init {
18 char *vde_switch;
19 char *descr;
20 int port;
21 char *group;
22 int mode;
23};
24
25extern const struct net_user_info vde_user_info;
26
27extern void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init);
28
29extern int vde_user_read(void *conn, void *buf, int len);
30extern int vde_user_write(void *conn, void *buf, int len);
31
32#endif
diff --git a/arch/um/drivers/vde_kern.c b/arch/um/drivers/vde_kern.c
new file mode 100644
index 000000000000..eb8cf31b820d
--- /dev/null
+++ b/arch/um/drivers/vde_kern.c
@@ -0,0 +1,136 @@
1/*
2 * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org).
3 * Licensed under the GPL.
4 *
5 * Transport usage:
6 * ethN=vde,<vde_switch>,<mac addr>,<port>,<group>,<mode>,<description>
7 *
8 */
9
10#include "linux/kernel.h"
11#include "linux/init.h"
12#include "linux/netdevice.h"
13#include "linux/etherdevice.h"
14#include "net_kern.h"
15#include "net_user.h"
16#include "vde.h"
17
18static void vde_init(struct net_device *dev, void *data)
19{
20 struct vde_init *init = data;
21 struct uml_net_private *pri;
22 struct vde_data *vpri;
23
24 pri = dev->priv;
25 vpri = (struct vde_data *) pri->user;
26
27 vpri->vde_switch = init->vde_switch;
28 vpri->descr = init->descr ? init->descr : "UML vde_transport";
29 vpri->args = NULL;
30 vpri->conn = NULL;
31 vpri->dev = dev;
32
33 printk(KERN_INFO "vde backend - %s, ", vpri->vde_switch ?
34 vpri->vde_switch : "(default socket)");
35
36 vde_init_libstuff(vpri, init);
37
38 printk(KERN_INFO "\n");
39}
40
41static int vde_read(int fd, struct sk_buff **skb, struct uml_net_private *lp)
42{
43 struct vde_data *pri = (struct vde_data *) &lp->user;
44
45 if (pri->conn != NULL) {
46 *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
47 if (*skb == NULL)
48 return -ENOMEM;
49
50 return vde_user_read(pri->conn, skb_mac_header(*skb),
51 (*skb)->dev->mtu + ETH_HEADER_OTHER);
52 }
53
54 printk(KERN_ERR "vde_read - we have no VDECONN to read from");
55 return -EBADF;
56}
57
58static int vde_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
59{
60 struct vde_data *pri = (struct vde_data *) &lp->user;
61
62 if (pri->conn != NULL)
63 return vde_user_write((void *)pri->conn, (*skb)->data,
64 (*skb)->len);
65
66 printk(KERN_ERR "vde_write - we have no VDECONN to write to");
67 return -EBADF;
68}
69
70static const struct net_kern_info vde_kern_info = {
71 .init = vde_init,
72 .protocol = eth_protocol,
73 .read = vde_read,
74 .write = vde_write,
75};
76
77static int vde_setup(char *str, char **mac_out, void *data)
78{
79 struct vde_init *init = data;
80 char *remain, *port_str = NULL, *mode_str = NULL, *last;
81
82 *init = ((struct vde_init)
83 { .vde_switch = NULL,
84 .descr = NULL,
85 .port = 0,
86 .group = NULL,
87 .mode = 0 });
88
89 remain = split_if_spec(str, &init->vde_switch, mac_out, &port_str,
90 &init->group, &mode_str, &init->descr, NULL);
91
92 if (remain != NULL)
93 printk(KERN_WARNING "vde_setup - Ignoring extra data :"
94 "'%s'\n", remain);
95
96 if (port_str != NULL) {
97 init->port = simple_strtoul(port_str, &last, 10);
98 if ((*last != '\0') || (last == port_str)) {
99 printk(KERN_ERR "vde_setup - Bad port : '%s'\n",
100 port_str);
101 return 0;
102 }
103 }
104
105 if (mode_str != NULL) {
106 init->mode = simple_strtoul(mode_str, &last, 8);
107 if ((*last != '\0') || (last == mode_str)) {
108 printk(KERN_ERR "vde_setup - Bad mode : '%s'\n",
109 mode_str);
110 return 0;
111 }
112 }
113
114 printk(KERN_INFO "Configured vde device: %s\n", init->vde_switch ?
115 init->vde_switch : "(default socket)");
116
117 return 1;
118}
119
120static struct transport vde_transport = {
121 .list = LIST_HEAD_INIT(vde_transport.list),
122 .name = "vde",
123 .setup = vde_setup,
124 .user = &vde_user_info,
125 .kern = &vde_kern_info,
126 .private_size = sizeof(struct vde_data),
127 .setup_size = sizeof(struct vde_init),
128};
129
130static int register_vde(void)
131{
132 register_transport(&vde_transport);
133 return 0;
134}
135
136late_initcall(register_vde);
diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c
new file mode 100644
index 000000000000..d3b5a065fc52
--- /dev/null
+++ b/arch/um/drivers/vde_user.c
@@ -0,0 +1,136 @@
1/*
2 * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org).
3 * Licensed under the GPL.
4 */
5
6#include <errno.h>
7#include <unistd.h>
8#include <libvdeplug.h>
9#include "net_user.h"
10#include "kern_util.h"
11#include "kern_constants.h"
12#include "user.h"
13#include "os.h"
14#include "um_malloc.h"
15#include "vde.h"
16
17#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
18
19static int vde_user_init(void *data, void *dev)
20{
21 struct vde_data *pri = data;
22 VDECONN *conn = NULL;
23 int err = -EINVAL;
24
25 pri->dev = dev;
26
27 conn = vde_open(pri->vde_switch, pri->descr, pri->args);
28
29 if (conn == NULL) {
30 err = -errno;
31 printk(UM_KERN_ERR "vde_user_init: vde_open failed, "
32 "errno = %d\n", errno);
33 return err;
34 }
35
36 printk(UM_KERN_INFO "vde backend - connection opened\n");
37
38 pri->conn = conn;
39
40 return 0;
41}
42
43static int vde_user_open(void *data)
44{
45 struct vde_data *pri = data;
46
47 if (pri->conn != NULL)
48 return vde_datafd(pri->conn);
49
50 printk(UM_KERN_WARNING "vde_open - we have no VDECONN to open");
51 return -EINVAL;
52}
53
54static void vde_remove(void *data)
55{
56 struct vde_data *pri = data;
57
58 if (pri->conn != NULL) {
59 printk(UM_KERN_INFO "vde backend - closing connection\n");
60 vde_close(pri->conn);
61 pri->conn = NULL;
62 kfree(pri->args);
63 pri->args = NULL;
64 return;
65 }
66
67 printk(UM_KERN_WARNING "vde_remove - we have no VDECONN to remove");
68}
69
70static int vde_set_mtu(int mtu, void *data)
71{
72 return mtu;
73}
74
75const struct net_user_info vde_user_info = {
76 .init = vde_user_init,
77 .open = vde_user_open,
78 .close = NULL,
79 .remove = vde_remove,
80 .set_mtu = vde_set_mtu,
81 .add_address = NULL,
82 .delete_address = NULL,
83 .max_packet = MAX_PACKET - ETH_HEADER_OTHER
84};
85
86void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init)
87{
88 struct vde_open_args *args;
89
90 vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL);
91 if (vpri->args == NULL) {
92 printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args"
93 "allocation failed");
94 return;
95 }
96
97 args = vpri->args;
98
99 args->port = init->port;
100 args->group = init->group;
101 args->mode = init->mode ? init->mode : 0700;
102
103 args->port ? printk(UM_KERN_INFO "port %d", args->port) :
104 printk(UM_KERN_INFO "undefined port");
105}
106
107int vde_user_read(void *conn, void *buf, int len)
108{
109 VDECONN *vconn = conn;
110 int rv;
111
112 if (vconn == NULL)
113 return 0;
114
115 rv = vde_recv(vconn, buf, len, 0);
116 if (rv < 0) {
117 if (errno == EAGAIN)
118 return 0;
119 return -errno;
120 }
121 else if (rv == 0)
122 return -ENOTCONN;
123
124 return rv;
125}
126
127int vde_user_write(void *conn, void *buf, int len)
128{
129 VDECONN *vconn = conn;
130
131 if (vconn == NULL)
132 return 0;
133
134 return vde_send(vconn, buf, len, 0);
135}
136