Commit ad43c3565bebada7e5a13288e37542fd940369e8

Authored by Jeff Dike
Committed by Linus Torvalds
1 parent 6d536e4b59

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>

Showing 5 changed files with 335 additions and 2 deletions Side-by-side Diff

... ... @@ -108,6 +108,28 @@
108 108 more than one without conflict. If you don't need UML networking,
109 109 say N.
110 110  
  111 +config 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 +
111 133 config UML_NET_MCAST
112 134 bool "Multicast transport"
113 135 depends on UML_NET
arch/um/drivers/Makefile
... ... @@ -19,10 +19,16 @@
19 19  
20 20 LDFLAGS_pcap.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libpcap.a)
21 21  
22   -targets := pcap_kern.o pcap_user.o
  22 +LDFLAGS_vde.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libvdeplug.a)
23 23  
  24 +targets := pcap_kern.o pcap_user.o vde_kern.o vde_user.o
  25 +
24 26 $(obj)/pcap.o: $(obj)/pcap_kern.o $(obj)/pcap_user.o
25 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 32 #XXX: The call below does not work because the flags are added before the
27 33 # object name, so nothing from the library gets linked.
28 34 #$(call if_changed,ld)
... ... @@ -37,6 +43,7 @@
37 43 obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o
38 44 obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o
39 45 obj-$(CONFIG_UML_NET_DAEMON) += daemon.o
  46 +obj-$(CONFIG_UML_NET_VDE) += vde.o
40 47 obj-$(CONFIG_UML_NET_MCAST) += mcast.o
41 48 obj-$(CONFIG_UML_NET_PCAP) += pcap.o
42 49 obj-$(CONFIG_UML_NET) += net.o
... ... @@ -54,7 +61,7 @@
54 61 obj-$(CONFIG_UML_RANDOM) += random.o
55 62  
56 63 # pcap_user.o must be added explicitly.
57   -USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o
  64 +USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o vde_user.o
58 65  
59 66 include arch/um/scripts/Makefile.rules
arch/um/drivers/vde.h
  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 +
  9 +struct vde_data {
  10 + char *vde_switch;
  11 + char *descr;
  12 + void *args;
  13 + void *conn;
  14 + void *dev;
  15 +};
  16 +
  17 +struct vde_init {
  18 + char *vde_switch;
  19 + char *descr;
  20 + int port;
  21 + char *group;
  22 + int mode;
  23 +};
  24 +
  25 +extern const struct net_user_info vde_user_info;
  26 +
  27 +extern void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init);
  28 +
  29 +extern int vde_user_read(void *conn, void *buf, int len);
  30 +extern int vde_user_write(void *conn, void *buf, int len);
  31 +
  32 +#endif
arch/um/drivers/vde_kern.c
  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 +
  18 +static 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 +
  41 +static 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 +
  58 +static 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 +
  70 +static 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 +
  77 +static 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 +
  120 +static 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 +
  130 +static int register_vde(void)
  131 +{
  132 + register_transport(&vde_transport);
  133 + return 0;
  134 +}
  135 +
  136 +late_initcall(register_vde);
arch/um/drivers/vde_user.c
  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 +
  19 +static 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 +
  43 +static 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 +
  54 +static 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 +
  70 +static int vde_set_mtu(int mtu, void *data)
  71 +{
  72 + return mtu;
  73 +}
  74 +
  75 +const 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 +
  86 +void 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 +
  107 +int 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 +
  127 +int 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 +}