VOL-2263: Issues with creating itu-pon-alloc object
- Wait for asynchronous ITU PON Alloc Configuration Completed
indication before reporting the response to CreateSched/RemoveSched
from voltha.
Change-Id: I56a06970625e891e197ff9d87e02d73b06070af5
diff --git a/agent/common/Queue.h b/agent/common/Queue.h
index 30fbbda..2e366ce 100644
--- a/agent/common/Queue.h
+++ b/agent/common/Queue.h
@@ -18,17 +18,21 @@
{
public:
- std::pair<T, bool> pop(int timeout)
+ // timeout is in milliseconds, wait_granularity in milliseconds
+ std::pair<T, bool> pop(int timeout, int wait_granularity=10)
{
std::cv_status status = std::cv_status::no_timeout;
std::unique_lock<std::mutex> mlock(mutex_);
static int duration = 0;
+ if (timeout < wait_granularity) {
+ wait_granularity = timeout;
+ }
while (queue_.empty())
{
- status = cond_.wait_for(mlock, std::chrono::seconds(1));
+ status = cond_.wait_for(mlock, std::chrono::milliseconds(wait_granularity));
if (status == std::cv_status::timeout)
{
- duration++;
+ duration+=wait_granularity;
if (duration > timeout)
{
duration = 0;
diff --git a/agent/common/core.h b/agent/common/core.h
index bfb6c9b..4e79d2c 100644
--- a/agent/common/core.h
+++ b/agent/common/core.h
@@ -38,7 +38,7 @@
BCM_LOG(level, id, "%s" fmt "%s", LIGHT_GREEN, ##__VA_ARGS__, NONE); \
else \
BCM_LOG(INFO, id, fmt, ##__VA_ARGS__);
-#define COLLECTION_PERIOD 15
+#define COLLECTION_PERIOD 15 // in seconds
#define BAL_DYNAMIC_LIST_BUFFER_SIZE (32 * 1024)
#define MAX_REGID_LENGTH 36
@@ -74,6 +74,33 @@
STATE = 26
};
+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;
+
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);
diff --git a/agent/common/server.cc b/agent/common/server.cc
index 9e1eb86..1c67137 100644
--- a/agent/common/server.cc
+++ b/agent/common/server.cc
@@ -182,7 +182,7 @@
state.connect();
while (state.is_connected()) {
- std::pair<openolt::Indication, bool> ind = oltIndQ.pop(COLLECTION_PERIOD);
+ std::pair<openolt::Indication, bool> ind = oltIndQ.pop(COLLECTION_PERIOD*1000, 1000);
if (ind.second == false) {
/* timeout - do lower priority periodic stuff like stats */
stats_collection();
diff --git a/agent/src/core.cc b/agent/src/core.cc
index 148ae08..691254b 100644
--- a/agent/src/core.cc
+++ b/agent/src/core.cc
@@ -142,11 +142,20 @@
/* '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;
+#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;
+
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
@@ -578,6 +587,60 @@
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;
+
+ // 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;
+ }
+ 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);
+ return err;
+}
+
char* openolt_read_sysinfo(const char* field_name, char* field_val)
{
FILE *fp;
@@ -865,6 +928,7 @@
}
bcmos_fastlock_init(&data_lock, 0);
+ bcmos_fastlock_init(&alloc_cfg_wait_lock, 0);
OPENOLT_LOG(INFO, openolt_log_id, "Enable OLT - %s-%s\n", VENDOR_ID, MODEL_ID);
//check BCM daemon is connected or not
@@ -2639,8 +2703,17 @@
port_no %u, alloc_id %d, err = %s\n", intf_id, onu_id,uni_id,port_no,alloc_id, bcmos_strerror(err));
return err;
}
- OPENOLT_LOG(INFO, openolt_log_id, "Create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d, port_no %u, \
-alloc_id %d\n", intf_id,onu_id,uni_id,port_no,alloc_id);
+
+ err = wait_for_alloc_action(intf_id, alloc_id, ALLOC_OBJECT_CREATE);
+ if (err) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d,\
+port_no %u, alloc_id %d, err = %s\n", intf_id, onu_id,uni_id,port_no,alloc_id, bcmos_strerror(err));
+ return err;
+ }
+
+ OPENOLT_LOG(INFO, openolt_log_id, "create upstream bandwidth allocation success, intf_id %d, onu_id %d, uni_id %d,\
+port_no %u, alloc_id %d\n", intf_id, onu_id,uni_id,port_no,alloc_id);
+
}
return BCM_ERR_OK;
@@ -2688,12 +2761,14 @@
bcmos_errno RemoveSched(int intf_id, int onu_id, int uni_id, int alloc_id, std::string direction) {
bcmos_errno err;
+ uint16_t sched_id;
if (direction == upstream) {
bcmolt_itupon_alloc_cfg cfg;
bcmolt_itupon_alloc_key key = { };
key.pon_ni = intf_id;
key.alloc_id = alloc_id;
+ sched_id = alloc_id;
BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
@@ -2702,18 +2777,25 @@
direction.c_str(), intf_id, alloc_id, bcmos_strerror(err));
return err;
}
- OPENOLT_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, intf_id %d, alloc_id %d\n", \
- direction.c_str(), intf_id, alloc_id);
+
+ err = wait_for_alloc_action(intf_id, alloc_id, ALLOC_OBJECT_DELETE);
+ if (err) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove scheduler, direction = %s, intf_id %d, alloc_id %d, err = %s\n",
+ direction.c_str(), intf_id, alloc_id, bcmos_strerror(err));
+ return err;
+ }
} else if (direction == downstream) {
bcmolt_tm_sched_cfg cfg;
bcmolt_tm_sched_key key = { };
if (is_tm_sched_id_present(intf_id, onu_id, uni_id, direction)) {
key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
+ sched_id = key.id;
} else {
OPENOLT_LOG(INFO, openolt_log_id, "schduler not present in %s, err %d\n", direction.c_str(), err);
return BCM_ERR_OK;
}
+
BCMOLT_CFG_INIT(&cfg, tm_sched, key);
err = bcmolt_cfg_clear(dev_id, &(cfg.hdr));
if (err) {
@@ -2721,10 +2803,10 @@
intf_id %d, onu_id %d, err = %s\n", direction.c_str(), key.id, intf_id, onu_id, bcmos_strerror(err));
return err;
}
- OPENOLT_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, id %d, intf_id %d, onu_id %d\n", \
- direction.c_str(), key.id, intf_id, onu_id);
}
+ OPENOLT_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, id %d, intf_id %d, onu_id %d\n",
+ direction.c_str(), sched_id, intf_id, onu_id);
free_tm_sched_id(intf_id, onu_id, uni_id, direction);
return BCM_ERR_OK;
}
diff --git a/agent/src/indications.cc b/agent/src/indications.cc
index 07edbd9..8425f0b 100644
--- a/agent/src/indications.cc
+++ b/agent/src/indications.cc
@@ -34,7 +34,8 @@
using grpc::Status;
extern Queue<openolt::Indication> oltIndQ;
-//Queue<openolt::Indication*> oltIndQ;
+extern std::map<alloc_cfg_compltd_key, Queue<alloc_cfg_complete_result> *> alloc_cfg_compltd_map;
+extern bcmos_fastlock alloc_cfg_wait_lock;
bool subscribed = false;
@@ -544,6 +545,67 @@
bcmolt_msg_free(msg);
}
+static void ItuPonAllocConfigCompletedInd(bcmolt_devid olt, bcmolt_msg *msg) {
+
+ switch (msg->obj_type) {
+ case BCMOLT_OBJ_ID_ITUPON_ALLOC:
+ switch (msg->subgroup) {
+ case BCMOLT_ITUPON_ALLOC_AUTO_SUBGROUP_CONFIGURATION_COMPLETED:
+ {
+ bcmolt_itupon_alloc_configuration_completed *pkt =
+ (bcmolt_itupon_alloc_configuration_completed*)msg;
+ bcmolt_itupon_alloc_configuration_completed_data *pkt_data =
+ &((bcmolt_itupon_alloc_configuration_completed*)msg)->data;
+
+ alloc_cfg_compltd_key key((uint32_t)pkt->key.pon_ni, (uint32_t) pkt->key.alloc_id);
+ alloc_cfg_complete_result res;
+ res.pon_intf_id = pkt->key.pon_ni;
+ res.alloc_id = pkt->key.alloc_id;
+
+ pkt_data->status == BCMOLT_RESULT_SUCCESS ? res.status = ALLOC_CFG_STATUS_SUCCESS: res.status = ALLOC_CFG_STATUS_FAIL;
+ switch (pkt_data->new_state) {
+ case BCMOLT_ACTIVATION_STATE_NOT_CONFIGURED:
+ res.state = ALLOC_OBJECT_STATE_NOT_CONFIGURED;
+ break;
+ case BCMOLT_ACTIVATION_STATE_INACTIVE:
+ res.state = ALLOC_OBJECT_STATE_INACTIVE;
+ break;
+ case BCMOLT_ACTIVATION_STATE_PROCESSING:
+ res.state = ALLOC_OBJECT_STATE_PROCESSING;
+ break;
+ case BCMOLT_ACTIVATION_STATE_ACTIVE:
+ res.state = ALLOC_OBJECT_STATE_ACTIVE;
+ break;
+ default:
+ OPENOLT_LOG(ERROR, openolt_log_id, "invalid itu pon alloc activation new_state, pon_intf %u, alloc_id %u, new_state %d\n",
+ pkt->key.pon_ni, pkt->key.alloc_id, pkt_data->new_state);
+ res.state = ALLOC_OBJECT_STATE_NOT_CONFIGURED;
+ }
+ OPENOLT_LOG(INFO, openolt_log_id, "received itu pon alloc cfg complete ind, pon intf %u, alloc_id %u, status %u, new_state %u\n",
+ pkt->key.pon_ni, pkt->key.alloc_id, pkt_data->status, pkt_data->new_state);
+
+ bcmos_fastlock_lock(&alloc_cfg_wait_lock);
+ // Push the result from BAL to queue
+ std::map<alloc_cfg_compltd_key, Queue<alloc_cfg_complete_result> *>::iterator it = alloc_cfg_compltd_map.find(key);
+ if (it == alloc_cfg_compltd_map.end()) {
+ // could be case of spurious aysnc response, OR, the application timed-out waiting for response and cleared the key.
+ bcmolt_msg_free(msg);
+ OPENOLT_LOG(ERROR, openolt_log_id, "alloc config key not found for alloc_id = %u, pon_intf = %u\n", pkt->key.alloc_id, pkt->key.pon_ni);
+ bcmos_fastlock_unlock(&alloc_cfg_wait_lock, 0);
+ return;
+ }
+ if (it->second) {
+ // Push the result
+ it->second->push(res);
+ }
+ bcmos_fastlock_unlock(&alloc_cfg_wait_lock, 0);
+ }
+ }
+ }
+
+ bcmolt_msg_free(msg);
+}
+
static void FlowOperIndication(bcmolt_devid olt, bcmolt_msg *msg) {
openolt::Indication ind;
OPENOLT_LOG(DEBUG, openolt_log_id, "flow oper state indication\n");
@@ -987,6 +1049,15 @@
if(rc != BCM_ERR_OK)
return Status(grpc::StatusCode::INTERNAL, "Packet indication subscribe failed");
+ rx_cfg.obj_type = BCMOLT_OBJ_ID_ITUPON_ALLOC;
+ rx_cfg.rx_cb = ItuPonAllocConfigCompletedInd;
+ rx_cfg.flags = BCMOLT_AUTO_FLAGS_NONE;
+ rx_cfg.subgroup = bcmolt_itupon_alloc_auto_subgroup_configuration_completed;
+ rc = bcmolt_ind_subscribe(current_device, &rx_cfg);
+ if(rc != BCM_ERR_OK)
+ return Status(grpc::StatusCode::INTERNAL, "ITU PON Alloc Configuration \
+Complete Indication subscribe failed");
+
subscribed = true;
return Status::OK;