Linux 網卡如何支持TSO GSO指南

來源鏈接:http://gavin1992.gotoip2.com/papperdetails_tech.php?pid=11
 

1.什麼是TSO GSO

  TSO是tcp segment offload的縮寫,GSO是 generic segmentation offload 的縮寫

  詳細解釋參看http://en.wikipedia.org/wiki/Large_segment_offload

  對TSO的簡單理解就是:

   比如:我們要用汽車把3000本書送到另一個城市,每趟車只能裝下1000本書,

那麼我們就要書分成3次來發。如何把3000本書分成3份的事情是我們做的,汽車司機只負責運輸。

  TSO的概念就是:我們把3000本書一起給司機,由他去負責拆分的事情,這樣我們就有更多的時間處理其他事情。

  對應到計算機系統中,“我們”就是CPU,“司機”就是網卡。

  在網絡系統中,發送tcp數據之前,CPU需要根據MTU(一般爲1500)來將數據放到多個包中發送,對每個數據包都要添加ip頭,tcp頭,分別計算IP校驗和,TCP校驗和。如果有了支持TSO的網卡,CPU可以直接將要發送的大數據發送到網卡上,由網卡硬件去負責分片和計算校驗和。

 

2. TSO GSO網卡驅動與系統的接口:

 

步驟1.       設置支持TSO support flag 同時需要支持SG

     netdev->features |= NETIF_F_TSO;

     netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;

 

 

步驟2       設置GSO最大值

netdev ->gso_max_size = 8*1024;  //網卡支持的gso size,通知系統每個tcp數據塊的最大長度。

                                                    //TCP的窗口大小最大爲64K,

 

步驟3:  發送函數需要處理skb數據

 支持tso的skb數據存儲格式如下:

第一塊數據存儲在skb的data->tail之間,其他分塊存儲在skb_shinfo(skb)->frags中。

代碼示例如下:

 

View Code
複製代碼
int xmit_support_sg_tso(struct sk_buff *skb)
{
    size 
= (skb->tail - skb->data);  // the first fragment is stored in the skb.
    for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)    {
            size 
+= skb_shinfo(skb)->frags[f].size; ////other frags .
    }

    memcpy(dbg_send_queue, skb
->data,   skb->tail - skb->data);   //real first frag
    for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)  //process frags.
    {
            
struct skb_frag_struct *frag;
            
int f_offset = 0;
            
int f_len = 0;
            
char *addr;
            
            frag 
= &skb_shinfo(skb)->frags[f];
            f_len 
= frag->size;
            f_offset 
= frag->page_offset;

            addr 
= (char *)page_address(frag->page) ;  //change page addr to virt addr.
            
           memcpy(dbg_send_queue, addr 
+ f_offset,         f_len);             
           offset 
+= f_len;
    }
}
複製代碼

 

步驟4: 支持    ethtool

static struct ethtool_ops comNIC_ethtool_ops = {

    .get_settings           = netdev_get_settings,

    .set_settings           = netdev_set_settings,

    .get_drvinfo            = netdev_get_drvinfo,

    .get_link               = netdev_get_link,

    .get_rx_csum            = cmb_ethtool_op_get_rx_csum,

    .set_rx_csum            = cmb_ethtool_op_set_rx_csum,

    .get_tx_csum            = cmb_ethtool_op_get_tx_csum,

    .set_tx_csum            = cmb_ethtool_op_set_tx_csum,

    //.set_sg                 = ethtool_op_set_sg,

#ifdef NETIF_F_TSO

    .get_tso                = cmb_ethtool_op_get_tso,

    .set_tso                = cmb_ethtool_op_set_tso,

#endif

}

 

命令行檢驗:

 

查看是否支持tso gso等:

ethtool -k comnic0

 

  設置tso gso打開和關閉

ethtool -K comnic0 tso off

ethtool -K comnic0 gso off

 

-----------------------------------驅動對tso gso的支持完成-----------------------------------------------

ps:1.支持tso需要同時聲明支持scattle / gather, 因爲skb的分片數據不是存儲在一個連續的地址上。當然:網卡硬件可以不支持scattle/gather這種DMA方式。

2. 需要同時支持硬件校驗和。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章