5f9769
From 3719a1add73b860c50d85fad0b270c1b69fb9147 Mon Sep 17 00:00:00 2001
5f9769
From: Dumitru Ceara <dceara@redhat.com>
5f9769
Date: Wed, 13 Jan 2021 10:23:32 +0100
5f9769
Subject: [PATCH 3/3] binding: Set Logical_Switch_Port.up when all OVS flows
5f9769
 are installed.
5f9769
5f9769
Using the ofctrl-seqno generic barrier, register a new type of
5f9769
notifications for Port_Bindings.  This allows us to delay setting
5f9769
the Logical_Switch_Port.up field until all OVS flows corresponding
5f9769
to the logical port and underlying OVS interface have been installed.
5f9769
5f9769
This commit also marks the OVS interface as "installed by OVN" by
5f9769
setting a new "ovn-installed" external-id in the OVS Interface record
5f9769
when the port is fully wired by OVN.
5f9769
5f9769
Signed-off-by: Dumitru Ceara <dceara@redhat.com>
5f9769
Acked-by: Mark Michelson <mmichels@redhat.com>
5f9769
Signed-off-by: Numan Siddique <numans@ovn.org>
5f9769
(cherry picked from upstream master commit 4d3cb42b076bb58fd8f01ab8ad146ffd539f2152)
5f9769
5f9769
Change-Id: Id8e4fc3b28110cab2571d4ff8bc5ef81ae9b88c4
5f9769
---
5f9769
 NEWS                        |   6 ++
5f9769
 controller/binding.c        | 181 ++++++++++++++++++++++++++++++++++++++++++++
5f9769
 controller/binding.h        |   5 ++
5f9769
 controller/ovn-controller.c |  14 +++-
5f9769
 northd/ovn-northd.c         |   6 +-
5f9769
 ovn-sb.ovsschema            |   5 +-
5f9769
 ovn-sb.xml                  |   8 ++
5f9769
 tests/ovn.at                |  32 ++++++++
5f9769
 utilities/ovn-sbctl.c       |   4 +
5f9769
 9 files changed, 254 insertions(+), 7 deletions(-)
5f9769
5f9769
diff --git a/NEWS b/NEWS
5f9769
index 7d2ba56..e89c5f4 100644
5f9769
--- a/NEWS
5f9769
+++ b/NEWS
5f9769
@@ -4,6 +4,12 @@ Post-v20.12.0
5f9769
    - BFD protocol support according to RFC880 [0]. Introduce next-hop BFD
5f9769
      availability check for OVN static routes.
5f9769
      [0] https://tools.ietf.org/html/rfc5880)
5f9769
+  - Change the semantic of the "Logical_Switch_Port.up" field such that it is
5f9769
+    set to "true" only when all corresponding OVS openflow operations have
5f9769
+    been processed.  This also introduces a new "OVS.Interface.external-id",
5f9769
+    "ovn-installed".  This external-id is set by ovn-controller only after all
5f9769
+    openflow operations corresponding to the OVS interface being added have
5f9769
+    been processed.
5f9769
 
5f9769
 OVN v20.12.0 - 18 Dec 2020
5f9769
 --------------------------
5f9769
diff --git a/controller/binding.c b/controller/binding.c
5f9769
index c8e8591..d44f635 100644
5f9769
--- a/controller/binding.c
5f9769
+++ b/controller/binding.c
5f9769
@@ -18,6 +18,7 @@
5f9769
 #include "ha-chassis.h"
5f9769
 #include "lflow.h"
5f9769
 #include "lport.h"
5f9769
+#include "ofctrl-seqno.h"
5f9769
 #include "patch.h"
5f9769
 
5f9769
 #include "lib/bitmap.h"
5f9769
@@ -34,6 +35,38 @@
5f9769
 
5f9769
 VLOG_DEFINE_THIS_MODULE(binding);
5f9769
 
