aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/lguest_net.c
blob: cab57911a80e041e1f7b536324f1c56de6a44c19 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
/*D:500
 * The Guest network driver.
 *
 * This is very simple a virtual network driver, and our last Guest driver.
 * The only trick is that it can talk directly to multiple other recipients
 * (ie. other Guests on the same network).  It can also be used with only the
 * Host on the network.
 :*/

/* Copyright 2006 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
//#define DEBUG
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/module.h>
#include <linux/mm_types.h>
#include <linux/io.h>
#include <linux/lguest_bus.h>

#define SHARED_SIZE		PAGE_SIZE
#define MAX_LANS		4
#define NUM_SKBS		8

/*M:011 Network code master Jeff Garzik points out numerous shortcomings in
 * this driver if it aspires to greatness.
 *
 * Firstly, it doesn't use "NAPI": the networking's New API, and is poorer for
 * it.  As he says "NAPI means system-wide load leveling, across multiple
 * network interfaces.  Lack of NAPI can mean competition at higher loads."
 *
 * He also points out that we don't implement set_mac_address, so users cannot
 * change the devices hardware address.  When I asked why one would want to:
 * "Bonding, and situations where you /do/ want the MAC address to "leak" out
 * of the host onto the wider net."
 *
 * Finally, he would like module unloading: "It is not unrealistic to think of
 * [un|re|]loading the net support module in an lguest guest.  And, adding
 * module support makes the programmer more responsible, because they now have
 * to learn to clean up after themselves.  Any driver that cannot clean up
 * after itself is an incomplete driver in my book."
 :*/

/*D:530 The "struct lguestnet_info" contains all the information we need to
 * know about the network device. */
struct lguestnet_info
{
	/* The mapped device page(s) (an array of "struct lguest_net"). */
	struct lguest_net *peer;
	/* The physical address of the device page(s) */
	unsigned long peer_phys;
	/* The size of the device page(s). */
	unsigned long mapsize;

	/* The lguest_device I come from */
	struct lguest_device *lgdev;

	/* My peerid (ie. my slot in the array). */
	unsigned int me;

	/* Receive queue: the network packets waiting to be filled. */
	struct sk_buff *skb[NUM_SKBS];
	struct lguest_dma dma[NUM_SKBS];
};
/*:*/

/* How many bytes left in this page. */
static unsigned int rest_of_page(void *data)
{
	return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE);
}

/*D:570 Each peer (ie. Guest or Host) on the network binds their receive
 * buffers to a different key: we simply use the physical address of the
 * device's memory page plus the peer number.  The Host insists that all keys
 * be a multiple of 4, so we multiply the peer number by 4. */
static unsigned long peer_key(struct lguestnet_info *info, unsigned peernum)
{
	return info->peer_phys + 4 * peernum;
}

/* This is the routine which sets up a "struct lguest_dma" to point to a
 * network packet, similar to req_to_dma() in lguest_blk.c.  The structure of a
 * "struct sk_buff" has grown complex over the years: it consists of a "head"
 * linear section pointed to by "skb->data", and possibly an array of
 * "fragments" in the case of a non-linear packet.
 *
 * Our receive buffers don't use fragments at all but outgoing skbs might, so
 * we handle it. */
static void skb_to_dma(const struct sk_buff *skb, unsigned int headlen,
		       struct lguest_dma *dma)
{
	unsigned int i, seg;

	/* First, we put the linear region into the "struct lguest_dma".  Each
	 * entry can't go over a page boundary, so even though all our packets
	 * are 1514 bytes or less, we might need to use two entries here: */
	for (i = seg = 0; i < headlen; seg++, i += rest_of_page(skb->data+i)) {
		dma->addr[seg] = virt_to_phys(skb->data + i);
		dma->len[seg] = min((unsigned)(headlen - i),
				    rest_of_page(skb->data + i));
	}

