小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

2410 TFTP源碼 學(xué)習(xí)筆記 - 湛藍(lán)思微的blog | 嵌入式在線博客

 jijo 2009-03-18
.sk_buff的結(jié)構(gòu)和操作:

struct sk_buff {

unsigned char pad[2];
unsigned char buf[ETH_FRAME_LEN];//buffer,這里是幀存儲的位置
unsigned int truesize;    /* Buffer size       */

unsigned char *data;    /* Data head pointer     */這個指針總是指向當(dāng)前層協(xié)議頭在buf中的位置或者當(dāng)前層協(xié)議數(shù)據(jù)部分在buf中的位置。
unsigned int len;    /* Length of actual data    */指示從*data位置到幀尾的length
};

buf[ETH_FRAME_LEN] 就是一幀實體,也是一幀協(xié)議棧的棧的實體。*data 是棧的指針,len則相當(dāng)棧的底部,但是它是變化的,意義是*data到*data+len部分是當(dāng)前協(xié)議層的內(nèi)容(接收),或者這部分是已經(jīng)填好的上層協(xié)議內(nèi)容(發(fā)送)。 對應(yīng)的操作有skb_push,skb_pull。

skb_push 用于從上層協(xié)議向下封裝數(shù)據(jù)包,相當(dāng)于壓棧。char *skb_pull(struct sk_buff *skb, unsigned int ln) 就是要向棧中寫入len字節(jié)前,先把棧指針*data-=ln, 而棧長len+=ln,返回當(dāng)前*data指針,數(shù)據(jù)或者協(xié)議頭(長度一定是ln)就可以往*data處填充了。很明顯這是個向下生長的滿棧 (FD) 。

skb_pull 用于從幀開始向上逐次解析協(xié)議。相當(dāng)于彈棧的過程, char *skb_pull(struct sk_buff *skb, unsigned int ln)就是從棧中彈出ln個字節(jié),*data+=ln, 棧長len-=ln,返回當(dāng)前*data。彈出的ln字節(jié)就是下層協(xié)議已經(jīng)處理過的協(xié)議頭,返回值指向本層協(xié)議頭,用它就可以開始解析本層協(xié)議了。

2、接收包的流程

1) 申請一個緩沖區(qū)sk_buf *skb, 以skb為參數(shù)調(diào)用以太網(wǎng)層的接收數(shù)據(jù)幀函數(shù)eth_rcv(skb)。eth_rcv(skb)調(diào)用board_eth_rcv(skb->data, &skb->len); board_eth_rcv調(diào)用CS8900 查詢函數(shù)CS8900DBG_IsReceivedPacket()檢查當(dāng)前是否收到數(shù)據(jù)幀,如果收到調(diào)用RcvPkt((BYTE *)data, 1532);接收幀。 這樣一幀數(shù)據(jù)就緩存到skb->buff中了。此時棧指針*data=buff,len=幀長。

2)處理以太網(wǎng)幀頭,彈棧skb_pull(skb, ETH_HLEN)。以太網(wǎng)的幀頭protocol解析上層協(xié)議是IP還是ARP,分別調(diào)用ip_rcv_packet(skb);(見4)或者arp_rcv_packet(skb);(見3)

3)如果是ARP報文,arp_rcv_packet(skb)處理ARP協(xié)議。判斷ARP頭的目標(biāo)IP是否為本地IP,不是丟棄。是則判斷ARP操作碼是否為ARP請求,是發(fā)送ARP reply。緩存對方MAC IP 至ARP cache.當(dāng)前幀的處理結(jié)束。

4)如果IP報文 ,ip_rcv_packet(skb); 處理IP層協(xié)議頭,檢查目的IP是否是本地IP,不是直接丟棄,是則根據(jù)IP頭的上層協(xié)議是UDP還是ICMP,分別調(diào)用udp_rcv_packet(skb);或者icmp_rcv_packet(skb);

5)如果是ICMP數(shù)據(jù)包,icmp_rcv_packet(skb); 處理ICMP報文,如果ICMP頭的類型是8,即請求回顯,則發(fā)送一個回顯ICMP報文。當(dāng)前幀的處理結(jié)束。

6)如果是UDP數(shù)據(jù)包,udp_rcv_packet(skb)處理UDP協(xié)議頭,檢查目的端口是否為TFTP端口。由于程序只有TFTP作為UDP的上層協(xié)議。 如果是則彈棧后調(diào)用tftp_rcv_packet(skb);

7)如果是ftfp包,tftp_rcv_packet(skb);處理TFTP協(xié)議,限于功能,只處理WRQ和DATA兩種請求,如果是WRQ請求,保存源IP和端口,發(fā)送一個ftfp應(yīng)答block=0,開始block++計數(shù)并進(jìn)入下載狀態(tài)。

如果是DATA包,判斷源IP和端口與上面保存的是否一致,當(dāng)前tftp包的block號與block計數(shù)是否相等。相等則拷貝數(shù)據(jù), 發(fā)送應(yīng)答,block++,判斷數(shù)據(jù)長是否小于512,是則表明block接收結(jié)束。當(dāng)前tftp包的block號

3、發(fā)送包過程

1)sk_buff結(jié)構(gòu)的另外兩個操作,skb_put操作和skb_reserve(預(yù)留)操作:申請一個緩沖示進(jìn)行任何操作的時候,*data=buff, len=0. 每層協(xié)議都有一個相對于下層協(xié)議頭的偏移,這個偏移是一定的。skb_reserve(skb,len)操作是把skb->data+=len。每層協(xié)議都實現(xiàn)對應(yīng)的reserve操作,它調(diào)用下層reserve,再把自己協(xié)議頭的長度len添加到預(yù)留空間skb_reserve(skb,len)。

skb_put(skb,len)操作則是實現(xiàn)內(nèi)容填充之后,skb->len+=len.

這兩個操作和skb_push在發(fā)送數(shù)據(jù)包中起重要作用。如發(fā)送TFTP包,申請緩沖區(qū),調(diào)用udp_skb_reserve(skb);把UDP頭到以太網(wǎng)幀頭的所有協(xié)議頭的位置預(yù)留出來。再向*data處添加TFTP頭和數(shù)據(jù)。

2)TFTP包發(fā)送過程

      發(fā)送TFTP應(yīng)答,tftp_send_ack :申請緩沖,預(yù)留所有下層協(xié)議(UDP,IP,ETH)協(xié)議頭空間,填寫TFTP頭和數(shù)據(jù)。調(diào)用udp_send(skb, client_ip, TFTP, client_port); 參數(shù)告訴下層相對的協(xié)議頭怎么填。如TFTP,client_port 是給UDP協(xié)議層的,指定了本地端口和目標(biāo)端口;client_ip則是給IP層的,給定目標(biāo)IP。

      udp_send(skb, client_ip, TFTP, client_port); UDP層壓棧后填寫自己UDP協(xié)議頭。調(diào)用ip_send(skb, ip, UDP); 指定目標(biāo)IP和上層協(xié)議是UDP協(xié)議。

      IP層ip_send(skb, ip, UDP); 填寫協(xié)議頭,在這里注意校驗和的計算。在ARP緩存中查找目標(biāo)IP對應(yīng)的MAC地址,查找成功然后調(diào)用下層eth_send(skb, dest_eth_addr, ETH_P_IP);查找失敗發(fā)送ARP查詢請求。

      ETH層 填充以太網(wǎng)幀頭,調(diào)用底層驅(qū)動函數(shù):board_eth_send(skb->data, skb->len);由CS8900芯片完成幀發(fā)送。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多