blob: 515eb32db43e2f83edce43292204ac8145d789e5 [file] [log] [blame]
/*
Copyright (C) 2018 Open Networking Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stats_collection.h"
#include <unistd.h>
#include <openolt.grpc.pb.h>
#include "indications.h"
#include "core.h"
#include "translation.h"
extern "C"
{
#include <bcmos_system.h>
#include <bcmolt_api.h>
#include <bcmolt_api_model_api_structs.h>
}
//FIXME
#define FLOWS_COUNT 100
bcmolt_flow_key* flows_keys = new bcmolt_flow_key[FLOWS_COUNT];
bcmolt_odid device_id = 0;
void init_stats() {
memset(flows_keys, 0, FLOWS_COUNT * sizeof(bcmolt_flow_key));
}
openolt::PortStatistics* get_default_port_statistics() {
openolt::PortStatistics* port_stats = new openolt::PortStatistics;
port_stats->set_intf_id(-1);
port_stats->set_rx_bytes(-1);
port_stats->set_rx_packets(-1);
port_stats->set_rx_ucast_packets(-1);
port_stats->set_rx_mcast_packets(-1);
port_stats->set_rx_bcast_packets(-1);
port_stats->set_rx_error_packets(-1);
port_stats->set_tx_bytes(-1);
port_stats->set_tx_packets(-1);
port_stats->set_tx_ucast_packets(-1);
port_stats->set_tx_mcast_packets(-1);
port_stats->set_tx_bcast_packets(-1);
port_stats->set_tx_error_packets(-1);
port_stats->set_rx_crc_errors(-1);
port_stats->set_bip_errors(-1);
return port_stats;
}
#if 0
openolt::FlowStatistics* get_default_flow_statistics() {
openolt::FlowStatistics* flow_stats = new openolt::FlowStatistics;
flow_stats->set_flow_id(-1);
flow_stats->set_rx_bytes(-1);
flow_stats->set_rx_packets(-1);
flow_stats->set_tx_bytes(-1);
flow_stats->set_tx_packets(-1);
return flow_stats;
}
#endif
openolt::PortStatistics* collectPortStatistics(bcmolt_intf_ref intf_ref) {
bcmos_errno err;
bcmolt_stat_flags clear_on_read = BCMOLT_STAT_FLAGS_NONE;
bcmolt_nni_interface_stats nni_stats;
bcmolt_onu_itu_pon_stats pon_stats;
bcmolt_pon_interface_itu_pon_stats itu_pon_stats;
openolt::PortStatistics* port_stats = get_default_port_statistics();
switch (intf_ref.intf_type) {
case BCMOLT_INTERFACE_TYPE_NNI:
{
bcmolt_nni_interface_key nni_intf_key;
nni_intf_key.id = intf_ref.intf_id;
/* init the API struct */
BCMOLT_STAT_INIT(&nni_stats, nni_interface, stats, nni_intf_key);
BCMOLT_MSG_FIELD_GET(&nni_stats, rx_bytes);
BCMOLT_MSG_FIELD_GET(&nni_stats, rx_packets);
BCMOLT_MSG_FIELD_GET(&nni_stats, rx_ucast_packets);
BCMOLT_MSG_FIELD_GET(&nni_stats, rx_mcast_packets);
BCMOLT_MSG_FIELD_GET(&nni_stats, rx_bcast_packets);
BCMOLT_MSG_FIELD_GET(&nni_stats, rx_error_packets);
BCMOLT_MSG_FIELD_GET(&nni_stats, tx_bytes);
BCMOLT_MSG_FIELD_GET(&nni_stats, tx_packets);
BCMOLT_MSG_FIELD_GET(&nni_stats, tx_ucast_packets);
BCMOLT_MSG_FIELD_GET(&nni_stats, tx_mcast_packets);
BCMOLT_MSG_FIELD_GET(&nni_stats, tx_bcast_packets);
BCMOLT_MSG_FIELD_GET(&nni_stats, tx_error_packets);
/* call API */
err = bcmolt_stat_get((bcmolt_oltid)device_id, &nni_stats.hdr, clear_on_read);
if (err == BCM_ERR_OK)
{
//std::cout << "Interface statistics retrieved"
// << " intf_id:" << intf_id << std::endl;
port_stats->set_rx_bytes(nni_stats.data.rx_bytes);
port_stats->set_rx_packets(nni_stats.data.rx_packets);
port_stats->set_rx_ucast_packets(nni_stats.data.rx_ucast_packets);
port_stats->set_rx_mcast_packets(nni_stats.data.rx_mcast_packets);
port_stats->set_rx_bcast_packets(nni_stats.data.rx_bcast_packets);
port_stats->set_rx_error_packets(nni_stats.data.rx_error_packets);
port_stats->set_tx_bytes(nni_stats.data.tx_bytes);
port_stats->set_tx_packets(nni_stats.data.tx_packets);
port_stats->set_tx_ucast_packets(nni_stats.data.tx_ucast_packets);
port_stats->set_tx_mcast_packets(nni_stats.data.tx_mcast_packets);
port_stats->set_tx_bcast_packets(nni_stats.data.tx_bcast_packets);
port_stats->set_tx_error_packets(nni_stats.data.tx_error_packets);
} else {
BCM_LOG(ERROR, openolt_log_id, "Failed to retrieve port statistics, intf_id %d, intf_type %d\n",
(int)intf_ref.intf_id, (int)intf_ref.intf_type);
}
break;
}
case BCMOLT_INTERFACE_TYPE_PON:
{
bcmolt_pon_interface_key key;
key.pon_ni = (bcmolt_interface)intf_ref.intf_id;
BCMOLT_STAT_INIT(&itu_pon_stats, pon_interface, itu_pon_stats, key);
BCMOLT_MSG_FIELD_GET(&itu_pon_stats, tx_packets);
BCMOLT_MSG_FIELD_GET(&itu_pon_stats, bip_errors);
BCMOLT_MSG_FIELD_GET(&itu_pon_stats, rx_crc_error);
/* call API */
err = bcmolt_stat_get((bcmolt_oltid)device_id, &itu_pon_stats.hdr, clear_on_read);
if (err == BCM_ERR_OK) {
port_stats->set_tx_packets(itu_pon_stats.data.tx_packets);
port_stats->set_bip_errors(itu_pon_stats.data.bip_errors);
port_stats->set_rx_crc_errors(itu_pon_stats.data.rx_crc_error);
} else {
BCM_LOG(ERROR, openolt_log_id, "Failed to retrieve port statistics, intf_id %d, intf_type %d\n",
(int)intf_ref.intf_id, (int)intf_ref.intf_type);
}
{
bcmolt_onu_key key;
key.pon_ni = (bcmolt_interface)intf_ref.intf_id;
BCMOLT_STAT_INIT(&pon_stats, onu, itu_pon_stats, key);
BCMOLT_MSG_FIELD_GET(&pon_stats, rx_bytes);
BCMOLT_MSG_FIELD_GET(&pon_stats, rx_packets);
BCMOLT_MSG_FIELD_GET(&pon_stats, tx_bytes);
/* call API */
err = bcmolt_stat_get((bcmolt_oltid)device_id, &pon_stats.hdr, clear_on_read);
if (err == BCM_ERR_OK) {
port_stats->set_rx_bytes(pon_stats.data.rx_bytes);
port_stats->set_rx_packets(pon_stats.data.rx_packets);
port_stats->set_tx_bytes(pon_stats.data.tx_bytes);
} else {
BCM_LOG(ERROR, openolt_log_id, "Failed to retrieve port statistics, intf_id %d, intf_type %d\n",
(int)intf_ref.intf_id, (int)intf_ref.intf_type);
}
}
break;
}
}
port_stats->set_intf_id(interface_key_to_port_no((bcmolt_interface_id)intf_ref.intf_id, (bcmolt_interface_type)intf_ref.intf_type));
time_t now;
time(&now);
port_stats->set_timestamp((int)now);
return port_stats;
}
#if 0
openolt::FlowStatistics* collectFlowStatistics(bcmbal_flow_id flow_id, bcmbal_flow_type flow_type) {
bcmos_errno err;
bcmbal_flow_stat stat; /**< declare main API struct */
bcmbal_flow_key key = { }; /**< declare key */
bcmos_bool clear_on_read = false;
openolt::FlowStatistics* flow_stats = get_default_flow_statistics();
//Key
key.flow_id = flow_id;
key.flow_type = flow_type;
/* init the API struct */
BCMBAL_STAT_INIT(&stat, flow, key);
BCMBAL_STAT_PROP_GET(&stat, flow, all_properties);
err = bcmbal_stat_get(DEFAULT_ATERM_ID, &stat.hdr, clear_on_read);
if (err == BCM_ERR_OK)
{
std::cout << "Flow statistics retrieved"
<< " flow_id:" << flow_id
<< " flow_type:" << flow_type << std::endl;
flow_stats->set_rx_bytes(stat.data.rx_bytes);
flow_stats->set_rx_packets(stat.data.rx_packets);
flow_stats->set_tx_bytes(stat.data.tx_bytes);
flow_stats->set_tx_packets(stat.data.tx_packets);
} else {
std::cout << "ERROR: Failed to retrieve flow statistics"
<< " flow_id:" << flow_id
<< " flow_type:" << flow_type << std::endl;
}
return flow_stats;
}
#endif
void stats_collection() {
if (!state.is_connected()) {
BCM_LOG(INFO, openolt_log_id, "Voltha is not connected, do not collect stats\n");
return;
}
if (!state.is_activated()) {
BCM_LOG(INFO, openolt_log_id, "The OLT is not up, do not collect stats\n");
return;
}
BCM_LOG(DEBUG, openolt_log_id, "Collecting statistics\n");
//Ports statistics
//Uplink ports
for (int i = 0; i < NumNniIf_(); i++) {
bcmolt_intf_ref intf_ref;
intf_ref.intf_type = BCMOLT_INTERFACE_TYPE_NNI;
intf_ref.intf_id = i;
openolt::PortStatistics* port_stats =
collectPortStatistics(intf_ref);
openolt::Indication ind;
ind.set_allocated_port_stats(port_stats);
oltIndQ.push(ind);
}
//Pon ports
for (int i = 0; i < NumPonIf_(); i++) {
bcmolt_intf_ref intf_ref;
intf_ref.intf_type = BCMOLT_INTERFACE_TYPE_PON;
intf_ref.intf_id = i;
openolt::PortStatistics* port_stats =
collectPortStatistics(intf_ref);
openolt::Indication ind;
ind.set_allocated_port_stats(port_stats);
oltIndQ.push(ind);
}
//Flows statistics
// flow_inst *current_entry = NULL;
//
// TAILQ_FOREACH(current_entry,
// &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
// flow_inst_next) {
// int flows_measurements = 0;
//
// for (int i = 0; i < FLOWS_COUNT; i++) {
//
// // bcmbal_flow_id flow_id = current_entry->api_req_flow_info.key.flow_id;
// // bcmbal_flow_type flow_type = current_entry->api_req_flow_info.key.flow_type;
//
// if (flows_keys[i].flow_id != 0) {
// openolt::FlowStatistics* flow_stats = collectFlowStatistics(flows_keys[i].flow_id, flows_keys[i].flow_type);
// if (flow_stats->rx_packets() == -1) {
// //It Failed
// flows_keys[i].flow_id = 0;
// } else {
// flow_stats->set_flow_id(flows_keys[i].flow_id);
// time(&now);
// flow_stats->set_timestamp((int)now);
// openolt::Indication ind;
// ind.set_allocated_flow_stats(flow_stats);
// oltIndQ.push(ind);
// flows_measurements ++;
// }
// }
//
// }
// std::cout << "Stats of " << flows_measurements << " flows retrieved" << std::endl;
}
/* Storing flow keys, temporary */
// void register_new_flow(bcmbal_flow_key key) {
// for (int i = 0; i < FLOWS_COUNT; i++) {
// if (flows_keys[i].flow_id == 0) {
// flows_keys[i] = key;
// break;
// }
// }
// }