	/* Now we handle the fragments: at least they're guaranteed not to go
	 * over a page.  skb_shinfo(skb) returns a pointer to the structure
	 * which tells us about the number of fragments and the fragment
	 * array. */
	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++, seg++) {
		const skb_frag_t *f = &skb_shinfo(skb)->frags[i];
		/* Should not happen with MTU less than 64k - 2 * PAGE_SIZE. */
		if (seg == LGUEST_MAX_DMA_SECTIONS) {
			/* We will end up sending a truncated packet should
			 * this ever happen.  Plus, a cool log message! */
			printk("Woah dude!  Megapacket!\n");
			break;
		}
		dma->addr[seg] = page_to_phys(f->page) + f->page_offset;
		dma->len[seg] = f->size;
	}

	/* If after all that we didn't use the entire "struct lguest_dma"
	 * array, we terminate it with a 0 length. */
	if (seg < LGUEST_MAX_DMA_SECTIONS)
		dma->len[seg] = 0;
}

/*
 * Packet transmission.
 *
 * Our packet transmission is a little unusual.  A real network card would just
 * send out the packet and leave the receivers to decide if they're interested.
 * Instead, we look through the network device memory page and see if any of
 * the ethernet addresses match the packet destination, and if so we send it to
 * that Guest.
 *
 * This is made a little more complicated in two cases.  The first case is
 * broadcast packets: for that we send the packet to all Guests on the network,
 * one at a time.  The second case is "promiscuous" mode, where a Guest wants
 * to see all the packets on the network.  We need a way for the Guest to tell
 * us it wants to see all packets, so it sets the "multicast" bit on its
 * published MAC address, which is never valid in a real ethernet address.
 */
#define PROMISC_BIT		0x01

/* This is the callback which is summoned whenever the network device's
 * multicast or promiscuous state changes.  If the card is in promiscuous mode,
 * we advertise that in our ethernet address in the device's memory.  We do the
 * same if Linux wants any or all multicast traffic.  */
static void lguestnet_set_multicast(struct net_device *dev)
{
	struct lguestnet_info *info = netdev_priv(dev);

	if ((dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) || dev->mc_count)
		info->peer[info->me].mac[0] |= PROMISC_BIT;
	else
		info->peer[info->me].mac[0] &= ~PROMISC_BIT;
}

/* A simple test function to see if a peer wants to see all packets.*/
static int promisc(struct lguestnet_info *info, unsigned int peer)
{
	return info->peer[peer].mac[0] & PROMISC_BIT;
}

/* Another simple function to see if a peer's advertised ethernet address
 * matches a packet's destination ethernet address. */
static int mac_eq(const unsigned char mac[ETH_ALEN],
		  struct lguestnet_info *info, unsigned int peer)
{
	/* Ignore multicast bit, which peer turns on to mean promisc. */
	if ((info->peer[peer].mac[0] & (~PROMISC_BIT)) != mac[0])
		return 0;
	return memcmp(mac+1, info->peer[peer].mac+1, ETH_ALEN-1) == 0;
}

/* This is the function which actually sends a packet once we've decided a
 * peer wants it: */
static void transfer_packet(struct net_device *dev,
			    struct sk_buff *skb,
			    unsigned int peernum)
{
	struct lguestnet_info *info = netdev_priv(dev);
	struct lguest_dma dma;

	/* We use our handy "struct lguest_dma" packing function to prepare
	 * the skb for sending. */
	skb_to_dma(skb, skb_headlen(skb), &dma);
	pr_debug("xfer length %04x (%u)\n", htons(skb->len), skb->len);

	/* This is the actual send call which copies the packet. */
	lguest_send_dma(peer_key(info, peernum), &dma);

	/* Check that the entire packet was transmitted.  If not, it could mean
	 * that the other Guest registered a short receive buffer, but this
	 * driver should never do that.  More likely, the peer is dead. */
	if (dma.used_len != skb->len) {
		dev->stats.tx_carrier_errors++;
		pr_debug("Bad xfer to peer %i: %i of %i (dma %p/%i)\n",
			 peernum, dma.used_len, skb->len,
			 (void *)dma.addr[0], dma.len[0]);
	} else {
		/* On success we update the stats. */
		dev->stats.tx_bytes += skb->len;
		dev->stats.tx_packets++;
	}
}

/* Another helper function to tell is if a slot in the device memory is unused.
 * Since we always set the Local Assignment bit in the ethernet address, the
 * first byte can never be 0. */
static int unused_peer(const struct lguest_net peer[], unsigned int num)
{
	return peer[num].mac[0] == 0;
}

