Code Monkey home page Code Monkey logo

blog's Introduction

I like playing with Linux Kernel.

blog's People

Contributors

shun159 avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

blog's Issues

ovnのソースを読む(初期化編)

初期化を読む

#2 の続き

  • ovn/controller/ovn-controller.c:main(int argc, char *argv[])

ざっくりと飛ばすが、次の関数が順に呼ばれている:

  • ofctrl_init(&group_table)
  • pinctrl_init()
  • lflow_init()
  • Open_vSwitchテーブルへの接続のための関数(いっぱい書いてるので省略)
  • get_ovnsb_remote(ovs_idl_loop.idl)
  • ovsdb_idl_track_add_all
  • ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl)
  • connection tracking zoneを初期化

ofctrl_initはovn/controller/ofctrl.cにあります。

void
ofctrl_init(struct group_table *group_table)
{
    swconn = rconn_create(5, 0, DSCP_DEFAULT, 1 << OFP13_VERSION);
    tx_counter = rconn_packet_counter_create();
    hmap_init(&installed_flows);
    ovs_list_init(&flow_updates);
    groups = group_table;
}

関数の一行目では、OpenFlow1.3で接続しているのだろうとおもいます。
関数の2行目では、投入されたフローを記録する変数というコメントがあります。これを起動時に初期化している。
関数の3行目も同様です、こちらは投入前のフローを記録する変数の初期化です。
4行目は見たとおりなので、省略します。

pinctrl_initはovn/controller/pinctrl.cにあります。
ofctrl_initと同様、関数の一行目では、OpenFlow1.3で接続しているのだろうとおもいます。

void
pinctrl_init(void)
{
    swconn = rconn_create(5, 0, DSCP_DEFAULT, 1 << OFP13_VERSION);
    conn_seq_no = 0;
    init_put_mac_bindings();
    init_send_garps();
}

get_ovnsb_remoteはovn/controller/ovn-controllerに定義されている。
ここでovn-controllerはリモートにある OVN Southbound DBへ接続される.
Open_vSwitchのexternal_idsにovn-remoteが定義されるまで待っている...

static char *
get_ovnsb_remote(struct ovsdb_idl *ovs_idl)
{
    while (1) {
        ovsdb_idl_run(ovs_idl);

        const struct ovsrec_open_vswitch *cfg
            = ovsrec_open_vswitch_first(ovs_idl);
        if (cfg) {
            const char *remote = smap_get(&cfg->external_ids, "ovn-remote");
            if (remote) {
                return xstrdup(remote);
            }
        }

        VLOG_INFO("OVN OVSDB remote not specified.  Waiting...");
        ovsdb_idl_wait(ovs_idl);
        poll_block();
    }
}

ovsdb_idl_track_add_all(ovnsb_idl_loop.idl)はlib/ovsdb-idl.cに定義されている.
これは全カラムを監視対象とし、変更を受け取れるように監視対象のDBを指定できるものに読める。

void
ovsdb_idl_track_add_column(struct ovsdb_idl *idl,
                           const struct ovsdb_idl_column *column)
{
    if (!(*ovsdb_idl_get_mode(idl, column) & OVSDB_IDL_ALERT)) {
        ovsdb_idl_add_column(idl, column);
    }
    *ovsdb_idl_get_mode(idl, column) |= OVSDB_IDL_TRACK;
}

ovsdb_idl_get_initial_snapshotはlib/ovsdb-idl.cに定義されている...
OVSDBサーバへ接続し、DBの内容を取り出すことも可能。

void
ovsdb_idl_get_initial_snapshot(struct ovsdb_idl *idl)
{
    while (1) {
        ovsdb_idl_run(idl);
        if (ovsdb_idl_has_ever_connected(idl)) {
            return;
        }
        ovsdb_idl_wait(idl);
        poll_block();
    }
}

..以降、メインループとなる。

ovnのソースを読む(これから読む)

ovn-controllerのソースを読む

はじめに

