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

分享

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

 杰的個(gè)人圖書館 2012-04-11

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跳過(guò)以太網(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é)議模塊是通過(guò)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來(lái)在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)。

 

如果在緩存中沒(méi)有查到匹配項(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部分涉及到路由表以及鄰居表,這都是很大的概念,在下一篇中介紹,這里直接略過(guò)了。

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

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多