diff --git a/.ovn.metadata b/.ovn.metadata index e8741e5..21e5af6 100644 --- a/.ovn.metadata +++ b/.ovn.metadata @@ -1,5 +1,5 @@ 002450621b33c5690060345b0aac25bc2426d675 SOURCES/docutils-0.12.tar.gz -c39c740cd246836bcb125432d2205d0f76504bc0 SOURCES/openvswitch-8986d4d.tar.gz -4b5217eba8aa5b020946395afa94e48ae81957e8 SOURCES/ovn-23.03.0.tar.gz +d5a30334edfe265936a26db900a8838c83ef4043 SOURCES/openvswitch-0187ead.tar.gz +28d5de798f88964283b144cdd8cb226059d403dd SOURCES/ovn-23.06.1.tar.gz d34f96421a86004aa5d26ecf975edefd09f948b1 SOURCES/Pygments-1.4.tar.gz 6beb30f18ffac3de7689b7fd63e9a8a7d9c8df3a SOURCES/Sphinx-1.1.3.tar.gz diff --git a/SOURCES/ovn23.03.patch b/SOURCES/ovn23.03.patch deleted file mode 100644 index 9478c3b..0000000 --- a/SOURCES/ovn23.03.patch +++ /dev/null @@ -1,10982 +0,0 @@ -diff --git a/.github/workflows/ovn-kubernetes.yml b/.github/workflows/ovn-kubernetes.yml -index c82b23a1f..1d554cd03 100644 ---- a/.github/workflows/ovn-kubernetes.yml -+++ b/.github/workflows/ovn-kubernetes.yml -@@ -56,7 +56,7 @@ jobs: - name: e2e - if: github.event_name != 'schedule' - runs-on: ubuntu-20.04 -- timeout-minutes: 120 -+ timeout-minutes: 220 - strategy: - fail-fast: false - matrix: -@@ -137,6 +137,9 @@ jobs: - working-directory: src/github.com/ovn-org/ovn-kubernetes - - - name: Run Tests -+ # e2e tests take ~60 minutes normally, 120 should be more than enough -+ # set 180 for control-plane tests as these might take a while -+ timeout-minutes: ${{ matrix.target == 'control-plane' && 180 || 120 }} - run: | - make -C test ${{ matrix.target }} - working-directory: src/github.com/ovn-org/ovn-kubernetes -diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml -index 0f8d9d193..edf4fb2fd 100644 ---- a/.github/workflows/test.yml -+++ b/.github/workflows/test.yml -@@ -17,7 +17,8 @@ jobs: - dependencies: | - automake libtool gcc bc libjemalloc2 libjemalloc-dev \ - libssl-dev llvm-dev libelf-dev libnuma-dev libpcap-dev \ -- selinux-policy-dev ncat python3-scapy isc-dhcp-server -+ selinux-policy-dev ncat python3-scapy isc-dhcp-server \ -+ iputils-arping - m32_dependecies: gcc-multilib - ARCH: ${{ matrix.cfg.arch }} - CC: ${{ matrix.cfg.compiler }} -diff --git a/NEWS b/NEWS -index 5e8aed06d..d7ba71ef5 100644 ---- a/NEWS -+++ b/NEWS -@@ -1,3 +1,17 @@ -+OVN v23.03.1 - xx xxx xxxx -+-------------------------- -+ - CT entries are not flushed by default anymore whenever a load balancer -+ backend is removed. A new, per-LB, option 'ct_flush' can be used to -+ restore the previous behavior. Disabled by default. -+ - Always allow IPv6 Router Discovery, Neighbor Discovery, and Multicast -+ Listener Discovery protocols, regardless of ACLs defined. -+ - Send ICMP Fragmentation Needed packets back to offending ports when -+ communicating with multichassis ports using frames that don't fit through a -+ tunnel. This is done only for logical switches that are attached to a -+ physical network via a localnet port, in which case multichassis ports may -+ have an effective MTU different from regular ports and hence may need this -+ mechanism to maintain connectivity with other peers in the network. -+ - OVN v23.03.0 - 03 Mar 2023 - -------------------------- - - ovn-controller: Experimental support for co-hosting multiple controller -diff --git a/configure.ac b/configure.ac -index b51d0f01e..0ba9e8d7e 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -13,7 +13,7 @@ - # limitations under the License. - - AC_PREREQ(2.63) --AC_INIT(ovn, 23.03.0, bugs@openvswitch.org) -+AC_INIT(ovn, 23.03.1, bugs@openvswitch.org) - AC_CONFIG_MACRO_DIR([m4]) - AC_CONFIG_AUX_DIR([build-aux]) - AC_CONFIG_HEADERS([config.h]) -diff --git a/controller/binding.c b/controller/binding.c -index 5df62baef..8fce6fc3f 100644 ---- a/controller/binding.c -+++ b/controller/binding.c -@@ -57,6 +57,10 @@ struct claimed_port { - static struct shash _claimed_ports = SHASH_INITIALIZER(&_claimed_ports); - static struct sset _postponed_ports = SSET_INITIALIZER(&_postponed_ports); - -+static void -+remove_additional_chassis(const struct sbrec_port_binding *pb, -+ const struct sbrec_chassis *chassis_rec); -+ - struct sset * - get_postponed_ports(void) - { -@@ -746,6 +750,19 @@ local_binding_get_lport_ofport(const struct shash *local_bindings, - u16_to_ofp(lbinding->iface->ofport[0]) : 0; - } - -+bool -+local_binding_is_ovn_installed(struct shash *local_bindings, -+ const char *pb_name) -+{ -+ struct local_binding *lbinding = -+ local_binding_find(local_bindings, pb_name); -+ if (lbinding && lbinding->iface) { -+ return smap_get_bool(&lbinding->iface->external_ids, -+ OVN_INSTALLED_EXT_ID, false); -+ } -+ return false; -+} -+ - bool - local_binding_is_up(struct shash *local_bindings, const char *pb_name, - const struct sbrec_chassis *chassis_rec) -@@ -783,6 +800,7 @@ local_binding_is_down(struct shash *local_bindings, const char *pb_name, - } else if (b_lport->pb->chassis) { - VLOG_DBG("lport %s already claimed by other chassis", - b_lport->pb->logical_port); -+ return true; - } - } - -@@ -834,6 +852,38 @@ local_binding_set_up(struct shash *local_bindings, const char *pb_name, - } - } - -+void -+local_binding_remove_ovn_installed( -+ struct shash *local_bindings, -+ const struct ovsrec_interface_table *iface_table, -+ const char *pb_name, bool ovs_readonly) -+{ -+ if (ovs_readonly) { -+ return; -+ } -+ struct local_binding *lbinding = -+ local_binding_find(local_bindings, pb_name); -+ if (lbinding && lbinding->iface) { -+ const struct uuid *iface_uuid = &lbinding->iface->header_.uuid; -+ remove_ovn_installed_for_uuid(iface_table, iface_uuid); -+ } -+} -+ -+void -+remove_ovn_installed_for_uuid(const struct ovsrec_interface_table *iface_table, -+ const struct uuid *iface_uuid) -+{ -+ const struct ovsrec_interface *iface_rec = -+ ovsrec_interface_table_get_for_uuid(iface_table, iface_uuid); -+ if (iface_rec && smap_get_bool(&iface_rec->external_ids, -+ OVN_INSTALLED_EXT_ID, false)) { -+ VLOG_INFO("Removing iface %s ovn-installed in OVS", -+ iface_rec->name); -+ ovsrec_interface_update_external_ids_delkey(iface_rec, -+ OVN_INSTALLED_EXT_ID); -+ } -+} -+ - void - local_binding_set_down(struct shash *local_bindings, const char *pb_name, - const struct sbrec_chassis *chassis_rec, -@@ -853,7 +903,6 @@ local_binding_set_down(struct shash *local_bindings, const char *pb_name, - - if (!sb_readonly && b_lport && b_lport->pb->n_up && b_lport->pb->up[0] && - (!b_lport->pb->chassis || b_lport->pb->chassis == chassis_rec)) { -- VLOG_INFO("Setting lport %s down in Southbound", pb_name); - binding_lport_set_down(b_lport, sb_readonly); - LIST_FOR_EACH (b_lport, list_node, &lbinding->binding_lports) { - binding_lport_set_down(b_lport, sb_readonly); -@@ -1028,6 +1077,26 @@ set_pb_chassis_in_sbrec(const struct sbrec_port_binding *pb, - } - } - -+void -+set_pb_additional_chassis_in_sbrec(const struct sbrec_port_binding *pb, -+ const struct sbrec_chassis *chassis_rec, -+ bool is_set) -+{ -+ if (!is_additional_chassis(pb, chassis_rec)) { -+ VLOG_INFO("Claiming lport %s for this additional chassis.", -+ pb->logical_port); -+ for (size_t i = 0; i < pb->n_mac; i++) { -+ VLOG_INFO("%s: Claiming %s", pb->logical_port, pb->mac[i]); -+ } -+ sbrec_port_binding_update_additional_chassis_addvalue(pb, chassis_rec); -+ if (pb->chassis == chassis_rec) { -+ sbrec_port_binding_set_chassis(pb, NULL); -+ } -+ } else if (!is_set) { -+ remove_additional_chassis(pb, chassis_rec); -+ } -+} -+ - bool - local_bindings_pb_chassis_is_set(struct shash *local_bindings, - const char *pb_name, -@@ -1228,8 +1297,8 @@ claim_lport(const struct sbrec_port_binding *pb, - } - set_pb_chassis_in_sbrec(pb, chassis_rec, true); - } else { -- if_status_mgr_claim_iface(if_mgr, pb, chassis_rec, -- sb_readonly); -+ if_status_mgr_claim_iface(if_mgr, pb, chassis_rec, iface_rec, -+ sb_readonly, can_bind); - } - register_claim_timestamp(pb->logical_port, now); - sset_find_and_delete(postponed_ports, pb->logical_port); -@@ -1239,29 +1308,19 @@ claim_lport(const struct sbrec_port_binding *pb, - return false; - } - } else { -- if (pb->n_up && !pb->up[0]) { -+ if ((pb->n_up && !pb->up[0]) || -+ !smap_get_bool(&iface_rec->external_ids, -+ OVN_INSTALLED_EXT_ID, false)) { - if_status_mgr_claim_iface(if_mgr, pb, chassis_rec, -- sb_readonly); -+ iface_rec, sb_readonly, -+ can_bind); - } - } - } - } else if (can_bind == CAN_BIND_AS_ADDITIONAL) { - if (!is_additional_chassis(pb, chassis_rec)) { -- if (sb_readonly) { -- return false; -- } -- -- VLOG_INFO("Claiming lport %s for this additional chassis.", -- pb->logical_port); -- for (size_t i = 0; i < pb->n_mac; i++) { -- VLOG_INFO("%s: Claiming %s", pb->logical_port, pb->mac[i]); -- } -- -- sbrec_port_binding_update_additional_chassis_addvalue(pb, -- chassis_rec); -- if (pb->chassis == chassis_rec) { -- sbrec_port_binding_set_chassis(pb, NULL); -- } -+ if_status_mgr_claim_iface(if_mgr, pb, chassis_rec, iface_rec, -+ sb_readonly, can_bind); - update_tracked = true; - } - } -@@ -1464,9 +1523,11 @@ consider_vif_lport_(const struct sbrec_port_binding *pb, - const char *requested_chassis_option = smap_get( - &pb->options, "requested-chassis"); - VLOG_INFO_RL(&rl, -- "Not claiming lport %s, chassis %s requested-chassis %s", -+ "Not claiming lport %s, chassis %s requested-chassis %s " -+ "pb->chassis %s", - pb->logical_port, b_ctx_in->chassis_rec->name, -- requested_chassis_option ? requested_chassis_option : "[]"); -+ requested_chassis_option ? requested_chassis_option : "[]", -+ pb->chassis ? pb->chassis->name: ""); - } - } - -@@ -2030,7 +2091,7 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) - free(lnet_lport); - } - -- /* Run through external lport list to see if these are external ports -+ /* Run through external lport list to see if there are external ports - * on local datapaths discovered from above loop, and update the - * corresponding local datapath accordingly. */ - struct lport *ext_lport; -@@ -2039,7 +2100,7 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) - free(ext_lport); - } - -- /* Run through multichassis lport list to see if these are ports -+ /* Run through multichassis lport list to see if there are ports - * on local datapaths discovered from above loop, and update the - * corresponding local datapath accordingly. */ - struct lport *multichassis_lport; -@@ -2288,6 +2349,11 @@ consider_iface_release(const struct ovsrec_interface *iface_rec, - return false; - } - } -+ if (lbinding->iface && lbinding->iface->name) { -+ if_status_mgr_remove_ovn_installed(b_ctx_out->if_mgr, -+ lbinding->iface->name, -+ &lbinding->iface->header_.uuid); -+ } - - } else if (lbinding && b_lport && b_lport->type == LP_LOCALPORT) { - /* lbinding is associated with a localport. Remove it from the -@@ -2558,6 +2624,7 @@ handle_deleted_lport(const struct sbrec_port_binding *pb, - if (ld) { - remove_pb_from_local_datapath(pb, - b_ctx_out, ld); -+ if_status_mgr_release_iface(b_ctx_out->if_mgr, pb->logical_port); - return; - } - -@@ -2581,6 +2648,7 @@ handle_deleted_lport(const struct sbrec_port_binding *pb, - remove_pb_from_local_datapath(pb, b_ctx_out, - ld); - } -+ if_status_mgr_release_iface(b_ctx_out->if_mgr, pb->logical_port); - } - } - -@@ -2627,6 +2695,11 @@ handle_deleted_vif_lport(const struct sbrec_port_binding *pb, - } - - handle_deleted_lport(pb, b_ctx_in, b_ctx_out); -+ if (lbinding && lbinding->iface && lbinding->iface->name) { -+ if_status_mgr_remove_ovn_installed(b_ctx_out->if_mgr, -+ lbinding->iface->name, -+ &lbinding->iface->header_.uuid); -+ } - return true; - } - -@@ -3314,6 +3387,24 @@ binding_lport_delete(struct shash *binding_lports, - binding_lport_destroy(b_lport); - } - -+void -+port_binding_set_down(const struct sbrec_chassis *chassis_rec, -+ const struct sbrec_port_binding_table *pb_table, -+ const char *iface_id, -+ const struct uuid *pb_uuid) -+{ -+ const struct sbrec_port_binding *pb = -+ sbrec_port_binding_table_get_for_uuid(pb_table, pb_uuid); -+ if (!pb) { -+ VLOG_DBG("port_binding already deleted for %s", iface_id); -+ } else if (pb->n_up && pb->up[0]) { -+ bool up = false; -+ sbrec_port_binding_set_up(pb, &up, 1); -+ VLOG_INFO("Setting lport %s down in Southbound", pb->logical_port); -+ set_pb_chassis_in_sbrec(pb, chassis_rec, false); -+ } -+} -+ - static void - binding_lport_set_up(struct binding_lport *b_lport, bool sb_readonly) - { -@@ -3331,6 +3422,7 @@ binding_lport_set_down(struct binding_lport *b_lport, bool sb_readonly) - if (sb_readonly || !b_lport || !b_lport->pb->n_up || !b_lport->pb->up[0]) { - return; - } -+ VLOG_INFO("Setting lport %s down in Southbound", b_lport->name); - - bool up = false; - sbrec_port_binding_set_up(b_lport->pb, &up, 1); -diff --git a/controller/binding.h b/controller/binding.h -index 6c3a98b02..46e618b97 100644 ---- a/controller/binding.h -+++ b/controller/binding.h -@@ -159,6 +159,14 @@ bool local_binding_is_up(struct shash *local_bindings, const char *pb_name, - bool local_binding_is_down(struct shash *local_bindings, const char *pb_name, - const struct sbrec_chassis *); - -+bool local_binding_is_ovn_installed(struct shash *local_bindings, -+ const char *pb_name); -+void local_binding_remove_ovn_installed( -+ struct shash *local_bindings, -+ const struct ovsrec_interface_table *iface_table, -+ const char *pb_name, -+ bool ovs_readonly); -+ - void local_binding_set_up(struct shash *local_bindings, const char *pb_name, - const struct sbrec_chassis *chassis_rec, - const char *ts_now_str, bool sb_readonly, -@@ -194,6 +202,18 @@ bool is_additional_chassis(const struct sbrec_port_binding *pb, - void set_pb_chassis_in_sbrec(const struct sbrec_port_binding *pb, - const struct sbrec_chassis *chassis_rec, - bool is_set); -+void -+set_pb_additional_chassis_in_sbrec(const struct sbrec_port_binding *pb, -+ const struct sbrec_chassis *chassis_rec, -+ bool is_set); -+ -+void remove_ovn_installed_for_uuid(const struct ovsrec_interface_table *, -+ const struct uuid *); -+ -+void port_binding_set_down(const struct sbrec_chassis *chassis_rec, -+ const struct sbrec_port_binding_table *pb_table, -+ const char *iface_id, -+ const struct uuid *pb_uuid); - - /* Corresponds to each Port_Binding.type. */ - enum en_lport_type { -diff --git a/controller/encaps.c b/controller/encaps.c -index 2662eaf98..b69d72584 100644 ---- a/controller/encaps.c -+++ b/controller/encaps.c -@@ -36,6 +36,8 @@ VLOG_DEFINE_THIS_MODULE(encaps); - */ - #define OVN_MVTEP_CHASSISID_DELIM '@' - -+static char *current_br_int_name = NULL; -+ - void - encaps_register_ovs_idl(struct ovsdb_idl *ovs_idl) - { -@@ -386,6 +388,21 @@ chassis_tzones_overlap(const struct sset *transport_zones, - return false; - } - -+static void -+clear_old_tunnels(const struct ovsrec_bridge *old_br_int, const char *prefix, -+ size_t prefix_len) -+{ -+ for (size_t i = 0; i < old_br_int->n_ports; i++) { -+ const struct ovsrec_port *port = old_br_int->ports[i]; -+ const char *id = smap_get(&port->external_ids, "ovn-chassis-id"); -+ if (id && !strncmp(port->name, prefix, prefix_len)) { -+ VLOG_DBG("Clearing old tunnel port \"%s\" (%s) from bridge " -+ "\"%s\".", port->name, id, old_br_int->name); -+ ovsrec_bridge_update_ports_delvalue(old_br_int, port); -+ } -+ } -+} -+ - void - encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, - const struct ovsrec_bridge *br_int, -@@ -393,12 +410,42 @@ encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, - const struct sbrec_chassis *this_chassis, - const struct sbrec_sb_global *sbg, - const struct ovsrec_open_vswitch_table *ovs_table, -- const struct sset *transport_zones) -+ const struct sset *transport_zones, -+ const struct ovsrec_bridge_table *bridge_table) - { - if (!ovs_idl_txn || !br_int) { - return; - } - -+ if (!current_br_int_name) { -+ /* The controller has just started, we need to look through all -+ * bridges for old tunnel ports. */ -+ char *tunnel_prefix = xasprintf("ovn%s-", get_chassis_idx(ovs_table)); -+ size_t prefix_len = strlen(tunnel_prefix); -+ -+ const struct ovsrec_bridge *br; -+ OVSREC_BRIDGE_TABLE_FOR_EACH (br, bridge_table) { -+ if (!strcmp(br->name, br_int->name)) { -+ continue; -+ } -+ clear_old_tunnels(br, tunnel_prefix, prefix_len); -+ } -+ -+ free(tunnel_prefix); -+ current_br_int_name = xstrdup(br_int->name); -+ } else if (strcmp(current_br_int_name, br_int->name)) { -+ /* The integration bridge was changed, clear tunnel ports from -+ * the old one. */ -+ const struct ovsrec_bridge *old_br_int = -+ get_bridge(bridge_table, current_br_int_name); -+ if (old_br_int) { -+ clear_old_tunnels(old_br_int, "", 0); -+ } -+ -+ free(current_br_int_name); -+ current_br_int_name = xstrdup(br_int->name); -+ } -+ - const struct sbrec_chassis *chassis_rec; - - struct tunnel_ctx tc = { -@@ -511,3 +558,9 @@ encaps_cleanup(struct ovsdb_idl_txn *ovs_idl_txn, - - return !any_changes; - } -+ -+void -+encaps_destroy(void) -+{ -+ free(current_br_int_name); -+} -diff --git a/controller/encaps.h b/controller/encaps.h -index 867c6f28c..3e58b3c82 100644 ---- a/controller/encaps.h -+++ b/controller/encaps.h -@@ -35,7 +35,8 @@ void encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, - const struct sbrec_chassis *, - const struct sbrec_sb_global *, - const struct ovsrec_open_vswitch_table *, -- const struct sset *transport_zones); -+ const struct sset *transport_zones, -+ const struct ovsrec_bridge_table *bridge_table); - - bool encaps_cleanup(struct ovsdb_idl_txn *ovs_idl_txn, - const struct ovsrec_bridge *br_int); -@@ -46,4 +47,6 @@ bool encaps_tunnel_id_parse(const char *tunnel_id, char **chassis_id, - bool encaps_tunnel_id_match(const char *tunnel_id, const char *chassis_id, - const char *encap_ip); - -+void encaps_destroy(void); -+ - #endif /* controller/encaps.h */ -diff --git a/controller/if-status.c b/controller/if-status.c -index d1c14ac30..2b2eb1679 100644 ---- a/controller/if-status.c -+++ b/controller/if-status.c -@@ -18,12 +18,14 @@ - #include "binding.h" - #include "if-status.h" - #include "ofctrl-seqno.h" -+#include "ovsport.h" - #include "simap.h" - - #include "lib/hmapx.h" - #include "lib/util.h" - #include "timeval.h" - #include "openvswitch/vlog.h" -+#include "lib/vswitch-idl.h" - #include "lib/ovn-sb-idl.h" - - VLOG_DEFINE_THIS_MODULE(if_status); -@@ -54,44 +56,54 @@ VLOG_DEFINE_THIS_MODULE(if_status); - */ - - enum if_state { -- OIF_CLAIMED, /* Newly claimed interface. pb->chassis update not yet -- initiated. */ -- OIF_INSTALL_FLOWS, /* Claimed interface with pb->chassis update sent to -- * SB (but update notification not confirmed, so the -- * update may be resent in any of the following states) -- * and for which flows are still being installed. -- */ -- OIF_MARK_UP, /* Interface with flows successfully installed in OVS -- * but not yet marked "up" in the binding module (in -- * SB and OVS databases). -- */ -- OIF_MARK_DOWN, /* Released interface but not yet marked "down" in the -- * binding module (in SB and/or OVS databases). -- */ -- OIF_INSTALLED, /* Interface flows programmed in OVS and binding marked -- * "up" in the binding module. -- */ -+ OIF_CLAIMED, /* Newly claimed interface. pb->chassis update not -+ yet initiated. */ -+ OIF_INSTALL_FLOWS, /* Claimed interface with pb->chassis update sent to -+ * SB (but update notification not confirmed, so the -+ * update may be resent in any of the following -+ * states and for which flows are still being -+ * installed. -+ */ -+ OIF_REM_OLD_OVN_INST, /* Interface with flows successfully installed in OVS -+ * but with ovn-installed still in OVSDB. -+ */ -+ OIF_MARK_UP, /* Interface with flows successfully installed in OVS -+ * but not yet marked "up" in the binding module (in -+ * SB and OVS databases). -+ */ -+ OIF_MARK_DOWN, /* Released interface but not yet marked "down" in -+ * the binding module (in SB and/or OVS databases). -+ */ -+ OIF_INSTALLED, /* Interface flows programmed in OVS and binding -+ * marked "up" in the binding module. -+ */ -+ OIF_UPDATE_PORT, /* Logical ports need to be set down, and pb->chassis -+ * removed. -+ */ - OIF_MAX, - }; - - static const char *if_state_names[] = { -- [OIF_CLAIMED] = "CLAIMED", -- [OIF_INSTALL_FLOWS] = "INSTALL_FLOWS", -- [OIF_MARK_UP] = "MARK_UP", -- [OIF_MARK_DOWN] = "MARK_DOWN", -- [OIF_INSTALLED] = "INSTALLED", -+ [OIF_CLAIMED] = "CLAIMED", -+ [OIF_INSTALL_FLOWS] = "INSTALL_FLOWS", -+ [OIF_REM_OLD_OVN_INST] = "REM_OLD_OVN_INST", -+ [OIF_MARK_UP] = "MARK_UP", -+ [OIF_MARK_DOWN] = "MARK_DOWN", -+ [OIF_INSTALLED] = "INSTALLED", -+ [OIF_UPDATE_PORT] = "UPDATE_PORT", - }; - - /* - * +----------------------+ - * +---> | | -- * | +-> | NULL | <--------------------------------------+++-+ -- * | | +----------------------+ | -- * | | ^ release_iface | claim_iface() | -- * | | | V - sbrec_update_chassis(if sb is rw) | -- * | | +----------------------+ | -- * | | | | <----------------------------------------+ | -- * | | | CLAIMED | <--------------------------------------+ | | -+ * | +-> | NULL | -+ * | | +----------------------+ -+ * | | ^ release_iface | claim_iface() -+ * | | | V - sbrec_update_chassis(if sb is rw) -+ * | | +----------------------+ -+ * | | | | <------------------------------------------+ -+ * | | | CLAIMED | <----------------------------------------+ | -+ * | | | | <--------------------------------------+ | | - * | | +----------------------+ | | | - * | | | V ^ | | | - * | | | | | handle_claims() | | | -@@ -109,43 +121,69 @@ static const char *if_state_names[] = { - * | | | - remove ovn-installed from ovsdb | | | - * | | | mgr_update() | | | - * | +----------------------+ - sbrec_update_chassis if needed | | | -- * | | | | | -- * | | mgr_run(seqno rcvd) | | | -- * | | - set port up in sb | | | -- * | release_iface | - set ovn-installed in ovs | | | -- * | V | | | -+ * | | | | | | -+ * | | +----------------------------------------+ | | | -+ * | | | | | | -+ * | | mgr_run(seqno rcvd, ovn-installed present) | | | | -+ * | V | | | | -+ * | +--------------------+ | | | | -+ * | | | mgr_run() | | | | -+ * +--- | REM_OLD_OVN_INST | - remove ovn-installed in ovs | | | | -+ * | +--------------------+ | | | | -+ * | | | | | | -+ * | | | | | | -+ * | | mgr_update( ovn_installed not present) | | | | -+ * | | | | | | -+ * | | +-------------------------------------------+ | | | -+ * | | | | | | -+ * | | | mgr_run(seqno rcvd, ovn-installed not present) | | | -+ * | | | - set port up in sb | | | -+ * | | | - set ovn-installed in ovs | | | -+ * |release_iface | | | | | -+ * | V V | | | - * | +----------------------+ | | | - * | | | mgr_run() | | | -- * +-- | MARK_UP | - set port up in sb | | | -- * | | - set ovn-installed in ovs | | | -- * | | mgr_update() | | | -- * +----------------------+ - sbrec_update_chassis if needed | | | -- * | | | | -- * | mgr_update(rcvd port up / ovn_installed & chassis set) | | | -- * V | | | -- * +----------------------+ | | | -- * | INSTALLED | ------------> claim_iface ---------------+ | | -- * +----------------------+ | | -- * | | | -- * | release_iface | | -- * V | | -- * +----------------------+ | | -- * | | ------------> claim_iface -----------------+ | -- * | MARK_DOWN | ------> mgr_update(rcvd port down) ----------+ -- * | | mgr_run() -- * | | - set port down in sb -- * | | mgr_update() -+ * +---| MARK_UP | - set port up in sb | | | -+ * | | | - set ovn-installed in ovs | | | -+ * | | | mgr_update() | | | -+ * | +----------------------+ - sbrec_update_chassis if needed | | | -+ * | | | | | -+ * | | mgr_update(rcvd port up / ovn_installed & chassis set) | | | -+ * | V | | | -+ * | +----------------------+ | | | -+ * | | INSTALLED | ------------> claim_iface ---------------+ | | -+ * | +----------------------+ | | -+ * | | | | -+ * | | release_iface | | -+ * |mgr_update( | | | -+ * | rcvd port down) | | | -+ * | V | | -+ * | +----------------------+ | | -+ * | | | ------------> claim_iface -----------------+ | -+ * +---+ MARK_DOWN | mgr_run() | -+ * | | | - set port down in sb | -+ * | | | mgr_update(sb is rw) | -+ * | +----------------------+ - sbrec_update_chassis(NULL) | -+ * | | | -+ * | | mgr_update(local binding not found) | -+ * | | | -+ * | V | -+ * | +----------------------+ | -+ * | | | ------------> claim_iface -------------------+ -+ * +---+ UPDATE_PORT | mgr_run() - * +----------------------+ - sbrec_update_chassis(NULL) - */ - - - struct ovs_iface { - char *id; /* Extracted from OVS external_ids.iface_id. */ -+ struct uuid pb_uuid; /* Port_binding uuid */ - enum if_state state; /* State of the interface in the state machine. */ - uint32_t install_seqno; /* Seqno at which this interface is expected to - * be fully programmed in OVS. Only used in state - * OIF_INSTALL_FLOWS. - */ -+ uint16_t mtu; /* Extracted from OVS interface.mtu field. */ - }; - - static uint64_t ifaces_usage; -@@ -155,6 +193,9 @@ struct if_status_mgr { - /* All local interfaces, mapping from 'iface-id' to 'struct ovs_iface'. */ - struct shash ifaces; - -+ /* local interfaces which need ovn-install removal */ -+ struct shash ovn_uninstall_hash; -+ - /* All local interfaces, stored per state. */ - struct hmapx ifaces_per_state[OIF_MAX]; - -@@ -167,18 +208,24 @@ struct if_status_mgr { - uint32_t iface_seqno; - }; - --static struct ovs_iface *ovs_iface_create(struct if_status_mgr *, -- const char *iface_id, -- enum if_state ); -+static struct ovs_iface * -+ovs_iface_create(struct if_status_mgr *, const char *iface_id, -+ const struct ovsrec_interface *iface_rec, -+ enum if_state); -+static void add_to_ovn_uninstall_hash(struct if_status_mgr *, const char *, -+ const struct uuid *); - static void ovs_iface_destroy(struct if_status_mgr *, struct ovs_iface *); -+static void ovn_uninstall_hash_destroy(struct if_status_mgr *mgr, char *name); - static void ovs_iface_set_state(struct if_status_mgr *, struct ovs_iface *, - enum if_state); - - static void if_status_mgr_update_bindings( - struct if_status_mgr *mgr, struct local_binding_data *binding_data, - const struct sbrec_chassis *, -+ const struct ovsrec_interface_table *iface_table, - bool sb_readonly, bool ovs_readonly); - -+static void ovn_uninstall_hash_account_mem(const char *name, bool erase); - struct if_status_mgr * - if_status_mgr_create(void) - { -@@ -189,6 +236,7 @@ if_status_mgr_create(void) - hmapx_init(&mgr->ifaces_per_state[i]); - } - shash_init(&mgr->ifaces); -+ shash_init(&mgr->ovn_uninstall_hash); - return mgr; - } - -@@ -202,6 +250,11 @@ if_status_mgr_clear(struct if_status_mgr *mgr) - } - ovs_assert(shash_is_empty(&mgr->ifaces)); - -+ SHASH_FOR_EACH_SAFE (node, &mgr->ovn_uninstall_hash) { -+ ovn_uninstall_hash_destroy(mgr, node->data); -+ } -+ ovs_assert(shash_is_empty(&mgr->ovn_uninstall_hash)); -+ - for (size_t i = 0; i < ARRAY_SIZE(mgr->ifaces_per_state); i++) { - ovs_assert(hmapx_is_empty(&mgr->ifaces_per_state[i])); - } -@@ -212,6 +265,7 @@ if_status_mgr_destroy(struct if_status_mgr *mgr) - { - if_status_mgr_clear(mgr); - shash_destroy(&mgr->ifaces); -+ shash_destroy(&mgr->ovn_uninstall_hash); - for (size_t i = 0; i < ARRAY_SIZE(mgr->ifaces_per_state); i++) { - hmapx_destroy(&mgr->ifaces_per_state[i]); - } -@@ -222,27 +276,35 @@ void - if_status_mgr_claim_iface(struct if_status_mgr *mgr, - const struct sbrec_port_binding *pb, - const struct sbrec_chassis *chassis_rec, -- bool sb_readonly) -+ const struct ovsrec_interface *iface_rec, -+ bool sb_readonly, enum can_bind bind_type) - { - const char *iface_id = pb->logical_port; - struct ovs_iface *iface = shash_find_data(&mgr->ifaces, iface_id); - - if (!iface) { -- iface = ovs_iface_create(mgr, iface_id, OIF_CLAIMED); -+ iface = ovs_iface_create(mgr, iface_id, iface_rec, OIF_CLAIMED); - } - -+ memcpy(&iface->pb_uuid, &pb->header_.uuid, sizeof(iface->pb_uuid)); - if (!sb_readonly) { -- set_pb_chassis_in_sbrec(pb, chassis_rec, true); -+ if (bind_type == CAN_BIND_AS_MAIN) { -+ set_pb_chassis_in_sbrec(pb, chassis_rec, true); -+ } else if (bind_type == CAN_BIND_AS_ADDITIONAL) { -+ set_pb_additional_chassis_in_sbrec(pb, chassis_rec, true); -+ } - } - - switch (iface->state) { - case OIF_CLAIMED: - case OIF_INSTALL_FLOWS: -+ case OIF_REM_OLD_OVN_INST: - case OIF_MARK_UP: - /* Nothing to do here. */ - break; - case OIF_INSTALLED: - case OIF_MARK_DOWN: -+ case OIF_UPDATE_PORT: - ovs_iface_set_state(mgr, iface, OIF_CLAIMED); - break; - case OIF_MAX: -@@ -271,9 +333,10 @@ if_status_mgr_release_iface(struct if_status_mgr *mgr, const char *iface_id) - switch (iface->state) { - case OIF_CLAIMED: - case OIF_INSTALL_FLOWS: -- /* Not yet fully installed interfaces can be safely deleted. */ -- ovs_iface_destroy(mgr, iface); -- break; -+ /* Not yet fully installed interfaces: -+ * pb->chassis still need to be deleted. -+ */ -+ case OIF_REM_OLD_OVN_INST: - case OIF_MARK_UP: - case OIF_INSTALLED: - /* Properly mark interfaces "down" if their flows were already -@@ -282,6 +345,7 @@ if_status_mgr_release_iface(struct if_status_mgr *mgr, const char *iface_id) - ovs_iface_set_state(mgr, iface, OIF_MARK_DOWN); - break; - case OIF_MARK_DOWN: -+ case OIF_UPDATE_PORT: - /* Nothing to do here. */ - break; - case OIF_MAX: -@@ -302,9 +366,10 @@ if_status_mgr_delete_iface(struct if_status_mgr *mgr, const char *iface_id) - switch (iface->state) { - case OIF_CLAIMED: - case OIF_INSTALL_FLOWS: -- /* Not yet fully installed interfaces can be safely deleted. */ -- ovs_iface_destroy(mgr, iface); -- break; -+ /* Not yet fully installed interfaces: -+ * pb->chassis still need to be deleted. -+ */ -+ case OIF_REM_OLD_OVN_INST: - case OIF_MARK_UP: - case OIF_INSTALLED: - /* Properly mark interfaces "down" if their flows were already -@@ -313,6 +378,7 @@ if_status_mgr_delete_iface(struct if_status_mgr *mgr, const char *iface_id) - ovs_iface_set_state(mgr, iface, OIF_MARK_DOWN); - break; - case OIF_MARK_DOWN: -+ case OIF_UPDATE_PORT: - /* Nothing to do here. */ - break; - case OIF_MAX: -@@ -346,12 +412,34 @@ if_status_handle_claims(struct if_status_mgr *mgr, - return rc; - } - -+static void -+clean_ovn_installed(struct if_status_mgr *mgr, -+ const struct ovsrec_interface_table *iface_table) -+{ -+ struct shash_node *node; -+ -+ SHASH_FOR_EACH_SAFE (node, &mgr->ovn_uninstall_hash) { -+ const struct uuid *iface_uuid = node->data; -+ remove_ovn_installed_for_uuid(iface_table, iface_uuid); -+ free(node->data); -+ char *node_name = shash_steal(&mgr->ovn_uninstall_hash, node); -+ ovn_uninstall_hash_account_mem(node_name, true); -+ free(node_name); -+ } -+} -+ - void - if_status_mgr_update(struct if_status_mgr *mgr, - struct local_binding_data *binding_data, - const struct sbrec_chassis *chassis_rec, -+ const struct ovsrec_interface_table *iface_table, -+ const struct sbrec_port_binding_table *pb_table, -+ bool ovs_readonly, - bool sb_readonly) - { -+ if (!ovs_readonly) { -+ clean_ovn_installed(mgr, iface_table); -+ } - if (!binding_data) { - return; - } -@@ -359,6 +447,17 @@ if_status_mgr_update(struct if_status_mgr *mgr, - struct shash *bindings = &binding_data->bindings; - struct hmapx_node *node; - -+ /* Move all interfaces that have been confirmed without ovn-installed, -+ * from OIF_REM_OLD_OVN_INST to OIF_MARK_UP. -+ */ -+ HMAPX_FOR_EACH_SAFE (node, &mgr->ifaces_per_state[OIF_REM_OLD_OVN_INST]) { -+ struct ovs_iface *iface = node->data; -+ -+ if (!local_binding_is_ovn_installed(bindings, iface->id)) { -+ ovs_iface_set_state(mgr, iface, OIF_MARK_UP); -+ } -+ } -+ - /* Interfaces in OIF_MARK_UP/INSTALL_FLOWS state have already set their - * pb->chassis. However, the update might still be in fly (confirmation - * not received yet) or pb->chassis was overwitten by another chassis. -@@ -390,6 +489,10 @@ if_status_mgr_update(struct if_status_mgr *mgr, - HMAPX_FOR_EACH_SAFE (node, &mgr->ifaces_per_state[OIF_MARK_DOWN]) { - struct ovs_iface *iface = node->data; - -+ if (!local_binding_find(bindings, iface->id)) { -+ ovs_iface_set_state(mgr, iface, OIF_UPDATE_PORT); -+ continue; -+ } - if (!sb_readonly) { - local_binding_set_pb(bindings, iface->id, chassis_rec, - NULL, false); -@@ -437,6 +540,21 @@ if_status_mgr_update(struct if_status_mgr *mgr, - } - } - -+ if (!sb_readonly) { -+ HMAPX_FOR_EACH_SAFE (node, &mgr->ifaces_per_state[OIF_UPDATE_PORT]) { -+ struct ovs_iface *iface = node->data; -+ port_binding_set_down(chassis_rec, pb_table, iface->id, -+ &iface->pb_uuid); -+ ovs_iface_destroy(mgr, node->data); -+ } -+ } else { -+ HMAPX_FOR_EACH_SAFE (node, &mgr->ifaces_per_state[OIF_UPDATE_PORT]) { -+ struct ovs_iface *iface = node->data; -+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); -+ VLOG_INFO_RL(&rl, "Not setting lport %s down as sb is readonly", -+ iface->id); -+ } -+ } - /* Register for a notification about flows being installed in OVS for all - * newly claimed interfaces for which pb->chassis has been updated. - * Request a seqno update when the flows for new interfaces have been -@@ -450,10 +568,23 @@ if_status_mgr_update(struct if_status_mgr *mgr, - } - } - -+void -+if_status_mgr_remove_ovn_installed(struct if_status_mgr *mgr, -+ const char *name, -+ const struct uuid *uuid) -+{ -+ VLOG_DBG("Adding %s to list of interfaces for which to remove " -+ "ovn-installed", name); -+ if (!shash_find_data(&mgr->ovn_uninstall_hash, name)) { -+ add_to_ovn_uninstall_hash(mgr, name, uuid); -+ } -+} -+ - void - if_status_mgr_run(struct if_status_mgr *mgr, - struct local_binding_data *binding_data, - const struct sbrec_chassis *chassis_rec, -+ const struct ovsrec_interface_table *iface_table, - bool sb_readonly, bool ovs_readonly) - { - struct ofctrl_acked_seqnos *acked_seqnos = -@@ -471,12 +602,25 @@ if_status_mgr_run(struct if_status_mgr *mgr, - iface->install_seqno)) { - continue; - } -- ovs_iface_set_state(mgr, iface, OIF_MARK_UP); -+ /* Wait for ovn-installed to be absent before moving to MARK_UP state. -+ * Most of the times ovn-installed is already absent and hence we will -+ * not have to wait. -+ * If there is no binding_data, we can't determine if ovn-installed is -+ * present or not; hence also go to the OIF_REM_OLD_OVN_INST state. -+ */ -+ if (!binding_data || -+ local_binding_is_ovn_installed(&binding_data->bindings, -+ iface->id)) { -+ ovs_iface_set_state(mgr, iface, OIF_REM_OLD_OVN_INST); -+ } else { -+ ovs_iface_set_state(mgr, iface, OIF_MARK_UP); -+ } - } - ofctrl_acked_seqnos_destroy(acked_seqnos); - - /* Update binding states. */ - if_status_mgr_update_bindings(mgr, binding_data, chassis_rec, -+ iface_table, - sb_readonly, ovs_readonly); - } - -@@ -492,8 +636,46 @@ ovs_iface_account_mem(const char *iface_id, bool erase) - } - } - -+static void -+ovn_uninstall_hash_account_mem(const char *name, bool erase) -+{ -+ uint32_t size = (strlen(name) + sizeof(struct uuid) + -+ sizeof(struct shash_node)); -+ if (erase) { -+ ifaces_usage -= size; -+ } else { -+ ifaces_usage += size; -+ } -+} -+ -+uint16_t -+if_status_mgr_iface_get_mtu(const struct if_status_mgr *mgr, -+ const char *iface_id) -+{ -+ const struct ovs_iface *iface = shash_find_data(&mgr->ifaces, iface_id); -+ return iface ? iface->mtu : 0; -+} -+ -+bool -+if_status_mgr_iface_update(const struct if_status_mgr *mgr, -+ const struct ovsrec_interface *iface_rec) -+{ -+ const char *iface_id = smap_get(&iface_rec->external_ids, "iface-id"); -+ if (!iface_id) { -+ return false; -+ } -+ uint16_t mtu = get_iface_mtu(iface_rec); -+ struct ovs_iface *iface = shash_find_data(&mgr->ifaces, iface_id); -+ if (iface && iface->mtu != mtu) { -+ iface->mtu = mtu; -+ return true; -+ } -+ return false; -+} -+ - static struct ovs_iface * - ovs_iface_create(struct if_status_mgr *mgr, const char *iface_id, -+ const struct ovsrec_interface *iface_rec, - enum if_state state) - { - struct ovs_iface *iface = xzalloc(sizeof *iface); -@@ -503,9 +685,20 @@ ovs_iface_create(struct if_status_mgr *mgr, const char *iface_id, - shash_add_nocopy(&mgr->ifaces, iface->id, iface); - ovs_iface_set_state(mgr, iface, state); - ovs_iface_account_mem(iface_id, false); -+ if_status_mgr_iface_update(mgr, iface_rec); - return iface; - } - -+static void -+add_to_ovn_uninstall_hash(struct if_status_mgr *mgr, const char *name, -+ const struct uuid *uuid) -+{ -+ struct uuid *new_uuid = xzalloc(sizeof *new_uuid); -+ memcpy(new_uuid, uuid, sizeof(*new_uuid)); -+ shash_add(&mgr->ovn_uninstall_hash, name, new_uuid); -+ ovn_uninstall_hash_account_mem(name, false); -+} -+ - static void - ovs_iface_destroy(struct if_status_mgr *mgr, struct ovs_iface *iface) - { -@@ -521,6 +714,23 @@ ovs_iface_destroy(struct if_status_mgr *mgr, struct ovs_iface *iface) - free(iface); - } - -+static void -+ovn_uninstall_hash_destroy(struct if_status_mgr *mgr, char *name) -+{ -+ struct shash_node *node = shash_find(&mgr->ovn_uninstall_hash, name); -+ char *node_name = NULL; -+ if (node) { -+ free(node->data); -+ VLOG_DBG("Interface name %s destroy", name); -+ node_name = shash_steal(&mgr->ovn_uninstall_hash, node); -+ ovn_uninstall_hash_account_mem(name, true); -+ free(node_name); -+ } else { -+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); -+ VLOG_WARN_RL(&rl, "Interface name %s not found", name); -+ } -+} -+ - static void - ovs_iface_set_state(struct if_status_mgr *mgr, struct ovs_iface *iface, - enum if_state state) -@@ -539,6 +749,7 @@ static void - if_status_mgr_update_bindings(struct if_status_mgr *mgr, - struct local_binding_data *binding_data, - const struct sbrec_chassis *chassis_rec, -+ const struct ovsrec_interface_table *iface_table, - bool sb_readonly, bool ovs_readonly) - { - if (!binding_data) { -@@ -558,7 +769,17 @@ if_status_mgr_update_bindings(struct if_status_mgr *mgr, - sb_readonly, ovs_readonly); - } - -- /* Notifiy the binding module to set "up" all bindings that have had -+ /* Notify the binding module to remove "ovn-installed" for all bindings -+ * in the OIF_REM_OLD_OVN_INST state. -+ */ -+ HMAPX_FOR_EACH (node, &mgr->ifaces_per_state[OIF_REM_OLD_OVN_INST]) { -+ struct ovs_iface *iface = node->data; -+ -+ local_binding_remove_ovn_installed(bindings, iface_table, iface->id, -+ ovs_readonly); -+ } -+ -+ /* Notify the binding module to set "up" all bindings that have had - * their flows installed but are not yet marked "up" in the binding - * module. - */ -diff --git a/controller/if-status.h b/controller/if-status.h -index 5bd187a25..15624bcfa 100644 ---- a/controller/if-status.h -+++ b/controller/if-status.h -@@ -17,8 +17,10 @@ - #define IF_STATUS_H 1 - - #include "openvswitch/shash.h" -+#include "lib/vswitch-idl.h" - - #include "binding.h" -+#include "lport.h" - - struct if_status_mgr; - struct simap; -@@ -29,15 +31,20 @@ void if_status_mgr_destroy(struct if_status_mgr *); - void if_status_mgr_claim_iface(struct if_status_mgr *, - const struct sbrec_port_binding *pb, - const struct sbrec_chassis *chassis_rec, -- bool sb_readonly); -+ const struct ovsrec_interface *iface_rec, -+ bool sb_readonly, enum can_bind bind_type); - void if_status_mgr_release_iface(struct if_status_mgr *, const char *iface_id); - void if_status_mgr_delete_iface(struct if_status_mgr *, const char *iface_id); - - void if_status_mgr_update(struct if_status_mgr *, struct local_binding_data *, - const struct sbrec_chassis *chassis, -+ const struct ovsrec_interface_table *iface_table, -+ const struct sbrec_port_binding_table *pb_table, -+ bool ovs_readonly, - bool sb_readonly); - void if_status_mgr_run(struct if_status_mgr *mgr, struct local_binding_data *, - const struct sbrec_chassis *, -+ const struct ovsrec_interface_table *iface_table, - bool sb_readonly, bool ovs_readonly); - void if_status_mgr_get_memory_usage(struct if_status_mgr *mgr, - struct simap *usage); -@@ -48,5 +55,12 @@ bool if_status_handle_claims(struct if_status_mgr *mgr, - const struct sbrec_chassis *chassis_rec, - struct hmap *tracked_datapath, - bool sb_readonly); -+void if_status_mgr_remove_ovn_installed(struct if_status_mgr *mgr, -+ const char *name, -+ const struct uuid *uuid); -+uint16_t if_status_mgr_iface_get_mtu(const struct if_status_mgr *mgr, -+ const char *iface_id); -+bool if_status_mgr_iface_update(const struct if_status_mgr *mgr, -+ const struct ovsrec_interface *iface_rec); - - # endif /* controller/if-status.h */ -diff --git a/controller/lflow.c b/controller/lflow.c -index 6a98b19e1..22faaf013 100644 ---- a/controller/lflow.c -+++ b/controller/lflow.c -@@ -397,7 +397,7 @@ consider_lflow_for_added_as_ips__( - : OFTABLE_LOG_EGRESS_PIPELINE); - uint8_t ptable = first_ptable + lflow->table_id; - uint8_t output_ptable = (ingress -- ? OFTABLE_REMOTE_OUTPUT -+ ? OFTABLE_OUTPUT_INIT - : OFTABLE_SAVE_INPORT); - - uint64_t ovnacts_stub[1024 / 8]; -@@ -1067,7 +1067,7 @@ consider_logical_flow__(const struct sbrec_logical_flow *lflow, - : OFTABLE_LOG_EGRESS_PIPELINE); - uint8_t ptable = first_ptable + lflow->table_id; - uint8_t output_ptable = (ingress -- ? OFTABLE_REMOTE_OUTPUT -+ ? OFTABLE_OUTPUT_INIT - : OFTABLE_SAVE_INPORT); - - /* Parse OVN logical actions. -@@ -1729,6 +1729,7 @@ add_lb_vip_hairpin_flows(const struct ovn_controller_lb *lb, - - static void - add_lb_ct_snat_hairpin_for_dp(const struct ovn_controller_lb *lb, -+ bool has_vip_port, - const struct sbrec_datapath_binding *datapath, - const struct hmap *local_datapaths, - struct match *dp_match, -@@ -1742,15 +1743,21 @@ add_lb_ct_snat_hairpin_for_dp(const struct ovn_controller_lb *lb, - match_set_metadata(dp_match, htonll(datapath->tunnel_key)); - } - -+ uint16_t priority = datapath ? 200 : 100; -+ if (!has_vip_port) { -+ /* If L4 ports are not specified for the current LB, we will decrease -+ * the flow priority in order to not collide with other LBs with more -+ * fine-grained configuration. -+ */ -+ priority -= 10; -+ } - /* A flow added for the "hairpin_snat_ip" case will have an extra - * datapath match, but it will also match on the less restrictive - * general case. Therefore, we set the priority in the - * "hairpin_snat_ip" case to be higher than the general case. */ -- ofctrl_add_or_append_flow(flow_table, OFTABLE_CT_SNAT_HAIRPIN, -- datapath ? 200 : 100, -- lb->slb->header_.uuid.parts[0], -- dp_match, dp_acts, &lb->slb->header_.uuid, -- NX_CTLR_NO_METER, NULL); -+ ofctrl_add_flow(flow_table, OFTABLE_CT_SNAT_HAIRPIN, -+ priority, lb->slb->header_.uuid.parts[0], -+ dp_match, dp_acts, &lb->slb->header_.uuid); - } - - /* Add a ct_snat flow for each VIP of the LB. If this LB does not use -@@ -1836,8 +1843,8 @@ add_lb_ct_snat_hairpin_vip_flow(const struct ovn_controller_lb *lb, - } - } - -- match_set_nw_proto(&match, lb->proto); - if (lb_vip->vip_port) { -+ match_set_nw_proto(&match, lb->proto); - if (!lb->hairpin_orig_tuple) { - match_set_ct_nw_proto(&match, lb->proto); - match_set_ct_tp_dst(&match, htons(lb_vip->vip_port)); -@@ -1854,18 +1861,20 @@ add_lb_ct_snat_hairpin_vip_flow(const struct ovn_controller_lb *lb, - } - - if (!use_hairpin_snat_ip) { -- add_lb_ct_snat_hairpin_for_dp(lb, NULL, NULL, -+ add_lb_ct_snat_hairpin_for_dp(lb, !!lb_vip->vip_port, NULL, NULL, - &match, &ofpacts, flow_table); - } else { - for (size_t i = 0; i < lb->slb->n_datapaths; i++) { -- add_lb_ct_snat_hairpin_for_dp(lb, lb->slb->datapaths[i], -- local_datapaths, -- &match, &ofpacts, flow_table); -+ add_lb_ct_snat_hairpin_for_dp(lb, !!lb_vip->vip_port, -+ lb->slb->datapaths[i], -+ local_datapaths, &match, -+ &ofpacts, flow_table); - } - if (lb->slb->datapath_group) { - for (size_t i = 0; i < lb->slb->datapath_group->n_datapaths; i++) { - add_lb_ct_snat_hairpin_for_dp( -- lb, lb->slb->datapath_group->datapaths[i], -+ lb, !!lb_vip->vip_port, -+ lb->slb->datapath_group->datapaths[i], - local_datapaths, &match, &ofpacts, flow_table); - } - } -diff --git a/controller/lflow.h b/controller/lflow.h -index dd742257b..2472dec29 100644 ---- a/controller/lflow.h -+++ b/controller/lflow.h -@@ -63,27 +63,36 @@ struct uuid; - * - * These are heavily documented in ovn-architecture(7), please update it if - * you make any changes. */ --#define OFTABLE_PHY_TO_LOG 0 --#define OFTABLE_LOG_INGRESS_PIPELINE 8 /* First of LOG_PIPELINE_LEN tables. */ --#define OFTABLE_REMOTE_OUTPUT 37 --#define OFTABLE_LOCAL_OUTPUT 38 --#define OFTABLE_CHECK_LOOPBACK 39 --#define OFTABLE_LOG_EGRESS_PIPELINE 40 /* First of LOG_PIPELINE_LEN tables. */ --#define OFTABLE_SAVE_INPORT 64 --#define OFTABLE_LOG_TO_PHY 65 --#define OFTABLE_MAC_BINDING 66 --#define OFTABLE_MAC_LOOKUP 67 --#define OFTABLE_CHK_LB_HAIRPIN 68 --#define OFTABLE_CHK_LB_HAIRPIN_REPLY 69 --#define OFTABLE_CT_SNAT_HAIRPIN 70 --#define OFTABLE_GET_FDB 71 --#define OFTABLE_LOOKUP_FDB 72 --#define OFTABLE_CHK_IN_PORT_SEC 73 --#define OFTABLE_CHK_IN_PORT_SEC_ND 74 --#define OFTABLE_CHK_OUT_PORT_SEC 75 --#define OFTABLE_ECMP_NH_MAC 76 --#define OFTABLE_ECMP_NH 77 --#define OFTABLE_CHK_LB_AFFINITY 78 -+#define OFTABLE_PHY_TO_LOG 0 -+ -+/* Start of LOG_PIPELINE_LEN tables. */ -+#define OFTABLE_LOG_INGRESS_PIPELINE 8 -+#define OFTABLE_OUTPUT_LARGE_PKT_DETECT 37 -+#define OFTABLE_OUTPUT_LARGE_PKT_PROCESS 38 -+#define OFTABLE_REMOTE_OUTPUT 39 -+#define OFTABLE_LOCAL_OUTPUT 40 -+#define OFTABLE_CHECK_LOOPBACK 41 -+ -+/* Start of the OUTPUT section of the pipeline. */ -+#define OFTABLE_OUTPUT_INIT OFTABLE_OUTPUT_LARGE_PKT_DETECT -+ -+/* Start of LOG_PIPELINE_LEN tables. */ -+#define OFTABLE_LOG_EGRESS_PIPELINE 42 -+#define OFTABLE_SAVE_INPORT 64 -+#define OFTABLE_LOG_TO_PHY 65 -+#define OFTABLE_MAC_BINDING 66 -+#define OFTABLE_MAC_LOOKUP 67 -+#define OFTABLE_CHK_LB_HAIRPIN 68 -+#define OFTABLE_CHK_LB_HAIRPIN_REPLY 69 -+#define OFTABLE_CT_SNAT_HAIRPIN 70 -+#define OFTABLE_GET_FDB 71 -+#define OFTABLE_LOOKUP_FDB 72 -+#define OFTABLE_CHK_IN_PORT_SEC 73 -+#define OFTABLE_CHK_IN_PORT_SEC_ND 74 -+#define OFTABLE_CHK_OUT_PORT_SEC 75 -+#define OFTABLE_ECMP_NH_MAC 76 -+#define OFTABLE_ECMP_NH 77 -+#define OFTABLE_CHK_LB_AFFINITY 78 - - struct lflow_ctx_in { - struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath; -diff --git a/controller/local_data.c b/controller/local_data.c -index acaf1de6d..cf0b21bb1 100644 ---- a/controller/local_data.c -+++ b/controller/local_data.c -@@ -22,6 +22,7 @@ - #include "lib/util.h" - #include "lib/vswitch-idl.h" - #include "openvswitch/vlog.h" -+#include "socket-util.h" - - /* OVN includes. */ - #include "encaps.h" -@@ -447,6 +448,7 @@ local_nonvif_data_run(const struct ovsrec_bridge *br_int, - tun->chassis_id = xstrdup(tunnel_id); - tun->ofport = u16_to_ofp(ofport); - tun->type = tunnel_type; -+ tun->is_ipv6 = ip ? addr_is_ipv6(ip) : false; - - free(hash_id); - free(ip); -diff --git a/controller/local_data.h b/controller/local_data.h -index 748f009aa..ad0fa7f94 100644 ---- a/controller/local_data.h -+++ b/controller/local_data.h -@@ -133,6 +133,7 @@ struct chassis_tunnel { - char *chassis_id; - ofp_port_t ofport; - enum chassis_tunnel_type type; -+ bool is_ipv6; - }; - - void local_nonvif_data_run(const struct ovsrec_bridge *br_int, -diff --git a/controller/mirror.c b/controller/mirror.c -index 665736966..0e5885e9b 100644 ---- a/controller/mirror.c -+++ b/controller/mirror.c -@@ -22,6 +22,7 @@ - - /* OVS includes. */ - #include "lib/vswitch-idl.h" -+#include "lib/socket-util.h" - #include "include/openvswitch/shash.h" - #include "openvswitch/vlog.h" - -@@ -69,6 +70,7 @@ static void set_mirror_iface_options(struct ovsrec_interface *, - static const struct ovsrec_port *get_iface_port( - const struct ovsrec_interface *, const struct ovsrec_bridge *); - -+char *get_mirror_tunnel_type(const struct sbrec_mirror *); - - void - mirror_register_ovs_idl(struct ovsdb_idl *ovs_idl) -@@ -244,24 +246,26 @@ set_mirror_iface_options(struct ovsrec_interface *iface, - smap_destroy(&options); - } - -+char * -+get_mirror_tunnel_type(const struct sbrec_mirror *sb_mirror) -+{ -+ bool is_ipv6 = addr_is_ipv6(sb_mirror->sink); -+ -+ return xasprintf(is_ipv6 ? "ip6%s" : "%s", sb_mirror->type); -+} -+ - static void - check_and_update_interface_table(const struct sbrec_mirror *sb_mirror, - const struct ovsrec_mirror *ovs_mirror) - { -- char *type; -- struct ovsrec_interface *iface = -- ovs_mirror->output_port->interfaces[0]; -- struct smap *opts = &iface->options; -- const char *erspan_ver = smap_get(opts, "erspan_ver"); -- if (erspan_ver) { -- type = "erspan"; -- } else { -- type = "gre"; -- } -- if (strcmp(type, sb_mirror->type)) { -- ovsrec_interface_set_type(iface, sb_mirror->type); -+ struct ovsrec_interface *iface = ovs_mirror->output_port->interfaces[0]; -+ char *type = get_mirror_tunnel_type(sb_mirror); -+ -+ if (strcmp(type, iface->type)) { -+ ovsrec_interface_set_type(iface, type); - } - set_mirror_iface_options(iface, sb_mirror); -+ free(type); - } - - static void -@@ -327,8 +331,11 @@ create_ovs_mirror(struct ovn_mirror *m, struct ovsdb_idl_txn *ovs_idl_txn, - char *port_name = xasprintf("ovn-%s", m->name); - - ovsrec_interface_set_name(iface, port_name); -- ovsrec_interface_set_type(iface, m->sb_mirror->type); -+ -+ char *type = get_mirror_tunnel_type(m->sb_mirror); -+ ovsrec_interface_set_type(iface, type); - set_mirror_iface_options(iface, m->sb_mirror); -+ free(type); - - struct ovsrec_port *port = ovsrec_port_insert(ovs_idl_txn); - ovsrec_port_set_name(port, port_name); -diff --git a/controller/ofctrl.c b/controller/ofctrl.c -index b1ba1c743..64a444ff6 100644 ---- a/controller/ofctrl.c -+++ b/controller/ofctrl.c -@@ -766,13 +766,18 @@ ofctrl_get_mf_field_id(void) - - /* Runs the OpenFlow state machine against 'br_int', which is local to the - * hypervisor on which we are running. Attempts to negotiate a Geneve option -- * field for class OVN_GENEVE_CLASS, type OVN_GENEVE_TYPE. */ --void -+ * field for class OVN_GENEVE_CLASS, type OVN_GENEVE_TYPE. -+ * -+ * Returns 'true' if an OpenFlow reconnect happened; 'false' otherwise. -+ */ -+bool - ofctrl_run(const struct ovsrec_bridge *br_int, - const struct ovsrec_open_vswitch_table *ovs_table, - struct shash *pending_ct_zones) - { - char *target = xasprintf("unix:%s/%s.mgmt", ovs_rundir(), br_int->name); -+ bool reconnected = false; -+ - if (strcmp(target, rconn_get_target(swconn))) { - VLOG_INFO("%s: connecting to switch", target); - rconn_connect(swconn, target, target); -@@ -782,10 +787,12 @@ ofctrl_run(const struct ovsrec_bridge *br_int, - rconn_run(swconn); - - if (!rconn_is_connected(swconn)) { -- return; -+ return reconnected; - } -+ - if (seqno != rconn_get_connection_seqno(swconn)) { - seqno = rconn_get_connection_seqno(swconn); -+ reconnected = true; - state = S_NEW; - - /* Reset the state of any outstanding ct flushes to resend them. */ -@@ -855,6 +862,8 @@ ofctrl_run(const struct ovsrec_bridge *br_int, - * point, so ensure that we come back again without waiting. */ - poll_immediate_wake(); - } -+ -+ return reconnected; - } - - void -@@ -909,6 +918,7 @@ ofctrl_recv(const struct ofp_header *oh, enum ofptype type) - } else if (type == OFPTYPE_ERROR) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300); - log_openflow_rl(&rl, VLL_INFO, oh, "OpenFlow error"); -+ rconn_reconnect(swconn); - } else { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300); - log_openflow_rl(&rl, VLL_DBG, oh, "OpenFlow packet ignored"); -diff --git a/controller/ofctrl.h b/controller/ofctrl.h -index f5751e3ee..105f9370b 100644 ---- a/controller/ofctrl.h -+++ b/controller/ofctrl.h -@@ -51,7 +51,7 @@ struct ovn_desired_flow_table { - void ofctrl_init(struct ovn_extend_table *group_table, - struct ovn_extend_table *meter_table, - int inactivity_probe_interval); --void ofctrl_run(const struct ovsrec_bridge *br_int, -+bool ofctrl_run(const struct ovsrec_bridge *br_int, - const struct ovsrec_open_vswitch_table *, - struct shash *pending_ct_zones); - enum mf_field_id ofctrl_get_mf_field_id(void); -diff --git a/controller/ovn-controller.8.xml b/controller/ovn-controller.8.xml -index ab52e2d34..f61f43008 100644 ---- a/controller/ovn-controller.8.xml -+++ b/controller/ovn-controller.8.xml -@@ -121,11 +121,11 @@ - that is needed in the current chassis. -

-

-- It is more optimal to set it to true in use cases when -- the chassis would anyway need to monitor most of the records in -- ovs-database, which would save the overhead of conditions -- processing, especially for server side. Typically, set it to -- true for environments that all workloads need to be -+ It is more efficient to set it to true in use cases -+ where the chassis would anyway need to monitor most of the records in -+ OVN Southbound database, which would save the overhead of -+ conditions processing, especially for server side. Typically, set it -+ to true for environments that all workloads need to be - reachable from each other. -

-

-@@ -171,16 +171,14 @@ -

- -

-- Supported tunnel types for connecting hypervisors -- are geneve and stt. Gateways may -- use geneve, vxlan, or -- stt. -+ Supported tunnel types for connecting hypervisors and gateways -+ are geneve, vxlan, and stt. -

- -

- Due to the limited amount of metadata in vxlan, -- the capabilities and performance of connected gateways will be -- reduced versus other tunnel formats. -+ the capabilities and performance of connected gateways and -+ hypervisors will be reduced versus other tunnel formats. -

- - -diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c -index 2d18bbfca..ead789fb9 100644 ---- a/controller/ovn-controller.c -+++ b/controller/ovn-controller.c -@@ -60,6 +60,7 @@ - #include "lib/ovn-dirs.h" - #include "lib/ovn-sb-idl.h" - #include "lib/ovn-util.h" -+#include "ovsport.h" - #include "patch.h" - #include "vif-plug.h" - #include "vif-plug-provider.h" -@@ -712,7 +713,7 @@ get_snat_ct_zone(const struct sbrec_datapath_binding *dp) - } - - static void --update_ct_zones(const struct shash *binding_lports, -+update_ct_zones(const struct sset *local_lports, - const struct hmap *local_datapaths, - struct simap *ct_zones, unsigned long *ct_zone_bitmap, - struct shash *pending_ct_zones) -@@ -725,9 +726,9 @@ update_ct_zones(const struct shash *binding_lports, - unsigned long unreq_snat_zones_map[BITMAP_N_LONGS(MAX_CT_ZONES)]; - struct simap unreq_snat_zones = SIMAP_INITIALIZER(&unreq_snat_zones); - -- struct shash_node *shash_node; -- SHASH_FOR_EACH (shash_node, binding_lports) { -- sset_add(&all_users, shash_node->name); -+ const char *local_lport; -+ SSET_FOR_EACH (local_lport, local_lports) { -+ sset_add(&all_users, local_lport); - } - - /* Local patched datapath (gateway routers) need zones assigned. */ -@@ -1060,6 +1061,7 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) - ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_name); - ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_bfd); - ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_bfd_status); -+ ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_mtu); - ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_type); - ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_options); - ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_ofport); -@@ -1158,6 +1160,56 @@ en_ofctrl_is_connected_run(struct engine_node *node, void *data) - engine_set_node_state(node, EN_UNCHANGED); - } - -+struct ed_type_if_status_mgr { -+ const struct if_status_mgr *manager; -+ const struct ovsrec_interface_table *iface_table; -+}; -+ -+static void * -+en_if_status_mgr_init(struct engine_node *node OVS_UNUSED, -+ struct engine_arg *arg OVS_UNUSED) -+{ -+ struct ed_type_if_status_mgr *data = xzalloc(sizeof *data); -+ return data; -+} -+ -+static void -+en_if_status_mgr_cleanup(void *data OVS_UNUSED) -+{ -+} -+ -+static void -+en_if_status_mgr_run(struct engine_node *node, void *data_) -+{ -+ enum engine_node_state state = EN_UNCHANGED; -+ struct ed_type_if_status_mgr *data = data_; -+ struct controller_engine_ctx *ctrl_ctx = engine_get_context()->client_ctx; -+ data->manager = ctrl_ctx->if_mgr; -+ data->iface_table = EN_OVSDB_GET(engine_get_input("OVS_interface", node)); -+ -+ const struct ovsrec_interface *iface; -+ OVSREC_INTERFACE_TABLE_FOR_EACH (iface, data->iface_table) { -+ if (if_status_mgr_iface_update(data->manager, iface)) { -+ state = EN_UPDATED; -+ } -+ } -+ engine_set_node_state(node, state); -+} -+ -+static bool -+if_status_mgr_ovs_interface_handler(struct engine_node *node, void *data) -+{ -+ struct ed_type_if_status_mgr *data_ = data; -+ -+ const struct ovsrec_interface *iface; -+ OVSREC_INTERFACE_TABLE_FOR_EACH_TRACKED (iface, data_->iface_table) { -+ if (if_status_mgr_iface_update(data_->manager, iface)) { -+ engine_set_node_state(node, EN_UPDATED); -+ } -+ } -+ return true; -+} -+ - /* This engine node is to wrap the OVS_interface input and maintain a copy of - * the old version of data for the column external_ids. - * -@@ -2010,7 +2062,11 @@ addr_sets_update(const struct sbrec_address_set_table *address_set_table, - if (sbrec_address_set_is_deleted(as)) { - expr_const_sets_remove(addr_sets, as->name); - sset_add(deleted, as->name); -- } else { -+ } -+ } -+ -+ SBREC_ADDRESS_SET_TABLE_FOR_EACH_TRACKED (as, address_set_table) { -+ if (!sbrec_address_set_is_deleted(as)) { - struct expr_constant_set *cs_old = shash_find_data(addr_sets, - as->name); - if (!cs_old) { -@@ -2381,7 +2437,7 @@ en_ct_zones_run(struct engine_node *node, void *data) - EN_OVSDB_GET(engine_get_input("OVS_bridge", node)); - - restore_ct_zones(bridge_table, ovs_table, ct_zones_data); -- update_ct_zones(&rt_data->lbinding_data.lports, &rt_data->local_datapaths, -+ update_ct_zones(&rt_data->local_lports, &rt_data->local_datapaths, - &ct_zones_data->current, ct_zones_data->bitmap, - &ct_zones_data->pending); - -@@ -2471,8 +2527,10 @@ ct_zones_runtime_data_handler(struct engine_node *node, void *data) - SHASH_FOR_EACH (shash_node, &tdp->lports) { - struct tracked_lport *t_lport = shash_node->data; - if (strcmp(t_lport->pb->type, "") -- && strcmp(t_lport->pb->type, "localport")) { -- /* We allocate zone-id's only to VIF and localport lports. */ -+ && strcmp(t_lport->pb->type, "localport") -+ && strcmp(t_lport->pb->type, "localnet")) { -+ /* We allocate zone-id's only to VIF, localport, and localnet -+ * lports. */ - continue; - } - -@@ -2697,7 +2755,8 @@ static void - lb_data_removed_five_tuples_add(struct ed_type_lb_data *lb_data, - const struct ovn_controller_lb *lb) - { -- if (!ovs_feature_is_supported(OVS_CT_TUPLE_FLUSH_SUPPORT)) { -+ if (!ovs_feature_is_supported(OVS_CT_TUPLE_FLUSH_SUPPORT) || -+ !lb->ct_flush) { - return; - } - -@@ -2716,7 +2775,8 @@ static void - lb_data_removed_five_tuples_remove(struct ed_type_lb_data *lb_data, - const struct ovn_controller_lb *lb) - { -- if (!ovs_feature_is_supported(OVS_CT_TUPLE_FLUSH_SUPPORT)) { -+ if (!ovs_feature_is_supported(OVS_CT_TUPLE_FLUSH_SUPPORT) || -+ !lb->ct_flush) { - return; - } - -@@ -4048,6 +4108,9 @@ static void init_physical_ctx(struct engine_node *node, - const struct ed_type_mff_ovn_geneve *ed_mff_ovn_geneve = - engine_get_input_data("mff_ovn_geneve", node); - -+ const struct ovsrec_interface_table *ovs_interface_table = -+ EN_OVSDB_GET(engine_get_input("if_status_mgr", node)); -+ - const struct ovsrec_open_vswitch_table *ovs_table = - EN_OVSDB_GET(engine_get_input("OVS_open_vswitch", node)); - const struct ovsrec_bridge_table *bridge_table = -@@ -4072,6 +4135,7 @@ static void init_physical_ctx(struct engine_node *node, - p_ctx->sbrec_port_binding_by_name = sbrec_port_binding_by_name; - p_ctx->sbrec_port_binding_by_datapath = sbrec_port_binding_by_datapath; - p_ctx->port_binding_table = port_binding_table; -+ p_ctx->ovs_interface_table = ovs_interface_table; - p_ctx->mc_group_table = multicast_group_table; - p_ctx->br_int = br_int; - p_ctx->chassis_table = chassis_table; -@@ -4085,6 +4149,9 @@ static void init_physical_ctx(struct engine_node *node, - p_ctx->patch_ofports = &non_vif_data->patch_ofports; - p_ctx->chassis_tunnels = &non_vif_data->chassis_tunnels; - -+ struct controller_engine_ctx *ctrl_ctx = engine_get_context()->client_ctx; -+ p_ctx->if_mgr = ctrl_ctx->if_mgr; -+ - pflow_output_get_debug(node, &p_ctx->debug); - } - -@@ -4128,6 +4195,63 @@ en_pflow_output_run(struct engine_node *node, void *data) - engine_set_node_state(node, EN_UPDATED); - } - -+static bool -+pflow_output_if_status_mgr_handler(struct engine_node *node, -+ void *data) -+{ -+ struct ed_type_pflow_output *pfo = data; -+ struct ed_type_runtime_data *rt_data = -+ engine_get_input_data("runtime_data", node); -+ struct ed_type_non_vif_data *non_vif_data = -+ engine_get_input_data("non_vif_data", node); -+ struct ed_type_if_status_mgr *if_mgr_data = -+ engine_get_input_data("if_status_mgr", node); -+ -+ struct physical_ctx p_ctx; -+ init_physical_ctx(node, rt_data, non_vif_data, &p_ctx); -+ -+ const struct ovsrec_interface *iface; -+ OVSREC_INTERFACE_TABLE_FOR_EACH_TRACKED (iface, if_mgr_data->iface_table) { -+ const char *iface_id = smap_get(&iface->external_ids, "iface-id"); -+ if (!iface_id) { -+ continue; -+ } -+ -+ const struct sbrec_port_binding *pb = lport_lookup_by_name( -+ p_ctx.sbrec_port_binding_by_name, iface_id); -+ if (!pb) { -+ continue; -+ } -+ if (pb->n_additional_chassis) { -+ /* Update flows for all ports in datapath. */ -+ struct sbrec_port_binding *target = -+ sbrec_port_binding_index_init_row( -+ p_ctx.sbrec_port_binding_by_datapath); -+ sbrec_port_binding_index_set_datapath(target, pb->datapath); -+ -+ const struct sbrec_port_binding *binding; -+ SBREC_PORT_BINDING_FOR_EACH_EQUAL ( -+ binding, target, p_ctx.sbrec_port_binding_by_datapath) { -+ bool removed = sbrec_port_binding_is_deleted(binding); -+ if (!physical_handle_flows_for_lport(binding, removed, &p_ctx, -+ &pfo->flow_table)) { -+ return false; -+ } -+ } -+ sbrec_port_binding_index_destroy_row(target); -+ } else { -+ /* If any multichassis ports, update flows for the port. */ -+ bool removed = sbrec_port_binding_is_deleted(pb); -+ if (!physical_handle_flows_for_lport(pb, removed, &p_ctx, -+ &pfo->flow_table)) { -+ return false; -+ } -+ } -+ engine_set_node_state(node, EN_UPDATED); -+ } -+ return true; -+} -+ - static bool - pflow_output_sb_port_binding_handler(struct engine_node *node, - void *data) -@@ -4611,6 +4735,7 @@ main(int argc, char *argv[]) - ENGINE_NODE_WITH_CLEAR_TRACK_DATA(port_groups, "port_groups"); - ENGINE_NODE(northd_options, "northd_options"); - ENGINE_NODE(dhcp_options, "dhcp_options"); -+ ENGINE_NODE(if_status_mgr, "if_status_mgr"); - ENGINE_NODE_WITH_CLEAR_TRACK_DATA(lb_data, "lb_data"); - - #define SB_NODE(NAME, NAME_STR) ENGINE_NODE_SB(NAME, NAME_STR); -@@ -4649,6 +4774,9 @@ main(int argc, char *argv[]) - engine_add_input(&en_non_vif_data, &en_ovs_interface, - non_vif_data_ovs_iface_handler); - -+ engine_add_input(&en_if_status_mgr, &en_ovs_interface, -+ if_status_mgr_ovs_interface_handler); -+ - /* Note: The order of inputs is important, all OVS interface changes must - * be handled before any ct_zone changes. - */ -@@ -4659,6 +4787,8 @@ main(int argc, char *argv[]) - engine_add_input(&en_pflow_output, &en_sb_chassis, - pflow_lflow_output_sb_chassis_handler); - -+ engine_add_input(&en_pflow_output, &en_if_status_mgr, -+ pflow_output_if_status_mgr_handler); - engine_add_input(&en_pflow_output, &en_sb_port_binding, - pflow_output_sb_port_binding_handler); - engine_add_input(&en_pflow_output, &en_sb_multicast_group, -@@ -5061,8 +5191,14 @@ main(int argc, char *argv[]) - - if (br_int) { - ct_zones_data = engine_get_data(&en_ct_zones); -- if (ct_zones_data) { -- ofctrl_run(br_int, ovs_table, &ct_zones_data->pending); -+ if (ct_zones_data && ofctrl_run(br_int, ovs_table, -+ &ct_zones_data->pending)) { -+ static struct vlog_rate_limit rl -+ = VLOG_RATE_LIMIT_INIT(1, 1); -+ -+ VLOG_INFO_RL(&rl, "OVS OpenFlow connection reconnected," -+ "force recompute."); -+ engine_set_force_recompute(true); - } - - if (chassis) { -@@ -5071,7 +5207,8 @@ main(int argc, char *argv[]) - chassis, - sbrec_sb_global_first(ovnsb_idl_loop.idl), - ovs_table, -- &transport_zones); -+ &transport_zones, -+ bridge_table); - - stopwatch_start(CONTROLLER_LOOP_STOPWATCH_NAME, - time_msec()); -@@ -5225,6 +5362,11 @@ main(int argc, char *argv[]) - stopwatch_start(IF_STATUS_MGR_UPDATE_STOPWATCH_NAME, - time_msec()); - if_status_mgr_update(if_mgr, binding_data, chassis, -+ ovsrec_interface_table_get( -+ ovs_idl_loop.idl), -+ sbrec_port_binding_table_get( -+ ovnsb_idl_loop.idl), -+ !ovs_idl_txn, - !ovnsb_idl_txn); - stopwatch_stop(IF_STATUS_MGR_UPDATE_STOPWATCH_NAME, - time_msec()); -@@ -5254,11 +5396,12 @@ main(int argc, char *argv[]) - stopwatch_start(IF_STATUS_MGR_RUN_STOPWATCH_NAME, - time_msec()); - if_status_mgr_run(if_mgr, binding_data, chassis, -+ ovsrec_interface_table_get( -+ ovs_idl_loop.idl), - !ovnsb_idl_txn, !ovs_idl_txn); - stopwatch_stop(IF_STATUS_MGR_RUN_STOPWATCH_NAME, - time_msec()); - } -- - } - - if (!engine_has_run()) { -@@ -5449,6 +5592,7 @@ loop_done: - binding_destroy(); - patch_destroy(); - mirror_destroy(); -+ encaps_destroy(); - if_status_mgr_destroy(if_mgr); - shash_destroy(&vif_plug_deleted_iface_ids); - shash_destroy(&vif_plug_changed_iface_ids); -@@ -5466,6 +5610,7 @@ loop_done: - free(cli_system_id); - } - service_stop(); -+ ovsrcu_exit(); - - exit(retval); - } -diff --git a/controller/ovsport.c b/controller/ovsport.c -index ec38c3fca..ebcb9cb6d 100644 ---- a/controller/ovsport.c -+++ b/controller/ovsport.c -@@ -264,3 +264,12 @@ maintain_interface_smap_column( - } - } - } -+ -+uint16_t -+get_iface_mtu(const struct ovsrec_interface *iface) -+{ -+ if (!iface || !iface->n_mtu || iface->mtu[0] <= 0) { -+ return 0; -+ } -+ return (uint16_t) iface->mtu[0]; -+} -diff --git a/controller/ovsport.h b/controller/ovsport.h -index e355ff7ff..c40c1855a 100644 ---- a/controller/ovsport.h -+++ b/controller/ovsport.h -@@ -57,4 +57,6 @@ const struct ovsrec_port * ovsport_lookup_by_interfaces( - const struct ovsrec_port * ovsport_lookup_by_interface( - struct ovsdb_idl_index *, struct ovsrec_interface *); - -+uint16_t get_iface_mtu(const struct ovsrec_interface *); -+ - #endif /* lib/ovsport.h */ -diff --git a/controller/physical.c b/controller/physical.c -index ec861f49c..d19eb9200 100644 ---- a/controller/physical.c -+++ b/controller/physical.c -@@ -41,6 +41,7 @@ - #include "lib/ovn-sb-idl.h" - #include "lib/ovn-util.h" - #include "ovn/actions.h" -+#include "if-status.h" - #include "physical.h" - #include "pinctrl.h" - #include "openvswitch/shash.h" -@@ -91,6 +92,7 @@ physical_register_ovs_idl(struct ovsdb_idl *ovs_idl) - - ovsdb_idl_add_table(ovs_idl, &ovsrec_table_interface); - ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_name); -+ ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_mtu); - ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_ofport); - ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_external_ids); - } -@@ -876,12 +878,12 @@ put_local_common_flows(uint32_t dp_key, - - uint32_t port_key = pb->tunnel_key; - -- /* Table 38, priority 100. -+ /* Table 40, priority 100. - * ======================= - * - * Implements output to local hypervisor. Each flow matches a - * logical output port on the local hypervisor, and resubmits to -- * table 39. -+ * table 41. - */ - - ofpbuf_clear(ofpacts_p); -@@ -891,13 +893,13 @@ put_local_common_flows(uint32_t dp_key, - - put_zones_ofpacts(zone_ids, ofpacts_p); - -- /* Resubmit to table 39. */ -+ /* Resubmit to table 41. */ - put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p); - ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, - pb->header_.uuid.parts[0], &match, ofpacts_p, - &pb->header_.uuid); - -- /* Table 39, Priority 100. -+ /* Table 41, Priority 100. - * ======================= - * - * Drop packets whose logical inport and outport are the same -@@ -1104,6 +1106,240 @@ setup_activation_strategy(const struct sbrec_port_binding *binding, - } - } - -+/* -+ * Insert a flow to determine if an IP packet is too big for the corresponding -+ * egress interface. -+ */ -+static void -+determine_if_pkt_too_big(struct ovn_desired_flow_table *flow_table, -+ const struct sbrec_port_binding *binding, -+ const struct sbrec_port_binding *mcp, -+ uint16_t mtu, bool is_ipv6, int direction) -+{ -+ struct ofpbuf ofpacts; -+ ofpbuf_init(&ofpacts, 0); -+ -+ /* Store packet too large flag in reg9[1]. */ -+ struct match match; -+ match_init_catchall(&match); -+ match_set_dl_type(&match, htons(is_ipv6 ? ETH_TYPE_IPV6 : ETH_TYPE_IP)); -+ match_set_metadata(&match, htonll(binding->datapath->tunnel_key)); -+ match_set_reg(&match, direction - MFF_REG0, mcp->tunnel_key); -+ -+ /* reg9[1] is REGBIT_PKT_LARGER as defined by northd */ -+ struct ofpact_check_pkt_larger *pkt_larger = -+ ofpact_put_CHECK_PKT_LARGER(&ofpacts); -+ pkt_larger->pkt_len = mtu; -+ pkt_larger->dst.field = mf_from_id(MFF_REG9); -+ pkt_larger->dst.ofs = 1; -+ -+ put_resubmit(OFTABLE_OUTPUT_LARGE_PKT_PROCESS, &ofpacts); -+ ofctrl_add_flow(flow_table, OFTABLE_OUTPUT_LARGE_PKT_DETECT, 100, -+ binding->header_.uuid.parts[0], &match, &ofpacts, -+ &binding->header_.uuid); -+ ofpbuf_uninit(&ofpacts); -+} -+ -+/* -+ * Insert a flow to reply with ICMP error for IP packets that are too big for -+ * the corresponding egress interface. -+ */ -+/* -+ * NOTE(ihrachys) This reimplements icmp_error as found in -+ * build_icmperr_pkt_big_flows. We may look into reusing the existing OVN -+ * action for this flow in the future. -+ */ -+static void -+reply_imcp_error_if_pkt_too_big(struct ovn_desired_flow_table *flow_table, -+ const struct sbrec_port_binding *binding, -+ const struct sbrec_port_binding *mcp, -+ uint16_t mtu, bool is_ipv6, int direction) -+{ -+ struct match match; -+ match_init_catchall(&match); -+ match_set_dl_type(&match, htons(is_ipv6 ? ETH_TYPE_IPV6 : ETH_TYPE_IP)); -+ match_set_metadata(&match, htonll(binding->datapath->tunnel_key)); -+ match_set_reg(&match, direction - MFF_REG0, mcp->tunnel_key); -+ match_set_reg_masked(&match, MFF_REG9 - MFF_REG0, 1 << 1, 1 << 1); -+ -+ /* Return ICMP error with a part of the original IP packet included. */ -+ struct ofpbuf ofpacts; -+ ofpbuf_init(&ofpacts, 0); -+ size_t oc_offset = encode_start_controller_op( -+ ACTION_OPCODE_ICMP, true, NX_CTLR_NO_METER, &ofpacts); -+ -+ struct ofpbuf inner_ofpacts; -+ ofpbuf_init(&inner_ofpacts, 0); -+ -+ /* The error packet is no longer too large, set REGBIT_PKT_LARGER = 0 */ -+ /* reg9[1] is REGBIT_PKT_LARGER as defined by northd */ -+ ovs_be32 value = htonl(0); -+ ovs_be32 mask = htonl(1 << 1); -+ ofpact_put_set_field( -+ &inner_ofpacts, mf_from_id(MFF_REG9), &value, &mask); -+ -+ /* The new error packet is delivered locally */ -+ /* REGBIT_EGRESS_LOOPBACK = 1 */ -+ value = htonl(1 << MLF_ALLOW_LOOPBACK_BIT); -+ mask = htonl(1 << MLF_ALLOW_LOOPBACK_BIT); -+ ofpact_put_set_field( -+ &inner_ofpacts, mf_from_id(MFF_LOG_FLAGS), &value, &mask); -+ -+ /* eth.src <-> eth.dst */ -+ put_stack(MFF_ETH_DST, ofpact_put_STACK_PUSH(&inner_ofpacts)); -+ put_stack(MFF_ETH_SRC, ofpact_put_STACK_PUSH(&inner_ofpacts)); -+ put_stack(MFF_ETH_DST, ofpact_put_STACK_POP(&inner_ofpacts)); -+ put_stack(MFF_ETH_SRC, ofpact_put_STACK_POP(&inner_ofpacts)); -+ -+ /* ip.src <-> ip.dst */ -+ put_stack(is_ipv6 ? MFF_IPV6_DST : MFF_IPV4_DST, -+ ofpact_put_STACK_PUSH(&inner_ofpacts)); -+ put_stack(is_ipv6 ? MFF_IPV6_SRC : MFF_IPV4_SRC, -+ ofpact_put_STACK_PUSH(&inner_ofpacts)); -+ put_stack(is_ipv6 ? MFF_IPV6_DST : MFF_IPV4_DST, -+ ofpact_put_STACK_POP(&inner_ofpacts)); -+ put_stack(is_ipv6 ? MFF_IPV6_SRC : MFF_IPV4_SRC, -+ ofpact_put_STACK_POP(&inner_ofpacts)); -+ -+ /* ip.ttl = 255 */ -+ struct ofpact_ip_ttl *ip_ttl = ofpact_put_SET_IP_TTL(&inner_ofpacts); -+ ip_ttl->ttl = 255; -+ -+ uint16_t frag_mtu = mtu - ETHERNET_OVERHEAD; -+ size_t frag_mtu_oc_offset; -+ if (is_ipv6) { -+ /* icmp6.type = 2 (Packet Too Big) */ -+ /* icmp6.code = 0 */ -+ uint8_t icmp_type = 2; -+ uint8_t icmp_code = 0; -+ ofpact_put_set_field( -+ &inner_ofpacts, mf_from_id(MFF_ICMPV6_TYPE), &icmp_type, NULL); -+ ofpact_put_set_field( -+ &inner_ofpacts, mf_from_id(MFF_ICMPV6_CODE), &icmp_code, NULL); -+ -+ /* icmp6.frag_mtu */ -+ frag_mtu_oc_offset = encode_start_controller_op( -+ ACTION_OPCODE_PUT_ICMP6_FRAG_MTU, true, NX_CTLR_NO_METER, -+ &inner_ofpacts); -+ ovs_be32 frag_mtu_ovs = htonl(frag_mtu); -+ ofpbuf_put(&inner_ofpacts, &frag_mtu_ovs, sizeof(frag_mtu_ovs)); -+ } else { -+ /* icmp4.type = 3 (Destination Unreachable) */ -+ /* icmp4.code = 4 (Fragmentation Needed) */ -+ uint8_t icmp_type = 3; -+ uint8_t icmp_code = 4; -+ ofpact_put_set_field( -+ &inner_ofpacts, mf_from_id(MFF_ICMPV4_TYPE), &icmp_type, NULL); -+ ofpact_put_set_field( -+ &inner_ofpacts, mf_from_id(MFF_ICMPV4_CODE), &icmp_code, NULL); -+ -+ /* icmp4.frag_mtu = */ -+ frag_mtu_oc_offset = encode_start_controller_op( -+ ACTION_OPCODE_PUT_ICMP4_FRAG_MTU, true, NX_CTLR_NO_METER, -+ &inner_ofpacts); -+ ovs_be16 frag_mtu_ovs = htons(frag_mtu); -+ ofpbuf_put(&inner_ofpacts, &frag_mtu_ovs, sizeof(frag_mtu_ovs)); -+ } -+ encode_finish_controller_op(frag_mtu_oc_offset, &inner_ofpacts); -+ -+ /* Finally, submit the ICMP error back to the ingress pipeline */ -+ put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, &inner_ofpacts); -+ -+ /* Attach nested actions to ICMP error controller handler */ -+ ofpacts_put_openflow_actions(inner_ofpacts.data, inner_ofpacts.size, -+ &ofpacts, OFP15_VERSION); -+ -+ /* Finalize the ICMP error controller handler */ -+ encode_finish_controller_op(oc_offset, &ofpacts); -+ -+ ofctrl_add_flow(flow_table, OFTABLE_OUTPUT_LARGE_PKT_PROCESS, 100, -+ binding->header_.uuid.parts[0], &match, &ofpacts, -+ &binding->header_.uuid); -+ -+ ofpbuf_uninit(&inner_ofpacts); -+ ofpbuf_uninit(&ofpacts); -+} -+ -+static uint16_t -+get_tunnel_overhead(struct chassis_tunnel const *tun) -+{ -+ uint16_t overhead = 0; -+ enum chassis_tunnel_type type = tun->type; -+ if (type == GENEVE) { -+ overhead += GENEVE_TUNNEL_OVERHEAD; -+ } else if (type == STT) { -+ overhead += STT_TUNNEL_OVERHEAD; -+ } else if (type == VXLAN) { -+ overhead += VXLAN_TUNNEL_OVERHEAD; -+ } else { -+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); -+ VLOG_WARN_RL(&rl, "Unknown tunnel type %d, can't determine overhead " -+ "size for Path MTU Discovery", type); -+ return 0; -+ } -+ overhead += tun->is_ipv6? IPV6_HEADER_LEN : IP_HEADER_LEN; -+ return overhead; -+} -+ -+static uint16_t -+get_effective_mtu(const struct sbrec_port_binding *mcp, -+ struct ovs_list *remote_tunnels, -+ const struct if_status_mgr *if_mgr) -+{ -+ /* Use interface MTU as a base for calculation */ -+ uint16_t iface_mtu = if_status_mgr_iface_get_mtu(if_mgr, -+ mcp->logical_port); -+ if (!iface_mtu) { -+ return 0; -+ } -+ -+ /* Iterate over all peer tunnels and find the biggest tunnel overhead */ -+ uint16_t overhead = 0; -+ struct tunnel *tun; -+ LIST_FOR_EACH (tun, list_node, remote_tunnels) { -+ overhead = MAX(overhead, get_tunnel_overhead(tun->tun)); -+ } -+ if (!overhead) { -+ return 0; -+ } -+ -+ return iface_mtu - overhead; -+} -+ -+static void -+handle_pkt_too_big_for_ip_version(struct ovn_desired_flow_table *flow_table, -+ const struct sbrec_port_binding *binding, -+ const struct sbrec_port_binding *mcp, -+ uint16_t mtu, bool is_ipv6) -+{ -+ /* ingress */ -+ determine_if_pkt_too_big(flow_table, binding, mcp, mtu, is_ipv6, -+ MFF_LOG_INPORT); -+ reply_imcp_error_if_pkt_too_big(flow_table, binding, mcp, mtu, is_ipv6, -+ MFF_LOG_INPORT); -+ -+ /* egress */ -+ determine_if_pkt_too_big(flow_table, binding, mcp, mtu, is_ipv6, -+ MFF_LOG_OUTPORT); -+ reply_imcp_error_if_pkt_too_big(flow_table, binding, mcp, mtu, is_ipv6, -+ MFF_LOG_OUTPORT); -+} -+ -+static void -+handle_pkt_too_big(struct ovn_desired_flow_table *flow_table, -+ struct ovs_list *remote_tunnels, -+ const struct sbrec_port_binding *binding, -+ const struct sbrec_port_binding *mcp, -+ const struct if_status_mgr *if_mgr) -+{ -+ uint16_t mtu = get_effective_mtu(mcp, remote_tunnels, if_mgr); -+ if (!mtu) { -+ return; -+ } -+ handle_pkt_too_big_for_ip_version(flow_table, binding, mcp, mtu, false); -+ handle_pkt_too_big_for_ip_version(flow_table, binding, mcp, mtu, true); -+} -+ - static void - enforce_tunneling_for_multichassis_ports( - struct local_datapath *ld, -@@ -1111,7 +1347,8 @@ enforce_tunneling_for_multichassis_ports( - const struct sbrec_chassis *chassis, - const struct hmap *chassis_tunnels, - enum mf_field_id mff_ovn_geneve, -- struct ovn_desired_flow_table *flow_table) -+ struct ovn_desired_flow_table *flow_table, -+ const struct if_status_mgr *if_mgr) - { - if (shash_is_empty(&ld->multichassis_ports)) { - return; -@@ -1156,6 +1393,8 @@ enforce_tunneling_for_multichassis_ports( - binding->header_.uuid.parts[0], &match, &ofpacts, - &binding->header_.uuid); - ofpbuf_uninit(&ofpacts); -+ -+ handle_pkt_too_big(flow_table, tuns, binding, mcp, if_mgr); - } - - struct tunnel *tun_elem; -@@ -1177,6 +1416,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, - const struct sbrec_port_binding *binding, - const struct sbrec_chassis *chassis, - const struct physical_debug *debug, -+ const struct if_status_mgr *if_mgr, - struct ovn_desired_flow_table *flow_table, - struct ofpbuf *ofpacts_p) - { -@@ -1233,12 +1473,12 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, - || ha_chassis_group_is_active(binding->ha_chassis_group, - active_tunnels, chassis))) { - -- /* Table 38, priority 100. -+ /* Table 40, priority 100. - * ======================= - * - * Implements output to local hypervisor. Each flow matches a - * logical output port on the local hypervisor, and resubmits to -- * table 39. For ports of type "chassisredirect", the logical -+ * table 41. For ports of type "chassisredirect", the logical - * output port is changed from the "chassisredirect" port to the - * underlying distributed port. */ - -@@ -1275,7 +1515,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, - ct_zones); - put_zones_ofpacts(&zone_ids, ofpacts_p); - -- /* Resubmit to table 39. */ -+ /* Resubmit to table 41. */ - put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p); - } - -@@ -1491,7 +1731,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, - ofport, flow_table); - } - -- /* Table 39, priority 160. -+ /* Table 41, priority 160. - * ======================= - * - * Do not forward local traffic from a localport to a localnet port. -@@ -1561,13 +1801,13 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, - } - } - -- /* Table 37, priority 150. -+ /* Table 39, priority 150. - * ======================= - * - * Handles packets received from ports of type "localport". These - * ports are present on every hypervisor. Traffic that originates at - * one should never go over a tunnel to a remote hypervisor, -- * so resubmit them to table 38 for local delivery. */ -+ * so resubmit them to table 40 for local delivery. */ - if (!strcmp(binding->type, "localport")) { - ofpbuf_clear(ofpacts_p); - put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts_p); -@@ -1581,7 +1821,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, - } - } else if (access_type == PORT_LOCALNET) { - /* Remote port connected by localnet port */ -- /* Table 38, priority 100. -+ /* Table 40, priority 100. - * ======================= - * - * Implements switching to localnet port. Each flow matches a -@@ -1596,14 +1836,16 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, - - put_load(localnet_port->tunnel_key, MFF_LOG_OUTPORT, 0, 32, ofpacts_p); - -- /* Resubmit to table 38. */ -+ /* Resubmit to table 40. */ - put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts_p); - ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, - binding->header_.uuid.parts[0], - &match, ofpacts_p, &binding->header_.uuid); - -- enforce_tunneling_for_multichassis_ports( -- ld, binding, chassis, chassis_tunnels, mff_ovn_geneve, flow_table); -+ enforce_tunneling_for_multichassis_ports(ld, binding, chassis, -+ chassis_tunnels, -+ mff_ovn_geneve, flow_table, -+ if_mgr); - - /* No more tunneling to set up. */ - goto out; -@@ -1613,7 +1855,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, - const char *redirect_type = smap_get(&binding->options, - "redirect-type"); - -- /* Table 38, priority 100. -+ /* Table 40, priority 100. - * ======================= - * - * Handles traffic that needs to be sent to a remote hypervisor. Each -@@ -1841,7 +2083,7 @@ consider_mc_group(struct ovsdb_idl_index *sbrec_port_binding_by_name, - } - } - -- /* Table 38, priority 100. -+ /* Table 40, priority 100. - * ======================= - * - * Handle output to the local logical ports in the multicast group, if -@@ -1857,7 +2099,7 @@ consider_mc_group(struct ovsdb_idl_index *sbrec_port_binding_by_name, - &match, &ofpacts, &mc->header_.uuid); - } - -- /* Table 37, priority 100. -+ /* Table 39, priority 100. - * ======================= - * - * Handle output to the remote chassis in the multicast group, if -@@ -1908,7 +2150,7 @@ physical_eval_port_binding(struct physical_ctx *p_ctx, - p_ctx->patch_ofports, - p_ctx->chassis_tunnels, - pb, p_ctx->chassis, &p_ctx->debug, -- flow_table, &ofpacts); -+ p_ctx->if_mgr, flow_table, &ofpacts); - ofpbuf_uninit(&ofpacts); - } - -@@ -2032,10 +2274,10 @@ physical_run(struct physical_ctx *p_ctx, - p_ctx->patch_ofports, - p_ctx->chassis_tunnels, binding, - p_ctx->chassis, &p_ctx->debug, -- flow_table, &ofpacts); -+ p_ctx->if_mgr, flow_table, &ofpacts); - } - -- /* Handle output to multicast groups, in tables 37 and 38. */ -+ /* Handle output to multicast groups, in tables 40 and 41. */ - const struct sbrec_multicast_group *mc; - SBREC_MULTICAST_GROUP_TABLE_FOR_EACH (mc, p_ctx->mc_group_table) { - consider_mc_group(p_ctx->sbrec_port_binding_by_name, -@@ -2056,7 +2298,7 @@ physical_run(struct physical_ctx *p_ctx, - * encapsulations have metadata about the ingress and egress logical ports. - * VXLAN encapsulations have metadata about the egress logical port only. - * We set MFF_LOG_DATAPATH, MFF_LOG_INPORT, and MFF_LOG_OUTPORT from the -- * tunnel key data where possible, then resubmit to table 38 to handle -+ * tunnel key data where possible, then resubmit to table 40 to handle - * packets to the local hypervisor. */ - struct chassis_tunnel *tun; - HMAP_FOR_EACH (tun, hmap_node, p_ctx->chassis_tunnels) { -@@ -2158,27 +2400,52 @@ physical_run(struct physical_ctx *p_ctx, - */ - add_default_drop_flow(p_ctx, OFTABLE_PHY_TO_LOG, flow_table); - -- /* Table 37, priority 150. -+ /* Table 37-38, priority 0. -+ * ======================== -+ * -+ * Default resubmit actions for OFTABLE_OUTPUT_LARGE_PKT_* tables. -+ */ -+ struct match match; -+ match_init_catchall(&match); -+ ofpbuf_clear(&ofpacts); -+ put_resubmit(OFTABLE_REMOTE_OUTPUT, &ofpacts); -+ ofctrl_add_flow(flow_table, OFTABLE_OUTPUT_LARGE_PKT_DETECT, 0, 0, &match, -+ &ofpacts, hc_uuid); -+ -+ match_init_catchall(&match); -+ match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0, -+ MLF_ALLOW_LOOPBACK, MLF_ALLOW_LOOPBACK); -+ ofpbuf_clear(&ofpacts); -+ put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); -+ ofctrl_add_flow(flow_table, OFTABLE_OUTPUT_LARGE_PKT_PROCESS, 10, 0, -+ &match, &ofpacts, hc_uuid); -+ -+ match_init_catchall(&match); -+ ofpbuf_clear(&ofpacts); -+ put_resubmit(OFTABLE_REMOTE_OUTPUT, &ofpacts); -+ ofctrl_add_flow(flow_table, OFTABLE_OUTPUT_LARGE_PKT_PROCESS, 0, 0, &match, -+ &ofpacts, hc_uuid); -+ -+ /* Table 39, priority 150. - * ======================= - * - * Handles packets received from a VXLAN tunnel which get resubmitted to - * OFTABLE_LOG_INGRESS_PIPELINE due to lack of needed metadata in VXLAN, -- * explicitly skip sending back out any tunnels and resubmit to table 38 -+ * explicitly skip sending back out any tunnels and resubmit to table 40 - * for local delivery, except packets which have MLF_ALLOW_LOOPBACK bit - * set. - */ -- struct match match; - match_init_catchall(&match); - match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0, MLF_RCV_FROM_RAMP, - MLF_RCV_FROM_RAMP | MLF_ALLOW_LOOPBACK); - -- /* Resubmit to table 38. */ -+ /* Resubmit to table 40. */ - ofpbuf_clear(&ofpacts); - put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); - ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 150, 0, - &match, &ofpacts, hc_uuid); - -- /* Table 37, priority 150. -+ /* Table 39, priority 150. - * ======================= - * - * Packets that should not be sent to other hypervisors. -@@ -2186,13 +2453,13 @@ physical_run(struct physical_ctx *p_ctx, - match_init_catchall(&match); - match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0, - MLF_LOCAL_ONLY, MLF_LOCAL_ONLY); -- /* Resubmit to table 38. */ -+ /* Resubmit to table 40. */ - ofpbuf_clear(&ofpacts); - put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); - ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 150, 0, - &match, &ofpacts, hc_uuid); - -- /* Table 37, Priority 0. -+ /* Table 39, Priority 0. - * ======================= - * - * Resubmit packets that are not directed at tunnels or part of a -@@ -2203,18 +2470,18 @@ physical_run(struct physical_ctx *p_ctx, - ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 0, 0, &match, - &ofpacts, hc_uuid); - -- /* Table 38, priority 0. -+ /* Table 40, priority 0. - * ====================== - * - * Drop packets that do not match previous flows. - */ - add_default_drop_flow(p_ctx, OFTABLE_LOCAL_OUTPUT, flow_table); - -- /* Table 39, Priority 0. -+ /* Table 41, Priority 0. - * ======================= - * - * Resubmit packets that don't output to the ingress port (already checked -- * in table 38) to the logical egress pipeline, clearing the logical -+ * in table 40) to the logical egress pipeline, clearing the logical - * registers (for consistent behavior with packets that get tunneled). */ - match_init_catchall(&match); - ofpbuf_clear(&ofpacts); -diff --git a/controller/physical.h b/controller/physical.h -index f450dca94..1f1ed55ef 100644 ---- a/controller/physical.h -+++ b/controller/physical.h -@@ -52,11 +52,13 @@ struct physical_ctx { - struct ovsdb_idl_index *sbrec_port_binding_by_name; - struct ovsdb_idl_index *sbrec_port_binding_by_datapath; - const struct sbrec_port_binding_table *port_binding_table; -+ const struct ovsrec_interface_table *ovs_interface_table; - const struct sbrec_multicast_group_table *mc_group_table; - const struct ovsrec_bridge *br_int; - const struct sbrec_chassis_table *chassis_table; - const struct sbrec_chassis *chassis; - const struct sset *active_tunnels; -+ const struct if_status_mgr *if_mgr; - struct hmap *local_datapaths; - struct sset *local_lports; - const struct simap *ct_zones; -diff --git a/controller/pinctrl.c b/controller/pinctrl.c -index 795847729..cd9760f07 100644 ---- a/controller/pinctrl.c -+++ b/controller/pinctrl.c -@@ -627,7 +627,7 @@ set_actions_and_enqueue_msg(struct rconn *swconn, - } - - /* Forwards a packet to 'out_port_key' even if that's on a remote -- * hypervisor, i.e., the packet is re-injected in table OFTABLE_REMOTE_OUTPUT. -+ * hypervisor, i.e., the packet is re-injected in table OFTABLE_OUTPUT_INIT. - */ - static void - pinctrl_forward_pkt(struct rconn *swconn, int64_t dp_key, -@@ -644,7 +644,7 @@ pinctrl_forward_pkt(struct rconn *swconn, int64_t dp_key, - - struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts); - resubmit->in_port = OFPP_CONTROLLER; -- resubmit->table_id = OFTABLE_REMOTE_OUTPUT; -+ resubmit->table_id = OFTABLE_OUTPUT_INIT; - - struct ofputil_packet_out po = { - .packet = dp_packet_data(pkt), -@@ -870,7 +870,7 @@ pinctrl_parse_dhcpv6_advt(struct rconn *swconn, const struct flow *ip_flow, - 0, 32, &ofpacts); - struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts); - resubmit->in_port = OFPP_CONTROLLER; -- resubmit->table_id = OFTABLE_REMOTE_OUTPUT; -+ resubmit->table_id = OFTABLE_OUTPUT_INIT; - - struct ofputil_packet_out po = { - .packet = dp_packet_data(&packet), -@@ -1499,7 +1499,7 @@ buffered_push_packet(struct buffered_packets *bp, - - struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&bi->ofpacts); - resubmit->in_port = OFPP_CONTROLLER; -- resubmit->table_id = OFTABLE_REMOTE_OUTPUT; -+ resubmit->table_id = OFTABLE_OUTPUT_INIT; - - bi->p = packet; - -@@ -2444,19 +2444,19 @@ compose_out_dhcpv6_opts(struct ofpbuf *userdata, - struct ofpbuf *out_dhcpv6_opts, ovs_be32 iaid) - { - while (userdata->size) { -- struct dhcp_opt6_header *userdata_opt = ofpbuf_try_pull( -+ struct dhcpv6_opt_header *userdata_opt = ofpbuf_try_pull( - userdata, sizeof *userdata_opt); - if (!userdata_opt) { - return false; - } - -- size_t size = ntohs(userdata_opt->size); -+ size_t size = ntohs(userdata_opt->len); - uint8_t *userdata_opt_data = ofpbuf_try_pull(userdata, size); - if (!userdata_opt_data) { - return false; - } - -- switch (ntohs(userdata_opt->opt_code)) { -+ switch (ntohs(userdata_opt->code)) { - case DHCPV6_OPT_SERVER_ID_CODE: - { - /* The Server Identifier option carries a DUID -@@ -2988,6 +2988,13 @@ pinctrl_handle_dns_lookup( - goto exit; - } - -+ /* Check if there is an additional record present, which is unsupported */ -+ if (in_dns_header->arcount) { -+ VLOG_DBG_RL(&rl, "Received DNS query with additional records, which" -+ " is unsupported"); -+ goto exit; -+ } -+ - struct udp_header *in_udp = dp_packet_l4(pkt_in); - size_t udp_len = ntohs(in_udp->udp_len); - size_t l4_len = dp_packet_l4_size(pkt_in); -@@ -7190,7 +7197,9 @@ bfd_monitor_send_msg(struct rconn *swconn, long long int *bfd_time) - pinctrl_send_bfd_tx_msg(swconn, entry, false); - - tx_timeout = MAX(entry->local_min_tx, entry->remote_min_rx); -- tx_timeout -= random_range((tx_timeout * 25) / 100); -+ if (tx_timeout >= 4) { -+ tx_timeout -= random_range(tx_timeout / 4); -+ } - entry->next_tx = cur_time + tx_timeout; - next: - if (*bfd_time > entry->next_tx) { -diff --git a/debian/changelog b/debian/changelog -index 11a07dd38..02a9953ba 100644 ---- a/debian/changelog -+++ b/debian/changelog -@@ -1,3 +1,9 @@ -+OVN (23.03.1-1) unstable; urgency=low -+ [ OVN team ] -+ * New upstream version -+ -+ -- OVN team Fri, 03 Mar 2023 10:40:37 -0500 -+ - ovn (23.03.0-1) unstable; urgency=low - - * New upstream version -diff --git a/include/ovn/actions.h b/include/ovn/actions.h -index 28479ede1..c973fce9c 100644 ---- a/include/ovn/actions.h -+++ b/include/ovn/actions.h -@@ -895,6 +895,9 @@ void ovnacts_free(struct ovnact[], size_t ovnacts_len); - char *ovnact_op_to_string(uint32_t); - int encode_ra_dnssl_opt(char *data, char *buf, int buf_len); - -+size_t encode_start_controller_op(enum action_opcode opcode, bool pause, -+ uint32_t meter_id, struct ofpbuf *ofpacts); -+void encode_finish_controller_op(size_t ofs, struct ofpbuf *ofpacts); - void encode_controller_op(enum action_opcode opcode, uint32_t meter_id, - struct ofpbuf *ofpacts); - -diff --git a/lib/actions.c b/lib/actions.c -index 781549d75..ec27223f9 100644 ---- a/lib/actions.c -+++ b/lib/actions.c -@@ -79,7 +79,7 @@ ovnact_init(struct ovnact *ovnact, enum ovnact_type type, size_t len) - ovnact->len = len; - } - --static size_t -+size_t - encode_start_controller_op(enum action_opcode opcode, bool pause, - uint32_t meter_id, struct ofpbuf *ofpacts) - { -@@ -100,7 +100,7 @@ encode_start_controller_op(enum action_opcode opcode, bool pause, - return ofs; - } - --static void -+void - encode_finish_controller_op(size_t ofs, struct ofpbuf *ofpacts) - { - struct ofpact_controller *oc = ofpbuf_at_assert(ofpacts, ofs, sizeof *oc); -@@ -2882,26 +2882,26 @@ static void - encode_put_dhcpv6_option(const struct ovnact_gen_option *o, - struct ofpbuf *ofpacts) - { -- struct dhcp_opt6_header *opt = ofpbuf_put_uninit(ofpacts, sizeof *opt); -+ struct dhcpv6_opt_header *opt = ofpbuf_put_uninit(ofpacts, sizeof *opt); - const union expr_constant *c = o->value.values; - size_t n_values = o->value.n_values; - size_t size; - -- opt->opt_code = htons(o->option->code); -+ opt->code = htons(o->option->code); - - if (!strcmp(o->option->type, "ipv6")) { - size = n_values * sizeof(struct in6_addr); -- opt->size = htons(size); -+ opt->len = htons(size); - for (size_t i = 0; i < n_values; i++) { - ofpbuf_put(ofpacts, &c[i].value.ipv6, sizeof(struct in6_addr)); - } - } else if (!strcmp(o->option->type, "mac")) { - size = sizeof(struct eth_addr); -- opt->size = htons(size); -+ opt->len = htons(size); - ofpbuf_put(ofpacts, &c->value.mac, size); - } else if (!strcmp(o->option->type, "str")) { - size = strlen(c->string); -- opt->size = htons(size); -+ opt->len = htons(size); - ofpbuf_put(ofpacts, c->string, size); - } - } -diff --git a/lib/lb.c b/lib/lb.c -index e941434c4..f88c1855b 100644 ---- a/lib/lb.c -+++ b/lib/lb.c -@@ -38,6 +38,7 @@ static const char *lb_neighbor_responder_mode_names[] = { - static struct nbrec_load_balancer_health_check * - ovn_lb_get_health_check(const struct nbrec_load_balancer *nbrec_lb, - const char *vip_port_str, bool template); -+static void ovn_lb_backends_clear(struct ovn_lb_vip *vip); - - struct ovn_lb_ip_set * - ovn_lb_ip_set_create(void) -@@ -238,6 +239,8 @@ ovn_lb_backends_init_template(struct ovn_lb_vip *lb_vip, const char *value_) - ds_put_format(&errors, "%s: should be a template of the form: " - "'^backendip_variable1[:^port_variable1|:port]', ", - atom); -+ free(backend_port); -+ free(backend_ip); - } - free(atom); - } -@@ -285,8 +288,27 @@ ovn_lb_vip_init_template(struct ovn_lb_vip *lb_vip, const char *lb_key_, - lb_key_); - } - -+ /* Backends can either be templates or explicit IPs and ports. */ - lb_vip->address_family = address_family; -- return ovn_lb_backends_init_template(lb_vip, lb_value); -+ lb_vip->template_backends = true; -+ char *template_error = ovn_lb_backends_init_template(lb_vip, lb_value); -+ -+ if (template_error) { -+ lb_vip->template_backends = false; -+ ovn_lb_backends_clear(lb_vip); -+ -+ char *explicit_error = ovn_lb_backends_init_explicit(lb_vip, lb_value); -+ if (explicit_error) { -+ char *error = -+ xasprintf("invalid backend: template (%s) OR explicit (%s)", -+ template_error, explicit_error); -+ free(explicit_error); -+ free(template_error); -+ return error; -+ } -+ free(template_error); -+ } -+ return NULL; - } - - /* Returns NULL on success, an error string on failure. The caller is -@@ -304,15 +326,29 @@ ovn_lb_vip_init(struct ovn_lb_vip *lb_vip, const char *lb_key, - address_family); - } - --void --ovn_lb_vip_destroy(struct ovn_lb_vip *vip) -+static void -+ovn_lb_backends_destroy(struct ovn_lb_vip *vip) - { -- free(vip->vip_str); -- free(vip->port_str); - for (size_t i = 0; i < vip->n_backends; i++) { - free(vip->backends[i].ip_str); - free(vip->backends[i].port_str); - } -+} -+ -+static void -+ovn_lb_backends_clear(struct ovn_lb_vip *vip) -+{ -+ ovn_lb_backends_destroy(vip); -+ vip->backends = NULL; -+ vip->n_backends = 0; -+} -+ -+void -+ovn_lb_vip_destroy(struct ovn_lb_vip *vip) -+{ -+ free(vip->vip_str); -+ free(vip->port_str); -+ ovn_lb_backends_destroy(vip); - free(vip->backends); - } - -@@ -357,11 +393,10 @@ ovn_lb_vip_format(const struct ovn_lb_vip *vip, struct ds *s, bool template) - } - - void --ovn_lb_vip_backends_format(const struct ovn_lb_vip *vip, struct ds *s, -- bool template) -+ovn_lb_vip_backends_format(const struct ovn_lb_vip *vip, struct ds *s) - { - bool needs_brackets = vip->address_family == AF_INET6 && vip->port_str -- && !template; -+ && !vip->template_backends; - for (size_t i = 0; i < vip->n_backends; i++) { - struct ovn_lb_backend *backend = &vip->backends[i]; - -@@ -798,6 +833,7 @@ ovn_controller_lb_create(const struct sbrec_load_balancer *sbrec_lb, - lb->hairpin_orig_tuple = smap_get_bool(&sbrec_lb->options, - "hairpin_orig_tuple", - false); -+ lb->ct_flush = smap_get_bool(&sbrec_lb->options, "ct_flush", false); - ovn_lb_get_hairpin_snat_ip(&sbrec_lb->header_.uuid, &sbrec_lb->options, - &lb->hairpin_snat_ips); - return lb; -diff --git a/lib/lb.h b/lib/lb.h -index 7a67b7426..e24f519db 100644 ---- a/lib/lb.h -+++ b/lib/lb.h -@@ -96,6 +96,9 @@ struct ovn_lb_vip { - */ - struct ovn_lb_backend *backends; - size_t n_backends; -+ bool template_backends; /* True if the backends are templates. False if -+ * they're explicitly specified. -+ */ - bool empty_backend_rej; - int address_family; - }; -@@ -188,6 +191,7 @@ struct ovn_controller_lb { - bool hairpin_orig_tuple; /* True if ovn-northd stores the original - * destination tuple in registers. - */ -+ bool ct_flush; /* True if we should flush CT after backend removal. */ - - struct lport_addresses hairpin_snat_ips; /* IP (v4 and/or v6) to be used - * as source for hairpinned -@@ -210,8 +214,7 @@ char *ovn_lb_vip_init(struct ovn_lb_vip *lb_vip, const char *lb_key, - void ovn_lb_vip_destroy(struct ovn_lb_vip *vip); - void ovn_lb_vip_format(const struct ovn_lb_vip *vip, struct ds *s, - bool template); --void ovn_lb_vip_backends_format(const struct ovn_lb_vip *vip, struct ds *s, -- bool template); -+void ovn_lb_vip_backends_format(const struct ovn_lb_vip *vip, struct ds *s); - - struct ovn_lb_5tuple { - struct hmap_node hmap_node; -diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h -index 2b20bc380..d718ed39a 100644 ---- a/lib/ovn-l7.h -+++ b/lib/ovn-l7.h -@@ -240,12 +240,6 @@ struct dhcp_opt_header { - #define DHCP_OPT_PAYLOAD(hdr) \ - (void *)((char *)hdr + sizeof(struct dhcp_opt_header)) - --/* Used in the OpenFlow PACKET_IN userdata */ --struct dhcp_opt6_header { -- ovs_be16 opt_code; -- ovs_be16 size; --}; -- - /* These are not defined in ovs/lib/dhcp.h, hence defining here. */ - #define OVN_DHCP_MSG_DECLINE 4 - #define OVN_DHCP_MSG_RELEASE 7 -diff --git a/lib/ovn-util.h b/lib/ovn-util.h -index a1a418a24..7510fda4b 100644 ---- a/lib/ovn-util.h -+++ b/lib/ovn-util.h -@@ -28,6 +28,13 @@ - #define ROUTE_ORIGIN_CONNECTED "connected" - #define ROUTE_ORIGIN_STATIC "static" - -+#define ETH_CRC_LENGTH 4 -+#define ETHERNET_OVERHEAD (ETH_HEADER_LEN + ETH_CRC_LENGTH) -+ -+#define GENEVE_TUNNEL_OVERHEAD 38 -+#define STT_TUNNEL_OVERHEAD 18 -+#define VXLAN_TUNNEL_OVERHEAD 30 -+ - struct eth_addr; - struct nbrec_logical_router_port; - struct ovsrec_flow_sample_collector_set_table; -diff --git a/northd/en-sync-sb.c b/northd/en-sync-sb.c -index 6e33901a8..20f0d8a82 100644 ---- a/northd/en-sync-sb.c -+++ b/northd/en-sync-sb.c -@@ -22,7 +22,6 @@ - #include "openvswitch/util.h" - - #include "en-sync-sb.h" --#include "include/ovn/expr.h" - #include "lib/inc-proc-eng.h" - #include "lib/lb.h" - #include "lib/ovn-nb-idl.h" -@@ -34,8 +33,15 @@ - - VLOG_DEFINE_THIS_MODULE(en_sync_to_sb); - -+/* This is just a type wrapper to enforce that it has to be sorted. */ -+struct sorted_addresses { -+ const char **arr; -+ size_t n; -+}; -+ -+ - static void sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, -- const char **addrs, size_t n_addrs, -+ struct sorted_addresses *addresses, - struct shash *sb_address_sets); - static void sync_addr_sets(const struct nbrec_address_set_table *, - const struct nbrec_port_group_table *, -@@ -44,11 +50,17 @@ static void sync_addr_sets(const struct nbrec_address_set_table *, - struct hmap *datapaths); - static const struct sbrec_address_set *sb_address_set_lookup_by_name( - struct ovsdb_idl_index *, const char *name); --static void update_sb_addr_set(const char **nb_addresses, size_t n_addresses, -+static void update_sb_addr_set(struct sorted_addresses *, - const struct sbrec_address_set *); - static void build_port_group_address_set(const struct nbrec_port_group *, - struct svec *ipv4_addrs, - struct svec *ipv6_addrs); -+static struct sorted_addresses -+sorted_addresses_from_nbrec(const struct nbrec_address_set *nb_as); -+static struct sorted_addresses -+sorted_addresses_from_svec(struct svec *addresses); -+static struct sorted_addresses -+sorted_addresses_from_sset(struct sset *addresses); - - void * - en_sync_to_sb_init(struct engine_node *node OVS_UNUSED, -@@ -133,8 +145,9 @@ sync_to_sb_addr_set_nb_address_set_handler(struct engine_node *node, - if (!sb_addr_set) { - return false; - } -- update_sb_addr_set((const char **) nb_addr_set->addresses, -- nb_addr_set->n_addresses, sb_addr_set); -+ struct sorted_addresses addrs = -+ sorted_addresses_from_nbrec(nb_addr_set); -+ update_sb_addr_set(&addrs, sb_addr_set); - } - - return true; -@@ -180,10 +193,14 @@ sync_to_sb_addr_set_nb_port_group_handler(struct engine_node *node, - struct svec ipv4_addrs = SVEC_EMPTY_INITIALIZER; - struct svec ipv6_addrs = SVEC_EMPTY_INITIALIZER; - build_port_group_address_set(nb_pg, &ipv4_addrs, &ipv6_addrs); -- update_sb_addr_set((const char **) ipv4_addrs.names, ipv4_addrs.n, -- sb_addr_set_v4); -- update_sb_addr_set((const char **) ipv6_addrs.names, ipv6_addrs.n, -- sb_addr_set_v6); -+ -+ struct sorted_addresses ipv4_addrs_sorted = -+ sorted_addresses_from_svec(&ipv4_addrs); -+ struct sorted_addresses ipv6_addrs_sorted = -+ sorted_addresses_from_svec(&ipv6_addrs); -+ -+ update_sb_addr_set(&ipv4_addrs_sorted, sb_addr_set_v4); -+ update_sb_addr_set(&ipv6_addrs_sorted, sb_addr_set_v6); - - free(ipv4_addrs_name); - free(ipv6_addrs_name); -@@ -197,7 +214,7 @@ sync_to_sb_addr_set_nb_port_group_handler(struct engine_node *node, - /* static functions. */ - static void - sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, -- const char **addrs, size_t n_addrs, -+ struct sorted_addresses *addresses, - struct shash *sb_address_sets) - { - const struct sbrec_address_set *sb_address_set; -@@ -206,10 +223,10 @@ sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, - if (!sb_address_set) { - sb_address_set = sbrec_address_set_insert(ovnsb_txn); - sbrec_address_set_set_name(sb_address_set, name); -- sbrec_address_set_set_addresses(sb_address_set, -- addrs, n_addrs); -+ sbrec_address_set_set_addresses(sb_address_set, addresses->arr, -+ addresses->n); - } else { -- update_sb_addr_set(addrs, n_addrs, sb_address_set); -+ update_sb_addr_set(addresses, sb_address_set); - } - } - -@@ -243,8 +260,11 @@ sync_addr_sets(const struct nbrec_address_set_table *nb_address_set_table, - - /* Service monitor MAC. */ - const char *svc_monitor_macp = northd_get_svc_monitor_mac(); -- sync_addr_set(ovnsb_txn, "svc_monitor_mac", &svc_monitor_macp, 1, -- &sb_address_sets); -+ struct sorted_addresses svc = { -+ .arr = &svc_monitor_macp, -+ .n = 1, -+ }; -+ sync_addr_set(ovnsb_txn, "svc_monitor_mac", &svc, &sb_address_sets); - - /* sync port group generated address sets first */ - const struct nbrec_port_group *nb_port_group; -@@ -255,14 +275,16 @@ sync_addr_sets(const struct nbrec_address_set_table *nb_address_set_table, - build_port_group_address_set(nb_port_group, &ipv4_addrs, &ipv6_addrs); - char *ipv4_addrs_name = xasprintf("%s_ip4", nb_port_group->name); - char *ipv6_addrs_name = xasprintf("%s_ip6", nb_port_group->name); -+ -+ struct sorted_addresses ipv4_addrs_sorted = -+ sorted_addresses_from_svec(&ipv4_addrs); -+ struct sorted_addresses ipv6_addrs_sorted = -+ sorted_addresses_from_svec(&ipv6_addrs); -+ - sync_addr_set(ovnsb_txn, ipv4_addrs_name, -- /* "char **" is not compatible with "const char **" */ -- (const char **) ipv4_addrs.names, -- ipv4_addrs.n, &sb_address_sets); -+ &ipv4_addrs_sorted, &sb_address_sets); - sync_addr_set(ovnsb_txn, ipv6_addrs_name, -- /* "char **" is not compatible with "const char **" */ -- (const char **) ipv6_addrs.names, -- ipv6_addrs.n, &sb_address_sets); -+ &ipv6_addrs_sorted, &sb_address_sets); - free(ipv4_addrs_name); - free(ipv6_addrs_name); - svec_destroy(&ipv4_addrs); -@@ -279,27 +301,26 @@ sync_addr_sets(const struct nbrec_address_set_table *nb_address_set_table, - if (sset_count(&od->lb_ips->ips_v4_reachable)) { - char *ipv4_addrs_name = lr_lb_address_set_name(od->tunnel_key, - AF_INET); -- const char **ipv4_addrs = -- sset_array(&od->lb_ips->ips_v4_reachable); - -- sync_addr_set(ovnsb_txn, ipv4_addrs_name, ipv4_addrs, -- sset_count(&od->lb_ips->ips_v4_reachable), -- &sb_address_sets); -+ struct sorted_addresses ipv4_addrs_sorted = -+ sorted_addresses_from_sset(&od->lb_ips->ips_v4_reachable); -+ -+ sync_addr_set(ovnsb_txn, ipv4_addrs_name, -+ &ipv4_addrs_sorted, &sb_address_sets); -+ free(ipv4_addrs_sorted.arr); - free(ipv4_addrs_name); -- free(ipv4_addrs); - } - - if (sset_count(&od->lb_ips->ips_v6_reachable)) { - char *ipv6_addrs_name = lr_lb_address_set_name(od->tunnel_key, - AF_INET6); -- const char **ipv6_addrs = -- sset_array(&od->lb_ips->ips_v6_reachable); -+ struct sorted_addresses ipv6_addrs_sorted = -+ sorted_addresses_from_sset(&od->lb_ips->ips_v6_reachable); - -- sync_addr_set(ovnsb_txn, ipv6_addrs_name, ipv6_addrs, -- sset_count(&od->lb_ips->ips_v6_reachable), -- &sb_address_sets); -+ sync_addr_set(ovnsb_txn, ipv6_addrs_name, -+ &ipv6_addrs_sorted, &sb_address_sets); -+ free(ipv6_addrs_sorted.arr); - free(ipv6_addrs_name); -- free(ipv6_addrs); - } - } - -@@ -308,10 +329,10 @@ sync_addr_sets(const struct nbrec_address_set_table *nb_address_set_table, - const struct nbrec_address_set *nb_address_set; - NBREC_ADDRESS_SET_TABLE_FOR_EACH (nb_address_set, - nb_address_set_table) { -+ struct sorted_addresses addrs = -+ sorted_addresses_from_nbrec(nb_address_set); - sync_addr_set(ovnsb_txn, nb_address_set->name, -- /* "char **" is not compatible with "const char **" */ -- (const char **) nb_address_set->addresses, -- nb_address_set->n_addresses, &sb_address_sets); -+ &addrs, &sb_address_sets); - } - - struct shash_node *node; -@@ -323,48 +344,39 @@ sync_addr_sets(const struct nbrec_address_set_table *nb_address_set_table, - } - - static void --update_sb_addr_set(const char **nb_addresses, size_t n_addresses, -+update_sb_addr_set(struct sorted_addresses *nb_addresses, - const struct sbrec_address_set *sb_as) - { -- struct expr_constant_set *cs_nb_as = -- expr_constant_set_create_integers( -- (const char *const *) nb_addresses, n_addresses); -- struct expr_constant_set *cs_sb_as = -- expr_constant_set_create_integers( -- (const char *const *) sb_as->addresses, sb_as->n_addresses); -- -- struct expr_constant_set *addr_added = NULL; -- struct expr_constant_set *addr_deleted = NULL; -- expr_constant_set_integers_diff(cs_sb_as, cs_nb_as, &addr_added, -- &addr_deleted); -- -- struct ds ds = DS_EMPTY_INITIALIZER; -- if (addr_added && addr_added->n_values) { -- for (size_t i = 0; i < addr_added->n_values; i++) { -- ds_clear(&ds); -- expr_constant_format(&addr_added->values[i], EXPR_C_INTEGER, &ds); -- sbrec_address_set_update_addresses_addvalue(sb_as, ds_cstr(&ds)); -+ size_t nb_index, sb_index; -+ -+ const char **nb_arr = nb_addresses->arr; -+ char **sb_arr = sb_as->addresses; -+ size_t nb_n = nb_addresses->n; -+ size_t sb_n = sb_as->n_addresses; -+ -+ for (nb_index = sb_index = 0; nb_index < nb_n && sb_index < sb_n;) { -+ int cmp = strcmp(nb_arr[nb_index], sb_arr[sb_index]); -+ if (cmp < 0) { -+ sbrec_address_set_update_addresses_addvalue(sb_as, -+ nb_arr[nb_index]); -+ nb_index++; -+ } else if (cmp > 0) { -+ sbrec_address_set_update_addresses_delvalue(sb_as, -+ sb_arr[sb_index]); -+ sb_index++; -+ } else { -+ nb_index++; -+ sb_index++; - } - } - -- if (addr_deleted && addr_deleted->n_values) { -- for (size_t i = 0; i < addr_deleted->n_values; i++) { -- ds_clear(&ds); -- expr_constant_format(&addr_deleted->values[i], -- EXPR_C_INTEGER, &ds); -- sbrec_address_set_update_addresses_delvalue(sb_as, ds_cstr(&ds)); -- } -+ for (; nb_index < nb_n; nb_index++) { -+ sbrec_address_set_update_addresses_addvalue(sb_as, nb_arr[nb_index]); - } - -- ds_destroy(&ds); -- expr_constant_set_destroy(cs_nb_as); -- free(cs_nb_as); -- expr_constant_set_destroy(cs_sb_as); -- free(cs_sb_as); -- expr_constant_set_destroy(addr_added); -- free(addr_added); -- expr_constant_set_destroy(addr_deleted); -- free(addr_deleted); -+ for (; sb_index < sb_n; sb_index++) { -+ sbrec_address_set_update_addresses_delvalue(sb_as, sb_arr[sb_index]); -+ } - } - - static void -@@ -403,3 +415,32 @@ sb_address_set_lookup_by_name(struct ovsdb_idl_index *sbrec_addr_set_by_name, - - return retval; - } -+ -+static struct sorted_addresses -+sorted_addresses_from_nbrec(const struct nbrec_address_set *nb_as) -+{ -+ /* The DB is already sorted. */ -+ return (struct sorted_addresses) { -+ .arr = (const char **) nb_as->addresses, -+ .n = nb_as->n_addresses, -+ }; -+} -+ -+static struct sorted_addresses -+sorted_addresses_from_svec(struct svec *addresses) -+{ -+ svec_sort(addresses); -+ return (struct sorted_addresses) { -+ .arr = (const char **) addresses->names, -+ .n = addresses->n, -+ }; -+} -+ -+static struct sorted_addresses -+sorted_addresses_from_sset(struct sset *addresses) -+{ -+ return (struct sorted_addresses) { -+ .arr = sset_sort(addresses), -+ .n = sset_count(addresses), -+ }; -+} -diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c -index d23993a55..fd025c92b 100644 ---- a/northd/inc-proc-northd.c -+++ b/northd/inc-proc-northd.c -@@ -34,10 +34,13 @@ - #include "en-lflow.h" - #include "en-northd-output.h" - #include "en-sync-sb.h" -+#include "unixctl.h" - #include "util.h" - - VLOG_DEFINE_THIS_MODULE(inc_proc_northd); - -+static unixctl_cb_func chassis_features_list; -+ - #define NB_NODES \ - NB_NODE(nb_global, "nb_global") \ - NB_NODE(copp, "copp") \ -@@ -306,6 +309,12 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, - engine_ovsdb_node_add_index(&en_sb_address_set, - "sbrec_address_set_by_name", - sbrec_address_set_by_name); -+ -+ struct northd_data *northd_data = -+ engine_get_internal_data(&en_northd); -+ unixctl_command_register("debug/chassis-features-list", "", 0, 0, -+ chassis_features_list, -+ &northd_data->features); - } - - /* Returns true if the incremental processing ended up updating nodes. */ -@@ -356,3 +365,20 @@ void inc_proc_northd_cleanup(void) - engine_cleanup(); - engine_set_context(NULL); - } -+ -+static void -+chassis_features_list(struct unixctl_conn *conn, int argc OVS_UNUSED, -+ const char *argv[] OVS_UNUSED, void *features_) -+{ -+ struct chassis_features *features = features_; -+ struct ds ds = DS_EMPTY_INITIALIZER; -+ -+ ds_put_format(&ds, "ct_no_masked_label: %s\n", -+ features->ct_no_masked_label ? "true" : "false"); -+ ds_put_format(&ds, "ct_lb_related: %s\n", -+ features->ct_lb_related ? "true" : "false"); -+ ds_put_format(&ds, "mac_binding_timestamp: %s\n", -+ features->mac_binding_timestamp ? "true" : "false"); -+ unixctl_command_reply(conn, ds_cstr(&ds)); -+ ds_destroy(&ds); -+} -diff --git a/northd/northd.c b/northd/northd.c -index 7ad4cdfad..66f14e9dd 100644 ---- a/northd/northd.c -+++ b/northd/northd.c -@@ -239,6 +239,8 @@ enum ovn_stage { - * one of the logical router's own IP addresses. */ - #define REGBIT_EGRESS_LOOPBACK "reg9[0]" - /* Register to store the result of check_pkt_larger action. */ -+/* This register is also used by ovn-controller in -+ * OFTABLE_OUTPUT_LARGE_PKT_DETECT table, for a similar goal. */ - #define REGBIT_PKT_LARGER "reg9[1]" - #define REGBIT_LOOKUP_NEIGHBOR_RESULT "reg9[2]" - #define REGBIT_LOOKUP_NEIGHBOR_IP_RESULT "reg9[3]" -@@ -432,6 +434,13 @@ build_chassis_features(const struct northd_input *input_data, - const struct sbrec_chassis *chassis; - - SBREC_CHASSIS_TABLE_FOR_EACH (chassis, input_data->sbrec_chassis) { -+ /* Only consider local AZ chassis. Remote ones don't install -+ * flows generated by the local northd. -+ */ -+ if (smap_get_bool(&chassis->other_config, "is-remote", false)) { -+ continue; -+ } -+ - bool ct_no_masked_label = - smap_get_bool(&chassis->other_config, - OVN_FEATURE_CT_NO_MASKED_LABEL, -@@ -552,7 +561,7 @@ free_chassis_queueid(struct hmap *set, const struct uuid *uuid, - static inline bool - port_has_qos_params(const struct smap *opts) - { -- return (smap_get(opts, "qos_max_rate") || -+ return (smap_get(opts, "qos_max_rate") || smap_get(opts, "qos_min_rate") || - smap_get(opts, "qos_burst")); - } - -@@ -1641,6 +1650,10 @@ ovn_port_destroy(struct hmap *ports, struct ovn_port *port) - * use it. */ - hmap_remove(ports, &port->key_node); - -+ if (port->peer) { -+ port->peer->peer = NULL; -+ } -+ - for (int i = 0; i < port->n_lsp_addrs; i++) { - destroy_lport_addresses(&port->lsp_addrs[i]); - } -@@ -3881,7 +3894,7 @@ build_lb_vip_actions(struct ovn_lb_vip *lb_vip, - const char *ct_lb_action = - features->ct_no_masked_label ? "ct_lb_mark" : "ct_lb"; - bool reject = !lb_vip->n_backends && lb_vip->empty_backend_rej; -- bool drop = false; -+ bool drop = !lb_vip->n_backends && !lb_vip->empty_backend_rej; - - if (lb_vip_nb->lb_health_check) { - ds_put_format(action, "%s(backends=", ct_lb_action); -@@ -5779,20 +5792,24 @@ skip_port_from_conntrack(struct ovn_datapath *od, struct ovn_port *op, - * know about the connection, as the icmp request went through the logical - * router on hostA, not hostB. This would only work with distributed - * conntrack state across all chassis. */ -- struct ds match_in = DS_EMPTY_INITIALIZER; -- struct ds match_out = DS_EMPTY_INITIALIZER; - -- ds_put_format(&match_in, "ip && inport == %s", op->json_key); -- ds_put_format(&match_out, "ip && outport == %s", op->json_key); -+ const char *ingress_action = "next;"; -+ const char *egress_action = od->has_stateful_acl -+ ? "next;" -+ : "ct_clear; next;"; -+ -+ char *ingress_match = xasprintf("ip && inport == %s", op->json_key); -+ char *egress_match = xasprintf("ip && outport == %s", op->json_key); -+ - ovn_lflow_add_with_lport_and_hint(lflows, od, in_stage, priority, -- ds_cstr(&match_in), "next;", op->key, -- &op->nbsp->header_); -+ ingress_match, ingress_action, -+ op->key, &op->nbsp->header_); - ovn_lflow_add_with_lport_and_hint(lflows, od, out_stage, priority, -- ds_cstr(&match_out), "next;", op->key, -- &op->nbsp->header_); -+ egress_match, egress_action, -+ op->key, &op->nbsp->header_); - -- ds_destroy(&match_in); -- ds_destroy(&match_out); -+ free(ingress_match); -+ free(egress_match); - } - - static void -@@ -5867,7 +5884,8 @@ build_pre_acls(struct ovn_datapath *od, const struct hmap *port_groups, - } - for (size_t i = 0; i < od->n_localnet_ports; i++) { - skip_port_from_conntrack(od, od->localnet_ports[i], -- S_SWITCH_IN_PRE_ACL, S_SWITCH_OUT_PRE_ACL, -+ S_SWITCH_IN_PRE_ACL, -+ S_SWITCH_OUT_PRE_ACL, - 110, lflows); - } - -@@ -6036,10 +6054,17 @@ build_pre_lb(struct ovn_datapath *od, const struct shash *meter_groups, - S_SWITCH_IN_PRE_LB, S_SWITCH_OUT_PRE_LB, - 110, lflows); - } -- for (size_t i = 0; i < od->n_localnet_ports; i++) { -- skip_port_from_conntrack(od, od->localnet_ports[i], -- S_SWITCH_IN_PRE_LB, S_SWITCH_OUT_PRE_LB, -- 110, lflows); -+ /* Localnet ports have no need for going through conntrack, unless -+ * the logical switch has a load balancer. Then, conntrack is necessary -+ * so that traffic arriving via the localnet port can be load -+ * balanced. -+ */ -+ if (!od->has_lb_vip) { -+ for (size_t i = 0; i < od->n_localnet_ports; i++) { -+ skip_port_from_conntrack(od, od->localnet_ports[i], -+ S_SWITCH_IN_PRE_LB, S_SWITCH_OUT_PRE_LB, -+ 110, lflows); -+ } - } - - /* Do not sent statless flows via conntrack */ -@@ -6700,6 +6725,8 @@ build_port_group_lswitches(struct northd_input *input_data, - } - } - -+#define IPV6_CT_OMIT_MATCH "nd || nd_ra || nd_rs || mldv1 || mldv2" -+ - static void - build_acls(struct ovn_datapath *od, const struct chassis_features *features, - struct hmap *lflows, const struct hmap *port_groups, -@@ -6847,20 +6874,26 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features, - ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX - 3, - ds_cstr(&match), ct_out_acl_action); - -- /* Ingress and Egress ACL Table (Priority 65532). -- * -- * Not to do conntrack on ND packets. */ -- ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, UINT16_MAX - 3, -- "nd || nd_ra || nd_rs || mldv1 || mldv2", "next;"); -- ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX - 3, -- "nd || nd_ra || nd_rs || mldv1 || mldv2", "next;"); -- - /* Reply and related traffic matched by an "allow-related" ACL - * should be allowed in the ls_in_acl_after_lb stage too. */ - ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL_AFTER_LB, UINT16_MAX - 3, - REGBIT_ACL_HINT_ALLOW_REL" == 1", "next;"); - } - -+ /* Ingress and Egress ACL Table (Priority 65532). -+ * -+ * Always allow service IPv6 protocols regardless of other ACLs defined. -+ * -+ * Also, don't send them to conntrack because session tracking -+ * for these protocols is not working properly: -+ * https://bugzilla.kernel.org/show_bug.cgi?id=11797. */ -+ ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, UINT16_MAX - 3, -+ IPV6_CT_OMIT_MATCH, "next;"); -+ ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX - 3, -+ IPV6_CT_OMIT_MATCH, "next;"); -+ ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL_AFTER_LB, UINT16_MAX - 3, -+ IPV6_CT_OMIT_MATCH, "next;"); -+ - /* Ingress or Egress ACL Table (Various priorities). */ - for (size_t i = 0; i < od->nbs->n_acls; i++) { - struct nbrec_acl *acl = od->nbs->acls[i]; -@@ -7089,7 +7122,9 @@ build_lb_rules_pre_stateful(struct hmap *lflows, struct ovn_northd_lb *lb, - * - load balancing affinity check: - * table=lr_in_lb_aff_check, priority=100 - * match=(new_lb_match) -- * action=(REGBIT_KNOWN_LB_SESSION = chk_lb_aff(); next;) -+ * action=(REG_NEXT_HOP_IPV4 = ip4.dst; -+ * REG_ORIG_TP_DPORT_ROUTER = tcp.dst; -+ * REGBIT_KNOWN_LB_SESSION = chk_lb_aff(); next;) - * - * - load balancing: - * table=lr_in_dnat, priority=150 -@@ -7130,16 +7165,11 @@ build_lb_affinity_lr_flows(struct hmap *lflows, struct ovn_northd_lb *lb, - return; - } - -- static char *aff_check = REGBIT_KNOWN_LB_SESSION" = chk_lb_aff(); next;"; -- -- ovn_lflow_add_with_dp_group( -- lflows, dp_bitmap, S_ROUTER_IN_LB_AFF_CHECK, 100, -- new_lb_match, aff_check, &lb->nlb->header_); -- - struct ds aff_action = DS_EMPTY_INITIALIZER; - struct ds aff_action_learn = DS_EMPTY_INITIALIZER; - struct ds aff_match = DS_EMPTY_INITIALIZER; - struct ds aff_match_learn = DS_EMPTY_INITIALIZER; -+ struct ds aff_check_action = DS_EMPTY_INITIALIZER; - - bool ipv6 = !IN6_IS_ADDR_V4MAPPED(&lb_vip->vip); - const char *ip_match = ipv6 ? "ip6" : "ip4"; -@@ -7155,6 +7185,20 @@ build_lb_affinity_lr_flows(struct hmap *lflows, struct ovn_northd_lb *lb, - ct_flag = "; force_snat"; - } - -+ /* Create affinity check flow. */ -+ ds_put_format(&aff_check_action, "%s = %s.dst; ", reg_vip, ip_match); -+ -+ if (lb_vip->port_str) { -+ ds_put_format(&aff_check_action, REG_ORIG_TP_DPORT_ROUTER" = %s.dst; ", -+ lb->proto); -+ } -+ ds_put_cstr(&aff_check_action, REGBIT_KNOWN_LB_SESSION -+ " = chk_lb_aff(); next;"); -+ -+ ovn_lflow_add_with_dp_group( -+ lflows, dp_bitmap, S_ROUTER_IN_LB_AFF_CHECK, 100, -+ new_lb_match, ds_cstr(&aff_check_action), &lb->nlb->header_); -+ - /* Prepare common part of affinity LB and affinity learn action. */ - ds_put_format(&aff_action, "%s = %s; ", reg_vip, lb_vip->vip_str); - ds_put_cstr(&aff_action_learn, "commit_lb_aff(vip = \""); -@@ -7252,6 +7296,7 @@ build_lb_affinity_lr_flows(struct hmap *lflows, struct ovn_northd_lb *lb, - ds_destroy(&aff_action_learn); - ds_destroy(&aff_match); - ds_destroy(&aff_match_learn); -+ ds_destroy(&aff_check_action); - } - - /* Builds the logical switch flows related to load balancer affinity. -@@ -7628,38 +7673,36 @@ build_lb_hairpin(struct ovn_datapath *od, struct hmap *lflows) - static void - build_vtep_hairpin(struct ovn_datapath *od, struct hmap *lflows) - { -- /* Ingress Pre-ARP flows for VTEP hairpining traffic. Priority 1000: -- * Packets that received from non-VTEP ports should continue processing. */ -+ if (!od->has_vtep_lports) { -+ /* There is no need in these flows if datapath has no vtep lports. */ -+ return; -+ } - -+ /* Ingress Pre-ARP flows for VTEP hairpining traffic. Priority 1000: -+ * Packets received from VTEP ports must go directly to L2LKP table. -+ */ - char *action = xasprintf("next(pipeline=ingress, table=%d);", - ovn_stage_get_table(S_SWITCH_IN_L2_LKUP)); -- /* send all traffic from VTEP directly to L2LKP table. */ - ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 1000, - REGBIT_FROM_RAMP" == 1", action); - free(action); - -- struct ds match = DS_EMPTY_INITIALIZER; -- size_t n_ports = od->n_router_ports; -- bool dp_has_l3dgw_ports = false; -- for (int i = 0; i < n_ports; i++) { -- if (is_l3dgw_port(od->router_ports[i]->peer)) { -- ds_put_format(&match, "%sis_chassis_resident(%s)%s", -- i == 0 ? REGBIT_FROM_RAMP" == 1 && (" : "", -- od->router_ports[i]->peer->cr_port->json_key, -- i < n_ports - 1 ? " || " : ")"); -- dp_has_l3dgw_ports = true; -- } -- } -- - /* Ingress pre-arp flow for traffic from VTEP (ramp) switch. - * Priority 2000: Packets, that were received from VTEP (ramp) switch and - * router ports of current datapath are l3dgw ports and they reside on - * current chassis, should be passed to next table for ARP/ND hairpin -- * processing. -- */ -- if (dp_has_l3dgw_ports) { -- ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 2000, ds_cstr(&match), -- "next;"); -+ * processing. */ -+ struct ds match = DS_EMPTY_INITIALIZER; -+ for (int i = 0; i < od->n_router_ports; i++) { -+ struct ovn_port *op = od->router_ports[i]->peer; -+ if (is_l3dgw_port(op)) { -+ ds_clear(&match); -+ ds_put_format(&match, -+ REGBIT_FROM_RAMP" == 1 && is_chassis_resident(%s)", -+ op->cr_port->json_key); -+ ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 2000, -+ ds_cstr(&match), "next;"); -+ } - } - ds_destroy(&match); - } -@@ -8877,7 +8920,7 @@ build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od, - if (od->nbs) { - - ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 110, -- "eth.dst == $svc_monitor_mac", -+ "eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)", - "handle_svc_check(inport);"); - - struct mcast_switch_info *mcast_sw_info = &od->mcast_info.sw; -@@ -10450,10 +10493,8 @@ enum lrouter_nat_lb_flow_type { - - struct lrouter_nat_lb_flows_ctx { - const char *new_action[LROUTER_NAT_LB_FLOW_MAX]; -- const char *est_action[LROUTER_NAT_LB_FLOW_MAX]; - - struct ds *new_match; -- struct ds *est_match; - struct ds *undnat_match; - - struct ovn_lb_vip *lb_vip; -@@ -10471,10 +10512,22 @@ build_distr_lrouter_nat_flows_for_lb(struct lrouter_nat_lb_flows_ctx *ctx, - enum lrouter_nat_lb_flow_type type, - struct ovn_datapath *od) - { -- char *gw_action = od->is_gw_router ? "ct_dnat;" : "ct_dnat_in_czone;"; -+ const char *undnat_action; -+ -+ switch (type) { -+ case LROUTER_NAT_LB_FLOW_FORCE_SNAT: -+ undnat_action = "flags.force_snat_for_lb = 1; next;"; -+ break; -+ case LROUTER_NAT_LB_FLOW_SKIP_SNAT: -+ undnat_action = "flags.skip_snat_for_lb = 1; next;"; -+ break; -+ case LROUTER_NAT_LB_FLOW_NORMAL: -+ case LROUTER_NAT_LB_FLOW_MAX: -+ undnat_action = od->is_gw_router ? "ct_dnat;" : "ct_dnat_in_czone;"; -+ break; -+ } - /* Store the match lengths, so we can reuse the ds buffer. */ - size_t new_match_len = ctx->new_match->length; -- size_t est_match_len = ctx->est_match->length; - size_t undnat_match_len = ctx->undnat_match->length; - - -@@ -10487,33 +10540,24 @@ build_distr_lrouter_nat_flows_for_lb(struct lrouter_nat_lb_flows_ctx *ctx, - if (ctx->lb_vip->n_backends || !ctx->lb_vip->empty_backend_rej) { - ds_put_format(ctx->new_match, " && is_chassis_resident(%s)", - od->l3dgw_ports[0]->cr_port->json_key); -- ds_put_format(ctx->est_match, " && is_chassis_resident(%s)", -- od->l3dgw_ports[0]->cr_port->json_key); - } - - ovn_lflow_add_with_hint__(ctx->lflows, od, S_ROUTER_IN_DNAT, ctx->prio, - ds_cstr(ctx->new_match), ctx->new_action[type], - NULL, meter, &ctx->lb->nlb->header_); -- ovn_lflow_add_with_hint(ctx->lflows, od, S_ROUTER_IN_DNAT, ctx->prio, -- ds_cstr(ctx->est_match), ctx->est_action[type], -- &ctx->lb->nlb->header_); - - ds_truncate(ctx->new_match, new_match_len); -- ds_truncate(ctx->est_match, est_match_len); - - if (!ctx->lb_vip->n_backends) { - return; - } - -- const char *action = (type == LROUTER_NAT_LB_FLOW_NORMAL) -- ? gw_action : ctx->est_action[type]; -- - ds_put_format(ctx->undnat_match, - ") && outport == %s && is_chassis_resident(%s)", - od->l3dgw_ports[0]->json_key, - od->l3dgw_ports[0]->cr_port->json_key); - ovn_lflow_add_with_hint(ctx->lflows, od, S_ROUTER_OUT_UNDNAT, 120, -- ds_cstr(ctx->undnat_match), action, -+ ds_cstr(ctx->undnat_match), undnat_action, - &ctx->lb->nlb->header_); - ds_truncate(ctx->undnat_match, undnat_match_len); - } -@@ -10556,11 +10600,6 @@ build_gw_lrouter_nat_flows_for_lb(struct lrouter_nat_lb_flows_ctx *ctx, - ctx->new_action[type], &ctx->lb->nlb->header_); - } - bitmap_free(dp_non_meter); -- -- ovn_lflow_add_with_dp_group( -- ctx->lflows, dp_bitmap, S_ROUTER_IN_DNAT, ctx->prio, -- ds_cstr(ctx->est_match), ctx->est_action[type], -- &ctx->lb->nlb->header_); - } - - static void -@@ -10572,19 +10611,13 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, - const struct shash *meter_groups, - const struct chassis_features *features) - { -- const char *ct_natted = features->ct_no_masked_label -- ? "ct_mark.natted" -- : "ct_label.natted"; -- - bool ipv4 = lb_vip->address_family == AF_INET; - const char *ip_match = ipv4 ? "ip4" : "ip6"; -- const char *ip_reg = ipv4 ? REG_NEXT_HOP_IPV4 : REG_NEXT_HOP_IPV6; - - int prio = 110; - - struct ds skip_snat_act = DS_EMPTY_INITIALIZER; - struct ds force_snat_act = DS_EMPTY_INITIALIZER; -- struct ds est_match = DS_EMPTY_INITIALIZER; - struct ds undnat_match = DS_EMPTY_INITIALIZER; - struct ds unsnat_match = DS_EMPTY_INITIALIZER; - -@@ -10601,19 +10634,14 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, - * of "ct_lb_mark($targets);". The other flow is for ct.est with - * an action of "next;". - */ -- ds_put_format(match, "ct.new && !ct.rel && %s && %s == %s", -- ip_match, ip_reg, lb_vip->vip_str); -+ ds_put_format(match, "ct.new && !ct.rel && %s && %s.dst == %s", -+ ip_match, ip_match, lb_vip->vip_str); - if (lb_vip->port_str) { - prio = 120; -- ds_put_format(match, " && %s && "REG_ORIG_TP_DPORT_ROUTER" == %s", -- lb->proto, lb_vip->port_str); -+ ds_put_format(match, " && %s && %s.dst == %s", -+ lb->proto, lb->proto, lb_vip->port_str); - } - -- ds_put_cstr(&est_match, "ct.est"); -- /* Clone the match after initial "ct.new" (6 bytes). */ -- ds_put_cstr(&est_match, ds_cstr(match) + 6); -- ds_put_format(&est_match, " && %s == 1", ct_natted); -- - /* Add logical flows to UNDNAT the load balanced reverse traffic in - * the router egress pipleine stage - S_ROUTER_OUT_UNDNAT if the logical - * router has a gateway router port associated. -@@ -10650,20 +10678,12 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, - .lflows = lflows, - .meter_groups = meter_groups, - .new_match = match, -- .est_match = &est_match, - .undnat_match = &undnat_match - }; - - ctx.new_action[LROUTER_NAT_LB_FLOW_NORMAL] = ds_cstr(action); -- ctx.est_action[LROUTER_NAT_LB_FLOW_NORMAL] = "next;"; -- - ctx.new_action[LROUTER_NAT_LB_FLOW_SKIP_SNAT] = ds_cstr(&skip_snat_act); -- ctx.est_action[LROUTER_NAT_LB_FLOW_SKIP_SNAT] = -- "flags.skip_snat_for_lb = 1; next;"; -- - ctx.new_action[LROUTER_NAT_LB_FLOW_FORCE_SNAT] = ds_cstr(&force_snat_act); -- ctx.est_action[LROUTER_NAT_LB_FLOW_FORCE_SNAT] = -- "flags.force_snat_for_lb = 1; next;"; - - enum { - LROUTER_NAT_LB_AFF = LROUTER_NAT_LB_FLOW_MAX, -@@ -10746,7 +10766,6 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, - - ds_destroy(&unsnat_match); - ds_destroy(&undnat_match); -- ds_destroy(&est_match); - ds_destroy(&skip_snat_act); - ds_destroy(&force_snat_act); - -@@ -10820,39 +10839,19 @@ build_lrouter_defrag_flows_for_lb(struct ovn_northd_lb *lb, - return; - } - -- struct ds defrag_actions = DS_EMPTY_INITIALIZER; - for (size_t i = 0; i < lb->n_vips; i++) { - struct ovn_lb_vip *lb_vip = &lb->vips[i]; -+ bool ipv6 = lb_vip->address_family == AF_INET6; - int prio = 100; - -- ds_clear(&defrag_actions); - ds_clear(match); -- -- if (lb_vip->address_family == AF_INET) { -- ds_put_format(match, "ip && ip4.dst == %s", lb_vip->vip_str); -- ds_put_format(&defrag_actions, REG_NEXT_HOP_IPV4" = %s; ", -- lb_vip->vip_str); -- } else { -- ds_put_format(match, "ip && ip6.dst == %s", lb_vip->vip_str); -- ds_put_format(&defrag_actions, REG_NEXT_HOP_IPV6" = %s; ", -- lb_vip->vip_str); -- } -- -- if (lb_vip->port_str) { -- ds_put_format(match, " && %s", lb->proto); -- prio = 110; -- -- ds_put_format(&defrag_actions, REG_ORIG_TP_DPORT_ROUTER -- " = %s.dst; ", lb->proto); -- } -- -- ds_put_format(&defrag_actions, "ct_dnat;"); -+ ds_put_format(match, "ip && ip%c.dst == %s", ipv6 ? '6' : '4', -+ lb_vip->vip_str); - - ovn_lflow_add_with_dp_group( - lflows, lb->nb_lr_map, S_ROUTER_IN_DEFRAG, prio, -- ds_cstr(match), ds_cstr(&defrag_actions), &lb->nlb->header_); -+ ds_cstr(match), "ct_dnat;", &lb->nlb->header_); - } -- ds_destroy(&defrag_actions); - } - - static void -@@ -10991,15 +10990,10 @@ copy_ra_to_sb(struct ovn_port *op, const char *address_mode) - } - - static inline bool --lrouter_nat_is_stateless(const struct nbrec_nat *nat) -+lrouter_dnat_and_snat_is_stateless(const struct nbrec_nat *nat) - { -- const char *stateless = smap_get(&nat->options, "stateless"); -- -- if (stateless && !strcmp(stateless, "true")) { -- return true; -- } -- -- return false; -+ return smap_get_bool(&nat->options, "stateless", false) && -+ !strcmp(nat->type, "dnat_and_snat"); - } - - /* Handles the match criteria and actions in logical flow -@@ -11698,6 +11692,25 @@ build_neigh_learning_flows_for_lrouter( - ovn_lflow_add(lflows, od, S_ROUTER_IN_LOOKUP_NEIGHBOR, 100, "nd_na", - ds_cstr(actions)); - -+ if (!learn_from_arp_request) { -+ /* Add flow to skip GARP LLA if we don't know it already. -+ * From RFC 2461, section 4.4, Neighbor Advertisement Message -+ * Format, the Destination Address should be: -+ * For solicited advertisements, the Source Address of -+ * an invoking Neighbor Solicitation or, if the -+ * solicitation's Source Address is the unspecified -+ * address, the all-nodes multicast address. */ -+ ds_clear(actions); -+ ds_put_format(actions, REGBIT_LOOKUP_NEIGHBOR_RESULT -+ " = lookup_nd(inport, ip6.src, nd.tll); " -+ REGBIT_LOOKUP_NEIGHBOR_IP_RESULT -+ " = lookup_nd_ip(inport, ip6.src); next;"); -+ ovn_lflow_add(lflows, od, S_ROUTER_IN_LOOKUP_NEIGHBOR, 110, -+ "nd_na && ip6.src == fe80::/10 " -+ "&& ip6.dst == ff00::/8", -+ ds_cstr(actions)); -+ } -+ - ds_clear(actions); - ds_put_format(actions, REGBIT_LOOKUP_NEIGHBOR_RESULT - " = lookup_nd(inport, ip6.src, nd.sll); %snext;", -@@ -12814,8 +12827,7 @@ build_gateway_redirect_flows_for_lrouter( - for (int j = 0; j < od->n_nat_entries; j++) { - const struct ovn_nat *nat = &od->nat_entries[j]; - -- if (!lrouter_nat_is_stateless(nat->nb) || -- strcmp(nat->nb->type, "dnat_and_snat") || -+ if (!lrouter_dnat_and_snat_is_stateless(nat->nb) || - (!nat->nb->allowed_ext_ips && !nat->nb->exempted_ext_ips)) { - continue; - } -@@ -13038,9 +13050,27 @@ build_misc_local_traffic_drop_flows_for_lrouter( - ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 50, - "eth.bcast", debug_drop_action()); - -+ /* Avoid ICMP time exceeded for multicast, silent drop instead. -+ * See RFC1812 section 5.3.1: -+ * If the TTL is reduced to zero (or less), the packet MUST be -+ * discarded, and if the destination is NOT A MULTICAST address the -+ * router MUST send an ICMP Time Exceeded message ... -+ * -+ * The reason behind is that TTL has special meanings for multicast. -+ * For example, TTL = 1 means restricted to the same subnet, not -+ * forwarded by the router. So it is very common to see multicast -+ * packets with ttl = 1, and generating ICMP for such packets is -+ * harmful from both slowpath performance and functionality point of -+ * view. -+ * -+ * (priority-31 flows will send ICMP time exceeded) */ -+ ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 32, -+ "ip.ttl == {0, 1} && !ip.later_frag && " -+ "(ip4.mcast || ip6.mcast)", debug_drop_action()); -+ - /* TTL discard */ - ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 30, -- "ip4 && ip.ttl == {0, 1}", debug_drop_action()); -+ "ip.ttl == {0, 1}", debug_drop_action()); - - /* Pass other traffic not already handled to the next table for - * routing. */ -@@ -13224,7 +13254,7 @@ build_ipv6_input_flows_for_lrouter_port( - "outport = %s; flags.loopback = 1; output; };", - ds_cstr(&ip_ds), op->json_key); - ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT, -- 100, ds_cstr(match), ds_cstr(actions), NULL, -+ 31, ds_cstr(match), ds_cstr(actions), NULL, - copp_meter_get(COPP_ICMP6_ERR, op->od->nbr->copp, - meter_groups), - &op->nbrp->header_); -@@ -13352,7 +13382,7 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op, - "outport = %s; flags.loopback = 1; output; };", - ds_cstr(&ip_ds), op->json_key); - ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT, -- 100, ds_cstr(match), ds_cstr(actions), NULL, -+ 31, ds_cstr(match), ds_cstr(actions), NULL, - copp_meter_get(COPP_ICMP4_ERR, op->od->nbr->copp, - meter_groups), - &op->nbrp->header_); -@@ -13597,13 +13627,13 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, - return; - } - -- bool stateless = lrouter_nat_is_stateless(nat); -+ bool stateless = lrouter_dnat_and_snat_is_stateless(nat); - if (od->is_gw_router) { - ds_clear(match); - ds_clear(actions); - ds_put_format(match, "ip && ip%s.dst == %s", - is_v6 ? "6" : "4", nat->external_ip); -- if (!strcmp(nat->type, "dnat_and_snat") && stateless) { -+ if (stateless) { - ds_put_format(actions, "next;"); - } else { - ds_put_cstr(actions, "ct_snat;"); -@@ -13628,7 +13658,7 @@ build_lrouter_in_unsnat_flow(struct hmap *lflows, struct ovn_datapath *od, - l3dgw_port->cr_port->json_key); - } - -- if (!strcmp(nat->type, "dnat_and_snat") && stateless) { -+ if (stateless) { - ds_put_format(actions, "next;"); - } else { - ds_put_cstr(actions, "ct_snat_in_czone;"); -@@ -13670,7 +13700,7 @@ build_lrouter_in_dnat_flow(struct hmap *lflows, struct ovn_datapath *od, - * IP address that needs to be DNATted from a external IP address - * to a logical IP address. */ - if (!strcmp(nat->type, "dnat") || !strcmp(nat->type, "dnat_and_snat")) { -- bool stateless = lrouter_nat_is_stateless(nat); -+ bool stateless = lrouter_dnat_and_snat_is_stateless(nat); - - if (od->is_gw_router) { - /* Packet when it goes from the initiator to destination. -@@ -13692,7 +13722,7 @@ build_lrouter_in_dnat_flow(struct hmap *lflows, struct ovn_datapath *od, - ds_put_format(actions, "flags.force_snat_for_dnat = 1; "); - } - -- if (!strcmp(nat->type, "dnat_and_snat") && stateless) { -+ if (stateless) { - ds_put_format(actions, "flags.loopback = 1; " - "ip%s.dst=%s; next;", - is_v6 ? "6" : "4", nat->logical_ip); -@@ -13782,8 +13812,7 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od, - ETH_ADDR_ARGS(mac)); - } - -- if (!strcmp(nat->type, "dnat_and_snat") && -- lrouter_nat_is_stateless(nat)) { -+ if (lrouter_dnat_and_snat_is_stateless(nat)) { - ds_put_format(actions, "next;"); - } else { - ds_put_format(actions, -@@ -13839,7 +13868,7 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, - return; - } - -- bool stateless = lrouter_nat_is_stateless(nat); -+ bool stateless = lrouter_dnat_and_snat_is_stateless(nat); - if (od->is_gw_router) { - ds_clear(match); - ds_put_format(match, "ip && ip%s.src == %s", -@@ -13905,7 +13934,7 @@ build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od, - ETH_ADDR_ARGS(mac)); - } - -- if (!strcmp(nat->type, "dnat_and_snat") && stateless) { -+ if (stateless) { - ds_put_format(actions, "ip%s.src=%s; next;", - is_v6 ? "6" : "4", nat->external_ip); - } else { -@@ -14217,10 +14246,10 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, - ovn_lflow_add(lflows, od, S_ROUTER_OUT_EGR_LOOP, 0, "1", "next;"); - ovn_lflow_add(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 0, "1", "next;"); - -- /* Ingress DNAT and DEFRAG Table (Priority 50/70). -- * -- * The defrag stage needs to have flows for ICMP in order to get -- * the correct ct_state that can be used by DNAT stage. -+ const char *ct_flag_reg = features->ct_no_masked_label -+ ? "ct_mark" -+ : "ct_label"; -+ /* Ingress DNAT (Priority 50/70). - * - * Allow traffic that is related to an existing conntrack entry. - * At the same time apply NAT for this traffic. -@@ -14231,16 +14260,10 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, - * that's generated from a non-listening UDP port. */ - if (od->has_lb_vip && features->ct_lb_related) { - ds_clear(match); -- const char *ct_flag_reg = features->ct_no_masked_label -- ? "ct_mark" -- : "ct_label"; - - ds_put_cstr(match, "ct.rel && !ct.est && !ct.new"); - size_t match_len = match->length; - -- ovn_lflow_add(lflows, od, S_ROUTER_IN_DEFRAG, 50, "icmp || icmp6", -- "ct_dnat;"); -- - ds_put_format(match, " && %s.skip_snat == 1", ct_flag_reg); - ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 70, ds_cstr(match), - "flags.skip_snat_for_lb = 1; ct_commit_nat;"); -@@ -14251,10 +14274,34 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, - "flags.force_snat_for_lb = 1; ct_commit_nat;"); - - ds_truncate(match, match_len); -- ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 50, -- "ct.rel && !ct.est && !ct.new", "ct_commit_nat;"); -+ ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 50, ds_cstr(match), -+ "ct_commit_nat;"); -+ } - -+ /* Ingress DNAT (Priority 50/70). -+ * -+ * Pass the traffic that is already established to the next table with -+ * proper flags set. -+ */ -+ if (od->has_lb_vip) { - ds_clear(match); -+ -+ ds_put_format(match, "ct.est && !ct.rel && !ct.new && %s.natted", -+ ct_flag_reg); -+ size_t match_len = match->length; -+ -+ ds_put_format(match, " && %s.skip_snat == 1", ct_flag_reg); -+ ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 70, ds_cstr(match), -+ "flags.skip_snat_for_lb = 1; next;"); -+ -+ ds_truncate(match, match_len); -+ ds_put_format(match, " && %s.force_snat == 1", ct_flag_reg); -+ ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 70, ds_cstr(match), -+ "flags.force_snat_for_lb = 1; next;"); -+ -+ ds_truncate(match, match_len); -+ ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 50, ds_cstr(match), -+ "next;"); - } - - /* If the router has load balancer or DNAT rules, re-circulate every packet -@@ -14267,6 +14314,9 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, - * flag set. Some NICs are unable to offload these flows. - */ - if (od->is_gw_router && (od->nbr->n_nat || od->has_lb_vip)) { -+ /* Do not send ND or ICMP packets to connection tracking. */ -+ ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 100, -+ "nd || nd_rs || nd_ra", "next;"); - ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 50, - "ip", "flags.loopback = 1; ct_dnat;"); - ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 50, -diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml -index 2eab2c4ae..5b3559d45 100644 ---- a/northd/ovn-northd.8.xml -+++ b/northd/ovn-northd.8.xml -@@ -748,6 +748,12 @@ - drop behavior. -

- -+

-+ A priority-65532 flow is added to allow IPv6 Neighbor solicitation, -+ Neighbor discover, Router solicitation, Router advertisement and MLD -+ packets regardless of other ACLs defined. -+

-+ -

- If the logical datapath has a stateful ACL or a load balancer with VIP - configured, the following flows will also be added: -@@ -824,12 +830,6 @@ - in the request direction are skipped here to let a newly created - ACL re-allow this connection. - -- --

  • -- A priority-65532 flow that allows IPv6 Neighbor solicitation, -- Neighbor discover, Router solicitation, Router advertisement and MLD -- packets. --
  • - - -

    -@@ -1090,24 +1090,28 @@ -

    -@@ -4721,6 +4687,11 @@ nd_ns { -

    Egress Table 1: UNDNAT on Gateway Routers

    - - - --

    Egress Table 4: Egress Loopback

    -+

    Egress Table 4: Post SNAT

    -+ -+

    -+ Packets reaching this table are processed according to the flows below: -+

    -+

    -+ -+

    Egress Table 5: Egress Loopback

    - -

    - For distributed logical routers where one of the logical router -@@ -5070,7 +5053,7 @@ clone { - - - --

    Egress Table 5: Delivery

    -+

    Egress Table 6: Delivery

    - -

    - Packets that reach this table are ready for delivery. It contains: -diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c -index 5f895b053..7d24648ff 100644 ---- a/northd/ovn-northd.c -+++ b/northd/ovn-northd.c -@@ -33,6 +33,7 @@ - #include "lib/ovn-l7.h" - #include "lib/ovn-nb-idl.h" - #include "lib/ovn-sb-idl.h" -+#include "lib/ovs-rcu.h" - #include "openvswitch/poll-loop.h" - #include "simap.h" - #include "stopwatch.h" -@@ -1048,6 +1049,8 @@ main(int argc, char *argv[]) - ovsdb_idl_loop_destroy(&ovnnb_idl_loop); - ovsdb_idl_loop_destroy(&ovnsb_idl_loop); - service_stop(); -+ run_update_worker_pool(0); -+ ovsrcu_exit(); - - exit(res); - } -diff --git a/ovn-architecture.7.xml b/ovn-architecture.7.xml -index cb1064f71..a2a87ec28 100644 ---- a/ovn-architecture.7.xml -+++ b/ovn-architecture.7.xml -@@ -1233,8 +1233,8 @@ - output port field, and since they do not carry a logical output port - field in the tunnel key, when a packet is received from ramp switch - VXLAN tunnel by an OVN hypervisor, the packet is resubmitted to table 8 -- to determine the output port(s); when the packet reaches table 37, -- these packets are resubmitted to table 38 for local delivery by -+ to determine the output port(s); when the packet reaches table 39, -+ these packets are resubmitted to table 40 for local delivery by - checking a MLF_RCV_FROM_RAMP flag, which is set when the packet - arrives from a ramp tunnel. -

    -@@ -1318,7 +1318,7 @@ - output port is known. These pieces of information are obtained - from the tunnel encapsulation metadata (see Tunnel - Encapsulations for encoding details). Then the actions resubmit -- to table 33 to enter the logical egress pipeline. -+ to table 38 to enter the logical egress pipeline. -

    - - -@@ -1439,38 +1439,42 @@ - -
  • -

    -- OpenFlow tables 37 through 39 implement the output action -- in the logical ingress pipeline. Specifically, table 37 handles -- packets to remote hypervisors, table 38 handles packets to the local -- hypervisor, and table 39 checks whether packets whose logical ingress -- and egress port are the same should be discarded. -+ OpenFlow tables 37 through 41 implement the output action -+ in the logical ingress pipeline. Specifically, table 37 serves as an -+ entry point to egress pipeline. Table 37 detects IP packets that are -+ too big for a corresponding interface. Table 38 produces ICMPv4 -+ Fragmentation Needed (or ICMPv6 Too Big) errors and deliver them back -+ to the offending port. table 39 handles packets to remote hypervisors, -+ table 40 handles packets to the local hypervisor, and table 41 checks -+ whether packets whose logical ingress and egress port are the same -+ should be discarded. -

    - -

    - Logical patch ports are a special case. Logical patch ports do not - have a physical location and effectively reside on every hypervisor. -- Thus, flow table 38, for output to ports on the local hypervisor, -+ Thus, flow table 40, for output to ports on the local hypervisor, - naturally implements output to unicast logical patch ports too. - However, applying the same logic to a logical patch port that is part - of a logical multicast group yields packet duplication, because each - hypervisor that contains a logical port in the multicast group will - also output the packet to the logical patch port. Thus, multicast -- groups implement output to logical patch ports in table 37. -+ groups implement output to logical patch ports in table 39. -

    - -

    -- Each flow in table 37 matches on a logical output port for unicast or -+ Each flow in table 39 matches on a logical output port for unicast or - multicast logical ports that include a logical port on a remote - hypervisor. Each flow's actions implement sending a packet to the port - it matches. For unicast logical output ports on remote hypervisors, - the actions set the tunnel key to the correct value, then send the - packet on the tunnel port to the correct hypervisor. (When the remote - hypervisor receives the packet, table 0 there will recognize it as a -- tunneled packet and pass it along to table 38.) For multicast logical -+ tunneled packet and pass it along to table 40.) For multicast logical - output ports, the actions send one copy of the packet to each remote - hypervisor, in the same way as for unicast destinations. If a - multicast group includes a logical port or ports on the local -- hypervisor, then its actions also resubmit to table 38. Table 37 also -+ hypervisor, then its actions also resubmit to table 40. Table 39 also - includes: -

    - -@@ -1478,7 +1482,7 @@ -
  • - A higher-priority rule to match packets received from ramp switch - tunnels, based on flag MLF_RCV_FROM_RAMP, and resubmit these packets -- to table 38 for local delivery. Packets received from ramp switch -+ to table 40 for local delivery. Packets received from ramp switch - tunnels reach here because of a lack of logical output port field in - the tunnel key and thus these packets needed to be submitted to table - 8 to determine the output port. -@@ -1486,7 +1490,7 @@ -
  • - A higher-priority rule to match packets received from ports of type - localport, based on the logical input port, and resubmit -- these packets to table 38 for local delivery. Ports of type -+ these packets to table 40 for local delivery. Ports of type - localport exist on every hypervisor and by definition - their traffic should never go out through a tunnel. -
  • -@@ -1501,41 +1505,41 @@ - packets, the packets only need to be delivered to local ports. - -
  • -- A fallback flow that resubmits to table 38 if there is no other -+ A fallback flow that resubmits to table 40 if there is no other - match. -
  • - - -

    -- Flows in table 38 resemble those in table 37 but for logical ports that -+ Flows in table 40 resemble those in table 39 but for logical ports that - reside locally rather than remotely. For unicast logical output ports -- on the local hypervisor, the actions just resubmit to table 39. For -+ on the local hypervisor, the actions just resubmit to table 41. For - multicast output ports that include one or more logical ports on the - local hypervisor, for each such logical port P, the actions - change the logical output port to P, then resubmit to table -- 39. -+ 41. -

    - -

    - A special case is that when a localnet port exists on the datapath, - remote port is connected by switching to the localnet port. In this -- case, instead of adding a flow in table 37 to reach the remote port, a -- flow is added in table 38 to switch the logical outport to the localnet -- port, and resubmit to table 38 as if it were unicasted to a logical -+ case, instead of adding a flow in table 39 to reach the remote port, a -+ flow is added in table 40 to switch the logical outport to the localnet -+ port, and resubmit to table 40 as if it were unicasted to a logical - port on the local hypervisor. -

    - -

    -- Table 39 matches and drops packets for which the logical input and -+ Table 41 matches and drops packets for which the logical input and - output ports are the same and the MLF_ALLOW_LOOPBACK flag is not - set. It also drops MLF_LOCAL_ONLY packets directed to a localnet port. -- It resubmits other packets to table 40. -+ It resubmits other packets to table 42. -

    - - -
  • -

    -- OpenFlow tables 40 through 63 execute the logical egress pipeline from -+ OpenFlow tables 42 through 62 execute the logical egress pipeline from - the Logical_Flow table in the OVN Southbound database. - The egress pipeline can perform a final stage of validation before - packet delivery. Eventually, it may execute an output -@@ -1554,7 +1558,7 @@ -

  • -

    - Table 64 bypasses OpenFlow loopback when MLF_ALLOW_LOOPBACK is set. -- Logical loopback was handled in table 39, but OpenFlow by default also -+ Logical loopback was handled in table 41, but OpenFlow by default also - prevents loopback to the OpenFlow ingress port. Thus, when - MLF_ALLOW_LOOPBACK is set, OpenFlow table 64 saves the OpenFlow ingress - port, sets it to zero, resubmits to table 65 for logical-to-physical -@@ -1592,8 +1596,8 @@ - traverse tables 0 to 65 as described in the previous section - Architectural Physical Life Cycle of a Packet, using the - logical datapath representing the logical switch that the sender is -- attached to. At table 37, the packet will use the fallback flow that -- resubmits locally to table 38 on the same hypervisor. In this case, -+ attached to. At table 39, the packet will use the fallback flow that -+ resubmits locally to table 40 on the same hypervisor. In this case, - all of the processing from table 0 to table 65 occurs on the hypervisor - where the sender resides. -

    -@@ -1624,7 +1628,7 @@ -

    - The packet traverses tables 8 to 65 a third and final time. If the - destination VM or container resides on a remote hypervisor, then table -- 37 will send the packet on a tunnel port from the sender's hypervisor -+ 39 will send the packet on a tunnel port from the sender's hypervisor - to the remote hypervisor. Finally table 65 will output the packet - directly to the destination VM or container. -

    -@@ -1651,9 +1655,9 @@ - When a hypervisor processes a packet on a logical datapath - representing a logical switch, and the logical egress port is a - l3gateway port representing connectivity to a gateway -- router, the packet will match a flow in table 37 that sends the -+ router, the packet will match a flow in table 39 that sends the - packet on a tunnel port to the chassis where the gateway router -- resides. This processing in table 37 is done in the same manner as -+ resides. This processing in table 39 is done in the same manner as - for VIFs. -

    - -@@ -1746,21 +1750,21 @@ - chassis, one additional mechanism is required. When a packet - leaves the ingress pipeline and the logical egress port is the - distributed gateway port, one of two different sets of actions is -- required at table 37: -+ required at table 39: -

    - - -@@ -1772,11 +1776,11 @@ - egress port to the type chassisredirect logical port is - simply a way to indicate that although the packet is destined for - the distributed gateway port, it needs to be redirected to a -- different chassis. At table 37, packets with this logical egress -- port are sent to a specific chassis, in the same way that table 37 -+ different chassis. At table 39, packets with this logical egress -+ port are sent to a specific chassis, in the same way that table 39 - directs packets whose logical egress port is a VIF or a type - l3gateway port to different chassis. Once the packet -- arrives at that chassis, table 38 resets the logical egress port to -+ arrives at that chassis, table 40 resets the logical egress port to - the value representing the distributed gateway port. For each - distributed gateway port, there is one type - chassisredirect port, in addition to the distributed -diff --git a/ovn-nb.xml b/ovn-nb.xml -index 8d56d0c6e..35acda107 100644 ---- a/ovn-nb.xml -+++ b/ovn-nb.xml -@@ -2036,6 +2036,14 @@ or - the affinity timeslot. Max supported affinity_timeout is 65535 - seconds. - -+ -+ -+ The value indicates whether ovn-controller should flush CT entries -+ that are related to this LB. The flush happens if the LB is removed, -+ any of the backends is updated/removed or the LB is not considered -+ local anymore by the ovn-controller. This option is set to -+ false by default. -+ - - - -diff --git a/ovn-sb.xml b/ovn-sb.xml -index a77f8f4ef..8ca206109 100644 ---- a/ovn-sb.xml -+++ b/ovn-sb.xml -@@ -472,9 +472,8 @@ - - - The encapsulation to use to transmit packets to this chassis. -- Hypervisors must use either geneve or -- stt. Gateways may use vxlan, -- geneve, or stt. -+ Hypervisors and gateways must use one of: geneve, -+ vxlan, or stt. - - - -diff --git a/rhel/usr_lib_systemd_system_ovn-db@.service b/rhel/usr_lib_systemd_system_ovn-db@.service -index 98556a673..c835e4967 100644 ---- a/rhel/usr_lib_systemd_system_ovn-db@.service -+++ b/rhel/usr_lib_systemd_system_ovn-db@.service -@@ -33,7 +33,7 @@ EnvironmentFile=-/etc/sysconfig/ovn-%i - ExecStartPre=-/usr/bin/chown -R ${OVN_USER_ID} ${OVN_DBDIR} - ExecStart=/usr/share/ovn/scripts/ovn-ctl \ - --ovn-user=${OVN_USER_ID} start_%i_ovsdb $OPTIONS $ovn_%i_opts --ExecStop=/usr/share/ovn/scripts/ovn-ctl stop_%i_ovsdb -+ExecStop=/usr/share/ovn/scripts/ovn-ctl stop_%i_ovsdb $OPTIONS $ovn_%i_opts - - [Install] - WantedBy=multi-user.target -diff --git a/rhel/usr_lib_systemd_system_ovn-northd.service b/rhel/usr_lib_systemd_system_ovn-northd.service -index d281f861c..6c4c6621c 100644 ---- a/rhel/usr_lib_systemd_system_ovn-northd.service -+++ b/rhel/usr_lib_systemd_system_ovn-northd.service -@@ -26,7 +26,7 @@ EnvironmentFile=-/etc/sysconfig/ovn-northd - ExecStartPre=-/usr/bin/chown -R ${OVN_USER_ID} ${OVN_DBDIR} - ExecStart=/usr/share/ovn/scripts/ovn-ctl \ - --ovn-user=${OVN_USER_ID} start_northd $OVN_NORTHD_OPTS --ExecStop=/usr/share/ovn/scripts/ovn-ctl stop_northd -+ExecStop=/usr/share/ovn/scripts/ovn-ctl stop_northd $OVN_NORTHD_OPTS - - [Install] - WantedBy=multi-user.target -diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at -index bbe142ae3..dd7eda516 100644 ---- a/tests/ovn-controller.at -+++ b/tests/ovn-controller.at -@@ -493,7 +493,8 @@ check ovn-nbctl --wait=hv sync - - # And check that it gets propagated to br-int external_ids. - as hv1 --OVS_WAIT_UNTIL([ovs-vsctl get Bridge br-int external_ids:ovn-nb-cfg], [0], [1]) -+OVS_WAIT_FOR_OUTPUT([ovs-vsctl get Bridge br-int external_ids:ovn-nb-cfg], [0], ["1" -+]) - - nb_cfg_ts=$(fetch_column Chassis_Private nb_cfg_timestamp name=hv1) - as hv1 -@@ -672,22 +673,26 @@ check ovs-vsctl del-ssl - start_daemon ovn-controller -p $key -c $cert -C $cacert - - # SSL should not connect because of key and cert mismatch --OVS_WAIT_UNTIL([ovn-appctl -t ovn-controller connection-status], [0], [not connected]) -+OVS_WAIT_FOR_OUTPUT([ovn-appctl -t ovn-controller connection-status], [0], [not connected -+]) - - # Modify the files with the correct key and cert, and reconnect should succeed - cp $PKIDIR/$key $key - cp $PKIDIR/$cert $cert - --OVS_WAIT_UNTIL([ovn-appctl -t ovn-controller connection-status], [0], [connected]) -+OVS_WAIT_FOR_OUTPUT([ovn-appctl -t ovn-controller connection-status], [0], [connected -+]) - - # Remove the files and expect the connection to drop - rm $key $cert --OVS_WAIT_UNTIL([ovn-appctl -t ovn-controller connection-status], [0], [not connected]) -+OVS_WAIT_FOR_OUTPUT([ovn-appctl -t ovn-controller connection-status], [0], [not connected -+]) - - # Restore the files again and expect the connection to recover - cp $PKIDIR/$key $key - cp $PKIDIR/$cert $cert --OVS_WAIT_UNTIL([ovn-appctl -t ovn-controller connection-status], [0], [connected]) -+OVS_WAIT_FOR_OUTPUT([ovn-appctl -t ovn-controller connection-status], [0], [connected -+]) - - cat hv1/ovn-controller.log - -@@ -868,7 +873,7 @@ meta=$(ovn-sbctl get datapath ls1 tunnel_key) - port=$(ovn-sbctl get port_binding ls1-rp tunnel_key) - check ovn-nbctl lrp-add lr0 rp-ls1 00:00:01:01:02:03 192.168.1.254/24 - --OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int | grep table=38 | grep -q "reg15=0x${port},metadata=0x${meta}"]) -+OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int | grep table=40 | grep -q "reg15=0x${port},metadata=0x${meta}"]) - - OVN_CLEANUP([hv1]) - AT_CLEANUP -@@ -912,14 +917,14 @@ for i in $(seq 10); do - check ovn-nbctl add address_set as1 addresses 10.0.0.$i - check ovn-nbctl --wait=hv sync - if test "$i" = 3; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1 actions=drop - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.2 actions=drop - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.3 actions=drop - ]) - fi -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$i -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$i - ]) - done - -@@ -934,15 +939,15 @@ for i in $(seq 10); do - check ovn-nbctl remove address_set as1 addresses 10.0.0.$i - check ovn-nbctl --wait=hv sync - if test "$i" = 9; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}'], [0], [dnl - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10 actions=drop - ]) - fi - if test "$i" = 10; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) - else -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((10 - $i)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((10 - $i)) - ]) - fi - done -@@ -960,7 +965,7 @@ for i in $(seq 10); do - check ovn-nbctl add address_set as1 addresses 10.0.0.$i,10.0.1.$i - check ovn-nbctl --wait=hv sync - if test "$i" = 3; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1 actions=drop - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.2 actions=drop -@@ -970,7 +975,7 @@ priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.1.2 actions=dr - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.1.3 actions=drop - ]) - fi -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i * 2)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i * 2)) - ]) - done - -@@ -987,11 +992,11 @@ reprocess_count_old=$(read_counter consider_logical_flow) - check ovn-nbctl add address_set as1 addresses 10.0.0.21,10.0.0.22 -- \ - remove address_set as1 addresses 10.0.0.10 - check ovn-nbctl --wait=hv sync --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.21], [0], [1 -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.21], [0], [1 - ]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.22], [0], [1 -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.22], [0], [1 - ]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.10], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.10], [1], [ignore]) - - reprocess_count_new=$(read_counter consider_logical_flow) - AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [0 -@@ -1003,9 +1008,9 @@ reprocess_count_old=$(read_counter consider_logical_flow) - check ovn-nbctl remove address_set as1 addresses 10.0.0.21,10.0.0.22 -- \ - add address_set as1 addresses 10.0.0.10 - check ovn-nbctl --wait=hv sync --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.21], [1], [ignore]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.22], [1], [ignore]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.10], [0], [1 -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.21], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.22], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.10], [0], [1 - ]) - - reprocess_count_new=$(read_counter consider_logical_flow) -@@ -1018,9 +1023,9 @@ reprocess_count_old=$(read_counter consider_logical_flow) - check ovn-nbctl add address_set as1 addresses 10.0.0.21 -- \ - remove address_set as1 addresses 10.0.0.10 - check ovn-nbctl --wait=hv sync --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.21], [0], [1 -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.21], [0], [1 - ]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.10], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.10], [1], [ignore]) - - reprocess_count_new=$(read_counter consider_logical_flow) - AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [0 -@@ -1032,12 +1037,12 @@ reprocess_count_old=$(read_counter consider_logical_flow) - check ovn-nbctl add address_set as1 addresses 10.0.0.22,10.0.0.23 -- \ - remove address_set as1 addresses 10.0.0.9,10.0.0.8 - check ovn-nbctl --wait=hv sync --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.22], [0], [1 -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.22], [0], [1 - ]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.23], [0], [1 -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.23], [0], [1 - ]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.8], [1], [ignore]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.9], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.8], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.9], [1], [ignore]) - - reprocess_count_new=$(read_counter consider_logical_flow) - AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [0 -@@ -1085,7 +1090,7 @@ for i in $(seq 10); do - check ovn-nbctl add address_set as1 addresses 10.0.0.$i - check ovn-nbctl --wait=hv sync - if test "$i" = 1; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl - priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1,tp_dst=111 actions=drop - priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1,tp_dst=222 actions=drop -@@ -1093,12 +1098,12 @@ priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1,tp_dst=33 - ]) - else - # (1 conj_id flow + 3 tp_dst flows) = 4 extra flows -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i + 4)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i + 4)) - ]) - fi - - if test "$i" = 3; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | \ - sed -r 's/conjunction.*,/conjunction,/' | \ - sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl -@@ -1124,17 +1129,17 @@ for i in $(seq 10); do - check ovn-nbctl remove address_set as1 addresses 10.0.0.$i - check ovn-nbctl --wait=hv sync - if test "$i" = 10; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) - elif test "$i" = 9; then - # no conjunction left -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl - priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,tp_dst=111 actions=drop - priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,tp_dst=222 actions=drop - priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,tp_dst=333 actions=drop - ]) - else -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((14 - $i)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((14 - $i)) - ]) - fi - done -@@ -1150,7 +1155,7 @@ for i in $(seq 10); do - check ovn-nbctl add address_set as1 addresses 10.0.0.$i,10.0.1.$i - check ovn-nbctl --wait=hv sync - if test "$i" = 3; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | \ - sed -r 's/conjunction.*,/conjunction,/' | \ - sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl -@@ -1166,7 +1171,7 @@ priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,tp_dst=222 actions=conjun - priority=1100,tcp,reg15=0x$port_key,metadata=0x$dp_key,tp_dst=333 actions=conjunction,2/2) - ]) - fi -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i * 2 + 4)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i * 2 + 4)) - ]) - done - -@@ -1182,11 +1187,11 @@ reprocess_count_old=$(read_counter consider_logical_flow) - check ovn-nbctl add address_set as1 addresses 10.0.0.21,10.0.0.22 -- \ - remove address_set as1 addresses 10.0.0.10 - check ovn-nbctl --wait=hv sync --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.21], [0], [1 -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.21], [0], [1 - ]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.22], [0], [1 -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.22], [0], [1 - ]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.10], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.10], [1], [ignore]) - - reprocess_count_new=$(read_counter consider_logical_flow) - AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [0 -@@ -1198,9 +1203,9 @@ reprocess_count_old=$(read_counter consider_logical_flow) - check ovn-nbctl remove address_set as1 addresses 10.0.0.21,10.0.0.22 -- \ - add address_set as1 addresses 10.0.0.10 - check ovn-nbctl --wait=hv sync --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.21], [1], [ignore]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.22], [1], [ignore]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.10], [0], [1 -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.21], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.22], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.10], [0], [1 - ]) - - reprocess_count_new=$(read_counter consider_logical_flow) -@@ -1213,9 +1218,9 @@ reprocess_count_old=$(read_counter consider_logical_flow) - check ovn-nbctl add address_set as1 addresses 10.0.0.21 -- \ - remove address_set as1 addresses 10.0.0.10 - check ovn-nbctl --wait=hv sync --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.21], [0], [1 -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.21], [0], [1 - ]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.10], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.10], [1], [ignore]) - - reprocess_count_new=$(read_counter consider_logical_flow) - AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [0 -@@ -1227,12 +1232,12 @@ reprocess_count_old=$(read_counter consider_logical_flow) - check ovn-nbctl add address_set as1 addresses 10.0.0.22,10.0.0.23 -- \ - remove address_set as1 addresses 10.0.0.9,10.0.0.8 - check ovn-nbctl --wait=hv sync --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.22], [0], [1 -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.22], [0], [1 - ]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep -c 10\.0\.0\.23], [0], [1 -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c 10\.0\.0\.23], [0], [1 - ]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.8], [1], [ignore]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10\.0\.0\.9], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.8], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10\.0\.0\.9], [1], [ignore]) - - reprocess_count_new=$(read_counter consider_logical_flow) - AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [0 -@@ -1282,18 +1287,18 @@ for i in $(seq 10); do - add address_set as2 addresses 10.0.0.$j - check ovn-nbctl --wait=hv sync - if test "$i" = 1; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1,nw_dst=10.0.0.6 actions=drop - ]) - else - # (1 conj_id + nw_src * i + nw_dst * i) = 1 + i*2 flows -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i*2 + 1)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i*2 + 1)) - ]) - fi - - if test "$i" = 3; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | \ - sed -r 's/conjunction.*,/conjunction,/' | \ - sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl -@@ -1321,15 +1326,15 @@ for i in $(seq 10); do - remove address_set as2 addresses 10.0.0.$j - check ovn-nbctl --wait=hv sync - if test "$i" = 10; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) - elif test "$i" = 9; then - # no conjunction left -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,nw_dst=10.0.0.15 actions=drop - ]) - else -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((21 - $i*2)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((21 - $i*2)) - ]) - fi - done -@@ -1350,14 +1355,14 @@ for i in $(seq 2 10); do - check ovn-nbctl add address_set as1 addresses 10.0.0.$i - check ovn-nbctl --wait=hv sync - if test "$i" = 3; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1,nw_dst=10.0.0.6 actions=drop - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.2,nw_dst=10.0.0.6 actions=drop - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.3,nw_dst=10.0.0.6 actions=drop - ]) - fi -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$i -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$i - ]) - done - -@@ -1376,16 +1381,16 @@ for i in $(seq 10); do - check ovn-nbctl remove address_set as1 addresses 10.0.0.$i - check ovn-nbctl --wait=hv sync - if test "$i" = 9; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}'], [0], [dnl - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,nw_dst=10.0.0.6 actions=drop - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,nw_dst=10.0.0.7 actions=drop - ]) - elif test "$i" = 10; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) - else - # 2 dst + (10 - i) src + 1 conj_id -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((10 - $i + 3)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((10 - $i + 3)) - ]) - fi - done -@@ -1439,18 +1444,18 @@ for i in $(seq 10); do - add address_set as2 addresses 10.0.0.$j - check ovn-nbctl --wait=hv sync - if test "$i" = 1; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_dst=10.0.0.6 actions=drop - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1 actions=drop - ]) - else -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i*2)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i*2)) - ]) - fi - - if test "$i" = 3; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | \ - sed -r 's/conjunction.*,/conjunction,/' | \ - sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl -@@ -1477,9 +1482,9 @@ for i in $(seq 10); do - remove address_set as2 addresses 10.0.0.$j - check ovn-nbctl --wait=hv sync - if test "$i" = 10; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) - else -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((20 - $i*2)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((20 - $i*2)) - ]) - fi - done -@@ -1535,21 +1540,21 @@ for i in $(seq 10); do - add address_set as2 addresses 10.0.0.$j - check ovn-nbctl --wait=hv sync - if test "$i" = 1; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1 actions=drop - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.6 actions=drop - ]) - elif test "$i" -lt 6; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i*2)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i*2)) - ]) - else -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((5 + $i)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((5 + $i)) - ]) - fi - - if test "$i" = 3; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | \ - sed -r 's/conjunction.*,/conjunction,/' | \ - sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl -@@ -1576,12 +1581,12 @@ for i in $(seq 10); do - remove address_set as2 addresses 10.0.0.$j - check ovn-nbctl --wait=hv sync - if test "$i" = 10; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) - elif test "$i" -lt 6; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((15 - $i)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((15 - $i)) - ]) - else -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((10 - ($i - 5)*2)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((10 - ($i - 5)*2)) - ]) - fi - done -@@ -1633,18 +1638,18 @@ for i in $(seq 10); do - check ovn-nbctl add address_set as1 addresses 10.0.0.$i - check ovn-nbctl --wait=hv sync - if test "$i" = 1; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.1,nw_dst=10.0.0.1 actions=drop - ]) - else - # (1 conj_id + nw_src * i + nw_dst * i) = 1 + i*2 flows -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i*2 + 1)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i*2 + 1)) - ]) - fi - - if test "$i" = 3; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | \ - sed -r 's/conjunction.*,/conjunction,/' | \ - sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl -@@ -1670,15 +1675,15 @@ for i in $(seq 10); do - check ovn-nbctl remove address_set as1 addresses 10.0.0.$i - check ovn-nbctl --wait=hv sync - if test "$i" = 10; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) - elif test "$i" = 9; then - # no conjunction left -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.0.10,nw_dst=10.0.0.10 actions=drop - ]) - else -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((21 - $i*2)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((21 - $i*2)) - ]) - fi - done -@@ -1694,7 +1699,7 @@ for i in $(seq 10); do - check ovn-nbctl add address_set as1 addresses 10.0.0.$i,10.0.1.$i - check ovn-nbctl --wait=hv sync - if test "$i" = 3; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | \ - sed -r 's/conjunction.*,/conjunction,/' | \ - sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl -@@ -1713,7 +1718,7 @@ priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.1.2 actions=co - priority=1100,ip,reg15=0x$port_key,metadata=0x$dp_key,nw_src=10.0.1.3 actions=conjunction,2/2) - ]) - fi -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$(($i * 4 + 1)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$(($i * 4 + 1)) - ]) - done - -@@ -1734,7 +1739,7 @@ check ovn-nbctl --wait=hv sync - reprocess_count_old=$(read_counter consider_logical_flow) - check ovn-nbctl add address_set as1 addresses 10.0.0.4,10.0.0.5 - check ovn-nbctl --wait=hv sync --AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | \ - sed -r 's/conjunction.*,/conjunction,/' | \ - sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl -@@ -1758,7 +1763,7 @@ AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [1 - # Delete 2 IPs - reprocess_count_old=$(read_counter consider_logical_flow) - check ovn-nbctl --wait=hv remove address_set as1 addresses 10.0.0.4,10.0.0.5 --AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | \ - sed -r 's/conjunction.*,/conjunction,/' | \ - sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl -@@ -1816,7 +1821,7 @@ check ovn-nbctl acl-add ls1 to-lport 100 'outport == "ls1-lp1" && ip4.src == $as - check ovn-nbctl acl-add ls1 to-lport 100 'outport == "ls1-lp1" && ip4.src == $as2 && tcp && tcp.dst == {201, 202}' drop - - check ovn-nbctl --wait=hv sync --AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | \ - sed -r 's/conjunction.[[0-9]]*,/conjunction,/g' | \ - sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl -@@ -1841,7 +1846,7 @@ reprocess_count_old=$(read_counter consider_logical_flow) - check ovn-nbctl add address_set as1 addresses 10.0.0.14,10.0.0.33 -- \ - add address_set as2 addresses 10.0.0.24,10.0.0.33 - check ovn-nbctl --wait=hv sync --AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | \ - sed -r 's/conjunction.[[0-9]]*,/conjunction,/g' | \ - sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl -@@ -1872,7 +1877,7 @@ reprocess_count_old=$(read_counter consider_logical_flow) - check ovn-nbctl remove address_set as1 addresses 10.0.0.14,10.0.0.33 -- \ - remove address_set as2 addresses 10.0.0.24,10.0.0.33 - check ovn-nbctl --wait=hv sync --AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | \ - sed -r 's/conjunction.[[0-9]]*,/conjunction,/g' | \ - sed -r 's/conj_id=.*,/conj_id=,/' | sort], [0], [dnl -@@ -1937,14 +1942,14 @@ for i in $(seq 5); do - check ovn-nbctl add address_set as1 addresses "aa\:aa\:aa\:aa\:aa\:0$i" - check ovn-nbctl --wait=hv sync - if test "$i" = 3; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl - priority=1100,reg15=0x$port_key,metadata=0x$dp_key,dl_src=aa:aa:aa:aa:aa:01 actions=drop - priority=1100,reg15=0x$port_key,metadata=0x$dp_key,dl_src=aa:aa:aa:aa:aa:02 actions=drop - priority=1100,reg15=0x$port_key,metadata=0x$dp_key,dl_src=aa:aa:aa:aa:aa:03 actions=drop - ]) - fi -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$i -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$i - ]) - done - -@@ -1958,17 +1963,17 @@ reprocess_count_old=$(read_counter consider_logical_flow) - for i in $(seq 5); do - check ovn-nbctl remove address_set as1 addresses "aa\:aa\:aa\:aa\:aa\:0$i" - check ovn-nbctl --wait=hv sync -- ovs-ofctl dump-flows br-int table=44 | grep "priority=1100" -+ ovs-ofctl dump-flows br-int table=46 | grep "priority=1100" - if test "$i" = 4; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}'], [0], [dnl - priority=1100,reg15=0x$port_key,metadata=0x$dp_key,dl_src=aa:aa:aa:aa:aa:05 actions=drop - ]) - fi - if test "$i" = 5; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) - else -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((5 - $i)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((5 - $i)) - ]) - fi - done -@@ -2018,14 +2023,14 @@ for i in $(seq 5); do - check ovn-nbctl add address_set as1 addresses "ff\:\:0$i" - check ovn-nbctl --wait=hv sync - if test "$i" = 3; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}' | sort], [0], [dnl - priority=1100,ipv6,reg15=0x$port_key,metadata=0x$dp_key,ipv6_src=ff::1 actions=drop - priority=1100,ipv6,reg15=0x$port_key,metadata=0x$dp_key,ipv6_src=ff::2 actions=drop - priority=1100,ipv6,reg15=0x$port_key,metadata=0x$dp_key,ipv6_src=ff::3 actions=drop - ]) - fi -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$i -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$i - ]) - done - -@@ -2040,15 +2045,15 @@ for i in $(seq 5); do - check ovn-nbctl remove address_set as1 addresses "ff\:\:0$i" - check ovn-nbctl --wait=hv sync - if test "$i" = 4; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44,reg15=0x$port_key | \ -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46,reg15=0x$port_key | \ - grep -v reply | awk '{print $7, $8}'], [0], [dnl - priority=1100,ipv6,reg15=0x$port_key,metadata=0x$dp_key,ipv6_src=ff::5 actions=drop - ]) - fi - if test "$i" = 5; then -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep "priority=1100"], [1], [ignore]) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep "priority=1100"], [1], [ignore]) - else -- AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=44 | grep -c "priority=1100"], [0], [$((5 - $i)) -+ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [$((5 - $i)) - ]) - fi - done -@@ -2060,6 +2065,57 @@ AT_CHECK([echo $(($reprocess_count_new - $reprocess_count_old))], [0], [2 - OVN_CLEANUP([hv1]) - AT_CLEANUP - -+AT_SETUP([ovn-controller - address set del-and-add]) -+ -+ovn_start -+ -+net_add n1 -+sim_add hv1 -+as hv1 -+check ovs-vsctl add-br br-phys -+ovn_attach n1 br-phys 192.168.0.1 -+check ovs-vsctl -- add-port br-int hv1-vif1 -- \ -+ set interface hv1-vif1 external-ids:iface-id=ls1-lp1 -+ -+check ovn-nbctl ls-add ls1 -+ -+check ovn-nbctl lsp-add ls1 ls1-lp1 \ -+-- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01" -+ -+wait_for_ports_up -+ovn-appctl -t ovn-controller vlog/set file:dbg -+ -+ovn-nbctl create address_set name=as1 addresses=8.8.8.8 -+check ovn-nbctl acl-add ls1 to-lport 100 'outport == "ls1-lp1" && ip4.src == $as1' drop -+check ovn-nbctl --wait=hv sync -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100"], [0], [1 -+]) -+ -+# pause ovn-northd -+check as northd ovn-appctl -t ovn-northd pause -+check as northd-backup ovn-appctl -t ovn-northd pause -+ -+# Simulate a SB address set "del and add" notification to ovn-controller in the -+# same IDL iteration. The flows programmed by ovn-controller should reflect the -+# newly added address set. In reality it can happen when CMS deletes an -+# address-set and immediately creates a new address-set with the same name -+# (with same or different content). The notification of the changes can come to -+# ovn-controller in one shot and the order of the "del" and "add" in the IDL is -+# undefined. This test runs the scenario ten times to make sure different -+# orders are covered and handled properly. -+ -+flow_count=$(ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100") -+for i in $(seq 10); do -+ # Delete and recreate the SB address set with same name and an extra IP. -+ addrs_=$(fetch_column address_set addresses name=as1) -+ addrs=${addrs_// /,} -+ AT_CHECK([ovn-sbctl destroy address_set as1 -- create address_set name=as1 addresses=$addrs,1.1.1.$i], [0], [ignore]) -+ OVS_WAIT_UNTIL([test $(as hv1 ovs-ofctl dump-flows br-int table=46 | grep -c "priority=1100") = "$(($i + 1))"]) -+done -+ -+OVN_CLEANUP([hv1]) -+AT_CLEANUP -+ - AT_SETUP([ovn-controller - I-P handle lb_hairpin_use_ct_mark change]) - - ovn_start --backup-northd=none -@@ -2161,7 +2217,7 @@ AT_CHECK([ovs-ofctl dump-flows br-int | grep 10.1.2.3], [0], [ignore]) - sleep 5 - - # Check after the wait --OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 10.1.2.4], [0], [ignore]) -+OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 10.1.2.4]) - lflow_run_2=$(ovn-appctl -t ovn-controller coverage/read-counter lflow_run) - - # Verify that the flow compute completed during the wait (after the wait it -@@ -2172,7 +2228,7 @@ AT_CHECK_UNQUOTED([echo $lflow_run_1], [0], [$lflow_run_2 - # Restart OVS this time, and wait until flows are reinstalled - OVS_APP_EXIT_AND_WAIT([ovs-vswitchd]) - start_daemon ovs-vswitchd --enable-dummy=system -vvconn -vofproto_dpif -vunixctl --OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 10.1.2.4], [0], [ignore]) -+OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 10.1.2.4]) - - check ovn-nbctl --wait=hv lb-add lb3 2.2.2.2 10.1.2.5 \ - -- ls-lb-add ls1 lb3 -diff --git a/tests/ovn-macros.at b/tests/ovn-macros.at -index ee942e8a6..6f2d085ae 100644 ---- a/tests/ovn-macros.at -+++ b/tests/ovn-macros.at -@@ -817,6 +817,29 @@ ovn_trace_client() { - ovs-appctl -t $target trace "$@" | tee trace | sed '/^# /d' - } - -+# Receives a string with scapy python code that represents a packet. -+# Returns a hex-string that contains bytes that reflect the packet symbolic -+# description. -+# -+# Scapy docs: https://scapy.readthedocs.io/en/latest/usage.html -+# -+# Example of usage: -+# -+# packet=$(fmt_pkt " -+# Ether(dst='ff:ff:ff:ff:ff:ff', src='50:64:00:00:00:01') / -+# IPv6(src='abed::1', dst='ff02::1:ff00:2') / -+# ICMPv6ND_NS(tgt='abed::2') -+# ") -+# -+# ovs-appctl netdev-dummy/receive $vif $packet -+# -+fmt_pkt() { -+ echo "from scapy.all import *; \ -+ import binascii; \ -+ out = binascii.hexlify(raw($1)); \ -+ print(out.decode())" | $PYTHON3 -+} -+ - OVS_END_SHELL_HELPERS - - m4_define([OVN_POPULATE_ARP], [AT_CHECK(ovn_populate_arp__, [0], [ignore])]) -diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at -index 2fffe1850..478a32f5a 100644 ---- a/tests/ovn-nbctl.at -+++ b/tests/ovn-nbctl.at -@@ -1482,6 +1482,32 @@ UUID LB PROTO VIP - - dnl --------------------------------------------------------------------- - -+OVN_NBCTL_TEST([ovn_nbctl_template_lbs], [Template LBs], [ -+check ovn-nbctl --template lb-add lb0 ^vip ^backend -+check ovn-nbctl --template lb-add lb1 ^vip:^vport ^backend udp -+check ovn-nbctl --template lb-add lb2 ^vip:^vport ^backend udp ipv4 -+check ovn-nbctl --template lb-add lb3 ^vip:^vport ^backend udp ipv6 -+check ovn-nbctl --template lb-add lb4 ^vip:^vport ^backend:^bport udp ipv4 -+check ovn-nbctl --template lb-add lb5 ^vip:^vport ^backend:^bport udp ipv6 -+check ovn-nbctl --template lb-add lb6 ^vip:^vport 1.1.1.1:111 udp ipv4 -+check ovn-nbctl --template lb-add lb7 ^vip:^vport [[1::1]]:111 udp ipv6 -+ -+AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl -+UUID LB PROTO VIP IPs -+<0> lb0 tcp ^vip ^backend -+<1> lb1 udp ^vip:^vport ^backend -+<2> lb2 udp ^vip:^vport ^backend -+<3> lb3 udp ^vip:^vport ^backend -+<4> lb4 udp ^vip:^vport ^backend:^bport -+<5> lb5 udp ^vip:^vport ^backend:^bport -+<6> lb6 udp ^vip:^vport 1.1.1.1:111 -+<7> lb7 udp ^vip:^vport [[1::1]]:111 -+]) -+ -+]) -+ -+dnl --------------------------------------------------------------------- -+ - OVN_NBCTL_TEST([ovn_nbctl_basic_lr], [basic logical router commands], [ - AT_CHECK([ovn-nbctl lr-add lr0]) - AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl -@@ -2599,6 +2625,7 @@ OVN_NBCTL_TEST_STOP "/terminating with signal 15/d" - AT_CLEANUP - - AT_SETUP([ovn-nbctl - daemon ssl files change]) -+AT_SKIP_IF([test "$HAVE_OPENSSL" = no]) - dnl Create ovn-nb database. - AT_CHECK([ovsdb-tool create ovn-nb.db $abs_top_srcdir/ovn-nb.ovsschema]) - -diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at -index 3fa02d2b3..93854dfdc 100644 ---- a/tests/ovn-northd.at -+++ b/tests/ovn-northd.at -@@ -2486,6 +2486,7 @@ check ovn-nbctl --wait=sb \ - - AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e ls_in_acl -e ls_out_acl | sort], [0], [dnl - table=17(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) -+ table=17(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=17(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) - table=3 (ls_out_acl_hint ), priority=0 , match=(1), action=(next;) - table=3 (ls_out_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) -@@ -2530,9 +2531,12 @@ ovn-nbctl --wait=sb clear logical_switch ls load_balancer - - AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e ls_in_acl -e ls_out_acl | sort], [0], [dnl - table=17(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) -+ table=17(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=3 (ls_out_acl_hint ), priority=65535, match=(1), action=(next;) -+ table=4 (ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=4 (ls_out_acl ), priority=65535, match=(1), action=(next;) - table=7 (ls_in_acl_hint ), priority=65535, match=(1), action=(next;) -+ table=8 (ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=8 (ls_in_acl ), priority=65535, match=(1), action=(next;) - ]) - -@@ -2871,7 +2875,6 @@ AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort | sed 's/tabl - AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/g'], [0], [dnl - table=??(ls_in_hairpin ), priority=0 , match=(1), action=(next;) - table=??(ls_in_hairpin ), priority=1 , match=((reg0[[6]] == 1 || reg0[[12]] == 1)), action=(eth.dst <-> eth.src; outport = inport; flags.loopback = 1; output;) -- table=??(ls_in_hairpin ), priority=1000 , match=(reg0[[14]] == 1), action=(next(pipeline=ingress, table=??);) - ]) - - check ovn-nbctl -- ls-lb-del sw0 lb0 -@@ -2887,7 +2890,6 @@ AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort | sed 's/tabl - - AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/g'], [0], [dnl - table=??(ls_in_hairpin ), priority=0 , match=(1), action=(next;) -- table=??(ls_in_hairpin ), priority=1000 , match=(reg0[[14]] == 1), action=(next(pipeline=ingress, table=??);) - ]) - - check ovn-nbctl -- add load_balancer_group $lbg load_balancer $lb0 -@@ -2908,7 +2910,6 @@ AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort | sed 's/tabl - AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/g'], [0], [dnl - table=??(ls_in_hairpin ), priority=0 , match=(1), action=(next;) - table=??(ls_in_hairpin ), priority=1 , match=((reg0[[6]] == 1 || reg0[[12]] == 1)), action=(eth.dst <-> eth.src; outport = inport; flags.loopback = 1; output;) -- table=??(ls_in_hairpin ), priority=1000 , match=(reg0[[14]] == 1), action=(next(pipeline=ingress, table=??);) - ]) - - AT_CLEANUP -@@ -3757,18 +3758,18 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl - - AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl - table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.100 && tcp), action=(reg0 = 10.0.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.10), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.100), action=(ct_dnat;) - ]) - - AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80), action=(ct_lb_mark(backends=10.0.0.4:8080);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(ct_lb_mark(backends=10.0.0.40:8080);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), action=(ct_lb_mark(backends=10.0.0.4:8080);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.100 && tcp && tcp.dst == 80), action=(ct_lb_mark(backends=10.0.0.40:8080);) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -3788,18 +3789,18 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl - - AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl - table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.100 && tcp), action=(reg0 = 10.0.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.10), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.100), action=(ct_dnat;) - ]) - - AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.100 && tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; force_snat);) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -3813,6 +3814,7 @@ AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [ - - AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl - table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) -+ table=? (lr_out_undnat ), priority=100 , match=(nd || nd_rs || nd_ra), action=(next;) - table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) - ]) - -@@ -3838,18 +3840,18 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl - - AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl - table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.100 && tcp), action=(reg0 = 10.0.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.10), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.100), action=(ct_dnat;) - ]) - - AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.100 && tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; force_snat);) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -3864,6 +3866,7 @@ AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [ - - AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl - table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) -+ table=? (lr_out_undnat ), priority=100 , match=(nd || nd_rs || nd_ra), action=(next;) - table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) - ]) - -@@ -3902,18 +3905,18 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl - - AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl - table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.100 && tcp), action=(reg0 = 10.0.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.10), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.100), action=(ct_dnat;) - ]) - - AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.100 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.100 && tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; force_snat);) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -3929,6 +3932,7 @@ AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [ - - AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl - table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) -+ table=? (lr_out_undnat ), priority=100 , match=(nd || nd_rs || nd_ra), action=(next;) - table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) - ]) - -@@ -3953,14 +3957,13 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl - - AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl - table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.100 && tcp), action=(reg0 = 10.0.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.20 && tcp), action=(reg0 = 10.0.0.20; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.100), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.20), action=(ct_dnat;) - ]) - - AT_CHECK([grep "lr_in_dnat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.20 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(flags.skip_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.20 && tcp && reg9[[16..31]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; skip_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.20 && tcp && tcp.dst == 80), action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; skip_snat);) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) - -@@ -3970,6 +3973,7 @@ AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sed 's/table=./t - - AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl - table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) -+ table=? (lr_out_undnat ), priority=100 , match=(nd || nd_rs || nd_ra), action=(next;) - table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) - ]) - -@@ -4111,6 +4115,7 @@ check ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0 - check ovn-nbctl --wait=sb sync - - check_stateful_flows() { -+ action=$1 - ovn-sbctl dump-flows sw0 > sw0flows - AT_CAPTURE_FILE([sw0flows]) - -@@ -4144,12 +4149,12 @@ check_stateful_flows() { - table=??(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_mark.blocked = 0; ct_label.label = reg3; }; next;) - ]) - -- AT_CHECK([grep "ls_out_pre_lb" sw0flows | sort], [0], [dnl -+ AT_CHECK_UNQUOTED([grep "ls_out_pre_lb" sw0flows | sort], [0], [dnl - table=1 (ls_out_pre_lb ), priority=0 , match=(1), action=(next;) - table=1 (ls_out_pre_lb ), priority=100 , match=(ip), action=(reg0[[2]] = 1; next;) - table=1 (ls_out_pre_lb ), priority=110 , match=(eth.mcast), action=(next;) -- table=1 (ls_out_pre_lb ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -- table=1 (ls_out_pre_lb ), priority=110 , match=(ip && outport == "sw0-lr0"), action=(next;) -+ table=1 (ls_out_pre_lb ), priority=110 , match=(eth.src == \$svc_monitor_mac), action=(next;) -+ table=1 (ls_out_pre_lb ), priority=110 , match=(ip && outport == "sw0-lr0"), action=($action) - table=1 (ls_out_pre_lb ), priority=110 , match=(nd || nd_rs || nd_ra || mldv1 || mldv2), action=(next;) - table=1 (ls_out_pre_lb ), priority=110 , match=(reg0[[16]] == 1), action=(next;) - ]) -@@ -4169,13 +4174,13 @@ check_stateful_flows() { - ]) - } - --check_stateful_flows -+check_stateful_flows "ct_clear; next;" - - # Add few ACLs - check ovn-nbctl --wait=sb acl-add sw0 from-lport 1002 "ip4 && tcp && tcp.dst == 80" allow-related - check ovn-nbctl --wait=sb acl-add sw0 to-lport 1002 "ip4 && tcp && tcp.src == 80" drop - --check_stateful_flows -+check_stateful_flows "next;" - - # Remove load balancers from sw0 - check ovn-nbctl ls-lb-del sw0 lb0 -@@ -4231,6 +4236,15 @@ AT_CHECK([grep "ls_out_stateful" sw0flows | sort], [0], [dnl - table=7 (ls_out_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_mark.blocked = 0; ct_label.label = reg3; }; next;) - ]) - -+# LB with event=false and reject=false -+AT_CHECK([ovn-nbctl create load_balancer name=lb1 options:reject=false options:event=false vips:\"10.0.0.20\"=\"\" protocol=tcp], [0], [ignore]) -+check ovn-nbctl --wait=sb ls-lb-add sw0 lb1 -+ -+AT_CHECK([ovn-sbctl dump-flows sw0 | grep "ls_in_lb " | sort ], [0], [dnl -+ table=12(ls_in_lb ), priority=0 , match=(1), action=(next;) -+ table=12(ls_in_lb ), priority=110 , match=(ct.new && ip4.dst == 10.0.0.20), action=(drop;) -+]) -+ - AT_CLEANUP - ]) - -@@ -4871,7 +4885,7 @@ check ovn-nbctl lsp-set-options ls2-ro2 router-port=ro2-ls2 - ovn-sbctl lflow-list ls1 > ls1_lflows - AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], [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), action=(handle_svc_check(inport);) -+ 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:02), action=(outport = "vm1"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -4883,7 +4897,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], - ovn-sbctl lflow-list ls2 > ls2_lflows - AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | sed 's/table=../table=??/' | sort], [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), action=(handle_svc_check(inport);) -+ 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:02:01), action=(outport = "ls2-ro2"; output;) - table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:02:02), action=(outport = "vm2"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -4903,7 +4917,7 @@ check ovn-nbctl --wait=sb lr-nat-add ro2 snat 20.0.0.200 192.168.2.200/30 - ovn-sbctl lflow-list ls1 > ls1_lflows - AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], [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), action=(handle_svc_check(inport);) -+ 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:02), action=(outport = "vm1"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -4916,7 +4930,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], - ovn-sbctl lflow-list ls2 > ls2_lflows - AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | sed 's/table=../table=??/' | sort], [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), action=(handle_svc_check(inport);) -+ 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:02:01), action=(outport = "ls2-ro2"; output;) - table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:02:02), action=(outport = "vm2"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -4937,7 +4951,7 @@ check ovn-nbctl --wait=sb lr-nat-add ro2 snat 40.0.0.200 192.168.2.148/30 - ovn-sbctl lflow-list ls1 > ls1_lflows - AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], [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), action=(handle_svc_check(inport);) -+ 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:02), action=(outport = "vm1"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -4951,7 +4965,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], - ovn-sbctl lflow-list ls2 > ls2_lflows - AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | sed 's/table=../table=??/' | sort], [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), action=(handle_svc_check(inport);) -+ 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:02:01), action=(outport = "ls2-ro2"; output;) - table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:02:02), action=(outport = "vm2"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -4970,7 +4984,7 @@ ovn-nbctl --wait=sb lr-lb-add ro1 lb1 - ovn-sbctl lflow-list ls1 > ls1_lflows - AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], [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), action=(handle_svc_check(inport);) -+ 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:02), action=(outport = "vm1"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -4988,7 +5002,7 @@ ovn-nbctl --wait=sb lb-add lb1 192.168.4.100:80 10.0.0.10:80 - ovn-sbctl lflow-list ls1 > ls1_lflows - AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], [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), action=(handle_svc_check(inport);) -+ 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:02), action=(outport = "vm1"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -5012,7 +5026,7 @@ ovn-nbctl --wait=sb lrp-set-gateway-chassis ro1-ls1 chassis-1 30 - ovn-sbctl lflow-list ls1 > ls1_lflows - AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | sed 's/table=../table=??/' | sort], [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), action=(handle_svc_check(inport);) -+ 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:02), action=(outport = "vm1"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -5211,25 +5225,23 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl - - AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl - table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.200), action=(reg0 = 172.168.0.200; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.100 && tcp), action=(reg0 = 172.168.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.210 && udp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = udp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.10), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.100), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.200), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.210), action=(ct_dnat;) - ]) - - AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=7 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone(10.0.0.3);) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.200 && ct_mark.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.200 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.80,10.0.0.81);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.100 && tcp && reg9[[16..31]] == 8082 && ct_mark.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60 && ct_mark.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.4:8080);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.100 && tcp && reg9[[16..31]] == 8082 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.200 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.80,10.0.0.81);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.4:8080);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && udp && udp.dst == 60 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -5284,25 +5296,23 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl - - AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl - table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.200), action=(reg0 = 172.168.0.200; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.100 && tcp), action=(reg0 = 172.168.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.210 && udp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = udp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.10), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.100), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.200), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.210), action=(ct_dnat;) - ]) - - AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=7 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.200 && ct_mark.natted == 1), action=(next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.200), action=(ct_lb_mark(backends=10.0.0.80,10.0.0.81);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.100 && tcp && reg9[[16..31]] == 8082 && ct_mark.natted == 1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60 && ct_mark.natted == 1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80), action=(ct_lb_mark(backends=10.0.0.4:8080);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.100 && tcp && reg9[[16..31]] == 8082), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.200), action=(ct_lb_mark(backends=10.0.0.80,10.0.0.81);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), action=(ct_lb_mark(backends=10.0.0.4:8080);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && udp && udp.dst == 60), action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -5314,6 +5324,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor - - AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl - table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) -+ table=? (lr_out_undnat ), priority=100 , match=(nd || nd_rs || nd_ra), action=(next;) - table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) - ]) - -@@ -5349,25 +5360,23 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl - - AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl - table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.200), action=(reg0 = 172.168.0.200; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.100 && tcp), action=(reg0 = 172.168.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.210 && udp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = udp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.10), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.100), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.200), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.210), action=(ct_dnat;) - ]) - - AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=7 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.200 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.200), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.80,10.0.0.81; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.100 && tcp && reg9[[16..31]] == 8082 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.100 && tcp && reg9[[16..31]] == 8082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.200), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.80,10.0.0.81; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && udp && udp.dst == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -5379,6 +5388,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor - - AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl - table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) -+ table=? (lr_out_undnat ), priority=100 , match=(nd || nd_rs || nd_ra), action=(next;) - table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) - ]) - -@@ -5416,28 +5426,25 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl - - AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl - table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.200), action=(reg0 = 172.168.0.200; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.10 && tcp), action=(reg0 = 172.168.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.100 && tcp), action=(reg0 = 172.168.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.210 && udp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = udp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.10), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.10), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.100), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.200), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.210), action=(ct_dnat;) - ]) - - AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=7 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.200 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.200), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.80,10.0.0.81; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.10 && tcp && reg9[[16..31]] == 9082 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.100 && tcp && reg9[[16..31]] == 8082 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.10 && tcp && reg9[[16..31]] == 9082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.100 && tcp && reg9[[16..31]] == 8082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.200), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.80,10.0.0.81; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.10 && tcp && tcp.dst == 9082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && udp && udp.dst == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -5449,6 +5456,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor - - AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl - table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) -+ table=? (lr_out_undnat ), priority=100 , match=(nd || nd_rs || nd_ra), action=(next;) - table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) - ]) - -@@ -5496,31 +5504,27 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl - - AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl - table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.200), action=(reg0 = 172.168.0.200; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.10 && tcp), action=(reg0 = 172.168.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.100 && tcp), action=(reg0 = 172.168.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.210 && udp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = udp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip6.dst == def0::2 && tcp), action=(xxreg0 = def0::2; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 10.0.0.10), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.10), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.100), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.200), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.210), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip6.dst == def0::2), action=(ct_dnat;) - ]) - - AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=7 (lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.200 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.200), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.80,10.0.0.81; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.10 && tcp && reg9[[16..31]] == 9082 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.100 && tcp && reg9[[16..31]] == 8082 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip6 && xxreg0 == def0::2 && tcp && reg9[[16..31]] == 8000 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.10 && tcp && reg9[[16..31]] == 9082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.100 && tcp && reg9[[16..31]] == 8082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip6 && xxreg0 == def0::2 && tcp && reg9[[16..31]] == 8000), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=[[aef0::2]]:80,[[aef0::3]]:80; force_snat);) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.200), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.80,10.0.0.81; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.10 && tcp && tcp.dst == 9082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && udp && udp.dst == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip6 && ip6.dst == def0::2 && tcp && tcp.dst == 8000), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=[[aef0::2]]:80,[[aef0::3]]:80; force_snat);) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -5532,6 +5536,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor - - AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl - table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) -+ table=? (lr_out_undnat ), priority=100 , match=(nd || nd_rs || nd_ra), action=(next;) - table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) - ]) - -@@ -5572,18 +5577,17 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl - - AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl - table=5 (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.210 && tcp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = tcp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=110 , match=(ip && ip4.dst == 172.168.0.210 && udp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = udp.dst; ct_dnat;) -- table=5 (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) -+ table=5 (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 172.168.0.210), action=(ct_dnat;) - ]) - - AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.210 && tcp && reg9[[16..31]] == 60 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.210 && tcp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.0.210 && udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && tcp && tcp.dst == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && udp && udp.dst == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -5594,6 +5598,7 @@ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sor - - AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl - table=? (lr_out_undnat ), priority=0 , match=(1), action=(next;) -+ table=? (lr_out_undnat ), priority=100 , match=(nd || nd_rs || nd_ra), action=(next;) - table=? (lr_out_undnat ), priority=50 , match=(ip), action=(flags.loopback = 1; ct_dnat;) - ]) - -@@ -5634,9 +5639,11 @@ ovn-sbctl set service_monitor $sm_vip2 status=offline - - AT_CHECK([ovn-sbctl dump-flows lr0 | grep "lr_in_dnat" | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.10.10 && ct_mark.natted == 1), action=(next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.10.10), action=(reg0 = 0; reject { outport <-> inport; next(pipeline=egress,table=3);};) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.10.10), action=(reg0 = 0; reject { outport <-> inport; next(pipeline=egress,table=3);};) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -5646,9 +5653,11 @@ check ovn-nbctl --wait=sb set load_balancer lb5 options:skip_snat=true - - AT_CHECK([ovn-sbctl dump-flows lr0 | grep "lr_in_dnat" | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.10.10 && ct_mark.natted == 1), action=(flags.skip_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.10.10), action=(flags.skip_snat_for_lb = 1; reg0 = 0; reject { outport <-> inport; next(pipeline=egress,table=3);};) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.10.10), action=(flags.skip_snat_for_lb = 1; reg0 = 0; reject { outport <-> inport; next(pipeline=egress,table=3);};) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -5660,9 +5669,58 @@ check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="route - - AT_CHECK([ovn-sbctl dump-flows lr0 | grep "lr_in_dnat" | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.168.10.10 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.168.10.10), action=(flags.force_snat_for_lb = 1; reg0 = 0; reject { outport <-> inport; next(pipeline=egress,table=3);};) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.10.10), action=(flags.force_snat_for_lb = 1; reg0 = 0; reject { outport <-> inport; next(pipeline=egress,table=3);};) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) -+]) -+ -+# LB with event=false and reject=false -+check ovn-nbctl lr-lb-del lr0 -+check ovn-nbctl remove logical_router lr0 options lb_force_snat_ip -+AT_CHECK([ovn-nbctl create load_balancer name=lb6 options:reject=false options:event=false vips:\"172.168.10.30\"=\"\" protocol=tcp], [0], [ignore]) -+check ovn-nbctl --wait=sb lr-lb-add lr0 lb6 -+ -+AT_CHECK([ovn-sbctl dump-flows lr0 | grep "lr_in_dnat" | sort], [0], [dnl -+ table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.10.30), action=(drop;) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) -+]) -+ -+# LB with event=false, reject=false and skip_snat -+check ovn-nbctl --wait=sb set load_balancer lb6 options:skip_snat=true -+ -+AT_CHECK([ovn-sbctl dump-flows lr0 | grep "lr_in_dnat" | sort], [0], [dnl -+ table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.10.30), action=(flags.skip_snat_for_lb = 1; drop;) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) -+]) -+ -+check ovn-nbctl remove load_balancer lb6 options skip_snat -+ -+# LB with event=false, reject=false and force_snat -+check ovn-nbctl --wait=sb set logical_router lr0 options:lb_force_snat_ip="router_ip" -+ -+AT_CHECK([ovn-sbctl dump-flows lr0 | grep "lr_in_dnat" | sort], [0], [dnl -+ table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.10.30), action=(flags.force_snat_for_lb = 1; drop;) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -6692,11 +6750,12 @@ dnl Flows to skip TTL == {0, 1} check for IGMP and MLD packets. - AT_CHECK([grep -e 'lr_in_ip_input ' lrflows | grep -e 'igmp' -e 'mld' -e 'ip.ttl == {0, 1}' | sed 's/table=../table=??/'], [0], [dnl - table=??(lr_in_ip_input ), priority=120 , match=((mldv1 || mldv2) && ip.ttl == 1), action=(next;) - table=??(lr_in_ip_input ), priority=120 , match=(igmp && ip.ttl == 1), action=(next;) -- table=??(lr_in_ip_input ), priority=100 , match=(inport == "lrp1" && 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 = 254; outport = "lrp1"; flags.loopback = 1; output; };) -- table=??(lr_in_ip_input ), priority=100 , match=(inport == "lrp1" && ip6 && ip6.src == 1010::/64 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst <-> eth.src; ip6.dst = ip6.src; ip6.src = 1010::1 ; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL exceeded in transit */ outport = "lrp1"; flags.loopback = 1; output; };) -- table=??(lr_in_ip_input ), priority=100 , match=(inport == "lrp2" && 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.20.20.1 ; ip.ttl = 254; outport = "lrp2"; flags.loopback = 1; output; };) -- table=??(lr_in_ip_input ), priority=100 , match=(inport == "lrp2" && ip6 && ip6.src == 2020::/64 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst <-> eth.src; ip6.dst = ip6.src; ip6.src = 2020::1 ; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL exceeded in transit */ outport = "lrp2"; flags.loopback = 1; output; };) -- table=??(lr_in_ip_input ), priority=30 , match=(ip4 && ip.ttl == {0, 1}), action=(drop;) -+ 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=31 , match=(inport == "lrp1" && 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 = 254; outport = "lrp1"; flags.loopback = 1; output; };) -+ table=??(lr_in_ip_input ), priority=31 , match=(inport == "lrp1" && ip6 && ip6.src == 1010::/64 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst <-> eth.src; ip6.dst = ip6.src; ip6.src = 1010::1 ; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL exceeded in transit */ outport = "lrp1"; flags.loopback = 1; output; };) -+ table=??(lr_in_ip_input ), priority=31 , match=(inport == "lrp2" && 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.20.20.1 ; ip.ttl = 254; outport = "lrp2"; flags.loopback = 1; output; };) -+ table=??(lr_in_ip_input ), priority=31 , match=(inport == "lrp2" && ip6 && ip6.src == 2020::/64 && ip.ttl == {0, 1} && !ip.later_frag), action=(icmp6 {eth.dst <-> eth.src; ip6.dst = ip6.src; ip6.src = 2020::1 ; ip.ttl = 254; icmp6.type = 3; /* Time exceeded */ icmp6.code = 0; /* TTL exceeded in transit */ outport = "lrp2"; flags.loopback = 1; output; };) -+ table=??(lr_in_ip_input ), priority=30 , match=(ip.ttl == {0, 1}), action=(drop;) - ]) - - dnl Flows to "route" (statically forward) without decrementing TTL for -@@ -6755,6 +6814,7 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], - table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) - table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) -@@ -6809,6 +6869,7 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], - table=??(ls_in_acl_after_lb ), priority=2003 , match=(reg0[[8]] == 1 && (ip4 && icmp)), action=(next;) - table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[10]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(ct_commit { ct_mark.blocked = 1; }; /* drop */) - table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[9]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(/* drop */) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) -@@ -6863,6 +6924,7 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], - table=??(ls_in_acl_after_lb ), priority=2001 , match=(reg0[[9]] == 1 && (ip4)), action=(/* drop */) - table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[10]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(ct_commit { ct_mark.blocked = 1; }; /* drop */) - table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[9]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(/* drop */) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) -@@ -7154,11 +7216,14 @@ flow="inport == \"lsp1\" && eth.src == 00:00:00:00:00:01 && eth.dst == 00:00:00: - AS_BOX([No ACL, default_acl_drop not set]) - check ovn-nbctl --wait=sb sync - AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl -+ table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl ), priority=65535, match=(1), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_hint ), priority=65535, match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) -+ table=??(ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_out_acl ), priority=65535, match=(1), action=(next;) - table=??(ls_out_acl_hint ), priority=65535, match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) -@@ -7173,11 +7238,14 @@ output("lsp2"); - AS_BOX([No ACL, default_acl_drop false]) - check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=false - AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl -+ table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl ), priority=65535, match=(1), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_hint ), priority=65535, match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) -+ table=??(ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_out_acl ), priority=65535, match=(1), action=(next;) - table=??(ls_out_acl_hint ), priority=65535, match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) -@@ -7192,11 +7260,14 @@ output("lsp2"); - AS_BOX([No ACL, default_acl_drop true]) - check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=true - AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl -+ table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl ), priority=65535, match=(1), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_hint ), priority=65535, match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) -+ table=??(ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_out_acl ), priority=65535, match=(1), action=(next;) - table=??(ls_out_acl_hint ), priority=65535, match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) -@@ -7218,12 +7289,15 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ - table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl ), priority=1001 , match=(ip4 && tcp), action=(next;) - table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) -+ table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_out_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_acl ), priority=34000, match=(eth.src == $svc_monitor_mac), action=(next;) -+ table=??(ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7240,12 +7314,15 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ - table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl ), priority=1001 , match=(ip4 && tcp), action=(next;) - table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) -+ table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_out_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_acl ), priority=34000, match=(eth.src == $svc_monitor_mac), action=(next;) -+ table=??(ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7262,12 +7339,15 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ - table=??(ls_in_acl ), priority=0 , match=(1), action=(drop;) - table=??(ls_in_acl ), priority=1001 , match=(ip4 && tcp), action=(next;) - table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) -+ table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(drop;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_out_acl ), priority=0 , match=(1), action=(drop;) - table=??(ls_out_acl ), priority=34000, match=(eth.src == $svc_monitor_mac), action=(next;) -+ table=??(ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7292,6 +7372,7 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ - table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) - table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(drop;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) -@@ -7343,13 +7424,16 @@ check ovn-nbctl --wait=sb remove NB_Global . options default_acl_drop - AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl - table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) -+ table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl_after_lb ), priority=1001 , match=(ip4 && tcp), action=(next;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_out_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_acl ), priority=34000, match=(eth.src == $svc_monitor_mac), action=(next;) -+ table=??(ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7365,13 +7449,16 @@ check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=false - AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl - table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) -+ table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl_after_lb ), priority=1001 , match=(ip4 && tcp), action=(next;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_out_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_acl ), priority=34000, match=(eth.src == $svc_monitor_mac), action=(next;) -+ table=??(ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7387,13 +7474,16 @@ check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=true - AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl - table=??(ls_in_acl ), priority=0 , match=(1), action=(drop;) - table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) -+ table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(drop;) - table=??(ls_in_acl_after_lb ), priority=1001 , match=(ip4 && tcp), action=(next;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_out_acl ), priority=0 , match=(1), action=(drop;) - table=??(ls_out_acl ), priority=34000, match=(eth.src == $svc_monitor_mac), action=(next;) -+ table=??(ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7418,6 +7508,7 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(drop;) - table=??(ls_in_acl_after_lb ), priority=1001 , match=(reg0[[7]] == 1 && (ip4 && tcp)), action=(reg0[[1]] = 1; next;) - table=??(ls_in_acl_after_lb ), priority=1001 , match=(reg0[[8]] == 1 && (ip4 && tcp)), action=(next;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) -@@ -7469,13 +7560,16 @@ check ovn-nbctl --wait=sb remove NB_Global . options default_acl_drop - AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl - table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) -+ table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_out_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_acl ), priority=1001 , match=(ip4 && tcp), action=(next;) - table=??(ls_out_acl ), priority=34000, match=(eth.src == $svc_monitor_mac), action=(next;) -+ table=??(ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7491,13 +7585,16 @@ check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=false - AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl - table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) -+ table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_out_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_acl ), priority=1001 , match=(ip4 && tcp), action=(next;) - table=??(ls_out_acl ), priority=34000, match=(eth.src == $svc_monitor_mac), action=(next;) -+ table=??(ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7513,13 +7610,16 @@ check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=true - AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/' | sort], [0], [dnl - table=??(ls_in_acl ), priority=0 , match=(1), action=(drop;) - table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) -+ table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(drop;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) - table=??(ls_out_acl ), priority=0 , match=(1), action=(drop;) - table=??(ls_out_acl ), priority=1001 , match=(ip4 && tcp), action=(next;) - table=??(ls_out_acl ), priority=34000, match=(eth.src == $svc_monitor_mac), action=(next;) -+ table=??(ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_out_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=0 , match=(1), action=(next;) - table=??(ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) -@@ -7542,6 +7642,7 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/ - table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) - table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(drop;) -+ table=??(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) - table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) - table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;) -@@ -7719,7 +7820,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl - table=??(ls_in_apply_port_sec), priority=0 , match=(1), action=(next;) - table=??(ls_in_apply_port_sec), priority=50 , match=(reg0[[15]] == 1), action=(drop;) - 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), action=(handle_svc_check(inport);) -+ 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=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) - table=??(ls_in_l2_unknown ), priority=0 , match=(1), action=(output;) - table=??(ls_in_l2_unknown ), priority=50 , match=(outport == "none"), action=(drop;) -@@ -7744,7 +7845,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl - table=??(ls_in_apply_port_sec), priority=0 , match=(1), action=(next;) - table=??(ls_in_apply_port_sec), priority=50 , match=(reg0[[15]] == 1), action=(drop;) - 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), action=(handle_svc_check(inport);) -+ 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:00:01), action=(outport = "sw0p1"; output;) - table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0p2"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -7770,7 +7871,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl - table=??(ls_in_apply_port_sec), priority=0 , match=(1), action=(next;) - table=??(ls_in_apply_port_sec), priority=50 , match=(reg0[[15]] == 1), action=(drop;) - 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), action=(handle_svc_check(inport);) -+ 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:00:01), action=(outport = "sw0p1"; output;) - table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0p2"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -7797,7 +7898,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl - table=??(ls_in_apply_port_sec), priority=0 , match=(1), action=(next;) - table=??(ls_in_apply_port_sec), priority=50 , match=(reg0[[15]] == 1), action=(drop;) - 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), action=(handle_svc_check(inport);) -+ 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:00:01), action=(drop;) - table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0p2"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -7824,7 +7925,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl - table=??(ls_in_apply_port_sec), priority=0 , match=(1), action=(next;) - table=??(ls_in_apply_port_sec), priority=50 , match=(reg0[[15]] == 1), action=(drop;) - 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), action=(handle_svc_check(inport);) -+ 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:00:01), action=(drop;) - table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0p2"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -7854,7 +7955,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl - table=??(ls_in_apply_port_sec), priority=0 , match=(1), action=(next;) - table=??(ls_in_apply_port_sec), priority=50 , match=(reg0[[15]] == 1), action=(drop;) - 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), action=(handle_svc_check(inport);) -+ 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:00:01), action=(outport = "sw0p1"; output;) - table=??(ls_in_l2_lkup ), priority=50 , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0p2"; output;) - table=??(ls_in_l2_lkup ), priority=70 , match=(eth.mcast), action=(outport = "_MC_flood"; output;) -@@ -7886,8 +7987,10 @@ check ovn-nbctl \ - AS_BOX([No chassis registered - use ct_lb_mark and ct_mark.natted]) - check ovn-nbctl --wait=sb sync - AT_CHECK([ovn-sbctl lflow-list | grep -e natted -e ct_lb], [0], [dnl -- table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 66.66.66.66 && ct_mark.natted == 1), action=(next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 66.66.66.66), action=(ct_lb_mark(backends=42.42.42.2);) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 66.66.66.66), action=(ct_lb_mark(backends=42.42.42.2);) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=6 (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip4.dst == 66.66.66.66), action=(reg1 = 66.66.66.66; ct_lb_mark;) - table=6 (ls_in_pre_stateful ), priority=110 , match=(reg0[[2]] == 1), action=(ct_lb_mark;) - table=12(ls_in_lb ), priority=110 , match=(ct.new && ip4.dst == 66.66.66.66), action=(reg0[[1]] = 0; ct_lb_mark(backends=42.42.42.2);) -@@ -7898,8 +8001,10 @@ AS_BOX([Chassis registered that doesn't support ct_lb_mark - use ct_lb and ct_la - check ovn-sbctl chassis-add hv geneve 127.0.0.1 - check ovn-nbctl --wait=sb sync - AT_CHECK([ovn-sbctl lflow-list | grep -e natted -e ct_lb], [0], [dnl -- table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 66.66.66.66 && ct_label.natted == 1), action=(next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 66.66.66.66), action=(ct_lb(backends=42.42.42.2);) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 66.66.66.66), action=(ct_lb(backends=42.42.42.2);) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_label.natted && ct_label.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_label.natted && ct_label.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_label.natted), action=(next;) - table=6 (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip4.dst == 66.66.66.66), action=(reg1 = 66.66.66.66; ct_lb;) - table=6 (ls_in_pre_stateful ), priority=110 , match=(reg0[[2]] == 1), action=(ct_lb;) - table=12(ls_in_lb ), priority=110 , match=(ct.new && ip4.dst == 66.66.66.66), action=(reg0[[1]] = 0; ct_lb(backends=42.42.42.2);) -@@ -7910,8 +8015,10 @@ AS_BOX([Chassis upgrades and supports ct_lb_mark - use ct_lb_mark and ct_mark.na - check ovn-sbctl set chassis hv other_config:ct-no-masked-label=true - check ovn-nbctl --wait=sb sync - AT_CHECK([ovn-sbctl lflow-list | grep -e natted -e ct_lb], [0], [dnl -- table=7 (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 66.66.66.66 && ct_mark.natted == 1), action=(next;) -- table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 66.66.66.66), action=(ct_lb_mark(backends=42.42.42.2);) -+ table=7 (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 66.66.66.66), action=(ct_lb_mark(backends=42.42.42.2);) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=6 (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip4.dst == 66.66.66.66), action=(reg1 = 66.66.66.66; ct_lb_mark;) - table=6 (ls_in_pre_stateful ), priority=110 , match=(reg0[[2]] == 1), action=(ct_lb_mark;) - table=12(ls_in_lb ), priority=110 , match=(ct.new && ip4.dst == 66.66.66.66), action=(reg0[[1]] = 0; ct_lb_mark(backends=42.42.42.2);) -@@ -8244,15 +8351,17 @@ AT_CAPTURE_FILE([R1flows]) - - AT_CHECK([grep "lr_in_lb_aff_check" R1flows | sort], [0], [dnl - table=6 (lr_in_lb_aff_check ), priority=0 , match=(1), action=(next;) -- table=6 (lr_in_lb_aff_check ), priority=100 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.16.0.10 && tcp && reg9[[16..31]] == 80), action=(reg9[[6]] = chk_lb_aff(); next;) -+ table=6 (lr_in_lb_aff_check ), priority=100 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && tcp && tcp.dst == 80), action=(reg0 = ip4.dst; reg9[[16..31]] = tcp.dst; reg9[[6]] = chk_lb_aff(); next;) - ]) - AT_CHECK([grep "lr_in_dnat " R1flows | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.16.0.10 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.16.0.10 && tcp && reg9[[16..31]] == 80), action=(ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && tcp && tcp.dst == 80), action=(ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80);) - table=7 (lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4 && reg4 == 10.0.0.2 && reg8[[0..15]] == 80), action=(reg0 = 172.16.0.10; ct_lb_mark(backends=10.0.0.2:80);) - table=7 (lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4 && reg4 == 20.0.0.2 && reg8[[0..15]] == 80), action=(reg0 = 172.16.0.10; ct_lb_mark(backends=20.0.0.2:80);) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -8270,11 +8379,13 @@ AT_CAPTURE_FILE([R1flows_skip_snat]) - - AT_CHECK([grep "lr_in_dnat " R1flows_skip_snat | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.16.0.10 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(flags.skip_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.16.0.10 && tcp && reg9[[16..31]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && tcp && tcp.dst == 80), action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);) - table=7 (lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4 && reg4 == 10.0.0.2 && reg8[[0..15]] == 80), action=(reg0 = 172.16.0.10; flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80; skip_snat);) - table=7 (lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4 && reg4 == 20.0.0.2 && reg8[[0..15]] == 80), action=(reg0 = 172.16.0.10; flags.skip_snat_for_lb = 1; ct_lb_mark(backends=20.0.0.2:80; skip_snat);) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -8289,11 +8400,13 @@ AT_CAPTURE_FILE([R1flows_force_snat]) - - AT_CHECK([grep "lr_in_dnat " R1flows_force_snat | sort], [0], [dnl - table=7 (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 172.16.0.10 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1), action=(flags.force_snat_for_lb = 1; next;) -- table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 172.16.0.10 && tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; force_snat);) -+ table=7 (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; force_snat);) - table=7 (lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4 && reg4 == 10.0.0.2 && reg8[[0..15]] == 80), action=(reg0 = 172.16.0.10; flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80; force_snat);) - table=7 (lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4 && reg4 == 20.0.0.2 && reg8[[0..15]] == 80), action=(reg0 = 172.16.0.10; flags.force_snat_for_lb = 1; ct_lb_mark(backends=20.0.0.2:80; force_snat);) -+ table=7 (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=7 (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=7 (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=7 (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -8330,8 +8443,9 @@ rm -f northd/ovn-northd.log - check as northd ovn-appctl -t NORTHD_TYPE vlog/reopen - check as northd ovn-appctl -t NORTHD_TYPE vlog/set jsonrpc:dbg - check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats --check ovn-nbctl add address_set $foo_as_uuid addresses 1.1.1.3 --wait_column '1.1.1.1 1.1.1.2 1.1.1.3' Address_Set addresses name=foo -+check ovn-nbctl add address_set $foo_as_uuid addresses 1.1.1.3 -- \ -+ add address_set $foo_as_uuid addresses 1.1.2.1/4 -+wait_column '1.1.1.1 1.1.1.2 1.1.1.3 1.1.2.1/4' Address_Set addresses name=foo - - # There should be no recompute of the sync_to_sb_addr_set engine node . - AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats sync_to_sb_addr_set recompute], [0], [0 -@@ -8341,8 +8455,9 @@ AT_CHECK([grep transact northd/ovn-northd.log | grep Address_Set | \ - grep -c mutate], [0], [1 - ]) - --check ovn-nbctl add address_set $foo_as_uuid addresses \ --1.1.1.4 -- remove address_set $foo_as_uuid addresses 1.1.1.1 -+check ovn-nbctl add address_set $foo_as_uuid addresses 1.1.1.4 -- \ -+ remove address_set $foo_as_uuid addresses 1.1.1.1 -- \ -+ remove address_set $foo_as_uuid addresses 1.1.2.1/4 - wait_column '1.1.1.2 1.1.1.3 1.1.1.4' Address_Set addresses name=foo - - # There should be no recompute of the sync_to_sb_addr_set engine node . -@@ -8569,12 +8684,13 @@ ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows0 - - AT_CHECK([grep -e "lr_in_defrag" -e "lr_in_dnat" lflows0], [0], [dnl - table=? (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=? (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 192.168.0.1), action=(reg0 = 192.168.0.1; ct_dnat;) -- table=? (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) -+ table=? (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 192.168.0.1), action=(ct_dnat;) - table=? (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=? (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 192.168.0.1 && ct_mark.natted == 1), action=(next;) -- table=? (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 192.168.0.1), action=(ct_lb_mark(backends=192.168.1.10);) -+ table=? (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 192.168.0.1), action=(ct_lb_mark(backends=192.168.1.10);) -+ table=? (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=? (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=? (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=? (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=? (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=? (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -8588,6 +8704,7 @@ AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows0 | grep "priority=65532"], - table=? (ls_out_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;) - table=? (ls_out_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) - table=? (ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) -+ table=?(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=?(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) - ]) - -@@ -8599,10 +8716,12 @@ ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows1 - - AT_CHECK([grep -e "lr_in_defrag" -e "lr_in_dnat" lflows1], [0], [dnl - table=? (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=? (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 192.168.0.1), action=(reg0 = 192.168.0.1; ct_dnat;) -+ table=? (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 192.168.0.1), action=(ct_dnat;) - table=? (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=? (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 192.168.0.1 && ct_label.natted == 1), action=(next;) -- table=? (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 192.168.0.1), action=(ct_lb(backends=192.168.1.10);) -+ table=? (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 192.168.0.1), action=(ct_lb(backends=192.168.1.10);) -+ table=? (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_label.natted), action=(next;) -+ table=? (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_label.natted && ct_label.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=? (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_label.natted && ct_label.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - ]) - - AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows1 | grep "priority=65532"], [0], [dnl -@@ -8614,6 +8733,7 @@ AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows1 | grep "priority=65532"], - table=? (ls_out_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;) - table=? (ls_out_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) - table=? (ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) -+ table=?(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=?(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) - ]) - -@@ -8625,12 +8745,13 @@ ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows2 - - AT_CHECK([grep -e "lr_in_defrag" -e "lr_in_dnat" lflows2], [0], [dnl - table=? (lr_in_defrag ), priority=0 , match=(1), action=(next;) -- table=? (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 192.168.0.1), action=(reg0 = 192.168.0.1; ct_dnat;) -- table=? (lr_in_defrag ), priority=50 , match=(icmp || icmp6), action=(ct_dnat;) -+ table=? (lr_in_defrag ), priority=100 , match=(ip && ip4.dst == 192.168.0.1), action=(ct_dnat;) - table=? (lr_in_dnat ), priority=0 , match=(1), action=(next;) -- table=? (lr_in_dnat ), priority=110 , match=(ct.est && !ct.rel && ip4 && reg0 == 192.168.0.1 && ct_mark.natted == 1), action=(next;) -- table=? (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && reg0 == 192.168.0.1), action=(ct_lb_mark(backends=192.168.1.10);) -+ table=? (lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 192.168.0.1), action=(ct_lb_mark(backends=192.168.1.10);) -+ table=? (lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) - table=? (lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) -+ table=? (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) -+ table=? (lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) - table=? (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) - table=? (lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) - ]) -@@ -8644,8 +8765,104 @@ AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows2 | grep "priority=65532"], - table=? (ls_out_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;) - table=? (ls_out_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;) - table=? (ls_out_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) -+ table=?(ls_in_acl_after_lb ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) - table=?(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;) - ]) - - AT_CLEANUP - ]) -+ -+OVN_FOR_EACH_NORTHD_NO_HV([ -+AT_SETUP([Chassis-feature compatibitility - remote chassis]) -+ovn_start -+ -+AS_BOX([Local chassis]) -+check ovn-sbctl chassis-add hv1 geneve 127.0.0.1 \ -+ -- set chassis hv1 other_config:ct-no-masked-label=true \ -+ -- set chassis hv1 other_config:ovn-ct-lb-related=true \ -+ -- set chassis hv1 other_config:mac-binding-timestamp=true -+ -+check ovn-nbctl --wait=sb sync -+ -+AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE debug/chassis-features-list], [0], [dnl -+ct_no_masked_label: true -+ct_lb_related: true -+mac_binding_timestamp: true -+]) -+ -+AS_BOX([Remote chassis]) -+check ovn-sbctl chassis-add hv2 geneve 127.0.0.2 \ -+ -- set chassis hv2 other_config:is-remote=true \ -+ -- set chassis hv2 other_config:ct-no-masked-label=false \ -+ -- set chassis hv2 other_config:ovn-ct-lb-related=false \ -+ -- set chassis hv2 other_config:mac-binding-timestamp=false -+ -+check ovn-nbctl --wait=sb sync -+ -+AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE debug/chassis-features-list], [0], [dnl -+ct_no_masked_label: true -+ct_lb_related: true -+mac_binding_timestamp: true -+]) -+ -+AT_CLEANUP -+]) -+ -+AT_SETUP([Localnet ports on LS with LB]) -+ovn_start -+# In the past, traffic arriving on localnet ports has skipped conntrack. -+# This test ensures that we still skip conntrack for localnet ports, -+# *except* for the case where the logical switch has a load balancer -+# configured. In this case, the localnet port will not skip conntrack, -+# allowing for traffic to be load balanced on the localnet port. -+ -+check ovn-nbctl ls-add sw -+check ovn-nbctl lsp-add sw sw-ln -+check ovn-nbctl lsp-set-type sw-ln localnet -+check ovn-nbctl lsp-set-addresses sw-ln unknown -+check ovn-nbctl --wait=sb sync -+ -+# Since this test is only concerned with logical flows, we don't need to -+# configure anything else that we normally would with regards to localnet -+# ports -+ -+ -+# First, ensure that conntrack is skipped for the localnet port since there -+# isn't a load balancer configured. -+ -+AT_CHECK([ovn-sbctl lflow-list sw | grep ls_in_pre_lb | grep priority=110 | grep sw-ln | sed 's/table=../table=??/'], [0], [dnl -+ table=??(ls_in_pre_lb ), priority=110 , match=(ip && inport == "sw-ln"), action=(next;) -+]) -+ -+AT_CHECK([ovn-sbctl lflow-list sw | grep ls_out_pre_lb | grep priority=110 | grep sw-ln | sed 's/table=../table=??/'], [0], [dnl -+ table=??(ls_out_pre_lb ), priority=110 , match=(ip && outport == "sw-ln"), action=(ct_clear; next;) -+]) -+ -+# Now add a load balancer and ensure that we no longer are skipping conntrack -+# for the localnet port -+ -+check ovn-nbctl lb-add lb 10.0.0.1:80 10.0.0.100:8080 tcp -+check ovn-nbctl ls-lb-add sw lb -+check ovn-nbctl --wait=sb sync -+ -+AT_CHECK([ovn-sbctl lflow-list sw | grep ls_in_pre_lb | grep priority=110 | grep sw-ln | sed 's/table=../table=??/'], [0], [dnl -+]) -+ -+AT_CHECK([ovn-sbctl lflow-list sw | grep ls_out_pre_lb | grep priority=110 | grep sw-ln | sed 's/table=../table=??/'], [0], [dnl -+]) -+ -+# And ensure that removing the load balancer from the switch results in skipping -+# conntrack again -+check ovn-nbctl ls-lb-del sw lb -+check ovn-nbctl --wait=sb sync -+ -+AT_CHECK([ovn-sbctl lflow-list sw | grep ls_in_pre_lb | grep priority=110 | grep sw-ln | sed 's/table=../table=??/'], [0], [dnl -+ table=??(ls_in_pre_lb ), priority=110 , match=(ip && inport == "sw-ln"), action=(next;) -+]) -+ -+AT_CHECK([ovn-sbctl lflow-list sw | grep ls_out_pre_lb | grep priority=110 | grep sw-ln | sed 's/table=../table=??/'], [0], [dnl -+ table=??(ls_out_pre_lb ), priority=110 , match=(ip && outport == "sw-ln"), action=(ct_clear; next;) -+]) -+ -+AT_CLEANUP -+]) -diff --git a/tests/ovn.at b/tests/ovn.at -index 55de7c85b..ed91d32d0 100644 ---- a/tests/ovn.at -+++ b/tests/ovn.at -@@ -992,10 +992,10 @@ next(pipeline=ingress, table=11); - - next(pipeline=egress); - formats as next(pipeline=egress, table=11); -- encodes as resubmit(,51) -+ encodes as resubmit(,53) - - next(pipeline=egress, table=5); -- encodes as resubmit(,45) -+ encodes as resubmit(,47) - - next(table=10); - formats as next(10); -@@ -4414,24 +4414,13 @@ response=${sha}${lrpmac}08060001080006040002${lrpmac}${tpa}${sha}${spa} - echo $response >> 3.expected - - # First ensure basic flow contents are as we expect. --AT_CHECK([ovn-sbctl lflow-list lsw0 | grep 'reg0[\[14\]]' | sort | sed 's/table=../table=??/g' | sed 's/is_chassis_resident([[^)]]*)/is_chassis_resident("??")/g'], [0], [dnl -+AT_CHECK([ovn-sbctl lflow-list lsw0 | grep 'reg0[\[14\]]' | sort | sed 's/table=../table=??/g'], [0], [dnl - table=??(ls_in_check_port_sec), priority=70 , match=(inport == "lp-vtep"), action=(reg0[[14]] = 1; next(pipeline=ingress, table=??);) - table=??(ls_in_hairpin ), priority=1000 , match=(reg0[[14]] == 1), action=(next(pipeline=ingress, table=??);) -- table=??(ls_in_hairpin ), priority=2000 , match=(reg0[[14]] == 1 && (is_chassis_resident("??") || is_chassis_resident("??"))), action=(next;) -+ table=??(ls_in_hairpin ), priority=2000 , match=(reg0[[14]] == 1 && is_chassis_resident("cr-lrp1")), action=(next;) -+ table=??(ls_in_hairpin ), priority=2000 , match=(reg0[[14]] == 1 && is_chassis_resident("cr-lrp2")), action=(next;) - ]) - --# We've ensured that the expected hairpin flows are present --# and that the expected number of "is_chassis_resident" fields are in --# the flow. Now we need to ensure the contents are correct. --# Unfortunately, the order of the "is_chassis_resident" fields is --# unpredictable. Therefore we sort them so the order is predictable. --actual_chassis=$(ovn-sbctl lflow-list lsw0 | grep 'ls_in_hairpin' | grep 'priority=2000' | grep -o 'is_chassis_resident([[^)]]*)' | sort) -- --expected_chassis='is_chassis_resident("cr-lrp1") --is_chassis_resident("cr-lrp2")' -- --check test "$expected_chassis" = "$actual_chassis" -- - # dump information with counters - echo "------ OVN dump ------" - ovn-nbctl show -@@ -5055,6 +5044,7 @@ AT_CLEANUP - - OVN_FOR_EACH_NORTHD([ - AT_SETUP([IP relocation using GARP request]) -+AT_SKIP_IF([test $HAVE_SCAPY = no]) - ovn_start - - # Logical network: -@@ -5154,7 +5144,9 @@ done - test_ip() { - # This packet has bad checksums but logical L3 routing doesn't check. - local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 -- local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 -+ local packet=$(fmt_pkt "Ether(dst='${dst_mac}', src='${src_mac}')/ \ -+ IP(dst='${dst_ip}', src='${src_ip}')/ \ -+ UDP(sport=53, dport=4369)") - shift; shift; shift; shift; shift - hv=hv`vif_to_hv $inport` - as $hv ovs-appctl netdev-dummy/receive vif$inport $packet -@@ -5169,7 +5161,9 @@ test_ip() { - # Routing decrements TTL and updates source and dest MAC - # (and checksum). - out_lrp=`vif_to_lrp $outport` -- echo f000000000${outport}00000000ff0${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 -+ echo $(fmt_pkt "Ether(dst='f0:00:00:00:00:${outport}', src='00:00:00:00:ff:${out_lrp}')/ \ -+ IP(src='${src_ip}', dst='${dst_ip}', ttl=63)/ \ -+ UDP(sport=53, dport=4369)") - fi >> $outport.expected - done - } -@@ -5185,8 +5179,10 @@ test_ip() { - # SHA and REPLY_HA are each 12 hex digits. - # SPA and TPA are each 8 hex digits. - test_arp() { -- local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5 -- local request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} -+ local inport=$1 sha=$2 spa=$3 tpa=$3 -+ local request=$(fmt_pkt "Ether(dst='ff:ff:ff:ff:ff:ff', src='${sha}')/ \ -+ ARP(hwsrc='${sha}', hwdst='ff:ff:ff:ff:ff:ff', psrc='${spa}', pdst='${tpa}')") -+ - hv=hv`vif_to_hv $inport` - as $hv ovs-appctl netdev-dummy/receive vif$inport $request - -@@ -5199,53 +5195,72 @@ test_arp() { - echo $request >> $i$j$k.expected - fi - done -+} - -- # Expect to receive the reply, if any. -- if test X$reply_ha != X; then -- lrp=`vif_to_lrp $inport` -- local reply=${sha}00000000ff0${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa} -- echo $reply >> $inport.expected -- fi -+test_na() { -+ local inport=$1 sha=$2 spa=$3 -+ local request=$(fmt_pkt "Ether(dst='ff:ff:ff:ff:ff:ff', src='${sha}')/ \ -+ IPv6(dst='ff01::1', src='${spa}')/ \ -+ ICMPv6ND_NA(tgt='${spa}')") -+ -+ hv=hv`vif_to_hv $inport` -+ as $hv ovs-appctl netdev-dummy/receive vif$inport $request -+ -+ # Expect to receive the broadcast ARP on the other logical switch ports if -+ # IP address is not configured to the switch patch port. -+ local i=`vif_to_ls $inport` -+ local j -+ for j in 1 2; do -+ if test $i$j != $inport; then -+ echo $request >> $i$j$k.expected -+ fi -+ done - } - --# lp11 send GARP request to announce ownership of 192.168.1.100. -+# lp11 send GARP request to announce ownership of 192.168.1.100 and fe80::abcd:1. - --sha=f00000000011 --spa=`ip_to_hex 192 168 1 100` --tpa=$spa -+sha="f0:00:00:00:00:11" -+spa="192.168.1.100" -+spa6="fe80::abcd:1" - - # When always_learn_from_arp_request=false, the new mac-binding will not be learned - # through GARP request. - ovn-nbctl --wait=hv set logical_router lr0 options:always_learn_from_arp_request=false - --test_arp 11 $sha $spa $tpa -+test_arp 11 $sha $spa -+test_na 11 $sha $spa6 - sleep 1 --check_row_count MAC_Binding 0 ip="192.168.1.100" -+check_row_count MAC_Binding 0 ip="$spa" -+check_row_count MAC_Binding 0 ip=\"$spa6\" - - # When always_learn_from_arp_request=true, the new mac-binding will be learned. - ovn-nbctl --wait=hv set logical_router lr0 options:always_learn_from_arp_request=true - --test_arp 11 $sha $spa $tpa --OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding ip="192.168.1.100" | wc -l` -gt 0]) -+test_arp 11 $sha $spa -+test_na 11 $sha $spa6 -+wait_row_count MAC_Binding 1 ip="$spa" mac=\"$sha\" -+wait_row_count MAC_Binding 1 ip=\"$spa6\" mac=\"$sha\" - ovn-nbctl --wait=hv sync - - # Send an IP packet from lp21 to 192.168.1.100, which should go to lp11. - --smac=f00000000021 --dmac=00000000ff02 --sip=`ip_to_hex 192 168 2 11` --dip=`ip_to_hex 192 168 1 100` -+smac="f0:00:00:00:00:21" -+dmac="00:00:00:00:ff:02" -+sip="192.168.2.11" -+dip="192.168.1.100" - test_ip 21 $smac $dmac $sip $dip 11 - --# lp12 send GARP request to announce ownership of 192.168.1.100. -+# lp12 send GARP request to announce ownership of 192.168.1.100 and fe80::abcd:1. - - # Even when always_learn_from_arp_request=false, the existing mac-binding should be - # updated through GARP request. - ovn-nbctl --wait=hv set logical_router lr0 options:always_learn_from_arp_request=false - --sha=f00000000012 --test_arp 12 $sha $spa $tpa --wait_row_count MAC_Binding 1 ip="192.168.1.100" mac='"f0:00:00:00:00:12"' -+sha="f0:00:00:00:00:12" -+test_arp 12 $sha $spa -+test_na 11 $sha $spa6 -+wait_row_count MAC_Binding 1 ip="$spa" mac=\"$sha\" -+wait_row_count MAC_Binding 1 ip=\"$spa6\" mac=\"$sha\" - ovn-nbctl --wait=hv sync - # give to the hv the time to send queued ip packets - sleep 1 -@@ -5753,7 +5768,7 @@ check ovn-nbctl --wait=hv sync - packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac && eth.dst==$rp_ls1_mac && - ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip && ip4.dst==$ls2_lp1_ip && - udp && udp.src==53 && udp.dst==4369" --AT_CHECK([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - - echo "---------NB dump-----" -@@ -5803,7 +5818,7 @@ packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac && eth.dst==$rp_ls1_mac && - ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip && ip4.dst==$ls2_lp1_ip && - udp && udp.src==53 && udp.dst==4369" - --as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - # The 2nd packet sent shound not be received. - OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) - -@@ -7741,7 +7756,6 @@ ls3_p1_mac=00:00:00:01:02:05 - check ovn-nbctl --wait=hv lr-policy-add R1 10 "ip4.src==192.168.1.0/24 && ip4.dst==172.16.1.0/24" drop - - # Check logical flow --ovn-sbctl dump-flows > sbflows - AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "192.168.1.0" | wc -l], [0], [dnl - 1 - ]) -@@ -7751,15 +7765,12 @@ packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && - ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip && - udp && udp.src==53 && udp.dst==4369" - --as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Check if packet hit the drop policy --AT_CHECK([ovs-ofctl dump-flows br-int | \ -+OVS_WAIT_UNTIL([test "1" = "$(ovs-ofctl dump-flows br-int | \ - grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24 actions=drop" | \ -- grep "priority=10" | \ -- grep "n_packets=1" | wc -l], [0], [dnl --1 --]) -+ grep "priority=10" | grep "n_packets=1" -c)"]) - - # Expected to drop the packet. - $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" pbr-hv/vif2-tx.pcap > vif2.packets -@@ -7770,7 +7781,7 @@ AT_FAIL_IF([test "$rcvd_packet" != ""]) - check ovn-nbctl --wait=hv lr-policy-add R1 20 "ip4.src==192.168.1.0/24 && ip4.dst==172.16.1.0/24" allow - - # Check logical flow --AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "192.168.1.0" | wc -l], [0], [dnl -+AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "192.168.1.0" -c], [0], [dnl - 2 - ]) - -@@ -7778,15 +7789,12 @@ AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "192.168.1.0" | wc -l] - packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && - ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip && - udp && udp.src==53 && udp.dst==4369" --as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Check if packet hit the allow policy --sleep 1 --AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \ -- grep "192.168.1.0" | \ -- grep "priority=20" | wc -l], [0], [dnl --1 --]) -+OVS_WAIT_UNTIL([test "1" = "$(ovs-ofctl dump-flows br-int | \ -+ grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24" | \ -+ grep "priority=20" | grep "n_packets=1" -c)"]) - - # Expected packet has TTL decreased by 1 - expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac && -@@ -7802,7 +7810,7 @@ check ovn-nbctl --wait=hv lr-policy-add R1 30 "ip4.src==192.168.1.0/24 && ip4.ds - # Check logical flow - AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \ - grep "192.168.1.0" | \ -- grep "priority=30" | wc -l], [0], [dnl -+ grep "priority=30" -c], [0], [dnl - 1 - ]) - -@@ -7810,21 +7818,12 @@ AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \ - packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && - ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip && - udp && udp.src==53 && udp.dst==4369" --as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet" --sleep 1 -+OVS_WAIT_UNTIL([as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - --echo "southbound flows" --ovn-sbctl --ovs dump-flows > sbflows --AT_CAPTURE_FILE([sbflows]) --echo "ovs flows" --ovs-ofctl dump-flows br-int > brflows --AT_CAPTURE_FILE([brflows]) - # Check if packet hit the allow policy --AT_CHECK([grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24" brflows | \ -- grep "priority=30" | \ -- grep "n_packets=1" | wc -l], [0], [dnl --1 --]) -+OVS_WAIT_UNTIL([test "1" = "$(ovs-ofctl dump-flows br-int | \ -+ grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24" | \ -+ grep "priority=30" | grep "n_packets=1" -c)"]) - echo "packet hit reroute policy" - - # Expected packet has TTL decreased by 1 -@@ -7927,9 +7926,7 @@ ls3_p1_mac=00:00:00:01:02:05 - check ovn-nbctl --wait=sb lr-policy-add R1 10 "ip6.src==2001::/64 && ip6.dst==2002::/64" drop - - # Check logical flow --ovn-sbctl dump-flows > sbflows --AT_CAPTURE_FILE([sbflows]) --AT_CHECK([grep lr_in_policy sbflows | grep "2001" | wc -l], [0], [dnl -+AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001" -c], [0], [dnl - 1 - ]) - -@@ -7938,15 +7935,12 @@ packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && - ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip && - udp && udp.src==53 && udp.dst==4369" - --as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Check if packet hit the drop policy --AT_CHECK([ovs-ofctl dump-flows br-int | \ -+OVS_WAIT_UNTIL([test "1" = "$(ovs-ofctl dump-flows br-int | \ - grep "ipv6_src=2001::/64,ipv6_dst=2002::/64 actions=drop" | \ -- grep "priority=10" | \ -- grep "n_packets=1" | wc -l], [0], [dnl --1 --]) -+ grep "priority=10" | grep "n_packets=1" -c)"]) - - # Expected to drop the packet. - $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" pbr-hv/vif2-tx.pcap > vif2.packets -@@ -7956,9 +7950,7 @@ AT_FAIL_IF([test -s vif2.packets]) - check ovn-nbctl --wait=sb lr-policy-add R1 20 "ip6.src==2001::/64 && ip6.dst==2002::/64" allow - - # Check logical flow --ovn-sbctl dump-flows > sbflows2 --AT_CAPTURE_FILE([sbflows2]) --AT_CHECK([grep lr_in_policy sbflows2 | grep "2001" | wc -l], [0], [dnl -+AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001" -c], [0], [dnl - 2 - ]) - -@@ -7966,16 +7958,12 @@ AT_CHECK([grep lr_in_policy sbflows2 | grep "2001" | wc -l], [0], [dnl - packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && - ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip && - udp && udp.src==53 && udp.dst==4369" --as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Check if packet hit the allow policy --ovn-sbctl dump-flows > sbflows3 --AT_CAPTURE_FILE([sbflows3]) --AT_CHECK([grep lr_in_policy sbflows3 | \ -- grep "2001" | \ -- grep "priority=20" | wc -l], [0], [dnl --1 --]) -+OVS_WAIT_UNTIL([test "1" = "$(ovs-ofctl dump-flows br-int | \ -+ grep "ipv6_src=2001::/64,ipv6_dst=2002::/64" | \ -+ grep "priority=20" | grep "n_packets=1" -c)"]) - - # Expected packet has TTL decreased by 1 - expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac && -@@ -7989,11 +7977,9 @@ OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected]) - check ovn-nbctl --wait=sb lr-policy-add R1 30 "ip6.src==2001::/64 && ip6.dst==2002::/64" reroute 2003::2 - - # Check logical flow --ovn-sbctl dump-flows > sbflows4 --AT_CAPTURE_FILE([sbflows4]) --AT_CHECK([grep lr_in_policy sbflows4 | \ -+AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \ - grep "2001" | \ -- grep "priority=30" | wc -l], [0], [dnl -+ grep "priority=30" -c], [0], [dnl - 1 - ]) - -@@ -8001,19 +7987,12 @@ AT_CHECK([grep lr_in_policy sbflows4 | \ - packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac && - ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip && - udp && udp.src==53 && udp.dst==4369" --as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet" --sleep 1 -+OVS_WAIT_UNTIL([as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - --ovn-sbctl dump-flows > sbflows5 --ovs-ofctl dump-flows br-int > offlows5 --AT_CAPTURE_FILE([sbflows5]) --AT_CAPTURE_FILE([offlows5]) - # Check if packet hit the allow policy --AT_CHECK([grep "ipv6_src=2001::/64,ipv6_dst=2002::/64" offlows5 | \ -- grep "priority=30" | \ -- grep "n_packets=1" | wc -l], [0], [dnl --1 --]) -+OVS_WAIT_UNTIL([test "1" = "$(ovs-ofctl dump-flows br-int | \ -+ grep "ipv6_src=2001::/64,ipv6_dst=2002::/64" | \ -+ grep "priority=30" | grep "n_packets=1" -c)"]) - - # Expected packet has TTL decreased by 1 - expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac && -@@ -9531,73 +9510,73 @@ AT_CAPTURE_FILE([sbflows]) - packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac && - ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip && - tcp && tcp.flags==2 && tcp.src==4360 && tcp.dst==80" --as hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Send packet that should be dropped with logging in the ingress pipeline. - packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac && - ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip && - tcp && tcp.flags==2 && tcp.src==4361 && tcp.dst==81" --as hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Send packet that should be dropped without logging in the eggress pipeline. - packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac && - ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip && - tcp && tcp.flags==2 && tcp.src==4360 && tcp.dst==180" --as hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Send packet that should be dropped with logging in the egress pipeline. - packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac && - ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip && - tcp && tcp.flags==2 && tcp.src==4361 && tcp.dst==181" --as hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Send packet that should be allowed without logging. - packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac && - ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip && - tcp && tcp.flags==2 && tcp.src==4362 && tcp.dst==82" --as hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Send packet that should be allowed with logging. - packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac && - ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip && - tcp && tcp.flags==2 && tcp.src==4363 && tcp.dst==83" --as hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Send packet that should allow related flows without logging. - packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac && - ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip && - tcp && tcp.flags==2 && tcp.src==4364 && tcp.dst==84" --as hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Send packet that should allow related flows with logging. - packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac && - ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip && - tcp && tcp.flags==2 && tcp.src==4365 && tcp.dst==85" --as hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Send packet that should be rejected without logging in the ingress pipeline. - packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac && - ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip && - tcp && tcp.flags==2 && tcp.src==4366 && tcp.dst==86" --as hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Send packet that should be rejected with logging in the ingress pipeline. - packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac && - ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip && - tcp && tcp.flags==2 && tcp.src==4367 && tcp.dst==87" --as hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Send packet that should be rejected without logging in the egress pipeline. - packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac && - ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip && - tcp && tcp.flags==2 && tcp.src==4366 && tcp.dst==186" --as hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Send packet that should be rejected with logging in the egress pipeline. - packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac && - ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip && - tcp && tcp.flags==2 && tcp.src==4367 && tcp.dst==187" --as hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - OVS_WAIT_UNTIL([ test 8 = $(grep -c 'acl_log' hv/ovn-controller.log) ]) - -@@ -10206,14 +10185,21 @@ AT_CHECK([test ! -z $foo2_zoneid]) - bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2) - AT_CHECK([test ! -z $bar2_zoneid]) - --ovn-nbctl lsp-del bar2 -+# When a port is removed from a logical switch, the ct-zone is flushed, then -+# the ct-zone-id is removed from external_ids. This is done in two steps( -+# ct-zone-id is removed when the transaction flushing the ct_zone is complete). -+# ovn-nbctl --wait=hv sync does not take this into account, and hence we need -+# two "wait=hv" before we are sure that the ct-zone-id is removed from -+# external_ids. -+ovn-nbctl --wait=hv lsp-del bar2 - ovn-nbctl --wait=hv sync - - bar2_zoneid=$(as hv2 ovs-vsctl get bridge br-int external_ids:ct-zone-bar2) - AT_CHECK([test -z $bar2_zoneid]) - - # Add back bar2 --ovn-nbctl lsp-add bar bar2 vm2 1 \ -+# Same comment as above: two "wait=hv" are needed. -+ovn-nbctl --wait=hv lsp-add bar bar2 vm2 1 \ - -- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3" - wait_for_ports_up - ovn-nbctl --wait=hv sync -@@ -11214,7 +11200,7 @@ hv1_gw1_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=ov - hv1_gw2_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=ovn-gw2-0) - - OVS_WAIT_UNTIL([ -- test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=37 | grep -c "active_backup,ofport,members:$hv1_gw1_ofport,$hv1_gw2_ofport") -+ test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=39 | grep -c "active_backup,ofport,members:$hv1_gw1_ofport,$hv1_gw2_ofport") - ]) - - test_ip_packet() -@@ -11324,7 +11310,7 @@ AT_CHECK( - ]) - - OVS_WAIT_UNTIL([ -- test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=37 | grep -c "active_backup,ofport,members:$hv1_gw2_ofport,$hv1_gw1_ofport") -+ test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=39 | grep -c "active_backup,ofport,members:$hv1_gw2_ofport,$hv1_gw1_ofport") - ]) - - test_ip_packet gw2 gw1 0 -@@ -11502,7 +11488,7 @@ hv1_gw1_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=ov - hv1_gw2_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=ovn-gw2-0) - - OVS_WAIT_UNTIL([ -- test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=37 | grep -c "active_backup,ofport,members:$hv1_gw1_ofport,$hv1_gw2_ofport") -+ test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=39 | grep -c "active_backup,ofport,members:$hv1_gw1_ofport,$hv1_gw2_ofport") - ]) - - test_ip_packet() -@@ -11582,7 +11568,7 @@ AT_CHECK([ovn-nbctl --wait=hv \ - ]) - - OVS_WAIT_UNTIL([ -- test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=37 | grep -c "active_backup,ofport,members:$hv1_gw2_ofport,$hv1_gw1_ofport") -+ test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=39 | grep -c "active_backup,ofport,members:$hv1_gw2_ofport,$hv1_gw1_ofport") - ]) - - test_ip_packet gw2 gw1 -@@ -11748,12 +11734,12 @@ AT_CAPTURE_FILE([hv2flows]) - - AT_CHECK( - [# Check that redirect mapping is programmed only on hv2 -- grep table=38 hv1flows | grep =0x3,metadata=0x1 | wc -l -- grep table=38 hv2flows | grep =0x3,metadata=0x1 | grep load:0x2- | wc -l -+ grep table=40 hv1flows | grep =0x3,metadata=0x1 | wc -l -+ grep table=40 hv2flows | grep =0x3,metadata=0x1 | grep load:0x2- | wc -l - - # Check that hv1 sends chassisredirect port traffic to hv2 -- grep table=37 hv1flows | grep =0x3,metadata=0x1 | grep output | wc -l -- grep table=37 hv2flows | grep =0x3,metadata=0x1 | wc -l -+ grep table=39 hv1flows | grep =0x3,metadata=0x1 | grep output | wc -l -+ grep table=39 hv2flows | grep =0x3,metadata=0x1 | wc -l - - # Check that arp reply on distributed gateway port is only programmed on hv2 - grep arp hv1flows | grep load:0x2- | grep =0x2,metadata=0x1 | wc -l -@@ -12254,7 +12240,7 @@ nexthop_mac="f00000010204" - AS_BOX([Send ip packet from foo1 to 8.8.8.8]) - src_mac="f00000010203" - dst_mac="000001010203" --packet=${foo_mac}${foo1_mac}08004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000 -+packet=${foo_mac}${foo1_mac}080045000028000000004006a916${foo1_ip}${dst_ip}0035111112345678000000005002faf069450000 - - AS_BOX([Wait for GARPs announcing gw IP to arrive]) - OVS_WAIT_UNTIL([ -@@ -12265,15 +12251,12 @@ grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1 - AS_BOX([Verify VLAN tagged packet on bridge connecting hv1 and hv2]) - # VLAN tagged packet with router port(192.168.1.1) MAC as destination MAC - # is expected on bridge connecting hv1 and hv2 --expected=${foo_mac}${foo1_mac}8100000208004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000 -+expected=${foo_mac}${foo1_mac}81000002080045000028000000004006a916${foo1_ip}${dst_ip}0035111112345678000000005002faf069450000 - echo $expected > hv1-br-ex_n2.expected - - AS_BOX([Verify packet at outside1 i.e nexthop(172.16.1.1) port]) - # Packet to Expect at outside1 i.e nexthop(172.16.1.1) port. --# As connection tracking not enabled for this test, snat can't be done on the packet. --# We still see foo1 as the source ip address. But source mac(gateway MAC) and --# dest mac(nexthop mac) are properly configured. --expected=${nexthop_mac}${gw_mac}08004500001c000000003f110100${foo1_ip}${dst_ip}0035111100080000 -+expected=${nexthop_mac}${gw_mac}080045000028000000003f06beaa${gw_ip}${dst_ip}0035111112345678000000005002faf07dd90000 - echo $expected > hv3-vif1.expected - - check as hv1 ovs-appctl dpctl/del-flows -@@ -12284,8 +12267,8 @@ as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet - as hv1 ovs-appctl ofproto/trace br-int in_port=hv1-vif1 $packet - sleep 2 - --AS_BOX([On hv1, table 37 check that no packet goes via the tunnel port]) --OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=37 \ -+AS_BOX([On hv1, table 40 check that no packet goes via the tunnel port]) -+OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=39 \ - | grep "NXM_NX_TUN_ID" | grep -v n_packets=0 | wc -l], [0], [[0 - ]]) - -@@ -12304,7 +12287,7 @@ cat hv1-br-ex_n2.expected > expout - AT_CHECK([sort hv1-br-ex_n2], [0], [expout]) - - AS_BOX([Check expected packet on nexthop interface]) --$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv3/vif1-tx.pcap | grep ${foo1_ip}${dst_ip} | uniq > hv3-vif1 -+$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv3/vif1-tx.pcap | grep ${gw_ip}${dst_ip} | uniq > hv3-vif1 - cat hv3-vif1.expected > expout - AT_CHECK([sort hv3-vif1], [0], [expout]) - -@@ -13260,38 +13243,35 @@ echo $hv2_gw1_ofport - echo $hv2_gw2_ofport - - echo "--- hv1 ---" --as hv1 ovs-ofctl dump-flows br-int table=37 -+as hv1 ovs-ofctl dump-flows br-int table=39 - - echo "--- hv2 ---" --as hv2 ovs-ofctl dump-flows br-int table=37 -+as hv2 ovs-ofctl dump-flows br-int table=39 - - gw1_chassis=$(fetch_column Chassis _uuid name=gw1) - gw2_chassis=$(fetch_column Chassis _uuid name=gw2) - --OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=37 | \ --grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \ -+OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=39 | \ -+grep active_backup | grep members:$hv1_gw1_ofport,$hv1_gw2_ofport \ - | wc -l], [0], [1 - ]) - --OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=37 | \ --grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \ -+OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=39 | \ -+grep active_backup | grep members:$hv2_gw1_ofport,$hv2_gw2_ofport \ - | wc -l], [0], [1 - ]) - --# make sure that flows for handling the outside router port reside on gw1 --OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \ --grep 00:00:02:01:02:04 | wc -l], [0], [[1 -+# make sure that flows for handling the outside router port reside on gw1 through ls_in_l2_lkup table -+OVS_WAIT_FOR_OUTPUT([as gw1 ovs-ofctl dump-flows br-int table=33 | \ -+grep "dl_dst=00:00:02:01:02:04" | wc -l], [0], [[1 - ]]) --OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \ --grep 00:00:02:01:02:04 | wc -l], [0], [[0 -+OVS_WAIT_FOR_OUTPUT([as gw2 ovs-ofctl dump-flows br-int table=33 | \ -+grep "dl_dst=00:00:02:01:02:04" | wc -l], [0], [[0 - ]]) - --# make sure ARP responder flows for outside router port reside on gw1 too --OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \ --grep arp_tpa=192.168.0.101 | wc -l], [0], [[1 --]]) --OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep arp_tpa=192.168.0.101 | wc -l], [0], [[0 --]]) -+# make sure ARP responder flows for outside router port reside on gw1 too through ls_in_arp_rsp table -+OVS_WAIT_UNTIL([test `as gw1 ovs-ofctl dump-flows br-int table=27 | \ -+grep arp_tpa=192.168.0.101 | wc -l` -ge 1]) - - # check that the chassis redirect port has been claimed by the gw1 chassis - wait_row_count Port_Binding 1 logical_port=cr-outside chassis=$gw1_chassis -@@ -13314,13 +13294,13 @@ wait_for_ports_up - check ovn-nbctl --wait=hv sync - - # we make sure that the hypervisors noticed, and inverted the slave ports --OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=37 | \ --grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \ -+OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=39 | \ -+grep active_backup | grep members:$hv1_gw2_ofport,$hv1_gw1_ofport \ - | wc -l], [0], [1 - ]) - --OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=37 | \ --grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \ -+OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=39 | \ -+grep active_backup | grep members:$hv2_gw2_ofport,$hv2_gw1_ofport \ - | wc -l], [0], [1 - ]) - -@@ -13372,11 +13352,11 @@ AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv1-0],[0], - ]]) - - # make sure that flows for handling the outside router port reside on gw2 now --OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \ --grep 00:00:02:01:02:04 | wc -l], [0], [[1 -+OVS_WAIT_FOR_OUTPUT([as gw2 ovs-ofctl dump-flows br-int table=33 | \ -+grep "dl_dst=00:00:02:01:02:04" | wc -l], [0], [[1 - ]]) --OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \ --grep 00:00:02:01:02:04 | wc -l], [0], [[0 -+OVS_WAIT_FOR_OUTPUT([as gw1 ovs-ofctl dump-flows br-int table=33 | \ -+grep "dl_dst=00:00:02:01:02:04" | wc -l], [0], [[0 - ]]) - - # disconnect GW2 from the network, GW1 should take over -@@ -13386,12 +13366,12 @@ as main ovs-vsctl del-port n1 $port - - bfd_dump - --# make sure that flows for handling the outside router port reside on gw2 now --OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \ --grep 00:00:02:01:02:04 | wc -l], [0], [[1 -+# make sure that flows for handling the outside router port reside on gw1 now -+OVS_WAIT_FOR_OUTPUT([as gw1 ovs-ofctl dump-flows br-int table=33 | \ -+grep "dl_dst=00:00:02:01:02:04" | wc -l], [0], [[1 - ]]) --OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \ --grep 00:00:02:01:02:04 | wc -l], [0], [[0 -+OVS_WAIT_FOR_OUTPUT([as gw2 ovs-ofctl dump-flows br-int table=33 | \ -+grep "dl_dst=00:00:02:01:02:04" | wc -l], [0], [[0 - ]]) - - # check that the chassis redirect port has been reclaimed by the gw1 chassis -@@ -13470,45 +13450,16 @@ ovn-nbctl set Logical_Router_Port outside ha_chassis_group=$hagrp1_uuid - wait_row_count HA_Chassis_Group 1 - wait_row_count HA_Chassis 2 - --OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=37 | \ --grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \ --| wc -l], [0], [1 -+OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=39 | \ -+grep active_backup | grep members:$hv1_gw1_ofport,$hv1_gw2_ofport \ -+| wc -l], [0], [0 - ]) - --OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=37 | \ --grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \ --| wc -l], [0], [1 -+OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=39 | \ -+grep active_backup | grep members:$hv2_gw1_ofport,$hv2_gw2_ofport \ -+| wc -l], [0], [0 - ]) - --# make sure that flows for handling the outside router port reside on gw1 --OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \ --grep 00:00:02:01:02:04 | wc -l], [0], [[1 --]]) --OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \ --grep 00:00:02:01:02:04 | wc -l], [0], [[0 --]]) -- --# make sure ARP responder flows for outside router port reside on gw1 too --OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \ --grep arp_tpa=192.168.0.101 | wc -l], [0], [[1 --]]) --OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep arp_tpa=192.168.0.101 | wc -l], [0], [[0 --]]) -- --# check that the chassis redirect port has been claimed by the gw1 chassis --# --# XXX actually it doesn't happen, the test has always been wrong here --# because the following just checks that "wc -l" succeeds (and it always --# does): --# --# OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \ --# logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1 --# ]]) --# --# If it were correct, then the following would be a good substitute: --# --# wait_row_count Port_Binding 1 logical_port=cr-outside chassis=$gw1_chassis -- - # Re add the ovs ports. - for i in 1 2; do - as hv$i -@@ -13519,6 +13470,34 @@ for i in 1 2; do - ofport-request=1 - done - -+# Re-add gw2 -+as gw2 ovn_attach n1 br-phys 192.168.0.1 -+ -+OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=39 | \ -+grep active_backup | grep members:$hv1_gw1_ofport,$hv1_gw2_ofport \ -+| wc -l], [0], [1 -+]) -+ -+OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=39 | \ -+grep active_backup | grep members:$hv2_gw1_ofport,$hv2_gw2_ofport \ -+| wc -l], [0], [1 -+]) -+ -+# make sure that flows for handling the outside router port reside on gw1 -+OVS_WAIT_FOR_OUTPUT([as gw1 ovs-ofctl dump-flows br-int table=33 | \ -+grep "dl_dst=00:00:02:01:02:04" | wc -l], [0], [[1 -+]]) -+OVS_WAIT_FOR_OUTPUT([as gw2 ovs-ofctl dump-flows br-int table=33 | \ -+grep "dl_dst:00:00:02:01:02:04" | wc -l], [0], [[0 -+]]) -+ -+# make sure ARP responder flows for outside router port reside on gw1 too -+OVS_WAIT_UNTIL([test `as gw1 ovs-ofctl dump-flows br-int table=27 | \ -+grep arp_tpa=192.168.0.101 | wc -l` -ge 1 ]) -+ -+# check that the chassis redirect port has been claimed by the gw1 chassis -+wait_row_count Port_Binding 1 logical_port=cr-outside chassis=$gw1_chassis -+ - hv1_ch_uuid=$(fetch_column Chassis _uuid name=hv1) - hv2_ch_uuid=$(fetch_column Chassis _uuid name=hv2) - exp_ref_ch_list="$hv1_ch_uuid $hv2_ch_uuid" -@@ -13527,29 +13506,18 @@ wait_column "$exp_ref_ch_list" HA_Chassis_Group ref_chassis - # Increase the priority of gw2 - ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 40 - --OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=37 | \ --grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \ -+OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=39 | \ -+grep active_backup | grep members:$hv1_gw2_ofport,$hv1_gw1_ofport \ - | wc -l], [0], [1 - ]) - --OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=37 | \ --grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \ -+OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=39 | \ -+grep active_backup | grep members:$hv2_gw2_ofport,$hv2_gw1_ofport \ - | wc -l], [0], [1 - ]) - - # check that the chassis redirect port has been reclaimed by the gw2 chassis --# --# XXX actually it doesn't happen, the test has always been wrong here --# because the following just checks that "wc -l" succeeds (and it always --# does): --# --# OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \ --# logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1 --# ]]) --# --# If it were correct, then the following would be a good substitute: --# --# wait_row_count Port_Binding 1 logical_port=cr-outside chassis=$gw2_chassis -+wait_row_count Port_Binding 1 logical_port=cr-outside chassis=$gw2_chassis - - # check BFD enablement on tunnel ports from gw1 ######### - as gw1 -@@ -13588,11 +13556,11 @@ AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv1-0],[0], - ]]) - - # make sure that flows for handling the outside router port reside on gw2 now --OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \ --grep 00:00:02:01:02:04 | wc -l], [0], [[1 -+OVS_WAIT_FOR_OUTPUT([as gw2 ovs-ofctl dump-flows br-int table=33 | \ -+grep "dl_dst=00:00:02:01:02:04" | wc -l], [0], [[1 - ]]) --OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \ --grep 00:00:02:01:02:04 | wc -l], [0], [[0 -+OVS_WAIT_FOR_OUTPUT([as gw1 ovs-ofctl dump-flows br-int table=33 | \ -+grep "dl_dst=00:00:02:01:02:04" | wc -l], [0], [[0 - ]]) - - # disconnect GW2 from the network, GW1 should take over -@@ -13603,11 +13571,11 @@ as main ovs-vsctl del-port n1 $port - bfd_dump - - # make sure that flows for handling the outside router port reside on gw2 now --OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \ --grep 00:00:02:01:02:04 | wc -l], [0], [[1 -+OVS_WAIT_FOR_OUTPUT([as gw1 ovs-ofctl dump-flows br-int table=33 | \ -+grep "dl_dst=00:00:02:01:02:04" | wc -l], [0], [[1 - ]]) --OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \ --grep 00:00:02:01:02:04 | wc -l], [0], [[0 -+OVS_WAIT_FOR_OUTPUT([as gw2 ovs-ofctl dump-flows br-int table=33 | \ -+grep "dl_dst=00:00:02:01:02:04" | wc -l], [0], [[0 - ]]) - - # check that the chassis redirect port has been reclaimed by the gw1 chassis -@@ -13889,6 +13857,133 @@ OVN_CLEANUP([gw1],[gw2],[hv1]) - AT_CLEANUP - ]) - -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([allow IPv6 RA / NA / MLD by default]) -+AT_SKIP_IF([test $HAVE_SCAPY = no]) -+ovn_start -+net_add n1 -+sim_add hv1 -+as hv1 -+ovs-vsctl add-br br-phys -+ovn_attach n1 br-phys 192.168.0.1 -+ -+lsp_mac_prefix=50:64:00:00:00:0 -+lsp_ip_prefix=10.0.0. -+lsp_ip6_prefix=aef0::5264:00ff:fe00:000 -+ -+check ovn-nbctl ls-add ls0 -+for i in 1 2; do -+ check ovn-nbctl lsp-add ls0 lsp$i -+ check ovn-nbctl lsp-set-addresses lsp$i \ -+ "${lsp_mac_prefix}$i ${lsp_ip_prefix}$i ${lsp_ip6_prefix}$i" -+ -+ # forbid all traffic for the ports -+ check ovn-nbctl acl-add ls0 \ -+ from-lport 1000 "inport == \"lsp$i\"" drop -+ check ovn-nbctl --apply-after-lb acl-add ls0\ -+ from-lport 1000 "inport == \"lsp$i\"" drop -+ check ovn-nbctl acl-add ls0 \ -+ to-lport 1000 "outport == \"lsp$i\"" drop -+ -+ check ovs-vsctl -- add-port br-int vif$i -- \ -+ set interface vif$i external-ids:iface-id=lsp$i \ -+ options:tx_pcap=hv1/vif$i-tx.pcap \ -+ options:rxq_pcap=hv1/vif$i-rx.pcap -+ : > $i.expected -+done -+ -+router_mac=fa:16:3e:00:00:01 -+router_prefix=fdad:1234:5678:: -+router_ip=${router_prefix}1 -+check ovn-nbctl lr-add lr0 -+check ovn-nbctl lrp-add lr0 lrp0 ${router_mac} ${router_ip}/64 -+check ovn-nbctl set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode="slaac" -+check ovn-nbctl \ -+ -- lsp-add ls0 rp0 \ -+ -- set Logical_Switch_Port rp0 type=router \ -+ options:router-port=lrp0 \ -+ addresses='"${router_mac} ${router_ip}"' -+ -+wait_for_ports_up -+ -+test_ns_na() { -+ local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 -+ -+ packet=$(fmt_pkt " -+ Ether(dst='ff:ff:ff:ff:ff:ff', src='${src_mac}') / -+ IPv6(src='${src_ip}', dst='ff02::1:ff00:2') / -+ ICMPv6ND_NS(tgt='${dst_ip}') -+ ") -+ as hv1 ovs-appctl netdev-dummy/receive vif${inport} $packet -+ -+ expected_packet=$(fmt_pkt " -+ Ether(dst='${src_mac}', src='${dst_mac}') / -+ IPv6(src='${dst_ip}', dst='${src_ip}') / -+ ICMPv6ND_NA(tgt='${dst_ip}', R=0, S=1) / -+ ICMPv6NDOptDstLLAddr(lladdr='${dst_mac}') -+ ") -+ echo $expected_packet >> $inport.expected -+} -+ -+test_rs_ra() { -+ local inport=$1 src_mac=$2 src_ip=$3 -+ local router_mac=$4 router_prefix=$5 router_ip=$6 -+ -+ packet=$(fmt_pkt " -+ Ether(dst='ff:ff:ff:ff:ff:ff', src='${src_mac}') / -+ IPv6(src='${src_ip}', dst='ff02::2') / -+ ICMPv6ND_RS() -+ ") -+ as hv1 ovs-appctl netdev-dummy/receive vif${inport} $packet -+ -+ expected_packet=$(fmt_pkt " -+ Ether(dst='${src_mac}', src='${router_mac}') / -+ IPv6(src='${router_ip}', dst='${src_ip}') / -+ ICMPv6ND_RA(chlim=255, prf=0, routerlifetime=65535) / -+ ICMPv6NDOptSrcLLAddr(lladdr='${router_mac}') / -+ ICMPv6NDOptPrefixInfo(prefix='${router_prefix}') -+ ") -+ echo $expected_packet >> $inport.expected -+} -+ -+test_mldv2() { -+ local inport=$1 outport=$2 src_mac=$3 src_ip=$4 -+ -+ packet=$(fmt_pkt " -+ Ether(dst='ff:ff:ff:ff:ff:ff', src='${src_mac}') / -+ IPv6(src='${src_ip}', dst='ff02::2') / -+ ICMPv6MLQuery2() -+ ") -+ as hv1 ovs-appctl netdev-dummy/receive vif${inport} $packet -+ -+ expected_packet=$packet -+ echo $expected_packet >> $outport.expected -+} -+ -+src_mac=${lsp_mac_prefix}1 -+dst_mac=${lsp_mac_prefix}2 -+src_ip=${lsp_ip6_prefix}1 -+dst_ip=${lsp_ip6_prefix}2 -+ -+as hv1 -+test_ns_na 1 $src_mac $dst_mac $src_ip $dst_ip -+ -+as hv1 -+router_local_ip=fe80::f816:3eff:fe00:1 -+test_rs_ra 1 $src_mac $src_ip $router_mac $router_prefix $router_local_ip -+ -+as hv1 -+src_ip=fe80::1 -+test_mldv2 1 2 $src_mac $src_ip -+ -+OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected]) -+OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [2.expected]) -+ -+OVN_CLEANUP([hv1]) -+ -+AT_CLEANUP -+]) -+ - OVN_FOR_EACH_NORTHD([ - AT_SETUP([IPv6 Neighbor Solicitation for unknown MAC]) - AT_KEYWORDS([ovn-nd_ns for unknown mac]) -@@ -14162,10 +14257,12 @@ wait_column "$hv1_uuid" Port_Binding requested_chassis logical_port=lsp0 - wait_column "$hv2_uuid" Port_Binding additional_chassis logical_port=lsp0 - wait_column "$hv2_uuid" Port_Binding requested_additional_chassis logical_port=lsp0 - --# Check ovn-installed updated for main chassis -+# Check ovn-installed updated for both chassis - wait_for_ports_up --OVS_WAIT_UNTIL([test `as hv1 ovs-vsctl get Interface lsp0 external_ids:ovn-installed` = '"true"']) --OVS_WAIT_UNTIL([test x`as hv2 ovs-vsctl get Interface lsp0 external_ids:ovn-installed` = x]) -+ -+for hv in hv1 hv2; do -+ OVS_WAIT_UNTIL([test `as $hv ovs-vsctl get Interface lsp0 external_ids:ovn-installed` = '"true"']) -+done - - # Check that setting iface:encap-ip populates Port_Binding:additional_encap - wait_row_count Encap 2 chassis_name=hv1 -@@ -14192,7 +14289,7 @@ wait_column "$hv2_uuid" Port_Binding requested_chassis logical_port=lsp0 - wait_column "" Port_Binding additional_chassis logical_port=lsp0 - wait_column "" Port_Binding requested_additional_chassis logical_port=lsp0 - --# Check ovn-installed updated for main chassis and not for other chassis -+# Check ovn-installed updated for main chassis and removed from additional chassis - wait_for_ports_up - OVS_WAIT_UNTIL([test `as hv2 ovs-vsctl get Interface lsp0 external_ids:ovn-installed` = '"true"']) - OVS_WAIT_UNTIL([test x`as hv1 ovs-vsctl get Interface lsp0 external_ids:ovn-installed` = x]) -@@ -15071,6 +15168,327 @@ OVN_CLEANUP([hv1],[hv2],[hv3]) - AT_CLEANUP - ]) - -+m4_define([MULTICHASSIS_PATH_MTU_DISCOVERY_TEST], -+ [OVN_FOR_EACH_NORTHD([ -+ AT_SETUP([localnet connectivity with multiple requested-chassis, path mtu discovery (ip=$1, tunnel=$2, mtu=$3)]) -+ AT_KEYWORDS([multi-chassis]) -+ AT_SKIP_IF([test $HAVE_SCAPY = no]) -+ -+ ovn_start -+ -+ net_add n1 -+ for i in 1 2; do -+ sim_add hv$i -+ as hv$i -+ check ovs-vsctl add-br br-phys -+ if test "x$1" = "xipv6"; then -+ ovn_attach n1 br-phys fd00::$i 64 $2 -+ else -+ ovn_attach n1 br-phys 192.168.0.$i 24 $2 -+ fi -+ check ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys -+ done -+ -+ first_mac=00:00:00:00:00:01 -+ second_mac=00:00:00:00:00:02 -+ multi1_mac=00:00:00:00:00:f0 -+ multi2_mac=00:00:00:00:00:f1 -+ first_ip=10.0.0.1 -+ second_ip=10.0.0.2 -+ multi1_ip=10.0.0.10 -+ multi2_ip=10.0.0.20 -+ first_ip6=abcd::1 -+ second_ip6=abcd::2 -+ multi1_ip6=abcd::f0 -+ multi2_ip6=abcd::f1 -+ -+ check ovn-nbctl ls-add ls0 -+ check ovn-nbctl lsp-add ls0 first -+ check ovn-nbctl lsp-add ls0 second -+ check ovn-nbctl lsp-add ls0 multi1 -+ check ovn-nbctl lsp-add ls0 multi2 -+ check ovn-nbctl lsp-set-addresses first "${first_mac} ${first_ip} ${first_ip6}" -+ check ovn-nbctl lsp-set-addresses second "${second_mac} ${second_ip} ${second_ip6}" -+ check ovn-nbctl lsp-set-addresses multi1 "${multi1_mac} ${multi1_ip} ${multi1_ip6}" -+ check ovn-nbctl lsp-set-addresses multi2 "${multi2_mac} ${multi2_ip} ${multi2_ip6}" -+ -+ check ovn-nbctl lsp-add ls0 public -+ check ovn-nbctl lsp-set-type public localnet -+ check ovn-nbctl lsp-set-addresses public unknown -+ check ovn-nbctl lsp-set-options public network_name=phys -+ -+ check ovn-nbctl lsp-set-options first requested-chassis=hv1 -+ check ovn-nbctl lsp-set-options second requested-chassis=hv2 -+ check ovn-nbctl lsp-set-options multi1 requested-chassis=hv1,hv2 -+ check ovn-nbctl lsp-set-options multi2 requested-chassis=hv1,hv2 -+ -+ as hv1 check ovs-vsctl -- add-port br-int first -- \ -+ set Interface first external-ids:iface-id=first \ -+ options:tx_pcap=hv1/first-tx.pcap \ -+ options:rxq_pcap=hv1/first-rx.pcap \ -+ ofport-request=1 -+ as hv2 check ovs-vsctl -- add-port br-int second -- \ -+ set Interface second external-ids:iface-id=second \ -+ options:tx_pcap=hv2/second-tx.pcap \ -+ options:rxq_pcap=hv2/second-rx.pcap \ -+ ofport-request=2 -+ -+ # Create interfaces for multichassis ports on both hv1 and hv2 -+ for hv in hv1 hv2; do -+ for i in 1 2; do -+ as $hv check ovs-vsctl -- add-port br-int multi${i} -- \ -+ set Interface multi${i} external-ids:iface-id=multi${i} \ -+ options:tx_pcap=$hv/multi${i}-tx.pcap \ -+ options:rxq_pcap=$hv/multi${i}-rx.pcap \ -+ ofport-request=${i}00 -+ done -+ done -+ -+ send_ip_packet() { -+ local inport=${1} hv=${2} eth_src=${3} eth_dst=${4} ipv4_src=${5} ipv4_dst=${6} data=${7} fail=${8} mtu=${9:-$3} -+ packet=$(fmt_pkt " -+ Ether(dst='${eth_dst}', src='${eth_src}') / -+ IP(src='${ipv4_src}', dst='${ipv4_dst}') / -+ ICMP(type=8) / bytes.fromhex('${data}') -+ ") -+ as hv${hv} ovs-appctl netdev-dummy/receive ${inport} ${packet} -+ if [[ x"${fail}" != x0 ]]; then -+ original_ip_frame=$(fmt_pkt " -+ IP(src='${ipv4_src}', dst='${ipv4_dst}') / -+ ICMP(type=8) / bytes.fromhex('${data}') -+ ") -+ # IP(flags=2) means DF (Don't Fragment) = 1 -+ # ICMP(type=3, code=4) means Destination Unreachable, Fragmentation Needed -+ packet=$(fmt_pkt " -+ Ether(dst='${eth_src}', src='${eth_dst}') / -+ IP(src='${ipv4_dst}', dst='${ipv4_src}', ttl=255, flags=2, id=0) / -+ ICMP(type=3, code=4, nexthopmtu=${mtu}) / -+ bytes.fromhex('${original_ip_frame:0:$((534 * 2))}') -+ ") -+ fi -+ echo ${packet} -+ } -+ -+ send_ip6_packet() { -+ local inport=${1} hv=${2} eth_src=${3} eth_dst=${4} ipv6_src=${5} ipv6_dst=${6} data=${7} fail=${8} mtu=${9:-$3} -+ packet=$(fmt_pkt " -+ Ether(dst='${eth_dst}', src='${eth_src}') / -+ IPv6(src='${ipv6_src}', dst='${ipv6_dst}') / -+ ICMPv6EchoRequest() / bytes.fromhex('${data}') -+ ") -+ as hv${hv} ovs-appctl netdev-dummy/receive ${inport} ${packet} -+ if [[ x"${fail}" != x0 ]]; then -+ original_ip_frame=$(fmt_pkt " -+ IPv6(src='${ipv6_src}', dst='${ipv6_dst}') / -+ ICMPv6EchoRequest() / bytes.fromhex('${data}') -+ ") -+ packet=$(fmt_pkt " -+ Ether(dst='${eth_src}', src='${eth_dst}') / -+ IPv6(src='${ipv6_dst}', dst='${ipv6_src}', hlim=255) / -+ ICMPv6PacketTooBig(mtu=${mtu}) / -+ bytes.fromhex('${original_ip_frame:0:$((1218 * 2))}') -+ ") -+ fi -+ echo ${packet} -+ } -+ -+ reset_env() { -+ for port in first multi1 multi2; do -+ as hv1 reset_pcap_file $port hv1/$port -+ done -+ for port in second multi1 multi2; do -+ as hv2 reset_pcap_file $port hv2/$port -+ done -+ for port in hv1/multi1 hv2/multi1 hv1/multi2 hv2/multi2 hv1/first hv2/second; do -+ : > $port.expected -+ done -+ } -+ -+ check_pkts() { -+ for port in hv1/multi1 hv2/multi1 hv1/multi2 hv2/multi2 hv1/first hv2/second; do -+ OVN_CHECK_PACKETS_REMOVE_BROADCAST([${port}-tx.pcap], [${port}.expected]) -+ done -+ } -+ -+ payload() { -+ echo $(cat /dev/urandom | tr -cd 'a-f0-9' | head -c ${1}) -+ } -+ -+ wait_for_ports_up -+ OVN_POPULATE_ARP -+ -+ reset_env -+ -+ AS_BOX([Packets of proper size are delivered from multichassis to regular ports]) -+ -+ len=1000 -+ packet=$(send_ip_packet multi1 1 $multi1_mac $first_mac $multi1_ip $first_ip $(payload $len) 0) -+ echo $packet >> hv1/first.expected -+ -+ packet=$(send_ip_packet multi1 1 $multi1_mac $second_mac $multi1_ip $second_ip $(payload $len) 0) -+ echo $packet >> hv2/second.expected -+ -+ packet=$(send_ip6_packet multi1 1 $multi1_mac $first_mac $multi1_ip6 $first_ip6 $(payload $len) 0) -+ echo $packet >> hv1/first.expected -+ -+ packet=$(send_ip6_packet multi1 1 $multi1_mac $second_mac $multi1_ip6 $second_ip6 $(payload $len) 0) -+ echo $packet >> hv2/second.expected -+ -+ check_pkts -+ reset_env -+ -+ AS_BOX([Oversized packets are not delivered from multichassis to regular ports]) -+ -+ len=3000 -+ packet=$(send_ip_packet multi1 1 $multi1_mac $first_mac $multi1_ip $first_ip $(payload $len) 1) -+ echo $packet >> hv1/multi1.expected -+ -+ packet=$(send_ip_packet multi1 1 $multi1_mac $second_mac $multi1_ip $second_ip $(payload $len) 1) -+ echo $packet >> hv1/multi1.expected -+ -+ packet=$(send_ip6_packet multi1 1 $multi1_mac $first_mac $multi1_ip6 $first_ip6 $(payload $len) 1) -+ echo $packet >> hv1/multi1.expected -+ -+ packet=$(send_ip6_packet multi1 1 $multi1_mac $second_mac $multi1_ip6 $second_ip6 $(payload $len) 1) -+ echo $packet >> hv1/multi1.expected -+ -+ check_pkts -+ reset_env -+ -+ AS_BOX([Packets of proper size are delivered from regular to multichassis ports]) -+ -+ len=1000 -+ packet=$(send_ip_packet first 1 $first_mac $multi1_mac $first_ip $multi1_ip $(payload $len) 0) -+ echo $packet >> hv1/multi1.expected -+ echo $packet >> hv2/multi1.expected -+ -+ packet=$(send_ip_packet second 2 $second_mac $multi1_mac $second_ip $multi1_ip $(payload $len) 0) -+ echo $packet >> hv1/multi1.expected -+ echo $packet >> hv2/multi1.expected -+ -+ packet=$(send_ip6_packet first 1 $first_mac $multi1_mac $first_ip6 $multi1_ip6 $(payload $len) 0) -+ echo $packet >> hv1/multi1.expected -+ echo $packet >> hv2/multi1.expected -+ -+ packet=$(send_ip6_packet second 2 $second_mac $multi1_mac $second_ip6 $multi1_ip6 $(payload $len) 0) -+ echo $packet >> hv1/multi1.expected -+ echo $packet >> hv2/multi1.expected -+ -+ check_pkts -+ reset_env -+ -+ AS_BOX([Oversized packets are not delivered from regular to multichassis ports]) -+ -+ len=3000 -+ packet=$(send_ip_packet first 1 $first_mac $multi1_mac $first_ip $multi1_ip $(payload $len) 1) -+ echo $packet >> hv1/first.expected -+ -+ packet=$(send_ip_packet second 2 $second_mac $multi1_mac $second_ip $multi1_ip $(payload $len) 1) -+ echo $packet >> hv2/second.expected -+ -+ packet=$(send_ip6_packet first 1 $first_mac $multi1_mac $first_ip6 $multi1_ip6 $(payload $len) 1) -+ echo $packet >> hv1/first.expected -+ -+ packet=$(send_ip6_packet second 2 $second_mac $multi1_mac $second_ip6 $multi1_ip6 $(payload $len) 1) -+ echo $packet >> hv2/second.expected -+ -+ check_pkts -+ reset_env -+ -+ AS_BOX([Packets of proper size are delivered from multichassis to multichassis ports]) -+ -+ len=1000 -+ packet=$(send_ip_packet multi1 1 $multi1_mac $multi2_mac $multi1_ip $multi2_ip $(payload $len) 0) -+ echo $packet >> hv1/multi2.expected -+ echo $packet >> hv2/multi2.expected -+ -+ packet=$(send_ip6_packet multi1 1 $multi1_mac $multi2_mac $multi1_ip6 $multi2_ip6 $(payload $len) 0) -+ echo $packet >> hv1/multi2.expected -+ echo $packet >> hv2/multi2.expected -+ -+ check_pkts -+ reset_env -+ -+ AS_BOX([Oversized packets are not delivered from multichassis to multichassis ports]) -+ -+ len=3000 -+ packet=$(send_ip_packet multi1 1 $multi1_mac $multi2_mac $multi1_ip $multi2_ip $(payload $len) 1) -+ echo $packet >> hv1/multi1.expected -+ -+ packet=$(send_ip6_packet multi1 1 $multi1_mac $multi2_mac $multi1_ip6 $multi2_ip6 $(payload $len) 1) -+ echo $packet >> hv1/multi1.expected -+ -+ check_pkts -+ reset_env -+ -+ AS_BOX([MTU updates are honored in ICMP Path MTU calculation]) -+ -+ set_mtu() { -+ local hv=${1} iface=${2} new_mtu=${3} -+ -+ iface_uuid=$(as ${hv} ovs-vsctl --bare --columns _uuid find Interface name=${iface}) -+ check as ${hv} ovs-vsctl set interface ${iface_uuid} mtu_request=${new_mtu} -+ } -+ -+ set_mtu_for_all_ports() { -+ for port in multi1 multi2 first; do -+ set_mtu hv1 ${port} ${1} -+ done -+ for port in multi1 multi2 second; do -+ set_mtu hv2 ${port} ${1} -+ done -+ } -+ -+ initial_mtu=1500 # all interfaces are 1500 by default -+ new_mtu=1400 -+ set_mtu_for_all_ports ${new_mtu} -+ mtu_diff=$((${initial_mtu} - ${new_mtu})) -+ -+ len=3000 -+ expected_ip_mtu=$(($3 - ${mtu_diff})) -+ packet=$(send_ip_packet first 1 $first_mac $multi1_mac $first_ip $multi1_ip $(payload $len) 1 ${expected_ip_mtu}) -+ echo $packet >> hv1/first.expected -+ -+ packet=$(send_ip_packet second 2 $second_mac $multi1_mac $second_ip $multi1_ip $(payload $len) 1 ${expected_ip_mtu}) -+ echo $packet >> hv2/second.expected -+ -+ packet=$(send_ip6_packet first 1 $first_mac $multi1_mac $first_ip6 $multi1_ip6 $(payload $len) 1 ${expected_ip_mtu}) -+ echo $packet >> hv1/first.expected -+ -+ packet=$(send_ip6_packet second 2 $second_mac $multi1_mac $second_ip6 $multi1_ip6 $(payload $len) 1 ${expected_ip_mtu}) -+ echo $packet >> hv2/second.expected -+ -+ packet=$(send_ip_packet multi1 1 $multi1_mac $first_mac $multi1_ip $first_ip $(payload $len) 1 ${expected_ip_mtu}) -+ echo $packet >> hv1/multi1.expected -+ -+ packet=$(send_ip_packet multi1 1 $multi1_mac $second_mac $multi1_ip $second_ip $(payload $len) 1 ${expected_ip_mtu}) -+ echo $packet >> hv1/multi1.expected -+ -+ packet=$(send_ip6_packet multi1 1 $multi1_mac $first_mac $multi1_ip6 $first_ip6 $(payload $len) 1 ${expected_ip_mtu}) -+ echo $packet >> hv1/multi1.expected -+ -+ packet=$(send_ip6_packet multi1 1 $multi1_mac $second_mac $multi1_ip6 $second_ip6 $(payload $len) 1 ${expected_ip_mtu}) -+ echo $packet >> hv1/multi1.expected -+ -+ packet=$(send_ip_packet multi1 1 $multi1_mac $multi2_mac $multi1_ip $multi2_ip $(payload $len) 1 ${expected_ip_mtu}) -+ echo $packet >> hv1/multi1.expected -+ -+ packet=$(send_ip6_packet multi1 1 $multi1_mac $multi2_mac $multi1_ip6 $multi2_ip6 $(payload $len) 1 ${expected_ip_mtu}) -+ echo $packet >> hv1/multi1.expected -+ -+ check_pkts -+ -+ OVN_CLEANUP([hv1],[hv2]) -+ -+ AT_CLEANUP -+ ])]) -+ -+# NOTE(ihar) no STT variants because it's not supported by upstream kernels -+MULTICHASSIS_PATH_MTU_DISCOVERY_TEST([ipv4], [geneve], [1424]) -+MULTICHASSIS_PATH_MTU_DISCOVERY_TEST([ipv6], [geneve], [1404]) -+MULTICHASSIS_PATH_MTU_DISCOVERY_TEST([ipv4], [vxlan], [1432]) -+MULTICHASSIS_PATH_MTU_DISCOVERY_TEST([ipv6], [vxlan], [1412]) -+ - OVN_FOR_EACH_NORTHD([ - AT_SETUP([options:activation-strategy for logical port]) - AT_KEYWORDS([multi-chassis]) -@@ -16278,25 +16696,25 @@ sleep 2 - # Get total number of ipv4 packets that received on ovs - - # sender side --flow=$(as hv1 ovs-ofctl dump-flows br-int table=44 | grep priority=2002|grep ip,metadata=0x1) -+flow=$(as hv1 ovs-ofctl dump-flows br-int table=46 | grep priority=2002|grep ip,metadata=0x1) - n_pkts="$(echo $flow|awk -F',' '{ print $4 }'|awk -F'=' '{ print $2 }')" - check test $n_pkts -eq 1 - - # receiver side --flow=$(as hv2 ovs-ofctl dump-flows br-int table=44 | grep priority=2002|grep ip,metadata=0x1) -+flow=$(as hv2 ovs-ofctl dump-flows br-int table=46 | grep priority=2002|grep ip,metadata=0x1) - n_pkts="$(echo $flow|awk -F',' '{ print $4 }'|awk -F'=' '{ print $2 }')" - check test $n_pkts -eq 1 - - # Get total number of ipv6 packets that received on ovs - - # sender side --flow=$(as hv1 ovs-ofctl dump-flows br-int table=44 | grep priority=2002|grep ipv6,metadata=0x1) -+flow=$(as hv1 ovs-ofctl dump-flows br-int table=46 | grep priority=2002|grep ipv6,metadata=0x1) - n_pkts="$(echo $flow|awk -F',' '{ print $4 }'|awk -F'=' '{ print $2 }')" - check test $n_pkts -eq 1 - - - # receiver side --flow=$(as hv2 ovs-ofctl dump-flows br-int table=44 | grep priority=2002|grep ipv6,metadata=0x1) -+flow=$(as hv2 ovs-ofctl dump-flows br-int table=46 | grep priority=2002|grep ipv6,metadata=0x1) - n_pkts="$(echo $flow|awk -F',' '{ print $4 }'|awk -F'=' '{ print $2 }')" - check test $n_pkts -eq 1 - -@@ -17210,7 +17628,7 @@ test_icmp() { - icmp4.code==0" - shift; shift; shift; shift; shift; shift - hv=hv`vif_to_hv $inport` -- as $hv ovs-appctl -t ovn-controller inject-pkt "$packet" -+ OVS_WAIT_UNTIL([as $hv ovs-appctl -t ovn-controller inject-pkt "$packet"]) - in_ls=`vif_to_ls $inport` - in_lrp=`vif_to_lrp $inport` - for outport; do -@@ -17856,17 +18274,17 @@ check ovn-nbctl acl-add ls1 to-lport 3 'ip4.src==10.0.0.1' allow - check ovn-nbctl --wait=hv sync - - # Check OVS flows, the less restrictive flows should have been installed. --AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ -+AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | \ - grep "priority=1003" | \ - sed 's/conjunction([[^)]]*)/conjunction()/g' | \ - sed 's/conj_id=[[0-9]]*,/conj_id=xxx,/g' | sort], [0], [dnl -- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) -- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) -- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45) -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() -+ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) -+ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) -+ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,47) -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() - ]) - - # Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed. -@@ -17901,17 +18319,17 @@ check ovn-nbctl acl-del ls1 to-lport 3 'ip4.src==10.0.0.1 || ip4.src==10.0.0.1' - check ovn-nbctl --wait=hv sync - - # Check OVS flows, the second less restrictive allow ACL should have been installed. --AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ -+AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | \ - grep "priority=1003" | \ - sed 's/conjunction([[^)]]*)/conjunction()/g' | \ - sed 's/conj_id=[[0-9]]*,/conj_id=xxx,/g' | sort], [0], [dnl -- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) -- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) -- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45) -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() -+ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) -+ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) -+ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,47) -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() - ]) - - # Remove the less restrictive allow ACL. -@@ -17919,17 +18337,17 @@ check ovn-nbctl acl-del ls1 to-lport 3 'ip4.src==10.0.0.1' - check ovn-nbctl --wait=hv sync - - # Check OVS flows, the 10.0.0.1 conjunction should have been reinstalled. --AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ -+AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | \ - grep "priority=1003" | \ - sed 's/conjunction([[^)]]*)/conjunction()/g' | \ - sed 's/conj_id=[[0-9]]*,/conj_id=xxx,/g' | sort], [0], [dnl -- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) -- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) -- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(),conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() -+ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) -+ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) -+ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(),conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() - ]) - - # Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed. -@@ -17959,17 +18377,17 @@ check ovn-nbctl acl-add ls1 to-lport 3 'ip4.src==10.0.0.1' allow - check ovn-nbctl --wait=hv sync - - # Check OVS flows, the less restrictive flows should have been installed. --AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ -+AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | \ - grep "priority=1003" | \ - sed 's/conjunction([[^)]]*)/conjunction()/g' | \ - sed 's/conj_id=[[0-9]]*,/conj_id=xxx,/g' | sort], [0], [dnl -- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) -- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) -- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45) -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() -+ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) -+ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) -+ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,47) -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() - ]) - - # Add another ACL that overlaps with the existing less restrictive ones. -@@ -17980,20 +18398,20 @@ check ovn-nbctl --wait=hv sync - # with an additional conjunction action. - # - # New non-conjunctive flows should be added to match on 'udp'. --AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ -+AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | \ - grep "priority=1003" | \ - sed 's/conjunction([[^)]]*)/conjunction()/g' | \ - sed 's/conj_id=[[0-9]]*,/conj_id=xxx,/g' | sort], [0], [dnl -- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) -- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) -- table=44, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,45) -- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction(),conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction(),conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45) -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction(),conjunction() -- table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() -- table=44, priority=1003,udp,metadata=0x1 actions=resubmit(,45) -- table=44, priority=1003,udp6,metadata=0x1 actions=resubmit(,45) -+ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) -+ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) -+ table=46, priority=1003,conj_id=xxx,ip,metadata=0x1 actions=resubmit(,47) -+ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction(),conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction(),conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,47) -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction(),conjunction() -+ table=46, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() -+ table=46, priority=1003,udp,metadata=0x1 actions=resubmit(,47) -+ table=46, priority=1003,udp6,metadata=0x1 actions=resubmit(,47) - ]) - - OVN_CLEANUP([hv1]) -@@ -18048,17 +18466,17 @@ check ovn-nbctl acl-add pg1 to-lport 100 'outport == @pg1 && ip4.src == $as2' al - - wait_for_ports_up - check ovn-nbctl --wait=hv sync --ovs-ofctl dump-flows br-int table=44 --AT_CHECK([test `ovs-ofctl dump-flows br-int table=44 | grep -c conj_id` = 2]) -+ovs-ofctl dump-flows br-int table=46 -+AT_CHECK([test `ovs-ofctl dump-flows br-int table=46 | grep -c conj_id` = 2]) - - echo ------- - # Add another address in as1, so that the 1st ACL will now generate 2 conjunctions. - ovn-nbctl set address_set as1 addresses="10.0.0.1,10.0.0.2" - check ovn-nbctl --wait=hv sync - --ovs-ofctl dump-flows br-int table=44 -+ovs-ofctl dump-flows br-int table=46 - # There should be 3 conjunctions in total (2 from 1st ACL + 1 from 2nd ACL) --AT_CHECK([test `ovs-ofctl dump-flows br-int table=44 | grep -c conj_id` = 3]) -+AT_CHECK([test `ovs-ofctl dump-flows br-int table=46 | grep -c conj_id` = 3]) - - OVN_CLEANUP([hv1]) - AT_CLEANUP -@@ -18276,7 +18694,7 @@ AT_SETUP([TTL exceeded]) - AT_KEYWORDS([ttl-exceeded]) - ovn_start - --# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST IPV4_ROUTER IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM -+# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST IPV4_ROUTER IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM SHOULD_REPLY - # - # Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv4 packet with - # ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified and TTL set to 1. -@@ -18292,6 +18710,7 @@ test_ip_packet() { - local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6 ip_router=$7 ip_chksum=$8 - local exp_ip_chksum=$9 exp_icmp_chksum=${10} - shift 10 -+ local should_reply=$1 - - local ip_ttl=01 - local packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst} -@@ -18300,27 +18719,31 @@ test_ip_packet() { - local icmp_type_code_response=0b00 - local icmp_data=00000000 - local reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data} -- local reply=${eth_src}${eth_dst}08004500003000004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload} -- echo $reply$orig_pkt_in_reply >> vif$inport.expected -+ if test $should_reply == yes; then -+ local reply=${eth_src}${eth_dst}08004500003000004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload} -+ echo $reply$orig_pkt_in_reply >> vif$inport.expected -+ fi - - as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet - } - --# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST IPV6_ROUTER EXP_ICMP_CHKSUM -+# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST IPV6_ROUTER EXP_ICMP_CHKSUM SHOULD_REPLY - # - # Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv6 - # packet with ETH_SRC, ETH_DST, IPV6_SRC and IPV6_DST as specified. - # IPV6_ROUTER and EXP_ICMP_CHKSUM are the source IP and checksum of the icmpv6 ttl exceeded - # packet sent by OVN logical router - test_ip6_packet() { -- local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8 -+ local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8 should_reply=$9 - shift 8 - - local ip6_hdr=6000000000151101${ipv6_src}${ipv6_dst} - local packet=${eth_dst}${eth_src}86dd${ip6_hdr}dbb8303900155bac6b646f65206676676e6d66720a - -- local reply=${eth_src}${eth_dst}86dd6000000000453afe${ipv6_router}${ipv6_src}0300${exp_icmp_chksum}00000000${ip6_hdr}dbb8303900155bac6b646f65206676676e6d66720a -- echo $reply >> vif$inport.expected -+ if test $should_reply == yes; then -+ local reply=${eth_src}${eth_dst}86dd6000000000453afe${ipv6_router}${ipv6_src}0300${exp_icmp_chksum}00000000${ip6_hdr}dbb8303900155bac6b646f65206676676e6d66720a -+ echo $reply >> vif$inport.expected -+ fi - - as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet - } -@@ -18343,6 +18766,8 @@ for i in 1 2; do - options:tx_pcap=hv$i/vif$i-tx.pcap \ - options:rxq_pcap=hv$i/vif$i-rx.pcap \ - ofport-request=$i -+ -+ ovs-appctl -t ovn-controller vlog/set file:dbg:pinctrl - done - - ovn-nbctl lr-add lr0 -@@ -18358,10 +18783,22 @@ OVN_POPULATE_ARP - wait_for_ports_up - ovn-nbctl --wait=hv sync - --test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 1 254) 0000 f87c ea96 --test_ip6_packet 1 1 000000000001 00000000ff01 20010db8000100000000000000000011 20010db8000200000000000000000011 20010db8000100000000000000000001 1c22 -+test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 1 254) 0000 f87c ea96 yes -+test_ip6_packet 1 1 000000000001 00000000ff01 20010db8000100000000000000000011 20010db8000200000000000000000011 20010db8000100000000000000000001 1c22 yes -+ -+# Should not send ICMP for multicast -+test_ip_packet 1 1 000000000001 01005e7f0001 $(ip_to_hex 192 168 1 1) $(ip_to_hex 239 255 0 1) $(ip_to_hex 192 168 1 254) 0000 000000000 no -+test_ip6_packet 1 1 000000000001 333300000001 20010db8000100000000000000000011 ff020000000000000000000000000001 20010db8000100000000000000000001 0000 no -+ - OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected]) - -+# Confirm from debug log that we only see 2 packet-ins (no packet-ins for -+# multicasts). This is necessary because not seeing ICMP messages doesn't -+# necessarily mean the packet-in didn't happen. It is possible that packet-in -+# is processed but the ICMP message got dropped. -+AT_CHECK([grep -c packet-in hv1/ovn-controller.log], [0], [2 -+]) -+ - OVN_CLEANUP([hv1], [hv2]) - AT_CLEANUP - ]) -@@ -18656,7 +19093,7 @@ packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac && eth.dst==$sw1_ro_mac && - udp && udp.src==53 && udp.dst==4369" - - # Start by Sending the packet and make sure it makes it there as expected --as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Expected packet has TTL decreased by 1 - expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac && -@@ -18670,7 +19107,7 @@ OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) - as hv2 ovs-appctl -t ovn-controller exit - - # Now send the packet again. This time, it should not arrive. --as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) - -@@ -19552,7 +19989,7 @@ packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac && eth.dst==$sw1_ro_mac && - udp && udp.src==53 && udp.dst==4369" - - # Start by Sending the packet and make sure it makes it there as expected --as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Expected packet has TTL decreased by 1 - expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac && -@@ -19566,7 +20003,7 @@ OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) - as hv2 ovs-appctl -t ovn-controller exit --restart - - # Now send the packet again. This time, it should still arrive --as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - cat expected expected > expected2 - -@@ -19705,7 +20142,7 @@ test_ip_packet_larger() { - # Set the packet length to 114. - pkt_len=0072 - packet=${dst_mac}${src_mac}08004500${pkt_len}000000004001c3dd -- orig_packet_l3=${src_ip}${dst_ip}0304fcfb00000000 -+ orig_packet_l3=${src_ip}${dst_ip}0800f7ff00000000 - orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 - orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 - orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 -@@ -19729,10 +20166,10 @@ test_ip_packet_larger() { - # Packet to expect at br-phys. - src_mac="000020201213" - dst_mac="00000012af11" -- src_ip=`ip_to_hex 10 0 0 3` -+ src_ip=`ip_to_hex 172 168 0 100` - dst_ip=`ip_to_hex 172 168 0 3` -- expected=${dst_mac}${src_mac}08004500${pkt_len}000000003f01c4dd -- expected=${expected}${src_ip}${dst_ip}0304fcfb00000000 -+ expected=${dst_mac}${src_mac}08004500${pkt_len}000000003f0121d4 -+ expected=${expected}${src_ip}${dst_ip}0800f7ff00000000 - expected=${expected}000000000000000000000000000000000000 - expected=${expected}000000000000000000000000000000000000 - expected=${expected}000000000000000000000000000000000000 -@@ -19793,7 +20230,7 @@ test_ip_packet_larger_ext() { - # Set the packet length to 114. - pkt_len=0072 - packet=${dst_mac}${src_mac}08004500${pkt_len}000000004001${checksum} -- orig_packet_l3=${src_ip}${dst_ip}0900000000000000 -+ orig_packet_l3=${src_ip}${dst_ip}0800f7ff00000000 - orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 - orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 - orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000 -@@ -19810,7 +20247,7 @@ test_ip_packet_larger_ext() { - dst_ip=`ip_to_hex 172 168 0 4` - # pkt len should be 146 (28 (icmp packet) + 118 (orig ip + payload)) - reply_pkt_len=008e -- ip_csum=f39b -+ ip_csum=$7 - icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe01${reply_checksum} - icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000$(printf "%04x" $mtu) - icmp_reply=${icmp_reply}4500${pkt_len}000000004001${checksum} -@@ -19985,10 +20422,10 @@ OVS_WAIT_FOR_OUTPUT([ - ]) - - AS_BOX([testing ingress traffic mtu 100 - IPv4]) --test_ip_packet_larger_ext 1 000020201213 $(ip_to_hex 172 168 0 100) 20cf 100 22b6 -+test_ip_packet_larger_ext 1 000020201213 $(ip_to_hex 172 168 0 100) 20d3 100 22b6 fc97 - - AS_BOX([testing ingress traffic mtu 100 - IPv4 FIP]) --test_ip_packet_larger_ext 2 f00000010204 $(ip_to_hex 172 168 0 110) 20c5 100 22ac -+test_ip_packet_larger_ext 2 f00000010204 $(ip_to_hex 172 168 0 110) 20c5 100 22ac fc9b - - AS_BOX([testing ingress traffic mtu 100 - IPv6]) - test_ip6_packet_larger_ext 1 000020201213 20000000000000000000000000000001 100 cc7a -@@ -20055,10 +20492,10 @@ OVS_WAIT_FOR_OUTPUT([ - ]) - - AS_BOX([testing ingress traffic mtu 100 for gw router - IPv4]) --test_ip_packet_larger_ext 1 000020201213 $(ip_to_hex 172 168 0 100) 20cf 100 22b6 -+test_ip_packet_larger_ext 1 000020201213 $(ip_to_hex 172 168 0 100) 20d3 100 22b6 fc97 - - AS_BOX([testing ingress traffic mtu 100 for gw router - IPv6]) --test_ip6_packet_larger_ext 1 000020201213 20000000000000000000000000000001 100 cc7a -+test_ip6_packet_larger_ext 1 000020201213 20000000000000000000000000000001 100 cc7a fc9b - - OVN_CLEANUP([hv1]) - AT_CLEANUP -@@ -21012,9 +21449,9 @@ check_virtual_offlows_present() { - lr0_dp_key=$(printf "%x" $(fetch_column Datapath_Binding tunnel_key external_ids:name=lr0)) - lr0_public_dp_key=$(printf "%x" $(fetch_column Port_Binding tunnel_key logical_port=lr0-public)) - -- AT_CHECK_UNQUOTED([as $hv ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | grep "priority=2000"], [0], [dnl -- table=44, priority=2000,ip,metadata=0x$sw0_dp_key actions=resubmit(,45) -- table=44, priority=2000,ipv6,metadata=0x$sw0_dp_key actions=resubmit(,45) -+ AT_CHECK_UNQUOTED([as $hv ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | grep "priority=2000"], [0], [dnl -+ table=46, priority=2000,ip,metadata=0x$sw0_dp_key actions=resubmit(,47) -+ table=46, priority=2000,ipv6,metadata=0x$sw0_dp_key actions=resubmit(,47) - ]) - - AT_CHECK_UNQUOTED([as $hv ovs-ofctl dump-flows br-int table=11 | ofctl_strip_all | \ -@@ -21025,7 +21462,7 @@ check_virtual_offlows_present() { - - check_virtual_offlows_not_present() { - hv=$1 -- AT_CHECK([as $hv ovs-ofctl dump-flows br-int table=45 | ofctl_strip_all | grep "priority=2000"], [1], [dnl -+ AT_CHECK([as $hv ovs-ofctl dump-flows br-int table=47 | ofctl_strip_all | grep "priority=2000"], [1], [dnl - ]) - - AT_CHECK([as $hv ovs-ofctl dump-flows br-int table=11 | ofctl_strip_all | \ -@@ -21116,7 +21553,7 @@ check_virtual_offlows_not_present hv2 - send_garp 1 1 $eth_src $eth_dst $spa $tpa - - OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ --logical_port=sw0-vir) = x$hv1_ch_uuid], [0], []) -+logical_port=sw0-vir) = x$hv1_ch_uuid]) - - AT_CHECK([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ - logical_port=sw0-vir) = xsw0-p1]) -@@ -21184,7 +21621,7 @@ tpa=$(ip_to_hex 10 0 0 10) - send_garp 1 2 $eth_src $eth_dst $spa $tpa - - OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ --logical_port=sw0-vir) = x$hv1_ch_uuid], [0], []) -+logical_port=sw0-vir) = x$hv1_ch_uuid]) - - OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ - logical_port=sw0-vir) = xsw0-p3]) -@@ -21217,7 +21654,7 @@ tpa=$(ip_to_hex 10 0 0 10) - send_garp 2 1 $eth_src $eth_dst $spa $tpa - - OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ --logical_port=sw0-vir) = x$hv2_ch_uuid], [0], []) -+logical_port=sw0-vir) = x$hv2_ch_uuid]) - - AT_CHECK([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ - logical_port=sw0-vir) = xsw0-p2]) -@@ -21249,7 +21686,7 @@ tpa=$(ip_to_hex 10 0 0 4) - send_arp_reply 1 1 $eth_src $eth_dst $spa $tpa - - OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ --logical_port=sw0-vir) = x$hv1_ch_uuid], [0], []) -+logical_port=sw0-vir) = x$hv1_ch_uuid]) - sleep 1 - - AT_CHECK([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ -@@ -21275,7 +21712,7 @@ check_virtual_offlows_not_present hv2 - as hv1 ovs-vsctl del-port hv1-vif1 - - OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ --logical_port=sw0-vir) = x], [0], []) -+logical_port=sw0-vir) = x]) - sleep 1 - - AT_CHECK([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ -@@ -21310,7 +21747,7 @@ send_arp_reply 2 1 $eth_src $eth_dst $spa $tpa - sleep 1 - - OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ --logical_port=sw0-vir) = x$hv2_ch_uuid], [0], []) -+logical_port=sw0-vir) = x$hv2_ch_uuid]) - sleep 1 - AT_CHECK([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ - logical_port=sw0-vir) = xsw0-p2]) -@@ -21335,7 +21772,7 @@ check_virtual_offlows_not_present hv1 - ovn-nbctl lsp-del sw0-p2 - - OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \ --logical_port=sw0-vir) = x], [0], []) -+logical_port=sw0-vir) = x]) - AT_CHECK([test x$(ovn-sbctl --bare --columns virtual_parent find port_binding \ - logical_port=sw0-vir) = x]) - -@@ -21516,7 +21953,7 @@ AT_CAPTURE_FILE([offlows]) - packet0="inport==\"sw0-p11\" && eth.src==00:00:00:00:00:11 && eth.dst==00:00:00:00:00:21 && - ip4 && ip.ttl==64 && ip4.src==192.168.1.11 && ip4.dst==192.168.1.100 && - tcp && tcp.src==10000 && tcp.dst==80" --as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet0" -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet0"]) - ovn-nbctl --wait=hv - - ovn-sbctl list controller_event > events -@@ -21545,7 +21982,7 @@ packet1="inport==\"sw1-p0\" && eth.src==00:00:00:00:00:33 && eth.dst==00:00:00:0 - ip4 && ip.ttl==64 && ip4.src==192.168.2.11 && ip4.dst==192.168.2.100 && - tcp && tcp.src==10000 && tcp.dst==80" - --as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet1" -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet1"]) - ovn-nbctl --wait=hv - ovn-sbctl list controller_event - uuid=$(ovn-sbctl list controller_event | awk '/_uuid/{print $3}') -@@ -21561,7 +21998,7 @@ packet2="inport==\"sw0-p11\" && eth.src==00:00:00:00:00:11 && eth.dst==00:00:00: - ip6 && ip.ttl==64 && ip6.src==2001::11 && ip6.dst==2001::10 && - tcp && tcp.src==10000 && tcp.dst==50051" - --as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet2" -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet2"]) - ovn-nbctl --wait=hv - ovn-sbctl list controller_event - uuid=$(ovn-sbctl list controller_event | awk '/_uuid/{print $3}') -@@ -23619,7 +24056,7 @@ m4_define([DVR_N_S_PING], - OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv4/vif-north-tx.pcap], [vif-north.expected]) - - # Confirm that packets did not go out via tunnel port. -- AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=38 | grep NXM_NX_TUN_METADATA0 | grep n_packets=0 | wc -l], [0], [[0 -+ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=39 | grep NXM_NX_TUN_METADATA0 | grep n_packets=0 | wc -l], [0], [[0 - ]]) - - # Confirm that packet went out via localnet port -@@ -23744,7 +24181,7 @@ send_garp 1 1 $eth_src $eth_dst $spa $tpa - - wait_row_count MAC_Binding 1 - --OVS_WAIT_UNTIL([ovn-sbctl --format=csv --bare --columns logical_port,ip,mac \ -+OVS_WAIT_FOR_OUTPUT([ovn-sbctl --format=csv --bare --columns logical_port,ip,mac \ - list mac_binding], [0], [lr0-sw0 - 10.0.0.30 - 50:54:00:00:00:03 -@@ -23791,7 +24228,7 @@ grep table_id=10 | wc -l`]) - - check_row_count MAC_Binding 1 - --OVS_WAIT_UNTIL([ovn-sbctl --format=csv --bare --columns logical_port,ip,mac \ -+OVS_WAIT_FOR_OUTPUT([ovn-sbctl --format=csv --bare --columns logical_port,ip,mac \ - list mac_binding], [0], [lr0-sw0 - 10.0.0.30 - 50:54:00:00:00:13 -@@ -23820,7 +24257,7 @@ OVS_WAIT_UNTIL( - | wc -l`] - ) - --OVS_WAIT_UNTIL([ovn-sbctl --format=csv --bare --columns logical_port,ip,mac \ -+OVS_WAIT_FOR_OUTPUT([ovn-sbctl --format=csv --bare --columns logical_port,ip,mac \ - find mac_binding ip=10.0.0.50], [0], [lr0-sw0 - 10.0.0.50 - 50:54:00:00:00:33 -@@ -24377,7 +24814,7 @@ AT_CAPTURE_FILE([sbflows2]) - OVS_WAIT_FOR_OUTPUT( - [ovn-sbctl dump-flows > sbflows2 - ovn-sbctl dump-flows lr0 | grep ct_lb_mark | grep priority=120 | sed 's/table=..//'], 0, -- [ (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80; hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");) -+ [ (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80; hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");) - ]) - - # get the svc monitor mac. -@@ -24419,8 +24856,7 @@ AT_CHECK( - AT_CAPTURE_FILE([sbflows4]) - ovn-sbctl dump-flows lr0 > sbflows4 - AT_CHECK([grep lr_in_dnat sbflows4 | grep priority=120 | sed 's/table=..//' | sort], [0], [dnl -- (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) -- (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && reg0 == 10.0.0.10 && tcp && reg9[[16..31]] == 80 && is_chassis_resident("cr-lr0-public")), action=(drop;) -+ (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(drop;) - ]) - - # Delete sw0-p1 -@@ -24576,7 +25012,7 @@ AT_CAPTURE_FILE([sbflows2]) - OVS_WAIT_FOR_OUTPUT( - [ovn-sbctl dump-flows > sbflows2 - ovn-sbctl dump-flows lr0 | grep ct_lb_mark | grep priority=120 | sed 's/table=..//'], 0, -- [ (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip6 && xxreg0 == 2001::a && tcp && reg9[[16..31]] == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=[[2001::3]]:80,[[2002::3]]:80; hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");) -+ [ (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip6 && ip6.dst == 2001::a && tcp && tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=[[2001::3]]:80,[[2002::3]]:80; hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");) - ]) - - # get the svc monitor mac. -@@ -24618,8 +25054,7 @@ AT_CHECK( - AT_CAPTURE_FILE([sbflows4]) - ovn-sbctl dump-flows lr0 > sbflows4 - AT_CHECK([grep lr_in_dnat sbflows4 | grep priority=120 | sed 's/table=..//' | sort], [0], [dnl -- (lr_in_dnat ), priority=120 , match=(ct.est && !ct.rel && ip6 && xxreg0 == 2001::a && tcp && reg9[[16..31]] == 80 && ct_mark.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;) -- (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip6 && xxreg0 == 2001::a && tcp && reg9[[16..31]] == 80 && is_chassis_resident("cr-lr0-public")), action=(drop;) -+ (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip6 && ip6.dst == 2001::a && tcp && tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(drop;) - ]) - - # Delete sw0-p1 -@@ -25447,7 +25882,7 @@ for s_az in $(seq 1 $n_az); do - udp && udp.src==53 && udp.dst==4369" - echo "sending: $packet" - AT_CHECK([ovn_trace --ovs "$packet" > ${s_az}-${d_az}-$i.ovn-trace]) -- AT_CHECK([ovs-appctl -t ovn-controller inject-pkt "$packet"]) -+ OVS_WAIT_UNTIL([ovs-appctl -t ovn-controller inject-pkt "$packet"]) - ovs_inport=$(ovs-vsctl --bare --columns=ofport find Interface external-ids:iface-id="$ovn_inport") - - ovs_packet=$(echo $packet | ovstest test-ovn expr-to-packets) -@@ -26002,7 +26437,7 @@ for i in $(seq 5001 5010); do - packet="inport==\"lsp11\" && eth.src==f0:00:00:00:01:11 && eth.dst==00:00:00:01:01:01 && - ip4 && ip.ttl==64 && ip4.src==192.168.1.11 && ip4.dst==10.0.0.123 && - tcp && tcp.src==$i && tcp.dst==80" -- AT_CHECK([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) -+ OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - for j in 1 2; do - # Assume all packets go to lsp2${j}. -@@ -26121,7 +26556,7 @@ wait_for_ports_up - # Test 1 - packet="inport==\"lsp11\" && eth.src==f0:00:00:00:01:11 && eth.dst==00:00:00:01:01:01 && - ip4 && ip.ttl==64 && ip4.src==192.168.1.11 && ip4.dst==2.2.2.2 && icmp" --AT_CHECK([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Assume no packets go neither to lsp21 nor to lsp22. - > expected_lsp21 -@@ -26151,7 +26586,7 @@ done - # Test 2 - packet="inport==\"lsp11\" && eth.src==f0:00:00:00:01:11 && eth.dst==00:00:00:01:01:01 && - ip4 && ip.ttl==64 && ip4.src==192.168.1.11 && ip4.dst==1.1.1.1 && icmp" --AT_CHECK([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Assume all packets go to lsp22. - exp_packet="eth.src==00:00:00:01:02:01 && eth.dst==f0:00:00:00:02:22 && -@@ -26181,7 +26616,7 @@ done - # Test 3 - packet="inport==\"lsp21\" && eth.src==f0:00:00:00:02:21 && eth.dst==00:00:00:01:02:01 && - ip4 && ip.ttl==64 && ip4.src==192.168.2.21 && ip4.dst==2.2.2.2 && icmp" --AT_CHECK([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Assume all packets go to lsp21. - exp_packet="eth.src==00:00:00:01:02:01 && eth.dst==f0:00:00:00:02:21 && -@@ -26278,7 +26713,7 @@ wait_for_ports_up - # test 1 - packet="inport==\"lsp11\" && eth.src==f0:00:00:00:01:11 && eth.dst==00:00:00:01:01:01 && - ip4 && ip.ttl==64 && ip4.src==192.168.1.11 && ip4.dst==192.168.2.21 && icmp" --AT_CHECK([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Assume all packets go to lsp21. - exp_packet="eth.src==00:00:00:01:02:01 && eth.dst==f0:00:00:00:02:21 && ip4 && -@@ -26312,7 +26747,7 @@ ovs-vsctl set interface hv1-vif2 options:tx_pcap=hv1/vif2-tx.pcap - # test 2 - packet="inport==\"lsp11\" && eth.src==f0:00:00:00:01:11 && eth.dst==00:00:00:01:01:01 && - ip4 && ip.ttl==64 && ip4.src==192.168.1.11 && ip4.dst==192.168.2.200 && icmp" --AT_CHECK([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Assume all packets go to lsp11. - exp_packet="eth.src==00:00:00:01:01:01 && eth.dst==f0:00:00:00:01:11 && ip4 && -@@ -26417,7 +26852,7 @@ for i in $(seq 1 2); do - packet="inport==\"lsp${i}1\" && eth.src==f0:00:00:00:0${i}:1${i} && - eth.dst==00:00:00:01:0${i}:01 && ip4 && ip.ttl==64 && - ip4.src==192.168.${i}.${i}1 && ip4.dst==10.0.0.1 && icmp" -- AT_CHECK([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) -+ OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Assume all packets go to lsp${di}1. - exp_packet="eth.src==00:00:00:01:0${di}:01 && eth.dst==f0:00:00:00:0${di}:1${di} && -@@ -26530,7 +26965,7 @@ for i in $(seq 1 2); do - packet="inport==\"lsp${i}1\" && eth.src==f0:00:00:00:0${i}:1${i} && - eth.dst==00:00:00:01:0${i}:01 && ip6 && ip.ttl==64 && - ip6.src==2001:db8:${i}::${i}1 && ip6.dst==2001:db8:2000::1 && icmp6" -- AT_CHECK([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) -+ OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Assume all packets go to lsp${di}1. - exp_packet="eth.src==00:00:00:01:0${di}:01 && eth.dst==f0:00:00:00:0${di}:1${di} && ip6 && -@@ -26650,7 +27085,7 @@ dst_ip=172.16.1.11 - packet="inport==\"lsp11\" && eth.src==$src_mac && eth.dst==$dst_mac && - ip4 && ip.ttl==64 && ip4.src==$src_ip && ip4.dst==$dst_ip && - udp && udp.src==53 && udp.dst==4369" --check as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Check if the packet hit the forwarding group policy - AT_CAPTURE_FILE([offlows2]) -@@ -27173,7 +27608,7 @@ ovn_attach n1 br-phys 192.168.0.1 - - # Chassis hv1 should add flows for the ls1 datapath in table 8 (ls_in_port_sec_l2). - dp_key=$(ovn-sbctl --bare --columns tunnel_key list Datapath_Binding ls1) --OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=8.*metadata=0x${dp_key}"], [0], [ignore]) -+OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=8.*metadata=0x${dp_key}"]) - - OVN_CLEANUP([hv1]) - AT_CLEANUP -@@ -27199,7 +27634,7 @@ ovs-vsctl add-br br-phys - ovn_attach n1 br-phys 192.168.0.1 - - # Port_Binding should be released. --OVS_WAIT_UNTIL([test 0 = $(ovn-sbctl show | grep Port_Binding -c)], [0]) -+OVS_WAIT_UNTIL([test 0 = $(ovn-sbctl show | grep Port_Binding -c)]) - - OVN_CLEANUP([hv1]) - AT_CLEANUP -@@ -27332,22 +27767,24 @@ sleep 5 - send_ipv4_pkt() { - local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 - local ip_src=$5 ip_dst=$6 -- packet=${eth_dst}${eth_src}08004500001c0000000040110000${ip_src}${ip_dst}0035111100080000 -+ local ip_cksum=$7 tcp_cksum=$8 -+ packet=${eth_dst}${eth_src}080045000028000000004006${ip_cksum}${ip_src}${ip_dst}0035111112345678000000005002faf0${tcp_cksum}0000 - tcpdump_hex $packet - as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet} - } - - send_icmp6_packet() { -- local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6 -+ local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6 tcp_cksum=$7 - -- local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst} -- local packet=${eth_dst}${eth_src}86dd${ip6_hdr}8000dcb662f00001 -+ local ip6_hdr=60000000001406ff${ipv6_src}${ipv6_dst} -+ local packet=${eth_dst}${eth_src}86dd${ip6_hdr}0035111112345678000000005002faf0${tcp_cksum}0000 - - as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet} - } - - send_ipv4_pkt hv1 hv1-vif1 505400000003 00000000ff01 \ -- $(ip_to_hex 10 0 0 3) $(ip_to_hex 172 168 0 120) -+ $(ip_to_hex 10 0 0 3) $(ip_to_hex 172 168 0 120) \ -+ c3ad 83dc - - AT_CAPTURE_FILE([offlows2]) - OVS_WAIT_UNTIL([ -@@ -27364,7 +27801,8 @@ AT_CHECK([ - - # Send the pkt from sw0-port2. Packet should not be marked. - send_ipv4_pkt hv1 hv1-vif2 505400000004 00000000ff01 \ -- $(ip_to_hex 10 0 0 4) $(ip_to_hex 172 168 0 120) -+ $(ip_to_hex 10 0 0 4) $(ip_to_hex 172 168 0 120) \ -+ c3ac 83db - - AT_CHECK([ - test 1 -eq $(as hv1 ovs-ofctl dump-flows br-phys table=0 | \ -@@ -27398,7 +27836,8 @@ AT_CHECK([ - - ovn-nbctl set logical_router_policy $pol1 options:pkt_mark=2 - send_ipv4_pkt hv1 hv1-vif1 505400000003 00000000ff01 \ -- $(ip_to_hex 10 0 0 3) $(ip_to_hex 172 168 0 120) -+ $(ip_to_hex 10 0 0 3) $(ip_to_hex 172 168 0 120) \ -+ c3ad 83dc - - OVS_WAIT_UNTIL([ - test 1 -eq $(as hv1 ovs-ofctl dump-flows br-int table=23 | \ -@@ -27431,7 +27870,8 @@ AT_CHECK([ - # Send with src ip 10.0.0.5. The reroute policy should be hit - # and the packet should be marked with 5. - send_ipv4_pkt hv1 hv1-vif1 505400000003 00000000ff01 \ -- $(ip_to_hex 10 0 0 5) $(ip_to_hex 172 168 0 120) -+ $(ip_to_hex 10 0 0 5) $(ip_to_hex 172 168 0 120) \ -+ c3ab 83da - - OVS_WAIT_UNTIL([ - test 1 -eq $(as hv1 ovs-ofctl dump-flows br-phys table=0 | \ -@@ -27443,7 +27883,7 @@ OVS_WAIT_UNTIL([ - src_ip6=aef00000000000000000000000000004 - dst_ip6=bef00000000000000000000000000004 - --send_icmp6_packet hv1 hv1-vif2 505400000004 00000000ff01 ${src_ip6} ${dst_ip6} -+send_icmp6_packet hv1 hv1-vif2 505400000004 00000000ff01 ${src_ip6} ${dst_ip6} cd16 - - OVS_WAIT_UNTIL([ - test 1 -eq $(as hv1 ovs-ofctl dump-flows br-phys table=0 | \ -@@ -27463,7 +27903,7 @@ AT_CHECK([ - src_ip6=aef00000000000000000000000000004 - dst_ip6=bef00000000000000000000000000005 - --send_icmp6_packet hv1 hv1-vif2 505400000004 00000000ff01 ${src_ip6} ${dst_ip6} -+send_icmp6_packet hv1 hv1-vif2 505400000004 00000000ff01 ${src_ip6} ${dst_ip6} cd15 - - OVS_WAIT_UNTIL([ - test 1 -eq $(as hv1 ovs-ofctl dump-flows br-phys table=0 | \ -@@ -27970,22 +28410,22 @@ AT_CHECK([test ! -z $p1_zoneid]) - p2_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-sw0-p2 | sed 's/"//g') - AT_CHECK([test ! -z $p2_zoneid]) - --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ - reg15=0x${p1_dpkey} | grep REG13 | wc -l) -eq 1]) - --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ - reg15=0x${p1_dpkey} | grep "load:0x${p1_zoneid}->NXM_NX_REG13" | wc -l) -eq 1]) - --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw1_dpkey},\ -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw1_dpkey},\ - reg15=0x${p2_dpkey} | grep REG13 | wc -l) -eq 1]) - --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw1_dpkey},\ -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw1_dpkey},\ - reg15=0x${p2_dpkey} | grep "load:0x${p2_zoneid}->NXM_NX_REG13" | wc -l) -eq 1]) - - ovs-vsctl set interface hv1-vif1 external_ids:iface-id=foo - OVS_WAIT_UNTIL([test x$(ovn-nbctl lsp-get-up sw0-p1) = xdown]) - --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ - reg15=0x${p1_dpkey} | grep REG13 | wc -l) -eq 0]) - - p1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-sw0-p1 | sed 's/"//g') -@@ -27997,16 +28437,16 @@ OVS_WAIT_UNTIL([test x$(ovn-nbctl lsp-get-up sw0-p1) = xup]) - p1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-sw0-p1 | sed 's/"//g') - AT_CHECK([test ! -z $p1_zoneid]) - --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ - reg15=0x${p1_dpkey} | grep REG13 | wc -l) -eq 1]) - --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ - reg15=0x${p1_dpkey} | grep "load:0x${p1_zoneid}->NXM_NX_REG13" | wc -l) -eq 1]) - - ovs-vsctl del-port hv1-vif2 - OVS_WAIT_UNTIL([test x$(ovn-nbctl lsp-get-up sw0-p2) = xdown]) - --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ - reg15=0x${p2_dpkey} | grep REG13 | wc -l) -eq 0]) - - p2_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-sw0-p2 | sed 's/"//g') -@@ -28014,7 +28454,7 @@ AT_CHECK([test -z $p2_zoneid]) - - ovn-nbctl lsp-del sw0-p1 - --OVS_WAIT_UNTIL([test $(ovs-ofctl dump-flows br-int table=38,metadata=${sw0_dpkey},\ -+OVS_WAIT_UNTIL([test $(ovs-ofctl dump-flows br-int table=40,metadata=${sw0_dpkey},\ - reg15=0x${p1_dpkey} | grep REG13 | wc -l) -eq 0]) - - p1_zoneid=$(as hv1 ovs-vsctl get bridge br-int external_ids:ct-zone-sw0-p1 | sed 's/"//g') -@@ -28737,7 +29177,7 @@ src_mac="f00000000102" - dst_mac="000000000101" - src_ip=`ip_to_hex 10 0 1 2` - dst_ip=`ip_to_hex 10 0 1 1` --packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 -+packet=${dst_mac}${src_mac}08004500001c00000000401164cf${src_ip}${dst_ip}0035111100080000 - as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet - - # Even after configuring a router owned IP for SNAT, no packet-ins should -@@ -28763,7 +29203,7 @@ src_mac="f00000000202" - dst_mac="000000000201" - src_ip=`ip_to_hex 10 0 2 2` - dst_ip=`ip_to_hex 10 0 1 1` --packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 -+packet=${dst_mac}${src_mac}08004500001c00000000401163cf${src_ip}${dst_ip}0035111100080000 - as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet - - # Still no packet-ins should reach ovn-controller. -@@ -29548,7 +29988,9 @@ OVS_WAIT_UNTIL([test x$(ovn-nbctl lsp-get-up sw1-p1) = xup]) - - check ovn-nbctl lb-add lb-ipv4-tcp 88.88.88.88:8080 42.42.42.1:4041 tcp - check ovn-nbctl lb-add lb-ipv4-udp 88.88.88.88:4040 42.42.42.1:2021 udp -+check ovn-nbctl lb-add lb-ipv4 88.88.88.89 42.42.42.2 - check ovn-nbctl lb-add lb-ipv6-tcp [[8800::0088]]:8080 [[4200::1]]:4041 tcp -+check ovn-nbctl lb-add lb-ipv6 8800::0089 4200::2 - check ovn-nbctl --wait=hv lb-add lb-ipv6-udp [[8800::0088]]:4040 [[4200::1]]:2021 udp - - AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | grep -v NXST], [1], [dnl -@@ -29839,6 +30281,119 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep - - table=70, priority=100,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) - ]) - -+check ovn-nbctl --wait=hv ls-lb-add sw0 lb-ipv4 -+OVS_WAIT_UNTIL( -+ [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 7] -+) -+ -+OVS_WAIT_UNTIL( -+ [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 7] -+) -+ -+AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl -+ table=68, priority=100,ct_mark=0x2/0x2,ip,reg1=0x58585859,nw_src=42.42.42.2,nw_dst=42.42.42.2 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.89,NXM_OF_IP_PROTO[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+]) -+ -+AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl -+]) -+ -+AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl -+ table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) -+ table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) -+ table=70, priority=100,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) -+ table=70, priority=100,udp,reg1=0x58585858,reg2=0xfc8/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) -+ table=70, priority=100,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) -+ table=70, priority=90,ip,reg1=0x58585859 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.89)) -+]) -+ -+AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl -+ table=68, priority=100,ct_mark=0x2/0x2,ip,reg1=0x58585859,nw_src=42.42.42.2,nw_dst=42.42.42.2 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.89,NXM_OF_IP_PROTO[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+]) -+ -+AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl -+]) -+ -+AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl -+ table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) -+ table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) -+ table=70, priority=100,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) -+ table=70, priority=100,udp,reg1=0x58585858,reg2=0xfc8/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) -+ table=70, priority=100,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) -+ table=70, priority=90,ip,reg1=0x58585859 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.89)) -+]) -+ -+check ovn-nbctl --wait=hv ls-lb-add sw0 lb-ipv6 -+OVS_WAIT_UNTIL( -+ [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 8] -+) -+ -+OVS_WAIT_UNTIL( -+ [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 8] -+) -+ -+AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl -+ table=68, priority=100,ct_mark=0x2/0x2,ip,reg1=0x58585859,nw_src=42.42.42.2,nw_dst=42.42.42.2 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.89,NXM_OF_IP_PROTO[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,ipv6,reg4=0x88000000,reg5=0,reg6=0,reg7=0x89,ipv6_src=4200::2,ipv6_dst=4200::2 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::89,NXM_OF_IP_PROTO[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+]) -+ -+AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl -+]) -+ -+AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl -+ table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) -+ table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) -+ table=70, priority=100,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) -+ table=70, priority=100,udp,reg1=0x58585858,reg2=0xfc8/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) -+ table=70, priority=100,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) -+ table=70, priority=90,ip,reg1=0x58585859 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.89)) -+ table=70, priority=90,ipv6,reg4=0x88000000,reg5=0,reg6=0,reg7=0x89 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::89)) -+]) -+ -+AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl -+ table=68, priority=100,ct_mark=0x2/0x2,ip,reg1=0x58585859,nw_src=42.42.42.2,nw_dst=42.42.42.2 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.89,NXM_OF_IP_PROTO[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,ipv6,reg4=0x88000000,reg5=0,reg6=0,reg7=0x89,ipv6_src=4200::2,ipv6_dst=4200::2 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::89,NXM_OF_IP_PROTO[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+ table=68, priority=100,ct_mark=0x2/0x2,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) -+]) -+ -+AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl -+]) -+ -+AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl -+ table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) -+ table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) -+ table=70, priority=100,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) -+ table=70, priority=100,udp,reg1=0x58585858,reg2=0xfc8/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) -+ table=70, priority=100,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) -+ table=70, priority=90,ip,reg1=0x58585859 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.89)) -+ table=70, priority=90,ipv6,reg4=0x88000000,reg5=0,reg6=0,reg7=0x89 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::89)) -+]) -+ -+check ovn-nbctl --wait=hv ls-lb-del sw0 lb-ipv4 -+check ovn-nbctl --wait=hv ls-lb-del sw0 lb-ipv6 -+ - # Check backwards compatibility with ovn-northd versions that don't store the - # original destination tuple. - # -@@ -30354,46 +30909,46 @@ AT_CHECK([kill -0 $(cat hv1/ovn-controller.pid)]) - check ovn-nbctl --wait=hv sync - - # Check OVS flows are installed properly. --AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ -+AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=46 | ofctl_strip_all | \ - grep "priority=2002" | grep conjunction | \ - sed 's/conjunction([[^)]]*)/conjunction()/g' | \ - sed 's/reg15=0x[[1-9]]/reg15=0xN/g' | sort], [0], [dnl -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x10/0xfff0 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x100/0xff00 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x1000/0xf000 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2/0xfffe actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x20/0xffe0 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x200/0xfe00 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2000/0xe000 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4/0xfffc actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x40/0xffc0 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x400/0xfc00 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4000/0xc000 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8/0xfff8 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x80/0xff80 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x800/0xf800 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8000/0x8000 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=1 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x100/0x100,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x10/0xfff0 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x100/0xff00 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x1000/0xf000 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2/0xfffe actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x20/0xffe0 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x200/0xfe00 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2000/0xe000 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4/0xfffc actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x40/0xffc0 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x400/0xfc00 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4000/0xc000 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8/0xfff8 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x80/0xff80 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x800/0xf800 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8000/0x8000 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=1 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() -- table=44, priority=2002,udp,reg0=0x80/0x80,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x10/0xfff0 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x100/0xff00 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x1000/0xf000 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2/0xfffe actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x20/0xffe0 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x200/0xfe00 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2000/0xe000 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4/0xfffc actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x40/0xffc0 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x400/0xfc00 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4000/0xc000 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8/0xfff8 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x80/0xff80 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x800/0xf800 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8000/0x8000 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,metadata=0x1,nw_src=192.168.47.4,tp_dst=1 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x100/0x100,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x10/0xfff0 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x100/0xff00 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x1000/0xf000 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2/0xfffe actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x20/0xffe0 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x200/0xfe00 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x2000/0xe000 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4/0xfffc actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x40/0xffc0 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x400/0xfc00 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x4000/0xc000 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8/0xfff8 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x80/0xff80 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x800/0xf800 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=0x8000/0x8000 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,metadata=0x1,nw_src=192.168.47.4,tp_dst=1 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() -+ table=46, priority=2002,udp,reg0=0x80/0x80,reg15=0xN,metadata=0x1,nw_src=192.168.47.4 actions=conjunction() - ]) - - OVN_CLEANUP([hv1]) -@@ -31568,7 +32123,7 @@ ovs-vsctl add-port br-int lsp0-0 -- set interface lsp0-0 external_ids:iface-id=l - ovs-vsctl add-port br-int lsp0-1 -- set interface lsp0-1 external_ids:iface-id=lsp0-1 - - check ovn-nbctl --wait=hv sync --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 22]) -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 22]) - - # Save the current lflow_run counter - lflow_run=$(ovn-appctl -t ovn-controller coverage/read-counter lflow_run) -@@ -31578,7 +32133,7 @@ lflow_run=$(ovn-appctl -t ovn-controller coverage/read-counter lflow_run) - # 1. Remove half of the ports from pg1. The excepted conjunction flows should be: - # 2 + 10 = 12 - check ovn-nbctl --wait=hv pg-set-ports pg1 $(for i in 0 1 2 3 4; do for j in 0 1; do echo lsp${i}-${j}; done; done) --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 12]) -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 12]) - - # 2. Unbind lsp0-0. The there shouldn't be any conjunction flows because the - # port group const set should have only one member (lsp0-1). And the total -@@ -31586,25 +32141,25 @@ AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l - # 10. - ovs-vsctl del-port br-int lsp0-0 - check ovn-nbctl --wait=hv sync --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 0]) --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep 192.168 | wc -l) == 10]) -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 0]) -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep 192.168 | wc -l) == 10]) - - # 3. Rebind lsp0-0. The expected conjunction flows are back to 12. - ovs-vsctl add-port br-int lsp0-0 -- set interface lsp0-0 external_ids:iface-id=lsp0-0 - check ovn-nbctl --wait=hv sync --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 12]) -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 12]) - - # 4. Bind a lsp (lsp9-0) that doesn't belong to pg1, should not see any change. - ovs-vsctl add-port br-int lsp9-0 -- set interface lsp9-0 external_ids:iface-id=lsp9-0 - check ovn-nbctl --wait=hv sync --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 12]) -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 12]) - - # 5. Bind another 2 lsps (lsp1-0 lsp1-1) that belong to pg1 and on a different - # LS (ls1), should see conjunction flows doubled (12 x 2 = 24) - ovs-vsctl add-port br-int lsp1-0 -- set interface lsp1-0 external_ids:iface-id=lsp1-0 - ovs-vsctl add-port br-int lsp1-1 -- set interface lsp1-1 external_ids:iface-id=lsp1-1 - check ovn-nbctl --wait=hv sync --AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 24]) -+AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 24]) - - # 6. Simulate a SB port-group "del and add" notification to ovn-controller in the - # same IDL iteration. ovn-controller should still program the same flows. In -@@ -31629,7 +32184,7 @@ for i in $(seq 1 10); do - check ovn-nbctl --wait=hv sync - - # Finally check flow count is the same as before. -- AT_CHECK([test $(ovs-ofctl dump-flows br-int table=44 | grep conjunction | wc -l) == 24]) -+ AT_CHECK([test $(ovs-ofctl dump-flows br-int table=46 | grep conjunction | wc -l) == 24]) - done - - # Make sure all the above was performed with I-P (no recompute) -@@ -31743,7 +32298,7 @@ packet="inport==\"sw1-lp1\" && eth.src==00:00:04:01:02:03 && - ip4.src==10.0.0.100 && ip4.dst==20.0.0.200 && - udp && udp.src==53 && udp.dst==4369" - --as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Check if packet hit the drop rule - AT_CHECK([ovs-ofctl dump-flows br-int | grep "nw_dst=20.0.0.0/24" | \ -@@ -31770,7 +32325,7 @@ packet="inport==\"sw1-lp1\" && eth.src==00:00:04:01:02:03 && - ip4.src==10.0.0.100 && ip4.dst==20.0.0.200 && - udp && udp.src==53 && udp.dst==4369" - --as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"]) - - # Check if packet hit the drop rule - AT_CHECK([ovs-ofctl dump-flows br-int "nw_src=10.0.0.0/24" | \ -@@ -31857,7 +32412,7 @@ packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$bcast_mac && - arp.op==1 && arp.sha==$ls1_p1_mac && arp.spa==$ls1_p1_ip && - arp.tha==$bcast_mac && arp.tpa==$proxy_ip1" - --as hv1 ovn-appctl -t ovn-controller inject-pkt "$packet" -+OVS_WAIT_UNTIL([as hv1 ovn-appctl -t ovn-controller inject-pkt "$packet"]) - - as hv1 ovs-ofctl dump-flows br-int| grep 169.254.239.254 | grep priority=50 > debug1 - AT_CAPTURE_FILE([debug1]) -@@ -31916,8 +32471,8 @@ check ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip4.src == 10.0. - - # The first ACL should be programmed, but the second one shouldn't. - check ovn-nbctl --wait=hv sync --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.111], [0], [ignore]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.122], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.111], [0], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.122], [1], [ignore]) - - # Now create the lport lp2. - check ovn-nbctl lsp-add lsw0 lp2 \ -@@ -31925,12 +32480,12 @@ check ovn-nbctl lsp-add lsw0 lp2 \ - - check ovn-nbctl --wait=hv sync - # Now the second ACL should be programmed. --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.122], [0], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.122], [0], [ignore]) - - # Remove the lport lp2 again, the OVS flow for the second ACL should be - # removed. - check ovn-nbctl --wait=hv lsp-del lp2 --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.122], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.122], [1], [ignore]) - - # Test similar scenario but when the referenced lport is not bound locally. - -@@ -31944,8 +32499,8 @@ check ovn-nbctl acl-add lsw0 to-lport 1002 'inport == "lp4" && ip4.dst == 10.0.0 - - # The ACL for lp3 should be programmed, but the one for lp4 shouldn't. - check ovn-nbctl --wait=hv sync --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.133], [0], [ignore]) --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.144], [1], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.133], [0], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.144], [1], [ignore]) - - # Now create the lport lp4. - check ovn-nbctl lsp-add lsw0 lp4 \ -@@ -31953,7 +32508,7 @@ check ovn-nbctl lsp-add lsw0 lp4 \ - - # Now the ACL for lp4 should be programmed. - check ovn-nbctl --wait=hv sync --AT_CHECK([ovs-ofctl dump-flows br-int table=44 | grep 10.0.0.144], [0], [ignore]) -+AT_CHECK([ovs-ofctl dump-flows br-int table=46 | grep 10.0.0.144], [0], [ignore]) - - OVN_CLEANUP([hv1]) - AT_CLEANUP -@@ -32108,7 +32663,6 @@ ovn-nbctl lrp-set-gateway-chassis DR-S3 hv4 - - ovn-nbctl --wait=sb sync - OVN_POPULATE_ARP -- - vif_to_ls () { - case ${1} in dnl ( - vif?[[11]]) echo ls ;; dnl ( -@@ -32222,6 +32776,9 @@ echo "Send Dummy ARP" - sip=`ip_to_hex 172 16 1 10` - tip=`ip_to_hex 172 16 1 50` - test_arp vif-north1 f0f000000011 $sip $tip -+OVS_WAIT_UNTIL( -+ [test 1 = `as hv1 ovs-ofctl dump-flows br-int table=67 | grep dl_src=f0:f0:00:00:00:11 | wc -l`] -+) - - echo "Send traffic North to South" - sip=`ip_to_hex 172 16 1 10` -@@ -32242,6 +32799,9 @@ echo "Send Dummy ARP" - sip=`ip_to_hex 10 0 0 10` - tip=`ip_to_hex 10 0 0 50` - test_arp vif-north2 f0f000000022 $sip $tip -+OVS_WAIT_UNTIL( -+ [test 1 = `as hv1 ovs-ofctl dump-flows br-int table=67 | grep dl_src=f0:f0:00:00:00:22 | wc -l`] -+) - - echo "Send traffic South to North2" - sip=`ip_to_hex 20 0 0 10` -@@ -32255,6 +32815,9 @@ echo "Send Dummy ARP" - sip=`ip_to_hex 192 168 0 10` - tip=`ip_to_hex 192 168 0 50` - test_arp vif-north3 f0f000000033 $sip $tip -+OVS_WAIT_UNTIL( -+ [test 1 = `as hv1 ovs-ofctl dump-flows br-int table=67 | grep dl_src=f0:f0:00:00:00:33 | wc -l`] -+) - - echo "Send traffic South to North3" - sip=`ip_to_hex 20 0 0 10` -@@ -33384,7 +33947,7 @@ check ovn-nbctl --wait=hv sync - # Use constants so that if tables or registers change, this test can - # be updated easily. - DNAT_TABLE=15 --SNAT_TABLE=43 -+SNAT_TABLE=45 - DNAT_ZONE_REG="NXM_NX_REG11[[0..15]]" - SNAT_ZONE_REG="NXM_NX_REG12[[0..15]]" - -@@ -33929,6 +34492,7 @@ m4_define([MULTIPLE_OVS_INT], - ovs-ofctl dump-flows br-int | grep $cookie | - sed -e 's/duration=[[0-9.]]*s, //g' | - sed -e 's/idle_age=[[0-9]]*, //g' | -+ sed -e 's/hard_age=[[0-9]]*, //g' | - sed -e 's/n_packets=[[0-9]]*, //g' | - sed -e 's/n_bytes=[[0-9]]*, //g' - } -@@ -34926,7 +35490,8 @@ check ovs-vsctl add-port br-int p1 -- set interface p1 external_ids:iface-id=lsp - wait_for_ports_up - ovn-nbctl --wait=hv sync - --check ovn-nbctl lb-add lb1 "192.168.0.10" "192.168.10.10,192.168.10.20" -+check ovn-nbctl lb-add lb1 "192.168.0.10" "192.168.10.10,192.168.10.20" \ -+ -- set load_balancer lb1 options:ct_flush="true" - check ovn-nbctl ls-lb-add sw lb1 - - # Remove a single backend -@@ -34949,7 +35514,8 @@ AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.0.10:0, backend=192.168. - AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.0.10:0, backend=192.168.10.30:0, protocol=0" hv1/ovn-controller.log], [0]) - - # Check flush for LB with port and protocol --check ovn-nbctl lb-add lb1 "192.168.30.10:80" "192.168.40.10:8080,192.168.40.20:8090" udp -+check ovn-nbctl lb-add lb1 "192.168.30.10:80" "192.168.40.10:8080,192.168.40.20:8090" udp \ -+ -- set load_balancer lb1 options:ct_flush="true" - check ovn-nbctl ls-lb-add sw lb1 - check ovn-nbctl lb-del lb1 - check ovn-nbctl --wait=hv sync -@@ -34958,7 +35524,8 @@ AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.30.10:80, backend=192.16 - AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.30.10:80, backend=192.168.40.20:8090, protocol=17" hv1/ovn-controller.log], [0]) - - # Check recompute when LB is no longer local --check ovn-nbctl lb-add lb1 "192.168.50.10:80" "192.168.60.10:8080" -+check ovn-nbctl lb-add lb1 "192.168.50.10:80" "192.168.60.10:8080" \ -+ -- set load_balancer lb1 options:ct_flush="true" - check ovn-nbctl ls-lb-add sw lb1 - check ovs-vsctl remove interface p1 external_ids iface-id - check ovn-appctl inc-engine/recompute -@@ -34968,6 +35535,193 @@ AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.50.10:80, backend=192.16 - - AT_CHECK([test "$(grep -c "Flushing CT for 5-tuple" hv1/ovn-controller.log)" = "6"], [0]) - -+# Check if CT flush is disabled by default -+check ovn-nbctl lb-del lb1 -+check ovn-nbctl lb-add lb1 "192.168.70.10:80" "192.168.80.10:8080,192.168.90.10:8080" -+check ovn-nbctl ls-lb-add sw lb1 -+check ovs-vsctl set interface p1 external_ids:iface-id=lsp1 -+check ovn-nbctl --wait=hv sync -+ -+AT_CHECK([test "$(grep -c "Flushing CT for 5-tuple" hv1/ovn-controller.log)" = "6"], [0]) -+ -+# Remove one backend -+check ovn-nbctl --wait=hv set load_balancer lb1 vips='"192.168.70.10:80"="192.168.80.10:8080"' -+ -+AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.70.10:80, backend=192.168.90.10:8080, protocol=6" hv1/ovn-controller.log], [1]) -+AT_CHECK([test "$(grep -c "Flushing CT for 5-tuple" hv1/ovn-controller.log)" = "6"], [0]) -+ -+check ovn-nbctl --wait=hv lb-del lb1 -+AT_CHECK([grep -q "Flushing CT for 5-tuple: vip=192.168.70.10:80, backend=192.168.80.10:8080, protocol=6" hv1/ovn-controller.log], [1]) -+AT_CHECK([test "$(grep -c "Flushing CT for 5-tuple" hv1/ovn-controller.log)" = "6"], [0]) -+ -+OVN_CLEANUP([hv1]) -+AT_CLEANUP -+]) -+ -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([Re-create encap tunnels during integration bridge migration]) -+ovn_start -+net_add n1 -+ -+sim_add hv1 -+as hv1 -+ovs-vsctl add-br br-phys -+ovn_attach n1 br-phys 192.168.0.1 -+ -+sim_add hv2 -+as hv2 -+ovs-vsctl add-br br-phys -+ovn_attach n1 br-phys 192.168.0.2 -+ -+check ovn-nbctl --wait=hv sync -+ -+check_tunnel_port() { -+ local hv=$1 -+ local br=$2 -+ local id=$3 -+ -+ as $hv -+ OVS_WAIT_UNTIL([ -+ test "$(ovs-vsctl --format=table --no-headings find port external_ids:ovn-chassis-id="$id" | wc -l)" = "1" -+ ]) -+ local tunnel_id=$(ovs-vsctl --bare --columns _uuid find port external_ids:ovn-chassis-id="$id") -+ AT_CHECK([ovs-vsctl --bare --columns ports find bridge name="$br" | grep -q "$tunnel_id"]) -+} -+ -+# Check that both chassis have tunnel -+check_tunnel_port hv1 br-int hv2@192.168.0.2 -+check_tunnel_port hv2 br-int hv1@192.168.0.1 -+ -+# Stop ovn-controller on hv1 -+check as hv1 ovn-appctl -t ovn-controller exit --restart -+ -+# The tunnel should remain intact -+check_tunnel_port hv1 br-int hv2@192.168.0.2 -+ -+# Change the bridge to br-int1 on hv1 -+as hv1 -+check ovs-vsctl add-br br-int1 -+check ovs-vsctl set open . external_ids:ovn-bridge="br-int1" -+start_daemon ovn-controller --verbose="encaps:dbg" -+check ovn-nbctl --wait=hv sync -+ -+# Check that the tunnel was created on br-int1 instead -+check_tunnel_port hv1 br-int1 hv2@192.168.0.2 -+check grep -q "Clearing old tunnel port \"ovn-hv2-0\" (hv2@192.168.0.2) from bridge \"br-int\"" hv1/ovn-controller.log -+ -+# Change the bridge to br-int1 on hv2 -+as hv2 -+check ovn-appctl vlog/set encaps:dbg -+check ovs-vsctl add-br br-int1 -+check ovs-vsctl set open . external_ids:ovn-bridge="br-int1" -+check ovn-nbctl --wait=hv sync -+ -+ -+# Check that the tunnel was created on br-int1 instead -+check_tunnel_port hv2 br-int1 hv1@192.168.0.1 -+check grep -q "Clearing old tunnel port \"ovn-hv1-0\" (hv1@192.168.0.1) from bridge \"br-int\"" hv2/ovn-controller.log -+ -+# Stop ovn-controller on hv1 -+check as hv1 ovn-appctl -t ovn-controller exit --restart -+ -+# The tunnel should remain intact -+check_tunnel_port hv1 br-int1 hv2@192.168.0.2 -+prev_id=$(ovs-vsctl --bare --columns _uuid find port external_ids:ovn-chassis-id="hv2@192.168.0.2") -+ -+# Start the controller again -+start_daemon ovn-controller --verbose="encaps:dbg" -+check ovn-nbctl --wait=hv sync -+check_tunnel_port hv1 br-int1 hv2@192.168.0.2 -+current_id=$(ovs-vsctl --bare --columns _uuid find port external_ids:ovn-chassis-id="hv2@192.168.0.2") -+ -+# The tunnel should be the same after restart -+check test "$current_id" = "$prev_id" -+ -+OVN_CLEANUP([hv1],[hv2]) -+AT_CLEANUP -+]) -+ -+# NOTE: This test case runs two ovn-controllers inside the same sandbox (hv1). -+# Each controller uses a unique chassis name - hv1 and hv2 - and manage -+# different bridges with different ports. -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([Encaps tunnel cleanup does not interfere with multiple controller on the same host]) -+ovn_start -+net_add n1 -+ -+sim_add hv1 -+as hv1 -+ovs-vsctl add-br br-phys-1 -+ovn_attach n1 br-phys-1 192.168.0.1 24 -+ -+ -+# now start the second virtual controller -+ovs-vsctl add-br br-phys-2 -+ -+ -+# the file is read once at startup so it's safe to write it -+# here after the first ovn-controller has started -+echo hv2 > ${OVN_SYSCONFDIR}/system-id-override -+ -+# for some reason SSL ovsdb configuration overrides CLI, so -+# delete ssl config from ovsdb to give CLI arguments priority -+ovs-vsctl del-ssl -+ -+start_virtual_controller n1 br-phys-2 br-int-2 192.168.0.2 24 geneve,vxlan hv2 \ -+ --pidfile=${OVS_RUNDIR}/ovn-controller-2.pid \ -+ --log-file=${OVS_RUNDIR}/ovn-controller-2.log \ -+ -p $PKIDIR/testpki-hv2-privkey.pem \ -+ -c $PKIDIR/testpki-hv2-cert.pem \ -+ -C $PKIDIR/testpki-cacert.pem -+pidfile="$OVS_RUNDIR"/ovn-controller-2.pid -+on_exit "test -e \"$pidfile\" && kill \`cat \"$pidfile\"\`" -+ -+ovn-nbctl --wait=hv sync -+ -+check_tunnel_port() { -+ local hv=$1 -+ local br=$2 -+ local id=$3 -+ -+ as $hv -+ OVS_WAIT_UNTIL([ -+ test "$(ovs-vsctl --format=table --no-headings find port external_ids:ovn-chassis-id="$id" | wc -l)" = "1" -+ ]) -+ local tunnel_id=$(ovs-vsctl --bare --columns _uuid find port external_ids:ovn-chassis-id="$id") -+ AT_CHECK([ovs-vsctl --bare --columns ports find bridge name="$br" | grep -q "$tunnel_id"]) -+} -+ -+check_tunnel_port hv1 br-int hv2@192.168.0.2 -+check_tunnel_port hv1 br-int-2 hv1@192.168.0.1 -+prev_id1=$(ovs-vsctl --bare --columns _uuid find port external_ids:ovn-chassis-id="hv1@192.168.0.1") -+prev_id2=$(ovs-vsctl --bare --columns _uuid find port external_ids:ovn-chassis-id="hv2@192.168.0.2") -+ -+# The hv2 is running we can remove the override file -+rm -f ${OVN_SYSCONFDIR}/system-id-override -+ -+check ovn-appctl -t ovn-controller exit --restart -+ -+# for some reason SSL ovsdb configuration overrides CLI, so -+# delete ssl config from ovsdb to give CLI arguments priority -+ovs-vsctl del-ssl -+ -+start_daemon ovn-controller --verbose="encaps:dbg" \ -+ -p $PKIDIR/testpki-hv1-privkey.pem \ -+ -c $PKIDIR/testpki-hv1-cert.pem \ -+ -C $PKIDIR/testpki-cacert.pem -+ -+check ovn-nbctl --wait=hv sync -+ -+check_tunnel_port hv1 br-int hv2@192.168.0.2 -+check_tunnel_port hv1 br-int-2 hv1@192.168.0.1 -+current_id1=$(ovs-vsctl --bare --columns _uuid find port external_ids:ovn-chassis-id="hv1@192.168.0.1") -+current_id2=$(ovs-vsctl --bare --columns _uuid find port external_ids:ovn-chassis-id="hv2@192.168.0.2") -+ -+# Check that restart of hv1 ovn-controller did not interfere with hv2 -+AT_CHECK([grep -q "Clearing old tunnel port \"ovn0-hv1-0\" (hv1@192.168.0.1) from bridge \"br-int-2\"" hv1/ovn-controller.log], [1]) -+check test "$current_id1" = "$prev_id1" -+check test "$current_id2" = "$prev_id2" -+ - OVN_CLEANUP([hv1]) - AT_CLEANUP - ]) -diff --git a/tests/ovs-macros.at b/tests/ovs-macros.at -index 36b58b5ae..cc5f6e3b1 100644 ---- a/tests/ovs-macros.at -+++ b/tests/ovs-macros.at -@@ -256,6 +256,13 @@ ovs_wait () { - ovs_wait_failed - AT_FAIL_IF([:]) - } -+ -+check_ovs_wait_until_args() { -+ AT_FAIL_IF([test $1 -ge 3]) -+ dnl The second argument should not be a number (confused with AT_CHECK ?). -+ AT_FAIL_IF([test $1 -eq 2 && test "$2" -eq "$2" 2>/dev/null]) -+} -+ - OVS_END_SHELL_HELPERS - m4_define([OVS_WAIT], [dnl - ovs_wait_cond () { -@@ -276,7 +283,8 @@ dnl zero code within reasonable time limit, then - dnl the test fails. In that case, runs IF-FAILED - dnl before aborting. - m4_define([OVS_WAIT_UNTIL], -- [OVS_WAIT([$1], [$2], [AT_LINE], [until $1])]) -+ [check_ovs_wait_until_args "$#" "$2" -+ OVS_WAIT([$1], [$2], [AT_LINE], [until $1])]) - - dnl OVS_WAIT_FOR_OUTPUT(COMMAND, EXIT-STATUS, STDOUT, STDERR) - dnl OVS_WAIT_FOR_OUTPUT_UNQUOTED(COMMAND, EXIT-STATUS, STDOUT, STDERR) -diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at -index d65f359a6..b8c5ae9ad 100644 ---- a/tests/system-common-macros.at -+++ b/tests/system-common-macros.at -@@ -44,43 +44,8 @@ m4_define([NS_CHECK_EXEC], - # appropriate type, and allows additional arguments to be passed. - m4_define([ADD_BR], [ovs-vsctl _ADD_BR([$1]) -- $2]) - --# ADD_INT([port], [namespace], [ovs-br], [ip_addr] [ip6_addr]) --# --# Add an internal port to 'ovs-br', then shift it into 'namespace' and --# configure it with 'ip_addr' (specified in CIDR notation). --# Optionally add an ipv6 address --m4_define([ADD_INT], -- [ AT_CHECK([ovs-vsctl add-port $3 $1 -- set int $1 type=internal]) -- AT_CHECK([ip link set $1 netns $2]) -- NS_CHECK_EXEC([$2], [ip addr add $4 dev $1]) -- NS_CHECK_EXEC([$2], [ip link set dev $1 up]) -- if test -n "$5"; then -- NS_CHECK_EXEC([$2], [ip -6 addr add $5 dev $1]) -- fi -- ] --) -- --# NS_ADD_INT([port], [namespace], [ovs-br], [ip_addr] [mac_addr] [ip6_addr] [default_gw] [default_ipv6_gw]) --# Create a namespace --# Add an internal port to 'ovs-br', then shift it into 'namespace'. --# Configure it with 'ip_addr' (specified in CIDR notation) and ip6_addr. --# Set mac_addr --# Add default gw for ipv4 and ipv6 --m4_define([NS_ADD_INT], -- [ AT_CHECK([ovs-vsctl add-port $3 $1 -- set int $1 type=internal external_ids:iface-id=$1]) -- ADD_NAMESPACES($2) -- AT_CHECK([ip link set $1 netns $2]) -- NS_CHECK_EXEC([$2], [ip link set $1 address $5]) -- NS_CHECK_EXEC([$2], [ip link set dev $1 up]) -- NS_CHECK_EXEC([$2], [ip addr add $4 dev $1]) -- NS_CHECK_EXEC([$2], [ip addr add $6 dev $1]) -- NS_CHECK_EXEC([$2], [ip route add default via $7 dev $1]) -- NS_CHECK_EXEC([$2], [ip -6 route add default via $8 dev $1]) -- ] --) -- - # ADD_VETH([port], [namespace], [ovs-br], [ip_addr] [mac_addr], [gateway], --# [ip_addr_flags]) -+# [ip_addr_flags] [ip6_addr] [gateway6]) - # - # Add a pair of veth ports. 'port' will be added to name space 'namespace', - # and "ovs-'port'" will be added to ovs bridge 'ovs-br'. -@@ -108,6 +73,12 @@ m4_define([ADD_VETH], - if test -n "$6"; then - NS_CHECK_EXEC([$2], [ip route add default via $6]) - fi -+ if test -n "$8"; then -+ NS_CHECK_EXEC([$2], [ip addr add $8 dev $1]) -+ fi -+ if test -n "$9"; then -+ NS_CHECK_EXEC([$2], [ip route add default via $9]) -+ fi - on_exit "ip link del ovs-$1" - ] - ) -@@ -263,7 +234,7 @@ m4_define([STRIP_MONITOR_CSUM], [grep "csum:" | sed 's/csum:.*/csum: /']) - # and limit the output to the rows containing 'ip-addr'. - # - m4_define([FORMAT_CT], -- [[grep -F "dst=$1" | sed -e 's/port=[0-9]*/port=/g' -e 's/id=[0-9]*/id=/g' -e 's/state=[0-9_A-Z]*/state=/g' | sort | uniq]]) -+ [[grep -F "dst=$1," | sed -e 's/port=[0-9]*/port=/g' -e 's/id=[0-9]*/id=/g' -e 's/state=[0-9_A-Z]*/state=/g' | sort | uniq]]) - - # NETNS_DAEMONIZE([namespace], [command], [pidfile]) - # -diff --git a/tests/system-ovn-kmod.at b/tests/system-ovn-kmod.at -index dd4996041..a1aee3313 100644 ---- a/tests/system-ovn-kmod.at -+++ b/tests/system-ovn-kmod.at -@@ -172,7 +172,7 @@ ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"192.168.1.2:12345,192 - - ovn-nbctl list load_balancer - ovn-sbctl dump-flows R2 --OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=41 | \ -+OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=43 | \ - grep 'nat(src=20.0.0.2)']) - - dnl Test load-balancing that includes L4 ports in NAT. -@@ -215,3 +215,139 @@ as - OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d - /connection dropped.*/d"]) - AT_CLEANUP -+ -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([LB correctly de-fragments traffic]) -+AT_KEYWORDS([ovnlb]) -+ -+CHECK_CONNTRACK() -+CHECK_CONNTRACK_NAT() -+AT_SKIP_IF([test $HAVE_SCAPY = no]) -+ -+ovn_start -+OVS_TRAFFIC_VSWITCHD_START() -+ADD_BR([br-int]) -+ADD_BR([br-ext]) -+ -+# Logical network: -+# 2 logical switches "public" (192.168.1.0/24) and "internal" (172.16.1.0/24) -+# connected to a router lr. -+# internal has a server. -+# client is connected through localnet. -+# -+# Load balancer for udp 192.168.1.20:4242 172.16.1.2 4242. -+ -+check ovs-ofctl add-flow br-ext action=normal -+# Set external-ids in br-int needed for ovn-controller -+check ovs-vsctl \ -+ -- set Open_vSwitch . external-ids:system-id=hv1 \ -+ -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ -+ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ -+ -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ -+ -- set bridge br-int fail-mode=secure other-config:disable-in-band=true \ -+ -- set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext -+ -+ -+# Start ovn-controller -+start_daemon ovn-controller -+ -+check ovn-nbctl lr-add lr -+check ovn-nbctl ls-add internal -+check ovn-nbctl ls-add public -+ -+check ovn-nbctl lrp-add lr lr-pub 00:00:01:01:02:03 192.168.1.1/24 -+check ovn-nbctl lsp-add public pub-lr -- set Logical_Switch_Port pub-lr \ -+ type=router options:router-port=lr-pub addresses=\"00:00:01:01:02:03\" -+ -+check ovn-nbctl lrp-add lr lr-internal 00:00:01:01:02:04 172.16.1.1/24 -+check ovn-nbctl lsp-add internal internal-lr -- set Logical_Switch_Port internal-lr \ -+ type=router options:router-port=lr-internal addresses=\"00:00:01:01:02:04\" -+ -+ovn-nbctl lsp-add public ln_port \ -+ -- lsp-set-addresses ln_port unknown \ -+ -- lsp-set-type ln_port localnet \ -+ -- lsp-set-options ln_port network_name=phynet -+ -+ADD_NAMESPACES(client) -+ADD_VETH(client, client, br-ext, "192.168.1.2/24", "f0:00:00:01:02:03", \ -+ "192.168.1.1") -+ -+ADD_NAMESPACES(server) -+ADD_VETH(server, server, br-int, "172.16.1.2/24", "f0:00:0f:01:02:03", \ -+ "172.16.1.1") -+check ovn-nbctl lsp-add internal server \ -+-- lsp-set-addresses server "f0:00:0f:01:02:03 172.16.1.2" -+ -+# Config OVN load-balancer with a VIP. -+check ovn-nbctl lb-add lb1 192.168.1.20:4242 172.16.1.2:4242 udp -+check ovn-nbctl lr-lb-add lr lb1 -+check ovn-nbctl set logical_router lr options:chassis=hv1 -+check ovn-nbctl set logical_router_port lr-internal options:gateway_mtu=800 -+ -+ovn-nbctl --wait=hv sync -+ -+NETNS_DAEMONIZE([server], [nc -l -u 172.16.1.2 4242 > /dev/null], [server.pid]) -+ -+# Collect ICMP packets on client side -+NETNS_DAEMONIZE([client], [tcpdump -l -U -i client -vnne \ -+icmp > client.pcap 2>client_err], [tcpdump0.pid]) -+OVS_WAIT_UNTIL([grep "listening" client_err]) -+ -+# Collect UDP packets on server side -+NETNS_DAEMONIZE([server], [tcpdump -l -U -i server -vnne \ -+'udp and ip[[6:2]] > 0 and not ip[[6]] = 64' > server.pcap 2>server_err], [tcpdump1.pid]) -+OVS_WAIT_UNTIL([grep "listening" server_err]) -+ -+check ip netns exec client python3 << EOF -+import os -+import socket -+import sys -+import time -+ -+FILE="client.pcap" -+ -+ -+def contains_string(file, str): -+ file = open(file, "r") -+ for line in file.readlines(): -+ if str in line: -+ return True -+ return False -+ -+ -+def need_frag_received(): -+ for _ in range(20): -+ if os.path.getsize(FILE) and contains_string(FILE, "need to frag"): -+ return True -+ time.sleep(0.5) -+ return False -+ -+ -+sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -+sock.sendto(b"x" * 1000, ("192.168.1.20", 4242)) -+if need_frag_received(): -+ sock.sendto(b"x" * 1000, ("192.168.1.20", 4242)) -+else: -+ print("Missing need frag") -+ sys.exit(1) -+EOF -+ -+OVS_WAIT_UNTIL([test "$(cat server.pcap | wc -l)" = "4"]) -+ -+ -+OVS_APP_EXIT_AND_WAIT([ovn-controller]) -+ -+as ovn-sb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as ovn-nb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as northd -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) -+ -+as -+OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -+/connection dropped.*/d"]) -+AT_CLEANUP -+]) -diff --git a/tests/system-ovn.at b/tests/system-ovn.at -index 84a459d6a..0b6e9f602 100644 ---- a/tests/system-ovn.at -+++ b/tests/system-ovn.at -@@ -1569,7 +1569,6 @@ bar3_ct=$(ovs-appctl dpctl/dump-conntrack | grep 30.0.0.2 | grep 172.16.1.4 -c) - AT_CHECK([test $(ovs-appctl dpctl/dump-conntrack | grep 30.0.0.2 | grep 172.16.1 -c) -ne 0]) - - if [[ "$bar1_ct" == "20" ]]; then -- AT_CHECK([test $bar1_ct -eq 20]) - AT_CHECK([test $bar2_ct -eq 0]) - AT_CHECK([test $bar3_ct -eq 0]) - else -@@ -1577,17 +1576,15 @@ else - fi - - if [[ "$bar2_ct" == "20" ]]; then -- AT_CHECK([test $bar1_ct -eq 20]) -- AT_CHECK([test $bar2_ct -eq 0]) -+ AT_CHECK([test $bar1_ct -eq 0]) - AT_CHECK([test $bar3_ct -eq 0]) - else - AT_CHECK([test $bar2_ct -eq 0]) - fi - - if [[ "$bar3_ct" == "20" ]]; then -- AT_CHECK([test $bar1_ct -eq 20]) -+ AT_CHECK([test $bar1_ct -eq 0]) - AT_CHECK([test $bar2_ct -eq 0]) -- AT_CHECK([test $bar3_ct -eq 0]) - else - AT_CHECK([test $bar3_ct -eq 0]) - fi -@@ -2246,7 +2243,7 @@ ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"192.168.1.2:80,192.16 - - ovn-nbctl list load_balancer - ovn-sbctl dump-flows R2 --OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=43 | \ -+OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=45 | \ - grep 'nat(src=20.0.0.2)']) - - check ovs-appctl dpctl/flush-conntrack -@@ -2285,7 +2282,7 @@ ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"192.168.1.2:80,192.16 - - ovn-nbctl list load_balancer - ovn-sbctl dump-flows R2 --OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=43 | \ -+OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=45 | \ - grep 'nat(src=20.0.0.2)']) - - rm -f wget*.log -@@ -4850,9 +4847,9 @@ NS_CHECK_EXEC([lsp], [tcpdump -l -nn -c 3 -i lsp ${filter} > lsp.pcap 2>tcpdump_ - OVS_WAIT_UNTIL([grep "listening" tcpdump_err]) - - # Generate IPv4 UDP hairpin traffic. --NS_CHECK_EXEC([lsp], [echo a | nc -u 88.88.88.88 4040 &], [0]) --NS_CHECK_EXEC([lsp], [echo a | nc -u 88.88.88.89 4040 &], [0]) --NS_CHECK_EXEC([lsp], [echo a | nc -u 88.88.88.90 2021 &], [0]) -+NS_CHECK_EXEC([lsp], [echo a | nc -u 88.88.88.88 4040], [ignore], [ignore], [ignore]) -+NS_CHECK_EXEC([lsp], [echo a | nc -u 88.88.88.89 4040], [ignore], [ignore], [ignore]) -+NS_CHECK_EXEC([lsp], [echo a | nc -u 88.88.88.90 2021], [ignore], [ignore], [ignore]) - - # Check hairpin traffic. - OVS_WAIT_UNTIL([ -@@ -4949,9 +4946,9 @@ NS_CHECK_EXEC([lsp], [tcpdump -l -nn -c 3 -i lsp $filter > lsp.pcap 2>tcpdump_er - OVS_WAIT_UNTIL([grep "listening" tcpdump_err]) - - # Generate IPv6 UDP hairpin traffic. --NS_CHECK_EXEC([lsp], [echo a | nc -u 8800::0088 4040 &], [0]) --NS_CHECK_EXEC([lsp], [echo a | nc -u 8800::0089 4040 &], [0]) --NS_CHECK_EXEC([lsp], [echo a | nc -u 8800::0090 2021 &], [0]) -+NS_CHECK_EXEC([lsp], [echo a | nc -u 8800::0088 4040], [ignore], [ignore], [ignore]) -+NS_CHECK_EXEC([lsp], [echo a | nc -u 8800::0089 4040], [ignore], [ignore], [ignore]) -+NS_CHECK_EXEC([lsp], [echo a | nc -u 8800::0090 2021], [ignore], [ignore], [ignore]) - - # Check hairpin traffic. - OVS_WAIT_UNTIL([ -@@ -5084,7 +5081,7 @@ OVS_WAIT_UNTIL([ - ]) - - OVS_WAIT_UNTIL([ -- n_pkt=$(ovs-ofctl dump-flows br-int table=44 | grep -v n_packets=0 | \ -+ n_pkt=$(ovs-ofctl dump-flows br-int table=46 | grep -v n_packets=0 | \ - grep controller | grep tp_dst=84 -c) - test $n_pkt -eq 1 - ]) -@@ -5334,7 +5331,7 @@ OVS_WAIT_UNTIL([ - ]) - - OVS_WAIT_UNTIL([ -- n_pkt=$(ovs-ofctl dump-flows br-int table=44 | grep -v n_packets=0 | \ -+ n_pkt=$(ovs-ofctl dump-flows br-int table=46 | grep -v n_packets=0 | \ - grep controller | grep tp_dst=84 -c) - test $n_pkt -eq 1 - ]) -@@ -7190,7 +7187,7 @@ NS_EXEC([sw01], [tcpdump -l -n -i sw01 icmp -Q in > reject.pcap &]) - check ovn-nbctl --may-exist meter-add acl-meter drop 10 pktps 0 - ip netns exec sw01 scapy -H <<-EOF - p = IP(src="192.168.1.2", dst="192.168.1.1") / UDP(dport = 12345) / Raw(b"X"*64) --send (p, iface='sw01', loop = 0, verbose = 0, count = 100) -+send (p, iface='sw01', loop = 0, verbose = 0, count = 40) - EOF - - # 10pps -@@ -8482,11 +8479,18 @@ check ovn-nbctl lsp-set-addresses ln unknown - check ovn-nbctl lr-nat-add lr1 snat 172.16.1.10 192.168.1.0/24 - check ovn-nbctl lr-nat-add lr1 snat 1711::10 2001::/64 - --NS_ADD_INT(ls1p1, ls1p1, br-int, "192.168.1.1/24", "00:00:00:01:01:01", "2001::1/64", "192.168.1.254", "2001::a" ) --NS_ADD_INT(ls1p2, ls1p2, br-int, "192.168.1.2/24", "00:00:00:01:01:02", "2001::2/64", "192.168.1.254", "2001::a" ) -+ADD_NAMESPACES(ls1p1) -+ADD_VETH(ls1p1, ls1p1, br-int, "192.168.1.1/24", "00:00:00:01:01:01", \ -+ "192.168.1.254", , "2001::1/64", "2001::a") -+ -+ADD_NAMESPACES(ls1p2) -+ADD_VETH(ls1p2, ls1p2, br-int, "192.168.1.2/24", "00:00:00:01:01:02", \ -+ "192.168.1.254", , "2001::2/64", "2001::a") - - ADD_NAMESPACES(ext1) --ADD_INT(ext1, ext1, br0, 172.16.1.1/24, 1711::1/64) -+ADD_VETH(ext1, ext1, br0, "172.16.1.1/24", "00:ee:00:01:01:01", \ -+ "172.16.1.254", , "1711::1/64", "1711::a") -+ - check ovn-nbctl --wait=hv sync - wait_for_ports_up - OVS_WAIT_UNTIL([test "$(ip netns exec ls1p1 ip a | grep 2001::1 | grep tentative)" = ""]) -@@ -8548,25 +8552,17 @@ wait_igmp_flows_installed() - } - - ADD_NAMESPACES(vm1) --ADD_INT([vm1], [vm1], [br-int], [42.42.42.1/24]) --NS_CHECK_EXEC([vm1], [ip link set vm1 address 00:00:00:00:00:01], [0]) --NS_CHECK_EXEC([vm1], [ip route add default via 42.42.42.5], [0]) --check ovs-vsctl set Interface vm1 external_ids:iface-id=vm1 -+ADD_VETH(vm1, vm1, br-int, "42.42.42.1/24", "00:00:00:00:00:01", \ -+ "42.42.42.5") - - ADD_NAMESPACES(vm2) --ADD_INT([vm2], [vm2], [br-int], [42.42.42.2/24]) --NS_CHECK_EXEC([vm2], [ip link set vm2 address 00:00:00:00:00:02], [0]) --NS_CHECK_EXEC([vm2], [ip link set lo up], [0]) --check ovs-vsctl set Interface vm2 external_ids:iface-id=vm2 -+ADD_VETH(vm2, vm2, br-int, "42.42.42.2/24", "00:00:00:00:00:02") - - ADD_NAMESPACES(vm3) - NETNS_DAEMONIZE([vm3], [tcpdump -n -i any -nnleX > vm3.pcap 2>/dev/null], [tcpdump3.pid]) - --ADD_INT([vm3], [vm3], [br-int], [42.42.42.3/24]) --NS_CHECK_EXEC([vm3], [ip link set vm3 address 00:00:00:00:00:03], [0]) --NS_CHECK_EXEC([vm3], [ip link set lo up], [0]) --NS_CHECK_EXEC([vm3], [ip route add default via 42.42.42.5], [0]) --check ovs-vsctl set Interface vm3 external_ids:iface-id=vm3 -+ADD_VETH(vm3, vm3, br-int, "42.42.42.3/24", "00:00:00:00:00:03", \ -+ "42.42.42.5") - - NS_CHECK_EXEC([vm2], [sysctl -w net.ipv4.igmp_max_memberships=100], [ignore], [ignore]) - NS_CHECK_EXEC([vm3], [sysctl -w net.ipv4.igmp_max_memberships=100], [ignore], [ignore]) -@@ -9639,7 +9635,7 @@ start_daemon ovn-controller - # | - # VM2 ----+ - # --# Two templated load balancer applied on LS1 and GW-Router with -+# Four templated load balancer applied on LS1 and GW-Router with - # VM1 as backend. The VIPs should be accessible from both VM2 and VM3. - - check ovn-nbctl \ -@@ -9667,7 +9663,7 @@ check ovn-nbctl \ - # VIP=66.66.66.66:777 backends=42.42.42.2:4343 proto=udp - - AT_CHECK([ovn-nbctl -- create chassis_template_var chassis="hv1" \ -- variables="{vip=66.66.66.66,vport1=666,backends1=\"42.42.42.2:4242\",vport2=777,backends2=\"42.42.42.2:4343\"}"], -+ variables="{vip=66.66.66.66,vport1=666,backends1=\"42.42.42.2:4242\",vport2=777,backends2=\"42.42.42.2:4343\",vport3=888,vport4=999}"], - [0], [ignore]) - - check ovn-nbctl --template lb-add lb-test-tcp "^vip:^vport1" "^backends1" tcp \ -@@ -9678,6 +9674,18 @@ check ovn-nbctl --template lb-add lb-test-udp "^vip:^vport2" "^backends2" udp \ - -- ls-lb-add ls1 lb-test-udp \ - -- lr-lb-add rtr lb-test-udp - -+# Add a TCP template LB with explicit backends that eventually expands to: -+# VIP=66.66.66.66:888 backends=42.42.42.2:4242 proto=tcp -+# And a UDP template LB that eventually expands to: -+# VIP=66.66.66.66:999 backends=42.42.42.2:4343 proto=udp -+check ovn-nbctl --template lb-add lb-test-tcp2 "^vip:^vport3" "42.42.42.2:4242" tcp ipv4 \ -+ -- ls-lb-add ls1 lb-test-tcp2 \ -+ -- lr-lb-add rtr lb-test-tcp2 -+ -+check ovn-nbctl --template lb-add lb-test-udp2 "^vip:^vport4" "42.42.42.2:4343" udp ipv4 \ -+ -- ls-lb-add ls1 lb-test-udp2 \ -+ -- lr-lb-add rtr lb-test-udp2 -+ - ADD_NAMESPACES(vm1) - ADD_VETH(vm1, vm1, br-int, "42.42.42.2/24", "00:00:00:00:00:01", "42.42.42.1") - -@@ -9698,13 +9706,15 @@ name: 'backends2' value: '42.42.42.2:4343' - name: 'vip' value: '66.66.66.66' - name: 'vport1' value: '666' - name: 'vport2' value: '777' -+name: 'vport3' value: '888' -+name: 'vport4' value: '999' - ]) - - # Start IPv4 TCP server on vm1. - NETNS_DAEMONIZE([vm1], [nc -k -l 42.42.42.2 4242], [nc-vm1.pid]) - - NETNS_DAEMONIZE([vm1], -- [tcpdump -n -i vm1 -nnleX -c3 udp and dst 42.42.42.2 and dst port 4343 > vm1.pcap 2>/dev/null], -+ [tcpdump -n -i vm1 -nnleX -c6 udp and dst 42.42.42.2 and dst port 4343 > vm1.pcap 2>/dev/null], - [tcpdump1.pid]) - - # Make sure connecting to the VIP works (hairpin, via ls and via lr). -@@ -9712,13 +9722,21 @@ NS_CHECK_EXEC([vm1], [nc 66.66.66.66 666 -z], [0], [ignore], [ignore]) - NS_CHECK_EXEC([vm2], [nc 66.66.66.66 666 -z], [0], [ignore], [ignore]) - NS_CHECK_EXEC([vm3], [nc 66.66.66.66 666 -z], [0], [ignore], [ignore]) - --NS_CHECK_EXEC([vm1], [echo a | nc -u 66.66.66.66 777 &], [0]) --NS_CHECK_EXEC([vm2], [echo a | nc -u 66.66.66.66 777 &], [0]) --NS_CHECK_EXEC([vm3], [echo a | nc -u 66.66.66.66 777 &], [0]) -+NS_CHECK_EXEC([vm1], [echo a | nc -u 66.66.66.66 777], [ignore], [ignore], [ignore]) -+NS_CHECK_EXEC([vm2], [echo a | nc -u 66.66.66.66 777], [ignore], [ignore], [ignore]) -+NS_CHECK_EXEC([vm3], [echo a | nc -u 66.66.66.66 777], [ignore], [ignore], [ignore]) -+ -+NS_CHECK_EXEC([vm1], [nc 66.66.66.66 888 -z], [0], [ignore], [ignore]) -+NS_CHECK_EXEC([vm2], [nc 66.66.66.66 888 -z], [0], [ignore], [ignore]) -+NS_CHECK_EXEC([vm3], [nc 66.66.66.66 888 -z], [0], [ignore], [ignore]) -+ -+NS_CHECK_EXEC([vm1], [echo a | nc -u 66.66.66.66 999], [ignore], [ignore], [ignore]) -+NS_CHECK_EXEC([vm2], [echo a | nc -u 66.66.66.66 999], [ignore], [ignore], [ignore]) -+NS_CHECK_EXEC([vm3], [echo a | nc -u 66.66.66.66 999], [ignore], [ignore], [ignore]) - - OVS_WAIT_UNTIL([ - requests=`grep "UDP" -c vm1.pcap` -- test "${requests}" -ge "3" -+ test "${requests}" -ge "6" - ]) - - AT_CLEANUP -@@ -9753,7 +9771,7 @@ start_daemon ovn-controller - # | - # VM2 ----+ - # --# Two templated load balancer applied on LS1 and GW-Router with -+# Four templated load balancer applied on LS1 and GW-Router with - # VM1 as backend. The VIPs should be accessible from both VM2 and VM3. - - check ovn-nbctl \ -@@ -9781,7 +9799,7 @@ check ovn-nbctl \ - # VIP=[6666::1]:777 backends=[4242::2]:4343 proto=udp - - AT_CHECK([ovn-nbctl -- create chassis_template_var chassis="hv1" \ -- variables="{vip=\"6666::1\",vport1=666,backends1=\"[[4242::2]]:4242\",vport2=777,backends2=\"[[4242::2]]:4343\"}"], -+ variables="{vip=\"6666::1\",vport1=666,backends1=\"[[4242::2]]:4242\",vport2=777,backends2=\"[[4242::2]]:4343\",vport3=888,vport4=999}"], - [0], [ignore]) - - check ovn-nbctl --template lb-add lb-test-tcp "^vip:^vport1" "^backends1" tcp ipv6 \ -@@ -9792,6 +9810,18 @@ check ovn-nbctl --template lb-add lb-test-udp "^vip:^vport2" "^backends2" udp ip - -- ls-lb-add ls1 lb-test-udp \ - -- lr-lb-add rtr lb-test-udp - -+# Add a TCP template LB with explicit backends that eventually expands to: -+# VIP=[6666::1]:888 backends=[4242::2]:4242 proto=tcp -+# And a UDP template LB that eventually expands to: -+# VIP=[6666::1]:999 backends=[4242::2]:4343 proto=udp -+check ovn-nbctl --template lb-add lb-test-tcp2 "^vip:^vport3" "[[4242::2]]:4242" tcp ipv6 \ -+ -- ls-lb-add ls1 lb-test-tcp2 \ -+ -- lr-lb-add rtr lb-test-tcp2 -+ -+check ovn-nbctl --template lb-add lb-test-udp2 "^vip:^vport4" "[[4242::2]]:4343" udp ipv6 \ -+ -- ls-lb-add ls1 lb-test-udp2 \ -+ -- lr-lb-add rtr lb-test-udp2 -+ - ADD_NAMESPACES(vm1) - ADD_VETH(vm1, vm1, br-int, "4242::2/64", "00:00:00:00:00:01", "4242::1") - OVS_WAIT_UNTIL([test "$(ip netns exec vm1 ip a | grep 4242::2 | grep tentative)" = ""]) -@@ -9815,13 +9845,15 @@ name: 'backends2' value: '[[4242::2]]:4343' - name: 'vip' value: '6666::1' - name: 'vport1' value: '666' - name: 'vport2' value: '777' -+name: 'vport3' value: '888' -+name: 'vport4' value: '999' - ]) - - # Start IPv6 TCP server on vm1. - NETNS_DAEMONIZE([vm1], [nc -k -l 4242::2 4242], [nc-vm1.pid]) - - NETNS_DAEMONIZE([vm1], -- [tcpdump -n -i vm1 -nnleX -c3 udp and dst 4242::2 and dst port 4343 > vm1.pcap 2>/dev/null], -+ [tcpdump -n -i vm1 -nnleX -c6 udp and dst 4242::2 and dst port 4343 > vm1.pcap 2>/dev/null], - [tcpdump1.pid]) - - # Make sure connecting to the VIP works (hairpin, via ls and via lr). -@@ -9829,13 +9861,21 @@ NS_CHECK_EXEC([vm1], [nc 6666::1 666 -z], [0], [ignore], [ignore]) - NS_CHECK_EXEC([vm2], [nc 6666::1 666 -z], [0], [ignore], [ignore]) - NS_CHECK_EXEC([vm3], [nc 6666::1 666 -z], [0], [ignore], [ignore]) - --NS_CHECK_EXEC([vm1], [echo a | nc -u 6666::1 777 &], [0]) --NS_CHECK_EXEC([vm2], [echo a | nc -u 6666::1 777 &], [0]) --NS_CHECK_EXEC([vm3], [echo a | nc -u 6666::1 777 &], [0]) -+NS_CHECK_EXEC([vm1], [echo a | nc -u 6666::1 777], [ignore], [ignore], [ignore]) -+NS_CHECK_EXEC([vm2], [echo a | nc -u 6666::1 777], [ignore], [ignore], [ignore]) -+NS_CHECK_EXEC([vm3], [echo a | nc -u 6666::1 777], [ignore], [ignore], [ignore]) -+ -+NS_CHECK_EXEC([vm1], [nc 6666::1 888 -z], [0], [ignore], [ignore]) -+NS_CHECK_EXEC([vm2], [nc 6666::1 888 -z], [0], [ignore], [ignore]) -+NS_CHECK_EXEC([vm3], [nc 6666::1 888 -z], [0], [ignore], [ignore]) -+ -+NS_CHECK_EXEC([vm1], [echo a | nc -u 6666::1 999], [ignore], [ignore], [ignore]) -+NS_CHECK_EXEC([vm2], [echo a | nc -u 6666::1 999], [ignore], [ignore], [ignore]) -+NS_CHECK_EXEC([vm3], [echo a | nc -u 6666::1 999], [ignore], [ignore], [ignore]) - - OVS_WAIT_UNTIL([ - requests=`grep "UDP" -c vm1.pcap` -- test "${requests}" -ge "3" -+ test "${requests}" -ge "6" - ]) - - AT_CLEANUP -@@ -10587,11 +10627,13 @@ check ovn-nbctl lsp-add bar bar3 \ - -- lsp-set-addresses bar3 "f0:00:0f:01:02:05 172.16.1.4" - - # Config OVN load-balancer with a VIP. --check ovn-nbctl lb-add lb1 30.0.0.1 "172.16.1.2,172.16.1.3,172.16.1.4" -+check ovn-nbctl lb-add lb1 30.0.0.1 "172.16.1.2,172.16.1.3,172.16.1.4" \ -+ -- set load_balancer lb1 options:ct_flush="true" - check ovn-nbctl ls-lb-add foo lb1 - - # Create another load-balancer with another VIP. - lb2_uuid=`ovn-nbctl create load_balancer name=lb2 vips:30.0.0.3="172.16.1.2,172.16.1.3,172.16.1.4"` -+check ovn-nbctl set load_balancer lb2 options:ct_flush="true" - check ovn-nbctl ls-lb-add foo lb2 - - # Config OVN load-balancer with another VIP (this time with ports). -@@ -10607,16 +10649,18 @@ OVS_START_L7([bar1], [http]) - OVS_START_L7([bar2], [http]) - OVS_START_L7([bar3], [http]) - --OVS_WAIT_FOR_OUTPUT([ -- for i in `seq 1 20`; do -- ip netns exec foo1 wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log; -- done -- ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -+m4_define([LB1_CT_ENTRIES], [dnl - tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=,dport=),reply=(src=172.16.1.2,dst=192.168.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) - tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=,dport=),reply=(src=172.16.1.3,dst=192.168.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) - tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=,dport=),reply=(src=172.16.1.4,dst=192.168.1.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) - ]) - -+OVS_WAIT_FOR_OUTPUT([ -+ for i in `seq 1 20`; do -+ ip netns exec foo1 wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log; -+ done -+ ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | sed -e 's/zone=[[0-9]]*/zone=/'], [0], [LB1_CT_ENTRIES]) -+ - OVS_WAIT_FOR_OUTPUT([ - for i in `seq 1 20`; do - ip netns exec foo1 wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log; -@@ -10690,6 +10734,535 @@ check ovn-nbctl lb-del lb2 - - OVS_WAIT_UNTIL([test "$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.3) | wc -l)" = "0"]) - -+# Check that LB has CT flush disabled by default -+check ovn-nbctl lb-add lb1 30.0.0.1 "172.16.1.2,172.16.1.3,172.16.1.4" -+check ovn-nbctl ls-lb-add foo lb1 -+ -+OVS_WAIT_FOR_OUTPUT([ -+ for i in `seq 1 20`; do -+ ip netns exec foo1 wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log; -+ done -+ ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | sed -e 's/zone=[[0-9]]*/zone=/'], [0], [LB1_CT_ENTRIES]) -+ -+# Remove one backend -+check ovn-nbctl --wait=hv set load_balancer lb1 vips='"30.0.0.1"="172.16.1.2,172.16.1.3"' -+ -+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | sed -e 's/zone=[[0-9]]*/zone=/'], [0], [LB1_CT_ENTRIES]) -+ -+# Remove whole LB -+check ovn-nbctl --wait=hv lb-del lb1 -+ -+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | sed -e 's/zone=[[0-9]]*/zone=/'], [0], [LB1_CT_ENTRIES]) -+ -+OVS_APP_EXIT_AND_WAIT([ovn-controller]) -+ -+as ovn-sb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as ovn-nb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as northd -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) -+ -+as -+OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -+/connection dropped.*/d"]) -+AT_CLEANUP -+]) -+ -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([ACL and committing to conntrack]) -+AT_KEYWORDS([acl]) -+ -+CHECK_CONNTRACK() -+CHECK_CONNTRACK_NAT() -+ovn_start -+OVS_TRAFFIC_VSWITCHD_START() -+ADD_BR([br-int]) -+# Set external-ids in br-int needed for ovn-controller -+ovs-vsctl \ -+ -- set Open_vSwitch . external-ids:system-id=hv1 \ -+ -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ -+ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ -+ -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ -+ -- set bridge br-int fail-mode=secure other-config:disable-in-band=true -+ -+start_daemon ovn-controller -+ -+check ovn-nbctl lr-add r1 -+check ovn-nbctl lrp-add r1 r1_s1 00:de:ad:fe:00:01 173.0.1.1/24 -+check ovn-nbctl lrp-add r1 r1_s2 00:de:ad:fe:00:02 173.0.2.1/24 -+ -+check ovn-nbctl ls-add s1 -+check ovn-nbctl lsp-add s1 s1_r1 -+check ovn-nbctl lsp-set-type s1_r1 router -+check ovn-nbctl lsp-set-addresses s1_r1 router -+check ovn-nbctl lsp-set-options s1_r1 router-port=r1_s1 -+ -+check ovn-nbctl ls-add s2 -+check ovn-nbctl lsp-add s2 s2_r1 -+check ovn-nbctl lsp-set-type s2_r1 router -+check ovn-nbctl lsp-set-addresses s2_r1 router -+check ovn-nbctl lsp-set-options s2_r1 router-port=r1_s2 -+ -+check ovn-nbctl lsp-add s1 vm1 -+check ovn-nbctl lsp-set-addresses vm1 "00:de:ad:01:00:01 173.0.1.2" -+ -+check ovn-nbctl lsp-add s2 vm2 -+check ovn-nbctl lsp-set-addresses vm2 "00:de:ad:01:00:02 173.0.2.2" -+ -+check ovn-nbctl lsp-add s2 vm3 -+check ovn-nbctl lsp-set-addresses vm3 "00:de:ad:01:00:03 173.0.2.3" -+ -+check ovn-nbctl lb-add lb1 30.0.0.1:80 173.0.2.2:80 udp -+check ovn-nbctl lb-add lb2 20.0.0.1:80 173.0.1.2:80 udp -+check ovn-nbctl lb-add lb1 30.0.0.1 173.0.2.2 -+check ovn-nbctl lb-add lb2 173.0.2.250 173.0.1.3 -+check ovn-nbctl ls-lb-add s1 lb1 -+check ovn-nbctl ls-lb-add s2 lb2 -+ -+ADD_NAMESPACES(vm1) -+ADD_VETH(vm1, vm1, br-int, "173.0.1.2/24", "00:de:ad:01:00:01", \ -+ "173.0.1.1") -+ADD_NAMESPACES(vm2) -+ADD_VETH(vm2, vm2, br-int, "173.0.2.2/24", "00:de:ad:01:00:02", \ -+ "173.0.2.1") -+ADD_NAMESPACES(vm3) -+ADD_VETH(vm3, vm3, br-int, "173.0.2.250/24", "00:de:ad:01:00:03", \ -+ "173.0.2.1") -+ -+check ovn-nbctl acl-add s1 from-lport 1001 "ip" allow -+check ovn-nbctl acl-add s1 to-lport 1002 "ip" allow -+check ovn-nbctl acl-add s2 from-lport 1003 "ip" allow -+check ovn-nbctl acl-add s2 to-lport 1004 "ip" allow -+check ovn-nbctl --wait=hv sync -+AS_BOX([initial ping]) -+# Send ping in background. Same ping, same flow throughout the test -+on_exit 'kill $(pidof ping)' -+NS_EXEC([vm1], [ping -c 10000 -i 0.1 30.0.0.1 > icmp.txt &]) -+ -+# Check for conntrack entries -+OVS_WAIT_FOR_OUTPUT([ -+ ovs-appctl dpctl/dump-conntrack | FORMAT_CT(173.0.1.2) | \ -+ sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -+icmp,orig=(src=173.0.1.2,dst=173.0.2.2,id=,type=8,code=0),reply=(src=173.0.2.2,dst=173.0.1.2,id=,type=0,code=0),zone= -+icmp,orig=(src=173.0.1.2,dst=30.0.0.1,id=,type=8,code=0),reply=(src=173.0.2.2,dst=173.0.1.2,id=,type=0,code=0),zone=,mark=2 -+]) -+ -+# Now check for multiple ct_commits -+ovs-appctl dpctl/dump-flows > dp_flows -+zone_id=$(ovn-appctl -t ovn-controller ct-zone-list | grep vm1 | cut -d ' ' -f2) -+AT_CHECK([test 1 = `cat dp_flows | grep "commit,zone=$zone_id" | wc -l`]) -+ -+check ovn-nbctl acl-del s1 from-lport 1001 "ip" -+check ovn-nbctl acl-del s1 to-lport 1002 "ip" -+check ovn-nbctl acl-del s2 from-lport 1003 "ip" -+check ovn-nbctl acl-del s2 to-lport 1004 "ip" -+ -+AS_BOX([acl drop echo request]) -+check ovn-nbctl --log --severity=alert --name=drop-flow-s1 acl-add s1 to-lport 2001 icmp4 drop -+# acl-drop to-lport s1 apply to traffic from s1 to vm1 and s1 to r1. -+check ovn-nbctl --wait=hv sync -+ -+# Check that traffic is blocked -+# Wait for some packets to hit the rule to avoid potential race conditions. Then count packets. -+OVS_WAIT_UNTIL([test `cat ovn-controller.log | grep acl_log | grep -c drop-flow-s1` -gt "0"]) -+total_icmp_pkts=$(cat icmp.txt | grep ttl | wc -l) -+ -+# Wait some time and check whether packets went through. In the worse race condition, the sleep is too short -+# and this test will still succeed. -+sleep 1 -+OVS_WAIT_UNTIL([ -+ total_icmp1_pkts=$(cat icmp.txt | grep ttl | wc -l) -+ test "${total_icmp1_pkts}" -eq "${total_icmp_pkts}" -+]) -+ -+AS_BOX([acl allow-related echo request]) -+check ovn-nbctl acl-add s1 to-lport 2002 "icmp4 && ip4.src == 173.0.1.2" allow-related -+# This rule has higher priority than to-lport 2001 icmp4 drop. -+# So traffic from s1 (w/ src=173.0.1.2) to r1 should be accepted -+# (return) traffic from s1 to vm1 should be accepted as return traffic -+check ovn-nbctl --wait=hv sync -+OVS_WAIT_UNTIL([ -+ total_icmp1_pkts=$(cat icmp.txt | grep ttl | wc -l) -+ test "${total_icmp1_pkts}" -gt "${total_icmp_pkts}" -+]) -+ -+# Check we did not break handling acl-drop for existing flows -+AS_BOX([acl drop echo request in s2]) -+check ovn-nbctl acl-del s1 to-lport 2001 icmp4 -+check ovn-nbctl --log --severity=alert --name=drop-flow-s2 acl-add s2 to-lport 2001 icmp4 drop -+check ovn-nbctl --wait=hv sync -+ -+OVS_WAIT_UNTIL([test `cat ovn-controller.log | grep acl_log | grep -c drop-flow-s2` -gt "0"]) -+ -+OVS_WAIT_FOR_OUTPUT([ -+ ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \ -+ sed -e 's/zone=[[0-9]]*/zone=/' | \ -+ sed -e 's/mark=[[0-9]]*/mark=/'], [0], [dnl -+icmp,orig=(src=173.0.1.2,dst=30.0.0.1,id=,type=8,code=0),reply=(src=173.0.2.2,dst=173.0.1.2,id=,type=0,code=0),zone=,mark= -+]) -+total_icmp_pkts=$(cat icmp.txt | grep ttl | wc -l) -+ -+# Allow ping again -+AS_BOX([acl allow echo request in s2]) -+check ovn-nbctl acl-add s2 to-lport 2005 icmp4 allow -+check ovn-nbctl --wait=hv sync -+OVS_WAIT_FOR_OUTPUT([ -+ ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \ -+ sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -+icmp,orig=(src=173.0.1.2,dst=30.0.0.1,id=,type=8,code=0),reply=(src=173.0.2.2,dst=173.0.1.2,id=,type=0,code=0),zone=,mark=2 -+]) -+OVS_WAIT_UNTIL([ -+ total_icmp1_pkts=$(cat icmp.txt | grep ttl | wc -l) -+ test "${total_icmp1_pkts}" -gt "${total_icmp_pkts}" -+]) -+ -+OVS_APP_EXIT_AND_WAIT([ovn-controller]) -+ -+as ovn-sb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as ovn-nb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as northd -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) -+ -+as -+OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -+/connection dropped.*/d"]) -+AT_CLEANUP -+]) -+ -+# This tests port->up/down and ovn-installed after adding and removing Ports and Interfaces. -+# 3 Conditions x 3 tests: -+# - 3 Conditions: -+# - In normal conditions -+# - Remove interface while starting and stopping SB and Controller -+# - Remove and add back interface while starting and stopping SB and Controller -+# - 3 tests: -+# - Add/Remove Logical Port -+# - Add/Remove iface-id -+# - Add/Remove Interface -+# Each tests/conditions checks for -+# - Port_binding->chassis -+# - Port up or down -+# - ovn-installed -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([ovn-install on slow ovsdb]) -+AT_KEYWORDS([ovn-install]) -+ -+OVS_TRAFFIC_VSWITCHD_START() -+# Restart ovsdb-server, this time with tcp -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+start_daemon ovsdb-server --remote=punix:"$OVS_RUNDIR"/db.sock --remote=ptcp:0:127.0.0.1 -+ -+ovn_start -+ADD_BR([br-int]) -+ -+# Set external-ids in br-int needed for ovn-controller -+ovs-vsctl \ -+ -- set Open_vSwitch . external-ids:system-id=hv1 \ -+ -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ -+ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ -+ -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ -+ -- set bridge br-int fail-mode=secure other-config:disable-in-band=true -+ -+# Start ovn-controller -+PARSE_LISTENING_PORT([$ovs_base/ovsdb-server.log], [TCP_PORT]) -+start_daemon ovn-controller tcp:127.0.0.1:$TCP_PORT -+ -+check ovn-nbctl ls-add ls1 -+check ovn-nbctl set Logical_Switch ls1 other_config:subnet=10.1.0.0/16 -+ -+check ovn-nbctl --wait=hv sync -+ -+add_logical_ports() { -+ echo Adding logical ports -+ check ovn-nbctl lsp-add ls1 lsp1 -+ check ovn-nbctl lsp-add ls1 lsp2 -+} -+ -+remove_logical_ports() { -+ echo Removing logical ports -+ check ovn-nbctl lsp-del lsp1 -+ check ovn-nbctl lsp-del lsp2 -+} -+ -+add_ovs_interface() { -+ echo Adding interface $1 $2 -+ ovs-vsctl --no-wait -- add-port br-int $1 \ -+ -- set Interface $1 external_ids:iface-id=$2 \ -+ -- set Interface $1 type=internal -+} -+add_ovs_interfaces() { -+ add_ovs_interface vif1 lsp1 -+ add_ovs_interface vif2 lsp2 -+} -+remove_ovs_interface() { -+ echo Removing interface $1 -+ check ovs-vsctl --no-wait -- del-port $1 -+} -+remove_ovs_interfaces() { -+ remove_ovs_interface vif1 -+ remove_ovs_interface vif2 -+} -+add_iface_ids() { -+ echo Adding iface-id vif1 lsp1 -+ ovs-vsctl --no-wait -- set Interface vif1 external_ids:iface-id=lsp1 -+ echo Adding iface-id vif2 lsp2 -+ ovs-vsctl --no-wait -- set Interface vif2 external_ids:iface-id=lsp2 -+} -+remove_iface_id() { -+ echo Removing iface-id $1 -+ check ovs-vsctl remove Interface $1 external_ids iface-id -+} -+remove_iface_ids() { -+ remove_iface_id vif1 -+ remove_iface_id vif2 -+} -+wait_for_local_bindings() { -+ OVS_WAIT_UNTIL( -+ [test `ovs-appctl -t ovn-controller debug/dump-local-bindings | grep interface | wc -l` -eq 2], -+ [kill -CONT $(cat ovn-sb/ovsdb-server.pid)] -+ ) -+} -+sleep_sb() { -+ echo SB going to sleep -+ AT_CHECK([kill -STOP $(cat ovn-sb/ovsdb-server.pid)]) -+} -+wake_up_sb() { -+ echo SB waking up -+ AT_CHECK([kill -CONT $(cat ovn-sb/ovsdb-server.pid)]) -+} -+sleep_controller() { -+ echo Controller going to sleep -+ ovn-appctl debug/pause -+ OVS_WAIT_UNTIL([test x$(ovn-appctl -t ovn-controller debug/status) = "xpaused"]) -+} -+ -+stop_ovsdb_controller_updates() { -+ TCP_PORT=$1 -+ echo Stopping updates from ovn-controller to ovsdb using port $TCP_PORT -+ on_exit 'iptables -C INPUT -p tcp --destination-port $TCP_PORT -j DROP 2>/dev/null && iptables -D INPUT -p tcp --destination-port $TCP_PORT -j DROP' -+ iptables -A INPUT -p tcp --destination-port $TCP_PORT -j DROP -+} -+restart_ovsdb_controller_updates() { -+ TCP_PORT=$1 -+ echo Restarting updates from ovn-controller to ovsdb -+ iptables -D INPUT -p tcp --destination-port $TCP_PORT -j DROP -+} -+wake_up_controller() { -+ echo Controller waking up -+ ovn-appctl debug/resume -+} -+ensure_controller_run() { -+# We want to make sure controller could run at least one full loop. -+# We can't use wait=hv as sb might be sleeping. -+# Use 2 ovn-appctl to guarentee that ovn-controller run the full loop, and not just the unixctl handling -+ OVS_WAIT_UNTIL([test x$(ovn-appctl -t ovn-controller debug/status) = "xrunning"]) -+ OVS_WAIT_UNTIL([test x$(ovn-appctl -t ovn-controller debug/status) = "xrunning"]) -+} -+sleep_ovsdb() { -+ echo OVSDB going to sleep -+ AT_CHECK([kill -STOP $(cat ovsdb-server.pid)]) -+} -+wake_up_ovsdb() { -+ echo OVSDB waking up -+ AT_CHECK([kill -CONT $(cat ovsdb-server.pid)]) -+} -+check_ovn_installed() { -+ OVS_WAIT_UNTIL([test `ovs-vsctl get Interface vif1 external_ids:ovn-installed` = '"true"']) -+ OVS_WAIT_UNTIL([test `ovs-vsctl get Interface vif2 external_ids:ovn-installed` = '"true"']) -+} -+check_ovn_uninstalled() { -+ OVS_WAIT_UNTIL([test x`ovs-vsctl get Interface vif2 external_ids:ovn-installed` = x]) -+ OVS_WAIT_UNTIL([test x`ovs-vsctl get Interface vif1 external_ids:ovn-installed` = x]) -+} -+check_ports_up() { -+ OVS_WAIT_UNTIL([test `ovn-sbctl get Port_Binding lsp1 up` = 'true']) -+ OVS_WAIT_UNTIL([test `ovn-sbctl get Port_Binding lsp2 up` = 'true']) -+} -+check_ports_down() { -+ OVS_WAIT_UNTIL([test `ovn-sbctl get Port_Binding lsp1 up` = 'false']) -+ OVS_WAIT_UNTIL([test `ovn-sbctl get Port_Binding lsp2 up` = 'false']) -+} -+ -+check_ports_bound() { -+ ch=$(fetch_column Chassis _uuid name=hv1) -+ wait_row_count Port_Binding 1 logical_port=lsp1 chassis=$ch -+ wait_row_count Port_Binding 1 logical_port=lsp2 chassis=$ch -+} -+check_ports_unbound() { -+ wait_column "" Port_Binding chassis logical_port=lsp1 -+ wait_column "" Port_Binding chassis logical_port=lsp2 -+} -+add_logical_ports -+add_ovs_interfaces -+wait_for_local_bindings -+wait_for_ports_up -+check ovn-nbctl --wait=hv sync -+############################################################ -+########## Remove interface while removing iface-id ######## -+############################################################ -+AS_BOX(["Remove interface while removing iface-id"]) -+stop_ovsdb_controller_updates $TCP_PORT -+remove_iface_id vif1 -+ensure_controller_run -+# OVSDB should be seen as ro now -+remove_iface_id vif2 -+ensure_controller_run -+# Controller delaying ovn-install removal for vif2 as ovsdb ro -+sleep_controller -+restart_ovsdb_controller_updates $TCP_PORT -+remove_ovs_interface vif2 -+# vif2, for which we want to remove ovn-install, is deleted -+wake_up_controller -+check_ovn_uninstalled -+check_ports_down -+check_ports_unbound -+add_ovs_interface vif2 lsp2 -+add_iface_ids -+check_ovn_installed -+check_ports_up -+check_ports_bound -+############################################################ -+################### Add/Remove iface-id #################### -+############################################################ -+AS_BOX(["iface-id removal and added back (no sleeping sb or controller)"]) -+remove_iface_ids -+check_ovn_uninstalled -+check_ports_down -+check_ports_unbound -+add_iface_ids -+check_ovn_installed -+check_ports_up -+check_ports_bound -+ -+AS_BOX(["iface-id removal"]) -+sleep_sb -+remove_iface_ids -+ensure_controller_run -+sleep_controller -+wake_up_sb -+wake_up_controller -+check_ovn_uninstalled -+check_ports_down -+check_ports_unbound -+add_iface_ids -+check ovn-nbctl --wait=hv sync -+ -+AS_BOX(["iface-id removal 2"]) -+# Block IDL from ovn-controller to OVSDB -+stop_ovsdb_controller_updates $TCP_PORT -+remove_iface_id vif2 -+ensure_controller_run -+ -+# OVSDB should now be seen as read-only by ovn-controller -+remove_iface_id vif1 -+ensure_controller_run -+ -+# Restart connection from ovn-controller to OVSDB -+restart_ovsdb_controller_updates $TCP_PORT -+check_ovn_uninstalled -+check_ports_down -+check_ports_unbound -+ -+add_iface_ids -+check ovn-nbctl --wait=hv sync -+ -+AS_BOX(["iface-id removal and added back"]) -+sleep_sb -+remove_iface_ids -+ensure_controller_run -+sleep_controller -+add_iface_ids -+wake_up_sb -+wake_up_controller -+check_ovn_installed -+check_ports_up -+check_ports_bound -+############################################################ -+###################### Add/Remove Interface ################ -+############################################################ -+AS_BOX(["Interface removal and added back (no sleeping sb or controller)"]) -+remove_ovs_interfaces -+check_ovn_uninstalled -+check_ports_down -+check_ports_unbound -+add_ovs_interfaces -+check_ovn_installed -+check_ports_up -+check_ports_bound -+check ovn-nbctl --wait=hv sync -+ -+AS_BOX(["Interface removal"]) -+sleep_sb -+remove_ovs_interfaces -+ensure_controller_run -+sleep_controller -+wake_up_sb -+wake_up_controller -+check_ovn_uninstalled -+check_ports_down -+check_ports_unbound -+add_ovs_interfaces -+check ovn-nbctl --wait=hv sync -+ -+AS_BOX(["Interface removal and added back"]) -+sleep_sb -+remove_ovs_interfaces -+ensure_controller_run -+sleep_controller -+add_ovs_interfaces -+wake_up_sb -+wake_up_controller -+check_ovn_installed -+check_ports_up -+check_ports_bound -+check ovn-nbctl --wait=hv sync -+############################################################ -+###################### Add/Remove Logical Port ############# -+############################################################ -+AS_BOX(["Logical port removal and added back (no sleeping sb or controller)"]) -+remove_logical_ports -+check_ovn_uninstalled -+check_ports_unbound -+sleep_ovsdb -+add_logical_ports -+ensure_controller_run -+wake_up_ovsdb -+check_ovn_installed -+check_ports_up -+check_ports_bound -+check ovn-nbctl --wait=hv sync -+ -+AS_BOX(["Logical port removal"]) -+sleep_sb -+remove_logical_ports -+ensure_controller_run -+sleep_controller -+wake_up_sb -+wake_up_controller -+check_ovn_uninstalled -+check_ports_unbound -+add_logical_ports -+check ovn-nbctl --wait=hv sync -+ -+AS_BOX(["Logical port removal and added back"]) -+sleep_sb -+remove_logical_ports -+ensure_controller_run -+sleep_controller -+add_logical_ports -+wake_up_sb -+wake_up_controller -+check_ovn_installed -+check_ports_up -+check_ports_bound -+ - OVS_APP_EXIT_AND_WAIT([ovn-controller]) - - as ovn-sb -@@ -10706,3 +11279,338 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d - /connection dropped.*/d"]) - AT_CLEANUP - ]) -+ -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([ovn mirroring]) -+AT_KEYWORDS([mirror]) -+AT_SKIP_IF([test $HAVE_TCPDUMP = no]) -+ -+CHECK_CONNTRACK() -+CHECK_CONNTRACK_NAT() -+ovn_start -+OVS_TRAFFIC_VSWITCHD_START() -+ADD_BR([br-int]) -+ADD_BR([br-mirror]) -+ -+# Set external-ids in br-int needed for ovn-controller -+ovs-vsctl \ -+ -- set Open_vSwitch . external-ids:system-id=hv1 \ -+ -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ -+ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ -+ -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ -+ -- set bridge br-int fail-mode=secure other-config:disable-in-band=true -+ -+# Start ovn-controller -+start_daemon ovn-controller -+ -+ovs-ofctl add-flow br-mirror action=normal -+ -+ovn-nbctl create Logical_Router name=R1 options:chassis=hv1 -+ -+ovn-nbctl ls-add foo -+ovn-nbctl ls-add bar -+ -+# Connect foo to R1 -+ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24 2001::1/64 -+ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \ -+ type=router options:router-port=foo addresses=\"00:00:01:01:02:03\" -+ -+# Connect bar to R1 -+ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24 2002::1/64 -+ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \ -+ type=router options:router-port=bar addresses=\"00:00:01:01:02:04\" -+ -+# Logical port 'foo1' in switch 'foo'. -+ADD_NAMESPACES(foo1) -+ADD_VETH(foo1, foo1, br-int, "2001::2/64", "f0:00:00:01:02:03", \ -+ "2001::1", "nodad", "192.168.1.2/24", "192.168.1.1") -+ovn-nbctl lsp-add foo foo1 \ -+-- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2 2001::2" -+ -+# Logical port 'bar1' in switch 'bar'. -+ADD_NAMESPACES(bar1) -+ADD_VETH(bar1, bar1, br-int, "2002::2/64", "f0:00:00:01:02:05", \ -+ "2002::1", "nodad", "192.168.2.2/24", "192.168.2.1") -+ovn-nbctl lsp-add bar bar1 \ -+-- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2 2002::2" -+ -+ovn-nbctl mirror-add mirror0 gre 1 to-lport 172.16.0.100 -+ovn-nbctl lsp-attach-mirror bar1 mirror0 -+ -+OVN_POPULATE_ARP -+check ovn-nbctl --wait=hv sync -+ -+ADD_NAMESPACES(mirror) -+ADD_VETH(mirror, mirror, br-mirror, "2003::b/64", "f0:00:00:01:07:06", \ -+ "2003::1", "nodad", "172.16.0.100/24", "172.16.0.1") -+AT_CHECK([ip addr add 172.16.0.101/24 dev br-mirror]) -+AT_CHECK([ip addr add 2003::a/64 dev br-mirror nodad]) -+AT_CHECK([ip link set dev br-mirror up]) -+ -+NS_CHECK_EXEC([mirror], [tcpdump -l -c 3 -neei mirror proto GRE > gre_mirror4.pcap 2>gre_mirror4_error &]) -+OVS_WAIT_UNTIL([grep "listening" gre_mirror4_error]) -+ -+NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \ -+[0], [dnl -+3 packets transmitted, 3 received, 0% packet loss, time 0ms -+]) -+OVS_WAIT_UNTIL([ -+ n_packets=$(grep "GRE" -c gre_mirror4.pcap) -+ test "${n_packets}" = "3" -+]) -+ -+killall tcpdump -+ -+ovn-nbctl mirror-del mirror0 -+ovn-nbctl mirror-add mirror1 gre 2 to-lport 2003::b -+ -+ovn-nbctl --wait=hv lsp-attach-mirror bar1 mirror1 -+ -+NS_CHECK_EXEC([mirror], [tcpdump -l -c 3 -neei mirror proto GRE > gre_mirror6.pcap 2>gre_mirror6_error &]) -+OVS_WAIT_UNTIL([grep "listening" gre_mirror6_error]) -+ -+NS_CHECK_EXEC([foo1], [ping6 -q -c 3 -i 0.3 -w 2 2002::2 | FORMAT_PING], \ -+[0], [dnl -+3 packets transmitted, 3 received, 0% packet loss, time 0ms -+]) -+ -+OVS_WAIT_UNTIL([ -+ n_packets=$(grep "GRE" -c gre_mirror6.pcap) -+ test "${n_packets}" = "3" -+]) -+ -+killall tcpdump -+ -+ovn-nbctl mirror-del mirror1 -+ovn-nbctl mirror-add mirror2 erspan 3 to-lport 172.16.0.100 -+ovn-nbctl --wait=hv lsp-attach-mirror bar1 mirror2 -+ -+NS_CHECK_EXEC([mirror], [tcpdump -l -c 3 -neei mirror ip[[22:2]]=0x88be > erspan_mirror4.pcap 2>erspan_mirror4_error &]) -+OVS_WAIT_UNTIL([grep "listening" erspan_mirror4_error]) -+ -+NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \ -+[0], [dnl -+3 packets transmitted, 3 received, 0% packet loss, time 0ms -+]) -+OVS_WAIT_UNTIL([ -+ n_packets=$(grep "gre-proto-0x88be" -c erspan_mirror4.pcap) -+ test "${n_packets}" = "3" -+]) -+ -+killall tcpdump -+ -+ovn-nbctl mirror-del mirror2 -+ovn-nbctl mirror-add mirror3 erspan 4 to-lport 2003::b -+ovn-nbctl --wait=hv lsp-attach-mirror bar1 mirror3 -+ -+NS_CHECK_EXEC([mirror], [tcpdump -l -c 3 -neei mirror ip6[[42:2]]=0x88be > erspan_mirror6.pcap 2>erspan_mirror6_error &]) -+OVS_WAIT_UNTIL([grep "listening" erspan_mirror6_error]) -+ -+NS_CHECK_EXEC([foo1], [ping6 -q -c 3 -i 0.3 -w 2 2002::2 | FORMAT_PING], \ -+[0], [dnl -+3 packets transmitted, 3 received, 0% packet loss, time 0ms -+]) -+OVS_WAIT_UNTIL([ -+ n_packets=$(grep "gre-proto-0x88be" -c erspan_mirror6.pcap) -+ test "${n_packets}" = "3" -+]) -+ -+killall tcpdump -+ -+uuid=$(fetch_column nb:mirror _uuid name="mirror3") -+ovn-nbctl --wait=hv set mirror $uuid type=gre -+ -+NS_CHECK_EXEC([mirror], [tcpdump -c 3 -l -neei mirror proto GRE > gre_mirror6.pcap 2>gre_mirror6_error &]) -+OVS_WAIT_UNTIL([grep "listening" gre_mirror6_error]) -+ -+NS_CHECK_EXEC([foo1], [ping6 -q -c 3 -i 0.3 -w 2 2002::2 | FORMAT_PING], \ -+[0], [dnl -+3 packets transmitted, 3 received, 0% packet loss, time 0ms -+]) -+ -+OVS_WAIT_UNTIL([ -+ n_packets=$(grep "GRE" -c gre_mirror6.pcap) -+ test "${n_packets}" = "3" -+]) -+ -+killall tcpdump -+ -+OVS_APP_EXIT_AND_WAIT([ovn-controller]) -+ -+as ovn-sb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as ovn-nb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as northd -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) -+ -+as -+OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -+/connection dropped.*/d"]) -+AT_CLEANUP -+]) -+ -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([load balancer with localnet port]) -+CHECK_CONNTRACK() -+CHECK_CONNTRACK_NAT() -+ovn_start -+OVS_TRAFFIC_VSWITCHD_START() -+ADD_BR([br-int]) -+ADD_BR([br-phys], [set Bridge br-phys fail-mode=standalone]) -+ -+# Set external-ids in br-int needed for ovn-controller -+ovs-vsctl \ -+ -- set Open_vSwitch . external-ids:system-id=hv1 \ -+ -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ -+ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ -+ -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ -+ -- set bridge br-int fail-mode=secure other-config:disable-in-band=true -+ -+start_daemon ovn-controller -+ -+check ovn-nbctl lr-add ro -+check ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 192.168.0.1/24 -+check ovn-nbctl lrp-add ro ro-pub 00:00:00:00:01:01 10.0.0.1/24 -+ -+check ovn-nbctl ls-add sw -+check ovn-nbctl lsp-add sw sw-vm1 \ -+ -- lsp-set-addresses sw-vm1 "00:00:00:00:00:02 192.168.0.2" -+check ovn-nbctl lsp-add sw sw-ro \ -+ -- lsp-set-type sw-ro router \ -+ -- lsp-set-addresses sw-ro router \ -+ -- lsp-set-options sw-ro router-port=ro-sw -+ -+check ovn-nbctl ls-add pub -+check ovn-nbctl lsp-add pub sw-ln \ -+ -- lsp-set-type sw-ln localnet \ -+ -- lsp-set-addresses sw-ln unknown \ -+ -- lsp-set-options sw-ln network_name=phys -+check ovn-nbctl lsp-add pub pub-ro \ -+ -- lsp-set-type pub-ro router \ -+ -- lsp-set-addresses pub-ro router \ -+ -- lsp-set-options pub-ro router-port=ro-pub -+ -+check ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys -+ -+ADD_NAMESPACES(sw-vm1) -+ADD_VETH(sw-vm1, sw-vm1, br-int, "192.168.0.2/24", "00:00:00:00:00:02", \ -+ "192.168.0.1") -+ -+ADD_NAMESPACES(ln) -+ADD_VETH(ln, ln, br-phys, "10.0.0.2/24", "00:00:00:00:01:02", \ -+ "10.0.0.1") -+ -+# We have the basic network set up. Now let's add a load balancer -+# on the "pub" logical switch. -+ -+check ovn-nbctl lb-add ln-lb 172.16.0.1:80 192.168.0.2:80 tcp -+check ovn-nbctl ls-lb-add pub ln-lb -+check ovn-nbctl --wait=hv sync -+ -+# Add a route so that the localnet port can reach the load balancer -+# VIP. -+NS_CHECK_EXEC([ln], [ip route add 172.16.0.1 via 10.0.0.1]) -+NS_CHECK_EXEC([ln], [ip route add 192.168.0.0/24 via 10.0.0.1]) -+ -+OVS_START_L7([sw-vm1], [http]) -+ -+NS_CHECK_EXEC([ln], [wget 172.16.0.1 -t 5 -T 1 --retry-connrefused -v -o wget.log]) -+ -+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.0.1) | \ -+sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl -+tcp,orig=(src=10.0.0.2,dst=172.16.0.1,sport=,dport=),reply=(src=192.168.0.2,dst=10.0.0.2,sport=,dport=),zone=,mark=2,protoinfo=(state=) -+]) -+ -+OVS_APP_EXIT_AND_WAIT([ovn-controller]) -+ -+as ovn-sb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as ovn-nb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as northd -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) -+ -+as -+OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -+/connection dropped.*/d"]) -+ -+AT_CLEANUP -+]) -+ -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([Traffic to router port via LLA]) -+ovn_start -+OVS_TRAFFIC_VSWITCHD_START() -+ADD_BR([br-int]) -+ADD_BR([br-phys], [set Bridge br-phys fail-mode=standalone]) -+ -+# Set external-ids in br-int needed for ovn-controller -+ovs-vsctl \ -+ -- set Open_vSwitch . external-ids:system-id=hv1 \ -+ -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ -+ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ -+ -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ -+ -- set bridge br-int fail-mode=secure other-config:disable-in-band=true -+ -+start_daemon ovn-controller -+ -+check ovn-nbctl lr-add lr0 -+check ovn-nbctl lrp-add lr0 lr0-ls0 00:00:00:00:00:01 fd00::1/64 -+ -+check ovn-nbctl ls-add ls0 -+check ovn-nbctl lsp-add ls0 vif0 \ -+ -- lsp-set-addresses vif0 "00:00:00:00:00:02 fd00::2" -+check ovn-nbctl lsp-add ls0 ls0-lr0 \ -+ -- lsp-set-type ls0-lr0 router \ -+ -- lsp-set-addresses ls0-lr0 router \ -+ -- lsp-set-options ls0-lr0 router-port=lr0-ls0 -+ -+ADD_NAMESPACES(vif0) -+ADD_VETH(vif0, vif0, br-int, "fd00::2/64", "00:00:00:00:00:02", "fd00::1") -+OVS_WAIT_UNTIL([test "$(ip netns exec vif0 ip a | grep fe80:: | grep tentative)" = ""]) -+ -+check ovn-nbctl set logical_router lr0 options:always_learn_from_arp_request=false -+ -+OVN_POPULATE_ARP -+wait_for_ports_up -+check ovn-nbctl --wait=sb sync -+ -+NS_CHECK_EXEC([vif0], [ping -q -c 3 -i 0.3 -w 2 fe80::200:ff:fe00:1 | FORMAT_PING], \ -+[0], [dnl -+3 packets transmitted, 3 received, 0% packet loss, time 0ms -+]) -+ -+check_row_count mac_binding 1 mac=\"00:00:00:00:00:02\" -+ovn-sbctl --all destroy mac_binding -+ -+ovn-nbctl --wait=hv set logical_router lr0 options:always_learn_from_arp_request=true -+ -+NS_CHECK_EXEC([vif0], [ping -q -c 3 -i 0.3 -w 2 fe80::200:ff:fe00:1 | FORMAT_PING], \ -+[0], [dnl -+3 packets transmitted, 3 received, 0% packet loss, time 0ms -+]) -+ -+check_row_count mac_binding 1 mac=\"00:00:00:00:00:02\" -+ -+OVS_APP_EXIT_AND_WAIT([ovn-controller]) -+ -+as ovn-sb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as ovn-nb -+OVS_APP_EXIT_AND_WAIT([ovsdb-server]) -+ -+as northd -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) -+ -+as -+OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -+/connection dropped.*/d"]) -+ -+AT_CLEANUP -+]) -diff --git a/utilities/containers/py-requirements.txt b/utilities/containers/py-requirements.txt -index d7bd21e0d..0d90765c9 100644 ---- a/utilities/containers/py-requirements.txt -+++ b/utilities/containers/py-requirements.txt -@@ -1,5 +1,6 @@ - flake8 - hacking>=3.0 -+scapy - sphinx - setuptools - pyelftools -diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c -index 45572fd30..9399f9462 100644 ---- a/utilities/ovn-nbctl.c -+++ b/utilities/ovn-nbctl.c -@@ -3033,7 +3033,7 @@ nbctl_lb_add(struct ctl_context *ctx) - } - - ovn_lb_vip_format(&lb_vip_parsed, &lb_vip_normalized, template); -- ovn_lb_vip_backends_format(&lb_vip_parsed, &lb_ips_new, template); -+ ovn_lb_vip_backends_format(&lb_vip_parsed, &lb_ips_new); - ovn_lb_vip_destroy(&lb_vip_parsed); - - const struct nbrec_load_balancer *lb = NULL; -@@ -4204,8 +4204,7 @@ print_routing_policy(const struct nbrec_logical_router_policy *policy, - policy->match, policy->action); - for (int i = 0; i < policy->n_nexthops; i++) { - char *next_hop = normalize_prefix_str(policy->nexthops[i]); -- char *fmt = i ? ", %s" : " %25s"; -- ds_put_format(s, fmt, next_hop); -+ ds_put_format(s, i ? ", %s" : " %25s", next_hop ? next_hop : ""); - free(next_hop); - } - } else { -@@ -6586,18 +6585,17 @@ print_route(const struct nbrec_logical_router_static_route *route, - { - - char *prefix = normalize_prefix_str(route->ip_prefix); -- char *next_hop = ""; -+ char *next_hop = NULL; - - if (!strcmp(route->nexthop, "discard")) { - next_hop = xasprintf("discard"); - } else if (route->nexthop[0]) { - next_hop = normalize_prefix_str(route->nexthop); - } -- ds_put_format(s, "%25s %25s", prefix, next_hop); -+ ds_put_format(s, "%25s %25s", prefix ? prefix : "", -+ next_hop ? next_hop : ""); - free(prefix); -- if (next_hop[0]) { -- free(next_hop); -- } -+ free(next_hop); - - if (route->policy) { - ds_put_format(s, " %s", route->policy); diff --git a/SOURCES/ovn23.06.patch b/SOURCES/ovn23.06.patch new file mode 100644 index 0000000..ccd46e5 --- /dev/null +++ b/SOURCES/ovn23.06.patch @@ -0,0 +1,669 @@ +diff --git a/NEWS b/NEWS +index ef000ef7b..0056bb175 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,3 +1,6 @@ ++OVN v23.06.2 - xx xxx xxxx ++-------------------------- ++ + OVN v23.06.1 - 29 Aug 2023 + -------------------------- + - Bug fixes +diff --git a/configure.ac b/configure.ac +index fc4ba024a..3ed093ebe 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -13,7 +13,7 @@ + # limitations under the License. + + AC_PREREQ(2.63) +-AC_INIT(ovn, 23.06.1, bugs@openvswitch.org) ++AC_INIT(ovn, 23.06.2, bugs@openvswitch.org) + AC_CONFIG_MACRO_DIR([m4]) + AC_CONFIG_AUX_DIR([build-aux]) + AC_CONFIG_HEADERS([config.h]) +diff --git a/controller/lflow.c b/controller/lflow.c +index 22faaf013..718b4a27a 100644 +--- a/controller/lflow.c ++++ b/controller/lflow.c +@@ -2513,10 +2513,10 @@ build_in_port_sec_default_flows(const struct sbrec_port_binding *pb, + * investigation. + * + * Eg. If there are below OF rules in the same table +- * (1) priority=90,icmp6,reg14=0x1,metadata=0x1,nw_ttl=225,icmp_type=135, ++ * (1) priority=90,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135, + * icmp_code=0,nd_sll=fa:16:3e:94:05:98 + * actions=load:0->NXM_NX_REG10[12] +- * (2) priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=225,icmp_type=135, ++ * (2) priority=80,icmp6,reg14=0x1,metadata=0x1,nw_ttl=255,icmp_type=135, + * icmp_code=0 actions=load:1->NXM_NX_REG10[12] + * + * An IPv6 NS packet with nd_sll = fa:16:3e:94:05:98 is matching on the +@@ -2801,7 +2801,7 @@ build_in_port_sec_nd_flows(const struct sbrec_port_binding *pb, + reset_match_for_port_sec_flows(pb, MFF_LOG_INPORT, m); + match_set_dl_type(m, htons(ETH_TYPE_IPV6)); + match_set_nw_proto(m, IPPROTO_ICMPV6); +- match_set_nw_ttl(m, 225); ++ match_set_nw_ttl(m, 255); + match_set_icmp_type(m, 135); + match_set_icmp_code(m, 0); + +diff --git a/controller/ofctrl.c b/controller/ofctrl.c +index 64a444ff6..a1676a788 100644 +--- a/controller/ofctrl.c ++++ b/controller/ofctrl.c +@@ -16,6 +16,7 @@ + #include + #include "bitmap.h" + #include "byte-order.h" ++#include "coverage.h" + #include "dirs.h" + #include "dp-packet.h" + #include "flow.h" +@@ -55,6 +56,8 @@ + + VLOG_DEFINE_THIS_MODULE(ofctrl); + ++COVERAGE_DEFINE(ofctrl_msg_too_long); ++ + /* An OpenFlow flow. */ + struct ovn_flow { + /* Key. */ +@@ -1273,6 +1276,37 @@ ofctrl_add_flow_metered(struct ovn_desired_flow_table *desired_flows, + meter_id, as_info, true); + } + ++struct ofpact_ref { ++ struct hmap_node hmap_node; ++ struct ofpact *ofpact; ++}; ++ ++static struct ofpact_ref * ++ofpact_ref_find(const struct hmap *refs, const struct ofpact *ofpact) ++{ ++ uint32_t hash = hash_bytes(ofpact, ofpact->len, 0); ++ ++ struct ofpact_ref *ref; ++ HMAP_FOR_EACH_WITH_HASH (ref, hmap_node, hash, refs) { ++ if (ofpacts_equal(ref->ofpact, ref->ofpact->len, ++ ofpact, ofpact->len)) { ++ return ref; ++ } ++ } ++ ++ return NULL; ++} ++ ++static void ++ofpact_refs_destroy(struct hmap *refs) ++{ ++ struct ofpact_ref *ref; ++ HMAP_FOR_EACH_POP (ref, hmap_node, refs) { ++ free(ref); ++ } ++ hmap_destroy(refs); ++} ++ + /* Either add a new flow, or append actions on an existing flow. If the + * flow existed, a new link will also be created between the new sb_uuid + * and the existing flow. */ +@@ -1292,6 +1326,21 @@ ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows, + meter_id); + existing = desired_flow_lookup_conjunctive(desired_flows, &f->flow); + if (existing) { ++ struct hmap existing_conj = HMAP_INITIALIZER(&existing_conj); ++ ++ struct ofpact *ofpact; ++ OFPACT_FOR_EACH (ofpact, existing->flow.ofpacts, ++ existing->flow.ofpacts_len) { ++ if (ofpact->type != OFPACT_CONJUNCTION) { ++ continue; ++ } ++ ++ struct ofpact_ref *ref = xmalloc(sizeof *ref); ++ ref->ofpact = ofpact; ++ uint32_t hash = hash_bytes(ofpact, ofpact->len, 0); ++ hmap_insert(&existing_conj, &ref->hmap_node, hash); ++ } ++ + /* There's already a flow with this particular match and action + * 'conjunction'. Append the action to that flow rather than + * adding a new flow. +@@ -1301,7 +1350,15 @@ ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows, + ofpbuf_use_stub(&compound, compound_stub, sizeof(compound_stub)); + ofpbuf_put(&compound, existing->flow.ofpacts, + existing->flow.ofpacts_len); +- ofpbuf_put(&compound, f->flow.ofpacts, f->flow.ofpacts_len); ++ ++ OFPACT_FOR_EACH (ofpact, f->flow.ofpacts, f->flow.ofpacts_len) { ++ if (ofpact->type != OFPACT_CONJUNCTION || ++ !ofpact_ref_find(&existing_conj, ofpact)) { ++ ofpbuf_put(&compound, ofpact, OFPACT_ALIGN(ofpact->len)); ++ } ++ } ++ ++ ofpact_refs_destroy(&existing_conj); + + mem_stats.desired_flow_usage -= desired_flow_size(existing); + free(existing->flow.ofpacts); +@@ -1769,6 +1826,18 @@ ovn_flow_log(const struct ovn_flow *f, const char *action) + } + } + ++static void ++ovn_flow_log_size_err(const struct ovn_flow *f) ++{ ++ COVERAGE_INC(ofctrl_msg_too_long); ++ ++ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); ++ ++ char *s = ovn_flow_to_string(f); ++ VLOG_ERR_RL(&rl, "The FLOW_MOD message is too big: %s", s); ++ free(s); ++} ++ + static void + ovn_flow_uninit(struct ovn_flow *f) + { +@@ -1888,15 +1957,27 @@ encode_bundle_add(struct ofpbuf *msg, struct ofputil_bundle_ctrl_msg *bc) + return ofputil_encode_bundle_add(OFP15_VERSION, &bam); + } + +-static void ++static bool + add_flow_mod(struct ofputil_flow_mod *fm, + struct ofputil_bundle_ctrl_msg *bc, + struct ovs_list *msgs) + { + struct ofpbuf *msg = encode_flow_mod(fm); + struct ofpbuf *bundle_msg = encode_bundle_add(msg, bc); ++ ++ uint32_t flow_mod_len = msg->size; ++ uint32_t bundle_len = bundle_msg->size; ++ + ofpbuf_delete(msg); ++ ++ if (flow_mod_len > UINT16_MAX || bundle_len > UINT16_MAX) { ++ ofpbuf_delete(bundle_msg); ++ ++ return false; ++ } ++ + ovs_list_push_back(msgs, &bundle_msg->list_node); ++ return true; + } + + /* group_table. */ +@@ -2235,7 +2316,10 @@ installed_flow_add(struct ovn_flow *d, + .new_cookie = htonll(d->cookie), + .command = OFPFC_ADD, + }; +- add_flow_mod(&fm, bc, msgs); ++ ++ if (!add_flow_mod(&fm, bc, msgs)) { ++ ovn_flow_log_size_err(d); ++ } + } + + static void +@@ -2259,7 +2343,7 @@ installed_flow_mod(struct ovn_flow *i, struct ovn_flow *d, + /* Use OFPFC_ADD so that cookie can be updated. */ + fm.command = OFPFC_ADD; + } +- add_flow_mod(&fm, bc, msgs); ++ bool result = add_flow_mod(&fm, bc, msgs); + + /* Replace 'i''s actions and cookie by 'd''s. */ + mem_stats.installed_flow_usage -= i->ofpacts_len - d->ofpacts_len; +@@ -2267,6 +2351,10 @@ installed_flow_mod(struct ovn_flow *i, struct ovn_flow *d, + i->ofpacts = xmemdup(d->ofpacts, d->ofpacts_len); + i->ofpacts_len = d->ofpacts_len; + i->cookie = d->cookie; ++ ++ if (!result) { ++ ovn_flow_log_size_err(i); ++ } + } + + static void +@@ -2280,7 +2368,10 @@ installed_flow_del(struct ovn_flow *i, + .table_id = i->table_id, + .command = OFPFC_DELETE_STRICT, + }; +- add_flow_mod(&fm, bc, msgs); ++ ++ if (!add_flow_mod(&fm, bc, msgs)) { ++ ovn_flow_log_size_err(i); ++ } + } + + static void +diff --git a/debian/changelog b/debian/changelog +index e1d505a7e..e147d113c 100644 +--- a/debian/changelog ++++ b/debian/changelog +@@ -1,3 +1,9 @@ ++OVN (23.06.2-1) unstable; urgency=low ++ [ OVN team ] ++ * New upstream version ++ ++ -- OVN team Tue, 29 Aug 2023 11:28:59 -0400 ++ + OVN (23.06.1-1) unstable; urgency=low + [ OVN team ] + * New upstream version +diff --git a/northd/northd.c b/northd/northd.c +index af871e260..3d6449c88 100644 +--- a/northd/northd.c ++++ b/northd/northd.c +@@ -259,7 +259,6 @@ enum ovn_stage { + #define REGBIT_LOOKUP_NEIGHBOR_RESULT "reg9[2]" + #define REGBIT_LOOKUP_NEIGHBOR_IP_RESULT "reg9[3]" + #define REGBIT_DST_NAT_IP_LOCAL "reg9[4]" +-#define REGBIT_KNOWN_ECMP_NH "reg9[5]" + #define REGBIT_KNOWN_LB_SESSION "reg9[6]" + + /* Register to store the eth address associated to a router port for packets +@@ -367,8 +366,7 @@ enum ovn_stage { + * | | EGRESS_LOOPBACK/ | G | UNUSED | + * | R9 | PKT_LARGER/ | 4 | | + * | | LOOKUP_NEIGHBOR_RESULT/ | | | +- * | | SKIP_LOOKUP_NEIGHBOR/ | | | +- * | | KNOWN_ECMP_NH} | | | ++ * | | SKIP_LOOKUP_NEIGHBOR} | | | + * | | | | | + * | | REG_ORIG_TP_DPORT_ROUTER | | | + * | | | | | +@@ -10326,15 +10324,13 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, + cidr); + free(cidr); + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DEFRAG, 100, +- ds_cstr(&base_match), +- REGBIT_KNOWN_ECMP_NH" = chk_ecmp_nh_mac(); ct_next;", +- &st_route->header_); ++ ds_cstr(&base_match), "ct_next;", ++ &st_route->header_); + + /* And packets that go out over an ECMP route need conntrack */ + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DEFRAG, 100, +- ds_cstr(route_match), +- REGBIT_KNOWN_ECMP_NH" = chk_ecmp_nh(); ct_next;", +- &st_route->header_); ++ ds_cstr(route_match), "ct_next;", ++ &st_route->header_); + + /* Save src eth and inport in ct_label for packets that arrive over + * an ECMP route. +@@ -10347,9 +10343,8 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, + ds_put_format(&actions, + "ct_commit { ct_label.ecmp_reply_eth = eth.src; " + " %s = %" PRId64 ";}; " +- "commit_ecmp_nh(ipv6 = %s, proto = tcp); next;", +- ct_ecmp_reply_port_match, out_port->sb->tunnel_key, +- IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "false" : "true"); ++ "next;", ++ ct_ecmp_reply_port_match, out_port->sb->tunnel_key); + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 100, + ds_cstr(&match), ds_cstr(&actions), + &st_route->header_); +@@ -10360,9 +10355,8 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, + ds_put_format(&actions, + "ct_commit { ct_label.ecmp_reply_eth = eth.src; " + " %s = %" PRId64 ";}; " +- "commit_ecmp_nh(ipv6 = %s, proto = udp); next;", +- ct_ecmp_reply_port_match, out_port->sb->tunnel_key, +- IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "false" : "true"); ++ "next;", ++ ct_ecmp_reply_port_match, out_port->sb->tunnel_key); + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 100, + ds_cstr(&match), ds_cstr(&actions), + &st_route->header_); +@@ -10373,53 +10367,49 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, + ds_put_format(&actions, + "ct_commit { ct_label.ecmp_reply_eth = eth.src; " + " %s = %" PRId64 ";}; " +- "commit_ecmp_nh(ipv6 = %s, proto = sctp); next;", +- ct_ecmp_reply_port_match, out_port->sb->tunnel_key, +- IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "false" : "true"); ++ "next;", ++ ct_ecmp_reply_port_match, out_port->sb->tunnel_key); + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 100, + ds_cstr(&match), ds_cstr(&actions), + &st_route->header_); + + ds_clear(&match); + ds_put_format(&match, +- "%s && (!ct.rpl && ct.est) && tcp && "REGBIT_KNOWN_ECMP_NH" == 0", ++ "%s && (!ct.rpl && ct.est) && tcp", + ds_cstr(&base_match)); + ds_clear(&actions); + ds_put_format(&actions, + "ct_commit { ct_label.ecmp_reply_eth = eth.src; " + " %s = %" PRId64 ";}; " +- "commit_ecmp_nh(ipv6 = %s, proto = tcp); next;", +- ct_ecmp_reply_port_match, out_port->sb->tunnel_key, +- IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "false" : "true"); ++ "next;", ++ ct_ecmp_reply_port_match, out_port->sb->tunnel_key); + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 100, + ds_cstr(&match), ds_cstr(&actions), + &st_route->header_); + + ds_clear(&match); + ds_put_format(&match, +- "%s && (!ct.rpl && ct.est) && udp && "REGBIT_KNOWN_ECMP_NH" == 0", ++ "%s && (!ct.rpl && ct.est) && udp", + ds_cstr(&base_match)); + ds_clear(&actions); + ds_put_format(&actions, + "ct_commit { ct_label.ecmp_reply_eth = eth.src; " + " %s = %" PRId64 ";}; " +- "commit_ecmp_nh(ipv6 = %s, proto = udp); next;", +- ct_ecmp_reply_port_match, out_port->sb->tunnel_key, +- IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "false" : "true"); ++ "next;", ++ ct_ecmp_reply_port_match, out_port->sb->tunnel_key); + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 100, + ds_cstr(&match), ds_cstr(&actions), + &st_route->header_); + ds_clear(&match); + ds_put_format(&match, +- "%s && (!ct.rpl && ct.est) && sctp && "REGBIT_KNOWN_ECMP_NH" == 0", ++ "%s && (!ct.rpl && ct.est) && sctp", + ds_cstr(&base_match)); + ds_clear(&actions); + ds_put_format(&actions, + "ct_commit { ct_label.ecmp_reply_eth = eth.src; " + " %s = %" PRId64 ";}; " +- "commit_ecmp_nh(ipv6 = %s, proto = sctp); next;", +- ct_ecmp_reply_port_match, out_port->sb->tunnel_key, +- IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "false" : "true"); ++ "next;", ++ ct_ecmp_reply_port_match, out_port->sb->tunnel_key); + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 100, + ds_cstr(&match), ds_cstr(&actions), + &st_route->header_); +@@ -10428,7 +10418,7 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, + * for where to route the packet. + */ + ds_put_format(&ecmp_reply, +- "ct.rpl && "REGBIT_KNOWN_ECMP_NH" == 1 && %s == %"PRId64, ++ "ct.rpl && %s == %"PRId64, + ct_ecmp_reply_port_match, out_port->sb->tunnel_key); + ds_clear(&match); + ds_put_format(&match, "%s && %s", ds_cstr(&ecmp_reply), +@@ -10853,6 +10843,10 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, + { + bool ipv4 = lb_vip->address_family == AF_INET; + const char *ip_match = ipv4 ? "ip4" : "ip6"; ++ char *aff_action[LROUTER_NAT_LB_FLOW_MAX] = { ++ [LROUTER_NAT_LB_FLOW_SKIP_SNAT] = "flags.skip_snat_for_lb = 1; ", ++ [LROUTER_NAT_LB_FLOW_FORCE_SNAT] = "flags.force_snat_for_lb = 1; ", ++ }; + + int prio = 110; + +@@ -10925,15 +10919,13 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, + ctx.new_action[LROUTER_NAT_LB_FLOW_SKIP_SNAT] = ds_cstr(&skip_snat_act); + ctx.new_action[LROUTER_NAT_LB_FLOW_FORCE_SNAT] = ds_cstr(&force_snat_act); + +- enum { +- LROUTER_NAT_LB_AFF = LROUTER_NAT_LB_FLOW_MAX, +- LROUTER_NAT_LB_AFF_FORCE_SNAT = LROUTER_NAT_LB_FLOW_MAX + 1, +- }; +- unsigned long *dp_bitmap[LROUTER_NAT_LB_FLOW_MAX + 2]; ++ unsigned long *gw_dp_bitmap[LROUTER_NAT_LB_FLOW_MAX]; ++ unsigned long *aff_dp_bitmap[LROUTER_NAT_LB_FLOW_MAX]; + + size_t bitmap_len = ods_size(lr_datapaths); +- for (size_t i = 0; i < LROUTER_NAT_LB_FLOW_MAX + 2; i++) { +- dp_bitmap[i] = bitmap_allocate(bitmap_len); ++ for (size_t i = 0; i < LROUTER_NAT_LB_FLOW_MAX; i++) { ++ gw_dp_bitmap[i] = bitmap_allocate(bitmap_len); ++ aff_dp_bitmap[i] = bitmap_allocate(bitmap_len); + } + + /* Group gw router since we do not have datapath dependency in +@@ -10954,18 +10946,13 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, + } + + if (!od->n_l3dgw_ports) { +- bitmap_set1(dp_bitmap[type], index); ++ bitmap_set1(gw_dp_bitmap[type], index); + } else { + build_distr_lrouter_nat_flows_for_lb(&ctx, type, od); + } + + if (lb->affinity_timeout) { +- if (!lport_addresses_is_empty(&od->lb_force_snat_addrs) || +- od->lb_force_snat_router_ip) { +- bitmap_set1(dp_bitmap[LROUTER_NAT_LB_AFF_FORCE_SNAT], index); +- } else { +- bitmap_set1(dp_bitmap[LROUTER_NAT_LB_AFF], index); +- } ++ bitmap_set1(aff_dp_bitmap[type], index); + } + + if (sset_contains(&od->external_ips, lb_vip->vip_str)) { +@@ -10988,33 +10975,20 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, + + for (size_t type = 0; type < LROUTER_NAT_LB_FLOW_MAX; type++) { + build_gw_lrouter_nat_flows_for_lb(&ctx, type, lr_datapaths, +- dp_bitmap[type]); ++ gw_dp_bitmap[type]); ++ build_lb_affinity_lr_flows(lflows, lb, lb_vip, ds_cstr(match), ++ aff_action[type], aff_dp_bitmap[type], ++ lr_datapaths); + } + +- /* LB affinity flows for datapaths where CMS has specified +- * force_snat_for_lb floag option. +- */ +- build_lb_affinity_lr_flows(lflows, lb, lb_vip, ds_cstr(match), +- "flags.force_snat_for_lb = 1; ", +- dp_bitmap[LROUTER_NAT_LB_AFF_FORCE_SNAT], +- lr_datapaths); +- +- /* LB affinity flows for datapaths where CMS has specified +- * skip_snat_for_lb floag option or regular datapaths. +- */ +- char *lb_aff_action = +- lb->skip_snat ? "flags.skip_snat_for_lb = 1; " : NULL; +- build_lb_affinity_lr_flows(lflows, lb, lb_vip, ds_cstr(match), +- lb_aff_action, dp_bitmap[LROUTER_NAT_LB_AFF], +- lr_datapaths); +- + ds_destroy(&unsnat_match); + ds_destroy(&undnat_match); + ds_destroy(&skip_snat_act); + ds_destroy(&force_snat_act); + +- for (size_t i = 0; i < LROUTER_NAT_LB_FLOW_MAX + 2; i++) { +- bitmap_free(dp_bitmap[i]); ++ for (size_t i = 0; i < LROUTER_NAT_LB_FLOW_MAX; i++) { ++ bitmap_free(gw_dp_bitmap[i]); ++ bitmap_free(aff_dp_bitmap[i]); + } + } + +@@ -11761,7 +11735,13 @@ build_gateway_get_l2_hdr_size(struct ovn_port *op) + struct ovn_port *localnet_port = peer->od->localnet_ports[i]; + const struct nbrec_logical_switch_port *nbsp = localnet_port->nbsp; + +- if (nbsp && nbsp->n_tag_request > 0) { ++ if (!nbsp || !nbsp->tag_request) { ++ continue; ++ } ++ ++ if (nbsp->tag_request[0] || ++ (nbsp->parent_name && nbsp->parent_name[0])) { ++ /* Valid tag. */ + return VLAN_ETH_HEADER_LEN; + } + } +diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at +index 35c79cd69..60cb947c4 100644 +--- a/tests/ovn-northd.at ++++ b/tests/ovn-northd.at +@@ -6193,6 +6193,23 @@ AT_CHECK([grep "lr_in_admission" lr0flows | grep -e "check_pkt_larger" | sort], + table=0 (lr_in_admission ), priority=50 , match=(eth.mcast && inport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1518); xreg0[[0..47]] = 00:00:20:20:12:13; next;) + ]) + ++# tag 0 requires a parent port ++check ovn-nbctl --wait=sb set Logical_Switch_Port ext-port tag_request=0 ++ ++ovn-sbctl dump-flows lr0 > lr0flows ++AT_CHECK([grep "lr_in_admission" lr0flows | grep -e "check_pkt_larger" | sort], [0], [dnl ++ table=0 (lr_in_admission ), priority=50 , match=(eth.dst == 00:00:20:20:12:13 && inport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); xreg0[[0..47]] = 00:00:20:20:12:13; next;) ++ table=0 (lr_in_admission ), priority=50 , match=(eth.mcast && inport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1514); xreg0[[0..47]] = 00:00:20:20:12:13; next;) ++]) ++ ++check ovn-nbctl --wait=sb set Logical_Switch_Port ext-port parent_name=ext-parent-port ++ ++ovn-sbctl dump-flows lr0 > lr0flows ++AT_CHECK([grep "lr_in_admission" lr0flows | grep -e "check_pkt_larger" | sort], [0], [dnl ++ table=0 (lr_in_admission ), priority=50 , match=(eth.dst == 00:00:20:20:12:13 && inport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1518); xreg0[[0..47]] = 00:00:20:20:12:13; next;) ++ table=0 (lr_in_admission ), priority=50 , match=(eth.mcast && inport == "lr0-public"), action=(reg9[[1]] = check_pkt_larger(1518); xreg0[[0..47]] = 00:00:20:20:12:13; next;) ++]) ++ + AT_CLEANUP + ]) + +@@ -6236,24 +6253,16 @@ AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | sed 's/192\.168\.0\..0/192. + table=??(lr_in_ip_routing_ecmp), priority=150 , match=(reg8[[0..15]] == 0), action=(next;) + ]) + +-AT_CHECK([grep -e "lr_in_ecmp_stateful".*commit_ecmp_nh lr0flows | sed 's/table=../table=??/' | sort], [0], [dnl +- table=??(lr_in_ecmp_stateful), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1 && (!ct.rpl && ct.est) && sctp && reg9[[5]] == 0), action=(ct_commit { ct_label.ecmp_reply_eth = eth.src; ct_label.ecmp_reply_port = 1;}; commit_ecmp_nh(ipv6 = false, proto = sctp); next;) +- table=??(lr_in_ecmp_stateful), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1 && (!ct.rpl && ct.est) && tcp && reg9[[5]] == 0), action=(ct_commit { ct_label.ecmp_reply_eth = eth.src; ct_label.ecmp_reply_port = 1;}; commit_ecmp_nh(ipv6 = false, proto = tcp); next;) +- table=??(lr_in_ecmp_stateful), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1 && (!ct.rpl && ct.est) && udp && reg9[[5]] == 0), action=(ct_commit { ct_label.ecmp_reply_eth = eth.src; ct_label.ecmp_reply_port = 1;}; commit_ecmp_nh(ipv6 = false, proto = udp); next;) +- table=??(lr_in_ecmp_stateful), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1 && (ct.new && !ct.est) && sctp), action=(ct_commit { ct_label.ecmp_reply_eth = eth.src; ct_label.ecmp_reply_port = 1;}; commit_ecmp_nh(ipv6 = false, proto = sctp); next;) +- table=??(lr_in_ecmp_stateful), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1 && (ct.new && !ct.est) && tcp), action=(ct_commit { ct_label.ecmp_reply_eth = eth.src; ct_label.ecmp_reply_port = 1;}; commit_ecmp_nh(ipv6 = false, proto = tcp); next;) +- table=??(lr_in_ecmp_stateful), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1 && (ct.new && !ct.est) && udp), action=(ct_commit { ct_label.ecmp_reply_eth = eth.src; ct_label.ecmp_reply_port = 1;}; commit_ecmp_nh(ipv6 = false, proto = udp); next;) +-]) +- +-AT_CHECK([grep -e "lr_in_defrag".*chk_ecmp_nh* lr0flows | sed 's/table=../table=??/' | sort], [0], [dnl +- table=??(lr_in_defrag ), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1), action=(reg9[[5]] = chk_ecmp_nh_mac(); ct_next;) +- table=??(lr_in_defrag ), priority=100 , match=(reg7 == 0 && ip4.dst == 1.0.0.1/32), action=(reg9[[5]] = chk_ecmp_nh(); ct_next;) ++AT_CHECK([grep -e "lr_in_defrag" lr0flows | sed 's/table=../table=??/' | sort], [0], [dnl ++ table=??(lr_in_defrag ), priority=0 , match=(1), action=(next;) ++ table=??(lr_in_defrag ), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1), action=(ct_next;) ++ table=??(lr_in_defrag ), priority=100 , match=(reg7 == 0 && ip4.dst == 1.0.0.1/32), action=(ct_next;) + ]) + + dnl The chassis was created with other_config:ct-no-masked-label=false, the flows + dnl should be using ct_label.ecmp_reply_port. + AT_CHECK([grep -e "lr_in_arp_resolve.*ecmp" lr0flows | sed 's/table=../table=??/'], [0], [dnl +- table=??(lr_in_arp_resolve ), priority=200 , match=(ct.rpl && reg9[[5]] == 1 && ct_label.ecmp_reply_port == 1), action=(push(xxreg1); xxreg1 = ct_label; eth.dst = xxreg1[[32..79]]; pop(xxreg1); next;) ++ table=??(lr_in_arp_resolve ), priority=200 , match=(ct.rpl && ct_label.ecmp_reply_port == 1), action=(push(xxreg1); xxreg1 = ct_label; eth.dst = xxreg1[[32..79]]; pop(xxreg1); next;) + ]) + + dnl Simulate an ovn-controller upgrade to a version that supports +@@ -6263,7 +6272,7 @@ check ovn-sbctl set chassis ch1 other_config:ct-no-masked-label=true + check ovn-nbctl --wait=sb sync + ovn-sbctl dump-flows lr0 > lr0flows + AT_CHECK([grep -e "lr_in_arp_resolve.*ecmp" lr0flows | sed 's/table=../table=??/'], [0], [dnl +- table=??(lr_in_arp_resolve ), priority=200 , match=(ct.rpl && reg9[[5]] == 1 && ct_mark.ecmp_reply_port == 1), action=(push(xxreg1); xxreg1 = ct_label; eth.dst = xxreg1[[32..79]]; pop(xxreg1); next;) ++ table=??(lr_in_arp_resolve ), priority=200 , match=(ct.rpl && ct_mark.ecmp_reply_port == 1), action=(push(xxreg1); xxreg1 = ct_label; eth.dst = xxreg1[[32..79]]; pop(xxreg1); next;) + ]) + + # add ecmp route with wrong nexthop +@@ -8807,6 +8816,26 @@ AT_CHECK([grep "lr_in_dnat " R1flows_force_snat | sed 's/table=../table=??/' | s + table=??(lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) + ]) + ++AS_BOX([Test LR flows - lb_force_snat_ip="172.16.0.1" + skip_snat=true]) ++check ovn-nbctl --wait=sb set logical_router R1 options:lb_force_snat_ip="172.16.0.1" ++check ovn-nbctl --wait=sb set load_balancer lb0 options:skip_snat=true ++ ++ovn-sbctl dump-flows R1 > R1flows_force_skip_snat ++AT_CAPTURE_FILE([R1flows_force_skip_snat]) ++ ++AT_CHECK([grep "lr_in_dnat " R1flows_force_skip_snat | sed 's/table=../table=??/' | sort], [0], [dnl ++ table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) ++ table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && tcp && tcp.dst == 80), action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);) ++ table=??(lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4 && reg4 == 10.0.0.2 && reg8[[0..15]] == 80), action=(reg0 = 172.16.0.10; flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80; skip_snat);) ++ table=??(lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4 && reg4 == 20.0.0.2 && reg8[[0..15]] == 80), action=(reg0 = 172.16.0.10; flags.skip_snat_for_lb = 1; ct_lb_mark(backends=20.0.0.2:80; skip_snat);) ++ table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted), action=(next;) ++ table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;) ++ table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) ++ table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) ++ table=??(lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;) ++ table=??(lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ++]) ++ + AT_CLEANUP + ]) + +diff --git a/tests/ovn.at b/tests/ovn.at +index 48dbc3347..acda8514e 100644 +--- a/tests/ovn.at ++++ b/tests/ovn.at +@@ -34023,10 +34023,10 @@ echo " table=74, priority=80,arp,reg14=0x$sw0p1_key,metadata=0x1 actions=load:0x + table=74, priority=80,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=255,icmp_type=135 actions=load:0->NXM_NX_REG10[[12]] + table=74, priority=80,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=255,icmp_type=136 actions=load:0x1->NXM_NX_REG10[[12]] + table=74, priority=90,arp,reg14=0x$sw0p1_key,metadata=0x1,dl_src=00:00:00:00:00:03,arp_sha=00:00:00:00:00:03 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=225,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=225,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:03 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=225,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=225,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:03 actions=load:0->NXM_NX_REG10[[12]]" > hv1_t74_flows.expected ++ table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:03 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:03 actions=load:0->NXM_NX_REG10[[12]]" > hv1_t74_flows.expected + + check_port_sec_offlows hv1 74 + +@@ -34060,12 +34060,12 @@ echo " table=74, priority=80,arp,reg14=0x$sw0p1_key,metadata=0x1 actions=load:0x + table=74, priority=80,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=255,icmp_type=136 actions=load:0x1->NXM_NX_REG10[[12]] + table=74, priority=90,arp,reg14=0x$sw0p1_key,metadata=0x1,dl_src=00:00:00:00:00:03,arp_spa=10.0.0.3,arp_sha=00:00:00:00:00:03 actions=load:0->NXM_NX_REG10[[12]] + table=74, priority=90,arp,reg14=0x$sw0p1_key,metadata=0x1,dl_src=00:00:00:00:00:13,arp_spa=10.0.0.13,arp_sha=00:00:00:00:00:13 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=225,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=225,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:03 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=225,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:13 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=225,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=225,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:03 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=225,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:13 actions=load:0->NXM_NX_REG10[[12]]" > hv1_t74_flows.expected ++ table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:03 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:13 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:03 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p1_key,metadata=0x1,nw_ttl=255,icmp_type=136,icmp_code=0,nd_tll=00:00:00:00:00:13 actions=load:0->NXM_NX_REG10[[12]]" > hv1_t74_flows.expected + + check_port_sec_offlows hv1 74 + +@@ -34144,13 +34144,13 @@ echo " table=74, priority=80,arp,reg14=0x$sw0p2_key,metadata=0x1 actions=load:0x + table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,dl_src=00:00:00:00:00:04,icmp_type=136,icmp_code=0,nd_target=2000::/64,nd_tll=00:00:00:00:00:04 actions=load:0->NXM_NX_REG10[[12]] + table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,dl_src=00:00:00:00:00:13,icmp_type=136,icmp_code=0,nd_target=aef0::4,nd_tll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] + table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,dl_src=00:00:00:00:00:13,icmp_type=136,icmp_code=0,nd_target=aef0::4,nd_tll=00:00:00:00:00:13 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=225,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=225,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:04 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=225,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:13 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=225,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:13,nd_tll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=225,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:13,nd_tll=00:00:00:00:00:13 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=225,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:4,nd_tll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] +- table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=225,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:4,nd_tll=00:00:00:00:00:04 actions=load:0->NXM_NX_REG10[[12]]" > hv2_t74_flows.expected ++ table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:04 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=255,icmp_type=135,icmp_code=0,nd_sll=00:00:00:00:00:13 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:13,nd_tll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:13,nd_tll=00:00:00:00:00:13 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:4,nd_tll=00:00:00:00:00:00 actions=load:0->NXM_NX_REG10[[12]] ++ table=74, priority=90,icmp6,reg14=0x$sw0p2_key,metadata=0x1,nw_ttl=255,icmp_type=136,icmp_code=0,nd_target=fe80::200:ff:fe00:4,nd_tll=00:00:00:00:00:04 actions=load:0->NXM_NX_REG10[[12]]" > hv2_t74_flows.expected + + check_port_sec_offlows hv2 74 + +diff --git a/utilities/checkpatch.py b/utilities/checkpatch.py +index da3224bbc..5467d604d 100755 +--- a/utilities/checkpatch.py ++++ b/utilities/checkpatch.py +@@ -196,7 +196,7 @@ skip_signoff_check = False + # + # Python isn't checked as flake8 performs these checks during build. + line_length_blacklist = re.compile( +- r'\.(am|at|etc|in|m4|mk|patch|py)$|^debian/.*$') ++ r'\.(am|at|etc|in|m4|mk|patch|py|yml)$|^debian/.*$') + + # Don't enforce a requirement that leading whitespace be all spaces on + # files that include these characters in their name, since these kinds diff --git a/SPECS/ovn23.03.spec b/SPECS/ovn23.03.spec deleted file mode 100644 index de8ca26..0000000 --- a/SPECS/ovn23.03.spec +++ /dev/null @@ -1,790 +0,0 @@ -# Copyright (C) 2009, 2010, 2013, 2014 Nicira Networks, Inc. -# -# Copying and distribution of this file, with or without modification, -# are permitted in any medium without royalty provided the copyright -# notice and this notice are preserved. This file is offered as-is, -# without warranty of any kind. -# -# If tests have to be skipped while building, specify the '--without check' -# option. For example: -# rpmbuild -bb --without check rhel/openvswitch-fedora.spec - -# This defines the base package name's version. - -%define pkgver 2.13 -%define pkgname ovn23.03 - -# If libcap-ng isn't available and there is no need for running OVS -# as regular user, specify the '--without libcapng' -%bcond_without libcapng - -# Enable PIE, bz#955181 -%global _hardened_build 1 - -# RHEL-7 doesn't define _rundir macro yet -# Fedora 15 onwards uses /run as _rundir -%if 0%{!?_rundir:1} -%define _rundir /run -%endif - -# Build python2 (that provides python) and python3 subpackages on Fedora -# Build only python3 (that provides python) subpackage on RHEL8 -# Build only python subpackage on RHEL7 -%if 0%{?rhel} > 7 || 0%{?fedora} -# On RHEL8 Sphinx is included in buildroot -%global external_sphinx 1 -%else -# Don't use external sphinx (RHV doesn't have optional repositories enabled) -%global external_sphinx 0 -%endif - -# We would see rpmlinit error - E: hardcoded-library-path in '% {_prefix}/lib'. -# But there is no solution to fix this. Using {_lib} macro will solve the -# rpmlink error, but will install the files in /usr/lib64/. -# OVN pacemaker ocf script file is copied in /usr/lib/ocf/resource.d/ovn/ -# and we are not sure if pacemaker looks into this path to find the -# OVN resource agent script. -%global ovnlibdir %{_prefix}/lib - -Name: %{pkgname} -Summary: Open Virtual Network support -Group: System Environment/Daemons -URL: http://www.ovn.org/ -Version: 23.03.0 -Release: 69%{?commit0:.%{date}git%{shortcommit0}}%{?dist} -Provides: openvswitch%{pkgver}-ovn-common = %{?epoch:%{epoch}:}%{version}-%{release} -Obsoletes: openvswitch%{pkgver}-ovn-common < 2.11.0-1 - -# Nearly all of openvswitch is ASL 2.0. The bugtool is LGPLv2+, and the -# lib/sflow*.[ch] files are SISSL -License: ASL 2.0 and LGPLv2+ and SISSL - -# Always pull an upstream release, since this is what we rebase to. -Source: https://github.com/ovn-org/ovn/archive/v%{version}.tar.gz#/ovn-%{version}.tar.gz - -%define ovscommit 8986d4d5564401eeef3dea828b51fe8bae2cc8aa -%define ovsshortcommit 8986d4d - -Source10: https://github.com/openvswitch/ovs/archive/%{ovscommit}.tar.gz#/openvswitch-%{ovsshortcommit}.tar.gz -%define ovsdir ovs-%{ovscommit} - -%define docutilsver 0.12 -%define pygmentsver 1.4 -%define sphinxver 1.1.3 -Source100: https://pypi.io/packages/source/d/docutils/docutils-%{docutilsver}.tar.gz -Source101: https://pypi.io/packages/source/P/Pygments/Pygments-%{pygmentsver}.tar.gz -Source102: https://pypi.io/packages/source/S/Sphinx/Sphinx-%{sphinxver}.tar.gz - -Source500: configlib.sh -Source501: gen_config_group.sh -Source502: set_config.sh - -# Important: source503 is used as the actual copy file -# @TODO: this causes a warning - fix it? -Source504: arm64-armv8a-linuxapp-gcc-config -Source505: ppc_64-power8-linuxapp-gcc-config -Source506: x86_64-native-linuxapp-gcc-config - -Patch: %{pkgname}.patch - -# FIXME Sphinx is used to generate some manpages, unfortunately, on RHEL, it's -# in the -optional repository and so we can't require it directly since RHV -# doesn't have the -optional repository enabled and so TPS fails -%if %{external_sphinx} -BuildRequires: python3-sphinx -%else -# Sphinx dependencies -BuildRequires: python-devel -BuildRequires: python-setuptools -#BuildRequires: python2-docutils -BuildRequires: python-jinja2 -BuildRequires: python-nose -#BuildRequires: python2-pygments -# docutils dependencies -BuildRequires: python-imaging -# pygments dependencies -BuildRequires: python-nose -%endif - -BuildRequires: gcc gcc-c++ make -BuildRequires: autoconf automake libtool -BuildRequires: systemd-units openssl openssl-devel -BuildRequires: python3-devel python3-setuptools -BuildRequires: desktop-file-utils -BuildRequires: groff-base graphviz -BuildRequires: unbound-devel - -# make check dependencies -BuildRequires: procps-ng -%if 0%{?rhel} == 8 || 0%{?fedora} -BuildRequires: python3-pyOpenSSL -%endif -BuildRequires: tcpdump - -%if %{with libcapng} -BuildRequires: libcap-ng libcap-ng-devel -%endif - -Requires: hostname openssl iproute module-init-tools - -Requires(post): systemd-units -Requires(preun): systemd-units -Requires(postun): systemd-units - -# to skip running checks, pass --without check -%bcond_without check - -%description -OVN, the Open Virtual Network, is a system to support virtual network -abstraction. OVN complements the existing capabilities of OVS to add -native support for virtual network abstractions, such as virtual L2 and L3 -overlays and security groups. - -%package central -Summary: Open Virtual Network support -License: ASL 2.0 -Requires: %{pkgname} -Requires: firewalld-filesystem -Provides: openvswitch%{pkgver}-ovn-central = %{?epoch:%{epoch}:}%{version}-%{release} -Obsoletes: openvswitch%{pkgver}-ovn-central < 2.11.0-1 - -%description central -OVN DB servers and ovn-northd running on a central node. - -%package host -Summary: Open Virtual Network support -License: ASL 2.0 -Requires: %{pkgname} -Requires: firewalld-filesystem -Provides: openvswitch%{pkgver}-ovn-host = %{?epoch:%{epoch}:}%{version}-%{release} -Obsoletes: openvswitch%{pkgver}-ovn-host < 2.11.0-1 - -%description host -OVN controller running on each host. - -%package vtep -Summary: Open Virtual Network support -License: ASL 2.0 -Requires: %{pkgname} -Provides: openvswitch%{pkgver}-ovn-vtep = %{?epoch:%{epoch}:}%{version}-%{release} -Obsoletes: openvswitch%{pkgver}-ovn-vtep < 2.11.0-1 - -%description vtep -OVN vtep controller - -%prep -%autosetup -n ovn-%{version} -a 10 -p 1 - -%build -%if 0%{?commit0:1} -# fix the snapshot unreleased version to be the released one. -sed -i.old -e "s/^AC_INIT(openvswitch,.*,/AC_INIT(openvswitch, %{version},/" configure.ac -%endif -./boot.sh - -# OVN source code is now separate. -# Build openvswitch first. -# XXX Current openvswitch2.13 doesn't -# use "2.13.0" for version. It's a commit hash -pushd %{ovsdir} -./boot.sh -%configure \ -%if %{with libcapng} - --enable-libcapng \ -%else - --disable-libcapng \ -%endif - --enable-ssl \ - --with-pkidir=%{_sharedstatedir}/openvswitch/pki - -make %{?_smp_mflags} -popd - -# Build OVN. -# XXX OVS version needs to be updated when ovs2.13 is updated. -%configure \ - --with-ovs-source=$PWD/%{ovsdir} \ -%if %{with libcapng} - --enable-libcapng \ -%else - --disable-libcapng \ -%endif - --enable-ssl \ - --with-pkidir=%{_sharedstatedir}/openvswitch/pki - -make %{?_smp_mflags} - -%install -%make_install -install -p -D -m 0644 \ - rhel/usr_share_ovn_scripts_systemd_sysconfig.template \ - $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/ovn - -for service in ovn-controller ovn-controller-vtep ovn-northd; do - install -p -D -m 0644 \ - rhel/usr_lib_systemd_system_${service}.service \ - $RPM_BUILD_ROOT%{_unitdir}/${service}.service -done - -install -d -m 0755 $RPM_BUILD_ROOT/%{_sharedstatedir}/ovn - -install -d $RPM_BUILD_ROOT%{ovnlibdir}/firewalld/services/ -install -p -m 0644 rhel/usr_lib_firewalld_services_ovn-central-firewall-service.xml \ - $RPM_BUILD_ROOT%{ovnlibdir}/firewalld/services/ovn-central-firewall-service.xml -install -p -m 0644 rhel/usr_lib_firewalld_services_ovn-host-firewall-service.xml \ - $RPM_BUILD_ROOT%{ovnlibdir}/firewalld/services/ovn-host-firewall-service.xml - -install -d -m 0755 $RPM_BUILD_ROOT%{ovnlibdir}/ocf/resource.d/ovn -ln -s %{_datadir}/ovn/scripts/ovndb-servers.ocf \ - $RPM_BUILD_ROOT%{ovnlibdir}/ocf/resource.d/ovn/ovndb-servers - -install -p -D -m 0644 rhel/etc_logrotate.d_ovn \ - $RPM_BUILD_ROOT/%{_sysconfdir}/logrotate.d/ovn - -# remove unneeded files. -rm -f $RPM_BUILD_ROOT%{_bindir}/ovs* -rm -f $RPM_BUILD_ROOT%{_bindir}/vtep-ctl -rm -f $RPM_BUILD_ROOT%{_sbindir}/ovs* -rm -f $RPM_BUILD_ROOT%{_mandir}/man1/ovs* -rm -f $RPM_BUILD_ROOT%{_mandir}/man5/ovs* -rm -f $RPM_BUILD_ROOT%{_mandir}/man5/vtep* -rm -f $RPM_BUILD_ROOT%{_mandir}/man7/ovs* -rm -f $RPM_BUILD_ROOT%{_mandir}/man8/ovs* -rm -f $RPM_BUILD_ROOT%{_mandir}/man8/vtep* -rm -rf $RPM_BUILD_ROOT%{_datadir}/ovn/python -rm -f $RPM_BUILD_ROOT%{_datadir}/ovn/scripts/ovs* -rm -rf $RPM_BUILD_ROOT%{_datadir}/ovn/bugtool-plugins -rm -f $RPM_BUILD_ROOT%{_libdir}/*.a -rm -f $RPM_BUILD_ROOT%{_libdir}/*.la -rm -f $RPM_BUILD_ROOT%{_libdir}/pkgconfig/*.pc -rm -f $RPM_BUILD_ROOT%{_includedir}/ovn/* -rm -f $RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d/ovs-appctl-bashcomp.bash -rm -f $RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d/ovs-vsctl-bashcomp.bash -rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/openvswitch -rm -f $RPM_BUILD_ROOT%{_datadir}/ovn/scripts/ovn-bugtool* -rm -f $RPM_BUILD_ROOT/%{_bindir}/ovn-docker-overlay-driver \ - $RPM_BUILD_ROOT/%{_bindir}/ovn-docker-underlay-driver - -%check -%if %{with check} - touch resolv.conf - export OVS_RESOLV_CONF=$(pwd)/resolv.conf - if ! make check TESTSUITEFLAGS='%{_smp_mflags}'; then - cat tests/testsuite.log - if ! make check TESTSUITEFLAGS='--recheck'; then - cat tests/testsuite.log - # Presently a test case - "2796: ovn -- ovn-controller incremental processing" - # is failing on aarch64 arch. Let's not exit for this arch - # until we figure out why it is failing. - # Test case 93: ovn.at:12105 ovn -- ACLs on Port Groups is failing - # repeatedly on s390x. This needs to be investigated. - %ifnarch aarch64 - %ifnarch ppc64le - %ifnarch s390x - exit 1 - %endif - %endif - %endif - fi - fi -%endif - -%clean -rm -rf $RPM_BUILD_ROOT - -%pre central -if [ $1 -eq 1 ] ; then - # Package install. - /bin/systemctl status ovn-northd.service >/dev/null - ovn_status=$? - rpm -ql openvswitch-ovn-central > /dev/null - if [[ "$?" = "0" && "$ovn_status" = "0" ]]; then - # ovn-northd service is running which means old openvswitch-ovn-central - # is already installed and it will be cleaned up. So start ovn-northd - # service when posttrans central is called. - touch %{_localstatedir}/lib/rpm-state/ovn-northd - fi -fi - -%pre host -if [ $1 -eq 1 ] ; then - # Package install. - /bin/systemctl status ovn-controller.service >/dev/null - ovn_status=$? - rpm -ql openvswitch-ovn-host > /dev/null - if [[ "$?" = "0" && "$ovn_status" = "0" ]]; then - # ovn-controller service is running which means old - # openvswitch-ovn-host is installed and it will be cleaned up. So - # start ovn-controller service when posttrans host is called. - touch %{_localstatedir}/lib/rpm-state/ovn-controller - fi -fi - -%pre vtep -if [ $1 -eq 1 ] ; then - # Package install. - /bin/systemctl status ovn-controller-vtep.service >/dev/null - ovn_status=$? - rpm -ql openvswitch-ovn-vtep > /dev/null - if [[ "$?" = "0" && "$ovn_status" = "0" ]]; then - # ovn-controller-vtep service is running which means old - # openvswitch-ovn-vtep is installed and it will be cleaned up. So - # start ovn-controller-vtep service when posttrans host is called. - touch %{_localstatedir}/lib/rpm-state/ovn-controller-vtep - fi -fi - -%preun central -%if 0%{?systemd_preun:1} - %systemd_preun ovn-northd.service -%else - if [ $1 -eq 0 ] ; then - # Package removal, not upgrade - /bin/systemctl --no-reload disable ovn-northd.service >/dev/null 2>&1 || : - /bin/systemctl stop ovn-northd.service >/dev/null 2>&1 || : - fi -%endif - -%preun host -%if 0%{?systemd_preun:1} - %systemd_preun ovn-controller.service -%else - if [ $1 -eq 0 ] ; then - # Package removal, not upgrade - /bin/systemctl --no-reload disable ovn-controller.service >/dev/null 2>&1 || : - /bin/systemctl stop ovn-controller.service >/dev/null 2>&1 || : - fi -%endif - -%preun vtep -%if 0%{?systemd_preun:1} - %systemd_preun ovn-controller-vtep.service -%else - if [ $1 -eq 0 ] ; then - # Package removal, not upgrade - /bin/systemctl --no-reload disable ovn-controller-vtep.service >/dev/null 2>&1 || : - /bin/systemctl stop ovn-controller-vtep.service >/dev/null 2>&1 || : - fi -%endif - -%post -%if %{with libcapng} -if [ $1 -eq 1 ]; then - sed -i 's:^#OVN_USER_ID=:OVN_USER_ID=:' %{_sysconfdir}/sysconfig/ovn - sed -i 's:\(.*su\).*:\1 openvswitch openvswitch:' %{_sysconfdir}/logrotate.d/ovn -fi -%endif - -%post central -%if 0%{?systemd_post:1} - %systemd_post ovn-northd.service -%else - # Package install, not upgrade - if [ $1 -eq 1 ]; then - /bin/systemctl daemon-reload >dev/null || : - fi -%endif - -%post host -%if 0%{?systemd_post:1} - %systemd_post ovn-controller.service -%else - # Package install, not upgrade - if [ $1 -eq 1 ]; then - /bin/systemctl daemon-reload >dev/null || : - fi -%endif - -%post vtep -%if 0%{?systemd_post:1} - %systemd_post ovn-controller-vtep.service -%else - # Package install, not upgrade - if [ $1 -eq 1 ]; then - /bin/systemctl daemon-reload >dev/null || : - fi -%endif - -%postun - -%postun central -%if 0%{?systemd_postun_with_restart:1} - %systemd_postun_with_restart ovn-northd.service -%else - /bin/systemctl daemon-reload >/dev/null 2>&1 || : - if [ "$1" -ge "1" ] ; then - # Package upgrade, not uninstall - /bin/systemctl try-restart ovn-northd.service >/dev/null 2>&1 || : - fi -%endif - -%postun host -%if 0%{?systemd_postun_with_restart:1} - %systemd_postun_with_restart ovn-controller.service -%else - /bin/systemctl daemon-reload >/dev/null 2>&1 || : - if [ "$1" -ge "1" ] ; then - # Package upgrade, not uninstall - /bin/systemctl try-restart ovn-controller.service >/dev/null 2>&1 || : - fi -%endif - -%postun vtep -%if 0%{?systemd_postun_with_restart:1} - %systemd_postun_with_restart ovn-controller-vtep.service -%else - /bin/systemctl daemon-reload >/dev/null 2>&1 || : - if [ "$1" -ge "1" ] ; then - # Package upgrade, not uninstall - /bin/systemctl try-restart ovn-controller-vtep.service >/dev/null 2>&1 || : - fi -%endif - -%posttrans central -if [ $1 -eq 1 ]; then - # Package install, not upgrade - if [ -e %{_localstatedir}/lib/rpm-state/ovn-northd ]; then - rm %{_localstatedir}/lib/rpm-state/ovn-northd - /bin/systemctl start ovn-northd.service >/dev/null 2>&1 || : - fi -fi - - -%posttrans host -if [ $1 -eq 1 ]; then - # Package install, not upgrade - if [ -e %{_localstatedir}/lib/rpm-state/ovn-controller ]; then - rm %{_localstatedir}/lib/rpm-state/ovn-controller - /bin/systemctl start ovn-controller.service >/dev/null 2>&1 || : - fi -fi - -%posttrans vtep -if [ $1 -eq 1 ]; then - # Package install, not upgrade - if [ -e %{_localstatedir}/lib/rpm-state/ovn-controller-vtep ]; then - rm %{_localstatedir}/lib/rpm-state/ovn-controller-vtep - /bin/systemctl start ovn-controller-vtep.service >/dev/null 2>&1 || : - fi -fi - -%files -%{_bindir}/ovn-nbctl -%{_bindir}/ovn-sbctl -%{_bindir}/ovn-trace -%{_bindir}/ovn-detrace -%{_bindir}/ovn_detrace.py -%{_bindir}/ovn-appctl -%{_bindir}/ovn-ic-nbctl -%{_bindir}/ovn-ic-sbctl -%dir %{_datadir}/ovn/ -%dir %{_datadir}/ovn/scripts/ -%{_datadir}/ovn/scripts/ovn-ctl -%{_datadir}/ovn/scripts/ovn-lib -%{_datadir}/ovn/scripts/ovndb-servers.ocf -%{_mandir}/man8/ovn-ctl.8* -%{_mandir}/man8/ovn-appctl.8* -%{_mandir}/man8/ovn-nbctl.8* -%{_mandir}/man8/ovn-ic-nbctl.8* -%{_mandir}/man8/ovn-trace.8* -%{_mandir}/man1/ovn-detrace.1* -%{_mandir}/man7/ovn-architecture.7* -%{_mandir}/man8/ovn-sbctl.8* -%{_mandir}/man8/ovn-ic-sbctl.8* -%{_mandir}/man5/ovn-nb.5* -%{_mandir}/man5/ovn-ic-nb.5* -%{_mandir}/man5/ovn-sb.5* -%{_mandir}/man5/ovn-ic-sb.5* -%dir %{ovnlibdir}/ocf/resource.d/ovn/ -%{ovnlibdir}/ocf/resource.d/ovn/ovndb-servers -%config(noreplace) %verify(not md5 size mtime) %{_sysconfdir}/logrotate.d/ovn -%config(noreplace) %verify(not md5 size mtime) %{_sysconfdir}/sysconfig/ovn - -%files central -%{_bindir}/ovn-northd -%{_bindir}/ovn-ic -%{_mandir}/man8/ovn-northd.8* -%{_mandir}/man8/ovn-ic.8* -%{_datadir}/ovn/ovn-nb.ovsschema -%{_datadir}/ovn/ovn-ic-nb.ovsschema -%{_datadir}/ovn/ovn-sb.ovsschema -%{_datadir}/ovn/ovn-ic-sb.ovsschema -%{_unitdir}/ovn-northd.service -%{ovnlibdir}/firewalld/services/ovn-central-firewall-service.xml - -%files host -%{_bindir}/ovn-controller -%{_mandir}/man8/ovn-controller.8* -%{_unitdir}/ovn-controller.service -%{ovnlibdir}/firewalld/services/ovn-host-firewall-service.xml - -%files vtep -%{_bindir}/ovn-controller-vtep -%{_mandir}/man8/ovn-controller-vtep.8* -%{_unitdir}/ovn-controller-vtep.service - -%changelog -* Fri Jun 09 2023 Igor Zhukov - 23.03.0-69 -- call ovsrcu_exit() before exit in ovn-northd and ovn-controller to make valgrind happy -[Upstream: a3aba935cda359db5d9c99e8ea9ba688e4f888bc] - -* Thu Jun 08 2023 Dumitru Ceara - 23.03.0-68 -- controller: Turn OFTABLE_OUTPUT_INIT into an alias. -[Upstream: 8c274866a29534c6ecb80f0242798edbb078bfda] - -* Thu Jun 08 2023 Ihar Hrachyshka - 23.03.0-67 -- Implement MTU Path Discovery for multichassis ports -[Upstream: 44e07200a8f04b70bbcba20d2b5346aa840b4f40] - -* Thu Jun 08 2023 Ihar Hrachyshka - 23.03.0-66 -- Add new egress tables to accommodate for too-big packets handling -[Upstream: 44d6692e28478e4e971de09045f42cc5c3000540] - -* Thu Jun 08 2023 Ihar Hrachyshka - 23.03.0-65 -- if-status: track interfaces for additional chassis -[Upstream: 57f15c6d78b4fbcd9ead81328e06a714b75942f0] - -* Thu Jun 08 2023 Ihar Hrachyshka - 23.03.0-64 -- Track interface MTU in if-status-mgr -[Upstream: e6f097fe148deb3f60c2e2fc57e80f91986f248e] - -* Thu Jun 08 2023 Ihar Hrachyshka - 23.03.0-63 -- Track ip version of tunnel in chassis_tunnel struct -[Upstream: c8fccfa720b7d8e176be05bfd37fd6e74764ee3d] - -* Thu Jun 08 2023 Ales Musil - 23.03.0-62 -- northd: Add logical flow to skip GARP with LLA (#2211240) -[Upstream: dc0b0b55d93cb2516f1759b65f198485597d4575] - -* Thu Jun 08 2023 Vladislav Odintsov - 23.03.0-61 -- northd: match only on supported protocols to handle_svc_check (#1913162) -[Upstream: 822861db016d9360d6a88a486d5db8d5936e66fa] - -* Thu Jun 08 2023 Xavier Simonart - 23.03.0-60 -- tests: Fixed "nested containers" test -[Upstream: f914cf2cab4b4a872d246961c6521cd8a48f2bd3] - -* Thu Jun 08 2023 Xavier Simonart - 23.03.0-59 -- tests: fix flaky Multiple OVS interfaces bound to same logical ports -[Upstream: 8f29930c22687c3247a784e1e2fe4a6dc0fdd86c] - -* Thu Jun 08 2023 Ales Musil - 23.03.0-58 -- system-tests: Prevent flakiness in ovn mirroring -[Upstream: 352041d0fa66772d86980f46c63e023c40286723] - -* Thu Jun 08 2023 Ales Musil - 23.03.0-57 -- northd: Fix address set incremental processing (#2196885) -[Upstream: e8baef1c0fc671fe4e2d3af63de979e22a0c899d] - -* Tue May 30 2023 Brian Haley - 23.03.0-56 -- controller: Ignore DNS queries with RRs -[Upstream: 529ea698f5d1d2b7083210318cfc0a64b701ca62] - -* Tue May 30 2023 Ales Musil - 23.03.0-55 -- ci: ovn-kubernetes: Align the timeouts with u/s ovnk -[Upstream: ecc0a06af3bb47fe49ee897896af35a0efe33486] - -* Tue May 30 2023 Dumitru Ceara - 23.03.0-54 -- controller: Handle OpenFlow errors. (#2134880) -[Upstream: 158463b94f5b6c37a37d9755ba9d5ef7473d35d3] - -* Tue May 30 2023 Vladislav Odintsov - 23.03.0-53 -- controller: fix typo in comments -[Upstream: f24e9bf7b4b5822e0d37a4382fe49607c132a3ee] - -* Tue May 30 2023 Vladislav Odintsov - 23.03.0-52 -- northd: build vtep hairpin lflows only for lswitches with vtep lports -[Upstream: 222f74acea04c9ae46bb3767ff256f8249ee7ab8] - -* Tue May 30 2023 Vladislav Odintsov - 23.03.0-51 -- northd: fix ls_in_hairpin l3dgw flow generation -[Upstream: e4f8547be8774c085ef212fbed3e5e76e77d661c] - -* Fri May 26 2023 Han Zhou - 23.03.0-50 -- ovn-controller.c: Fix assertion failure during address set update. -[Upstream: 777786f38a61041898891ccbb3f139b0552e5794] - -* Fri May 19 2023 Mark Michelson - 23.03.0-49 -- Pass localnet traffic through CT when a LB is configured. (#2164652) -[Upstream: 2449608303464d62ff5b1a89e20e476248d1e82b] - -* Fri May 19 2023 Mark Michelson - 23.03.0-48 -- tests: Use stricter IP match for FORMAT_CT. -[Upstream: a1d8ebd306021844646629c42bd638203399c568] - -* Wed May 17 2023 Ales Musil - 23.03.0-47 -- tests: Fix flakiness of policy based routing on slower systems -[Upstream: bb22fe9c4591dc96d98bf2c2c3f629efb5721757] - -* Wed May 17 2023 Vladislav Odintsov - 23.03.0-46 -- ovn-controller docs: fix typo in ovn-monitor-all description -[Upstream: 0ba1609d6426cd779f48cb5a97e63c0a7811dc03] - -* Wed May 10 2023 Ales Musil - 23.03.0-45 -- system-tests: Replace use of ADD_INT with ADD_VETH -[Upstream: c2f36b530613728100b1dbdf7f967c4a87053155] - -* Wed May 10 2023 Lorenzo Bianconi - 23.03.0-44 -- controller: fix possible unaligned accesses in DHCPv6 code -[Upstream: 080cbcd95d3d065524272f5f1d0bed11df35a9d4] - -* Tue May 09 2023 Lorenzo Bianconi - 23.03.0-43 -- mirror: fix ovn mirror support with IPv6 (#2168119) -[Upstream: 5255303229f4da0c1478656597c774510ceda4e9] - -* Mon May 08 2023 Xavier Simonart - 23.03.0-42 -- ovn-controller: fixed port not always set down when unbinding interface (#2150905) -[Upstream: 39930c0254bc8758b5722e0f2c3a7fdc43256888] - -* Mon May 08 2023 Xavier Simonart - 23.03.0-41 -- ovn-controller: fixed ovn-installed not always properly added or removed. -[Upstream: 395eac485b871ef75bb0b5f29b09ebd1cb877ca8] - -* Mon May 08 2023 Wei Li - 23.03.0-40 -- documentation: packets that arrive from other chassis resubmit to table 38 -[Upstream: 4ad402df2870c44234945b462345bfcb0c95b6f6] - -* Mon May 08 2023 Tao Liu - 23.03.0-39 -- northd: fix use-after-free after lrp destroyed -[Upstream: fd0111e59c6a78acf70dd47e10e724210c2e94ea] - -* Mon May 08 2023 Ihar Hrachyshka - 23.03.0-38 -- docs: document that vxlan is supported for encap type -[Upstream: 31bc347255a9206b29dc3f9af14c8af75ea9600e] - -* Mon May 08 2023 Xavier Simonart - 23.03.0-37 -- tests: Fixed flaky lr multiple gw ports -[Upstream: 94dea8bb6bba439de673fa4fa72e3fa3f8c44593] - -* Mon May 08 2023 Xavier Simonart - 23.03.0-36 -- Fix test "load-balancing" -[Upstream: bfdfb9a0565b2f21f59120b360db1aa59b24f96d] - -* Fri May 05 2023 Dumitru Ceara - 23.03.0-35 -- tests: Retry inject-pkt in case ovn-controller is still busy. -[Upstream: d6cad0cc05f752a83f72c82881a76642301125b9] - -* Tue May 02 2023 wangchuanlei - 23.03.0-34 -- pinctrl: fix restart of controller when bfd min_tx is too low. -[Upstream: 77d0ff0dace95ce6c8453c2b95f65d18892133b6] - -* Tue May 02 2023 Ales Musil - 23.03.0-33 -- ovn-nbctl: Fix unhandled NULL return from normalize_prefix_str -[Upstream: 86ceec393a9b776990bb24625bf9ca13ce9dfe05] - -* Mon May 01 2023 Xavier Simonart - 23.03.0-32 -- tests: decrease risk of flaky failures of ovn -- CoPP system test -[Upstream: b81229835436b63a593e0e6a55bb639309101592] - -* Mon May 01 2023 Xavier Simonart - 23.03.0-31 -- tests: check arguments count of OVS_WAIT_UNTIL -[Upstream: 352c584c403ce914b59e3c3c95028949ec3ede05] - -* Mon May 01 2023 Xavier Simonart - 23.03.0-30 -- tests: Fixed wrong usage of OVS_WAIT_UNTIL -[Upstream: b88d8bbba3ba59ee0a3c2d3fb62cab748e1b59dc] - -* Mon May 01 2023 Xavier Simonart - 23.03.0-29 -- tests: Fixed "1 LR with HA distributed router gateway port" -[Upstream: 1758332a51766231e74479302ee8efdfc07bf33c] - -* Fri Apr 21 2023 Mark Michelson - 23.03.0-28 -- tests: Skip "daemon ssl files change" when SSL is disabled. -[Upstream: 3d231640d852bc4c7b49d17de80ba747bebe8817] - -* Wed Apr 19 2023 Ihar Hrachyshka - 23.03.0-27 -- Omit ACLs for nd || nd_ra || nd_rs || mldv1 || mldv2 (#2149731) -[Upstream: 6e6cc27bdb9735a6461b53771b3969a2ca230cab] - -* Wed Apr 19 2023 Ihar Hrachyshka - 23.03.0-26 -- tests: define fmt_pkt function to construct packets with scapy -[Upstream: b797e5dbd955ee61d503bb38dade490957bce563] - -* Wed Apr 19 2023 Ales Musil - 23.03.0-25 -- controller: Prevent race in tunnel cleanup -[Upstream: 40befbb1d508db48f894cb190637ee33cccf0977] - -* Thu Apr 13 2023 Han Zhou - 23.03.0-24 -- northd.c: Avoid sending ICMP time exceeded for multicast packets. -[Upstream: a38a5df4a49ddf678d6a50de39b613b8f0305e26] - -* Thu Apr 13 2023 Han Zhou - 23.03.0-23 -- northd.c: TTL discard flow should support for both ipv4 and ipv6. -[Upstream: d42d070bd2598b72c13d2a67209d368acc8128b8] - -* Tue Apr 11 2023 Ales Musil - 23.03.0-22 -- northd: Update the is_stateless helper for router nat -[Upstream: 99b42566998c9e9b952cdfe3f8435e8bd79eca43] - -* Tue Apr 11 2023 Eelco Chaudron - 23.03.0-21 -- ci: Add arping package to run floating IP tests. -[Upstream: 825164cd4164e9c9bf5c66ebe00e147f1e2ac1fd] - -* Tue Apr 11 2023 Ales Musil - 23.03.0-20 -- controller: Clear tunnels from old integration bridge (#2173635) -[Upstream: 8481abcc04fee5e0ecd881e599be178625ad1522] - -* Tue Apr 11 2023 Lorenzo Bianconi - 23.03.0-19 -- northd: revert ct.inv drop flows -[Upstream: 04d7552479736bd2da84dd5d2be146fa4a51e3e6] - -* Thu Apr 06 2023 Lorenzo Bianconi - 23.03.0-18 -- northd: take into account qos_min_rate in port_has_qos_params -[Upstream: 0bbcfb52f0248d839e413acaf2b116bb7b1c4db6] - -* Thu Mar 30 2023 Ales Musil - 23.03.0-17 -- system-tests: Reduce flakiness of netcat UDP clients -[Upstream: 6c2d80c5bb6a2cd7c353b796a7d46b3962a06c9f] - -* Tue Mar 28 2023 Dumitru Ceara - 23.03.0-16 -- Revert "DOWNSTREAM: Forcefully disable backend conntrack flushing." -[Upstream: 8c98303437610a32faff8c0e7d8eff419b40619e] - -* Tue Mar 28 2023 Xavier Simonart - 23.03.0-15 -- northd: prevents sending packet to conntrack for router ports (#2062431) -[Upstream: 2bab96e899b5da5ae0c3b24bd04ece93d1339824] - -* Tue Mar 28 2023 Dumitru Ceara - 23.03.0-14 -- lb: Allow IPv6 template LBs to use explicit backends. -[Upstream: d01fdfdb2c97222cf326c8ab5579f670ded6e3cb] - -* Tue Mar 28 2023 Lorenzo Bianconi - 23.03.0-13 -- controller: lflow: do not use tcp as default IP protocol for ct_snat_to_vip action (#2157846) -[Upstream: 6a16c741e5a10a817ca8251898f48bf9eeb971f5] - -* Tue Mar 28 2023 Ales Musil - 23.03.0-12 -- northd: Drop packets for LBs with no backends (#2177173) -[Upstream: 77384b7fe3f7d3260fd2f94a3bd75b8ca79f56ae] - -* Mon Mar 27 2023 Ales Musil - 23.03.0-11 -- northd: Use generic ct.est flows for LR LBs (#2172048 2170885) -[Upstream: 81eaa98bbb608bda320abfa0122ba073de6597d7] - -* Thu Mar 23 2023 Lorenzo Bianconi - 23.03.0-10 -- northd: drop ct.inv packets in post snat and lb_aff_learn stages (#2160685) -[Upstream: 0af110c400cc29bb037172cdfd674794716771df] - -* Mon Mar 20 2023 Ales Musil - 23.03.0-9 -- controller: Add config option per LB to enable/disable CT flush (#2178962) -[Upstream: 89fc85fa7f2b00f404ec5aef4ce8f2236474fbab] - -* Thu Mar 16 2023 Dumitru Ceara - 23.03.0-8 -- DOWNSTREAM: Forcefully disable backend conntrack flushing. (#2178962) -[Upstream: b7522be8bf28534cc422234e8d9484b9ef4220d9] - -* Thu Mar 16 2023 Dumitru Ceara - 23.03.0-7 -- northd: Ignore remote chassis when computing the supported feature set. -[Upstream: 80b7e48a877abd337eb54b9bb9c7b4280aa9ff74] - -* Wed Mar 08 2023 Ilya Maximets - 23.03.0-6 -- controller: Use ofctrl_add_flow for CT SNAT hairpin flows. -[Upstream: 888215e2164b476462f12d206a3d734958ef79e2] - -* Wed Mar 08 2023 Vladislav Odintsov - 23.03.0-5 -- rhel: pass options to stop daemon command in systemd units -[Upstream: ed7095613abf3d36cbcf347e1238b84e6843eaf1] - -* Fri Mar 03 2023 Mark Michelson - 23.03.0-4 -- Prepare for 23.03.1. -[Upstream: e98ea52f12de2a7d6a9a7547b6b0a493a78f0fed] - diff --git a/SPECS/ovn23.06.spec b/SPECS/ovn23.06.spec new file mode 100644 index 0000000..9a9a793 --- /dev/null +++ b/SPECS/ovn23.06.spec @@ -0,0 +1,560 @@ +# Copyright (C) 2009, 2010, 2013, 2014 Nicira Networks, Inc. +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. This file is offered as-is, +# without warranty of any kind. +# +# If tests have to be skipped while building, specify the '--without check' +# option. For example: +# rpmbuild -bb --without check rhel/openvswitch-fedora.spec + +# This defines the base package name's version. + +%define pkgver 2.13 +%define pkgname ovn23.06 + +# If libcap-ng isn't available and there is no need for running OVS +# as regular user, specify the '--without libcapng' +%bcond_without libcapng + +# Enable PIE, bz#955181 +%global _hardened_build 1 + +# RHEL-7 doesn't define _rundir macro yet +# Fedora 15 onwards uses /run as _rundir +%if 0%{!?_rundir:1} +%define _rundir /run +%endif + +# Build python2 (that provides python) and python3 subpackages on Fedora +# Build only python3 (that provides python) subpackage on RHEL8 +# Build only python subpackage on RHEL7 +%if 0%{?rhel} > 7 || 0%{?fedora} +# On RHEL8 Sphinx is included in buildroot +%global external_sphinx 1 +%else +# Don't use external sphinx (RHV doesn't have optional repositories enabled) +%global external_sphinx 0 +%endif + +# We would see rpmlinit error - E: hardcoded-library-path in '% {_prefix}/lib'. +# But there is no solution to fix this. Using {_lib} macro will solve the +# rpmlink error, but will install the files in /usr/lib64/. +# OVN pacemaker ocf script file is copied in /usr/lib/ocf/resource.d/ovn/ +# and we are not sure if pacemaker looks into this path to find the +# OVN resource agent script. +%global ovnlibdir %{_prefix}/lib + +Name: %{pkgname} +Summary: Open Virtual Network support +Group: System Environment/Daemons +URL: http://www.ovn.org/ +Version: 23.06.1 +Release: 11%{?commit0:.%{date}git%{shortcommit0}}%{?dist} +Provides: openvswitch%{pkgver}-ovn-common = %{?epoch:%{epoch}:}%{version}-%{release} +Obsoletes: openvswitch%{pkgver}-ovn-common < 2.11.0-1 + +# Nearly all of openvswitch is ASL 2.0. The bugtool is LGPLv2+, and the +# lib/sflow*.[ch] files are SISSL +License: ASL 2.0 and LGPLv2+ and SISSL + +%define ovncommit a20f880efdba9dcf19c1df77b31a3b8b9dffa345 + +# Always pull an upstream release, since this is what we rebase to. +Source: https://github.com/ovn-org/ovn/archive/%{ovncommit}.tar.gz#/ovn-%{version}.tar.gz + +%define ovscommit 0187eadfce4505d502e57c0e688b830f0a1ec728 +%define ovsshortcommit 0187ead + +Source10: https://github.com/openvswitch/ovs/archive/%{ovscommit}.tar.gz#/openvswitch-%{ovsshortcommit}.tar.gz +%define ovsdir ovs-%{ovscommit} + +%define docutilsver 0.12 +%define pygmentsver 1.4 +%define sphinxver 1.1.3 +Source100: https://pypi.io/packages/source/d/docutils/docutils-%{docutilsver}.tar.gz +Source101: https://pypi.io/packages/source/P/Pygments/Pygments-%{pygmentsver}.tar.gz +Source102: https://pypi.io/packages/source/S/Sphinx/Sphinx-%{sphinxver}.tar.gz + +Source500: configlib.sh +Source501: gen_config_group.sh +Source502: set_config.sh + +# Important: source503 is used as the actual copy file +# @TODO: this causes a warning - fix it? +Source504: arm64-armv8a-linuxapp-gcc-config +Source505: ppc_64-power8-linuxapp-gcc-config +Source506: x86_64-native-linuxapp-gcc-config + +Patch: %{pkgname}.patch + +# FIXME Sphinx is used to generate some manpages, unfortunately, on RHEL, it's +# in the -optional repository and so we can't require it directly since RHV +# doesn't have the -optional repository enabled and so TPS fails +%if %{external_sphinx} +BuildRequires: python3-sphinx +%else +# Sphinx dependencies +BuildRequires: python-devel +BuildRequires: python-setuptools +#BuildRequires: python2-docutils +BuildRequires: python-jinja2 +BuildRequires: python-nose +#BuildRequires: python2-pygments +# docutils dependencies +BuildRequires: python-imaging +# pygments dependencies +BuildRequires: python-nose +%endif + +BuildRequires: gcc gcc-c++ make +BuildRequires: autoconf automake libtool +BuildRequires: systemd-units openssl openssl-devel +BuildRequires: python3-devel python3-setuptools +BuildRequires: desktop-file-utils +BuildRequires: groff-base graphviz +BuildRequires: unbound-devel + +# make check dependencies +BuildRequires: procps-ng +%if 0%{?rhel} == 8 || 0%{?fedora} +BuildRequires: python3-pyOpenSSL +%endif +BuildRequires: tcpdump + +%if %{with libcapng} +BuildRequires: libcap-ng libcap-ng-devel +%endif + +Requires: hostname openssl iproute module-init-tools + +Requires(post): systemd-units +Requires(preun): systemd-units +Requires(postun): systemd-units + +# to skip running checks, pass --without check +%bcond_without check + +%description +OVN, the Open Virtual Network, is a system to support virtual network +abstraction. OVN complements the existing capabilities of OVS to add +native support for virtual network abstractions, such as virtual L2 and L3 +overlays and security groups. + +%package central +Summary: Open Virtual Network support +License: ASL 2.0 +Requires: %{pkgname} +Requires: firewalld-filesystem +Provides: openvswitch%{pkgver}-ovn-central = %{?epoch:%{epoch}:}%{version}-%{release} +Obsoletes: openvswitch%{pkgver}-ovn-central < 2.11.0-1 + +%description central +OVN DB servers and ovn-northd running on a central node. + +%package host +Summary: Open Virtual Network support +License: ASL 2.0 +Requires: %{pkgname} +Requires: firewalld-filesystem +Provides: openvswitch%{pkgver}-ovn-host = %{?epoch:%{epoch}:}%{version}-%{release} +Obsoletes: openvswitch%{pkgver}-ovn-host < 2.11.0-1 + +%description host +OVN controller running on each host. + +%package vtep +Summary: Open Virtual Network support +License: ASL 2.0 +Requires: %{pkgname} +Provides: openvswitch%{pkgver}-ovn-vtep = %{?epoch:%{epoch}:}%{version}-%{release} +Obsoletes: openvswitch%{pkgver}-ovn-vtep < 2.11.0-1 + +%description vtep +OVN vtep controller + +%prep +%autosetup -n ovn-%{ovncommit} -a 10 -p 1 + +%build +%if 0%{?commit0:1} +# fix the snapshot unreleased version to be the released one. +sed -i.old -e "s/^AC_INIT(openvswitch,.*,/AC_INIT(openvswitch, %{version},/" configure.ac +%endif +./boot.sh + +# OVN source code is now separate. +# Build openvswitch first. +# XXX Current openvswitch2.13 doesn't +# use "2.13.0" for version. It's a commit hash +pushd %{ovsdir} +./boot.sh +%configure \ +%if %{with libcapng} + --enable-libcapng \ +%else + --disable-libcapng \ +%endif + --enable-ssl \ + --with-pkidir=%{_sharedstatedir}/openvswitch/pki + +make %{?_smp_mflags} +popd + +# Build OVN. +# XXX OVS version needs to be updated when ovs2.13 is updated. +%configure \ + --with-ovs-source=$PWD/%{ovsdir} \ +%if %{with libcapng} + --enable-libcapng \ +%else + --disable-libcapng \ +%endif + --enable-ssl \ + --with-pkidir=%{_sharedstatedir}/openvswitch/pki + +make %{?_smp_mflags} + +%install +%make_install +install -p -D -m 0644 \ + rhel/usr_share_ovn_scripts_systemd_sysconfig.template \ + $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/ovn + +for service in ovn-controller ovn-controller-vtep ovn-northd; do + install -p -D -m 0644 \ + rhel/usr_lib_systemd_system_${service}.service \ + $RPM_BUILD_ROOT%{_unitdir}/${service}.service +done + +install -d -m 0755 $RPM_BUILD_ROOT/%{_sharedstatedir}/ovn + +install -d $RPM_BUILD_ROOT%{ovnlibdir}/firewalld/services/ +install -p -m 0644 rhel/usr_lib_firewalld_services_ovn-central-firewall-service.xml \ + $RPM_BUILD_ROOT%{ovnlibdir}/firewalld/services/ovn-central-firewall-service.xml +install -p -m 0644 rhel/usr_lib_firewalld_services_ovn-host-firewall-service.xml \ + $RPM_BUILD_ROOT%{ovnlibdir}/firewalld/services/ovn-host-firewall-service.xml + +install -d -m 0755 $RPM_BUILD_ROOT%{ovnlibdir}/ocf/resource.d/ovn +ln -s %{_datadir}/ovn/scripts/ovndb-servers.ocf \ + $RPM_BUILD_ROOT%{ovnlibdir}/ocf/resource.d/ovn/ovndb-servers + +install -p -D -m 0644 rhel/etc_logrotate.d_ovn \ + $RPM_BUILD_ROOT/%{_sysconfdir}/logrotate.d/ovn + +# remove unneeded files. +rm -f $RPM_BUILD_ROOT%{_bindir}/ovs* +rm -f $RPM_BUILD_ROOT%{_bindir}/vtep-ctl +rm -f $RPM_BUILD_ROOT%{_sbindir}/ovs* +rm -f $RPM_BUILD_ROOT%{_mandir}/man1/ovs* +rm -f $RPM_BUILD_ROOT%{_mandir}/man5/ovs* +rm -f $RPM_BUILD_ROOT%{_mandir}/man5/vtep* +rm -f $RPM_BUILD_ROOT%{_mandir}/man7/ovs* +rm -f $RPM_BUILD_ROOT%{_mandir}/man8/ovs* +rm -f $RPM_BUILD_ROOT%{_mandir}/man8/vtep* +rm -rf $RPM_BUILD_ROOT%{_datadir}/ovn/python +rm -f $RPM_BUILD_ROOT%{_datadir}/ovn/scripts/ovs* +rm -rf $RPM_BUILD_ROOT%{_datadir}/ovn/bugtool-plugins +rm -f $RPM_BUILD_ROOT%{_libdir}/*.a +rm -f $RPM_BUILD_ROOT%{_libdir}/*.la +rm -f $RPM_BUILD_ROOT%{_libdir}/pkgconfig/*.pc +rm -f $RPM_BUILD_ROOT%{_includedir}/ovn/* +rm -f $RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d/ovs-appctl-bashcomp.bash +rm -f $RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d/ovs-vsctl-bashcomp.bash +rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/openvswitch +rm -f $RPM_BUILD_ROOT%{_datadir}/ovn/scripts/ovn-bugtool* +rm -f $RPM_BUILD_ROOT/%{_bindir}/ovn-docker-overlay-driver \ + $RPM_BUILD_ROOT/%{_bindir}/ovn-docker-underlay-driver + +%check +%if %{with check} + touch resolv.conf + export OVS_RESOLV_CONF=$(pwd)/resolv.conf + if ! make check TESTSUITEFLAGS='%{_smp_mflags}'; then + cat tests/testsuite.log + if ! make check TESTSUITEFLAGS='--recheck'; then + cat tests/testsuite.log + # Presently a test case - "2796: ovn -- ovn-controller incremental processing" + # is failing on aarch64 arch. Let's not exit for this arch + # until we figure out why it is failing. + # Test case 93: ovn.at:12105 ovn -- ACLs on Port Groups is failing + # repeatedly on s390x. This needs to be investigated. + %ifnarch aarch64 + %ifnarch ppc64le + %ifnarch s390x + exit 1 + %endif + %endif + %endif + fi + fi +%endif + +%clean +rm -rf $RPM_BUILD_ROOT + +%pre central +if [ $1 -eq 1 ] ; then + # Package install. + /bin/systemctl status ovn-northd.service >/dev/null + ovn_status=$? + rpm -ql openvswitch-ovn-central > /dev/null + if [[ "$?" = "0" && "$ovn_status" = "0" ]]; then + # ovn-northd service is running which means old openvswitch-ovn-central + # is already installed and it will be cleaned up. So start ovn-northd + # service when posttrans central is called. + touch %{_localstatedir}/lib/rpm-state/ovn-northd + fi +fi + +%pre host +if [ $1 -eq 1 ] ; then + # Package install. + /bin/systemctl status ovn-controller.service >/dev/null + ovn_status=$? + rpm -ql openvswitch-ovn-host > /dev/null + if [[ "$?" = "0" && "$ovn_status" = "0" ]]; then + # ovn-controller service is running which means old + # openvswitch-ovn-host is installed and it will be cleaned up. So + # start ovn-controller service when posttrans host is called. + touch %{_localstatedir}/lib/rpm-state/ovn-controller + fi +fi + +%pre vtep +if [ $1 -eq 1 ] ; then + # Package install. + /bin/systemctl status ovn-controller-vtep.service >/dev/null + ovn_status=$? + rpm -ql openvswitch-ovn-vtep > /dev/null + if [[ "$?" = "0" && "$ovn_status" = "0" ]]; then + # ovn-controller-vtep service is running which means old + # openvswitch-ovn-vtep is installed and it will be cleaned up. So + # start ovn-controller-vtep service when posttrans host is called. + touch %{_localstatedir}/lib/rpm-state/ovn-controller-vtep + fi +fi + +%preun central +%if 0%{?systemd_preun:1} + %systemd_preun ovn-northd.service +%else + if [ $1 -eq 0 ] ; then + # Package removal, not upgrade + /bin/systemctl --no-reload disable ovn-northd.service >/dev/null 2>&1 || : + /bin/systemctl stop ovn-northd.service >/dev/null 2>&1 || : + fi +%endif + +%preun host +%if 0%{?systemd_preun:1} + %systemd_preun ovn-controller.service +%else + if [ $1 -eq 0 ] ; then + # Package removal, not upgrade + /bin/systemctl --no-reload disable ovn-controller.service >/dev/null 2>&1 || : + /bin/systemctl stop ovn-controller.service >/dev/null 2>&1 || : + fi +%endif + +%preun vtep +%if 0%{?systemd_preun:1} + %systemd_preun ovn-controller-vtep.service +%else + if [ $1 -eq 0 ] ; then + # Package removal, not upgrade + /bin/systemctl --no-reload disable ovn-controller-vtep.service >/dev/null 2>&1 || : + /bin/systemctl stop ovn-controller-vtep.service >/dev/null 2>&1 || : + fi +%endif + +%post +%if %{with libcapng} +if [ $1 -eq 1 ]; then + sed -i 's:^#OVN_USER_ID=:OVN_USER_ID=:' %{_sysconfdir}/sysconfig/ovn + sed -i 's:\(.*su\).*:\1 openvswitch openvswitch:' %{_sysconfdir}/logrotate.d/ovn +fi +%endif + +%post central +%if 0%{?systemd_post:1} + %systemd_post ovn-northd.service +%else + # Package install, not upgrade + if [ $1 -eq 1 ]; then + /bin/systemctl daemon-reload >dev/null || : + fi +%endif + +%post host +%if 0%{?systemd_post:1} + %systemd_post ovn-controller.service +%else + # Package install, not upgrade + if [ $1 -eq 1 ]; then + /bin/systemctl daemon-reload >dev/null || : + fi +%endif + +%post vtep +%if 0%{?systemd_post:1} + %systemd_post ovn-controller-vtep.service +%else + # Package install, not upgrade + if [ $1 -eq 1 ]; then + /bin/systemctl daemon-reload >dev/null || : + fi +%endif + +%postun + +%postun central +%if 0%{?systemd_postun_with_restart:1} + %systemd_postun_with_restart ovn-northd.service +%else + /bin/systemctl daemon-reload >/dev/null 2>&1 || : + if [ "$1" -ge "1" ] ; then + # Package upgrade, not uninstall + /bin/systemctl try-restart ovn-northd.service >/dev/null 2>&1 || : + fi +%endif + +%postun host +%if 0%{?systemd_postun_with_restart:1} + %systemd_postun_with_restart ovn-controller.service +%else + /bin/systemctl daemon-reload >/dev/null 2>&1 || : + if [ "$1" -ge "1" ] ; then + # Package upgrade, not uninstall + /bin/systemctl try-restart ovn-controller.service >/dev/null 2>&1 || : + fi +%endif + +%postun vtep +%if 0%{?systemd_postun_with_restart:1} + %systemd_postun_with_restart ovn-controller-vtep.service +%else + /bin/systemctl daemon-reload >/dev/null 2>&1 || : + if [ "$1" -ge "1" ] ; then + # Package upgrade, not uninstall + /bin/systemctl try-restart ovn-controller-vtep.service >/dev/null 2>&1 || : + fi +%endif + +%posttrans central +if [ $1 -eq 1 ]; then + # Package install, not upgrade + if [ -e %{_localstatedir}/lib/rpm-state/ovn-northd ]; then + rm %{_localstatedir}/lib/rpm-state/ovn-northd + /bin/systemctl start ovn-northd.service >/dev/null 2>&1 || : + fi +fi + + +%posttrans host +if [ $1 -eq 1 ]; then + # Package install, not upgrade + if [ -e %{_localstatedir}/lib/rpm-state/ovn-controller ]; then + rm %{_localstatedir}/lib/rpm-state/ovn-controller + /bin/systemctl start ovn-controller.service >/dev/null 2>&1 || : + fi +fi + +%posttrans vtep +if [ $1 -eq 1 ]; then + # Package install, not upgrade + if [ -e %{_localstatedir}/lib/rpm-state/ovn-controller-vtep ]; then + rm %{_localstatedir}/lib/rpm-state/ovn-controller-vtep + /bin/systemctl start ovn-controller-vtep.service >/dev/null 2>&1 || : + fi +fi + +%files +%{_bindir}/ovn-nbctl +%{_bindir}/ovn-sbctl +%{_bindir}/ovn-trace +%{_bindir}/ovn-detrace +%{_bindir}/ovn_detrace.py +%{_bindir}/ovn-appctl +%{_bindir}/ovn-ic-nbctl +%{_bindir}/ovn-ic-sbctl +%dir %{_datadir}/ovn/ +%dir %{_datadir}/ovn/scripts/ +%{_datadir}/ovn/scripts/ovn-ctl +%{_datadir}/ovn/scripts/ovn-lib +%{_datadir}/ovn/scripts/ovndb-servers.ocf +%{_mandir}/man8/ovn-ctl.8* +%{_mandir}/man8/ovn-appctl.8* +%{_mandir}/man8/ovn-nbctl.8* +%{_mandir}/man8/ovn-ic-nbctl.8* +%{_mandir}/man8/ovn-trace.8* +%{_mandir}/man1/ovn-detrace.1* +%{_mandir}/man7/ovn-architecture.7* +%{_mandir}/man8/ovn-sbctl.8* +%{_mandir}/man8/ovn-ic-sbctl.8* +%{_mandir}/man5/ovn-nb.5* +%{_mandir}/man5/ovn-ic-nb.5* +%{_mandir}/man5/ovn-sb.5* +%{_mandir}/man5/ovn-ic-sb.5* +%dir %{ovnlibdir}/ocf/resource.d/ovn/ +%{ovnlibdir}/ocf/resource.d/ovn/ovndb-servers +%config(noreplace) %verify(not md5 size mtime) %{_sysconfdir}/logrotate.d/ovn +%config(noreplace) %verify(not md5 size mtime) %{_sysconfdir}/sysconfig/ovn + +%files central +%{_bindir}/ovn-northd +%{_bindir}/ovn-ic +%{_mandir}/man8/ovn-northd.8* +%{_mandir}/man8/ovn-ic.8* +%{_datadir}/ovn/ovn-nb.ovsschema +%{_datadir}/ovn/ovn-ic-nb.ovsschema +%{_datadir}/ovn/ovn-sb.ovsschema +%{_datadir}/ovn/ovn-ic-sb.ovsschema +%{_unitdir}/ovn-northd.service +%{ovnlibdir}/firewalld/services/ovn-central-firewall-service.xml + +%files host +%{_bindir}/ovn-controller +%{_mandir}/man8/ovn-controller.8* +%{_unitdir}/ovn-controller.service +%{ovnlibdir}/firewalld/services/ovn-host-firewall-service.xml + +%files vtep +%{_bindir}/ovn-controller-vtep +%{_mandir}/man8/ovn-controller-vtep.8* +%{_unitdir}/ovn-controller-vtep.service + +%changelog +* Thu Sep 14 2023 Lorenzo Bianconi - 23.06.1-11 +- northd: check if parent_name is set for tag_request 0 +[Upstream: c869db90e2b18515caad8ad95555d989d3379e3f] + +* Thu Sep 14 2023 Ales Musil - 23.06.1-10 +- ofctrl: Prevent conjunction duplication (#2175928) +[Upstream: 4281178a8882d0194ce8edf35018227ab20fa80e] + +* Thu Sep 14 2023 Ales Musil - 23.06.1-9 +- ofctrl: Do not try to program long flows (#1955167) +[Upstream: f18bbbbc1ec0110cde8146ea4e2b34b1ec488ba7] + +* Mon Sep 11 2023 Dumitru Ceara - 23.06.1-8 +- northd: Always ct commit ECMP symmetric traffic in the original direction. +[Upstream: 6de90ba4c43e1798a63167fd7f790126cf240e9c] + +* Wed Sep 06 2023 Ihar Hrachyshka - 23.06.1-7 +- Use correct nw_ttl=255 to match against legit NAs +[Upstream: 059d1337af1be97b8f89fcf65e2ba6c9ae217d76] + +* Wed Sep 06 2023 Dumitru Ceara - 23.06.1-6 +- checkpatch: Ignore yml files when checking line lengths. +[Upstream: 18b9ca0630c537b142d6ac849a6a2092d4f5bc0f] + +* Wed Aug 30 2023 Ales Musil - 23.06.1-5 +- northd: Make sure that skip_snat=true is evaluated before force_snat (#2224260) +[Upstream: 04cf3fd8c2de752ac6ca538f6570547a69dcaac3] + +* Tue Aug 29 2023 Mark Michelson - 23.06.1-4 +- Prepare for 23.06.2. +[Upstream: c215b5237d46e7aa3b7e095f1e955db5b646e4eb] +