[VOL-3871] Support all T-Cont Types

- Use CIR in traffic shaping info as assured bandwidth
- Use GIR in traffic shaping info as fixed bandwidth
- Set alloc type according to GIR value to accomodate T-Cont Type 1
- Reorganize bandwidth value checks
- In case of AdditionalBW_None, max bw is not equalized with guaranteed bw anymore if they are not equal.
- Set CBR_NRT_BW (instead of CBR_RT_BW) as GIR

Change-Id: I752a6b273b124138e68f3a4201fc5b93771c2adc
diff --git a/agent/src/core_api_handler.cc b/agent/src/core_api_handler.cc
index 95a3a67..a987540 100644
--- a/agent/src/core_api_handler.cc
+++ b/agent/src/core_api_handler.cc
@@ -2308,91 +2308,98 @@
         key.pon_ni = intf_id;
         key.alloc_id = alloc_id;
         int bw_granularity = (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY;
+        /*
+            PIR: Maximum Bandwidth
+            CIR: Assured Bandwidth
+            GIR: Fixed Bandwidth
+        */
         int pir_bw = tf_sh_info.pir()*125; // conversion from kbps to bytes/sec
         int cir_bw = tf_sh_info.cir()*125; // conversion from kbps to bytes/sec
+        int gir_bw = tf_sh_info.gir()*125; // conversion from kbps to bytes/sec
+        int guaranteed_bw = cir_bw+gir_bw;
         //offset to match bandwidth granularity
         int offset_pir_bw = pir_bw%bw_granularity;
-        int offset_cir_bw = cir_bw%bw_granularity;
+        int offset_gir_bw = gir_bw%bw_granularity;
+        int offset_guaranteed_bw = guaranteed_bw%bw_granularity;
 
         pir_bw = pir_bw - offset_pir_bw;
-        cir_bw = cir_bw - offset_cir_bw;
+        gir_bw = gir_bw - offset_gir_bw;
+        guaranteed_bw = guaranteed_bw - offset_guaranteed_bw;
 
         BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
 
+        OPENOLT_LOG(INFO, openolt_log_id, "Creating alloc_id %d with pir = %d bytes/sec, cir = %d bytes/sec, gir = %d bytes/sec, additional_bw = %d.\n", alloc_id, pir_bw, cir_bw, gir_bw, additional_bw);
+
+        if (pir_bw == 0) {
+            OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be at least %d bytes/sec\n",
+                        (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
+            return BCM_ERR_PARM;
+        } else if (pir_bw < guaranteed_bw) {
+            OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed bandwidth (%d)\n",
+                        pir_bw, guaranteed_bw);
+            return BCM_ERR_PARM;
+        }
+
+        // Setting additional bw eligibility and validating bw provisionings
         switch (additional_bw) {
-            case 2: //AdditionalBW_BestEffort
-                if (pir_bw == 0) {
-                   OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
-%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
-                   return BCM_ERR_PARM;
-                } else if (pir_bw < cir_bw) {
-                   OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
-bandwidth (%d)\n", pir_bw, cir_bw);
-                   return BCM_ERR_PARM;
-                } else if (pir_bw == cir_bw) {
-                   OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
-bandwidth for additional bandwidth eligibility of type best_effort\n");
-                   return BCM_ERR_PARM;
+
+            case tech_profile::AdditionalBW::AdditionalBW_BestEffort: //AdditionalBW_BestEffort - For T-Cont types 4 & 5
+                if (pir_bw == guaranteed_bw) {
+                    OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
+bandwidth for additional bandwidth eligibility of type Best Effort\n");
+                    return BCM_ERR_PARM;
                 }
                 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_BEST_EFFORT);
                 break;
-            case 1: //AdditionalBW_NA
-                if (pir_bw == 0) {
-                    OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
-%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
-                    return BCM_ERR_PARM;
-                } else if (cir_bw == 0) {
+
+            case tech_profile::AdditionalBW::AdditionalBW_NA: //AdditionalBW_NA - For T-Cont types 3 & 5
+                if (guaranteed_bw == 0) {
                     OPENOLT_LOG(ERROR, openolt_log_id, "Guaranteed bandwidth must be greater than zero for \
 additional bandwidth eligibility of type Non-Assured (NA)\n");
                     return BCM_ERR_PARM;
-                } else if (pir_bw < cir_bw) {
-                    OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
-bandwidth (%d)\n", pir_bw, cir_bw);
-                    return BCM_ERR_PARM;
-                } else if (pir_bw == cir_bw) {
+                } else if (pir_bw == guaranteed_bw) {
                     OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
-bandwidth for additional bandwidth eligibility of type non_assured\n");
+bandwidth for additional bandwidth eligibility of type Non-Assured\n");
                     return BCM_ERR_PARM;
                 }
                 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NON_ASSURED);
                 break;
-            case 0: //AdditionalBW_None
-                if (pir_bw == 0) {
-                    OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
-16000 bytes/sec\n");
-                    return BCM_ERR_PARM;
-                } else if (cir_bw == 0) {
-                   OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
+
+            case tech_profile::AdditionalBW::AdditionalBW_None: //AdditionalBW_None - For T-Cont types 1 & 2
+                if (guaranteed_bw != pir_bw) {
+                    OPENOLT_LOG(ERROR, openolt_log_id, "Guaranteed bandwidth must be equal to maximum bandwidth \
 for additional bandwidth eligibility of type None\n");
                     return BCM_ERR_PARM;
-                } else if (pir_bw > cir_bw) {
-                   OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
-for additional bandwidth eligibility of type None\n");
-                   OPENOLT_LOG(ERROR, openolt_log_id, "Setting Maximum bandwidth (%d) to Guaranteed \
-bandwidth in None eligibility\n", pir_bw);
-                   cir_bw = pir_bw;
-                } else if (pir_bw < cir_bw) {
-                   OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
-bandwidth (%d)\n", pir_bw, cir_bw);
-                   OPENOLT_LOG(ERROR, openolt_log_id, "Setting Maximum bandwidth (%d) to Guaranteed \
-bandwidth in None eligibility\n", pir_bw);
-                   cir_bw = pir_bw;
                 }
                 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NONE);
                 break;
+
             default:
+                OPENOLT_LOG(ERROR, openolt_log_id, "Invalid additional bandwidth eligibility value (%d) supplied.\n", additional_bw);
                 return BCM_ERR_PARM;
         }
+
         /* CBR Real Time Bandwidth which require shaping of the bandwidth allocations
            in a fine granularity. */
         BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_bw, 0);
