《OVN Logical Flows and ovn-trace》翻译

2023-05-16

在本篇文章中,我将解释什么是Logical Flow以及如何使用ovn-trace去更好地理解它们。同时,我也会用一些例子来解释,为什么使用Logical Flow这种抽象模型能让新特性的添加变得出乎意料的简单。

But First, OpenFlow Basics

在深入Logical Flow之前,对于OpenFlow有一个基本的了解是非常必要的。OpenFlow是一个用来对Open vSwitch的packet processing pipeline进行编辑的协议。它能够让你定义一系列伴有rule(flow)的table,每个rule中还包含了priority,match,和一系列的action。对于每个table,能够匹配的flow中优先级最高(数字越大,优先级越高)的将被执行。

首先,让我们来想象一个简单的virtual switch,它有着两个端口,port1和port2


                        +--------+
            (1)         |        |          (2)
           port1 -------| br-int |-------- port2
                        |        |
                        +--------+


我们可以用以下命令创建一个有着两个port的bridge:


$ ovs-vsctl add-br br-int
$ ovs-vsctl add-port br-int port1
$ ovs-vsctl add-port br-int port2

$ ovs-vsctl show
3b1995d8-9683-45db-8929-36c62abdbd31
    Bridge br-int
        Port "port1"
            Interface "port1"
        Port br-int
            Interface br-int
                type: internal
        Port "port2"
            Interface "port2"
  

  

最简单的例子是创建一个table让所有从port1进入的包转发到port2,所有从port2进入的包转发到port1


    Table  Priority  Match      Actions
    -----  --------  ---------- -------
    0      0         in_port=1  output:2
    0      0         in_port=2  output:1  

 

我们可以用ovs-ofctl命令来编辑ovs中的pipeline:


$ ovs-ofctl del-flows br-int
$ ovs-ofctl add-flow br-int
$ ovs-ofctl add-flow br-int "table=0, priority=0, in_port=1, actions=output:2"
$ ovs-ofctl add-flow br-int "table=0, priority=0, in_port=2, actions=output:1"

$ ovs-ofctl dump-flows br-int
NXST_FLOW reply (xid=0x4):
  cookie=0x0, duration=9.679s, table=0, n_packets=0, n_bytes=0, idle_age=9, priority=0,in_port=1 actions=output:2
  cookie=0x0, duration=2.287s, table=0, n_packets=0, n_bytes=0, idle_age=2, priority=0,in_port=2 actions=output:1
  

  

我们还可以对这个例子进行扩展,从而来演示不同priority的使用。现在我们只允许源mac地址为00:00:00:00:01的包进入port1以及只允许源mac地址为00:00:00:00:00:02的包进入port2(basic source port security)。我们接着使用table 0来实现port security,再用table 1决定包的走向。

 

(当然,这些都可以在一个table中完成,但是这样就不能演示table和priority的使用了,而这恰恰是这个例子的主要目的)


    Table  Priority  Match                               Actions
    -----  --------  ----------------------------------- ------------
    0      10        in_port=1,dl_src=00:00:00:00:00:01  resubmit(,1)
    0      10        in_port=2,dl_src=00:00:00:00:00:02  resubmit(,1)
    0      0                                             drop
    1      0         in_port=1                           output:2
    1      0         in_port=2                           output:1  

同样,我们使用ovs-ofctl编辑如下pipeline:


$ ovs-ofctl del-flows br-int
$ ovs-ofctl add-flow br-int "table=0, priority=10, in_port=1, dl_src=00:00:00:00:00:01, actions=resubmit(,1)"
$ ovs-ofctl add-flow br-int "table=0, priority=10, in_port=2, dl_src=00:00:00:00:00:02, actions=resubmit(,1)"
$ ovs-ofctl add-flow br-int "table=0, priority=0, actions=drop"
$ ovs-ofctl add-flow br-int "table=1, priority=0, in_port=1,actions=output:2"
$ ovs-ofctl add-flow br-int "table=1, priority=0, in_port=2,actions=output:1"

$ ovs-ofctl dump-flows br-int
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=72.132s, table=0, n_packets=0, n_bytes=0, idle_age=72, priority=10,in_port=1,dl_src=00:00:00:00:00:01 actions=resubmit(,1)
 cookie=0x0, duration=60.565s, table=0, n_packets=0, n_bytes=0, idle_age=60, priority=10,in_port=2,dl_src=00:00:00:00:00:02 actions=resubmit(,1)
 cookie=0x0, duration=28.127s, table=0, n_packets=0, n_bytes=0, idle_age=28, priority=0 actions=drop
 cookie=0x0, duration=13.887s, table=1, n_packets=0, n_bytes=0, idle_age=13, priority=0,in_port=1 actions=output:2
 cookie=0x0, duration=4.023s, table=1, n_packets=0, n_bytes=0, idle_age=4, priority=0,in_port=2 actions=output:1
  

  