5f9769
+/* External ID to be set in the OVS.Interface record when the OVS interface
5f9769
+ * is ready for use, i.e., is bound to an OVN port and its corresponding
5f9769
+ * flows have been installed.
5f9769
+ */
5f9769
+#define OVN_INSTALLED_EXT_ID "ovn-installed"
5f9769
+
5f9769
+/* Set of OVS interface IDs that have been released in the most recent
5f9769
+ * processing iterations.  This gets updated in release_lport() and is
5f9769
+ * periodically emptied in binding_seqno_run().
5f9769
+ */
5f9769
+static struct sset binding_iface_released_set =
5f9769
+    SSET_INITIALIZER(&binding_iface_released_set);
5f9769
+
5f9769
+/* Set of OVS interface IDs that have been bound in the most recent
5f9769
+ * processing iterations.  This gets updated in release_lport() and is
5f9769
+ * periodically emptied in binding_seqno_run().
5f9769
+ */
5f9769
+static struct sset binding_iface_bound_set =
5f9769
+    SSET_INITIALIZER(&binding_iface_bound_set);
5f9769
+
5f9769
+static void
5f9769
+binding_iface_released_add(const char *iface_id)
5f9769
+{
5f9769
+    sset_add(&binding_iface_released_set, iface_id);
5f9769
+}
5f9769
+
5f9769
+static void
5f9769
+binding_iface_bound_add(const char *iface_id)
5f9769
+{
5f9769
+    sset_add(&binding_iface_bound_set, iface_id);
5f9769
+}
5f9769
+
5f9769
 #define OVN_QOS_TYPE "linux-htb"
5f9769
 
