ovnが面白い

~ 変態的 Flow Tableを求めて ~

おまえ誰

 

Eishun Kondoh@shun159

 

TremaとLagopusとOpenvSwitchの大ファンです!

 

最近何故かプログラマに転向してました。 (元)ネットワークSIer勤務。

 

  1. OVN?

  2. OVNのフローテーブル

今日みなさんとお話ししてみたいこと

OVN?

  1. 仮想ネットワークに特化している(汎用的なコントローラではない)

  2. L2・L3・L4 ACL・オーバーレイネットワークの機能を提供する

  3. 上の機能は、Open vSwitchの既存の機能を使って実装する

  4. OVNは、現在(2015年1月時点)のNeutronのOpen vSwitch統合をシンプルにし、性能を上げる。

論理スイッチ・論理ルータを構成する。

更に、それらごとにACL、LB, NAT, QoSといった

機能を保存する。

OVN Southbound (OVN-SB)

OVN Southbound(OVN-NB)

OVN Southbound(OVN-SB)

論理・物理のマッピングを行った情報。

また、加えて論理フローが格納されている。

各HVからの物理情報が元になっている。

OVN Southbound(OVN-NB)

Text

Text

OVN Southbound(OVN-SB)

OVN Southbound(OVN-NB)

OVN-SBとOVN-NBをそれぞれの

変更を監視している。OVN-NBの内容を元にOVN-NBに対して、論理フローを作成して、

書き込みを行う。

Text

Text

OVN Southbound

OVN-NBの内容と、各HV内に同居している

Open_vSwitchDBの内容を組み合わせ、

OpenFlowプロトコル経由で

Group Table及び、Flow Tableを構築する。

CMS plugin

OvS 2.6.1時点では…

  • クラスレスな静的経路

  • ステートフルなアクセス制御

  • ステートフルなLB

  • ステートフルな{S|D}NAT

  • DHCP{v4|v6(?)} サーバー

  • L3トンネリング

ステートフルな×××

conntrack table

table=21,priority=100,ip,reg0=0x1/0x1,metadata=0x1 
actions=ct(table=22,zone=NXM_NX_REG13[0..15])
table=23, priority=65535,
ct_state=-new+est-rel-inv+trk,metadata=0x1 
actions=load:0x1->NXM_NX_XXREG0[98],resubmit(,24)

ステートフルな×××

recirc先テーブルを指定すれば、

その先のテーブル処理以降zoneから引いた

ct_stateがついてまわる.

conntrack情報を引いて、

flow_tableに再投入. NATも同様

L3トンネリング

L3トンネリング

  • Hypervisor 間通信はGeneve, STTだけサポート
  • ただし、ToRスイッチとの接続のためにVXLANもサポートしている
  • なぜ、OVNがGeneveやSTTしかサポートできないかは次のページ…

Geneveの場合

  • tun_id (24 bit)
    • logical datapath 24bit
  • tun_metadata(32bit)
    • reserved    1bit
    • ​ingress port 15 bit
    • egress port  16 bit

STTの場合

  • tun_id(64 bit)
    • reverved           9 bit
    • ingress port     15 bit
    • egress port      16 bit
    • ​logical datapath 24 bit

24

bit

(イケているか否かはさておいておいて)

まぁ無理だろ…

OVN DHCP(v4) Server

メカニズム

普通のDHCPって

多分大体こうかな

pool DB

lease DB

DHCP Server

DISCOVER

OFFER || NAK

REQUEST

ACK || NAK

reserve

allocate

OVN DHCPは…

  • DHCPを受け取るのはソケットの代わりのpacket_in2
    • packet_in2: pipelineをpauseできる、resumeできる, userdataを前もって指定できる。DHCP optionはこのuserdataに持っている.
  • Lease
    • Logical_Switch_Portのdynamic_addressesとmacのペア代わり.
    • addressをdynamicと指定した段階でallocateされている.
  • DISCOVERとREQUEST以外は受け付けない男前仕様(今後どうなる?)
    • (ねぇねぇ、INFORMは? DECLINEは?)

ちょっとこれ見て

table=26, 
priority=100,
## === matches ===
##
udp,
reg14=0x1,
metadata=0x1,
dl_src=0a:00:00:00:00:01,
nw_src=0.0.0.0,
nw_dst=255.255.255.255,
tp_src=68,
tp_dst=67 
## === actions ===
##
actions=controller(userdata=00.00.00.02.00.00.00.00.
                   00.01.de.10.00.00.00.63.0a.00.00.02.
                   01.04.ff.ff.ff.00.
                   01.04.ff.ff.ff.00.
                   03.04.0a.00.00.fe.
                   36.04.0a.00.00.fd.
                   33.04.00.00.00.b4,pause),
resubmit(,27)

ちょっとこれ見て

