免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Linux內(nèi)核分析 - 網(wǎng)絡(luò)[三]:從netif_receive_skb()說起

netif_receive_skb()函數(shù)中,可以看出處理的是像ARPIP這些鏈路層以上的協(xié)議,那么,鏈路層報(bào)頭是在哪里去掉的呢?答案是網(wǎng)卡驅(qū)動(dòng)中,在調(diào)用netif_receive_skb()前,

skb->protocol = eth_type_trans(skb, bp->dev);

該函數(shù)對(duì)處理后skb>data跳過以太網(wǎng)報(bào)頭,由mac_header指示以太網(wǎng)報(bào)頭:

進(jìn)入netif_receive_skb()函數(shù)

list_for_each_entry_rcu(ptype,&ptype_base[ntohs(type) & PTYPE_HASH_MASK], list)

按照協(xié)議類型依次由相應(yīng)的協(xié)議模塊進(jìn)行處理,而所以的協(xié)議模塊處理都會(huì)注冊(cè)在ptype_base中,實(shí)際是鏈表結(jié)構(gòu)。

net/core/dev.c

static struct list_head ptype_base __read_mostly;   /* Taps */

 

而相應(yīng)的協(xié)議模塊是通過dev_add_pack()函數(shù)加入的:

void dev_add_pack(struct packet_type *pt)

{

     int hash;

 

     spin_lock_bh(&ptype_lock);

     if (pt->type == htons(ETH_P_ALL))

              list_add_rcu(&pt->list, &ptype_all);

     else {

              hash = ntohs(pt->type) & PTYPE_HASH_MASK;

              list_add_rcu(&pt->list, &ptype_base[hash]);

     }

     spin_unlock_bh(&ptype_lock);

}

 

ARP處理為例

該模塊的定義,它會(huì)在arp_init()中注冊(cè)進(jìn)ptype_base鏈表中:

static struct packet_type arp_packet_type __read_mostly = {

     .type =      cpu_to_be16(ETH_P_ARP),

     .func =      arp_rcv,

};

 

然后在根據(jù)報(bào)文的TYPE來在ptype_base中查找相應(yīng)協(xié)議模塊進(jìn)行處理時(shí),實(shí)際調(diào)用arp_rcv()進(jìn)行接收

arp_rcv() --> arp_process()

arp = arp_hdr(skb);

……

arp_ptr= (unsigned char *)(arp+1);

sha= arp_ptr;

arp_ptr += dev->addr_len;

memcpy(&sip, arp_ptr, 4);

arp_ptr += 4;

arp_ptr += dev->addr_len;

memcpy(&tip, arp_ptr, 4);

操作后這指針位置:

然后判斷是ARP請(qǐng)求報(bào)文,這時(shí)先查詢路由表ip_route_input()

if (arp->ar_op == htons(ARPOP_REQUEST) &&

         ip_route_input(skb, tip, sip, 0, dev) == 0)

ip_route_input()函數(shù)中,先在cache中查詢是否存在相應(yīng)的路由表項(xiàng):

hash = rt_hash(daddr, saddr, iif, rt_genid(net));

緩存的路由項(xiàng)在內(nèi)核中組織成hash表的形式,因此在查詢時(shí),先算出的hash值,再用該項(xiàng)- rt_hash_table[hash].chain即可。這里可以看到,緩存路由項(xiàng)包括了源IP地址、目的IP地址、網(wǎng)卡號(hào)。

 

如果在緩存中沒有查到匹配項(xiàng),或指定不查詢cache,則查詢路由表ip_route_input_slow();

進(jìn)入ip_route_input_slow()函數(shù),最終調(diào)用fib_lookup()得到查詢結(jié)果fib_result

if ((err = fib_lookup(net, &fl, &res)) != 0)

如果結(jié)果fib_result合法,則需要更新路由緩存,將此次查詢結(jié)果寫入緩存

hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net));

err = rt_intern_hash(hash, rth, NULL, skb, fl.iif);

 

在查找完路由表后,回到arp_process()函數(shù),如果路由項(xiàng)指向本地,則應(yīng)由本機(jī)接收該報(bào)文:

if (addr_type == RTN_LOCAL) {

              ……

              if (!dont_send) {

                       n = neigh_event_ns(&arp_tbl, sha, &sip, dev);

                       if (n) {

                                 arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);

                                 neigh_release(n);

                       }

              }

              goto out;

     }

首先更新鄰居表neigh_event_ns(),然后發(fā)送ARP響應(yīng) – arp_send。

至此,大致的ARP流程完成。由于ARP部分涉及到路由表以及鄰居表,這都是很大的概念,在下一篇中介紹,這里直接略過了。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
linux內(nèi)核中VLAN收發(fā)處理
Linux內(nèi)核二層數(shù)據(jù)包接收流程
一個(gè)險(xiǎn)惡bug的深入分析
Android socket創(chuàng)建、綁定流程分析(二)
ptype_base和ptype_all理解,netid_receive_skb()函數(shù)注解
TCP/IP學(xué)習(xí)(28)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服