Linux网络协议栈(三)--如何写基本的网络驱动程序


Linux Device Driver(3rd version)的第17章已经解释的很详细了,大家可以参考,当然,在2.6.24之后的内核中,使用了N-NAPI,所以书中第17章的程序snull是无法在2.6.24内核中编译通过的,下面是我根据2.6.24内核所作的patch:
--- /home/heyunqi/examples/snull/snull.c 2005-02-01 04:31:02.000000000 +0800
+++ snull.c 2008-08-05 18:12:47.000000000 +0800
@@ -15,7 +15,6 @@
  * $Id: snull.c,v 1.21 2004/11/05 02:36:03 rubini Exp $
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/moduleparam.h>
@@ -87,6 +86,8 @@
  u8 *tx_packetdata;
  struct sk_buff *skb;
  spinlock_t lock;
+ struct napi_struct napi;
+ struct net_device *dev;
 };
 
 static void snull_tx_timeout(struct net_device *dev);
@@ -284,11 +285,12 @@
 /*
  * The poll implementation.
  */
-static int snull_poll(struct net_device *dev, int *budget)
+static int snull_poll(struct napi_struct *napi, int budget)
 {
- int npackets = 0, quota = min(dev->quota, *budget);
+ int npackets = 0, quota = budget;
  struct sk_buff *skb;
- struct snull_priv *priv = netdev_priv(dev);
+ struct snull_priv *priv = container_of(napi,struct snull_priv,napi);
+ struct net_device * dev = priv->dev;
  struct snull_packet *pkt;
    
  while (npackets < quota && priv->rx_queue) {
@@ -315,10 +317,10 @@
   snull_release_buffer(pkt);
  }
  /* If we processed all packets, we're done; tell the kernel and reenable ints */
- *budget -= npackets;
- dev->quota -= npackets;
+ budget -= npackets;
+ //dev->quota -= npackets;
  if (! priv->rx_queue) {
-  netif_rx_complete(dev);
+  netif_rx_complete(dev,napi);
   snull_rx_ints(dev, 1);
   return 0;
  }
@@ -403,7 +405,7 @@
  priv->status = 0;
  if (statusword & SNULL_RX_INTR) {
   snull_rx_ints(dev, 0);  /* Disable further interrupts */
-  netif_rx_schedule(dev);
+  netif_rx_schedule(dev,&priv->napi);
  }
  if (statusword & SNULL_TX_INTR) {
          /* a transmission is over: free the skb */
@@ -572,33 +574,6 @@
  * This function is called to fill up an eth header, since arp is not
  * available on the interface
  */
-int snull_rebuild_header(struct sk_buff *skb)
-{
- struct ethhdr *eth = (struct ethhdr *) skb->data;
- struct net_device *dev = skb->dev;
-   
- memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
- memcpy(eth->h_dest, dev->dev_addr, dev->addr_len);
- eth->h_dest[ETH_ALEN-1]   ^= 0x01;   /* dest is us xor 1 */
- return 0;
-}
-
-
-int snull_header(struct sk_buff *skb, struct net_device *dev,
-                unsigned short type, void *daddr, void *saddr,
-                unsigned int len)
-{
- struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);
-
- eth->h_proto = htons(type);
- memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len);
- memcpy(eth->h_dest,   daddr ? daddr : dev->dev_addr, dev->addr_len);
- eth->h_dest[ETH_ALEN-1]   ^= 0x01;   /* dest is us xor 1 */
- return (dev->hard_header_len);
-}
-
-
-
 
 
 /*
@@ -651,18 +626,11 @@
  dev->do_ioctl        = snull_ioctl;
  dev->get_stats       = snull_stats;
  dev->change_mtu      = snull_change_mtu; 
- dev->rebuild_header  = snull_rebuild_header;
- dev->hard_header     = snull_header;
  dev->tx_timeout      = snull_tx_timeout;
  dev->watchdog_timeo = timeout;
- if (use_napi) {
-  dev->poll        = snull_poll;
-  dev->weight      = 2;
- }
  /* keep the default flags, just add NOARP */
  dev->flags           |= IFF_NOARP;
  dev->features        |= NETIF_F_NO_CSUM;
- dev->hard_header_cache = NULL;      /* Disable caching */
 
  /*
   * Then, initialize the priv field. This encloses the statistics
@@ -707,16 +675,24 @@
 int snull_init_module(void)
 {
  int result, i, ret = -ENOMEM;
+ struct snull_priv* priv;
 
  snull_interrupt = use_napi ? snull_napi_interrupt : snull_regular_interrupt;
 
  /* Allocate the devices */
+ /* Allocate the devices */
  snull_devs[0] = alloc_netdev(sizeof(struct snull_priv), "sn%d",
    snull_init);
  snull_devs[1] = alloc_netdev(sizeof(struct snull_priv), "sn%d",
    snull_init);
  if (snull_devs[0] == NULL || snull_devs[1] == NULL)
   goto out;
+ priv = netdev_priv(snull_devs[0]);
+ priv->dev = snull_devs[0];
+ netif_napi_add(priv->dev, &priv->napi, snull_poll, 64);
+ priv = netdev_priv(snull_devs[1]);
+ priv->dev = snull_devs[1];
+ netif_napi_add(priv->dev, &priv->napi, snull_poll, 64);
 
  ret = -ENODEV;
  for (i = 0; i < 2;  i++)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值