+        /* Since we can assign minimum 64000 bytes/sec for cbr_rt_bw, we prefer assigning
+           gir_bw to cbr_nrt_bw to allow smaller amounts.
+           TODO: Specify CBR_RT_BW and CBR_NRT_BW separately from VOLTHA */
         /* Fixed Bandwidth with no critical requirement of shaping */
-        BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_bw, 0);
+        BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_bw, gir_bw);
         /* Dynamic bandwidth which the OLT is committed to allocate upon demand */
-        BCMOLT_MSG_FIELD_SET(&cfg, sla.guaranteed_bw, cir_bw);
+        BCMOLT_MSG_FIELD_SET(&cfg, sla.guaranteed_bw, guaranteed_bw);
         /* Maximum allocated bandwidth allowed for this alloc ID */
         BCMOLT_MSG_FIELD_SET(&cfg, sla.maximum_bw, pir_bw);
-        BCMOLT_MSG_FIELD_SET(&cfg, sla.alloc_type, BCMOLT_ALLOC_TYPE_NSR);
+
+        if (pir_bw == gir_bw) { // T-Cont Type 1 --> set alloc type to NONE
+            // the condition cir_bw == 0 is implicitly satistied
+            OPENOLT_LOG(INFO, openolt_log_id, "Setting alloc type to NONE since maximum bandwidth is equal to fixed bandwidth\n");
+            BCMOLT_MSG_FIELD_SET(&cfg, sla.alloc_type, BCMOLT_ALLOC_TYPE_NONE);
+        } else { // For other T-Cont types, set alloc type to NSR. TODO: read the default from a config file.
+            BCMOLT_MSG_FIELD_SET(&cfg, sla.alloc_type, BCMOLT_ALLOC_TYPE_NSR);
+        }
+
         /* Set to True for AllocID with CBR RT Bandwidth that requires compensation
            for skipped allocations during quiet window */
         BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_compensation, BCMOS_FALSE);