5f9769
 struct qos_queue {
5f9769
@@ -845,6 +878,7 @@ claim_lport(const struct sbrec_port_binding *pb,
5f9769
             return false;
5f9769
         }
5f9769
 
5f9769
+        binding_iface_bound_add(pb->logical_port);
5f9769
         if (pb->chassis) {
5f9769
             VLOG_INFO("Changing chassis for lport %s from %s to %s.",
5f9769
                     pb->logical_port, pb->chassis->name,
5f9769
@@ -908,7 +942,9 @@ release_lport(const struct sbrec_port_binding *pb, bool sb_readonly,
5f9769
         sbrec_port_binding_set_virtual_parent(pb, NULL);
5f9769
     }
5f9769
 
5f9769
+    sbrec_port_binding_set_up(pb, NULL, 0);
5f9769
     update_lport_tracking(pb, tracked_datapaths);
5f9769
+    binding_iface_released_add(pb->logical_port);
5f9769
     VLOG_INFO("Releasing lport %s from this chassis.", pb->logical_port);
5f9769
     return true;
5f9769
 }
5f9769
@@ -2358,3 +2394,148 @@ delete_done:
5f9769
     destroy_qos_map(&qos_map);
5f9769
     return handled;
5f9769
 }
5f9769
+
5f9769
+/* Registered ofctrl seqno type for port_binding flow installation. */
5f9769
+static size_t binding_seq_type_pb_cfg;
5f9769
+
5f9769
+/* Binding specific seqno to be acked by ofctrl when flows for new interfaces
5f9769
+ * have been installed.
5f9769
+ */
5f9769
+static uint32_t binding_iface_seqno = 0;
5f9769
+
5f9769
+/* Map indexed by iface-id containing the sequence numbers that when acked
5f9769
+ * indicate that the OVS flows for the iface-id have been installed.
5f9769
+ */
5f9769
+static struct simap binding_iface_seqno_map =
5f9769
+    SIMAP_INITIALIZER(&binding_iface_seqno_map);
5f9769
+
5f9769
+void
5f9769
+binding_init(void)
5f9769
+{
5f9769
+    binding_seq_type_pb_cfg = ofctrl_seqno_add_type();
5f9769
+}
5f9769
+
5f9769
+/* Processes new release/bind operations OVN ports.  For newly bound ports
5f9769
+ * it creates ofctrl seqno update requests that will be acked when
5f9769
+ * corresponding OVS flows have been installed.
5f9769
+ *
5f9769
+ * NOTE: Should be called only when valid SB and OVS transactions are
5f9769
+ * available.
5f9769
+ */
5f9769
+void
5f9769
+binding_seqno_run(struct shash *local_bindings)
5f9769
+{
5f9769
+    const char *iface_id;
5f9769
+    const char *iface_id_next;
5f9769
+
5f9769
+    SSET_FOR_EACH_SAFE (iface_id, iface_id_next, &binding_iface_released_set) {
5f9769
+        struct shash_node *lb_node = shash_find(local_bindings, iface_id);
5f9769
+
5f9769
+        /* If the local binding still exists (i.e., the OVS interface is
5f9769
+         * still configured locally) then remove the external id and remove
5f9769
+         * it from the in-flight seqno map.
5f9769
+         */
5f9769
+        if (lb_node) {
5f9769
+            struct local_binding *lb = lb_node->data;
5f9769
+
5f9769
+            if (lb->iface && smap_get(&lb->iface->external_ids,
5f9769
+                                      OVN_INSTALLED_EXT_ID)) {
5f9769
+                ovsrec_interface_update_external_ids_delkey(
5f9769
+                    lb->iface, OVN_INSTALLED_EXT_ID);
5f9769
+            }
5f9769
+        }
5f9769
+        simap_find_and_delete(&binding_iface_seqno_map, iface_id);
5f9769
+        sset_delete(&binding_iface_released_set,
5f9769
+                    SSET_NODE_FROM_NAME(iface_id));
5f9769
+    }
5f9769
+
5f9769
+    bool new_ifaces = false;
5f9769
+    uint32_t new_seqno = binding_iface_seqno + 1;
5f9769
+
5f9769
+    SSET_FOR_EACH_SAFE (iface_id, iface_id_next, &binding_iface_bound_set) {
5f9769
+        struct shash_node *lb_node = shash_find(local_bindings, iface_id);
5f9769
+
5f9769
+        if (lb_node) {
5f9769
+            /* This is a newly bound interface, make sure we reset the
5f9769
+             * Port_Binding 'up' field and the OVS Interface 'external-id'.
5f9769
+             */
5f9769
+            struct local_binding *lb = lb_node->data;
5f9769
+
5f9769
+            ovs_assert(lb->pb && lb->iface);
5f9769
+            new_ifaces = true;
5f9769
+
5f9769
+            if (smap_get(&lb->iface->external_ids, OVN_INSTALLED_EXT_ID)) {
5f9769
+                ovsrec_interface_update_external_ids_delkey(
5f9769
+                    lb->iface, OVN_INSTALLED_EXT_ID);
5f9769
+            }
5f9769
+            sbrec_port_binding_set_up(lb->pb, NULL, 0);
5f9769
+            simap_put(&binding_iface_seqno_map, lb->name, new_seqno);
5f9769
+        }
5f9769
+        sset_delete(&binding_iface_bound_set, SSET_NODE_FROM_NAME(iface_id));
5f9769
+    }
5f9769
+
5f9769
+    /* Request a seqno update when the flows for new interfaces have been
5f9769
+     * installed in OVS.
5f9769
+     */
5f9769
+    if (new_ifaces) {
5f9769
+        binding_iface_seqno = new_seqno;
5f9769
+        ofctrl_seqno_update_create(binding_seq_type_pb_cfg, new_seqno);
5f9769
+    }
5f9769
+}
5f9769
+
5f9769
+/* Processes ofctrl seqno ACKs for new bindings.  Sets the
5f9769
+ * 'OVN_INSTALLED_EXT_ID' external-id in the OVS interface and the
5f9769
+ * Port_Binding.up field for all ports for which OVS flows have been
5f9769
+ * installed.
5f9769
+ *
5f9769
+ * NOTE: Should be called only when valid SB and OVS transactions are
5f9769
+ * available.
5f9769
+ */
5f9769
+void
5f9769
+binding_seqno_install(struct shash *local_bindings)
5f9769
+{
5f9769
+    struct ofctrl_acked_seqnos *acked_seqnos =
5f9769
+            ofctrl_acked_seqnos_get(binding_seq_type_pb_cfg);
5f9769
+    struct simap_node *node;
5f9769
+    struct simap_node *node_next;
5f9769
+
5f9769
+    SIMAP_FOR_EACH_SAFE (node, node_next, &binding_iface_seqno_map) {
5f9769
+        struct shash_node *lb_node = shash_find(local_bindings, node->name);
5f9769
+        bool up = true;
5f9769
+
5f9769
+        if (!lb_node) {
5f9769
+            goto del_seqno;
5f9769
+        }
5f9769
+
5f9769
+        struct local_binding *lb = lb_node->data;
5f9769
+        if (!lb->pb || !lb->iface) {
5f9769
+            goto del_seqno;
5f9769
+        }
5f9769
+
5f9769
+        if (!ofctrl_acked_seqnos_contains(acked_seqnos, node->data)) {
5f9769
+            continue;
5f9769
+        }
5f9769
+
5f9769
+        ovsrec_interface_update_external_ids_setkey(lb->iface,
5f9769
+                                                    OVN_INSTALLED_EXT_ID,
5f9769
+                                                    "true");
5f9769
+        sbrec_port_binding_set_up(lb->pb, &up, 1);
5f9769
+
5f9769
+        struct shash_node *child_node;
5f9769
+        SHASH_FOR_EACH (child_node, &lb->children) {
5f9769
+            struct local_binding *lb_child = child_node->data;
5f9769
+            sbrec_port_binding_set_up(lb_child->pb, &up, 1);
5f9769
+        }
5f9769
+
5f9769
+del_seqno:
5f9769
+        simap_delete(&binding_iface_seqno_map, node);
5f9769
+    }
5f9769
+
5f9769
+    ofctrl_acked_seqnos_destroy(acked_seqnos);
5f9769
+}
5f9769
+
5f9769
+void
5f9769
+binding_seqno_flush(void)
5f9769
+{
5f9769
+    simap_clear(&binding_iface_seqno_map);
5f9769
+}
5f9769
diff --git a/controller/binding.h b/controller/binding.h
5f9769
index 2885971..c9ebef4 100644
5f9769
--- a/controller/binding.h
5f9769
+++ b/controller/binding.h
5f9769
@@ -135,4 +135,9 @@ bool binding_handle_ovs_interface_changes(struct binding_ctx_in *,
5f9769
 bool binding_handle_port_binding_changes(struct binding_ctx_in *,
5f9769
                                          struct binding_ctx_out *);
5f9769
 void binding_tracked_dp_destroy(struct hmap *tracked_datapaths);
5f9769
+
5f9769
+void binding_init(void);
5f9769
+void binding_seqno_run(struct shash *local_bindings);
5f9769
+void binding_seqno_install(struct shash *local_bindings);
5f9769
+void binding_seqno_flush(void);
5f9769
 #endif /* controller/binding.h */
5f9769
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
5f9769
index bb1c659..5599ea4 100644
5f9769
--- a/controller/ovn-controller.c
5f9769
+++ b/controller/ovn-controller.c
5f9769
@@ -981,6 +981,7 @@ en_ofctrl_is_connected_run(struct engine_node *node, void *data)
5f9769
         /* Flush ofctrl seqno requests when the ofctrl connection goes down. */
5f9769
         if (!of_data->connected) {
5f9769
             ofctrl_seqno_flush();
5f9769
+            binding_seqno_flush();
5f9769
         }
5f9769
         engine_set_node_state(node, EN_UPDATED);
5f9769
         return;
5f9769
@@ -2404,13 +2405,14 @@ main(int argc, char *argv[])
5f9769
 
5f9769
     daemonize_complete();
5f9769
 
5f9769
+    /* Register ofctrl seqno types. */
5f9769
+    ofctrl_seq_type_nb_cfg = ofctrl_seqno_add_type();
5f9769
+
5f9769
+    binding_init();
5f9769
     patch_init();
5f9769
     pinctrl_init();
5f9769
     lflow_init();
5f9769
 
5f9769
-    /* Register ofctrl seqno types. */
5f9769
-    ofctrl_seq_type_nb_cfg = ofctrl_seqno_add_type();
5f9769
-
5f9769
     /* Connect to OVS OVSDB instance. */
5f9769
     struct ovsdb_idl_loop ovs_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
5f9769
         ovsdb_idl_create(ovs_remote, &ovsrec_idl_class, false, true));
5f9769
@@ -2879,6 +2881,9 @@ main(int argc, char *argv[])
5f9769
                                                        ovnsb_idl_loop.idl),