/* Finally, here is the routine which handles an outgoing packet.  It's called
 * "start_xmit" for traditional reasons. */
static int lguestnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	unsigned int i;
	int broadcast;
	struct lguestnet_info *info = netdev_priv(dev);
	/* Extract the destination ethernet address from the packet. */
	const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;

	pr_debug("%s: xmit %02x:%02x:%02x:%02x:%02x:%02x\n",
		 dev->name, dest[0],dest[1],dest[2],dest[3],dest[4],dest[5]);

	/* If it's a multicast packet, we broadcast to everyone.  That's not
	 * very efficient, but there are very few applications which actually
	 * use multicast, which is a shame really.
	 *
	 * As etherdevice.h points out: "By definition the broadcast address is
	 * also a multicast address."  So we don't have to test for broadcast
	 * packets separately. */
	broadcast = is_multicast_ether_addr(dest);

	/* Look through all the published ethernet addresses to see if we
	 * should send this packet. */
	for (i = 0; i < info->mapsize/sizeof(struct lguest_net); i++) {
		/* We don't send to ourselves (we actually can't SEND_DMA to
		 * ourselves anyway), and don't send to unused slots.*/
		if (i == info->me || unused_peer(info->peer, i))
			continue;

		/* If it's broadcast we send it.  If they want every packet we
		 * send it.  If the destination matches their address we send
		 * it.  Otherwise we go to the next peer. */
		if (!broadcast && !promisc(info, i) && !mac_eq(dest, info, i))
			continue;

		pr_debug("lguestnet %s: sending from %i to %i\n",
			 dev->name, info->me, i);
		/* Our routine which actually does the transfer. */
		transfer_packet(dev, skb, i);
	}

	/* An xmit routine is expected to dispose of the packet, so we do. */
	dev_kfree_skb(skb);

	/* As per kernel convention, 0 means success.  This is why I love
	 * networking: even if we never sent to anyone, that's still
	 * success! */
	return 0;
}

/*D:560
 * Packet receiving.
 *
 * First, here's a helper routine which fills one of our array of receive
 * buffers: */
static int fill_slot(struct net_device *dev, unsigned int slot)
{
	struct lguestnet_info *info = netdev_priv(dev);

	/* We can receive ETH_DATA_LEN (1500) byte packets, plus a standard
	 * ethernet header of ETH_HLEN (14) bytes. */
	info->skb[slot] = netdev_alloc_skb(dev, ETH_HLEN + ETH_DATA_LEN);
	if (!info->skb[slot]) {
		printk("%s: could not fill slot %i\n", dev->name, slot);
		return -ENOMEM;
	}

	/* skb_to_dma() is a helper which sets up the "struct lguest_dma" to
	 * point to the data in the skb: we also use it for sending out a
	 * packet. */
	skb_to_dma(info->skb[slot], ETH_HLEN + ETH_DATA_LEN, &info->dma[slot]);

	/* This is a Write Memory Barrier: it ensures that the entry in the
	 * receive buffer array is written *before* we set the "used_len" entry
	 * to 0.  If the Host were looking at the receive buffer array from a
	 * different CPU, it could potentially see "used_len = 0" and not see
	 * the updated receive buffer information.  This would be a horribly
	 * nasty bug, so make sure the compiler and CPU know this has to happen
	 * first. */
	wmb();
	/* Writing 0 to "used_len" tells the Host it can use this receive
	 * buffer now. */
	info->dma[slot].used_len = 0;
	return 0;
}

/* This is the actual receive routine.  When we receive an interrupt from the
 * Host to tell us a packet has been delivered, we arrive here: */