@@ -2409,7 +2416,7 @@
         err = bcmolt_cfg_set(dev_id, &cfg.hdr);
         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));
+port_no %u, alloc_id %d, err = %s (%s)\n", intf_id, onu_id,uni_id,port_no,alloc_id, bcmos_strerror(err), cfg.hdr.hdr.err_text);
             return err;
         }
 #ifndef SCALE_AND_PERF
diff --git a/agent/test/src/test_core.cc b/agent/test/src/test_core.cc
index 2d2bede..7f8a4df 100644
--- a/agent/test/src/test_core.cc
+++ b/agent/test/src/test_core.cc
@@ -1969,6 +1969,7 @@
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_BestEffort);
     traffic_sched->set_direction(tech_profile::Direction::UPSTREAM);
     traffic_sched->set_allocated_scheduler(scheduler);
+    traffic_shaping_info->set_gir(0);
     traffic_shaping_info->set_cir(64000);
     traffic_shaping_info->set_pir(0);
     traffic_sched->set_allocated_traffic_shaping_info(traffic_shaping_info);
@@ -1983,6 +1984,7 @@
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_BestEffort);
     traffic_sched->set_direction(tech_profile::Direction::UPSTREAM);
     traffic_sched->set_allocated_scheduler(scheduler);
+    traffic_shaping_info->set_gir(0);
     traffic_shaping_info->set_cir(64000);
     traffic_shaping_info->set_pir(32000);
     traffic_sched->set_allocated_traffic_shaping_info(traffic_shaping_info);
@@ -1997,6 +1999,7 @@
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_BestEffort);
     traffic_sched->set_direction(tech_profile::Direction::UPSTREAM);
     traffic_sched->set_allocated_scheduler(scheduler);
+    traffic_shaping_info->set_gir(0);
     traffic_shaping_info->set_cir(64000);
     traffic_shaping_info->set_pir(64000);
     traffic_sched->set_allocated_traffic_shaping_info(traffic_shaping_info);
@@ -2011,6 +2014,7 @@
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_NA);
     traffic_sched->set_direction(tech_profile::Direction::UPSTREAM);
     traffic_sched->set_allocated_scheduler(scheduler);
+    traffic_shaping_info->set_gir(0);
     traffic_shaping_info->set_cir(64000);
     traffic_shaping_info->set_pir(0);
     traffic_sched->set_allocated_traffic_shaping_info(traffic_shaping_info);
@@ -2025,6 +2029,7 @@
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_NA);
     traffic_sched->set_direction(tech_profile::Direction::UPSTREAM);
     traffic_sched->set_allocated_scheduler(scheduler);
+    traffic_shaping_info->set_gir(0);
     traffic_shaping_info->set_cir(0);
     traffic_shaping_info->set_pir(32000);
     traffic_sched->set_allocated_traffic_shaping_info(traffic_shaping_info);
@@ -2039,6 +2044,7 @@
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_NA);
     traffic_sched->set_direction(tech_profile::Direction::UPSTREAM);
     traffic_sched->set_allocated_scheduler(scheduler);
+    traffic_shaping_info->set_gir(0);
     traffic_shaping_info->set_cir(64000);
     traffic_shaping_info->set_pir(32000);
     traffic_sched->set_allocated_traffic_shaping_info(traffic_shaping_info);
@@ -2053,6 +2059,7 @@
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_NA);
     traffic_sched->set_direction(tech_profile::Direction::UPSTREAM);
     traffic_sched->set_allocated_scheduler(scheduler);
