2007-07-26 10:41:03 -07:00
/*D:500
* The Guest network driver .
2007-07-19 01:49:28 -07:00
*
2007-07-26 10:41:03 -07:00
* 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
2007-07-19 01:49:28 -07:00
*
* 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
2007-07-26 10:41:05 -07:00
/*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 . "
: */
2007-07-26 10:41:03 -07:00
/*D:530 The "struct lguestnet_info" contains all the information we need to
* know about the network device . */
2007-07-19 01:49:28 -07:00
struct lguestnet_info
{
2007-07-26 10:41:03 -07:00
/* The mapped device page(s) (an array of "struct lguest_net"). */
2007-07-19 01:49:28 -07:00
struct lguest_net * peer ;
2007-07-26 10:41:03 -07:00
/* The physical address of the device page(s) */
2007-07-19 01:49:28 -07:00
unsigned long peer_phys ;
2007-07-26 10:41:03 -07:00
/* The size of the device page(s). */
2007-07-19 01:49:28 -07:00
unsigned long mapsize ;
/* The lguest_device I come from */
struct lguest_device * lgdev ;
2007-07-26 10:41:03 -07:00
/* My peerid (ie. my slot in the array). */
2007-07-19 01:49:28 -07:00
unsigned int me ;
2007-07-26 10:41:03 -07:00
/* Receive queue: the network packets waiting to be filled. */
2007-07-19 01:49:28 -07:00
struct sk_buff * skb [ NUM_SKBS ] ;
struct lguest_dma dma [ NUM_SKBS ] ;
} ;
2007-07-26 10:41:03 -07:00
/*:*/
2007-07-19 01:49:28 -07:00
/* How many bytes left in this page. */
static unsigned int rest_of_page ( void * data )
{
return PAGE_SIZE - ( ( unsigned long ) data % PAGE_SIZE ) ;
}
2007-07-26 10:41:03 -07:00
/*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. */
2007-07-19 01:49:28 -07:00
static unsigned long peer_key ( struct lguestnet_info * info , unsigned peernum )
{
return info - > peer_phys + 4 * peernum ;
}
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
static void skb_to_dma ( const struct sk_buff * skb , unsigned int headlen ,
struct lguest_dma * dma )
{
unsigned int i , seg ;
2007-07-26 10:41:03 -07:00
/* 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 : */
2007-07-19 01:49:28 -07:00
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 ) ) ;
}
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
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 ) {
2007-07-26 10:41:03 -07:00
/* We will end up sending a truncated packet should
* this ever happen . Plus , a cool log message ! */
2007-07-19 01:49:28 -07:00
printk ( " Woah dude! Megapacket! \n " ) ;
break ;
}
dma - > addr [ seg ] = page_to_phys ( f - > page ) + f - > page_offset ;
dma - > len [ seg ] = f - > size ;
}
2007-07-26 10:41:03 -07:00
/* If after all that we didn't use the entire "struct lguest_dma"
* array , we terminate it with a 0 length . */
2007-07-19 01:49:28 -07:00
if ( seg < LGUEST_MAX_DMA_SECTIONS )
dma - > len [ seg ] = 0 ;
}
2007-07-26 10:41:03 -07:00
/*
* 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 .
*/
2007-07-19 01:49:28 -07:00
# define PROMISC_BIT 0x01
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
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 ;
}
2007-07-26 10:41:03 -07:00
/* A simple test function to see if a peer wants to see all packets.*/
2007-07-19 01:49:28 -07:00
static int promisc ( struct lguestnet_info * info , unsigned int peer )
{
return info - > peer [ peer ] . mac [ 0 ] & PROMISC_BIT ;
}
2007-07-26 10:41:03 -07:00
/* Another simple function to see if a peer's advertised ethernet address
* matches a packet ' s destination ethernet address . */
2007-07-19 01:49:28 -07:00
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 ;
}
2007-07-26 10:41:03 -07:00
/* This is the function which actually sends a packet once we've decided a
* peer wants it : */
2007-07-19 01:49:28 -07:00
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 ;
2007-07-26 10:41:03 -07:00
/* We use our handy "struct lguest_dma" packing function to prepare
* the skb for sending . */
2007-07-19 01:49:28 -07:00
skb_to_dma ( skb , skb_headlen ( skb ) , & dma ) ;
pr_debug ( " xfer length %04x (%u) \n " , htons ( skb - > len ) , skb - > len ) ;
2007-07-26 10:41:03 -07:00
/* This is the actual send call which copies the packet. */
2007-07-19 01:49:28 -07:00
lguest_send_dma ( peer_key ( info , peernum ) , & dma ) ;
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
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 {
2007-07-26 10:41:03 -07:00
/* On success we update the stats. */
2007-07-19 01:49:28 -07:00
dev - > stats . tx_bytes + = skb - > len ;
dev - > stats . tx_packets + + ;
}
}
2007-07-26 10:41:03 -07:00
/* 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. */
2007-07-19 01:49:28 -07:00
static int unused_peer ( const struct lguest_net peer [ ] , unsigned int num )
{
return peer [ num ] . mac [ 0 ] = = 0 ;
}
2007-07-26 10:41:03 -07:00
/* Finally, here is the routine which handles an outgoing packet. It's called
* " start_xmit " for traditional reasons . */
2007-07-19 01:49:28 -07:00
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 ) ;
2007-07-26 10:41:03 -07:00
/* Extract the destination ethernet address from the packet. */
2007-07-19 01:49:28 -07:00
const unsigned char * dest = ( ( struct ethhdr * ) skb - > data ) - > h_dest ;
2007-10-03 17:59:30 -07:00
DECLARE_MAC_BUF ( mac ) ;
2007-07-19 01:49:28 -07:00
2007-10-03 17:59:30 -07:00
pr_debug ( " %s: xmit %s \n " , dev - > name , print_mac ( mac , dest ) ) ;
2007-07-19 01:49:28 -07:00
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
broadcast = is_multicast_ether_addr ( dest ) ;
2007-07-26 10:41:03 -07:00
/* Look through all the published ethernet addresses to see if we
* should send this packet . */
2007-07-19 01:49:28 -07:00
for ( i = 0 ; i < info - > mapsize / sizeof ( struct lguest_net ) ; i + + ) {
2007-07-26 10:41:03 -07:00
/* We don't send to ourselves (we actually can't SEND_DMA to
* ourselves anyway ) , and don ' t send to unused slots . */
2007-07-19 01:49:28 -07:00
if ( i = = info - > me | | unused_peer ( info - > peer , i ) )
continue ;
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
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 ) ;
2007-07-26 10:41:03 -07:00
/* Our routine which actually does the transfer. */
2007-07-19 01:49:28 -07:00
transfer_packet ( dev , skb , i ) ;
}
2007-07-26 10:41:03 -07:00
/* An xmit routine is expected to dispose of the packet, so we do. */
2007-07-19 01:49:28 -07:00
dev_kfree_skb ( skb ) ;
2007-07-26 10:41:03 -07:00
/* As per kernel convention, 0 means success. This is why I love
* networking : even if we never sent to anyone , that ' s still
* success ! */
2007-07-19 01:49:28 -07:00
return 0 ;
}
2007-07-26 10:41:03 -07:00
/*D:560
* Packet receiving .
*
* First , here ' s a helper routine which fills one of our array of receive
* buffers : */
2007-07-19 01:49:28 -07:00
static int fill_slot ( struct net_device * dev , unsigned int slot )
{
struct lguestnet_info * info = netdev_priv ( dev ) ;
2007-07-26 10:41:03 -07:00
/* We can receive ETH_DATA_LEN (1500) byte packets, plus a standard
* ethernet header of ETH_HLEN ( 14 ) bytes . */
2007-07-19 01:49:28 -07:00
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 ;
}
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
skb_to_dma ( info - > skb [ slot ] , ETH_HLEN + ETH_DATA_LEN , & info - > dma [ slot ] ) ;
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
wmb ( ) ;
2007-07-26 10:41:03 -07:00
/* Writing 0 to "used_len" tells the Host it can use this receive
* buffer now . */
2007-07-19 01:49:28 -07:00
info - > dma [ slot ] . used_len = 0 ;
return 0 ;
}
2007-07-26 10:41:03 -07:00
/* 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 : */
2007-07-19 01:49:28 -07:00
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 ;
2007-07-26 10:41:03 -07:00
/* Look through our entire receive array for an entry which has data
* in it . */
2007-07-19 01:49:28 -07:00
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 ;
2007-07-26 10:41:03 -07:00
/* We've found one! Remember the skb (we grabbed the length
* above ) , and immediately refill the slot we ' ve taken it
* from . */
2007-07-19 01:49:28 -07:00
done + + ;
skb = info - > skb [ i ] ;
fill_slot ( dev , i ) ;
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
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 ;
}
2007-07-26 10:41:03 -07:00
/* 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 ) . */
2007-07-19 01:49:28 -07:00
skb_put ( skb , length ) ;
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
skb - > protocol = eth_type_trans ( skb , dev ) ;
2007-07-26 10:41:03 -07:00
/* If this device doesn't need checksums for sending, we also
* don ' t need to check the packets when they come in . */
2007-07-19 01:49:28 -07:00
if ( dev - > features & NETIF_F_NO_CSUM )
skb - > ip_summed = CHECKSUM_UNNECESSARY ;
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
pr_debug ( " Receiving skb proto 0x%04x len %i type %i \n " ,
ntohs ( skb - > protocol ) , skb - > len , skb - > pkt_type ) ;
2007-07-26 10:41:03 -07:00
/* Update the packet and byte counts (visible from ifconfig,
* and good for debugging ) . */
2007-07-19 01:49:28 -07:00
dev - > stats . rx_bytes + = skb - > len ;
dev - > stats . rx_packets + + ;
2007-07-26 10:41:03 -07:00
/* Hand our fresh network packet into the stack's "network
* interface receive " routine. That will free the packet
* itself when it ' s finished . */
2007-07-19 01:49:28 -07:00
netif_rx ( skb ) ;
}
2007-07-26 10:41:03 -07:00
/* If we found any packets, we assume the interrupt was for us. */
2007-07-19 01:49:28 -07:00
return done ? IRQ_HANDLED : IRQ_NONE ;
}
2007-07-26 10:41:03 -07:00
/*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 . */
2007-07-19 01:49:28 -07:00
static int lguestnet_open ( struct net_device * dev )
{
int i ;
struct lguestnet_info * info = netdev_priv ( dev ) ;
2007-07-26 10:41:03 -07:00
/* Copy our MAC address into the device page, so others on the network
* can find us . */
2007-07-19 01:49:28 -07:00
memcpy ( info - > peer [ info - > me ] . mac , dev - > dev_addr , ETH_ALEN ) ;
2007-07-26 10:41:03 -07:00
/* We might already be in promisc mode (dev->flags & IFF_PROMISC). Our
* set_multicast callback handles this already , so we call it now . */
2007-07-19 01:49:28 -07:00
lguestnet_set_multicast ( dev ) ;
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
for ( i = 0 ; i < ARRAY_SIZE ( info - > dma ) ; i + + ) {
if ( fill_slot ( dev , i ) ! = 0 )
goto cleanup ;
}
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
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 ;
}
2007-07-26 10:41:03 -07:00
/*:*/
2007-07-19 01:49:28 -07:00
2007-07-26 10:41:03 -07:00
/* The close routine is called when the device is no longer in use: we clean up
* elegantly . */
2007-07-19 01:49:28 -07:00
static int lguestnet_close ( struct net_device * dev )
{
unsigned int i ;
struct lguestnet_info * info = netdev_priv ( dev ) ;
2007-07-26 10:41:03 -07:00
/* Clear all trace of our existence out of the device memory by setting
* the slot which held our MAC address to 0 ( unused ) . */
2007-07-19 01:49:28 -07:00
memset ( & info - > peer [ info - > me ] , 0 , sizeof ( info - > peer [ info - > me ] ) ) ;
2007-07-26 10:41:03 -07:00
/* Unregister our array of receive buffers */
2007-07-19 01:49:28 -07:00
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 ;
}
2007-07-26 10:41:03 -07:00
/*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. :*/
2007-07-19 01:49:28 -07:00
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 ;
/* 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 ;
2007-07-26 10:41:03 -07:00
/* We don't actually support multicast yet, but turning on/off
* promisc also calls dev - > set_multicast_list . */
2007-07-19 01:49:28 -07:00
dev - > set_multicast_list = lguestnet_set_multicast ;
SET_NETDEV_DEV ( dev , & lgdev - > dev ) ;
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
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 ) ;
2007-07-26 10:41:03 -07:00
/* 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 . */
2007-07-19 01:49:28 -07:00
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 " ) ;
2007-07-26 10:41:03 -07:00
/*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 ? "
*/