table=26, 
priority=100,
## === matches ===
##
udp,
reg14=0x1,
metadata=0x1,
dl_src=0a:00:00:00:00:01,
nw_src=0.0.0.0,
nw_dst=255.255.255.255,
tp_src=68,
tp_dst=67 
## === actions ===
## (注) offeripのNXM_NX_XXREG0はバイナリを見た感じ。にしては長さが合っていない。
actions=controller(userdata=00.00.00.02.00.00.00.00.    # nested_action=ACTION_OPCODE_PUT_DHCP_OPTS
                   00.01.de.10.00.00.00.63.0a.00.00.02. # NXM_NX_XXREG0 offerip=10.0.0.2
                   01.04.ff.ff.ff.00.                   # subnet mask 255.255.255.0
                   01.04.ff.ff.ff.00.                   # subnet mask 255.255.255.0(なんで?)
                   03.04.0a.00.00.fe.                   # router      10.0.0.254
                   36.04.0a.00.00.fd.                   # server ID   10.0.0.253
                   33.04.00.00.00.b4,pause),            # lease_time  180
resubmit(,27)

ちょっとこれ見て

以上、概要でした。

OVNのフローパイプライン

まずちょっとこれ見て

パイプライン(基本セット)

/* 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
enum ovn_stage {
#define PIPELINE_STAGES                                               \
    /* Logical switch ingress stages. */                              \
    PIPELINE_STAGE(SWITCH, IN,  PORT_SEC_L2,    0, "ls_in_port_sec_l2")     \
    PIPELINE_STAGE(SWITCH, IN,  PORT_SEC_IP,    1, "ls_in_port_sec_ip")     \
    PIPELINE_STAGE(SWITCH, IN,  PORT_SEC_ND,    2, "ls_in_port_sec_nd")     \
    PIPELINE_STAGE(SWITCH, IN,  PRE_ACL,        3, "ls_in_pre_acl")      \
    PIPELINE_STAGE(SWITCH, IN,  PRE_LB,         4, "ls_in_pre_lb")         \
    PIPELINE_STAGE(SWITCH, IN,  PRE_STATEFUL,   5, "ls_in_pre_stateful")    \
    PIPELINE_STAGE(SWITCH, IN,  ACL,            6, "ls_in_acl")          \
    PIPELINE_STAGE(SWITCH, IN,  LB,             7, "ls_in_lb")           \
    PIPELINE_STAGE(SWITCH, IN,  STATEFUL,       8, "ls_in_stateful")     \
    PIPELINE_STAGE(SWITCH, IN,  ARP_ND_RSP,     9, "ls_in_arp_rsp")      \
    PIPELINE_STAGE(SWITCH, IN,  DHCP_OPTIONS,   10, "ls_in_dhcp_options") \
    PIPELINE_STAGE(SWITCH, IN,  DHCP_RESPONSE,  11, "ls_in_dhcp_response") \
    PIPELINE_STAGE(SWITCH, IN,  L2_LKUP,        12, "ls_in_l2_lkup")      \

論理パイプライン(入力)

                                                                      \
    /* Logical switch egress stages. */                               \
    PIPELINE_STAGE(SWITCH, OUT, PRE_LB,       0, "ls_out_pre_lb")     \
    PIPELINE_STAGE(SWITCH, OUT, PRE_ACL,      1, "ls_out_pre_acl")     \
    PIPELINE_STAGE(SWITCH, OUT, PRE_STATEFUL, 2, "ls_out_pre_stateful")  \
    PIPELINE_STAGE(SWITCH, OUT, LB,           3, "ls_out_lb")            \
    PIPELINE_STAGE(SWITCH, OUT, ACL,          4, "ls_out_acl")            \
    PIPELINE_STAGE(SWITCH, OUT, STATEFUL,     5, "ls_out_stateful")       \
    PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_IP,  6, "ls_out_port_sec_ip")    \
    PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_L2,  7, "ls_out_port_sec_l2")    \

論理パイプライン(出力)

とはいえ、全部読むわけには行かないので…(個人的に)注目したいところにフォーカスを当ててみます。

table=IN_PRE_STATEFUL, priority=100,ip,reg0=0x1/0x1,metadata=Logical_Datapath1(lsw)
  actions=ct(table=22,zone=NXM_NX_REG13[0..15])
table=IN_PRE_STATEFUL, priority=0,metadata=Logical_Datapath1(lsw)
  actions=resubmit(,IN_ACL)

table=IN_ACL, priority=65535,ct_state=+inv+trk,metadata=Logical_Datapath1(lsw)
  actions=drop
table=IN_ACL, priority=65535,ct_state=+est+rpl+trk,ct_label=0x1/0x1,metadata=Logical_Datapath1(lsw)
  actions=drop
table=IN_ACL, priority=65535,ct_state=-new-est+rel-inv+trk,ct_label=0/0x1,metadata=Logical_Datapath1(lsw)
  actions=resubmit(,IN_LB)
table=IN_ACL, priority=65535,ct_state=-new+est-rel+rpl-inv+trk,ct_label=0/0x1,metadata=Logical_Datapath1(lsw)
  actions=resubmit(,IN_LB)
table=IN_ACL, priority=2002,ct_state=-new+est-rpl+trk,ct_label=0/0x1,ip,reg14=lport1,metadata=Logical_Datapath1(lsw)
  actions=resubmit(,IN_LB)
