[{"id":3680033,"web_url":"http://patchwork.ozlabs.org/comment/3680033/","msgid":"<CACDpfc57HOi8f2GF7bM=V0t8fCAu1hFaYyK9v1RrZRzozSM3OQ@mail.gmail.com>","list_archive_url":null,"date":"2026-04-21T19:32:16","subject":"Re: [ovs-dev] [Patch ovn v8] ovn-controller: Port up/ovn-installed\n reported too early.","submitter":{"id":88238,"url":"http://patchwork.ozlabs.org/api/people/88238/","name":"Jacob Tanenbaum","email":"jtanenba@redhat.com"},"content":"Recheck-request: github-robot-_Build_and_Test\n\nOn Tue, Apr 21, 2026 at 10:44 AM Jacob Tanenbaum <jtanenba@redhat.com>\nwrote:\n\n> When ovn-monitor-all is set to false ovn-controller sets ovn-installed\n> on OVS interfaces too early. ovn-controller needs to wait for the\n> response from the southbound database with the updates to the newly\n> monitored fields only then can it install flows and label the OVS\n> interface as installed.\n>\n> Reported-at: https://redhat.atlassian.net/browse/FDP-2887\n> Signed-off-by: Jacob Tanenbaum <jtanenba@redhat.com>\n>\n> ---\n> v7->v8\n> * removed printing in the system testcases that shouldn't be there and\n>   caused failure.\n>\n> v6->v7\n> * added an sset that holds the uuid's of datapaths that are waiting for\n>   sb updates\n> * added back the the state OIF_WAITING_SB_COND to the if_mgr state\n>   machine.\n> * no longer hold if the datapath is updated in the local_datapaths\n>   struct as that is generated each transaction and cannot be relied\n>   upon.\n> * removed some leftover logic from previous patch versions\n>\n> v5->v6\n> * simplified the logic as requested, Ales saw that we did not need to\n>   save the seqno if we checked before the engine run.\n> * removing the extra state from the state machine\n> * removing some leftover logic that was seen.\n>\n> v4->v5\n> * corrected a sanitizer error: used bool update_seqno without\n>   initializing\n>\n> v3->v4\n> * Added state OIF_WAITING_SB_COND to the state machine that manages\n>   the adding of interfaces. This state waits until the Southbound has\n>   updated the ovn-controller of relevent information about ports related\n>   to it\n> * Addressed several nits\n>\n> v2->v3\n> * adding the ld->monitor_updated required the additiona of checking for\n>   monitor_all in update_sb_monitors. I didn't account for being able to\n>   toggle on monitor_all\n>\n> v1->v2\n> * if_status_mgr_run() will run everytime the conditional seqno is\n>   changed so it should be safe to only skip when the expected_seqno and\n>   seqno returned from ovn are strictly not equal, that way we do not\n>   have to deal with overflow in the seqno. Additionally add a boolean to\n>   the local_datapath in the event that the seqno wraps around at the\n>   same time the datapath would go back into the state OIF_INSTALL_FLOWS.\n> * remove setting the state to itself for OIF_INSTALL_FLOWS in\n>   if_status_mgr_update()\n> * added assert(pb) in if_status_mgr_run()\n> * removed a manual loop looking for the local_datapath and replaced with\n>   get_local_datapath() in if_status_mgr_run\n> * remove a few nit spelling errors in the test case\n>\n> diff --git a/controller/if-status.c b/controller/if-status.c\n> index ee9337e63..34875d23e 100644\n> --- a/controller/if-status.c\n> +++ b/controller/if-status.c\n> @@ -18,6 +18,7 @@\n>  #include \"binding.h\"\n>  #include \"if-status.h\"\n>  #include \"lib/ofctrl-seqno.h\"\n> +#include \"local_data.h\"\n>  #include \"ovsport.h\"\n>  #include \"simap.h\"\n>\n> @@ -58,6 +59,11 @@ VLOG_DEFINE_THIS_MODULE(if_status);\n>  enum if_state {\n>      OIF_CLAIMED,          /* Newly claimed interface. pb->chassis update\n> not\n>                               yet initiated. */\n> +    OIF_WAITING_SB_COND,  /* Waiting for the Southbound database to update\n> +                           * ovn-controller for a given datapath. We\n> should\n> +                           * only be waiting in this state when\n> monitor_all\n> +                           * is false AND it is the first time that we see\n> +                           * a specific datapath. */\n>      OIF_INSTALL_FLOWS,    /* Claimed interface with pb->chassis update\n> sent to\n>                             * SB (but update notification not confirmed,\n> so the\n>                             * update may be resent in any of the following\n> @@ -87,6 +93,7 @@ enum if_state {\n>\n>  static const char *if_state_names[] = {\n>      [OIF_CLAIMED]          = \"CLAIMED\",\n> +    [OIF_WAITING_SB_COND]  = \"WAITING_SB_COND\",\n>      [OIF_INSTALL_FLOWS]    = \"INSTALL_FLOWS\",\n>      [OIF_REM_OLD_OVN_INST] = \"REM_OLD_OVN_INST\",\n>      [OIF_MARK_UP]          = \"MARK_UP\",\n> @@ -114,7 +121,18 @@ static const char *if_state_names[] = {\n>   * | |                 |  +--+\n>  | | |\n>   * | |                 |\n>  | | |\n>   * | |                 | mgr_update(when sb is rw i.e. pb->chassis)\n> | | |\n> - * | |                 |            has been updated\n>  | | |\n> + * | |                 V            has been updated\n>  | | |\n> + * | |   +----------------------+\n> | | |\n> + * | |   |                      |\n> | | |\n> + * | |   |    WAITING_SB_COND   |\n> | | |\n> + * | |   |                      |\n> | | |\n> + * | |   |                      |\n> | | |\n> + * | |   +----------------------+\n> | | |\n> + * | |                 |\n>  | | |\n> + * | |                 |\n>  | | |\n> + * | |                 |   mgr_update(when sb_cond_seqno == expected)\n> | | |\n> + * | |                 |   - request seqno\n>  | | |\n> + * | |                 |\n>  | | |\n>   * | | release_iface   | - request seqno\n>  | | |\n>   * | |                 |\n>  | | |\n>   * | |                 V\n>  | | |\n> @@ -335,6 +353,7 @@ if_status_mgr_claim_iface(struct if_status_mgr *mgr,\n>\n>      switch (iface->state) {\n>      case OIF_CLAIMED:\n> +    case OIF_WAITING_SB_COND:\n>      case OIF_INSTALL_FLOWS:\n>      case OIF_REM_OLD_OVN_INST:\n>      case OIF_MARK_UP:\n> @@ -383,6 +402,7 @@ if_status_mgr_release_iface(struct if_status_mgr *mgr,\n> const char *iface_id)\n>\n>      switch (iface->state) {\n>      case OIF_CLAIMED:\n> +    case OIF_WAITING_SB_COND:\n>      case OIF_INSTALL_FLOWS:\n>          /* Not yet fully installed interfaces:\n>           * pb->chassis still need to be deleted.\n> @@ -424,6 +444,7 @@ if_status_mgr_delete_iface(struct if_status_mgr *mgr,\n> const char *iface_id,\n>\n>      switch (iface->state) {\n>      case OIF_CLAIMED:\n> +    case OIF_WAITING_SB_COND:\n>      case OIF_INSTALL_FLOWS:\n>          /* Not yet fully installed interfaces:\n>           * pb->chassis still need to be deleted.\n> @@ -500,6 +521,8 @@ if_status_mgr_update(struct if_status_mgr *mgr,\n>                       const struct sbrec_chassis *chassis_rec,\n>                       const struct ovsrec_interface_table *iface_table,\n>                       const struct sbrec_port_binding_table *pb_table,\n> +                     const struct hmap *local_datapaths,\n> +                     const struct sset *waiting_sb_update,\n>                       bool ovs_readonly,\n>                       bool sb_readonly)\n>  {\n> @@ -622,9 +645,7 @@ if_status_mgr_update(struct if_status_mgr *mgr,\n>               * in if_status_handle_claims or if_status_mgr_claim_iface\n>               */\n>              if (iface->is_vif) {\n> -                ovs_iface_set_state(mgr, iface, OIF_INSTALL_FLOWS);\n> -                iface->install_seqno = mgr->iface_seqno + 1;\n> -                new_ifaces = true;\n> +                ovs_iface_set_state(mgr, iface, OIF_WAITING_SB_COND);\n>              } else {\n>                  ovs_iface_set_state(mgr, iface, OIF_MARK_UP);\n>              }\n> @@ -639,6 +660,32 @@ if_status_mgr_update(struct if_status_mgr *mgr,\n>          }\n>      }\n>\n> +    if (!sb_readonly) {\n> +        HMAPX_FOR_EACH_SAFE (node,\n> +                             &mgr->ifaces_per_state[OIF_WAITING_SB_COND])\n> {\n> +            struct ovs_iface *iface = node->data;\n> +            if (local_datapaths) {\n> +                const struct sbrec_port_binding *pb =\n> +                    sbrec_port_binding_table_get_for_uuid(pb_table,\n> +\n> &iface->pb_uuid);\n> +                ovs_assert(pb);\n> +                struct local_datapath *ld =\n> +                    get_local_datapath(local_datapaths,\n> +                                       pb->datapath->tunnel_key);\n> +                if (!ld) {\n> +                    continue;\n> +                }\n> +                char *uuid = uuid_to_string(&ld->datapath->header_.uuid);\n> +                if (!sset_contains(waiting_sb_update, uuid)) {\n> +                    ovs_iface_set_state(mgr, iface, OIF_INSTALL_FLOWS);\n> +                    iface->install_seqno = mgr->iface_seqno + 1;\n> +                    new_ifaces = true;\n> +                }\n> +                free(uuid);\n> +            }\n> +        }\n> +    }\n> +\n>      if (!sb_readonly) {\n>          HMAPX_FOR_EACH_SAFE (node,\n> &mgr->ifaces_per_state[OIF_UPDATE_PORT]) {\n>              struct ovs_iface *iface = node->data;\n> diff --git a/controller/if-status.h b/controller/if-status.h\n> index d15ca3008..67018d113 100644\n> --- a/controller/if-status.h\n> +++ b/controller/if-status.h\n> @@ -43,6 +43,8 @@ void if_status_mgr_update(struct if_status_mgr *, struct\n> local_binding_data *,\n>                            const struct sbrec_chassis *chassis,\n>                            const struct ovsrec_interface_table\n> *iface_table,\n>                            const struct sbrec_port_binding_table *pb_table,\n> +                          const struct hmap *local_datapaths,\n> +                          const struct sset *waiting_sb_update,\n>                            bool ovs_readonly,\n>                            bool sb_readonly);\n>  void if_status_mgr_run(struct if_status_mgr *mgr, struct\n> local_binding_data *,\n> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c\n> index da43051ed..a25892056 100644\n> --- a/controller/ovn-controller.c\n> +++ b/controller/ovn-controller.c\n> @@ -1511,6 +1511,7 @@ en_runtime_data_clear_tracked_data(void *data_)\n>  }\n>\n>  static void *\n> +\n>  en_runtime_data_init(struct engine_node *node OVS_UNUSED,\n>                       struct engine_arg *arg OVS_UNUSED)\n>  {\n> @@ -7596,6 +7597,8 @@ main(int argc, char *argv[])\n>      int ovs_txn_status = 1;\n>      bool sb_monitor_all = false;\n>      struct tracked_acl_ids *tracked_acl_ids = NULL;\n> +    struct sset waiting_sb_update;\n> +    sset_init(&waiting_sb_update);\n>      while (!exit_args.exiting) {\n>          ovsrcu_quiesce_end();\n>\n> @@ -7842,6 +7845,7 @@ main(int argc, char *argv[])\n>\n>                      bool recompute_allowed = (ovnsb_idl_txn &&\n>                                                !ofctrl_has_backlog());\n> +\n>                      engine_run(recompute_allowed);\n>                      tracked_acl_ids = engine_get_data(&en_acl_id);\n>\n> @@ -7951,6 +7955,9 @@ main(int argc, char *argv[])\n>\n> sbrec_mirror_table_get(ovnsb_idl_loop.idl),\n>                                     br_int,\n>                                     &runtime_data->lbinding_data.bindings);\n> +                        if (ovnsb_cond_seqno ==\n> ovnsb_expected_cond_seqno) {\n> +                            sset_clear(&waiting_sb_update);\n> +                        }\n>                          /* Updating monitor conditions if runtime data or\n>                           * logical datapath goups changed. */\n>                          if (engine_node_changed(&en_runtime_data)\n> @@ -7973,6 +7980,23 @@ main(int argc, char *argv[])\n>                                   * a continuous reason for monitor\n> updates. */\n>                                  daemon_started_recently_countdown();\n>                              }\n> +\n> +                            if (!sb_monitor_all && runtime_data) {\n> +                                struct hmap *tracked_dp_bindings =\n> +                                    &runtime_data->tracked_dp_bindings;\n> +                                struct tracked_datapath *tdp;\n> +                                HMAP_FOR_EACH_SAFE (tdp,\n> +                                                    node,\n> +                                                    tracked_dp_bindings) {\n> +                                    char *uuid =\n> +\n> uuid_to_string(&tdp->dp->header_.uuid);\n> +                                    if (tdp->tracked_type ==\n> +                                        TRACKED_RESOURCE_NEW) {\n> +                                        sset_add(&waiting_sb_update,\n> uuid);\n> +                                    }\n> +                                    free(uuid);\n> +                                }\n> +                            }\n>                          }\n>                          /* If there is no new expected seqno we have\n> finished\n>                           * loading all needed data from southbound. We\n> then\n> @@ -8017,6 +8041,10 @@ main(int argc, char *argv[])\n>                                                      ovs_idl_loop.idl),\n>                                           sbrec_port_binding_table_get(\n>                                                      ovnsb_idl_loop.idl),\n> +                                         runtime_data ?\n> +\n>  &runtime_data->local_datapaths\n> +                                               : NULL,\n> +                                         &waiting_sb_update,\n>                                           !ovs_idl_txn,\n>                                           !ovnsb_idl_txn);\n>                      stopwatch_stop(IF_STATUS_MGR_UPDATE_STOPWATCH_NAME,\n> diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at\n> index c98de9bc4..9dc7555ba 100644\n> --- a/tests/ovn-controller.at\n> +++ b/tests/ovn-controller.at\n> @@ -3944,3 +3944,69 @@ OVN_CLEANUP([hv1], [hv2\n>  /already has encap ip.*cannot duplicate on/d])\n>  AT_CLEANUP\n>  ])\n> +\n> +OVN_FOR_EACH_NORTHD([\n> +AT_SETUP([ovn-installed])\n> +ovn_start\n> +\n> +net_add n1\n> +sim_add hv1\n> +\n> +as hv1\n> +ovs-vsctl add-br br-phys\n> +ovn_attach n1 br-phys 192.168.0.1\n> +ovn-appctl vlog/set dbg\n> +ovs-vsctl add-port br-int vif1 -- \\\n> +    set Interface vif1 external-ids:iface-id=lsp1\n> +\n> +check ovn-nbctl ls-add ls1\n> +sleep_controller hv1\n> +check ovn-nbctl --wait=sb lsp-add ls1 lsp1 -- \\\n> +                          lsp-set-addresses lsp1 \"f0:00:00:00:00:01\n> 10.0.0.1\"\n> +\n> +sleep_sb\n> +wake_up_controller hv1\n> +\n> +# Wait for pflow for lsp1\n> +OVS_WAIT_UNTIL([\n> +    ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface\n> name=vif1)\n> +    echo \"vif1 port=$ofport\"\n> +    test -n \"$ofport\" && test 1 -le $(as hv1 ovs-ofctl dump-flows br-int\n> | grep -c in_port=$ofport)\n> +])\n> +\n> +# If ovn-installed in ovs, all flows should be installed.\n> +# In that case, there should be at least one flow with lsp1 address.\n> +OVS_WAIT_UNTIL([\n> +    ovn_installed=$(as hv1 ovs-vsctl get Interface vif1\n> external_ids:ovn-installed)\n> +    echo $ovn_installed\n> +    flow_count=$(as hv1 ovs-ofctl dump-flows br-int | grep -Fc \"10.0.0.1\")\n> +    # for the monitor-all=true case the flow gets installed because\n> ovn-controller is monitoring all\n> +    # tables in OVN_SOUTHBOUND.\n> +    if test -n \"$ovn_installed\"; then\n> +        as hv1 ovs-ofctl dump-flows br-int > output\n> +        test $flow_count -ge 1\n> +    else\n> +        true\n> +    fi\n> +])\n> +\n> +wake_up_sb\n> +# After the southbound db has woken up and can send the update to the\n> +# ovn-controller not monitoring all tables in the southbound db it\n> +# should be able to install the interface.\n> +OVS_WAIT_UNTIL([\n> +    ovn_installed=$(as hv1 ovs-vsctl get Interface vif1\n> external_ids:ovn-installed)\n> +    flow_count=$(as hv1 ovs-ofctl dump-flows br-int | grep -Fc \"10.0.0.1\")\n> +    echo \"installed=$ovn_installed, count=$flow_count\"\n> +    if test -n \"$ovn_installed\"; then\n> +        as hv1 ovs-ofctl dump-flows br-int > output\n> +        test $flow_count -ge 1\n> +    else\n> +        false\n> +    fi\n> +])\n> +wait_for_ports_up\n> +\n> +OVN_CLEANUP([hv1])\n> +AT_CLEANUP\n> +])\n> --\n> 2.53.0\n>\n>","headers":{"Return-Path":"<ovs-dev-bounces@openvswitch.org>","X-Original-To":["incoming@patchwork.ozlabs.org","dev@openvswitch.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","ovs-dev@lists.linuxfoundation.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=W1RK6dre;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=140.211.166.136; helo=smtp3.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)","smtp3.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key)\n header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=W1RK6dre","smtp2.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","smtp2.osuosl.org; dkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=W1RK6dre"],"Received":["from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g0XYy6YsRz1yGt\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 05:32:38 +1000 (AEST)","from localhost (localhost [127.0.0.1])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id D58D5608D1;\n\tTue, 21 Apr 2026 19:32:36 +0000 (UTC)","from smtp3.osuosl.org ([127.0.0.1])\n by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id J1ZEiVoOFcQB; Tue, 21 Apr 2026 19:32:35 +0000 (UTC)","from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp3.osuosl.org (Postfix) with ESMTPS id A56E0608BD;\n\tTue, 21 Apr 2026 19:32:35 +0000 (UTC)","from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 8BC1BC058E;\n\tTue, 21 Apr 2026 19:32:35 +0000 (UTC)","from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 0DB23C058D\n for <dev@openvswitch.org>; Tue, 21 Apr 2026 19:32:35 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id E7DD440269\n for <dev@openvswitch.org>; Tue, 21 Apr 2026 19:32:34 +0000 (UTC)","from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id JGCZDi71ND3T for <dev@openvswitch.org>;\n Tue, 21 Apr 2026 19:32:33 +0000 (UTC)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by smtp2.osuosl.org (Postfix) with ESMTPS id 1287F42076\n for <dev@openvswitch.org>; Tue, 21 Apr 2026 19:32:32 +0000 (UTC)","from mail-yx1-f70.google.com (mail-yx1-f70.google.com\n [74.125.224.70]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-206-r4bdg080NkeOMJETdnXV9Q-1; Tue, 21 Apr 2026 15:32:29 -0400","by mail-yx1-f70.google.com with SMTP id\n 956f58d0204a3-649df163c11so6490045d50.1\n for <dev@openvswitch.org>; Tue, 21 Apr 2026 12:32:29 -0700 (PDT)"],"X-Virus-Scanned":["amavis at osuosl.org","amavis at osuosl.org"],"X-Comment":"SPF check N/A for local connections - client-ip=140.211.9.56;\n helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ","DKIM-Filter":["OpenDKIM Filter v2.11.0 smtp3.osuosl.org A56E0608BD","OpenDKIM Filter v2.11.0 smtp2.osuosl.org 1287F42076"],"Received-SPF":"Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.124;\n helo=us-smtp-delivery-124.mimecast.com; envelope-from=jtanenba@redhat.com;\n receiver=<UNKNOWN>","DMARC-Filter":"OpenDMARC Filter v1.4.2 smtp2.osuosl.org 1287F42076","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1776799951;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=m0711rGFhpgEgVXW0Ku2cnTfsuIoR5MxT/YVRPFdE9Y=;\n b=W1RK6drenpUaCcwL8RY/v3hYC9mUcOGkqWSmTQXv03arZHUALx8I97Vgk/BOHIJk4H62yd\n y7bvLP8lAZSSdM8K5bvJ6R9NXzADJ+zF1elCA0FwSIlfZObfpA0B+cAwckO2+lIhi0zqZu\n 1FutnOhUa0FTf2BSCGKdRjYiVsbAd88=","X-MC-Unique":"r4bdg080NkeOMJETdnXV9Q-1","X-Mimecast-MFC-AGG-ID":"r4bdg080NkeOMJETdnXV9Q_1776799949","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776799949; x=1777404749;\n h=to:subject:message-id:date:from:in-reply-to:references:mime-version\n :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id\n :reply-to;\n bh=m0711rGFhpgEgVXW0Ku2cnTfsuIoR5MxT/YVRPFdE9Y=;\n b=OBf37xQ9fPBafF98veo2qpdx8xdmZ1OrT5fC25+qS+dkv7kQVVC06pEHkInAQYBd4q\n 687OP3AKWqfUwAPPlTXa8t33Vu6chhWS0QjBcSXPZ3zbVA4Ydfus0gplu5LM8mRA17Xm\n geIfB/BN2tk8wUFHFXMJhge/th7S5CCzfbGWMScrRvkAZ7ds5nC5w1sNwIUkqMpn0v0E\n LsWQkNha5W9RV9T8jSFRTSMrUviXjEwaMCnFeKM1hoTCOS1IIDhxQggyVSwHnVUYt5A3\n bhWv/xn+maBZcEocXPZLJuDV030x9p081wCoaAzTKjgAIYLI7evvLUPYdWnkbI//YjnW\n DBFg==","X-Gm-Message-State":"AOJu0Yzpd8uAOsOjPHmrIRKoLfW3DYlylOiHc1gPkhZdKK2+NYfgBzaA\n JhfyGxMtmeAMjgTv/o6C0e/d1iehfcEg4jiB6D9nxqSZ95lwhZpHauOEy5XJbqB6N1tJJBaATGx\n 0cDBExxpeYB1vKQNg5V64YXGUV1R5z7QRqFa1Uk+80+X9ddXezUfLpfsXx/+sj9Z9x/HXVWoB10\n m58nlM90xvNKNjy8XWBcOpTuowb1trc8cSC8Z5xEU=","X-Gm-Gg":"AeBDieuqRARW/qRF7rH3RyEkc1qi3DDnnPefogqc+YrmBGyX/r9QXNmyFsmFCNPv+Y8\n p8PH+QsfdutC7Xxu+clvXlsZFDcEdItlRe8lcMlcXEb70/DcwZiKJn/JjGlw4gF/mQk/a96721T\n wUyu2nlEWWnUrDu1e8ZeJwbXvVUEI1+auhtoN+tFwzoxq2pyYi4Deu75LlKvthgs33uMpoRfFqG\n 6mQcrbi//PCyv7aT9oHeEMT9Dvh2gpxs0uY33+AqP5lLi4/qw==","X-Received":["by 2002:a53:de44:0:b0:650:11b3:3f57 with SMTP id\n 956f58d0204a3-653107f8e16mr13625716d50.2.1776799948674;\n Tue, 21 Apr 2026 12:32:28 -0700 (PDT)","by 2002:a53:de44:0:b0:650:11b3:3f57 with SMTP id\n 956f58d0204a3-653107f8e16mr13625688d50.2.1776799947952; Tue, 21 Apr 2026\n 12:32:27 -0700 (PDT)"],"MIME-Version":"1.0","References":"<20260421144425.1191802-1-jtanenba@redhat.com>","In-Reply-To":"<20260421144425.1191802-1-jtanenba@redhat.com>","Date":"Tue, 21 Apr 2026 15:32:16 -0400","X-Gm-Features":"AQROBzAG3qgn5vkGGOvU2x4UMi10m_qkgmBuEs4PDWg_T16ZXf5daamsSzxwfUI","Message-ID":"\n <CACDpfc57HOi8f2GF7bM=V0t8fCAu1hFaYyK9v1RrZRzozSM3OQ@mail.gmail.com>","To":"dev@openvswitch.org","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"M6qM8dck5pe2K3dW-w3dPG4ZkQ4-n0yzd0tWeSnB57I_1776799949","X-Mimecast-Originator":"redhat.com","X-Content-Filtered-By":"Mailman/MimeDel 2.1.30","Subject":"Re: [ovs-dev] [Patch ovn v8] ovn-controller: Port up/ovn-installed\n reported too early.","X-BeenThere":"ovs-dev@openvswitch.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"<ovs-dev.openvswitch.org>","List-Unsubscribe":"<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>","List-Archive":"<http://mail.openvswitch.org/pipermail/ovs-dev/>","List-Post":"<mailto:ovs-dev@openvswitch.org>","List-Help":"<mailto:ovs-dev-request@openvswitch.org?subject=help>","List-Subscribe":"<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>","From":"Jacob Tanenbaum via dev <ovs-dev@openvswitch.org>","Reply-To":"Jacob Tanenbaum <jtanenba@redhat.com>","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"base64","Errors-To":"ovs-dev-bounces@openvswitch.org","Sender":"\"dev\" <ovs-dev-bounces@openvswitch.org>"}},{"id":3681411,"web_url":"http://patchwork.ozlabs.org/comment/3681411/","msgid":"<4837bc5f-19c9-4694-a7e9-b00e90f006f1@redhat.com>","list_archive_url":null,"date":"2026-04-23T12:00:48","subject":"Re: [ovs-dev] [Patch ovn v8] ovn-controller: Port up/ovn-installed\n reported too early.","submitter":{"id":76591,"url":"http://patchwork.ozlabs.org/api/people/76591/","name":"Dumitru Ceara","email":"dceara@redhat.com"},"content":"On 4/21/26 4:44 PM, Jacob Tanenbaum wrote:\n> When ovn-monitor-all is set to false ovn-controller sets ovn-installed\n> on OVS interfaces too early. ovn-controller needs to wait for the\n> response from the southbound database with the updates to the newly\n> monitored fields only then can it install flows and label the OVS\n> interface as installed.\n> \n> Reported-at: https://redhat.atlassian.net/browse/FDP-2887\n> Signed-off-by: Jacob Tanenbaum <jtanenba@redhat.com>\n> \n\nHi Jacob,\n\nThanks for the new revision!\n\n> ---\n> v7->v8\n> * removed printing in the system testcases that shouldn't be there and\n>   caused failure.\n> \n> v6->v7\n> * added an sset that holds the uuid's of datapaths that are waiting for\n>   sb updates\n> * added back the the state OIF_WAITING_SB_COND to the if_mgr state\n>   machine.\n> * no longer hold if the datapath is updated in the local_datapaths\n>   struct as that is generated each transaction and cannot be relied\n>   upon.\n> * removed some leftover logic from previous patch versions\n> \n> v5->v6\n> * simplified the logic as requested, Ales saw that we did not need to\n>   save the seqno if we checked before the engine run.\n> * removing the extra state from the state machine\n> * removing some leftover logic that was seen.\n> \n> v4->v5\n> * corrected a sanitizer error: used bool update_seqno without\n>   initializing\n> \n> v3->v4\n> * Added state OIF_WAITING_SB_COND to the state machine that manages\n>   the adding of interfaces. This state waits until the Southbound has\n>   updated the ovn-controller of relevent information about ports related\n>   to it\n> * Addressed several nits\n> \n> v2->v3\n> * adding the ld->monitor_updated required the additiona of checking for\n>   monitor_all in update_sb_monitors. I didn't account for being able to\n>   toggle on monitor_all\n> \n> v1->v2\n> * if_status_mgr_run() will run everytime the conditional seqno is\n>   changed so it should be safe to only skip when the expected_seqno and\n>   seqno returned from ovn are strictly not equal, that way we do not\n>   have to deal with overflow in the seqno. Additionally add a boolean to\n>   the local_datapath in the event that the seqno wraps around at the\n>   same time the datapath would go back into the state OIF_INSTALL_FLOWS.\n> * remove setting the state to itself for OIF_INSTALL_FLOWS in\n>   if_status_mgr_update()\n> * added assert(pb) in if_status_mgr_run()\n> * removed a manual loop looking for the local_datapath and replaced with\n>   get_local_datapath() in if_status_mgr_run\n> * remove a few nit spelling errors in the test case\n> \n> diff --git a/controller/if-status.c b/controller/if-status.c\n> index ee9337e63..34875d23e 100644\n> --- a/controller/if-status.c\n> +++ b/controller/if-status.c\n> @@ -18,6 +18,7 @@\n>  #include \"binding.h\"\n>  #include \"if-status.h\"\n>  #include \"lib/ofctrl-seqno.h\"\n> +#include \"local_data.h\"\n>  #include \"ovsport.h\"\n>  #include \"simap.h\"\n>  \n> @@ -58,6 +59,11 @@ VLOG_DEFINE_THIS_MODULE(if_status);\n>  enum if_state {\n>      OIF_CLAIMED,          /* Newly claimed interface. pb->chassis update not\n>                               yet initiated. */\n> +    OIF_WAITING_SB_COND,  /* Waiting for the Southbound database to update\n> +                           * ovn-controller for a given datapath. We should\n> +                           * only be waiting in this state when monitor_all\n> +                           * is false AND it is the first time that we see\n> +                           * a specific datapath. */\n>      OIF_INSTALL_FLOWS,    /* Claimed interface with pb->chassis update sent to\n>                             * SB (but update notification not confirmed, so the\n>                             * update may be resent in any of the following\n> @@ -87,6 +93,7 @@ enum if_state {\n>  \n>  static const char *if_state_names[] = {\n>      [OIF_CLAIMED]          = \"CLAIMED\",\n> +    [OIF_WAITING_SB_COND]  = \"WAITING_SB_COND\",\n>      [OIF_INSTALL_FLOWS]    = \"INSTALL_FLOWS\",\n>      [OIF_REM_OLD_OVN_INST] = \"REM_OLD_OVN_INST\",\n>      [OIF_MARK_UP]          = \"MARK_UP\",\n> @@ -114,7 +121,18 @@ static const char *if_state_names[] = {\n>   * | |                 |  +--+                                           | | |\n>   * | |                 |                                                 | | |\n>   * | |                 | mgr_update(when sb is rw i.e. pb->chassis)      | | |\n> - * | |                 |            has been updated                     | | |\n> + * | |                 V            has been updated                     | | |\n> + * | |   +----------------------+                                        | | |\n> + * | |   |                      |                                        | | |\n> + * | |   |    WAITING_SB_COND   |                                        | | |\n> + * | |   |                      |                                        | | |\n> + * | |   |                      |                                        | | |\n> + * | |   +----------------------+                                        | | |\n> + * | |                 |                                                 | | |\n> + * | |                 |                                                 | | |\n> + * | |                 |   mgr_update(when sb_cond_seqno == expected)    | | |\n> + * | |                 |   - request seqno                               | | |\n> + * | |                 |                                                 | | |\n>   * | | release_iface   | - request seqno                                 | | |\n>   * | |                 |                                                 | | |\n>   * | |                 V                                                 | | |\n> @@ -335,6 +353,7 @@ if_status_mgr_claim_iface(struct if_status_mgr *mgr,\n>  \n>      switch (iface->state) {\n>      case OIF_CLAIMED:\n> +    case OIF_WAITING_SB_COND:\n>      case OIF_INSTALL_FLOWS:\n>      case OIF_REM_OLD_OVN_INST:\n>      case OIF_MARK_UP:\n> @@ -383,6 +402,7 @@ if_status_mgr_release_iface(struct if_status_mgr *mgr, const char *iface_id)\n>  \n>      switch (iface->state) {\n>      case OIF_CLAIMED:\n> +    case OIF_WAITING_SB_COND:\n>      case OIF_INSTALL_FLOWS:\n>          /* Not yet fully installed interfaces:\n>           * pb->chassis still need to be deleted.\n> @@ -424,6 +444,7 @@ if_status_mgr_delete_iface(struct if_status_mgr *mgr, const char *iface_id,\n>  \n>      switch (iface->state) {\n>      case OIF_CLAIMED:\n> +    case OIF_WAITING_SB_COND:\n>      case OIF_INSTALL_FLOWS:\n>          /* Not yet fully installed interfaces:\n>           * pb->chassis still need to be deleted.\n> @@ -500,6 +521,8 @@ if_status_mgr_update(struct if_status_mgr *mgr,\n>                       const struct sbrec_chassis *chassis_rec,\n>                       const struct ovsrec_interface_table *iface_table,\n>                       const struct sbrec_port_binding_table *pb_table,\n> +                     const struct hmap *local_datapaths,\n> +                     const struct sset *waiting_sb_update,\n\nI was going to suggest a more descriptive name here but (see comment in\novn-controller.c below) given that I think we should be storing this set\nin runtime_data I wonder now if we should just have a flag in 'struct\nlocal_datapath' that tells us if the datapath is fully processed or if\nwe're \"waiting_sb_update\".\n\nThen we wouldn't need this new sset/uuidset.\n\n>                       bool ovs_readonly,\n>                       bool sb_readonly)\n>  {\n> @@ -622,9 +645,7 @@ if_status_mgr_update(struct if_status_mgr *mgr,\n>               * in if_status_handle_claims or if_status_mgr_claim_iface\n>               */\n>              if (iface->is_vif) {\n> -                ovs_iface_set_state(mgr, iface, OIF_INSTALL_FLOWS);\n> -                iface->install_seqno = mgr->iface_seqno + 1;\n> -                new_ifaces = true;\n> +                ovs_iface_set_state(mgr, iface, OIF_WAITING_SB_COND);\n>              } else {\n>                  ovs_iface_set_state(mgr, iface, OIF_MARK_UP);\n>              }\n> @@ -639,6 +660,32 @@ if_status_mgr_update(struct if_status_mgr *mgr,\n>          }\n>      }\n>  \n> +    if (!sb_readonly) {\n> +        HMAPX_FOR_EACH_SAFE (node,\n> +                             &mgr->ifaces_per_state[OIF_WAITING_SB_COND]) {\n> +            struct ovs_iface *iface = node->data;\n> +            if (local_datapaths) {\n> +                const struct sbrec_port_binding *pb =\n> +                    sbrec_port_binding_table_get_for_uuid(pb_table,\n> +                                                          &iface->pb_uuid);\n> +                ovs_assert(pb);\n\nIs there a chance that the port binding is deleted from the SB database\nwhile the interface is still in OIF_WAITING_SB_COND state.  All other\nport binding lookups in this file check for NULL gracefully (e.g., \"if\n(pb && ...)\").  Should this use a NULL check instead?\n\n\n> +                struct local_datapath *ld =\n> +                    get_local_datapath(local_datapaths,\n> +                                       pb->datapath->tunnel_key);\n> +                if (!ld) {\n> +                    continue;\n> +                }\n> +                char *uuid = uuid_to_string(&ld->datapath->header_.uuid);\n> +                if (!sset_contains(waiting_sb_update, uuid)) {\n> +                    ovs_iface_set_state(mgr, iface, OIF_INSTALL_FLOWS);\n> +                    iface->install_seqno = mgr->iface_seqno + 1;\n> +                    new_ifaces = true;\n> +                }\n> +                free(uuid);\n> +            }\n> +        }\n> +    }\n> +\n\nIn if_status_mgr_update_bindings() we do local_binding_set_down() for\nall ifaces that are in state OIF_INSTALL_FLOWS.  But now that we have\nthe new OIF_WAITING_SB_COND state (happening before transitioning to\nOIF_INSTALL_FLOWS, potentially in different ovn-controller runs) should\nwe also call local_binding_set_down() for those too?\n\n>      if (!sb_readonly) {\n>          HMAPX_FOR_EACH_SAFE (node, &mgr->ifaces_per_state[OIF_UPDATE_PORT]) {\n>              struct ovs_iface *iface = node->data;\n> diff --git a/controller/if-status.h b/controller/if-status.h\n> index d15ca3008..67018d113 100644\n> --- a/controller/if-status.h\n> +++ b/controller/if-status.h\n> @@ -43,6 +43,8 @@ void if_status_mgr_update(struct if_status_mgr *, struct local_binding_data *,\n>                            const struct sbrec_chassis *chassis,\n>                            const struct ovsrec_interface_table *iface_table,\n>                            const struct sbrec_port_binding_table *pb_table,\n> +                          const struct hmap *local_datapaths,\n> +                          const struct sset *waiting_sb_update,\n>                            bool ovs_readonly,\n>                            bool sb_readonly);\n>  void if_status_mgr_run(struct if_status_mgr *mgr, struct local_binding_data *,\n> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c\n> index da43051ed..a25892056 100644\n> --- a/controller/ovn-controller.c\n> +++ b/controller/ovn-controller.c\n> @@ -1511,6 +1511,7 @@ en_runtime_data_clear_tracked_data(void *data_)\n>  }\n>  \n>  static void *\n> +\n\nNit: empty line not needed.\n\n>  en_runtime_data_init(struct engine_node *node OVS_UNUSED,\n>                       struct engine_arg *arg OVS_UNUSED)\n>  {\n> @@ -7596,6 +7597,8 @@ main(int argc, char *argv[])\n>      int ovs_txn_status = 1;\n>      bool sb_monitor_all = false;\n>      struct tracked_acl_ids *tracked_acl_ids = NULL;\n> +    struct sset waiting_sb_update;\n> +    sset_init(&waiting_sb_update);\n\nNit: missing sset_destroy.\n\n>      while (!exit_args.exiting) {\n>          ovsrcu_quiesce_end();\n>  \n> @@ -7842,6 +7845,7 @@ main(int argc, char *argv[])\n>  \n>                      bool recompute_allowed = (ovnsb_idl_txn &&\n>                                                !ofctrl_has_backlog());\n> +\n\nNit: unrelated new line.\n\n>                      engine_run(recompute_allowed);\n>                      tracked_acl_ids = engine_get_data(&en_acl_id);\n>  \n> @@ -7951,6 +7955,9 @@ main(int argc, char *argv[])\n>                                     sbrec_mirror_table_get(ovnsb_idl_loop.idl),\n>                                     br_int,\n>                                     &runtime_data->lbinding_data.bindings);\n> +                        if (ovnsb_cond_seqno == ovnsb_expected_cond_seqno) {\n> +                            sset_clear(&waiting_sb_update);\n> +                        }\n>                          /* Updating monitor conditions if runtime data or\n>                           * logical datapath goups changed. */\n>                          if (engine_node_changed(&en_runtime_data)\n> @@ -7973,6 +7980,23 @@ main(int argc, char *argv[])\n>                                   * a continuous reason for monitor updates. */\n>                                  daemon_started_recently_countdown();\n>                              }\n> +\n> +                            if (!sb_monitor_all && runtime_data) {\n> +                                struct hmap *tracked_dp_bindings =\n> +                                    &runtime_data->tracked_dp_bindings;\n> +                                struct tracked_datapath *tdp;\n> +                                HMAP_FOR_EACH_SAFE (tdp,\n> +                                                    node,\n> +                                                    tracked_dp_bindings) {\n> +                                    char *uuid =\n> +                                        uuid_to_string(&tdp->dp->header_.uuid);\n> +                                    if (tdp->tracked_type ==\n> +                                        TRACKED_RESOURCE_NEW) {\n> +                                        sset_add(&waiting_sb_update, uuid);\n\nThis should be an uuidset instead of a sset.\n\n> +                                    }\n> +                                    free(uuid);\n\nIt feels odd that we're doing this here.  Shouldn't the uuidset be part\nof the runtime_data state (struct ed_type_runtime_data), updated in\nadd_local_datapath() -> tracked_datapath_add(.., TRACKED_RESOURCE_NEW)?\n\n> +                                }\n> +                            }\n>                          }\n>                          /* If there is no new expected seqno we have finished\n>                           * loading all needed data from southbound. We then\n> @@ -8017,6 +8041,10 @@ main(int argc, char *argv[])\n>                                                      ovs_idl_loop.idl),\n>                                           sbrec_port_binding_table_get(\n>                                                      ovnsb_idl_loop.idl),\n> +                                         runtime_data ?\n> +                                               &runtime_data->local_datapaths\n> +                                               : NULL,\n> +                                         &waiting_sb_update,\n\nWith my comment above addressed, we'd pass\n&runtime_data->waiting_sb_update here instead.\n\n>                                           !ovs_idl_txn,\n>                                           !ovnsb_idl_txn);\n>                      stopwatch_stop(IF_STATUS_MGR_UPDATE_STOPWATCH_NAME,\n> diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at\n> index c98de9bc4..9dc7555ba 100644\n> --- a/tests/ovn-controller.at\n> +++ b/tests/ovn-controller.at\n> @@ -3944,3 +3944,69 @@ OVN_CLEANUP([hv1], [hv2\n>  /already has encap ip.*cannot duplicate on/d])\n>  AT_CLEANUP\n>  ])\n> +\n> +OVN_FOR_EACH_NORTHD([\n> +AT_SETUP([ovn-installed])\n> +ovn_start\n> +\n> +net_add n1\n> +sim_add hv1\n> +\n> +as hv1\n> +ovs-vsctl add-br br-phys\n> +ovn_attach n1 br-phys 192.168.0.1\n> +ovn-appctl vlog/set dbg\n> +ovs-vsctl add-port br-int vif1 -- \\\n> +    set Interface vif1 external-ids:iface-id=lsp1\n> +\n> +check ovn-nbctl ls-add ls1\n> +sleep_controller hv1\n> +check ovn-nbctl --wait=sb lsp-add ls1 lsp1 -- \\\n> +                          lsp-set-addresses lsp1 \"f0:00:00:00:00:01 10.0.0.1\"\n> +\n> +sleep_sb\n> +wake_up_controller hv1\n> +\n> +# Wait for pflow for lsp1\n\nNit: Comments should be sentences and end with dot.\n\n> +OVS_WAIT_UNTIL([\n> +    ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=vif1)\n> +    echo \"vif1 port=$ofport\"\n> +    test -n \"$ofport\" && test 1 -le $(as hv1 ovs-ofctl dump-flows br-int | grep -c in_port=$ofport)\n> +])\n> +\n> +# If ovn-installed in ovs, all flows should be installed.\n> +# In that case, there should be at least one flow with lsp1 address.\n> +OVS_WAIT_UNTIL([\n> +    ovn_installed=$(as hv1 ovs-vsctl get Interface vif1 external_ids:ovn-installed)\n> +    echo $ovn_installed\n\nShould the echo be removed?\n\n> +    flow_count=$(as hv1 ovs-ofctl dump-flows br-int | grep -Fc \"10.0.0.1\")\n> +    # for the monitor-all=true case the flow gets installed because ovn-controller is monitoring all\n> +    # tables in OVN_SOUTHBOUND.\n> +    if test -n \"$ovn_installed\"; then\n> +        as hv1 ovs-ofctl dump-flows br-int > output\n\nThis too, was it for debugging purposes?\n\n> +        test $flow_count -ge 1\n> +    else\n> +        true\n\nDid you mean \"false\" here?  Otherwise, if ovn-installed is not present,\nwe break out of the OVS_WAIT_UNTIL() immediately, or am I missing something?\n\n> +    fi\n> +])\n> +\n> +wake_up_sb\n> +# After the southbound db has woken up and can send the update to the\n> +# ovn-controller not monitoring all tables in the southbound db it\n> +# should be able to install the interface.\n> +OVS_WAIT_UNTIL([\n> +    ovn_installed=$(as hv1 ovs-vsctl get Interface vif1 external_ids:ovn-installed)\n> +    flow_count=$(as hv1 ovs-ofctl dump-flows br-int | grep -Fc \"10.0.0.1\")\n> +    echo \"installed=$ovn_installed, count=$flow_count\"\n> +    if test -n \"$ovn_installed\"; then\n> +        as hv1 ovs-ofctl dump-flows br-int > output\n> +        test $flow_count -ge 1\n> +    else\n> +        false\n> +    fi\n> +])\n> +wait_for_ports_up\n> +\n> +OVN_CLEANUP([hv1])\n> +AT_CLEANUP\n> +])\n\nRegards,\nDumitru","headers":{"Return-Path":"<ovs-dev-bounces@openvswitch.org>","X-Original-To":["incoming@patchwork.ozlabs.org","dev@openvswitch.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","ovs-dev@lists.linuxfoundation.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=LsK+g0hj;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=140.211.166.137; helo=smtp4.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)","smtp4.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key)\n header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=LsK+g0hj","smtp1.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","smtp1.osuosl.org;\n dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com\n header.a=rsa-sha256 header.s=mimecast20190719 header.b=LsK+g0hj"],"Received":["from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g1ZSB12fkz1yD5\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 22:01:14 +1000 (AEST)","from localhost (localhost [127.0.0.1])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id 0A80240F62;\n\tThu, 23 Apr 2026 12:01:12 +0000 (UTC)","from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id ept_qryPOcjN; Thu, 23 Apr 2026 12:01:07 +0000 (UTC)","from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp4.osuosl.org (Postfix) with ESMTPS id D0B5640F5A;\n\tThu, 23 Apr 2026 12:01:07 +0000 (UTC)","from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id B3A80C058E;\n\tThu, 23 Apr 2026 12:01:07 +0000 (UTC)","from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n by lists.linuxfoundation.org (Postfix) with ESMTP id EF246C058D\n for <dev@openvswitch.org>; Thu, 23 Apr 2026 12:01:06 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id D352E83760\n for <dev@openvswitch.org>; Thu, 23 Apr 2026 12:01:06 +0000 (UTC)","from smtp1.osuosl.org ([127.0.0.1])\n by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id uuFyVj_HU1tD for <dev@openvswitch.org>;\n Thu, 23 Apr 2026 12:01:02 +0000 (UTC)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by smtp1.osuosl.org (Postfix) with ESMTPS id 2B10880C6D\n for <dev@openvswitch.org>; Thu, 23 Apr 2026 12:01:01 +0000 (UTC)","from mail-pl1-f199.google.com (mail-pl1-f199.google.com\n [209.85.214.199]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-323-EYm-pn6IOzmwznFx5FySvQ-1; Thu, 23 Apr 2026 08:00:58 -0400","by mail-pl1-f199.google.com with SMTP id\n d9443c01a7336-2b79f4b35b7so7024635ad.0\n for <dev@openvswitch.org>; Thu, 23 Apr 2026 05:00:58 -0700 (PDT)","from ?IPV6:2001:1c05:1417:d800:d1ef:9817:2a26:625d?\n (2001-1c05-1417-d800-d1ef-9817-2a26-625d.cable.dynamic.v6.ziggo.nl.\n [2001:1c05:1417:d800:d1ef:9817:2a26:625d])\n by smtp.gmail.com with ESMTPSA id\n d9443c01a7336-2b5faa494e1sm190564045ad.35.2026.04.23.05.00.51\n (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n Thu, 23 Apr 2026 05:00:54 -0700 (PDT)"],"X-Virus-Scanned":["amavis at osuosl.org","amavis at osuosl.org"],"X-Comment":"SPF check N/A for local connections -\n client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ","DKIM-Filter":["OpenDKIM Filter v2.11.0 smtp4.osuosl.org D0B5640F5A","OpenDKIM Filter v2.11.0 smtp1.osuosl.org 2B10880C6D"],"Received-SPF":"Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124;\n helo=us-smtp-delivery-124.mimecast.com; envelope-from=dceara@redhat.com;\n receiver=<UNKNOWN>","DMARC-Filter":"OpenDMARC Filter v1.4.2 smtp1.osuosl.org 2B10880C6D","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1776945660;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=a7EJg5g+ywJsp2MpTX7Oe3f617HnrDg7RWo+o0Seo2Y=;\n b=LsK+g0hjYOXdeWbbPIKWg6R/2/Z/O8FzKFK4dhAgK9wMWY0DAuQ4EvkFL9UfWCPs25ufVV\n vY+DxTvf4/9yqtoSq0WefTtdeOg4J9SYDJP9rBptaVY8nQ8w+eBSl67F9k1c814fPDMBXb\n zbNZADiGdJfbpaRS/xBXECTBz8VSBkA=","X-MC-Unique":"EYm-pn6IOzmwznFx5FySvQ-1","X-Mimecast-MFC-AGG-ID":"EYm-pn6IOzmwznFx5FySvQ_1776945658","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776945658; x=1777550458;\n h=content-transfer-encoding:in-reply-to:content-language:from\n :references:cc:to:subject:user-agent:mime-version:date:message-id\n :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id\n :reply-to;\n bh=a7EJg5g+ywJsp2MpTX7Oe3f617HnrDg7RWo+o0Seo2Y=;\n b=Oq/eDo8rM4Nc4iLV7l5fp4uFLK/opXBtQQGOruk87yUjpJClG0ISX2bFBXs6gIyg/f\n w4Ic4+lPXBb6+9u8s4Me//s2t7EPZwrnjfpnaseOZpmlSNm+cElqulfNYl2gn8QQw4sF\n 0BzX5uq4smsGMEZNBMNXZ1pCCtKk57MtIQw+bakDctCKHfyvAksslqe/cbPiFpn8cgEs\n LV5pexFPbBWEyBlurh+RlfoH/MzML5z6GLcPo/45cdmH+L/NpGz4gn3ZwAMTEvm0s5Jh\n wSs23OwKQ2c8s4li5C0GQ+RK0HqVrKO7pwqsha854SUM/pBOb2JkVpfvSkP/5Hsl32vJ\n iw/g==","X-Forwarded-Encrypted":"i=1;\n AFNElJ9ETPi66GI9gjlT4HjICs7PGhM1l/1GNsDEQZucAn2UheMHWnUndhNzdNH6AR3L9KJzbnw=@openvswitch.org","X-Gm-Message-State":"AOJu0YxdJ8c08m16eXPZ0G4YL7qBGee72YBwvd154Al5kA5r0ORCEyxl\n XC6gIKxK/cPr1pHqXf8KB9Gv/hHLvSGVUQQveHTqN93yeDyWevWsn7Eyenf2DMjQsbHzR77IqDs\n EOb1ViBKvfwWWuoEQBEkIITqKs34e/k2ZFk/+9f2xh3q0wobrTLM5xg==","X-Gm-Gg":"AeBDiesYp9mZ/VDUZVQ0PdfQFOL3YDNT+M8TxkqzDAAUAYqRNQl08AcrSebZw2bZYUR\n YceWNA9GF5BVSmmAsvAO3JiRBj/eAQihGEPXJwyOoW8ie8E9qFk++z5bbVHTNscggHFhOei3Ef6\n bIFiE0GBGl08pCG1uMazKnlw3UX01JZjfnApmtMkopo6n6NLvaE6SsLR9F2T8itjiYu6oQZ1K4w\n 1dffZnSVKEhxviQYOBfVDY7MkWdQr5Vu5IqJ+DDyFFSxui3QpYUX4HwF7iobz6Hey4LPFiDXMZu\n pE2gkmpNXpApY7RgHgiWGVVAzaMRHmE5zJ/Axam9pXvuZPfRnfROFZMWKJlhO+it7kGk8Pz2QWN\n ZG5PQ56imcRPlu9ZFgzAR5rBWpejgYXBKaPdDeXLModuQJlAuncw+tgLy664A+yDv+Rg9Nx/hXx\n s6aKPL6CLppgBY3/iqxtO3wsppP3vfcjjv+UM3oM9Std/c/5BvnVoxU8fUWNcH0D1zkVRAGVerB\n bYUgalP5tQ=","X-Received":["by 2002:a17:903:68d:b0:2b2:497e:3f60 with SMTP id\n d9443c01a7336-2b5fa0126ccmr177445285ad.33.1776945656542;\n Thu, 23 Apr 2026 05:00:56 -0700 (PDT)","by 2002:a17:903:68d:b0:2b2:497e:3f60 with SMTP id\n d9443c01a7336-2b5fa0126ccmr177444565ad.33.1776945655434;\n Thu, 23 Apr 2026 05:00:55 -0700 (PDT)"],"Message-ID":"<4837bc5f-19c9-4694-a7e9-b00e90f006f1@redhat.com>","Date":"Thu, 23 Apr 2026 14:00:48 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","To":"Jacob Tanenbaum <jtanenba@redhat.com>, dev@openvswitch.org","References":"<20260421144425.1191802-1-jtanenba@redhat.com>","In-Reply-To":"<20260421144425.1191802-1-jtanenba@redhat.com>","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"ALNWiHovxZet-nHQCAvKtUqzzbm3BJW-GgrfSkfX6CU_1776945658","X-Mimecast-Originator":"redhat.com","Content-Language":"en-US","Subject":"Re: [ovs-dev] [Patch ovn v8] ovn-controller: Port up/ovn-installed\n reported too early.","X-BeenThere":"ovs-dev@openvswitch.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"<ovs-dev.openvswitch.org>","List-Unsubscribe":"<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>","List-Archive":"<http://mail.openvswitch.org/pipermail/ovs-dev/>","List-Post":"<mailto:ovs-dev@openvswitch.org>","List-Help":"<mailto:ovs-dev-request@openvswitch.org?subject=help>","List-Subscribe":"<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>","From":"Dumitru Ceara via dev <ovs-dev@openvswitch.org>","Reply-To":"Dumitru Ceara <dceara@redhat.com>","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"ovs-dev-bounces@openvswitch.org","Sender":"\"dev\" <ovs-dev-bounces@openvswitch.org>"}}]