VOL-2502: Update README.md for openolt agent after BAL3.2.3.2 migration
VOL-2503: Provides test target for openolt-agent for Jenkins CI Integration
VOL-2504: Reorganize openolt-agent core.cc file
Change-Id: Id22fb881fcb9cc19d1f2ba044716731157d3a64e
diff --git a/agent/Makefile.in b/agent/Makefile.in
index ad6d605..514dd3c 100644
--- a/agent/Makefile.in
+++ b/agent/Makefile.in
@@ -47,11 +47,19 @@
#
# Build directory
BUILD_DIR = build
+
+# Protobuf installation
+PROTOBUF_VER = 3.5.0
+PROTOBUF_ADDR = https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOBUF_VER)/protobuf-cpp-$(PROTOBUF_VER).tar.gz
+PROTOBUF_DST = /tmp/protobuf-$(PROTOBUF_VER)
+protoc-bin = $(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)/bin/protoc
+
#
# GRPC installation
GRPC_ADDR = https://github.com/grpc/grpc
GRPC_DST = /tmp/grpc
GRPC_VER = v1.10.x
+grpc-cpp-plugin-bin = $(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)/bin/grpc_cpp_plugin
USER := $(shell echo $(USER))
#
@@ -82,7 +90,7 @@
CPPFLAGS += `pkg-config --cflags protobuf grpc`
CPPFLAGS += -DVERSION=\"$(VERSION)\" -DBAL_VER=\"$(BAL_VER)\" -DLABEL_VCS_URL=\"$(LABEL_VCS_URL)\" \
-DLABEL_VCS_REF=\"$(LABEL_VCS_REF)\" -DLABEL_BUILD_DATE=\"$(LABEL_BUILD_DATE)\" \
- -DLABEL_COMMIT_DATE=\"$(LABEL_COMMIT_DATE)\"
+ -DLABEL_COMMIT_DATE=\"$(LABEL_COMMIT_DATE)\" -DFLOW_CHECKER
CXXFLAGS += -std=c++11 -fpermissive -Wno-literal-suffix
LDFLAGS += @LDFLAGS@
LDFLAGS += `pkg-config --libs protobuf grpc++ grpc` -ldl -lgpr
@@ -90,21 +98,31 @@
export CXX CXXFLAGS OPENOLT_PROTO_VER
-prereq:
+prereqs-system:
sudo apt-get -q -y install git pkg-config build-essential autoconf libtool libgflags-dev libgtest-dev clang libc++-dev unzip docker.io
sudo apt-get install -y build-essential autoconf libssl-dev gawk debhelper dh-systemd init-system-helpers curl cmake ccache g++-4.9
- # Install GRPC, libprotobuf and protoc
+prereqs-local: $(protoc-bin) $(grpc-cpp-plugin-bin)
+
+$(protoc-bin):
+ # Install protobuf
+ rm -rf $(PROTOBUF_DST)
+ cd /tmp && wget $(PROTOBUF_ADDR)
+ cd /tmp && tar -zxvf protobuf-cpp-$(PROTOBUF_VER).tar.gz
+ cd $(PROTOBUF_DST) && ./autogen.sh
+ mkdir -p $(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)
+ cd $(PROTOBUF_DST) && ./configure --prefix=$(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)
+ make -C $(PROTOBUF_DST)
+ make -C $(PROTOBUF_DST) install
+
+$(grpc-cpp-plugin-bin):
+ # Install GRPC, protoc
rm -rf $(GRPC_DST)
- git clone -b $(GRPC_VER) $(GRPC_ADDR) $(GRPC_DST)
+ cd /tmp && git clone -b $(GRPC_VER) $(GRPC_ADDR) $(GRPC_DST)
cd $(GRPC_DST) && git submodule update --init
- cd $(GRPC_DST)/third_party/protobuf && ./autogen.sh && ./configure
- make -C $(GRPC_DST)/third_party/protobuf
- sudo make -C $(GRPC_DST)/third_party/protobuf install
- sudo ldconfig
+ mkdir -p $(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)
make -C $(GRPC_DST)
- sudo make -C $(GRPC_DST) install
- sudo ldconfig
+ make -C $(GRPC_DST) install prefix=$(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)
docker:
echo $(USER)
@@ -328,4 +346,4 @@
distclean: clean-src clean
@rm -rf $(BUILD_DIR)
-.PHONY: onl sdk bal protos prereq sim .FORCE
+.PHONY: onl sdk bal protos prereqs-system prereqs-local sim .FORCE
diff --git a/agent/common/core.h b/agent/common/core.h
index dedc4c3..f73051e 100644
--- a/agent/common/core.h
+++ b/agent/common/core.h
@@ -23,6 +23,27 @@
#include "state.h"
+extern "C"
+{
+#include <bcmolt_api.h>
+#include <bcmolt_api_model_supporting_enums.h>
+
+#include <bcmolt_api_conn_mgr.h>
+//CLI header files
+#include <bcmcli_session.h>
+#include <bcmcli.h>
+#include <bcm_api_cli.h>
+
+#include <bcmos_common.h>
+#include <bcm_config.h>
+// FIXME : dependency problem
+// #include <bcm_common_gpon.h>
+// #include <bcm_dev_log_task.h>
+}
+// ************************//
+// Macros used by the core //
+// ************************//
+
#define NONE "\033[m"
#define LIGHT_RED "\033[1;31m"
#define BROWN "\033[0;33m"
@@ -38,83 +59,144 @@
BCM_LOG(level, id, "%s" fmt "%s", LIGHT_GREEN, ##__VA_ARGS__, NONE); \
else \
BCM_LOG(INFO, id, fmt, ##__VA_ARGS__);
+
+
+#define ACL_LOG(level,msg,err) \
+ do { \
+ OPENOLT_LOG(level, openolt_log_id, "--------> %s (acl_id %d) err: %d <--------\n", msg, key.id, err); \
+ OPENOLT_LOG(level, openolt_log_id, "action_type %s\n", \
+ GET_ACL_ACTION_TYPE(action_type)); \
+ OPENOLT_LOG(level, openolt_log_id, "classifier(ether type %d), ip_proto %d, src_port %d, dst_port %d\n", \
+ acl_key.ether_type, acl_key.ip_proto, acl_key.src_port, acl_key.dst_port); \
+ } while(0)
+
+#define FLOW_LOG(level,msg,err) \
+ do { \
+ OPENOLT_LOG(level, openolt_log_id, "--------> %s (flow_id %d) err: %d <--------\n", msg, key.flow_id, err); \
+ OPENOLT_LOG(level, openolt_log_id, "intf_id %d, onu_id %d, uni_id %d, port_no %u, cookie %"PRIu64"\n", \
+ access_intf_id, onu_id, uni_id, port_no, cookie); \
+ OPENOLT_LOG(level, openolt_log_id, "flow_type %s, queue_id %d, sched_id %d\n", flow_type.c_str(), \
+ cfg.data.egress_qos.u.fixed_queue.queue_id, cfg.data.egress_qos.tm_sched.id); \
+ OPENOLT_LOG(level, openolt_log_id, "Ingress(intfd_type %s, intf_id %d), Egress(intf_type %s, intf_id %d)\n", \
+ GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), cfg.data.ingress_intf.intf_id, \
+ GET_FLOW_INTERFACE_TYPE(cfg.data.egress_intf.intf_type), cfg.data.egress_intf.intf_id); \
+ OPENOLT_LOG(level, openolt_log_id, "classifier(o_vid %d, o_pbits %d, i_vid %d, i_pbits %d, ether type 0x%x)\n", \
+ c_val.o_vid, c_val.o_pbits, c_val.i_vid, c_val.i_pbits, classifier.eth_type()); \
+ OPENOLT_LOG(level, openolt_log_id, "classifier(ip_proto 0x%x, gemport_id %d, src_port %d, dst_port %d, pkt_tag_type %s)\n", \
+ c_val.ip_proto, gemport_id, c_val.src_port, c_val.dst_port, GET_PKT_TAG_TYPE(c_val.pkt_tag_type)); \
+ OPENOLT_LOG(level, openolt_log_id, "action(cmds_bitmask %s, o_vid %d, o_pbits %d, i_vid %d, i_pbits %d)\n\n", \
+ get_flow_acton_command(a_val.cmds_bitmask), a_val.o_vid, a_val.o_pbits, a_val.i_vid, a_val.i_pbits); \
+ } while(0)
+
+#define FLOW_PARAM_LOG() \
+ do { \
+ OPENOLT_LOG(INFO, openolt_log_id, "--------> flow comparison (now before) <--------\n"); \
+ OPENOLT_LOG(INFO, openolt_log_id, "flow_id (%d %d)\n", \
+ key.flow_id, it->first.first); \
+ OPENOLT_LOG(INFO, openolt_log_id, "onu_id (%d %lu)\n", \
+ cfg.data.onu_id , get_flow_status(it->first.first, it->first.second, ONU_ID)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "type (%d %lu)\n", \
+ key.flow_type, get_flow_status(it->first.first, it->first.second, FLOW_TYPE)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "svc_port_id (%d %lu)\n", \
+ cfg.data.svc_port_id, get_flow_status(it->first.first, it->first.second, SVC_PORT_ID)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "priority (%d %lu)\n", \
+ cfg.data.priority, get_flow_status(it->first.first, it->first.second, PRIORITY)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "cookie (%lu %lu)\n", \
+ cfg.data.cookie, get_flow_status(it->first.first, it->first.second, COOKIE)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "ingress intf_type (%s %s)\n", \
+ GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), \
+ GET_FLOW_INTERFACE_TYPE(get_flow_status(it->first.first, it->first.second, INGRESS_INTF_TYPE))); \
+ OPENOLT_LOG(INFO, openolt_log_id, "ingress intf id (%d %lu)\n", \
+ cfg.data.ingress_intf.intf_id , get_flow_status(it->first.first, it->first.second, INGRESS_INTF_ID)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "egress intf_type (%d %lu)\n", \
+ cfg.data.egress_intf.intf_type , get_flow_status(it->first.first, it->first.second, EGRESS_INTF_TYPE)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "egress intf_id (%d %lu)\n", \
+ cfg.data.egress_intf.intf_id , get_flow_status(it->first.first, it->first.second, EGRESS_INTF_ID)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "classifier o_vid (%d %lu)\n", \
+ c_val.o_vid , get_flow_status(it->first.first, it->first.second, CLASSIFIER_O_VID)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "classifier o_pbits (%d %lu)\n", \
+ c_val.o_pbits , get_flow_status(it->first.first, it->first.second, CLASSIFIER_O_PBITS)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "classifier i_vid (%d %lu)\n", \
+ c_val.i_vid , get_flow_status(it->first.first, it->first.second, CLASSIFIER_I_VID)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "classifier i_pbits (%d %lu)\n", \
+ c_val.i_pbits , get_flow_status(it->first.first, it->first.second, CLASSIFIER_I_PBITS)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "classifier ether_type (0x%x 0x%lx)\n", \
+ c_val.ether_type , get_flow_status(it->first.first, it->first.second, CLASSIFIER_ETHER_TYPE)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "classifier ip_proto (%d %lu)\n", \
+ c_val.ip_proto , get_flow_status(it->first.first, it->first.second, CLASSIFIER_IP_PROTO)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "classifier src_port (%d %lu)\n", \
+ c_val.src_port , get_flow_status(it->first.first, it->first.second, CLASSIFIER_SRC_PORT)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "classifier dst_port (%d %lu)\n", \
+ c_val.dst_port , get_flow_status(it->first.first, it->first.second, CLASSIFIER_DST_PORT)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "classifier pkt_tag_type (%s %s)\n", \
+ GET_PKT_TAG_TYPE(c_val.pkt_tag_type), \
+ GET_PKT_TAG_TYPE(get_flow_status(it->first.first, it->first.second, CLASSIFIER_PKT_TAG_TYPE))); \
+ OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos type (%d %lu)\n", \
+ cfg.data.egress_qos.type , get_flow_status(it->first.first, it->first.second, EGRESS_QOS_TYPE)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos queue_id (%d %lu)\n", \
+ cfg.data.egress_qos.u.fixed_queue.queue_id, \
+ get_flow_status(it->first.first, it->first.second, EGRESS_QOS_QUEUE_ID)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos sched_id (%d %lu)\n", \
+ cfg.data.egress_qos.tm_sched.id, \
+ get_flow_status(it->first.first, it->first.second, EGRESS_QOS_TM_SCHED_ID)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "classifier cmds_bitmask (%s %s)\n", \
+ get_flow_acton_command(a_val.cmds_bitmask), \
+ get_flow_acton_command(get_flow_status(it->first.first, it->first.second, ACTION_CMDS_BITMASK))); \
+ OPENOLT_LOG(INFO, openolt_log_id, "action o_vid (%d %lu)\n", \
+ a_val.o_vid , get_flow_status(it->first.first, it->first.second, ACTION_O_VID)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "action i_vid (%d %lu)\n", \
+ a_val.i_vid , get_flow_status(it->first.first, it->first.second, ACTION_I_VID)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "action o_pbits (%d %lu)\n", \
+ a_val.o_pbits , get_flow_status(it->first.first, it->first.second, ACTION_O_PBITS)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "action i_pbits (%d %lu)\n\n", \
+ a_val.i_pbits, get_flow_status(it->first.first, it->first.second, ACTION_I_PBITS)); \
+ OPENOLT_LOG(INFO, openolt_log_id, "group_id (%d %lu)\n\n", \
+ a_val.group_id, get_flow_status(it->first.first, it->first.second, GROUP_ID)); \
+ } while(0)
+
#define COLLECTION_PERIOD 15 // in seconds
#define BAL_DYNAMIC_LIST_BUFFER_SIZE (32 * 1024)
#define MAX_REGID_LENGTH 36
+#define BAL_RSC_MANAGER_BASE_TM_SCHED_ID 16384
+#define MAX_TM_QMP_ID 16
+#define TMQ_MAP_PROFILE_SIZE 8
+#define MAX_TM_SCHED_ID 1023
+#define MAX_SUBS_TM_SCHED_ID (MAX_SUPPORTED_PON == 16 ? MAX_TM_SCHED_ID-4-16 : MAX_TM_SCHED_ID-10-64)
+#define EAP_ETHER_TYPE 34958
+#define XGS_BANDWIDTH_GRANULARITY 16000
+#define GPON_BANDWIDTH_GRANULARITY 32000
+#define NUM_OF_PRIORITIES 8
+#define NUMBER_OF_DEFAULT_INTERFACE_QUEUES 4 // <= NUM_OF_PRIORITIES
+#define FILL_ARRAY(ARRAY,START,END,VALUE) for(int i=START;i<END;ARRAY[i++]=VALUE);
+#define COUNT_OF(array) (sizeof(array) / sizeof(array[0]))
+
+#define GET_FLOW_INTERFACE_TYPE(type) \
+ (type == BCMOLT_FLOW_INTERFACE_TYPE_PON) ? "PON" : \
+ (type == BCMOLT_FLOW_INTERFACE_TYPE_NNI) ? "NNI" : \
+ (type == BCMOLT_FLOW_INTERFACE_TYPE_HOST) ? "HOST" : "unknown"
+#define GET_PKT_TAG_TYPE(type) \
+ (type == BCMOLT_PKT_TAG_TYPE_UNTAGGED) ? "UNTAG" : \
+ (type == BCMOLT_PKT_TAG_TYPE_SINGLE_TAG) ? "SINGLE_TAG" : \
+ (type == BCMOLT_PKT_TAG_TYPE_DOUBLE_TAG) ? "DOUBLE_TAG" : "unknown"
+#define GET_ACL_ACTION_TYPE(type) \
+ (type == BCMOLT_ACCESS_CONTROL_FWD_ACTION_TYPE_TRAP_TO_HOST) ? "trap_to_host" : \
+ (type == BCMOLT_ACCESS_CONTROL_FWD_ACTION_TYPE_DROP) ? "drop" : \
+ (type == BCMOLT_ACCESS_CONTROL_FWD_ACTION_TYPE_REDIRECT) ? "redirction" : "unknown"
+#define GET_ACL_MEMBERS_UPDATE_COMMAND(command) \
+ (command == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD) ? "add" : \
+ (command == BCMOLT_MEMBERS_UPDATE_COMMAND_REMOVE) ? "remove" : \
+ (command == BCMOLT_MEMBERS_UPDATE_COMMAND_SET) ? "set" : "unknown"
+#define GET_INTERFACE_TYPE(type) \
+ (type == BCMOLT_INTERFACE_TYPE_PON) ? "PON" : \
+ (type == BCMOLT_INTERFACE_TYPE_NNI) ? "NNI" : \
+ (type == BCMOLT_INTERFACE_TYPE_HOST) ? "HOST" : "unknown"
+
extern State state;
-enum FLOW_CFG {
- ONU_ID = 0,
- FLOW_TYPE = 1,
- SVC_PORT_ID = 2,
- PRIORITY = 3,
- COOKIE = 4,
- INGRESS_INTF_TYPE= 5,
- EGRESS_INTF_TYPE= 6,
- INGRESS_INTF_ID = 7,
- EGRESS_INTF_ID = 8,
- CLASSIFIER_O_VID = 9,
- CLASSIFIER_O_PBITS = 10,
- CLASSIFIER_I_VID = 11,
- CLASSIFIER_I_PBITS = 12,
- CLASSIFIER_ETHER_TYPE = 13,
- CLASSIFIER_IP_PROTO =14,
- CLASSIFIER_SRC_PORT = 15,
- CLASSIFIER_DST_PORT = 16,
- CLASSIFIER_PKT_TAG_TYPE = 17,
- EGRESS_QOS_TYPE = 18,
- EGRESS_QOS_QUEUE_ID = 19,
- EGRESS_QOS_TM_SCHED_ID = 20,
- ACTION_CMDS_BITMASK = 21,
- ACTION_O_VID = 22,
- ACTION_O_PBITS = 23,
- ACTION_I_VID = 24,
- ACTION_I_PBITS = 25,
- STATE = 26,
- GROUP_ID = 27
-};
-
-enum AllocCfgAction {
- ALLOC_OBJECT_CREATE,
- ALLOC_OBJECT_DELETE
-};
-
-enum AllocObjectState {
- ALLOC_OBJECT_STATE_NOT_CONFIGURED,
- ALLOC_OBJECT_STATE_INACTIVE,
- ALLOC_OBJECT_STATE_PROCESSING,
- ALLOC_OBJECT_STATE_ACTIVE
-};
-
-enum AllocCfgStatus {
- ALLOC_CFG_STATUS_SUCCESS,
- ALLOC_CFG_STATUS_FAIL
-};
-
-typedef struct {
- uint32_t pon_intf_id;
- uint32_t alloc_id;
- AllocObjectState state;
- AllocCfgStatus status;
-} alloc_cfg_complete_result;
-
-// key for map used for tracking ITU PON Alloc Configuration results from BAL
-typedef std::tuple<uint32_t, uint32_t> alloc_cfg_compltd_key;
-
-// The elements in this acl_classifier_key structure constitute key to
-// acl_classifier_to_acl_id_map.
-// Fill invalid values in the acl_classifier_key structure to -1.
-typedef struct acl_classifier_key {
- int32_t ether_type;
- int16_t ip_proto;
- int32_t src_port;
- int32_t dst_port;
- // Add more classifiers elements as needed here
- // For now, ACLs will be classified only based on
- // above elements.
-} acl_classifier_key;
-
+//***************************************//
+// Function declations used by the core. //
+//***************************************//
Status Enable_(int argc, char *argv[]);
Status ActivateOnu_(uint32_t intf_id, uint32_t onu_id,
const char *vendor_id, const char *vendor_specific, uint32_t pir);
@@ -156,4 +238,16 @@
void stats_collection();
Status check_connection();
Status check_bal_ready();
+
+// Stubbed defntions of bcmolt_cfg_get required for unit-test
+#ifdef TEST_MODE
+extern bcmos_errno bcmolt_cfg_get__bal_state_stub(bcmolt_oltid olt_id, void* ptr);
+extern bcmos_errno bcmolt_cfg_get__onu_state_stub(bcmolt_oltid olt_id, void* ptr);
+extern bcmos_errno bcmolt_cfg_get__tm_sched_stub(bcmolt_oltid olt_id, void* ptr);
+extern bcmos_errno bcmolt_cfg_get__pon_intf_stub(bcmolt_oltid olt_id, void* ptr);
+extern bcmos_errno bcmolt_cfg_get__nni_intf_stub(bcmolt_oltid olt_id, void* ptr);
+extern bcmos_errno bcmolt_cfg_get__olt_topology_stub(bcmolt_oltid olt_id, void* ptr);
+extern bcmos_errno bcmolt_cfg_get__flow_stub(bcmolt_oltid olt_id, void* ptr);
+#endif //TEST_MODE
+
#endif
diff --git a/agent/configure b/agent/configure
index 7c41265..f861fd7 100755
--- a/agent/configure
+++ b/agent/configure
@@ -574,8 +574,6 @@
LIBOBJS=
cross_compiling=no
subdirs=
-MFLAGS=
-MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='openolt'
diff --git a/agent/src/core.cc b/agent/src/core_api_handler.cc
similarity index 65%
rename from agent/src/core.cc
rename to agent/src/core_api_handler.cc
index 0337bed..24e956d 100644
--- a/agent/src/core.cc
+++ b/agent/src/core_api_handler.cc
@@ -31,11 +31,12 @@
#include "device.h"
#include "core.h"
+#include "core_data.h"
#include "indications.h"
#include "stats_collection.h"
#include "error_format.h"
#include "state.h"
-#include "utils.h"
+#include "core_utils.h"
extern "C"
{
@@ -56,171 +57,13 @@
// #include <bcm_dev_log_task.h>
}
-dev_log_id openolt_log_id = bcm_dev_log_id_register("OPENOLT", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
-dev_log_id omci_log_id = bcm_dev_log_id_register("OMCI", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
-
-#define BAL_RSC_MANAGER_BASE_TM_SCHED_ID 16384
-#define MAX_TM_QMP_ID 16
-#define TMQ_MAP_PROFILE_SIZE 8
-#define MAX_TM_SCHED_ID 1023
-#define MAX_SUBS_TM_SCHED_ID (MAX_SUPPORTED_PON == 16 ? MAX_TM_SCHED_ID-4-16 : MAX_TM_SCHED_ID-10-64)
-#define EAP_ETHER_TYPE 34958
-#define XGS_BANDWIDTH_GRANULARITY 16000
-#define GPON_BANDWIDTH_GRANULARITY 32000
-#define NUM_OF_PRIORITIES 8
-#define NUMBER_OF_DEFAULT_INTERFACE_QUEUES 4 // <= NUM_OF_PRIORITIES
-#define FILL_ARRAY(ARRAY,START,END,VALUE) for(int i=START;i<END;ARRAY[i++]=VALUE);
-#define COUNT_OF(array) (sizeof(array) / sizeof(array[0]))
-
-#define GET_FLOW_INTERFACE_TYPE(type) \
- (type == BCMOLT_FLOW_INTERFACE_TYPE_PON) ? "PON" : \
- (type == BCMOLT_FLOW_INTERFACE_TYPE_NNI) ? "NNI" : \
- (type == BCMOLT_FLOW_INTERFACE_TYPE_HOST) ? "HOST" : "unknown"
-#define GET_PKT_TAG_TYPE(type) \
- (type == BCMOLT_PKT_TAG_TYPE_UNTAGGED) ? "UNTAG" : \
- (type == BCMOLT_PKT_TAG_TYPE_SINGLE_TAG) ? "SINGLE_TAG" : \
- (type == BCMOLT_PKT_TAG_TYPE_DOUBLE_TAG) ? "DOUBLE_TAG" : "unknown"
-#define GET_ACL_ACTION_TYPE(type) \
- (type == BCMOLT_ACCESS_CONTROL_FWD_ACTION_TYPE_TRAP_TO_HOST) ? "trap_to_host" : \
- (type == BCMOLT_ACCESS_CONTROL_FWD_ACTION_TYPE_DROP) ? "drop" : \
- (type == BCMOLT_ACCESS_CONTROL_FWD_ACTION_TYPE_REDIRECT) ? "redirction" : "unknown"
-#define GET_ACL_MEMBERS_UPDATE_COMMAND(command) \
- (command == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD) ? "add" : \
- (command == BCMOLT_MEMBERS_UPDATE_COMMAND_REMOVE) ? "remove" : \
- (command == BCMOLT_MEMBERS_UPDATE_COMMAND_SET) ? "set" : "unknown"
-#define GET_INTERFACE_TYPE(type) \
- (type == BCMOLT_INTERFACE_TYPE_PON) ? "PON" : \
- (type == BCMOLT_INTERFACE_TYPE_NNI) ? "NNI" : \
- (type == BCMOLT_INTERFACE_TYPE_HOST) ? "HOST" : "unknown"
-
-static unsigned int num_of_nni_ports = 0;
-static unsigned int num_of_pon_ports = 0;
static std::string intf_technologies[MAX_SUPPORTED_PON];
static const std::string UNKNOWN_TECH("unknown");
static const std::string MIXED_TECH("mixed");
static std::string board_technology(UNKNOWN_TECH);
static std::string chip_family(UNKNOWN_TECH);
-static unsigned int OPENOLT_FIELD_LEN = 200;
static std::string firmware_version = "Openolt.2019.07.01";
-const uint32_t tm_upstream_sched_id_start = (MAX_SUPPORTED_PON == 16 ? \
- MAX_TM_SCHED_ID-3 : MAX_TM_SCHED_ID-9);
-const uint32_t tm_downstream_sched_id_start = (MAX_SUPPORTED_PON == 16 ? \
- tm_upstream_sched_id_start-16 : tm_upstream_sched_id_start-64);
-
-/* Max Queue ID supported is 7 so based on priority_q configured for GEMPORTS
-in TECH PROFILE respective Queue ID from this list will be used for both
-US and DS Queues*/
-const uint32_t queue_id_list[8] = {0, 1, 2, 3, 4, 5, 6, 7};
-
-const std::string upstream = "upstream";
-const std::string downstream = "downstream";
-const std::string multicast = "multicast";
-bcmolt_oltid dev_id = 0;
-
-/* Constants used for retrying some BAL APIs */
-const uint32_t BAL_API_RETRY_TIME_IN_USECS = 1000000;
-const uint32_t MAX_BAL_API_RETRY_COUNT = 5;
-
-/* Current session */
-static bcmcli_session *current_session;
-static bcmcli_entry *api_parent_dir;
-bcmos_bool status_bcm_cli_quit = BCMOS_FALSE;
-bcmos_task bal_cli_thread;
-const char *bal_cli_thread_name = "bal_cli_thread";
-uint16_t flow_id_counters = 0;
-State state;
-
-static std::map<uint32_t, uint32_t> flowid_to_port; // For mapping upstream flows to logical ports
-static std::map<uint32_t, uint32_t> flowid_to_gemport; // For mapping downstream flows into gemports
-static std::map<uint32_t, std::set<uint32_t> > port_to_flows; // For mapping logical ports to downstream flows
-
-/* This represents the Key to 'sched_map' map.
- Represents (pon_intf_id, onu_id, uni_id, direction) */
-typedef std::tuple<uint32_t, uint32_t, uint32_t, std::string> sched_map_key_tuple;
-/* 'sched_map' maps sched_map_key_tuple to DBA (Upstream) or
- Subscriber (Downstream) Scheduler ID */
-static std::map<sched_map_key_tuple, int> sched_map;
-
-/* Flow control is for flow_id and flow_type */
-typedef std::pair<uint16_t, uint16_t> flow_pair;
-static std::map<flow_pair, int32_t> flow_map;
-
-/* This represents the Key to 'qos_type_map' map.
- Represents (pon_intf_id, onu_id, uni_id) */
-typedef std::tuple<uint32_t, uint32_t, uint32_t> qos_type_map_key_tuple;
-/* 'qos_type_map' maps qos_type_map_key_tuple to qos_type*/
-static std::map<qos_type_map_key_tuple, bcmolt_egress_qos_type> qos_type_map;
-
-/* This represents the Key to 'sched_qmp_id_map' map.
-Represents (sched_id, pon_intf_id, onu_id, uni_id) */
-typedef std::tuple<uint32_t, uint32_t, uint32_t, uint32_t> sched_qmp_id_map_key_tuple;
-/* 'sched_qmp_id_map' maps sched_qmp_id_map_key_tuple to TM Queue Mapping Profile ID */
-static std::map<sched_qmp_id_map_key_tuple, int> sched_qmp_id_map;
-/* 'qmp_id_to_qmp_map' maps TM Queue Mapping Profile ID to TM Queue Mapping Profile */
-static std::map<int, std::vector < uint32_t > > qmp_id_to_qmp_map;
-
-// Flag used to watch whether mocked alloc_cfg_compltd_key is added to alloc_cfg_compltd_map
-#ifdef TEST_MODE
-bool ALLOC_CFG_FLAG = false;
-#endif
-
-#define ALLOC_CFG_COMPLETE_WAIT_TIMEOUT 1000 // in milli-seconds
-// Map used to track response from BAL for ITU PON Alloc Configuration.
-// The key is alloc_cfg_compltd_key and value is a concurrent thread-safe queue which is
-// used for pushing (from BAL) and popping (at application) the results.
-std::map<alloc_cfg_compltd_key, Queue<alloc_cfg_complete_result> *> alloc_cfg_compltd_map;
-// Lock to protect critical section data structure used for handling AllocObject configuration response.
-bcmos_fastlock alloc_cfg_wait_lock;
-
-
-/*** ACL Handling related data start ***/
-
-static std::map<acl_classifier_key, uint16_t> acl_classifier_to_acl_id_map;
-
-bool operator<(const acl_classifier_key& a1, const acl_classifier_key& a2)
-{
- return ((a1.ether_type + 2*a1.ip_proto + 3*a1.src_port + 4*a1.dst_port) <
- (a2.ether_type + 2*a2.ip_proto + 3*a2.src_port + 4*a2.dst_port));
-}
-
-typedef std::tuple<uint16_t, std::string> flow_id_flow_direction;
-typedef std::tuple<int16_t, uint16_t, int32_t> acl_id_gem_id_intf_id;
-static std::map<flow_id_flow_direction, acl_id_gem_id_intf_id> flow_to_acl_map;
-
-// Keeps a reference count of how many flows are referencing a given ACL ID.
-// Key represents the ACL-ID and value is number of flows referencing the given ACL-ID.
-// When there is at least one flow referencing the ACL-ID, the ACL should be installed.
-// When there are no flows referencing the ACL-ID, the ACL should be removed.
-static std::map<uint16_t, uint16_t> acl_ref_cnt;
-
-typedef std::tuple<uint16_t, uint16_t> gem_id_intf_id; // key to gem_ref_cnt
-// Keeps a reference count of how many ACL related flows are referencing a given (gem-id, pon_intf_id).
-// When there is at least on flow, we should install the gem. When there are no flows
-// the gem should be removed.
-static std::map<gem_id_intf_id, uint16_t> gem_ref_cnt;
-
-// Needed to keep track of how many flows for a given acl_id, intf_id and intf_type are
-// installed. When there is at least on flow for this key, we should have interface registered
-// for the given ACL-ID. When there are no flows, the intf should unregister itself from
-// the ACL-ID.
-typedef std::tuple<uint16_t, uint8_t, std::string> acl_id_intf_id_intf_type;
-static std::map<acl_id_intf_id_intf_type, uint16_t> intf_acl_registration_ref_cnt;
-
-#define MAX_ACL_ID 33
-std::bitset<MAX_ACL_ID> acl_id_bitset;
-
-/*** ACL Handling related data end ***/
-
-std::bitset<MAX_TM_SCHED_ID> tm_sched_bitset;
-std::bitset<MAX_TM_QMP_ID> tm_qmp_bitset;
-
-static bcmos_fastlock data_lock;
-
-
-#define MIN_ALLOC_ID_GPON 256
-#define MIN_ALLOC_ID_XGSPON 1024
-
static bcmos_errno CreateSched(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, \
uint32_t port_no, uint32_t alloc_id, tech_profile::AdditionalBW additional_bw, uint32_t weight, \
uint32_t priority, tech_profile::SchedulingPolicy sched_policy,
@@ -233,441 +76,6 @@
static bcmos_errno CreateDefaultSched(uint32_t intf_id, const std::string direction);
static bcmos_errno CreateDefaultQueue(uint32_t intf_id, const std::string direction);
-uint16_t get_dev_id(void) {
- return dev_id;
-}
-
-// Stubbed defntions of bcmolt_cfg_get required for unit-test
-#ifdef TEST_MODE
-extern bcmos_errno bcmolt_cfg_get__bal_state_stub(bcmolt_oltid olt_id, void* ptr);
-extern bcmos_errno bcmolt_cfg_get__onu_state_stub(bcmolt_oltid olt_id, void* ptr);
-extern bcmos_errno bcmolt_cfg_get__tm_sched_stub(bcmolt_oltid olt_id, void* ptr);
-extern bcmos_errno bcmolt_cfg_get__pon_intf_stub(bcmolt_oltid olt_id, void* ptr);
-extern bcmos_errno bcmolt_cfg_get__nni_intf_stub(bcmolt_oltid olt_id, void* ptr);
-extern bcmos_errno bcmolt_cfg_get__olt_topology_stub(bcmolt_oltid olt_id, void* ptr);
-extern bcmos_errno bcmolt_cfg_get__flow_stub(bcmolt_oltid olt_id, void* ptr);
-#endif
-/**
-* Returns the default NNI (Upstream direction) or PON (Downstream direction) scheduler
-* Every NNI port and PON port have default scheduler.
-* The NNI0 default scheduler ID is 18432, and NNI1 is 18433 and so on.
-* Similarly, PON0 default scheduler ID is 16384. PON1 is 16385 and so on.
-*
-* @param intf_id NNI or PON interface ID
-* @param direction "upstream" or "downstream"
-*
-* @return default scheduler ID for the given interface.
-*/
-static inline int get_default_tm_sched_id(int intf_id, std::string direction) {
- if (direction.compare(upstream) == 0) {
- return tm_upstream_sched_id_start + intf_id;
- } else if (direction.compare(downstream) == 0) {
- return tm_downstream_sched_id_start + intf_id;
- }
- else {
- OPENOLT_LOG(ERROR, openolt_log_id, "invalid direction - %s\n", direction.c_str());
- return 0;
- }
-}
-
-/**
-* Gets a unique tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
-* The tm_sched_id is locally cached in a map, so that it can rendered when necessary.
-* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
-*
-* @param intf_id NNI or PON intf ID
-* @param onu_id ONU ID
-* @param uni_id UNI ID
-* @param gemport_id GEM Port ID
-* @param direction Upstream or downstream
-*
-* @return tm_sched_id
-*/
-uint32_t get_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
- sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
- int sched_id = -1;
-
- std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
- if (it != sched_map.end()) {
- sched_id = it->second;
- }
- if (sched_id != -1) {
- return sched_id;
- }
-
- bcmos_fastlock_lock(&data_lock);
- // Complexity of O(n). Is there better way that can avoid linear search?
- for (sched_id = 0; sched_id < MAX_TM_SCHED_ID; sched_id++) {
- if (tm_sched_bitset[sched_id] == 0) {
- tm_sched_bitset[sched_id] = 1;
- break;
- }
- }
- bcmos_fastlock_unlock(&data_lock, 0);
-
- if (sched_id < MAX_TM_SCHED_ID) {
- bcmos_fastlock_lock(&data_lock);
- sched_map[key] = sched_id;
- bcmos_fastlock_unlock(&data_lock, 0);
- return sched_id;
- } else {
- return -1;
- }
-}
-
-/**
-* Free tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
-*
-* @param intf_id NNI or PON intf ID
-* @param onu_id ONU ID
-* @param uni_id UNI ID
-* @param gemport_id GEM Port ID
-* @param direction Upstream or downstream
-*/
-void free_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
- sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
- std::map<sched_map_key_tuple, int>::const_iterator it;
- bcmos_fastlock_lock(&data_lock);
- it = sched_map.find(key);
- if (it != sched_map.end()) {
- tm_sched_bitset[it->second] = 0;
- sched_map.erase(it);
- }
- bcmos_fastlock_unlock(&data_lock, 0);
-}
-
-bool is_tm_sched_id_present(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
- sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
- std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
- if (it != sched_map.end()) {
- return true;
- }
- return false;
-}
-
-/**
-* Check whether given two tm qmp profiles are equal or not
-*
-* @param tmq_map_profileA <vector> TM QUEUE MAPPING PROFILE
-* @param tmq_map_profileB <vector> TM QUEUE MAPPING PROFILE
-*
-* @return boolean, true if given tmq_map_profiles are equal else false
-*/
-
-bool check_tm_qmp_equality(std::vector<uint32_t> tmq_map_profileA, std::vector<uint32_t> tmq_map_profileB) {
- for (uint32_t i = 0; i < TMQ_MAP_PROFILE_SIZE; i++) {
- if (tmq_map_profileA[i] != tmq_map_profileB[i]) {
- return false;
- }
- }
- return true;
-}
-
-/**
-* Modifies given queues_pbit_map to parsable format
-* e.g: Modifes "0b00000101" to "10100000"
-*
-* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
-* @param size Queue count
-*
-* @return string queues_pbit_map
-*/
-std::string* get_valid_queues_pbit_map(std::string *queues_pbit_map, uint32_t size) {
- for(uint32_t i=0; i < size; i++) {
- /* Deletes 2 characters from index number 0 */
- queues_pbit_map[i].erase(0, 2);
- std::reverse(queues_pbit_map[i].begin(), queues_pbit_map[i].end());
- }
- return queues_pbit_map;
-}
-
-/**
-* Creates TM QUEUE MAPPING PROFILE for given queues_pbit_map and queues_priority_q
-*
-* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
-* @param queues_priority_q PRIORITY_Q configured for each GEM in TECH PROFILE
-* @param size Queue count
-*
-* @return <vector> TM QUEUE MAPPING PROFILE
-*/
-std::vector<uint32_t> get_tmq_map_profile(std::string *queues_pbit_map, uint32_t *queues_priority_q, uint32_t size) {
- std::vector<uint32_t> tmq_map_profile(8,0);
-
- for(uint32_t i=0; i < size; i++) {
- for (uint32_t j = 0; j < queues_pbit_map[i].size(); j++) {
- if (queues_pbit_map[i][j]=='1') {
- tmq_map_profile.at(j) = queue_id_list[queues_priority_q[i]];
- }
- }
- }
- return tmq_map_profile;
-}
-
-/**
-* Gets corresponding tm_qmp_id for a given tmq_map_profile
-*
-* @param <vector> TM QUEUE MAPPING PROFILE
-*
-* @return tm_qmp_id
-*/
-int get_tm_qmp_id(std::vector<uint32_t> tmq_map_profile) {
- int tm_qmp_id = -1;
-
- std::map<int, std::vector < uint32_t > >::const_iterator it = qmp_id_to_qmp_map.begin();
- while(it != qmp_id_to_qmp_map.end()) {
- if(check_tm_qmp_equality(tmq_map_profile, it->second)) {
- tm_qmp_id = it->first;
- break;
- }
- it++;
- }
- return tm_qmp_id;
-}
-
-/**
-* Updates sched_qmp_id_map with given sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id
-*
-* @param upstream/downstream sched_id
-* @param PON intf ID
-* @param onu_id ONU ID
-* @param uni_id UNI ID
-* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
-*/
-void update_sched_qmp_id_map(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
- uint32_t uni_id, int tm_qmp_id) {
- bcmos_fastlock_lock(&data_lock);
- sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
- sched_qmp_id_map.insert(make_pair(key, tm_qmp_id));
- bcmos_fastlock_unlock(&data_lock, 0);
-}
-
-/**
-* Gets corresponding tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
-*
-* @param upstream/downstream sched_id
-* @param PON intf ID
-* @param onu_id ONU ID
-* @param uni_id UNI ID
-*
-* @return tm_qmp_id
-*/
-int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id) {
- sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
- int tm_qmp_id = -1;
-
- std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
- if (it != sched_qmp_id_map.end()) {
- tm_qmp_id = it->second;
- }
- return tm_qmp_id;
-}
-
-/**
-* Gets a unique tm_qmp_id for a given tmq_map_profile
-* The tm_qmp_id is locally cached in a map, so that it can be rendered when necessary.
-* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
-*
-* @param upstream/downstream sched_id
-* @param PON intf ID
-* @param onu_id ONU ID
-* @param uni_id UNI ID
-* @param <vector> TM QUEUE MAPPING PROFILE
-*
-* @return tm_qmp_id
-*/
-int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id, \
- std::vector<uint32_t> tmq_map_profile) {
- int tm_qmp_id;
-
- bcmos_fastlock_lock(&data_lock);
- /* Complexity of O(n). Is there better way that can avoid linear search? */
- for (tm_qmp_id = 0; tm_qmp_id < MAX_TM_QMP_ID; tm_qmp_id++) {
- if (tm_qmp_bitset[tm_qmp_id] == 0) {
- tm_qmp_bitset[tm_qmp_id] = 1;
- break;
- }
- }
- bcmos_fastlock_unlock(&data_lock, 0);
-
- if (tm_qmp_id < MAX_TM_QMP_ID) {
- bcmos_fastlock_lock(&data_lock);
- qmp_id_to_qmp_map.insert(make_pair(tm_qmp_id, tmq_map_profile));
- bcmos_fastlock_unlock(&data_lock, 0);
- update_sched_qmp_id_map(sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id);
- return tm_qmp_id;
- } else {
- return -1;
- }
-}
-
-/**
-* Free tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
-*
-* @param upstream/downstream sched_id
-* @param PON intf ID
-* @param onu_id ONU ID
-* @param uni_id UNI ID
-* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
-*
-* @return boolean, true if no more reference for TM QMP else false
-*/
-bool free_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
- uint32_t uni_id, int tm_qmp_id) {
- bool result;
- sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
- std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
- bcmos_fastlock_lock(&data_lock);
- if (it != sched_qmp_id_map.end()) {
- sched_qmp_id_map.erase(it);
- }
- bcmos_fastlock_unlock(&data_lock, 0);
-
- uint32_t tm_qmp_ref_count = 0;
- std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it2 = sched_qmp_id_map.begin();
- while(it2 != sched_qmp_id_map.end()) {
- if(it2->second == tm_qmp_id) {
- tm_qmp_ref_count++;
- }
- it2++;
- }
-
- if (tm_qmp_ref_count == 0) {
- std::map<int, std::vector < uint32_t > >::const_iterator it3 = qmp_id_to_qmp_map.find(tm_qmp_id);
- if (it3 != qmp_id_to_qmp_map.end()) {
- bcmos_fastlock_lock(&data_lock);
- tm_qmp_bitset[tm_qmp_id] = 0;
- qmp_id_to_qmp_map.erase(it3);
- bcmos_fastlock_unlock(&data_lock, 0);
- OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So clearing it\n", \
- tm_qmp_id, tm_qmp_ref_count);
- result = true;
- }
- } else {
- OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So not clearing it\n", \
- tm_qmp_id, tm_qmp_ref_count);
- result = false;
- }
- return result;
-}
-
-// Gets free ACL ID if available, else -1
-int get_acl_id() {
- int acl_id;
- bcmos_fastlock_lock(&data_lock);
- /* Complexity of O(n). Is there better way that can avoid linear search? */
- for (acl_id = 0; acl_id < MAX_ACL_ID; acl_id++) {
- if (acl_id_bitset[acl_id] == 0) {
- acl_id_bitset[acl_id] = 1;
- break;
- }
- }
- bcmos_fastlock_unlock(&data_lock, 0);
- if (acl_id < MAX_ACL_ID) {
- return acl_id ;
- } else {
- return -1;
- }
-}
-
-// Frees up the ACL ID.
-void free_acl_id (int acl_id) {
- if (acl_id < MAX_ACL_ID) {
- bcmos_fastlock_lock(&data_lock);
- acl_id_bitset[acl_id] = 0;
- bcmos_fastlock_unlock(&data_lock, 0);
- }
-}
-
-/**
-* Returns qos type as string
-*
-* @param qos_type bcmolt_egress_qos_type enum
-*/
-std::string get_qos_type_as_string(bcmolt_egress_qos_type qos_type) {
- switch (qos_type)
- {
- case BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE: return "FIXED_QUEUE";
- case BCMOLT_EGRESS_QOS_TYPE_TC_TO_QUEUE: return "TC_TO_QUEUE";
- case BCMOLT_EGRESS_QOS_TYPE_PBIT_TO_TC: return "PBIT_TO_TC";
- case BCMOLT_EGRESS_QOS_TYPE_NONE: return "NONE";
- case BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE: return "PRIORITY_TO_QUEUE";
- default: OPENOLT_LOG(ERROR, openolt_log_id, "qos-type-not-supported %d\n", qos_type);
- return "qos-type-not-supported";
- }
-}
-
-/**
-* Gets/Updates qos type for given pon_intf_id, onu_id, uni_id
-*
-* @param PON intf ID
-* @param onu_id ONU ID
-* @param uni_id UNI ID
-* @param queue_size TrafficQueues Size
-*
-* @return qos_type
-*/
-bcmolt_egress_qos_type get_qos_type(uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t queue_size = 0) {
- qos_type_map_key_tuple key(pon_intf_id, onu_id, uni_id);
- bcmolt_egress_qos_type egress_qos_type = BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
- std::string qos_string;
-
- std::map<qos_type_map_key_tuple, bcmolt_egress_qos_type>::const_iterator it = qos_type_map.find(key);
- if (it != qos_type_map.end()) {
- egress_qos_type = it->second;
- qos_string = get_qos_type_as_string(egress_qos_type);
- OPENOLT_LOG(INFO, openolt_log_id, "Qos-type for subscriber connected to pon_intf_id %d, onu_id %d and uni_id %d is %s\n", \
- pon_intf_id, onu_id, uni_id, qos_string.c_str());
- }
- else {
- /* QOS Type has been pre-defined as Fixed Queue but it will be updated based on number of GEMPORTS
- associated for a given subscriber. If GEM count = 1 for a given subscriber, qos_type will be Fixed Queue
- else Priority to Queue */
- egress_qos_type = (queue_size > 1) ? \
- BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
- bcmos_fastlock_lock(&data_lock);
- qos_type_map.insert(make_pair(key, egress_qos_type));
- bcmos_fastlock_unlock(&data_lock, 0);
- qos_string = get_qos_type_as_string(egress_qos_type);
- OPENOLT_LOG(INFO, openolt_log_id, "Qos-type for subscriber connected to pon_intf_id %d, onu_id %d and uni_id %d is %s\n", \
- pon_intf_id, onu_id, uni_id, qos_string.c_str());
- }
- return egress_qos_type;
-}
-
-/**
-* Clears qos type for given pon_intf_id, onu_id, uni_id
-*
-* @param PON intf ID
-* @param onu_id ONU ID
-* @param uni_id UNI ID
-*/
-void clear_qos_type(uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id) {
- qos_type_map_key_tuple key(pon_intf_id, onu_id, uni_id);
- std::map<qos_type_map_key_tuple, bcmolt_egress_qos_type>::const_iterator it = qos_type_map.find(key);
- bcmos_fastlock_lock(&data_lock);
- if (it != qos_type_map.end()) {
- qos_type_map.erase(it);
- OPENOLT_LOG(INFO, openolt_log_id, "Cleared Qos-type for subscriber connected to pon_intf_id %d, onu_id %d and uni_id %d\n", \
- pon_intf_id, onu_id, uni_id);
- }
- bcmos_fastlock_unlock(&data_lock, 0);
-}
-
-/**
-* Returns Scheduler/Queue direction as string
-*
-* @param direction as specified in tech_profile.proto
-*/
-std::string GetDirection(int direction) {
- switch (direction)
- {
- case tech_profile::Direction::UPSTREAM: return upstream;
- case tech_profile::Direction::DOWNSTREAM: return downstream;
- default: OPENOLT_LOG(ERROR, openolt_log_id, "direction-not-supported %d\n", direction);
- return "direction-not-supported";
- }
-}
-
inline const char *get_flow_acton_command(uint32_t command) {
char actions[200] = { };
char *s_actions_ptr = actions;
@@ -682,95 +90,6 @@
return s_actions_ptr;
}
-// This method handles waiting for AllocObject configuration.
-// Returns error if the AllocObject is not in the appropriate state based on action requested.
-bcmos_errno wait_for_alloc_action(uint32_t intf_id, uint32_t alloc_id, AllocCfgAction action) {
- Queue<alloc_cfg_complete_result> cfg_result;
- alloc_cfg_compltd_key k(intf_id, alloc_id);
- alloc_cfg_compltd_map[k] = &cfg_result;
- bcmos_errno err = BCM_ERR_OK;
- #ifdef TEST_MODE
- ALLOC_CFG_FLAG = true;
- #endif
-
- // Try to pop the result from BAL with a timeout of ALLOC_CFG_COMPLETE_WAIT_TIMEOUT ms
- std::pair<alloc_cfg_complete_result, bool> result = cfg_result.pop(ALLOC_CFG_COMPLETE_WAIT_TIMEOUT);
- if (result.second == false) {
- OPENOLT_LOG(ERROR, openolt_log_id, "timeout waiting for alloc cfg complete indication intf_id %d, alloc_id %d\n",
- intf_id, alloc_id);
- // Invalidate the queue pointer.
- bcmos_fastlock_lock(&alloc_cfg_wait_lock);
- alloc_cfg_compltd_map[k] = NULL;
- bcmos_fastlock_unlock(&alloc_cfg_wait_lock, 0);
- err = BCM_ERR_INTERNAL;
- #ifdef TEST_MODE
- ALLOC_CFG_FLAG = false;
- #endif
- }
- else if (result.first.status == ALLOC_CFG_STATUS_FAIL) {
- OPENOLT_LOG(ERROR, openolt_log_id, "error processing alloc cfg request intf_id %d, alloc_id %d\n",
- intf_id, alloc_id);
- err = BCM_ERR_INTERNAL;
- }
-
- if (err == BCM_ERR_OK) {
- if (action == ALLOC_OBJECT_CREATE) {
- if (result.first.state != ALLOC_OBJECT_STATE_ACTIVE) {
- OPENOLT_LOG(ERROR, openolt_log_id, "alloc object not in active state intf_id %d, alloc_id %d alloc_obj_state %d\n",
- intf_id, alloc_id, result.first.state);
- err = BCM_ERR_INTERNAL;
- } else {
- OPENOLT_LOG(INFO, openolt_log_id, "Create upstream bandwidth allocation success, intf_id %d, alloc_id %d\n",
- intf_id, alloc_id);
- }
- } else { // ALLOC_OBJECT_DELETE
- if (result.first.state != ALLOC_OBJECT_STATE_NOT_CONFIGURED) {
- OPENOLT_LOG(ERROR, openolt_log_id, "alloc object is not reset intf_id %d, alloc_id %d alloc_obj_state %d\n",
- intf_id, alloc_id, result.first.state);
- err = BCM_ERR_INTERNAL;
- } else {
- OPENOLT_LOG(INFO, openolt_log_id, "Remove alloc object success, intf_id %d, alloc_id %d\n",
- intf_id, alloc_id);
- }
- }
- }
-
- // Remove entry from map
- bcmos_fastlock_lock(&alloc_cfg_wait_lock);
- alloc_cfg_compltd_map.erase(k);
- bcmos_fastlock_unlock(&alloc_cfg_wait_lock, 0);
- #ifdef TEST_MODE
- ALLOC_CFG_FLAG = false;
- #endif
- return err;
-}
-
-char* openolt_read_sysinfo(const char* field_name, char* field_val)
-{
- FILE *fp;
- /* Prepare the command*/
- char command[150];
-
- snprintf(command, sizeof command, "bash -l -c \"onlpdump -s\" | perl -ne 'print $1 if /%s: (\\S+)/'", field_name);
- /* Open the command for reading. */
- fp = popen(command, "r");
- if (fp == NULL) {
- /*The client has to check for a Null field value in this case*/
- OPENOLT_LOG(INFO, openolt_log_id, "Failed to query the %s\n", field_name);
- return field_val;
- }
-
- /*Read the field value*/
- if (fp) {
- uint8_t ret;
- ret = fread(field_val, OPENOLT_FIELD_LEN, 1, fp);
- if (ret >= OPENOLT_FIELD_LEN)
- OPENOLT_LOG(INFO, openolt_log_id, "Read data length %u\n", ret);
- pclose(fp);
- }
- return field_val;
-}
-
Status GetDeviceInfo_(openolt::DeviceInfo* device_info) {
device_info->set_vendor(VENDOR_ID);
device_info->set_model(MODEL_ID);
@@ -894,104 +213,6 @@
return Status::OK;
}
-Status pushOltOperInd(uint32_t intf_id, const char *type, const char *state)
-{
- openolt::Indication ind;
- openolt::IntfOperIndication* intf_oper_ind = new openolt::IntfOperIndication;
-
- intf_oper_ind->set_type(type);
- intf_oper_ind->set_intf_id(intf_id);
- intf_oper_ind->set_oper_state(state);
- ind.set_allocated_intf_oper_ind(intf_oper_ind);
- oltIndQ.push(ind);
- return Status::OK;
-}
-
-#define CLI_HOST_PROMPT_FORMAT "BCM.%u> "
-
-/* Build CLI prompt */
-static void openolt_cli_get_prompt_cb(bcmcli_session *session, char *buf, uint32_t max_len)
-{
- snprintf(buf, max_len, CLI_HOST_PROMPT_FORMAT, dev_id);
-}
-
-static int _bal_apiend_cli_thread_handler(long data)
-{
- char init_string[]="\n";
- bcmcli_session *sess = current_session;
- bcmos_task_parm bal_cli_task_p_dummy;
-
- /* Switch to interactive mode if not stopped in the init script */
- if (!bcmcli_is_stopped(sess)) {
- /* Force a CLI command prompt
- * The string passed into the parse function
- * must be modifiable, so a string constant like
- * bcmcli_parse(current_session, "\n") will not
- * work.
- */
- bcmcli_parse(sess, init_string);
-
- /* Process user input until EOF or quit command */
- bcmcli_driver(sess);
- }
- OPENOLT_LOG(INFO, openolt_log_id, "BAL API End CLI terminated\n");
-
- /* Cleanup */
- bcmcli_session_close(current_session);
- bcmcli_token_destroy(NULL);
- return 0;
-}
-
-/* Init API CLI commands for the current device */
-bcmos_errno bcm_openolt_api_cli_init(bcmcli_entry *parent_dir, bcmcli_session *session)
-{
- bcmos_errno rc;
-
- api_parent_dir = parent_dir;
-
- rc = bcm_api_cli_set_commands(session);
-
-#ifdef BCM_SUBSYSTEM_HOST
- /* Subscribe for device change indication */
- rc = rc ? rc : bcmolt_olt_sel_ind_register(_api_cli_olt_change_ind);
-#endif
-
- return rc;
-}
-
-static bcmos_errno bcm_cli_quit(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
-{
- bcmcli_stop(session);
- bcmcli_session_print(session, "CLI terminated by 'Quit' command\n");
- status_bcm_cli_quit = BCMOS_TRUE;
-
- return BCM_ERR_OK;
-}
-
-int get_status_bcm_cli_quit(void) {
- return status_bcm_cli_quit;
-}
-
-bcmos_errno bcmolt_apiend_cli_init() {
- bcmos_errno ret;
- bcmos_task_parm bal_cli_task_p = {};
- bcmos_task_parm bal_cli_task_p_dummy;
-
- /** before creating the task, check if it is already created by the other half of BAL i.e. Core side */
- if (BCM_ERR_OK != bcmos_task_query(&bal_cli_thread, &bal_cli_task_p_dummy)) {
- /* Create BAL CLI thread */
- bal_cli_task_p.name = bal_cli_thread_name;
- bal_cli_task_p.handler = _bal_apiend_cli_thread_handler;
- bal_cli_task_p.priority = TASK_PRIORITY_CLI;
-
- ret = bcmos_task_create(&bal_cli_thread, &bal_cli_task_p);
- if (BCM_ERR_OK != ret) {
- bcmos_printf("Couldn't create BAL API end CLI thread\n");
- return ret;
- }
- }
-}
-
Status Enable_(int argc, char *argv[]) {
bcmos_errno err;
bcmolt_host_init_parms init_parms = {};
@@ -1162,29 +383,6 @@
return grpc::Status(grpc::StatusCode::UNKNOWN, "failed to re-enable olt ,few PON ports are still in disabled state");
}
-bcmos_errno get_pon_interface_status(bcmolt_interface pon_ni, bcmolt_interface_state *state) {
- bcmos_errno err;
- bcmolt_pon_interface_key pon_key;
- bcmolt_pon_interface_cfg pon_cfg;
- pon_key.pon_ni = pon_ni;
-
- BCMOLT_CFG_INIT(&pon_cfg, pon_interface, pon_key);
- BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, state);
- BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, itu);
- #ifdef TEST_MODE
- // It is impossible to mock the setting of pon_cfg.data.state because
- // the actual bcmolt_cfg_get passes the address of pon_cfg.hdr and we cannot
- // set the pon_cfg.data.state. So a new stub function is created and address
- // of pon_cfg is passed. This is one-of case where we need to add test specific
- // code in production code.
- err = bcmolt_cfg_get__pon_intf_stub(dev_id, &pon_cfg);
- #else
- err = bcmolt_cfg_get(dev_id, &pon_cfg.hdr);
- #endif
- *state = pon_cfg.data.state;
- return err;
-}
-
inline uint64_t get_flow_status(uint16_t flow_id, uint16_t flow_type, uint16_t data_id) {
bcmos_errno err;
bcmolt_flow_key flow_key;
@@ -1600,36 +798,6 @@
return Status::OK;
}
-/* Same as bcmolt_cfg_get but with added logic of retrying the API
- in case of some specific failures like timeout or object not yet ready
-*/
-bcmos_errno bcmolt_cfg_get_mult_retry(bcmolt_oltid olt, bcmolt_cfg *cfg) {
- bcmos_errno err;
- uint32_t current_try = 0;
-
- while (current_try < MAX_BAL_API_RETRY_COUNT) {
- err = bcmolt_cfg_get(olt, cfg);
- current_try++;
-
- if (err == BCM_ERR_STATE || err == BCM_ERR_TIMEOUT) {
- OPENOLT_LOG(WARNING, openolt_log_id, "bcmolt_cfg_get: err = %s\n", bcmos_strerror(err));
- bcmos_usleep(BAL_API_RETRY_TIME_IN_USECS);
- continue;
- }
- else {
- break;
- }
- }
-
- if (err != BCM_ERR_OK) {
- OPENOLT_LOG(ERROR, openolt_log_id, "bcmolt_cfg_get tried (%d) times with retry time(%d usecs) err = %s\n",
- current_try,
- BAL_API_RETRY_TIME_IN_USECS,
- bcmos_strerror(err));
- }
- return err;
-}
-
Status ProbeDeviceCapabilities_() {
bcmos_errno err;
bcmolt_device_cfg dev_cfg = { };
@@ -1727,87 +895,6 @@
return Status::OK;
}
-#if 0
-Status ProbePonIfTechnology_() {
- // Probe maximum extent possible as configured into BAL driver to determine
- // which are active in the current BAL topology. And for those
- // that are active, determine each port's access technology, i.e. "gpon" or "xgspon".
- for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
- bcmolt_pon_interface_cfg interface_obj;
- bcmolt_pon_interface_key interface_key;
-
- interface_key.pon_ni = intf_id;
- BCMOLT_CFG_INIT(&interface_obj, pon_interface, interface_key);
- if (board_technology == "XGS-PON"
- BCMOLT_MSG_FIELD_GET(&interface_obj, xgs_ngpon2_trx);
- else if (board_technology == "GPON")
- BCMOLT_MSG_FIELD_GET(&interface_obj, gpon_trx);
-
- bcmos_errno err = bcmolt_cfg_get(dev_id, &interface_obj.hdr);
- if (err != BCM_ERR_OK) {
- intf_technologies[intf_id] = UNKNOWN_TECH;
- if(err != BCM_ERR_RANGE) OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get PON config: %d err %d\n", intf_id, err);
- }
- else {
- if (board_technology == "XGS-PON") {
- switch(interface_obj.data.xgpon_trx.transceiver_type) {
- case BCMOLT_XGPON_TRX_TYPE_LTH_7222_PC:
- case BCMOLT_XGPON_TRX_TYPE_WTD_RTXM266_702:
- case BCMOLT_XGPON_TRX_TYPE_LTH_7222_BC_PLUS:
- case BCMOLT_XGPON_TRX_TYPE_LTH_7226_PC:
- case BCMOLT_XGPON_TRX_TYPE_LTH_5302_PC:
- case BCMOLT_XGPON_TRX_TYPE_LTH_7226_A_PC_PLUS:
- case BCMOLT_XGPON_TRX_TYPE_D272RR_SSCB_DM:
- intf_technologies[intf_id] = "XGS-PON";
- break;
- }
- } else if (board_technology == "GPON") {
- switch(interface_obj.data.gpon_trx.transceiver_type) {
- case BCMOLT_TRX_TYPE_SPS_43_48_H_HP_CDE_SD_2013:
- case BCMOLT_TRX_TYPE_LTE_3680_M:
- case BCMOLT_TRX_TYPE_SOURCE_PHOTONICS:
- case BCMOLT_TRX_TYPE_LTE_3680_P_TYPE_C_PLUS:
- case BCMOLT_TRX_TYPE_LTE_3680_P_BC:
- intf_technologies[intf_id] = "GPON";
- break;
- }
- }
-
- if (board_technology != UNKNOWN_TECH) {
- board_technology = intf_technologies[intf_id];
- } else if (board_technology != MIXED_TECH && board_technology != intf_technologies[intf_id]) {
- intf_technologies[intf_id] = MIXED_TECH;
- }
-
- }
- }
- return Status::OK;
-}
-#endif
-unsigned NumNniIf_() {return num_of_nni_ports;}
-unsigned NumPonIf_() {return num_of_pon_ports;}
-
-bcmos_errno get_nni_interface_status(bcmolt_interface id, bcmolt_interface_state *state) {
- bcmos_errno err;
- bcmolt_nni_interface_key nni_key;
- bcmolt_nni_interface_cfg nni_cfg;
- nni_key.id = id;
-
- BCMOLT_CFG_INIT(&nni_cfg, nni_interface, nni_key);
- BCMOLT_FIELD_SET_PRESENT(&nni_cfg.data, nni_interface_cfg_data, state);
- #ifdef TEST_MODE
- // It is impossible to mock the setting of nni_cfg.data.state because
- // the actual bcmolt_cfg_get passes the address of nni_cfg.hdr and we cannot
- // set the nni_cfg.data.state. So a new stub function is created and address
- // of nni_cfg is passed. This is one-of case where we need to add test specific
- // code in production code.
- err = bcmolt_cfg_get__nni_intf_stub(dev_id, &nni_cfg);
- #else
- err = bcmolt_cfg_get(dev_id, &nni_cfg.hdr);
- #endif
- *state = nni_cfg.data.state;
- return err;
-}
Status SetStateUplinkIf_(uint32_t intf_id, bool set_state) {
bcmos_errno err = BCM_ERR_OK;
@@ -2195,492 +1282,6 @@
return Status::OK;
}
-
-uint32_t GetPortNum_(uint32_t flow_id) {
- bcmos_fastlock_lock(&data_lock);
- uint32_t port_no = 0;
- std::map<uint32_t, uint32_t >::const_iterator it = flowid_to_port.find(flow_id);
- if (it != flowid_to_port.end()) {
- port_no = it->second;
- }
- bcmos_fastlock_unlock(&data_lock, 0);
- return port_no;
-}
-
-#define ACL_LOG(level,msg,err) \
- do { \
- OPENOLT_LOG(level, openolt_log_id, "--------> %s (acl_id %d) err: %d <--------\n", msg, key.id, err); \
- OPENOLT_LOG(level, openolt_log_id, "action_type %s\n", \
- GET_ACL_ACTION_TYPE(action_type)); \
- OPENOLT_LOG(level, openolt_log_id, "classifier(ether type %d), ip_proto %d, src_port %d, dst_port %d\n", \
- acl_key.ether_type, acl_key.ip_proto, acl_key.src_port, acl_key.dst_port); \
- } while(0)
-
-#define FLOW_LOG(level,msg,err) \
- do { \
- OPENOLT_LOG(level, openolt_log_id, "--------> %s (flow_id %d) err: %d <--------\n", msg, key.flow_id, err); \
- OPENOLT_LOG(level, openolt_log_id, "intf_id %d, onu_id %d, uni_id %d, port_no %u, cookie %"PRIu64"\n", \
- access_intf_id, onu_id, uni_id, port_no, cookie); \
- OPENOLT_LOG(level, openolt_log_id, "flow_type %s, queue_id %d, sched_id %d\n", flow_type.c_str(), \
- cfg.data.egress_qos.u.fixed_queue.queue_id, cfg.data.egress_qos.tm_sched.id); \
- OPENOLT_LOG(level, openolt_log_id, "Ingress(intfd_type %s, intf_id %d), Egress(intf_type %s, intf_id %d)\n", \
- GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), cfg.data.ingress_intf.intf_id, \
- GET_FLOW_INTERFACE_TYPE(cfg.data.egress_intf.intf_type), cfg.data.egress_intf.intf_id); \
- OPENOLT_LOG(level, openolt_log_id, "classifier(o_vid %d, o_pbits %d, i_vid %d, i_pbits %d, ether type 0x%x)\n", \
- c_val.o_vid, c_val.o_pbits, c_val.i_vid, c_val.i_pbits, classifier.eth_type()); \
- OPENOLT_LOG(level, openolt_log_id, "classifier(ip_proto 0x%x, gemport_id %d, src_port %d, dst_port %d, pkt_tag_type %s)\n", \
- c_val.ip_proto, gemport_id, c_val.src_port, c_val.dst_port, GET_PKT_TAG_TYPE(c_val.pkt_tag_type)); \
- OPENOLT_LOG(level, openolt_log_id, "action(cmds_bitmask %s, o_vid %d, o_pbits %d, i_vid %d, i_pbits %d)\n\n", \
- get_flow_acton_command(a_val.cmds_bitmask), a_val.o_vid, a_val.o_pbits, a_val.i_vid, a_val.i_pbits); \
- } while(0)
-
-#define FLOW_PARAM_LOG() \
- do { \
- OPENOLT_LOG(INFO, openolt_log_id, "--------> flow comparison (now before) <--------\n"); \
- OPENOLT_LOG(INFO, openolt_log_id, "flow_id (%d %d)\n", \
- key.flow_id, it->first.first); \
- OPENOLT_LOG(INFO, openolt_log_id, "onu_id (%d %lu)\n", \
- cfg.data.onu_id , get_flow_status(it->first.first, it->first.second, ONU_ID)); \
- OPENOLT_LOG(INFO, openolt_log_id, "type (%d %lu)\n", \
- key.flow_type, get_flow_status(it->first.first, it->first.second, FLOW_TYPE)); \
- OPENOLT_LOG(INFO, openolt_log_id, "svc_port_id (%d %lu)\n", \
- cfg.data.svc_port_id, get_flow_status(it->first.first, it->first.second, SVC_PORT_ID)); \
- OPENOLT_LOG(INFO, openolt_log_id, "priority (%d %lu)\n", \
- cfg.data.priority, get_flow_status(it->first.first, it->first.second, PRIORITY)); \
- OPENOLT_LOG(INFO, openolt_log_id, "cookie (%lu %lu)\n", \
- cfg.data.cookie, get_flow_status(it->first.first, it->first.second, COOKIE)); \
- OPENOLT_LOG(INFO, openolt_log_id, "ingress intf_type (%s %s)\n", \
- GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), \
- GET_FLOW_INTERFACE_TYPE(get_flow_status(it->first.first, it->first.second, INGRESS_INTF_TYPE))); \
- OPENOLT_LOG(INFO, openolt_log_id, "ingress intf id (%d %lu)\n", \
- cfg.data.ingress_intf.intf_id , get_flow_status(it->first.first, it->first.second, INGRESS_INTF_ID)); \
- OPENOLT_LOG(INFO, openolt_log_id, "egress intf_type (%d %lu)\n", \
- cfg.data.egress_intf.intf_type , get_flow_status(it->first.first, it->first.second, EGRESS_INTF_TYPE)); \
- OPENOLT_LOG(INFO, openolt_log_id, "egress intf_id (%d %lu)\n", \
- cfg.data.egress_intf.intf_id , get_flow_status(it->first.first, it->first.second, EGRESS_INTF_ID)); \
- OPENOLT_LOG(INFO, openolt_log_id, "classifier o_vid (%d %lu)\n", \
- c_val.o_vid , get_flow_status(it->first.first, it->first.second, CLASSIFIER_O_VID)); \
- OPENOLT_LOG(INFO, openolt_log_id, "classifier o_pbits (%d %lu)\n", \
- c_val.o_pbits , get_flow_status(it->first.first, it->first.second, CLASSIFIER_O_PBITS)); \
- OPENOLT_LOG(INFO, openolt_log_id, "classifier i_vid (%d %lu)\n", \
- c_val.i_vid , get_flow_status(it->first.first, it->first.second, CLASSIFIER_I_VID)); \
- OPENOLT_LOG(INFO, openolt_log_id, "classifier i_pbits (%d %lu)\n", \
- c_val.i_pbits , get_flow_status(it->first.first, it->first.second, CLASSIFIER_I_PBITS)); \
- OPENOLT_LOG(INFO, openolt_log_id, "classifier ether_type (0x%x 0x%lx)\n", \
- c_val.ether_type , get_flow_status(it->first.first, it->first.second, CLASSIFIER_ETHER_TYPE)); \
- OPENOLT_LOG(INFO, openolt_log_id, "classifier ip_proto (%d %lu)\n", \
- c_val.ip_proto , get_flow_status(it->first.first, it->first.second, CLASSIFIER_IP_PROTO)); \
- OPENOLT_LOG(INFO, openolt_log_id, "classifier src_port (%d %lu)\n", \
- c_val.src_port , get_flow_status(it->first.first, it->first.second, CLASSIFIER_SRC_PORT)); \
- OPENOLT_LOG(INFO, openolt_log_id, "classifier dst_port (%d %lu)\n", \
- c_val.dst_port , get_flow_status(it->first.first, it->first.second, CLASSIFIER_DST_PORT)); \
- OPENOLT_LOG(INFO, openolt_log_id, "classifier pkt_tag_type (%s %s)\n", \
- GET_PKT_TAG_TYPE(c_val.pkt_tag_type), \
- GET_PKT_TAG_TYPE(get_flow_status(it->first.first, it->first.second, CLASSIFIER_PKT_TAG_TYPE))); \
- OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos type (%d %lu)\n", \
- cfg.data.egress_qos.type , get_flow_status(it->first.first, it->first.second, EGRESS_QOS_TYPE)); \
- OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos queue_id (%d %lu)\n", \
- cfg.data.egress_qos.u.fixed_queue.queue_id, \
- get_flow_status(it->first.first, it->first.second, EGRESS_QOS_QUEUE_ID)); \
- OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos sched_id (%d %lu)\n", \
- cfg.data.egress_qos.tm_sched.id, \
- get_flow_status(it->first.first, it->first.second, EGRESS_QOS_TM_SCHED_ID)); \
- OPENOLT_LOG(INFO, openolt_log_id, "classifier cmds_bitmask (%s %s)\n", \
- get_flow_acton_command(a_val.cmds_bitmask), \
- get_flow_acton_command(get_flow_status(it->first.first, it->first.second, ACTION_CMDS_BITMASK))); \
- OPENOLT_LOG(INFO, openolt_log_id, "action o_vid (%d %lu)\n", \
- a_val.o_vid , get_flow_status(it->first.first, it->first.second, ACTION_O_VID)); \
- OPENOLT_LOG(INFO, openolt_log_id, "action i_vid (%d %lu)\n", \
- a_val.i_vid , get_flow_status(it->first.first, it->first.second, ACTION_I_VID)); \
- OPENOLT_LOG(INFO, openolt_log_id, "action o_pbits (%d %lu)\n", \
- a_val.o_pbits , get_flow_status(it->first.first, it->first.second, ACTION_O_PBITS)); \
- OPENOLT_LOG(INFO, openolt_log_id, "action i_pbits (%d %lu)\n\n", \
- a_val.i_pbits, get_flow_status(it->first.first, it->first.second, ACTION_I_PBITS)); \
- OPENOLT_LOG(INFO, openolt_log_id, "group_id (%d %lu)\n\n", \
- a_val.group_id, get_flow_status(it->first.first, it->first.second, GROUP_ID)); \
- } while(0)
-
-#define FLOW_CHECKER
-//#define SHOW_FLOW_PARAM
-
-Status install_gem_port(int32_t intf_id, int32_t onu_id, int32_t gemport_id) {
- bcmos_errno err;
- bcmolt_itupon_gem_cfg cfg; /* declare main API struct */
- bcmolt_itupon_gem_key key = {}; /* declare key */
- bcmolt_gem_port_configuration configuration = {};
-
- key.pon_ni = intf_id;
- key.gem_port_id = gemport_id;
-
- BCMOLT_CFG_INIT(&cfg, itupon_gem, key);
-
- bcmolt_gem_port_direction configuration_direction;
- configuration_direction = BCMOLT_GEM_PORT_DIRECTION_BIDIRECTIONAL;
- BCMOLT_FIELD_SET(&configuration, gem_port_configuration, direction, configuration_direction);
-
- bcmolt_gem_port_type configuration_type;
- configuration_type = BCMOLT_GEM_PORT_TYPE_UNICAST;
- BCMOLT_FIELD_SET(&configuration, gem_port_configuration, type, configuration_type);
-
- BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, configuration, configuration);
-
- BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, onu_id, onu_id);
-
- bcmolt_control_state encryption_mode;
- encryption_mode = BCMOLT_CONTROL_STATE_DISABLE;
- BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, encryption_mode, encryption_mode);
-
- bcmolt_us_gem_port_destination upstream_destination_queue;
- upstream_destination_queue = BCMOLT_US_GEM_PORT_DESTINATION_DATA;
- BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, upstream_destination_queue, upstream_destination_queue);
-
- bcmolt_control_state control;
- control = BCMOLT_CONTROL_STATE_ENABLE;
- BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, control, control);
-
- err = bcmolt_cfg_set(dev_id, &cfg.hdr);
- if(err != BCM_ERR_OK) {
- OPENOLT_LOG(ERROR, openolt_log_id, "failed to install gem_port = %d\n", gemport_id);
- return bcm_to_grpc_err(err, "Access_Control set ITU PON Gem port failed");
- }
-
- OPENOLT_LOG(INFO, openolt_log_id, "gem port installed successfully = %d\n", gemport_id);
-
- return Status::OK;
-}
-
-Status remove_gem_port(int32_t intf_id, int32_t gemport_id) {
- bcmolt_itupon_gem_cfg gem_cfg;
- bcmolt_itupon_gem_key key = {
- .pon_ni = (bcmolt_interface)intf_id,
- .gem_port_id = (bcmolt_gem_port_id)gemport_id
- };
- bcmos_errno err;
-
- BCMOLT_CFG_INIT(&gem_cfg, itupon_gem, key);
- err = bcmolt_cfg_clear(dev_id, &gem_cfg.hdr);
- if (err != BCM_ERR_OK)
- {
- OPENOLT_LOG(ERROR, openolt_log_id, "failed to remove gem_port = %d err=%s\n", gemport_id, gem_cfg.hdr.hdr.err_text);
- return bcm_to_grpc_err(err, "Access_Control clear ITU PON Gem port failed");
- }
-
- OPENOLT_LOG(INFO, openolt_log_id, "gem port removed successfully = %d\n", gemport_id);
-
- return Status::OK;
-}
-
-Status update_acl_interface(int32_t intf_id, bcmolt_interface_type intf_type, uint32_t access_control_id,
- bcmolt_members_update_command acl_cmd) {
- bcmos_errno err;
- bcmolt_access_control_interfaces_update oper; /* declare main API struct */
- bcmolt_access_control_key acl_key = {}; /* declare key */
- bcmolt_intf_ref interface_ref_list_elem = {};
- bcmolt_interface_type interface_ref_list_elem_intf_type;
- bcmolt_interface_id interface_ref_list_elem_intf_id;
- bcmolt_intf_ref_list_u8 interface_ref_list = {};
-
- if (acl_cmd != BCMOLT_MEMBERS_UPDATE_COMMAND_ADD && acl_cmd != BCMOLT_MEMBERS_UPDATE_COMMAND_REMOVE) {
- OPENOLT_LOG(ERROR, openolt_log_id, "acl cmd = %d not supported currently\n", acl_cmd);
- return bcm_to_grpc_err(BCM_ERR_PARM, "unsupported acl cmd");
- }
- interface_ref_list.arr = (bcmolt_intf_ref*)bcmos_calloc(sizeof(bcmolt_intf_ref)*1);
-
- if (interface_ref_list.arr == NULL)
- return bcm_to_grpc_err(BCM_ERR_PARM, "allocate interface_ref_list failed");
- OPENOLT_LOG(INFO, openolt_log_id, "update acl interface received for intf_id = %d, intf_type = %s, acl_id = %d, acl_cmd = %s\n",
- intf_id, intf_type == BCMOLT_INTERFACE_TYPE_PON? "pon": "nni", access_control_id,
- acl_cmd == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD? "add": "remove");
-
- acl_key.id = access_control_id;
-
- /* Initialize the API struct. */
- BCMOLT_OPER_INIT(&oper, access_control, interfaces_update, acl_key);
-
- bcmolt_members_update_command command;
- command = acl_cmd;
- BCMOLT_FIELD_SET(&oper.data, access_control_interfaces_update_data, command, command);
-
- interface_ref_list_elem_intf_type = intf_type;
- BCMOLT_FIELD_SET(&interface_ref_list_elem, intf_ref, intf_type, interface_ref_list_elem_intf_type);
-
- interface_ref_list_elem_intf_id = intf_id;
- BCMOLT_FIELD_SET(&interface_ref_list_elem, intf_ref, intf_id, interface_ref_list_elem_intf_id);
-
- interface_ref_list.len = 1;
- BCMOLT_ARRAY_ELEM_SET(&interface_ref_list, 0, interface_ref_list_elem);
-
- BCMOLT_FIELD_SET(&oper.data, access_control_interfaces_update_data, interface_ref_list, interface_ref_list);
-
- err = bcmolt_oper_submit(dev_id, &oper.hdr);
- if (err != BCM_ERR_OK) {
- OPENOLT_LOG(ERROR, openolt_log_id, "update acl interface fail for intf_id = %d, intf_type = %s, acl_id = %d, acl_cmd = %s\n",
- intf_id, intf_type == BCMOLT_INTERFACE_TYPE_PON? "pon": "nni", access_control_id,
- acl_cmd == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD? "add": "remove");
- return bcm_to_grpc_err(err, "Access_Control submit interface failed");
- }
-
- bcmos_free(interface_ref_list.arr);
- OPENOLT_LOG(INFO, openolt_log_id, "update acl interface success for intf_id = %d, intf_type = %s, acl_id = %d, acl_cmd = %s\n",
- intf_id, intf_type == BCMOLT_INTERFACE_TYPE_PON? "pon": "nni", access_control_id,
- acl_cmd == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD? "add": "remove");
-
- return Status::OK;
-}
-
-Status install_acl(const acl_classifier_key acl_key) {
-
- bcmos_errno err;
- bcmolt_access_control_cfg cfg;
- bcmolt_access_control_key key = { };
- bcmolt_classifier c_val = { };
- // hardcode the action for now.
- bcmolt_access_control_fwd_action_type action_type = BCMOLT_ACCESS_CONTROL_FWD_ACTION_TYPE_TRAP_TO_HOST;
-
- int acl_id = get_acl_id();
- if (acl_id < 0) {
- OPENOLT_LOG(ERROR, openolt_log_id, "exhausted acl_id for eth_type = %d, ip_proto = %d, src_port = %d, dst_port = %d\n",
- acl_key.ether_type, acl_key.ip_proto, acl_key.src_port, acl_key.dst_port);
- bcmos_fastlock_unlock(&data_lock, 0);
- return bcm_to_grpc_err(BCM_ERR_INTERNAL, "exhausted acl id");
- }
-
- key.id = acl_id;
- /* config access control instance */
- BCMOLT_CFG_INIT(&cfg, access_control, key);
-
- if (acl_key.ether_type > 0) {
- OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify ether_type 0x%04x\n", acl_key.ether_type);
- BCMOLT_FIELD_SET(&c_val, classifier, ether_type, acl_key.ether_type);
- }
-
- if (acl_key.ip_proto > 0) {
- OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify ip_proto %d\n", acl_key.ip_proto);
- BCMOLT_FIELD_SET(&c_val, classifier, ip_proto, acl_key.ip_proto);
- }
-
- if (acl_key.dst_port > 0) {
- OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify dst_port %d\n", acl_key.dst_port);
- BCMOLT_FIELD_SET(&c_val, classifier, dst_port, acl_key.dst_port);
- }
-
- if (acl_key.src_port > 0) {
- OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify src_port %d\n", acl_key.src_port);
- BCMOLT_FIELD_SET(&c_val, classifier, src_port, acl_key.src_port);
- }
-
- BCMOLT_MSG_FIELD_SET(&cfg, classifier, c_val);
- BCMOLT_MSG_FIELD_SET(&cfg, priority, 10000);
- BCMOLT_MSG_FIELD_SET(&cfg, statistics_control, BCMOLT_CONTROL_STATE_ENABLE);
-
- BCMOLT_MSG_FIELD_SET(&cfg, forwarding_action.action, action_type);
-
- err = bcmolt_cfg_set(dev_id, &cfg.hdr);
- if (err != BCM_ERR_OK) {
- OPENOLT_LOG(ERROR, openolt_log_id, "Access_Control set configuration failed, Error %d\n", err);
- // Free the acl_id
- free_acl_id(acl_id);
- return bcm_to_grpc_err(err, "Access_Control set configuration failed");
- }
-
- ACL_LOG(INFO, "ACL add ok", err);
-
- // Update the map that we have installed an acl for the given classfier.
- acl_classifier_to_acl_id_map[acl_key] = acl_id;
- return Status::OK;
-}
-
-Status remove_acl(int acl_id) {
- bcmos_errno err;
- bcmolt_access_control_cfg cfg; /* declare main API struct */
- bcmolt_access_control_key key = {}; /* declare key */
-
- key.id = acl_id;
-
- /* Initialize the API struct. */
- BCMOLT_CFG_INIT(&cfg, access_control, key);
- BCMOLT_FIELD_SET_PRESENT(&cfg.data, access_control_cfg_data, state);
- err = bcmolt_cfg_get(dev_id, &cfg.hdr);
- if (err != BCM_ERR_OK) {
- OPENOLT_LOG(ERROR, openolt_log_id, "Access_Control get state failed\n");
- return bcm_to_grpc_err(err, "Access_Control get state failed");
- }
-
- if (cfg.data.state == BCMOLT_CONFIG_STATE_CONFIGURED) {
- key.id = acl_id;
- /* Initialize the API struct. */
- BCMOLT_CFG_INIT(&cfg, access_control, key);
-
- err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
- if (err != BCM_ERR_OK) {
- // Should we free acl_id here ? We should ideally never land here..
- OPENOLT_LOG(ERROR, openolt_log_id, "Error %d while removing Access_Control rule ID %d\n",
- err, acl_id);
- return Status(grpc::StatusCode::INTERNAL, "Failed to remove Access_Control");
- }
- }
-
- // Free up acl_id
- free_acl_id(acl_id);
-
- OPENOLT_LOG(INFO, openolt_log_id, "acl removed successfully %d\n", acl_id);
-
- return Status::OK;
-}
-
-// Formulates ACL Classifier Key based on the following fields
-// a. ether_type b. ip_proto c. src_port d. dst_port
-// If any of the field is not available it is populated as -1.
-void formulate_acl_classifier_key(acl_classifier_key *key, const ::openolt::Classifier& classifier) {
-
- // TODO: Is 0 a valid value for any of the following classifiers?
- // because in the that case, the 'if' check would fail and -1 would be filled as value.
- //
- if (classifier.eth_type()) {
- OPENOLT_LOG(DEBUG, openolt_log_id, "classify ether_type 0x%04x\n", classifier.eth_type());
- key->ether_type = classifier.eth_type();
- } else key->ether_type = -1;
-
- if (classifier.ip_proto()) {
- OPENOLT_LOG(DEBUG, openolt_log_id, "classify ip_proto %d\n", classifier.ip_proto());
- key->ip_proto = classifier.ip_proto();
- } else key->ip_proto = -1;
-
-
- if (classifier.src_port()) {
- OPENOLT_LOG(DEBUG, openolt_log_id, "classify src_port %d\n", classifier.src_port());
- key->src_port = classifier.src_port();
- } else key->src_port = -1;
-
-
- if (classifier.dst_port()) {
- OPENOLT_LOG(DEBUG, openolt_log_id, "classify dst_port %d\n", classifier.dst_port());
- key->dst_port = classifier.dst_port();
- } else key->dst_port = -1;
-}
-
-Status handle_acl_rule_install(int32_t onu_id, uint32_t flow_id,
- const std::string flow_type, int32_t access_intf_id,
- int32_t network_intf_id, int32_t gemport_id,
- const ::openolt::Classifier& classifier) {
- int acl_id;
- int32_t intf_id = flow_type.compare(upstream) == 0? access_intf_id: network_intf_id;
- const std::string intf_type = flow_type.compare(upstream) == 0? "pon": "nni";
- bcmolt_interface_type olt_if_type = intf_type == "pon"? BCMOLT_INTERFACE_TYPE_PON: BCMOLT_INTERFACE_TYPE_NNI;
-
- Status resp;
-
- // few map keys we are going to use later.
- flow_id_flow_direction fl_id_fl_dir(flow_id, flow_type);
- gem_id_intf_id gem_intf(gemport_id, access_intf_id);
- acl_classifier_key acl_key;
- formulate_acl_classifier_key(&acl_key, classifier);
- const acl_classifier_key acl_key_const = {.ether_type=acl_key.ether_type, .ip_proto=acl_key.ip_proto,
- .src_port=acl_key.src_port, .dst_port=acl_key.dst_port};
-
- bcmos_fastlock_lock(&data_lock);
-
- // Check if the acl is already installed
- if (acl_classifier_to_acl_id_map.count(acl_key_const) > 0) {
- // retreive the acl_id
- acl_id = acl_classifier_to_acl_id_map[acl_key_const];
- acl_id_gem_id_intf_id ac_id_gm_id_if_id(acl_id, gemport_id, intf_id);
- if (flow_to_acl_map.count(fl_id_fl_dir)) {
- // coult happen if same trap flow is received again
- OPENOLT_LOG(INFO, openolt_log_id, "flow and related acl already handled, nothing more to do\n");
- bcmos_fastlock_unlock(&data_lock, 0);
- return Status::OK;
- }
-
- OPENOLT_LOG(INFO, openolt_log_id, "Acl for flow_id=%u with eth_type = %d, ip_proto = %d, src_port = %d, dst_port = %d already installed with acl id = %u\n",
- flow_id, acl_key.ether_type, acl_key.ip_proto, acl_key.src_port, acl_key.dst_port, acl_id);
-
- // The acl_ref_cnt is needed to know how many flows refer an ACL.
- // When the flow is removed, we decrement the reference count.
- // When the reference count becomes 0, we remove the ACL.
- if (acl_ref_cnt.count(acl_id) > 0) {
- acl_ref_cnt[acl_id] ++;
- } else {
- // We should ideally not land here. The acl_ref_cnt should have been
- // initialized the first time acl was installed.
- acl_ref_cnt[acl_id] = 1;
- }
-
- } else {
- resp = install_acl(acl_key_const);
- if (!resp.ok()) {
- OPENOLT_LOG(ERROR, openolt_log_id, "Acl for flow_id=%u with eth_type = %d, ip_proto = %d, src_port = %d, dst_port = %d failed\n",
- flow_id, acl_key_const.ether_type, acl_key_const.ip_proto, acl_key_const.src_port, acl_key_const.dst_port);
- bcmos_fastlock_unlock(&data_lock, 0);
- return resp;
- }
-
- acl_id = acl_classifier_to_acl_id_map[acl_key_const];
-
- // Initialize the acl reference count
- acl_ref_cnt[acl_id] = 1;
-
- OPENOLT_LOG(INFO, openolt_log_id, "acl add success for flow_id=%u with acl_id=%d\n", flow_id, acl_id);
- }
-
- // Register the interface for the given acl
- acl_id_intf_id_intf_type ac_id_inf_id_inf_type(acl_id, intf_id, intf_type);
- // This is needed to keep a track of which interface (pon/nni) has registered for an ACL.
- // If it is registered, how many flows refer to it.
- if (intf_acl_registration_ref_cnt.count(ac_id_inf_id_inf_type) > 0) {
- intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type]++;
- } else {
- // The given interface is not registered for the ACL. We need to do it now.
- resp = update_acl_interface(intf_id, olt_if_type, acl_id, BCMOLT_MEMBERS_UPDATE_COMMAND_ADD);
- if (!resp.ok()){
- OPENOLT_LOG(ERROR, openolt_log_id, "failed to update acl interfaces intf_id=%d, intf_type=%s, acl_id=%d", intf_id, intf_type.c_str(), acl_id);
- // TODO: Ideally we should return error from hear and clean up other other stateful
- // counters we creaed earlier. Will leave it out for now.
- }
- intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type] = 1;
- }
-
-
- // Install the gem port if needed.
- if (gemport_id > 0 && access_intf_id >= 0) {
- if (gem_ref_cnt.count(gem_intf) > 0) {
- // The gem port is already installed
- // Increment the ref counter indicating number of flows referencing this gem port
- gem_ref_cnt[gem_intf]++;
- OPENOLT_LOG(DEBUG, openolt_log_id, "increment gem_ref_cnt in acl handler, ref_cnt=%d\n", gem_ref_cnt[gem_intf]);
-
- } else {
- // We should ideally never land here. The gem port should have been created the
- // first time ACL was installed.
- // Install the gem port
- Status resp = install_gem_port(access_intf_id, onu_id, gemport_id);
- if (!resp.ok()) {
- // TODO: We might need to reverse all previous data, but leave it out for now.
- OPENOLT_LOG(ERROR, openolt_log_id, "failed to install the gemport=%d for acl_id=%d, intf_id=%d\n", gemport_id, acl_id, access_intf_id);
- bcmos_fastlock_unlock(&data_lock, 0);
- return resp;
- }
- // Initialize the refence count for the gemport.
- gem_ref_cnt[gem_intf] = 1;
- OPENOLT_LOG(DEBUG, openolt_log_id, "intialized gem ref count in acl handler\n");
- }
- } else {
- OPENOLT_LOG(DEBUG, openolt_log_id, "not incrementing gem_ref_cnt in acl handler flow_id=%d, gemport_id=%d, intf_id=%d\n", flow_id, gemport_id, access_intf_id);
- }
-
- // Update the flow_to_acl_map
- // This info is needed during flow remove. We need to which ACL ID and GEM PORT ID
- // the flow was referring to.
- // After retrieving the ACL ID and GEM PORT ID, we decrement the corresponding
- // reference counters for those ACL ID and GEMPORT ID.
- acl_id_gem_id_intf_id ac_id_gm_id_if_id(acl_id, gemport_id, intf_id);
- flow_to_acl_map[fl_id_fl_dir] = ac_id_gm_id_if_id;
-
- bcmos_fastlock_unlock(&data_lock, 0);
-
- return Status::OK;
-}
-
Status FlowAdd_(int32_t access_intf_id, int32_t onu_id, int32_t uni_id, uint32_t port_no,
uint32_t flow_id, const std::string flow_type,
int32_t alloc_id, int32_t network_intf_id,
@@ -2783,19 +1384,6 @@
}
{
- /* removed by BAL v3.0
- if (classifier.o_tpid()) {
- OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_tpid 0x%04x\n", classifier.o_tpid());
- BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_tpid, classifier.o_tpid());
- }
- */
- /* removed by BAL v3.0
- if (classifier.i_tpid()) {
- OPENOLT_LOG(DEBUG, openolt_log_id, "classify i_tpid 0x%04x\n", classifier.i_tpid());
- BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, i_tpid, classifier.i_tpid());
- }
- */
-
if (classifier.eth_type()) {
ether_type = classifier.eth_type();
OPENOLT_LOG(DEBUG, openolt_log_id, "classify ether_type 0x%04x\n", classifier.eth_type());
@@ -2894,12 +1482,7 @@
OPENOLT_LOG(DEBUG, openolt_log_id, "action pop o_tag\n");
BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, BCMOLT_ACTION_CMD_ID_REMOVE_OUTER_TAG);
}
- /* removed by BAL v3.0
- if (cmd.trap_to_host()) {
- OPENOLT_LOG(INFO, openolt_log_id, "action trap-to-host\n");
- BCMBAL_ATTRIBUTE_PROP_SET(&val, action, cmds_bitmask, BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST);
- }
- */
+
if (action.o_vid()) {
OPENOLT_LOG(DEBUG, openolt_log_id, "action o_vid=%d\n", action.o_vid());
o_vid = action.o_vid();
@@ -2910,12 +1493,7 @@
OPENOLT_LOG(DEBUG, openolt_log_id, "action o_pbits=0x%x\n", action.o_pbits());
BCMOLT_FIELD_SET(&a_val, action, o_pbits, action.o_pbits());
}
- /* removed by BAL v3.0
- if (action.o_tpid()) {
- OPENOLT_LOG(INFO, openolt_log_id, "action o_tpid=0x%04x\n", action.o_tpid());
- BCMBAL_ATTRIBUTE_PROP_SET(&val, action, o_tpid, action.o_tpid());
- }
- */
+
if (action.i_vid()) {
OPENOLT_LOG(DEBUG, openolt_log_id, "action i_vid=%d\n", action.i_vid());
BCMOLT_FIELD_SET(&a_val, action, i_vid, action.i_vid());
@@ -2925,12 +1503,7 @@
OPENOLT_LOG(DEBUG, openolt_log_id, "action i_pbits=0x%x\n", action.i_pbits());
BCMOLT_FIELD_SET(&a_val, action, i_pbits, action.i_pbits());
}
- /* removed by BAL v3.0
- if (action.i_tpid()) {
- OPENOLT_LOG(DEBUG, openolt_log_id, "action i_tpid=0x%04x\n", action.i_tpid());
- BCMBAL_ATTRIBUTE_PROP_SET(&val, action, i_tpid, action.i_tpid());
- }
- */
+
BCMOLT_MSG_FIELD_SET(&cfg, action, a_val);
if ((access_intf_id >= 0) && (onu_id >= 0)) {
@@ -3088,57 +1661,6 @@
return Status::OK;
}
-void clear_gem_port(int gemport_id, int access_intf_id) {
- gem_id_intf_id gem_intf(gemport_id, access_intf_id);
- if (gemport_id > 0 && access_intf_id >= 0 && gem_ref_cnt.count(gem_intf) > 0) {
- OPENOLT_LOG(DEBUG, openolt_log_id, "decrementing gem_ref_cnt gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
- gem_ref_cnt[gem_intf]--;
- if (gem_ref_cnt[gem_intf] == 0) {
- // For datapath flow this may not be necessary (to be verified)
- remove_gem_port(access_intf_id, gemport_id);
- gem_ref_cnt.erase(gem_intf);
- OPENOLT_LOG(DEBUG, openolt_log_id, "removing gem_ref_cnt entry gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
- } else {
- OPENOLT_LOG(DEBUG, openolt_log_id, "gem_ref_cnt not zero yet gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
- }
- } else {
- OPENOLT_LOG(DEBUG, openolt_log_id, "not decrementing gem_ref_cnt gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
- }
-}
-
-Status handle_acl_rule_cleanup(int16_t acl_id, int32_t gemport_id, int32_t intf_id, const std::string flow_type) {
- const std::string intf_type= flow_type.compare(upstream) == 0 ? "pon": "nni";
- acl_id_intf_id_intf_type ac_id_inf_id_inf_type(acl_id, intf_id, intf_type);
- intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type]--;
- if (intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type] == 0) {
- bcmolt_interface_type olt_if_type = intf_type == "pon"? BCMOLT_INTERFACE_TYPE_PON: BCMOLT_INTERFACE_TYPE_NNI;
- Status resp = update_acl_interface(intf_id, olt_if_type, acl_id, BCMOLT_MEMBERS_UPDATE_COMMAND_REMOVE);
- if (!resp.ok()){
- OPENOLT_LOG(ERROR, openolt_log_id, "failed to update acl interfaces intf_id=%d, intf_type=%s, acl_id=%d", intf_id, intf_type.c_str(), acl_id);
- }
- intf_acl_registration_ref_cnt.erase(ac_id_inf_id_inf_type);
- }
-
- acl_ref_cnt[acl_id]--;
- if (acl_ref_cnt[acl_id] == 0) {
- remove_acl(acl_id);
- acl_ref_cnt.erase(acl_id);
- // Iterate acl_classifier_to_acl_id_map and delete classifier the key corresponding to acl_id
- std::map<acl_classifier_key, uint16_t>::iterator it;
- for (it=acl_classifier_to_acl_id_map.begin(); it!=acl_classifier_to_acl_id_map.end(); ++it) {
- if (it->second == acl_id) {
- OPENOLT_LOG(INFO, openolt_log_id, "cleared classifier key corresponding to acl_id = %d\n", acl_id);
- acl_classifier_to_acl_id_map.erase(it->first);
- break;
- }
- }
- }
-
- clear_gem_port(gemport_id, intf_id);
-
- return Status::OK;
-}
-
Status FlowRemove_(uint32_t flow_id, const std::string flow_type) {
bcmolt_flow_cfg cfg;
@@ -3878,52 +2400,6 @@
return Status::OK;
}
-Status check_connection() {
- int maxTrials = 60;
- while (!bcmolt_api_conn_mgr_is_connected(dev_id)) {
- sleep(1);
- if (--maxTrials == 0)
- return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check connection failed");
- else
- OPENOLT_LOG(INFO, openolt_log_id, "waiting for daemon connection ...\n");
- }
- OPENOLT_LOG(INFO, openolt_log_id, "daemon is connected\n");
- return Status::OK;
-}
-
-Status check_bal_ready() {
- bcmos_errno err;
- int maxTrials = 30;
- bcmolt_olt_cfg olt_cfg = { };
- bcmolt_olt_key olt_key = { };
-
- BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
- BCMOLT_MSG_FIELD_GET(&olt_cfg, bal_state);
-
- while (olt_cfg.data.bal_state != BCMOLT_BAL_STATE_BAL_AND_SWITCH_READY) {
- if (--maxTrials == 0)
- return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check bal ready failed");
- sleep(5);
- #ifdef TEST_MODE
- // It is impossible to mock the setting of olt_cfg.data.bal_state because
- // the actual bcmolt_cfg_get passes the address of olt_cfg.hdr and we cannot
- // set the olt_cfg.data.bal_state. So a new stub function is created and address
- // of olt_cfg is passed. This is one-of case where we need to add test specific
- // code in production code.
- if (bcmolt_cfg_get__bal_state_stub(dev_id, &olt_cfg)) {
- #else
- if (bcmolt_cfg_get(dev_id, &olt_cfg.hdr)) {
- #endif
- continue;
- }
- else
- OPENOLT_LOG(INFO, openolt_log_id, "waiting for BAL ready ...\n");
- }
-
- OPENOLT_LOG(INFO, openolt_log_id, "BAL is ready\n");
- return Status::OK;
-}
-
Status PerformGroupOperation_(const openolt::Group *group_cfg) {
bcmos_errno err;
diff --git a/agent/src/core_data.cc b/agent/src/core_data.cc
new file mode 100644
index 0000000..dc98400
--- /dev/null
+++ b/agent/src/core_data.cc
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <iostream>
+#include <memory>
+#include <string>
+
+#include "Queue.h"
+#include <sstream>
+#include <chrono>
+#include <thread>
+#include <bitset>
+#include <inttypes.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "device.h"
+#include "core.h"
+#include "core_data.h"
+#include "indications.h"
+#include "stats_collection.h"
+#include "error_format.h"
+#include "state.h"
+#include "core_utils.h"
+
+extern "C"
+{
+#include <bcmolt_api.h>
+#include <bcmolt_host_api.h>
+#include <bcmolt_api_model_supporting_enums.h>
+
+#include <bcmolt_api_conn_mgr.h>
+//CLI header files
+#include <bcmcli_session.h>
+#include <bcmcli.h>
+#include <bcm_api_cli.h>
+
+#include <bcmos_common.h>
+#include <bcm_config.h>
+// FIXME : dependency problem
+// #include <bcm_common_gpon.h>
+// #include <bcm_dev_log_task.h>
+}
+
+dev_log_id openolt_log_id = bcm_dev_log_id_register("OPENOLT", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+dev_log_id omci_log_id = bcm_dev_log_id_register("OMCI", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+
+
+unsigned int num_of_nni_ports = 0;
+unsigned int num_of_pon_ports = 0;
+
+const uint32_t tm_upstream_sched_id_start = (MAX_SUPPORTED_PON == 16 ? \
+ MAX_TM_SCHED_ID-3 : MAX_TM_SCHED_ID-9);
+const uint32_t tm_downstream_sched_id_start = (MAX_SUPPORTED_PON == 16 ? \
+ tm_upstream_sched_id_start-16 : tm_upstream_sched_id_start-64);
+
+/* Max Queue ID supported is 7 so based on priority_q configured for GEMPORTS
+in TECH PROFILE respective Queue ID from this list will be used for both
+US and DS Queues*/
+const uint32_t queue_id_list[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+
+const std::string upstream = "upstream";
+const std::string downstream = "downstream";
+const std::string multicast = "multicast";
+bcmolt_oltid dev_id = 0;
+
+/* Constants used for retrying some BAL APIs */
+const uint32_t BAL_API_RETRY_TIME_IN_USECS = 1000000;
+const uint32_t MAX_BAL_API_RETRY_COUNT = 5;
+
+const unsigned int OPENOLT_FIELD_LEN = 200;
+
+/* Current session */
+bcmcli_session *current_session;
+bcmcli_entry *api_parent_dir;
+bcmos_bool status_bcm_cli_quit = BCMOS_FALSE;
+bcmos_task bal_cli_thread;
+const char *bal_cli_thread_name = "bal_cli_thread";
+uint16_t flow_id_counters = 0;
+State state;
+
+std::map<uint32_t, uint32_t> flowid_to_port; // For mapping upstream flows to logical ports
+std::map<uint32_t, uint32_t> flowid_to_gemport; // For mapping downstream flows into gemports
+std::map<uint32_t, std::set<uint32_t> > port_to_flows; // For mapping logical ports to downstream flows
+
+/* This represents the Key to 'sched_map' map.
+ Represents (pon_intf_id, onu_id, uni_id, direction) */
+typedef std::tuple<uint32_t, uint32_t, uint32_t, std::string> sched_map_key_tuple;
+/* 'sched_map' maps sched_map_key_tuple to DBA (Upstream) or
+ Subscriber (Downstream) Scheduler ID */
+std::map<sched_map_key_tuple, int> sched_map;
+
+/* Flow control is for flow_id and flow_type */
+typedef std::pair<uint16_t, uint16_t> flow_pair;
+std::map<flow_pair, int32_t> flow_map;
+
+/* This represents the Key to 'qos_type_map' map.
+ Represents (pon_intf_id, onu_id, uni_id) */
+typedef std::tuple<uint32_t, uint32_t, uint32_t> qos_type_map_key_tuple;
+/* 'qos_type_map' maps qos_type_map_key_tuple to qos_type*/
+std::map<qos_type_map_key_tuple, bcmolt_egress_qos_type> qos_type_map;
+
+/* This represents the Key to 'sched_qmp_id_map' map.
+Represents (sched_id, pon_intf_id, onu_id, uni_id) */
+typedef std::tuple<uint32_t, uint32_t, uint32_t, uint32_t> sched_qmp_id_map_key_tuple;
+/* 'sched_qmp_id_map' maps sched_qmp_id_map_key_tuple to TM Queue Mapping Profile ID */
+std::map<sched_qmp_id_map_key_tuple, int> sched_qmp_id_map;
+/* 'qmp_id_to_qmp_map' maps TM Queue Mapping Profile ID to TM Queue Mapping Profile */
+std::map<int, std::vector < uint32_t > > qmp_id_to_qmp_map;
+
+// Flag used to watch whether mocked alloc_cfg_compltd_key is added to alloc_cfg_compltd_map
+#ifdef TEST_MODE
+bool ALLOC_CFG_FLAG = false;
+#endif
+
+// Map used to track response from BAL for ITU PON Alloc Configuration.
+// The key is alloc_cfg_compltd_key and value is a concurrent thread-safe queue which is
+// used for pushing (from BAL) and popping (at application) the results.
+std::map<alloc_cfg_compltd_key, Queue<alloc_cfg_complete_result> *> alloc_cfg_compltd_map;
+// Lock to protect critical section data structure used for handling AllocObject configuration response.
+bcmos_fastlock alloc_cfg_wait_lock;
+
+
+/*** ACL Handling related data start ***/
+
+std::map<acl_classifier_key, uint16_t> acl_classifier_to_acl_id_map;
+
+bool operator<(const acl_classifier_key& a1, const acl_classifier_key& a2)
+{
+ return ((a1.ether_type + 2*a1.ip_proto + 3*a1.src_port + 4*a1.dst_port) <
+ (a2.ether_type + 2*a2.ip_proto + 3*a2.src_port + 4*a2.dst_port));
+}
+
+typedef std::tuple<uint16_t, std::string> flow_id_flow_direction;
+typedef std::tuple<int16_t, uint16_t, int32_t> acl_id_gem_id_intf_id;
+std::map<flow_id_flow_direction, acl_id_gem_id_intf_id> flow_to_acl_map;
+
+// Keeps a reference count of how many flows are referencing a given ACL ID.
+// Key represents the ACL-ID and value is number of flows referencing the given ACL-ID.
+// When there is at least one flow referencing the ACL-ID, the ACL should be installed.
+// When there are no flows referencing the ACL-ID, the ACL should be removed.
+std::map<uint16_t, uint16_t> acl_ref_cnt;
+
+typedef std::tuple<uint16_t, uint16_t> gem_id_intf_id; // key to gem_ref_cnt
+// Keeps a reference count of how many ACL related flows are referencing a given (gem-id, pon_intf_id).
+// When there is at least on flow, we should install the gem. When there are no flows
+// the gem should be removed.
+std::map<gem_id_intf_id, uint16_t> gem_ref_cnt;
+
+// Needed to keep track of how many flows for a given acl_id, intf_id and intf_type are
+// installed. When there is at least on flow for this key, we should have interface registered
+// for the given ACL-ID. When there are no flows, the intf should unregister itself from
+// the ACL-ID.
+typedef std::tuple<uint16_t, uint8_t, std::string> acl_id_intf_id_intf_type;
+std::map<acl_id_intf_id_intf_type, uint16_t> intf_acl_registration_ref_cnt;
+
+std::bitset<MAX_ACL_ID> acl_id_bitset;
+
+/*** ACL Handling related data end ***/
+
+std::bitset<MAX_TM_SCHED_ID> tm_sched_bitset;
+std::bitset<MAX_TM_QMP_ID> tm_qmp_bitset;
+
+// Lock used to gaurd critical section during various API handling at the core_api_handler
+bcmos_fastlock data_lock;
diff --git a/agent/src/core_data.h b/agent/src/core_data.h
new file mode 100644
index 0000000..5c900f5
--- /dev/null
+++ b/agent/src/core_data.h
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OPENOLT_CORE_DATA_H_
+#define OPENOLT_CORE_DATA_H_
+
+#include <bitset>
+
+#include "core.h"
+#include "Queue.h"
+
+extern "C"
+{
+#include <bcmolt_api.h>
+#include <bcmolt_api_model_supporting_enums.h>
+
+#include <bcmolt_api_conn_mgr.h>
+//CLI header files
+#include <bcmcli_session.h>
+#include <bcmcli.h>
+#include <bcm_api_cli.h>
+
+#include <bcmos_common.h>
+#include <bcm_config.h>
+// FIXME : dependency problem
+// #include <bcm_common_gpon.h>
+// #include <bcm_dev_log_task.h>
+}
+
+#define ALLOC_CFG_COMPLETE_WAIT_TIMEOUT 1000 // in milli-seconds
+
+#define MIN_ALLOC_ID_GPON 256
+#define MIN_ALLOC_ID_XGSPON 1024
+
+#define MAX_ACL_ID 33
+
+// **************************************//
+// Enums and structures used by the core //
+// **************************************//
+enum FLOW_CFG {
+ ONU_ID = 0,
+ FLOW_TYPE = 1,
+ SVC_PORT_ID = 2,
+ PRIORITY = 3,
+ COOKIE = 4,
+ INGRESS_INTF_TYPE= 5,
+ EGRESS_INTF_TYPE= 6,
+ INGRESS_INTF_ID = 7,
+ EGRESS_INTF_ID = 8,
+ CLASSIFIER_O_VID = 9,
+ CLASSIFIER_O_PBITS = 10,
+ CLASSIFIER_I_VID = 11,
+ CLASSIFIER_I_PBITS = 12,
+ CLASSIFIER_ETHER_TYPE = 13,
+ CLASSIFIER_IP_PROTO =14,
+ CLASSIFIER_SRC_PORT = 15,
+ CLASSIFIER_DST_PORT = 16,
+ CLASSIFIER_PKT_TAG_TYPE = 17,
+ EGRESS_QOS_TYPE = 18,
+ EGRESS_QOS_QUEUE_ID = 19,
+ EGRESS_QOS_TM_SCHED_ID = 20,
+ ACTION_CMDS_BITMASK = 21,
+ ACTION_O_VID = 22,
+ ACTION_O_PBITS = 23,
+ ACTION_I_VID = 24,
+ ACTION_I_PBITS = 25,
+ STATE = 26,
+ GROUP_ID = 27
+};
+
+enum AllocCfgAction {
+ ALLOC_OBJECT_CREATE,
+ ALLOC_OBJECT_DELETE
+};
+
+enum AllocObjectState {
+ ALLOC_OBJECT_STATE_NOT_CONFIGURED,
+ ALLOC_OBJECT_STATE_INACTIVE,
+ ALLOC_OBJECT_STATE_PROCESSING,
+ ALLOC_OBJECT_STATE_ACTIVE
+};
+
+enum AllocCfgStatus {
+ ALLOC_CFG_STATUS_SUCCESS,
+ ALLOC_CFG_STATUS_FAIL
+};
+
+typedef struct {
+ uint32_t pon_intf_id;
+ uint32_t alloc_id;
+ AllocObjectState state;
+ AllocCfgStatus status;
+} alloc_cfg_complete_result;
+
+// key for map used for tracking ITU PON Alloc Configuration results from BAL
+typedef std::tuple<uint32_t, uint32_t> alloc_cfg_compltd_key;
+
+// The elements in this acl_classifier_key structure constitute key to
+// acl_classifier_to_acl_id_map.
+// Fill invalid values in the acl_classifier_key structure to -1.
+typedef struct acl_classifier_key {
+ int32_t ether_type;
+ int16_t ip_proto;
+ int32_t src_port;
+ int32_t dst_port;
+ // Add more classifiers elements as needed here
+ // For now, ACLs will be classified only based on
+ // above elements.
+} acl_classifier_key;
+
+// *******************************************************//
+// Extern Variable/Constant declarations used by the core //
+// *******************************************************//
+extern State state;
+
+extern dev_log_id openolt_log_id;
+extern dev_log_id omci_log_id;
+
+extern unsigned int num_of_nni_ports;
+extern unsigned int num_of_pon_ports;
+
+extern const uint32_t tm_upstream_sched_id_start;
+extern const uint32_t tm_downstream_sched_id_start;
+
+extern const uint32_t queue_id_list[8];
+
+extern const std::string upstream;
+extern const std::string downstream;
+extern const std::string multicast;
+extern bcmolt_oltid dev_id;
+
+extern const uint32_t BAL_API_RETRY_TIME_IN_USECS;
+extern const uint32_t MAX_BAL_API_RETRY_COUNT;
+
+extern const unsigned int OPENOLT_FIELD_LEN;
+
+/* Current session */
+extern bcmcli_session *current_session;
+extern bcmcli_entry *api_parent_dir;
+extern bcmos_bool status_bcm_cli_quit;
+extern bcmos_task bal_cli_thread;
+extern const char *bal_cli_thread_name;
+extern uint16_t flow_id_counters;
+
+extern std::map<uint32_t, uint32_t> flowid_to_port; // For mapping upstream flows to logical ports
+extern std::map<uint32_t, uint32_t> flowid_to_gemport; // For mapping downstream flows into gemports
+extern std::map<uint32_t, std::set<uint32_t> > port_to_flows; // For mapping logical ports to downstream flows
+
+/* This represents the Key to 'sched_map' map.
+ Represents (pon_intf_id, onu_id, uni_id, direction) */
+typedef std::tuple<uint32_t, uint32_t, uint32_t, std::string> sched_map_key_tuple;
+/* 'sched_map' maps sched_map_key_tuple to DBA (Upstream) or
+ Subscriber (Downstream) Scheduler ID */
+extern std::map<sched_map_key_tuple, int> sched_map;
+
+/* Flow control is for flow_id and flow_type */
+typedef std::pair<uint16_t, uint16_t> flow_pair;
+extern std::map<flow_pair, int32_t> flow_map;
+
+/* This represents the Key to 'qos_type_map' map.
+ Represents (pon_intf_id, onu_id, uni_id) */
+typedef std::tuple<uint32_t, uint32_t, uint32_t> qos_type_map_key_tuple;
+/* 'qos_type_map' maps qos_type_map_key_tuple to qos_type*/
+extern std::map<qos_type_map_key_tuple, bcmolt_egress_qos_type> qos_type_map;
+
+/* This represents the Key to 'sched_qmp_id_map' map.
+Represents (sched_id, pon_intf_id, onu_id, uni_id) */
+typedef std::tuple<uint32_t, uint32_t, uint32_t, uint32_t> sched_qmp_id_map_key_tuple;
+/* 'sched_qmp_id_map' maps sched_qmp_id_map_key_tuple to TM Queue Mapping Profile ID */
+extern std::map<sched_qmp_id_map_key_tuple, int> sched_qmp_id_map;
+/* 'qmp_id_to_qmp_map' maps TM Queue Mapping Profile ID to TM Queue Mapping Profile */
+extern std::map<int, std::vector < uint32_t > > qmp_id_to_qmp_map;
+
+// Flag used to watch whether mocked alloc_cfg_compltd_key is added to alloc_cfg_compltd_map
+#ifdef TEST_MODE
+extern bool ALLOC_CFG_FLAG;
+#endif
+
+// Map used to track response from BAL for ITU PON Alloc Configuration.
+// The key is alloc_cfg_compltd_key and value is a concurrent thread-safe queue which is
+// used for pushing (from BAL) and popping (at application) the results.
+extern std::map<alloc_cfg_compltd_key, Queue<alloc_cfg_complete_result> *> alloc_cfg_compltd_map;
+// Lock to protect critical section data structure used for handling AllocObject configuration response.
+extern bcmos_fastlock alloc_cfg_wait_lock;
+
+
+/*** ACL Handling related data start ***/
+
+extern std::map<acl_classifier_key, uint16_t> acl_classifier_to_acl_id_map;
+extern bool operator<(const acl_classifier_key& a1, const acl_classifier_key& a2);
+
+typedef std::tuple<uint16_t, std::string> flow_id_flow_direction;
+typedef std::tuple<int16_t, uint16_t, int32_t> acl_id_gem_id_intf_id;
+extern std::map<flow_id_flow_direction, acl_id_gem_id_intf_id> flow_to_acl_map;
+
+// Keeps a reference count of how many flows are referencing a given ACL ID.
+// Key represents the ACL-ID and value is number of flows referencing the given ACL-ID.
+// When there is at least one flow referencing the ACL-ID, the ACL should be installed.
+// When there are no flows referencing the ACL-ID, the ACL should be removed.
+extern std::map<uint16_t, uint16_t> acl_ref_cnt;
+
+typedef std::tuple<uint16_t, uint16_t> gem_id_intf_id; // key to gem_ref_cnt
+// Keeps a reference count of how many ACL related flows are referencing a given (gem-id, pon_intf_id).
+// When there is at least on flow, we should install the gem. When there are no flows
+// the gem should be removed.
+extern std::map<gem_id_intf_id, uint16_t> gem_ref_cnt;
+
+// Needed to keep track of how many flows for a given acl_id, intf_id and intf_type are
+// installed. When there is at least on flow for this key, we should have interface registered
+// for the given ACL-ID. When there are no flows, the intf should unregister itself from
+// the ACL-ID.
+typedef std::tuple<uint16_t, uint8_t, std::string> acl_id_intf_id_intf_type;
+extern std::map<acl_id_intf_id_intf_type, uint16_t> intf_acl_registration_ref_cnt;
+
+extern std::bitset<MAX_ACL_ID> acl_id_bitset;
+
+/*** ACL Handling related data end ***/
+
+extern std::bitset<MAX_TM_SCHED_ID> tm_sched_bitset;
+extern std::bitset<MAX_TM_QMP_ID> tm_qmp_bitset;
+
+extern Queue<openolt::Indication> oltIndQ;
+
+extern bcmos_fastlock data_lock;
+
+
+#endif // OPENOLT_CORE_DATA_H_
diff --git a/agent/src/core_utils.cc b/agent/src/core_utils.cc
new file mode 100644
index 0000000..f63ca52
--- /dev/null
+++ b/agent/src/core_utils.cc
@@ -0,0 +1,1221 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "core_utils.h"
+
+std::string serial_number_to_str(bcmolt_serial_number* serial_number) {
+#define SERIAL_NUMBER_SIZE 12
+ char buff[SERIAL_NUMBER_SIZE+1];
+
+ sprintf(buff, "%c%c%c%c%1X%1X%1X%1X%1X%1X%1X%1X",
+ serial_number->vendor_id.arr[0],
+ serial_number->vendor_id.arr[1],
+ serial_number->vendor_id.arr[2],
+ serial_number->vendor_id.arr[3],
+ serial_number->vendor_specific.arr[0]>>4 & 0x0f,
+ serial_number->vendor_specific.arr[0] & 0x0f,
+ serial_number->vendor_specific.arr[1]>>4 & 0x0f,
+ serial_number->vendor_specific.arr[1] & 0x0f,
+ serial_number->vendor_specific.arr[2]>>4 & 0x0f,
+ serial_number->vendor_specific.arr[2] & 0x0f,
+ serial_number->vendor_specific.arr[3]>>4 & 0x0f,
+ serial_number->vendor_specific.arr[3] & 0x0f);
+
+ return buff;
+}
+
+std::string vendor_specific_to_str(char const * const vendor_specific) {
+ char buff[SERIAL_NUMBER_SIZE+1];
+
+ sprintf(buff, "%1X%1X%1X%1X%1X%1X%1X%1X",
+ vendor_specific[0]>>4 & 0x0f,
+ vendor_specific[0] & 0x0f,
+ vendor_specific[1]>>4 & 0x0f,
+ vendor_specific[1] & 0x0f,
+ vendor_specific[2]>>4 & 0x0f,
+ vendor_specific[2] & 0x0f,
+ vendor_specific[3]>>4 & 0x0f,
+ vendor_specific[3] & 0x0f);
+
+ return buff;
+}
+/**
+* Returns the default NNI (Upstream direction) or PON (Downstream direction) scheduler
+* Every NNI port and PON port have default scheduler.
+* The NNI0 default scheduler ID is 18432, and NNI1 is 18433 and so on.
+* Similarly, PON0 default scheduler ID is 16384. PON1 is 16385 and so on.
+*
+* @param intf_id NNI or PON interface ID
+* @param direction "upstream" or "downstream"
+*
+* @return default scheduler ID for the given interface.
+*/
+
+uint16_t get_dev_id(void) {
+ return dev_id;
+}
+
+int get_default_tm_sched_id(int intf_id, std::string direction) {
+ if (direction.compare(upstream) == 0) {
+ return tm_upstream_sched_id_start + intf_id;
+ } else if (direction.compare(downstream) == 0) {
+ return tm_downstream_sched_id_start + intf_id;
+ }
+ else {
+ OPENOLT_LOG(ERROR, openolt_log_id, "invalid direction - %s\n", direction.c_str());
+ return 0;
+ }
+}
+
+/**
+* Gets a unique tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
+* The tm_sched_id is locally cached in a map, so that it can rendered when necessary.
+* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
+*
+* @param intf_id NNI or PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+* @param gemport_id GEM Port ID
+* @param direction Upstream or downstream
+*
+* @return tm_sched_id
+*/
+uint32_t get_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
+ sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
+ int sched_id = -1;
+
+ std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
+ if (it != sched_map.end()) {
+ sched_id = it->second;
+ }
+ if (sched_id != -1) {
+ return sched_id;
+ }
+
+ bcmos_fastlock_lock(&data_lock);
+ // Complexity of O(n). Is there better way that can avoid linear search?
+ for (sched_id = 0; sched_id < MAX_TM_SCHED_ID; sched_id++) {
+ if (tm_sched_bitset[sched_id] == 0) {
+ tm_sched_bitset[sched_id] = 1;
+ break;
+ }
+ }
+ bcmos_fastlock_unlock(&data_lock, 0);
+
+ if (sched_id < MAX_TM_SCHED_ID) {
+ bcmos_fastlock_lock(&data_lock);
+ sched_map[key] = sched_id;
+ bcmos_fastlock_unlock(&data_lock, 0);
+ return sched_id;
+ } else {
+ return -1;
+ }
+}
+
+/**
+* Free tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
+*
+* @param intf_id NNI or PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+* @param gemport_id GEM Port ID
+* @param direction Upstream or downstream
+*/
+void free_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
+ sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
+ std::map<sched_map_key_tuple, int>::const_iterator it;
+ bcmos_fastlock_lock(&data_lock);
+ it = sched_map.find(key);
+ if (it != sched_map.end()) {
+ tm_sched_bitset[it->second] = 0;
+ sched_map.erase(it);
+ }
+ bcmos_fastlock_unlock(&data_lock, 0);
+}
+
+bool is_tm_sched_id_present(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
+ sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
+ std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
+ if (it != sched_map.end()) {
+ return true;
+ }
+ return false;
+}
+
+/**
+* Check whether given two tm qmp profiles are equal or not
+*
+* @param tmq_map_profileA <vector> TM QUEUE MAPPING PROFILE
+* @param tmq_map_profileB <vector> TM QUEUE MAPPING PROFILE
+*
+* @return boolean, true if given tmq_map_profiles are equal else false
+*/
+
+bool check_tm_qmp_equality(std::vector<uint32_t> tmq_map_profileA, std::vector<uint32_t> tmq_map_profileB) {
+ for (uint32_t i = 0; i < TMQ_MAP_PROFILE_SIZE; i++) {
+ if (tmq_map_profileA[i] != tmq_map_profileB[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+* Modifies given queues_pbit_map to parsable format
+* e.g: Modifes "0b00000101" to "10100000"
+*
+* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
+* @param size Queue count
+*
+* @return string queues_pbit_map
+*/
+std::string* get_valid_queues_pbit_map(std::string *queues_pbit_map, uint32_t size) {
+ for(uint32_t i=0; i < size; i++) {
+ /* Deletes 2 characters from index number 0 */
+ queues_pbit_map[i].erase(0, 2);
+ std::reverse(queues_pbit_map[i].begin(), queues_pbit_map[i].end());
+ }
+ return queues_pbit_map;
+}
+
+/**
+* Creates TM QUEUE MAPPING PROFILE for given queues_pbit_map and queues_priority_q
+*
+* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
+* @param queues_priority_q PRIORITY_Q configured for each GEM in TECH PROFILE
+* @param size Queue count
+*
+* @return <vector> TM QUEUE MAPPING PROFILE
+*/
+std::vector<uint32_t> get_tmq_map_profile(std::string *queues_pbit_map, uint32_t *queues_priority_q, uint32_t size) {
+ std::vector<uint32_t> tmq_map_profile(8,0);
+
+ for(uint32_t i=0; i < size; i++) {
+ for (uint32_t j = 0; j < queues_pbit_map[i].size(); j++) {
+ if (queues_pbit_map[i][j]=='1') {
+ tmq_map_profile.at(j) = queue_id_list[queues_priority_q[i]];
+ }
+ }
+ }
+ return tmq_map_profile;
+}
+
+/**
+* Gets corresponding tm_qmp_id for a given tmq_map_profile
+*
+* @param <vector> TM QUEUE MAPPING PROFILE
+*
+* @return tm_qmp_id
+*/
+int get_tm_qmp_id(std::vector<uint32_t> tmq_map_profile) {
+ int tm_qmp_id = -1;
+
+ std::map<int, std::vector < uint32_t > >::const_iterator it = qmp_id_to_qmp_map.begin();
+ while(it != qmp_id_to_qmp_map.end()) {
+ if(check_tm_qmp_equality(tmq_map_profile, it->second)) {
+ tm_qmp_id = it->first;
+ break;
+ }
+ it++;
+ }
+ return tm_qmp_id;
+}
+
+/**
+* Updates sched_qmp_id_map with given sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id
+*
+* @param upstream/downstream sched_id
+* @param PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
+*/
+void update_sched_qmp_id_map(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
+ uint32_t uni_id, int tm_qmp_id) {
+ bcmos_fastlock_lock(&data_lock);
+ sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
+ sched_qmp_id_map.insert(make_pair(key, tm_qmp_id));
+ bcmos_fastlock_unlock(&data_lock, 0);
+}
+
+/**
+* Gets corresponding tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
+*
+* @param upstream/downstream sched_id
+* @param PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+*
+* @return tm_qmp_id
+*/
+int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id) {
+ sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
+ int tm_qmp_id = -1;
+
+ std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
+ if (it != sched_qmp_id_map.end()) {
+ tm_qmp_id = it->second;
+ }
+ return tm_qmp_id;
+}
+
+/**
+* Gets a unique tm_qmp_id for a given tmq_map_profile
+* The tm_qmp_id is locally cached in a map, so that it can be rendered when necessary.
+* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
+*
+* @param upstream/downstream sched_id
+* @param PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+* @param <vector> TM QUEUE MAPPING PROFILE
+*
+* @return tm_qmp_id
+*/
+int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id, \
+ std::vector<uint32_t> tmq_map_profile) {
+ int tm_qmp_id;
+
+ bcmos_fastlock_lock(&data_lock);
+ /* Complexity of O(n). Is there better way that can avoid linear search? */
+ for (tm_qmp_id = 0; tm_qmp_id < MAX_TM_QMP_ID; tm_qmp_id++) {
+ if (tm_qmp_bitset[tm_qmp_id] == 0) {
+ tm_qmp_bitset[tm_qmp_id] = 1;
+ break;
+ }
+ }
+ bcmos_fastlock_unlock(&data_lock, 0);
+
+ if (tm_qmp_id < MAX_TM_QMP_ID) {
+ bcmos_fastlock_lock(&data_lock);
+ qmp_id_to_qmp_map.insert(make_pair(tm_qmp_id, tmq_map_profile));
+ bcmos_fastlock_unlock(&data_lock, 0);
+ update_sched_qmp_id_map(sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id);
+ return tm_qmp_id;
+ } else {
+ return -1;
+ }
+}
+
+/**
+* Free tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
+*
+* @param upstream/downstream sched_id
+* @param PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
+*
+* @return boolean, true if no more reference for TM QMP else false
+*/
+bool free_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
+ uint32_t uni_id, int tm_qmp_id) {
+ bool result;
+ sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
+ std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
+ bcmos_fastlock_lock(&data_lock);
+ if (it != sched_qmp_id_map.end()) {
+ sched_qmp_id_map.erase(it);
+ }
+ bcmos_fastlock_unlock(&data_lock, 0);
+
+ uint32_t tm_qmp_ref_count = 0;
+ std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it2 = sched_qmp_id_map.begin();
+ while(it2 != sched_qmp_id_map.end()) {
+ if(it2->second == tm_qmp_id) {
+ tm_qmp_ref_count++;
+ }
+ it2++;
+ }
+
+ if (tm_qmp_ref_count == 0) {
+ std::map<int, std::vector < uint32_t > >::const_iterator it3 = qmp_id_to_qmp_map.find(tm_qmp_id);
+ if (it3 != qmp_id_to_qmp_map.end()) {
+ bcmos_fastlock_lock(&data_lock);
+ tm_qmp_bitset[tm_qmp_id] = 0;
+ qmp_id_to_qmp_map.erase(it3);
+ bcmos_fastlock_unlock(&data_lock, 0);
+ OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So clearing it\n", \
+ tm_qmp_id, tm_qmp_ref_count);
+ result = true;
+ }
+ } else {
+ OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So not clearing it\n", \
+ tm_qmp_id, tm_qmp_ref_count);
+ result = false;
+ }
+ return result;
+}
+
+// Gets free ACL ID if available, else -1
+int get_acl_id() {
+ int acl_id;
+ bcmos_fastlock_lock(&data_lock);
+ /* Complexity of O(n). Is there better way that can avoid linear search? */
+ for (acl_id = 0; acl_id < MAX_ACL_ID; acl_id++) {
+ if (acl_id_bitset[acl_id] == 0) {
+ acl_id_bitset[acl_id] = 1;
+ break;
+ }
+ }
+ bcmos_fastlock_unlock(&data_lock, 0);
+ if (acl_id < MAX_ACL_ID) {
+ return acl_id ;
+ } else {
+ return -1;
+ }
+}
+
+// Frees up the ACL ID.
+void free_acl_id (int acl_id) {
+ if (acl_id < MAX_ACL_ID) {
+ bcmos_fastlock_lock(&data_lock);
+ acl_id_bitset[acl_id] = 0;
+ bcmos_fastlock_unlock(&data_lock, 0);
+ }
+}
+
+/**
+* Returns qos type as string
+*
+* @param qos_type bcmolt_egress_qos_type enum
+*/
+std::string get_qos_type_as_string(bcmolt_egress_qos_type qos_type) {
+ switch (qos_type)
+ {
+ case BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE: return "FIXED_QUEUE";
+ case BCMOLT_EGRESS_QOS_TYPE_TC_TO_QUEUE: return "TC_TO_QUEUE";
+ case BCMOLT_EGRESS_QOS_TYPE_PBIT_TO_TC: return "PBIT_TO_TC";
+ case BCMOLT_EGRESS_QOS_TYPE_NONE: return "NONE";
+ case BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE: return "PRIORITY_TO_QUEUE";
+ default: OPENOLT_LOG(ERROR, openolt_log_id, "qos-type-not-supported %d\n", qos_type);
+ return "qos-type-not-supported";
+ }
+}
+
+/**
+* Gets/Updates qos type for given pon_intf_id, onu_id, uni_id
+*
+* @param PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+* @param queue_size TrafficQueues Size
+*
+* @return qos_type
+*/
+bcmolt_egress_qos_type get_qos_type(uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t queue_size) {
+ qos_type_map_key_tuple key(pon_intf_id, onu_id, uni_id);
+ bcmolt_egress_qos_type egress_qos_type = BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
+ std::string qos_string;
+
+ std::map<qos_type_map_key_tuple, bcmolt_egress_qos_type>::const_iterator it = qos_type_map.find(key);
+ if (it != qos_type_map.end()) {
+ egress_qos_type = it->second;
+ qos_string = get_qos_type_as_string(egress_qos_type);
+ OPENOLT_LOG(INFO, openolt_log_id, "Qos-type for subscriber connected to pon_intf_id %d, onu_id %d and uni_id %d is %s\n", \
+ pon_intf_id, onu_id, uni_id, qos_string.c_str());
+ }
+ else {
+ /* QOS Type has been pre-defined as Fixed Queue but it will be updated based on number of GEMPORTS
+ associated for a given subscriber. If GEM count = 1 for a given subscriber, qos_type will be Fixed Queue
+ else Priority to Queue */
+ egress_qos_type = (queue_size > 1) ? \
+ BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
+ bcmos_fastlock_lock(&data_lock);
+ qos_type_map.insert(make_pair(key, egress_qos_type));
+ bcmos_fastlock_unlock(&data_lock, 0);
+ qos_string = get_qos_type_as_string(egress_qos_type);
+ OPENOLT_LOG(INFO, openolt_log_id, "Qos-type for subscriber connected to pon_intf_id %d, onu_id %d and uni_id %d is %s\n", \
+ pon_intf_id, onu_id, uni_id, qos_string.c_str());
+ }
+ return egress_qos_type;
+}
+
+/**
+* Clears qos type for given pon_intf_id, onu_id, uni_id
+*
+* @param PON intf ID
+* @param onu_id ONU ID
+* @param uni_id UNI ID
+*/
+void clear_qos_type(uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id) {
+ qos_type_map_key_tuple key(pon_intf_id, onu_id, uni_id);
+ std::map<qos_type_map_key_tuple, bcmolt_egress_qos_type>::const_iterator it = qos_type_map.find(key);
+ bcmos_fastlock_lock(&data_lock);
+ if (it != qos_type_map.end()) {
+ qos_type_map.erase(it);
+ OPENOLT_LOG(INFO, openolt_log_id, "Cleared Qos-type for subscriber connected to pon_intf_id %d, onu_id %d and uni_id %d\n", \
+ pon_intf_id, onu_id, uni_id);
+ }
+ bcmos_fastlock_unlock(&data_lock, 0);
+}
+
+/**
+* Returns Scheduler/Queue direction as string
+*
+* @param direction as specified in tech_profile.proto
+*/
+std::string GetDirection(int direction) {
+ switch (direction)
+ {
+ case tech_profile::Direction::UPSTREAM: return upstream;
+ case tech_profile::Direction::DOWNSTREAM: return downstream;
+ default: OPENOLT_LOG(ERROR, openolt_log_id, "direction-not-supported %d\n", direction);
+ return "direction-not-supported";
+ }
+}
+
+// This method handles waiting for AllocObject configuration.
+// Returns error if the AllocObject is not in the appropriate state based on action requested.
+bcmos_errno wait_for_alloc_action(uint32_t intf_id, uint32_t alloc_id, AllocCfgAction action) {
+ Queue<alloc_cfg_complete_result> cfg_result;
+ alloc_cfg_compltd_key k(intf_id, alloc_id);
+ alloc_cfg_compltd_map[k] = &cfg_result;
+ bcmos_errno err = BCM_ERR_OK;
+ #ifdef TEST_MODE
+ ALLOC_CFG_FLAG = true;
+ #endif
+
+ // Try to pop the result from BAL with a timeout of ALLOC_CFG_COMPLETE_WAIT_TIMEOUT ms
+ std::pair<alloc_cfg_complete_result, bool> result = cfg_result.pop(ALLOC_CFG_COMPLETE_WAIT_TIMEOUT);
+ if (result.second == false) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "timeout waiting for alloc cfg complete indication intf_id %d, alloc_id %d\n",
+ intf_id, alloc_id);
+ // Invalidate the queue pointer.
+ bcmos_fastlock_lock(&alloc_cfg_wait_lock);
+ alloc_cfg_compltd_map[k] = NULL;
+ bcmos_fastlock_unlock(&alloc_cfg_wait_lock, 0);
+ err = BCM_ERR_INTERNAL;
+ #ifdef TEST_MODE
+ ALLOC_CFG_FLAG = false;
+ #endif
+ }
+ else if (result.first.status == ALLOC_CFG_STATUS_FAIL) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "error processing alloc cfg request intf_id %d, alloc_id %d\n",
+ intf_id, alloc_id);
+ err = BCM_ERR_INTERNAL;
+ }
+
+ if (err == BCM_ERR_OK) {
+ if (action == ALLOC_OBJECT_CREATE) {
+ if (result.first.state != ALLOC_OBJECT_STATE_ACTIVE) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "alloc object not in active state intf_id %d, alloc_id %d alloc_obj_state %d\n",
+ intf_id, alloc_id, result.first.state);
+ err = BCM_ERR_INTERNAL;
+ } else {
+ OPENOLT_LOG(INFO, openolt_log_id, "Create upstream bandwidth allocation success, intf_id %d, alloc_id %d\n",
+ intf_id, alloc_id);
+ }
+ } else { // ALLOC_OBJECT_DELETE
+ if (result.first.state != ALLOC_OBJECT_STATE_NOT_CONFIGURED) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "alloc object is not reset intf_id %d, alloc_id %d alloc_obj_state %d\n",
+ intf_id, alloc_id, result.first.state);
+ err = BCM_ERR_INTERNAL;
+ } else {
+ OPENOLT_LOG(INFO, openolt_log_id, "Remove alloc object success, intf_id %d, alloc_id %d\n",
+ intf_id, alloc_id);
+ }
+ }
+ }
+
+ // Remove entry from map
+ bcmos_fastlock_lock(&alloc_cfg_wait_lock);
+ alloc_cfg_compltd_map.erase(k);
+ bcmos_fastlock_unlock(&alloc_cfg_wait_lock, 0);
+ #ifdef TEST_MODE
+ ALLOC_CFG_FLAG = false;
+ #endif
+ return err;
+}
+
+char* openolt_read_sysinfo(const char* field_name, char* field_val)
+{
+ FILE *fp;
+ /* Prepare the command*/
+ char command[150];
+
+ snprintf(command, sizeof command, "bash -l -c \"onlpdump -s\" | perl -ne 'print $1 if /%s: (\\S+)/'", field_name);
+ /* Open the command for reading. */
+ fp = popen(command, "r");
+ if (fp == NULL) {
+ /*The client has to check for a Null field value in this case*/
+ OPENOLT_LOG(INFO, openolt_log_id, "Failed to query the %s\n", field_name);
+ return field_val;
+ }
+
+ /*Read the field value*/
+ if (fp) {
+ uint8_t ret;
+ ret = fread(field_val, OPENOLT_FIELD_LEN, 1, fp);
+ if (ret >= OPENOLT_FIELD_LEN)
+ OPENOLT_LOG(INFO, openolt_log_id, "Read data length %u\n", ret);
+ pclose(fp);
+ }
+ return field_val;
+}
+
+Status pushOltOperInd(uint32_t intf_id, const char *type, const char *state)
+{
+ openolt::Indication ind;
+ openolt::IntfOperIndication* intf_oper_ind = new openolt::IntfOperIndication;
+
+ intf_oper_ind->set_type(type);
+ intf_oper_ind->set_intf_id(intf_id);
+ intf_oper_ind->set_oper_state(state);
+ ind.set_allocated_intf_oper_ind(intf_oper_ind);
+ oltIndQ.push(ind);
+ return Status::OK;
+}
+
+#define CLI_HOST_PROMPT_FORMAT "BCM.%u> "
+
+/* Build CLI prompt */
+void openolt_cli_get_prompt_cb(bcmcli_session *session, char *buf, uint32_t max_len)
+{
+ snprintf(buf, max_len, CLI_HOST_PROMPT_FORMAT, dev_id);
+}
+
+int _bal_apiend_cli_thread_handler(long data)
+{
+ char init_string[]="\n";
+ bcmcli_session *sess = current_session;
+ bcmos_task_parm bal_cli_task_p_dummy;
+
+ /* Switch to interactive mode if not stopped in the init script */
+ if (!bcmcli_is_stopped(sess)) {
+ /* Force a CLI command prompt
+ * The string passed into the parse function
+ * must be modifiable, so a string constant like
+ * bcmcli_parse(current_session, "\n") will not
+ * work.
+ */
+ bcmcli_parse(sess, init_string);
+
+ /* Process user input until EOF or quit command */
+ bcmcli_driver(sess);
+ }
+ OPENOLT_LOG(INFO, openolt_log_id, "BAL API End CLI terminated\n");
+
+ /* Cleanup */
+ bcmcli_session_close(current_session);
+ bcmcli_token_destroy(NULL);
+ return 0;
+}
+
+/* Init API CLI commands for the current device */
+bcmos_errno bcm_openolt_api_cli_init(bcmcli_entry *parent_dir, bcmcli_session *session)
+{
+ bcmos_errno rc;
+
+ api_parent_dir = parent_dir;
+
+ rc = bcm_api_cli_set_commands(session);
+
+#ifdef BCM_SUBSYSTEM_HOST
+ /* Subscribe for device change indication */
+ rc = rc ? rc : bcmolt_olt_sel_ind_register(_api_cli_olt_change_ind);
+#endif
+
+ return rc;
+}
+
+bcmos_errno bcm_cli_quit(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ bcmcli_stop(session);
+ bcmcli_session_print(session, "CLI terminated by 'Quit' command\n");
+ status_bcm_cli_quit = BCMOS_TRUE;
+
+ return BCM_ERR_OK;
+}
+
+int get_status_bcm_cli_quit(void) {
+ return status_bcm_cli_quit;
+}
+
+bcmos_errno bcmolt_apiend_cli_init() {
+ bcmos_errno ret;
+ bcmos_task_parm bal_cli_task_p = {};
+ bcmos_task_parm bal_cli_task_p_dummy;
+
+ /** before creating the task, check if it is already created by the other half of BAL i.e. Core side */
+ if (BCM_ERR_OK != bcmos_task_query(&bal_cli_thread, &bal_cli_task_p_dummy)) {
+ /* Create BAL CLI thread */
+ bal_cli_task_p.name = bal_cli_thread_name;
+ bal_cli_task_p.handler = _bal_apiend_cli_thread_handler;
+ bal_cli_task_p.priority = TASK_PRIORITY_CLI;
+
+ ret = bcmos_task_create(&bal_cli_thread, &bal_cli_task_p);
+ if (BCM_ERR_OK != ret) {
+ bcmos_printf("Couldn't create BAL API end CLI thread\n");
+ return ret;
+ }
+ }
+}
+
+bcmos_errno get_pon_interface_status(bcmolt_interface pon_ni, bcmolt_interface_state *state) {
+ bcmos_errno err;
+ bcmolt_pon_interface_key pon_key;
+ bcmolt_pon_interface_cfg pon_cfg;
+ pon_key.pon_ni = pon_ni;
+
+ BCMOLT_CFG_INIT(&pon_cfg, pon_interface, pon_key);
+ BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, state);
+ BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, itu);
+ #ifdef TEST_MODE
+ // It is impossible to mock the setting of pon_cfg.data.state because
+ // the actual bcmolt_cfg_get passes the address of pon_cfg.hdr and we cannot
+ // set the pon_cfg.data.state. So a new stub function is created and address
+ // of pon_cfg is passed. This is one-of case where we need to add test specific
+ // code in production code.
+ err = bcmolt_cfg_get__pon_intf_stub(dev_id, &pon_cfg);
+ #else
+ err = bcmolt_cfg_get(dev_id, &pon_cfg.hdr);
+ #endif
+ *state = pon_cfg.data.state;
+ return err;
+}
+
+/* Same as bcmolt_cfg_get but with added logic of retrying the API
+ in case of some specific failures like timeout or object not yet ready
+*/
+bcmos_errno bcmolt_cfg_get_mult_retry(bcmolt_oltid olt, bcmolt_cfg *cfg) {
+ bcmos_errno err;
+ uint32_t current_try = 0;
+
+ while (current_try < MAX_BAL_API_RETRY_COUNT) {
+ err = bcmolt_cfg_get(olt, cfg);
+ current_try++;
+
+ if (err == BCM_ERR_STATE || err == BCM_ERR_TIMEOUT) {
+ OPENOLT_LOG(WARNING, openolt_log_id, "bcmolt_cfg_get: err = %s\n", bcmos_strerror(err));
+ bcmos_usleep(BAL_API_RETRY_TIME_IN_USECS);
+ continue;
+ }
+ else {
+ break;
+ }
+ }
+
+ if (err != BCM_ERR_OK) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "bcmolt_cfg_get tried (%d) times with retry time(%d usecs) err = %s\n",
+ current_try,
+ BAL_API_RETRY_TIME_IN_USECS,
+ bcmos_strerror(err));
+ }
+ return err;
+}
+
+
+unsigned NumNniIf_() {return num_of_nni_ports;}
+unsigned NumPonIf_() {return num_of_pon_ports;}
+
+bcmos_errno get_nni_interface_status(bcmolt_interface id, bcmolt_interface_state *state) {
+ bcmos_errno err;
+ bcmolt_nni_interface_key nni_key;
+ bcmolt_nni_interface_cfg nni_cfg;
+ nni_key.id = id;
+
+ BCMOLT_CFG_INIT(&nni_cfg, nni_interface, nni_key);
+ BCMOLT_FIELD_SET_PRESENT(&nni_cfg.data, nni_interface_cfg_data, state);
+ #ifdef TEST_MODE
+ // It is impossible to mock the setting of nni_cfg.data.state because
+ // the actual bcmolt_cfg_get passes the address of nni_cfg.hdr and we cannot
+ // set the nni_cfg.data.state. So a new stub function is created and address
+ // of nni_cfg is passed. This is one-of case where we need to add test specific
+ // code in production code.
+ err = bcmolt_cfg_get__nni_intf_stub(dev_id, &nni_cfg);
+ #else
+ err = bcmolt_cfg_get(dev_id, &nni_cfg.hdr);
+ #endif
+ *state = nni_cfg.data.state;
+ return err;
+}
+
+Status install_gem_port(int32_t intf_id, int32_t onu_id, int32_t gemport_id) {
+ bcmos_errno err;
+ bcmolt_itupon_gem_cfg cfg; /* declare main API struct */
+ bcmolt_itupon_gem_key key = {}; /* declare key */
+ bcmolt_gem_port_configuration configuration = {};
+
+ key.pon_ni = intf_id;
+ key.gem_port_id = gemport_id;
+
+ BCMOLT_CFG_INIT(&cfg, itupon_gem, key);
+
+ bcmolt_gem_port_direction configuration_direction;
+ configuration_direction = BCMOLT_GEM_PORT_DIRECTION_BIDIRECTIONAL;
+ BCMOLT_FIELD_SET(&configuration, gem_port_configuration, direction, configuration_direction);
+
+ bcmolt_gem_port_type configuration_type;
+ configuration_type = BCMOLT_GEM_PORT_TYPE_UNICAST;
+ BCMOLT_FIELD_SET(&configuration, gem_port_configuration, type, configuration_type);
+
+ BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, configuration, configuration);
+
+ BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, onu_id, onu_id);
+
+ bcmolt_control_state encryption_mode;
+ encryption_mode = BCMOLT_CONTROL_STATE_DISABLE;
+ BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, encryption_mode, encryption_mode);
+
+ bcmolt_us_gem_port_destination upstream_destination_queue;
+ upstream_destination_queue = BCMOLT_US_GEM_PORT_DESTINATION_DATA;
+ BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, upstream_destination_queue, upstream_destination_queue);
+
+ bcmolt_control_state control;
+ control = BCMOLT_CONTROL_STATE_ENABLE;
+ BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, control, control);
+
+ err = bcmolt_cfg_set(dev_id, &cfg.hdr);
+ if(err != BCM_ERR_OK) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "failed to install gem_port = %d\n", gemport_id);
+ return bcm_to_grpc_err(err, "Access_Control set ITU PON Gem port failed");
+ }
+
+ OPENOLT_LOG(INFO, openolt_log_id, "gem port installed successfully = %d\n", gemport_id);
+
+ return Status::OK;
+}
+
+Status remove_gem_port(int32_t intf_id, int32_t gemport_id) {
+ bcmolt_itupon_gem_cfg gem_cfg;
+ bcmolt_itupon_gem_key key = {
+ .pon_ni = (bcmolt_interface)intf_id,
+ .gem_port_id = (bcmolt_gem_port_id)gemport_id
+ };
+ bcmos_errno err;
+
+ BCMOLT_CFG_INIT(&gem_cfg, itupon_gem, key);
+ err = bcmolt_cfg_clear(dev_id, &gem_cfg.hdr);
+ if (err != BCM_ERR_OK)
+ {
+ OPENOLT_LOG(ERROR, openolt_log_id, "failed to remove gem_port = %d err=%s\n", gemport_id, gem_cfg.hdr.hdr.err_text);
+ return bcm_to_grpc_err(err, "Access_Control clear ITU PON Gem port failed");
+ }
+
+ OPENOLT_LOG(INFO, openolt_log_id, "gem port removed successfully = %d\n", gemport_id);
+
+ return Status::OK;
+}
+
+Status update_acl_interface(int32_t intf_id, bcmolt_interface_type intf_type, uint32_t access_control_id,
+ bcmolt_members_update_command acl_cmd) {
+ bcmos_errno err;
+ bcmolt_access_control_interfaces_update oper; /* declare main API struct */
+ bcmolt_access_control_key acl_key = {}; /* declare key */
+ bcmolt_intf_ref interface_ref_list_elem = {};
+ bcmolt_interface_type interface_ref_list_elem_intf_type;
+ bcmolt_interface_id interface_ref_list_elem_intf_id;
+ bcmolt_intf_ref_list_u8 interface_ref_list = {};
+
+ if (acl_cmd != BCMOLT_MEMBERS_UPDATE_COMMAND_ADD && acl_cmd != BCMOLT_MEMBERS_UPDATE_COMMAND_REMOVE) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "acl cmd = %d not supported currently\n", acl_cmd);
+ return bcm_to_grpc_err(BCM_ERR_PARM, "unsupported acl cmd");
+ }
+ interface_ref_list.arr = (bcmolt_intf_ref*)bcmos_calloc(sizeof(bcmolt_intf_ref)*1);
+
+ if (interface_ref_list.arr == NULL)
+ return bcm_to_grpc_err(BCM_ERR_PARM, "allocate interface_ref_list failed");
+ OPENOLT_LOG(INFO, openolt_log_id, "update acl interface received for intf_id = %d, intf_type = %s, acl_id = %d, acl_cmd = %s\n",
+ intf_id, intf_type == BCMOLT_INTERFACE_TYPE_PON? "pon": "nni", access_control_id,
+ acl_cmd == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD? "add": "remove");
+
+ acl_key.id = access_control_id;
+
+ /* Initialize the API struct. */
+ BCMOLT_OPER_INIT(&oper, access_control, interfaces_update, acl_key);
+
+ bcmolt_members_update_command command;
+ command = acl_cmd;
+ BCMOLT_FIELD_SET(&oper.data, access_control_interfaces_update_data, command, command);
+
+ interface_ref_list_elem_intf_type = intf_type;
+ BCMOLT_FIELD_SET(&interface_ref_list_elem, intf_ref, intf_type, interface_ref_list_elem_intf_type);
+
+ interface_ref_list_elem_intf_id = intf_id;
+ BCMOLT_FIELD_SET(&interface_ref_list_elem, intf_ref, intf_id, interface_ref_list_elem_intf_id);
+
+ interface_ref_list.len = 1;
+ BCMOLT_ARRAY_ELEM_SET(&interface_ref_list, 0, interface_ref_list_elem);
+
+ BCMOLT_FIELD_SET(&oper.data, access_control_interfaces_update_data, interface_ref_list, interface_ref_list);
+
+ err = bcmolt_oper_submit(dev_id, &oper.hdr);
+ if (err != BCM_ERR_OK) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "update acl interface fail for intf_id = %d, intf_type = %s, acl_id = %d, acl_cmd = %s\n",
+ intf_id, intf_type == BCMOLT_INTERFACE_TYPE_PON? "pon": "nni", access_control_id,
+ acl_cmd == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD? "add": "remove");
+ return bcm_to_grpc_err(err, "Access_Control submit interface failed");
+ }
+
+ bcmos_free(interface_ref_list.arr);
+ OPENOLT_LOG(INFO, openolt_log_id, "update acl interface success for intf_id = %d, intf_type = %s, acl_id = %d, acl_cmd = %s\n",
+ intf_id, intf_type == BCMOLT_INTERFACE_TYPE_PON? "pon": "nni", access_control_id,
+ acl_cmd == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD? "add": "remove");
+
+ return Status::OK;
+}
+
+Status install_acl(const acl_classifier_key acl_key) {
+
+ bcmos_errno err;
+ bcmolt_access_control_cfg cfg;
+ bcmolt_access_control_key key = { };
+ bcmolt_classifier c_val = { };
+ // hardcode the action for now.
+ bcmolt_access_control_fwd_action_type action_type = BCMOLT_ACCESS_CONTROL_FWD_ACTION_TYPE_TRAP_TO_HOST;
+
+ int acl_id = get_acl_id();
+ if (acl_id < 0) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "exhausted acl_id for eth_type = %d, ip_proto = %d, src_port = %d, dst_port = %d\n",
+ acl_key.ether_type, acl_key.ip_proto, acl_key.src_port, acl_key.dst_port);
+ bcmos_fastlock_unlock(&data_lock, 0);
+ return bcm_to_grpc_err(BCM_ERR_INTERNAL, "exhausted acl id");
+ }
+
+ key.id = acl_id;
+ /* config access control instance */
+ BCMOLT_CFG_INIT(&cfg, access_control, key);
+
+ if (acl_key.ether_type > 0) {
+ OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify ether_type 0x%04x\n", acl_key.ether_type);
+ BCMOLT_FIELD_SET(&c_val, classifier, ether_type, acl_key.ether_type);
+ }
+
+ if (acl_key.ip_proto > 0) {
+ OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify ip_proto %d\n", acl_key.ip_proto);
+ BCMOLT_FIELD_SET(&c_val, classifier, ip_proto, acl_key.ip_proto);
+ }
+
+ if (acl_key.dst_port > 0) {
+ OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify dst_port %d\n", acl_key.dst_port);
+ BCMOLT_FIELD_SET(&c_val, classifier, dst_port, acl_key.dst_port);
+ }
+
+ if (acl_key.src_port > 0) {
+ OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify src_port %d\n", acl_key.src_port);
+ BCMOLT_FIELD_SET(&c_val, classifier, src_port, acl_key.src_port);
+ }
+
+ BCMOLT_MSG_FIELD_SET(&cfg, classifier, c_val);
+ BCMOLT_MSG_FIELD_SET(&cfg, priority, 10000);
+ BCMOLT_MSG_FIELD_SET(&cfg, statistics_control, BCMOLT_CONTROL_STATE_ENABLE);
+
+ BCMOLT_MSG_FIELD_SET(&cfg, forwarding_action.action, action_type);
+
+ err = bcmolt_cfg_set(dev_id, &cfg.hdr);
+ if (err != BCM_ERR_OK) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "Access_Control set configuration failed, Error %d\n", err);
+ // Free the acl_id
+ free_acl_id(acl_id);
+ return bcm_to_grpc_err(err, "Access_Control set configuration failed");
+ }
+
+ ACL_LOG(INFO, "ACL add ok", err);
+
+ // Update the map that we have installed an acl for the given classfier.
+ acl_classifier_to_acl_id_map[acl_key] = acl_id;
+ return Status::OK;
+}
+
+Status remove_acl(int acl_id) {
+ bcmos_errno err;
+ bcmolt_access_control_cfg cfg; /* declare main API struct */
+ bcmolt_access_control_key key = {}; /* declare key */
+
+ key.id = acl_id;
+
+ /* Initialize the API struct. */
+ BCMOLT_CFG_INIT(&cfg, access_control, key);
+ BCMOLT_FIELD_SET_PRESENT(&cfg.data, access_control_cfg_data, state);
+ err = bcmolt_cfg_get(dev_id, &cfg.hdr);
+ if (err != BCM_ERR_OK) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "Access_Control get state failed\n");
+ return bcm_to_grpc_err(err, "Access_Control get state failed");
+ }
+
+ if (cfg.data.state == BCMOLT_CONFIG_STATE_CONFIGURED) {
+ key.id = acl_id;
+ /* Initialize the API struct. */
+ BCMOLT_CFG_INIT(&cfg, access_control, key);
+
+ err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
+ if (err != BCM_ERR_OK) {
+ // Should we free acl_id here ? We should ideally never land here..
+ OPENOLT_LOG(ERROR, openolt_log_id, "Error %d while removing Access_Control rule ID %d\n",
+ err, acl_id);
+ return Status(grpc::StatusCode::INTERNAL, "Failed to remove Access_Control");
+ }
+ }
+
+ // Free up acl_id
+ free_acl_id(acl_id);
+
+ OPENOLT_LOG(INFO, openolt_log_id, "acl removed successfully %d\n", acl_id);
+
+ return Status::OK;
+}
+
+// Formulates ACL Classifier Key based on the following fields
+// a. ether_type b. ip_proto c. src_port d. dst_port
+// If any of the field is not available it is populated as -1.
+void formulate_acl_classifier_key(acl_classifier_key *key, const ::openolt::Classifier& classifier) {
+
+ // TODO: Is 0 a valid value for any of the following classifiers?
+ // because in the that case, the 'if' check would fail and -1 would be filled as value.
+ //
+ if (classifier.eth_type()) {
+ OPENOLT_LOG(DEBUG, openolt_log_id, "classify ether_type 0x%04x\n", classifier.eth_type());
+ key->ether_type = classifier.eth_type();
+ } else key->ether_type = -1;
+
+ if (classifier.ip_proto()) {
+ OPENOLT_LOG(DEBUG, openolt_log_id, "classify ip_proto %d\n", classifier.ip_proto());
+ key->ip_proto = classifier.ip_proto();
+ } else key->ip_proto = -1;
+
+
+ if (classifier.src_port()) {
+ OPENOLT_LOG(DEBUG, openolt_log_id, "classify src_port %d\n", classifier.src_port());
+ key->src_port = classifier.src_port();
+ } else key->src_port = -1;
+
+
+ if (classifier.dst_port()) {
+ OPENOLT_LOG(DEBUG, openolt_log_id, "classify dst_port %d\n", classifier.dst_port());
+ key->dst_port = classifier.dst_port();
+ } else key->dst_port = -1;
+}
+
+Status handle_acl_rule_install(int32_t onu_id, uint32_t flow_id,
+ const std::string flow_type, int32_t access_intf_id,
+ int32_t network_intf_id, int32_t gemport_id,
+ const ::openolt::Classifier& classifier) {
+ int acl_id;
+ int32_t intf_id = flow_type.compare(upstream) == 0? access_intf_id: network_intf_id;
+ const std::string intf_type = flow_type.compare(upstream) == 0? "pon": "nni";
+ bcmolt_interface_type olt_if_type = intf_type == "pon"? BCMOLT_INTERFACE_TYPE_PON: BCMOLT_INTERFACE_TYPE_NNI;
+
+ Status resp;
+
+ // few map keys we are going to use later.
+ flow_id_flow_direction fl_id_fl_dir(flow_id, flow_type);
+ gem_id_intf_id gem_intf(gemport_id, access_intf_id);
+ acl_classifier_key acl_key;
+ formulate_acl_classifier_key(&acl_key, classifier);
+ const acl_classifier_key acl_key_const = {.ether_type=acl_key.ether_type, .ip_proto=acl_key.ip_proto,
+ .src_port=acl_key.src_port, .dst_port=acl_key.dst_port};
+
+ bcmos_fastlock_lock(&data_lock);
+
+ // Check if the acl is already installed
+ if (acl_classifier_to_acl_id_map.count(acl_key_const) > 0) {
+ // retreive the acl_id
+ acl_id = acl_classifier_to_acl_id_map[acl_key_const];
+ acl_id_gem_id_intf_id ac_id_gm_id_if_id(acl_id, gemport_id, intf_id);
+ if (flow_to_acl_map.count(fl_id_fl_dir)) {
+ // coult happen if same trap flow is received again
+ OPENOLT_LOG(INFO, openolt_log_id, "flow and related acl already handled, nothing more to do\n");
+ bcmos_fastlock_unlock(&data_lock, 0);
+ return Status::OK;
+ }
+
+ OPENOLT_LOG(INFO, openolt_log_id, "Acl for flow_id=%u with eth_type = %d, ip_proto = %d, src_port = %d, dst_port = %d already installed with acl id = %u\n",
+ flow_id, acl_key.ether_type, acl_key.ip_proto, acl_key.src_port, acl_key.dst_port, acl_id);
+
+ // The acl_ref_cnt is needed to know how many flows refer an ACL.
+ // When the flow is removed, we decrement the reference count.
+ // When the reference count becomes 0, we remove the ACL.
+ if (acl_ref_cnt.count(acl_id) > 0) {
+ acl_ref_cnt[acl_id] ++;
+ } else {
+ // We should ideally not land here. The acl_ref_cnt should have been
+ // initialized the first time acl was installed.
+ acl_ref_cnt[acl_id] = 1;
+ }
+
+ } else {
+ resp = install_acl(acl_key_const);
+ if (!resp.ok()) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "Acl for flow_id=%u with eth_type = %d, ip_proto = %d, src_port = %d, dst_port = %d failed\n",
+ flow_id, acl_key_const.ether_type, acl_key_const.ip_proto, acl_key_const.src_port, acl_key_const.dst_port);
+ bcmos_fastlock_unlock(&data_lock, 0);
+ return resp;
+ }
+
+ acl_id = acl_classifier_to_acl_id_map[acl_key_const];
+
+ // Initialize the acl reference count
+ acl_ref_cnt[acl_id] = 1;
+
+ OPENOLT_LOG(INFO, openolt_log_id, "acl add success for flow_id=%u with acl_id=%d\n", flow_id, acl_id);
+ }
+
+ // Register the interface for the given acl
+ acl_id_intf_id_intf_type ac_id_inf_id_inf_type(acl_id, intf_id, intf_type);
+ // This is needed to keep a track of which interface (pon/nni) has registered for an ACL.
+ // If it is registered, how many flows refer to it.
+ if (intf_acl_registration_ref_cnt.count(ac_id_inf_id_inf_type) > 0) {
+ intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type]++;
+ } else {
+ // The given interface is not registered for the ACL. We need to do it now.
+ resp = update_acl_interface(intf_id, olt_if_type, acl_id, BCMOLT_MEMBERS_UPDATE_COMMAND_ADD);
+ if (!resp.ok()){
+ OPENOLT_LOG(ERROR, openolt_log_id, "failed to update acl interfaces intf_id=%d, intf_type=%s, acl_id=%d", intf_id, intf_type.c_str(), acl_id);
+ // TODO: Ideally we should return error from hear and clean up other other stateful
+ // counters we creaed earlier. Will leave it out for now.
+ }
+ intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type] = 1;
+ }
+
+
+ // Install the gem port if needed.
+ if (gemport_id > 0 && access_intf_id >= 0) {
+ if (gem_ref_cnt.count(gem_intf) > 0) {
+ // The gem port is already installed
+ // Increment the ref counter indicating number of flows referencing this gem port
+ gem_ref_cnt[gem_intf]++;
+ OPENOLT_LOG(DEBUG, openolt_log_id, "increment gem_ref_cnt in acl handler, ref_cnt=%d\n", gem_ref_cnt[gem_intf]);
+
+ } else {
+ // We should ideally never land here. The gem port should have been created the
+ // first time ACL was installed.
+ // Install the gem port
+ Status resp = install_gem_port(access_intf_id, onu_id, gemport_id);
+ if (!resp.ok()) {
+ // TODO: We might need to reverse all previous data, but leave it out for now.
+ OPENOLT_LOG(ERROR, openolt_log_id, "failed to install the gemport=%d for acl_id=%d, intf_id=%d\n", gemport_id, acl_id, access_intf_id);
+ bcmos_fastlock_unlock(&data_lock, 0);
+ return resp;
+ }
+ // Initialize the refence count for the gemport.
+ gem_ref_cnt[gem_intf] = 1;
+ OPENOLT_LOG(DEBUG, openolt_log_id, "intialized gem ref count in acl handler\n");
+ }
+ } else {
+ OPENOLT_LOG(DEBUG, openolt_log_id, "not incrementing gem_ref_cnt in acl handler flow_id=%d, gemport_id=%d, intf_id=%d\n", flow_id, gemport_id, access_intf_id);
+ }
+
+ // Update the flow_to_acl_map
+ // This info is needed during flow remove. We need to which ACL ID and GEM PORT ID
+ // the flow was referring to.
+ // After retrieving the ACL ID and GEM PORT ID, we decrement the corresponding
+ // reference counters for those ACL ID and GEMPORT ID.
+ acl_id_gem_id_intf_id ac_id_gm_id_if_id(acl_id, gemport_id, intf_id);
+ flow_to_acl_map[fl_id_fl_dir] = ac_id_gm_id_if_id;
+
+ bcmos_fastlock_unlock(&data_lock, 0);
+
+ return Status::OK;
+}
+
+void clear_gem_port(int gemport_id, int access_intf_id) {
+ gem_id_intf_id gem_intf(gemport_id, access_intf_id);
+ if (gemport_id > 0 && access_intf_id >= 0 && gem_ref_cnt.count(gem_intf) > 0) {
+ OPENOLT_LOG(DEBUG, openolt_log_id, "decrementing gem_ref_cnt gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
+ gem_ref_cnt[gem_intf]--;
+ if (gem_ref_cnt[gem_intf] == 0) {
+ // For datapath flow this may not be necessary (to be verified)
+ remove_gem_port(access_intf_id, gemport_id);
+ gem_ref_cnt.erase(gem_intf);
+ OPENOLT_LOG(DEBUG, openolt_log_id, "removing gem_ref_cnt entry gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
+ } else {
+ OPENOLT_LOG(DEBUG, openolt_log_id, "gem_ref_cnt not zero yet gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
+ }
+ } else {
+ OPENOLT_LOG(DEBUG, openolt_log_id, "not decrementing gem_ref_cnt gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
+ }
+}
+
+Status handle_acl_rule_cleanup(int16_t acl_id, int32_t gemport_id, int32_t intf_id, const std::string flow_type) {
+ const std::string intf_type= flow_type.compare(upstream) == 0 ? "pon": "nni";
+ acl_id_intf_id_intf_type ac_id_inf_id_inf_type(acl_id, intf_id, intf_type);
+ intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type]--;
+ if (intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type] == 0) {
+ bcmolt_interface_type olt_if_type = intf_type == "pon"? BCMOLT_INTERFACE_TYPE_PON: BCMOLT_INTERFACE_TYPE_NNI;
+ Status resp = update_acl_interface(intf_id, olt_if_type, acl_id, BCMOLT_MEMBERS_UPDATE_COMMAND_REMOVE);
+ if (!resp.ok()){
+ OPENOLT_LOG(ERROR, openolt_log_id, "failed to update acl interfaces intf_id=%d, intf_type=%s, acl_id=%d", intf_id, intf_type.c_str(), acl_id);
+ }
+ intf_acl_registration_ref_cnt.erase(ac_id_inf_id_inf_type);
+ }
+
+ acl_ref_cnt[acl_id]--;
+ if (acl_ref_cnt[acl_id] == 0) {
+ remove_acl(acl_id);
+ acl_ref_cnt.erase(acl_id);
+ // Iterate acl_classifier_to_acl_id_map and delete classifier the key corresponding to acl_id
+ std::map<acl_classifier_key, uint16_t>::iterator it;
+ for (it=acl_classifier_to_acl_id_map.begin(); it!=acl_classifier_to_acl_id_map.end(); ++it) {
+ if (it->second == acl_id) {
+ OPENOLT_LOG(INFO, openolt_log_id, "cleared classifier key corresponding to acl_id = %d\n", acl_id);
+ acl_classifier_to_acl_id_map.erase(it->first);
+ break;
+ }
+ }
+ }
+
+ clear_gem_port(gemport_id, intf_id);
+
+ return Status::OK;
+}
+
+Status check_bal_ready() {
+ bcmos_errno err;
+ int maxTrials = 30;
+ bcmolt_olt_cfg olt_cfg = { };
+ bcmolt_olt_key olt_key = { };
+
+ BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
+ BCMOLT_MSG_FIELD_GET(&olt_cfg, bal_state);
+
+ while (olt_cfg.data.bal_state != BCMOLT_BAL_STATE_BAL_AND_SWITCH_READY) {
+ if (--maxTrials == 0)
+ return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check bal ready failed");
+ sleep(5);
+ #ifdef TEST_MODE
+ // It is impossible to mock the setting of olt_cfg.data.bal_state because
+ // the actual bcmolt_cfg_get passes the address of olt_cfg.hdr and we cannot
+ // set the olt_cfg.data.bal_state. So a new stub function is created and address
+ // of olt_cfg is passed. This is one-of case where we need to add test specific
+ // code in production code.
+ if (bcmolt_cfg_get__bal_state_stub(dev_id, &olt_cfg)) {
+ #else
+ if (bcmolt_cfg_get(dev_id, &olt_cfg.hdr)) {
+ #endif
+ continue;
+ }
+ else
+ OPENOLT_LOG(INFO, openolt_log_id, "waiting for BAL ready ...\n");
+ }
+
+ OPENOLT_LOG(INFO, openolt_log_id, "BAL is ready\n");
+ return Status::OK;
+}
+
+Status check_connection() {
+ int maxTrials = 60;
+ while (!bcmolt_api_conn_mgr_is_connected(dev_id)) {
+ sleep(1);
+ if (--maxTrials == 0)
+ return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check connection failed");
+ else
+ OPENOLT_LOG(INFO, openolt_log_id, "waiting for daemon connection ...\n");
+ }
+ OPENOLT_LOG(INFO, openolt_log_id, "daemon is connected\n");
+ return Status::OK;
+}
+
diff --git a/agent/src/core_utils.h b/agent/src/core_utils.h
new file mode 100644
index 0000000..5a7c6bd
--- /dev/null
+++ b/agent/src/core_utils.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OPENOLT_CORE_UTILS_H_
+#define OPENOLT_CORE_UTILS_H_
+#include <string>
+#include <unistd.h>
+
+#include "core.h"
+#include "core_data.h"
+#include "error_format.h"
+
+extern "C"
+{
+#include <bcmolt_api.h>
+#include <bcmolt_host_api.h>
+#include <bcmolt_api_model_supporting_enums.h>
+#include <bcmolt_api_model_supporting_structs.h>
+
+#include <bcmolt_api_conn_mgr.h>
+//CLI header files
+#include <bcmcli_session.h>
+#include <bcmcli.h>
+#include <bcm_api_cli.h>
+
+#include <bcmos_common.h>
+#include <bcm_config.h>
+// FIXME : dependency problem
+// #include <bcm_common_gpon.h>
+// #include <bcm_dev_log_task.h>
+}
+
+
+std::string serial_number_to_str(bcmolt_serial_number* serial_number);
+std::string vendor_specific_to_str(const char* const serial_number);
+uint16_t get_dev_id(void);
+int get_default_tm_sched_id(int intf_id, std::string direction);
+uint32_t get_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction);
+void free_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction);
+bool is_tm_sched_id_present(int pon_intf_id, int onu_id, int uni_id, std::string direction);
+bool check_tm_qmp_equality(std::vector<uint32_t> tmq_map_profileA, std::vector<uint32_t> tmq_map_profileB);
+std::string* get_valid_queues_pbit_map(std::string *queues_pbit_map, uint32_t size);
+std::vector<uint32_t> get_tmq_map_profile(std::string *queues_pbit_map, uint32_t *queues_priority_q, uint32_t size);
+int get_tm_qmp_id(std::vector<uint32_t> tmq_map_profile);
+void update_sched_qmp_id_map(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id,
+ uint32_t uni_id, int tm_qmp_id);
+int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id);
+int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id,
+ std::vector<uint32_t> tmq_map_profile);
+bool free_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id,
+ uint32_t uni_id, int tm_qmp_id);
+int get_acl_id();
+void free_acl_id (int acl_id);
+std::string get_qos_type_as_string(bcmolt_egress_qos_type qos_type);
+bcmolt_egress_qos_type get_qos_type(uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t queue_size=0);
+void clear_qos_type(uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id);
+std::string GetDirection(int direction);
+bcmos_errno wait_for_alloc_action(uint32_t intf_id, uint32_t alloc_id, AllocCfgAction action);
+char* openolt_read_sysinfo(const char* field_name, char* field_val);
+Status pushOltOperInd(uint32_t intf_id, const char *type, const char *state);
+void openolt_cli_get_prompt_cb(bcmcli_session *session, char *buf, uint32_t max_len);
+int _bal_apiend_cli_thread_handler(long data);
+bcmos_errno bcm_openolt_api_cli_init(bcmcli_entry *parent_dir, bcmcli_session *session);
+bcmos_errno bcm_cli_quit(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms);
+int get_status_bcm_cli_quit(void);
+bcmos_errno bcmolt_apiend_cli_init();
+bcmos_errno get_pon_interface_status(bcmolt_interface pon_ni, bcmolt_interface_state *state);
+bcmos_errno bcmolt_cfg_get_mult_retry(bcmolt_oltid olt, bcmolt_cfg *cfg);
+unsigned NumNniIf_();
+unsigned NumPonIf_();
+bcmos_errno get_nni_interface_status(bcmolt_interface id, bcmolt_interface_state *state);
+Status install_gem_port(int32_t intf_id, int32_t onu_id, int32_t gemport_id);
+Status remove_gem_port(int32_t intf_id, int32_t gemport_id);
+Status update_acl_interface(int32_t intf_id, bcmolt_interface_type intf_type, uint32_t access_control_id,
+ bcmolt_members_update_command acl_cmd);
+Status install_acl(const acl_classifier_key acl_key);
+Status remove_acl(int acl_id);
+void formulate_acl_classifier_key(acl_classifier_key *key, const ::openolt::Classifier& classifier);
+Status handle_acl_rule_install(int32_t onu_id, uint32_t flow_id,
+ const std::string flow_type, int32_t access_intf_id,
+ int32_t network_intf_id, int32_t gemport_id,
+ const ::openolt::Classifier& classifier);
+void clear_gem_port(int gemport_id, int access_intf_id);
+Status handle_acl_rule_cleanup(int16_t acl_id, int32_t gemport_id, int32_t intf_id, const std::string flow_type);
+Status check_bal_ready();
+Status check_connection();
+#endif // OPENOLT_CORE_UTILS_H_
+
+
diff --git a/agent/src/indications.cc b/agent/src/indications.cc
index c9f112e..b4eeb58 100644
--- a/agent/src/indications.cc
+++ b/agent/src/indications.cc
@@ -16,7 +16,8 @@
#include "indications.h"
#include "core.h"
-#include "utils.h"
+#include "core_data.h"
+#include "core_utils.h"
#include "stats_collection.h"
#include "translation.h"
#include "state.h"
diff --git a/agent/src/stats_collection.cc b/agent/src/stats_collection.cc
index f0feca4..9caa98e 100644
--- a/agent/src/stats_collection.cc
+++ b/agent/src/stats_collection.cc
@@ -20,6 +20,7 @@
#include "indications.h"
#include "core.h"
+#include "core_data.h"
#include "translation.h"
extern "C"
diff --git a/agent/src/utils.cc b/agent/src/utils.cc
deleted file mode 100644
index 21ca84b..0000000
--- a/agent/src/utils.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
-
- * http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <string.h>
-#include "utils.h"
-
-std::string serial_number_to_str(bcmolt_serial_number* serial_number) {
-#define SERIAL_NUMBER_SIZE 12
- char buff[SERIAL_NUMBER_SIZE+1];
-
- sprintf(buff, "%c%c%c%c%1X%1X%1X%1X%1X%1X%1X%1X",
- serial_number->vendor_id.arr[0],
- serial_number->vendor_id.arr[1],
- serial_number->vendor_id.arr[2],
- serial_number->vendor_id.arr[3],
- serial_number->vendor_specific.arr[0]>>4 & 0x0f,
- serial_number->vendor_specific.arr[0] & 0x0f,
- serial_number->vendor_specific.arr[1]>>4 & 0x0f,
- serial_number->vendor_specific.arr[1] & 0x0f,
- serial_number->vendor_specific.arr[2]>>4 & 0x0f,
- serial_number->vendor_specific.arr[2] & 0x0f,
- serial_number->vendor_specific.arr[3]>>4 & 0x0f,
- serial_number->vendor_specific.arr[3] & 0x0f);
-
- return buff;
-}
-
-std::string vendor_specific_to_str(char const * const vendor_specific) {
- char buff[SERIAL_NUMBER_SIZE+1];
-
- sprintf(buff, "%1X%1X%1X%1X%1X%1X%1X%1X",
- vendor_specific[0]>>4 & 0x0f,
- vendor_specific[0] & 0x0f,
- vendor_specific[1]>>4 & 0x0f,
- vendor_specific[1] & 0x0f,
- vendor_specific[2]>>4 & 0x0f,
- vendor_specific[2] & 0x0f,
- vendor_specific[3]>>4 & 0x0f,
- vendor_specific[3] & 0x0f);
-
- return buff;
-}
-
diff --git a/agent/src/utils.h b/agent/src/utils.h
deleted file mode 100644
index c35d6f0..0000000
--- a/agent/src/utils.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
-
- * http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef OPENOLT_UTILS_H_
-#define OPENOLT_UTILS_H_
-
-#include <string>
-
-extern "C"
-{
-#include <bcmos_system.h>
-#include <bcmolt_api.h>
-#include <bcmolt_api_model_supporting_structs.h>
-}
-
-std::string serial_number_to_str(bcmolt_serial_number* serial_number);
-std::string vendor_specific_to_str(const char* const serial_number);
-
-#endif
diff --git a/agent/test/Makefile.in b/agent/test/Makefile.in
index f3f0e5e..2d700cd 100644
--- a/agent/test/Makefile.in
+++ b/agent/test/Makefile.in
@@ -27,10 +27,27 @@
# openolt.proto and tech_profile.proto
OPENOLT_PROTO_VER ?= v1.0.3
+GTEST_VER ?= release-1.8.0
+gtest-target = $(HOME)/openolt-agent-test-lib/gtest/$(GTEST_VER)/lib/libgtest.a
+
+CMOCK_VER ?= 0207b30
+cmock-target = $(HOME)/openolt-agent-test-lib/cmock/$(CMOCK_VER)/include/cmock.h
+
+GMOCK_GLOBAL_VER ?= 1.0.2
+gmock-global-target = $(HOME)/openolt-agent-test-lib/gmock-global/$(GMOCK_GLOBAL_VER)/gmock-global/gmock-global.h
+
+
# GRPC installation
GRPC_ADDR = https://github.com/grpc/grpc
GRPC_DST = /tmp/grpc
GRPC_VER = v1.10.x
+grpc-cpp-plugin-bin = $(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)/bin/grpc_cpp_plugin
+
+# Protobuf installation
+PROTOBUF_VER = 3.5.0
+PROTOBUF_ADDR = https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOBUF_VER)/protobuf-cpp-$(PROTOBUF_VER).tar.gz
+PROTOBUF_DST = /tmp/protobuf-$(PROTOBUF_VER)
+protoc-bin = $(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)/bin/protoc
USER := $(shell echo $(USER))
#
@@ -43,63 +60,79 @@
CXX = g++-4.9
CXXFLAGS += -g -O2
-CXXFLAGS += $(shell pkg-config --cflags-only-I grpc++)
-CPPFLAGS += `pkg-config --cflags protobuf grpc`
+CXXFLAGS += $(shell PKG_CONFIG_PATH=$(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)/lib/pkgconfig pkg-config --cflags-only-I grpc++)
+CPPFLAGS += `PKG_CONFIG_PATH=$(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)/lib/pkgconfig pkg-config --cflags protobuf grpc`
CXXFLAGS += -std=c++11 -fpermissive -Wno-literal-suffix
CXXFLAGS += -DTEST_MODE -DENABLE_LOG
LDFLAGS +=
-LDFLAGS += `pkg-config --libs protobuf grpc++ grpc` -ldl -lgpr
+LDFLAGS += `PKG_CONFIG_PATH=$(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)/lib/pkgconfig pkg-config --libs protobuf grpc++ grpc` -ldl -lgpr
CXXFLAGSDEVICE = -I../device -I../device/$(OPENOLTDEVICE) -I../device/generic
export CXX CXXFLAGS OPENOLT_PROTO_VER
-BAL_API_DIR=bal-api-3.2.3.2
+BAL_API_VER=bal-api-3.2.3.2
+BAL_API_DIR=$(BAL_API_VER)
BALLIBNAME=bcm_host_api_stubs
BALLIBDIR=$(BAL_API_DIR)/stubs
BAL_INC = -I$(BAL_API_DIR)/include \
-I$(BAL_API_DIR)/include/object_model
-CXXFLAGS += $(BAL_INC)
+TEST_LIB_INC = -I$(HOME)/openolt-agent-test-lib/gtest/$(GTEST_VER)/include \
+ -I$(HOME)/openolt-agent-test-lib/cmock/$(CMOCK_VER)/include \
+ -I$(HOME)/openolt-agent-test-lib/gmock-global/$(GMOCK_GLOBAL_VER)
+CXXFLAGS += $(BAL_INC) $(TEST_LIB_INC)
-
-prereq:
+prereqs-system:
sudo apt-get -q -y install git pkg-config build-essential autoconf libtool libgflags-dev libgtest-dev clang libc++-dev unzip docker.io
sudo apt-get install -y build-essential autoconf libssl-dev gawk debhelper dh-systemd init-system-helpers curl cmake ccache g++-4.9
- # Install GRPC, libprotobuf and protoc
+prereqs-local: $(protoc-bin) $(grpc-cpp-plugin-bin) prereqs-test-lib
+
+$(protoc-bin):
+ # Install protobuf
+ rm -rf $(PROTOBUF_DST)
+ cd /tmp && wget $(PROTOBUF_ADDR)
+ cd /tmp && tar -zxvf protobuf-cpp-$(PROTOBUF_VER).tar.gz
+ cd $(PROTOBUF_DST) && ./autogen.sh
+ mkdir -p $(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)
+ cd $(PROTOBUF_DST) && ./configure --prefix=$(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)
+ make -C $(PROTOBUF_DST)
+ make -C $(PROTOBUF_DST) install
+
+$(grpc-cpp-plugin-bin):
+ # Install GRPC, protoc
rm -rf $(GRPC_DST)
- git clone -b $(GRPC_VER) $(GRPC_ADDR) $(GRPC_DST)
+ cd /tmp && git clone -b $(GRPC_VER) $(GRPC_ADDR) $(GRPC_DST)
cd $(GRPC_DST) && git submodule update --init
- cd $(GRPC_DST)/third_party/protobuf && ./autogen.sh && ./configure
- make -C $(GRPC_DST)/third_party/protobuf
- sudo make -C $(GRPC_DST)/third_party/protobuf install
- sudo ldconfig
+ mkdir -p $(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)
make -C $(GRPC_DST)
- sudo make -C $(GRPC_DST) install
- sudo ldconfig
+ make -C $(GRPC_DST) install prefix=$(HOME)/openolt-agent-test-lib/grpc/$(GRPC_VER)
-prereq-mock-lib: gtest cmock gmock-global
+prereqs-test-lib: $(gtest-target) $(cmock-target) $(gmock-global-target)
-gtest:
- # Install gtest and gmock
+$(gtest-target):
+ # Install gtest
rm -rf /tmp/googletest && cd /tmp && git clone https://github.com/google/googletest.git
- cd /tmp/googletest && git checkout release-1.8.0
- cd /tmp/googletest && cmake CMakeLists.txt
+ cd /tmp/googletest && git checkout $(GTEST_VER)
+ mkdir -p $(HOME)/openolt-agent-test-lib/gtest/$(GTEST_VER)
+ cd /tmp/googletest && cmake CMakeLists.txt -DCMAKE_INSTALL_PREFIX=$(HOME)/openolt-agent-test-lib/gtest/$(GTEST_VER)
make -C /tmp/googletest
- sudo make -C /tmp/googletest install
+ make -C /tmp/googletest install
-cmock:
+$(cmock-target):
# Install c-mock
rm -rf /tmp/C-Mock && cd /tmp && git clone https://github.com/hjagodzinski/C-Mock.git
- cd /tmp/C-Mock && git checkout 0207b3026f04bbdf0bd9d9f8dfd00945a4318251
- make -C /tmp/C-Mock
- sudo make -C /tmp/C-Mock install
+ cd /tmp/C-Mock && git checkout $(CMOCK_VER)
+ mkdir -p $(HOME)/openolt-agent-test-lib/cmock/$(CMOCK_VER)
+ make -C /tmp/C-Mock install PREFIX=$(HOME)/openolt-agent-test-lib/cmock/$(CMOCK_VER)
-gmock-global:
+$(gmock-global-target):
# Install gmock-global
rm -rf /tmp/gmock-global && cd /tmp && git clone https://github.com/apriorit/gmock-global.git
- cd /tmp/gmock-global && git checkout 1.0.2
- sudo cp -rf /tmp/gmock-global/include/gmock-global /usr/local/include/
+ cd /tmp/gmock-global && git checkout $(GMOCK_GLOBAL_VER)
+ mkdir -p $(HOME)/openolt-agent-test-lib/gmock-global/$(GMOCK_GLOBAL_VER)
+ cp -rf /tmp/gmock-global/include/gmock-global $(HOME)/openolt-agent-test-lib/gmock-global/$(GMOCK_GLOBAL_VER)
+
########################################################################
##
##
@@ -109,7 +142,7 @@
.DEFAULT_GOAL := all
-.PHONY = bcm_host_api_stubs libopenoltapi.a libopenolt.a build clean
+.PHONY = bcm_host_api_stubs libopenoltapi.a libopenolt.a build clean prereqs-system prereqs-local
all: bcm_host_api_stubs libopenoltapi.a libopenolt.a build
@@ -120,26 +153,26 @@
#TEST_SRCS = $($(filter-out src/bal_stub.cc, $(wildcard src/*.cc)))
TEST_SRCS = src/main_test.cc src/bal_mocker.cc src/test_core.cc
TEST_OBJS = $(TEST_SRCS:.cc=.o)
+
build: $(TEST_OBJS)
- $(CXX) $(shell cmock-config --libs) -L$(TEST_OPENOLT_LIB_DIR) -L/usr/lib/ -I/usr/include -I./inc -o $(TEST_BIN) $(TEST_OBJS) -lgmock -lgtest -lopenolt -lopenoltapi $(LDFLAGS)
+ $(CXX) $(shell cmock-config --libs $(HOME)/openolt-agent-test-lib/gtest/$(GTEST_VER)/lib) -L$(TEST_OPENOLT_LIB_DIR) -L/usr/lib/ -I/usr/include -I./inc -I../src -o $(TEST_BIN) $(TEST_OBJS) -lgmock -lgtest -lopenolt -lopenoltapi $(LDFLAGS)
src/%.o: src/%.cc
- $(CXX) $(CXXFLAGS) $(CXXFLAGSDEVICE) -I./inc -I../common -I/usr/include -c $< -o $@
+ $(CXX) $(CXXFLAGS) $(CXXFLAGSDEVICE) $(TEST_LIB_INC) -I./inc -I../common -I../src -I/usr/include -c $< -o $@
# bcm_host_api_stubs
-BAL_API_DIR=bal-api-3.2.3.2
bcm_host_api_stubs:
# TODO: There is temporary hack below to introduce the definition of bcmos_mutex.
- # This should ideally come as part of bal-api-3.2.3.2
+ # This should ideally come as part of bal-api-x.x.x.x
if [ -d $(BAL_API_DIR) ]; then \
echo "$(BAL_API_DIR) exists"; \
else \
- git clone https://github.com/balapi/bal-api-3.2.3.2.git ;\
- sed -i "\$$i #define BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT 0" ./bal-api-3.2.3.2/include/bcmos_system.h; \
- sed -i "\$$i struct bcmos_mutex \{ pthread_mutex_t m; };" ./bal-api-3.2.3.2/include/bcmos_system.h; \
- sed -i "\$$i extern void* bcmos_calloc(uint32_t size);" ./bal-api-3.2.3.2/include/bcmos_common.h; \
- sed -i "\$$i #define BCMOLT_INTERFACE_TYPE_EPON_1_G 3" ./bal-api-3.2.3.2/include/bcmos_common.h; \
- sed -i "\$$i #define BCMOLT_INTERFACE_TYPE_EPON_10_G 4" ./bal-api-3.2.3.2/include/bcmos_common.h; \
+ git clone https://github.com/balapi/$(BAL_API_VER).git ;\
+ sed -i "\$$i #define BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT 0" ./$(BAL_API_DIR)/include/bcmos_system.h; \
+ sed -i "\$$i struct bcmos_mutex \{ pthread_mutex_t m; };" ./$(BAL_API_DIR)/include/bcmos_system.h; \
+ sed -i "\$$i extern void* bcmos_calloc(uint32_t size);" ./$(BAL_API_DIR)/include/bcmos_common.h; \
+ sed -i "\$$i #define BCMOLT_INTERFACE_TYPE_EPON_1_G 3" ./$(BAL_API_DIR)/include/bcmos_common.h; \
+ sed -i "\$$i #define BCMOLT_INTERFACE_TYPE_EPON_10_G 4" ./$(BAL_API_DIR)/include/bcmos_common.h; \
fi
# openoltapi
@@ -161,16 +194,16 @@
ar cr lib/$@ $^
ranlib lib/$@
../common/%.o: ../common/%.cc
- $(CXX) $(CXXFLAGS) $(CXXFLAGSDEVICE) -I../common -I./inc -I./device/$(OPENOLTDEVICE) -c $< -o $@
+ $(CXX) $(CXXFLAGS) $(CXXFLAGSDEVICE) -I../common -I./inc -I../src -c $< -o $@
../src/%.o: ../src/%.cc
- $(CXX) $(CXXFLAGS) $(CXXFLAGSDEVICE) -I../common -I./inc -I./device/$(OPENOLTDEVICE) -c $< -o $@
+ $(CXX) $(CXXFLAGS) $(CXXFLAGSDEVICE) -I../common -I./inc -I../src -c $< -o $@
src/%.o: src/%.cc
- $(CXX) $(CXXFLAGS) $(CXXFLAGSDEVICE) -I../common -I./inc -I./device/$(OPENOLTDEVICE) -c $< -o $@
+ $(CXX) $(CXXFLAGS) $(CXXFLAGSDEVICE) -I../common -I./inc -I../src -c $< -o $@
../device/$(OPENOLTDEVICE)/%.o: ../device/$(OPENOLTDEVICE)/%.cc
- $(CXX) $(CXXFLAGS) $(CXXFLAGSDEVICE) -I../common -I./inc -I./device/$(OPENOLTDEVICE) -c $< -o $@
+ $(CXX) $(CXXFLAGS) $(CXXFLAGSDEVICE) -I../common -I./inc -I../src -c $< -o $@
test: all
- ./test_openolt --gtest_output="xml:./test_openolt_report.xml"
+ ./test_openolt --gtest_output="xml:./test_openolt_report_xunit.xml"
clean:
- rm -f src/*.o lib/*.a ../src/*.o ../common/*.o ./test_openolt ./test_openolt_report.xml
+ rm -f src/*.o lib/*.a ../src/*.o ../common/*.o ./test_openolt ./test_openolt_report_xunit.xml
diff --git a/agent/test/README.md b/agent/test/README.md
index 6a3b40a..8b34329 100644
--- a/agent/test/README.md
+++ b/agent/test/README.md
@@ -29,9 +29,7 @@
make OPENOLT_PROTO_VER=master test
```
-By default, the OPENOLT_PROTO_VER defaults to git tag *v1.0.3* of https://github.com/opencord/voltha-protos repo.
-
-Once you have successfully built and run the unit-test, the test report will be available in `test_openolt_report.xml` file in `agent/test`.
+Once you have successfully built and run the unit-test, the test report will be available in `test_openolt_report_xunit.xml` file in `agent/test`.
To clean all build artifacts and test reports, do `make clean` in `agent/test`.
## Adding new Unit Test Cases
diff --git a/agent/test/configure b/agent/test/configure
index 7c41265..f861fd7 100755
--- a/agent/test/configure
+++ b/agent/test/configure
@@ -574,8 +574,6 @@
LIBOBJS=
cross_compiling=no
subdirs=
-MFLAGS=
-MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='openolt'
diff --git a/agent/test/inc/bal_mocker.h b/agent/test/inc/bal_mocker.h
index f60c581..50b981d 100644
--- a/agent/test/inc/bal_mocker.h
+++ b/agent/test/inc/bal_mocker.h
@@ -15,7 +15,7 @@
*/
#ifndef __BAL_MOCKER_H__
#define __BAL_MOCKER_H__
-#include <cmock/cmock.h>
+#include <cmock.h>
#include <gmock-global/gmock-global.h>
#include <cstdlib>
#include <grpc++/grpc++.h>
diff --git a/agent/test/src/test_core.cc b/agent/test/src/test_core.cc
index 1d3c2ef..137faac 100644
--- a/agent/test/src/test_core.cc
+++ b/agent/test/src/test_core.cc
@@ -17,6 +17,7 @@
#include "Queue.h"
#include "bal_mocker.h"
#include "core.h"
+#include "core_data.h"
#include <future>
using namespace testing;
using namespace std;
@@ -227,7 +228,7 @@
// For testing Enable/Disable functionality
////////////////////////////////////////////////////////////////////////
-int num_of_pon_ports = 16;
+int num_of_pon_port = 16;
// Create a mock function for bcmolt_cfg_get__olt_topology_stub C++ function
MOCK_GLOBAL_FUNC2(bcmolt_cfg_get__olt_topology_stub, bcmos_errno(bcmolt_oltid, void*));
@@ -243,7 +244,7 @@
BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
- olt_cfg.data.topology.topology_maps.len = num_of_pon_ports;
+ olt_cfg.data.topology.topology_maps.len = num_of_pon_port;
EXPECT_GLOBAL_CALL(bcmolt_cfg_get__olt_topology_stub, bcmolt_cfg_get__olt_topology_stub(_, _))
.WillOnce(DoAll(SetArg1ToBcmOltCfg(olt_cfg), Return(bal_cfg_get_stub_res)));
@@ -309,7 +310,7 @@
pon_cfg.data.state = BCMOLT_INTERFACE_STATE_INACTIVE;
EXPECT_GLOBAL_CALL(bcmolt_cfg_get__pon_intf_stub, bcmolt_cfg_get__pon_intf_stub(_, _))
- .Times(num_of_pon_ports)
+ .Times(num_of_pon_port)
.WillRepeatedly(DoAll(SetArg1ToBcmOltPonCfg(pon_cfg), Return(olt_cfg_get_pon_stub_res)));
bcmolt_tm_sched_cfg tm_sched_cfg;
@@ -318,7 +319,7 @@
tm_sched_cfg.data.state = BCMOLT_CONFIG_STATE_NOT_CONFIGURED;
EXPECT_GLOBAL_CALL(bcmolt_cfg_get__tm_sched_stub, bcmolt_cfg_get__tm_sched_stub(_, _))
- .Times(num_of_pon_ports)
+ .Times(num_of_pon_port)
.WillRepeatedly(DoAll(SetArg1ToBcmOltTmSchedCfg(tm_sched_cfg), Return(olt_cfg_get_tmstub_res)));
olt_reenable_res = Reenable_();
@@ -343,10 +344,10 @@
pon_cfg.data.state = BCMOLT_INTERFACE_STATE_INACTIVE;
EXPECT_GLOBAL_CALL(bcmolt_cfg_get__pon_intf_stub, bcmolt_cfg_get__pon_intf_stub(_, _))
- .Times(num_of_pon_ports)
+ .Times(num_of_pon_port)
.WillRepeatedly(DoAll(SetArg1ToBcmOltPonCfg(pon_cfg), Return(olt_cfg_get_pon_stub_res)));
EXPECT_CALL(balMock,bcmolt_oper_submit(_, _))
- .Times(num_of_pon_ports)
+ .Times(num_of_pon_port)
.WillRepeatedly(Return(olt_oper_res));
olt_reenable_res = Reenable_();
@@ -372,7 +373,7 @@
BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
- olt_cfg.data.topology.topology_maps.len = num_of_pon_ports;
+ olt_cfg.data.topology.topology_maps.len = num_of_pon_port;
}
virtual void TearDown() {