diff --git a/.ovn.metadata b/.ovn.metadata
index df4ddae..864e447 100644
--- a/.ovn.metadata
+++ b/.ovn.metadata
@@ -1,5 +1,5 @@
002450621b33c5690060345b0aac25bc2426d675 SOURCES/docutils-0.12.tar.gz
-18ee4650f5907758dbd949b7b82bfb029666d8f8 SOURCES/openvswitch-6f24c2b.tar.gz
-8fc7b574476db8f38307923fd6e476df9b65b009 SOURCES/ovn-22.06.0.tar.gz
+ec8fc0e9030828262e24b495d9ba8f234aa5db77 SOURCES/openvswitch-64b7958.tar.gz
+cae717fbee361a235064a1d79b012b2590908f7c SOURCES/ovn-22.09.0.tar.gz
d34f96421a86004aa5d26ecf975edefd09f948b1 SOURCES/Pygments-1.4.tar.gz
6beb30f18ffac3de7689b7fd63e9a8a7d9c8df3a SOURCES/Sphinx-1.1.3.tar.gz
diff --git a/SOURCES/ovn22.06.patch b/SOURCES/ovn22.06.patch
deleted file mode 100644
index 426711d..0000000
--- a/SOURCES/ovn22.06.patch
+++ /dev/null
@@ -1,1519 +0,0 @@
-diff --git a/NEWS b/NEWS
-index e335f64c2..32e342a18 100644
---- a/NEWS
-+++ b/NEWS
-@@ -1,3 +1,6 @@
-+OVN v22.06.1 - xx xxx xxxx
-+--------------------------
-+
- OVN v22.06.0 - 03 Jun 2022
- --------------------------
- - Support IGMP and MLD snooping on transit logical switches that connect
-@@ -24,6 +27,8 @@ OVN v22.06.0 - 03 Jun 2022
- - Added support for setting the Next server IP in the DHCP header
- using the private DHCP option - 253 in native OVN DHCPv4 responder.
- - Support list of chassis for Logical_Switch_Port:options:requested-chassis.
-+ - Support Logical_Switch_Port:options:activation-strategy for live migration
-+ scenarios.
-
- OVN v22.03.0 - 11 Mar 2022
- --------------------------
-diff --git a/configure.ac b/configure.ac
-index b649441bc..739e0295e 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -13,7 +13,7 @@
- # limitations under the License.
-
- AC_PREREQ(2.63)
--AC_INIT(ovn, 22.06.0, bugs@openvswitch.org)
-+AC_INIT(ovn, 22.06.1, bugs@openvswitch.org)
- AC_CONFIG_MACRO_DIR([m4])
- AC_CONFIG_AUX_DIR([build-aux])
- AC_CONFIG_HEADERS([config.h])
-diff --git a/controller/lport.c b/controller/lport.c
-index bf55d83f2..add7e91aa 100644
---- a/controller/lport.c
-+++ b/controller/lport.c
-@@ -197,3 +197,25 @@ get_peer_lport(const struct sbrec_port_binding *pb,
- peer_name);
- return (peer && peer->datapath) ? peer : NULL;
- }
-+
-+bool
-+lport_is_activated_by_activation_strategy(const struct sbrec_port_binding *pb,
-+ const struct sbrec_chassis *chassis)
-+{
-+ const char *activated_chassis = smap_get(&pb->options,
-+ "additional-chassis-activated");
-+ if (activated_chassis) {
-+ char *save_ptr;
-+ char *tokstr = xstrdup(activated_chassis);
-+ for (const char *chassis_name = strtok_r(tokstr, ",", &save_ptr);
-+ chassis_name != NULL;
-+ chassis_name = strtok_r(NULL, ",", &save_ptr)) {
-+ if (!strcmp(chassis_name, chassis->name)) {
-+ free(tokstr);
-+ return true;
-+ }
-+ }
-+ free(tokstr);
-+ }
-+ return false;
-+}
-diff --git a/controller/lport.h b/controller/lport.h
-index 115881655..644c67255 100644
---- a/controller/lport.h
-+++ b/controller/lport.h
-@@ -70,4 +70,7 @@ const struct sbrec_port_binding *lport_get_peer(
- const struct sbrec_port_binding *lport_get_l3gw_peer(
- const struct sbrec_port_binding *,
- struct ovsdb_idl_index *sbrec_port_binding_by_name);
-+bool
-+lport_is_activated_by_activation_strategy(const struct sbrec_port_binding *pb,
-+ const struct sbrec_chassis *chassis);
- #endif /* controller/lport.h */
-diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
-index 2793c8687..69615308e 100644
---- a/controller/ovn-controller.c
-+++ b/controller/ovn-controller.c
-@@ -1128,6 +1128,53 @@ ovs_interface_shadow_ovs_interface_handler(struct engine_node *node,
- return true;
- }
-
-+struct ed_type_activated_ports {
-+ struct ovs_list *activated_ports;
-+};
-+
-+static void *
-+en_activated_ports_init(struct engine_node *node OVS_UNUSED,
-+ struct engine_arg *arg OVS_UNUSED)
-+{
-+ struct ed_type_activated_ports *data = xzalloc(sizeof *data);
-+ data->activated_ports = NULL;
-+ return data;
-+}
-+
-+static void
-+en_activated_ports_cleanup(void *data_)
-+{
-+ struct ed_type_activated_ports *data = data_;
-+ if (!data->activated_ports) {
-+ return;
-+ }
-+
-+ struct activated_port *pp;
-+ LIST_FOR_EACH_POP (pp, list, data->activated_ports) {
-+ free(pp);
-+ }
-+ free(data->activated_ports);
-+ data->activated_ports = NULL;
-+}
-+
-+static void
-+en_activated_ports_clear_tracked_data(void *data)
-+{
-+ en_activated_ports_cleanup(data);
-+}
-+
-+static void
-+en_activated_ports_run(struct engine_node *node, void *data_)
-+{
-+ struct ed_type_activated_ports *data = data_;
-+ enum engine_node_state state = EN_UNCHANGED;
-+ data->activated_ports = get_ports_to_activate_in_engine();
-+ if (data->activated_ports) {
-+ state = EN_UPDATED;
-+ }
-+ engine_set_node_state(node, state);
-+}
-+
- struct ed_type_runtime_data {
- /* Contains "struct local_datapath" nodes. */
- struct hmap local_datapaths;
-@@ -3164,6 +3211,49 @@ pflow_output_ct_zones_handler(struct engine_node *node OVS_UNUSED,
- return !ct_zones_data->recomputed;
- }
-
-+static bool
-+pflow_output_activated_ports_handler(struct engine_node *node, void *data)
-+{
-+ struct ed_type_activated_ports *ap =
-+ engine_get_input_data("activated_ports", node);
-+ if (!ap->activated_ports) {
-+ return true;
-+ }
-+
-+ 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 physical_ctx p_ctx;
-+ init_physical_ctx(node, rt_data, non_vif_data, &p_ctx);
-+
-+ struct activated_port *pp;
-+ LIST_FOR_EACH (pp, list, ap->activated_ports) {
-+ struct ovsdb_idl_index *sbrec_datapath_binding_by_key =
-+ engine_ovsdb_node_get_index(
-+ engine_get_input("SB_datapath_binding", node),
-+ "key");
-+ struct ovsdb_idl_index *sbrec_port_binding_by_key =
-+ engine_ovsdb_node_get_index(
-+ engine_get_input("SB_port_binding", node),
-+ "key");
-+ const struct sbrec_port_binding *pb = lport_lookup_by_key(
-+ sbrec_datapath_binding_by_key, sbrec_port_binding_by_key,
-+ pp->dp_key, pp->port_key);
-+ if (pb) {
-+ if (!physical_handle_flows_for_lport(pb, false, &p_ctx,
-+ &pfo->flow_table)) {
-+ return false;
-+ }
-+ tag_port_as_activated_in_engine(pp);
-+ }
-+ }
-+ engine_set_node_state(node, EN_UPDATED);
-+ return true;
-+}
-+
- static void *
- en_flow_output_init(struct engine_node *node OVS_UNUSED,
- struct engine_arg *arg OVS_UNUSED)
-@@ -3445,6 +3535,7 @@ main(int argc, char *argv[])
- ENGINE_NODE(non_vif_data, "non_vif_data");
- ENGINE_NODE(mff_ovn_geneve, "mff_ovn_geneve");
- ENGINE_NODE(ofctrl_is_connected, "ofctrl_is_connected");
-+ ENGINE_NODE_WITH_CLEAR_TRACK_DATA(activated_ports, "activated_ports");
- ENGINE_NODE(pflow_output, "physical_flow_output");
- ENGINE_NODE_WITH_CLEAR_TRACK_DATA(lflow_output, "logical_flow_output");
- ENGINE_NODE(flow_output, "flow_output");
-@@ -3492,6 +3583,14 @@ main(int argc, char *argv[])
- engine_add_input(&en_pflow_output, &en_sb_multicast_group,
- pflow_output_sb_multicast_group_handler);
-
-+ /* pflow_output needs to access the SB datapath binding and hence a noop
-+ * handler.
-+ */
-+ engine_add_input(&en_pflow_output, &en_sb_datapath_binding,
-+ engine_noop_handler);
-+ engine_add_input(&en_pflow_output, &en_activated_ports,
-+ pflow_output_activated_ports_handler);
-+
- engine_add_input(&en_pflow_output, &en_runtime_data,
- pflow_output_runtime_data_handler);
- engine_add_input(&en_pflow_output, &en_sb_encap, NULL);
-diff --git a/controller/physical.c b/controller/physical.c
-index 24de86f24..fc8280a99 100644
---- a/controller/physical.c
-+++ b/controller/physical.c
-@@ -40,7 +40,9 @@
- #include "lib/mcast-group-index.h"
- #include "lib/ovn-sb-idl.h"
- #include "lib/ovn-util.h"
-+#include "ovn/actions.h"
- #include "physical.h"
-+#include "pinctrl.h"
- #include "openvswitch/shash.h"
- #include "simap.h"
- #include "smap.h"
-@@ -984,6 +986,94 @@ enum access_type {
- PORT_HA_REMOTE,
- };
-
-+static void
-+setup_rarp_activation_strategy(const struct sbrec_port_binding *binding,
-+ ofp_port_t ofport, struct zone_ids *zone_ids,
-+ struct ovn_desired_flow_table *flow_table,
-+ struct ofpbuf *ofpacts_p)
-+{
-+ struct match match = MATCH_CATCHALL_INITIALIZER;
-+
-+ /* Unblock the port on ingress RARP. */
-+ match_set_dl_type(&match, htons(ETH_TYPE_RARP));
-+ match_set_in_port(&match, ofport);
-+ ofpbuf_clear(ofpacts_p);
-+
-+ load_logical_ingress_metadata(binding, zone_ids, ofpacts_p);
-+
-+ size_t ofs = ofpacts_p->size;
-+ struct ofpact_controller *oc = ofpact_put_CONTROLLER(ofpacts_p);
-+ oc->max_len = UINT16_MAX;
-+ oc->reason = OFPR_ACTION;
-+
-+ struct action_header ah = {
-+ .opcode = htonl(ACTION_OPCODE_ACTIVATION_STRATEGY_RARP)
-+ };
-+ ofpbuf_put(ofpacts_p, &ah, sizeof ah);
-+
-+ ofpacts_p->header = oc;
-+ oc->userdata_len = ofpacts_p->size - (ofs + sizeof *oc);
-+ ofpact_finish_CONTROLLER(ofpacts_p, &oc);
-+ put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p);
-+
-+ ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 1010,
-+ binding->header_.uuid.parts[0],
-+ &match, ofpacts_p, &binding->header_.uuid);
-+ ofpbuf_clear(ofpacts_p);
-+
-+ /* Block all non-RARP traffic for the port, both directions. */
-+ match_init_catchall(&match);
-+ match_set_in_port(&match, ofport);
-+
-+ ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 1000,
-+ binding->header_.uuid.parts[0],
-+ &match, ofpacts_p, &binding->header_.uuid);
-+
-+ match_init_catchall(&match);
-+ uint32_t dp_key = binding->datapath->tunnel_key;
-+ uint32_t port_key = binding->tunnel_key;
-+ match_set_metadata(&match, htonll(dp_key));
-+ match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key);
-+
-+ ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 1000,
-+ binding->header_.uuid.parts[0],
-+ &match, ofpacts_p, &binding->header_.uuid);
-+}
-+
-+static void
-+setup_activation_strategy(const struct sbrec_port_binding *binding,
-+ const struct sbrec_chassis *chassis,
-+ uint32_t dp_key, uint32_t port_key,
-+ ofp_port_t ofport, struct zone_ids *zone_ids,
-+ struct ovn_desired_flow_table *flow_table,
-+ struct ofpbuf *ofpacts_p)
-+{
-+ for (size_t i = 0; i < binding->n_additional_chassis; i++) {
-+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
-+ if (binding->additional_chassis[i] == chassis) {
-+ const char *strategy = smap_get(&binding->options,
-+ "activation-strategy");
-+ if (strategy
-+ && !lport_is_activated_by_activation_strategy(binding,
-+ chassis)
-+ && !pinctrl_is_port_activated(dp_key, port_key)) {
-+ if (!strcmp(strategy, "rarp")) {
-+ setup_rarp_activation_strategy(binding, ofport,
-+ zone_ids, flow_table,
-+ ofpacts_p);
-+ } else {
-+ VLOG_WARN_RL(&rl,
-+ "Unknown activation strategy defined for "
-+ "port %s: %s",
-+ binding->logical_port, strategy);
-+ return;
-+ }
-+ }
-+ return;
-+ }
-+ }
-+}
-+
- static void
- consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
- enum mf_field_id mff_ovn_geneve,
-@@ -1239,6 +1329,10 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
- }
- }
-
-+ setup_activation_strategy(binding, chassis, dp_key, port_key,
-+ ofport, &zone_ids, flow_table,
-+ ofpacts_p);
-+
- /* Remember the size with just strip vlan added so far,
- * as we're going to remove this with ofpbuf_pull() later. */
- uint32_t ofpacts_orig_size = ofpacts_p->size;
-diff --git a/controller/pinctrl.c b/controller/pinctrl.c
-index 428863293..f954362b7 100644
---- a/controller/pinctrl.c
-+++ b/controller/pinctrl.c
-@@ -29,10 +29,12 @@
- #include "lport.h"
- #include "mac-learn.h"
- #include "nx-match.h"
-+#include "ofctrl.h"
- #include "latch.h"
- #include "lib/packets.h"
- #include "lib/sset.h"
- #include "openvswitch/ofp-actions.h"
-+#include "openvswitch/ofp-flow.h"
- #include "openvswitch/ofp-msgs.h"
- #include "openvswitch/ofp-packet.h"
- #include "openvswitch/ofp-print.h"
-@@ -152,8 +154,8 @@ VLOG_DEFINE_THIS_MODULE(pinctrl);
- * and pinctrl_run().
- * 'pinctrl_handler_seq' is used by pinctrl_run() to
- * wake up pinctrl_handler thread from poll_block() if any changes happened
-- * in 'send_garp_rarp_data', 'ipv6_ras' and 'buffered_mac_bindings'
-- * structures.
-+ * in 'send_garp_rarp_data', 'ipv6_ras', 'ports_to_activate_in_db' and
-+ * 'buffered_mac_bindings' structures.
- *
- * 'pinctrl_main_seq' is used by pinctrl_handler() thread to wake up
- * the main thread from poll_block() when mac bindings/igmp groups need to
-@@ -198,6 +200,17 @@ static void wait_put_mac_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn);
- static void send_mac_binding_buffered_pkts(struct rconn *swconn)
- OVS_REQUIRES(pinctrl_mutex);
-
-+static void pinctrl_rarp_activation_strategy_handler(const struct match *md);
-+
-+static void init_activated_ports(void);
-+static void destroy_activated_ports(void);
-+static void wait_activated_ports(void);
-+static void run_activated_ports(
-+ struct ovsdb_idl_txn *ovnsb_idl_txn,
-+ struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
-+ struct ovsdb_idl_index *sbrec_port_binding_by_name,
-+ const struct sbrec_chassis *chassis);
-+
- static void init_send_garps_rarps(void);
- static void destroy_send_garps_rarps(void);
- static void send_garp_rarp_wait(long long int send_garp_rarp_time);
-@@ -522,6 +535,7 @@ pinctrl_init(void)
- init_ipv6_ras();
- init_ipv6_prefixd();
- init_buffered_packets_map();
-+ init_activated_ports();
- init_event_table();
- ip_mcast_snoop_init();
- init_put_vport_bindings();
-@@ -3269,6 +3283,12 @@ process_packet_in(struct rconn *swconn, const struct ofp_header *msg)
- ovs_mutex_unlock(&pinctrl_mutex);
- break;
-
-+ case ACTION_OPCODE_ACTIVATION_STRATEGY_RARP:
-+ ovs_mutex_lock(&pinctrl_mutex);
-+ pinctrl_rarp_activation_strategy_handler(&pin.flow_metadata);
-+ ovs_mutex_unlock(&pinctrl_mutex);
-+ break;
-+
- default:
- VLOG_WARN_RL(&rl, "unrecognized packet-in opcode %"PRIu32,
- ntohl(ah->opcode));
-@@ -3533,6 +3553,8 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
- bfd_monitor_run(ovnsb_idl_txn, bfd_table, sbrec_port_binding_by_name,
- chassis, active_tunnels);
- run_put_fdbs(ovnsb_idl_txn, sbrec_fdb_by_dp_key_mac);
-+ run_activated_ports(ovnsb_idl_txn, sbrec_datapath_binding_by_key,
-+ sbrec_port_binding_by_key, chassis);
- ovs_mutex_unlock(&pinctrl_mutex);
- }
-
-@@ -4030,12 +4052,15 @@ prepare_ipv6_ras(const struct shash *local_active_ports_ras,
- void
- pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn)
- {
-+ ovs_mutex_lock(&pinctrl_mutex);
- wait_put_mac_bindings(ovnsb_idl_txn);
- wait_controller_event(ovnsb_idl_txn);
- wait_put_vport_bindings(ovnsb_idl_txn);
- int64_t new_seq = seq_read(pinctrl_main_seq);
- seq_wait(pinctrl_main_seq, new_seq);
- wait_put_fdbs(ovnsb_idl_txn);
-+ wait_activated_ports();
-+ ovs_mutex_unlock(&pinctrl_mutex);
- }
-
- /* Called by ovn-controller. */
-@@ -4050,6 +4075,7 @@ pinctrl_destroy(void)
- destroy_ipv6_ras();
- destroy_ipv6_prefixd();
- destroy_buffered_packets_map();
-+ destroy_activated_ports();
- event_table_destroy();
- destroy_put_mac_bindings();
- destroy_put_vport_bindings();
-@@ -7727,6 +7753,152 @@ pinctrl_handle_svc_check(struct rconn *swconn, const struct flow *ip_flow,
- }
- }
-
-+static struct ovs_list ports_to_activate_in_db = OVS_LIST_INITIALIZER(
-+ &ports_to_activate_in_db);
-+static struct ovs_list ports_to_activate_in_engine = OVS_LIST_INITIALIZER(
-+ &ports_to_activate_in_engine);
-+
-+struct ovs_list *
-+get_ports_to_activate_in_engine(void)
-+{
-+ ovs_mutex_lock(&pinctrl_mutex);
-+ if (ovs_list_is_empty(&ports_to_activate_in_engine)) {
-+ ovs_mutex_unlock(&pinctrl_mutex);
-+ return NULL;
-+ }
-+
-+ struct ovs_list *ap = xmalloc(sizeof *ap);
-+ ovs_list_init(ap);
-+ struct activated_port *pp;
-+ LIST_FOR_EACH (pp, list, &ports_to_activate_in_engine) {
-+ struct activated_port *new = xmalloc(sizeof *new);
-+ new->dp_key = pp->dp_key;
-+ new->port_key = pp->port_key;
-+ ovs_list_push_front(ap, &new->list);
-+ }
-+ ovs_mutex_unlock(&pinctrl_mutex);
-+ return ap;
-+}
-+
-+static void
-+init_activated_ports(void)
-+ OVS_REQUIRES(pinctrl_mutex)
-+{
-+ ovs_list_init(&ports_to_activate_in_db);
-+ ovs_list_init(&ports_to_activate_in_engine);
-+}
-+
-+static void
-+destroy_activated_ports(void)
-+ OVS_REQUIRES(pinctrl_mutex)
-+{
-+ struct activated_port *pp;
-+ LIST_FOR_EACH_POP (pp, list, &ports_to_activate_in_db) {
-+ free(pp);
-+ }
-+ LIST_FOR_EACH_POP (pp, list, &ports_to_activate_in_engine) {
-+ free(pp);
-+ }
-+}
-+
-+static void
-+wait_activated_ports(void)
-+ OVS_REQUIRES(pinctrl_mutex)
-+{
-+ if (!ovs_list_is_empty(&ports_to_activate_in_engine)) {
-+ poll_immediate_wake();
-+ }
-+}
-+
-+bool pinctrl_is_port_activated(int64_t dp_key, int64_t port_key)
-+{
-+ const struct activated_port *pp;
-+ ovs_mutex_lock(&pinctrl_mutex);
-+ LIST_FOR_EACH (pp, list, &ports_to_activate_in_db) {
-+ if (pp->dp_key == dp_key && pp->port_key == port_key) {
-+ ovs_mutex_unlock(&pinctrl_mutex);
-+ return true;
-+ }
-+ }
-+ LIST_FOR_EACH (pp, list, &ports_to_activate_in_engine) {
-+ if (pp->dp_key == dp_key && pp->port_key == port_key) {
-+ ovs_mutex_unlock(&pinctrl_mutex);
-+ return true;
-+ }
-+ }
-+ ovs_mutex_unlock(&pinctrl_mutex);
-+ return false;
-+}
-+
-+static void
-+run_activated_ports(struct ovsdb_idl_txn *ovnsb_idl_txn,
-+ struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
-+ struct ovsdb_idl_index *sbrec_port_binding_by_key,
-+ const struct sbrec_chassis *chassis)
-+ OVS_REQUIRES(pinctrl_mutex)
-+{
-+ if (!ovnsb_idl_txn) {
-+ return;
-+ }
-+
-+ struct activated_port *pp;
-+ LIST_FOR_EACH_SAFE (pp, list, &ports_to_activate_in_db) {
-+ const struct sbrec_port_binding *pb = lport_lookup_by_key(
-+ sbrec_datapath_binding_by_key, sbrec_port_binding_by_key,
-+ pp->dp_key, pp->port_key);
-+ if (!pb || lport_is_activated_by_activation_strategy(pb, chassis)) {
-+ ovs_list_remove(&pp->list);
-+ free(pp);
-+ continue;
-+ }
-+ const char *activated_chassis = smap_get(
-+ &pb->options, "additional-chassis-activated");
-+ char *activated_str;
-+ if (activated_chassis) {
-+ activated_str = xasprintf(
-+ "%s,%s", activated_chassis, chassis->name);
-+ sbrec_port_binding_update_options_setkey(
-+ pb, "additional-chassis-activated", activated_str);
-+ free(activated_str);
-+ } else {
-+ sbrec_port_binding_update_options_setkey(
-+ pb, "additional-chassis-activated", chassis->name);
-+ }
-+ }
-+}
-+
-+void
-+tag_port_as_activated_in_engine(struct activated_port *ap) {
-+ ovs_mutex_lock(&pinctrl_mutex);
-+ struct activated_port *pp;
-+ LIST_FOR_EACH_SAFE (pp, list, &ports_to_activate_in_engine) {
-+ if (pp->dp_key == ap->dp_key && pp->port_key == ap->port_key) {
-+ ovs_list_remove(&pp->list);
-+ free(pp);
-+ }
-+ }
-+ ovs_mutex_unlock(&pinctrl_mutex);
-+}
-+
-+static void
-+pinctrl_rarp_activation_strategy_handler(const struct match *md)
-+ OVS_REQUIRES(pinctrl_mutex)
-+{
-+ /* Tag the port as activated in-memory. */
-+ struct activated_port *pp = xmalloc(sizeof *pp);
-+ pp->port_key = md->flow.regs[MFF_LOG_INPORT - MFF_REG0];
-+ pp->dp_key = ntohll(md->flow.metadata);
-+ ovs_list_push_front(&ports_to_activate_in_db, &pp->list);
-+
-+ pp = xmalloc(sizeof *pp);
-+ pp->port_key = md->flow.regs[MFF_LOG_INPORT - MFF_REG0];
-+ pp->dp_key = ntohll(md->flow.metadata);
-+ ovs_list_push_front(&ports_to_activate_in_engine, &pp->list);
-+
-+ /* Notify main thread on pending additional-chassis-activated updates. */
-+ notify_pinctrl_main();
-+}
-+
- static struct hmap put_fdbs;
-
- /* MAC learning (fdb) related functions. Runs within the main
-diff --git a/controller/pinctrl.h b/controller/pinctrl.h
-index 88f18e983..d4f52e94d 100644
---- a/controller/pinctrl.h
-+++ b/controller/pinctrl.h
-@@ -20,6 +20,7 @@
- #include
-
- #include "lib/sset.h"
-+#include "openvswitch/list.h"
- #include "openvswitch/meta-flow.h"
-
- struct hmap;
-@@ -33,6 +34,7 @@ struct sbrec_dns_table;
- struct sbrec_controller_event_table;
- struct sbrec_service_monitor_table;
- struct sbrec_bfd_table;
-+struct sbrec_port_binding;
-
- void pinctrl_init(void);
- void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
-@@ -56,4 +58,14 @@ void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
- void pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn);
- void pinctrl_destroy(void);
- void pinctrl_set_br_int_name(char *br_int_name);
-+
-+struct activated_port {
-+ uint32_t dp_key;
-+ uint32_t port_key;
-+ struct ovs_list list;
-+};
-+
-+void tag_port_as_activated_in_engine(struct activated_port *ap);
-+struct ovs_list *get_ports_to_activate_in_engine(void);
-+bool pinctrl_is_port_activated(int64_t dp_key, int64_t port_key);
- #endif /* controller/pinctrl.h */
-diff --git a/debian/changelog b/debian/changelog
-index caef68452..1c2de53bd 100644
---- a/debian/changelog
-+++ b/debian/changelog
-@@ -1,3 +1,9 @@
-+OVN (22.06.1-1) unstable; urgency=low
-+ [ OVN team ]
-+ * New upstream version
-+
-+ -- OVN team Fri, 03 Jun 2022 11:54:08 -0400
-+
- ovn (22.06.0-1) unstable; urgency=low
-
- * New upstream version
-diff --git a/include/ovn/actions.h b/include/ovn/actions.h
-index 1ae496960..33c319f1c 100644
---- a/include/ovn/actions.h
-+++ b/include/ovn/actions.h
-@@ -683,6 +683,9 @@ enum action_opcode {
- /* put_fdb(inport, eth.src).
- */
- ACTION_OPCODE_PUT_FDB,
-+
-+ /* activation_strategy_rarp() */
-+ ACTION_OPCODE_ACTIVATION_STRATEGY_RARP,
- };
-
- /* Header. */
-diff --git a/northd/northd.c b/northd/northd.c
-index f120c2366..dd62c4098 100644
---- a/northd/northd.c
-+++ b/northd/northd.c
-@@ -3470,6 +3470,16 @@ ovn_port_update_sbrec(struct northd_input *input_data,
- smap_add(&options, "vlan-passthru", "true");
- }
-
-+ /* Retain activated chassis flags. */
-+ if (op->sb->requested_additional_chassis) {
-+ const char *activated_str = smap_get(
-+ &op->sb->options, "additional-chassis-activated");
-+ if (activated_str) {
-+ smap_add(&options, "additional-chassis-activated",
-+ activated_str);
-+ }
-+ }
-+
- sbrec_port_binding_set_options(op->sb, &options);
- smap_destroy(&options);
- if (ovn_is_known_nb_lsp_type(op->nbsp->type)) {
-@@ -10976,6 +10986,9 @@ build_neigh_learning_flows_for_lrouter(
- copp_meter_get(COPP_ARP, od->nbr->copp,
- meter_groups));
-
-+ ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 95,
-+ "nd_ns && (ip6.src == 0 || nd.sll == 0)", "next;");
-+
- ovn_lflow_metered(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 95,
- "nd_na && nd.tll == 0",
- "put_nd(inport, nd.target, eth.src); next;",
-@@ -12021,6 +12034,7 @@ build_gateway_redirect_flows_for_lrouter(
- }
- for (size_t i = 0; i < od->n_l3dgw_ports; i++) {
- const struct ovsdb_idl_row *stage_hint = NULL;
-+ bool add_def_flow = true;
-
- if (od->l3dgw_ports[i]->nbrp) {
- stage_hint = &od->l3dgw_ports[i]->nbrp->header_;
-@@ -12039,22 +12053,42 @@ build_gateway_redirect_flows_for_lrouter(
- ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_GW_REDIRECT, 50,
- ds_cstr(match), ds_cstr(actions),
- stage_hint);
-- }
-+ for (int j = 0; j < od->n_nat_entries; j++) {
-+ const struct ovn_nat *nat = &od->nat_entries[j];
-
-- for (int i = 0; i < od->n_nat_entries; i++) {
-- const struct ovn_nat *nat = &od->nat_entries[i];
-+ if (!lrouter_nat_is_stateless(nat->nb) ||
-+ strcmp(nat->nb->type, "dnat_and_snat") ||
-+ (!nat->nb->allowed_ext_ips && !nat->nb->exempted_ext_ips)) {
-+ continue;
-+ }
-
-- if (!lrouter_nat_is_stateless(nat->nb) ||
-- strcmp(nat->nb->type, "dnat_and_snat")) {
-- continue;
-- }
-+ struct ds match_ext = DS_EMPTY_INITIALIZER;
-+ struct nbrec_address_set *as = nat->nb->allowed_ext_ips
-+ ? nat->nb->allowed_ext_ips : nat->nb->exempted_ext_ips;
-+ ds_put_format(&match_ext, "%s && ip%s.src == $%s",
-+ ds_cstr(match), nat_entry_is_v6(nat) ? "6" : "4",
-+ as->name);
-
-- ds_clear(match);
-- ds_put_format(match, "ip && ip%s.dst == %s",
-- nat_entry_is_v6(nat) ? "6" : "4",
-- nat->nb->external_ip);
-- ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, 100,
-- ds_cstr(match), "drop;");
-+ if (nat->nb->allowed_ext_ips) {
-+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_GW_REDIRECT,
-+ 75, ds_cstr(&match_ext),
-+ ds_cstr(actions), stage_hint);
-+ if (add_def_flow) {
-+ ds_clear(&match_ext);
-+ ds_put_format(&match_ext, "ip && ip%s.dst == %s",
-+ nat_entry_is_v6(nat) ? "6" : "4",
-+ nat->nb->external_ip);
-+ ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, 70,
-+ ds_cstr(&match_ext), "drop;");
-+ add_def_flow = false;
-+ }
-+ } else if (nat->nb->exempted_ext_ips) {
-+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_GW_REDIRECT,
-+ 75, ds_cstr(&match_ext), "drop;",
-+ stage_hint);
-+ }
-+ ds_destroy(&match_ext);
-+ }
- }
-
- /* Packets are allowed by default. */
-diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
-index 1f7022490..32858c0b4 100644
---- a/northd/ovn-northd.8.xml
-+++ b/northd/ovn-northd.8.xml
-@@ -2323,6 +2323,12 @@ next;
- to learn the neighbor.
-
-
-+
-+ A priority-95 flow with the match nd_ns &&
-+ (ip6.src == 0 || nd.sll == 0)
and applies the action
-+ next;
-+
-+
-
- A priority-90 flow with the match arp
and
- applies the action
-@@ -3018,8 +3024,7 @@ icmp6 {
- ip && ip6.dst == B
- with an action ct_snat;
. If the NAT rule is of type
- dnat_and_snat and has stateless=true
in the
-- options, then the action would be ip4/6.dst=
-- (B)
.
-+ options, then the action would be next;
.
-
-
-
-@@ -3059,7 +3064,7 @@ icmp6 {
- action ct_snat_in_czone;
to unSNAT in the common
- zone. If the NAT rule is of type dnat_and_snat and has
- stateless=true
in the options, then the action
-- would be ip4/6.dst=(B)
.
-+ would be next;
.
-
-
-
-@@ -4217,6 +4222,26 @@ icmp6 {
- external ip and D is NAT external mac.
-
-
-+
-+ For each dnat_and_snat
NAT rule with
-+ stateless=true
and allowed_ext_ips
-+ configured, a priority-75 flow is programmed with match
-+ ip4.dst == B
and action
-+ outport = CR; next;
where B
-+ is the NAT rule external IP and CR is the
-+ chassisredirect
port representing the instance
-+ of the logical router distributed gateway port on the
-+ gateway chassis. Moreover a priority-70 flow is programmed
-+ with same match and action drop;
.
-+ For each dnat_and_snat
NAT rule with
-+ stateless=true
and exempted_ext_ips
-+ configured, a priority-75 flow is programmed with match
-+ ip4.dst == B
and action
-+ drop;
where B is the NAT rule
-+ external IP.
-+ A similar flow is added for IPv6 traffic.
-+
-+
-
- For each NAT rule in the OVN Northbound database that can
- be handled in a distributed manner, a priority-80 logical flow
-@@ -4415,8 +4440,7 @@ nd_ns {
- is the logical router gateway port, with an action
- ct_dnat_in_czone;
. If the NAT rule is of type
- dnat_and_snat and has stateless=true
in the
-- options, then the action would be ip4/6.src=
-- (B)
.
-+ options, then the action would be next;
.
-
-
-
-diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
-index e4e980720..ab28756af 100644
---- a/northd/ovn-northd.c
-+++ b/northd/ovn-northd.c
-@@ -107,7 +107,10 @@ static const char *rbac_port_binding_auth[] =
- static const char *rbac_port_binding_update[] =
- {"chassis", "additional_chassis",
- "encap", "additional_encap",
-- "up", "virtual_parent"};
-+ "up", "virtual_parent",
-+ /* NOTE: we only need to update the additional-chassis-activated key,
-+ * but RBAC_Role doesn't support mutate operation for subkeys. */
-+ "options"};
-
- static const char *rbac_mac_binding_auth[] =
- {""};
-diff --git a/ovn-nb.xml b/ovn-nb.xml
-index c197f431f..e700b2e88 100644
---- a/ovn-nb.xml
-+++ b/ovn-nb.xml
-@@ -1045,6 +1045,17 @@
-
-
-
-+
-+ If used with multiple chassis set in
-+ , specifies an activation strategy
-+ for all additional chassis. By default, no activation strategy is
-+ used, meaning additional port locations are immediately available for
-+ use. When set to "rarp", the port is blocked for ingress and egress
-+ communication until a RARP packet is sent from a new location. The
-+ "rarp" strategy is useful in live migration scenarios for virtual
-+ machines.
-+
-+
-
- If set, this port will be bound by ovn-controller
- only if this same key and value is configured in the
-diff --git a/ovn-sb.xml b/ovn-sb.xml
-index 9f47a037e..49e851e2a 100644
---- a/ovn-sb.xml
-+++ b/ovn-sb.xml
-@@ -3374,6 +3374,21 @@ tcp.flags = RST;
-
-
-
-+
-+ If used with multiple chassis set in ,
-+ specifies an activation strategy for all additional chassis. By
-+ default, no activation strategy is used, meaning additional port
-+ locations are immediately available for use. When set to "rarp", the
-+ port is blocked for ingress and egress communication until a RARP
-+ packet is sent from a new location. The "rarp" strategy is useful
-+ in live migration scenarios for virtual machines.
-+
-+
-+
-+ When is set, this option indicates
-+ that the port was activated using the strategy specified.
-+
-+
-
- If set, this port will be bound by ovn-controller
- only if this same key and value is configured in the
-diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
-index a071b3689..76e5a5c2b 100644
---- a/tests/ovn-northd.at
-+++ b/tests/ovn-northd.at
-@@ -6734,6 +6734,7 @@ AT_CHECK([cat lrflows | grep -e lr_in_lookup_neighbor -e lr_in_learn_neighbor |
- table=2 (lr_in_learn_neighbor), priority=90 , match=(nd_na), action=(put_nd(inport, nd.target, nd.tll); next;)
- table=2 (lr_in_learn_neighbor), priority=90 , match=(nd_ns), action=(put_nd(inport, ip6.src, nd.sll); next;)
- table=2 (lr_in_learn_neighbor), priority=95 , match=(nd_na && nd.tll == 0), action=(put_nd(inport, nd.target, eth.src); next;)
-+ table=2 (lr_in_learn_neighbor), priority=95 , match=(nd_ns && (ip6.src == 0 || nd.sll == 0)), action=(next;)
- ])
-
- AT_CLEANUP
-diff --git a/tests/ovn.at b/tests/ovn.at
-index 3c079e0fb..1aa562de5 100644
---- a/tests/ovn.at
-+++ b/tests/ovn.at
-@@ -7432,7 +7432,7 @@ ovs-vsctl -- add-port br-int vif2 -- \
- # Allow some time for ovn-northd and ovn-controller to catch up.
- wait_for_ports_up
- check ovn-nbctl --wait=hv sync
--ovn-nbctl dump-flows > sbflows
-+ovn-sbctl dump-flows > sbflows
- AT_CAPTURE_FILE([sbflows])
-
- for i in 1 2; do
-@@ -8037,7 +8037,7 @@ wait_for_ports_up
- check ovn-nbctl --wait=hv sync
- sleep 1
-
--ovn-nbctl dump-flows > sbflows
-+ovn-sbctl dump-flows > sbflows
- AT_CAPTURE_FILE([sbflows])
-
- for i in 1 2; do
-@@ -14015,6 +14015,7 @@ AT_CLEANUP
-
- OVN_FOR_EACH_NORTHD([
- AT_SETUP([options:multiple requested-chassis for logical port])
-+AT_KEYWORDS([multi-chassis])
- ovn_start
-
- net_add n1
-@@ -14104,6 +14105,7 @@ AT_CLEANUP
-
- OVN_FOR_EACH_NORTHD([
- AT_SETUP([options:multiple requested-chassis for logical port: change chassis role])
-+AT_KEYWORDS([multi-chassis])
- ovn_start
-
- net_add n1
-@@ -14153,6 +14155,7 @@ AT_CLEANUP
-
- OVN_FOR_EACH_NORTHD([
- AT_SETUP([options:multiple requested-chassis for logical port: unclaimed behavior])
-+AT_KEYWORDS([multi-chassis])
- ovn_start
-
- net_add n1
-@@ -14233,6 +14236,7 @@ AT_CLEANUP
-
- OVN_FOR_EACH_NORTHD([
- AT_SETUP([basic connectivity with multiple requested-chassis])
-+AT_KEYWORDS([multi-chassis])
- ovn_start
-
- net_add n1
-@@ -14567,6 +14571,7 @@ AT_CLEANUP
-
- OVN_FOR_EACH_NORTHD([
- AT_SETUP([localnet connectivity with multiple requested-chassis])
-+AT_KEYWORDS([multi-chassis])
- ovn_start
-
- net_add n1
-@@ -14924,6 +14929,391 @@ OVN_CLEANUP([hv1],[hv2],[hv3])
- AT_CLEANUP
- ])
-
-+OVN_FOR_EACH_NORTHD([
-+AT_SETUP([options:activation-strategy for logical port])
-+AT_KEYWORDS([multi-chassis])
-+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.11
-+
-+sim_add hv2
-+as hv2
-+check ovs-vsctl add-br br-phys
-+ovn_attach n1 br-phys 192.168.0.12
-+
-+sim_add hv3
-+as hv3
-+check ovs-vsctl add-br br-phys
-+ovn_attach n1 br-phys 192.168.0.13
-+
-+# Disable local ARP responder to pass ARP requests through tunnels
-+check ovn-nbctl ls-add ls0 -- add Logical_Switch ls0 other_config vlan-passthru=true
-+
-+check ovn-nbctl lsp-add ls0 migrator
-+check ovn-nbctl lsp-set-options migrator requested-chassis=hv1,hv2 \
-+ activation-strategy=rarp
-+
-+check ovn-nbctl lsp-add ls0 first
-+check ovn-nbctl lsp-set-options first requested-chassis=hv1
-+check ovn-nbctl lsp-add ls0 second
-+check ovn-nbctl lsp-set-options second requested-chassis=hv2
-+check ovn-nbctl lsp-add ls0 outside
-+check ovn-nbctl lsp-set-options outside requested-chassis=hv3
-+
-+check ovn-nbctl lsp-set-addresses migrator "00:00:00:00:00:10 10.0.0.10"
-+check ovn-nbctl lsp-set-addresses first "00:00:00:00:00:01 10.0.0.1"
-+check ovn-nbctl lsp-set-addresses second "00:00:00:00:00:02 10.0.0.2"
-+check ovn-nbctl lsp-set-addresses outside "00:00:00:00:00:03 10.0.0.3"
-+
-+for hv in hv1 hv2; do
-+ as $hv check ovs-vsctl -- add-port br-int migrator -- \
-+ set Interface migrator external-ids:iface-id=migrator \
-+ options:tx_pcap=$hv/migrator-tx.pcap \
-+ options:rxq_pcap=$hv/migrator-rx.pcap
-+done
-+
-+as hv1 check ovs-vsctl -- add-port br-int first -- \
-+ set Interface first external-ids:iface-id=first
-+as hv2 check ovs-vsctl -- add-port br-int second -- \
-+ set Interface second external-ids:iface-id=second
-+as hv3 check ovs-vsctl -- add-port br-int outside -- \
-+ set Interface outside external-ids:iface-id=outside
-+
-+for hv in hv1 hv2 hv3; do
-+ wait_row_count Chassis 1 name=$hv
-+done
-+hv1_uuid=$(fetch_column Chassis _uuid name=hv1)
-+hv2_uuid=$(fetch_column Chassis _uuid name=hv2)
-+hv3_uuid=$(fetch_column Chassis _uuid name=hv3)
-+
-+wait_column "$hv1_uuid" Port_Binding chassis logical_port=migrator
-+wait_column "$hv1_uuid" Port_Binding requested_chassis logical_port=migrator
-+wait_column "$hv2_uuid" Port_Binding additional_chassis logical_port=migrator
-+wait_column "$hv2_uuid" Port_Binding requested_additional_chassis logical_port=migrator
-+
-+wait_column "$hv1_uuid" Port_Binding chassis logical_port=first
-+wait_column "$hv2_uuid" Port_Binding chassis logical_port=second
-+wait_column "$hv3_uuid" Port_Binding chassis logical_port=outside
-+
-+OVN_POPULATE_ARP
-+
-+send_arp() {
-+ local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
-+ local request=${eth_dst}${eth_src}08060001080006040001${eth_src}${spa}${eth_dst}${tpa}
-+ as ${hv} ovs-appctl netdev-dummy/receive $inport $request
-+ echo "${request}"
-+}
-+
-+send_rarp() {
-+ local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
-+ local request=${eth_dst}${eth_src}80350001080006040001${eth_src}${spa}${eth_dst}${tpa}
-+ as ${hv} ovs-appctl netdev-dummy/receive $inport $request
-+ echo "${request}"
-+}
-+
-+reset_pcap_file() {
-+ local hv=$1
-+ local iface=$2
-+ local pcap_file=$3
-+ as $hv check ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-+ options:rxq_pcap=dummy-rx.pcap
-+ check rm -f ${pcap_file}*.pcap
-+ as $hv check ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-+ options:rxq_pcap=${pcap_file}-rx.pcap
-+}
-+
-+reset_env() {
-+ reset_pcap_file hv1 migrator hv1/migrator
-+ reset_pcap_file hv2 migrator hv2/migrator
-+ reset_pcap_file hv1 first hv1/first
-+ reset_pcap_file hv2 second hv2/second
-+ reset_pcap_file hv3 outside hv3/outside
-+
-+ for port in hv1/migrator hv2/migrator hv1/first hv2/second hv3/outside; do
-+ : > $port.expected
-+ done
-+}
-+
-+check_packets() {
-+ OVN_CHECK_PACKETS([hv1/migrator-tx.pcap], [hv1/migrator.expected])
-+ OVN_CHECK_PACKETS([hv2/migrator-tx.pcap], [hv2/migrator.expected])
-+ OVN_CHECK_PACKETS([hv3/outside-tx.pcap], [hv3/outside.expected])
-+ OVN_CHECK_PACKETS([hv1/first-tx.pcap], [hv1/first.expected])
-+ OVN_CHECK_PACKETS([hv2/second-tx.pcap], [hv2/second.expected])
-+}
-+
-+migrator_spa=$(ip_to_hex 10 0 0 10)
-+first_spa=$(ip_to_hex 10 0 0 1)
-+second_spa=$(ip_to_hex 10 0 0 2)
-+outside_spa=$(ip_to_hex 10 0 0 3)
-+
-+reset_env
-+
-+# Packet from hv3:Outside arrives to hv1:Migrator
-+# hv3:Outside cannot reach hv2:Migrator because it is blocked by RARP strategy
-+request=$(send_arp hv3 outside 000000000003 000000000010 $outside_spa $migrator_spa)
-+echo $request >> hv1/migrator.expected
-+
-+# Packet from hv1:First arrives to hv1:Migrator
-+# hv1:First cannot reach hv2:Migrator because it is blocked by RARP strategy
-+request=$(send_arp hv1 first 000000000001 000000000010 $first_spa $migrator_spa)
-+echo $request >> hv1/migrator.expected
-+
-+# Packet from hv2:Second arrives to hv1:Migrator
-+# hv2:Second cannot reach hv2:Migrator because it is blocked by RARP strategy
-+request=$(send_arp hv2 second 000000000002 000000000010 $second_spa $migrator_spa)
-+echo $request >> hv1/migrator.expected
-+
-+check_packets
-+reset_env
-+
-+# Packet from hv1:Migrator arrives to hv3:Outside
-+request=$(send_arp hv1 migrator 000000000010 000000000003 $migrator_spa $outside_spa)
-+echo $request >> hv3/outside.expected
-+
-+# Packet from hv1:Migrator arrives to hv1:First
-+request=$(send_arp hv1 migrator 000000000010 000000000001 $migrator_spa $first_spa)
-+echo $request >> hv1/first.expected
-+
-+# Packet from hv1:Migrator arrives to hv2:Second
-+request=$(send_arp hv1 migrator 000000000010 000000000002 $migrator_spa $second_spa)
-+echo $request >> hv2/second.expected
-+
-+check_packets
-+reset_env
-+
-+# hv2:Migrator cannot reach to hv3:Outside because it is blocked by RARP strategy
-+request=$(send_arp hv2 migrator 000000000010 000000000003 $migrator_spa $outside_spa)
-+
-+check_packets
-+reset_env
-+
-+AT_CHECK([ovn-sbctl find port_binding logical_port=migrator | grep -q additional-chassis-activated], [1])
-+
-+# Now activate hv2:Migrator location
-+request=$(send_rarp hv2 migrator 000000000010 ffffffffffff $migrator_spa $migrator_spa)
-+
-+# RARP was reinjected into the pipeline
-+echo $request >> hv3/outside.expected
-+echo $request >> hv1/first.expected
-+echo $request >> hv2/second.expected
-+
-+check_packets
-+reset_env
-+
-+pb_uuid=$(ovn-sbctl --bare --columns _uuid find Port_Binding logical_port=migrator)
-+OVS_WAIT_UNTIL([test xhv2 = x$(ovn-sbctl get Port_Binding $pb_uuid options:additional-chassis-activated | tr -d '""')])
-+
-+# Now packet arrives to both locations
-+request=$(send_arp hv3 outside 000000000003 000000000010 $outside_spa $migrator_spa)
-+echo $request >> hv1/migrator.expected
-+echo $request >> hv2/migrator.expected
-+
-+check_packets
-+reset_env
-+
-+# Packet from hv1:Migrator still arrives to hv3:Outside
-+request=$(send_arp hv1 migrator 000000000010 000000000003 $migrator_spa $outside_spa)
-+echo $request >> hv3/outside.expected
-+
-+check_packets
-+reset_env
-+
-+# hv2:Migrator can now reach to hv3:Outside because RARP strategy activated it
-+request=$(send_arp hv2 migrator 000000000010 000000000003 $migrator_spa $outside_spa)
-+echo $request >> hv3/outside.expected
-+
-+check_packets
-+
-+# complete port migration and check that -activated flag is reset
-+check ovn-nbctl lsp-set-options migrator requested-chassis=hv2
-+OVS_WAIT_UNTIL([test x = x$(ovn-sbctl get Port_Binding $pb_uuid options:additional-chassis-activated)])
-+
-+OVN_CLEANUP([hv1],[hv2],[hv3])
-+
-+AT_CLEANUP
-+])
-+
-+OVN_FOR_EACH_NORTHD([
-+AT_SETUP([options:activation-strategy=rarp is not waiting for southbound db])
-+AT_KEYWORDS([multi-chassis])
-+# unskip when ovn-controller is able to process incremental updates to flow
-+# table without ovsdb transaction available
-+AT_SKIP_IF([true])
-+
-+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.11
-+
-+sim_add hv2
-+as hv2
-+check ovs-vsctl add-br br-phys
-+ovn_attach n1 br-phys 192.168.0.12
-+
-+# Disable local ARP responder to pass ARP requests through tunnels
-+check ovn-nbctl ls-add ls0 -- add Logical_Switch ls0 other_config vlan-passthru=true
-+
-+check ovn-nbctl lsp-add ls0 migrator
-+check ovn-nbctl lsp-set-options migrator requested-chassis=hv1,hv2 \
-+ activation-strategy=rarp
-+
-+check ovn-nbctl lsp-add ls0 first
-+check ovn-nbctl lsp-set-options first requested-chassis=hv1
-+
-+check ovn-nbctl lsp-set-addresses migrator "00:00:00:00:00:10 10.0.0.10"
-+check ovn-nbctl lsp-set-addresses first "00:00:00:00:00:01 10.0.0.1"
-+
-+for hv in hv1 hv2; do
-+ as $hv check ovs-vsctl -- add-port br-int migrator -- \
-+ set Interface migrator external-ids:iface-id=migrator \
-+ options:tx_pcap=$hv/migrator-tx.pcap \
-+ options:rxq_pcap=$hv/migrator-rx.pcap
-+done
-+
-+as hv1 check ovs-vsctl -- add-port br-int first -- \
-+ set Interface first external-ids:iface-id=first
-+
-+for hv in hv1 hv2; do
-+ wait_row_count Chassis 1 name=$hv
-+done
-+hv1_uuid=$(fetch_column Chassis _uuid name=hv1)
-+hv2_uuid=$(fetch_column Chassis _uuid name=hv2)
-+
-+wait_column "$hv1_uuid" Port_Binding chassis logical_port=migrator
-+wait_column "$hv1_uuid" Port_Binding requested_chassis logical_port=migrator
-+wait_column "$hv2_uuid" Port_Binding additional_chassis logical_port=migrator
-+wait_column "$hv2_uuid" Port_Binding requested_additional_chassis logical_port=migrator
-+
-+wait_column "$hv1_uuid" Port_Binding chassis logical_port=first
-+
-+OVN_POPULATE_ARP
-+
-+send_arp() {
-+ local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
-+ local request=${eth_dst}${eth_src}08060001080006040001${eth_src}${spa}${eth_dst}${tpa}
-+ as ${hv} ovs-appctl netdev-dummy/receive $inport $request
-+ echo "${request}"
-+}
-+
-+send_rarp() {
-+ local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
-+ local request=${eth_dst}${eth_src}80350001080006040001${eth_src}${spa}${eth_dst}${tpa}
-+ as ${hv} ovs-appctl netdev-dummy/receive $inport $request
-+ echo "${request}"
-+}
-+
-+reset_pcap_file() {
-+ local hv=$1
-+ local iface=$2
-+ local pcap_file=$3
-+ as $hv check ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-+ options:rxq_pcap=dummy-rx.pcap
-+ check rm -f ${pcap_file}*.pcap
-+ as $hv check ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-+ options:rxq_pcap=${pcap_file}-rx.pcap
-+}
-+
-+reset_env() {
-+ reset_pcap_file hv1 migrator hv1/migrator
-+ reset_pcap_file hv2 migrator hv2/migrator
-+ reset_pcap_file hv1 first hv1/first
-+
-+ for port in hv1/migrator hv2/migrator hv1/first; do
-+ : > $port.expected
-+ done
-+}
-+
-+check_packets() {
-+ OVN_CHECK_PACKETS([hv1/migrator-tx.pcap], [hv1/migrator.expected])
-+ OVN_CHECK_PACKETS([hv2/migrator-tx.pcap], [hv2/migrator.expected])
-+ OVN_CHECK_PACKETS([hv1/first-tx.pcap], [hv1/first.expected])
-+}
-+
-+migrator_spa=$(ip_to_hex 10 0 0 10)
-+first_spa=$(ip_to_hex 10 0 0 1)
-+
-+reset_env
-+
-+# Packet from hv1:First arrives to hv1:Migrator
-+# hv1:First cannot reach hv2:Migrator because it is blocked by RARP strategy
-+request=$(send_arp hv1 first 000000000001 000000000010 $first_spa $migrator_spa)
-+echo $request >> hv1/migrator.expected
-+
-+check_packets
-+reset_env
-+
-+# Packet from hv1:Migrator arrives to hv1:First
-+request=$(send_arp hv1 migrator 000000000010 000000000001 $migrator_spa $first_spa)
-+echo $request >> hv1/first.expected
-+
-+check_packets
-+reset_env
-+
-+# hv2:Migrator cannot reach to hv1:First because it is blocked by RARP strategy
-+request=$(send_arp hv2 migrator 000000000010 000000000001 $migrator_spa $first_spa)
-+
-+check_packets
-+reset_env
-+
-+# Before proceeding, stop ovsdb-server to make sure we test in the environment
-+# that can't remove flows triggered by updates to database
-+as ovn-sb
-+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-+
-+# Now activate hv2:Migrator location
-+request=$(send_rarp hv2 migrator 000000000010 ffffffffffff $migrator_spa $migrator_spa)
-+
-+# RARP was reinjected into the pipeline
-+echo $request >> hv1/first.expected
-+
-+# Now packet from hv1:First arrives to both locations
-+request=$(send_arp hv1 first 000000000001 000000000010 $first_spa $migrator_spa)
-+echo $request >> hv1/migrator.expected
-+echo $request >> hv2/migrator.expected
-+
-+# Packet from hv1:Migrator still arrives to hv1:First
-+request=$(send_arp hv1 migrator 000000000010 000000000001 $migrator_spa $first_spa)
-+echo $request >> hv1/first.expected
-+
-+# hv2:Migrator can now reach to hv1:First because RARP strategy activated it
-+request=$(send_arp hv2 migrator 000000000010 000000000001 $migrator_spa $first_spa)
-+echo $request >> hv1/first.expected
-+
-+check_packets
-+
-+# restart ovsdb-server before cleaning up to give ovn-controller a chance to
-+# exit gracefully
-+mv $ovs_base/ovn-sb/ovsdb-server.log $ovs_base/ovn-sb/ovsdb-server.log.prev
-+as ovn-sb start_daemon ovsdb-server \
-+ -vjsonrpc \
-+ --remote=punix:$ovs_base/ovn-sb/$1.sock \
-+ --remote=db:OVN_Southbound,SB_Global,connections \
-+ --private-key=$PKIDIR/testpki-test-privkey.pem \
-+ --certificate=$PKIDIR/testpki-test-cert.pem \
-+ --ca-cert=$PKIDIR/testpki-cacert.pem \
-+ $ovs_base/ovn-sb/ovn-sb.db
-+
-+PARSE_LISTENING_PORT([$ovs_base/ovn-sb/ovsdb-server.log], [TCP_PORT])
-+for i in 1 2; do
-+ as hv$i
-+ ovs-vsctl \
-+ -- set Open_vSwitch . external-ids:ovn-remote=ssl:127.0.0.1:$TCP_PORT
-+done
-+OVN_CLEANUP([hv1],[hv2])
-+
-+AT_CLEANUP
-+])
-+
- OVN_FOR_EACH_NORTHD([
- AT_SETUP([options:requested-chassis for logical port])
- ovn_start
-diff --git a/tests/system-ovn.at b/tests/system-ovn.at
-index 4bf22593a..df2da3408 100644
---- a/tests/system-ovn.at
-+++ b/tests/system-ovn.at
-@@ -6741,6 +6741,21 @@ NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 172.18.2.10 | FORMAT_PING], \
- [0], [dnl
- 3 packets transmitted, 3 received, 0% packet loss, time 0ms
- ])
-+
-+dnat_and_snat_uuid=$(fetch_column nb:NAT _uuid external_ip=172.18.2.10)
-+ovn-nbctl set NAT $dnat_and_snat_uuid options:stateless=true
-+
-+# A ping from vm1 should hairpin in lr1 and successfully DNAT to vm2
-+NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 172.18.2.10 | FORMAT_PING], \
-+[0], [dnl
-+3 packets transmitted, 3 received, 0% packet loss, time 0ms
-+])
-+# A ping from vm2 should hairpin in lr1 and successfully DNAT to vm2
-+NS_CHECK_EXEC([vm2], [ping -q -c 3 -i 0.3 -w 2 172.18.2.10 | FORMAT_PING], \
-+[0], [dnl
-+3 packets transmitted, 3 received, 0% packet loss, time 0ms
-+])
-+
- kill $(pidof ovn-controller)
-
- as ovn-sb
-diff --git a/utilities/ovn-ctl b/utilities/ovn-ctl
-index d733aa42d..93be9b84b 100755
---- a/utilities/ovn-ctl
-+++ b/utilities/ovn-ctl
-@@ -42,8 +42,21 @@ ovn_ic_db_conf_file="$ovn_etcdir/ovn-ic-db-params.conf"
-
- pidfile_is_running () {
- pidfile=$1
-- test -e "$pidfile" && [ -s "$pidfile" ] && pid=`cat "$pidfile"` && pid_exists "$pid"
--} >/dev/null 2>&1
-+ cmd=$2
-+ if [ ! -s "$pidfile" ]; then
-+ # file missing or empty
-+ return 1
-+ fi
-+ pid=`cat "$pidfile"`
-+ if ! pid_exists $pid; then
-+ # pid is dead
-+ return 1
-+ fi
-+ if [ -n "$cmd" ]; then
-+ return $(pid_comm_check "$cmd" "$pid")
-+ fi
-+ return 0
-+}
-
- stop_nb_ovsdb() {
- OVS_RUNDIR=${OVS_RUNDIR} stop_ovn_daemon ovnnb_db $DB_NB_PIDFILE $DB_NB_CTRL_SOCK
-@@ -199,7 +212,7 @@ start_ovsdb__() {
- ovn_install_dir "$ovn_etcdir"
-
- # Check and eventually start ovsdb-server for DB
-- if pidfile_is_running $db_pid_file; then
-+ if pidfile_is_running $db_pid_file ovsdb-server; then
- return
- fi
-
-@@ -298,6 +311,10 @@ $cluster_remote_port
- set "$@" --sync-from=`cat $active_conf_file`
- fi
-
-+ if test X"$extra_args" != X; then
-+ set "$@" $extra_args
-+ fi
-+
- local run_ovsdb_in_bg="no"
- local process_id=
- if test X$detach = Xno && test $mode = cluster && test -z "$cluster_remote_addr" ; then
-@@ -528,6 +545,10 @@ start_ic () {
-
- set "$@" $OVN_IC_LOG $ovn_ic_params
-
-+ if test X"$extra_args" != X; then
-+ set "$@" $extra_args
-+ fi
-+
- OVS_RUNDIR=${OVS_RUNDIR} start_ovn_daemon "$OVN_IC_PRIORITY" "$OVN_IC_WRAPPER" "$@"
- fi
- }
-@@ -550,6 +571,10 @@ start_controller () {
-
- [ "$OVN_USER" != "" ] && set "$@" --user "$OVN_USER"
-
-+ if test X"$extra_args" != X; then
-+ set "$@" $extra_args
-+ fi
-+
- OVS_RUNDIR=${OVS_RUNDIR} start_ovn_daemon "$OVN_CONTROLLER_PRIORITY" "$OVN_CONTROLLER_WRAPPER" "$@"
- }
-
-@@ -577,6 +602,10 @@ start_controller_vtep () {
-
- [ "$OVN_USER" != "" ] && set "$@" --user "$OVN_USER"
-
-+ if test X"$extra_args" != X; then
-+ set "$@" $extra_args
-+ fi
-+
- OVS_RUNDIR=${OVS_RUNDIR} start_ovn_daemon "$OVN_CONTROLLER_PRIORITY" "$OVN_CONTROLLER_WRAPPER" "$@"
- }
-
-@@ -1093,8 +1122,10 @@ EOF
-
- set_defaults
- command=
-+extra_args=
- for arg
- do
-+ shift
- case $arg in
- -h | --help)
- usage
-@@ -1117,6 +1148,10 @@ do
- type=bool
- set_option
- ;;
-+ --)
-+ extra_args=$@
-+ break
-+ ;;
- -*)
- echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
- exit 1
-diff --git a/utilities/ovn-ctl.8.xml b/utilities/ovn-ctl.8.xml
-index a1d39b22b..42d16fabc 100644
---- a/utilities/ovn-ctl.8.xml
-+++ b/utilities/ovn-ctl.8.xml
-@@ -4,7 +4,10 @@
- ovn-ctl -- Open Virtual Network northbound daemon lifecycle utility
-
- Synopsis
-- ovn-ctl
[options] command
-+
-+ ovn-ctl
[options] command
-+ [--- extra_args]
-+
-
- Description
- This program is intended to be invoked internally by Open Virtual Network
-@@ -156,6 +159,15 @@
-
--db-nb-probe-interval-to-active=Time in milliseconds
- --db-sb-probe-interval-to-active=Time in milliseconds
-
-+ Extra Options
-+
-+ Any options after '--' will be passed on to the binary run by
-+ command with the exception of start_northd, which can have
-+ options specified in ovn-northd-db-params.conf. Any extra_args
-+ passed to start_northd will be passed to the ovsdb-servers if
-+ --ovn-manage-ovsdb=yes
-+
-+
- Configuration files
- Following are the optional configuration files. If present, it should be located in the etc dir
-
-diff --git a/utilities/ovn-dbctl.c b/utilities/ovn-dbctl.c
-index a292e589d..c4cc8c9b2 100644
---- a/utilities/ovn-dbctl.c
-+++ b/utilities/ovn-dbctl.c
-@@ -202,6 +202,13 @@ ovn_dbctl_main(int argc, char *argv[],
- error = ctl_parse_commands(argc - optind, argv_ + optind,
- &local_options, &commands, &n_commands);
- if (error) {
-+ ovsdb_idl_destroy(idl);
-+ idl = the_idl = NULL;
-+
-+ for (int i = 0; i < argc; i++) {
-+ free(argv_[i]);
-+ }
-+ free(argv_);
- ctl_fatal("%s", error);
- }
-
diff --git a/SOURCES/ovn22.09.patch b/SOURCES/ovn22.09.patch
new file mode 100644
index 0000000..ba07376
--- /dev/null
+++ b/SOURCES/ovn22.09.patch
@@ -0,0 +1,1164 @@
+diff --git a/NEWS b/NEWS
+index ef6a99fed..0392d8d23 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,3 +1,6 @@
++OVN v22.09.1 - xx xxx xxxx
++--------------------------
++
+ OVN v22.09.0 - 16 Sep 2022
+ --------------------------
+ - ovn-controller: Add configuration knob, through OVS external-id
+diff --git a/configure.ac b/configure.ac
+index 765aacb17..c79d79ffe 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -13,7 +13,7 @@
+ # limitations under the License.
+
+ AC_PREREQ(2.63)
+-AC_INIT(ovn, 22.09.0, bugs@openvswitch.org)
++AC_INIT(ovn, 22.09.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 8f6b4b19d..c3d2b2e42 100644
+--- a/controller/binding.c
++++ b/controller/binding.c
+@@ -2666,7 +2666,7 @@ consider_patch_port_for_local_datapaths(const struct sbrec_port_binding *pb,
+ get_local_datapath(b_ctx_out->local_datapaths,
+ peer->datapath->tunnel_key);
+ }
+- if (peer_ld && need_add_patch_peer_to_local(
++ if (peer_ld && need_add_peer_to_local(
+ b_ctx_in->sbrec_port_binding_by_name, peer,
+ b_ctx_in->chassis_rec)) {
+ add_local_datapath(
+@@ -2681,7 +2681,7 @@ consider_patch_port_for_local_datapaths(const struct sbrec_port_binding *pb,
+ /* Add the peer datapath to the local datapaths if it's
+ * not present yet.
+ */
+- if (need_add_patch_peer_to_local(
++ if (need_add_peer_to_local(
+ b_ctx_in->sbrec_port_binding_by_name, pb,
+ b_ctx_in->chassis_rec)) {
+ add_local_datapath_peer_port(
+diff --git a/controller/local_data.c b/controller/local_data.c
+index 9eee568d1..035f10fff 100644
+--- a/controller/local_data.c
++++ b/controller/local_data.c
+@@ -115,14 +115,19 @@ local_datapath_destroy(struct local_datapath *ld)
+ free(ld);
+ }
+
+-/* Checks if pb is a patch port and the peer datapath should be added to local
+- * datapaths. */
++/* Checks if pb is running on local gw router or pb is a patch port
++ * and the peer datapath should be added to local datapaths. */
+ bool
+-need_add_patch_peer_to_local(
++need_add_peer_to_local(
+ struct ovsdb_idl_index *sbrec_port_binding_by_name,
+ const struct sbrec_port_binding *pb,
+ const struct sbrec_chassis *chassis)
+ {
++ /* This port is running on local gw router. */
++ if (!strcmp(pb->type, "l3gateway") && pb->chassis == chassis) {
++ return true;
++ }
++
+ /* If it is not a patch port, no peer to add. */
+ if (strcmp(pb->type, "patch")) {
+ return false;
+@@ -571,7 +576,7 @@ add_local_datapath__(struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
+ peer_name);
+
+ if (peer && peer->datapath) {
+- if (need_add_patch_peer_to_local(
++ if (need_add_peer_to_local(
+ sbrec_port_binding_by_name, pb, chassis)) {
+ struct local_datapath *peer_ld =
+ add_local_datapath__(sbrec_datapath_binding_by_key,
+diff --git a/controller/local_data.h b/controller/local_data.h
+index d898c8aa5..b5429eb58 100644
+--- a/controller/local_data.h
++++ b/controller/local_data.h
+@@ -66,7 +66,7 @@ struct local_datapath *local_datapath_alloc(
+ struct local_datapath *get_local_datapath(const struct hmap *,
+ uint32_t tunnel_key);
+ bool
+-need_add_patch_peer_to_local(
++need_add_peer_to_local(
+ struct ovsdb_idl_index *sbrec_port_binding_by_name,
+ const struct sbrec_port_binding *,
+ const struct sbrec_chassis *);
+diff --git a/controller/physical.c b/controller/physical.c
+index f3c8bddce..705146316 100644
+--- a/controller/physical.c
++++ b/controller/physical.c
+@@ -803,6 +803,14 @@ put_replace_router_port_mac_flows(struct ovsdb_idl_index
+
+ ofpact_put_OUTPUT(ofpacts_p)->port = ofport;
+
++ /* Replace the MAC back and strip vlan. In case of l2 flooding
++ * traffic (ARP/ND) we need to restore previous state so other ports
++ * do not receive the traffic tagged and with wrong MAC. */
++ ofpact_put_SET_ETH_SRC(ofpacts_p)->mac = router_port_mac;
++ if (tag) {
++ ofpact_put_STRIP_VLAN(ofpacts_p);
++ }
++
+ ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 150,
+ localnet_port->header_.uuid.parts[0],
+ &match, ofpacts_p, &localnet_port->header_.uuid);
+diff --git a/controller/pinctrl.c b/controller/pinctrl.c
+index 3f5d0af79..1e4230ed3 100644
+--- a/controller/pinctrl.c
++++ b/controller/pinctrl.c
+@@ -4378,7 +4378,7 @@ run_buffered_binding(struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
+ const struct sbrec_port_binding *pb;
+ SBREC_PORT_BINDING_FOR_EACH_EQUAL (pb, target,
+ sbrec_port_binding_by_datapath) {
+- if (strcmp(pb->type, "patch")) {
++ if (strcmp(pb->type, "patch") && strcmp(pb->type, "l3gateway")) {
+ continue;
+ }
+ struct buffered_packets *cur_qp;
+diff --git a/debian/changelog b/debian/changelog
+index 267e12baa..5ed83900b 100644
+--- a/debian/changelog
++++ b/debian/changelog
+@@ -1,3 +1,9 @@
++OVN (22.09.1-1) unstable; urgency=low
++ [ OVN team ]
++ * New upstream version
++
++ -- OVN team Fri, 16 Sep 2022 13:54:11 -0400
++
+ ovn (22.09.0-1) unstable; urgency=low
+
+ * New upstream version
+diff --git a/northd/northd.c b/northd/northd.c
+index 84440a47f..a7b1c6404 100644
+--- a/northd/northd.c
++++ b/northd/northd.c
+@@ -1040,7 +1040,16 @@ init_mcast_info_for_switch_datapath(struct ovn_datapath *od)
+ mcast_sw_info->query_max_response =
+ smap_get_ullong(&od->nbs->other_config, "mcast_query_max_response",
+ OVN_MCAST_DEFAULT_QUERY_MAX_RESPONSE_S);
++}
+
++static void
++init_mcast_flow_count(struct ovn_datapath *od)
++{
++ if (od->nbr) {
++ return;
++ }
++
++ struct mcast_switch_info *mcast_sw_info = &od->mcast_info.sw;
+ mcast_sw_info->active_v4_flows = ATOMIC_VAR_INIT(0);
+ mcast_sw_info->active_v6_flows = ATOMIC_VAR_INIT(0);
+ }
+@@ -8451,6 +8460,10 @@ build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group,
+ if (atomic_compare_exchange_strong(
+ &mcast_sw_info->active_v4_flows, &table_size,
+ mcast_sw_info->table_size)) {
++ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
++
++ VLOG_INFO_RL(&rl, "Too many active mcast flows: %"PRIu64,
++ mcast_sw_info->active_v4_flows);
+ return;
+ }
+ atomic_add(&mcast_sw_info->active_v4_flows, 1, &dummy);
+@@ -13633,7 +13646,8 @@ static void
+ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows,
+ const struct hmap *ports, struct ds *match,
+ struct ds *actions,
+- const struct shash *meter_groups)
++ const struct shash *meter_groups,
++ bool ct_lb_mark)
+ {
+ if (!od->nbr) {
+ return;
+@@ -13827,6 +13841,26 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows,
+ }
+ }
+
++ if (od->nbr->n_nat) {
++ ds_clear(match);
++ const char *ct_natted = ct_lb_mark ?
++ "ct_mark.natted" :
++ "ct_label.natted";
++ ds_put_format(match, "ip && %s == 1", ct_natted);
++ /* This flow is unique since it is in the egress pipeline but checks
++ * the value of ct_label.natted, which would have been set in the
++ * ingress pipeline. If a change is ever introduced that clears or
++ * otherwise invalidates the ct_label between the ingress and egress
++ * pipelines, then an alternative will need to be devised.
++ */
++ ds_clear(actions);
++ ds_put_cstr(actions, REGBIT_DST_NAT_IP_LOCAL" = 1; next;");
++ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_CHECK_DNAT_LOCAL,
++ 50, ds_cstr(match), ds_cstr(actions),
++ &od->nbr->header_);
++
++ }
++
+ /* Handle force SNAT options set in the gateway router. */
+ if (od->is_gw_router) {
+ if (dnat_force_snat_ip) {
+@@ -13925,7 +13959,8 @@ build_lswitch_and_lrouter_iterate_by_od(struct ovn_datapath *od,
+ build_misc_local_traffic_drop_flows_for_lrouter(od, lsi->lflows);
+ build_lrouter_arp_nd_for_datapath(od, lsi->lflows, lsi->meter_groups);
+ build_lrouter_nat_defrag_and_lb(od, lsi->lflows, lsi->ports, &lsi->match,
+- &lsi->actions, lsi->meter_groups);
++ &lsi->actions, lsi->meter_groups,
++ lsi->features->ct_no_masked_label);
+ }
+
+ /* Helper function to combine all lflow generation which is iterated by port.
+@@ -15148,6 +15183,11 @@ build_mcast_groups(struct lflow_input *input_data,
+
+ hmap_init(mcast_groups);
+ hmap_init(igmp_groups);
++ struct ovn_datapath *od;
++
++ HMAP_FOR_EACH (od, key_node, datapaths) {
++ init_mcast_flow_count(od);
++ }
+
+ HMAP_FOR_EACH (op, key_node, ports) {
+ if (op->nbrp && lrport_is_enabled(op->nbrp)) {
+@@ -15205,8 +15245,7 @@ build_mcast_groups(struct lflow_input *input_data,
+ }
+
+ /* If the datapath value is stale, purge the group. */
+- struct ovn_datapath *od =
+- ovn_datapath_from_sbrec(datapaths, sb_igmp->datapath);
++ od = ovn_datapath_from_sbrec(datapaths, sb_igmp->datapath);
+
+ if (!od || ovn_datapath_is_stale(od)) {
+ sbrec_igmp_group_delete(sb_igmp);
+@@ -15251,7 +15290,6 @@ build_mcast_groups(struct lflow_input *input_data,
+ * IGMP groups are based on the groups learnt by their multicast enabled
+ * peers.
+ */
+- struct ovn_datapath *od;
+ HMAP_FOR_EACH (od, key_node, datapaths) {
+
+ if (ovs_list_is_empty(&od->mcast_info.groups)) {
+diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
+index dae961c87..177b6341d 100644
+--- a/northd/ovn-northd.8.xml
++++ b/northd/ovn-northd.8.xml
+@@ -4392,6 +4392,22 @@ nd_ns {
+
+
+
++
++ This table also installs a priority-50 logical flow for each logical
++ router that has NATs configured on it. The flow has match
++ ip && ct_label.natted == 1
and action
++ REGBIT_DST_NAT_IP_LOCAL = 1; next;
. This is intended
++ to ensure that traffic that was DNATted locally will use a separate
++ conntrack zone for SNAT if SNAT is required later in the egress
++ pipeline. Note that this flow checks the value of
++ ct_label.natted
, which is set in the ingress pipeline.
++ This means that ovn-northd assumes that this value is carried over
++ from the ingress pipeline to the egress pipeline and is not altered
++ or cleared. If conntrack label values are ever changed to be cleared
++ between the ingress and egress pipelines, then the match conditions
++ of this flow will be updated accordingly.
++
++
+ Egress Table 1: UNDNAT
+
+
+diff --git a/rhel/ovn-fedora.spec.in b/rhel/ovn-fedora.spec.in
+index 821eb03cc..57dc977c1 100644
+--- a/rhel/ovn-fedora.spec.in
++++ b/rhel/ovn-fedora.spec.in
+@@ -65,6 +65,7 @@ BuildRequires: tcpdump
+ BuildRequires: unbound unbound-devel
+
+ Requires: openssl hostname iproute module-init-tools openvswitch
++Requires: python3-openvswitch
+
+ Requires(post): systemd-units
+ Requires(preun): systemd-units
+diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
+index 7c3c84007..15588cc52 100644
+--- a/tests/ovn-northd.at
++++ b/tests/ovn-northd.at
+@@ -5019,6 +5019,7 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
+
+ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl
+ table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;)
++ table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ct_mark.natted == 1), action=(reg9[[4]] = 1; next;)
+ table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.10 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;)
+ table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.20 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;)
+ table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.30 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;)
+@@ -5093,6 +5094,7 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
+
+ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl
+ table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;)
++ table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ct_mark.natted == 1), action=(reg9[[4]] = 1; next;)
+ table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.10 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;)
+ table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.20 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;)
+ table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ip4.dst == 172.168.0.30 && is_chassis_resident("cr-lr0-public")), action=(reg9[[4]] = 1; next;)
+@@ -5161,6 +5163,7 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
+
+ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl
+ table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;)
++ table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ct_mark.natted == 1), action=(reg9[[4]] = 1; next;)
+ ])
+
+ AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl
+@@ -5221,6 +5224,7 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
+
+ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl
+ table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;)
++ table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ct_mark.natted == 1), action=(reg9[[4]] = 1; next;)
+ ])
+
+ AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl
+@@ -5286,6 +5290,7 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
+
+ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl
+ table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;)
++ table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ct_mark.natted == 1), action=(reg9[[4]] = 1; next;)
+ ])
+
+ AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl
+@@ -5364,6 +5369,7 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
+
+ AT_CHECK([grep "lr_out_chk_dnat_local" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl
+ table=? (lr_out_chk_dnat_local), priority=0 , match=(1), action=(reg9[[4]] = 0; next;)
++ table=? (lr_out_chk_dnat_local), priority=50 , match=(ip && ct_mark.natted == 1), action=(reg9[[4]] = 1; next;)
+ ])
+
+ AT_CHECK([grep "lr_out_undnat" lr0flows | sed 's/table=./table=?/' | sort], [0], [dnl
+@@ -6129,7 +6135,6 @@ AT_CHECK([grep -e "(lr_in_ip_routing ).*outport" lr0flows | sed 's/table=../ta
+ ])
+
+ AT_CLEANUP
+-])
+
+ OVN_FOR_EACH_NORTHD([
+ AT_SETUP([check exclude-lb-vips-from-garp option])
+diff --git a/tests/ovn.at b/tests/ovn.at
+index 80e9192ca..dd72996dd 100644
+--- a/tests/ovn.at
++++ b/tests/ovn.at
+@@ -32889,3 +32889,32 @@ check ovn-nbctl --wait=hv sync
+ OVN_CLEANUP([hv1])
+ AT_CLEANUP
+ ])
++
++OVN_FOR_EACH_NORTHD([
++AT_SETUP([ovn-controller: batch add port and delete port in same IDL])
++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
++check ovs-vsctl add-port br-int p1
++
++check ovs-vsctl set interface p1 external-ids:iface-id=sw0-port1
++check ovn-nbctl --wait=hv sync
++ovn-appctl debug/pause
++OVS_WAIT_UNTIL([test x$(as hv1 ovn-appctl -t ovn-controller debug/status) = "xpaused"])
++
++check ovn-nbctl ls-add sw0 -- lsp-add sw0 sw0-port1
++check ovn-nbctl lsp-del sw0-port1
++check ovn-nbctl --wait=sb sync
++
++ovn-appctl debug/resume
++check ovn-nbctl --wait=hv sync
++
++check ovn-nbctl ls-del sw0
++check ovn-nbctl --wait=hv sync
++OVN_CLEANUP([hv1])
++AT_CLEANUP
++])
+diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at
+index 616a87fcf..8e6cb415c 100644
+--- a/tests/system-common-macros.at
++++ b/tests/system-common-macros.at
+@@ -44,15 +44,38 @@ 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])
++# 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])
+ ]
+ )
+
+@@ -333,4 +356,166 @@ m4_define([OVS_CHECK_CT_CLEAR],
+
+ # OVS_CHECK_CT_ZERO_SNAT()
+ m4_define([OVS_CHECK_CT_ZERO_SNAT],
+- [AT_SKIP_IF([! grep -q "Datapath supports ct_zero_snat" ovs-vswitchd.log])]))
++ [AT_SKIP_IF([! grep -q "Datapath supports ct_zero_snat" ovs-vswitchd.log])])
++
++# OVN_TEST_IPV6_PREFIX_DELEGATION()
++m4_define([OVN_TEST_IPV6_PREFIX_DELEGATION],
++[
++ovn_start
++OVS_TRAFFIC_VSWITCHD_START()
++
++ADD_BR([br-int])
++ADD_BR([br-ext])
++
++ovs-ofctl add-flow br-ext action=normal
++# 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
++
++ADD_NAMESPACES(sw01)
++ADD_VETH(sw01, sw01, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
++ "192.168.1.1")
++ADD_NAMESPACES(sw11)
++ADD_VETH(sw11, sw11, br-int, "192.168.2.2/24", "f0:00:00:02:02:03", \
++ "192.168.2.1")
++ADD_NAMESPACES(server)
++ADD_VETH(s1, server, br-ext, "2001:1db8:3333::2/64", "f0:00:00:01:02:05", \
++ "2001:1db8:3333::1")
++
++if test X"$1" = X"GR"; then
++ ovn-nbctl create Logical_Router name=R1 options:chassis=hv1
++else
++ ovn-nbctl lr-add R1
++fi
++
++ovn-nbctl ls-add sw0
++ovn-nbctl ls-add sw1
++ovn-nbctl ls-add public
++
++ovn-nbctl lrp-add R1 rp-sw0 00:00:01:01:02:03 192.168.1.1/24
++ovn-nbctl lrp-add R1 rp-sw1 00:00:03:01:02:03 192.168.2.1/24
++ovn-nbctl lrp-add R1 rp-public 00:00:02:01:02:03 172.16.1.1/24
++
++if test X"$1" != X"GR"; then
++ ovn-nbctl lrp-set-gateway-chassis rp-public hv1
++fi
++
++ovn-nbctl lsp-add sw0 sw0-rp -- set Logical_Switch_Port sw0-rp \
++ type=router options:router-port=rp-sw0 \
++ -- lsp-set-addresses sw0-rp router
++ovn-nbctl lsp-add sw1 sw1-rp -- set Logical_Switch_Port sw1-rp \
++ type=router options:router-port=rp-sw1 \
++ -- lsp-set-addresses sw1-rp router
++
++ovn-nbctl lsp-add public public-rp -- set Logical_Switch_Port public-rp \
++ type=router options:router-port=rp-public \
++ -- lsp-set-addresses public-rp router
++
++ovn-nbctl lsp-add sw0 sw01 \
++ -- lsp-set-addresses sw01 "f0:00:00:01:02:03 192.168.1.2"
++
++ovn-nbctl lsp-add sw1 sw11 \
++ -- lsp-set-addresses sw11 "f0:00:00:02:02:03 192.168.2.2"
++
++OVS_WAIT_UNTIL([test "$(ip netns exec server ip a | grep 2001:1db8:3333::2 | grep tentative)" = ""])
++OVS_WAIT_UNTIL([test "$(ip netns exec server ip a | grep fe80 | grep tentative)" = ""])
++
++AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext])
++ovn-nbctl lsp-add public public1 \
++ -- lsp-set-addresses public1 unknown \
++ -- lsp-set-type public1 localnet \
++ -- lsp-set-options public1 network_name=phynet
++
++ovn-nbctl set logical_router_port rp-public options:prefix_delegation=true
++ovn-nbctl set logical_router_port rp-public options:prefix=true
++ovn-nbctl set logical_router_port rp-sw0 options:prefix=true
++ovn-nbctl set logical_router_port rp-sw1 options:prefix=true
++
++OVN_POPULATE_ARP
++
++ovn-nbctl --wait=hv sync
++
++cat > /etc/dhcp/dhcpd.conf < pkt.pcap &])
++
++NETNS_DAEMONIZE([server], [dhcpd -6 -f s1 > dhcpd.log 2>&1], [dhcpd.pid])
++ovn-nbctl --wait=hv sync
++
++OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-public ipv6_prefix | cut -c4-15)" = ""])
++OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c4-15)" = ""])
++OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw1 ipv6_prefix | cut -c4-15)" = ""])
++
++AT_CHECK([ovn-nbctl get logical_router_port rp-public ipv6_prefix | cut -c3-16], [0], [dnl
++[2001:1db8:3333]
++])
++AT_CHECK([ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16], [0], [dnl
++[2001:1db8:3333]
++])
++AT_CHECK([ovn-nbctl get logical_router_port rp-sw1 ipv6_prefix | cut -c3-16], [0], [dnl
++[2001:1db8:3333]
++])
++
++prefix=$(ovn-nbctl list logical_router_port rp-public | awk -F/ '/ipv6_prefix/{print substr($ 1,25,9)}' | sed 's/://g')
++ovn-nbctl list logical_router_port rp-public > /tmp/rp-public
++ovn-nbctl set logical_router_port rp-sw0 options:prefix=false
++ovn-nbctl set logical_router_port rp-sw1 options:prefix=false
++# Renew message
++NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x05 and ip6[[113:4]]=0x${prefix} > renew.pcap &])
++# Reply message with Status OK
++NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x07 and ip6[[81:4]]=0x${prefix} > reply.pcap &])
++
++OVS_WAIT_UNTIL([
++ total_pkts=$(cat renew.pcap | wc -l)
++ test "${total_pkts}" = "1"
++])
++
++OVS_WAIT_UNTIL([
++ total_pkts=$(cat reply.pcap | wc -l)
++ test "${total_pkts}" = "1"
++])
++
++kill $(pidof tcpdump)
++
++ovn-nbctl set logical_router_port rp-sw0 options:prefix=false
++ovn-nbctl clear logical_router_port rp-sw0 ipv6_prefix
++OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16)" = "[2001:1db8:3333]"])
++AT_CHECK([ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16], [0], [dnl
++[]
++])
++
++kill $(pidof 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(["/.*error receiving.*/d
++/failed to query port patch-.*/d
++/.*terminating with signal 15.*/d"])
++]))
+diff --git a/tests/system-ovn.at b/tests/system-ovn.at
+index 8acfb3e39..20c058415 100644
+--- a/tests/system-ovn.at
++++ b/tests/system-ovn.at
+@@ -5272,158 +5272,22 @@ AT_CLEANUP
+ ])
+
+ OVN_FOR_EACH_NORTHD([
+-AT_SETUP([IPv6 prefix delegation])
++AT_SETUP([IPv6 prefix delegation - distributed router])
+ AT_SKIP_IF([test $HAVE_DHCPD = no])
+ AT_SKIP_IF([test $HAVE_TCPDUMP = no])
+ AT_KEYWORDS([ovn-ipv6-prefix_d])
+
+-ovn_start
+-OVS_TRAFFIC_VSWITCHD_START()
+-
+-ADD_BR([br-int])
+-ADD_BR([br-ext])
+-
+-ovs-ofctl add-flow br-ext action=normal
+-# 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
+-
+-ovn-nbctl lr-add R1
+-
+-ovn-nbctl ls-add sw0
+-ovn-nbctl ls-add sw1
+-ovn-nbctl ls-add public
+-
+-ovn-nbctl lrp-add R1 rp-sw0 00:00:01:01:02:03 192.168.1.1/24
+-ovn-nbctl lrp-add R1 rp-sw1 00:00:03:01:02:03 192.168.2.1/24
+-ovn-nbctl lrp-add R1 rp-public 00:00:02:01:02:03 172.16.1.1/24 \
+- -- lrp-set-gateway-chassis rp-public hv1
+-
+-ovn-nbctl lsp-add sw0 sw0-rp -- set Logical_Switch_Port sw0-rp \
+- type=router options:router-port=rp-sw0 \
+- -- lsp-set-addresses sw0-rp router
+-ovn-nbctl lsp-add sw1 sw1-rp -- set Logical_Switch_Port sw1-rp \
+- type=router options:router-port=rp-sw1 \
+- -- lsp-set-addresses sw1-rp router
+-
+-ovn-nbctl lsp-add public public-rp -- set Logical_Switch_Port public-rp \
+- type=router options:router-port=rp-public \
+- -- lsp-set-addresses public-rp router
+-
+-ADD_NAMESPACES(sw01)
+-ADD_VETH(sw01, sw01, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
+- "192.168.1.1")
+-ovn-nbctl lsp-add sw0 sw01 \
+- -- lsp-set-addresses sw01 "f0:00:00:01:02:03 192.168.1.2"
+-
+-ADD_NAMESPACES(sw11)
+-ADD_VETH(sw11, sw11, br-int, "192.168.2.2/24", "f0:00:00:02:02:03", \
+- "192.168.2.1")
+-ovn-nbctl lsp-add sw1 sw11 \
+- -- lsp-set-addresses sw11 "f0:00:00:02:02:03 192.168.2.2"
+-
+-ADD_NAMESPACES(server)
+-ADD_VETH(s1, server, br-ext, "2001:1db8:3333::2/64", "f0:00:00:01:02:05", \
+- "2001:1db8:3333::1")
+-
+-OVS_WAIT_UNTIL([test "$(ip netns exec server ip a | grep 2001:1db8:3333::2 | grep tentative)" = ""])
+-OVS_WAIT_UNTIL([test "$(ip netns exec server ip a | grep fe80 | grep tentative)" = ""])
+-
+-AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext])
+-ovn-nbctl lsp-add public public1 \
+- -- lsp-set-addresses public1 unknown \
+- -- lsp-set-type public1 localnet \
+- -- lsp-set-options public1 network_name=phynet
+-
+-ovn-nbctl set logical_router_port rp-public options:prefix_delegation=true
+-ovn-nbctl set logical_router_port rp-public options:prefix=true
+-ovn-nbctl set logical_router_port rp-sw0 options:prefix=true
+-ovn-nbctl set logical_router_port rp-sw1 options:prefix=true
+-
+-OVN_POPULATE_ARP
+-
+-ovn-nbctl --wait=hv sync
+-
+-cat > /etc/dhcp/dhcpd.conf < dhcpd.log 2>&1], [dhcpd.pid])
+-ovn-nbctl --wait=hv sync
+-
+-OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-public ipv6_prefix | cut -c4-15)" = ""])
+-OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c4-15)" = ""])
+-OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw1 ipv6_prefix | cut -c4-15)" = ""])
+-
+-AT_CHECK([ovn-nbctl get logical_router_port rp-public ipv6_prefix | cut -c3-16], [0], [dnl
+-[2001:1db8:3333]
+-])
+-AT_CHECK([ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16], [0], [dnl
+-[2001:1db8:3333]
+-])
+-AT_CHECK([ovn-nbctl get logical_router_port rp-sw1 ipv6_prefix | cut -c3-16], [0], [dnl
+-[2001:1db8:3333]
+-])
+-
+-prefix=$(ovn-nbctl list logical_router_port rp-public | awk -F/ '/ipv6_prefix/{print substr($1,25,9)}' | sed 's/://g')
+-ovn-nbctl set logical_router_port rp-sw0 options:prefix=false
+-ovn-nbctl set logical_router_port rp-sw1 options:prefix=false
+-
+-# Renew message
+-NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x05 and ip6[[113:4]]=0x${prefix} > renew.pcap &])
+-# Reply message with Status OK
+-NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x07 and ip6[[81:4]]=0x${prefix} > reply.pcap &])
+-
+-OVS_WAIT_UNTIL([
+- total_pkts=$(cat renew.pcap | wc -l)
+- test "${total_pkts}" = "1"
+-])
+-
+-OVS_WAIT_UNTIL([
+- total_pkts=$(cat reply.pcap | wc -l)
+- test "${total_pkts}" = "1"
+-])
+-
+-kill $(pidof tcpdump)
+-
+-ovn-nbctl set logical_router_port rp-sw0 options:prefix=false
+-ovn-nbctl clear logical_router_port rp-sw0 ipv6_prefix
+-OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16)" = "[2001:1db8:3333]"])
+-AT_CHECK([ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16], [0], [dnl
+-[]
++OVN_TEST_IPV6_PREFIX_DELEGATION(DGP)
++AT_CLEANUP
+ ])
+
+-kill $(pidof 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])
++OVN_FOR_EACH_NORTHD([
++AT_SETUP([IPv6 prefix delegation - gw router])
++AT_SKIP_IF([test $HAVE_DHCPD = no])
++AT_SKIP_IF([test $HAVE_TCPDUMP = no])
++AT_KEYWORDS([ovn-ipv6-prefix_d])
+
+-as
+-OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d
+-/.*terminating with signal 15.*/d"])
++OVN_TEST_IPV6_PREFIX_DELEGATION(GR)
+ AT_CLEANUP
+ ])
+
+@@ -8343,3 +8207,393 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
+
+ AT_CLEANUP
+ ])
++
++OVN_FOR_EACH_NORTHD([
++AT_SETUP([SNAT in gateway router mode])
++AT_KEYWORDS([ovnnat])
++
++CHECK_CONNTRACK()
++CHECK_CONNTRACK_NAT()
++ovn_start
++OVS_TRAFFIC_VSWITCHD_START()
++
++ADD_BR([br-int])
++check ovs-ofctl add-flow br0 action=normal
++# 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
++
++check ip link set br0 up
++check ovs-vsctl set open . external-ids:ovn-bridge-mappings=provider:br0
++
++check ovn-nbctl ls-add ls1
++check ovn-nbctl lsp-add ls1 ls1p1
++check ovn-nbctl lsp-set-addresses ls1p1 "00:00:00:01:01:01 192.168.1.1 2001::1"
++check ovn-nbctl lsp-add ls1 ls1p2
++check ovn-nbctl lsp-set-addresses ls1p2 "00:00:00:01:01:02 192.168.1.2 2001::2"
++
++check ovn-nbctl lr-add lr1
++check ovn-nbctl lrp-add lr1 lr1-ls1 00:00:00:00:00:01 192.168.1.254/24 2001::a/64
++check ovn-nbctl lsp-add ls1 ls1-lr1
++check ovn-nbctl lsp-set-addresses ls1-lr1 "00:00:00:00:00:01 192.168.1.254 2001::a"
++check ovn-nbctl lsp-set-type ls1-lr1 router
++check ovn-nbctl lsp-set-options ls1-lr1 router-port=lr1-ls1
++
++check ovn-nbctl set logical_router lr1 options:chassis=hv1
++
++check ovn-nbctl lrp-add lr1 lr1-pub 00:00:00:00:0f:01 172.16.1.254/24 1711::a/64
++check ovn-nbctl ls-add pub
++check ovn-nbctl lsp-add pub pub-lr1
++check ovn-nbctl lsp-set-type pub-lr1 router
++check ovn-nbctl lsp-set-options pub-lr1 router-port=lr1-pub
++check ovn-nbctl lsp-set-addresses pub-lr1 router
++
++check ovn-nbctl lsp-add pub ln -- lsp-set-options ln network_name=provider
++check ovn-nbctl lsp-set-type ln localnet
++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(ext1)
++ADD_INT(ext1, ext1, br0, 172.16.1.1/24, 1711::1/64)
++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)" = ""])
++OVS_WAIT_UNTIL([test "$(ip netns exec ls1p2 ip a | grep 2002::1 | grep tentative)" = ""])
++
++NS_CHECK_EXEC([ls1p1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.1 | FORMAT_PING], \
++[0], [dnl
++3 packets transmitted, 3 received, 0% packet loss, time 0ms
++])
++
++NS_CHECK_EXEC([ls1p1], [ping6 -v -q -c 3 -i 0.3 -w 2 1711::1 | FORMAT_PING], \
++[0], [dnl
++3 packets transmitted, 3 received, 0% packet loss, time 0ms
++])
++
++OVS_APP_EXIT_AND_WAIT([ovn-controller])
++as
++OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
++/connection dropped.*/d
++/removing policing failed: No such device/d"])
++AT_CLEANUP
++])
++
++OVN_FOR_EACH_NORTHD([
++AT_SETUP([mcast flow count])
++AT_KEYWORDS([ovnigmp IP-multicast])
++AT_SKIP_IF([test $HAVE_TCPDUMP = no])
++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 ovn-controller
++start_daemon ovn-controller
++
++check ovn-nbctl ls-add ls
++check ovn-nbctl lsp-add ls vm1
++check ovn-nbctl lsp-set-addresses vm1 00:00:00:00:00:01
++check ovn-nbctl lsp-add ls vm2
++check ovn-nbctl lsp-set-addresses vm2 00:00:00:00:00:02
++check ovn-nbctl lsp-add ls vm3
++check ovn-nbctl lsp-set-addresses vm3 00:00:00:00:00:03
++
++check ovn-nbctl set logical_switch ls other_config:mcast_querier=false other_config:mcast_snoop=true other_config:mcast_query_interval=30 other_config:mcast_eth_src=00:00:00:00:00:05 other_config:mcast_ip4_src=42.42.42.5 other_config:mcast_ip6_src=fe80::1 other_config:mcast_idle_timeout=3000
++ovn-sbctl list ip_multicast
++
++wait_igmp_flows_installed()
++{
++ OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int table=31 | \
++ grep 'priority=90' | grep "nw_dst=$1"])
++}
++
++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_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_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
++
++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])
++wait_for_ports_up
++
++NS_CHECK_EXEC([vm3], [ip addr add 228.0.0.1 dev vm3 autojoin], [0])
++wait_igmp_flows_installed 228.0.0.1
++
++NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 228.0.0.1], [ignore], [ignore])
++
++OVS_WAIT_UNTIL([
++ requests=`grep "ICMP echo request" -c vm3.pcap`
++ test "${requests}" -ge "3"
++])
++
++NETNS_DAEMONIZE([vm2], [tcpdump -n -i any -nnleX > vm2.pcap 2>/dev/null], [tcpdump2.pid])
++
++for i in `seq 1 40`;do
++ NS_CHECK_EXEC([vm2], [ip addr add 228.1.$i.1 dev vm2 autojoin &], [0])
++ NS_CHECK_EXEC([vm3], [ip addr add 229.1.$i.1 dev vm3 autojoin &], [0])
++ # Do not go too fast. If going fast, there is a higher chance of sb being busy, causing full recompute (engine has not run)
++ # In this test, we do not want too many recomputes as they might hide I+I related errors
++ sleep 0.2
++done
++
++for i in `seq 1 40`;do
++ wait_igmp_flows_installed 228.1.$i.1
++ wait_igmp_flows_installed 229.1.$i.1
++done
++ovn-sbctl list multicast_group
++
++NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 228.1.1.1], [ignore], [ignore])
++
++OVS_WAIT_UNTIL([
++ requests=`grep "ICMP echo request" -c vm2.pcap`
++ test "${requests}" -ge "3"
++])
++
++# The test could succeed thanks to a lucky northd recompute...after hitting too any flows
++# Double check we never hit error condition
++AT_CHECK([grep -qE 'Too many active mcast flows' northd/ovn-northd.log], [1])
++
++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
++/removing policing failed: No such device/d"])
++AT_CLEANUP
++])
++
++OVN_FOR_EACH_NORTHD([
++AT_SETUP([DVR ping router port])
++AT_KEYWORDS([dvr])
++
++ovn_start
++
++OVS_TRAFFIC_VSWITCHD_START()
++ADD_BR([br-int])
++ADD_BR([br-ext])
++
++check ovs-ofctl add-flow br-ext action=normal
++# 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
++
++check ovs-vsctl set open . external_ids:ovn-bridge-mappings=phys:br-ext
++check ovs-vsctl set open . external-ids:ovn-chassis-mac-mappings="phys:ee:00:00:00:00:10"
++
++
++check ovn-nbctl ls-add internal
++
++check ovn-nbctl lsp-add internal ln_internal "" 100
++check ovn-nbctl lsp-set-addresses ln_internal unknown
++check ovn-nbctl lsp-set-type ln_internal localnet
++check ovn-nbctl lsp-set-options ln_internal network_name=phys
++
++check ovn-nbctl lsp-add internal internal-gw
++check ovn-nbctl lsp-set-type internal-gw router
++check ovn-nbctl lsp-set-addresses internal-gw router
++check ovn-nbctl lsp-set-options internal-gw router-port=gw-internal
++
++check ovn-nbctl lsp-add internal vif0
++# Set address as unknown so that LRP has to generate ARP request
++check ovn-nbctl lsp-set-addresses vif0 unknown
++
++check ovn-nbctl lr-add gw
++check ovn-nbctl lrp-add gw gw-internal 00:00:00:00:20:00 192.168.20.1/24
++
++ADD_NAMESPACES(vif0)
++ADD_VETH(vif0, vif0, br-int, "192.168.20.10/24", "00:00:00:00:20:10", "192.168.20.1")
++
++check ovn-nbctl --wait=sb sync
++check ovn-nbctl --wait=hv sync
++
++NS_CHECK_EXEC([vif0], [ping -q -c 3 -i 0.3 -w 1 192.168.20.1 | FORMAT_PING], \
++[0], [dnl
++3 packets transmitted, 3 received, 0% packet loss, time 0ms
++])
++
++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([SNAT in separate zone from DNAT])
++
++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
++
++# The goal of this test is to ensure that when traffic is first DNATted
++# (by way of a load balancer), and then SNATted, the SNAT happens in a
++# separate conntrack zone from the DNAT.
++
++start_daemon ovn-controller
++
++check ovn-nbctl ls-add public
++
++check ovn-nbctl lr-add r1
++check ovn-nbctl lrp-add r1 r1_public 00:de:ad:ff:00:01 172.16.0.1/16
++check ovn-nbctl lrp-add r1 r1_s1 00:de:ad:fe:00:01 173.0.1.1/24
++check ovn-nbctl lrp-set-gateway-chassis r1_public hv1
++
++check ovn-nbctl lb-add r1_lb 30.0.0.1 172.16.0.102
++check ovn-nbctl lr-lb-add r1 r1_lb
++
++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 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 public public_r1
++check ovn-nbctl lsp-set-type public_r1 router
++check ovn-nbctl lsp-set-addresses public_r1 router
++check ovn-nbctl lsp-set-options public_r1 router-port=r1_public nat-addresses=router
++
++check ovn-nbctl lr-add r2
++check ovn-nbctl lrp-add r2 r2_public 00:de:ad:ff:00:02 172.16.0.2/16
++check ovn-nbctl lrp-add r2 r2_s2 00:de:ad:fe:00:02 173.0.2.1/24
++check ovn-nbctl lr-nat-add r2 dnat_and_snat 172.16.0.102 173.0.2.2
++check ovn-nbctl lrp-set-gateway-chassis r2_public hv1
++
++check ovn-nbctl ls-add s2
++check ovn-nbctl lsp-add s2 s2_r2
++check ovn-nbctl lsp-set-type s2_r2 router
++check ovn-nbctl lsp-set-addresses s2_r2 router
++check ovn-nbctl lsp-set-options s2_r2 router-port=r2_s2
++
++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 public public_r2
++check ovn-nbctl lsp-set-type public_r2 router
++check ovn-nbctl lsp-set-addresses public_r2 router
++check ovn-nbctl lsp-set-options public_r2 router-port=r2_public nat-addresses=router
++
++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")
++
++check ovn-nbctl lr-nat-add r1 dnat_and_snat 172.16.0.101 173.0.1.2 vm1 00:00:00:01:02:03
++check ovn-nbctl --wait=hv sync
++
++# Next, make sure that a ping works as expected
++NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.1 | FORMAT_PING], \
++[0], [dnl
++3 packets transmitted, 3 received, 0% packet loss, time 0ms
++])
++
++# Finally, make sure that conntrack shows two separate zones being used for
++# DNAT and SNAT
++AT_CHECK([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=172.16.0.102,dst=173.0.1.2,id=,type=0,code=0),zone=,mark=2
++])
++
++# The final two entries appear identical here. That is because FORMAT_CT
++# scrubs the zone numbers. In actuality, the zone numbers are different,
++# which is why there are two entries.
++AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.0.102) | \
++sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl
++icmp,orig=(src=172.16.0.101,dst=172.16.0.102,id=,type=8,code=0),reply=(src=173.0.2.2,dst=172.16.0.101,id=,type=0,code=0),zone=
++icmp,orig=(src=173.0.1.2,dst=172.16.0.102,id=,type=8,code=0),reply=(src=172.16.0.102,dst=172.16.0.101,id=,type=0,code=0),zone=
++icmp,orig=(src=173.0.1.2,dst=172.16.0.102,id=,type=8,code=0),reply=(src=172.16.0.102,dst=172.16.0.101,id=,type=0,code=0),zone=
++])
++
++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/SPECS/ovn22.06.spec b/SPECS/ovn22.06.spec
deleted file mode 100644
index 23798b6..0000000
--- a/SPECS/ovn22.06.spec
+++ /dev/null
@@ -1,591 +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 ovn22.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: 22.06.0
-Release: 16%{?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 6f24c2bc769afde0a390ce344de1a7d9c592e5a6
-%define ovsshortcommit 6f24c2b
-
-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 Jul 01 2022 Mark Michelson - 22.06.0-16
-- ovs: Bump submodule to newer version (#2102618)
-[Gerrit: 5593044a8be0d2ce730e4890cf213ee760916889]
-[Upstream: 5593044a8be0d2ce730e4890cf213ee760916889]
-
-* Wed Jun 29 2022 Ihar Hrachyshka - 22.06.0-15
-- tests: add multi-chassis keyword to relevant test cases
-[Gerrit: 4bdade3593ae3c6604822716d22ab04b0af962da]
-[Upstream: 4bdade3593ae3c6604822716d22ab04b0af962da]
-
-* Wed Jun 29 2022 Lorenzo Bianconi - 22.06.0-14
-- northd: add condition for stateless nat drop flow in S_ROUTER_IN_GW_REDIRECT pipeline (#2094980)
-[Gerrit: 9885154fc41005dbb8fbbdca9e3a38d892870f53]
-[Upstream: 9885154fc41005dbb8fbbdca9e3a38d892870f53]
-
-* Wed Jun 29 2022 Ales Musil - 22.06.0-13
-- northd.c: Add flow to skip put_nd action if ip6.src or nd.sll is 0
-[Gerrit: c5596102cb84e22086d7807b31cbe5c9e893ac38]
-[Upstream: 0a4bc2075f7df1bb38338cde1973c931aa5e1942]
-
-* Wed Jun 29 2022 Terry Wilson - 22.06.0-12
-- Allow arbitrary args to be passed to called binary
-[Gerrit: 849106f6ee75d7b1ff990763325d41d45c843a64]
-[Upstream: 849106f6ee75d7b1ff990763325d41d45c843a64]
-
-* Mon Jun 27 2022 Ihar Hrachyshka - 22.06.0-11
-- tests: ovn-nbctl dump-flows -> ovn-sbctl dump-flows
-[Gerrit: 656a91b6b5cd9d9e48b8e938fcffb81ead2d9fda]
-[Upstream: 656a91b6b5cd9d9e48b8e938fcffb81ead2d9fda]
-
-* Mon Jun 27 2022 Ihar Hrachyshka - 22.06.0-10
-- Fix memleak in ovn-nbctl when args can't be parsed
-[Gerrit: 70b360325c13f399835b1f5c7ac0c0acd4832773]
-[Upstream: 70b360325c13f399835b1f5c7ac0c0acd4832773]
-
-* Mon Jun 20 2022 Ihar Hrachyshka - 22.06.0-9
-- Implement RARP activation strategy for ports
-[Gerrit: c75ddaf804cc8ea8499706430b438ae53f2f1224]
-[Upstream: ee20c48c2f5ce9d512adfcbea3ee300f8bb09625]
-
-* Tue Jun 14 2022 Ihar Hrachyshka - 22.06.0-8
-- Fix pidfile_is_running when $cmd is not passed
-[Gerrit: 44e047d6f1be5ae4f564e82a928cf1f08f1908ef]
-[Upstream: 6e57adfe5a35fc36ef290c6e9ae7e616f73cd3d2]
-
-* Thu Jun 09 2022 Ihar Hrachyshka - 22.06.0-7
-- Lock pinctrl_mutex for pinctrl_wait
-[Gerrit: 6e36ad7a52ec4e6443ccb3185bda6421cdf6747e]
-[Upstream: 6e36ad7a52ec4e6443ccb3185bda6421cdf6747e]
-
-* Thu Jun 09 2022 Terry Wilson - 22.06.0-6
-- Ensure pid belongs to ovsdb-server in ovn-ctl
-[Gerrit: d0847f56913245c19a33e087f730c084ca674c83]
-[Upstream: d0847f56913245c19a33e087f730c084ca674c83]
-
-* Thu Jun 09 2022 Terry Wilson - 22.06.0-5
-- Handle re-used pids in pidfile_is_running
-[Gerrit: 98e7d4b3675b237c770763377382075ac08c64ba]
-[Upstream: 98e7d4b3675b237c770763377382075ac08c64ba]
-
-* Fri Jun 03 2022 Mark Michelson - 22.06.0-4
-- Prepare for 22.06.1.
-[Gerrit: 437dc3a01266d7f128bba532c674c5827af1bd6f]
-[Upstream: 437dc3a01266d7f128bba532c674c5827af1bd6f]
-
diff --git a/SPECS/ovn22.09.spec b/SPECS/ovn22.09.spec
new file mode 100644
index 0000000..9f85fe0
--- /dev/null
+++ b/SPECS/ovn22.09.spec
@@ -0,0 +1,558 @@
+# 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 ovn22.09
+
+# 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: 22.09.0
+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
+
+# 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 64b79581be012db6053e9caead4090f5becbc3b8
+%define ovsshortcommit 64b7958
+
+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
+* Thu Oct 20 2022 Xavier Simonart - 22.09.0-11
+- ovs: Bump submodule to tip of branch-3.0 and add related test (#2126450)
+[Upstream: c18415d5ae7273c633190df4ac9e872a0a0f9709]
+
+* Wed Oct 05 2022 Lorenzo Bianconi - 22.09.0-10
+- controller: fix ipv6 prefix delegation in gw router mode (#2129244 2129247)
+[Upstream: f2042a2e6aeb1a7fe266316337545331f5186dd0]
+
+* Wed Oct 05 2022 Vladislav Odintsov - 22.09.0-9
+- spec: require python3-openvswitch for ovn-detrace
+[Upstream: 29e4d43966fbf34d9707e31880c455f22a643bb3]
+
+* Mon Oct 03 2022 Mark Michelson - 22.09.0-8
+- northd: Use separate SNAT for already-DNATted traffic.
+[Upstream: 51044dbfdba234a3f50d8c9c952335e41b72a39b]
+
+* Fri Sep 30 2022 Ales Musil - 22.09.0-7
+- controller: Restore MAC and vlan for DVR scenario (#2123837)
+[Upstream: 86e99bf95a2191ebdcd5d03335ff8add2a636f55]
+
+* Fri Sep 30 2022 Xavier Simonart - 22.09.0-6
+- northd: Fix multicast table full (#2094710)
+[Upstream: 40dd85eb8d2d2d88f9000b6be6fb263b4bd1a27f]
+
+* Tue Sep 27 2022 Xavier Simonart - 22.09.0-5
+- controller: Fix first ping from lsp to external through snat failing (#2130045)
+[Upstream: 76a01e53a9fcc3184211cca10787d462cb86a352]
+
+* Fri Sep 16 2022 Mark Michelson - 22.09.0-4
+- Prepare for 22.09.1.
+[Upstream: 854c2b1a4ba9ef35e03348d1bd4fc8265f3f74a3]
+