亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪(fǎng)問(wèn)板塊 發(fā)新帖
查看: 7884 | 回復(fù): 6
打印 上一主題 下一主題

請(qǐng)教個(gè)napi_struct 、net_device數(shù)據(jù)結(jié)構(gòu)中與鏈表相關(guān)的幾個(gè)問(wèn)題 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2011-04-13 21:30 |只看該作者 |倒序?yàn)g覽
本帖最后由 lofeng410 于 2011-04-19 08:09 編輯

struct napi_struct
        struct list_head        poll_list;        unsigned long                state;
        int                        weight;
        int                        (*poll)(struct napi_struct *, int);
#ifdef CONFIG_NETPOLL
        spinlock_t                poll_lock;
        int                        poll_owner;
#endif

        unsigned int                gro_count;

        struct net_device        *dev;
        struct list_head        dev_list;        struct sk_buff                *gro_list;
        struct sk_buff                *skb;
};
  1. struct net_device
  2. {
  3.                struct list_head        dev_list;
  4.         struct list_head        napi_list;
復(fù)制代碼
在這兩個(gè)結(jié)構(gòu)體中,那四個(gè)標(biāo)紅的struct list_head類(lèi)型的變量之間是什么關(guān)系呢?

1.
在netif_napi_add()中,有這樣的操作:
list_add(&napi->dev_list, &dev->napi_list);
這樣是不是說(shuō)每個(gè)網(wǎng)口可能有多個(gè)struct napi_struct類(lèi)型的變量?

2.
感覺(jué)著四個(gè)struct list_head類(lèi)型的變量中,就poll_list有多用(在net_rx_action中輪詢(xún)?cè)撴湵恚,其他的都沒(méi)有用,具體是這樣子的么?

3.void __napi_schedule(struct napi_struct *n)
{
        unsigned long flags;

        local_irq_save(flags);
       list_add_tail(&n->poll_list, &__get_cpu_var(softnet_data).poll_list);
        __raise_softirq_irqoff(NET_RX_SOFTIRQ);
        local_irq_restore(flags);
}
static void net_rx_action(struct softirq_action *h)
{
        struct list_head *list = &__get_cpu_var(softnet_data).poll_list;
從這兩個(gè)地方看,處理時(shí)總是使用&__get_cpu_var(softnet_data).poll_list,好像每個(gè)CPU的poll處理隊(duì)列是屬于同一個(gè)網(wǎng)口,那這樣就意味著一個(gè)CPU固定用于處理某個(gè)網(wǎng)口。但是我們有沒(méi)有強(qiáng)制約定說(shuō)每個(gè)網(wǎng)口的中斷致能送到固定的CPU上,這樣該如何來(lái)理解呢?

論壇徽章:
0
2 [報(bào)告]
發(fā)表于 2011-04-19 08:10 |只看該作者
使用的內(nèi)核版本為2.6.32.12

論壇徽章:
0
3 [報(bào)告]
發(fā)表于 2011-04-19 09:24 |只看該作者
內(nèi)核要改寫(xiě)NAPI這塊接口,引入了napi_struct結(jié)構(gòu),就是為多隊(duì)列做支持的,每個(gè)隊(duì)列,而非原來(lái)的每個(gè)網(wǎng)卡,對(duì)應(yīng)一個(gè)napi結(jié)構(gòu),例如igb中有:
        for (i = 0; i < adapter->num_rx_queues; i++) {
                struct igb_ring *ring = &(adapter->rx_ring);
                ring->count = adapter->rx_ring_count;
                ring->adapter = adapter;
                ring->queue_index = i;
                ring->itr_register = E1000_ITR;

                /* set a default napi handler for each rx_ring */
                netif_napi_add(adapter->netdev, &ring->napi, igb_poll, 64);
        }

為每個(gè)rx queue注冊(cè)napi……

評(píng)分

參與人數(shù) 1可用積分 +6 收起 理由
Godbach + 6 感謝分享

查看全部評(píng)分

論壇徽章:
0
4 [報(bào)告]
發(fā)表于 2011-04-19 23:44 |只看該作者
回復(fù) 3# 獨(dú)孤九賤


    非常感謝~

    另外請(qǐng)教一個(gè)問(wèn)題哈:
                不知大俠是如何來(lái)跟蹤linux中協(xié)議棧的變動(dòng)的?感覺(jué)隨著內(nèi)核版本的遞增,其協(xié)議棧變動(dòng)太大。我現(xiàn)在對(duì)著2.6.32的內(nèi)核代碼來(lái)看《深入理解LINUX網(wǎng)絡(luò)技術(shù)內(nèi)幕》,看的有
                點(diǎn)云里霧里

論壇徽章:
0
5 [報(bào)告]
發(fā)表于 2011-04-20 04:45 |只看該作者
1. 這樣是不是說(shuō)每個(gè)網(wǎng)口可能有多個(gè)struct napi_struct類(lèi)型的變量?

是的,在NAPI機(jī)制里面,網(wǎng)卡驅(qū)動(dòng)自己配置和管理napi_struct實(shí)例,如果驅(qū)動(dòng)愿意,完全可以建立多個(gè)napi_struct實(shí)例,add到net_device的napi_list中,就是 list_add(&napi->dev_list, &dev->napi_list);做的。

2.
感覺(jué)著四個(gè)struct list_head類(lèi)型的變量中,就poll_list有多用(在net_rx_action中輪詢(xún)?cè)撴湵恚渌亩紱](méi)有用,具體是這樣子的么?

不是的,四個(gè)都有用。net_device.napi_list應(yīng)該是這塊網(wǎng)卡下面掛的napi_struct鏈表的表頭
net_device.dev_list應(yīng)該是把這塊網(wǎng)卡實(shí)例鏈接到其他鏈表里面的節(jié)點(diǎn)。
napi_struct.dev_list是把napi_struct實(shí)例掛接到net_device.napi_list鏈表里面的節(jié)點(diǎn)。
napi_struct.poll_list是用來(lái)把自己掛接到softnet_data.poll_list里面的節(jié)點(diǎn)。
softnet_data.poll_list是每個(gè)CPU處理的napi_struct鏈表表頭。

3 從這兩個(gè)地方看,處理時(shí)總是使用&__get_cpu_var(softnet_data).poll_list,好像每個(gè)CPU的poll處理隊(duì)列是屬于同一個(gè)網(wǎng)口,那這樣就意味著一個(gè)CPU固定用于處理某個(gè)網(wǎng)口。但是我們有沒(méi)有強(qiáng)制約定說(shuō)每個(gè)網(wǎng)口的中斷致能送到固定的CPU上,這樣該如何來(lái)理解呢?

這里理解有點(diǎn)偏差,NAPI的基本過(guò)程是這樣,當(dāng)網(wǎng)卡接收到數(shù)據(jù),網(wǎng)卡中斷被觸發(fā),某一個(gè)CPU會(huì)處理這個(gè)中斷,假設(shè)這個(gè)CPU為CPUA。 CPUA處理中斷處理程序,生成一個(gè)napi_struct實(shí)例,關(guān)閉網(wǎng)卡中斷,調(diào)用napi_schedule()把napi_struct實(shí)例鏈接到CPUA的softnet_data.poll_list上,并觸發(fā)軟中斷,然后退出中斷處理程序。這時(shí),網(wǎng)絡(luò)軟中斷子系統(tǒng)開(kāi)始運(yùn)行,以輪詢(xún)的方式接收網(wǎng)卡的大量數(shù)據(jù)包(net_rx_action)。

這里軟中斷仍然是CPUA來(lái)處理的,因?yàn)?軟中斷可以用兩種方式觸發(fā),第一個(gè)是中斷退出時(shí),這個(gè)時(shí)候肯定是與中斷處理程序同一個(gè)CPU。另一種是 ksoftirq內(nèi)核線(xiàn)程,每個(gè)CPU都有自己的軟中斷,所以CPUA在中斷處理程序中產(chǎn)生的nap_struct仍然由本CPU來(lái)處理。所以軟中斷中使用 __get_cpu_var(softnet_data).poll_list是沒(méi)有問(wèn)題的。

