網路子系統在鏈路層的收發過程剖析(一)【轉】

來源:互聯網
上載者:User

標籤:

轉自:http://linux.chinaunix.net/techdoc/net/2007/01/30/949381.shtml

R.wen (
[email protected]
)

1),Skb_buff


/* To allow 64K frame to be packed as single skb without frag_list */
#define MAX_SKB_FRAGS (65536/PAGE_SIZE + 2)

typedef struct skb_frag_struct skb_frag_t;

struct skb_frag_struct {
       struct page *page;
       __u16 page_offset;
       __u16 size;
};

/* This data is invariant across clones and lives at
* the end of the header data, ie. at skb->end.
*/
struct skb_shared_info {
       atomic_t  dataref;
       unsigned short       nr_frags;
       unsigned short       gso_size;
       /* Warning: this field is not always filled in (UFO)! */
       unsigned short       gso_segs;
       unsigned short  gso_type;
       unsigned int    ip6_frag_id;
       struct sk_buff *frag_list;
       skb_frag_t      frags[MAX_SKB_FRAGS];
};


Skb比較複雜的部分在於skb_shared_info部分,alloc_skb()在為資料分配空間的時候,會在這個資料的末尾加上一個skb_shared_info結構,這個結構就是用於scatter/gather IO的實現的。它主要用於提高效能,避免資料的多次拷貝。例如,當使用者用sendmsg分送一個數組結構的資料時,這些資料在物理可能是不連續的(大多數情況),在不支援scatter/gather IO的網卡上,它只能通過重新拷貝,將它重裝成連續的skb(skb_linearize),才可以進行DMA操作。而在支援S/G IO上,它就省去了這次拷貝。






2),網卡(PCI裝置的註冊)
       系統啟動的時候,pci會掃描所有的PCI裝置然後根據註冊驅動的id_table,找到相匹配的驅動,實現關聯。當找到匹配的驅動時,它會執行相關驅動程式中的probe函數,而網卡的net_device就是在這個函數裡面初始化的並註冊到核心的。


3),網卡鏈路狀態檢測
       當網卡鏈路狀態變化時(如斷開或連上),網卡會通知驅動程式或者由驅動程式去查詢網卡的相關寄存器位(例如在timeout時去查詢這些位),然後由netif_carrier_on/off去通知核心這個變化。

void netif_carrier_on(struct net_device *dev)
{   // test_and_clear_bit - Clear a bit and return its old value
       if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state))
              linkwatch_fire_event(dev);
       if (netif_running(dev))
              __netdev_watchdog_up(dev);
}

static inline netif_carrier_off(struct net_device *dev)
{
//test_and_set_bit - Set a bit and return its old value
    if (!test_and_set_bit(_ _LINK_STATE_NOCARRIER, &dev->state))
        linkwatch_fire_event(dev);
}

這樣,netif_carrier_on會調用linkwatch_fire_event,它會建立一個lw_event結構:

       struct lw_event {
       struct list_head list;
       struct net_device *dev;
};
並將這個結構初始化後(event->dev = dev;)加入到事件隊列中:
              spin_lock_irqsave(&lweventlist_lock, flags);
              list_add_tail(&event->list, &lweventlist);
              spin_unlock_irqrestore(&lweventlist_lock, flags);

然後它調用schedule_work(&linkwatch_work)由核心線程去處理這些事件。它最終由linkwatch_run_queue(void)去完成這些處理工作:

list_for_each_safe(n, next, &head) {
              struct lw_event *event = list_entry(n, struct lw_event, list);
              struct net_device *dev = event->dev;
       …
              if (dev->flags & IFF_UP) {
                     if (netif_carrier_ok(dev)) {
                            dev_activate(dev);
                     } else
                            dev_deactivate(dev);
                     netdev_state_change(dev);
              }
}

可以看到,它的最主要工作之一就是netdev_state_change(dev):
void netdev_state_change(struct net_device *dev)
{
       if (dev->flags & IFF_UP) {
              raw_notifier_call_chain(&netdev_chain,
                            NETDEV_CHANGE, dev);
              rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
       }
}

這個函數通知註冊到netdev_chain鏈表的所有子系統,這個網卡的鏈路狀態有了變化。就是說,如果某個子系統對網卡的鏈路狀態變化感興趣,它就可以註冊到進這個鏈表,在變化產生時,核心便會通知這些子系統。

注意:a. 它只會在網卡狀態為UP時,才會發出通知,因為,如果狀態為DOWN,網卡鏈路的狀態改變也沒什麼意義。
         b. 每個見網卡的這些狀態變化的事件lw_event是不會隊列的,即每個網卡只有一個事件的執行個體在隊列中。還有由上面看到的lw_event結構,它只是包含發生狀態變化的網卡裝置,而沒有包含它是鏈上或是斷開的狀狀參數。

                                                 07.01.29

網路子系統在鏈路層的收發過程剖析(一)【轉】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.