Open vSwitch还提供了一种能够追踪包从整个pipeline流通路径的机制。在这里,我们将追踪一个有着期望的mac地址的包从port1流入的过程。追踪程序的输出显示包被重新提交到了table 1并且之后从port 2输出了。输出的内容有点啰嗦,我们只要看"Rule"和"OpenFlow actions"这些列就可以知道哪些flow被执行了。


$ ovs-appctl ofproto/trace br-int in_port=1,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02 -generate
Bridge: br-int
Flow: in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,dl_type=0x0000

Rule: table=0 cookie=0 priority=10,in_port=1,dl_src=00:00:00:00:00:01
OpenFlow actions=resubmit(,1)

    Resubmitted flow: in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,dl_type=0x0000
    Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0 reg8=0x0 reg9=0x0 reg10=0x0 reg11=0x0 reg12=0x0 reg13=0x0 reg14=0x0 reg15=0x0
    Resubmitted  odp: drop
    Resubmitted megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:01,dl_type=0x0000
    Rule: table=1 cookie=0 priority=0,in_port=1
    OpenFlow actions=output:2

Final flow: unchanged
Megaflow: recirc_id=0,in_port=1,dl_src=00:00:00:00:00:01,dl_type=0x0000
Datapath actions: 3
  

  

OpenFlow可以用来构建更加复杂的pipeline。如果想知道更多细节,参见ovs-ofctl(8) man page。

 

OVN Logical Flows

上一节对OpenFlow进行了概述,展示了如何使用OpenFlow在单个switch里面构建packet processing pipelines。即使只在一台机器上对这些pipeline进行配置都让人觉得很麻烦,更不要说配置成千上万的机器了。但是只要有一个SDN controller,我们就能轻松地对许多switch进行配置,而这正是OVN在Open vSwtich这个项目中扮演的角色。OVN会完成所有OpenFlow的配置工作,用以实现你通过高层的接口配置的network topologies以及security policies。

那么OVN是怎么知道每台机器上需要的flow的呢?OVN解决这个问题的核心抽象模型就是Logical Flow。从概念上来说,Logical Flows和OpenFlow是类似的,它们都由table组成,table中包含flow,每个flow都有priority,match和action。两者最大的不同是,logical flow对整个网络的行为进行了详细地描述并且能扩展到任意数量的主机上。并且它把对于具体网络行为的定义和对于现实的物理设备的布局(有多少机器以及机器端口的分布)分离了开来。

OVN通过logical flow对网络进行编辑。之后,这些logical flow又会分发到每台机器上运行ovn-controller中。而ovn-controller知道根据当前的物理环境(本地端口在哪以及如何到达其他机器)将这些logical flow编译到OpenFlow中。

接着让我们用OVN来创建一个和上一节类似的例子。我们要创建的是一个带有两个logical ports的OVN logical switch。


$ ovn-nbctl ls-add sw0

$ ovn-nbctl lsp-add sw0 sw0-port1
$ ovn-nbctl lsp-set-address sw0-port1 00:00:00:00:00:01
$ ovn-nbctl lsp-set-port-security sw0-port1 00:00:00:00:00:01

$ ovn-nbctl lsp-add sw0 sw0-port2
$ ovn-nbctl lsp-set-addresses sw0-port2 00:00:00:00:00:02
$ ovn-nbctl lsp-set-port-security sw0-port2 00:00:00:00:00:02

$ ovn-nbctl show sw0
    switch 48d5f699-7ffe-4627-a369-2fc905e44b32 (sw0)
        port sw0-port1
            addresses: ["00:00:00:00:00:01"]
        port sw0-port2
            addresses: ["00:00:00:00:00:02"]
  

  

OVN定义了一个logical switch,sw0,使用了两个pipeline:一个ingress pipeline以及一个egress pipeline。当一个包流入网络时,生成该包的机器上的ingress pipeline将被执行。如果该包的目的地是同一台机器,那么egress pipeline也将被执行。