table=IN_ACL, priority=2002,ct_state=+new-est+trk,ip,reg14=lport1,metadata=Logical_Datapath1(lsw)
  actions=load:0x1->NXM_NX_XXREG0[97],resubmit(,IN_LB)
table=IN_ACL, priority=1,ct_state=+est+trk,ct_label=0x1/0x1,ip,metadata=Logical_Datapath1(lsw)
  actions=load:0x1->NXM_NX_XXREG0[97],resubmit(,IN_LB)
table=IN_ACL, priority=1,ct_state=-est+trk,ip,metadata=Logical_Datapath1(lsw)
  actions=load:0x1->NXM_NX_XXREG0[97] resubmit(,IN_LB)
table=IN_ACL, priority=0,metadata=Logical_Datapath1(lsw)
  actions=resubmit(,IN_LB)

table=OUT_ACL, priority=65535,ct_state=+est+rpl+trk,ct_label=0x1/0x1,metadata=Logical_Datapath1(lsw)
  actions=drop
table=OUT_ACL, priority=65535,ct_state=-new+est-rel+rpl-inv+trk,ct_label=0/0x1,metadata=Logical_Datapath1(lsw)
  actions=resubmit(,OUT_STATEFUL)
table=OUT_ACL, priority=65535,ct_state=+inv+trk,metadata=Logical_Datapath1(lsw)
  actions=drop
table=OUT_ACL, priority=65535,ct_state=-new-est+rel-inv+trk,ct_label=0/0x1,metadata=Logical_Datapath1(lsw)
  actions=resubmit(,OUT_STATEFUL)
table=OUT_ACL, priority=2002,ct_state=+new-est+trk,icmp,reg15=lport1,metadata=Logical_Datapath1(lsw)
  actions=load:0x1->NXM_NX_XXREG0[97],resubmit(,OUT_STATEFUL)
table=OUT_ACL, priority=2002,ct_state=-new+est-rpl+trk,ct_label=0/0x1,icmp,reg15=lport1,metadata=Logical_Datapath1(lsw) 
  actions=resubmit(,OUT_STATEFUL)
table=OUT_ACL, priority=2002,ct_state=-new+est-rpl+trk,ct_label=0x1/0x1,icmp,reg15=lport1,metadata=Logical_Datapath1(lsw)
  actions=load:0x1->NXM_NX_XXREG0[97],resubmit(,OUT_STATEFUL)
table=OUT_ACL, priority=2002,ct_state=+new-est+trk,tcp,reg15=lport1,metadata=Logical_Datapath1(lsw),tp_dst=22
  actions=load:0x1->NXM_NX_XXREG0[97],resubmit(,OUT_STATEFUL)
table=OUT_ACL, priority=2002,ct_state=-new+est-rpl+trk,ct_label=0x1/0x1,tcp,reg15=lport1,metadata=Logical_Datapath1(lsw),tp_dst=22 
  actions=load:0x1->NXM_NX_XXREG0[97],resubmit(,OUT_STATEFUL)
table=OUT_ACL, priority=2002,ct_state=-new+est-rpl+trk,ct_label=0/0x1,tcp,reg15=lport1,metadata=Logical_Datapath1(lsw),tp_dst=22 
  actions=resubmit(,OUT_STATEFUL)
table=OUT_ACL, priority=2001,ct_state=+est+trk,ct_label=0/0x1,ip,reg15=lport1,metadata=Logical_Datapath1(lsw) 
  actions=ct(commit,zone=NXM_NX_REG13[0..15],exec(load:0x1->NXM_NX_CT_LABEL[0]))
table=OUT_ACL, priority=2001,ct_state=+est+trk,ct_label=0x1/0x1,ip,reg15=lport1,metadata=Logical_Datapath1(lsw) 
  actions=drop
table=OUT_ACL, priority=2001,ct_state=-est+trk,ip,reg15=lport1,metadata=Logical_Datapath1(lsw)
  actions=drop
table=OUT_ACL, priority=1,ct_state=+est+trk,ct_label=0x1/0x1,ip,metadata=Logical_Datapath1(lsw)
  actions=load:0x1->NXM_NX_XXREG0[97],resubmit(,OUT_STATEFUL)
table=OUT_ACL, priority=1,ct_state=-est+trk,ip,metadata=Logical_Datapath1(lsw)
  actions=load:0x1->NXM_NX_XXREG0[97],resubmit(,OUT_STATEFUL)
table=OUT_ACL, priority=0,metadata=Logical_Datapath1(lsw)
  actions=resubmit(,OUT_STATEFUL)

レジスタフィールドとCT_LABELの使い方が

巧い…

最後に:

  • OVNは仮想ネットワークのためのプラットフォーム

    • そういえばkubernatesのプラグインもありました.
  • ほとんどの機能をフローだけで実現している…

    • ​好きな人には好きだろうけど…これデバッグとなるとなあ
      • ​どの場合でも論理フローと物理フローが一致するとは限らない
    • 構成、という点ではシンプルになるかもしれない。
      • OVNそのものはとてもシンプルだなぁと
    • NXAST_CONTROLLER2、もうなんでもありだなあ…