linux迴環網卡驅動設計

来源:http://www.cnblogs.com/chd-zhangbo/archive/2016/01/26/5159949.html
-Advertisement-
Play Games

迴環網卡驅動1.迴環網卡和普通網卡的區別是他是虛擬的不是實際的物理網卡,它相當於把普通網卡的發送端和接收端短接在一起。2.在內核源代碼里的迴環網卡程式(drivers/net/loopback.c)不是以一個模塊的形式給出,但是他的初始化(loopback_net_init)和退出函數(loopba...


迴環網卡驅動
1.迴環網卡和普通網卡的區別是他是虛擬的不是實際的物理網卡,它相當於把普通網卡的發送端和接收端短接在一起。

2.在內核源代碼里的迴環網卡程式(drivers/net/loopback.c)不是以一個模塊的形式給出,但是他的初始化(loopback_net_init)和退出函數(loopback_dev_free)會被內核的其他部分調用到。

3.參照網卡初始化的流程圖進行設計驅動程式,其中分配net_device結構不能用alloc_etherdev函數,因為該函數是分配乙太網卡的結構體的,要用alloc_netdev函數來給迴環網卡分配結構體。參考內核源代碼別人如何用使用這個函數alloc_netdev(0, "lo", loopback_setup);第一個0表示net_device這個結構體的私有成員的大小,一般選擇0,第二個表示網卡名字,ifconfig顯示的名稱,第三個就是具體的網卡結構體的初始化函數指針。
struct net_device *dev;
dev = alloc_netdev(0, "lo", loopback_setup);
最終會調用到loopback_setup函數。(至於在將函數指針作為參數的時候如何傳遞形參,就要複習C語言了)
4.迴環網卡不需要初始化硬體。所以直接註冊迴環網卡的結構體到內核(第三步)。最後指定迴環網卡註冊到網路子系統。
net->loopback_dev = dev;這一步很關鍵。

5.具體的初始化(loopback_setup)(第二步)
(1)基地址,MAC地址以及中斷號都用不著,主要是netdev_ops這個結構體,他包含了這個網卡支持的操作。

(2)表示迴環網卡支持的最大的接收數據的包的大小,除了正式數據,還有相關網路協議的頭部分。
dev->mtu          = (16 * 1024) + 20 + 20 + 12;有效數據一般定義為16KB。

(3)加上表示迴環網卡專有的標誌。
dev->flags          = IFF_LOOPBACK;

(4)加上構造報頭的結構體指針,這個結構體指針指向的結構體成員是眾多構造乙太網報頭的函數指針。
dev->header_ops          = &eth_header_ops;
理想查找可看到
extern const struct header_ops eth_header_ops;

struct header_ops {
     int     (*create) (struct sk_buff *skb, struct net_device *dev,
                  unsigned short type, const void *daddr,
                  const void *saddr, unsigned len);
     int     (*parse)(const struct sk_buff *skb, unsigned char *haddr);
     int     (*rebuild)(struct sk_buff *skb);
#define HAVE_HEADER_CACHE
     int     (*cache)(const struct neighbour *neigh, struct hh_cache *hh);
     void     (*cache_update)(struct hh_cache *hh,
                    const struct net_device *dev,
                    const unsigned char *haddr);
};
6.數據發送

static int loopback_net_xmit(struct sk_buff *skb,struct net_device *dev)
{
skb->protocol = eth_type_trans(skb,dev);

packets++;
bytes += skb->len;

netif_rx(skb);

return 0;
}


}
(1)第一個參數是協議棧傳送給迴環網卡的包數據,第二個參數是迴環網卡的結構體。

(2)停止發送隊列
通知上層暫停送數據,好讓txd發送已送達的數據,但是不涉及硬體,所以在迴環網卡可忽略。相應的,將數據寫入寄存器和喚醒再次發送以及釋放隊列就可忽略。

(3)信息統計,表明上層送下來的包的協議
skb->protocol = eth_type_trans(skb, dev);

(4)統計發送過來的數據大小以及包的個數。

bytes += skb->len;

netif_rx(skb);


7.由於從協議棧來的數據包(skb)存放到txd,而且txd不需要往外發送,txd和rxd“連”在一起,所以直接在發送部分調用普通網卡的接收部分的netif_rx(skb)函數,所以發送的同時就完成了接收。同時我們更清楚地看到在發送的時候不能釋放skb,否則沒有可接收的數據。

8.實現獲取網卡狀態的函數

static struct net_device_stats *loopback_get_stats(struct net_device *dev)
{
struct net_device_stats *stats = &dev->stats;

stats->rx_packets = packets;
stats->tx_packets = packets;
stats->rx_bytes = bytes;
stats->tx_bytes = bytes;

return stats;
}


從這個結構體可以獲取網卡狀態信息
/* The main device statistics structure */
struct rtnl_link_stats64 {
     __u64     rx_packets;          /* total packets received     */
     __u64     tx_packets;          /* total packets transmitted     */
     __u64     rx_bytes;          /* total bytes received      */
     __u64     tx_bytes;          /* total bytes transmitted     */
     __u64     rx_errors;          /* bad packets received          */
     __u64     tx_errors;          /* packet transmit problems     */
     __u64     rx_dropped;          /* no space in linux buffers     */
     __u64     tx_dropped;          /* no space available in linux     */
     __u64     multicast;          /* multicast packets received     */
     __u64     collisions;

