From patchwork Mon Aug 2 20:48:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Numan Siddique X-Patchwork-Id: 1512565 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GdqqZ2Vjtz9s1l for ; Tue, 3 Aug 2021 06:49:14 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id E3DE040623; Mon, 2 Aug 2021 20:49:11 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id vYTJFS9pWWYy; Mon, 2 Aug 2021 20:49:10 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id DA43540603; Mon, 2 Aug 2021 20:49:09 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id B13D6C001A; Mon, 2 Aug 2021 20:49:09 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 4CBD1C001A for ; Mon, 2 Aug 2021 20:49:08 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 6815D40611 for ; Mon, 2 Aug 2021 20:49:05 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Qwt0J5MmLh2R for ; Mon, 2 Aug 2021 20:49:04 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by smtp4.osuosl.org (Postfix) with ESMTPS id 1629540603 for ; Mon, 2 Aug 2021 20:49:03 +0000 (UTC) Received: (Authenticated sender: numans@ovn.org) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 03D8B1BF203; Mon, 2 Aug 2021 20:48:59 +0000 (UTC) From: numans@ovn.org To: dev@openvswitch.org Date: Mon, 2 Aug 2021 16:48:57 -0400 Message-Id: <20210802204857.2547919-1-numans@ovn.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210802204816.2547744-1-numans@ovn.org> References: <20210802204816.2547744-1-numans@ovn.org> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn v4 2/5] binding: Add the localport port binding in the binding_lport information. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Numan Siddique If there is an OVS interface present with the external_ids:iface-id set to a localport port binding, we create a 'struct local_binding' for this OVS interface but we do not associate the binding_lport to this local_binding. This patch now associates the binding_lport now. Future patch will make use of this information in handling the runtime data changes in the pflow engine node. Acked-by: Han Zhou Reviewed-by: Mark Michelson Signed-off-by: Numan Siddique --- controller/binding.c | 164 +++++++++++++++++++++++++++++++++------- tests/ovn-controller.at | 35 ++++++++- 2 files changed, 170 insertions(+), 29 deletions(-) diff --git a/controller/binding.c b/controller/binding.c index 96dc906f9..f9b4a626d 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -590,6 +590,11 @@ static struct binding_lport *local_binding_add_lport( enum en_lport_type); static struct binding_lport *local_binding_get_primary_lport( struct local_binding *); +static struct binding_lport *local_binding_get_first_lport( + struct local_binding *lbinding); +static struct binding_lport *local_binding_get_primary_or_localport_lport( + struct local_binding *lbinding); + static bool local_binding_handle_stale_binding_lports( struct local_binding *lbinding, struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out, struct hmap *qos_map); @@ -780,12 +785,15 @@ binding_dump_local_bindings(struct local_binding_data *lbinding_data, if (num_lports) { struct shash child_lports = SHASH_INITIALIZER(&child_lports); struct binding_lport *primary_lport = NULL; + struct binding_lport *localport_lport = NULL; struct binding_lport *b_lport; bool first_elem = true; LIST_FOR_EACH (b_lport, list_node, &lbinding->binding_lports) { if (first_elem && b_lport->type == LP_VIF) { primary_lport = b_lport; + } else if (first_elem && b_lport->type == LP_LOCALPORT) { + localport_lport = b_lport; } else { shash_add(&child_lports, b_lport->name, b_lport); } @@ -795,6 +803,9 @@ binding_dump_local_bindings(struct local_binding_data *lbinding_data, if (primary_lport) { ds_put_format(out_data, "primary lport : [%s]\n", primary_lport->name); + } else if (localport_lport) { + ds_put_format(out_data, "localport lport : [%s]\n", + localport_lport->name); } else { ds_put_format(out_data, "no primary lport\n"); } @@ -984,8 +995,7 @@ claim_lport(const struct sbrec_port_binding *pb, * Caller should make sure that this is the case. */ static bool -release_lport(const struct sbrec_port_binding *pb, bool sb_readonly, - struct hmap *tracked_datapaths, struct if_status_mgr *if_mgr) +release_lport_(const struct sbrec_port_binding *pb, bool sb_readonly) { if (pb->encap) { if (sb_readonly) { @@ -1008,9 +1018,20 @@ release_lport(const struct sbrec_port_binding *pb, bool sb_readonly, sbrec_port_binding_set_virtual_parent(pb, NULL); } + VLOG_INFO("Releasing lport %s from this chassis.", pb->logical_port); + return true; +} + +static bool +release_lport(const struct sbrec_port_binding *pb, bool sb_readonly, + struct hmap *tracked_datapaths, struct if_status_mgr *if_mgr) +{ + if (!release_lport_(pb, sb_readonly)) { + return false; + } + update_lport_tracking(pb, tracked_datapaths, false); if_status_mgr_release_iface(if_mgr, pb->logical_port); - VLOG_INFO("Releasing lport %s from this chassis.", pb->logical_port); return true; } @@ -1296,6 +1317,36 @@ consider_virtual_lport(const struct sbrec_port_binding *pb, return true; } +static bool +consider_localport(const struct sbrec_port_binding *pb, + struct binding_ctx_in *b_ctx_in, + struct binding_ctx_out *b_ctx_out) +{ + struct shash *local_bindings = &b_ctx_out->lbinding_data->bindings; + struct local_binding *lbinding = local_binding_find(local_bindings, + pb->logical_port); + + if (!lbinding) { + return true; + } + + local_binding_add_lport(&b_ctx_out->lbinding_data->lports, lbinding, pb, + LP_LOCALPORT); + + /* If the port binding is claimed, then release it as localport is claimed + * by any ovn-controller. */ + if (pb->chassis == b_ctx_in->chassis_rec) { + if (!release_lport_(pb, !b_ctx_in->ovnsb_idl_txn)) { + return false; + } + + remove_related_lport(pb, b_ctx_out); + } + + update_related_lport(pb, b_ctx_out); + return true; +} + /* Considers either claiming the lport or releasing the lport * for non VIF lports. */ @@ -1522,11 +1573,14 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) switch (lport_type) { case LP_PATCH: - case LP_LOCALPORT: case LP_VTEP: update_related_lport(pb, b_ctx_out); break; + case LP_LOCALPORT: + consider_localport(pb, b_ctx_in, b_ctx_out); + break; + case LP_VIF: consider_vif_lport(pb, b_ctx_in, b_ctx_out, NULL, qos_map_ptr); break; @@ -1705,7 +1759,6 @@ consider_iface_claim(const struct ovsrec_interface *iface_rec, smap_replace(b_ctx_out->local_iface_ids, iface_rec->name, iface_id); struct shash *local_bindings = &b_ctx_out->lbinding_data->bindings; - struct shash *binding_lports = &b_ctx_out->lbinding_data->lports; struct local_binding *lbinding = local_binding_find(local_bindings, iface_id); @@ -1716,27 +1769,34 @@ consider_iface_claim(const struct ovsrec_interface *iface_rec, lbinding->iface = iface_rec; } - struct binding_lport *b_lport = local_binding_get_primary_lport(lbinding); + struct binding_lport *b_lport = + local_binding_get_primary_or_localport_lport(lbinding); const struct sbrec_port_binding *pb = NULL; if (!b_lport) { pb = lport_lookup_by_name(b_ctx_in->sbrec_port_binding_by_name, lbinding->name); - if (pb && get_lport_type(pb) == LP_VIF) { - b_lport = local_binding_add_lport(binding_lports, lbinding, pb, - LP_VIF); - } + } else { + pb = b_lport->pb; } - if (!b_lport) { - /* There is no binding lport for this local binding. */ + if (!pb) { + /* There is no port_binding row for this local binding. */ return true; } - if (!consider_vif_lport(b_lport->pb, b_ctx_in, b_ctx_out, - lbinding, qos_map)) { + enum en_lport_type lport_type = get_lport_type(pb); + if (lport_type == LP_LOCALPORT) { + return consider_localport(pb, b_ctx_in, b_ctx_out); + } + + if (lport_type == LP_VIF && + !consider_vif_lport(pb, b_ctx_in, b_ctx_out, lbinding, qos_map)) { return false; } + /* Get the (updated) b_lport again for the lbinding. */ + b_lport = local_binding_get_primary_lport(lbinding); + /* Update the child local_binding's iface (if any children) and try to * claim the container lbindings. */ LIST_FOR_EACH (b_lport, list_node, &lbinding->binding_lports) { @@ -1776,7 +1836,8 @@ consider_iface_release(const struct ovsrec_interface *iface_rec, struct shash *binding_lports = &b_ctx_out->lbinding_data->lports; lbinding = local_binding_find(local_bindings, iface_id); - struct binding_lport *b_lport = local_binding_get_primary_lport(lbinding); + struct binding_lport *b_lport = + local_binding_get_primary_or_localport_lport(lbinding); if (is_binding_lport_this_chassis(b_lport, b_ctx_in->chassis_rec)) { struct local_datapath *ld = get_local_datapath(b_ctx_out->local_datapaths, @@ -1796,6 +1857,10 @@ consider_iface_release(const struct ovsrec_interface *iface_rec, } } + } else if (lbinding && b_lport && b_lport->type == LP_LOCALPORT) { + /* lbinding is associated with a localport. Remove it from the + * related lports. */ + remove_related_lport(b_lport->pb, b_ctx_out); } if (lbinding) { @@ -2131,6 +2196,8 @@ binding_handle_port_binding_changes(struct binding_ctx_in *b_ctx_in, SHASH_INITIALIZER(&deleted_virtual_pbs); struct shash deleted_vif_pbs = SHASH_INITIALIZER(&deleted_vif_pbs); + struct shash deleted_localport_pbs = + SHASH_INITIALIZER(&deleted_localport_pbs); struct shash deleted_other_pbs = SHASH_INITIALIZER(&deleted_other_pbs); const struct sbrec_port_binding *pb; @@ -2165,6 +2232,8 @@ binding_handle_port_binding_changes(struct binding_ctx_in *b_ctx_in, shash_add(&deleted_container_pbs, pb->logical_port, pb); } else if (lport_type == LP_VIRTUAL) { shash_add(&deleted_virtual_pbs, pb->logical_port, pb); + } else if (lport_type == LP_LOCALPORT) { + shash_add(&deleted_localport_pbs, pb->logical_port, pb); } else { shash_add(&deleted_other_pbs, pb->logical_port, pb); } @@ -2199,6 +2268,12 @@ binding_handle_port_binding_changes(struct binding_ctx_in *b_ctx_in, } } + SHASH_FOR_EACH_SAFE (node, node_next, &deleted_localport_pbs) { + handle_deleted_vif_lport(node->data, LP_LOCALPORT, b_ctx_in, + b_ctx_out); + shash_delete(&deleted_localport_pbs, node); + } + SHASH_FOR_EACH_SAFE (node, node_next, &deleted_other_pbs) { handle_deleted_lport(node->data, b_ctx_in, b_ctx_out); shash_delete(&deleted_other_pbs, node); @@ -2208,6 +2283,7 @@ delete_done: shash_destroy(&deleted_container_pbs); shash_destroy(&deleted_virtual_pbs); shash_destroy(&deleted_vif_pbs); + shash_destroy(&deleted_localport_pbs); shash_destroy(&deleted_other_pbs); if (!handled) { @@ -2267,8 +2343,11 @@ delete_done: b_ctx_out, qos_map_ptr); break; - case LP_PATCH: case LP_LOCALPORT: + handled = consider_localport(pb, b_ctx_in, b_ctx_out); + break; + + case LP_PATCH: case LP_VTEP: update_related_lport(pb, b_ctx_out); if (lport_type == LP_PATCH) { @@ -2427,6 +2506,24 @@ local_binding_delete(struct local_binding *lbinding, local_binding_destroy(lbinding, binding_lports); } +static struct binding_lport * +local_binding_get_first_lport(struct local_binding *lbinding) +{ + if (!lbinding) { + return NULL; + } + + if (!ovs_list_is_empty(&lbinding->binding_lports)) { + struct binding_lport *b_lport = NULL; + b_lport = CONTAINER_OF(ovs_list_front(&lbinding->binding_lports), + struct binding_lport, list_node); + + return b_lport; + } + + return NULL; +} + /* Returns the primary binding lport if present in lbinding's * binding lports list. A binding lport is considered primary * if binding lport's type is LP_VIF and the name matches @@ -2439,15 +2536,26 @@ local_binding_get_primary_lport(struct local_binding *lbinding) return NULL; } - if (!ovs_list_is_empty(&lbinding->binding_lports)) { - struct binding_lport *b_lport = NULL; - b_lport = CONTAINER_OF(ovs_list_front(&lbinding->binding_lports), - struct binding_lport, list_node); - - if (b_lport->type == LP_VIF && + struct binding_lport *b_lport = local_binding_get_first_lport(lbinding); + if (b_lport && b_lport->type == LP_VIF && !strcmp(lbinding->name, b_lport->name)) { - return b_lport; - } + return b_lport; + } + + return NULL; +} + +static struct binding_lport * +local_binding_get_primary_or_localport_lport(struct local_binding *lbinding) +{ + if (!lbinding) { + return NULL; + } + + struct binding_lport *b_lport = local_binding_get_first_lport(lbinding); + if (b_lport && (b_lport->type == LP_VIF || b_lport->type == LP_LOCALPORT) + && !strcmp(lbinding->name, b_lport->name)) { + return b_lport; } return NULL; @@ -2495,8 +2603,10 @@ local_binding_handle_stale_binding_lports(struct local_binding *lbinding, struct binding_ctx_out *b_ctx_out, struct hmap *qos_map) { - /* Check if this lbinding has a primary binding_lport or not. */ - struct binding_lport *p_lport = local_binding_get_primary_lport(lbinding); + /* Check if this lbinding has a primary binding_lport or + * localport binding_lport or not. */ + struct binding_lport *p_lport = + local_binding_get_primary_or_localport_lport(lbinding); if (p_lport) { /* Nothing to be done. */ return true; @@ -2663,6 +2773,7 @@ binding_lport_check_and_cleanup(struct binding_lport *b_lport, switch (b_lport->type) { case LP_VIF: + case LP_LOCALPORT: if (strcmp(b_lport->name, b_lport->lbinding->name)) { cleanup_blport = true; } @@ -2682,7 +2793,6 @@ binding_lport_check_and_cleanup(struct binding_lport *b_lport, break; case LP_PATCH: - case LP_LOCALPORT: case LP_VTEP: case LP_L2GATEWAY: case LP_L3GATEWAY: diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at index ef1fd7379..e8550a5dc 100644 --- a/tests/ovn-controller.at +++ b/tests/ovn-controller.at @@ -510,6 +510,18 @@ primary lport : [[lsp1]] ---------------------------------------- ]) +# Set the port type to localport +check ovn-nbctl lsp-set-type lsp1 localport +check as hv1 ovs-vsctl set open . external_ids:ovn-cms-options=localport +OVS_WAIT_UNTIL([test localport = $(ovn-sbctl get chassis . other_config:ovn-cms-options)]) + +AT_CHECK([as hv1 ovn-appctl -t ovn-controller debug/dump-local-bindings], [0], [dnl +Local bindings: +name: [[lsp1]], OVS interface name : [[vif1]], num binding lports : [[1]] +localport lport : [[lsp1]] +---------------------------------------- +]) + # pause ovn-northd check as northd ovn-appctl -t ovn-northd pause check as northd-backup ovn-appctl -t ovn-northd pause @@ -527,22 +539,41 @@ do check as hv1 ovs-vsctl set open . external_ids:ovn-cms-options=$type OVS_WAIT_UNTIL([test $type = $(ovn-sbctl get chassis . other_config:ovn-cms-options)]) - AT_CHECK([as hv1 ovn-appctl -t ovn-controller debug/dump-local-bindings], [0], [dnl + if [[ "$type" == "localport" ]]; then + AT_CHECK([as hv1 ovn-appctl -t ovn-controller debug/dump-local-bindings], [0], [dnl +Local bindings: +name: [[lsp1]], OVS interface name : [[vif1]], num binding lports : [[1]] +localport lport : [[lsp1]] +---------------------------------------- +]) + else + AT_CHECK([as hv1 ovn-appctl -t ovn-controller debug/dump-local-bindings], [0], [dnl Local bindings: name: [[lsp1]], OVS interface name : [[vif1]], num binding lports : [[0]] ---------------------------------------- ]) + fi echo "Updating to $update_type from $type" check ovn-sbctl set port_binding lsp1 type=$update_type check as hv1 ovs-vsctl set open . external_ids:ovn-cms-options=$update_type OVS_WAIT_UNTIL([test $update_type = $(ovn-sbctl get chassis . other_config:ovn-cms-options)]) - AT_CHECK([as hv1 ovn-appctl -t ovn-controller debug/dump-local-bindings], [0], [dnl + if [[ "$update_type" == "localport" ]]; then + AT_CHECK([as hv1 ovn-appctl -t ovn-controller debug/dump-local-bindings], [0], [dnl +Local bindings: +name: [[lsp1]], OVS interface name : [[vif1]], num binding lports : [[1]] +localport lport : [[lsp1]] +---------------------------------------- +]) + else + AT_CHECK([as hv1 ovn-appctl -t ovn-controller debug/dump-local-bindings], [0], [dnl Local bindings: name: [[lsp1]], OVS interface name : [[vif1]], num binding lports : [[0]] ---------------------------------------- ]) + fi + # Set the port binding type back to VIF. check ovn-sbctl set port_binding lsp1 type=\"\" check as hv1 ovs-vsctl set open . external_ids:ovn-cms-options=foo