ovn-architecture。まずはこちらを読む。

                                    CMS
                                     |
                                     |
                         +-----------|-----------+
                         |           |           |
                         |     OVN/CMS Plugin    |
                         |           |           |
                         |           |           |
                         |   OVN Northbound DB   |
                         |           |           |
                         |           |           |
                         |       ovn-northd      |
                         |           |           |
                         +-----------|-----------+
                                     |
                                     |
                           +-------------------+
                           | OVN Southbound DB |
                           +-------------------+
                                     |
                                     |
                  +------------------+------------------+
                  |                  |                  |
    HV 1          |                  |    HV n          |
  +---------------|---------------+  .  +---------------|---------------+
  |               |               |  .  |               |               |
  |        ovn-controller         |  .  |        ovn-controller         |
  |         |          |          |  .  |         |          |          |
  |         |          |          |     |         |          |          |
  |  ovs-vswitchd   ovsdb-server  |     |  ovs-vswitchd   ovsdb-server  |
  |                               |     |                               |
  +-------------------------------+     +-------------------------------+
    1. OVN/CMS plugin: OVNのインターフェイスとなるCMSのプラグイン。OpenStackならNeutronのプラグインに当たる。
    1. OVN Northbound DB: CMSから入力されたデータを保存する。logical switch, router, aclなどの中間表現データがCMSプラグインから入力される。
    1. ovn-northd: OVN Nouthbound DB と OVN Southbound DBをつなぐ。Southbound DBとNorthboundDBとのデータ構造の相互変換の役割も担っている。
    1. OVN Southbound DB: このシステムの中心となる。どのようにして他のハイパーバイザーに到達するかを管理するPhysical Networkテーブル、論理ネットワークが論理フローで記述されている Logical Networkテーブル, 論理ネットワークコンポーネントと物理ネットワークを紐付ける Bindingで構成されている。ハイパーバイザーはPhysical NetoworkテーブルとPort Bindingテーブルへ、ovn-northdは Logical Networkテーブルにデータを格納していく。
    1. ovn-controller: ハイパーバイザーとゲートウエイごとに配置されるコントローラエージェント。Northbound側においては、OVN Southbound DBへ接続し、Physical NetworkとBindingテーブルから設定、状態などを取得する。Southbound側においては、ovs-vswitchdへopenflowコントローラとして接続し、ネットワークの制御を行う。
    1. ovs-vswitchd と ovsdb-server: 従前からovsにあるコンポーネント。

ovn-controllerのモジュール

  • binding: OVN southbound:Bindingテーブルの管理モジュール
  • chassis: OVN southbound:Chassisテーブルの管理モジュール
  • encaps: OVN southbound:Encapテーブルの管理モジュール
  • lflow: OVN southbound:LogicalFlowテーブルの管理モジュール
  • lport: OVN southbound:PortBindingテーブルの管理モジュール
  • ofctl: OpenFlowコントローラ.flow_table, group_table, tlv_table, ct_tableの管理モジュール
  • patch: 同一ハイパーバイザー内でのブリッジ間接続のためのpatch port管理
  • physical: OpenFlow アクションの組み立てるモジュール
  • pinctrl: Openflowのpacket_inハンドラモジュール

memo: VerneMQ vs eMQTT