+    traffic_shaping_info->set_gir(0);
     traffic_shaping_info->set_cir(64000);
     traffic_shaping_info->set_pir(64000);
     traffic_sched->set_allocated_traffic_shaping_info(traffic_shaping_info);
@@ -2067,6 +2074,7 @@
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_None);
     traffic_sched->set_direction(tech_profile::Direction::UPSTREAM);
     traffic_sched->set_allocated_scheduler(scheduler);
+    traffic_shaping_info->set_gir(0);
     traffic_shaping_info->set_cir(64000);
     traffic_shaping_info->set_pir(0);
     traffic_sched->set_allocated_traffic_shaping_info(traffic_shaping_info);
@@ -2081,6 +2089,7 @@
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_None);
     traffic_sched->set_direction(tech_profile::Direction::UPSTREAM);
     traffic_sched->set_allocated_scheduler(scheduler);
+    traffic_shaping_info->set_gir(0);
     traffic_shaping_info->set_cir(0);
     traffic_shaping_info->set_pir(32000);
     traffic_sched->set_allocated_traffic_shaping_info(traffic_shaping_info);
@@ -2089,38 +2098,62 @@
     ASSERT_TRUE( status.error_message() != Status::OK.error_message() );
 }
 
-// Test 15 - CreateTrafficSchedulers-Upstream Success (AdditionalBW_None-Max BW > Guaranteed BW) case
-TEST_F(TestCreateTrafficSchedulers, AdditionalBW_NoneMaxBWGtGuaranteedBwSuccess) {
+// Test 15 - CreateTrafficSchedulers-Upstream Failure (AdditionalBW_None-Max BW > Guaranteed BW) case
+TEST_F(TestCreateTrafficSchedulers, AdditionalBW_NoneMaxBWGtGuaranteedBwFailure) {
     scheduler->set_direction(tech_profile::Direction::UPSTREAM);
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_None);
     traffic_sched->set_direction(tech_profile::Direction::UPSTREAM);
     traffic_sched->set_allocated_scheduler(scheduler);
+    traffic_shaping_info->set_gir(0);
     traffic_shaping_info->set_cir(64000);
     traffic_shaping_info->set_pir(128000);
     traffic_sched->set_allocated_traffic_shaping_info(traffic_shaping_info);
 
-    bcmos_errno olt_cfg_set_res = BCM_ERR_OK;
-    ON_CALL(balMock, bcmolt_cfg_set(_, _)).WillByDefault(Return(olt_cfg_set_res));
-
-    future<Status> future_res = async(launch::async, CreateTrafficSchedulers_, traffic_scheds);
-    future<int> push_alloc_cfg_complt = \
-    async(launch::async, TestCreateTrafficSchedulers::PushAllocCfgResult, ALLOC_OBJECT_STATE_ACTIVE, ALLOC_CFG_STATUS_SUCCESS);
-
-    Status status = future_res.get();
-    int res = push_alloc_cfg_complt.get();
-    ASSERT_TRUE( status.error_message() == Status::OK.error_message() );
+    Status status = CreateTrafficSchedulers_(traffic_scheds);
+    ASSERT_TRUE( status.error_message() != Status::OK.error_message() );
 }
 
