skb操作函式

2021-05-27 01:03:31 字數 2399 閱讀 7929

使用乙個 sk_buff 結構的網路驅動利用正式介面函式來操作它. 許多函式操作乙個 socket 快取; 這裡是最有趣的幾個:

struct sk_buff *alloc_skb(unsigned int len, int priority);

struct sk_buff *dev_alloc_skb(unsigned int len);

分配乙個快取區. alloc_skb 函式分配乙個快取並且將 skb->data 和 skb->tail 都初始化成 skb->head. dev_alloc_skb 函式是使用 gfp_atomic 優先順序呼叫 alloc_skb 的快捷方法, 並且在 skb->head 和 skb->data 之間保留了一些空間. 這個資料空間用在網路層之間的優化, 驅動不要動它.

void kfree_skb(struct sk_buff *skb);

void dev_kfree_skb(struct sk_buff *skb);

void dev_kfree_skb_irq(struct sk_buff *skb);

void dev_kfree_skb_any(struct sk_buff *skb);

釋放快取. kfree_skb 呼叫由核心在內部使用. 乙個驅動應當使用一種 dev_kfree_skb 的變體: 在非中斷上下文中使用 dev_kfree_skb, 在中斷上下文中使用 dev_kfree_skb_irq, 或者 dev_kfree_skb_any 在任何 2 種情況下.

unsigned char *skb_put(struct sk_buff *skb, int len);

unsigned char *__skb_put(struct sk_buff *skb, int len);

更新 sk_buff 結構中的 tail 和 len 成員; 它們用來增加資料到快取的結尾, 每個函式的返回值是 skb->tail 的前乙個值(換句話說, 它指向剛剛建立的資料空間). 驅動可以使用返回值通過引用 memcpy(skb_put(...), data, len) 來拷貝資料或者乙個等同的東東. 兩個函式的區別在於 skb_put 檢查以確認資料適合快取, 而 __skb_put 省略這個檢查.

unsigned char *skb_push(struct sk_buff *skb, int len);

unsigned char *__skb_push(struct sk_buff *skb, int len);

遞減 skb->data 和遞增 skb->len 的函式. 它們與 skb_put 相似, 除了資料是新增到報文的開始而不是結尾. 返回值指向剛剛建立的資料空間. 這些函式用來在傳送報文之前新增乙個硬體頭部. 又一次, __skb_push 不同在它不檢查空間是否足夠.

int skb_tailroom(struct sk_buff *skb);

返回可以在快取中放置資料的可用空間數量. 如果驅動放了多於它能持有的資料到快取中, 系統傻掉. 儘管你可能反對說乙個 printk 會足夠來標識出這個錯誤, 記憶體破壞對系統是非常有害的以至於開發者決定採取確定的動作. 實際中, 你不該需要檢查可用空間, 如果快取被正確地分配了. 因為驅動常常在分配快取前獲知報文的大小, 只有乙個嚴重壞掉的驅動會在快取中安放太多的資料, 這樣出亂子就可當作乙個應得的懲罰.

int skb_headroom(struct sk_buff *skb);

返回 data 前面的可用空間數量, 就是, 可以 "push" 給快取多少位元組.

void skb_reserve(struct sk_buff *skb, int len);

遞增 data 和 tail. 這個函式可用來在填充資料前保留空間. 大部分乙太網介面保留 2 個位元組在報文的前面; 因此, ip 頭對齊到 16 位元組, 在 14 位元組的乙太網頭後面. snull 也這樣做, 儘管沒有在"報文接收"一節中展現這個指令以避免在那時引入過多概念.

unsigned char *skb_pull(struct sk_buff *skb, int len);

從報文的頭部去除資料. 驅動不會需要使用這個函式, 但是為完整而包含在這兒. 它遞減 skb->len 和遞增 skb->data; 這是硬體頭如何從進入報文開始被剝離.

int skb_is_nonlinear(struct sk_buff *skb);

返回乙個真值, 如果這個 skb 分離為多個片為發散/匯聚 i/o.

int skb_headlen(struct sk_buff *skb);

返回 skb 的第乙個片的長度(由 skb->data 指著).

void *kmap_skb_frag(skb_frag_t *frag);

void kunmap_skb_frag(void *vaddr);

如果你必須從核心中的乙個非線性 skb 直接訪問片, 這些函式為你對映以及去對映它們. 使用乙個原子性 kmap, 因此你不能一次對映多於乙個片.

linux核心中如何修改skb報文

核心 中有許多用於計算校驗和的api,下面是linux網路技術內幕相關api的截圖 sk buf中的csum欄位 sk buf中的ip summed欄位 ip summed欄位表示l4層的校驗和狀態。根據報文的不同 輸入報文和輸出報文 ip summed會有不同的取值。當資料報為輸入報文 defin...

在2 6 30上修改以及重構skb

上次看了ubuntuer兄寫的教你修改以及重構skb 受益匪淺,真是經典之作。但ubuntuer兄的 是基於2.6.18的,比較舊。今天經過摸索,我終於讓其可以在2.6.30上執行了,如下 skb diy.c include include include include include inclu...

linux核心根據skb獲取目的mac位址

工作筆記工作筆記linux程式設計 直接通過skb裡面的資訊獲取mac,如下 1.struct ethhdr eth hdr struct ethhdr skb mac header skb 2.if skb mac header was set skb 3.注意 需要先通過skb mac head...