diff --git a/.gitignore b/.gitignore index ea11613..00f1750 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ /ovn-21.03.0.tar.gz /openvswitch-2.15.90.tar.gz /ovn-21.06.0.tar.gz +/ovn-21.06.90.tar.gz +/openvswitch-2.16.0.tar.gz diff --git a/0001-fedora-Use-PROFILE-SYSTEM-in-SSL_CTX_set_cipher_list.patch b/0001-fedora-Use-PROFILE-SYSTEM-in-SSL_CTX_set_cipher_list.patch index 20f79a2..dc338a5 100644 --- a/0001-fedora-Use-PROFILE-SYSTEM-in-SSL_CTX_set_cipher_list.patch +++ b/0001-fedora-Use-PROFILE-SYSTEM-in-SSL_CTX_set_cipher_list.patch @@ -11,10 +11,10 @@ Signed-off-by: Numan Siddique lib/stream-ssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/openvswitch-2.15.90/lib/stream-ssl.c b/openvswitch-2.15.90/lib/stream-ssl.c +diff --git a/openvswitch-2.16.0/lib/stream-ssl.c b/openvswitch-2.16.0/lib/stream-ssl.c index fed71801b..78e54c39e 100644 ---- a/openvswitch-2.15.90/lib/stream-ssl.c -+++ b/openvswitch-2.15.90/lib/stream-ssl.c +--- a/openvswitch-2.16.0/lib/stream-ssl.c ++++ b/openvswitch-2.16.0/lib/stream-ssl.c @@ -1014,7 +1014,7 @@ do_ssl_init(void) SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); diff --git a/ovn-21.06.0.patch b/ovn-21.06.0.patch deleted file mode 100644 index df70d00..0000000 --- a/ovn-21.06.0.patch +++ /dev/null @@ -1,1402 +0,0 @@ -diff --git a/controller/binding.c b/controller/binding.c -index 7fde0fdbb..ba558efdb 100644 ---- a/controller/binding.c -+++ b/controller/binding.c -@@ -22,6 +22,7 @@ - #include "patch.h" - - #include "lib/bitmap.h" -+#include "lib/hmapx.h" - #include "openvswitch/poll-loop.h" - #include "lib/sset.h" - #include "lib/util.h" -@@ -108,6 +109,7 @@ add_local_datapath__(struct ovsdb_idl_index *sbrec_datapath_binding_by_key, - hmap_insert(local_datapaths, &ld->hmap_node, dp_key); - ld->datapath = datapath; - ld->localnet_port = NULL; -+ shash_init(&ld->external_ports); - ld->has_local_l3gateway = has_local_l3gateway; - - if (tracked_datapaths) { -@@ -474,6 +476,18 @@ is_network_plugged(const struct sbrec_port_binding *binding_rec, - return network ? !!shash_find_data(bridge_mappings, network) : false; - } - -+static void -+update_ld_external_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) { -+ shash_replace(&ld->external_ports, binding_rec->logical_port, -+ binding_rec); -+ } -+} -+ - static void - update_ld_localnet_port(const struct sbrec_port_binding *binding_rec, - struct shash *bridge_mappings, -@@ -531,38 +545,41 @@ remove_local_lports(const char *iface_id, struct binding_ctx_out *b_ctx) - } - } - --/* Add a port binding ID (of the form "dp-key"_"port-key") to the set of local -- * lport IDs. Also track if the set has changed. -+/* Add a port binding to the set of locally relevant lports. -+ * Also track if the set has changed. - */ - static void --update_local_lport_ids(const struct sbrec_port_binding *pb, -- struct binding_ctx_out *b_ctx) -+update_related_lport(const struct sbrec_port_binding *pb, -+ struct binding_ctx_out *b_ctx) - { - char buf[16]; - get_unique_lport_key(pb->datapath->tunnel_key, pb->tunnel_key, - buf, sizeof(buf)); -- if (sset_add(b_ctx->local_lport_ids, buf) != NULL) { -- b_ctx->local_lport_ids_changed = true; -+ if (sset_add(&b_ctx->related_lports->lport_ids, buf) != NULL) { -+ b_ctx->related_lports_changed = true; - - if (b_ctx->tracked_dp_bindings) { - /* Add the 'pb' to the tracked_datapaths. */ - tracked_binding_datapath_lport_add(pb, b_ctx->tracked_dp_bindings); - } - } -+ sset_add(&b_ctx->related_lports->lport_names, pb->logical_port); - } - --/* Remove a port binding id from the set of local lport IDs. Also track if -- * the set has changed. -+/* Remove a port binding id from the set of locally relevant lports. -+ * Also track if the set has changed. - */ - static void --remove_local_lport_ids(const struct sbrec_port_binding *pb, -- struct binding_ctx_out *b_ctx) -+remove_related_lport(const struct sbrec_port_binding *pb, -+ struct binding_ctx_out *b_ctx) - { - char buf[16]; - get_unique_lport_key(pb->datapath->tunnel_key, pb->tunnel_key, - buf, sizeof(buf)); -- if (sset_find_and_delete(b_ctx->local_lport_ids, buf)) { -- b_ctx->local_lport_ids_changed = true; -+ sset_find_and_delete(&b_ctx->related_lports->lport_names, -+ pb->logical_port); -+ if (sset_find_and_delete(&b_ctx->related_lports->lport_ids, buf)) { -+ b_ctx->related_lports_changed = true; - - if (b_ctx->tracked_dp_bindings) { - /* Add the 'pb' to the tracked_datapaths. */ -@@ -678,6 +695,20 @@ static struct binding_lport *binding_lport_check_and_cleanup( - - static char *get_lport_type_str(enum en_lport_type lport_type); - -+void -+related_lports_init(struct related_lports *rp) -+{ -+ sset_init(&rp->lport_names); -+ sset_init(&rp->lport_ids); -+} -+ -+void -+related_lports_destroy(struct related_lports *rp) -+{ -+ sset_destroy(&rp->lport_names); -+ sset_destroy(&rp->lport_ids); -+} -+ - void - local_binding_data_init(struct local_binding_data *lbinding_data) - { -@@ -1172,7 +1203,7 @@ release_binding_lport(const struct sbrec_chassis *chassis_rec, - struct binding_ctx_out *b_ctx_out) - { - if (is_binding_lport_this_chassis(b_lport, chassis_rec)) { -- remove_local_lport_ids(b_lport->pb, b_ctx_out); -+ remove_related_lport(b_lport->pb, b_ctx_out); - if (!release_lport(b_lport->pb, sb_readonly, - b_ctx_out->tracked_dp_bindings, - b_ctx_out->if_mgr)) { -@@ -1214,7 +1245,7 @@ consider_vif_lport_(const struct sbrec_port_binding *pb, - pb->datapath, false, - b_ctx_out->local_datapaths, - b_ctx_out->tracked_dp_bindings); -- update_local_lport_ids(pb, b_ctx_out); -+ update_related_lport(pb, b_ctx_out); - update_local_lports(pb->logical_port, b_ctx_out); - if (b_lport->lbinding->iface && qos_map && b_ctx_in->ovs_idl_txn) { - get_qos_params(pb, qos_map); -@@ -1405,7 +1436,7 @@ consider_virtual_lport(const struct sbrec_port_binding *pb, - * its entry from the local_lport_ids if present. This is required - * when a virtual port moves from one chassis to other.*/ - if (!virtual_b_lport) { -- remove_local_lport_ids(pb, b_ctx_out); -+ remove_related_lport(pb, b_ctx_out); - } - - return true; -@@ -1430,7 +1461,7 @@ consider_nonvif_lport_(const struct sbrec_port_binding *pb, - b_ctx_out->local_datapaths, - b_ctx_out->tracked_dp_bindings); - -- update_local_lport_ids(pb, b_ctx_out); -+ update_related_lport(pb, b_ctx_out); - return claim_lport(pb, NULL, b_ctx_in->chassis_rec, NULL, - !b_ctx_in->ovnsb_idl_txn, false, - b_ctx_out->tracked_dp_bindings, -@@ -1482,7 +1513,7 @@ consider_localnet_lport(const struct sbrec_port_binding *pb, - get_qos_params(pb, qos_map); - } - -- update_local_lport_ids(pb, b_ctx_out); -+ update_related_lport(pb, b_ctx_out); - } - - static bool -@@ -1512,7 +1543,7 @@ consider_ha_lport(const struct sbrec_port_binding *pb, - pb->datapath, false, - b_ctx_out->local_datapaths, - b_ctx_out->tracked_dp_bindings); -- update_local_lport_ids(pb, b_ctx_out); -+ update_related_lport(pb, b_ctx_out); - } - - return consider_nonvif_lport_(pb, our_chassis, false, b_ctx_in, b_ctx_out); -@@ -1614,8 +1645,9 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) - !sset_is_empty(b_ctx_out->egress_ifaces) ? &qos_map : NULL; - - struct ovs_list localnet_lports = OVS_LIST_INITIALIZER(&localnet_lports); -+ struct ovs_list external_lports = OVS_LIST_INITIALIZER(&external_lports); - -- struct localnet_lport { -+ struct lport { - struct ovs_list list_node; - const struct sbrec_port_binding *pb; - }; -@@ -1634,7 +1666,7 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) - case LP_PATCH: - case LP_LOCALPORT: - case LP_VTEP: -- update_local_lport_ids(pb, b_ctx_out); -+ update_related_lport(pb, b_ctx_out); - break; - - case LP_VIF: -@@ -1663,11 +1695,14 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) - - case LP_EXTERNAL: - consider_external_lport(pb, b_ctx_in, b_ctx_out); -+ struct lport *ext_lport = xmalloc(sizeof *ext_lport); -+ ext_lport->pb = pb; -+ ovs_list_push_back(&external_lports, &ext_lport->list_node); - break; - - case LP_LOCALNET: { - consider_localnet_lport(pb, b_ctx_in, b_ctx_out, &qos_map); -- struct localnet_lport *lnet_lport = xmalloc(sizeof *lnet_lport); -+ struct lport *lnet_lport = xmalloc(sizeof *lnet_lport); - lnet_lport->pb = pb; - ovs_list_push_back(&localnet_lports, &lnet_lport->list_node); - break; -@@ -1694,7 +1729,7 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) - /* Run through each localnet lport list to see if it is a localnet port - * on local datapaths discovered from above loop, and update the - * corresponding local datapath accordingly. */ -- struct localnet_lport *lnet_lport; -+ struct lport *lnet_lport; - LIST_FOR_EACH_POP (lnet_lport, list_node, &localnet_lports) { - update_ld_localnet_port(lnet_lport->pb, &bridge_mappings, - b_ctx_out->egress_ifaces, -@@ -1702,6 +1737,15 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) - free(lnet_lport); - } - -+ /* Run through external lport list to see if these are external ports -+ * on local datapaths discovered from above loop, and update the -+ * corresponding local datapath accordingly. */ -+ struct lport *ext_lport; -+ LIST_FOR_EACH_POP (ext_lport, list_node, &external_lports) { -+ update_ld_external_ports(ext_lport->pb, b_ctx_out->local_datapaths); -+ free(ext_lport); -+ } -+ - shash_destroy(&bridge_mappings); - - if (!sset_is_empty(b_ctx_out->egress_ifaces) -@@ -1895,7 +1939,7 @@ remove_pb_from_local_datapath(const struct sbrec_port_binding *pb, - struct binding_ctx_out *b_ctx_out, - struct local_datapath *ld) - { -- remove_local_lport_ids(pb, b_ctx_out); -+ remove_related_lport(pb, b_ctx_out); - if (!strcmp(pb->type, "patch") || - !strcmp(pb->type, "l3gateway")) { - remove_local_datapath_peer_port(pb, ld, b_ctx_out->local_datapaths); -@@ -1904,6 +1948,8 @@ remove_pb_from_local_datapath(const struct sbrec_port_binding *pb, - pb->logical_port)) { - ld->localnet_port = NULL; - } -+ } else if (!strcmp(pb->type, "external")) { -+ shash_find_and_delete(&ld->external_ports, pb->logical_port); - } - - if (!strcmp(pb->type, "l3gateway")) { -@@ -2407,6 +2453,9 @@ binding_handle_port_binding_changes(struct binding_ctx_in *b_ctx_in, - shash_add(&deleted_virtual_pbs, pb->logical_port, pb); - } else { - shash_add(&deleted_other_pbs, pb->logical_port, pb); -+ if (lport_type == LP_EXTERNAL) { -+ hmapx_add(b_ctx_out->extport_updated_datapaths, pb->datapath); -+ } - } - } - -@@ -2502,7 +2551,7 @@ delete_done: - case LP_PATCH: - case LP_LOCALPORT: - case LP_VTEP: -- update_local_lport_ids(pb, b_ctx_out); -+ update_related_lport(pb, b_ctx_out); - if (lport_type == LP_PATCH) { - if (!ld) { - /* If 'ld' for this lport is not present, then check if -@@ -2561,6 +2610,8 @@ delete_done: - - case LP_EXTERNAL: - handled = consider_external_lport(pb, b_ctx_in, b_ctx_out); -+ update_ld_external_ports(pb, b_ctx_out->local_datapaths); -+ hmapx_add(b_ctx_out->extport_updated_datapaths, pb->datapath); - break; - - case LP_LOCALNET: { -@@ -2926,23 +2977,3 @@ cleanup: - - return b_lport; - } -- --struct sset * --binding_collect_local_binding_lports(struct local_binding_data *lbinding_data) --{ -- struct sset *lports = xzalloc(sizeof *lports); -- sset_init(lports); -- struct shash_node *shash_node; -- SHASH_FOR_EACH (shash_node, &lbinding_data->lports) { -- struct binding_lport *b_lport = shash_node->data; -- sset_add(lports, b_lport->name); -- } -- return lports; --} -- --void --binding_destroy_local_binding_lports(struct sset *lports) --{ -- sset_destroy(lports); -- free(lports); --} -diff --git a/controller/binding.h b/controller/binding.h -index 8f3289476..8fd54092e 100644 ---- a/controller/binding.h -+++ b/controller/binding.h -@@ -22,6 +22,7 @@ - #include "openvswitch/hmap.h" - #include "openvswitch/uuid.h" - #include "openvswitch/list.h" -+#include "sset.h" - - struct hmap; - struct ovsdb_idl; -@@ -56,6 +57,19 @@ struct binding_ctx_in { - const struct ovsrec_interface_table *iface_table; - }; - -+/* Locally relevant port bindings, e.g., VIFs that might be bound locally, -+ * patch ports. -+ */ -+struct related_lports { -+ struct sset lport_names; /* Set of port names. */ -+ struct sset lport_ids; /* Set of _ -+ * IDs for fast lookup. -+ */ -+}; -+ -+void related_lports_init(struct related_lports *); -+void related_lports_destroy(struct related_lports *); -+ - struct binding_ctx_out { - struct hmap *local_datapaths; - struct local_binding_data *lbinding_data; -@@ -65,11 +79,9 @@ struct binding_ctx_out { - /* Track if local_lports have been updated. */ - bool local_lports_changed; - -- /* sset of local lport ids in the format -- * _. */ -- struct sset *local_lport_ids; -- /* Track if local_lport_ids has been updated. */ -- bool local_lport_ids_changed; -+ /* Port bindings that are relevant to the local chassis. */ -+ struct related_lports *related_lports; -+ bool related_lports_changed; - - /* Track if non-vif port bindings (e.g., patch, external) have been - * added/deleted. -@@ -88,6 +100,8 @@ struct binding_ctx_out { - struct hmap *tracked_dp_bindings; - - struct if_status_mgr *if_mgr; -+ -+ struct hmapx *extport_updated_datapaths; - }; - - struct local_binding_data { -@@ -133,13 +147,4 @@ bool binding_handle_port_binding_changes(struct binding_ctx_in *, - void binding_tracked_dp_destroy(struct hmap *tracked_datapaths); - - void binding_dump_local_bindings(struct local_binding_data *, struct ds *); -- --/* Generates a sset of lport names from local_binding_data. -- * Note: the caller is responsible for destroying and freeing the returned -- * sset, by calling binding_detroy_local_binding_lports(). */ --struct sset *binding_collect_local_binding_lports(struct local_binding_data *); -- --/* Destroy and free the lports sset returned by -- * binding_collect_local_binding_lports(). */ --void binding_destroy_local_binding_lports(struct sset *lports); - #endif /* controller/binding.h */ -diff --git a/controller/lflow.c b/controller/lflow.c -index 680b8cca1..4270d0a33 100644 ---- a/controller/lflow.c -+++ b/controller/lflow.c -@@ -611,7 +611,7 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, - get_unique_lport_key(dp_id, port_id, buf, sizeof(buf)); - lflow_resource_add(l_ctx_out->lfrr, REF_TYPE_PORTBINDING, buf, - &lflow->header_.uuid); -- if (!sset_contains(l_ctx_in->local_lport_ids, buf)) { -+ if (!sset_contains(l_ctx_in->related_lport_ids, buf)) { - VLOG_DBG("lflow "UUID_FMT - " port %s in match is not local, skip", - UUID_ARGS(&lflow->header_.uuid), -diff --git a/controller/lflow.h b/controller/lflow.h -index 3c929d8a6..076b05beb 100644 ---- a/controller/lflow.h -+++ b/controller/lflow.h -@@ -143,7 +143,7 @@ struct lflow_ctx_in { - const struct shash *addr_sets; - const struct shash *port_groups; - const struct sset *active_tunnels; -- const struct sset *local_lport_ids; -+ const struct sset *related_lport_ids; - }; - - struct lflow_ctx_out { -diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c -index 07c6fcfd1..f9f83d37b 100644 ---- a/controller/ovn-controller.c -+++ b/controller/ovn-controller.c -@@ -970,9 +970,10 @@ struct ed_type_runtime_data { - * local hypervisor, and localnet ports. */ - struct sset local_lports; - -- /* Contains the same ports as local_lports, but in the format: -- * _ */ -- struct sset local_lport_ids; -+ /* Port bindings that are relevant to the local chassis (VIFs bound -+ * localy, patch ports). -+ */ -+ struct related_lports related_lports; - struct sset active_tunnels; - - /* runtime data engine private data. */ -@@ -986,6 +987,9 @@ struct ed_type_runtime_data { - - /* CT zone data. Contains datapaths that had updated CT zones */ - struct hmapx ct_updated_datapaths; -+ -+ /* Contains datapaths that had updated external ports. */ -+ struct hmapx extport_updated_datapaths; - }; - - /* struct ed_type_runtime_data has the below members for tracking the -@@ -1068,7 +1072,7 @@ en_runtime_data_init(struct engine_node *node OVS_UNUSED, - - hmap_init(&data->local_datapaths); - sset_init(&data->local_lports); -- sset_init(&data->local_lport_ids); -+ related_lports_init(&data->related_lports); - sset_init(&data->active_tunnels); - sset_init(&data->egress_ifaces); - smap_init(&data->local_iface_ids); -@@ -1078,6 +1082,7 @@ en_runtime_data_init(struct engine_node *node OVS_UNUSED, - hmap_init(&data->tracked_dp_bindings); - - hmapx_init(&data->ct_updated_datapaths); -+ hmapx_init(&data->extport_updated_datapaths); - - return data; - } -@@ -1088,7 +1093,7 @@ en_runtime_data_cleanup(void *data) - struct ed_type_runtime_data *rt_data = data; - - sset_destroy(&rt_data->local_lports); -- sset_destroy(&rt_data->local_lport_ids); -+ related_lports_destroy(&rt_data->related_lports); - sset_destroy(&rt_data->active_tunnels); - sset_destroy(&rt_data->egress_ifaces); - smap_destroy(&rt_data->local_iface_ids); -@@ -1096,12 +1101,14 @@ en_runtime_data_cleanup(void *data) - HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, - &rt_data->local_datapaths) { - free(cur_node->peer_ports); -+ shash_destroy(&cur_node->external_ports); - hmap_remove(&rt_data->local_datapaths, &cur_node->hmap_node); - free(cur_node); - } - hmap_destroy(&rt_data->local_datapaths); - local_binding_data_destroy(&rt_data->lbinding_data); - hmapx_destroy(&rt_data->ct_updated_datapaths); -+ hmapx_destroy(&rt_data->extport_updated_datapaths); - } - - static void -@@ -1181,14 +1188,15 @@ init_binding_ctx(struct engine_node *node, - b_ctx_out->local_datapaths = &rt_data->local_datapaths; - b_ctx_out->local_lports = &rt_data->local_lports; - b_ctx_out->local_lports_changed = false; -- b_ctx_out->local_lport_ids = &rt_data->local_lport_ids; -- b_ctx_out->local_lport_ids_changed = false; -+ b_ctx_out->related_lports = &rt_data->related_lports; -+ b_ctx_out->related_lports_changed = false; - b_ctx_out->non_vif_ports_changed = false; - b_ctx_out->egress_ifaces = &rt_data->egress_ifaces; - b_ctx_out->lbinding_data = &rt_data->lbinding_data; - b_ctx_out->local_iface_ids = &rt_data->local_iface_ids; - b_ctx_out->tracked_dp_bindings = NULL; - b_ctx_out->if_mgr = ctrl_ctx->if_mgr; -+ b_ctx_out->extport_updated_datapaths = &rt_data->extport_updated_datapaths; - } - - static void -@@ -1197,7 +1205,6 @@ en_runtime_data_run(struct engine_node *node, void *data) - struct ed_type_runtime_data *rt_data = data; - struct hmap *local_datapaths = &rt_data->local_datapaths; - struct sset *local_lports = &rt_data->local_lports; -- struct sset *local_lport_ids = &rt_data->local_lport_ids; - struct sset *active_tunnels = &rt_data->active_tunnels; - - static bool first_run = true; -@@ -1208,23 +1215,25 @@ en_runtime_data_run(struct engine_node *node, void *data) - struct local_datapath *cur_node, *next_node; - HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, local_datapaths) { - free(cur_node->peer_ports); -+ shash_destroy(&cur_node->external_ports); - hmap_remove(local_datapaths, &cur_node->hmap_node); - free(cur_node); - } - hmap_clear(local_datapaths); - local_binding_data_destroy(&rt_data->lbinding_data); - sset_destroy(local_lports); -- sset_destroy(local_lport_ids); -+ related_lports_destroy(&rt_data->related_lports); - sset_destroy(active_tunnels); - sset_destroy(&rt_data->egress_ifaces); - smap_destroy(&rt_data->local_iface_ids); - sset_init(local_lports); -- sset_init(local_lport_ids); -+ related_lports_init(&rt_data->related_lports); - sset_init(active_tunnels); - sset_init(&rt_data->egress_ifaces); - smap_init(&rt_data->local_iface_ids); - local_binding_data_init(&rt_data->lbinding_data); - hmapx_clear(&rt_data->ct_updated_datapaths); -+ hmapx_clear(&rt_data->extport_updated_datapaths); - } - - struct binding_ctx_in b_ctx_in; -@@ -1289,7 +1298,7 @@ runtime_data_sb_port_binding_handler(struct engine_node *node, void *data) - return false; - } - -- if (b_ctx_out.local_lport_ids_changed || -+ if (b_ctx_out.related_lports_changed || - b_ctx_out.non_vif_ports_changed || - !hmap_is_empty(b_ctx_out.tracked_dp_bindings)) { - engine_set_node_state(node, EN_UPDATED); -@@ -1599,11 +1608,8 @@ en_port_groups_run(struct engine_node *node, void *data) - struct ed_type_runtime_data *rt_data = - engine_get_input_data("runtime_data", node); - -- struct sset *local_b_lports = binding_collect_local_binding_lports( -- &rt_data->lbinding_data); -- port_groups_init(pg_table, local_b_lports, &pg->port_group_ssets, -- &pg->port_groups_cs_local); -- binding_destroy_local_binding_lports(local_b_lports); -+ port_groups_init(pg_table, &rt_data->related_lports.lport_names, -+ &pg->port_group_ssets, &pg->port_groups_cs_local); - - engine_set_node_state(node, EN_UPDATED); - } -@@ -1620,12 +1626,9 @@ port_groups_sb_port_group_handler(struct engine_node *node, void *data) - struct ed_type_runtime_data *rt_data = - engine_get_input_data("runtime_data", node); - -- struct sset *local_b_lports = binding_collect_local_binding_lports( -- &rt_data->lbinding_data); -- port_groups_update(pg_table, local_b_lports, &pg->port_group_ssets, -- &pg->port_groups_cs_local, &pg->new, &pg->deleted, -- &pg->updated); -- binding_destroy_local_binding_lports(local_b_lports); -+ port_groups_update(pg_table, &rt_data->related_lports.lport_names, -+ &pg->port_group_ssets, &pg->port_groups_cs_local, -+ &pg->new, &pg->deleted, &pg->updated); - - if (!sset_is_empty(&pg->new) || !sset_is_empty(&pg->deleted) || - !sset_is_empty(&pg->updated)) { -@@ -1658,9 +1661,6 @@ port_groups_runtime_data_handler(struct engine_node *node, void *data) - goto out; - } - -- struct sset *local_b_lports = binding_collect_local_binding_lports( -- &rt_data->lbinding_data); -- - const struct sbrec_port_group *pg_sb; - SBREC_PORT_GROUP_TABLE_FOR_EACH (pg_sb, pg_table) { - struct sset *pg_lports = shash_find_data(&pg->port_group_ssets, -@@ -1687,13 +1687,12 @@ port_groups_runtime_data_handler(struct engine_node *node, void *data) - if (need_update) { - expr_const_sets_add_strings(&pg->port_groups_cs_local, pg_sb->name, - (const char *const *) pg_sb->ports, -- pg_sb->n_ports, local_b_lports); -+ pg_sb->n_ports, -+ &rt_data->related_lports.lport_names); - sset_add(&pg->updated, pg_sb->name); - } - } - -- binding_destroy_local_binding_lports(local_b_lports); -- - out: - if (!sset_is_empty(&pg->new) || !sset_is_empty(&pg->deleted) || - !sset_is_empty(&pg->updated)) { -@@ -1973,6 +1972,7 @@ static void init_physical_ctx(struct engine_node *node, - p_ctx->mff_ovn_geneve = ed_mff_ovn_geneve->mff_ovn_geneve; - p_ctx->local_bindings = &rt_data->lbinding_data.bindings; - p_ctx->ct_updated_datapaths = &rt_data->ct_updated_datapaths; -+ p_ctx->extport_updated_datapaths = &rt_data->extport_updated_datapaths; - } - - static void init_lflow_ctx(struct engine_node *node, -@@ -2077,7 +2077,7 @@ static void init_lflow_ctx(struct engine_node *node, - l_ctx_in->addr_sets = addr_sets; - l_ctx_in->port_groups = port_groups; - l_ctx_in->active_tunnels = &rt_data->active_tunnels; -- l_ctx_in->local_lport_ids = &rt_data->local_lport_ids; -+ l_ctx_in->related_lport_ids = &rt_data->related_lports.lport_ids; - - l_ctx_out->flow_table = &fo->flow_table; - l_ctx_out->group_table = &fo->group_table; -@@ -2424,6 +2424,7 @@ flow_output_physical_flow_changes_handler(struct engine_node *node, void *data) - /* This indicates that we need to recompute the physical flows. */ - physical_clear_unassoc_flows_with_db(&fo->flow_table); - physical_clear_dp_flows(&p_ctx, &rt_data->ct_updated_datapaths, -+ &rt_data->extport_updated_datapaths, - &fo->flow_table); - physical_run(&p_ctx, &fo->flow_table); - return true; -diff --git a/controller/ovn-controller.h b/controller/ovn-controller.h -index 5d9466880..2bf1fecbf 100644 ---- a/controller/ovn-controller.h -+++ b/controller/ovn-controller.h -@@ -67,6 +67,8 @@ struct local_datapath { - - size_t n_peer_ports; - size_t n_allocated_peer_ports; -+ -+ struct shash external_ports; - }; - - struct local_datapath *get_local_datapath(const struct hmap *, -diff --git a/controller/physical.c b/controller/physical.c -index 018e09540..cfd68f835 100644 ---- a/controller/physical.c -+++ b/controller/physical.c -@@ -1272,6 +1272,52 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, - ofctrl_add_flow(flow_table, OFTABLE_CHECK_LOOPBACK, 160, - binding->header_.uuid.parts[0], &match, - ofpacts_p, &binding->header_.uuid); -+ -+ /* localport traffic directed to external is *not* local */ -+ struct shash_node *node; -+ SHASH_FOR_EACH (node, &ld->external_ports) { -+ const struct sbrec_port_binding *pb = node->data; -+ -+ /* skip ports that are not claimed by this chassis */ -+ if (!pb->chassis) { -+ continue; -+ } -+ if (strcmp(pb->chassis->name, chassis->name)) { -+ continue; -+ } -+ -+ ofpbuf_clear(ofpacts_p); -+ for (int i = 0; i < MFF_N_LOG_REGS; i++) { -+ put_load(0, MFF_REG0 + i, 0, 32, ofpacts_p); -+ } -+ put_resubmit(OFTABLE_LOG_EGRESS_PIPELINE, ofpacts_p); -+ -+ /* allow traffic directed to external MAC address */ -+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); -+ for (int i = 0; i < pb->n_mac; i++) { -+ char *err_str; -+ struct eth_addr peer_mac; -+ if ((err_str = str_to_mac(pb->mac[i], &peer_mac))) { -+ VLOG_WARN_RL( -+ &rl, "Parsing MAC failed for external port: %s, " -+ "with error: %s", pb->logical_port, err_str); -+ free(err_str); -+ continue; -+ } -+ -+ match_init_catchall(&match); -+ match_set_metadata(&match, htonll(dp_key)); -+ match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, -+ port_key); -+ match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0, -+ MLF_LOCALPORT, MLF_LOCALPORT); -+ match_set_dl_dst(&match, peer_mac); -+ -+ ofctrl_add_flow(flow_table, OFTABLE_CHECK_LOOPBACK, 170, -+ binding->header_.uuid.parts[0], &match, -+ ofpacts_p, &binding->header_.uuid); -+ } -+ } - } - - } else if (!tun && !is_ha_remote) { -@@ -1957,18 +2003,24 @@ physical_clear_unassoc_flows_with_db(struct ovn_desired_flow_table *flow_table) - void - physical_clear_dp_flows(struct physical_ctx *p_ctx, - struct hmapx *ct_updated_datapaths, -+ struct hmapx *extport_updated_datapaths, - struct ovn_desired_flow_table *flow_table) - { - const struct sbrec_port_binding *binding; - SBREC_PORT_BINDING_TABLE_FOR_EACH (binding, p_ctx->port_binding_table) { -- if (!hmapx_find(ct_updated_datapaths, binding->datapath)) { -- continue; -+ if (hmapx_find(ct_updated_datapaths, binding->datapath)) { -+ const struct sbrec_port_binding *peer = -+ get_binding_peer(p_ctx->sbrec_port_binding_by_name, binding); -+ ofctrl_remove_flows(flow_table, &binding->header_.uuid); -+ if (peer) { -+ ofctrl_remove_flows(flow_table, &peer->header_.uuid); -+ } - } -- const struct sbrec_port_binding *peer = -- get_binding_peer(p_ctx->sbrec_port_binding_by_name, binding); -- ofctrl_remove_flows(flow_table, &binding->header_.uuid); -- if (peer) { -- ofctrl_remove_flows(flow_table, &peer->header_.uuid); -+ -+ if (hmapx_find(extport_updated_datapaths, binding->datapath)) { -+ if (!strcmp(binding->type, "localnet")) { -+ ofctrl_remove_flows(flow_table, &binding->header_.uuid); -+ } - } - } - } -diff --git a/controller/physical.h b/controller/physical.h -index 0bf13f268..f9cd883a7 100644 ---- a/controller/physical.h -+++ b/controller/physical.h -@@ -57,6 +57,7 @@ struct physical_ctx { - enum mf_field_id mff_ovn_geneve; - struct shash *local_bindings; - struct hmapx *ct_updated_datapaths; -+ struct hmapx *extport_updated_datapaths; - }; - - void physical_register_ovs_idl(struct ovsdb_idl *); -@@ -65,6 +66,7 @@ void physical_run(struct physical_ctx *, - void physical_clear_unassoc_flows_with_db(struct ovn_desired_flow_table *); - void physical_clear_dp_flows(struct physical_ctx *p_ctx, - struct hmapx *ct_updated_datapaths, -+ struct hmapx *extport_updated_datapaths, - struct ovn_desired_flow_table *flow_table); - void physical_handle_port_binding_changes(struct physical_ctx *, - struct ovn_desired_flow_table *); -diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml -index 407464602..21ae0ca60 100644 ---- a/northd/ovn-northd.8.xml -+++ b/northd/ovn-northd.8.xml -@@ -1072,8 +1072,10 @@ output; - localport ports) that are down (unless - ignore_lsp_down is configured as true in options - column of NB_Global table of the Northbound -- database), for logical ports of type virtual and for -- logical ports with 'unknown' address set. -+ database), for logical ports of type virtual, for -+ logical ports with 'unknown' address set and for logical ports of -+ a logical switch configured with -+ other_config:vlan-passthru=true. -

