ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/netback/interface.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 019411cc3ae5
children 48c0f5489d44
line source
1 /******************************************************************************
2 * arch/xen/drivers/netif/backend/interface.c
3 *
4 * Network-device interface management.
5 *
6 * Copyright (c) 2004-2005, Keir Fraser
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation; or, when distributed
11 * separately from the Linux kernel or incorporated into other
12 * software packages, subject to the following license:
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this source file (the "Software"), to deal in the Software without
16 * restriction, including without limitation the rights to use, copy, modify,
17 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
18 * and to permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30 * IN THE SOFTWARE.
31 */
33 #include "common.h"
34 #include <linux/ethtool.h>
35 #include <linux/rtnetlink.h>
37 static void __netif_up(netif_t *netif)
38 {
39 struct net_device *dev = netif->dev;
40 spin_lock_bh(&dev->xmit_lock);
41 netif->active = 1;
42 spin_unlock_bh(&dev->xmit_lock);
43 enable_irq(netif->irq);
44 netif_schedule_work(netif);
45 }
47 static void __netif_down(netif_t *netif)
48 {
49 struct net_device *dev = netif->dev;
50 disable_irq(netif->irq);
51 spin_lock_bh(&dev->xmit_lock);
52 netif->active = 0;
53 spin_unlock_bh(&dev->xmit_lock);
54 netif_deschedule_work(netif);
55 }
57 static int net_open(struct net_device *dev)
58 {
59 netif_t *netif = netdev_priv(dev);
60 if (netif->status == CONNECTED)
61 __netif_up(netif);
62 netif_start_queue(dev);
63 return 0;
64 }
66 static int net_close(struct net_device *dev)
67 {
68 netif_t *netif = netdev_priv(dev);
69 netif_stop_queue(dev);
70 if (netif->status == CONNECTED)
71 __netif_down(netif);
72 return 0;
73 }
75 static struct ethtool_ops network_ethtool_ops =
76 {
77 .get_tx_csum = ethtool_op_get_tx_csum,
78 .set_tx_csum = ethtool_op_set_tx_csum,
79 };
81 netif_t *netif_alloc(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
82 {
83 int err = 0, i;
84 struct net_device *dev;
85 netif_t *netif;
86 char name[IFNAMSIZ] = {};
88 snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
89 dev = alloc_netdev(sizeof(netif_t), name, ether_setup);
90 if (dev == NULL) {
91 DPRINTK("Could not create netif: out of memory\n");
92 return ERR_PTR(-ENOMEM);
93 }
95 netif = netdev_priv(dev);
96 memset(netif, 0, sizeof(*netif));
97 netif->domid = domid;
98 netif->handle = handle;
99 netif->status = DISCONNECTED;
100 atomic_set(&netif->refcnt, 1);
101 init_waitqueue_head(&netif->waiting_to_free);
102 netif->dev = dev;
104 netif->credit_bytes = netif->remaining_credit = ~0UL;
105 netif->credit_usec = 0UL;
106 init_timer(&netif->credit_timeout);
108 dev->hard_start_xmit = netif_be_start_xmit;
109 dev->get_stats = netif_be_get_stats;
110 dev->open = net_open;
111 dev->stop = net_close;
112 dev->features = NETIF_F_IP_CSUM;
114 SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
116 /* Disable queuing. */
117 dev->tx_queue_len = 0;
119 for (i = 0; i < ETH_ALEN; i++)
120 if (be_mac[i] != 0)
121 break;
122 if (i == ETH_ALEN) {
123 /*
124 * Initialise a dummy MAC address. We choose the numerically
125 * largest non-broadcast address to prevent the address getting
126 * stolen by an Ethernet bridge for STP purposes.
127 * (FE:FF:FF:FF:FF:FF)
128 */
129 memset(dev->dev_addr, 0xFF, ETH_ALEN);
130 dev->dev_addr[0] &= ~0x01;
131 } else
132 memcpy(dev->dev_addr, be_mac, ETH_ALEN);
134 rtnl_lock();
135 err = register_netdevice(dev);
136 rtnl_unlock();
137 if (err) {
138 DPRINTK("Could not register new net device %s: err=%d\n",
139 dev->name, err);
140 free_netdev(dev);
141 return ERR_PTR(err);
142 }
144 DPRINTK("Successfully created netif\n");
145 return netif;
146 }
148 static int map_frontend_pages(
149 netif_t *netif, grant_ref_t tx_ring_ref, grant_ref_t rx_ring_ref)
150 {
151 struct gnttab_map_grant_ref op;
152 int ret;
154 gnttab_set_map_op(&op, (unsigned long)netif->tx_comms_area->addr,
155 GNTMAP_host_map, tx_ring_ref, netif->domid);
157 lock_vm_area(netif->tx_comms_area);
158 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
159 unlock_vm_area(netif->tx_comms_area);
160 BUG_ON(ret);
162 if (op.status) {
163 DPRINTK(" Gnttab failure mapping tx_ring_ref!\n");
164 return op.status;
165 }
167 netif->tx_shmem_ref = tx_ring_ref;
168 netif->tx_shmem_handle = op.handle;
170 gnttab_set_map_op(&op, (unsigned long)netif->rx_comms_area->addr,
171 GNTMAP_host_map, rx_ring_ref, netif->domid);
173 lock_vm_area(netif->rx_comms_area);
174 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
175 unlock_vm_area(netif->rx_comms_area);
176 BUG_ON(ret);
178 if (op.status) {
179 DPRINTK(" Gnttab failure mapping rx_ring_ref!\n");
180 return op.status;
181 }
183 netif->rx_shmem_ref = rx_ring_ref;
184 netif->rx_shmem_handle = op.handle;
186 return 0;
187 }
189 static void unmap_frontend_pages(netif_t *netif)
190 {
191 struct gnttab_unmap_grant_ref op;
192 int ret;
194 gnttab_set_unmap_op(&op, (unsigned long)netif->tx_comms_area->addr,
195 GNTMAP_host_map, netif->tx_shmem_handle);
197 lock_vm_area(netif->tx_comms_area);
198 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
199 unlock_vm_area(netif->tx_comms_area);
200 BUG_ON(ret);
202 gnttab_set_unmap_op(&op, (unsigned long)netif->rx_comms_area->addr,
203 GNTMAP_host_map, netif->rx_shmem_handle);
205 lock_vm_area(netif->rx_comms_area);
206 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
207 unlock_vm_area(netif->rx_comms_area);
208 BUG_ON(ret);
209 }
211 int netif_map(netif_t *netif, unsigned long tx_ring_ref,
212 unsigned long rx_ring_ref, unsigned int evtchn)
213 {
214 int err = -ENOMEM;
215 netif_tx_sring_t *txs;
216 netif_rx_sring_t *rxs;
217 struct evtchn_bind_interdomain bind_interdomain;
219 /* Already connected through? */
220 if (netif->irq)
221 return 0;
223 netif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
224 if (netif->tx_comms_area == NULL)
225 return -ENOMEM;
226 netif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
227 if (netif->rx_comms_area == NULL)
228 goto err_rx;
230 err = map_frontend_pages(netif, tx_ring_ref, rx_ring_ref);
231 if (err)
232 goto err_map;
234 bind_interdomain.remote_dom = netif->domid;
235 bind_interdomain.remote_port = evtchn;
237 err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
238 &bind_interdomain);
239 if (err)
240 goto err_hypervisor;
242 netif->evtchn = bind_interdomain.local_port;
244 netif->irq = bind_evtchn_to_irqhandler(
245 netif->evtchn, netif_be_int, 0, netif->dev->name, netif);
246 disable_irq(netif->irq);
248 txs = (netif_tx_sring_t *)netif->tx_comms_area->addr;
249 BACK_RING_INIT(&netif->tx, txs, PAGE_SIZE);
251 rxs = (netif_rx_sring_t *)
252 ((char *)netif->rx_comms_area->addr);
253 BACK_RING_INIT(&netif->rx, rxs, PAGE_SIZE);
255 netif->rx_req_cons_peek = 0;
257 netif_get(netif);
258 wmb(); /* Other CPUs see new state before interface is started. */
260 rtnl_lock();
261 netif->status = CONNECTED;
262 wmb();
263 if (netif_running(netif->dev))
264 __netif_up(netif);
265 rtnl_unlock();
267 return 0;
268 err_hypervisor:
269 unmap_frontend_pages(netif);
270 err_map:
271 free_vm_area(netif->rx_comms_area);
272 err_rx:
273 free_vm_area(netif->tx_comms_area);
274 return err;
275 }
277 static void netif_free(netif_t *netif)
278 {
279 atomic_dec(&netif->refcnt);
280 wait_event(netif->waiting_to_free, atomic_read(&netif->refcnt) == 0);
282 if (netif->irq)
283 unbind_from_irqhandler(netif->irq, netif);
285 unregister_netdev(netif->dev);
287 if (netif->tx.sring) {
288 unmap_frontend_pages(netif);
289 free_vm_area(netif->tx_comms_area);
290 free_vm_area(netif->rx_comms_area);
291 }
293 free_netdev(netif->dev);
294 }
296 void netif_disconnect(netif_t *netif)
297 {
298 switch (netif->status) {
299 case CONNECTED:
300 rtnl_lock();
301 netif->status = DISCONNECTING;
302 wmb();
303 if (netif_running(netif->dev))
304 __netif_down(netif);
305 rtnl_unlock();
306 netif_put(netif);
307 /* fall through */
308 case DISCONNECTED:
309 netif_free(netif);
310 break;
311 default:
312 BUG();
313 }
314 }
316 /*
317 * Local variables:
318 * c-file-style: "linux"
319 * indent-tabs-mode: t
320 * c-indent-level: 8
321 * c-basic-offset: 8
322 * tab-width: 8
323 * End:
324 */