igb(4)を理解する為にデータシートを読む(RSSハッシュキーの取り出し)
まずはこのフローを見てもらうと分かりやすいのだけれど、FreeBSDのイーサーネットドライバでは割り込みハンドラ(em_irq_fast)からtaskqueue_enqueueを呼んでカーネルスレッドを起こして、このスレッドが実際にパケットを取り出しに行く(em_irq_fast)。
フロー図ではem(4)の関数名を使っているが、ここではigb(4)を見ていくのでem_irq_fast→igb_irq_fast、em_rxeof→igb_rxeofと読み替えて欲しい。
igb_rxeofが行っている事は、大雑把に言うと以下の通りである;
- for (i = rxr->next_to_check; count != 0;)というループでRing上のパケットを一つづつ見に行く
- mbufとして取り出す
- 何パケットか繋ぐ
- チェックサムオフロードの為にigb_rx_checksumを呼ぶ
- igb_rx_inputへ渡す
この流れの詳細はここでは省略する。
ここでは、どうやったらNICで計算したRSSハッシュ値が受け取れるのか知りたいので、mbufとして取り出す手前で
union e1000_adv_rx_desc *cur = &rxr->rx_base[i];
として取り出されているAdvanced Receive Descriptorの内容を見てみる。
igb(4)が対応するイーサネットコントローラの一つである82576EBのデータシートをダウンロードして見てみよう。
7.1.5章にAdvanced Receive Descriptorの構造が書いてある。
igb_rxeofで参照しているのはcur->wbとなっているし内容的にも7.1.5.2のWriteback formatの方だろう。
(Read formatがどこで使われているかはよくわからなかったので後で確認してみようと思う)
0-3bitのRSS TypeはどのRSS hash functionでhashしたかを示す値。
ドライバでは使われていないが(!)、取り出すとしたら
u16 pkt = le16toh(cur->wb.lower.lo_dword.hs_rss.pkt_info); u8 rsstype = (u8)(pkt & E1000_RXDAVD_RSSTYPE_MASK);
といった所だろう。
32-63bitはRSS Hash Value/Fragment Checksum and IP identificationと書いてあるが、RSS有効の時はハッシュ値で無効の時はIP Identification/fragment checksumに使うらしい。
これもドライバで使われていないが、
u32 rss = le32toh(cur->wb.lower.hi_dword.rss);
で取り出せる。
RSSから脱線するけど、4-16bitのPacket Typeが面白くて、IPv4かIPv6か、TCPかUDPかだけでなくてNFSかどうかまでわかるらしい。