論壇徽章:
0
6 [報(bào)告]
發(fā)表于 2024-08-30 16:32 |只看該作者

linux數(shù)據(jù)包接收流程 napi機(jī)制

最近剛?cè)腴T(mén)linux。主要是看驅(qū)動(dòng)相關(guān)的,目前在看網(wǎng)卡收包的過(guò)程。也看了napi模式的收包。但是現(xiàn)在比較疑惑napi結(jié)構(gòu)體和設(shè)備的對(duì)應(yīng)關(guān)系是什么啊?是一個(gè)napi_struct對(duì)應(yīng)一個(gè)網(wǎng)卡,還是一個(gè)napi_struct對(duì)應(yīng)一個(gè)隊(duì)列?
以及在do_IRQ中:
irq_enter()和irq_exit()的作用就是為了進(jìn)入和退出硬中斷上下文嗎?(進(jìn)入硬中斷上下文其他中斷就沒(méi)辦法搶占了,linux新版本禁止內(nèi)核搶占?)

unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
{
  struct pt_regs *old_regs = set_irq_regs(regs);

  /* high bit used in ret_from_ code  */
  unsigned vector = ~regs->orig_ax;
  unsigned irq;

  exit_idle();
  irq_enter();
  irq = __this_cpu_read(vector_irq[vector]);
//省略了中間的代碼
  irq_exit();
  set_irq_regs(old_regs);
  return 1;
}



