Network Device Driver
Apr 19, 2002
Yongguang Zhang
Today's Lecture
- Doing a Network Device Driver
struct net_device
- char name[IFNAMSIZ];
- name of device (e.g., "eth0")
- if "XXX%d" during registration, the kernel will fill in for you
- unsigned short flags;
- Interface flags
- IFF_UP, IFF_RUNNING, IFF_LOOPBACK, IFF_POINTOPOINT, IFF_NOTRAILERS, IFF_NOARP, IFF_PROMISC, IFF_BROADCAST, IFF_ALLMULTI, IFF_MULTICAST, ...
More struct net_device Fields
- int (*init)(struct net_device *dev);
- Called once during registration (if not NULL)
- int (*open)(struct net_device *dev);
- int (*stop)(struct net_device *dev);
- int (*hard_start_xmit)(struct sk_buff *skb, struct net_device *dev);
- Hardware start transmitting
- struct net_device_stats* (*get_stats)(struct net_device *dev);
More struct net_device Fields
Module Init/Exit Functions
- Need a "module init" function to initialize and register the device driver
- Call register_netdev (struct net_device * dev)
- Write a "module exit" function to unregister the device driver
- Specify the "module init" and "module exit" functions as
- module_init(xxx_init_module)
- module_exit(xxx_exit)
When to Populate the Fields
- Name and init(): must be set before register
- Other fields
- Can be populated in xxx_init_module(), or xxx_init()
Skeleton Private Data Structure
struct xxx_struct {
struct net_device dev;
struct net_device_stats stats;
...
} xxx_dev;
Skeleton "Module Init" Function
static int __init xxx_init_module(void)
{
/* probe the hardware, ... */
strcpy(xxx_dev.dev.name, "xxx%d");
xxx_dev.dev.priv = &xxx_dev;
xxx_dev.dev.init = xxx_init;
...
if (register_netdev(&xxx_dev.dev) != 0)
return -EIO;
/* rest of the initial setup */
printk( ... ); return 0;
}
Skeleton "Exit" Function
static void __exit xxx_exit (void)
{
/* clean up */
unregister_netdev(&xxx_dev.dev);
/* clean up */
}
module_init(xxx_init_module);
module_exit(xxx_exit);
Skeleton "Init" Function
static int xxx_init(struct net_device *dev)
{
/* more hardware setup */
/* more setup for dev fields */
dev->open = xxx_open;
dev->hard_start_xmit = xxx_xmit;
…
/* Fill in ethernet-generic values. */
ether_setup(dev);
dev->tx_queue_len = 0;
return 0;
}
Skeleton "Open" Operation
static int xxx_open(struct net_device *dev)
{
/* set up the interrupt service routine */
r = request_irq(dev->irq, &xxx_interrupt, 0, dev->name, dev);
netif_start_queue(dev);
MOD_INC_USE_COUNT;
}
Who calls xxx_open()?
- When you turn up the interface (ifconfig ... up)
Example Transmit Functions
static int xxx_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct xxx_struct *xxx_dev = dev->priv;
/* hardware instructions to really sending out the packet */
xxx_dev->stats.tx_packets++;
xxx_dev->stats.tx_bytes+=skb->len;
dev_kfree_skb(skb);
return 0;
}
Example Interrupt Functions
static void xxx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
/* check the interrupt */
/* if for output, is it end of transmission or abort ... */
/* if for input (incoming packet) */
...
xxx_receive(dev);
...
}
Example Receive Function
static void xxx_receive(struct net_device *dev)
{
struct xxx_struct *xxx_dev = dev->priv;
struct sk_buff *skb;
/* find out the packet len (len) */
skb = dev_alloc_skb(len+2); /* allocate the packet buffer */
skb->dev = dev;
skb_reserve(skb, 2); /* 16 byte align */
skb_put(skb, len); /* make room */
/* have the hardware read the packet into skb */
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
xxx_dev->stats.rx_packets++; xxx_dev->stats.rx_bytes+=len;
return;
}
Rest of This Lecture
- Projects Q&A
- Evaluation Forms
© 2002 Yongguang Zhang