This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / xen / netback / loopback.c
1 /******************************************************************************
2  * netback/loopback.c
3  * 
4  * A two-interface loopback device to emulate a local netfront-netback
5  * connection. This ensures that local packet delivery looks identical
6  * to inter-domain delivery. Most importantly, packets delivered locally
7  * originating from other domains will get *copied* when they traverse this
8  * driver. This prevents unbounded delays in socket-buffer queues from
9  * causing the netback driver to "seize up".
10  * 
11  * This driver creates a symmetric pair of loopback interfaces with names
12  * vif0.0 and veth0. The intention is that 'vif0.0' is bound to an Ethernet
13  * bridge, just like a proper netback interface, while a local IP interface
14  * is configured on 'veth0'.
15  * 
16  * As with a real netback interface, vif0.0 is configured with a suitable
17  * dummy MAC address. No default is provided for veth0: a reasonable strategy
18  * is to transfer eth0's MAC address to veth0, and give eth0 a dummy address
19  * (to avoid confusing the Etherbridge).
20  * 
21  * Copyright (c) 2005 K A Fraser
22  * 
23  * This program is free software; you can redistribute it and/or
24  * modify it under the terms of the GNU General Public License version 2
25  * as published by the Free Software Foundation; or, when distributed
26  * separately from the Linux kernel or incorporated into other
27  * software packages, subject to the following license:
28  * 
29  * Permission is hereby granted, free of charge, to any person obtaining a copy
30  * of this source file (the "Software"), to deal in the Software without
31  * restriction, including without limitation the rights to use, copy, modify,
32  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
33  * and to permit persons to whom the Software is furnished to do so, subject to
34  * the following conditions:
35  * 
36  * The above copyright notice and this permission notice shall be included in
37  * all copies or substantial portions of the Software.
38  * 
39  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
44  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
45  * IN THE SOFTWARE.
46  */
47
48 #include <linux/config.h>
49 #include <linux/module.h>
50 #include <linux/netdevice.h>
51 #include <linux/inetdevice.h>
52 #include <linux/etherdevice.h>
53 #include <linux/skbuff.h>
54 #include <linux/ethtool.h>
55 #include <net/dst.h>
56
57 static int nloopbacks = 8;
58 module_param(nloopbacks, int, 0);
59 MODULE_PARM_DESC(nloopbacks, "Number of netback-loopback devices to create");
60
61 struct net_private {
62         struct net_device *loopback_dev;
63         struct net_device_stats stats;
64 };
65
66 static int loopback_open(struct net_device *dev)
67 {
68         struct net_private *np = netdev_priv(dev);
69         memset(&np->stats, 0, sizeof(np->stats));
70         netif_start_queue(dev);
71         return 0;
72 }
73
74 static int loopback_close(struct net_device *dev)
75 {
76         netif_stop_queue(dev);
77         return 0;
78 }
79
80 static int loopback_start_xmit(struct sk_buff *skb, struct net_device *dev)
81 {
82         struct net_private *np = netdev_priv(dev);
83
84         dst_release(skb->dst);
85         skb->dst = NULL;
86
87         skb_orphan(skb);
88
89         np->stats.tx_bytes += skb->len;
90         np->stats.tx_packets++;
91
92         /* Switch to loopback context. */
93         dev = np->loopback_dev;
94         np  = netdev_priv(dev);
95
96         np->stats.rx_bytes += skb->len;
97         np->stats.rx_packets++;
98
99         if (skb->ip_summed == CHECKSUM_HW) {
100                 /* Defer checksum calculation. */
101                 skb->proto_csum_blank = 1;
102                 /* Must be a local packet: assert its integrity. */
103                 skb->proto_data_valid = 1;
104         }
105
106         skb->ip_summed = skb->proto_data_valid ?
107                 CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
108
109         skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */
110         skb->protocol = eth_type_trans(skb, dev);
111         skb->dev      = dev;
112         dev->last_rx  = jiffies;
113         netif_rx(skb);
114
115         return 0;
116 }
117
118 static struct net_device_stats *loopback_get_stats(struct net_device *dev)
119 {
120         struct net_private *np = netdev_priv(dev);
121         return &np->stats;
122 }
123
124 static struct ethtool_ops network_ethtool_ops =
125 {
126         .get_tx_csum = ethtool_op_get_tx_csum,
127         .set_tx_csum = ethtool_op_set_tx_csum,
128         .get_sg = ethtool_op_get_sg,
129         .set_sg = ethtool_op_set_sg,
130         .get_tso = ethtool_op_get_tso,
131         .set_tso = ethtool_op_set_tso,
132         .get_link = ethtool_op_get_link,
133 };
134
135 /*
136  * Nothing to do here. Virtual interface is point-to-point and the
137  * physical interface is probably promiscuous anyway.
138  */
139 static void loopback_set_multicast_list(struct net_device *dev)
140 {
141 }
142
143 static void loopback_construct(struct net_device *dev, struct net_device *lo)
144 {
145         struct net_private *np = netdev_priv(dev);
146
147         np->loopback_dev     = lo;
148
149         dev->open            = loopback_open;
150         dev->stop            = loopback_close;
151         dev->hard_start_xmit = loopback_start_xmit;
152         dev->get_stats       = loopback_get_stats;
153         dev->set_multicast_list = loopback_set_multicast_list;
154         dev->change_mtu      = NULL; /* allow arbitrary mtu */
155
156         dev->tx_queue_len    = 0;
157
158         dev->features        = (NETIF_F_HIGHDMA |
159                                 NETIF_F_LLTX |
160                                 NETIF_F_TSO |
161                                 NETIF_F_SG |
162                                 NETIF_F_IP_CSUM);
163
164         SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
165
166         /*
167          * We do not set a jumbo MTU on the interface. Otherwise the network
168          * stack will try to send large packets that will get dropped by the
169          * Ethernet bridge (unless the physical Ethernet interface is
170          * configured to transfer jumbo packets). If a larger MTU is desired
171          * then the system administrator can specify it using the 'ifconfig'
172          * command.
173          */
174         /*dev->mtu             = 16*1024;*/
175 }
176
177 static int __init make_loopback(int i)
178 {
179         struct net_device *dev1, *dev2;
180         char dev_name[IFNAMSIZ];
181         int err = -ENOMEM;
182
183         sprintf(dev_name, "vif0.%d", i);
184         dev1 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
185         if (!dev1)
186                 return err;
187
188         sprintf(dev_name, "veth%d", i);
189         dev2 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
190         if (!dev2)
191                 goto fail_netdev2;
192
193         loopback_construct(dev1, dev2);
194         loopback_construct(dev2, dev1);
195
196         /*
197          * Initialise a dummy MAC address for the 'dummy backend' interface. We
198          * choose the numerically largest non-broadcast address to prevent the
199          * address getting stolen by an Ethernet bridge for STP purposes.
200          */
201         memset(dev1->dev_addr, 0xFF, ETH_ALEN);
202         dev1->dev_addr[0] &= ~0x01;
203
204         if ((err = register_netdev(dev1)) != 0)
205                 goto fail;
206
207         if ((err = register_netdev(dev2)) != 0) {
208                 unregister_netdev(dev1);
209                 goto fail;
210         }
211
212         return 0;
213
214  fail:
215         free_netdev(dev2);
216  fail_netdev2:
217         free_netdev(dev1);
218         return err;
219 }
220
221 static void __init clean_loopback(int i)
222 {
223         struct net_device *dev1, *dev2;
224         char dev_name[IFNAMSIZ];
225
226         sprintf(dev_name, "vif0.%d", i);
227         dev1 = dev_get_by_name(dev_name);
228         sprintf(dev_name, "veth%d", i);
229         dev2 = dev_get_by_name(dev_name);
230         if (dev1 && dev2) {
231                 unregister_netdev(dev2);
232                 unregister_netdev(dev1);
233                 free_netdev(dev2);
234                 free_netdev(dev1);
235         }
236 }
237
238 static int __init loopback_init(void)
239 {
240         int i, err = 0;
241
242         for (i = 0; i < nloopbacks; i++)
243                 if ((err = make_loopback(i)) != 0)
244                         break;
245
246         return err;
247 }
248
249 module_init(loopback_init);
250
251 static void __exit loopback_exit(void)
252 {
253         int i;
254
255         for (i = nloopbacks; i-- > 0; )
256                 clean_loopback(i);
257 }
258
259 module_exit(loopback_exit);
260
261 MODULE_LICENSE("Dual BSD/GPL");