-// Test 16 - CreateTrafficSchedulers-Upstream Success (AdditionalBW_None-Max BW < Guaranteed BW) case
-TEST_F(TestCreateTrafficSchedulers, AdditionalBW_NoneMaxBWLtGuaranteedBwSuccess) {
+// Test 16 - CreateTrafficSchedulers-Upstream Failure (AdditionalBW_None-Max BW < Guaranteed BW) case
+TEST_F(TestCreateTrafficSchedulers, AdditionalBW_NoneMaxBWLtGuaranteedBwFailure) {
     scheduler->set_direction(tech_profile::Direction::UPSTREAM);
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_None);
     traffic_sched->set_direction(tech_profile::Direction::UPSTREAM);
     traffic_sched->set_allocated_scheduler(scheduler);
+    traffic_shaping_info->set_gir(0);
     traffic_shaping_info->set_cir(64000);
     traffic_shaping_info->set_pir(32000);
     traffic_sched->set_allocated_traffic_shaping_info(traffic_shaping_info);
 
+    Status status = CreateTrafficSchedulers_(traffic_scheds);
+    ASSERT_TRUE( status.error_message() != Status::OK.error_message() );
+}
+
+// Test 17 - CreateTrafficSchedulers-Upstream Failure (Invalid AdditionalBW value) case
+TEST_F(TestCreateTrafficSchedulers, AdditionalBW_InvalidValueFailure) {
+    scheduler->set_direction(tech_profile::Direction::UPSTREAM);
+    scheduler->set_additional_bw(9);
+    traffic_sched->set_direction(tech_profile::Direction::UPSTREAM);
+    traffic_sched->set_allocated_scheduler(scheduler);
+    traffic_shaping_info->set_gir(0);
+    traffic_shaping_info->set_cir(64000);
+    traffic_shaping_info->set_pir(128000);
+    traffic_sched->set_allocated_traffic_shaping_info(traffic_shaping_info);
+
+    Status status = CreateTrafficSchedulers_(traffic_scheds);
+    ASSERT_TRUE( status.error_message() != Status::OK.error_message() );
+}
+
+// Test 18 - CreateTrafficSchedulers-Upstream Success (AdditionalBW_None-Max BW = Fixed BW) case
+TEST_F(TestCreateTrafficSchedulers, AdditionalBW_NoneMaxBWEqFixedBwSuccess) {
+    scheduler->set_direction(tech_profile::Direction::UPSTREAM);
+    scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_None);
+    traffic_sched->set_direction(tech_profile::Direction::UPSTREAM);
+    traffic_sched->set_allocated_scheduler(scheduler);
+    traffic_shaping_info->set_gir(64000);
+    traffic_shaping_info->set_cir(0);
+    traffic_shaping_info->set_pir(64000);
+    traffic_sched->set_allocated_traffic_shaping_info(traffic_shaping_info);
+
     bcmos_errno olt_cfg_set_res = BCM_ERR_OK;
     ON_CALL(balMock, bcmolt_cfg_set(_, _)).WillByDefault(Return(olt_cfg_set_res));
 
@@ -2133,7 +2166,7 @@
     ASSERT_TRUE( status.error_message() == Status::OK.error_message() );
 }
 
-// Test 17 - CreateTrafficSchedulers-Downstream success case
+// Test 19 - CreateTrafficSchedulers-Downstream success case
 TEST_F(TestCreateTrafficSchedulers, CreateTrafficSchedulersDownstreamSuccess) {
     scheduler->set_direction(tech_profile::Direction::DOWNSTREAM);
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_BestEffort);
@@ -2150,7 +2183,7 @@
     ASSERT_TRUE( status.error_message() == Status::OK.error_message() );
 }
 
-// Test 18 - CreateTrafficSchedulers-Downstream Failure case
+// Test 20 - CreateTrafficSchedulers-Downstream Failure case
 TEST_F(TestCreateTrafficSchedulers, CreateTrafficSchedulersDownstreamFailure) {
     scheduler->set_direction(tech_profile::Direction::DOWNSTREAM);
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_BestEffort);
@@ -2167,7 +2200,7 @@
     ASSERT_TRUE( status.error_message() != Status::OK.error_message() );
 }
 
-// Test 19 - CreateTrafficSchedulers-Invalid direction Failure case
+// Test 21 - CreateTrafficSchedulers-Invalid direction Failure case
 TEST_F(TestCreateTrafficSchedulers, CreateTrafficSchedulersInvalidDirectionFailure) {
     scheduler->set_direction(tech_profile::Direction::BIDIRECTIONAL);
     scheduler->set_additional_bw(tech_profile::AdditionalBW::AdditionalBW_BestEffort);