[VOL-3728] Support in OLT agent to send periodic onu stats and gem stats
- Add GetOnuStatistics and GetGemPortStatistics API

Change-Id: I2d796600ee6b002edbbd037ba063d1648429ffe7
diff --git a/BUILDING.md b/BUILDING.md
index fa766e4..e592a0f 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -151,7 +151,7 @@
 make OPENOLTDEVICE=asfvolt16 OPENOLT_PROTO_VER=master
 ```
 
-By default, the `OPENOLT_PROTO_VER` defaults to git tag *v4.0.3* of the
+By default, the `OPENOLT_PROTO_VER` defaults to git tag *v4.0.11* of the
 [voltha-protos](https://gerrit.opencord.org/gitweb?p=voltha-protos.git;a=summary)
 repo.
 
diff --git a/Makefile b/Makefile
index d3ecd08..ee5bda2 100644
--- a/Makefile
+++ b/Makefile
@@ -27,13 +27,13 @@
 
 ## Variables
 OPENOLTDEVICE     ?= asfvolt16
-OPENOLT_PROTO_VER ?= v4.0.3
+OPENOLT_PROTO_VER ?= v4.0.11
 
 DOCKER                     ?= docker
 DOCKER_REGISTRY            ?=
 DOCKER_REPOSITORY          ?= voltha/
 DOCKER_EXTRA_ARGS          ?=
-DOCKER_TAG                 ?= 2.1.0
+DOCKER_TAG                 ?= 2.1.1
 IMAGENAME                  = ${DOCKER_REGISTRY}${DOCKER_REPOSITORY}openolt-test:${DOCKER_TAG}
 
 DOCKER_BUILD_ARGS ?= \
diff --git a/VERSION b/VERSION
index 4772543..6e9a403 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.3.2
+3.3.3-dev
diff --git a/agent/Makefile.in b/agent/Makefile.in
index 7866c44..9a99b6b 100644
--- a/agent/Makefile.in
+++ b/agent/Makefile.in
@@ -42,7 +42,7 @@
 # This specifies the GIT tag in https://github.com/opencord/voltha-protos
 # repo that we need to refer to, to pick the right version of
 # openolt.proto and tech_profile.proto
-OPENOLT_PROTO_VER ?= v4.0.3
+OPENOLT_PROTO_VER ?= v4.0.11
 
 # Variables used for Inband build
 INBAND = "n"
diff --git a/agent/common/core.h b/agent/common/core.h
index c9c7bf1..ab4c788 100644
--- a/agent/common/core.h
+++ b/agent/common/core.h
@@ -241,6 +241,8 @@
 uint32_t GetPortNum_(uint32_t flow_id);
 Status GetLogicalOnuDistanceZero_(uint32_t intf_id, openolt::OnuLogicalDistance* response);
 Status GetLogicalOnuDistance_(uint32_t intf_id, uint32_t onu_id, openolt::OnuLogicalDistance* response);
+Status GetOnuStatistics_(uint32_t intf_id, uint32_t onu_id, openolt::OnuStatistics *onu_stats);
+Status GetGemPortStatistics_(uint32_t intf_id, uint32_t gemport_id, openolt::GemPortStatistics* gemport_stats);
 int get_status_bcm_cli_quit(void);
 uint16_t get_dev_id(void);
 Status pushOltOperInd(uint32_t intf_id, const char *type, const char *state);
diff --git a/agent/common/server.cc b/agent/common/server.cc
index 0294a34..e04a9ba 100644
--- a/agent/common/server.cc
+++ b/agent/common/server.cc
@@ -326,6 +326,26 @@
             request->onu_id(),
             response);
     };
+
+    Status GetOnuStatistics(
+            ServerContext* context,
+            const openolt::Onu* request,
+            openolt::OnuStatistics* response) override {
+        return GetOnuStatistics_(
+            request->intf_id(),
+            request->onu_id(),
+            response);
+    }
+
+    Status GetGemPortStatistics(
+            ServerContext* context,
+            const openolt::OnuPacket* request,
+            openolt::GemPortStatistics* response) override {
+        return GetGemPortStatistics_(
+            request->intf_id(),
+            request->gemport_id(),
+            response);
+    }
 };
 
 void RunServer(int argc, char** argv) {
diff --git a/agent/src/core_api_handler.cc b/agent/src/core_api_handler.cc
index d6263c4..2c5ff83 100644
--- a/agent/src/core_api_handler.cc
+++ b/agent/src/core_api_handler.cc
@@ -3181,3 +3181,31 @@
 
     return Status::OK;
 }
+
+Status GetOnuStatistics_(uint32_t intf_id, uint32_t onu_id, openolt::OnuStatistics* onu_stats) {
+    bcmos_errno err;
+
+    err = get_onu_statistics((bcmolt_interface_id)intf_id, (bcmolt_onu_id)onu_id, onu_stats);
+
+    if (err != BCM_ERR_OK) {
+        OPENOLT_LOG(ERROR, openolt_log_id, "retrieval of ONU statistics failed - PON ID = %u, ONU ID = %u, err = %d - %s", intf_id, onu_id, err, bcmos_strerror(err));
+        return grpc::Status(grpc::StatusCode::INTERNAL, "retrieval of ONU statistics failed");
+    }
+
+    OPENOLT_LOG(INFO, openolt_log_id, "retrieved ONU statistics for PON ID = %d, ONU ID = %d\n", (int)intf_id, (int)onu_id);
+    return Status::OK;
+}
+
+Status GetGemPortStatistics_(uint32_t intf_id, uint32_t gemport_id, openolt::GemPortStatistics* gemport_stats) {
+    bcmos_errno err;
+
+    err = get_gemport_statistics((bcmolt_interface_id)intf_id, (bcmolt_gem_port_id)gemport_id, gemport_stats);
+
+    if (err != BCM_ERR_OK) {
+        OPENOLT_LOG(ERROR, openolt_log_id, "retrieval of GEMPORT statistics failed - PON ID = %u, ONU ID = %u, err = %d - %s", intf_id, gemport_id, err, bcmos_strerror(err));
+        return grpc::Status(grpc::StatusCode::INTERNAL, "retrieval of GEMPORT statistics failed");
+    }
+
+    OPENOLT_LOG(INFO, openolt_log_id, "retrieved GEMPORT statistics for PON ID = %d, GEMPORT ID = %d\n", (int)intf_id, (int)gemport_id);
+    return Status::OK;
+}
diff --git a/agent/src/stats_collection.cc b/agent/src/stats_collection.cc
index 99747f4..5065f6b 100644
--- a/agent/src/stats_collection.cc
+++ b/agent/src/stats_collection.cc
@@ -83,6 +83,49 @@
     return port_stats;
 }
 
+openolt::OnuStatistics get_default_onu_statistics() {
+    openolt::OnuStatistics onu_stats;
+
+    onu_stats.set_positive_drift(-1);
+    onu_stats.set_negative_drift(-1);
+    onu_stats.set_delimiter_miss_detection(-1);
+    onu_stats.set_bip_errors(-1);
+    onu_stats.set_bip_units(-1);
+    onu_stats.set_fec_corrected_symbols(-1);
+    onu_stats.set_fec_codewords_corrected(-1);
+    onu_stats.set_fec_codewords_uncorrectable(-1);
+    onu_stats.set_fec_codewords(-1);
+    onu_stats.set_fec_corrected_units(-1);
+    onu_stats.set_xgem_key_errors(-1);
+    onu_stats.set_xgem_loss(-1);
+    onu_stats.set_rx_ploams_error(-1);
+    onu_stats.set_rx_ploams_non_idle(-1);
+    onu_stats.set_rx_omci(-1);
+    onu_stats.set_rx_omci_packets_crc_error(-1);
+    onu_stats.set_rx_bytes(-1);
+    onu_stats.set_rx_packets(-1);
+    onu_stats.set_tx_bytes(-1);
+    onu_stats.set_tx_packets(-1);
+    onu_stats.set_ber_reported(-1);
+    onu_stats.set_lcdg_errors(-1);
+    onu_stats.set_rdi_errors(-1);
+
+    return onu_stats;
+}
+
+openolt::GemPortStatistics get_default_gemport_statistics() {
+    openolt::GemPortStatistics gemport_stats;
+
+    gemport_stats.set_intf_id(-1);
+    gemport_stats.set_gemport_id(-1);
+    gemport_stats.set_rx_packets(-1);
+    gemport_stats.set_rx_bytes(-1);
+    gemport_stats.set_tx_packets(-1);
+    gemport_stats.set_tx_bytes(-1);
+
+    return gemport_stats;
+}
+
 #if 0
 openolt::FlowStatistics* get_default_flow_statistics() {
     openolt::FlowStatistics* flow_stats = new openolt::FlowStatistics;
@@ -291,6 +334,129 @@
 
 }
 
+bcmos_errno get_onu_statistics(bcmolt_interface_id intf_id, bcmolt_onu_id onu_id, openolt::OnuStatistics* onu_stats) {
+    bcmos_errno err = BCM_ERR_OK;
+
+#ifndef TEST_MODE
+    *onu_stats = get_default_onu_statistics();
+    bcmolt_stat_flags clear_on_read = BCMOLT_STAT_FLAGS_NONE;
+    bcmolt_onu_itu_pon_stats itu_onu_stats;
+
+    {
+        bcmolt_onu_key key;
+        key.pon_ni = intf_id;
+        key.onu_id = onu_id;
+        BCMOLT_STAT_INIT(&itu_onu_stats, onu, itu_pon_stats, key);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, positive_drift);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, negative_drift);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, delimiter_miss_detection);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, bip_errors);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, bip_units);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, fec_corrected_symbols);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, fec_codewords_corrected);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, fec_codewords_uncorrectable);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, fec_codewords);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, fec_corrected_units);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, xgem_key_errors);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, xgem_loss);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, rx_ploams_error);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, rx_ploams_non_idle);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, rx_omci);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, rx_omci_packets_crc_error);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, rx_bytes);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, rx_packets);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, tx_bytes);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, tx_packets);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, ber_reported);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, lcdg_errors);
+        BCMOLT_MSG_FIELD_GET(&itu_onu_stats, rdi_errors);
+
+        /* call API */
+        err = bcmolt_stat_get((bcmolt_oltid)device_id, &itu_onu_stats.hdr, clear_on_read);
+        if (err == BCM_ERR_OK) {
+            onu_stats->set_positive_drift(itu_onu_stats.data.positive_drift);
+            onu_stats->set_negative_drift(itu_onu_stats.data.negative_drift);
+            onu_stats->set_delimiter_miss_detection(itu_onu_stats.data.delimiter_miss_detection);
+            onu_stats->set_bip_errors(itu_onu_stats.data.bip_errors);
+            onu_stats->set_bip_units(itu_onu_stats.data.bip_units);
+            onu_stats->set_fec_corrected_symbols(itu_onu_stats.data.fec_corrected_symbols);
+            onu_stats->set_fec_codewords_corrected(itu_onu_stats.data.fec_codewords_corrected);
+            onu_stats->set_fec_codewords_uncorrectable(itu_onu_stats.data.fec_codewords_uncorrectable);
+            onu_stats->set_fec_codewords(itu_onu_stats.data.fec_codewords);
+            onu_stats->set_fec_corrected_units(itu_onu_stats.data.fec_corrected_units);
+            onu_stats->set_xgem_key_errors(itu_onu_stats.data.xgem_key_errors);
+            onu_stats->set_xgem_loss(itu_onu_stats.data.xgem_loss);
+            onu_stats->set_rx_ploams_error(itu_onu_stats.data.rx_ploams_error);
+            onu_stats->set_rx_ploams_non_idle(itu_onu_stats.data.rx_ploams_non_idle);
+            onu_stats->set_rx_omci(itu_onu_stats.data.rx_omci);
+            onu_stats->set_rx_omci_packets_crc_error(itu_onu_stats.data.rx_omci_packets_crc_error);
+            onu_stats->set_rx_bytes(itu_onu_stats.data.rx_bytes);
+            onu_stats->set_rx_packets(itu_onu_stats.data.rx_packets);
+            onu_stats->set_tx_bytes(itu_onu_stats.data.tx_bytes);
+            onu_stats->set_tx_packets(itu_onu_stats.data.tx_packets);
+            onu_stats->set_ber_reported(itu_onu_stats.data.ber_reported);
+            onu_stats->set_lcdg_errors(itu_onu_stats.data.lcdg_errors);
+            onu_stats->set_rdi_errors(itu_onu_stats.data.rdi_errors);
+        } else {
+            OPENOLT_LOG(ERROR, openolt_log_id,  "Failed to retrieve ONU statistics, intf_id %d, onu_id %d, err no: %d - %s\n",
+                        (int)intf_id, (int)onu_id, err, bcmos_strerror(err));
+            return err;
+        }
+    }
+
+    onu_stats->set_intf_id(intf_id);
+    onu_stats->set_onu_id(onu_id);
+    time_t now;
+    time(&now);
+    onu_stats->set_timestamp((int)now);
+#endif
+
+    return err;
+}
+
+bcmos_errno get_gemport_statistics(bcmolt_interface_id intf_id, bcmolt_gem_port_id gemport_id, openolt::GemPortStatistics* gemport_stats) {
+    bcmos_errno err = BCM_ERR_OK;
+
+#ifndef TEST_MODE
+    *gemport_stats = get_default_gemport_statistics();
+    bcmolt_stat_flags clear_on_read = BCMOLT_STAT_FLAGS_NONE;
+    bcmolt_itupon_gem_stats gem_stats;
+
+    {
+        bcmolt_itupon_gem_key key;
+        key.pon_ni = intf_id;
+        key.gem_port_id = gemport_id;
+
+        BCMOLT_STAT_INIT(&gem_stats, itupon_gem, stats, key);
+        BCMOLT_MSG_FIELD_GET(&gem_stats, rx_packets);
+        BCMOLT_MSG_FIELD_GET(&gem_stats, rx_bytes);
+        BCMOLT_MSG_FIELD_GET(&gem_stats, tx_packets);
+        BCMOLT_MSG_FIELD_GET(&gem_stats, tx_bytes);
+
+        /* call API */
+        err = bcmolt_stat_get((bcmolt_oltid)device_id, &gem_stats.hdr, clear_on_read);
+        if (err == BCM_ERR_OK) {
+            gemport_stats->set_rx_packets(gem_stats.data.rx_packets);
+            gemport_stats->set_rx_bytes(gem_stats.data.rx_bytes);
+            gemport_stats->set_tx_packets(gem_stats.data.tx_packets);
+            gemport_stats->set_tx_bytes(gem_stats.data.tx_bytes);
+        } else {
+            OPENOLT_LOG(ERROR, openolt_log_id,  "Failed to retrieve GEMPORT statistics, intf_id %d, gemport_id %d, err no: %d - %s\n",
+                        (int)intf_id, (int)gemport_id, err, bcmos_strerror(err));
+            return err;
+        }
+    }
+
+    gemport_stats->set_intf_id(intf_id);
+    gemport_stats->set_gemport_id(gemport_id);
+    time_t now;
+    time(&now);
+    gemport_stats->set_timestamp((int)now);
+#endif
+
+    return err;
+}
+
 #if 0
 openolt::FlowStatistics* collectFlowStatistics(bcmbal_flow_id flow_id, bcmbal_flow_type flow_type) {
 
diff --git a/agent/src/stats_collection.h b/agent/src/stats_collection.h
index dd5835d..9281655 100644
--- a/agent/src/stats_collection.h
+++ b/agent/src/stats_collection.h
@@ -28,6 +28,8 @@
 void stop_collecting_statistics();
 openolt::PortStatistics* get_default_port_statistics();
 openolt::PortStatistics* collectPortStatistics(bcmolt_interface_id intf_id, bcmolt_interface_type intf_type);
+bcmos_errno get_onu_statistics(bcmolt_interface_id intf_id, bcmolt_onu_id onu_id, openolt::OnuStatistics* onu_stats);
+bcmos_errno get_gemport_statistics(bcmolt_interface_id intf_id, bcmolt_gem_port_id gemport_id, openolt::GemPortStatistics* gemport_stats);
 #if 0
 openolt::FlowStatistics* get_default_flow_statistics();
 openolt::FlowStatistics* collectFlowStatistics(bcmbal_flow_id flow_id, bcmbal_flow_type flow_type);
diff --git a/agent/test/Makefile b/agent/test/Makefile
index 25c7ce0..66986e3 100644
--- a/agent/test/Makefile
+++ b/agent/test/Makefile
@@ -21,7 +21,7 @@
 TOP_DIR=`pwd`
 OPENOLTDEVICE ?= asfvolt16
 
-OPENOLT_PROTO_VER ?= v4.0.3
+OPENOLT_PROTO_VER ?= v4.0.11
 
 ########################################################################
 ##
@@ -30,7 +30,7 @@
 ##
 ##
 
-CXX = g++
+CXX = g++-4.9
 CXXFLAGS += -g -O2
 CXXFLAGS += `pkg-config --cflags-only-I grpc++` -I/usr/local/include/pcapplusplus/
 CPPFLAGS += `pkg-config --cflags protobuf grpc`
diff --git a/protos/Makefile b/protos/Makefile
index 0cf8a72..2494a08 100644
--- a/protos/Makefile
+++ b/protos/Makefile
@@ -19,7 +19,7 @@
 # This specifies the GIT tag in https://github.com/opencord/voltha-protos
 # repo that we need to refer to, to pick the right version of
 # openolt.proto, ext_config.proto and tech_profile.proto
-OPENOLT_PROTO_VER ?= v4.0.3
+OPENOLT_PROTO_VER ?= v4.0.11
 
 CXX ?= g++
 CPPFLAGS += `pkg-config --cflags protobuf grpc` -I googleapis/gens -I./