亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? 網卡驅動.txt

?? 帶有非常詳細注釋的網卡驅動,對于學習網卡驅動的同志來說是不可多得的好資料
?? TXT
?? 第 1 頁 / 共 3 頁
字號:
        }
        /*
         * skb_reserver用來增加skb的date和tail,因為以太網頭部為14字節長,再補上兩個字節就剛好16字節邊界
         * 對齊,所以大多數以太網設備都會在數據包之前保留2個字節。
         */
        skb_reserve(skb, 2); /* align IP on 16B boundary */  
        memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen);

        skb->dev = dev;                        /*skb與接收設備就關聯起來了,它在網絡棧中會被廣泛使用,沒道理不知道數據是誰接收來的吧*/
        skb->protocol = eth_type_trans(skb, dev);        /*獲取上層協議類型,這樣,上層處理函數才知道如何進一步處理*/
        skb->ip_summed = CHECKSUM_UNNECESSARY;                 /* 設置較驗標志:不進行任何校驗,作者的驅動的收發都在內存中進行,是沒有必要進行校驗*/
        
        /*累加計數器*/
        priv->stats.rx_packets++;
        priv->stats.rx_bytes += pkt->datalen;
        
        /*
         * 把數據包交給上層。netif_rx會逐步調用netif_rx_schedule -->__netif_rx_schedule,
         * __netif_rx_schedule函數會調用__raise_softirq_irqoff(NET_RX_SOFTIRQ);觸發網絡接收數據包的軟中斷函數net_rx_action。
         * 軟中斷是Linux內核完成中斷推后處理工作的一種機制,請參考《Linux內核設計與實現》第二版。
         * 唯一需要提及的是,這個軟中斷函數net_rx_action是在網絡系統初始化的時候(linux/net/core/dev.c):注冊的
         * open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);
         */
        netif_rx(skb);
  out:
        return;
}
    

/*
* NAPI 的poll輪詢函數.
*/
static int snull_poll(struct net_device *dev, int *budget)
{
        /*
         * dev->quota是當前CPU能夠從所有接口中接收數據包的最大數目,budget是在
         * 初始化階段分配給接口的weight值,輪詢函數必須接受二者之間的最小值。表示
         * 輪詢函數本次要處理的數據包個數。
         */
        int npackets = 0, quota = min(dev->quota, *budget);
        struct sk_buff *skb;
        struct snull_priv *priv = netdev_priv(dev);
        struct snull_packet *pkt;
    
            /*這個循環次數由要處理的數據包個數,并且,以處理完接收隊列為上限*/
        while (npackets < quota && priv->rx_queue) {
                /*從隊列中取出數據包*/
                pkt = snull_dequeue_buf(dev);
                
                /*接下來的處理,和傳統中斷事實上是一樣的*/
                skb = dev_alloc_skb(pkt->datalen + 2);
                if (! skb) {
                        if (printk_ratelimit())
                                printk(KERN_NOTICE "snull: packet dropped\n");
                        priv->stats.rx_dropped++;
                        snull_release_buffer(pkt);
                        continue;
                }
                skb_reserve(skb, 2); /* align IP on 16B boundary */  
                memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen);
                skb->dev = dev;
                skb->protocol = eth_type_trans(skb, dev);
                skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
                
                /*需要調用netif_receive_skb而不是net_rx將包交給上層協議棧*/
                netif_receive_skb(skb);
                
                /*累加計數器 */
                npackets++;
                priv->stats.rx_packets++;
                priv->stats.rx_bytes += pkt->datalen;
                snull_release_buffer(pkt);
        }
        /* If we processed all packets, we're done; tell the kernel and reenable ints */
        *budget -= npackets;
        dev->quota -= npackets;
        
        //
        if (! priv->rx_queue) {
                netif_rx_complete(dev);
                snull_rx_ints(dev, 1);
                return 0;
        }
        /* We couldn't process everything. */
        return 1;
}
            
        
/*
* 設備的中斷函數,當需要發/收數據,出現錯誤,連接狀態變化等,它會被觸發
* 對于典型的網絡設備,一般會在open函數中注冊中斷函數,這樣,當網絡設備產生中斷時,如接收到數據包時,
* 中斷函數將會被調用。不過在這個例子中,因為沒有真正的物理設備,所以,不存在注冊中斷,也就不存在觸
* 發,對于接收和發送,它都是在自己設計的函數的特定位置被調用。
* 這個中斷函數設計得很簡單,就是取得設備的狀態,判斷是“接收”還是“發送”的中斷,以調用相應的處理函數。
* 而對于,“是哪個設備產生的中斷”這個問題,則由調用它的函數通過第二個參數的賦值來決定。
*/
static void snull_regular_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
        int statusword;
        struct snull_priv *priv;
        struct snull_packet *pkt = NULL;
        /*
         * 通常,需要檢查 "device" 指針以確保這個中斷是發送給自己的。
         * 然后為 "struct device *dev" 賦
         */
        struct net_device *dev = (struct net_device *)dev_id;

        /* paranoid */
        if (!dev)
                return;

        /* 鎖住設備 */
        priv = netdev_priv(dev);
        spin_lock(&priv->lock);

        /* 取得設備狀態指字,對于真實設備,使用I/O指令,比如:int txsr = inb(TX_STATUS); */
        statusword = priv->status;
        priv->status = 0;
        if (statusword & SNULL_RX_INTR) {                /*如果是接收數據包的中斷*/
                /* send it to snull_rx for handling */
                pkt = priv->rx_queue;
                if (pkt) {
                        priv->rx_queue = pkt->next;
                        snull_rx(dev, pkt);
                }
        }
        if (statusword & SNULL_TX_INTR) {                /*如果是發送數據包的中斷*/
                /* a transmission is over: free the skb */
                priv->stats.tx_packets++;
                priv->stats.tx_bytes += priv->tx_packetlen;
                dev_kfree_skb(priv->skb);
        }

        /* 釋放鎖 */
        spin_unlock(&priv->lock);
        
        /*釋放緩沖區*/
        if (pkt) snull_release_buffer(pkt); /* Do this outside the lock! */
        return;
}

/*
* A NAPI interrupt handler.
* 在設備初始化的時候,poll指向指向了snull_poll函數,所以,NAPI中斷處理函數很簡單,
* 當“接收中斷”到達的時候,它就屏蔽此中斷,然后netif_rx_schedule函數接收,接收函數
* 會在未來某一時刻調用注冊的snull_poll函數實現輪詢,當然,對于“傳輸中斷”,處理方法
* 同傳統中斷處理并無二致。
*/
static void snull_napi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
        int statusword;
        struct snull_priv *priv;

        /*
         * As usual, check the "device" pointer for shared handlers.
         * Then assign "struct device *dev"
         */
        struct net_device *dev = (struct net_device *)dev_id;
        /* ... and check with hw if it's really ours */

        /* paranoid */
        if (!dev)
                return;

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

        /* retrieve statusword: real netdevices use I/O instructions */
        statusword = priv->status;
        priv->status = 0;
        
        /*
         * 唯一的區別就在這里,它先屏蔽掉接收中斷,然后調用netif_rx_schedule,而不是netif_rx
         * 重點還是在于poll函數的設計。
         */
        if (statusword & SNULL_RX_INTR) {
                snull_rx_ints(dev, 0);  /* Disable further interrupts */
                netif_rx_schedule(dev);
        }
        if (statusword & SNULL_TX_INTR) {
                /* a transmission is over: free the skb */
                priv->stats.tx_packets++;
                priv->stats.tx_bytes += priv->tx_packetlen;
                dev_kfree_skb(priv->skb);
        }

        /* Unlock the device and we are done */
        spin_unlock(&priv->lock);
        return;
}