     /* detailed rx_errors: */
     __u64     rx_length_errors;
     __u64     rx_over_errors;          /* receiver ring buff overflow     */
     __u64     rx_crc_errors;          /* recved pkt with crc error     */
     __u64     rx_frame_errors;     /* recv'd frame alignment error */
     __u64     rx_fifo_errors;          /* recv'r fifo overrun          */
     __u64     rx_missed_errors;     /* receiver missed packet     */

     /* detailed tx_errors */
     __u64     tx_aborted_errors;
     __u64     tx_carrier_errors;
     __u64     tx_fifo_errors;
     __u64     tx_heartbeat_errors;
     __u64     tx_window_errors;

     /* for cslip etc */
     __u64     rx_compressed;
     __u64     tx_compressed;
};
主要是這四個成員
  stats->rx_packets = packets;
     stats->tx_packets = packets;
     stats->rx_bytes   = bytes;
     stats->tx_bytes   = bytes;
。實際上自己可以重寫這個獲取狀態的函數,因為struct net_device *dev有一個成員就是struct net_device_stats     stats;所以可以在重寫的時候定義一個struct net_device_stats     stats指向形參傳遞進來的迴環網卡結構體的stats成員,同樣只需要註意stats成員的上述四個成員即可。

9.在退出該驅動的時候就是取消註冊結構體。達到註銷網卡的目的。

static __net_exit void loopback_net_exit(struct net *net)
{
struct net_device *dev = net->loopback_dev;

unregister_netdev(dev);
}

 

 

下麵為範例代碼

#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/socket.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/in.h>
#include <linux/init.h>

#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <net/sock.h>
#include <net/checksum.h>
#include <linux/if_ether.h> /* For the statistics structure. */
#include <linux/if_arp.h> /* For ARPHRD_ETHER */
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/percpu.h>
#include <net/net_namespace.h>
#include <linux/u64_stats_sync.h>

unsigned long packets = 0;
unsigned long bytes = 0;

//struct net_device *dev;

static __net_exit void loopback_net_exit(struct net *net)
{
struct net_device *dev = net->loopback_dev;

unregister_netdev(dev);
}


static int loopback_net_xmit(struct sk_buff *skb,struct net_device *dev)
{
skb->protocol = eth_type_trans(skb,dev);

packets++;
bytes += skb->len;

netif_rx(skb);

return 0;
}


static struct net_device_stats *loopback_get_stats(struct net_device *dev)
{
struct net_device_stats *stats = &dev->stats;

stats->rx_packets = packets;
stats->tx_packets = packets;
stats->rx_bytes = bytes;
stats->tx_bytes = bytes;

return stats;
}


static const struct net_device_ops loopback_ops =
{
.ndo_start_xmit = loopback_net_xmit,
.ndo_get_stats = loopback_get_stats,
};


/*
* The loopback device is special. There is only one instance
* per network namespace.
*/
static void loopback_setup(struct net_device *dev)
{
dev->mtu = (16 * 1024) + 20 + 20 + 12;
dev->flags = IFF_LOOPBACK;
dev->header_ops = &eth_header_ops;
dev->netdev_ops = &loopback_ops;
}

/* Setup and register the loopback device. */
static int loopback_net_init(struct net *net)
{
struct net_device *dev;
//1.
dev = alloc_netdev(0, "lo", loopback_setup);

//4.
register_netdev(dev);

net->loopback_dev = dev;

return 0;
}

/* Registered in net/core/dev.c */
struct pernet_operations __net_initdata loopback_net_ops = {
.init = loopback_net_init,
.exit = loopback_net_exit,
};


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 安裝環境Linux伺服器:SuSe11-linux 64/32位Oracle伺服器:Oracle11gR2 64/32位系統要求記憶體:必須高於1G的物理記憶體交換空間:一般為記憶體的2倍,例如:1G的記憶體可以設置swap 分區為3G大小硬碟 :5G以上安裝包為了選擇正確的ORACLE版本,我們需要先瞭解...
  • 第一:其實最好的方法是直接用: mysqldump -u用戶名 -p密碼 資料庫名 < 資料庫名.sql 在linux在操作的,測試過一個一萬多行的導入數據,共121m。在linux下,幾秒內導入成功。如果是在phpmyadmin,或者在各個終端中實施導入121M的數據,是比較困難的,你會遇...
  • 一、RAID簡介傳統磁碟的劣勢:IO性能極弱、穩定性極差。影響電腦性能的組件一般包括:CPU、主板匯流排IO、記憶體IO、硬碟IO、網卡IO。現代的電腦匯流排、記憶體速度可以達到5G每秒,甚至更高,但是硬碟IO往往較低,硬碟是絕大多數電腦的性能瓶頸。RAID(Redundant Array of .....
  • vim快捷鍵不廢話,看圖。<a style="text decoration: none" title="vim鍵盤圖大圖" href="http://images.cnblogs.com/cnblogs_com/BYRans/761498/o_vim.png" target="_blank" 點....
  • Linux Apache svn
  • linux zip命令的基本用法是:zip [參數] [打包後的文件名] [打包的目錄路徑]linux zip命令參數列表:-a 將文件轉成ASCII模式-F 嘗試修複損壞的壓縮文件-h 顯示幫助界面-m 將文件壓縮之後,刪除源文件-n 特定字元串 不壓縮具有特定字尾字元串的文件-o 將壓縮文件內的...
  • 1.選擇路由 若要將數據包發至PC2,則linux系統通過查詢路由表可知168.1.1.10(目的地址)的網關地址為192.168.1.1,此時linux系統選擇網卡1發送數據包。2.鄰居子系統(通過arp協議建立起鄰居的信息) 選擇網卡1發送數據時,首先將數據包發給鄰居(網關),再由鄰居轉...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...