sw0-port1 and sw0-port2 on the same host:

    +--------------------------------------------------------------------------+
    |                                                                          |
    |                               Host A                                     |
    |                                                                          |
    |   +---------+                                              +---------+   |
    |   |sw0-port1| --> ingress pipeline --> egress pipeline --> |sw0-port2|   |
    |   +---------+                                              +---------+   |
    |                                                                          |
    +--------------------------------------------------------------------------+  

如果该包的目的地在远程机器上,那么该包首先要经过一个tunnel进行传输,然后在远程机器上执行egress pipeline


sw0-port1 and sw0-port2 on separate hosts:

    +--------------------------------------+
    |                                      |
    |             Host A                   |
    |                                      |
    |   +---------+                        |
    |   |sw0-port1| --> ingress pipeline   |
    |   +---------+           ||           |
    |                         ||           |
    +-------------------------||-----------+
                              ||
                              \/
                         geneve tunnel
                              ||
                              ||
    +-------------------------||-----------+
    |                         ||           |
    |             Host B      ||           |
    |                         ||           |
    |   +---------+           \/           |
    |   |sw0-port2| < -- egress pipeline   |
    |   +---------+                        |
    |                                      |
    +--------------------------------------+  

你可以使用"ovn-sbctl lflow-list"命令来查看完整的logical flow。它看起来会和OpenFlow有些相似,但是还是有非常不一样的地方的:

  1. Ports是一个逻辑概念,它位于网络中的某处,而不是一个switch中的physical ports
  2. pipeline中的每一个table除了编号以外还多了一个名字。这个名字描述了pipeline在该阶段的作用
  3. 匹配更灵活。支持复杂的布尔运算,对于程序员应该是很熟悉的了
  4. OVN logical flows扩展的action远远超过了OpenFlow。我们可以用logical flow的语法控制一些高级的特性,例如DHCP。具体的match和syntax的语法可以参见ovn-sb(5)中关于Logical_Flow的文档