/*
* Transmit a packet (low level interface)
*/
static void snull_hw_tx(char *buf, int len, struct net_device *dev)
{
        /*
         * This function deals with hw details. This interface loops
         * back the packet to the other snull interface (if any).
         * In other words, this function implements the snull behaviour,
         * while all other procedures are rather device-independent
         */
        struct iphdr *ih;
        struct net_device *dest;
        struct snull_priv *priv;
        u32 *saddr, *daddr;
        struct snull_packet *tx_buffer;
    
        /* I am paranoid. Ain't I? */
        if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) {
                printk("snull: Hmm... packet too short (%i octets)\n",
                                len);
                return;
        }

        if (0) { /* enable this conditional to look at the data */
                int i;
                PDEBUG("len is %i\n" KERN_DEBUG "data:",len);
                for (i=14 ; i<len; i++)
                        printk(" %02x",buf[i]&0xff);
                printk("\n");
        }
        /*
         * 取得來源IP和目的IP地址
         */
        ih = (struct iphdr *)(buf+sizeof(struct ethhdr));
        saddr = &ih->saddr;
        daddr = &ih->daddr;
        
        /*
         * 這里做了三個調換,以實現欺騙:來源地址第三octet 0<->1,目的地址第三octet 0<->1,設備snX編輯0<->1,這樣做的理由是:
         * sn0(發):192.168.0.88 --> 192.168.0.99        做了調換后,就變成:
         * sn1(收):192.168.1.88 --> 192.168.1.99        因為sn1的地址就是192.168.1.99,所以,它收到這個包后,會回應:
         * sn1(發):192.168.1.99 --> 192.168.1.88        ,同樣地,做了這樣的調換后,就變成:
         * sn0(收):192.168.0.99 --> 192.168.0.88        這樣,sn0就會收到這個包,實現了ping的請求與應答,^o^
         */
        ((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */
        ((u8 *)daddr)[2] ^= 1;

        /*重新計算較驗和*/
        ih->check = 0;         /* and rebuild the checksum (ip needs it) */
        ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl);

        /*輸出調試信息*/
        if (dev == snull_devs[0])
                PDEBUGG("%08x:%05i --> %08x:%05i\n",
                                ntohl(ih->saddr),ntohs(((struct tcphdr *)(ih+1))->source),
                                ntohl(ih->daddr),ntohs(((struct tcphdr *)(ih+1))->dest));
        else
                PDEBUGG("%08x:%05i <-- %08x:%05i\n",
                                ntohl(ih->daddr),ntohs(((struct tcphdr *)(ih+1))->dest),
                                ntohl(ih->saddr),ntohs(((struct tcphdr *)(ih+1))->source));

        /*調換設備編號,即dest指向接收設備,原因如前所述*/
        dest = snull_devs[dev == snull_devs[0] ? 1 : 0];
        
        /*將發送的數據添加到接收設備的接收隊列中*/
        priv = netdev_priv(dest);
        tx_buffer = snull_get_tx_buffer(dev);
        tx_buffer->datalen = len;
        memcpy(tx_buffer->data, buf, len);
        snull_enqueue_buf(dest, tx_buffer);
        
        /*
         * 如果設備接收標志打開,就調用中斷函數把數據包發送給目標設備——即觸發目的設備的接收中斷,這樣
         * 中斷程序就會自接收設備的接收隊列中接收數據包,并交給上層網絡棧處理
        */
        if (priv->rx_int_enabled) {
                priv->status |= SNULL_RX_INTR;
                snull_interrupt(0, dest, NULL);
        }

        /*發送完成后,觸發“發送完成”中斷*/
        priv = netdev_priv(dev);
        priv->tx_packetlen = len;
        priv->tx_packetdata = buf;
        priv->status |= SNULL_TX_INTR;
        
        /*

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产亚洲精品超碰| 欧美日韩黄色一区二区| 久久综合久久久久88| 国产在线精品一区在线观看麻豆| 色哟哟一区二区三区| 一区二区三区精品在线| 欧美影院精品一区| 久久成人免费电影| 亚洲视频在线观看三级| 欧美精品乱人伦久久久久久| 国产精品综合一区二区三区| 亚洲成人精品影院| 国产精品天天看| 3atv在线一区二区三区| 99久久综合精品| 老司机精品视频线观看86| 日韩中文字幕91| 亚洲男人天堂av网| 久久久av毛片精品| 欧美综合一区二区| thepron国产精品| 色噜噜狠狠色综合欧洲selulu| 美女爽到高潮91| 亚洲午夜一区二区| 中文字幕日本不卡| 国产欧美日韩在线观看| 日韩精品一区二区三区在线| 色婷婷综合五月| 在线电影国产精品| 日本一区二区三区视频视频| 亚洲欧美国产三级| 美日韩一区二区| 国产精品一区二区你懂的| 99热精品国产| 欧美一卡2卡三卡4卡5免费| 在线观看日韩高清av| 日韩欧美国产综合一区| 自拍偷自拍亚洲精品播放| 亚洲成av人影院在线观看网| 国产激情视频一区二区三区欧美| 青青草国产成人99久久| 天天操天天综合网| 肉色丝袜一区二区| 成人综合激情网| caoporn国产一区二区| 欧美日韩国产精品成人| 国产欧美日韩在线视频| 日韩一区精品视频| 91久久精品国产91性色tv| 久久伊人中文字幕| 偷窥少妇高潮呻吟av久久免费| 国产成人精品三级麻豆| 91精品在线观看入口| 亚洲精品一二三四区| 亚洲国产日韩精品| 91玉足脚交白嫩脚丫在线播放| 99久久久久久| 欧美挠脚心视频网站| 亚洲欧洲精品一区二区精品久久久| 日本大胆欧美人术艺术动态| 麻豆91在线看| 欧美性受xxxx| 亚洲精品国产视频| 成人av综合一区| 欧美性猛交xxxxxx富婆| 成人欧美一区二区三区1314| 国产激情视频一区二区在线观看 | 久久精品久久久精品美女| 91国产免费看| 中文字幕在线播放不卡一区| 国产美女主播视频一区| 2欧美一区二区三区在线观看视频| 亚洲v日本v欧美v久久精品| 在线视频国内一区二区| 亚洲精品国久久99热| 99精品视频在线免费观看| 国产精品灌醉下药二区| 五月天婷婷综合| 欧美色区777第一页| 久久久99精品久久| 国产成人a级片| 国产欧美视频一区二区| 不卡的av中国片| 亚洲欧美偷拍卡通变态| 色综合天天天天做夜夜夜夜做| 欧美老女人第四色| 手机精品视频在线观看| 日韩午夜激情视频| 亚洲激情第一区| 欧美在线free| 免费一级片91| 国产午夜亚洲精品理论片色戒| 国产成人三级在线观看| 国产精品美女久久久久久2018| www.欧美日韩| 视频一区在线视频| 亚洲精品一线二线三线无人区| 亚洲影视在线观看| av在线综合网| 天天综合色天天综合| 精品福利在线导航| 99久久综合狠狠综合久久| 亚洲综合清纯丝袜自拍| 欧美电视剧免费观看| 高清国产一区二区三区| 精品va天堂亚洲国产| a4yy欧美一区二区三区| 午夜精品视频在线观看| 欧美精品一区二区三区一线天视频| 国产综合色在线视频区| 亚洲情趣在线观看| 欧美成人欧美edvon| 日韩精品午夜视频| 国产精品免费网站在线观看| 欧美性感一区二区三区| 国产精品一区二区你懂的| 亚洲国产aⅴ天堂久久| 久久蜜桃av一区精品变态类天堂| 在线看日本不卡| 国产激情偷乱视频一区二区三区| 亚洲国产精品麻豆| 国产精品久久影院| 精品少妇一区二区三区视频免付费 | 免费人成精品欧美精品 | 在线一区二区三区四区五区 | 日韩精品在线看片z| 色婷婷亚洲综合| 国产乱一区二区| 日日骚欧美日韩| 一区二区高清视频在线观看| 国产情人综合久久777777| 欧美日韩一本到| 色综合久久综合| 成人动漫精品一区二区| 国产一区二区精品久久99| 日本不卡一区二区三区高清视频| 国产精品久久久久一区二区三区| 欧美大黄免费观看| 91精品国产91热久久久做人人| 成人国产一区二区三区精品| 另类小说一区二区三区| 视频一区国产视频| 亚洲综合丝袜美腿| 亚洲精品国产视频| 亚洲美女少妇撒尿| 亚洲免费av在线| 亚洲欧美视频在线观看视频| 国产精品久久久久影院亚瑟| 国产欧美一区二区三区在线看蜜臀 | aaa国产一区| 成人免费视频网站在线观看| 国产在线一区观看| 国产综合久久久久久久久久久久| 蜜桃在线一区二区三区| 美女脱光内衣内裤视频久久网站| 水蜜桃久久夜色精品一区的特点| 同产精品九九九| 蜜桃视频一区二区| 紧缚奴在线一区二区三区| 亚洲天堂福利av| 一区二区三区日韩欧美精品| 亚洲欧美一区二区三区极速播放 | 国产精品原创巨作av| 激情综合网av| 粉嫩aⅴ一区二区三区四区五区| 国产成人丝袜美腿| 99国产欧美久久久精品| 91国产免费看| 日韩一区二区麻豆国产| 精品国产一区二区三区不卡| 久久久另类综合| 中文字幕一区二区在线观看| 亚洲另类春色国产| 日本亚洲电影天堂| 国产一区二区在线影院| 成人高清av在线| 日韩一区二区三区视频在线观看| 日韩免费视频一区二区| 国产精品网站在线| 亚洲午夜精品网| 久久91精品国产91久久小草 | 亚洲夂夂婷婷色拍ww47| 日韩av电影天堂| 大胆亚洲人体视频| 欧美日韩在线电影| 久久女同性恋中文字幕| 亚洲男同1069视频| 精品一区二区三区免费| 97se亚洲国产综合自在线不卡| 欧美区一区二区三区| 国产日产欧产精品推荐色| 亚洲成人一二三| 国产成人在线视频网址| 欧美无乱码久久久免费午夜一区| 精品久久人人做人人爱| 亚洲狼人国产精品| 国产美女久久久久| 欧美高清精品3d| 亚洲人成亚洲人成在线观看图片| 久草热8精品视频在线观看|