5f9769
                                               ovnsb_cond_seqno,
5f9769
                                               ovnsb_expected_cond_seqno));
5f9769
+                    if (runtime_data && ovs_idl_txn && ovnsb_idl_txn) {
5f9769
+                        binding_seqno_run(&runtime_data->local_bindings);
5f9769
+                    }
5f9769
 
5f9769
                     flow_output_data = engine_get_data(&en_flow_output);
5f9769
                     if (flow_output_data && ct_zones_data) {
5f9769
@@ -2889,6 +2894,9 @@ main(int argc, char *argv[])
5f9769
                                    engine_node_changed(&en_flow_output));
5f9769
                     }
5f9769
                     ofctrl_seqno_run(ofctrl_get_cur_cfg());
5f9769
+                    if (runtime_data && ovs_idl_txn && ovnsb_idl_txn) {
5f9769
+                        binding_seqno_install(&runtime_data->local_bindings);
5f9769
+                    }
5f9769
                 }
5f9769
 
5f9769
             }
5f9769
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
5f9769
index 9f8fb3b..307ee9c 100644
5f9769
--- a/northd/ovn-northd.c
5f9769
+++ b/northd/ovn-northd.c
5f9769
@@ -13049,7 +13049,7 @@ handle_port_binding_changes(struct northd_context *ctx, struct hmap *ports,
5f9769
             continue;
5f9769
         }