在軟中斷處理函數(shù)net_rx_action中:
幾處local_irq_disable和local_irq_enable的作用是什么啊?我看書(shū)上說(shuō)這兩個(gè)函數(shù)的功能是禁止/激活cpu本地中斷的傳遞?那他會(huì)影響網(wǎng)卡中斷嗎?
static void net_rx_action(struct softirq_action *h)
{
  struct softnet_data *sd = &__get_cpu_var(softnet_data);
  unsigned long time_limit = jiffies + 2;
  int budget = netdev_budget;
  void *have;

  local_irq_disable();

  while (!list_empty(&sd->poll_list)) {
    struct napi_struct *n;
    int work, weight;
    if (unlikely(budget <= 0 || time_after(jiffies, time_limit)))
      goto softnet_break;

    local_irq_enable();

    n = list_first_entry(&sd->poll_list, struct napi_struct, poll_list);

    have = netpoll_poll_lock(n);

    weight = n->weight;
    work = 0;
    if (test_bit(NAPI_STATE_SCHED, &n->state)) {
      work = n->poll(n, weight);
      trace_napi_poll(n);
    }

    WARN_ON_ONCE(work > weight);

    budget -= work;

    local_irq_disable();
    if (unlikely(work == weight)) {
      if (unlikely(napi_disable_pending(n))) {
        local_irq_enable();
        napi_complete(n);
        local_irq_disable();
      } else
        list_move_tail(&n->poll_list, &sd->poll_list);
    }

    netpoll_poll_unlock(have);
  }
out:
  net_rps_action_and_irq_enable(sd);
#ifdef CONFIG_NET_DMA
  dma_issue_pending_all();
#endif
  return;

softnet_break:
  sd->time_squeeze++;
  __raise_softirq_irqoff(NET_RX_SOFTIRQ);
  goto out;
}


以及在e1000注冊(cè)的軟中斷處理函數(shù)中為什么當(dāng)一個(gè)napi的work<weight的時(shí)候,移除了napi之后,就可以重新打開(kāi)網(wǎng)卡中斷呢?
那其他napi結(jié)構(gòu)體的處理不就是在開(kāi)中斷的環(huán)境下執(zhí)行了嗎?還是說(shuō)一個(gè)napi結(jié)構(gòu)體就對(duì)應(yīng)一個(gè)網(wǎng)卡。

論壇徽章:
0
7 [報(bào)告]
發(fā)表于 2024-08-30 16:40 |只看該作者
回復(fù) 5# wangjl_sdu

