Linuxのポーリング処理のコードを読んでみよう 〜ポーリング編〜
Linuxのポーリング処理のコードを読んでみよう 〜割り込み編〜 - かーねる・う゛いえむにっきの続き。
まず、前回最後にスケジュールしたNET_RX_SOFTIRQってソフトウェア割り込みがどこで登録されてて、どれがハンドラかって所から見てみる。
net_dev_init()って関数を見ると、こんなコードがある。
open_softirq(NET_TX_SOFTIRQ, net_tx_action); open_softirq(NET_RX_SOFTIRQ, net_rx_action);
このnet_rx_action()がハンドラだろう。
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 * accidently 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; }
これがスケジュールされる度に実行されるわけだ。
前回の記事では____napi_scheduleでnapiをpercpuなsoftnet_dataにlist_add_tailしていた。
ここではこれを逆に取り出している。
NAPI_STATE_SCHEDがn->stateに立っているならn->poll(n, n->weight)を呼び、workに取得パケット数を代入。
取得パケット数が上限に達していて(恐らくまだパケットがバッファに残ってる)、napiが止められてなければlist_move_tailでこのnapiをリストの最後に移動している(複数NICが有る場合、ポーリングが公平に行われるようにする為)。
取得パケット数が上限に達していない場合、whileループするとまた同じnapiを取得しそうに読めるが、これはドライバ側でリストから外してるからっぽい。
一回のn->poll()の上限の他に、一回のnet_rx_action()での上限取得数と上限時間も設定されている。
これは、ポーリングタスクが非常に忙しい時に、他のタスクへコンテキストが渡らなくなるのを防ぐため。
一回のソフトウェア割り込みでの上限取得数はint budget = netdev_budgetで定義され、n->poll()する度にbudget -= workで引き算され、0になったらgoto softnet_breakしている。
上限時間はunsigned long time_limit = jiffies + 2で定義され、time_after(jiffies, time_limit)でチェックされ、上限時間を超過していたらgoto softnet_breakしている。
softnet_breakラベルでは、__raise_softirq_irqoff(NET_RX_SOFTIRQ)でポーリングをスケジュールしてから関数を抜けている。
ところでポーリング処理で呼ばれているn->poll()だが、ここでは要するにe1000_clean()の事なので、今度はこれを見てみる。
3411 static int e1000_clean(struct napi_struct *napi, int budget) 3412 { 3413 struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi); 3414 int tx_clean_complete = 0, work_done = 0; 3415 3416 tx_clean_complete = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]); 3417 3418 adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget); 3419 3420 if (!tx_clean_complete) 3421 work_done = budget;
3416行目では送信のポーリングを行っているけど、今回は受信処理を見てきているので省略。
3418行目では受信のポーリングを行っている。関数ポインタになってるけど、どこでセットしてるんだろうか。
コードを追っていくと、1000_configure_rx()にこんなコードがある。
1740 if (adapter->netdev->mtu > ETH_DATA_LEN) { 1741 rdlen = adapter->rx_ring[0].count * 1742 sizeof(struct e1000_rx_desc); 1743 adapter->clean_rx = e1000_clean_jumbo_rx_irq; 1744 adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers; 1745 } else { 1746 rdlen = adapter->rx_ring[0].count * 1747 sizeof(struct e1000_rx_desc); 1748 adapter->clean_rx = e1000_clean_rx_irq; 1749 adapter->alloc_rx_buf = e1000_alloc_rx_buffers; 1750 }
ジャンボフレーム対応のルーチンと非対応のルーチンが別々になっているという事のようだ。
ここではe1000_clean_rx_irq()の方を見ていこう。
3827 static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, 3828 struct e1000_rx_ring *rx_ring, 3829 int *work_done, int work_to_do) 3830 { 3831 struct e1000_hw *hw = &adapter->hw; 3832 struct net_device *netdev = adapter->netdev; 3833 struct pci_dev *pdev = adapter->pdev; 3834 struct e1000_rx_desc *rx_desc, *next_rxd; 3835 struct e1000_buffer *buffer_info, *next_buffer; 3836 unsigned long flags; 3837 u32 length; 3838 unsigned int i; 3839 int cleaned_count = 0; 3840 bool cleaned = false; 3841 unsigned int total_rx_bytes=0, total_rx_packets=0; 3842 3843 i = rx_ring->next_to_clean; 3844 rx_desc = E1000_RX_DESC(*rx_ring, i); 3845 buffer_info = &rx_ring->buffer_info[i]; 3846 3847 while (rx_desc->status & E1000_RXD_STAT_DD) { 3848 struct sk_buff *skb; 3849 u8 status; 3850 3851 if (*work_done >= work_to_do) 3852 break; 3853 (*work_done)++; 3854 rmb(); /* read descriptor and rx_buffer_info after status DD */ 3855 3856 status = rx_desc->status; 3857 skb = buffer_info->skb; 3858 buffer_info->skb = NULL; 3859 3860 prefetch(skb->data - NET_IP_ALIGN); 3861 3862 if (++i == rx_ring->count) i = 0; 3863 next_rxd = E1000_RX_DESC(*rx_ring, i); 3864 prefetch(next_rxd); 3865 3866 next_buffer = &rx_ring->buffer_info[i]; 3867 3868 cleaned = true; 3869 cleaned_count++; 3870 dma_unmap_single(&pdev->dev, buffer_info->dma, 3871 buffer_info->length, DMA_FROM_DEVICE); 3872 buffer_info->dma = 0; 3873 3874 length = le16_to_cpu(rx_desc->length); 3875 /* !EOP means multiple descriptors were used to store a single 3876 * packet, if thats the case we need to toss it. In fact, we 3877 * to toss every packet with the EOP bit clear and the next 3878 * frame that _does_ have the EOP bit set, as it is by 3879 * definition only a frame fragment 3880 */ 3881 if (unlikely(!(status & E1000_RXD_STAT_EOP))) 3882 adapter->discarding = true; 3883 3884 if (adapter->discarding) { 3885 /* All receives must fit into a single buffer */ 3886 e_dbg("Receive packet consumed multiple buffers\n"); 3887 /* recycle */ 3888 buffer_info->skb = skb; 3889 if (status & E1000_RXD_STAT_EOP) 3890 adapter->discarding = false; 3891 goto next_desc; 3892 } 3893 3894 if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { 3895 u8 last_byte = *(skb->data + length - 1); 3896 if (TBI_ACCEPT(hw, status, rx_desc->errors, length, 3897 last_byte)) { 3898 spin_lock_irqsave(&adapter->stats_lock, flags); 3899 e1000_tbi_adjust_stats(hw, &adapter->stats, 3900 length, skb->data); 3901 spin_unlock_irqrestore(&adapter->stats_lock, 3902 flags); 3903 length--; 3904 } else { 3905 /* recycle */ 3906 buffer_info->skb = skb; 3907 goto next_desc; 3908 } 3909 } 3910 3911 /* adjust length to remove Ethernet CRC, this must be 3912 * done after the TBI_ACCEPT workaround above */ 3913 length -= 4; 3914 3915 /* probably a little skewed due to removing CRC */ 3916 total_rx_bytes += length; 3917 total_rx_packets++; 3918 3919 e1000_check_copybreak(netdev, buffer_info, length, &skb); 3920 3921 skb_put(skb, length); 3922 3923 /* Receive Checksum Offload */ 3924 e1000_rx_checksum(adapter, 3925 (u32)(status) | 3926 ((u32)(rx_desc->errors) << 24), 3927 le16_to_cpu(rx_desc->csum), skb); 3928 3929 skb->protocol = eth_type_trans(skb, netdev); 3930 3931 e1000_receive_skb(adapter, status, rx_desc->special, skb); 3932 3933 next_desc: 3934 rx_desc->status = 0; 3935 3936 /* return some buffers to hardware, one at a time is too slow */ 3937 if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { 3938 adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); 3939 cleaned_count = 0; 3940 } 3941 3942 /* use prefetched values */ 3943 rx_desc = next_rxd; 3944 buffer_info = next_buffer; 3945 } 3946 rx_ring->next_to_clean = i; 3947 3948 cleaned_count = E1000_DESC_UNUSED(rx_ring); 3949 if (cleaned_count) 3950 adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); 3951 3952 adapter->total_rx_packets += total_rx_packets; 3953 adapter->total_rx_bytes += total_rx_bytes; 3954 netdev->stats.rx_bytes += total_rx_bytes; 3955 netdev->stats.rx_packets += total_rx_packets; 3956 return cleaned; 3957 }
rx_descはe1000のレジスタっぽいね。
3847行目で、E1000_RXD_STAT_DDビットがたってる間だけ、パケット取得のループを実行。
3857行目で、skbにパケットを一つ取り出し、3931行目でe1000_receive_skb()を呼び出す。
e1000_receive_skb()はVLANのハードウェアアクセラレーションを使わない場合は単にnetif_receive_skb()を呼び出すだけの関数。
netif_receive_skb()はパケットを上位レイヤ(TCP/IPスタック)に渡す。
以上の処理を、最大work_to_do回行い、行った回数をwork_doneで返している。
このwork_to_doはnapi->weightであるので、前の記事で書いてる netif_napi_add()に渡した64がそのまま来ている。
ドライバ固有になってるのは、恐らく、NICのリングバッファサイズから最適値が左右されるからだろう。
再びe1000_clean()に戻る。
3423 /* If budget not fully consumed, exit the polling mode */ 3424 if (work_done < budget) { 3425 if (likely(adapter->itr_setting & 3)) 3426 e1000_set_itr(adapter); 3427 napi_complete(napi); 3428 if (!test_bit(__E1000_DOWN, &adapter->flags)) 3429 e1000_irq_enable(adapter); 3430 } 3431 3432 return work_done; 3433 }
もし、work_doneがbudget(weightのこと)より小さければ、もうバッファにパケットが残ってないという事なので、ポーリングを終了する処理を行う。
3427行目で呼んでるnapi_complete()でインタフェースをポーリング対象のリストから外している。
void __napi_complete(struct napi_struct *n) { BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); BUG_ON(n->gro_list); list_del(&n->poll_list); smp_mb__before_clear_bit(); clear_bit(NAPI_STATE_SCHED, &n->state); } EXPORT_SYMBOL(__napi_complete);
3429行目で e1000_irq_enable()を呼んで割り込みを再開。
これがe1000_intr()のe1000_irq_disable()と対になっているわけだ。
※skbに関する参考資料:http://ftp.gnumonks.org/pub/doc/skb-doc.html