网卡中断
<h2>概述</h2>
<p>调用树:</p>
<pre><code class="language-c">igb_msix_ring
napi_schedule
__napi_schedule
____napi_schedule // 将 napi 加入到当前 CPU 的 softnet_data-&gt;poll_list 中,再触发接收软中断
__raise_softirq_irqoff // 触发软中断</code></pre>
<p>1、网卡中断响应函数,先将 napi 加入到当前 CPU 的 softnet_data->poll_list 中,再触发接收软中断</p>
<h2>网卡中断响应</h2>
<p>注册的中断函数为 <code>igb_msix_ring</code>,注意到 <code>*data</code> 参数,即是 q_vector,里面保存有中断或网卡相关的信息</p>
<pre><code class="language-c">// file: igb_main.c
static irqreturn_t igb_msix_ring(int irq, void *data)
{
struct igb_q_vector *q_vector = data;
/* Write the ITR value calculated from the previous interrupt. */
igb_write_itr(q_vector);
napi_schedule(&amp;q_vector-&gt;napi); // 将 napi 加入到当前 CPU 的 softnet_data-&gt;poll_list 中,再触发接收软中断
return IRQ_HANDLED;
}</code></pre>
<pre><code class="language-c">//file: net/core/dev.c
/**
* __napi_schedule - schedule for receive
* @n: entry to schedule
*
* The entry's receive function will be scheduled to run
*/
void __napi_schedule(struct napi_struct *n)
{
unsigned long flags;
local_irq_save(flags);
____napi_schedule(&amp;__get_cpu_var(softnet_data), n);
local_irq_restore(flags);
}
EXPORT_SYMBOL(__napi_schedule);
/* Called with irq disabled */
static inline void ____napi_schedule(struct softnet_data *sd,
struct napi_struct *napi)
{
list_add_tail(&amp;napi-&gt;poll_list, &amp;sd-&gt;poll_list);
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
}</code></pre>