5f9769
 
5f9769
-        bool up = (sb->chassis || lsp_is_router(op->nbsp));
5f9769
+        bool up = ((sb->up && (*sb->up)) || lsp_is_router(op->nbsp));
5f9769
         if (!op->nbsp->up || *op->nbsp->up != up) {
5f9769
             nbrec_logical_switch_port_set_up(op->nbsp, &up, 1);
5f9769
         }
5f9769
@@ -13197,7 +13197,7 @@ static const char *rbac_encap_update[] =
5f9769
 static const char *rbac_port_binding_auth[] =
5f9769
     {""};
5f9769
 static const char *rbac_port_binding_update[] =
5f9769
-    {"chassis"};
5f9769
+    {"chassis", "up"};
5f9769
 
5f9769
 static const char *rbac_mac_binding_auth[] =
5f9769
     {""};
5f9769
@@ -13684,6 +13684,8 @@ main(int argc, char *argv[])
5f9769
     ovsdb_idl_add_column(ovnsb_idl_loop.idl,
5f9769
                          &sbrec_port_binding_col_virtual_parent);
5f9769
     ovsdb_idl_add_column(ovnsb_idl_loop.idl,
5f9769
+                         &sbrec_port_binding_col_up);
5f9769
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl,
5f9769
                          &sbrec_gateway_chassis_col_chassis);
5f9769
     ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_gateway_chassis_col_name);
