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