- - -diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c -index 3dae7bb1c..315ec7b2f 100644 ---- a/northd/ovn-northd.c -+++ b/northd/ovn-northd.c -@@ -7007,6 +7007,10 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op, - return; - } - -+ if (is_vlan_transparent(op->od)) { -+ return; -+ } -+ - for (size_t i = 0; i < op->n_lsp_addrs; i++) { - for (size_t j = 0; j < op->lsp_addrs[i].n_ipv4_addrs; j++) { - ds_clear(match); -@@ -7371,6 +7375,7 @@ build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, - - struct mcast_switch_info *mcast_sw_info = - &igmp_group->datapath->mcast_info.sw; -+ uint64_t table_size = mcast_sw_info->table_size; - - if (IN6_IS_ADDR_V4MAPPED(&igmp_group->address)) { - /* RFC 4541, section 2.1.2, item 2: Skip groups in the 224.0.0.X -@@ -7381,10 +7386,8 @@ build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, - if (ip_is_local_multicast(group_address)) { - return; - } -- - if (atomic_compare_exchange_strong( -- &mcast_sw_info->active_v4_flows, -- (uint64_t *) &mcast_sw_info->table_size, -+ &mcast_sw_info->active_v4_flows, &table_size, - mcast_sw_info->table_size)) { - return; - } -@@ -7399,8 +7402,7 @@ build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, - return; - } - if (atomic_compare_exchange_strong( -- &mcast_sw_info->active_v6_flows, -- (uint64_t *) &mcast_sw_info->table_size, -+ &mcast_sw_info->active_v6_flows, &table_size, - mcast_sw_info->table_size)) { - return; - } -@@ -11800,6 +11802,7 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, - ds_put_format(actions, - "clone { ct_clear; " - "inport = outport; outport = \"\"; " -+ "eth.dst <-> eth.src; " - "flags = 0; flags.loopback = 1; "); - for (int j = 0; j < MFF_N_LOG_REGS; j++) { - ds_put_format(actions, "reg%d = 0; ", j); -diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl -index 3afa80a3b..eef171091 100644 ---- a/northd/ovn_northd.dl -+++ b/northd/ovn_northd.dl -@@ -3309,7 +3309,8 @@ for (CheckLspIsUp[check_lsp_is_up]) { - ((lsp_is_up(lsp) or not check_lsp_is_up) - or lsp.__type == "router" or lsp.__type == "localport") and - lsp.__type != "external" and lsp.__type != "virtual" and -- not lsp.addresses.contains("unknown")) -+ not lsp.addresses.contains("unknown") and -+ not sw.is_vlan_transparent) - { - var __match = "arp.tpa == ${addr.addr} && arp.op == 1" in - { -@@ -3359,7 +3360,8 @@ for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam - .ea = ea, .addr = addr) - if lsp.is_enabled() and - (lsp_is_up(lsp) or lsp.__type == "router" or lsp.__type == "localport") and -- lsp.__type != "external" and lsp.__type != "virtual") -+ lsp.__type != "external" and lsp.__type != "virtual" and -+ not sw.is_vlan_transparent) - { - var __match = "nd_ns && ip6.dst == {${addr.addr}, ${addr.solicited_node()}} && nd.target == ${addr.addr}" in - var actions = "${if (lsp.__type == \"router\") \"nd_na_router\" else \"nd_na\"} { " -@@ -5649,7 +5651,7 @@ for (r in &Router(._uuid = lr_uuid, - } in - if (nat.nat.__type == "dnat" or nat.nat.__type == "dnat_and_snat") { - None = l3dgw_port in -- var __match = "ip && ip4.dst == ${nat.nat.external_ip}" in -+ var __match = "ip && ${ipX}.dst == ${nat.nat.external_ip}" in - (var ext_ip_match, var ext_flow) = lrouter_nat_add_ext_ip_match( - r, nat, __match, ipX, true, mask) in - { -@@ -5925,6 +5927,7 @@ for (r in &Router(._uuid = lr_uuid, - var actions = - "clone { ct_clear; " - "inport = outport; outport = \"\"; " -+ "eth.dst <-> eth.src; " - "flags = 0; flags.loopback = 1; " ++ - regs.join("") ++ - "${rEGBIT_EGRESS_LOOPBACK()} = 1; " -diff --git a/tests/ovn.at b/tests/ovn.at -index aa80a7c48..515bcf7c7 100644 ---- a/tests/ovn.at -+++ b/tests/ovn.at -@@ -3169,6 +3169,118 @@ OVN_CLEANUP([hv-1],[hv-2]) - AT_CLEANUP - ]) - -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([ovn -- VLAN transparency, passthru=true, ARP responder disabled]) -+ovn_start -+ -+net_add net -+check ovs-vsctl add-br br-phys -+ovn_attach net br-phys 192.168.0.1 -+ -+check ovn-nbctl ls-add ls -+check ovn-nbctl --wait=sb add Logical-Switch ls other_config vlan-passthru=true -+ -+for i in 1 2; do -+ check ovn-nbctl lsp-add ls lsp$i -+ check ovn-nbctl lsp-set-addresses lsp$i "f0:00:00:00:00:0$i 10.0.0.$i" -+done -+ -+for i in 1 2; do -+ check ovs-vsctl add-port br-int vif$i -- set Interface vif$i external-ids:iface-id=lsp$i \ -+ options:tx_pcap=vif$i-tx.pcap \ -+ options:rxq_pcap=vif$i-rx.pcap \ -+ ofport-request=$i -+done -+ -+wait_for_ports_up -+ -+ovn-sbctl dump-flows ls > lsflows -+AT_CAPTURE_FILE([lsflows]) -+ -+AT_CHECK([grep -w "ls_in_arp_rsp" lsflows | sort], [0], [dnl -+ table=16(ls_in_arp_rsp ), priority=0 , match=(1), action=(next;) -+]) -+ -+test_arp() { -+ local inport=$1 outport=$2 sha=$3 spa=$4 tpa=$5 reply_ha=$6 -+ tag=8100fefe -+ local request=ffffffffffff${sha}${tag}08060001080006040001${sha}${spa}ffffffffffff${tpa} -+ ovs-appctl netdev-dummy/receive vif$inport $request -+ echo $request >> $outport.expected -+ -+ local reply=${sha}${reply_ha}${tag}08060001080006040002${reply_ha}${tpa}${sha}${spa} -+ ovs-appctl netdev-dummy/receive vif$outport $reply -+ echo $reply >> $inport.expected -+} -+ -+test_arp 1 2 f00000000001 0a000001 0a000002 f00000000002 -+test_arp 2 1 f00000000002 0a000002 0a000001 f00000000001 -+ -+for i in 1 2; do -+ OVN_CHECK_PACKETS([vif$i-tx.pcap], [$i.expected]) -+done -+ -+AT_CLEANUP -+]) -+ -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([ovn -- VLAN transparency, passthru=true, ND/NA responder disabled]) -+ovn_start -+ -+net_add net -+check ovs-vsctl add-br br-phys -+ovn_attach net br-phys 192.168.0.1 -+ -+check ovn-nbctl ls-add ls -+check ovn-nbctl --wait=sb add Logical-Switch ls other_config vlan-passthru=true -+ -+for i in 1 2; do -+ check ovn-nbctl lsp-add ls lsp$i -+ check ovn-nbctl lsp-set-addresses lsp$i "f0:00:00:00:00:0$i fe00::$i" -+done -+ -+for i in 1 2; do -+ check ovs-vsctl add-port br-int vif$i -- set Interface vif$i external-ids:iface-id=lsp$i \ -+ options:tx_pcap=vif$i-tx.pcap \ -+ options:rxq_pcap=vif$i-rx.pcap \ -+ ofport-request=$i -+done -+ -+wait_for_ports_up -+ -+ovn-sbctl dump-flows ls > lsflows -+AT_CAPTURE_FILE([lsflows]) -+ -+AT_CHECK([grep -w "ls_in_arp_rsp" lsflows | sort], [0], [dnl -+ table=16(ls_in_arp_rsp ), priority=0 , match=(1), action=(next;) -+]) -+ -+test_nd_na() { -+ local inport=$1 outport=$2 sha=$3 spa=$4 tpa=$5 reply_ha=$6 -+ tag=8100fefe -+ icmp_type=87 -+ local request=ffffffffffff${sha}${tag}86dd6000000000183aff${spa}ff0200000000000000000001ff${tpa: -6}${icmp_type}007ea100000000${tpa} -+ ovs-appctl netdev-dummy/receive vif$inport $request -+ echo $request >> $outport.expected -+ echo $request -+ -+ icmp_type=88 -+ local reply=${sha}${reply_ha}${tag}86dd6000000000183aff${tpa}${spa}${icmp_type}003da540000000${tpa} -+ ovs-appctl netdev-dummy/receive vif$outport $reply -+ echo $reply >> $inport.expected -+ echo $reply -+} -+ -+test_nd_na 1 2 f00000000001 fe000000000000000000000000000001 fe000000000000000000000000000002 f00000000002 -+test_nd_na 2 1 f00000000002 fe000000000000000000000000000002 fe000000000000000000000000000001 f00000000001 -+ -+for i in 1 2; do -+ OVN_CHECK_PACKETS([vif$i-tx.pcap], [$i.expected]) -+done -+ -+AT_CLEANUP -+]) -+ - OVN_FOR_EACH_NORTHD([ - AT_SETUP([ovn -- VLAN transparency, passthru=true, multiple hosts]) - ovn_start -@@ -11260,7 +11372,7 @@ ovn-nbctl lsp-add foo ln-foo - ovn-nbctl lsp-set-addresses ln-foo unknown - ovn-nbctl lsp-set-options ln-foo network_name=public - ovn-nbctl lsp-set-type ln-foo localnet --AT_CHECK([ovn-nbctl set Logical_Switch_Port ln-foo tag=2]) -+check ovn-nbctl set Logical_Switch_Port ln-foo tag_request=2 - - # Create localnet port in alice - ovn-nbctl lsp-add alice ln-alice -@@ -12024,6 +12136,91 @@ OVN_CLEANUP([hv1]) - AT_CLEANUP - ]) - -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([localport doesn't suppress ARP directed to external port]) -+ -+ovn_start -+net_add n1 -+ -+check ovs-vsctl add-br br-phys -+check ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys -+ovn_attach n1 br-phys 192.168.0.1 -+ -+check ovn-nbctl ls-add ls -+ -+# create topology to allow to talk from localport through localnet to external port -+check ovn-nbctl lsp-add ls lp -+check ovn-nbctl lsp-set-addresses lp "00:00:00:00:00:01 10.0.0.1" -+check ovn-nbctl lsp-set-type lp localport -+check ovs-vsctl add-port br-int lp -- set Interface lp external-ids:iface-id=lp -+ -+check ovn-nbctl --wait=sb ha-chassis-group-add hagrp -+check ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp main 10 -+check ovn-nbctl lsp-add ls lext -+check ovn-nbctl lsp-set-addresses lext "00:00:00:00:00:02 10.0.0.2" -+check ovn-nbctl lsp-set-type lext external -+hagrp_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group name=hagrp` -+check ovn-nbctl set logical_switch_port lext ha_chassis_group=$hagrp_uuid -+ -+check ovn-nbctl lsp-add ls ln -+check ovn-nbctl lsp-set-addresses ln unknown -+check ovn-nbctl lsp-set-type ln localnet -+check ovn-nbctl lsp-set-options ln network_name=phys -+check ovn-nbctl --wait=hv sync -+ -+# also create second external port AFTER localnet to check that order is irrelevant -+check ovn-nbctl lsp-add ls lext2 -+check ovn-nbctl lsp-set-addresses lext2 "00:00:00:00:00:10 10.0.0.10" -+check ovn-nbctl lsp-set-type lext2 external -+check ovn-nbctl set logical_switch_port lext2 ha_chassis_group=$hagrp_uuid -+check ovn-nbctl --wait=hv sync -+ -+# create and immediately delete an external port to later check that flows for -+# deleted ports are not left over in flow table -+check ovn-nbctl lsp-add ls lext-deleted -+check ovn-nbctl lsp-set-addresses lext-deleted "00:00:00:00:00:03 10.0.0.3" -+check ovn-nbctl lsp-set-type lext-deleted external -+check ovn-nbctl set logical_switch_port lext-deleted ha_chassis_group=$hagrp_uuid -+check ovn-nbctl --wait=hv sync -+check ovn-nbctl lsp-del lext-deleted -+check ovn-nbctl --wait=hv sync -+ -+send_garp() { -+ local inport=$1 eth_src=$2 eth_dst=$3 spa=$4 tpa=$5 -+ local request=${eth_dst}${eth_src}08060001080006040001${eth_src}${spa}${eth_dst}${tpa} -+ ovs-appctl netdev-dummy/receive $inport $request -+} -+ -+spa=$(ip_to_hex 10 0 0 1) -+tpa=$(ip_to_hex 10 0 0 2) -+send_garp lp 000000000001 000000000002 $spa $tpa -+ -+spa=$(ip_to_hex 10 0 0 1) -+tpa=$(ip_to_hex 10 0 0 10) -+send_garp lp 000000000001 000000000010 $spa $tpa -+ -+spa=$(ip_to_hex 10 0 0 1) -+tpa=$(ip_to_hex 10 0 0 3) -+send_garp lp 000000000001 000000000003 $spa $tpa -+ -+dnl external traffic from localport should be sent to localnet -+AT_CHECK([tcpdump -r main/br-phys_n1-tx.pcap arp[[24:4]]=0x0a000002 | wc -l],[0],[dnl -+1 -+],[ignore]) -+ -+#dnl ...regardless of localnet / external ports creation order -+AT_CHECK([tcpdump -r main/br-phys_n1-tx.pcap arp[[24:4]]=0x0a00000a | wc -l],[0],[dnl -+1 -+],[ignore]) -+ -+dnl traffic from localport should not be sent to deleted external port -+AT_CHECK([tcpdump -r main/br-phys_n1-tx.pcap arp[[24:4]]=0x0a000003 | wc -l],[0],[dnl -+0 -+],[ignore]) -+ -+AT_CLEANUP -+]) -+ - OVN_FOR_EACH_NORTHD([ - AT_SETUP([ovn -- 1 LR with HA distributed router gateway port]) - ovn_start -@@ -12668,7 +12865,7 @@ $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap | trim_zeros - AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], []) - - # change localnet port tag. --AT_CHECK([ovn-nbctl set Logical_Switch_Port ln_port tag=2014]) -+check ovn-nbctl set Logical_Switch_Port ln_port tag_request=2014 - - # wait for earlier changes to take effect - OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-ofctl dump-flows br-int table=65 | \ -@@ -17311,27 +17508,29 @@ logical_port=sw0-vir) = x]) - as hv1 - ovs-vsctl set interface hv1-vif3 external-ids:iface-id=sw0-vir - --AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding \ --logical_port=sw0-vir) = x], [0], []) -+wait_column "" Port_Binding chassis logical_port=sw0-vir - - # Cleanup hv1-vif3. - as hv1 - ovs-vsctl del-port hv1-vif3 - --AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding \ --logical_port=sw0-vir) = x], [0], []) -+wait_column "" Port_Binding chassis logical_port=sw0-vir - - check_virtual_offlows_present() { - hv=$1 - -- AT_CHECK([as $hv ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | grep "priority=2000"], [0], [dnl -- table=44, priority=2000,ip,metadata=0x1 actions=resubmit(,45) -- table=44, priority=2000,ipv6,metadata=0x1 actions=resubmit(,45) -+ sw0_dp_key=$(printf "%x" $(fetch_column Datapath_Binding tunnel_key external_ids:name=sw0)) -+ lr0_dp_key=$(printf "%x" $(fetch_column Datapath_Binding tunnel_key external_ids:name=lr0)) -+ lr0_public_dp_key=$(printf "%x" $(fetch_column Port_Binding tunnel_key logical_port=lr0-public)) -+ -+ AT_CHECK_UNQUOTED([as $hv ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | grep "priority=2000"], [0], [dnl -+ table=44, priority=2000,ip,metadata=0x$sw0_dp_key actions=resubmit(,45) -+ table=44, priority=2000,ipv6,metadata=0x$sw0_dp_key actions=resubmit(,45) - ]) - -- AT_CHECK([as $hv ovs-ofctl dump-flows br-int table=11 | ofctl_strip_all | \ -+ AT_CHECK_UNQUOTED([as $hv ovs-ofctl dump-flows br-int table=11 | ofctl_strip_all | \ - grep "priority=92" | grep 172.168.0.50], [0], [dnl -- table=11, priority=92,arp,reg14=0x3,metadata=0x3,arp_tpa=172.168.0.50,arp_op=1 actions=move:NXM_OF_ETH_SRC[[]]->NXM_OF_ETH_DST[[]],mod_dl_src:10:54:00:00:00:10,load:0x2->NXM_OF_ARP_OP[[]],move:NXM_NX_ARP_SHA[[]]->NXM_NX_ARP_THA[[]],load:0x105400000010->NXM_NX_ARP_SHA[[]],push:NXM_OF_ARP_SPA[[]],push:NXM_OF_ARP_TPA[[]],pop:NXM_OF_ARP_SPA[[]],pop:NXM_OF_ARP_TPA[[]],move:NXM_NX_REG14[[]]->NXM_NX_REG15[[]],load:0x1->NXM_NX_REG10[[0]],resubmit(,37) -+ table=11, priority=92,arp,reg14=0x$lr0_public_dp_key,metadata=0x$lr0_dp_key,arp_tpa=172.168.0.50,arp_op=1 actions=move:NXM_OF_ETH_SRC[[]]->NXM_OF_ETH_DST[[]],mod_dl_src:10:54:00:00:00:10,load:0x2->NXM_OF_ARP_OP[[]],move:NXM_NX_ARP_SHA[[]]->NXM_NX_ARP_THA[[]],load:0x105400000010->NXM_NX_ARP_SHA[[]],push:NXM_OF_ARP_SPA[[]],push:NXM_OF_ARP_TPA[[]],pop:NXM_OF_ARP_SPA[[]],pop:NXM_OF_ARP_TPA[[]],move:NXM_NX_REG14[[]]->NXM_NX_REG15[[]],load:0x1->NXM_NX_REG10[[0]],resubmit(,37) - ]) - } - -@@ -26688,6 +26887,50 @@ OVN_CLEANUP([hv1]) - AT_CLEANUP - ]) - -+# Tests that ACLs referencing port groups that include ports connected to -+# logical routers are correctly applied. -+OVN_FOR_EACH_NORTHD([ -+AT_SETUP([ovn -- ACL with Port Group including router ports]) -+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 ovn-nbctl \ -+ -- lr-add lr \ -+ -- ls-add ls \ -+ -- lrp-add lr lrp_ls 00:00:00:00:00:01 42.42.42.1/24 \ -+ -- lsp-add ls ls_lr \ -+ -- lsp-set-addresses ls_lr router \ -+ -- lsp-set-type ls_lr router \ -+ -- lsp-set-options ls_lr router-port=lr_ls \ -+ -- lsp-add ls vm1 -+ -+check ovn-nbctl pg-add pg ls_lr \ -+ -- acl-add pg from-lport 1 'inport == @pg && ip4.dst == 42.42.42.42' drop -+ -+check ovs-vsctl add-port br-int vm1 \ -+ -- set interface vm1 external_ids:iface-id=vm1 -+ -+wait_for_ports_up -+check ovn-nbctl --wait=hv sync -+ -+dp_key=$(fetch_column Datapath_Binding tunnel_key external_ids:name=ls) -+rtr_port_key=$(fetch_column Port_Binding tunnel_key logical_port=ls_lr) -+ -+# Check that ovn-controller adds a flow to drop packets with dest IP -+# 42.42.42.42 coming from the router port. -+AT_CHECK([ovs-ofctl dump-flows br-int table=17 | grep "reg14=0x${rtr_port_key},metadata=0x${dp_key},nw_dst=42.42.42.42 actions=drop" -c], [0], [dnl -+1 -+]) -+ -+OVN_CLEANUP([hv1]) -+AT_CLEANUP -+]) -+ - OVN_FOR_EACH_NORTHD([ - AT_SETUP([ovn -- Static route with discard nexthop]) - ovn_start -diff --git a/tests/system-ovn.at b/tests/system-ovn.at -index 310bd3d5a..1f9b90eb6 100644 ---- a/tests/system-ovn.at -+++ b/tests/system-ovn.at -@@ -1348,7 +1348,7 @@ as ovn-nb - OVS_APP_EXIT_AND_WAIT([ovsdb-server]) - - as northd --OVS_APP_EXIT_AND_WAIT([ovn-northd]) -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) - - as - OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -@@ -3121,7 +3121,7 @@ as ovn-nb - OVS_APP_EXIT_AND_WAIT([ovsdb-server]) - - as northd --OVS_APP_EXIT_AND_WAIT([ovn-northd]) -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) - - as - OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -@@ -4577,7 +4577,7 @@ as ovn-nb - OVS_APP_EXIT_AND_WAIT([ovsdb-server]) - - as northd --OVS_APP_EXIT_AND_WAIT([ovn-northd]) -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) - - as - OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -@@ -4663,7 +4663,7 @@ as ovn-nb - OVS_APP_EXIT_AND_WAIT([ovsdb-server]) - - as northd --OVS_APP_EXIT_AND_WAIT([ovn-northd]) -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) - - as - OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -@@ -4903,7 +4903,7 @@ as ovn-nb - OVS_APP_EXIT_AND_WAIT([ovsdb-server]) - - as northd --OVS_APP_EXIT_AND_WAIT([ovn-northd]) -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) - - as - OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -@@ -5287,7 +5287,7 @@ as ovn-nb - OVS_APP_EXIT_AND_WAIT([ovsdb-server]) - - as northd --OVS_APP_EXIT_AND_WAIT([ovn-northd]) -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) - - as - OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -@@ -5527,7 +5527,7 @@ as ovn-nb - OVS_APP_EXIT_AND_WAIT([ovsdb-server]) - - as northd --OVS_APP_EXIT_AND_WAIT([ovn-northd]) -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) - - as - OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -@@ -5689,7 +5689,7 @@ as ovn-nb - OVS_APP_EXIT_AND_WAIT([ovsdb-server]) - - as northd --OVS_APP_EXIT_AND_WAIT([ovn-northd]) -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) - - as - OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -@@ -5738,7 +5738,7 @@ as ovn-nb - OVS_APP_EXIT_AND_WAIT([ovsdb-server]) - - as northd --OVS_APP_EXIT_AND_WAIT([ovn-northd]) -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) - - as - OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d -@@ -5831,7 +5831,7 @@ as ovn-nb - OVS_APP_EXIT_AND_WAIT([ovsdb-server]) - - as northd --OVS_APP_EXIT_AND_WAIT([ovn-northd]) -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) - - as - OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d -@@ -5893,7 +5893,7 @@ as ovn-nb - OVS_APP_EXIT_AND_WAIT([ovsdb-server]) - - as northd --OVS_APP_EXIT_AND_WAIT([ovn-northd]) -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) - - as - OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d -@@ -6044,7 +6044,7 @@ as ovn-nb - OVS_APP_EXIT_AND_WAIT([ovsdb-server]) - - as northd --OVS_APP_EXIT_AND_WAIT([ovn-northd]) -+OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) - - as - OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d -@@ -6091,7 +6091,6 @@ check ovn-nbctl pg-add pg1 sw1-p1 - check ovn-nbctl acl-add pg1 from-lport 1002 "ip" allow-related - check ovn-nbctl acl-add pg1 to-lport 1002 "ip" allow-related - -- - OVN_POPULATE_ARP - ovn-nbctl --wait=hv sync - -@@ -6179,5 +6178,117 @@ 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(ovn -- DNAT LR hairpin IPv4) -+AT_KEYWORDS(hairpin) -+ -+ovn_start -+ -+OVS_TRAFFIC_VSWITCHD_START() -+ADD_BR([br-int]) -+ -+# Set external-ids in br-int needed for ovn-controller -+ovs-vsctl \ -+ -- set Open_vSwitch . external-ids:system-id=hv1 \ -+ -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ -+ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ -+ -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ -+ -- set bridge br-int fail-mode=secure other-config:disable-in-band=true -+ -+start_daemon ovn-controller -+ -+# Logical network: -+# Two VMs -+# * VM1 with IP address 192.168.100.5 -+# * VM2 with IP address 192.168.100.6 -+# The VMs connect to logical switch ls1. -+# -+# An external router with IP address 172.18.1.2. We simulate this with a network namespace. -+# There will be no traffic going here in this test. -+# The external router connects to logical switch ls-pub -+# -+# One logical router (lr1) connects to ls1 and ls-pub. The router port connected to ls-pub is -+# a gateway port. -+# * The subnet connected to ls1 is 192.168.100.0/24. The Router IP address is 192.168.100.1 -+# * The subnet connected to ls-pub is 172.18.1.0/24. The Router IP address is 172.168.1.1 -+# lr1 has the following attributes: -+# * It has a "default" static route that sends traffic out the gateway router port. -+# * It has a DNAT rule that translates 172.18.2.10 to 192.168.100.6 (VM2) -+# -+# In this test, we want to ensure that a ping from VM1 to IP address 172.18.2.10 reaches VM2. -+ -+ovn-nbctl ls-add ls1 -+ovn-nbctl lsp-add ls1 vm1 -- lsp-set-addresses vm1 "00:00:00:00:00:05 192.168.100.5" -+ovn-nbctl lsp-add ls1 vm2 -- lsp-set-addresses vm2 "00:00:00:00:00:06 192.168.100.6" -+ -+ovn-nbctl ls-add ls-pub -+ovn-nbctl lsp-add ls-pub ext-router -- lsp-set-addresses ext-router "00:00:00:00:01:02 172.18.1.2" -+ -+ovn-nbctl lr-add lr1 -+ovn-nbctl lrp-add lr1 lr1-ls1 00:00:00:00:00:01 192.168.100.1/24 -+ovn-nbctl lsp-add ls1 ls1-lr1 \ -+ -- lsp-set-type ls1-lr1 router \ -+ -- lsp-set-addresses ls1-lr1 00:00:00:00:00:01 \ -+ -- lsp-set-options ls1-lr1 router-port=lr1-ls1 -+ -+ovn-nbctl lrp-add lr1 lr1-ls-pub 00:00:00:00:01:01 172.18.1.1/24 -+ovn-nbctl lrp-set-gateway-chassis lr1-ls-pub hv1 -+ovn-nbctl lsp-add ls-pub ls-pub-lr1 \ -+ -- lsp-set-type ls-pub-lr1 router \ -+ -- lsp-set-addresses ls-pub-lr1 00:00:00:00:01:01 \ -+ -- lsp-set-options ls-pub-lr1 router-port=lr1-ls-pub -+ -+ovn-nbctl lr-nat-add lr1 snat 172.18.1.1 192.168.100.0/24 -+ovn-nbctl lr-nat-add lr1 dnat_and_snat 172.18.2.10 192.168.100.6 -+ovn-nbctl lr-route-add lr1 0.0.0.0/0 172.18.1.2 -+ -+#ls1_uuid=$(fetch_column Port_Binding datapath logical_port=vm1) -+#ovn-sbctl create MAC_Binding ip=172.18.2.10 datapath=$ls1_uuid logical_port=vm2 mac="00:00:00:00:00:06" -+ -+OVN_POPULATE_ARP -+ovn-nbctl --wait=hv sync -+ -+ADD_NAMESPACES(vm1) -+ADD_VETH(vm1, vm1, br-int, "192.168.100.5/24", "00:00:00:00:00:05", \ -+ "192.168.100.1") -+ -+ADD_NAMESPACES(vm2) -+ADD_VETH(vm2, vm2, br-int, "192.168.100.6/24", "00:00:00:00:00:06", \ -+ "192.168.100.1") -+ -+ADD_NAMESPACES(ext-router) -+ADD_VETH(ext-router, ext-router, br-int, "172.18.1.2/24", "00:00:00:00:01:02", \ -+ "172.18.1.1") -+ -+# Let's take a quick look at the logical flows -+ovn-sbctl lflow-list -+ -+# Let's check what ovn-trace says... -+ovn-trace ls1 'inport == "vm1" && eth.src == 00:00:00:00:00:05 && ip4.src == 192.168.100.5 && eth.dst == 00:00:00:00:00:01 && ip4.dst == 172.18.2.10 && ip.ttl == 32' -+ -+# 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 -+]) -+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 -+/.*terminating with signal 15.*/d"]) -+ - AT_CLEANUP - ]) diff --git a/ovn.spec b/ovn.spec index 8aac409..b974bd0 100644 --- a/ovn.spec +++ b/ovn.spec @@ -43,7 +43,7 @@ Name: ovn Summary: Open Virtual Network support URL: http://www.openvswitch.org/ Version: 21.06.0 -Release: 13%{?commit0:.%{date}git%{shortcommit0}}%{?dist} +Release: 14%{?commit0:.%{date}git%{shortcommit0}}%{?dist} Obsoletes: openvswitch-ovn-common < %{?epoch_ovs:%{epoch_ovs}:}2.11.0-8 Provides: openvswitch-ovn-common = %{?epoch:%{epoch}:}%{version}-%{release} @@ -66,13 +66,13 @@ Source: https://www.openvswitch.org/releases/ovn-%{version}.tar.gz # comes from openvswitch package. # The ovs commit used is 5601e86c4ec("Set release date for 2.14.0."). # The ovs tarball is generated manually by running - "make dist" in the ovs repository. -%define ovsver 2.15.90 +%define ovsver 2.16.0 %define ovsdir openvswitch-%{ovsver} Source10: https://openvswitch.org/releases/openvswitch-%{ovsver}.tar.gz # ovn-patches -Patch001: ovn-21.06.0.patch +#Patch001: # OpenvSwitch backports (400-) if required. # Address crpto policy for fedora @@ -440,6 +440,10 @@ fi %{_unitdir}/ovn-controller-vtep.service %changelog +* Thu Aug 19 2021 Numan Siddique - 21.06.0-14 +- Synced with OVN upstream commit cee67610a9220752ce2de236d615d864ad41ab1b +- Updated OVS sources to v2.16.0 tar file. + * Thu Jul 22 2021 Fedora Release Engineering - 21.06.0-13 - Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild diff --git a/sources b/sources index adeff4a..fc58214 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (ovn-21.06.0.tar.gz) = 2ac0197abfff832c167baffb6971c9897b04d85f440a6ad1e09fc4b78a1dda70ec6638a9396ffb0c8dd44ffe55242de868950cbcd1b6a850f172b424e043ec81 -SHA512 (openvswitch-2.15.90.tar.gz) = 4c28207ac0388b2fa83ebe48725bb8c74dcc6e55c569445179946e6040e45265455930bd4ea35a718db19581e194d56a1542af1a4e189af98f47bbfb57b7c5c7 +SHA512 (ovn-21.06.0.tar.gz) = d7e3cc5bdf443a6db7028c040f8481313ce6aa81062ef8a6eaa05e8b6a609aa0c780cb7fae758233afc9fb766d3bd20ca6d51848706a77f7325ca2d0193aef83 +SHA512 (openvswitch-2.16.0.tar.gz) = 70e348bded7773577ee2cde32b9b446f3aac2777b3c294319d417aa2346296bdaae548861eced3eb30d61d854dd028f0e32d7b798b7d2dc7ed75bf2018b7695e