ovn 配置逻辑路由器实现三层转发

本文使用ovn搭建一个三层转发的环境,拓扑图如下

image.png

两个虚拟交换机ls1和ls2,端口ip网段分别为 10.10.10.0/24和 10.10.20.0/24。
虚拟交换机上分别连接两个vm(使用namespace模拟),使用dhclient动态获取ip。
一个虚拟路由器lr1,连接两个虚拟交换机ls1和ls2,实现跨网段通信。

值得注意的是,这里的逻辑路由器不同于neutron中的分布式路由器,虽然ovn逻辑路由器也是分布式的,但它只是一个逻辑上的,不存在实体,而是靠流表实现转发,neutron中的分布式路由器会在每个节点上使用namespace模拟路由器。

创建ls和lr

//创建两个虚拟交换机 ls1 和 ls2
ovn-nbctl ls-add ls1
ovn-nbctl ls-add ls2
//创建一个虚拟路由器 lr1
ovn-nbctl lr-add lr1

//在虚拟路由器上添加端口,用来连接虚拟交换机 ls1
ovn-nbctl lrp-add lr1 lr1-ls1 00:00:00:00:00:01 10.10.10.1/24

//在虚拟交换机 ls1 添加端口,用来连接虚拟路由器 lr1
ovn-nbctl lsp-add ls1 ls1-lr1
//端口类型必须为 router
ovn-nbctl lsp-set-type ls1-lr1 router
//设置地址,必须和 lr1-ls1 的一致
ovn-nbctl lsp-set-addresses ls1-lr1 00:00:00:00:00:01
//指定 router-port
ovn-nbctl lsp-set-options ls1-lr1 router-port=lr1-ls1

//在虚拟路由器上添加端口,用来连接虚拟交换机 ls2
ovn-nbctl lrp-add lr1 lr1-ls2 00:00:00:00:00:02 10.10.20.1/24

//在虚拟交换机 ls2 添加端口,用来连接虚拟路由器 lr1
ovn-nbctl lsp-add ls2 ls2-lr1
//端口类型必须为 router
ovn-nbctl lsp-set-type ls2-lr1 router
//设置地址,必须和 lr1-ls2 的一致
ovn-nbctl lsp-set-addresses ls2-lr1 00:00:00:00:00:02
//指定 router-port
ovn-nbctl lsp-set-options ls2-lr1 router-port=lr1-ls2

查看当前配置

# ovn-nbctl show
switch bf0d3638-0395-4dc8-acba-15ef0d9e6992 (ls2)
    port ls2-lr1
        type: router
        addresses: ["00:00:00:00:00:02"]
        router-port: lr1-ls2
switch 3c3a2c91-5415-411a-89c2-bbccdd400cd4 (ls1)
    port ls1-lr1
        type: router
        addresses: ["00:00:00:00:00:01"]
        router-port: lr1-ls1
router c92da6ff-54f3-45c9-b459-0725263f2ecc (lr1)
    port lr1-ls1
        mac: "00:00:00:00:00:01"
        networks: ["10.10.10.1/24"]
    port lr1-ls2
        mac: "00:00:00:00:00:02"
        networks: ["10.10.20.1/24"]

添加vm对应的端口

//在虚拟交换机 ls1 上添加两个端口,指定 mac 和 ip(10.10.10.0/24网段),用来连接vm
ovn-nbctl lsp-add ls1 ls1-vm1
ovn-nbctl lsp-set-addresses ls1-vm1 "00:00:00:00:00:03 10.10.10.2"
ovn-nbctl lsp-set-port-security ls1-vm1 "00:00:00:00:00:03 10.10.10.2"

ovn-nbctl lsp-add ls1 ls1-vm2
ovn-nbctl lsp-set-addresses ls1-vm2 "00:00:00:00:00:04 10.10.10.3"
ovn-nbctl lsp-set-port-security ls1-vm2 "00:00:00:00:00:04 10.10.10.3"

//在虚拟交换机 ls2 上添加两个端口,指定 mac 和 ip(10.10.20.0/24网段),用来连接vm
ovn-nbctl lsp-add ls2 ls2-vm1
ovn-nbctl lsp-set-addresses ls2-vm1 "00:00:00:00:00:03 10.10.20.2"
ovn-nbctl lsp-set-port-security ls2-vm1 "00:00:00:00:00:03 10.10.20.2"

ovn-nbctl lsp-add ls2 ls2-vm2
ovn-nbctl lsp-set-addresses ls2-vm2 "00:00:00:00:00:04 10.10.20.3"
ovn-nbctl lsp-set-port-security ls2-vm2 "00:00:00:00:00:04 10.10.20.3"

查看当前配置

//这里注意,ls1和ls2上的端口的ip是不同网段的,但是mac地址是可以重复的。
# ovn-nbctl show
switch bf0d3638-0395-4dc8-acba-15ef0d9e6992 (ls2)
    port ls2-vm2
        addresses: ["00:00:00:00:00:04 10.10.20.3"]
    port ls2-vm1
        addresses: ["00:00:00:00:00:03 10.10.20.2"]
    port ls2-lr1
        type: router
        addresses: ["00:00:00:00:00:02"]
        router-port: lr1-ls2
switch 3c3a2c91-5415-411a-89c2-bbccdd400cd4 (ls1)
    port ls1-lr1
        type: router
        addresses: ["00:00:00:00:00:01"]
        router-port: lr1-ls1
    port ls1-vm2
        addresses: ["00:00:00:00:00:04 10.10.10.3"]
    port ls1-vm1
        addresses: ["00:00:00:00:00:03 10.10.10.2"]
router c92da6ff-54f3-45c9-b459-0725263f2ecc (lr1)
    port lr1-ls1
        mac: "00:00:00:00:00:01"
        networks: ["10.10.10.1/24"]
    port lr1-ls2
        mac: "00:00:00:00:00:02"
        networks: ["10.10.20.1/24"]

创建dhcp选项,并绑定到logical switch port,以便vm可以申请ip地址

//创建 dhcp 选项,网段为 10.10.10.0/24
ovn-nbctl dhcp-options-create 10.10.10.0/24
//查看刚创建的 dhcp 选项UUID
ovn-nbctl dhcp-options-list
//通过 UUID 设置此 dhcp 选项的其他参数
ovn-nbctl dhcp-options-set-options 025a611c-c6ae-4f1e-8903-293620759a42 \
server_id=10.10.10.1 server_mac=00:00:00:00:00:01 lease_time=3600 router=10.10.10.1

//设置 logical_switch_port 的 dhcp 字段,指向上面创建的 dhcp 选项
ovn-nbctl lsp-set-dhcpv4-options ls1-vm1 025a611c-c6ae-4f1e-8903-293620759a42
ovn-nbctl lsp-get-dhcpv4-options ls1-vm1

ovn-nbctl lsp-set-dhcpv4-options ls1-vm2 025a611c-c6ae-4f1e-8903-293620759a42
ovn-nbctl lsp-get-dhcpv4-options ls1-vm2

//创建 dhcp 选项,网段为 10.10.20.0/24
ovn-nbctl dhcp-options-create 10.10.20.0/24
//查看刚创建的 dhcp 选项UUID
ovn-nbctl dhcp-options-list
//通过 UUID 设置此 dhcp 选项的其他参数
ovn-nbctl dhcp-options-set-options 6e278b8c-2d6f-4a5d-8256-a91d9770bcb9 \
server_id=10.10.20.1 server_mac=00:00:00:00:00:02 lease_time=3600 router=10.10.20.1

//设置 logical_switch_port 的 dhcp 字段,指向上面创建的 dhcp 选项
ovn-nbctl lsp-set-dhcpv4-options ls2-vm1 6e278b8c-2d6f-4a5d-8256-a91d9770bcb9
ovn-nbctl lsp-get-dhcpv4-options ls2-vm1
 
ovn-nbctl lsp-set-dhcpv4-options ls2-vm2 6e278b8c-2d6f-4a5d-8256-a91d9770bcb9
ovn-nbctl lsp-get-dhcpv4-options ls2-vm2

查看dhcp选项

# ovn-nbctl list dhcp_options
_uuid               : 6e278b8c-2d6f-4a5d-8256-a91d9770bcb9
cidr                : "10.10.20.0/24"
external_ids        : {}
options             : {lease_time="3600", router="10.10.20.1", server_id="10.10.20.1", server_mac="00:00:00:00:00:02"}

_uuid               : 025a611c-c6ae-4f1e-8903-293620759a42
cidr                : "10.10.10.0/24"
external_ids        : {}
options             : {lease_time="3600", router="10.10.10.1", server_id="10.10.10.1", server_mac="00:00:00:00:00:01"}

使用namespace模拟vm,并动态申请ip

//在 master 节点上,创建两个namespace,用来模拟两个vm,使用 "iface-id" 指定
//这两个vm属于 ls1
ip netns add vm1
ovs-vsctl add-port br-int vm1 -- set interface vm1 type=internal
ip link set vm1 address 00:00:00:00:00:03
ip link set vm1 netns vm1
ovs-vsctl set Interface vm1 external_ids:iface-id=ls1-vm1
//申请 ip
ip netns exec vm1 dhclient vm1
ip netns exec vm1 ip addr show vm1
ip netns exec vm1 ip route show

ip netns add vm2
ovs-vsctl add-port br-int vm2 -- set interface vm2 type=internal
ip link set vm2 address 00:00:00:00:00:04
ip link set vm2 netns vm2
ovs-vsctl set Interface vm2 external_ids:iface-id=ls1-vm2
//申请 ip
ip netns exec vm2 dhclient vm2
ip netns exec vm2 ip addr show vm2
ip netns exec vm2 ip route show

//在 node1 节点上,创建两个namespace,用来模拟两个vm,使用 "iface-id" 指定这两个vm属于 ls2
ip netns add vm1
ovs-vsctl add-port br-int vm1 -- set interface vm1 type=internal
ip link set vm1 address 00:00:00:00:00:03
ip link set vm1 netns vm1
ovs-vsctl set Interface vm1 external_ids:iface-id=ls2-vm1
//申请 ip
ip netns exec vm1 dhclient vm1
ip netns exec vm1 ip addr show vm1
ip netns exec vm1 ip route show

ip netns add vm2
ovs-vsctl add-port br-int vm2 -- set interface vm2 type=internal
ip link set vm2 address 00:00:00:00:00:04
ip link set vm2 netns vm2
ovs-vsctl set Interface vm2 external_ids:iface-id=ls2-vm2
//申请 ip
ip netns exec vm2 dhclient vm2
ip netns exec vm2 ip addr show vm2
ip netns exec vm2 ip route show

# ip netns exec vm1 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
64: vm1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ether 00:00:00:00:00:03 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.2/24 brd 10.10.10.255 scope global dynamic vm1
       valid_lft 3484sec preferred_lft 3484sec
    inet6 fe80::200:ff:fe00:3/64 scope link
       valid_lft forever preferred_lft forever
//ping网段
# ip netns exec vm1 ping 10.10.10.1
PING 10.10.10.1 (10.10.10.1) 56(84) bytes of data.
64 bytes from 10.10.10.1: icmp_seq=1 ttl=254 time=1.78 ms
^C
--- 10.10.10.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.776/1.776/1.776/0.000 ms
//ping同网段的vm2
# ip netns exec vm1 ping 10.10.10.3
PING 10.10.10.3 (10.10.10.3) 56(84) bytes of data.
64 bytes from 10.10.10.3: icmp_seq=1 ttl=64 time=1.29 ms
^C
--- 10.10.10.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.287/1.287/1.287/0.000 ms

//ping跨网段的网关
# ip netns exec vm1 ping 10.10.20.1
PING 10.10.20.1 (10.10.20.1) 56(84) bytes of data.
64 bytes from 10.10.20.1: icmp_seq=1 ttl=254 time=0.785 ms
^C
--- 10.10.20.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.785/0.785/0.785/0.000 ms

//ping跨网段的vm1
# ip netns exec vm1 ping 10.10.20.2
PING 10.10.20.2 (10.10.20.2) 56(84) bytes of data.
64 bytes from 10.10.20.2: icmp_seq=1 ttl=63 time=7.60 ms
^C
--- 10.10.20.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 7.601/7.601/7.601/0.000 ms

//ping跨网段的vm2
# ip netns exec vm1 ping 10.10.20.3
PING 10.10.20.3 (10.10.20.3) 56(84) bytes of data.
64 bytes from 10.10.20.3: icmp_seq=1 ttl=63 time=6.65 ms
^C
--- 10.10.20.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 6.649/6.649/6.649/0.000 ms

查看sbdb的logical flow信息

# ovn-sbctl lflow-list
Datapath: "lr1" (971c4f82-1d3e-402c-b511-be9a412983f1)  Pipeline: ingress
  table=0 (lr_in_admission    ), priority=100  , match=(vlan.present || eth.src[40]), action=(drop;)
  table=0 (lr_in_admission    ), priority=50   , match=(eth.dst == 00:00:00:00:00:01 && inport == "lr1-ls1"), action=(xreg0[0..47] = 00:00:00:00:00:01; next;)
  table=0 (lr_in_admission    ), priority=50   , match=(eth.dst == 00:00:00:00:00:02 && inport == "lr1-ls2"), action=(xreg0[0..47] = 00:00:00:00:00:02; next;)
  table=0 (lr_in_admission    ), priority=50   , match=(eth.mcast && inport == "lr1-ls1"), action=(xreg0[0..47] = 00:00:00:00:00:01; next;)
  table=0 (lr_in_admission    ), priority=50   , match=(eth.mcast && inport == "lr1-ls2"), action=(xreg0[0..47] = 00:00:00:00:00:02; next;)
  table=1 (lr_in_lookup_neighbor), priority=100  , match=(arp.op == 2), action=(reg9[2] = lookup_arp(inport, arp.spa, arp.sha); next;)
  table=1 (lr_in_lookup_neighbor), priority=100  , match=(inport == "lr1-ls1" && arp.spa == 10.10.10.0/24 && arp.op == 1), action=(reg9[2] = lookup_arp(inport, arp.spa, arp.sha); next;)
  table=1 (lr_in_lookup_neighbor), priority=100  , match=(inport == "lr1-ls2" && arp.spa == 10.10.20.0/24 && arp.op == 1), action=(reg9[2] = lookup_arp(inport, arp.spa, arp.sha); next;)
  table=1 (lr_in_lookup_neighbor), priority=100  , match=(nd_na), action=(reg9[2] = lookup_nd(inport, nd.target, nd.tll); next;)
  table=1 (lr_in_lookup_neighbor), priority=100  , match=(nd_ns), action=(reg9[2] = lookup_nd(inport, ip6.src, nd.sll); next;)
  table=1 (lr_in_lookup_neighbor), priority=0    , match=(1), action=(reg9[2] = 1; next;)
  table=2 (lr_in_learn_neighbor), priority=100  , match=(reg9[2] == 1), action=(next;)
  table=2 (lr_in_learn_neighbor), priority=90   , match=(arp), action=(put_arp(inport, arp.spa, arp.sha); next;)
  table=2 (lr_in_learn_neighbor), priority=90   , match=(nd_na), action=(put_nd(inport, nd.target, nd.tll); next;)
  table=2 (lr_in_learn_neighbor), priority=90   , match=(nd_ns), action=(put_nd(inport, ip6.src, nd.sll); next;)
  table=3 (lr_in_ip_input     ), priority=100  , match=(ip4.src == {10.10.10.1, 10.10.10.255} && reg9[0] == 0), action=(drop;)
  table=3 (lr_in_ip_input     ), priority=100  , match=(ip4.src == {10.10.20.1, 10.10.20.255} && reg9[0] == 0), action=(drop;)
  table=3 (lr_in_ip_input     ), priority=100  , match=(ip4.src_mcast ||ip4.src == 255.255.255.255 || ip4.src == 127.0.0.0/8 || ip4.dst == 127.0.0.0/8 || ip4.src == 0.0.0.0/8 || ip4.dst == 0.0.0.0/8), action=(drop;)
  table=3 (lr_in_ip_input     ), priority=100  , match=(ip6.dst == fe80::200:ff:fe00:1 && udp.src == 547 && udp.dst == 546), action=(reg0 = 0; handle_dhcpv6_reply;)
  table=3 (lr_in_ip_input     ), priority=100  , match=(ip6.dst == fe80::200:ff:fe00:2 && udp.src == 547 && udp.dst == 546), action=(reg0 = 0; handle_dhcpv6_reply;)
  table=3 (lr_in_ip_input     ), priority=90   , match=(inport == "lr1-ls1" && arp.op == 1 && arp.tpa == 10.10.10.1 && arp.spa == 10.10.10.0/24), action=(eth.dst = eth.src; eth.src = xreg0[0..47]; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = xreg0[0..47]; arp.tpa = arp.spa; arp.spa = 10.10.10.1; outport = inport; flags.loopback = 1; output;)
  table=3 (lr_in_ip_input     ), priority=90   , match=(inport == "lr1-ls1" && ip6.dst == {fe80::200:ff:fe00:1, ff02::1:ff00:1} && nd_ns && nd.target == fe80::200:ff:fe00:1), action=(nd_na_router { eth.src = xreg0[0..47]; ip6.src = fe80::200:ff:fe00:1; nd.target = fe80::200:ff:fe00:1; nd.tll = xreg0[0..47]; outport = inport; flags.loopback = 1; output; };)
  table=3 (lr_in_ip_input     ), priority=90   , match=(inport == "lr1-ls2" && arp.op == 1 && arp.tpa == 10.10.20.1 && arp.spa == 10.10.20.0/24), action=(eth.dst = eth.src; eth.src = xreg0[0..47]; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = xreg0[0..47]; arp.tpa = arp.spa; arp.spa = 10.10.20.1; outport = inport; flags.loopback = 1; output;)
  table=3 (lr_in_ip_input     ), priority=90   , match=(inport == "lr1-ls2" && ip6.dst == {fe80::200:ff:fe00:2, ff02::1:ff00:2} && nd_ns && nd.target == fe80::200:ff:fe00:2), action=(nd_na_router { eth.src = xreg0[0..47]; ip6.src = fe80::200:ff:fe00:2; nd.target = fe80::200:ff:fe00:2; nd.tll = xreg0[0..47]; outport = inport; flags.loopback = 1; output; };)
  table=3 (lr_in_ip_input     ), priority=90   , match=(ip4.dst == 10.10.10.1 && icmp4.type == 8 && icmp4.code == 0), action=(ip4.dst <-> ip4.src; ip.ttl = 255; icmp4.type = 0; flags.loopback = 1; next; )
  table=3 (lr_in_ip_input     ), priority=90   , match=(ip4.dst == 10.10.20.1 && icmp4.type == 8 && icmp4.code == 0), action=(ip4.dst <-> ip4.src; ip.ttl = 255; icmp4.type = 0; flags.loopback = 1; next; )
  table=3 (lr_in_ip_input     ), priority=90   , match=(ip6.dst == fe80::200:ff:fe00:1 && icmp6.type == 128 && icmp6.code == 0), action=(ip6.dst <-> ip6.src; ip.ttl = 255; icmp6.type = 129; flags.loopback = 1; next; )
  table=3 (lr_in_ip_input     ), priority=90   , match=(ip6.dst == fe80::200:ff:fe00:2 && icmp6.type == 128 && icmp6.code == 0), action=(ip6.dst <-> ip6.src; ip.ttl = 255; icmp6.type = 129; flags.loopback = 1; next; )
  table=3 (lr_in_ip_input     ), priority=85   , match=(arp || nd), action=(drop;)
  table=3 (lr_in_ip_input     ), priority=84   , match=(nd_rs || nd_ra), action=(next;)
  table=3 (lr_in_ip_input     ), priority=83   , match=(ip6.mcast_rsvd), action=(drop;)
  table=3 (lr_in_ip_input     ), priority=82   , match=(ip4.mcast || ip6.mcast), action=(drop;)
  table=3 (lr_in_ip_input     ), priority=80   , match=(ip4 && ip4.dst == 10.10.10.1 && !ip.later_frag && sctp), action=(sctp_abort {eth.dst <-> eth.src; ip4.dst <-> ip4.src; next; };)
  table=3 (lr_in_ip_input     ), priority=80   , match=(ip4 && ip4.dst == 10.10.10.1 && !ip.later_frag && tcp), action=(tcp_reset {eth.dst <-> eth.src; ip4.dst <-> ip4.src; next; };)
  table=3 (lr_in_ip_input     ), priority=80   , match=(ip4 && ip4.dst == 10.10.10.1 && !ip.later_frag && udp), action=(icmp4 {eth.dst <-> eth.src; ip4.dst <-> ip4.src; ip.ttl = 255; icmp4.type = 3; icmp4.code = 3; next; };)
  table=3 (lr_in_ip_input     ), priority=80   , match=(ip4 && ip4.dst == 10.10.20.1 && !ip.later_frag && sctp), action=(sctp_abort {eth.dst <-> eth.src; ip4.dst <-> ip4.src; next; };)
  table=3 (lr_in_ip_input     ), priority=80   , match=(ip4 && ip4.dst == 10.10.20.1 && !ip.later_frag && tcp), action=(tcp_reset {eth.dst <-> eth.src; ip4.dst <-> ip4.src; next; };)
  table=3 (lr_in_ip_input     ), priority=80   , match=(ip4 && ip4.dst == 10.10.20.1 && !ip.later_frag && udp), action=(icmp4 {eth.dst <-> eth.src; ip4.dst <-> ip4.src; ip.ttl = 255; icmp4.type = 3; icmp4.code = 3; next; };)
  table=3 (lr_in_ip_input     ), priority=80   , match=(ip6 && ip6.dst == fe80::200:ff:fe00:1 && !ip.later_frag && sctp), action=(sctp_abort {eth.dst <-> eth.src; ip6.dst <-> ip6.src; next; };)
  table=3 (lr_in_ip_input     ), priority=80   , match=(ip6 && ip6.dst == fe80::200:ff:fe00:1 && !ip.later_frag && tcp), action=(tcp_reset {eth.dst <-> eth.src; ip6.dst <-> ip6.src; next; };)
  table=3 (lr_in_ip_input     ), priority=80   , match=(ip6 && ip6.dst == fe80::200:ff:fe00:1 && !ip.later_frag && udp), action=(icmp6 {eth.dst <-> eth.src; ip6.dst <-> ip6.src; ip.ttl = 255; icmp6.type = 1; icmp6.code = 4; next; };)
  table=3 (lr_in_ip_input     ), priority=80   , match=(ip6 && ip6.dst == fe80::200:ff:fe00:2 && !ip.later_frag && sctp), action=(sctp_abort {eth.dst <-> eth.src; ip6.dst <-> ip6.src; next; };)
  table=3 (lr_in_ip_input     ), priority=80   , match=(ip6 && ip6.dst == fe80::200:ff:fe00:2 && !ip.later_frag && tcp), action=(tcp_reset {eth.dst <-> eth.src; ip6.dst <-> ip6.src; next; };)
  table=3 (lr_in_ip_input     ), priority=80   , match=(ip6 && ip6.dst == fe80::200:ff:fe00:2 && !ip.later_frag && udp), action=(icmp6 {eth.dst <-> eth.src; ip6.dst <-> ip6.src; ip.ttl = 255; icmp6.type = 1; icmp6.code = 4; next; };)
  table=3 (lr_in_ip_input     ), priority=70   , match=(ip4 && ip4.dst == 10.10.10.1 && !ip.later_frag), action=(icmp4 {eth.dst <-> eth.src; ip4.dst <-> ip4.src; ip.ttl = 255; icmp4.type = 3; icmp4.code = 2; next; };)
  table=3 (lr_in_ip_input     ), priority=70   , match=(ip4 && ip4.dst == 10.10.20.1 && !ip.later_frag), action=(icmp4 {eth.dst <-> eth.src; ip4.dst <-> ip4.src; ip.ttl = 255; icmp4.type = 3; icmp4.code = 2; next; };)
  table=3 (lr_in_ip_input     ), priority=70   , match=(ip6 && ip6.dst == fe80::200:ff:fe00:1 && !ip.later_frag), action=(icmp6 {eth.dst <-> eth.src; ip6.dst <-> ip6.src; ip.ttl = 255; icmp6.type = 1; icmp6.code = 3; next; };)
  table=3 (lr_in_ip_input     ), priority=70   , match=(ip6 && ip6.dst == fe80::200:ff:fe00:2 && !ip.later_frag), action=(icmp6 {eth.dst <-> eth.src; ip6.dst <-> ip6.src; ip.ttl = 255; icmp6.type = 1; icmp6.code = 3; next; };)
  table=3 (lr_in_ip_input     ), priority=60   , match=(ip4.dst == {10.10.10.1}), action=(drop;)
  table=3 (lr_in_ip_input     ), priority=60   , match=(ip4.dst == {10.10.20.1}), action=(drop;)
  table=3 (lr_in_ip_input     ), priority=60   , match=(ip6.dst == {fe80::200:ff:fe00:1}), action=(drop;)
  table=3 (lr_in_ip_input     ), priority=60   , match=(ip6.dst == {fe80::200:ff:fe00:2}), action=(drop;)
  table=3 (lr_in_ip_input     ), priority=50   , match=(eth.bcast), action=(drop;)
  table=3 (lr_in_ip_input     ), priority=40   , match=(inport == "lr1-ls1" && ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst <-> eth.src; icmp4.type = 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 10.10.10.1; ip.ttl = 255; next; };)
  table=3 (lr_in_ip_input     ), priority=40   , match=(inport == "lr1-ls2" && ip4 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp4 {eth.dst <-> eth.src; icmp4.type = 11; /* Time exceeded */ icmp4.code = 0; /* TTL exceeded in transit */ ip4.dst = ip4.src; ip4.src = 10.10.20.1; ip.ttl = 255; next; };)
  table=3 (lr_in_ip_input     ), priority=30   , match=(ip4 && ip.ttl == {0, 1}), action=(drop;)
  table=3 (lr_in_ip_input     ), priority=0    , match=(1), action=(next;)
  table=4 (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
  table=5 (lr_in_unsnat       ), priority=0    , match=(1), action=(next;)
  table=6 (lr_in_dnat         ), priority=0    , match=(1), action=(next;)
  table=7 (lr_in_ecmp_stateful), priority=0    , match=(1), action=(next;)
  table=8 (lr_in_nd_ra_options), priority=0    , match=(1), action=(next;)
  table=9 (lr_in_nd_ra_response), priority=0    , match=(1), action=(next;)
  table=10(lr_in_ip_routing   ), priority=550  , match=(nd_rs || nd_ra), action=(drop;)
  table=10(lr_in_ip_routing   ), priority=129  , match=(inport == "lr1-ls1" && ip6.dst == fe80::/64), action=(ip.ttl--; reg8[0..15] = 0; xxreg0 = ip6.dst; xxreg1 = fe80::200:ff:fe00:1; eth.src = 00:00:00:00:00:01; outport = "lr1-ls1"; flags.loopback = 1; next;)
  table=10(lr_in_ip_routing   ), priority=129  , match=(inport == "lr1-ls2" && ip6.dst == fe80::/64), action=(ip.ttl--; reg8[0..15] = 0; xxreg0 = ip6.dst; xxreg1 = fe80::200:ff:fe00:2; eth.src = 00:00:00:00:00:02; outport = "lr1-ls2"; flags.loopback = 1; next;)
  table=10(lr_in_ip_routing   ), priority=49   , match=(ip4.dst == 10.10.10.0/24), action=(ip.ttl--; reg8[0..15] = 0; reg0 = ip4.dst; reg1 = 10.10.10.1; eth.src = 00:00:00:00:00:01; outport = "lr1-ls1"; flags.loopback = 1; next;)
  table=10(lr_in_ip_routing   ), priority=49   , match=(ip4.dst == 10.10.20.0/24), action=(ip.ttl--; reg8[0..15] = 0; reg0 = ip4.dst; reg1 = 10.10.20.1; eth.src = 00:00:00:00:00:02; outport = "lr1-ls2"; flags.loopback = 1; next;)
  table=11(lr_in_ip_routing_ecmp), priority=150  , match=(reg8[0..15] == 0), action=(next;)
  table=12(lr_in_policy       ), priority=0    , match=(1), action=(reg8[0..15] = 0; next;)
  table=13(lr_in_policy_ecmp  ), priority=150  , match=(reg8[0..15] == 0), action=(next;)
  table=14(lr_in_arp_resolve  ), priority=500  , match=(ip4.mcast || ip6.mcast), action=(next;)
  table=14(lr_in_arp_resolve  ), priority=100  , match=(outport == "lr1-ls1" && reg0 == 10.10.10.2), action=(eth.dst = 00:00:00:00:00:03; next;)
  table=14(lr_in_arp_resolve  ), priority=100  , match=(outport == "lr1-ls1" && reg0 == 10.10.10.3), action=(eth.dst = 00:00:00:00:00:04; next;)
  table=14(lr_in_arp_resolve  ), priority=100  , match=(outport == "lr1-ls2" && reg0 == 10.10.20.2), action=(eth.dst = 00:00:00:00:00:03; next;)
  table=14(lr_in_arp_resolve  ), priority=100  , match=(outport == "lr1-ls2" && reg0 == 10.10.20.3), action=(eth.dst = 00:00:00:00:00:04; next;)
  table=14(lr_in_arp_resolve  ), priority=0    , match=(ip4), action=(get_arp(outport, reg0); next;)
  table=14(lr_in_arp_resolve  ), priority=0    , match=(ip6), action=(get_nd(outport, xxreg0); next;)
  table=15(lr_in_chk_pkt_len  ), priority=0    , match=(1), action=(next;)
  table=16(lr_in_larger_pkts  ), priority=0    , match=(1), action=(next;)
  table=17(lr_in_gw_redirect  ), priority=0    , match=(1), action=(next;)
  table=18(lr_in_arp_request  ), priority=100  , match=(eth.dst == 00:00:00:00:00:00 && ip4), action=(arp { eth.dst = ff:ff:ff:ff:ff:ff; arp.spa = reg1; arp.tpa = reg0; arp.op = 1; output; };)
  table=18(lr_in_arp_request  ), priority=100  , match=(eth.dst == 00:00:00:00:00:00 && ip6), action=(nd_ns { nd.target = xxreg0; output; };)
  table=18(lr_in_arp_request  ), priority=0    , match=(1), action=(output;)
Datapath: "lr1" (971c4f82-1d3e-402c-b511-be9a412983f1)  Pipeline: egress
  table=0 (lr_out_undnat      ), priority=0    , match=(1), action=(next;)
  table=1 (lr_out_snat        ), priority=120  , match=(nd_ns), action=(next;)
  table=1 (lr_out_snat        ), priority=0    , match=(1), action=(next;)
  table=2 (lr_out_egr_loop    ), priority=0    , match=(1), action=(next;)
  table=3 (lr_out_delivery    ), priority=100  , match=(outport == "lr1-ls1"), action=(output;)
  table=3 (lr_out_delivery    ), priority=100  , match=(outport == "lr1-ls2"), action=(output;)
Datapath: "ls1" (919643ab-44c5-4368-b6ff-f701093af973)  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 == "ls1-lr1"), action=(next;)
  table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport == "ls1-vm1" && eth.src == {00:00:00:00:00:03}), action=(next;)
  table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport == "ls1-vm2" && eth.src == {00:00:00:00:00:04}), action=(next;)
  table=1 (ls_in_port_sec_ip  ), priority=90   , match=(inport == "ls1-vm1" && eth.src == 00:00:00:00:00:03 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(next;)
  table=1 (ls_in_port_sec_ip  ), priority=90   , match=(inport == "ls1-vm1" && eth.src == 00:00:00:00:00:03 && ip4.src == {10.10.10.2}), action=(next;)
  table=1 (ls_in_port_sec_ip  ), priority=90   , match=(inport == "ls1-vm2" && eth.src == 00:00:00:00:00:04 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(next;)
  table=1 (ls_in_port_sec_ip  ), priority=90   , match=(inport == "ls1-vm2" && eth.src == 00:00:00:00:00:04 && ip4.src == {10.10.10.3}), action=(next;)
  table=1 (ls_in_port_sec_ip  ), priority=80   , match=(inport == "ls1-vm1" && eth.src == 00:00:00:00:00:03 && ip), action=(drop;)
  table=1 (ls_in_port_sec_ip  ), priority=80   , match=(inport == "ls1-vm2" && eth.src == 00:00:00:00:00:04 && ip), action=(drop;)
  table=1 (ls_in_port_sec_ip  ), priority=0    , match=(1), action=(next;)
  table=2 (ls_in_port_sec_nd  ), priority=90   , match=(inport == "ls1-vm1" && eth.src == 00:00:00:00:00:03 && arp.sha == 00:00:00:00:00:03 && arp.spa == {10.10.10.2}), action=(next;)
  table=2 (ls_in_port_sec_nd  ), priority=90   , match=(inport == "ls1-vm2" && eth.src == 00:00:00:00:00:04 && arp.sha == 00:00:00:00:00:04 && arp.spa == {10.10.10.3}), action=(next;)
  table=2 (ls_in_port_sec_nd  ), priority=80   , match=(inport == "ls1-vm1" && (arp || nd)), action=(drop;)
  table=2 (ls_in_port_sec_nd  ), priority=80   , match=(inport == "ls1-vm2" && (arp || nd)), action=(drop;)
  table=2 (ls_in_port_sec_nd  ), priority=0    , match=(1), action=(next;)
  table=3 (ls_in_lookup_fdb   ), priority=0    , match=(1), action=(next;)
  table=4 (ls_in_put_fdb      ), priority=0    , match=(1), action=(next;)
  table=5 (ls_in_pre_acl      ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(next;)
  table=5 (ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
  table=6 (ls_in_pre_lb       ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(next;)
  table=6 (ls_in_pre_lb       ), priority=110  , match=(ip && inport == "ls1-lr1"), action=(next;)
  table=6 (ls_in_pre_lb       ), priority=110  , match=(nd || nd_rs || nd_ra || mldv1 || mldv2), action=(next;)
  table=6 (ls_in_pre_lb       ), priority=0    , match=(1), action=(next;)
  table=7 (ls_in_pre_stateful ), priority=100  , match=(reg0[0] == 1), action=(ct_next;)
  table=7 (ls_in_pre_stateful ), priority=0    , match=(1), action=(next;)
  table=8 (ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
  table=9 (ls_in_acl          ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;)
  table=9 (ls_in_acl          ), priority=0    , match=(1), action=(next;)
  table=10(ls_in_qos_mark     ), priority=0    , match=(1), action=(next;)
  table=11(ls_in_qos_meter    ), priority=0    , match=(1), action=(next;)
  table=12(ls_in_lb           ), priority=0    , match=(1), action=(next;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[1] == 1), action=(ct_commit { ct_label.blocked = 0; }; next;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[2] == 1 && ip4 && sctp), action=(reg1 = ip4.dst; reg2[0..15] = sctp.dst; ct_lb;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[2] == 1 && ip4 && tcp), action=(reg1 = ip4.dst; reg2[0..15] = tcp.dst; ct_lb;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[2] == 1 && ip4 && udp), action=(reg1 = ip4.dst; reg2[0..15] = udp.dst; ct_lb;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[2] == 1 && ip6 && sctp), action=(xxreg1 = ip6.dst; reg2[0..15] = sctp.dst; ct_lb;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[2] == 1 && ip6 && tcp), action=(xxreg1 = ip6.dst; reg2[0..15] = tcp.dst; ct_lb;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[2] == 1 && ip6 && udp), action=(xxreg1 = ip6.dst; reg2[0..15] = udp.dst; ct_lb;)
  table=13(ls_in_stateful     ), priority=0    , match=(1), action=(next;)
  table=14(ls_in_pre_hairpin  ), priority=0    , match=(1), action=(next;)
  table=15(ls_in_nat_hairpin  ), priority=0    , match=(1), action=(next;)
  table=16(ls_in_hairpin      ), priority=0    , match=(1), action=(next;)
  table=17(ls_in_arp_rsp      ), priority=100  , match=(arp.tpa == 10.10.10.2 && arp.op == 1 && inport == "ls1-vm1"), action=(next;)
  table=17(ls_in_arp_rsp      ), priority=100  , match=(arp.tpa == 10.10.10.3 && arp.op == 1 && inport == "ls1-vm2"), action=(next;)
  table=17(ls_in_arp_rsp      ), priority=50   , match=(arp.tpa == 10.10.10.2 && arp.op == 1), action=(eth.dst = eth.src; eth.src = 00:00:00:00:00:03; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 00:00:00:00:00:03; arp.tpa = arp.spa; arp.spa = 10.10.10.2; outport = inport; flags.loopback = 1; output;)
  table=17(ls_in_arp_rsp      ), priority=50   , match=(arp.tpa == 10.10.10.3 && arp.op == 1), action=(eth.dst = eth.src; eth.src = 00:00:00:00:00:04; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 00:00:00:00:00:04; arp.tpa = arp.spa; arp.spa = 10.10.10.3; outport = inport; flags.loopback = 1; output;)
  table=17(ls_in_arp_rsp      ), priority=0    , match=(1), action=(next;)
  table=18(ls_in_dhcp_options ), priority=100  , match=(inport == "ls1-vm1" && eth.src == 00:00:00:00:00:03 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(reg0[3] = put_dhcp_opts(offerip = 10.10.10.2, lease_time = 3600, netmask = 255.255.255.0, router = 10.10.10.1, server_id = 10.10.10.1); next;)
  table=18(ls_in_dhcp_options ), priority=100  , match=(inport == "ls1-vm1" && eth.src == 00:00:00:00:00:03 && ip4.src == 10.10.10.2 && ip4.dst == {10.10.10.1, 255.255.255.255} && udp.src == 68 && udp.dst == 67), action=(reg0[3] = put_dhcp_opts(offerip = 10.10.10.2, lease_time = 3600, netmask = 255.255.255.0, router = 10.10.10.1, server_id = 10.10.10.1); next;)
  table=18(ls_in_dhcp_options ), priority=100  , match=(inport == "ls1-vm2" && eth.src == 00:00:00:00:00:04 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(reg0[3] = put_dhcp_opts(offerip = 10.10.10.3, lease_time = 3600, netmask = 255.255.255.0, router = 10.10.10.1, server_id = 10.10.10.1); next;)
  table=18(ls_in_dhcp_options ), priority=100  , match=(inport == "ls1-vm2" && eth.src == 00:00:00:00:00:04 && ip4.src == 10.10.10.3 && ip4.dst == {10.10.10.1, 255.255.255.255} && udp.src == 68 && udp.dst == 67), action=(reg0[3] = put_dhcp_opts(offerip = 10.10.10.3, lease_time = 3600, netmask = 255.255.255.0, router = 10.10.10.1, server_id = 10.10.10.1); next;)
  table=18(ls_in_dhcp_options ), priority=0    , match=(1), action=(next;)
  table=19(ls_in_dhcp_response), priority=100  , match=(inport == "ls1-vm1" && eth.src == 00:00:00:00:00:03 && ip4 && udp.src == 68 && udp.dst == 67 && reg0[3]), action=(eth.dst = eth.src; eth.src = 00:00:00:00:00:01; ip4.src = 10.10.10.1; udp.src = 67; udp.dst = 68; outport = inport; flags.loopback = 1; output;)
  table=19(ls_in_dhcp_response), priority=100  , match=(inport == "ls1-vm2" && eth.src == 00:00:00:00:00:04 && ip4 && udp.src == 68 && udp.dst == 67 && reg0[3]), action=(eth.dst = eth.src; eth.src = 00:00:00:00:00:01; ip4.src = 10.10.10.1; udp.src = 67; udp.dst = 68; outport = inport; flags.loopback = 1; output;)
  table=19(ls_in_dhcp_response), priority=0    , match=(1), action=(next;)
  table=20(ls_in_dns_lookup   ), priority=0    , match=(1), action=(next;)
  table=21(ls_in_dns_response ), priority=0    , match=(1), action=(next;)
  table=22(ls_in_external_port), priority=0    , match=(1), action=(next;)
  table=23(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(handle_svc_check(inport);)
  table=23(ls_in_l2_lkup      ), priority=80   , match=(flags[1] == 0 && arp.op == 1 && arp.tpa == { 10.10.10.1}), action=(clone {outport = "ls1-lr1"; output; }; outport = "_MC_flood_l2"; output;)
  table=23(ls_in_l2_lkup      ), priority=80   , match=(flags[1] == 0 && nd_ns && nd.target == { fe80::200:ff:fe00:1}), action=(clone {outport = "ls1-lr1"; output; }; outport = "_MC_flood_l2"; output;)
  table=23(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {00:00:00:00:00:01} && (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood_l2"; output;)
  table=23(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = "_MC_flood"; output;)
  table=23(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:01), action=(outport = "ls1-lr1"; output;)
  table=23(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:03), action=(outport = "ls1-vm1"; output;)
  table=23(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:04), action=(outport = "ls1-vm2"; output;)
  table=23(ls_in_l2_lkup      ), priority=0    , match=(1), action=(outport = get_fdb(eth.dst); next;)
  table=24(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), action=(drop;)
  table=24(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
Datapath: "ls1" (919643ab-44c5-4368-b6ff-f701093af973)  Pipeline: egress
  table=0 (ls_out_pre_lb      ), priority=110  , match=(eth.src == $svc_monitor_mac), action=(next;)
  table=0 (ls_out_pre_lb      ), priority=110  , match=(ip && outport == "ls1-lr1"), action=(next;)
  table=0 (ls_out_pre_lb      ), priority=110  , match=(nd || nd_rs || nd_ra || mldv1 || mldv2), action=(next;)
  table=0 (ls_out_pre_lb      ), priority=0    , match=(1), action=(next;)
  table=1 (ls_out_pre_acl     ), priority=110  , match=(eth.src == $svc_monitor_mac), 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_hint    ), priority=0    , match=(1), action=(next;)
  table=5 (ls_out_acl         ), priority=34000, match=(eth.src == $svc_monitor_mac), action=(next;)
  table=5 (ls_out_acl         ), priority=34000, match=(outport == "ls1-vm1" && eth.src == 00:00:00:00:00:01 && ip4.src == 10.10.10.1 && udp && udp.src == 67 && udp.dst == 68), action=(next;)
  table=5 (ls_out_acl         ), priority=34000, match=(outport == "ls1-vm2" && eth.src == 00:00:00:00:00:01 && ip4.src == 10.10.10.1 && udp && udp.src == 67 && udp.dst == 68), action=(next;)
  table=5 (ls_out_acl         ), priority=0    , match=(1), action=(next;)
  table=6 (ls_out_qos_mark    ), priority=0    , match=(1), action=(next;)
  table=7 (ls_out_qos_meter   ), priority=0    , match=(1), action=(next;)
  table=8 (ls_out_stateful    ), priority=100  , match=(reg0[1] == 1), action=(ct_commit { ct_label.blocked = 0; }; next;)
  table=8 (ls_out_stateful    ), priority=100  , match=(reg0[2] == 1), action=(ct_lb;)
  table=8 (ls_out_stateful    ), priority=0    , match=(1), action=(next;)
  table=9 (ls_out_port_sec_ip ), priority=90   , match=(outport == "ls1-vm1" && eth.dst == 00:00:00:00:00:03 && ip4.dst == {255.255.255.255, 224.0.0.0/4, 10.10.10.2}), action=(next;)
  table=9 (ls_out_port_sec_ip ), priority=90   , match=(outport == "ls1-vm2" && eth.dst == 00:00:00:00:00:04 && ip4.dst == {255.255.255.255, 224.0.0.0/4, 10.10.10.3}), action=(next;)
  table=9 (ls_out_port_sec_ip ), priority=80   , match=(outport == "ls1-vm1" && eth.dst == 00:00:00:00:00:03 && ip), action=(drop;)
  table=9 (ls_out_port_sec_ip ), priority=80   , match=(outport == "ls1-vm2" && eth.dst == 00:00:00:00:00:04 && ip), action=(drop;)
  table=9 (ls_out_port_sec_ip ), priority=0    , match=(1), action=(next;)
  table=10(ls_out_port_sec_l2 ), priority=100  , match=(eth.mcast), action=(output;)
  table=10(ls_out_port_sec_l2 ), priority=50   , match=(outport == "ls1-lr1"), action=(output;)
  table=10(ls_out_port_sec_l2 ), priority=50   , match=(outport == "ls1-vm1" && eth.dst == {00:00:00:00:00:03}), action=(output;)
  table=10(ls_out_port_sec_l2 ), priority=50   , match=(outport == "ls1-vm2" && eth.dst == {00:00:00:00:00:04}), action=(output;)
Datapath: "ls2" (15665d7c-8d79-469c-8202-1a5d626ff297)  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 == "ls2-lr1"), action=(next;)
  table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport == "ls2-vm1" && eth.src == {00:00:00:00:00:03}), action=(next;)
  table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport == "ls2-vm2" && eth.src == {00:00:00:00:00:04}), action=(next;)
  table=1 (ls_in_port_sec_ip  ), priority=90   , match=(inport == "ls2-vm1" && eth.src == 00:00:00:00:00:03 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(next;)
  table=1 (ls_in_port_sec_ip  ), priority=90   , match=(inport == "ls2-vm1" && eth.src == 00:00:00:00:00:03 && ip4.src == {10.10.20.2}), action=(next;)
  table=1 (ls_in_port_sec_ip  ), priority=90   , match=(inport == "ls2-vm2" && eth.src == 00:00:00:00:00:04 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(next;)
  table=1 (ls_in_port_sec_ip  ), priority=90   , match=(inport == "ls2-vm2" && eth.src == 00:00:00:00:00:04 && ip4.src == {10.10.20.3}), action=(next;)
  table=1 (ls_in_port_sec_ip  ), priority=80   , match=(inport == "ls2-vm1" && eth.src == 00:00:00:00:00:03 && ip), action=(drop;)
  table=1 (ls_in_port_sec_ip  ), priority=80   , match=(inport == "ls2-vm2" && eth.src == 00:00:00:00:00:04 && ip), action=(drop;)
  table=1 (ls_in_port_sec_ip  ), priority=0    , match=(1), action=(next;)
  table=2 (ls_in_port_sec_nd  ), priority=90   , match=(inport == "ls2-vm1" && eth.src == 00:00:00:00:00:03 && arp.sha == 00:00:00:00:00:03 && arp.spa == {10.10.20.2}), action=(next;)
  table=2 (ls_in_port_sec_nd  ), priority=90   , match=(inport == "ls2-vm2" && eth.src == 00:00:00:00:00:04 && arp.sha == 00:00:00:00:00:04 && arp.spa == {10.10.20.3}), action=(next;)
  table=2 (ls_in_port_sec_nd  ), priority=80   , match=(inport == "ls2-vm1" && (arp || nd)), action=(drop;)
  table=2 (ls_in_port_sec_nd  ), priority=80   , match=(inport == "ls2-vm2" && (arp || nd)), action=(drop;)
  table=2 (ls_in_port_sec_nd  ), priority=0    , match=(1), action=(next;)
  table=3 (ls_in_lookup_fdb   ), priority=0    , match=(1), action=(next;)
  table=4 (ls_in_put_fdb      ), priority=0    , match=(1), action=(next;)
  table=5 (ls_in_pre_acl      ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(next;)
  table=5 (ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
  table=6 (ls_in_pre_lb       ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(next;)
  table=6 (ls_in_pre_lb       ), priority=110  , match=(ip && inport == "ls2-lr1"), action=(next;)
  table=6 (ls_in_pre_lb       ), priority=110  , match=(nd || nd_rs || nd_ra || mldv1 || mldv2), action=(next;)
  table=6 (ls_in_pre_lb       ), priority=0    , match=(1), action=(next;)
  table=7 (ls_in_pre_stateful ), priority=100  , match=(reg0[0] == 1), action=(ct_next;)
  table=7 (ls_in_pre_stateful ), priority=0    , match=(1), action=(next;)
  table=8 (ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
  table=9 (ls_in_acl          ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;)
  table=9 (ls_in_acl          ), priority=0    , match=(1), action=(next;)
  table=10(ls_in_qos_mark     ), priority=0    , match=(1), action=(next;)
  table=11(ls_in_qos_meter    ), priority=0    , match=(1), action=(next;)
  table=12(ls_in_lb           ), priority=0    , match=(1), action=(next;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[1] == 1), action=(ct_commit { ct_label.blocked = 0; }; next;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[2] == 1 && ip4 && sctp), action=(reg1 = ip4.dst; reg2[0..15] = sctp.dst; ct_lb;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[2] == 1 && ip4 && tcp), action=(reg1 = ip4.dst; reg2[0..15] = tcp.dst; ct_lb;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[2] == 1 && ip4 && udp), action=(reg1 = ip4.dst; reg2[0..15] = udp.dst; ct_lb;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[2] == 1 && ip6 && sctp), action=(xxreg1 = ip6.dst; reg2[0..15] = sctp.dst; ct_lb;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[2] == 1 && ip6 && tcp), action=(xxreg1 = ip6.dst; reg2[0..15] = tcp.dst; ct_lb;)
  table=13(ls_in_stateful     ), priority=100  , match=(reg0[2] == 1 && ip6 && udp), action=(xxreg1 = ip6.dst; reg2[0..15] = udp.dst; ct_lb;)
  table=13(ls_in_stateful     ), priority=0    , match=(1), action=(next;)
  table=14(ls_in_pre_hairpin  ), priority=0    , match=(1), action=(next;)
  table=15(ls_in_nat_hairpin  ), priority=0    , match=(1), action=(next;)
  table=16(ls_in_hairpin      ), priority=0    , match=(1), action=(next;)
  table=17(ls_in_arp_rsp      ), priority=100  , match=(arp.tpa == 10.10.20.2 && arp.op == 1 && inport == "ls2-vm1"), action=(next;)
  table=17(ls_in_arp_rsp      ), priority=100  , match=(arp.tpa == 10.10.20.3 && arp.op == 1 && inport == "ls2-vm2"), action=(next;)
  table=17(ls_in_arp_rsp      ), priority=50   , match=(arp.tpa == 10.10.20.2 && arp.op == 1), action=(eth.dst = eth.src; eth.src = 00:00:00:00:00:03; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 00:00:00:00:00:03; arp.tpa = arp.spa; arp.spa = 10.10.20.2; outport = inport; flags.loopback = 1; output;)
  table=17(ls_in_arp_rsp      ), priority=50   , match=(arp.tpa == 10.10.20.3 && arp.op == 1), action=(eth.dst = eth.src; eth.src = 00:00:00:00:00:04; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 00:00:00:00:00:04; arp.tpa = arp.spa; arp.spa = 10.10.20.3; outport = inport; flags.loopback = 1; output;)
  table=17(ls_in_arp_rsp      ), priority=0    , match=(1), action=(next;)
  table=18(ls_in_dhcp_options ), priority=100  , match=(inport == "ls2-vm1" && eth.src == 00:00:00:00:00:03 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(reg0[3] = put_dhcp_opts(offerip = 10.10.20.2, lease_time = 3600, netmask = 255.255.255.0, router = 10.10.20.1, server_id = 10.10.20.1); next;)
  table=18(ls_in_dhcp_options ), priority=100  , match=(inport == "ls2-vm1" && eth.src == 00:00:00:00:00:03 && ip4.src == 10.10.20.2 && ip4.dst == {10.10.20.1, 255.255.255.255} && udp.src == 68 && udp.dst == 67), action=(reg0[3] = put_dhcp_opts(offerip = 10.10.20.2, lease_time = 3600, netmask = 255.255.255.0, router = 10.10.20.1, server_id = 10.10.20.1); next;)
  table=18(ls_in_dhcp_options ), priority=100  , match=(inport == "ls2-vm2" && eth.src == 00:00:00:00:00:04 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(reg0[3] = put_dhcp_opts(offerip = 10.10.20.3, lease_time = 3600, netmask = 255.255.255.0, router = 10.10.20.1, server_id = 10.10.20.1); next;)
  table=18(ls_in_dhcp_options ), priority=100  , match=(inport == "ls2-vm2" && eth.src == 00:00:00:00:00:04 && ip4.src == 10.10.20.3 && ip4.dst == {10.10.20.1, 255.255.255.255} && udp.src == 68 && udp.dst == 67), action=(reg0[3] = put_dhcp_opts(offerip = 10.10.20.3, lease_time = 3600, netmask = 255.255.255.0, router = 10.10.20.1, server_id = 10.10.20.1); next;)
  table=18(ls_in_dhcp_options ), priority=0    , match=(1), action=(next;)
  table=19(ls_in_dhcp_response), priority=100  , match=(inport == "ls2-vm1" && eth.src == 00:00:00:00:00:03 && ip4 && udp.src == 68 && udp.dst == 67 && reg0[3]), action=(eth.dst = eth.src; eth.src = 00:00:00:00:00:02; ip4.src = 10.10.20.1; udp.src = 67; udp.dst = 68; outport = inport; flags.loopback = 1; output;)
  table=19(ls_in_dhcp_response), priority=100  , match=(inport == "ls2-vm2" && eth.src == 00:00:00:00:00:04 && ip4 && udp.src == 68 && udp.dst == 67 && reg0[3]), action=(eth.dst = eth.src; eth.src = 00:00:00:00:00:02; ip4.src = 10.10.20.1; udp.src = 67; udp.dst = 68; outport = inport; flags.loopback = 1; output;)
  table=19(ls_in_dhcp_response), priority=0    , match=(1), action=(next;)
  table=20(ls_in_dns_lookup   ), priority=0    , match=(1), action=(next;)
  table=21(ls_in_dns_response ), priority=0    , match=(1), action=(next;)
  table=22(ls_in_external_port), priority=0    , match=(1), action=(next;)
  table=23(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(handle_svc_check(inport);)
  table=23(ls_in_l2_lkup      ), priority=80   , match=(flags[1] == 0 && arp.op == 1 && arp.tpa == { 10.10.20.1}), action=(clone {outport = "ls2-lr1"; output; }; outport = "_MC_flood_l2"; output;)
  table=23(ls_in_l2_lkup      ), priority=80   , match=(flags[1] == 0 && nd_ns && nd.target == { fe80::200:ff:fe00:2}), action=(clone {outport = "ls2-lr1"; output; }; outport = "_MC_flood_l2"; output;)
  table=23(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {00:00:00:00:00:02} && (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood_l2"; output;)
  table=23(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = "_MC_flood"; output;)
  table=23(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "ls2-lr1"; output;)
  table=23(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:03), action=(outport = "ls2-vm1"; output;)
  table=23(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:04), action=(outport = "ls2-vm2"; output;)
  table=23(ls_in_l2_lkup      ), priority=0    , match=(1), action=(outport = get_fdb(eth.dst); next;)
  table=24(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), action=(drop;)
  table=24(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
Datapath: "ls2" (15665d7c-8d79-469c-8202-1a5d626ff297)  Pipeline: egress
  table=0 (ls_out_pre_lb      ), priority=110  , match=(eth.src == $svc_monitor_mac), action=(next;)
  table=0 (ls_out_pre_lb      ), priority=110  , match=(ip && outport == "ls2-lr1"), action=(next;)
  table=0 (ls_out_pre_lb      ), priority=110  , match=(nd || nd_rs || nd_ra || mldv1 || mldv2), action=(next;)
  table=0 (ls_out_pre_lb      ), priority=0    , match=(1), action=(next;)
  table=1 (ls_out_pre_acl     ), priority=110  , match=(eth.src == $svc_monitor_mac), 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_hint    ), priority=0    , match=(1), action=(next;)
  table=5 (ls_out_acl         ), priority=34000, match=(eth.src == $svc_monitor_mac), action=(next;)
  table=5 (ls_out_acl         ), priority=34000, match=(outport == "ls2-vm1" && eth.src == 00:00:00:00:00:02 && ip4.src == 10.10.20.1 && udp && udp.src == 67 && udp.dst == 68), action=(next;)
  table=5 (ls_out_acl         ), priority=34000, match=(outport == "ls2-vm2" && eth.src == 00:00:00:00:00:02 && ip4.src == 10.10.20.1 && udp && udp.src == 67 && udp.dst == 68), action=(next;)
  table=5 (ls_out_acl         ), priority=0    , match=(1), action=(next;)
  table=6 (ls_out_qos_mark    ), priority=0    , match=(1), action=(next;)
  table=7 (ls_out_qos_meter   ), priority=0    , match=(1), action=(next;)
  table=8 (ls_out_stateful    ), priority=100  , match=(reg0[1] == 1), action=(ct_commit { ct_label.blocked = 0; }; next;)
  table=8 (ls_out_stateful    ), priority=100  , match=(reg0[2] == 1), action=(ct_lb;)
  table=8 (ls_out_stateful    ), priority=0    , match=(1), action=(next;)
  table=9 (ls_out_port_sec_ip ), priority=90   , match=(outport == "ls2-vm1" && eth.dst == 00:00:00:00:00:03 && ip4.dst == {255.255.255.255, 224.0.0.0/4, 10.10.20.2}), action=(next;)
  table=9 (ls_out_port_sec_ip ), priority=90   , match=(outport == "ls2-vm2" && eth.dst == 00:00:00:00:00:04 && ip4.dst == {255.255.255.255, 224.0.0.0/4, 10.10.20.3}), action=(next;)
  table=9 (ls_out_port_sec_ip ), priority=80   , match=(outport == "ls2-vm1" && eth.dst == 00:00:00:00:00:03 && ip), action=(drop;)
  table=9 (ls_out_port_sec_ip ), priority=80   , match=(outport == "ls2-vm2" && eth.dst == 00:00:00:00:00:04 && ip), action=(drop;)
  table=9 (ls_out_port_sec_ip ), priority=0    , match=(1), action=(next;)
  table=10(ls_out_port_sec_l2 ), priority=100  , match=(eth.mcast), action=(output;)
  table=10(ls_out_port_sec_l2 ), priority=50   , match=(outport == "ls2-lr1"), action=(output;)
  table=10(ls_out_port_sec_l2 ), priority=50   , match=(outport == "ls2-vm1" && eth.dst == {00:00:00:00:00:03}), action=(output;)
  table=10(ls_out_port_sec_l2 ), priori

也可参考:ovn 配置逻辑路由器实现三层转发 - 简书 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Open Virtual Network(OVN)是建立在Open vSwitch(OVS)之上的虚拟网络解决方案。OVN通过OVS提供的网络转发和流量处理功能来实现网络通信。 OVN和OVS之间的通信是通过Northbound、Southbound和Southbound数据库实现的。 1. Northbound:Northbound是OVN和外部管理平面之间的接口。外部管理平面可以是OpenStack、Kubernetes等云管理平台或其他管理工具。通过Northbound接口,管理平面可以向OVN提供逻辑网络配置(如逻辑交换机、逻辑端口等),并获取网络状态和统计数据。 2. Southbound:Southbound是OVN和底层网络设备之间的接口。底层网络设备可以是物理交换机、虚拟交换机等。通过Southbound接口,OVN可以向底层网络设备下发流表规则,以实现逻辑网络的转发和流量处理。 3. Southbound数据库:Southbound数据库是一个存储底层网络设备状态和配置信息的数据库。OVN使用Southbound数据库来同步逻辑网络配置和底层网络设备状态。Southbound数据库可以是OVSDB(Open vSwitch Database)或其他兼容的数据库。 具体通信流程如下: 1. 外部管理平面通过Northbound接口将逻辑网络配置写入OVN控制器。 2. OVN控制器将逻辑网络配置存储在自己的数据库中。 3. OVN控制器将逻辑网络配置转换为OVS的规则,并将其下发到相应的OVS交换机上。 4. OVS交换机根据收到的规则进行数据包的转发和流量处理。 5. OVS交换机将处理后的数据包发送到目标主机或底层网络设备。 以上是OVN和OVS之间通信的基本流程。通过这种方式,OVN实现了对逻辑网络的管理和控制,而OVS提供了实际的网络转发和流量处理功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值