The main difference relies on the underlying distributed storage engine.
Emqtt and RabbitMQ use Mnesia (http://erlang.org/doc/apps/mnesia/Mnesia_overview.html) for its underlying distributed storage engine. 
VerneMQ uses an eventual consistent datastore backed by LevelDB.
We decided to not use Mnesia because Mnesia doesn't tolerate network partitions very well. 
Before starting VerneMQ our company consulted on RabbitMQ setups and we experienced those issues hands-on. 
This made us following a completely different approach to enable clustering.

https://github.com/erlio/vernemq/issues/83

これはブログです。

snabbの作者、lukegoさんがgithubのissueにブログを書くのをみて
これはよい、私もやってみようよ!と思いたった次第です。

ovnのソースを読む(フローテーブル編)

フローを読む(概論)

#3 の続き

物理的(OpenFlow的な)なフローテーブルを読む。

ovn-architectureでも記述されているが、ovnは以下のフローを扱っている。

ovn/controller/lflow.h

/* OpenFlow table numbers.
 *
 * These are heavily documented in ovn-architecture(7), please update it if
 * you make any changes. */
#define OFTABLE_PHY_TO_LOG            0
#define OFTABLE_LOG_INGRESS_PIPELINE 16 /* First of LOG_PIPELINE_LEN tables. */
#define OFTABLE_REMOTE_OUTPUT        32
#define OFTABLE_LOCAL_OUTPUT         33
#define OFTABLE_CHECK_LOOPBACK       34
#define OFTABLE_LOG_EGRESS_PIPELINE  48 /* First of LOG_PIPELINE_LEN tables. */
#define OFTABLE_SAVE_INPORT          64
#define OFTABLE_LOG_TO_PHY           65
#define OFTABLE_MAC_BINDING          66

/* The number of tables for the ingress and egress pipelines. */
#define LOG_PIPELINE_LEN 16

各論理パイプライン処理は16テーブル存在できることになっている。
入力は16から31、出力なら48から63の範囲となる。これらは、論理データパスごとに存在している。

論理スイッチ、ルータ、LB、ACL、DHCPサーバなどの処理がここに記述される。
それ以外は、共通的な転送処理を行う。

  • PHY_TO_LOG: conntrackゾーンの初期化、入力ポートの物理(OpenFlowポート)からOVN論理ポートへ変換される
  • LOG_INGRESS_PIPELINE: 論理的なネットワーク処理を行う入力パイプラインテーブル。何をするかは上の通り。
  • REMOTE_OUTPUT: リモートハイパーバイザーへパケットを送信する。
  • LOCAL_OUTPUT: ローカルハイパーバイザーへパケットを送信する。
  • CHECK_LOOPBACK: 入力ポートへの出力を防ぐ用
  • LOG_EGRESS_PIPELINE: 論理的なネットワーク処理を行う出力パイプラインテーブル。何をするかは上の通り。
  • SAVE_INPORT: nxm_reg10の1bit目には、loopbackへの出力を許可するかどうかをbitフラグで設定できる。許可されている場合、in_portに0をset_fieldする.
  • LOG_TO_PHY: 論理ポートから物理ポートへ変換。出力される。
  • MAC_BINDING: 情報がないが、、、、おそらく、、ソースコードを読む限りでは, ipv(4|6)アドレスとmac_addressのペアとtunnel_idの構築に関連付け、アプリから参照するための一時的なテーブル(table 65で転送処理が終端していて、66は転送ようではない)

ovn/lib/logical-fields.h

/* Logical fields.
 *
 * These values are documented in ovn-architecture(7), please update the
 * documentation if you change any of them. */
#define MFF_LOG_DATAPATH MFF_METADATA /* Logical datapath (64 bits). */
#define MFF_LOG_FLAGS      MFF_REG10  /* One of MLF_* (32 bits). */
#define MFF_LOG_DNAT_ZONE  MFF_REG11  /* conntrack dnat zone for gateway router
                                       * (32 bits). */
#define MFF_LOG_SNAT_ZONE  MFF_REG12  /* conntrack snat zone for gateway router
                                       * (32 bits). */
#define MFF_LOG_CT_ZONE    MFF_REG13  /* Logical conntrack zone for lports
                                       * (32 bits). */
#define MFF_LOG_INPORT     MFF_REG14  /* Logical input port (32 bits). */
#define MFF_LOG_OUTPORT    MFF_REG15  /* Logical output port (32 bits). */

/* Logical registers.
 *
 * Make sure these don't overlap with the logical fields! */
#define MFF_LOG_REG0 MFF_REG0
#define MFF_N_LOG_REGS 10

NXM_NX_REG10は上の通り、Flag用フィールドとして利用されている。以下の通り:

  • 1 bit ALLOW_LOOPBACK: Nested containerなどの通信を想定しているようだ。これはlflowで指定
  • 2 bit RCV_FROM_VXLAN: OVNは、STTまたは、Geneveをハイパーバイザー内外の通信のヒントとなる,
    論理データパス、論理ポートなどをトンネル越しにさせる為に利用しているが、
    vxlanを使った場合、これをサポートしない為、出力ポートをテーブルから拾うように動作する。

補足であるが、openvswitch 2.6から16個の32bit register(nicira拡張)が利用可能となっている。
また、openflow 1.5から仕様に明記されている、8つの64bit のexteneded register(xreg)に加え、
4つの128bit extended extended register(xxreg)が利用可能となっている。
xreg及びxxregはそれぞれのサイズで、registerをオーバーライドしている.
例:xreg0を使えばreg0とreg1が、xxreg0ならばreg0から3までが利用されることになっている。

かいつまんで説明すれば良いが、もっともこのovn-controllerの解読をすすめる上で、
難関となるのが、論理フローの部分となる。

論理的(OVN的な)なフローテーブルを読む。

論理的なフローテーブルとは、上で触れた通り、
各論理データパスごとに異なる機能をOpenFlow的なフローで表現したフローエントリを、
「お気持ちの分」人間が読みやすいように抽象的にしたものであるが、ここでは論理テーブルパイプラインごとに、
定義されている処理をOpenFlow的におってみる.

また、今回は時間的な都合により省いているが、論理ルータのフローテーブルはmetadataに格納されている論理データパスが示す
論理スイッチか、またルータかによって同じ論理フローパイプライン上に存在することができるようになっている。

まず、論理データパスごとのテーブルパイプラインにどのようなものがあるかを見る。
上から、論理テーブル0から、、、

Logical_Switch

Ingress

  • PORT_SEC_L2 (table_id: 16): vlan_vid == untagged かつ、src_mac != mcastなパケットをdrop。それ以外はresubmit(,17)となる。
  • PORT_SEC_IP (table_id: 17): ipv4アドレスのフィルタ。lsp-set-port-securityで指定したIPアドレスとDHCPリスエストパケットを通すが、IPアドレス無指定の場合はresubmit(,18)となっている.
  • PORT_SEC_ND (table_id: 18): NDフィルタ(ipv4 && ipv6共用)。lsp-set-addressで指定したIPアドレスがある場合、ipv4アドレスの場合,arp\_spa, ipv6の場合はnd_{sll|tll}がチェック対象となる.次はPRE_ACLresubmit(,19)
  • PRE_ACL (table_id: 19): チェック対象のプロトコルを次のテーブルに渡す前に、xxregの97bit(つまりreg0の1bit)目にヒントを書いて次のテーブルに通す。次はPRE_LBresubmit(,20)
  • PRE_LB (table_id: 20): VIP宛に来たIPアドレスに対して、xxregの97bit(つまりreg0の1bit)目にヒントを書く。次PRE_STATEFULresubmit(,21)
  • PRE_STATEFUL (table_id: 21): OpenvSwitchのctアクションは各ゾーンごとのconntrackテーブルからエントリを引っ張ってきて、openflowテーブルで処理するにはrecircをおこなう必要がある。ovnの場合では、22へrecircしている.次ACL(ct(table=22))
  • ACL (table_id: 22): チェック対象のプロトコルについて、新規セッションかどうかを見る処理をする。既存セッションならxxregの98bit(つまりreg0の2bit)目にヒントを書く,次はQOS_MARKresubmit(,23)
  • QOS_MARK (table_id: 23): 飛ばす。次はLBresubmit(,24)
  • LB (table_id: 24): group tableを使ったLB。 group_id=1,type=select,bucket=weight:100,actions=ct(commit,table=25,zone=NXM_NX_REG13[0..15],nat(dst=10.0.0.1)),bucket=weight:100,actions=ct(commit,table=25,zone=NXM_NX_REG13[0..15],nat(dst=10.0.0.2))
  • STATEFUL (table_id: 25): (?)
  • ARP_ND_RSP (table_id: 25): ARPハンドリング。ここで返すのではなく、 resubmit(26)するかresubmit(32)する
  • DHCP_OPTIONS (table_id: 26):
  • DHCP_RESPONSE (table_id: 27):
  • L2_LKUP (table_id: 28): FDBが格納されている。マッチしなければ論理ポートにffffが格納され、resubmit(32)する。

Egress

  • PRE_LB: (table_id: ):
  • PRE_ACL: (table_id: ):
  • PRE_STATEFUL: (table_id: ):
  • LB: (table_id: ):
  • ACL: (table_id: ):
  • QOS_MARK: (table_id: ):
  • STATE_FUL: (table_id: ):
  • PORT_SEC_IP:(table_id: ):
  • PORT_SEC_L2:(table_id: ):

TODO: ovn/actions.covn/controller/lflowを読んで解説をかく

Poptrie: A Compressed Trie with Population Count for Fast and Scalable Software IP Routing Table Lookup

Poptrie: A Compressed Trie with Population Count for Fast and Scalable Software IP Routing Table Lookup

http://delivery.acm.org/10.1145/2790000/2787474/p57-asai.pdf?ip=202.232.30.200&id=2787474&acc=OA&key=4D4702B0C3E38B35%2E4D4702B0C3E38B35%2E4D4702B0C3E38B35%2EC4E28C16103F6B69&CFID=699313198&CFTOKEN=53317265&__acm__=1480652675_a81753bc396b6b0681ab706f782370b4

SAIL, DXR, TreeBitMapと比較して、強力である。と言った特徴がある。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.