免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2980 | 回复: 2
打印 上一主题 下一主题

虚拟网卡驱动snull中的MAC地址问题!!! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-01-12 10:39 |只看该作者 |倒序浏览
http://www.cs.fsu.edu/找的snull.c想做一个虚拟网卡。然后做成内核模块的方式。内核版本是2.6.27.5
这个是源码:
snull.c

  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/moduleparam.h>

  4. #include <linux/sched.h>
  5. #include <linux/kernel.h> /* printk() */
  6. #include <linux/slab.h> /* kmalloc() */
  7. #include <linux/errno.h>  /* error codes */
  8. #include <linux/types.h>  /* size_t */
  9. #include <linux/interrupt.h> /* mark_bh */

  10. #include <linux/in.h>
  11. #include <linux/netdevice.h>   /* struct device, and other headers */
  12. #include <linux/etherdevice.h> /* eth_type_trans */
  13. #include <linux/ip.h>          /* struct iphdr */
  14. #include <linux/tcp.h>         /* struct tcphdr */
  15. #include <linux/skbuff.h>

  16. #include "snull.h"

  17. #include <linux/in6.h>
  18. #include <asm/checksum.h>

  19. MODULE_AUTHOR("Alessandro Rubini, Jonathan Corbet");
  20. MODULE_LICENSE("Dual BSD/GPL");

  21. static int lockup = 0;
  22. module_param(lockup, int, 0);

  23. //static int timeout = SNULL_TIMEOUT;
  24. static int timeout = 10;
  25. module_param(timeout, int, 0);


  26. static int use_napi = 0;
  27. module_param(use_napi, int, 0);


  28. struct net_device *snull_devs[2];

  29. struct snull_packet {
  30.         struct snull_packet *next;
  31.         struct net_device *dev;
  32.         int     datalen;
  33.         u8 data[ETH_DATA_LEN];
  34. };

  35. int pool_size = 8;
  36. module_param(pool_size, int, 0);


  37. struct snull_priv {
  38.         struct net_device_stats stats;
  39.         int status;
  40.         struct snull_packet *ppool;
  41.         struct snull_packet *rx_queue;  /* List of incoming packets */
  42.         int rx_int_enabled;
  43.         int tx_packetlen;
  44.         u8 *tx_packetdata;
  45.         struct sk_buff *skb;
  46.         spinlock_t lock;
  47.         struct net_device *dev;
  48.         struct napi_struct napi;
  49. };

  50. static void snull_tx_timeout(struct net_device *dev);
  51. static void (*snull_interrupt)(int, void *, struct pt_regs *);

  52. void snull_setup_pool(struct net_device *dev)
  53. {
  54.         struct snull_priv *priv = netdev_priv(dev);
  55.         int i;
  56.         struct snull_packet *pkt;

  57.         priv->ppool = NULL;
  58.         for (i = 0; i < pool_size; i++) {
  59.                 pkt = kmalloc (sizeof (struct snull_packet), GFP_KERNEL);
  60.                 if (pkt == NULL) {
  61.                         printk (KERN_NOTICE "Ran out of memory allocating packet pool\n");
  62.                         return;
  63.                 }
  64.                 pkt->dev = dev;
  65.                 pkt->next = priv->ppool;
  66.                 priv->ppool = pkt;
  67.         }
  68. }

  69. void snull_teardown_pool(struct net_device *dev)
  70. {
  71.         struct snull_priv *priv = netdev_priv(dev);
  72.         struct snull_packet *pkt;
  73.    
  74.         while ((pkt = priv->ppool)) {
  75.                 priv->ppool = pkt->next;
  76.                 kfree (pkt);
  77.                 /* FIXME - in-flight packets ? */
  78.         }
  79. }   


  80. struct snull_packet *snull_get_tx_buffer(struct net_device *dev)
  81. {
  82.         struct snull_priv *priv = netdev_priv(dev);
  83.         unsigned long flags;
  84.         struct snull_packet *pkt;
  85.    
  86.         spin_lock_irqsave(&priv->lock, flags);
  87.         pkt = priv->ppool;
  88.         priv->ppool = pkt->next;
  89.         if (priv->ppool == NULL) {
  90.                 printk (KERN_INFO "Pool empty\n");
  91.                 netif_stop_queue(dev);
  92.         }
  93.         spin_unlock_irqrestore(&priv->lock, flags);
  94.         return pkt;
  95. }


  96. void snull_release_buffer(struct snull_packet *pkt)
  97. {
  98.         unsigned long flags;
  99.         struct snull_priv *priv = netdev_priv(pkt->dev);
  100.         
  101.         spin_lock_irqsave(&priv->lock, flags);
  102.         pkt->next = priv->ppool;
  103.         priv->ppool = pkt;
  104.         spin_unlock_irqrestore(&priv->lock, flags);
  105.         if (netif_queue_stopped(pkt->dev) && pkt->next == NULL)
  106.                 netif_wake_queue(pkt->dev);
  107. }

  108. void snull_enqueue_buf(struct net_device *dev, struct snull_packet *pkt)
  109. {
  110.         unsigned long flags;
  111.         struct snull_priv *priv = netdev_priv(dev);

  112.         spin_lock_irqsave(&priv->lock, flags);
  113.         pkt->next = priv->rx_queue;  /* FIXME - misorders packets */
  114.         priv->rx_queue = pkt;
  115.         spin_unlock_irqrestore(&priv->lock, flags);
  116. }

  117. struct snull_packet *snull_dequeue_buf(struct net_device *dev)
  118. {
  119.         struct snull_priv *priv = netdev_priv(dev);
  120.         struct snull_packet *pkt;
  121.         unsigned long flags;

  122.         spin_lock_irqsave(&priv->lock, flags);
  123.         pkt = priv->rx_queue;
  124.         if (pkt != NULL)
  125.                 priv->rx_queue = pkt->next;
  126.         spin_unlock_irqrestore(&priv->lock, flags);
  127.         return pkt;
  128. }


  129. static void snull_rx_ints(struct net_device *dev, int enable)
  130. {
  131.         struct snull_priv *priv = netdev_priv(dev);
  132.         priv->rx_int_enabled = enable;
  133. }


  134. int snull_open(struct net_device *dev)
  135. {
  136.         memcpy(dev->dev_addr, "\0SNUL0", ETH_ALEN);
  137.         if (dev == snull_devs[1])
  138.                 dev->dev_addr[ETH_ALEN-1]++; /* \0SNUL1 */
  139.         netif_start_queue(dev);
  140.         return 0;
  141. }

  142. int snull_release(struct net_device *dev)
  143. {
  144.     /* release ports, irq and such -- like fops->close */

  145.         netif_stop_queue(dev); /* can't transmit any more */
  146.         return 0;
  147. }

  148. int snull_set_mac_address(struct net_device *dev,void *p)
  149. {
  150.         int i;
  151.         struct sockaddr *addr = p;
  152.         if(netif_running(dev))
  153.         {
  154.                 return -EBUSY;
  155.         }
  156.        
  157.         if(!is_valid_ether_addr(addr->sa_data))
  158.         {
  159.                 return -EADDRNOTAVAIL;
  160.         }
  161.        
  162.         memcpy(dev->dev_addr,addr->sa_data,dev->addr_len);
  163.        
  164.         memcpy(dev->dev_addr, "\0SNUL0", ETH_ALEN);
  165.                 printk(KERN_ALERT "mac_open2,%s\n",dev->dev_addr);
  166.         if (dev == snull_devs[1])
  167.                 dev->dev_addr[ETH_ALEN-1]++; /* \0SNUL1 */
  168.         return 0;
  169. }


  170. int snull_config(struct net_device *dev, struct ifmap *map)
  171. {
  172.                 printk(KERN_ALERT "snull_config\n");
  173.         if (dev->flags & IFF_UP) /* can't act on a running interface */
  174.                 return -EBUSY;

  175.         /* Don't allow changing the I/O address */
  176.         if (map->base_addr != dev->base_addr) {
  177.                 printk(KERN_WARNING "snull: Can't change I/O address\n");
  178.                 return -EOPNOTSUPP;
  179.         }

  180.         /* Allow changing the IRQ */
  181.         if (map->irq != dev->irq) {
  182.                 dev->irq = map->irq;
  183.                 /* request_irq() is delayed to open-time */
  184.         }

  185.         /* ignore other fields */
  186.         return 0;
  187. }

  188. void snull_rx(struct net_device *dev, struct snull_packet *pkt)
  189. {
  190.         struct sk_buff *skb;
  191.         struct snull_priv *priv = netdev_priv(dev);

  192.         skb = dev_alloc_skb(pkt->datalen + 2);
  193.         if (!skb) {
  194.                 if (printk_ratelimit())
  195.                         printk(KERN_NOTICE "snull rx: low on mem - packet dropped\n");
  196.                 priv->stats.rx_dropped++;
  197.                 goto out;
  198.         }
  199.         skb_reserve(skb, 2); /* align IP on 16B boundary */  
  200.         memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen);

  201.         /* Write metadata, and then pass to the receive level */
  202.         skb->dev = dev;
  203.         skb->protocol = eth_type_trans(skb, dev);
  204.         skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
  205.         priv->stats.rx_packets++;
  206.         priv->stats.rx_bytes += pkt->datalen;
  207.         netif_rx(skb);
  208.   out:
  209.         return;
  210. }
  211.    

  212. /*
  213. * The poll implementation.
  214. */
  215. static int snull_poll(struct napi_struct *napi, int budget)
  216. {
  217.         int npackets = 0;
  218.         struct sk_buff *skb;
  219.         struct snull_priv  *priv = container_of(napi, struct snull_priv, napi);
  220.         struct net_device  *dev =  priv->dev;
  221.         struct snull_packet *pkt;
  222.    
  223.         while (npackets < budget && priv->rx_queue) {
  224.                 pkt = snull_dequeue_buf(dev);
  225.                 skb = dev_alloc_skb(pkt->datalen + 2);
  226.                 if (! skb) {
  227.                         if (printk_ratelimit())
  228.                                 printk(KERN_NOTICE "snull: packet dropped\n");
  229.                         priv->stats.rx_dropped++;
  230.                         snull_release_buffer(pkt);
  231.                         continue;
  232.                 }
  233.                 skb_reserve(skb, 2); /* align IP on 16B boundary */  
  234.                 memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen);
  235.                 skb->dev = dev;
  236.                 skb->protocol = eth_type_trans(skb, dev);
  237.                 skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
  238.                 netif_receive_skb(skb);
  239.                 /* Maintain stats */
  240.                 npackets++;
  241.                 priv->stats.rx_packets++;
  242.                 priv->stats.rx_bytes += pkt->datalen;
  243.                 snull_release_buffer(pkt);
  244.         }
  245.         if (npackets < budget) {
  246.                 napi_complete(napi);
  247.                 snull_rx_ints(dev, 1);
  248.         }
  249.         return npackets;
  250. }
  251.             
  252.         
  253. static void snull_regular_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  254. {
  255.         int statusword;
  256.         struct snull_priv *priv;
  257.         struct snull_packet *pkt = NULL;

  258.         struct net_device *dev = (struct net_device *)dev_id;
  259.         /* ... and check with hw if it's really ours */

  260.         /* paranoid */
  261.         if (!dev)
  262.                 return;

  263.         /* Lock the device */
  264.         priv = netdev_priv(dev);
  265.         spin_lock(&priv->lock);

  266.         statusword = priv->status;
  267.         priv->status = 0;
  268.         if (statusword & SNULL_RX_INTR) {
  269.                 /* send it to snull_rx for handling */
  270.                 pkt = priv->rx_queue;
  271.                 if (pkt) {
  272.                         priv->rx_queue = pkt->next;
  273.                         snull_rx(dev, pkt);
  274.                 }
  275.         }
  276.         if (statusword & SNULL_TX_INTR) {
  277.                 /* a transmission is over: free the skb */
  278.                 priv->stats.tx_packets++;
  279.                 priv->stats.tx_bytes += priv->tx_packetlen;
  280.                 dev_kfree_skb(priv->skb);
  281.         }

  282.         /* Unlock the device and we are done */
  283.         spin_unlock(&priv->lock);
  284.         if (pkt) snull_release_buffer(pkt); /* Do this outside the lock! */
  285.         return;
  286. }


  287. static void snull_napi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  288. {
  289.         int statusword;
  290.         struct snull_priv *priv;


  291.         struct net_device *dev = (struct net_device *)dev_id;

  292.         if (!dev)
  293.                 return;

  294.         /* Lock the device */
  295.         priv = netdev_priv(dev);
  296.         spin_lock(&priv->lock);

  297.         statusword = priv->status;
  298.         priv->status = 0;
  299.         if (statusword & SNULL_RX_INTR) {
  300.                 snull_rx_ints(dev, 0);  /* Disable further interrupts */
  301.                 napi_schedule(&priv->napi);
  302.         }
  303.         if (statusword & SNULL_TX_INTR) {
  304.                 priv->stats.tx_packets++;
  305.                 priv->stats.tx_bytes += priv->tx_packetlen;
  306.                 dev_kfree_skb(priv->skb);
  307.         }

  308.         spin_unlock(&priv->lock);
  309.         return;
  310. }


  311. static void snull_hw_tx(char *buf, int len, struct net_device *dev)
  312. {

  313.         struct iphdr *ih;
  314.         struct net_device *dest;
  315.         struct snull_priv *priv;
  316.         u32 *saddr, *daddr;
  317.         struct snull_packet *tx_buffer;
  318.    
  319.         /* I am paranoid. Ain't I? */
  320.         if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) {
  321.                 printk("snull: Hmm... packet too short (%i octets)\n",
  322.                                 len);
  323.                 return;
  324.         }

  325.         if (0) { /* enable this conditional to look at the data */
  326.                 int i;
  327.                 PDEBUG("len is %i\n" KERN_DEBUG "data:",len);
  328.                 for (i=14 ; i<len; i++)
  329.                         printk(" %02x",buf[i]&0xff);
  330.                 printk("\n");
  331.         }
  332.         ih = (struct iphdr *)(buf+sizeof(struct ethhdr));
  333.         saddr = &ih->saddr;
  334.         daddr = &ih->daddr;

  335.         ((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */
  336.         ((u8 *)daddr)[2] ^= 1;

  337.         ih->check = 0;         /* and rebuild the checksum (ip needs it) */
  338.         ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl);

  339.         if (dev == snull_devs[0])
  340.                 PDEBUGG("%08x:%05i --> %08x:%05i\n",
  341.                                 ntohl(ih->saddr),ntohs(((struct tcphdr *)(ih+1))->source),
  342.                                 ntohl(ih->daddr),ntohs(((struct tcphdr *)(ih+1))->dest));
  343.         else
  344.                 PDEBUGG("%08x:%05i <-- %08x:%05i\n",
  345.                                 ntohl(ih->daddr),ntohs(((struct tcphdr *)(ih+1))->dest),
  346.                                 ntohl(ih->saddr),ntohs(((struct tcphdr *)(ih+1))->source));

  347.         dest = snull_devs[dev == snull_devs[0] ? 1 : 0];
  348.         priv = netdev_priv(dest);
  349.         tx_buffer = snull_get_tx_buffer(dev);
  350.         tx_buffer->datalen = len;
  351.         memcpy(tx_buffer->data, buf, len);
  352.         snull_enqueue_buf(dest, tx_buffer);
  353.         if (priv->rx_int_enabled) {
  354.                 priv->status |= SNULL_RX_INTR;
  355.                 snull_interrupt(0, dest, NULL);
  356.         }

  357.         priv = netdev_priv(dev);
  358.         priv->tx_packetlen = len;
  359.         priv->tx_packetdata = buf;
  360.         priv->status |= SNULL_TX_INTR;
  361.         if (lockup && ((priv->stats.tx_packets + 1) % lockup) == 0) {
  362.                 /* Simulate a dropped transmit interrupt */
  363.                 netif_stop_queue(dev);
  364.                 PDEBUG("Simulate lockup at %ld, txp %ld\n", jiffies,
  365.                                 (unsigned long) priv->stats.tx_packets);
  366.         }
  367.         else
  368.                 snull_interrupt(0, dev, NULL);
  369. }

  370. int snull_tx(struct sk_buff *skb, struct net_device *dev)
  371. {
  372.         int len;
  373.         char *data, shortpkt[ETH_ZLEN];
  374.         struct snull_priv *priv = netdev_priv(dev);
  375.         
  376.         data = skb->data;
  377.         len = skb->len;
  378.         if (len < ETH_ZLEN) {
  379.                 memset(shortpkt, 0, ETH_ZLEN);
  380.                 memcpy(shortpkt, skb->data, skb->len);
  381.                 len = ETH_ZLEN;
  382.                 data = shortpkt;
  383.         }
  384.         dev->trans_start = jiffies; /* save the timestamp */

  385.         priv->skb = skb;

  386.         snull_hw_tx(data, len, dev);

  387.         return 0; /* Our simple device can not fail */
  388. }

  389. /*
  390. * Deal with a transmit timeout.
  391. */
  392. void snull_tx_timeout (struct net_device *dev)
  393. {
  394.         struct snull_priv *priv = netdev_priv(dev);

  395.         PDEBUG("Transmit timeout at %ld, latency %ld\n", jiffies,
  396.                         jiffies - dev->trans_start);
  397.         /* Simulate a transmission interrupt to get things moving */
  398.         priv->status = SNULL_TX_INTR;
  399.         snull_interrupt(0, dev, NULL);
  400.         priv->stats.tx_errors++;
  401.         netif_wake_queue(dev);
  402.         return;
  403. }


  404. int snull_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  405. {
  406.         PDEBUG("ioctl\n");
  407.         return 0;
  408. }

  409. struct net_device_stats *snull_stats(struct net_device *dev)
  410. {
  411.         struct snull_priv *priv = netdev_priv(dev);
  412.         return &priv->stats;
  413. }


  414. int snull_rebuild_header(struct sk_buff *skb)
  415. {
  416.         struct ethhdr *eth = (struct ethhdr *) skb->data;
  417.         struct net_device *dev = skb->dev;
  418.    
  419.         memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
  420.         memcpy(eth->h_dest, dev->dev_addr, dev->addr_len);
  421.         eth->h_dest[ETH_ALEN-1]   ^= 0x01;   /* dest is us xor 1 */
  422.         return 0;
  423. }


  424. int snull_header(struct sk_buff *skb, struct net_device *dev,
  425.                  unsigned short type, const void *daddr, const void *saddr,
  426.                 unsigned int len)
  427. {
  428.         struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);

  429.         eth->h_proto = htons(type);
  430.         memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len);
  431.         memcpy(eth->h_dest,   daddr ? daddr : dev->dev_addr, dev->addr_len);
  432.         eth->h_dest[ETH_ALEN-1]   ^= 0x01;   /* dest is us xor 1 */
  433.         return (dev->hard_header_len);
  434. }


  435. int snull_change_mtu(struct net_device *dev, int new_mtu)
  436. {
  437.         unsigned long flags;
  438.         struct snull_priv *priv = netdev_priv(dev);
  439.         spinlock_t *lock = &priv->lock;
  440.    
  441.         /* check ranges */
  442.         if ((new_mtu < 68) || (new_mtu > 1500))
  443.                 return -EINVAL;

  444.         spin_lock_irqsave(lock, flags);
  445.         dev->mtu = new_mtu;
  446.         spin_unlock_irqrestore(lock, flags);
  447.         return 0; /* success */
  448. }

  449. static const struct header_ops snull_header_ops = {
  450.         .create  = snull_header,
  451.         .rebuild = snull_rebuild_header,
  452.         .cache   = NULL,  /* disable caching */
  453. };


  454. void snull_init(struct net_device *dev)
  455. {
  456.                 printk(KERN_ALERT "call snull_init\n");
  457.         struct snull_priv *priv;
  458. #if 0

  459. #endif

  460.         ether_setup(dev); /* assign some of the fields */

  461.         dev->open = snull_open,
  462.         dev->stop = snull_release,
  463.         dev->set_config = snull_config,
  464.         dev->hard_start_xmit = snull_tx,
  465. //        dev->do_ioctl = snull_ioctl,
  466.         dev->get_stats = snull_stats,
  467.         dev->change_mtu = snull_change_mtu,
  468.         dev->tx_timeout = snull_tx_timeout,
  469.                 dev->set_mac_address = snull_set_mac_address;
  470. //        dev->netdev_ops      = &snull_netdev_ops;
  471.         dev->header_ops      = &snull_header_ops;
  472.         dev->watchdog_timeo = timeout;
  473.         /* keep the default flags, just add NOARP */
  474.         dev->flags           |= IFF_NOARP;
  475.         dev->features        |= NETIF_F_NO_CSUM;
  476.         /*
  477.          * Then, initialize the priv field. This encloses the statistics
  478.          * and a few private fields.
  479.          */
  480.         priv = netdev_priv(dev);
  481.         memset(priv, 0, sizeof(struct snull_priv));
  482.         priv->dev = dev;
  483.         netif_napi_add(dev, &priv->napi, snull_poll, 2);
  484.         /* The last parameter above is the NAPI "weight". */
  485.         spin_lock_init(&priv->lock);
  486.         snull_rx_ints(dev, 1);          /* enable receive interrupts */
  487.         snull_setup_pool(dev);
  488. }


  489. void snull_cleanup(void)
  490. {
  491.         int i;
  492.    
  493.         for (i = 0; i < 2;  i++) {
  494.                 if (snull_devs[i]) {
  495.                         unregister_netdev(snull_devs[i]);
  496.                         snull_teardown_pool(snull_devs[i]);
  497.                         free_netdev(snull_devs[i]);
  498.                 }
  499.         }
  500.         return;
  501. }




  502. int snull_init_module(void)
  503. {
  504.         int result, i, ret = -ENOMEM;

  505.         snull_interrupt = use_napi ? snull_napi_interrupt : snull_regular_interrupt;

  506.         /* Allocate the devices */
  507.         snull_devs[0] = alloc_netdev(sizeof(struct snull_priv), "sn%d",
  508.                         snull_init);
  509.         snull_devs[1] = alloc_netdev(sizeof(struct snull_priv), "sn%d",
  510.                         snull_init);
  511.         if (snull_devs[0] == NULL || snull_devs[1] == NULL)
  512.                 goto out;

  513.         ret = -ENODEV;
  514.         for (i = 0; i < 2;  i++)
  515.                 if ((result = register_netdev(snull_devs[i])))
  516.                         printk("snull: error %i registering device \"%s\"\n",
  517.                                         result, snull_devs[i]->name);
  518.                 else
  519.                         ret = 0;
  520.    out:
  521.         if (ret)
  522.                 snull_cleanup();
  523.         return ret;
  524. }


  525. module_init(snull_init_module);
  526. module_exit(snull_cleanup);

