debuggers.hg

view linux-2.6.10-xen-sparse/drivers/xen/netback/interface.c @ 3639:ef59b38283a5

bitkeeper revision 1.1159.212.64 (42000361XrdUoEK_vD6RMga2eLmwZg)

Allow specification of backend vif MAC addresses. If a backend
MAC is not provided, generate one as before

Signed-off-by: Jody Belka <knew-xen@pimb.org>
Signed-off-by: ian.pratt@cl.cam.ac.uk
author iap10@labyrinth.cl.cam.ac.uk
date Tue Feb 01 22:32:01 2005 +0000 (2005-02-01)
parents 2abc9e0c7f87
children bbe8541361dd
line source
1 /******************************************************************************
2 * arch/xen/drivers/netif/backend/interface.c
3 *
4 * Network-device interface management.
5 *
6 * Copyright (c) 2004, Keir Fraser
7 */
9 #include "common.h"
10 #include <linux/rtnetlink.h>
12 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
13 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
14 #endif
16 #define NETIF_HASHSZ 1024
17 #define NETIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(NETIF_HASHSZ-1))
19 static netif_t *netif_hash[NETIF_HASHSZ];
21 netif_t *netif_find_by_handle(domid_t domid, unsigned int handle)
22 {
23 netif_t *netif = netif_hash[NETIF_HASH(domid, handle)];
24 while ( (netif != NULL) &&
25 ((netif->domid != domid) || (netif->handle != handle)) )
26 netif = netif->hash_next;
27 return netif;
28 }
30 static void __netif_up(netif_t *netif)
31 {
32 struct net_device *dev = netif->dev;
33 spin_lock_bh(&dev->xmit_lock);
34 netif->active = 1;
35 spin_unlock_bh(&dev->xmit_lock);
36 (void)request_irq(netif->irq, netif_be_int, 0, dev->name, netif);
37 netif_schedule_work(netif);
38 }
40 static void __netif_down(netif_t *netif)
41 {
42 struct net_device *dev = netif->dev;
43 spin_lock_bh(&dev->xmit_lock);
44 netif->active = 0;
45 spin_unlock_bh(&dev->xmit_lock);
46 free_irq(netif->irq, netif);
47 netif_deschedule_work(netif);
48 }
50 static int net_open(struct net_device *dev)
51 {
52 netif_t *netif = netdev_priv(dev);
53 if ( netif->status == CONNECTED )
54 __netif_up(netif);
55 netif_start_queue(dev);
56 return 0;
57 }
59 static int net_close(struct net_device *dev)
60 {
61 netif_t *netif = netdev_priv(dev);
62 netif_stop_queue(dev);
63 if ( netif->status == CONNECTED )
64 __netif_down(netif);
65 return 0;
66 }
68 static void __netif_disconnect_complete(void *arg)
69 {
70 netif_t *netif = (netif_t *)arg;
71 ctrl_msg_t cmsg;
72 netif_be_disconnect_t disc;
74 /*
75 * These can't be done in netif_disconnect() because at that point there
76 * may be outstanding requests in the network stack whose asynchronous
77 * responses must still be notified to the remote driver.
78 */
79 unbind_evtchn_from_irq(netif->evtchn);
80 vfree(netif->tx); /* Frees netif->rx as well. */
82 /* Construct the deferred response message. */
83 cmsg.type = CMSG_NETIF_BE;
84 cmsg.subtype = CMSG_NETIF_BE_DISCONNECT;
85 cmsg.id = netif->disconnect_rspid;
86 cmsg.length = sizeof(netif_be_disconnect_t);
87 disc.domid = netif->domid;
88 disc.netif_handle = netif->handle;
89 disc.status = NETIF_BE_STATUS_OKAY;
90 memcpy(cmsg.msg, &disc, sizeof(disc));
92 /*
93 * Make sure message is constructed /before/ status change, because
94 * after the status change the 'netif' structure could be deallocated at
95 * any time. Also make sure we send the response /after/ status change,
96 * as otherwise a subsequent CONNECT request could spuriously fail if
97 * another CPU doesn't see the status change yet.
98 */
99 mb();
100 if ( netif->status != DISCONNECTING )
101 BUG();
102 netif->status = DISCONNECTED;
103 mb();
105 /* Send the successful response. */
106 ctrl_if_send_response(&cmsg);
107 }
109 void netif_disconnect_complete(netif_t *netif)
110 {
111 INIT_WORK(&netif->work, __netif_disconnect_complete, (void *)netif);
112 schedule_work(&netif->work);
113 }
115 void netif_create(netif_be_create_t *create)
116 {
117 int err = 0;
118 domid_t domid = create->domid;
119 unsigned int handle = create->netif_handle;
120 struct net_device *dev;
121 netif_t **pnetif, *netif;
122 char name[IFNAMSIZ];
124 snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
125 dev = alloc_netdev(sizeof(netif_t), name, ether_setup);
126 if ( dev == NULL )
127 {
128 DPRINTK("Could not create netif: out of memory\n");
129 create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
130 return;
131 }
133 netif = netdev_priv(dev);
134 memset(netif, 0, sizeof(*netif));
135 netif->domid = domid;
136 netif->handle = handle;
137 netif->status = DISCONNECTED;
138 atomic_set(&netif->refcnt, 0);
139 netif->dev = dev;
141 netif->credit_bytes = netif->remaining_credit = ~0UL;
142 netif->credit_usec = 0UL;
143 /*init_ac_timer(&new_vif->credit_timeout);*/
145 pnetif = &netif_hash[NETIF_HASH(domid, handle)];
146 while ( *pnetif != NULL )
147 {
148 if ( ((*pnetif)->domid == domid) && ((*pnetif)->handle == handle) )
149 {
150 DPRINTK("Could not create netif: already exists\n");
151 create->status = NETIF_BE_STATUS_INTERFACE_EXISTS;
152 free_netdev(dev);
153 return;
154 }
155 pnetif = &(*pnetif)->hash_next;
156 }
158 dev->hard_start_xmit = netif_be_start_xmit;
159 dev->get_stats = netif_be_get_stats;
160 dev->open = net_open;
161 dev->stop = net_close;
163 /* Disable queuing. */
164 dev->tx_queue_len = 0;
166 if ( (create->be_mac[0] == 0) && (create->be_mac[1] == 0) &&
167 (create->be_mac[2] == 0) && (create->be_mac[3] == 0) &&
168 (create->be_mac[4] == 0) && (create->be_mac[5] == 0) )
169 {
170 /*
171 * Initialise a dummy MAC address. We choose the numerically largest
172 * non-broadcast address to prevent the address getting stolen by an
173 * Ethernet bridge for STP purposes. (FE:FF:FF:FF:FF:FF)
174 */
175 memset(dev->dev_addr, 0xFF, ETH_ALEN);
176 dev->dev_addr[0] &= ~0x01;
177 }
178 else
179 {
180 memcpy(dev->dev_addr, create->be_mac, ETH_ALEN);
181 }
183 memcpy(netif->fe_dev_addr, create->mac, ETH_ALEN);
185 rtnl_lock();
186 err = register_netdevice(dev);
187 rtnl_unlock();
189 if ( err != 0 )
190 {
191 DPRINTK("Could not register new net device %s: err=%d\n",
192 dev->name, err);
193 create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
194 free_netdev(dev);
195 return;
196 }
198 netif->hash_next = *pnetif;
199 *pnetif = netif;
201 DPRINTK("Successfully created netif\n");
202 create->status = NETIF_BE_STATUS_OKAY;
203 }
205 void netif_destroy(netif_be_destroy_t *destroy)
206 {
207 domid_t domid = destroy->domid;
208 unsigned int handle = destroy->netif_handle;
209 netif_t **pnetif, *netif;
211 pnetif = &netif_hash[NETIF_HASH(domid, handle)];
212 while ( (netif = *pnetif) != NULL )
213 {
214 if ( (netif->domid == domid) && (netif->handle == handle) )
215 {
216 if ( netif->status != DISCONNECTED )
217 goto still_connected;
218 goto destroy;
219 }
220 pnetif = &netif->hash_next;
221 }
223 destroy->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
224 return;
226 still_connected:
227 destroy->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
228 return;
230 destroy:
231 *pnetif = netif->hash_next;
232 unregister_netdev(netif->dev);
233 free_netdev(netif->dev);
234 destroy->status = NETIF_BE_STATUS_OKAY;
235 }
237 void netif_connect(netif_be_connect_t *connect)
238 {
239 domid_t domid = connect->domid;
240 unsigned int handle = connect->netif_handle;
241 unsigned int evtchn = connect->evtchn;
242 unsigned long tx_shmem_frame = connect->tx_shmem_frame;
243 unsigned long rx_shmem_frame = connect->rx_shmem_frame;
244 struct vm_struct *vma;
245 pgprot_t prot;
246 int error;
247 netif_t *netif;
248 #if 0
249 struct net_device *eth0_dev;
250 #endif
252 netif = netif_find_by_handle(domid, handle);
253 if ( unlikely(netif == NULL) )
254 {
255 DPRINTK("netif_connect attempted for non-existent netif (%u,%u)\n",
256 connect->domid, connect->netif_handle);
257 connect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
258 return;
259 }
261 if ( netif->status != DISCONNECTED )
262 {
263 connect->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
264 return;
265 }
267 if ( (vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP)) == NULL )
268 {
269 connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
270 return;
271 }
273 prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED);
274 error = direct_remap_area_pages(&init_mm,
275 VMALLOC_VMADDR(vma->addr),
276 tx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
277 prot, domid);
278 error |= direct_remap_area_pages(&init_mm,
279 VMALLOC_VMADDR(vma->addr) + PAGE_SIZE,
280 rx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
281 prot, domid);
282 if ( error != 0 )
283 {
284 if ( error == -ENOMEM )
285 connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
286 else if ( error == -EFAULT )
287 connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
288 else
289 connect->status = NETIF_BE_STATUS_ERROR;
290 vfree(vma->addr);
291 return;
292 }
294 netif->evtchn = evtchn;
295 netif->irq = bind_evtchn_to_irq(evtchn);
296 netif->tx_shmem_frame = tx_shmem_frame;
297 netif->rx_shmem_frame = rx_shmem_frame;
298 netif->tx =
299 (netif_tx_interface_t *)vma->addr;
300 netif->rx =
301 (netif_rx_interface_t *)((char *)vma->addr + PAGE_SIZE);
302 netif->tx->resp_prod = netif->rx->resp_prod = 0;
303 netif_get(netif);
304 wmb(); /* Other CPUs see new state before interface is started. */
306 rtnl_lock();
307 netif->status = CONNECTED;
308 wmb();
309 if ( netif_running(netif->dev) )
310 __netif_up(netif);
311 rtnl_unlock();
313 connect->status = NETIF_BE_STATUS_OKAY;
314 }
316 int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id)
317 {
318 domid_t domid = disconnect->domid;
319 unsigned int handle = disconnect->netif_handle;
320 netif_t *netif;
322 netif = netif_find_by_handle(domid, handle);
323 if ( unlikely(netif == NULL) )
324 {
325 DPRINTK("netif_disconnect attempted for non-existent netif"
326 " (%u,%u)\n", disconnect->domid, disconnect->netif_handle);
327 disconnect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
328 return 1; /* Caller will send response error message. */
329 }
331 if ( netif->status == CONNECTED )
332 {
333 rtnl_lock();
334 netif->status = DISCONNECTING;
335 netif->disconnect_rspid = rsp_id;
336 wmb();
337 if ( netif_running(netif->dev) )
338 __netif_down(netif);
339 rtnl_unlock();
340 netif_put(netif);
341 return 0; /* Caller should not send response message. */
342 }
344 disconnect->status = NETIF_BE_STATUS_OKAY;
345 return 1;
346 }
348 void netif_interface_init(void)
349 {
350 memset(netif_hash, 0, sizeof(netif_hash));
351 }