static irqreturn_t lguestnet_rcv(int irq, void *dev_id)
{
	struct net_device *dev = dev_id;
	struct lguestnet_info *info = netdev_priv(dev);
	unsigned int i, done = 0;

	/* Look through our entire receive array for an entry which has data
	 * in it. */
	for (i = 0; i < ARRAY_SIZE(info->dma); i++) {
		unsigned int length;
		struct sk_buff *skb;

		length = info->dma[i].used_len;
		if (length == 0)
			continue;

		/* We've found one!  Remember the skb (we grabbed the length
		 * above), and immediately refill the slot we've taken it
		 * from. */
		done++;
		skb = info->skb[i];
		fill_slot(dev, i);

		/* This shouldn't happen: micropackets could be sent by a
		 * badly-behaved Guest on the network, but the Host will never
		 * stuff more data in the buffer than the buffer length. */
		if (length < ETH_HLEN || length > ETH_HLEN + ETH_DATA_LEN) {
			pr_debug(KERN_WARNING "%s: unbelievable skb len: %i\n",
				 dev->name, length);
			dev_kfree_skb(skb);
			continue;
		}

		/* skb_put(), what a great function!  I've ranted about this
		 * function before (http://lkml.org/lkml/1999/9/26/24).  You
		 * call it after you've added data to the end of an skb (in
		 * this case, it was the Host which wrote the data). */
		skb_put(skb, length);

		/* The ethernet header contains a protocol field: we use the
		 * standard helper to extract it, and place the result in
		 * skb->protocol.  The helper also sets up skb->pkt_type and
		 * eats up the ethernet header from the front of the packet. */
		skb->protocol = eth_type_trans(skb, dev);

		/* If this device doesn't need checksums for sending, we also
		 * don't need to check the packets when they come in. */
		if (dev->features & NETIF_F_NO_CSUM)
			skb->ip_summed = CHECKSUM_UNNECESSARY;

		/* As a last resort for debugging the driver or the lguest I/O
		 * subsystem, you can uncomment the "#define DEBUG" at the top
		 * of this file, which turns all the pr_debug() into printk()
		 * and floods the logs. */
		pr_debug("Receiving skb proto 0x%04x len %i type %i\n",
			 ntohs(skb->protocol), skb->len, skb->pkt_type);

		/* Update the packet and byte counts (visible from ifconfig,
		 * and good for debugging). */
		dev->stats.rx_bytes += skb->len;
		dev->stats.rx_packets++;

		/* Hand our fresh network packet into the stack's "network
		 * interface receive" routine.  That will free the packet
		 * itself when it's finished. */
		netif_rx(skb);
	}

	/* If we found any packets, we assume the interrupt was for us. */
	return done ? IRQ_HANDLED : IRQ_NONE;
}

/*D:550 This is where we start: when the device is brought up by dhcpd or
 * ifconfig.  At this point we advertise our MAC address to the rest of the
 * network, and register receive buffers ready for incoming packets. */
static int lguestnet_open(struct net_device *dev)
{
	int i;
	struct lguestnet_info *info = netdev_priv(dev);

	/* Copy our MAC address into the device page, so others on the network
	 * can find us. */
	memcpy(info->peer[info->me].mac, dev->dev_addr, ETH_ALEN);

	/* We might already be in promisc mode (dev->flags & IFF_PROMISC).  Our
	 * set_multicast callback handles this already, so we call it now. */
	lguestnet_set_multicast(dev);

	/* Allocate packets and put them into our "struct lguest_dma" array.
	 * If we fail to allocate all the packets we could still limp along,
	 * but it's a sign of real stress so we should probably give up now. */
	for (i = 0; i < ARRAY_SIZE(info->dma); i++) {
		if (fill_slot(dev, i) != 0)
			goto cleanup;
	}

	/* Finally we tell the Host where our array of "struct lguest_dma"
	 * receive buffers is, binding it to the key corresponding to the
	 * device's physical memory plus our peerid. */
	if (lguest_bind_dma(peer_key(info,info->me), info->dma,
			    NUM_SKBS, lgdev_irq(info->lgdev)) != 0)
		goto cleanup;
	return 0;

cleanup:
	while (--i >= 0)
		dev_kfree_skb(info->skb[i]);
	return -ENOMEM;
}
/*:*/

/* The close routine is called when the device is no longer in use: we clean up
 * elegantly. */
static int lguestnet_close(struct net_device *dev)
{
	unsigned int i;
	struct lguestnet_info *info = netdev_priv(dev);

	/* Clear all trace of our existence out of the device memory by setting
	 * the slot which held our MAC address to 0 (unused). */
	memset(&info->peer[info->me], 0, sizeof(info->peer[info->me]));

	/* Unregister our array of receive buffers */
	lguest_unbind_dma(peer_key(info, info->me), info->dma);
	for (i = 0; i < ARRAY_SIZE(info->dma); i++)
		dev_kfree_skb(info->skb[i]);
	return 0;
}

/*D:510 The network device probe function is basically a standard ethernet
 * device setup.  It reads the "struct lguest_device_desc" and sets the "struct
 * net_device".  Oh, the line-by-line excitement!  Let's skip over it. :*/
static int lguestnet_probe(struct lguest_device *lgdev)
{
	int err, irqf = IRQF_SHARED;
	struct net_device *dev;
	struct lguestnet_info *info;
	struct lguest_device_desc *desc = &lguest_devices[lgdev->index];

	pr_debug("lguest_net: probing for device %i\n", lgdev->index);

	dev = alloc_etherdev(sizeof(struct lguestnet_info));
	if (!dev)
		return -ENOMEM;

	SET_MODULE_OWNER(dev);

	/* Ethernet defaults with some changes */
	ether_setup(dev);
	dev->set_mac_address = NULL;

	dev->dev_addr[0] = 0x02; /* set local assignment bit (IEEE802) */
	dev->dev_addr[1] = 0x00;
	memcpy(&dev->dev_addr[2], &lguest_data.guestid, 2);
	dev->dev_addr[4] = 0x00;
	dev->dev_addr[5] = 0x00;

	dev->open = lguestnet_open;
	dev->stop = lguestnet_close;
	dev->hard_start_xmit = lguestnet_start_xmit;

	/* We don't actually support multicast yet, but turning on/off
	 * promisc also calls dev->set_multicast_list. */
	dev->set_multicast_list = lguestnet_set_multicast;
	SET_NETDEV_DEV(dev, &lgdev->dev);

	/* The network code complains if you have "scatter-gather" capability
	 * if you don't also handle checksums (it seem that would be
	 * "illogical").  So we use a lie of omission and don't tell it that we
	 * can handle scattered packets unless we also don't want checksums,
	 * even though to us they're completely independent. */
	if (desc->features & LGUEST_NET_F_NOCSUM)
		dev->features = NETIF_F_SG|NETIF_F_NO_CSUM;

	info = netdev_priv(dev);
	info->mapsize = PAGE_SIZE * desc->num_pages;
	info->peer_phys = ((unsigned long)desc->pfn << PAGE_SHIFT);
	info->lgdev = lgdev;
	info->peer = lguest_map(info->peer_phys, desc->num_pages);
	if (!info->peer) {
		err = -ENOMEM;
		goto free;
	}

	/* This stores our peerid (upper bits reserved for future). */
	info->me = (desc->features & (info->mapsize-1));

	err = register_netdev(dev);
	if (err) {
		pr_debug("lguestnet: registering device failed\n");
		goto unmap;
	}

	if (lguest_devices[lgdev->index].features & LGUEST_DEVICE_F_RANDOMNESS)
		irqf |= IRQF_SAMPLE_RANDOM;
	if (request_irq(lgdev_irq(lgdev), lguestnet_rcv, irqf, "lguestnet",
			dev) != 0) {
		pr_debug("lguestnet: cannot get irq %i\n", lgdev_irq(lgdev));
		goto unregister;
	}

	pr_debug("lguestnet: registered device %s\n", dev->name);
	/* Finally, we put the "struct net_device" in the generic "struct
	 * lguest_device"s private pointer.  Again, it's not necessary, but
	 * makes sure the cool kernel kids don't tease us. */
	lgdev->private = dev;
	return 0;

unregister:
	unregister_netdev(dev);
unmap:
	lguest_unmap(info->peer);
free:
	free_netdev(dev);
	return err;
}

static struct lguest_driver lguestnet_drv = {
	.name = "lguestnet",
	.owner = THIS_MODULE,
	.device_type = LGUEST_DEVICE_T_NET,
	.probe = lguestnet_probe,
};

static __init int lguestnet_init(void)
{
	return register_lguest_driver(&lguestnet_drv);
}
module_init(lguestnet_init);

MODULE_DESCRIPTION("Lguest network driver");
MODULE_LICENSE("GPL");

/*D:580
 * This is the last of the Drivers, and with this we have covered the many and
 * wonderous and fine (and boring) details of the Guest.
 *
 * "make Launcher" beckons, where we answer questions like "Where do Guests
 * come from?", and "What do you do when someone asks for optimization?"
 */