复制代码
现在的问题是,每次在insmod snull.ko后,sn0\sn1的MAC地址都是00:00:00:00:00:00
我的理解是用ifconfig sn0 up,会调用snull_open,然后函数里面会给sn0赋值MAC地址。可是这个不行,是我的理解有问题么?

后来发现,需要ifconfig sn0 hw ether 00:12:34:56:78:90这样,sn0才会调用snull_open赋值MAC地址。

请问问题出在哪儿了?各位大侠~~~

论坛徽章:
0
2 [报告]
发表于 2012-01-12 10:39 |只看该作者
这个是snull.h


  1. #undef PDEBUG             /* undef it, just in case */
  2. #ifdef SNULL_DEBUG
  3. #  ifdef __KERNEL__
  4. /* This one if debugging is on, and kernel space */
  5. #    define PDEBUG(fmt, args...) printk( KERN_DEBUG "snull: " fmt, ## args)
  6. #  else
  7. /* This one for user space */
  8. #    define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
  9. #  endif
  10. #else
  11. #  define PDEBUG(fmt, args...) /* not debugging: nothing */
  12. #endif

  13. #undef PDEBUGG
  14. #define PDEBUGG(fmt, args...) /* nothing: it's a placeholder */

  15. #define SNULL_RX_INTR 0x0001
  16. #define SNULL_TX_INTR 0x0002

  17. /* Default timeout period */
  18. #define SNULL_TIMEOUT 5   /* In jiffies */

  19. extern struct net_device *snull_devs[];
复制代码

论坛徽章:
0
3 [报告]
发表于 2012-03-06 23:08 |只看该作者
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP