From 42fd60d03aaa82afcbaa4a8db48bc53cff1ad9e8 Mon Sep 17 00:00:00 2001 From: Alfredo Moralejo Date: Nov 23 2022 17:01:35 +0000 Subject: Update to ovn22.09-22.09.0-11.el9 from FDP --- diff --git a/.ovn.metadata b/.ovn.metadata index df4ddae..2f44139 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 +cae717fbee361a235064a1d79b012b2590908f7c SOURCES/ovn-22.09.0.tar.gz +d34f96421a86004aa5d26ecf975edefd09f948b1 SOURCES/Pygments-1.4.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 e08a142..0000000 --- a/SOURCES/ovn22.06.patch +++ /dev/null @@ -1,2344 +0,0 @@ -diff --git a/AUTHORS.rst b/AUTHORS.rst -index d3747f8d1..5d60088e4 100644 ---- a/AUTHORS.rst -+++ b/AUTHORS.rst -@@ -395,6 +395,7 @@ Vishal Deep Ajmera vishal.deep.ajmera@ericsson.com - Vivien Bernet-Rollande vbr@soprive.net - Vladislav Odintsov odivlad@gmail.com - wangqianyu wang.qianyu@zte.com.cn -+wangchuanlei wangchuanlei@inspur.com - Wang Sheng-Hui shhuiw@gmail.com - Wang Zhike wangzhike@jd.com - Wei Li liw@dtdream.com -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/binding.c b/controller/binding.c -index 2279570f9..9025681db 100644 ---- a/controller/binding.c -+++ b/controller/binding.c -@@ -386,6 +386,23 @@ update_ld_external_ports(const struct sbrec_port_binding *binding_rec, - } - } - -+static void -+update_ld_multichassis_ports(const struct sbrec_port_binding *binding_rec, -+ struct hmap *local_datapaths) -+{ -+ struct local_datapath *ld = get_local_datapath( -+ local_datapaths, binding_rec->datapath->tunnel_key); -+ if (!ld) { -+ return; -+ } -+ if (binding_rec->additional_chassis) { -+ add_local_datapath_multichassis_port(ld, binding_rec->logical_port, -+ binding_rec); -+ } else { -+ remove_local_datapath_multichassis_port(ld, binding_rec->logical_port); -+ } -+} -+ - static void - update_ld_localnet_port(const struct sbrec_port_binding *binding_rec, - struct shash *bridge_mappings, -@@ -1752,6 +1769,8 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) - - struct ovs_list localnet_lports = OVS_LIST_INITIALIZER(&localnet_lports); - struct ovs_list external_lports = OVS_LIST_INITIALIZER(&external_lports); -+ struct ovs_list multichassis_ports = OVS_LIST_INITIALIZER( -+ &multichassis_ports); - - struct lport { - struct ovs_list list_node; -@@ -1787,6 +1806,13 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) - - case LP_VIF: - consider_vif_lport(pb, b_ctx_in, b_ctx_out, NULL, qos_map_ptr); -+ if (pb->additional_chassis) { -+ struct lport *multichassis_lport = xmalloc( -+ sizeof *multichassis_lport); -+ multichassis_lport->pb = pb; -+ ovs_list_push_back(&multichassis_ports, -+ &multichassis_lport->list_node); -+ } - break; - - case LP_CONTAINER: -@@ -1862,6 +1888,16 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) - free(ext_lport); - } - -+ /* Run through multichassis lport list to see if these are ports -+ * on local datapaths discovered from above loop, and update the -+ * corresponding local datapath accordingly. */ -+ struct lport *multichassis_lport; -+ LIST_FOR_EACH_POP (multichassis_lport, list_node, &multichassis_ports) { -+ update_ld_multichassis_ports(multichassis_lport->pb, -+ b_ctx_out->local_datapaths); -+ free(multichassis_lport); -+ } -+ - shash_destroy(&bridge_mappings); - - if (!sset_is_empty(b_ctx_out->egress_ifaces) -@@ -1934,6 +1970,7 @@ remove_pb_from_local_datapath(const struct sbrec_port_binding *pb, - } else if (!strcmp(pb->type, "external")) { - remove_local_datapath_external_port(ld, pb->logical_port); - } -+ remove_local_datapath_multichassis_port(ld, pb->logical_port); - } - - static void -@@ -2677,6 +2714,7 @@ delete_done: - case LP_VIF: - case LP_CONTAINER: - case LP_VIRTUAL: -+ update_ld_multichassis_ports(pb, b_ctx_out->local_datapaths); - handled = handle_updated_vif_lport(pb, lport_type, b_ctx_in, - b_ctx_out, qos_map_ptr); - break; -diff --git a/controller/lflow.c b/controller/lflow.c -index 934b23698..6055097b5 100644 ---- a/controller/lflow.c -+++ b/controller/lflow.c -@@ -1775,6 +1775,7 @@ add_lb_vip_hairpin_reply_action(struct in6_addr *vip6, ovs_be32 vip, - uint64_t cookie, struct ofpbuf *ofpacts) - { - struct match match = MATCH_CATCHALL_INITIALIZER; -+ size_t ol_offset = ofpacts->size; - struct ofpact_learn *ol = ofpact_put_LEARN(ofpacts); - struct ofpact_learn_spec *ol_spec; - unsigned int imm_bytes; -@@ -1928,6 +1929,8 @@ add_lb_vip_hairpin_reply_action(struct in6_addr *vip6, ovs_be32 vip, - src_imm = ofpbuf_put_zeros(ofpacts, OFPACT_ALIGN(imm_bytes)); - memcpy(src_imm, &imm_reg_value, imm_bytes); - -+ /* Reload ol pointer since ofpacts buffer can be reallocated. */ -+ ol = ofpbuf_at_assert(ofpacts, ol_offset, sizeof *ol); - ofpact_finish_LEARN(ofpacts, &ol); - } - -diff --git a/controller/local_data.c b/controller/local_data.c -index 98445902b..7f874fc19 100644 ---- a/controller/local_data.c -+++ b/controller/local_data.c -@@ -72,6 +72,7 @@ local_datapath_alloc(const struct sbrec_datapath_binding *dp) - ld->is_switch = datapath_is_switch(dp); - ld->is_transit_switch = datapath_is_transit_switch(dp); - shash_init(&ld->external_ports); -+ shash_init(&ld->multichassis_ports); - /* memory accounting - common part. */ - local_datapath_usage += sizeof *ld; - -@@ -97,13 +98,20 @@ local_datapath_destroy(struct local_datapath *ld) - SHASH_FOR_EACH (node, &ld->external_ports) { - local_datapath_usage -= strlen(node->name); - } -- local_datapath_usage -= shash_count(&ld->external_ports) * sizeof *node; -+ SHASH_FOR_EACH (node, &ld->multichassis_ports) { -+ local_datapath_usage -= strlen(node->name); -+ } -+ local_datapath_usage -= (shash_count(&ld->external_ports) -+ * sizeof *node); -+ local_datapath_usage -= (shash_count(&ld->multichassis_ports) -+ * sizeof *node); - local_datapath_usage -= sizeof *ld; - local_datapath_usage -= - ld->n_allocated_peer_ports * sizeof *ld->peer_ports; - - free(ld->peer_ports); - shash_destroy(&ld->external_ports); -+ shash_destroy(&ld->multichassis_ports); - free(ld); - } - -@@ -274,6 +282,26 @@ remove_local_datapath_external_port(struct local_datapath *ld, - } - } - -+void -+add_local_datapath_multichassis_port(struct local_datapath *ld, -+ char *logical_port, const void *data) -+{ -+ if (!shash_replace(&ld->multichassis_ports, logical_port, data)) { -+ local_datapath_usage += sizeof(struct shash_node) + -+ strlen(logical_port); -+ } -+} -+ -+void -+remove_local_datapath_multichassis_port(struct local_datapath *ld, -+ char *logical_port) -+{ -+ if (shash_find_and_delete(&ld->multichassis_ports, logical_port)) { -+ local_datapath_usage -= sizeof(struct shash_node) + -+ strlen(logical_port); -+ } -+} -+ - void - local_datapath_memory_usage(struct simap *usage) - { -diff --git a/controller/local_data.h b/controller/local_data.h -index 9306ddf15..d898c8aa5 100644 ---- a/controller/local_data.h -+++ b/controller/local_data.h -@@ -58,6 +58,7 @@ struct local_datapath { - size_t n_allocated_peer_ports; - - struct shash external_ports; -+ struct shash multichassis_ports; - }; - - struct local_datapath *local_datapath_alloc( -@@ -155,5 +156,10 @@ void add_local_datapath_external_port(struct local_datapath *ld, - char *logical_port, const void *data); - void remove_local_datapath_external_port(struct local_datapath *ld, - char *logical_port); -+void add_local_datapath_multichassis_port(struct local_datapath *ld, -+ char *logical_port, -+ const void *data); -+void remove_local_datapath_multichassis_port(struct local_datapath *ld, -+ char *logical_port); - - #endif /* controller/local_data.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..2e9138036 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; -@@ -2953,6 +3000,11 @@ static void init_physical_ctx(struct engine_node *node, - engine_get_input("SB_port_binding", node), - "name"); - -+ struct ovsdb_idl_index *sbrec_port_binding_by_datapath = -+ engine_ovsdb_node_get_index( -+ engine_get_input("SB_port_binding", node), -+ "datapath"); -+ - struct sbrec_multicast_group_table *multicast_group_table = - (struct sbrec_multicast_group_table *)EN_OVSDB_GET( - engine_get_input("SB_multicast_group", node)); -@@ -2992,6 +3044,7 @@ static void init_physical_ctx(struct engine_node *node, - struct simap *ct_zones = &ct_zones_data->current; - - p_ctx->sbrec_port_binding_by_name = sbrec_port_binding_by_name; -+ p_ctx->sbrec_port_binding_by_datapath = sbrec_port_binding_by_datapath; - p_ctx->port_binding_table = port_binding_table; - p_ctx->mc_group_table = multicast_group_table; - p_ctx->br_int = br_int; -@@ -3164,6 +3217,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 +3541,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 +3589,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..816a557e7 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,155 @@ 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 -+enforce_tunneling_for_multichassis_ports( -+ struct local_datapath *ld, -+ const struct sbrec_port_binding *binding, -+ const struct sbrec_chassis *chassis, -+ const struct hmap *chassis_tunnels, -+ enum mf_field_id mff_ovn_geneve, -+ struct ovn_desired_flow_table *flow_table) -+{ -+ if (shash_is_empty(&ld->multichassis_ports)) { -+ return; -+ } -+ -+ struct ovs_list *tuns = get_remote_tunnels(binding, chassis, -+ chassis_tunnels); -+ if (ovs_list_is_empty(tuns)) { -+ free(tuns); -+ return; -+ } -+ -+ uint32_t dp_key = binding->datapath->tunnel_key; -+ uint32_t port_key = binding->tunnel_key; -+ -+ struct shash_node *node; -+ SHASH_FOR_EACH (node, &ld->multichassis_ports) { -+ const struct sbrec_port_binding *mcp = node->data; -+ -+ struct ofpbuf ofpacts; -+ ofpbuf_init(&ofpacts, 0); -+ -+ bool is_vtep_port = !strcmp(binding->type, "vtep"); -+ /* rewrite MFF_IN_PORT to bypass OpenFlow loopback check for ARP/ND -+ * responder in L3 networks. */ -+ if (is_vtep_port) { -+ put_load(ofp_to_u16(OFPP_NONE), MFF_IN_PORT, 0, 16, &ofpacts); -+ } -+ -+ struct match match; -+ match_outport_dp_and_port_keys(&match, dp_key, port_key); -+ match_set_reg(&match, MFF_LOG_INPORT - MFF_REG0, mcp->tunnel_key); -+ -+ struct tunnel *tun; -+ LIST_FOR_EACH (tun, list_node, tuns) { -+ put_encapsulation(mff_ovn_geneve, tun->tun, -+ binding->datapath, port_key, is_vtep_port, -+ &ofpacts); -+ ofpact_put_OUTPUT(&ofpacts)->port = tun->tun->ofport; -+ } -+ ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 110, -+ binding->header_.uuid.parts[0], &match, &ofpacts, -+ &binding->header_.uuid); -+ ofpbuf_uninit(&ofpacts); -+ } -+ -+ struct tunnel *tun_elem; -+ LIST_FOR_EACH_POP (tun_elem, list_node, tuns) { -+ free(tun_elem); -+ } -+ free(tuns); -+} -+ - static void - consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, - enum mf_field_id mff_ovn_geneve, -@@ -1239,6 +1390,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; -@@ -1415,6 +1570,9 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, - binding->header_.uuid.parts[0], - &match, ofpacts_p, &binding->header_.uuid); - -+ enforce_tunneling_for_multichassis_ports( -+ ld, binding, chassis, chassis_tunnels, mff_ovn_geneve, flow_table); -+ - /* No more tunneling to set up. */ - goto out; - } -@@ -1733,20 +1891,49 @@ physical_handle_flows_for_lport(const struct sbrec_port_binding *pb, - - ofctrl_remove_flows(flow_table, &pb->header_.uuid); - -+ struct local_datapath *ldp = -+ get_local_datapath(p_ctx->local_datapaths, -+ pb->datapath->tunnel_key); - if (!strcmp(pb->type, "external")) { - /* External lports have a dependency on the localnet port. - * We need to remove the flows of the localnet port as well - * and re-consider adding the flows for it. - */ -- struct local_datapath *ldp = -- get_local_datapath(p_ctx->local_datapaths, -- pb->datapath->tunnel_key); - if (ldp && ldp->localnet_port) { - ofctrl_remove_flows(flow_table, &ldp->localnet_port->header_.uuid); - physical_eval_port_binding(p_ctx, ldp->localnet_port, flow_table); - } - } - -+ if (ldp) { -+ bool multichassis_state_changed = ( -+ !!pb->additional_chassis == -+ !!shash_find(&ldp->multichassis_ports, pb->logical_port) -+ ); -+ if (multichassis_state_changed) { -+ if (pb->additional_chassis) { -+ add_local_datapath_multichassis_port( -+ ldp, pb->logical_port, pb); -+ } else { -+ remove_local_datapath_multichassis_port( -+ ldp, pb->logical_port); -+ } -+ -+ struct sbrec_port_binding *target = -+ sbrec_port_binding_index_init_row( -+ p_ctx->sbrec_port_binding_by_datapath); -+ sbrec_port_binding_index_set_datapath(target, ldp->datapath); -+ -+ const struct sbrec_port_binding *port; -+ SBREC_PORT_BINDING_FOR_EACH_EQUAL ( -+ port, target, p_ctx->sbrec_port_binding_by_datapath) { -+ ofctrl_remove_flows(flow_table, &port->header_.uuid); -+ physical_eval_port_binding(p_ctx, port, flow_table); -+ } -+ sbrec_port_binding_index_destroy_row(target); -+ } -+ } -+ - if (!removed) { - physical_eval_port_binding(p_ctx, pb, flow_table); - if (!strcmp(pb->type, "patch")) { -diff --git a/controller/physical.h b/controller/physical.h -index ee4b1ae1f..1b8f1ea55 100644 ---- a/controller/physical.h -+++ b/controller/physical.h -@@ -45,6 +45,7 @@ struct local_nonvif_data; - - struct physical_ctx { - struct ovsdb_idl_index *sbrec_port_binding_by_name; -+ struct ovsdb_idl_index *sbrec_port_binding_by_datapath; - const struct sbrec_port_binding_table *port_binding_table; - const struct sbrec_multicast_group_table *mc_group_table; - const struct ovsrec_bridge *br_int; -diff --git a/controller/pinctrl.c b/controller/pinctrl.c -index 428863293..2fcf91bc9 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)); -@@ -3434,11 +3454,11 @@ pinctrl_handler(void *arg_) - - ip_mcast_querier_run(swconn, &send_mcast_query_time); - } -- } - -- ovs_mutex_lock(&pinctrl_mutex); -- svc_monitors_run(swconn, &svc_monitors_next_run_time); -- ovs_mutex_unlock(&pinctrl_mutex); -+ ovs_mutex_lock(&pinctrl_mutex); -+ svc_monitors_run(swconn, &svc_monitors_next_run_time); -+ ovs_mutex_unlock(&pinctrl_mutex); -+ } - - rconn_run_wait(swconn); - rconn_recv_wait(swconn); -@@ -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/ic/ovn-ic.c b/ic/ovn-ic.c -index 8511cb9ac..95a5ff0de 100644 ---- a/ic/ovn-ic.c -+++ b/ic/ovn-ic.c -@@ -925,7 +925,12 @@ parse_route(const char *s_prefix, const char *s_nexthop, - } - - unsigned int nlen; -- return ip46_parse_cidr(s_nexthop, nexthop, &nlen); -+ if (!ip46_parse_cidr(s_nexthop, nexthop, &nlen)) { -+ return false; -+ } -+ -+ /* Do not learn routes with link-local next hop. */ -+ return !in6_is_lla(nexthop); - } - - /* Return false if can't be added due to bad format. */ -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..f6b84c318 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)) { -@@ -3832,6 +3842,13 @@ ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn, struct ovn_northd_lb *lb, - backend_nb->svc_mon_src_ip); - } - -+ if ((!op->sb->n_up || !op->sb->up[0]) -+ && mon_info->sbrec_mon->status -+ && !strcmp(mon_info->sbrec_mon->status, "online")) { -+ sbrec_service_monitor_set_status(mon_info->sbrec_mon, -+ "offline"); -+ } -+ - backend_nb->sbrec_monitor = mon_info->sbrec_mon; - mon_info->required = true; - } -@@ -10976,6 +10993,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 +12041,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 +12060,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..47fd5a544 100644 ---- a/ovn-nb.xml -+++ b/ovn-nb.xml -@@ -610,6 +610,7 @@ - Determines whether unregistered multicast traffic should be flooded - or not. Only applicable if - is enabled. -+ Default: false. - - -@@ -1045,6 +1046,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 -@@ -1129,12 +1141,13 @@ - type='{"type": "boolean"}'> - If set to true, multicast packets (except reports) are - unconditionally forwarded to the specific port. -+ Default: false. - - - - If set to true, multicast reports are unconditionally -- forwarded to the specific port. -+ forwarded to the specific port. Default: false. - - - -@@ -2900,6 +2913,10 @@ - has :mcast_relay set - to true. -

    -+ -+

    -+ Default: false. -+

    - - - - - -+ -+ 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-ic.at b/tests/ovn-ic.at -index 05bd3e9a6..89f223562 100644 ---- a/tests/ovn-ic.at -+++ b/tests/ovn-ic.at -@@ -492,6 +492,56 @@ OVN_CLEANUP_IC([az1], [az2]) - AT_CLEANUP - ]) - -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([ovn-ic -- route sync -- IPv6 route tables]) -+AT_KEYWORDS([IPv6-route-sync]) -+ -+ovn_init_ic_db -+ovn-ic-nbctl ts-add ts1 -+ -+for i in 1 2; do -+ ovn_start az$i -+ ovn_as az$i -+ -+ # Enable route learning at AZ level -+ ovn-nbctl set nb_global . options:ic-route-learn=true -+ # Enable route advertising at AZ level -+ ovn-nbctl set nb_global . options:ic-route-adv=true -+ -+ # Create LRP and connect to TS -+ ovn-nbctl lr-add lr$i -+ ovn-nbctl lrp-add lr$i lrp-lr$i-ts1 aa:aa:aa:aa:aa:0$i 2001:db8:1::$i/64 -+ ovn-nbctl lsp-add ts1 lsp-ts1-lr$i \ -+ -- lsp-set-addresses lsp-ts1-lr$i router \ -+ -- lsp-set-type lsp-ts1-lr$i router \ -+ -- lsp-set-options lsp-ts1-lr$i router-port=lrp-lr$i-ts1 -+ -+ ovn-nbctl lrp-add lr$i lrp-lr$i-p$i 00:00:00:00:00:0$i 2002:db8:1::$i/64 -+done -+ -+for i in 1 2; do -+ OVS_WAIT_UNTIL([ovn_as az$i ovn-nbctl lr-route-list lr$i | grep learned]) -+done -+ -+AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr1 | awk '/learned/{print $1, $2}'], [0], [dnl -+2002:db8:1::/64 2001:db8:1::2 -+]) -+ -+# Do not learn routes from link-local nexthops -+for i in 1 2; do -+ ovn_as az$i -+ ovn-nbctl lrp-del lrp-lr$i-ts1 -+ ovn-nbctl lrp-add lr$i lrp-lr$i-ts1 aa:aa:aa:aa:aa:0$i 169.254.100.$i/24 -+done -+ -+OVS_WAIT_WHILE([ovn_as az1 ovn-nbctl lr-route-list lr1 | grep learned]) -+AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr1 | grep -q learned], [1]) -+ -+OVN_CLEANUP_IC([az1], [az2]) -+ -+AT_CLEANUP -+]) -+ - OVN_FOR_EACH_NORTHD([ - AT_SETUP([ovn-ic -- route sync -- route tables]) - -diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at -index a071b3689..773904f95 100644 ---- a/tests/ovn-northd.at -+++ b/tests/ovn-northd.at -@@ -1213,6 +1213,13 @@ ovn-nbctl ls-add sw1 - ovn-nbctl --wait=sb lsp-add sw1 sw1-p1 -- lsp-set-addresses sw1-p1 \ - "02:00:00:00:00:03 20.0.0.3" - -+# service_monitors state online requires corresponding port_binding to be "up" -+ovn-sbctl chassis-add hv1 geneve 127.0.0.1 -+ovn-sbctl lsp-bind sw0-p1 hv1 -+ovn-sbctl lsp-bind sw1-p1 hv1 -+wait_row_count nb:Logical_Switch_Port 1 name=sw0-p1 'up=true' -+wait_row_count nb:Logical_Switch_Port 1 name=sw1-p1 'up=true' -+ - wait_row_count Service_Monitor 0 - - ovn-nbctl --wait=sb set load_balancer . ip_port_mappings:10.0.0.3=sw0-p1:10.0.0.2 -@@ -1226,7 +1233,7 @@ check ovn-nbctl --wait=sb ls-lb-add sw0 lb1 - AT_CAPTURE_FILE([sbflows]) - OVS_WAIT_FOR_OUTPUT( - [ovn-sbctl dump-flows sw0 | tee sbflows | grep 'priority=120.*backends' | sed 's/table=..//'], 0, [dnl -- (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) -+ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) - ]) - - AS_BOX([Delete the Load_Balancer_Health_Check]) -@@ -1236,7 +1243,7 @@ wait_row_count Service_Monitor 0 - AT_CAPTURE_FILE([sbflows2]) - OVS_WAIT_FOR_OUTPUT( - [ovn-sbctl dump-flows sw0 | tee sbflows2 | grep 'priority=120.*backends' | sed 's/table=..//'], [0], --[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) -+[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) - ]) - - AS_BOX([Create the Load_Balancer_Health_Check again.]) -@@ -1248,7 +1255,7 @@ check ovn-nbctl --wait=sb sync - - ovn-sbctl dump-flows sw0 | grep backends | grep priority=120 > lflows.txt - AT_CHECK([cat lflows.txt | sed 's/table=..//'], [0], [dnl -- (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) -+ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) - ]) - - AS_BOX([Get the uuid of both the service_monitor]) -@@ -1258,7 +1265,7 @@ sm_sw1_p1=$(fetch_column Service_Monitor _uuid logical_port=sw1-p1) - AT_CAPTURE_FILE([sbflows3]) - OVS_WAIT_FOR_OUTPUT( - [ovn-sbctl dump-flows sw0 | tee sbflows 3 | grep 'priority=120.*backends' | sed 's/table=..//'], [0], --[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) -+[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) - ]) - - AS_BOX([Set the service monitor for sw1-p1 to offline]) -@@ -1269,7 +1276,7 @@ check ovn-nbctl --wait=sb sync - AT_CAPTURE_FILE([sbflows4]) - OVS_WAIT_FOR_OUTPUT( - [ovn-sbctl dump-flows sw0 | tee sbflows4 | grep 'priority=120.*backends' | sed 's/table=..//'], [0], --[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80);) -+[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80);) - ]) - - AS_BOX([Set the service monitor for sw0-p1 to offline]) -@@ -1298,7 +1305,7 @@ check ovn-nbctl --wait=sb sync - AT_CAPTURE_FILE([sbflows7]) - OVS_WAIT_FOR_OUTPUT( - [ovn-sbctl dump-flows sw0 | tee sbflows7 | grep backends | grep priority=120 | sed 's/table=..//'], 0, --[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) -+[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) - ]) - - AS_BOX([Set the service monitor for sw1-p1 to error]) -@@ -1309,7 +1316,7 @@ check ovn-nbctl --wait=sb sync - ovn-sbctl dump-flows sw0 | grep "ip4.dst == 10.0.0.10 && tcp.dst == 80" \ - | grep priority=120 > lflows.txt - AT_CHECK([cat lflows.txt | sed 's/table=..//'], [0], [dnl -- (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80);) -+ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80);) - ]) - - AS_BOX([Add one more vip to lb1]) -@@ -1335,8 +1342,8 @@ AT_CAPTURE_FILE([sbflows9]) - OVS_WAIT_FOR_OUTPUT( - [ovn-sbctl dump-flows sw0 | tee sbflows9 | grep backends | grep priority=120 | sed 's/table=..//' | sort], - 0, --[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80);) -- (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg0[[1]] = 0; reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb_mark(backends=10.0.0.3:1000);) -+[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80);) -+ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg0[[1]] = 0; reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb(backends=10.0.0.3:1000);) - ]) - - AS_BOX([Set the service monitor for sw1-p1 to online]) -@@ -1349,8 +1356,8 @@ AT_CAPTURE_FILE([sbflows10]) - OVS_WAIT_FOR_OUTPUT( - [ovn-sbctl dump-flows sw0 | tee sbflows10 | grep backends | grep priority=120 | sed 's/table=..//' | sort], - 0, --[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) -- (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg0[[1]] = 0; reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb_mark(backends=10.0.0.3:1000,20.0.0.3:80);) -+[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) -+ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg0[[1]] = 0; reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb(backends=10.0.0.3:1000,20.0.0.3:80);) - ]) - - AS_BOX([Associate lb1 to sw1]) -@@ -1359,8 +1366,8 @@ AT_CAPTURE_FILE([sbflows11]) - OVS_WAIT_FOR_OUTPUT( - [ovn-sbctl dump-flows sw1 | tee sbflows11 | grep backends | grep priority=120 | sed 's/table=..//' | sort], - 0, [dnl -- (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) -- (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg0[[1]] = 0; reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb_mark(backends=10.0.0.3:1000,20.0.0.3:80);) -+ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) -+ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg0[[1]] = 0; reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb(backends=10.0.0.3:1000,20.0.0.3:80);) - ]) - - AS_BOX([Now create lb2 same as lb1 but udp protocol.]) -@@ -6734,6 +6741,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..fd064b999 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 -@@ -14660,6 +14665,14 @@ reset_env() { - for port in hv1/migrator hv2/migrator hv1/first hv2/second hv3/third; do - : > $port.expected - done -+ -+ for hv in hv1 hv2 hv3; do -+ : > $hv/n1.expected -+ done -+ -+ reset_pcap_file hv1 br-phys_n1 hv1/br-phys_n1 -+ reset_pcap_file hv2 br-phys_n1 hv2/br-phys_n1 -+ reset_pcap_file hv3 br-phys_n1 hv3/br-phys_n1 - } - - check_packets() { -@@ -14670,6 +14683,10 @@ check_packets() { - OVN_CHECK_PACKETS_CONTAIN([hv1/first-tx.pcap], [hv1/first.expected]) - OVN_CHECK_PACKETS_CONTAIN([hv2/second-tx.pcap], [hv2/second.expected]) - OVN_CHECK_PACKETS_CONTAIN([hv3/third-tx.pcap], [hv3/third.expected]) -+ -+ OVN_CHECK_PACKETS_CONTAIN([hv1/br-phys_n1-tx.pcap], [hv1/n1.expected]) -+ OVN_CHECK_PACKETS_CONTAIN([hv2/br-phys_n1-tx.pcap], [hv2/n1.expected]) -+ OVN_CHECK_PACKETS_CONTAIN([hv3/br-phys_n1-tx.pcap], [hv3/n1.expected]) - } - - migrator_tpa=$(ip_to_hex 10 0 0 100) -@@ -14694,10 +14711,10 @@ wait_column "" Port_Binding requested_additional_chassis logical_port=migrator - wait_for_ports_up - - # advertise location of ports through localnet port --send_garp hv1 migrator 0000000000ff ffffffffffff $migrator_spa $migrator_tpa --send_garp hv1 first 000000000001 ffffffffffff $first_spa $first_tpa --send_garp hv2 second 000000000002 ffffffffffff $second_spa $second_tpa --send_garp hv3 third 000000000003 ffffffffffff $third_spa $third_tpa -+send_garp hv1 migrator 0000000000ff ffffffffffff $migrator_tpa $migrator_tpa -+send_garp hv1 first 000000000001 ffffffffffff $first_spa $first_spa -+send_garp hv2 second 000000000002 ffffffffffff $second_spa $second_spa -+send_garp hv3 third 000000000003 ffffffffffff $third_spa $third_spa - reset_env - - # check that... -@@ -14717,6 +14734,7 @@ echo $request >> hv3/third.expected - # unicast from Second doesn't arrive to hv2:Migrator - request=$(send_arp hv2 second 000000000002 0000000000ff $second_spa $migrator_tpa) - echo $request >> hv1/migrator.expected -+echo $request >> hv2/n1.expected - - # mcast from Second arrives to hv1:Migrator - # mcast from Second doesn't arrive to hv2:Migrator -@@ -14724,11 +14742,13 @@ request=$(send_arp hv2 second 000000000002 ffffffffffff $second_spa $migrator_tp - echo $request >> hv1/migrator.expected - echo $request >> hv1/first.expected - echo $request >> hv3/third.expected -+echo $request >> hv2/n1.expected - - # unicast from Third arrives to hv1:Migrator - # unicast from Third doesn't arrive to hv2:Migrator - request=$(send_arp hv3 third 000000000003 0000000000ff $third_spa $migrator_tpa) - echo $request >> hv1/migrator.expected -+echo $request >> hv3/n1.expected - - # mcast from Third arrives to hv1:Migrator - # mcast from Third doesn't arrive to hv2:Migrator -@@ -14736,14 +14756,17 @@ request=$(send_arp hv3 third 000000000003 ffffffffffff $third_spa $migrator_tpa) - echo $request >> hv1/migrator.expected - echo $request >> hv1/first.expected - echo $request >> hv2/second.expected -+echo $request >> hv3/n1.expected - - # unicast from hv1:Migrator arrives to First, Second, and Third - request=$(send_arp hv1 migrator 0000000000ff 000000000001 $migrator_tpa $first_spa) - echo $request >> hv1/first.expected - request=$(send_arp hv1 migrator 0000000000ff 000000000002 $migrator_tpa $second_spa) - echo $request >> hv2/second.expected -+echo $request >> hv1/n1.expected - request=$(send_arp hv1 migrator 0000000000ff 000000000003 $migrator_tpa $third_spa) - echo $request >> hv3/third.expected -+echo $request >> hv1/n1.expected - - # unicast from hv2:Migrator doesn't arrive to First, Second, or Third - request=$(send_arp hv2 migrator 0000000000ff 000000000001 $migrator_tpa $first_spa) -@@ -14755,6 +14778,7 @@ request=$(send_arp hv1 migrator 0000000000ff ffffffffffff $migrator_tpa $first_s - echo $request >> hv1/first.expected - echo $request >> hv2/second.expected - echo $request >> hv3/third.expected -+echo $request >> hv1/n1.expected - - # mcast from hv2:Migrator doesn't arrive to First, Second, or Third - request=$(send_arp hv2 migrator 0000000000ff ffffffffffff $migrator_tpa $first_spa) -@@ -14841,8 +14865,18 @@ echo $request >> hv1/first.expected - echo $request >> hv2/second.expected - echo $request >> hv3/third.expected - -+# unicast from Second arrives to Third through localnet port -+request=$(send_arp hv2 second 000000000002 000000000003 $second_spa $third_spa) -+echo $request >> hv2/n1.expected -+ - check_packets - -+# Wait for MAC address of migrator to be on hv1 related port in main switch. -+# Hence the MAC will not migrate back unexpectedly later. -+p1=$(as main ovs-ofctl show n1 | grep hv1_br-phys | awk '{print int($1)}') -+p2=$(as main ovs-ofctl show n1 | grep hv2_br-phys | awk '{print int($1)}') -+OVS_WAIT_UNTIL([test x`as main ovs-appctl fdb/show n1 | grep 00:00:00:00:00:ff | awk '{print $1}'` = x$p1]) -+ - # Complete migration: destination is bound - check ovn-nbctl lsp-set-options migrator requested-chassis=hv2 - wait_column "$hv2_uuid" Port_Binding chassis logical_port=migrator -@@ -14852,17 +14886,22 @@ wait_column "" Port_Binding requested_additional_chassis logical_port=migrator - wait_for_ports_up - - check ovn-nbctl --wait=hv sync --sleep 1 -+OVS_WAIT_UNTIL([test `as hv2 ovs-vsctl get Interface migrator external_ids:ovn-installed` = '"true"']) - - # advertise new location of the port through localnet port --send_garp hv2 migrator 0000000000ff ffffffffffff $migrator_spa $migrator_tpa -+send_garp hv2 migrator 0000000000ff ffffffffffff $migrator_tpa $migrator_tpa -+ - reset_env - -+# Wait for MAC address of migrator to be on hv2 port in main switch -+OVS_WAIT_UNTIL([test x`as main ovs-appctl fdb/show n1 | grep 00:00:00:00:00:ff | awk '{print $1}'` = x$p2]) -+ - # check that... - # unicast from Third doesn't arrive to hv1:Migrator - # unicast from Third arrives to hv2:Migrator - request=$(send_arp hv3 third 000000000003 0000000000ff $third_spa $migrator_tpa) - echo $request >> hv2/migrator.expected -+echo $request >> hv3/n1.expected - - # mcast from Third doesn't arrive to hv1:Migrator - # mcast from Third arrives to hv2:Migrator -@@ -14870,11 +14909,13 @@ request=$(send_arp hv3 third 000000000003 ffffffffffff $third_spa $migrator_tpa) - echo $request >> hv2/migrator.expected - echo $request >> hv1/first.expected - echo $request >> hv2/second.expected -+echo $request >> hv3/n1.expected - - # unicast from First doesn't arrive to hv1:Migrator - # unicast from First arrives to hv2:Migrator - request=$(send_arp hv1 first 000000000001 0000000000ff $first_spa $migrator_tpa) - echo $request >> hv2/migrator.expected -+echo $request >> hv1/n1.expected - - # mcast from First doesn't arrive to hv1:Migrator - # mcast from First arrives to hv2:Migrator binding -@@ -14882,6 +14923,7 @@ request=$(send_arp hv1 first 000000000001 ffffffffffff $first_spa $migrator_tpa) - echo $request >> hv2/migrator.expected - echo $request >> hv2/second.expected - echo $request >> hv3/third.expected -+echo $request >> hv1/n1.expected - - # unicast from Second doesn't arrive to hv1:Migrator - # unicast from Second arrives to hv2:Migrator -@@ -14903,10 +14945,12 @@ request=$(send_arp hv1 migrator 0000000000ff 000000000003 $migrator_tpa $third_s - # unicast from hv2:Migrator arrives to First, Second, and Third - request=$(send_arp hv2 migrator 0000000000ff 000000000001 $migrator_tpa $first_spa) - echo $request >> hv1/first.expected -+echo $request >> hv2/n1.expected - request=$(send_arp hv2 migrator 0000000000ff 000000000002 $migrator_tpa $second_spa) - echo $request >> hv2/second.expected - request=$(send_arp hv2 migrator 0000000000ff 000000000003 $migrator_tpa $third_spa) - echo $request >> hv3/third.expected -+echo $request >> hv2/n1.expected - - # mcast from hv1:Migrator doesn't arrive to First, Second, or Third - request=$(send_arp hv1 migrator 0000000000ff ffffffffffff $migrator_tpa $first_spa) -@@ -14916,14 +14960,400 @@ request=$(send_arp hv2 migrator 0000000000ff ffffffffffff $migrator_tpa $first_s - echo $request >> hv1/first.expected - echo $request >> hv2/second.expected - echo $request >> hv3/third.expected -+echo $request >> hv2/n1.expected -+ -+check_packets -+ -+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..1cabf1f31 100644 ---- a/tests/system-ovn.at -+++ b/tests/system-ovn.at -@@ -4441,7 +4441,7 @@ tcp,orig=(src=10.0.0.4,dst=10.0.0.10,sport=,dport=),reply=(src - tcp,orig=(src=10.0.0.4,dst=10.0.0.10,sport=,dport=),reply=(src=20.0.0.3,dst=10.0.0.4,sport=,dport=),zone=,mark=2,protoinfo=(state=) - ]) - --# Stop webserer in sw0-p1 -+# Stop webserver in sw0-p1 - kill `cat $sw0_p1_pid_file` - - # Wait until service_monitor for sw0-p1 is set to offline -@@ -4465,6 +4465,15 @@ sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl - tcp,orig=(src=10.0.0.4,dst=10.0.0.10,sport=,dport=),reply=(src=20.0.0.3,dst=10.0.0.4,sport=,dport=),zone=,mark=2,protoinfo=(state=) - ]) - -+# trigger port binding release and check if status changed to offline -+ovs-vsctl remove interface ovs-sw1-p1 external_ids iface-id -+wait_row_count Service_Monitor 2 -+wait_row_count Service_Monitor 2 status=offline -+ -+ovs-vsctl set interface ovs-sw1-p1 external_ids:iface-id=sw1-p1 -+wait_row_count Service_Monitor 2 -+wait_row_count Service_Monitor 1 status=online -+ - # Create udp load balancer. - ovn-nbctl lb-add lb2 10.0.0.10:80 10.0.0.3:80,20.0.0.3:80 udp - lb_udp=`ovn-nbctl lb-list | grep udp | awk '{print $1}'` -@@ -6741,6 +6750,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/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c -index 6a8ba6330..2918db1c6 100644 ---- a/utilities/ovn-nbctl.c -+++ b/utilities/ovn-nbctl.c -@@ -5345,7 +5345,7 @@ nbctl_lrp_set_gateway_chassis(struct ctl_context *ctx) - } - - const char *chassis_name = ctx->argv[2]; -- if (ctx->argv[3]) { -+ if (ctx->argc == 4) { - error = parse_priority(ctx->argv[3], &priority); - if (error) { - ctx->error = 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 a47f189..0000000 --- a/SPECS/ovn22.06.spec +++ /dev/null @@ -1,631 +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: 24%{?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 -* Tue Jul 19 2022 wangchuanlei - 22.06.0-24 -- pinctrl: fix ovn-controller abort when service start. -[Gerrit: 593b3c25e1ab88db3e13fe93c8a265e7efea3863] -[Upstream: f61bb7a5e7b0387233a4237902065bc84b0be82f] - -* Tue Jul 19 2022 Lorenzo Bianconi - 22.06.0-23 -- lflow: fix possible use-after-free in add_lb_vip_hairpin_reply_action -[Gerrit: 6bcb3b7931c3e705c9d2ff0235accc0575cfbc7b] -[Upstream: 25cb8878699a2b74825bdea4c77b9d713b91cb80] - -* Tue Jul 19 2022 Lorenzo Bianconi - 22.06.0-22 -- ovn-ic: do not learn routes with link-local next-hops (#2100355) -[Gerrit: 55d2f0c805ef912aab5483fed384e2b749fbe413] -[Upstream: cb0e2b3f44daeafb2f02f07289e3c410ee6ead28] - -* Tue Jul 12 2022 Xavier Simonart - 22.06.0-21 -- tests: fixed flaky test localnet connectivity with multiple requested-chassis -[Gerrit: 592ba5643c5e250e0f2fd0232d475cee1a3e2014] -[Upstream: 592ba5643c5e250e0f2fd0232d475cee1a3e2014] - -* Mon Jul 11 2022 Dumitru Ceara - 22.06.0-20 -- ovn-nb: Properly document multicast flood config defaults. -[Gerrit: 503e7333efc193fd8457f981e32d48ec27c417df] -[Upstream: 503e7333efc193fd8457f981e32d48ec27c417df] - -* Mon Jul 11 2022 Ales Musil - 22.06.0-19 -- ovn-nbctl: Fix priority arg of lrp-set-gateway-chassis (#2102930) -[Gerrit: bc46ab4dbdd866307ce4851fc68170764625f397] -[Upstream: 2721412c4ea30497938f89ed9364e07ce70d15e0] - -* Mon Jul 11 2022 Ihar Hrachyshka - 22.06.0-18 -- Always funnel multichassis port traffic through tunnels -[Gerrit: 894bcac4922928eb5701bdeb0fd8319973fd3ba6] -[Upstream: 7084cf437421aedac019a4151d0b6ce9208e695a] - -* Thu Jul 07 2022 Vladislav Odintsov - 22.06.0-17 -- northd: set svc_mon status to offline if port_binding released (#2103740) -[Gerrit: 8cc90ac02fff34d640c551230c712f9184d35e2a] -[Upstream: 23e203a3f30bd57ef8d0def7ee2698e588782d0c] - -* 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] +