5f9769
     ovsdb_idl_add_column(ovnsb_idl_loop.idl,
5f9769
diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
5f9769
index 97db6de..b418434 100644
5f9769
--- a/ovn-sb.ovsschema
5f9769
+++ b/ovn-sb.ovsschema
5f9769
@@ -1,7 +1,7 @@
5f9769
 {
5f9769
     "name": "OVN_Southbound",
5f9769
-    "version": "20.13.0",
5f9769
-    "cksum": "3035725595 25676",
5f9769
+    "version": "20.14.0",
5f9769
+    "cksum": "1412040198 25748",
5f9769
     "tables": {
5f9769
         "SB_Global": {
5f9769
             "columns": {
5f9769
@@ -225,6 +225,7 @@
5f9769
                 "nat_addresses": {"type": {"key": "string",
5f9769
                                            "min": 0,
5f9769
                                            "max": "unlimited"}},
5f9769
+                "up": {"type": {"key": "boolean", "min": 0, "max": 1}},
5f9769
                 "external_ids": {"type": {"key": "string",
5f9769
                                  "value": "string",
5f9769
                                  "min": 0,
5f9769
diff --git a/ovn-sb.xml b/ovn-sb.xml
5f9769
index eb440e4..4c82d51 100644
5f9769
--- a/ovn-sb.xml
5f9769
+++ b/ovn-sb.xml
5f9769
@@ -2771,6 +2771,14 @@ tcp.flags = RST;
5f9769
         

5f9769
       </column>
5f9769
 
5f9769
+      <column name="up">
5f9769
+        

5f9769
+          This is set to true whenever all OVS flows
5f9769
+          required by this Port_Binding have been installed.  This is
5f9769
+          populated by ovn-controller.
5f9769
+        

5f9769
+      </column>
5f9769
+
5f9769
       <column name="tunnel_key">
5f9769
         

5f9769
           A number that represents the logical port in the key (e.g. STT key or
5f9769
diff --git a/tests/ovn.at b/tests/ovn.at
5f9769
index a4fafa5..dfb94d2 100644
5f9769
--- a/tests/ovn.at
5f9769
+++ b/tests/ovn.at
5f9769
@@ -23662,3 +23662,35 @@ as ovn-nb
5f9769
 OVS_APP_EXIT_AND_WAIT([ovsdb-server])
5f9769
 
5f9769
 AT_CLEANUP
5f9769
+
5f9769
+AT_SETUP([ovn -- propagate Port_Binding.up to NB and OVS])
5f9769
+ovn_start
5f9769
+
5f9769
+net_add n1
5f9769
+sim_add hv1
5f9769
+as hv1
5f9769
+ovs-vsctl add-br br-phys
5f9769
+ovn_attach n1 br-phys 192.168.0.1
5f9769
+
5f9769
+check ovn-nbctl ls-add ls
5f9769
+
5f9769
+AS_BOX([add OVS port for existing LSP])
5f9769
+check ovn-nbctl lsp-add ls lsp1
5f9769
+check ovn-nbctl --wait=hv sync
5f9769
+check_column "[]" Port_Binding up logical_port=lsp1
5f9769
+
5f9769
+check ovs-vsctl add-port br-int lsp1 -- set Interface lsp1 external-ids:iface-id=lsp1
5f9769
+check_column "true" Port_Binding up logical_port=lsp1
5f9769
+wait_column "true" nb:Logical_Switch_Port up name=lsp1
5f9769
+OVS_WAIT_UNTIL([test `ovs-vsctl get Interface lsp1 external_ids:ovn-installed` = '"true"'])
5f9769
+
5f9769
+AS_BOX([add LSP for existing OVS port])
5f9769
+check ovs-vsctl add-port br-int lsp2 -- set Interface lsp2 external-ids:iface-id=lsp2
5f9769
+check ovn-nbctl lsp-add ls lsp2
5f9769
+check ovn-nbctl --wait=hv sync
5f9769
+check_column "true" Port_Binding up logical_port=lsp2
5f9769
+wait_column "true" nb:Logical_Switch_Port up name=lsp2
5f9769
+OVS_WAIT_UNTIL([test `ovs-vsctl get Interface lsp2 external_ids:ovn-installed` = '"true"'])
5f9769
+
5f9769
+OVN_CLEANUP([hv1])
5f9769
+AT_CLEANUP
5f9769
diff --git a/utilities/ovn-sbctl.c b/utilities/ovn-sbctl.c
5f9769
index 0a1b9ff..c38e8ec 100644
5f9769
--- a/utilities/ovn-sbctl.c
5f9769
+++ b/utilities/ovn-sbctl.c
5f9769
@@ -526,6 +526,7 @@ pre_get_info(struct ctl_context *ctx)
5f9769
     ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_tunnel_key);
5f9769
     ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_chassis);
5f9769
     ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_datapath);
5f9769
+    ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_up);
5f9769
 
5f9769
     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_logical_datapath);
5f9769
     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_logical_dp_group);
5f9769
@@ -665,6 +666,7 @@ cmd_lsp_bind(struct ctl_context *ctx)
5f9769
     struct sbctl_chassis *sbctl_ch;
5f9769
     struct sbctl_port_binding *sbctl_bd;
5f9769
     char *lport_name, *ch_name;
5f9769
+    bool up = true;
5f9769
 
5f9769
     /* port_binding must exist, chassis must exist! */
5f9769
     lport_name = ctx->argv[1];
5f9769
@@ -683,6 +685,7 @@ cmd_lsp_bind(struct ctl_context *ctx)
5f9769
         }
5f9769
     }
5f9769
     sbrec_port_binding_set_chassis(sbctl_bd->bd_cfg, sbctl_ch->ch_cfg);
5f9769
+    sbrec_port_binding_set_up(sbctl_bd->bd_cfg, &up, 1);
5f9769
     sbctl_context_invalidate_cache(ctx);
5f9769
 }
5f9769
 
5f9769
@@ -699,6 +702,7 @@ cmd_lsp_unbind(struct ctl_context *ctx)
5f9769
     sbctl_bd = find_port_binding(sbctl_ctx, lport_name, must_exist);
5f9769
     if (sbctl_bd) {
5f9769
         sbrec_port_binding_set_chassis(sbctl_bd->bd_cfg, NULL);
5f9769
+        sbrec_port_binding_set_up(sbctl_bd->bd_cfg, NULL, 0);
5f9769
     }
5f9769
 }
5f9769
 
5f9769
-- 
5f9769
1.8.3.1
5f9769