avatar

Liang DONG
(looking for a job)

Chief Engineer
vc2004 (at) gmail.com
Hong Kong, China
+852 (hidden)
中文 / English / Cantonese
Software Engineering • System Architecture • Cloud Computing
书当快意读易尽,
客有可人期不来


Understanding OVN and Geneve Protocol

OVN and Geneve

  • date: 2016-12-15
  • category: Networking
  • tags: ovn, geneve, vxlan

本文浅谈一下 OVN 和 Geneve,以及一点点应用和 code

Encapsulation in OVN

OVN 支持三种隧道模式,Geneve,STT 和 VxLAN,但是其中 VxLAN 并不是什么情况下就能用的,Hypervisor 到 Hypervisor 之间的隧道模式只能走 Geneve 和 STT,到 GW 和 Vtep GW 的隧道才能用 VxLAN,这是为什么呢?

Why Geneve & STT

因为只有 STT 和 Geneve 支持携带大于 32bit 的 Metadata,VxLAN 并不支持这一特性。并且 STT 和 Geneve 支持使用随机的 UDP 和 TCP 源端口,这些包在 ECMP 里更容易被分布到不同的路径里,VxLAN 的固定端口很容易就打到一条路径上了。

STT 由于是 fake 出来的 TCP 包,网卡只要支持 TSO,就很容易达到高性能。VxLAN 现在一般网卡也都支持 Offloading了,但是就笔者经验,可能还有各种各样的问题。Geneve 比较新,也有新网卡支持了.

Geneve in OVN

OVSDB 里的 Geneve tunnel 长这样

1
2
3
4
5
        Port "ovn-711117-0"
            Interface "ovn-711117-0"
                type: geneve
                options: {csum="true", key=flow, remote_ip="172.18.3.153"}
                

key=flow 含义是 VNI 由 flow 来决定。

拿一个 OVN 里的 Geneve 包来举例,

Geneve in OVN

OVN 使用了 VNI 和 Options 来携带了 Metadata,其中

Logical Datapath as VNI

VNI 使用了 Logical Datapath,也就是 0xb1, 这个和 southbound database 里 datapath_binding 表里的 tunnel key 一致

1
2
3
_uuid               : 8fc46e14-1c0e-4129-a123-a69bf093c04e
external_ids        : {logical-switch="182eaadd-2cc3-4ff3-9bef-3793bb2463ec", name="neutron-f3dc2e30-f3e8-472b-abf8-ed455fc928f4"}
tunnel_key          : 177

Options

Options 里携带了一个 OVN 的 TLV,其中 Option Data 为 0001002,其中第一个0是保留位。后面的 001 和 002 是 Logical Inpurt Port 和 Logical Output Port,和 southbound database 里的 port_biding 表里的 tunnel key 一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
_uuid              : e40c929d-1997-4fac-bad3-867996eebd03
chassis            : 869e09ab-d47e-4f18-8562-e28692dc0b39
datapath           : 8fc46e14-1c0e-4129-a123-a69bf093c04e
logical_port       : "dedf0130-50eb-480d-9030-13b826093c4f"
mac                : ["fa:16:3e:ae:9a:b6 192.168.7.13"]
options            : {}
parent_port        : []
tag                : []
tunnel_key         : 1
type               : ""

_uuid              : b410ed4b-de0f-4d66-9815-1ea56b0a833c
chassis            : be5e84f9-3d01-431b-bdfa-208411c102c9
datapath           : 8fc46e14-1c0e-4129-a123-a69bf093c04e
logical_port       : "a3347aa1-a8fb-4e30-820c-04c7e1459dd3"
mac                : ["fa:16:3e:01:73:be 192.168.7.14"]
options            : {}
parent_port        : []
tag                : []
tunnel_key         : 2
type               : ""

Show Me The Code

在 ovn/controller/physical.h 中,定义 Class 为0x0102 和 type 0x80,可以看到和上图一致。

1
2
3
#define OVN_GENEVE_CLASS 0x0102  /* Assigned Geneve class for OVN. */
#define OVN_GENEVE_TYPE 0x80     /* Critical option. */
#define OVN_GENEVE_LEN 4

在 ovn/controller/physical.c 中,可以看到 ovn-controller 在 encapsulation 的时候,如果是 Geneve,会把 datapath的 tunnel key 放到 MFF_TUN_ID 里,outport 和 inport 放到 mff_ovn_geneve 里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static void
put_encapsulation(enum mf_field_id mff_ovn_geneve,
                  const struct chassis_tunnel *tun,
                  const struct sbrec_datapath_binding *datapath,
                  uint16_t outport, struct ofpbuf *ofpacts)
{
    if (tun->type == GENEVE) {
        put_load(datapath->tunnel_key, MFF_TUN_ID, 0, 24, ofpacts);
        put_load(outport, mff_ovn_geneve, 0, 32, ofpacts);
        put_move(MFF_LOG_INPORT, 0, mff_ovn_geneve, 16, 15, ofpacts);
    } else if (tun->type == STT) {
        put_load(datapath->tunnel_key | (outport << 24), MFF_TUN_ID, 0, 64,
                 ofpacts);
        put_move(MFF_LOG_INPORT, 0, MFF_TUN_ID, 40, 15, ofpacts);
    } else if (tun->type == VXLAN) {
        put_load(datapath->tunnel_key, MFF_TUN_ID, 0, 24, ofpacts);
    } else {
        OVS_NOT_REACHED();
    }
}

在头文件定义里,可以看到 MFF_TUN_ID 就是 VNI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    /* "tun_id" (aka "tunnel_id").
     *
     * The "key" or "tunnel ID" or "VNI" in a packet received via a keyed
     * tunnel.  For protocols in which the key is shorter than 64 bits, the key
     * is stored in the low bits and the high bits are zeroed.  For non-keyed
     * tunnels and packets not received via a tunnel, the value is 0.
     *
     * Type: be64.
     * Maskable: bitwise.
     * Formatting: hexadecimal.
     * Prerequisites: none.
     * Access: read/write.
     * NXM: NXM_NX_TUN_ID(16) since v1.1.
     * OXM: OXM_OF_TUNNEL_ID(38) since OF1.3 and v1.10.
     * Prefix lookup member: tunnel.tun_id.
     */
     
    MFF_TUN_ID,
 

Reference

  • OVN Architecture: http://openvswitch.org/support/dist-docs/ovn-architecture.7.html
  • OVN Repo: https://github.com/openvswitch/ovs/tree/master/ovn

Powered by Jekyll and Minimal Light theme.