return;
}
@@ -9466,8 +9567,6 @@ build_lswitch_ip_unicast_lookup(struct ovn_port *op,
"outport = \""MC_UNKNOWN "\"; output;"
: "outport = %s; output;")
: debug_drop_action();
- ds_clear(actions);
- ds_put_format(actions, action, op->json_key);
if (lsp_is_router(op->nbsp) && op->peer && op->peer->nbrp) {
/* For ports connected to logical routers add flows to bypass the
@@ -9514,14 +9613,35 @@ build_lswitch_ip_unicast_lookup(struct ovn_port *op,
if (add_chassis_resident_check) {
ds_put_format(match, " && is_chassis_resident(%s)", json_key);
}
+ } else if (op->cr_port) {
+ ds_clear(actions);
+ ds_put_format(actions, action, op->cr_port->json_key);
+
+ struct ds m = DS_EMPTY_INITIALIZER;
+ ds_put_format(&m, "eth.dst == %s && !is_chassis_resident(%s)",
+ op->peer->lrp_networks.ea_s,
+ op->cr_port->json_key);
+
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_L2_LKUP, 50,
+ ds_cstr(&m), ds_cstr(actions),
+ &op->nbsp->header_,
+ op->lflow_ref);
+ ds_destroy(&m);
+ ds_put_format(match, " && is_chassis_resident(%s)",
+ op->cr_port->json_key);
}
+ ds_clear(actions);
+ ds_put_format(actions, action, op->json_key);
ovn_lflow_add_with_hint(lflows, op->od,
S_SWITCH_IN_L2_LKUP, 50,
ds_cstr(match), ds_cstr(actions),
&op->nbsp->header_,
op->lflow_ref);
} else {
+ ds_clear(actions);
+ ds_put_format(actions, action, op->json_key);
for (size_t i = 0; i < op->n_lsp_addrs; i++) {
ds_clear(match);
ds_put_format(match, "eth.dst == %s", op->lsp_addrs[i].ea_s);
@@ -11619,6 +11739,15 @@ build_lrouter_port_nat_arp_nd_flow(struct ovn_port *op,
return;
}
+ if (op->peer && op->peer->cr_port) {
+ /* We don't add the below flows if the router port's peer has
+ * a chassisresident port. That's because routing is centralized on
+ * the gateway chassis for the traffic from the peer port to this
+ * router or from this router to the peer logical switch.
+ */
+ return;
+ }
+
/* Mac address to use when replying to ARP/NS. */
const char *mac_s = REG_INPORT_ETH_ADDR;
struct eth_addr mac;
@@ -14852,6 +14981,17 @@ lrouter_check_nat_entry(const struct ovn_datapath *od,
/* For distributed router NAT, determine whether this NAT rule
* satisfies the conditions for distributed NAT processing. */
*distributed = false;
+
+ /* NAT cannnot be distributed if the gateway port's peer
+ * has a chassisresident port (and the routing is centralized
+ * on the gateway chassis for the traffic from the peer
+ * to this router and traffic to the peer.)
+ */
+ struct ovn_port *l3dgw_port = *nat_l3dgw_port;
+ if (l3dgw_port && l3dgw_port->peer && l3dgw_port->peer->cr_port) {
+ return 0;
+ }
+
if (od->n_l3dgw_ports && !strcmp(nat->type, "dnat_and_snat") &&
nat->logical_port && nat->external_mac) {
if (eth_addr_from_string(nat->external_mac, mac)) {
diff --git a/northd/northd.h b/northd/northd.h
index 18cad5234a..dad3a77673 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -325,6 +325,7 @@ struct ovn_datapath {
* will be NULL. */
struct ovn_port **l3dgw_ports;
size_t n_l3dgw_ports;
+ size_t n_allocated_l3dgw_ports;
/* router datapath has a logical port with redirect-type set to bridged. */
bool redirect_bridged;
diff --git a/tests/multinode-macros.at b/tests/multinode-macros.at
index c04506a52a..25cfa186ee 100644
--- a/tests/multinode-macros.at
+++ b/tests/multinode-macros.at
@@ -66,7 +66,7 @@ m_count_rows() {
m_check_row_count() {
local db=$(parse_db $1) table=$(parse_table $1); shift
local count=$1; shift
- local found=$(m_count_rows $c $db:$table "$@")
+ local found=$(m_count_rows $db:$table "$@")
echo
echo "Checking for $count rows in $db $table${1+ with $*}... found $found"
if test "$count" != "$found"; then
diff --git a/tests/multinode.at b/tests/multinode.at
index b959a25506..d549bedd66 100644
--- a/tests/multinode.at
+++ b/tests/multinode.at
@@ -890,4 +890,181 @@ M_NS_CHECK_EXEC([ovn-chassis-1], [sw0p1], [ping -q -c 3
-i 0.3 -w 2 172.20.1.2 |
M_NS_CHECK_EXEC([ovn-chassis-1], [sw0p1], [ping -c 20 -i 0.5 -s 1300 -M do 172.20.1.2 2>&1 |grep -q "mtu = 1150"])
+# Reset back to geneve tunnels
+for c in ovn-chassis-1 ovn-chassis-2 ovn-gw-1
+do
+ m_as $c ovs-vsctl set open . external-ids:ovn-encap-type=geneve
+done
+
+AT_CLEANUP
+
+AT_SETUP([ovn multinode NAT on a provider network with no localnet ports])
+
+# Check that ovn-fake-multinode setup is up and running
+check_fake_multinode_setup
+
+# Delete the multinode NB and OVS resources before starting the test.
+cleanup_multinode_resources
+
+check multinode_nbctl ls-add sw0
+check multinode_nbctl lsp-add sw0 sw0-port1
+check multinode_nbctl lsp-set-addresses sw0-port1 "50:54:00:00:00:03 10.0.0.3
1000::3"
+check multinode_nbctl lsp-add sw0 sw0-port2
+check multinode_nbctl lsp-set-addresses sw0-port2 "50:54:00:00:00:04 10.0.0.4
1000::4"
+
+m_as ovn-chassis-1 /data/create_fake_vm.sh sw0-port1 sw0p1 50:54:00:00:00:03
10.0.0.3 24 10.0.0.1 1000::3/64 1000::a
+m_as ovn-chassis-2 /data/create_fake_vm.sh sw0-port2 sw0p2 50:54:00:00:00:04
10.0.0.4 24 10.0.0.1 1000::4/64 1000::a
+
+m_wait_for_ports_up
+
+M_NS_CHECK_EXEC([ovn-chassis-1], [sw0p1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.4 |
FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+# Create the second logical switch with one port
+check multinode_nbctl ls-add sw1
+check multinode_nbctl lsp-add sw1 sw1-port1
+check multinode_nbctl lsp-set-addresses sw1-port1 "40:54:00:00:00:03 20.0.0.3
2000::3"
+
+# Create a logical router and attach both logical switches
+check multinode_nbctl lr-add lr0
+check multinode_nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
1000::a/64
+check multinode_nbctl lsp-add sw0 sw0-lr0
+check multinode_nbctl lsp-set-type sw0-lr0 router
+check multinode_nbctl lsp-set-addresses sw0-lr0 router
+check multinode_nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
+
+check multinode_nbctl lrp-add lr0 lr0-sw1 00:00:00:00:ff:02 20.0.0.1/24
2000::a/64
+check multinode_nbctl lsp-add sw1 sw1-lr0
+check multinode_nbctl lsp-set-type sw1-lr0 router
+check multinode_nbctl lsp-set-addresses sw1-lr0 router
+check multinode_nbctl lsp-set-options sw1-lr0 router-port=lr0-sw1
+
+m_as ovn-chassis-2 /data/create_fake_vm.sh sw1-port1 sw1p1 40:54:00:00:00:03
20.0.0.3 24 20.0.0.1 2000::3/64 2000::a
+
+# create exteranl connection for N/S traffic
+check multinode_nbctl ls-add public
+check multinode_nbctl lsp-add public ln-public
+check multinode_nbctl lsp-set-type ln-public localnet
+check multinode_nbctl lsp-set-addresses ln-public unknown
+check multinode_nbctl lsp-set-options ln-public network_name=public
+
+check multinode_nbctl lrp-add lr0 lr0-public 00:11:22:00:ff:01 172.20.0.100/24
+check multinode_nbctl lsp-add public public-lr0
+check multinode_nbctl lsp-set-type public-lr0 router
+check multinode_nbctl lsp-set-addresses public-lr0 router
+check multinode_nbctl lsp-set-options public-lr0 router-port=lr0-public
+check multinode_nbctl lrp-set-gateway-chassis lr0-public ovn-gw-1 10
+
+check multinode_nbctl lr-nat-add lr0 dnat_and_snat 172.20.0.110 10.0.0.3
sw0-port1 30:54:00:00:00:03
+check multinode_nbctl lr-nat-add lr0 dnat_and_snat 172.20.0.120 20.0.0.3
+check multinode_nbctl lr-nat-add lr0 snat 172.20.0.100 10.0.0.0/24
+check multinode_nbctl lr-nat-add lr0 snat 172.20.0.100 20.0.0.0/24
+
+# Create a logical port pub-p1 and bind it in ovn-chassis-1
+check multinode_nbctl lsp-add public public-port1
+check multinode_nbctl lsp-set-addresses public-port1 "60:54:00:00:00:03
172.168.0.50"
+
+m_as ovn-chassis-1 /data/create_fake_vm.sh public-port1 pubp1
60:54:00:00:00:03 172.20.0.50 24 172.20.0.100
+
+check multinode_nbctl --wait=hv sync
+
+# First do basic ping tests before deleting the localnet port - ln-public.
+# Once the localnet port is deleted from public ls, routing for 172.20.0.0/24
+# is centralized on ovn-gw-1.
+
+# This function checks the North-South traffic.
+run_ns_traffic() {
+ M_NS_CHECK_EXEC([ovn-chassis-1], [pubp1], [arp -d 172.20.0.110], [ignore],
[ignore])
+ M_NS_CHECK_EXEC([ovn-chassis-1], [pubp1], [arp -d 172.20.0.120], [ignore],
[ignore])
+
+ M_NS_CHECK_EXEC([ovn-chassis-1], [sw0p1], [ping -q -c 3 -i 0.3 -w 2
172.20.0.100 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+ M_NS_CHECK_EXEC([ovn-chassis-1], [sw0p1], [ping -q -c 3 -i 0.3 -w 2
172.20.0.110 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+ M_NS_CHECK_EXEC([ovn-chassis-1], [sw0p1], [ping -q -c 3 -i 0.3 -w 2
172.20.0.120 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+ M_NS_CHECK_EXEC([ovn-chassis-1], [sw0p1], [ping -q -c 3 -i 0.3 -w 2
172.20.0.50 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+ M_NS_CHECK_EXEC([ovn-chassis-2], [sw1p1], [ping -q -c 3 -i 0.3 -w 2
172.20.0.50 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+ # Now ping from pubp1 to 172.20.0.100, 172.20.0.110, 172.20.0.120, 10.0.0.3
and 20.0.0.3
+ M_NS_CHECK_EXEC([ovn-chassis-1], [pubp1], [ping -q -c 3 -i 0.3 -w 2
172.20.0.100 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+ M_NS_CHECK_EXEC([ovn-chassis-1], [pubp1], [ping -q -c 3 -i 0.3 -w 2
172.20.0.110 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+ M_NS_CHECK_EXEC([ovn-chassis-1], [pubp1], [ping -q -c 3 -i 0.3 -w 2
172.20.0.120 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+ M_NS_CHECK_EXEC([ovn-chassis-1], [pubp1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.3
| FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+ M_NS_CHECK_EXEC([ovn-chassis-1], [pubp1], [ping -q -c 3 -i 0.3 -w 2 20.0.0.3
| FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+}
+
+# Test out the N-S traffic.
+run_ns_traffic
+
+# Delete the localnet port by changing the type of ln-public to VIF port.
+check multinode_nbctl --wait=hv lsp-set-type ln-public ""
+
+# cr-port should not be created for public-lr0 since the option
+# overlay_provider_network=true is not yet set for public.
+m_check_row_count Port_Binding 0 logical_port=cr-public-lr0
+
+# Set the option now.
+check multinode_nbctl --wait=hv set logical_switch public
other_config:overlay_provider_network=true
+
+m_check_row_count Port_Binding 1 logical_port=cr-public-lr0
+m_check_column chassisredirect Port_Binding type logical_port=cr-public-lr0
+
+# Test out the N-S traffic.
+run_ns_traffic
+
+# Re-add the localnet port
+check multinode_nbctl --wait=hv lsp-set-type ln-public localnet
+
+m_check_row_count Port_Binding 0 logical_port=cr-public-lr0
+
+# Test out the N-S traffic.
+run_ns_traffic
+
+# Delete the ln-public port this time.
+check multinode_nbctl --wait=hv lsp-del ln-public
+
+m_check_row_count Port_Binding 1 logical_port=cr-public-lr0
+m_check_column chassisredirect Port_Binding type logical_port=cr-public-lr0
+
+# Test out the N-S traffic.
+run_ns_traffic
+
AT_CLEANUP
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 3d944a3aef..451e57d61d 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -2061,7 +2061,7 @@ match=(inport == "lrp-public" && nd_ns && nd.target ==
\$${lb_as_v6}), dnl
action=(nd_na { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll =
xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };)
])
-# xreg0[0..47] isn't used anywhere else.
+# xreg0[[0..47]] isn't used anywhere else.
AT_CHECK([ovn-sbctl lflow-list | grep "xreg0\[[0..47\]]" | grep -vE
'lr_in_admission|lr_in_ip_input'], [1], [])
# Test chassis redirect port.
@@ -2089,7 +2089,7 @@ action=(xreg0[[0..47]] = 00:00:00:00:01:00; next;)
])
# Ingress router port is used for ARP reply/NA in lr_in_ip_input.
-# xxreg0[0..47] is used unless external_mac is set.
+# xxreg0[[0..47]] is used unless external_mac is set.
# Priority 90 flows (per router).
AT_CHECK_UNQUOTED([ovn-sbctl lflow-list | grep -E "lr_in_ip_input.*priority=90" | grep
"arp\|nd" | ovn_strip_lflows], [0], [dnl
table=??(lr_in_ip_input ), priority=90 , dnl
@@ -2164,7 +2164,7 @@ match=(inport == "lrp-public" && arp.op == 1 && arp.tpa ==
43.43.43.4 && is_chas
action=(eth.dst = eth.src; eth.src = 00:00:00:00:00:02; arp.op = 2; /* ARP reply */
arp.tha = arp.sha; arp.sha = 00:00:00:00:00:02; arp.tpa <-> arp.spa; outport =
inport; flags.loopback = 1; output;)
])
-# xreg0[0..47] isn't used anywhere else.
+# xreg0[[0..47]] isn't used anywhere else.
AT_CHECK([ovn-sbctl lflow-list | grep "xreg0\[[0..47\]]" | grep -vE
'lr_in_admission|lr_in_ip_input'], [1], [])
AT_CLEANUP
@@ -5434,13 +5434,14 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | grep
"192.168.4.100" | grep "_MC_flo
AS_BOX([Configuring ro1-ls1 router port as a gateway router port])
-ovn-nbctl --wait=sb lrp-set-gateway-chassis ro1-ls1 chassis-1 30
+check ovn-nbctl lrp-set-gateway-chassis ro1-ls1 chassis-1 30
+check ovn-nbctl --wait=sb lsp-add ls1 ln-ls1 -- lsp-set-type ln-ls1 localnet
ovn-sbctl lflow-list ls1 > ls1_lflows
AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | ovn_strip_lflows], [0], [dnl
table=??(ls_in_l2_lkup ), priority=0 , match=(1), action=(outport =
get_fdb(eth.dst); next;)
table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst == $svc_monitor_mac
&& (tcp || icmp || icmp6)), action=(handle_svc_check(inport);)
- table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:01),
action=(outport = "ls1-ro1"; output;)
+ table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:01 &&
is_chassis_resident("cr-ro1-ls1")), action=(outport = "ls1-ro1"; output;)
table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:01:02),
action=(outport = "vm1"; output;)
table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport =
"_MC_flood"; output;)
table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src == {00:00:00:00:01:01}
&& (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = "_MC_flood_l2";
output;)
@@ -12435,3 +12436,512 @@ check_engine_stats northd recompute nocompute
check_engine_stats lflow recompute nocompute
AT_CLEANUP
+
+OVN_FOR_EACH_NORTHD_NO_HV([
+AT_SETUP([NAT on a provider network with no localnet ports])
+AT_KEYWORDS([dnat])
+ovn_start
+
+check ovn-nbctl -- ls-add sw0 -- ls-add sw1
+check ovn-nbctl lsp-add sw0 sw0-port1
+check ovn-nbctl lr-add lr0
+check ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
+check ovn-nbctl lsp-add sw0 sw0-lr0
+check ovn-nbctl lsp-set-type sw0-lr0 router
+check ovn-nbctl lsp-set-addresses sw0-lr0 00:00:00:00:ff:01
+check ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
+
+check ovn-nbctl lrp-add lr0 lr0-sw1 00:00:00:00:ff:03 20.0.0.1/24
+check ovn-nbctl lsp-add sw1 sw1-lr0
+check ovn-nbctl lsp-set-type sw1-lr0 router
+check ovn-nbctl lsp-set-addresses sw1-lr0 router
+check ovn-nbctl lsp-set-options sw1-lr0 router-port=lr0-sw1
+
+check ovn-sbctl chassis-add gw1 geneve 127.0.0.1
+check ovn-nbctl ls-add public
+check ovn-nbctl lsp-add public pub-p1
+
+# localnet port
+check ovn-nbctl lsp-add public ln-public
+check ovn-nbctl lsp-set-type ln-public localnet
+check ovn-nbctl lsp-set-addresses ln-public unknown
+check ovn-nbctl lsp-set-options ln-public network_name=public
+
+check ovn-nbctl lrp-add lr0 lr0-public 00:00:00:00:ff:02 172.168.0.10/24
+check ovn-nbctl lrp-set-gateway-chassis lr0-public gw1
+
+check ovn-nbctl lsp-add public public-lr0
+check ovn-nbctl lsp-set-type public-lr0 router
+check ovn-nbctl lsp-set-addresses public-lr0 router
+check ovn-nbctl lsp-set-options public-lr0 router-port=lr0-public
+
+check ovn-nbctl lr-nat-add lr0 dnat_and_snat 172.168.0.110 10.0.0.3 sw0-port1
30:54:00:00:00:03
+check ovn-nbctl lr-nat-add lr0 dnat_and_snat 172.168.0.120 20.0.0.3
+check ovn-nbctl lr-nat-add lr0 snat 172.168.0.100 10.0.0.0/24
+check ovn-nbctl lr-nat-add lr0 snat 172.168.0.100 20.0.0.0/24
+
+check ovn-nbctl --wait=sb sync
+
+check_flows_no_cr_port_for_public_lr0() {
+ # check that there is no port binding cr-public-lr0
+ check_row_count Port_Binding 0 logical_port=cr-public-lr0
+
+ ovn-sbctl dump-flows lr0 > lr0flows
+ ovn-sbctl dump-flows public > publicflows
+
+AT_CHECK([grep "lr_in_admission" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_admission ), priority=0 , match=(1), action=(drop;)
+ table=??(lr_in_admission ), priority=100 , match=(vlan.present ||
eth.src[[40]]), action=(drop;)
+ table=??(lr_in_admission ), priority=110 , match=(((ip4 && icmp4.type == 3 && icmp4.code == 4)
|| (ip6 && icmp6.type == 2 && icmp6.code == 0)) && flags.tunnel_rx == 1), action=(drop;)
+ table=??(lr_in_admission ), priority=120 , match=(((ip4 && icmp4.type == 3 && icmp4.code == 4) || (ip6 && icmp6.type == 2
&& icmp6.code == 0)) && eth.dst == 00:00:00:00:ff:02 && !is_chassis_resident("cr-lr0-public") && flags.tunnel_rx == 1),
action=(outport <-> inport; inport = "lr0-public"; next;)
+ table=??(lr_in_admission ), priority=50 , match=(eth.dst == 00:00:00:00:ff:01 &&
inport == "lr0-sw0"), action=(xreg0[[0..47]] = 00:00:00:00:ff:01; next;)
+ table=??(lr_in_admission ), priority=50 , match=(eth.dst == 00:00:00:00:ff:02 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(xreg0[[0..47]] =
00:00:00:00:ff:02; next;)
+ table=??(lr_in_admission ), priority=50 , match=(eth.dst == 00:00:00:00:ff:03 &&
inport == "lr0-sw1"), action=(xreg0[[0..47]] = 00:00:00:00:ff:03; next;)
+ table=??(lr_in_admission ), priority=50 , match=(eth.dst == 30:54:00:00:00:03 && inport ==
"lr0-public" && is_chassis_resident("sw0-port1")), action=(xreg0[[0..47]] =
00:00:00:00:ff:02; next;)
+ table=??(lr_in_admission ), priority=50 , match=(eth.mcast && inport ==
"lr0-public"), action=(xreg0[[0..47]] = 00:00:00:00:ff:02; next;)
+ table=??(lr_in_admission ), priority=50 , match=(eth.mcast && inport ==
"lr0-sw0"), action=(xreg0[[0..47]] = 00:00:00:00:ff:01; next;)
+ table=??(lr_in_admission ), priority=50 , match=(eth.mcast && inport ==
"lr0-sw1"), action=(xreg0[[0..47]] = 00:00:00:00:ff:03; next;)
+])
+
+AT_CHECK([grep "lr_in_ip_input" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_ip_input ), priority=0 , match=(1), action=(next;)
+ table=??(lr_in_ip_input ), priority=100 , match=(ip4.src == {10.0.0.1,
10.0.0.255} && reg9[[0]] == 0), action=(drop;)
+ table=??(lr_in_ip_input ), priority=100 , match=(ip4.src == {172.168.0.10,
172.168.0.255} && reg9[[0]] == 0), action=(drop;)
+ table=??(lr_in_ip_input ), priority=100 , match=(ip4.src == {20.0.0.1,
20.0.0.255} && reg9[[0]] == 0), action=(drop;)
+ table=??(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=??(lr_in_ip_input ), priority=100 , match=(ip6.dst == fe80::200:ff:fe00:ff01
&& udp.src == 547 && udp.dst == 546), action=(reg0 = 0; handle_dhcpv6_reply;)
+ table=??(lr_in_ip_input ), priority=100 , match=(ip6.dst == fe80::200:ff:fe00:ff02
&& udp.src == 547 && udp.dst == 546), action=(reg0 = 0; handle_dhcpv6_reply;)
+ table=??(lr_in_ip_input ), priority=100 , match=(ip6.dst == fe80::200:ff:fe00:ff03
&& udp.src == 547 && udp.dst == 546), action=(reg0 = 0; handle_dhcpv6_reply;)
+ table=??(lr_in_ip_input ), priority=120 , match=(inport == "lr0-public"
&& ip4.src == 172.168.0.100), action=(next;)
+ table=??(lr_in_ip_input ), priority=30 , match=(ip.ttl == {0, 1}),
action=(drop;)
+ table=??(lr_in_ip_input ), priority=31 , match=(inport == "lr0-public" && 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 ; ip.ttl = 254; outport = "lr0-public"; flags.loopback = 1; output; };)
+ table=??(lr_in_ip_input ), priority=31 , match=(inport == "lr0-sw0" && 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.0.0.1 ; ip.ttl = 254; outport = "lr0-sw0"; flags.loopback = 1;
output; };)
+ table=??(lr_in_ip_input ), priority=31 , match=(inport == "lr0-sw1" && 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 = 20.0.0.1 ; ip.ttl = 254; outport = "lr0-sw1"; flags.loopback = 1;
output; };)
+ table=??(lr_in_ip_input ), priority=32 , match=(ip.ttl == {0, 1} &&
!ip.later_frag && (ip4.mcast || ip6.mcast)), action=(drop;)
+ table=??(lr_in_ip_input ), priority=50 , match=(eth.bcast),
action=(drop;)
+ table=??(lr_in_ip_input ), priority=60 , match=(ip4.dst ==
{10.0.0.1}), action=(drop;)
+ table=??(lr_in_ip_input ), priority=60 , match=(ip4.dst ==
{172.168.0.10}), action=(drop;)
+ table=??(lr_in_ip_input ), priority=60 , match=(ip4.dst ==
{20.0.0.1}), action=(drop;)
+ table=??(lr_in_ip_input ), priority=60 , match=(ip6.dst ==
{fe80::200:ff:fe00:ff01}), action=(drop;)
+ table=??(lr_in_ip_input ), priority=60 , match=(ip6.dst ==
{fe80::200:ff:fe00:ff02}), action=(drop;)
+ table=??(lr_in_ip_input ), priority=60 , match=(ip6.dst ==
{fe80::200:ff:fe00:ff03}), action=(drop;)
+ table=??(lr_in_ip_input ), priority=82 , match=(ip4.mcast ||
ip6.mcast), action=(drop;)
+ table=??(lr_in_ip_input ), priority=83 , match=(ip6.mcast_rsvd),
action=(drop;)
+ table=??(lr_in_ip_input ), priority=84 , match=(nd_rs || nd_ra),
action=(next;)
+ table=??(lr_in_ip_input ), priority=85 , match=(arp || nd),
action=(drop;)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.100), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.110), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.120), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(inport == "lr0-public" && arp.op == 1 && arp.tpa ==
172.168.0.10 && arp.spa == 172.168.0.0/24 && is_chassis_resident("cr-lr0-public")), 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; outport =
inport; flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(inport == "lr0-public" && ip6.dst ==
{fe80::200:ff:fe00:ff02, ff02::1:ff00:ff02} && nd_ns && nd.target == fe80::200:ff:fe00:ff02 &&
is_chassis_resident("cr-lr0-public")), action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll =
xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };)
+ table=??(lr_in_ip_input ), priority=90 , match=(inport == "lr0-sw0" && arp.op == 1
&& arp.tpa == 10.0.0.1 && arp.spa == 10.0.0.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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(inport == "lr0-sw0" && ip6.dst ==
{fe80::200:ff:fe00:ff01, ff02::1:ff00:ff01} && nd_ns && nd.target == fe80::200:ff:fe00:ff01),
action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll = xreg0[[0..47]]; outport = inport;
flags.loopback = 1; output; };)
+ table=??(lr_in_ip_input ), priority=90 , match=(inport == "lr0-sw1" && arp.op == 1
&& arp.tpa == 20.0.0.1 && arp.spa == 20.0.0.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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(inport == "lr0-sw1" && ip6.dst ==
{fe80::200:ff:fe00:ff03, ff02::1:ff00:ff03} && nd_ns && nd.target == fe80::200:ff:fe00:ff03),
action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll = xreg0[[0..47]]; outport = inport;
flags.loopback = 1; output; };)
+ table=??(lr_in_ip_input ), priority=90 , match=(ip4.dst == 10.0.0.1 && icmp4.type ==
8 && icmp4.code == 0), action=(ip4.dst <-> ip4.src; ip.ttl = 255; icmp4.type = 0;
flags.loopback = 1; next; )
+ table=??(lr_in_ip_input ), priority=90 , match=(ip4.dst == 172.168.0.10 &&
icmp4.type == 8 && icmp4.code == 0), action=(ip4.dst <-> ip4.src; ip.ttl = 255;
icmp4.type = 0; flags.loopback = 1; next; )
+ table=??(lr_in_ip_input ), priority=90 , match=(ip4.dst == 20.0.0.1 && icmp4.type ==
8 && icmp4.code == 0), action=(ip4.dst <-> ip4.src; ip.ttl = 255; icmp4.type = 0;
flags.loopback = 1; next; )
+ table=??(lr_in_ip_input ), priority=90 , match=(ip6.dst == fe80::200:ff:fe00:ff01 &&
icmp6.type == 128 && icmp6.code == 0), action=(ip6.dst <-> ip6.src; ip.ttl = 255;
icmp6.type = 129; flags.loopback = 1; next; )
+ table=??(lr_in_ip_input ), priority=90 , match=(ip6.dst == fe80::200:ff:fe00:ff02 &&
icmp6.type == 128 && icmp6.code == 0), action=(ip6.dst <-> ip6.src; ip.ttl = 255;
icmp6.type = 129; flags.loopback = 1; next; )
+ table=??(lr_in_ip_input ), priority=90 , match=(ip6.dst == fe80::200:ff:fe00:ff03 &&
icmp6.type == 128 && icmp6.code == 0), action=(ip6.dst <-> ip6.src; ip.ttl = 255;
icmp6.type = 129; flags.loopback = 1; next; )
+ table=??(lr_in_ip_input ), priority=91 , match=(inport == "lr0-public" &&
arp.op == 1 && arp.tpa == 172.168.0.100), action=(drop;)
+ table=??(lr_in_ip_input ), priority=91 , match=(inport == "lr0-public" &&
arp.op == 1 && arp.tpa == 172.168.0.110), action=(drop;)
+ table=??(lr_in_ip_input ), priority=91 , match=(inport == "lr0-public" &&
arp.op == 1 && arp.tpa == 172.168.0.120), action=(drop;)
+ table=??(lr_in_ip_input ), priority=92 , match=(inport == "lr0-public" && arp.op == 1 &&
arp.tpa == 172.168.0.100 && is_chassis_resident("cr-lr0-public")), 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; outport =
inport; flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=92 , match=(inport == "lr0-public" && arp.op == 1 &&
arp.tpa == 172.168.0.110 && is_chassis_resident("sw0-port1")), action=(eth.dst = eth.src; eth.src =
30:54:00:00:00:03; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 30:54:00:00:00:03; arp.tpa <-> arp.spa; outport
= inport; flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=92 , match=(inport == "lr0-public" && arp.op == 1 &&
arp.tpa == 172.168.0.120 && is_chassis_resident("cr-lr0-public")), 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; outport =
inport; flags.loopback = 1; output;)
+])
+
+AT_CHECK([grep "lr_in_unsnat" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_unsnat ), priority=0 , match=(1), action=(next;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.100 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.110
&& inport == "lr0-public"), action=(ct_snat;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.120 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;)
+])
+
+AT_CHECK([grep "lr_in_defrag" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_defrag ), priority=0 , match=(1), action=(next;)
+])
+
+AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;)
+ table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.110
&& inport == "lr0-public"), action=(ct_dnat(10.0.0.3);)
+ table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.120 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(20.0.0.3);)
+])
+
+AT_CHECK([grep "lr_in_arp_resolve" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_arp_resolve ), priority=0 , match=(1), action=(drop;)
+ table=??(lr_in_arp_resolve ), priority=1 , match=(ip4),
action=(get_arp(outport, reg0); next;)
+ table=??(lr_in_arp_resolve ), priority=1 , match=(ip6),
action=(get_nd(outport, xxreg0); next;)
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.100), action=(eth.dst = 00:00:00:00:ff:02; next;)
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.110), action=(eth.dst = 30:54:00:00:00:03; next;)
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.120), action=(eth.dst = 00:00:00:00:ff:02; next;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.100), action=(drop;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.110), action=(drop;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.120), action=(drop;)
+ table=??(lr_in_arp_resolve ), priority=500 , match=(ip4.mcast ||
ip6.mcast), action=(next;)
+])
+
+AT_CHECK([grep "lr_in_gw_redirect" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_gw_redirect ), priority=0 , match=(1), action=(next;)
+ table=??(lr_in_gw_redirect ), priority=100 , match=(ip4.src == 10.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("sw0-port1")), action=(eth.src = 30:54:00:00:00:03;
reg1 = 172.168.0.110; next;)
+ table=??(lr_in_gw_redirect ), priority=50 , match=(outport == "lr0-public"),
action=(outport = "cr-lr0-public"; next;)
+])
+
+AT_CHECK([grep "lr_out_undnat" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_out_undnat ), priority=0 , match=(1), action=(next;)
+ table=??(lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 &&
outport == "lr0-public"), action=(eth.src = 30:54:00:00:00:03; ct_dnat;)
+ table=??(lr_out_undnat ), priority=100 , match=(ip && ip4.src == 20.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;)
+])
+
+AT_CHECK([grep "lr_out_post_undnat" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_out_post_undnat ), priority=0 , match=(1), action=(next;)
+])
+
+AT_CHECK([grep "lr_out_snat" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_out_snat ), priority=0 , match=(1), action=(next;)
+ table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;)
+ table=??(lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public") && (!ct.trk || !ct.rpl)),
action=(ct_snat(172.168.0.100);)
+ table=??(lr_out_snat ), priority=153 , match=(ip && ip4.src == 20.0.0.0/24 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public") && (!ct.trk || !ct.rpl)),
action=(ct_snat(172.168.0.100);)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("sw0-port1") && (!ct.trk || !ct.rpl)), action=(eth.src =
30:54:00:00:00:03; ct_snat(172.168.0.110);)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 20.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public") && (!ct.trk || !ct.rpl)),
action=(ct_snat(172.168.0.120);)
+])
+
+AT_CHECK([grep "lr_out_egr_loop" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_out_egr_loop ), priority=0 , match=(1), action=(next;)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.100 && outport == "lr0-public"
&& is_chassis_resident("cr-lr0-public")), action=(clone { ct_clear; inport = outport; outport = "";
eth.dst <-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0;
reg7 = 0; reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.110 && outport == "lr0-public"
&& is_chassis_resident("sw0-port1")), action=(clone { ct_clear; inport = outport; outport = ""; eth.dst
<-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0; reg7 = 0;
reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.120 && outport == "lr0-public"
&& is_chassis_resident("cr-lr0-public")), action=(clone { ct_clear; inport = outport; outport = "";
eth.dst <-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0;
reg7 = 0; reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+])
+
+AT_CHECK([grep "ls_in_l2_lkup" publicflows | ovn_strip_lflows], [0], [dnl
+ table=??(ls_in_l2_lkup ), priority=0 , match=(1), action=(outport =
get_fdb(eth.dst); next;)
+ table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst == $svc_monitor_mac
&& (tcp || icmp || icmp6)), action=(handle_svc_check(inport);)
+ table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:ff:02 &&
is_chassis_resident("cr-lr0-public")), action=(outport = "public-lr0"; output;)
+ table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 30:54:00:00:00:03 &&
is_chassis_resident("sw0-port1")), action=(outport = "public-lr0"; output;)
+ table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport =
"_MC_flood"; output;)
+ table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src == {00:00:00:00:ff:02,
30:54:00:00:00:03} && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa
== 172.168.0.10), action=(clone {outport = "public-lr0"; output; }; outport = "_MC_flood_l2";
output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa
== 172.168.0.100), action=(clone {outport = "public-lr0"; output; }; outport = "_MC_flood_l2";
output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa
== 172.168.0.110), action=(clone {outport = "public-lr0"; output; }; outport = "_MC_flood_l2";
output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa
== 172.168.0.120), action=(clone {outport = "public-lr0"; output; }; outport = "_MC_flood_l2";
output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && nd_ns && nd.target ==
fe80::200:ff:fe00:ff02), action=(clone {outport = "public-lr0"; output; }; outport =
"_MC_flood_l2"; output;)
+])
+
+AT_CHECK([grep -e "172.168.0.110" -e "172.168.0.120" -e "10.0.0.3" -e "20.0.0.3" -e
"30:54:00:00:00:03" -e "sw0-port1" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_admission ), priority=50 , match=(eth.dst == 30:54:00:00:00:03 && inport ==
"lr0-public" && is_chassis_resident("sw0-port1")), action=(xreg0[[0..47]] =
00:00:00:00:ff:02; next;)
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.110), action=(eth.dst = 30:54:00:00:00:03; next;)
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.120), action=(eth.dst = 00:00:00:00:ff:02; next;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.110), action=(drop;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.120), action=(drop;)
+ table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.110
&& inport == "lr0-public"), action=(ct_dnat(10.0.0.3);)
+ table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.120 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(20.0.0.3);)
+ table=??(lr_in_gw_redirect ), priority=100 , match=(ip4.src == 10.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("sw0-port1")), action=(eth.src = 30:54:00:00:00:03;
reg1 = 172.168.0.110; next;)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.110), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.120), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=91 , match=(inport == "lr0-public" &&
arp.op == 1 && arp.tpa == 172.168.0.110), action=(drop;)
+ table=??(lr_in_ip_input ), priority=91 , match=(inport == "lr0-public" &&
arp.op == 1 && arp.tpa == 172.168.0.120), action=(drop;)
+ table=??(lr_in_ip_input ), priority=92 , match=(inport == "lr0-public" && arp.op == 1 &&
arp.tpa == 172.168.0.110 && is_chassis_resident("sw0-port1")), action=(eth.dst = eth.src; eth.src =
30:54:00:00:00:03; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 30:54:00:00:00:03; arp.tpa <-> arp.spa; outport
= inport; flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=92 , match=(inport == "lr0-public" && arp.op == 1 &&
arp.tpa == 172.168.0.120 && is_chassis_resident("cr-lr0-public")), 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; outport =
inport; flags.loopback = 1; output;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.110
&& inport == "lr0-public"), action=(ct_snat;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.120 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.110 && outport == "lr0-public"
&& is_chassis_resident("sw0-port1")), action=(clone { ct_clear; inport = outport; outport = ""; eth.dst
<-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0; reg7 = 0;
reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.120 && outport == "lr0-public"
&& is_chassis_resident("cr-lr0-public")), action=(clone { ct_clear; inport = outport; outport = "";
eth.dst <-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0;
reg7 = 0; reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("sw0-port1") && (!ct.trk || !ct.rpl)), action=(eth.src =
30:54:00:00:00:03; ct_snat(172.168.0.110);)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 20.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public") && (!ct.trk || !ct.rpl)),
action=(ct_snat(172.168.0.120);)
+ table=??(lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 &&
outport == "lr0-public"), action=(eth.src = 30:54:00:00:00:03; ct_dnat;)
+ table=??(lr_out_undnat ), priority=100 , match=(ip && ip4.src == 20.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;)
+])
+
+AT_CHECK([grep -e "172.168.0.110" -e "172.168.0.120" -e "10.0.0.3" -e "20.0.0.3" -e
"30:54:00:00:00:03" -e "sw0-port1" publicflows | ovn_strip_lflows], [0], [dnl
+ table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 30:54:00:00:00:03 &&
is_chassis_resident("sw0-port1")), action=(outport = "public-lr0"; output;)
+ table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src == {00:00:00:00:ff:02,
30:54:00:00:00:03} && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa
== 172.168.0.110), action=(clone {outport = "public-lr0"; output; }; outport = "_MC_flood_l2";
output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa
== 172.168.0.120), action=(clone {outport = "public-lr0"; output; }; outport = "_MC_flood_l2";
output;)
+])
+}
+
+check_flows_cr_port_for_public_lr0() {
+ # check that there is port binding cr-public-lr0
+ check_row_count Port_Binding 1 logical_port=cr-public-lr0
+ check_column chassisredirect Port_Binding type logical_port=cr-public-lr0
+
+ ovn-sbctl dump-flows lr0 > lr0flows
+ ovn-sbctl dump-flows public > publicflows
+
+AT_CHECK([grep "lr_in_admission" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_admission ), priority=0 , match=(1), action=(drop;)
+ table=??(lr_in_admission ), priority=100 , match=(vlan.present ||
eth.src[[40]]), action=(drop;)
+ table=??(lr_in_admission ), priority=110 , match=(((ip4 && icmp4.type == 3 && icmp4.code == 4)
|| (ip6 && icmp6.type == 2 && icmp6.code == 0)) && flags.tunnel_rx == 1), action=(drop;)
+ table=??(lr_in_admission ), priority=120 , match=(((ip4 && icmp4.type == 3 && icmp4.code == 4) || (ip6 && icmp6.type == 2
&& icmp6.code == 0)) && eth.dst == 00:00:00:00:ff:02 && !is_chassis_resident("cr-lr0-public") && flags.tunnel_rx == 1),
action=(outport <-> inport; inport = "lr0-public"; next;)
+ table=??(lr_in_admission ), priority=50 , match=(eth.dst == 00:00:00:00:ff:01 &&
inport == "lr0-sw0"), action=(xreg0[[0..47]] = 00:00:00:00:ff:01; next;)
+ table=??(lr_in_admission ), priority=50 , match=(eth.dst == 00:00:00:00:ff:02 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(xreg0[[0..47]] =
00:00:00:00:ff:02; next;)
+ table=??(lr_in_admission ), priority=50 , match=(eth.dst == 00:00:00:00:ff:03 &&
inport == "lr0-sw1"), action=(xreg0[[0..47]] = 00:00:00:00:ff:03; next;)
+ table=??(lr_in_admission ), priority=50 , match=(eth.mcast && inport ==
"lr0-public"), action=(xreg0[[0..47]] = 00:00:00:00:ff:02; next;)
+ table=??(lr_in_admission ), priority=50 , match=(eth.mcast && inport ==
"lr0-sw0"), action=(xreg0[[0..47]] = 00:00:00:00:ff:01; next;)
+ table=??(lr_in_admission ), priority=50 , match=(eth.mcast && inport ==
"lr0-sw1"), action=(xreg0[[0..47]] = 00:00:00:00:ff:03; next;)
+])
+
+AT_CHECK([grep "lr_in_ip_input" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_ip_input ), priority=0 , match=(1), action=(next;)
+ table=??(lr_in_ip_input ), priority=100 , match=(ip4.src == {10.0.0.1,
10.0.0.255} && reg9[[0]] == 0), action=(drop;)
+ table=??(lr_in_ip_input ), priority=100 , match=(ip4.src == {172.168.0.10,
172.168.0.255} && reg9[[0]] == 0), action=(drop;)
+ table=??(lr_in_ip_input ), priority=100 , match=(ip4.src == {20.0.0.1,
20.0.0.255} && reg9[[0]] == 0), action=(drop;)
+ table=??(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=??(lr_in_ip_input ), priority=100 , match=(ip6.dst == fe80::200:ff:fe00:ff01
&& udp.src == 547 && udp.dst == 546), action=(reg0 = 0; handle_dhcpv6_reply;)
+ table=??(lr_in_ip_input ), priority=100 , match=(ip6.dst == fe80::200:ff:fe00:ff02
&& udp.src == 547 && udp.dst == 546), action=(reg0 = 0; handle_dhcpv6_reply;)
+ table=??(lr_in_ip_input ), priority=100 , match=(ip6.dst == fe80::200:ff:fe00:ff03
&& udp.src == 547 && udp.dst == 546), action=(reg0 = 0; handle_dhcpv6_reply;)
+ table=??(lr_in_ip_input ), priority=120 , match=(inport == "lr0-public"
&& ip4.src == 172.168.0.100), action=(next;)
+ table=??(lr_in_ip_input ), priority=30 , match=(ip.ttl == {0, 1}),
action=(drop;)
+ table=??(lr_in_ip_input ), priority=31 , match=(inport == "lr0-public" && 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 ; ip.ttl = 254; outport = "lr0-public"; flags.loopback = 1; output; };)
+ table=??(lr_in_ip_input ), priority=31 , match=(inport == "lr0-sw0" && 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.0.0.1 ; ip.ttl = 254; outport = "lr0-sw0"; flags.loopback = 1;
output; };)
+ table=??(lr_in_ip_input ), priority=31 , match=(inport == "lr0-sw1" && 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 = 20.0.0.1 ; ip.ttl = 254; outport = "lr0-sw1"; flags.loopback = 1;
output; };)
+ table=??(lr_in_ip_input ), priority=32 , match=(ip.ttl == {0, 1} &&
!ip.later_frag && (ip4.mcast || ip6.mcast)), action=(drop;)
+ table=??(lr_in_ip_input ), priority=50 , match=(eth.bcast),
action=(drop;)
+ table=??(lr_in_ip_input ), priority=60 , match=(ip4.dst ==
{10.0.0.1}), action=(drop;)
+ table=??(lr_in_ip_input ), priority=60 , match=(ip4.dst ==
{172.168.0.10}), action=(drop;)
+ table=??(lr_in_ip_input ), priority=60 , match=(ip4.dst ==
{20.0.0.1}), action=(drop;)
+ table=??(lr_in_ip_input ), priority=60 , match=(ip6.dst ==
{fe80::200:ff:fe00:ff01}), action=(drop;)
+ table=??(lr_in_ip_input ), priority=60 , match=(ip6.dst ==
{fe80::200:ff:fe00:ff02}), action=(drop;)
+ table=??(lr_in_ip_input ), priority=60 , match=(ip6.dst ==
{fe80::200:ff:fe00:ff03}), action=(drop;)
+ table=??(lr_in_ip_input ), priority=82 , match=(ip4.mcast ||
ip6.mcast), action=(drop;)
+ table=??(lr_in_ip_input ), priority=83 , match=(ip6.mcast_rsvd),
action=(drop;)
+ table=??(lr_in_ip_input ), priority=84 , match=(nd_rs || nd_ra),
action=(next;)
+ table=??(lr_in_ip_input ), priority=85 , match=(arp || nd),
action=(drop;)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.100), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.110), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.120), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(inport == "lr0-public" && arp.op == 1
&& arp.tpa == 172.168.0.10 && arp.spa == 172.168.0.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;
outport = inport; flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(inport == "lr0-public" && ip6.dst ==
{fe80::200:ff:fe00:ff02, ff02::1:ff00:ff02} && nd_ns && nd.target == fe80::200:ff:fe00:ff02 &&
is_chassis_resident("cr-lr0-public")), action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll =
xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };)
+ table=??(lr_in_ip_input ), priority=90 , match=(inport == "lr0-sw0" && arp.op == 1
&& arp.tpa == 10.0.0.1 && arp.spa == 10.0.0.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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(inport == "lr0-sw0" && ip6.dst ==
{fe80::200:ff:fe00:ff01, ff02::1:ff00:ff01} && nd_ns && nd.target == fe80::200:ff:fe00:ff01),
action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll = xreg0[[0..47]]; outport = inport;
flags.loopback = 1; output; };)
+ table=??(lr_in_ip_input ), priority=90 , match=(inport == "lr0-sw1" && arp.op == 1
&& arp.tpa == 20.0.0.1 && arp.spa == 20.0.0.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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(inport == "lr0-sw1" && ip6.dst ==
{fe80::200:ff:fe00:ff03, ff02::1:ff00:ff03} && nd_ns && nd.target == fe80::200:ff:fe00:ff03),
action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll = xreg0[[0..47]]; outport = inport;
flags.loopback = 1; output; };)
+ table=??(lr_in_ip_input ), priority=90 , match=(ip4.dst == 10.0.0.1 && icmp4.type ==
8 && icmp4.code == 0), action=(ip4.dst <-> ip4.src; ip.ttl = 255; icmp4.type = 0;
flags.loopback = 1; next; )
+ table=??(lr_in_ip_input ), priority=90 , match=(ip4.dst == 172.168.0.10 &&
icmp4.type == 8 && icmp4.code == 0), action=(ip4.dst <-> ip4.src; ip.ttl = 255;
icmp4.type = 0; flags.loopback = 1; next; )
+ table=??(lr_in_ip_input ), priority=90 , match=(ip4.dst == 20.0.0.1 && icmp4.type ==
8 && icmp4.code == 0), action=(ip4.dst <-> ip4.src; ip.ttl = 255; icmp4.type = 0;
flags.loopback = 1; next; )
+ table=??(lr_in_ip_input ), priority=90 , match=(ip6.dst == fe80::200:ff:fe00:ff01 &&
icmp6.type == 128 && icmp6.code == 0), action=(ip6.dst <-> ip6.src; ip.ttl = 255;
icmp6.type = 129; flags.loopback = 1; next; )
+ table=??(lr_in_ip_input ), priority=90 , match=(ip6.dst == fe80::200:ff:fe00:ff02 &&
icmp6.type == 128 && icmp6.code == 0), action=(ip6.dst <-> ip6.src; ip.ttl = 255;
icmp6.type = 129; flags.loopback = 1; next; )
+ table=??(lr_in_ip_input ), priority=90 , match=(ip6.dst == fe80::200:ff:fe00:ff03 &&
icmp6.type == 128 && icmp6.code == 0), action=(ip6.dst <-> ip6.src; ip.ttl = 255;
icmp6.type = 129; flags.loopback = 1; next; )
+])
+
+AT_CHECK([grep "lr_in_unsnat" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_unsnat ), priority=0 , match=(1), action=(next;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.100 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.110 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.120 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;)
+])
+
+AT_CHECK([grep "lr_in_defrag" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_defrag ), priority=0 , match=(1), action=(next;)
+])
+
+AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;)
+ table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.110 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);)
+ table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.120 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(20.0.0.3);)
+])
+
+AT_CHECK([grep "lr_in_arp_resolve" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_arp_resolve ), priority=0 , match=(1), action=(drop;)
+ table=??(lr_in_arp_resolve ), priority=1 , match=(ip4),
action=(get_arp(outport, reg0); next;)
+ table=??(lr_in_arp_resolve ), priority=1 , match=(ip6),
action=(get_nd(outport, xxreg0); next;)
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.100), action=(eth.dst = 00:00:00:00:ff:02; next;)
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.110), action=(eth.dst = 00:00:00:00:ff:02; next;)
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.120), action=(eth.dst = 00:00:00:00:ff:02; next;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.100), action=(drop;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.110), action=(drop;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.120), action=(drop;)
+ table=??(lr_in_arp_resolve ), priority=500 , match=(ip4.mcast ||
ip6.mcast), action=(next;)
+])
+
+AT_CHECK([grep "lr_in_gw_redirect" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_gw_redirect ), priority=0 , match=(1), action=(next;)
+ table=??(lr_in_gw_redirect ), priority=50 , match=(outport == "lr0-public"),
action=(outport = "cr-lr0-public"; next;)
+])
+
+AT_CHECK([grep "lr_out_undnat" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_out_undnat ), priority=0 , match=(1), action=(next;)
+ table=??(lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;)
+ table=??(lr_out_undnat ), priority=100 , match=(ip && ip4.src == 20.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;)
+])
+
+AT_CHECK([grep "lr_out_post_undnat" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_out_post_undnat ), priority=0 , match=(1), action=(next;)
+])
+
+AT_CHECK([grep "lr_out_snat" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_out_snat ), priority=0 , match=(1), action=(next;)
+ table=??(lr_out_snat ), priority=120 , match=(nd_ns), action=(next;)
+ table=??(lr_out_snat ), priority=153 , match=(ip && ip4.src == 10.0.0.0/24 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public") && (!ct.trk || !ct.rpl)),
action=(ct_snat(172.168.0.100);)
+ table=??(lr_out_snat ), priority=153 , match=(ip && ip4.src == 20.0.0.0/24 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public") && (!ct.trk || !ct.rpl)),
action=(ct_snat(172.168.0.100);)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public") && (!ct.trk || !ct.rpl)),
action=(ct_snat(172.168.0.110);)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 20.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public") && (!ct.trk || !ct.rpl)),
action=(ct_snat(172.168.0.120);)
+])
+
+AT_CHECK([grep "lr_out_egr_loop" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_out_egr_loop ), priority=0 , match=(1), action=(next;)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.100 && outport == "lr0-public"
&& is_chassis_resident("cr-lr0-public")), action=(clone { ct_clear; inport = outport; outport = "";
eth.dst <-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0;
reg7 = 0; reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.110 && outport == "lr0-public"
&& is_chassis_resident("cr-lr0-public")), action=(clone { ct_clear; inport = outport; outport = "";
eth.dst <-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0;
reg7 = 0; reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.120 && outport == "lr0-public"
&& is_chassis_resident("cr-lr0-public")), action=(clone { ct_clear; inport = outport; outport = "";
eth.dst <-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0;
reg7 = 0; reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+])
+
+AT_CHECK([grep "ls_in_l2_lkup" publicflows | ovn_strip_lflows], [0], [dnl
+ table=??(ls_in_l2_lkup ), priority=0 , match=(1), action=(outport =
get_fdb(eth.dst); next;)
+ table=??(ls_in_l2_lkup ), priority=110 , match=(eth.dst == $svc_monitor_mac
&& (tcp || icmp || icmp6)), action=(handle_svc_check(inport);)
+ table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:ff:02 &&
!is_chassis_resident("cr-public-lr0")), action=(outport = "cr-public-lr0"; output;)
+ table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:ff:02 &&
is_chassis_resident("cr-public-lr0")), action=(outport = "public-lr0"; output;)
+ table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 30:54:00:00:00:03 &&
is_chassis_resident("sw0-port1")), action=(outport = "public-lr0"; output;)
+ table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport =
"_MC_flood"; output;)
+ table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src == {00:00:00:00:ff:02,
30:54:00:00:00:03} && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.10
&& is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0"; output; }; outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.100
&& is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0"; output; }; outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.110
&& is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0"; output; }; outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.120
&& is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0"; output; }; outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && nd_ns && nd.target ==
fe80::200:ff:fe00:ff02 && is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0";
output; }; outport = "_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=81 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.10
&& !is_chassis_resident("cr-public-lr0")), action=(clone {outport = "cr-public-lr0"; output; }; outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=81 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.100
&& !is_chassis_resident("cr-public-lr0")), action=(clone {outport = "cr-public-lr0"; output; }; outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=81 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.110
&& !is_chassis_resident("cr-public-lr0")), action=(clone {outport = "cr-public-lr0"; output; }; outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=81 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.120
&& !is_chassis_resident("cr-public-lr0")), action=(clone {outport = "cr-public-lr0"; output; }; outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=81 , match=(flags[[1]] == 0 && nd_ns && nd.target ==
fe80::200:ff:fe00:ff02 && !is_chassis_resident("cr-public-lr0")), action=(clone {outport =
"cr-public-lr0"; output; }; outport = "_MC_flood_l2"; output;)
+])
+
+AT_CHECK([grep -e "172.168.0.110" -e "172.168.0.120" -e "10.0.0.3" -e "20.0.0.3" -e
"30:54:00:00:00:03" -e "sw0-port1" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.110), action=(eth.dst = 00:00:00:00:ff:02; next;)
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.120), action=(eth.dst = 00:00:00:00:ff:02; next;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.110), action=(drop;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.120), action=(drop;)
+ table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.110 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);)
+ table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.120 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(20.0.0.3);)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.110), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.120), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.110 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.120 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.110 && outport == "lr0-public"
&& is_chassis_resident("cr-lr0-public")), action=(clone { ct_clear; inport = outport; outport = "";
eth.dst <-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0;
reg7 = 0; reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.120 && outport == "lr0-public"
&& is_chassis_resident("cr-lr0-public")), action=(clone { ct_clear; inport = outport; outport = "";
eth.dst <-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0;
reg7 = 0; reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public") && (!ct.trk || !ct.rpl)),
action=(ct_snat(172.168.0.110);)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 20.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public") && (!ct.trk || !ct.rpl)),
action=(ct_snat(172.168.0.120);)
+ table=??(lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;)
+ table=??(lr_out_undnat ), priority=100 , match=(ip && ip4.src == 20.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;)
+])
+
+AT_CHECK([grep -e "172.168.0.110" -e "172.168.0.120" -e "10.0.0.3" -e "20.0.0.3" -e
"30:54:00:00:00:03" -e "sw0-port1" publicflows | ovn_strip_lflows], [0], [dnl
+ table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 30:54:00:00:00:03 &&
is_chassis_resident("sw0-port1")), action=(outport = "public-lr0"; output;)
+ table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src == {00:00:00:00:ff:02,
30:54:00:00:00:03} && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.110
&& is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0"; output; }; outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.120
&& is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0"; output; }; outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=81 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.110
&& !is_chassis_resident("cr-public-lr0")), action=(clone {outport = "cr-public-lr0"; output; }; outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=81 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.120
&& !is_chassis_resident("cr-public-lr0")), action=(clone {outport = "cr-public-lr0"; output; }; outport =
"_MC_flood_l2"; output;)
+])
+}
+
+# Check that the lflows are as expected when public has localnet port.
+check_flows_no_cr_port_for_public_lr0
+
+# Remove the localnet port from public logical switch.
+check ovn-nbctl --wait=sb lsp-set-type ln-public ""
+
+# Check that the lflows are as expected and there is no cr port
+# created for "public-lr0" when public has no localnet port
+# since public doesn't have the option "overlay_provider_network=true"
+# set.
+check_row_count Port_Binding 0 logical_port=cr-public-lr0
+
+ovn-sbctl dump-flows lr0 > lr0flows
+ovn-sbctl dump-flows public > publicflows
+
+AT_CHECK([grep -e "172.168.0.110" -e "172.168.0.120" -e "10.0.0.3" -e "20.0.0.3" -e
"30:54:00:00:00:03" -e "sw0-port1" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_admission ), priority=50 , match=(eth.dst == 30:54:00:00:00:03 && inport ==
"lr0-public" && is_chassis_resident("sw0-port1")), action=(xreg0[[0..47]] =
00:00:00:00:ff:02; next;)
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.110), action=(eth.dst = 30:54:00:00:00:03; next;)
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.120), action=(eth.dst = 00:00:00:00:ff:02; next;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.110), action=(drop;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.120), action=(drop;)
+ table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.110
&& inport == "lr0-public"), action=(ct_dnat(10.0.0.3);)
+ table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.120 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(20.0.0.3);)
+ table=??(lr_in_gw_redirect ), priority=100 , match=(ip4.src == 10.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("sw0-port1")), action=(eth.src = 30:54:00:00:00:03;
reg1 = 172.168.0.110; next;)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.110), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.120), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=91 , match=(inport == "lr0-public" &&
arp.op == 1 && arp.tpa == 172.168.0.110), action=(drop;)
+ table=??(lr_in_ip_input ), priority=91 , match=(inport == "lr0-public" &&
arp.op == 1 && arp.tpa == 172.168.0.120), action=(drop;)
+ table=??(lr_in_ip_input ), priority=92 , match=(inport == "lr0-public" && arp.op == 1 &&
arp.tpa == 172.168.0.110 && is_chassis_resident("sw0-port1")), action=(eth.dst = eth.src; eth.src =
30:54:00:00:00:03; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 30:54:00:00:00:03; arp.tpa <-> arp.spa; outport
= inport; flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=92 , match=(inport == "lr0-public" && arp.op == 1 &&
arp.tpa == 172.168.0.120 && is_chassis_resident("cr-lr0-public")), 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; outport =
inport; flags.loopback = 1; output;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.110
&& inport == "lr0-public"), action=(ct_snat;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.120 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.110 && outport == "lr0-public"
&& is_chassis_resident("sw0-port1")), action=(clone { ct_clear; inport = outport; outport = ""; eth.dst
<-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0; reg7 = 0;
reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.120 && outport == "lr0-public"
&& is_chassis_resident("cr-lr0-public")), action=(clone { ct_clear; inport = outport; outport = "";
eth.dst <-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0;
reg7 = 0; reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("sw0-port1") && (!ct.trk || !ct.rpl)), action=(eth.src =
30:54:00:00:00:03; ct_snat(172.168.0.110);)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 20.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public") && (!ct.trk || !ct.rpl)),
action=(ct_snat(172.168.0.120);)
+ table=??(lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 &&
outport == "lr0-public"), action=(eth.src = 30:54:00:00:00:03; ct_dnat;)
+ table=??(lr_out_undnat ), priority=100 , match=(ip && ip4.src == 20.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;)
+])
+
+AT_CHECK([grep -e "172.168.0.110" -e "172.168.0.120" -e "10.0.0.3" -e "20.0.0.3" -e
"30:54:00:00:00:03" -e "sw0-port1" publicflows | ovn_strip_lflows], [0], [dnl
+ table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 30:54:00:00:00:03 &&
is_chassis_resident("sw0-port1")), action=(outport = "public-lr0"; output;)
+ table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src == {00:00:00:00:ff:02,
30:54:00:00:00:03} && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa
== 172.168.0.110), action=(clone {outport = "public-lr0"; output; }; outport = "_MC_flood_l2";
output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa
== 172.168.0.120), action=(clone {outport = "public-lr0"; output; }; outport = "_MC_flood_l2";
output;)
+])
+
+
+# Set the option "overlay_provider_network=true" for public.
+check ovn-nbctl --wait=sb set logical_switch public
other_config:overlay_provider_network=true
+
+# Check that the lflows are as expected and there is cr port created for
public-lr0.
+check_flows_cr_port_for_public_lr0
+
+# Set the type of ln-public back to localnet
+check ovn-nbctl --wait=sb lsp-set-type ln-public localnet
+
+# Check that the lflows are as expected when public has localnet port.
+check_flows_no_cr_port_for_public_lr0
+
+# Delete the localnet port
+check ovn-nbctl --wait=sb lsp-del ln-public
+
+# Check that the lflows are as expected when public has no localnet port.
+check_flows_cr_port_for_public_lr0
+
+# Create multiple gateway ports. chassisresident port should not be
+# created for 'public-lr0' even if there is no localnet port on 'public'
+# logical switch.
+check ovn-nbctl --wait=sb lrp-set-gateway-chassis lr0-sw0 gw1
+# check that there is no port binding cr-public-lr0
+check_row_count Port_Binding 0 logical_port=cr-public-lr0
+
+ovn-sbctl dump-flows lr0 > lr0flows
+ovn-sbctl dump-flows public > publicflows
+
+AT_CHECK([grep -e "172.168.0.110" -e "172.168.0.120" -e "10.0.0.3" -e "20.0.0.3" -e
"30:54:00:00:00:03" -e "sw0-port1" lr0flows | ovn_strip_lflows], [0], [dnl
+ table=??(lr_in_admission ), priority=50 , match=(eth.dst == 30:54:00:00:00:03 && inport ==
"lr0-public" && is_chassis_resident("sw0-port1")), action=(xreg0[[0..47]] =
00:00:00:00:ff:02; next;)
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.110), action=(eth.dst = 30:54:00:00:00:03; next;)
+ table=??(lr_in_arp_resolve ), priority=100 , match=(outport == "lr0-public"
&& reg0 == 172.168.0.120), action=(eth.dst = 00:00:00:00:ff:02; next;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.110), action=(drop;)
+ table=??(lr_in_arp_resolve ), priority=150 , match=(inport == "lr0-public" && outport ==
"lr0-public" && ip4.dst == 172.168.0.120), action=(drop;)
+ table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.110
&& inport == "lr0-public"), action=(ct_dnat(10.0.0.3);)
+ table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.120 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(20.0.0.3);)
+ table=??(lr_in_gw_redirect ), priority=100 , match=(ip4.src == 10.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("sw0-port1")), action=(eth.src = 30:54:00:00:00:03;
reg1 = 172.168.0.110; next;)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.110), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=90 , match=(arp.op == 1 && arp.tpa ==
172.168.0.120), 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; outport = inport;
flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=91 , match=(inport == "lr0-public" &&
arp.op == 1 && arp.tpa == 172.168.0.110), action=(drop;)
+ table=??(lr_in_ip_input ), priority=91 , match=(inport == "lr0-public" &&
arp.op == 1 && arp.tpa == 172.168.0.120), action=(drop;)
+ table=??(lr_in_ip_input ), priority=92 , match=(inport == "lr0-public" && arp.op == 1 &&
arp.tpa == 172.168.0.110 && is_chassis_resident("sw0-port1")), action=(eth.dst = eth.src; eth.src =
30:54:00:00:00:03; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 30:54:00:00:00:03; arp.tpa <-> arp.spa; outport
= inport; flags.loopback = 1; output;)
+ table=??(lr_in_ip_input ), priority=92 , match=(inport == "lr0-public" && arp.op == 1 &&
arp.tpa == 172.168.0.120 && is_chassis_resident("cr-lr0-public")), 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; outport =
inport; flags.loopback = 1; output;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.110
&& inport == "lr0-public"), action=(ct_snat;)
+ table=??(lr_in_unsnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.120 && inport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_snat;)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.110 && outport == "lr0-public"
&& is_chassis_resident("sw0-port1")), action=(clone { ct_clear; inport = outport; outport = ""; eth.dst
<-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0; reg7 = 0;
reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+ table=??(lr_out_egr_loop ), priority=100 , match=(ip4.dst == 172.168.0.120 && outport == "lr0-public"
&& is_chassis_resident("cr-lr0-public")), action=(clone { ct_clear; inport = outport; outport = "";
eth.dst <-> eth.src; flags = 0; flags.loopback = 1; reg0 = 0; reg1 = 0; reg2 = 0; reg3 = 0; reg4 = 0; reg5 = 0; reg6 = 0;
reg7 = 0; reg8 = 0; reg9 = 0; reg9[[0]] = 1; next(pipeline=ingress, table=??); };)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 10.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("sw0-port1") && (!ct.trk || !ct.rpl)), action=(eth.src =
30:54:00:00:00:03; ct_snat(172.168.0.110);)
+ table=??(lr_out_snat ), priority=161 , match=(ip && ip4.src == 20.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public") && (!ct.trk || !ct.rpl)),
action=(ct_snat(172.168.0.120);)
+ table=??(lr_out_undnat ), priority=100 , match=(ip && ip4.src == 10.0.0.3 &&
outport == "lr0-public"), action=(eth.src = 30:54:00:00:00:03; ct_dnat;)
+ table=??(lr_out_undnat ), priority=100 , match=(ip && ip4.src == 20.0.0.3 && outport ==
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;)
+])
+
+AT_CHECK([grep -e "172.168.0.110" -e "172.168.0.120" -e "10.0.0.3" -e "20.0.0.3" -e
"30:54:00:00:00:03" -e "sw0-port1" publicflows | ovn_strip_lflows], [0], [dnl
+ table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 30:54:00:00:00:03 &&
is_chassis_resident("sw0-port1")), action=(outport = "public-lr0"; output;)
+ table=??(ls_in_l2_lkup ), priority=75 , match=(eth.src == {00:00:00:00:ff:02,
30:54:00:00:00:03} && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport =
"_MC_flood_l2"; output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa
== 172.168.0.110), action=(clone {outport = "public-lr0"; output; }; outport = "_MC_flood_l2";
output;)
+ table=??(ls_in_l2_lkup ), priority=80 , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa
== 172.168.0.120), action=(clone {outport = "public-lr0"; output; }; outport = "_MC_flood_l2";
output;)
+])
+
+AT_CLEANUP
+])
diff --git a/tests/ovn.at b/tests/ovn.at
index e81cd4f45a..8b1d3c846f 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -21181,10 +21181,10 @@ ovn-nbctl lsp-add sw0 rp-sw0 -- set
Logical_Switch_Port rp-sw0 \
type=router options:router-port=sw0 \
-- lsp-set-addresses rp-sw0 router
-ovn-nbctl lrp-add lr0 sw1 00:00:02:01:02:03 172.16.1.1/24 2002:0:0:0:0:0:0:1/64 \
- -- lrp-set-gateway-chassis sw1 hv2
+ovn-nbctl lrp-add lr0 lr0-sw1 00:00:02:01:02:03 172.16.1.1/24
2002:0:0:0:0:0:0:1/64 \
+ -- lrp-set-gateway-chassis lr0-sw1 hv2
ovn-nbctl lsp-add sw1 rp-sw1 -- set Logical_Switch_Port rp-sw1 \
- type=router options:router-port=sw1 \
+ type=router options:router-port=lr0-sw1 \
-- lsp-set-addresses rp-sw1 router
ovn-nbctl lsp-add sw0 sw0-p0 \
@@ -21196,6 +21196,8 @@ ovn-nbctl lsp-add sw0 sw0-p1 \
ovn-nbctl lsp-add sw1 sw1-p0 \
-- lsp-set-addresses sw1-p0 unknown
+check ovn-nbctl lsp-add sw1 ln-sw1 -- lsp-set-type ln-sw1 localnet
+
ovn-nbctl lr-nat-add lr0 snat 172.16.1.1 192.168.1.0/24
ovn-nbctl lr-nat-add lr0 snat 2002::1 2001::/64