您好!不知道現(xiàn)在還能不能看見(jiàn)提問(wèn),我想請(qǐng)問(wèn)您的意思就是一個(gè)網(wǎng)卡是可以有多個(gè)napi_struct的對(duì)嗎?每個(gè)napi_struct都會(huì)掛到cpu的softnet_data上?那在例如intel的e1000網(wǎng)卡中,當(dāng)一個(gè)napi_struct處理完之后(即滿(mǎn)足work<weight)的時(shí)候,就移除掉該napi_struct并且重新打開(kāi)網(wǎng)卡中斷?那這個(gè)時(shí)候后面沒(méi)有處理的napi_struct怎么辦?(假設(shè)這個(gè)時(shí)候軟中斷的配額和時(shí)間都還有剩余),處理完一個(gè)napi結(jié)構(gòu)體就開(kāi)中斷的話(huà),那napi輪詢(xún)體現(xiàn)在哪里?e1000注冊(cè)的軟中斷處理函數(shù)
static int e1000_clean(struct napi_struct *napi, int budget)
{
  struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
  int tx_clean_complete = 0, work_done = 0;

  tx_clean_complete = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]);

  adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget);

  if (!tx_clean_complete)
    work_done = budget;

  /* If budget not fully consumed, exit the polling mode */
  if (work_done < budget) {
    if (likely(adapter->itr_setting & 3))
      e1000_set_itr(adapter);
    napi_complete(napi);
    if (!test_bit(__E1000_DOWN, &adapter->flags))
      e1000_irq_enable(adapter);
  }

  return work_done;
}
最后還想請(qǐng)教一下在net_rx_action中,這幾個(gè)local_irq_disable和local_irq_enable開(kāi)關(guān)中斷針對(duì)的是cpu本地中斷,那這個(gè)本地中斷包括網(wǎng)卡的接收中斷嗎?
static void net_rx_action(struct softirq_action *h)
{
  struct softnet_data *sd = &__get_cpu_var(softnet_data);
  unsigned long time_limit = jiffies + 2;
  int budget = netdev_budget;
  void *have;

  local_irq_disable();

  while (!list_empty(&sd->poll_list)) {
    struct napi_struct *n;
    int work, weight;

    /* If softirq window is exhuasted then punt.
     * Allow this to run for 2 jiffies since which will allow
     * an average latency of 1.5/HZ.
     */
    if (unlikely(budget <= 0 || time_after(jiffies, time_limit)))
      goto softnet_break;

    local_irq_enable();

    /* Even though interrupts have been re-enabled, this
     * access is safe because interrupts can only add new
     * entries to the tail of this list, and only ->poll()
     * calls can remove this head entry from the list.
     */
    n = list_first_entry(&sd->poll_list, struct napi_struct, poll_list);

    have = netpoll_poll_lock(n);

    weight = n->weight;

    /* This NAPI_STATE_SCHED test is for avoiding a race
     * with netpoll's poll_napi().  Only the entity which
     * obtains the lock and sees NAPI_STATE_SCHED set will
     * actually make the ->poll() call.  Therefore we avoid
     * accidentally calling ->poll() when NAPI is not scheduled.
     */
    work = 0;
    if (test_bit(NAPI_STATE_SCHED, &n->state)) {
      work = n->poll(n, weight);
      trace_napi_poll(n);
    }

    WARN_ON_ONCE(work > weight);

    budget -= work;

   local_irq_disable();

    /* Drivers must not modify the NAPI state if they
     * consume the entire weight.  In such cases this code
     * still "owns" the NAPI instance and therefore can
     * move the instance around on the list at-will.
     */
    if (unlikely(work == weight)) {
      if (unlikely(napi_disable_pending(n))) {
        local_irq_enable();
        napi_complete(n);
        local_irq_disable();
      } else
        list_move_tail(&n->poll_list, &sd->poll_list);
    }

    netpoll_poll_unlock(have);
  }
out:
  net_rps_action_and_irq_enable(sd);

#ifdef CONFIG_NET_DMA
  /*
   * There may not be any more sk_buffs coming right now, so push
   * any pending DMA copies to hardware
   */
  dma_issue_pending_all();
#endif

  return;

softnet_break:
  sd->time_squeeze++;
  __raise_softirq_irqoff(NET_RX_SOFTIRQ);
  goto out;
}




您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專(zhuān)區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過(guò)ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP