Open vSwitchのソースコードを読む(9) dpif

2013-06-18 by Daisuke Kotani

dpif の構造

datapath には2種類あります。dpif_linux と dpif_netdev です。dpif_linux は kernel module と連携して動くもので、dpif_netdev は userspace process のみで転送処理を行うものです。

ofproto と dpif の間の処理はofproto-dpif.cに、dpifとdpif-linux / dpif-netdevの間の処理はdpif.cに、dpif-linuxに関する処理はdpif-linux.cに書かれています。

ofproto-dpif

ofprotoからdpifへのインターフェイスは、ofproto-dpif.c の下部で ofproto_dpif_class で定義されています。これは、ofproto_class 構造体で、このメンバはそれぞれの処理を行う関数へのポインタになっています。

ofproto の dpif 特有のデータは、ofproto_dpif 構造体に入っています。 また、ofproto_dpif と datapath の間で様々な変換(ポート番号の表記など)を行うために必要なデータが dpif_backer 構造体に入っていて、どんな dpif を使っているのかという情報とそのdpifで様々な操作を行うための関数のポインタが入っている構造体へのポインタがあるのが dpif 構造体です。

階層構造は、(ofproto) - (ofproto_dpif) - (dpif_backer) - (dpif) - (dpif_linux or dpif_netdev) というようになっています。

facet と subfacet

dpif では、パケットの処理ルールは flow 単位で管理されています。flow は flow.c に flow構造体として定義されています。

Open vSwitch は様々なdatapathで使えるように考慮して設計されています。datapath の機能には異なると考えられます。例えば、TCP/UDP のポートまで見ることができる datapath や、Ethernet Address しか見ることができない datapath もあるでしょう。これらの違いを吸収するのが facet と subfacet です。

flow は facet と1対1で対応し、facet はいくつもの subfacet を持つ事ができます。subfacet は datapath に合わせて作られます。例えば、datapath が userspace の flow より詳しいところまで見ることができるのであれば、subfacet は複数作られることもあるでしょうし、datapath が flow ほど詳しく見る事ができないこともあります。VLAN splinter を使うと1つのflowをマッチさせるのに複数のsubfacetを使う必要があるかもしれません。

facet と subfacet がどういう関係にあるかは key_fitness と呼ばれ、odp_key_fitness で定数値が宣言されています。完全に一致する、subfacet のほうが細かい、subfacet のほうが粗い、の3種類があります。

/* How well a kernel-provided flow key (a sequence of OVS_KEY_ATTR_*
 * attributes) matches OVS userspace expectations.
 *
 * These values are arranged so that greater values are "more important" than
 * lesser ones.  In particular, a single flow key can fit the descriptions for
 * both ODP_FIT_TOO_LITTLE and ODP_FIT_TOO_MUCH.  Such a key is treated as
 * ODP_FIT_TOO_LITTLE. */
enum odp_key_fitness {
    ODP_FIT_PERFECT,            /* The key had exactly the fields we expect. */
    ODP_FIT_TOO_MUCH,           /* The key had fields we don't understand. */
    ODP_FIT_TOO_LITTLE,         /* The key lacked fields we expected to see. */
    ODP_FIT_ERROR,              /* The key was invalid. */
};

ofproto-dpif の type_run, type_run_fast, run, run_fast

ofproto_dpif_class にポインタが入っている type_run, type_run_fast は、main loop で毎回呼ばれるもので、パケットの処理を追っていく上で重要な関数であると考えられます。dpif に関する処理は長くて面倒なので^^;、これらから順に見ていきます。

type_run のポイントは、

dpif_run(backer->dpif)

です。ここから dpif_class (ここではdpif_linuxと考えます)のrun (dpif_linux_run), nln_run が順に呼び出されて、kernel との間の netlink のパケットの読み出しを行っています。

type_run_fast は、dpif_backer_run_fast関数を経由して、handle_upcalls関数を呼び出しています。これは、kernel から flow miss で userspace process に渡されたパケットを処理するための関数です。handle_upcalls 関数は、flow の検索など重要な要素を含んでいると推測されますので、flow table の管理のところで細かく見ます。



このエントリーをはてなブックマークに追加