在本例中,pipeline中还保留了很多额外的stage,用于未被用到的特性,所以下面很多table的flow实际上没有做任何事情

 


    $ ovn-sbctl lflow-list
    Datapath: "sw0" (d7bf4a7b-e915-4502-8f9d-5995d33f5d10)  Pipeline: ingress
      table=0 (ls_in_port_sec_l2  ), priority=100  , match=(eth.src[40]), action=(drop;)
      table=0 (ls_in_port_sec_l2  ), priority=100  , match=(vlan.present), action=(drop;)
      table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport == "sw0-port1" && eth.src == {00:00:00:00:00:01}), action=(next;)
      table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport == "sw0-port2" && eth.src == {00:00:00:00:00:02}), action=(next;)
      table=1 (ls_in_port_sec_ip  ), priority=0    , match=(1), action=(next;)
      table=2 (ls_in_port_sec_nd  ), priority=90   , match=(inport == "sw0-port1" && eth.src == 00:00:00:00:00:01 && arp.sha == 00:00:00:00:00:01), action=(next;)
      table=2 (ls_in_port_sec_nd  ), priority=90   , match=(inport == "sw0-port1" && eth.src == 00:00:00:00:00:01 && ip6 && nd && ((nd.sll == 00:00:00:00:00:00 || nd.sll == 00:00:00:00:00:01) || ((nd.tll == 00:00:00:00:00:00 || nd.tll == 00:00:00:00:00:01)))), action=(next;)
      table=2 (ls_in_port_sec_nd  ), priority=90   , match=(inport == "sw0-port2" && eth.src == 00:00:00:00:00:02 && arp.sha == 00:00:00:00:00:02), action=(next;)
      table=2 (ls_in_port_sec_nd  ), priority=90   , match=(inport == "sw0-port2" && eth.src == 00:00:00:00:00:02 && ip6 && nd && ((nd.sll == 00:00:00:00:00:00 || nd.sll == 00:00:00:00:00:02) || ((nd.tll == 00:00:00:00:00:00 || nd.tll == 00:00:00:00:00:02)))), action=(next;)
      table=2 (ls_in_port_sec_nd  ), priority=80   , match=(inport == "sw0-port1" && (arp || nd)), action=(drop;)
      table=2 (ls_in_port_sec_nd  ), priority=80   , match=(inport == "sw0-port2" && (arp || nd)), action=(drop;)
      table=2 (ls_in_port_sec_nd  ), priority=0    , match=(1), action=(next;)
      table=3 (ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
      table=4 (ls_in_pre_lb       ), priority=0    , match=(1), action=(next;)
      table=5 (ls_in_pre_stateful ), priority=100  , match=(reg0[0] == 1), action=(ct_next;)
      table=5 (ls_in_pre_stateful ), priority=0    , match=(1), action=(next;)
      table=6 (ls_in_acl          ), priority=0    , match=(1), action=(next;)
      table=7 (ls_in_qos_mark     ), priority=0    , match=(1), action=(next;)
      table=8 (ls_in_lb           ), priority=0    , match=(1), action=(next;)
      table=9 (ls_in_stateful     ), priority=100  , match=(reg0[1] == 1), action=(ct_commit(ct_label=0/1); next;)
      table=9 (ls_in_stateful     ), priority=100  , match=(reg0[2] == 1), action=(ct_lb;)
      table=9 (ls_in_stateful     ), priority=0    , match=(1), action=(next;)
      table=10(ls_in_arp_rsp      ), priority=0    , match=(1), action=(next;)
      table=11(ls_in_dhcp_options ), priority=0    , match=(1), action=(next;)
      table=12(ls_in_dhcp_response), priority=0    , match=(1), action=(next;)
      table=13(ls_in_l2_lkup      ), priority=100  , match=(eth.mcast), action=(outport = "_MC_flood"; output;)
      table=13(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:01), action=(outport = "sw0-port1"; output;)
      table=13(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0-port2"; output;)
    Datapath: "sw0" (d7bf4a7b-e915-4502-8f9d-5995d33f5d10)  Pipeline: egress
      table=0 (ls_out_pre_lb      ), priority=0    , match=(1), action=(next;)
      table=1 (ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
      table=2 (ls_out_pre_stateful), priority=100  , match=(reg0[0] == 1), action=(ct_next;)
      table=2 (ls_out_pre_stateful), priority=0    , match=(1), action=(next;)
      table=3 (ls_out_lb          ), priority=0    , match=(1), action=(next;)
      table=4 (ls_out_acl         ), priority=0    , match=(1), action=(next;)
      table=5 (ls_out_qos_mark    ), priority=0    , match=(1), action=(next;)
      table=6 (ls_out_stateful    ), priority=100  , match=(reg0[1] == 1), action=(ct_commit(ct_label=0/1); next;)
      table=6 (ls_out_stateful    ), priority=100  , match=(reg0[2] == 1), action=(ct_lb;)
      table=6 (ls_out_stateful    ), priority=0    , match=(1), action=(next;)
      table=7 (ls_out_port_sec_ip ), priority=0    , match=(1), action=(next;)
      table=8 (ls_out_port_sec_l2 ), priority=100  , match=(eth.mcast), action=(output;)
      table=8 (ls_out_port_sec_l2 ), priority=50   , match=(outport == "sw0-port1" && eth.dst == {00:00:00:00:00:01}), action=(output;)
      table=8 (ls_out_port_sec_l2 ), priority=50   , match=(outport == "sw0-port2" && eth.dst == {00:00:00:00:00:02}), action=(output;)
  

  

立即logical flow最好的方式就是使用ovn-trace命令。ovn-trace能够让你看到OVN对一个包是怎么处理的。

ovn-trace需要两个参数:


$ ovn-trace DATAPATH MICROFLOW
  

  

DATAPATH标识了sample packet开始进入的logical datapath(一个logical switch或者一个logical router)。MICROFLOW描述了模拟的sample packet。具体的细节详见ovn-trace(8) man page。

给定上文中的OVN配置,让我们来看看OVN会怎么处理一个由sw0-port1进入并将发往sw0-port2的包。ovn-trace的输出结果有多个详略程度可供选择。第一个是--minimal,它会告诉你这个包发生了些什么,但是会省略很多不必要的细节。在这个例子中,我们将看到的最终结果是该包将被发往sw0-port2。


$ ovn-trace --minimal sw0 'inport == "sw0-port1" && eth.src == 00:00:00:00:00:01 && eth.dst == 00:00:00:00:00:02'
# reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,dl_type=0x0000 output("sw0-port2");
  

  

下一个等级是--summary。在这个模式,我们能知道更多的关于包处理的细节,包括那个pipeline被执行了。如果我们对于同一个sample packet使用ovn-trace,我们将看到如下内容:

  1. 包从sw0-port1进入网络(sw0)并且运行了ingress pipeline
  2. 我们可以看到"sw0-port2"设置到了"output"这个变量中,这以为着该包的目的端口是"sw0-port2"
  3. 包从ingress pipeline输出,并且输出到"sw0"的egress pipeline并且输出变量设置为"sw0-port2"
  4. egress pipeline中的output action将被执行,它将把包输出到当前"output"变量对应的值中,即"sw0-port2"

    $ ovn-trace --summary sw0 'inport == "sw0-port1" && eth.src == 00:00:00:00:00:01 && eth.dst == 00:00:00:00:00:02'
    # reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,dl_type=0x0000
    ingress(dp="sw0", inport="sw0-port1") {
        outport = "sw0-port2";
        output;
        egress(dp="sw0", inport="sw0-port1", outport="sw0-port2") {
            output;
            /* output to "sw0-port2", type "" */;
        };
    };
  

  

当你在debug或者要修改代码的时候,你可能需要更细节的输出。ovn-trace有一个--detail选项。在这种模式下,你将获得更多的细节,关于包流动过程中遇到的每一个meaningful logical flow。你可以看到table number,pipeline stage name,full match,以及flow的priority number。你还可以看到负责创建该logical flow的OVN源代码的位置


    $ ovn-trace --detailed sw0 'inport == "sw0-port1" && eth.src == 00:00:00:00:00:01 && eth.dst == 00:00:00:00:00:02'
    # reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,dl_type=0x0000

    ingress(dp="sw0", inport="sw0-port1")
    -------------------------------------
     0. ls_in_port_sec_l2 (ovn-northd.c:2827): inport == "sw0-port1" && eth.src == {00:00:00:00:00:01}, priority 50
        next(1);
    13. ls_in_l2_lkup (ovn-northd.c:3095): eth.dst == 00:00:00:00:00:02, priority 50
        outport = "sw0-port2";
        output;

    egress(dp="sw0", inport="sw0-port1", outport="sw0-port2")
    ---------------------------------------------------------
     8. ls_out_port_sec_l2 (ovn-northd.c:3170): outport == "sw0-port2" && eth.dst == {00:00:00:00:00:02}, priority 50
        output;
        /* output to "sw0-port2", type "" */
  

  

另一个使用ovn-trace的例子是观察一个包为什么会被丢弃。我们已经设置了port security,现在让我们来看看从sw0-port1发出一个有着非预期源mac地址的包,它的执行路径是什么样的。从输出我们可以看到,这个包进入了sw0但是不能匹配table 0中任何一个flow,这意味着这个包会被丢弃。我们还可以看到table 0被命名为"ls_in_port_sec_l2",其实就是"Logical Switch ingress L2 port security"的缩写。


    $ ovn-trace --detailed sw0 'inport == "sw0-port1" && eth.src == 00:00:00:00:00:ff && eth.dst == 00:00:00:00:00:02'
# reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:ff,dl_dst=00:00:00:00:00:02,dl_type=0x0000

    ingress(dp="sw0", inport="sw0-port1")
    -------------------------------------
    0. ls_in_port_sec_l2: no match (implicit drop)
  

  

另一个相似的例子是,一个包有着未知的目的mac地址。在这种情况下,我们将看到这个包成功通过了table 0,但是未能匹配table 13,"ls_in_l2_lkup","Logical Switch ingress L2 lookup"的缩写。


    $ ovn-trace --detailed sw0 'inport == "sw0-port1" && eth.src == 00:00:00:00:00:01 && eth.dst == 00:00:00:00:00:ff'
    # reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:ff,dl_type=0x0000

    ingress(dp="sw0", inport="sw0-port1")
    -------------------------------------
     0. ls_in_port_sec_l2 (ovn-northd.c:2827): inport == "sw0-port1" && eth.src == {00:00:00:00:00:01}, priority 50
        next(1);
    13. ls_in_l2_lkup: no match (implicit drop)
  

  

到目前为止我们已经看过了在单个L2 logical network中的几个例子。接下来我们来创建一个新的环境用来演示ovn-trace怎么跨多个网络进行工作。我们将会创建两个network,每个有2个port,并且将他们连接到一个logical router上。


#!/bin/bash

# Create the first logical switch and its two ports.
ovn-nbctl ls-add sw0

ovn-nbctl lsp-add sw0 sw0-port1
ovn-nbctl lsp-set-addresses sw0-port1 "00:00:00:00:00:01 10.0.0.51"
ovn-nbctl lsp-set-port-security sw0-port1 "00:00:00:00:00:01 10.0.0.51"

ovn-nbctl lsp-add sw0 sw0-port2
ovn-nbctl lsp-set-addresses sw0-port2 "00:00:00:00:00:02 10.0.0.52"
ovn-nbctl lsp-set-port-security sw0-port2 "00:00:00:00:00:02 10.0.0.52"

# Create the second logical switch and its two ports.
ovn-nbctl ls-add sw1

ovn-nbctl lsp-add sw1 sw1-port1
ovn-nbctl lsp-set-addresses sw1-port1 "00:00:00:00:00:03 192.168.1.51"
ovn-nbctl lsp-set-port-security sw1-port1 "00:00:00:00:00:03 192.168.1.51"

ovn-nbctl lsp-add sw1 sw1-port2
ovn-nbctl lsp-set-addresses sw1-port2 "00:00:00:00:00:04 192.168.1.52"
ovn-nbctl lsp-set-port-security sw1-port2 "00:00:00:00:00:04 192.168.1.52"

# Create a logical router between sw0 and sw1.
ovn-nbctl create Logical_Router name=lr0

ovn-nbctl lrp-add lr0 lrp0 00:00:00:00:ff:01 10.0.0.1/24
ovn-nbctl lsp-add sw0 sw0-lrp0 \
    -- set Logical_Switch_Port sw0-lrp0 type=router \
    options:router-port=lrp0 addresses='"00:00:00:00:ff:01"'

ovn-nbctl lrp-add lr0 lrp1 00:00:00:00:ff:02 192.168.1.1/24
ovn-nbctl lsp-add sw1 sw1-lrp1 \
    -- set Logical_Switch_Port sw1-lrp1 type=router \
    options:router-port=lrp1 addresses='"00:00:00:00:ff:02"'
  

  

我们可以使用"ovn-nbctl show"命令来观察最终的逻辑网络的配置


$ ovn-nbctl show
    switch bf4ba6c6-91c5-4f56-9981-72643816f923 (sw1)
        port sw1-lrp1
            addresses: ["00:00:00:00:ff:02"]
        port sw1-port2
            addresses: ["00:00:00:00:00:04 192.168.1.52"]
        port sw1-port1
            addresses: ["00:00:00:00:00:03 192.168.1.51"]
    switch 13b80127-4b36-46ea-816a-1ba4ffd6ac57 (sw0)
        port sw0-port1
            addresses: ["00:00:00:00:00:01 10.0.0.51"]
        port sw0-lrp0
            addresses: ["00:00:00:00:ff:01"]
        port sw0-port2
            addresses: ["00:00:00:00:00:02 10.0.0.52"]
    router 68935017-967a-4c4a-9dad-5d325a9f203a (lr0)
        port lrp0
            mac: "00:00:00:00:ff:01"
            networks: ["10.0.0.1/24"]
        port lrp1
            mac: "00:00:00:00:ff:02"
            networks: ["192.168.1.1/24"]
  

  

我们现在可以对一个包进行追踪,这个包从sw0-port1发往sw1-port2,中间需要经过路由器。minimal output将会显示最终的结果是,这个包会从sw1-port2输出。我们还将看到过程中对这个包所做的修改。当包经过logical router时,TTL会减小,源和目的mac地址都会针对下一跳进行更新。


$ ovn-trace --minimal sw0 'inport == "sw0-port1" && \
                           eth.src == 00:00:00:00:00:01 && \
                           ip4.src == 10.0.0.51 && \
                           eth.dst == 00:00:00:00:ff:01 && \
                           ip4.dst == 192.168.1.52 && \
                           ip.ttl == 32'
# ip,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:ff:01,nw_src=10.0.0.51,nw_dst=192.168.1.52,nw_proto=0,nw_tos=0,nw_ecn=0,nw_ttl=32
ip.ttl--;
eth.src = 00:00:00:00:ff:02;
eth.dst = 00:00:00:00:00:04;
output("sw1-port2");
  

  

如果你想要观察得更仔细,可以同样执行上述命令,将--minimal改为--summary或者--detailed即可。你也可以对sample packet进行改变,看看到底会发生什么。

 

A Powerful Abstraction

我在文章的最开始就已经说过,我觉得OVN的Logical Flows是非常强大的抽象,它可以让对OVN添加特性变得异常简单。既然现在我们对logical flow有了一定的了解,下面我将说明一些最近新添加的特性,用于演示向OVN添加特性是多么地简单。

 

SOURCE BASED ROUTING

OVN已经支持了L3 gateways,它能够提供OVN logical network和physical network的连接。一个典型的OVN网络一般会有一个L3 gateway位于某台机器上。使用单个L3 gateway的缺陷是所有发往physical network的流量必须流经L3 gateway所在的机器。

最近Gurucharan Shetty添加了在OVN logical network中对于multiple L3 gateway的支持。它能够基于源IP地址在gateway之间分发流量。

我们并不需要知道这一改变的所有细节。我只想说明的是我们仅仅需要改动非常少量的代码就能实现这一特性。让我们来看一看diffstat。


Documentation:
 NEWS                          |    1 
 ovn/ovn-nb.xml                |   28 +++++
 ovn/utilities/ovn-nbctl.8.xml |    8 +

Database schema update:
 ovn/ovn-nb.ovsschema          |    8 +

Command line utility support for new db schema additions:
 ovn/utilities/ovn-nbctl.c     |   43 ++++++--

Changes to how OVN builds logical flows to add support for this feature:
 ovn/northd/ovn-northd.c       |   24 +++-

Test code:
 tests/ovn-nbctl.at            |   42 ++++----
 tests/ovn.at                  |  219 ++++++++++++++++++++++++++++++++++++++++++

 8 files changed, 334 insertions(+), 39 deletions(-)
  

  

最终要的是ovn-northd.c中的24行代码变动。这些代码用于更新logical flow的创建。这让我非常震惊,因为这个特性对于网络的行为有着非常重要的影响,但是却只用几行的C代码就搞定了。

 

DSCP

另一个通过logical flow添加特性的例子是这个patch,它基于arbitrary traffic classifier为设定IP包中的DSCP域提供了支持。这个patch在OVN northbound database中添加了一个新的QoS table。在这个table中定义了一个match(或者traffic classfier)以及相应DSCP值,用于设置那些匹配该classfier的包。

这个改变对应了ovn-northd.c中的80行代码。这个patch看起来比它实际的要大一些,因为它会为QoS创建一个新的pipeline stage并且还需要对它之后的stage进行重新编号。实现这个特性,只需要能插入能够匹配配置好的match(traffic classfier),之后在执行OVN logical flow actions"ip.dscp=VALUE; next"的flow就可以了。

 

DHCP

OVN支持DHCPv4和DHCPv6,所有这些都是通过logical flow实现的。在很多情况下,如果要改变它们的行为,只需要改变那些生成DHCP相关的logical flow的代码就可以了。

最近的一个例子是这个patch,它添加了对无状态DHCPv6的支持。有了无状态DHCPv6,我们能够提供一些configuration entries(例如DNS地址),但是不提供IPv6地址。这对于DHCPv6的logical flows只是一个小小的调整,只要OVN创建的应答能够有选择地包含IPv6地址选项就可以了。

 

Conclusion

我希望你对OVN Logical Flows已经有了更深的理解,它其实就是一个用于定义逻辑网络行为的,可扩展到多台机器上的match-action pipeline。

转载于:https://www.cnblogs.com/YaoDD/p/7489141.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

《OVN Logical Flows and ovn-trace》翻译 的相关文章

随机推荐

  • 防火墙关闭后不能ping通的解决办法

    修改被ping服务器的防火墙设置 xff1a 开始 控制面板 防火墙 高级 入站规则 文件和打印机共享 回显请求 ICMPv4 In 右键 启用 一共有两个 转载于 https www cnblogs com zhjx0521 p 1041
  • cmake设置mfc编译项目

    cmake minimum required VERSION 3 0 项目名 set PROJ NAME DCMLIB project PROJ NAME 设置变量 set CMAKE ALLOW LOOSE LOOP CONSTRUCTS
  • css 调转180度:transform: rotate(180deg);

    css 调转180度 xff1a transform rotate 180deg 转载于 https www cnblogs com shark1100913 p 8961298 html
  • OpenStack虚拟机冷迁移与热迁移

    一 虚拟机迁移分析 openstacvk虚拟机迁移分为冷迁移和热迁移两种方式 1 1冷迁移 xff1a 冷迁移 cold migration xff0c 也叫静态迁移 关闭电源的虚拟机进行迁移 通过冷迁移 xff0c 可以选择将关联的磁盘从
  • ubuntu下安装谷歌浏览器

    deb 是 Debian Linux 的安装格式 xff0c 在 ubuntu 中同样可以使用 要安装 deb 安装包 xff0c 需要使用 dpkg这个终端命令 xff0c 命令格式如下 xff1a sudo dpkg i lt pack
  • 更改root与vnc密码,配置vnc

    更改root密码 登录到root用户下 passwd 更改vnc密码 vncpasswd 配置vnc vi etc sysconfig vncservers 找到vncservers 61 34 1 myusername 34 这个字符串
  • linux vnc端口修改,vncserver端口的修改

    vnc的默认端口是5901 xff0c 这个说法是不对的 vnc并不是只有一个端口 先看看这个配置 VNCSERVERS 61 34 1 oracle 2 root 34 VNCSERVERARGS 1 61 34 geometry 800
  • winform布局格式

    一 默认布局 可以加panel xff0c 也可以不加 xff1b 通过鼠标拖动控件的方式 xff0c 根据自己的想法布局 拖动控件的过程中 xff0c 会有对齐的线 xff0c 方便操作 xff1b 也可选中要布局的控件 xff0c 在工
  • 事件(信号量、邮箱、消息队列)

    对于共享数据 xff0c 单纯通过加锁来保护在代码实现上这并不是很困难的 真正困难的地方是辨认出需要共享的数据和临界区 xff01 这里有一个很好的经验 xff1a 如果有其他的执行线程可以访问这些数据 xff0c 那么就要给这些数据加锁
  • Hadoop通过API访问HDFS

    1 version 1 通过Hadoop API访问HDFS 64 throws IOException 64 Test public void readFileByAPI throws IOException 获取hadoop配置信息 C
  • 对新课程的学习与期望

    我希望这门课可以让我熟练的掌握网站开发的知识 xff0c 我希望学完这门课后我可以创建出一个我网站 xff0c 我计划每周在这门课上花费13个小时 xff0c 每个礼拜的周一到周五的晚上花两个小时学习高级网站开发 转载于 https www
  • Neutron系列 : Neutron OVS OpenFlow 流表 和 L2 Population(8)

    问题导读 xff1a 1 怎样使用arp responder xff1f 2 怎样搭建l2pop环境 xff1f 3 ARP Responder arp responder 的原理不复杂 Neutorn DB 中保存了所有的端口的 MAC
  • SDN控制器ONOS的学习过程[mininet]

    命令语法 这个符号代表现在处于 Linux 的shell 交互下 xff0c 需要使用的是 Linux 命令mininet gt 这个符号表示现在处于 Mininet 交互下 xff0c 需要使用的是 Mininet 的命令 xff03 这
  • 什么是网络操作系统?网络操作系统具有哪些基本功能?

    网络操作系统是网络上各计算机能方便而有效地共享网络资源 xff0c 为网络用户提供所需的各种服务的软件和有关规程的集合 网络操作系统与通常的操作系统有所不同 xff0c 它除了应具有通常操作系统应具有的处理机管理 存储器管理 设备管理和文件
  • [教程] 【原创】媒体扫描耗电的彻底解决办法(申精)

    http bbs gfan com android 6740350 1 1 html 原创处女贴 xff0c 呵呵 研究换4 1 2也有段时间了 xff0c 4 1 2各方面功能均让我挺满意的 xff0c 用着也蛮顺手的 偶尔上论坛 xff
  • Error Domain=PlugInKit Code=13 打开相册模拟器卡顿

    问题描述 xff1a discovery errors encountered while discovering extensions Error Domain 61 PlugInKit Code 61 13 34 query cance
  • Arch Linux中通过AUR安装Redis Desktop Manager失败

    笔者在安装Redis Desktop Manager时出现了Failed to connect to chromium googlesource com port 443 Connection timed out错误 xff0c 具体见文末
  • 远程linux桌面灰屏,解决配置Ubuntu中vnc远程显示灰屏

    解决配置Ubuntu中vnc远程显示灰屏 a 缺失图形化工具 b vnc xstartup 权限不对 1 Ubuntu 16 04 安装 VNC 及 Mate 桌面环境 https www htcp net 880 html Fluxbox
  • linux客户端连接iscsi,配置ISCSI客户端(LINUX)redhat5-iSCSI-INITIATOR

    ISCSI 4的客户端装上去后会有 etc iscsi conf 配置文件 xff0c 直接按照模板参数修改就可以了 在ISCSI6的客户端配置方式有些变化 xff0c 这让我搞了一下午 xff0c 也参考的51CTO某技术大师的博客 xf
  • 《OVN Logical Flows and ovn-trace》翻译

    在本篇文章中 xff0c 我将解释什么是Logical Flow以及如何使用ovn trace去更好地理解它们 同时 xff0c 我也会用一些例子来解释 xff0c 为什么使用Logical Flow这种抽象模型能让新特性的添加变得出乎意料