ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/netback/loopback.c @ 10040:91c77df11b43

When we copy packet sin netback/netfront make sure the new skb has
all the necessary fields initialised. In particular, before we were
not copying ip_summed and that screws up checksum offload.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed May 10 17:30:42 2006 +0100 (2006-05-10)
parents 8f0f24dae963
children 48c0f5489d44
line source
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 */
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>
57 static int nloopbacks = 8;
58 module_param(nloopbacks, int, 0);
59 MODULE_PARM_DESC(nloopbacks, "Number of netback-loopback devices to create");
61 struct net_private {
62 struct net_device *loopback_dev;
63 struct net_device_stats stats;
64 };
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 }
74 static int loopback_close(struct net_device *dev)
75 {
76 netif_stop_queue(dev);
77 return 0;
78 }
80 static int loopback_start_xmit(struct sk_buff *skb, struct net_device *dev)
81 {
82 struct net_private *np = netdev_priv(dev);
84 dst_release(skb->dst);
85 skb->dst = NULL;
87 skb_orphan(skb);
89 np->stats.tx_bytes += skb->len;
90 np->stats.tx_packets++;
92 /* Switch to loopback context. */
93 dev = np->loopback_dev;
94 np = netdev_priv(dev);
96 np->stats.rx_bytes += skb->len;
97 np->stats.rx_packets++;
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 }
106 skb->ip_summed = skb->proto_data_valid ?
107 CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
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);
115 return 0;
116 }
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 }
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 };
130 /*
131 * Nothing to do here. Virtual interface is point-to-point and the
132 * physical interface is probably promiscuous anyway.
133 */
134 static void loopback_set_multicast_list(struct net_device *dev)
135 {
136 }
138 static void loopback_construct(struct net_device *dev, struct net_device *lo)
139 {
140 struct net_private *np = netdev_priv(dev);
142 np->loopback_dev = lo;
144 dev->open = loopback_open;
145 dev->stop = loopback_close;
146 dev->hard_start_xmit = loopback_start_xmit;
147 dev->get_stats = loopback_get_stats;
148 dev->set_multicast_list = loopback_set_multicast_list;
150 dev->tx_queue_len = 0;
152 dev->features = (NETIF_F_HIGHDMA |
153 NETIF_F_LLTX |
154 NETIF_F_IP_CSUM);
156 SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
158 /*
159 * We do not set a jumbo MTU on the interface. Otherwise the network
160 * stack will try to send large packets that will get dropped by the
161 * Ethernet bridge (unless the physical Ethernet interface is
162 * configured to transfer jumbo packets). If a larger MTU is desired
163 * then the system administrator can specify it using the 'ifconfig'
164 * command.
165 */
166 /*dev->mtu = 16*1024;*/
167 }
169 static int __init make_loopback(int i)
170 {
171 struct net_device *dev1, *dev2;
172 char dev_name[IFNAMSIZ];
173 int err = -ENOMEM;
175 sprintf(dev_name, "vif0.%d", i);
176 dev1 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
177 if (!dev1)
178 return err;
180 sprintf(dev_name, "veth%d", i);
181 dev2 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
182 if (!dev2)
183 goto fail_netdev2;
185 loopback_construct(dev1, dev2);
186 loopback_construct(dev2, dev1);
188 /*
189 * Initialise a dummy MAC address for the 'dummy backend' interface. We
190 * choose the numerically largest non-broadcast address to prevent the
191 * address getting stolen by an Ethernet bridge for STP purposes.
192 */
193 memset(dev1->dev_addr, 0xFF, ETH_ALEN);
194 dev1->dev_addr[0] &= ~0x01;
196 if ((err = register_netdev(dev1)) != 0)
197 goto fail;
199 if ((err = register_netdev(dev2)) != 0) {
200 unregister_netdev(dev1);
201 goto fail;
202 }
204 return 0;
206 fail:
207 free_netdev(dev2);
208 fail_netdev2:
209 free_netdev(dev1);
210 return err;
211 }
213 static void __init clean_loopback(int i)
214 {
215 struct net_device *dev1, *dev2;
216 char dev_name[IFNAMSIZ];
218 sprintf(dev_name, "vif0.%d", i);
219 dev1 = dev_get_by_name(dev_name);
220 sprintf(dev_name, "veth%d", i);
221 dev2 = dev_get_by_name(dev_name);
222 if (dev1 && dev2) {
223 unregister_netdev(dev2);
224 unregister_netdev(dev1);
225 free_netdev(dev2);
226 free_netdev(dev1);
227 }
228 }
230 static int __init loopback_init(void)
231 {
232 int i, err = 0;
234 for (i = 0; i < nloopbacks; i++)
235 if ((err = make_loopback(i)) != 0)
236 break;
238 return err;
239 }
241 module_init(loopback_init);
243 static void __exit loopback_exit(void)
244 {
245 int i;
247 for (i = nloopbacks; i-- > 0; )
248 clean_loopback(i);
249 }
251 module_exit(loopback_exit);
253 MODULE_LICENSE("Dual BSD/GPL");
255 /*
256 * Local variables:
257 * c-file-style: "linux"
258 * indent-tabs-mode: t
259 * c-indent-level: 8
260 * c-basic-offset: 8
261 * tab-width: 8
262 * End:
263 */