VOL-1126 OLT disable/reenable

Change-Id: Icbfad962807945e26c50e467ec079d40b346060d
diff --git a/protos/openolt.proto b/protos/openolt.proto
index bc9e953..c4d4fd0 100644
--- a/protos/openolt.proto
+++ b/protos/openolt.proto
@@ -18,6 +18,20 @@
 
 service Openolt {
 
+    rpc DisableOlt(Empty) returns (Empty) {
+        option (google.api.http) = {
+          post: "/v1/Disable"
+          body: "*"
+        };
+    }
+
+    rpc ReenableOlt(Empty) returns (Empty) {
+        option (google.api.http) = {
+          post: "/v1/Reenable"
+          body: "*"
+        };
+    }
+
     rpc ActivateOnu(Onu) returns (Empty) {
         option (google.api.http) = {
           post: "/v1/EnableOnu"
diff --git a/src/core.cc b/src/core.cc
index 33ae435..eacbf27 100644
--- a/src/core.cc
+++ b/src/core.cc
@@ -27,6 +27,7 @@
 #include "indications.h"
 #include "stats_collection.h"
 #include "error_format.h"
+#include "state.h"
 
 extern "C"
 {
@@ -35,12 +36,12 @@
 #include <bal_api_end.h>
 }
 
+
 Status Enable_() {
-    static bool enabled = false;
     bcmbal_access_terminal_cfg acc_term_obj;
     bcmbal_access_terminal_key key = { };
 
-    if (!enabled) {
+    if (!state::is_activated()) {
         std::cout << "Enable OLT" << std::endl;
         key.access_term_id = DEFAULT_ATERM_ID;
         BCMBAL_CFG_INIT(&acc_term_obj, access_terminal, key);
@@ -50,9 +51,58 @@
             std::cout << "ERROR: Failed to enable OLT" << std::endl;
             return bcm_to_grpc_err(err, "Failed to enable OLT");
         }
-        enabled = true;
     }
+    //If already enabled, generate an extra indication ????
     return Status::OK;
+
+}
+
+Status Disable_() {
+    // bcmbal_access_terminal_cfg acc_term_obj;
+    // bcmbal_access_terminal_key key = { };
+    //
+    // if (state::is_activated) {
+    //     std::cout << "Disable OLT" << std::endl;
+    //     key.access_term_id = DEFAULT_ATERM_ID;
+    //     BCMBAL_CFG_INIT(&acc_term_obj, access_terminal, key);
+    //     BCMBAL_CFG_PROP_SET(&acc_term_obj, access_terminal, admin_state, BCMBAL_STATE_DOWN);
+    //     bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(acc_term_obj.hdr));
+    //     if (err) {
+    //         std::cout << "ERROR: Failed to disable OLT" << std::endl;
+    //         return bcm_to_grpc_err(err, "Failed to disable OLT");
+    //     }
+    // }
+    // //If already disabled, generate an extra indication ????
+    // return Status::OK;
+    //This fails with Operation Not Supported, bug ???
+
+    //TEMPORARY WORK AROUND
+    Status status = DisableUplinkIf_(0);
+    if (status.ok()) {
+        state::deactivate();
+        openolt::Indication ind;
+        openolt::OltIndication* olt_ind = new openolt::OltIndication;
+        olt_ind->set_oper_state("down");
+        ind.set_allocated_olt_ind(olt_ind);
+        std::cout << "Disable OLT, add an extra indication" << std::endl;
+        oltIndQ.push(ind);
+    }
+    return status;
+
+}
+
+Status Reenable_() {
+    Status status = EnableUplinkIf_(0);
+    if (status.ok()) {
+        state::activate();
+        openolt::Indication ind;
+        openolt::OltIndication* olt_ind = new openolt::OltIndication;
+        olt_ind->set_oper_state("up");
+        ind.set_allocated_olt_ind(olt_ind);
+        std::cout << "Reenable OLT, add an extra indication" << std::endl;
+        oltIndQ.push(ind);
+    }
+    return status;
 }
 
 Status EnablePonIf_(uint32_t intf_id) {
@@ -74,6 +124,44 @@
     return Status::OK;
 }
 
+Status DisableUplinkIf_(uint32_t intf_id) {
+    bcmbal_interface_cfg interface_obj;
+    bcmbal_interface_key interface_key;
+
+    interface_key.intf_id = intf_id;
+    interface_key.intf_type = BCMBAL_INTF_TYPE_NNI;
+
+    BCMBAL_CFG_INIT(&interface_obj, interface, interface_key);
+    BCMBAL_CFG_PROP_SET(&interface_obj, interface, admin_state, BCMBAL_STATE_DOWN);
+
+    bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(interface_obj.hdr));
+    if (err) {
+        std::cout << "ERROR: Failed to disable Uplink interface: " << intf_id << std::endl;
+        return bcm_to_grpc_err(err, "Failed to disable Uplink interface");
+    }
+
+    return Status::OK;
+}
+
+Status EnableUplinkIf_(uint32_t intf_id) {
+    bcmbal_interface_cfg interface_obj;
+    bcmbal_interface_key interface_key;
+
+    interface_key.intf_id = intf_id;
+    interface_key.intf_type = BCMBAL_INTF_TYPE_NNI;
+
+    BCMBAL_CFG_INIT(&interface_obj, interface, interface_key);
+    BCMBAL_CFG_PROP_SET(&interface_obj, interface, admin_state, BCMBAL_STATE_UP);
+
+    bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(interface_obj.hdr));
+    if (err) {
+        std::cout << "ERROR: Failed to enable Uplink interface: " << intf_id << std::endl;
+        return bcm_to_grpc_err(err, "Failed to enable Uplink interface");
+    }
+
+    return Status::OK;
+}
+
 Status DisablePonIf_(uint32_t intf_id) {
     bcmbal_interface_cfg interface_obj;
     bcmbal_interface_key interface_key;
diff --git a/src/core.h b/src/core.h
index 99e8bde..182b06d 100644
--- a/src/core.h
+++ b/src/core.h
@@ -31,6 +31,8 @@
     const char *vendor_id, const char *vendor_specific);
 Status EnablePonIf_(uint32_t intf_id);
 Status DisablePonIf_(uint32_t intf_id);
+Status EnableUplinkIf_(uint32_t intf_id);
+Status DisableUplinkIf_(uint32_t intf_id);
 Status OmciMsgOut_(uint32_t intf_id, uint32_t onu_id, const std::string pkt);
 Status OnuPacketOut_(uint32_t intf_id, uint32_t onu_id, const std::string pkt);
 Status UplinkPacketOut_(uint32_t intf_id, const std::string pkt);
@@ -40,6 +42,9 @@
                 uint32_t gemport_id, uint32_t priority,
                 const ::openolt::Classifier& classifier,
                 const ::openolt::Action& action);
+Status Disable_();
+Status Reenable_();
+
 
 static Status SchedAdd_(int intf_id, int onu_id, int agg_port_id);
 static Status SchedRemove_(int intf_id, int onu_id, int agg_port_id);
diff --git a/src/server.cc b/src/server.cc
index 46b8bff..5c46332 100644
--- a/src/server.cc
+++ b/src/server.cc
@@ -45,6 +45,20 @@
 
 class OpenoltService final : public openolt::Openolt::Service {
 
+    Status DisableOlt(
+            ServerContext* context,
+            const openolt::Empty* request,
+            openolt::Empty* response) override {
+        return Disable_();
+    }
+
+    Status ReenableOlt(
+            ServerContext* context,
+            const openolt::Empty* request,
+            openolt::Empty* response) override {
+        return Reenable_();
+    }
+
     Status ActivateOnu(
             ServerContext* context,
             const openolt::Onu* request,