Home » Mailing lists » Devel » [RFC] network namespaces
[PATCH 8/9] network namespaces: device to pass packets between namespaces [message #5171 is a reply to message #5165] |
Tue, 15 August 2006 14:48 |
Andrey Savochkin
Messages: 47 Registered: December 2005
|
Member |
|
|
A simple device to pass packets between a namespace and its child.
Signed-off-by: Andrey Savochkin <saw@swsoft.com>
---
Makefile | 3
veth.c | 327 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++
2 files changed, 330 insertions(+)
--- ./drivers/net/Makefile.veveth Mon Aug 14 17:03:45 2006
+++ ./drivers/net/Makefile Tue Aug 15 13:46:15 2006
@@ -124,6 +124,9 @@ obj-$(CONFIG_SLIP) += slip.o
obj-$(CONFIG_SLHC) += slhc.o
obj-$(CONFIG_DUMMY) += dummy.o
+ifeq ($(CONFIG_NET_NS),y)
+obj-m += veth.o
+endif
obj-$(CONFIG_IFB) += ifb.o
obj-$(CONFIG_DE600) += de600.o
obj-$(CONFIG_DE620) += de620.o
--- ./drivers/net/veth.c.veveth Tue Aug 15 13:44:46 2006
+++ ./drivers/net/veth.c Tue Aug 15 13:46:15 2006
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2006 SWsoft
+ *
+ * Written by Andrey Savochkin <saw@sw.ru>,
+ * reusing code by Andrey Mirkin <amirkin@sw.ru>.
+ */
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/ctype.h>
+#include <asm/semaphore.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <net/dst.h>
+#include <net/xfrm.h>
+
+struct veth_struct
+{
+ struct net_device *pair;
+ struct net_device_stats stats;
+};
+
+#define veth_from_netdev(dev) ((struct veth_struct *)(netdev_priv(dev)))
+
+/* ------------------------------------------------------------ ------- *
+ *
+ * Device functions
+ *
+ * ------------------------------------------------------------ ------- */
+
+static struct net_device_stats *get_stats(struct net_device *dev);
+static int veth_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_device_stats *stats;
+ struct veth_struct *entry;
+ struct net_device *rcv;
+ struct net_namespace *orig_net_ns;
+ int length;
+
+ stats = get_stats(dev);
+ entry = veth_from_netdev(dev);
+ rcv = entry->pair;
+
+ if (!(rcv->flags & IFF_UP))
+ /* Target namespace does not want to receive packets */
+ goto outf;
+
+ dst_release(skb->dst);
+ skb->dst = NULL;
+ secpath_reset(skb);
+ skb_orphan(skb);
+#ifdef CONFIG_NETFILTER
+ nf_conntrack_put(skb->nfct);
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ nf_conntrack_put_reasm(skb->nfct_reasm);
+#endif
+#ifdef CONFIG_BRIDGE_NETFILTER
+ nf_bridge_put(skb->nf_bridge);
+#endif
+#endif
+
+ push_net_ns(rcv->net_ns, orig_net_ns);
+ skb->dev = rcv;
+ skb->pkt_type = PACKET_HOST;
+ skb->protocol = eth_type_trans(skb, rcv);
+
+ length = skb->len;
+ stats->tx_bytes += length;
+ stats->tx_packets++;
+ stats = get_stats(rcv);
+ stats->rx_bytes += length;
+ stats->rx_packets++;
+
+ netif_rx(skb);
+ pop_net_ns(orig_net_ns);
+ return 0;
+
+outf:
+ stats->tx_dropped++;
+ kfree_skb(skb);
+ return 0;
+}
+
+static int veth_open(struct net_device *dev)
+{
+ return 0;
+}
+
+static int veth_close(struct net_device *dev)
+{
+ return 0;
+}
+
+static void veth_destructor(struct net_device *dev)
+{
+ free_netdev(dev);
+}
+
+static struct net_device_stats *get_stats(struct net_device *dev)
+{
+ return &veth_from_netdev(dev)->stats;
+}
+
+int veth_init_dev(struct net_device *dev)
+{
+ dev->hard_start_xmit = veth_xmit;
+ dev->open = veth_open;
+ dev->stop = veth_close;
+ dev->destructor = veth_destructor;
+ dev->get_stats = get_stats;
+
+ ether_setup(dev);
+
+ dev->tx_queue_len = 0;
+ return 0;
+}
+
+static void veth_setup(struct net_device *dev)
+{
+ dev->init = veth_init_dev;
+}
+
+static inline int is_veth_dev(struct net_device *dev)
+{
+ return dev->init == veth_init_dev;
+}
+
+/* ------------------------------------------------------------ ------- *
+ *
+ * Management interface
+ *
+ * ------------------------------------------------------------ ------- */
+
+struct net_device *veth_dev_alloc(char *name, char *addr)
+{
+ struct net_device *dev;
+
+ dev = alloc_netdev(sizeof(struct veth_struct), name, veth_setup);
+ if (dev != NULL) {
+ memcpy(dev->dev_addr, addr, ETH_ALEN);
+ dev->addr_len = ETH_ALEN;
+ }
+ return dev;
+}
+
+int veth_entry_add(char *parent_name, char *parent_addr,
+ char *child_name, char *child_addr,
+ struct net_namespace *child_ns)
+{
+ struct net_device *parent_dev, *child_dev;
+ struct net_namespace *parent_ns;
+ int err;
+
+ err = -ENOMEM;
+ if ((parent_dev = veth_dev_alloc(parent_name, parent_addr)) == NULL)
+ goto out_alocp;
+ if ((child_dev = veth_dev_alloc(child_name, child_addr)) == NULL)
+ goto out_alocc;
+ veth_from_netdev(parent_dev)->pair = child_dev;
+ veth_from_netdev(child_dev)->pair = parent_dev;
+
+ /*
+ * About serialization, see comments to veth_pair_del().
+ */
+ rtnl_lock();
+ if ((err = register_netdevice(parent_dev)))
+ goto out_regp;
+
+ push_net_ns(child_ns, parent_ns);
+ if ((err = register_netdevice(child_dev)))
+ goto out_regc;
+ pop_net_ns(parent_ns);
+ rtnl_unlock();
+ return 0;
+
+out_regc:
+ pop_net_ns(parent_ns);
+ unregister_netdevice(parent_dev);
+ rtnl_unlock();
+ free_netdev(child_dev);
+ return err;
+
+out_regp:
+ rtnl_unlock();
+ free_netdev(child_dev);
+out_alocc:
+ free_netdev(parent_dev);
+out_alocp:
+ return err;
+}
+
+static void veth_pair_del(struct net_device *parent_dev)
+{
+ struct net_device *child_dev;
+ struct net_namespace *parent_ns, *child_ns;
+
+ child_dev = veth_from_netdev(parent_dev)->pair;
+ child_ns = get_net_ns(child_dev->net_ns);
+
+ dev_close(child_dev);
+ synchronize_net();
+ /*
+ * Now child_dev does not send or receives anything.
+ * This means child_dev->hard_start_xmit is not called anymore.
+ */
+ unregister_netdevice(parent_dev);
+ /*
+ * At this point child_dev has dead pointer to parent_dev.
+ * But this pointer is not dereferenced.
+ */
+ push_net_ns(child_ns, parent_ns);
+ unregister_netdevice(child_dev);
+ pop_net_ns(parent_ns);
+
+ put_net_ns(child_ns);
+}
+
+int veth_entry_del(char *parent_name)
+{
+ struct net_device *dev;
+
+ if ((dev = dev_get_by_name(parent_name)) == NULL)
+ return -ENODEV;
+
+ rtnl_lock();
+ veth_pair_del(dev);
+ dev_put(dev);
+ rtnl_unlock();
+
+ return 0;
+}
+
+void veth_entry_del_all(void)
+{
+ struct net_device **p, *dev;
+
+ rtnl_lock();
+ for (p = &dev_base; (dev = *p) != NULL; ) {
+ if (!is_veth_dev(dev)) {
+ p = &dev->next;
+ continue;
+ }
+
+ dev_hold(dev);
+ veth_pair_del(dev);
+ dev_put(dev);
+ }
+ rtnl_unlock();
+}
+
+/* ------------------------------------------------------------ ------- *
+ *
+ * Information in proc
+ *
+ * ------------------------------------------------------------ ------- */
+
+#ifdef CONFIG_PROC_FS
+
+#define ADDR_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
+#define ADDR(x) (x)[0],(x)[1],(x)[2],(x)[3],(x)[4],(x)[5]
+#define ADDR_HDR "%-17s"
+
+static int veth_proc_show(struct seq_file *m,
+ struct net_device *dev, void *data)
+{
+ struct net_device *pair;
+
+ if (dev == SEQ_START_TOKEN) {
+ seq_puts(m, "Version: 1.0\n");
+ seq_printf(m, "%-*s " ADDR_HDR " %-*s " ADDR_HDR "\n",
+ IFNAMSIZ, "Name", "Address",
+ IFNAMSIZ, "PeerName", "PeerAddress");
+ return 0;
+ }
+
+ if (!is_veth_dev(dev))
+ return 0;
+
+ pair = veth_from_netdev(dev)->pair;
+ seq_printf(m, "%-*s " ADDR_FMT " %-*s " ADDR_FMT "\n",
+ IFNAMSIZ, dev->name, ADDR(dev->dev_addr),
+ IFNAMSIZ, pair->name, ADDR(pair->dev_addr));
+ return 0;
+}
+
+static int veth_proc_create(void)
+{
+ return netdev_proc_create("veth_list", &veth_proc_show, NULL,
+ THIS_MODULE);
+}
+
+static void veth_proc_remove(void)
+{
+ netdev_proc_remove("net/veth_list");
+}
+
+#else
+
+static inline int veth_proc_create(void) { return 0; }
+static inline void veth_proc_remove(void) { }
+
+#endif
+
+/* ------------------------------------------------------------ ------- *
+ *
+ * Module initialization
+ *
+ * ------------------------------------------------------------ ------- */
+
+int __init veth_init(void)
+{
+ veth_proc_create();
+ return 0;
+}
+
+void __exit veth_exit(void)
+{
+ veth_proc_remove();
+ veth_entry_del_all();
+}
+
+module_init(veth_init)
+module_exit(veth_exit)
+
+MODULE_DESCRIPTION("Virtual Ethernet Device");
+MODULE_LICENSE("GPL v2");
...
|
|
|
|
|
[RFC] network namespaces
|
|
|
[PATCH 1/9] network namespaces: core and device list
|
|
|
Re: [PATCH 1/9] network namespaces: core and device list
|
|
|
Re: [PATCH 1/9] network namespaces: core and device list
|
|
|
[PATCH 2/9] network namespaces: IPv4 routing
|
|
|
[PATCH 6/9] allow proc_dir_entries to have destructor
|
|
|
[PATCH 5/9] network namespaces: async socket operations
|
|
|
Re: [PATCH 5/9] network namespaces: async socket operations
|
|
|
Re: [PATCH 5/9] network namespaces: async socket operations
|
|
|
[PATCH 7/9] net_device seq_file
|
|
|
[PATCH 8/9] network namespaces: device to pass packets between namespaces
|
|
|
[PATCH 4/9] network namespaces: socket hashes
|
|
|
Re: [PATCH 4/9] network namespaces: socket hashes
|
|
|
Re: [PATCH 4/9] network namespaces: socket hashes
|
|
|
Re: [PATCH 4/9] network namespaces: socket hashes
|
|
|
[PATCH 9/9] network namespaces: playing with pass-through device
|
|
|
Re: [RFC] network namespaces
By: serue on Wed, 16 August 2006 11:53
|
|
|
Re: [RFC] network namespaces
|
|
|
Re: [RFC] network namespaces
By: ebiederm on Wed, 16 August 2006 17:35
|
|
|
Re: [RFC] network namespaces
By: dev on Thu, 17 August 2006 08:28
|
|
|
Re: [RFC] network namespaces
|
|
|
Re: [RFC] network namespaces
By: ebiederm on Tue, 05 September 2006 14:45
|
|
|
Re: [RFC] network namespaces
|
|
|
Re: [RFC] network namespaces
|
|
|
Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
By: kir on Wed, 06 September 2006 17:36
|
|
|
Re: [RFC] network namespaces
By: ebiederm on Wed, 06 September 2006 18:34
|
|
|
Re: [RFC] network namespaces
By: kir on Wed, 06 September 2006 18:56
|
|
|
Re: [RFC] network namespaces
|
|
|
RE: [RFC] network namespaces
|
|
|
Re: [RFC] network namespaces
|
|
|
Re: [RFC] network namespaces
By: ebiederm on Thu, 07 September 2006 18:29
|
|
|
Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
By: dev on Thu, 07 September 2006 16:20
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: [RFC] network namespaces
By: ebiederm on Tue, 12 September 2006 03:26
|
|
|
Re: Re: [RFC] network namespaces
By: ebiederm on Sun, 10 September 2006 03:41
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: [RFC] network namespaces
By: ebiederm on Tue, 12 September 2006 03:28
|
|
|
Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
By: ebiederm on Thu, 07 September 2006 19:50
|
|
|
Re: Re: [RFC] network namespaces
|
|
|
Re: [RFC] network namespaces
By: ebiederm on Wed, 06 September 2006 17:58
|
|
|
Re: [RFC] network namespaces
By: ebiederm on Tue, 05 September 2006 18:27
|
|
|
Re: [RFC] network namespaces
By: dev on Wed, 06 September 2006 14:52
|
|
|
Re: [RFC] network namespaces
|
|
|
Re: [RFC] network namespaces
By: dev on Tue, 05 September 2006 15:44
|
|
|
Re: [RFC] network namespaces
By: ebiederm on Tue, 05 September 2006 17:09
|
|
|
Re: [RFC] network namespaces
|
|
|
Re: Re: [RFC] network namespaces
By: kir on Wed, 06 September 2006 15:09
|
|
|
Re: [RFC] network namespaces
By: ebiederm on Wed, 06 September 2006 20:40
|
|
|
Re: [RFC] network namespaces
By: ebiederm on Wed, 06 September 2006 23:25
|
|
|
Re: [RFC] network namespaces
|
|
|
Re: [RFC] network namespaces
By: ebiederm on Thu, 07 September 2006 05:11
|
|
|
Re: [RFC] network namespaces
|
|
|
Re: [RFC] network namespaces
By: ebiederm on Sun, 10 September 2006 11:48
|
Goto Forum:
Current Time: Fri Oct 18 19:52:06 GMT 2024
Total time taken to generate the page: 0.04901 seconds
|