blob: 4fb84ca3e4bb0d2e44119e9762f4a3e3189cd105 [file] [log] [blame]
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001/*
Girish Gowdraa707e7c2019-11-07 11:36:13 +05302 * Copyright 2018-present Open Networking Foundation
Shad Ansarib7b0ced2018-05-11 21:53:32 +00003
Girish Gowdraa707e7c2019-11-07 11:36:13 +05304 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Shad Ansarib7b0ced2018-05-11 21:53:32 +00007
Girish Gowdraa707e7c2019-11-07 11:36:13 +05308 * http://www.apache.org/licenses/LICENSE-2.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00009
Girish Gowdraa707e7c2019-11-07 11:36:13 +053010 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +000016
17#include <iostream>
18#include <memory>
19#include <string>
20
21#include "Queue.h"
Shad Ansarib7b0ced2018-05-11 21:53:32 +000022#include <sstream>
Nicolas Palpacuer9c352082018-08-14 16:37:14 -040023#include <chrono>
24#include <thread>
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -080025#include <bitset>
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000026#include <inttypes.h>
Jason Huangbf45ffb2019-10-30 17:29:02 +080027#include <unistd.h>
Shad Ansarib7b0ced2018-05-11 21:53:32 +000028
Craig Lutgen88a22ad2018-10-04 12:30:46 -050029#include "device.h"
Shad Ansarib7b0ced2018-05-11 21:53:32 +000030#include "core.h"
31#include "indications.h"
Nicolas Palpacuer0f19b1a2018-06-07 17:29:31 -040032#include "stats_collection.h"
Nicolas Palpacuer73222e02018-07-16 12:20:26 -040033#include "error_format.h"
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -040034#include "state.h"
Craig Lutgen88a22ad2018-10-04 12:30:46 -050035#include "utils.h"
Shad Ansarib7b0ced2018-05-11 21:53:32 +000036
37extern "C"
38{
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000039#include <bcmolt_api.h>
40#include <bcmolt_host_api.h>
41#include <bcmolt_api_model_supporting_enums.h>
42
43#include <bal_version.h>
44#include <bcmolt_api_conn_mgr.h>
45//CLI header files
46#include <bcmcli_session.h>
47#include <bcmcli.h>
48#include <bcm_api_cli.h>
49
50#include <bcmos_common.h>
51#include <bcm_config.h>
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -040052// FIXME : dependency problem
53// #include <bcm_common_gpon.h>
Nicolas Palpacuer967438f2018-09-07 14:41:54 -040054// #include <bcm_dev_log_task.h>
Shad Ansarib7b0ced2018-05-11 21:53:32 +000055}
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000056
Shad Ansarib7b0ced2018-05-11 21:53:32 +000057
Nicolas Palpacuer967438f2018-09-07 14:41:54 -040058dev_log_id openolt_log_id = bcm_dev_log_id_register("OPENOLT", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
59dev_log_id omci_log_id = bcm_dev_log_id_register("OMCI", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
60
Craig Lutgen88a22ad2018-10-04 12:30:46 -050061#define BAL_RSC_MANAGER_BASE_TM_SCHED_ID 16384
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -080062#define MAX_TM_QUEUE_ID 8192
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000063#define MAX_TM_QMP_ID 16
64#define TMQ_MAP_PROFILE_SIZE 8
65#define MAX_TM_SCHED_ID 1023
66#define MAX_SUBS_TM_SCHED_ID (MAX_SUPPORTED_PON == 16 ? MAX_TM_SCHED_ID-4-16 : MAX_TM_SCHED_ID-10-64)
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -080067#define EAP_ETHER_TYPE 34958
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000068#define XGS_BANDWIDTH_GRANULARITY 16000
69#define GPON_BANDWIDTH_GRANULARITY 32000
70#define FILL_ARRAY(ARRAY,START,END,VALUE) for(int i=START;i<END;ARRAY[i++]=VALUE);
71#define COUNT_OF(array) (sizeof(array) / sizeof(array[0]))
72
73#define GET_FLOW_INTERFACE_TYPE(type) \
74 (type == BCMOLT_FLOW_INTERFACE_TYPE_PON) ? "PON" : \
75 (type == BCMOLT_FLOW_INTERFACE_TYPE_NNI) ? "NNI" : \
76 (type == BCMOLT_FLOW_INTERFACE_TYPE_HOST) ? "HOST" : "unknown"
77#define GET_PKT_TAG_TYPE(type) \
78 (type == BCMOLT_PKT_TAG_TYPE_UNTAGGED) ? "UNTAG" : \
79 (type == BCMOLT_PKT_TAG_TYPE_SINGLE_TAG) ? "SINGLE_TAG" : \
80 (type == BCMOLT_PKT_TAG_TYPE_DOUBLE_TAG) ? "DOUBLE_TAG" : "unknown"
Nicolas Palpacuer967438f2018-09-07 14:41:54 -040081
Craig Lutgen88a22ad2018-10-04 12:30:46 -050082static unsigned int num_of_nni_ports = 0;
83static unsigned int num_of_pon_ports = 0;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000084static std::string intf_technologies[MAX_SUPPORTED_PON];
Craig Lutgen88a22ad2018-10-04 12:30:46 -050085static const std::string UNKNOWN_TECH("unknown");
Craig Lutgenb2601f02018-10-23 13:04:31 -050086static const std::string MIXED_TECH("mixed");
87static std::string board_technology(UNKNOWN_TECH);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000088static std::string chip_family(UNKNOWN_TECH);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -080089static unsigned int OPENOLT_FIELD_LEN = 200;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000090static std::string firmware_version = "Openolt.2019.07.01";
Nicolas Palpacuerdff96792018-09-06 14:59:32 -040091
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000092const uint32_t tm_upstream_sched_id_start = (MAX_SUPPORTED_PON == 16 ? \
93 MAX_TM_SCHED_ID-3 : MAX_TM_SCHED_ID-9);
94const uint32_t tm_downstream_sched_id_start = (MAX_SUPPORTED_PON == 16 ? \
95 tm_upstream_sched_id_start-16 : tm_upstream_sched_id_start-64);
96
97/* Max Queue ID supported is 7 so based on priority_q configured for GEMPORTS
98in TECH PROFILE respective Queue ID from this list will be used for both
99US and DS Queues*/
100const uint32_t queue_id_list[8] = {0, 1, 2, 3, 4, 5, 6, 7};
101
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700102const std::string upstream = "upstream";
103const std::string downstream = "downstream";
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000104bcmolt_oltid dev_id = 0;
105
106/* Current session */
107static bcmcli_session *current_session;
108static bcmcli_entry *api_parent_dir;
109bcmos_bool status_bcm_cli_quit = BCMOS_FALSE;
110bcmos_task bal_cli_thread;
111const char *bal_cli_thread_name = "bal_cli_thread";
112uint16_t flow_id_counters = 0;
113int flow_id_data[16384][2];
114
115/* QOS Type has been pre-defined as Fixed Queue but it will be updated based on number of GEMPORTS
116 associated for a given subscriber. If GEM count = 1 for a given subscriber, qos_type will be Fixed Queue
117 else Priority to Queue */
118bcmolt_egress_qos_type qos_type = BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700119
Shad Ansariedef2132018-08-10 22:14:50 +0000120State state;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400121
Craig Lutgen967a1d02018-11-27 10:41:51 -0600122static std::map<uint32_t, uint32_t> flowid_to_port; // For mapping upstream flows to logical ports
123static std::map<uint32_t, uint32_t> flowid_to_gemport; // For mapping downstream flows into gemports
124static std::map<uint32_t, std::set<uint32_t> > port_to_flows; // For mapping logical ports to downstream flows
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800125
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000126/* This represents the Key to 'sched_map' map.
127 Represents (pon_intf_id, onu_id, uni_id, direction) */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800128typedef std::tuple<uint32_t, uint32_t, uint32_t, std::string> sched_map_key_tuple;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000129/* 'sched_map' maps sched_map_key_tuple to DBA (Upstream) or
130 Subscriber (Downstream) Scheduler ID */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800131static std::map<sched_map_key_tuple, int> sched_map;
132
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000133/* This represents the Key to 'sched_qmp_id_map' map.
134Represents (sched_id, pon_intf_id, onu_id, uni_id) */
135typedef std::tuple<uint32_t, uint32_t, uint32_t, uint32_t> sched_qmp_id_map_key_tuple;
136/* 'sched_qmp_id_map' maps sched_qmp_id_map_key_tuple to TM Queue Mapping Profile ID */
137static std::map<sched_qmp_id_map_key_tuple, int> sched_qmp_id_map;
138/* 'qmp_id_to_qmp_map' maps TM Queue Mapping Profile ID to TM Queue Mapping Profile */
139static std::map<int, std::vector < uint32_t > > qmp_id_to_qmp_map;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800140
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800141std::bitset<MAX_TM_SCHED_ID> tm_sched_bitset;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000142std::bitset<MAX_TM_QMP_ID> tm_qmp_bitset;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800143
144static bcmos_fastlock data_lock;
Craig Lutgen967a1d02018-11-27 10:41:51 -0600145
146#define MIN_ALLOC_ID_GPON 256
147#define MIN_ALLOC_ID_XGSPON 1024
148
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800149static bcmos_errno CreateSched(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, \
150 uint32_t port_no, uint32_t alloc_id, tech_profile::AdditionalBW additional_bw, uint32_t weight, \
151 uint32_t priority, tech_profile::SchedulingPolicy sched_policy,
152 tech_profile::TrafficShapingInfo traffic_shaping_info);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000153static bcmos_errno RemoveSched(int intf_id, int onu_id, int uni_id, int alloc_id, std::string direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800154static bcmos_errno CreateQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, \
155 uint32_t priority, uint32_t gemport_id);
156static bcmos_errno RemoveQueue(std::string direction, int intf_id, int onu_id, int uni_id, uint32_t port_no, int alloc_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000157static bcmos_errno CreateDefaultSched(uint32_t intf_id, const std::string direction);
158static bcmos_errno CreateDefaultQueue(uint32_t intf_id, const std::string direction);
159
160uint16_t get_dev_id(void) {
161 return dev_id;
162}
Shad Ansari627b5782018-08-13 22:49:32 +0000163
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400164// Stubbed defntions of bcmolt_cfg_get required for unit-test
165#ifdef TEST_MODE
166extern bcmos_errno bcmolt_cfg_get__bal_state_stub(bcmolt_oltid olt_id, void* ptr);
167extern bcmos_errno bcmolt_cfg_get__olt_topology_stub(bcmolt_oltid olt_id, void* ptr);
168#endif
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800169/**
170* Returns the default NNI (Upstream direction) or PON (Downstream direction) scheduler
171* Every NNI port and PON port have default scheduler.
172* The NNI0 default scheduler ID is 18432, and NNI1 is 18433 and so on.
173* Similarly, PON0 default scheduler ID is 16384. PON1 is 16385 and so on.
174*
175* @param intf_id NNI or PON interface ID
176* @param direction "upstream" or "downstream"
177*
178* @return default scheduler ID for the given interface.
179*/
180static inline int get_default_tm_sched_id(int intf_id, std::string direction) {
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700181 if (direction.compare(upstream) == 0) {
182 return tm_upstream_sched_id_start + intf_id;
183 } else if (direction.compare(downstream) == 0) {
184 return tm_downstream_sched_id_start + intf_id;
185 }
186 else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000187 OPENOLT_LOG(ERROR, openolt_log_id, "invalid direction - %s\n", direction.c_str());
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700188 return 0;
189 }
190}
191
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800192/**
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800193* Gets a unique tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
194* The tm_sched_id is locally cached in a map, so that it can rendered when necessary.
195* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
196*
197* @param intf_id NNI or PON intf ID
198* @param onu_id ONU ID
199* @param uni_id UNI ID
200* @param gemport_id GEM Port ID
201* @param direction Upstream or downstream
202*
203* @return tm_sched_id
204*/
205uint32_t get_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
206 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
207 int sched_id = -1;
208
209 std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
210 if (it != sched_map.end()) {
211 sched_id = it->second;
212 }
213 if (sched_id != -1) {
214 return sched_id;
215 }
216
217 bcmos_fastlock_lock(&data_lock);
218 // Complexity of O(n). Is there better way that can avoid linear search?
219 for (sched_id = 0; sched_id < MAX_TM_SCHED_ID; sched_id++) {
220 if (tm_sched_bitset[sched_id] == 0) {
221 tm_sched_bitset[sched_id] = 1;
222 break;
223 }
224 }
225 bcmos_fastlock_unlock(&data_lock, 0);
226
227 if (sched_id < MAX_TM_SCHED_ID) {
228 bcmos_fastlock_lock(&data_lock);
229 sched_map[key] = sched_id;
230 bcmos_fastlock_unlock(&data_lock, 0);
231 return sched_id;
232 } else {
233 return -1;
234 }
235}
236
237/**
238* Free tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
239*
240* @param intf_id NNI or PON intf ID
241* @param onu_id ONU ID
242* @param uni_id UNI ID
243* @param gemport_id GEM Port ID
244* @param direction Upstream or downstream
245*/
246void free_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
247 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
248 std::map<sched_map_key_tuple, int>::const_iterator it;
249 bcmos_fastlock_lock(&data_lock);
250 it = sched_map.find(key);
251 if (it != sched_map.end()) {
252 tm_sched_bitset[it->second] = 0;
253 sched_map.erase(it);
254 }
255 bcmos_fastlock_unlock(&data_lock, 0);
256}
257
258bool is_tm_sched_id_present(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
259 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000260 std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
261 if (it != sched_map.end()) {
262 return true;
263 }
264 return false;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800265}
266
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000267/**
268* Check whether given two tm qmp profiles are equal or not
269*
270* @param tmq_map_profileA <vector> TM QUEUE MAPPING PROFILE
271* @param tmq_map_profileB <vector> TM QUEUE MAPPING PROFILE
272*
273* @return boolean, true if given tmq_map_profiles are equal else false
274*/
275
276bool check_tm_qmp_equality(std::vector<uint32_t> tmq_map_profileA, std::vector<uint32_t> tmq_map_profileB) {
277 for (uint32_t i = 0; i < TMQ_MAP_PROFILE_SIZE; i++) {
278 if (tmq_map_profileA[i] != tmq_map_profileB[i]) {
279 return false;
280 }
281 }
282 return true;
Shad Ansari627b5782018-08-13 22:49:32 +0000283}
284
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000285/**
286* Modifies given queues_pbit_map to parsable format
287* e.g: Modifes "0b00000101" to "10100000"
288*
289* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
290* @param size Queue count
291*
292* @return string queues_pbit_map
293*/
294std::string* get_valid_queues_pbit_map(std::string *queues_pbit_map, uint32_t size) {
295 for(uint32_t i=0; i < size; i++) {
296 /* Deletes 2 characters from index number 0 */
297 queues_pbit_map[i].erase(0, 2);
298 std::reverse(queues_pbit_map[i].begin(), queues_pbit_map[i].end());
299 }
300 return queues_pbit_map;
301}
302
303/**
304* Creates TM QUEUE MAPPING PROFILE for given queues_pbit_map and queues_priority_q
305*
306* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
307* @param queues_priority_q PRIORITY_Q configured for each GEM in TECH PROFILE
308* @param size Queue count
309*
310* @return <vector> TM QUEUE MAPPING PROFILE
311*/
312std::vector<uint32_t> get_tmq_map_profile(std::string *queues_pbit_map, uint32_t *queues_priority_q, uint32_t size) {
313 std::vector<uint32_t> tmq_map_profile(8,0);
314
315 for(uint32_t i=0; i < size; i++) {
316 for (uint32_t j = 0; j < queues_pbit_map[i].size(); j++) {
317 if (queues_pbit_map[i][j]=='1') {
318 tmq_map_profile.at(j) = queue_id_list[queues_priority_q[i]];
319 }
320 }
321 }
322 return tmq_map_profile;
323}
324
325/**
326* Gets corresponding tm_qmp_id for a given tmq_map_profile
327*
328* @param <vector> TM QUEUE MAPPING PROFILE
329*
330* @return tm_qmp_id
331*/
332int get_tm_qmp_id(std::vector<uint32_t> tmq_map_profile) {
333 int tm_qmp_id = -1;
334
335 std::map<int, std::vector < uint32_t > >::const_iterator it = qmp_id_to_qmp_map.begin();
336 while(it != qmp_id_to_qmp_map.end()) {
337 if(check_tm_qmp_equality(tmq_map_profile, it->second)) {
338 tm_qmp_id = it->first;
339 break;
340 }
341 it++;
342 }
343 return tm_qmp_id;
344}
345
346/**
347* Updates sched_qmp_id_map with given sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id
348*
349* @param upstream/downstream sched_id
350* @param PON intf ID
351* @param onu_id ONU ID
352* @param uni_id UNI ID
353* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
354*/
355void update_sched_qmp_id_map(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
356 uint32_t uni_id, int tm_qmp_id) {
357 bcmos_fastlock_lock(&data_lock);
358 sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
359 sched_qmp_id_map.insert(make_pair(key, tm_qmp_id));
360 bcmos_fastlock_unlock(&data_lock, 0);
361}
362
363/**
364* Gets corresponding tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
365*
366* @param upstream/downstream sched_id
367* @param PON intf ID
368* @param onu_id ONU ID
369* @param uni_id UNI ID
370*
371* @return tm_qmp_id
372*/
373int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id) {
374 sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
375 int tm_qmp_id = -1;
376
377 std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
378 if (it != sched_qmp_id_map.end()) {
379 tm_qmp_id = it->second;
380 }
381 return tm_qmp_id;
382}
383
384/**
385* Gets a unique tm_qmp_id for a given tmq_map_profile
386* The tm_qmp_id is locally cached in a map, so that it can be rendered when necessary.
387* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
388*
389* @param upstream/downstream sched_id
390* @param PON intf ID
391* @param onu_id ONU ID
392* @param uni_id UNI ID
393* @param <vector> TM QUEUE MAPPING PROFILE
394*
395* @return tm_qmp_id
396*/
397int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id, \
398 std::vector<uint32_t> tmq_map_profile) {
399 int tm_qmp_id;
400
401 bcmos_fastlock_lock(&data_lock);
402 /* Complexity of O(n). Is there better way that can avoid linear search? */
403 for (tm_qmp_id = 0; tm_qmp_id < MAX_TM_QMP_ID; tm_qmp_id++) {
404 if (tm_qmp_bitset[tm_qmp_id] == 0) {
405 tm_qmp_bitset[tm_qmp_id] = 1;
406 break;
407 }
408 }
409 bcmos_fastlock_unlock(&data_lock, 0);
410
411 if (tm_qmp_id < MAX_TM_QMP_ID) {
412 bcmos_fastlock_lock(&data_lock);
413 qmp_id_to_qmp_map.insert(make_pair(tm_qmp_id, tmq_map_profile));
414 bcmos_fastlock_unlock(&data_lock, 0);
415 update_sched_qmp_id_map(sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id);
416 return tm_qmp_id;
417 } else {
418 return -1;
419 }
420}
421
422/**
423* Free tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
424*
425* @param upstream/downstream sched_id
426* @param PON intf ID
427* @param onu_id ONU ID
428* @param uni_id UNI ID
429* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
430*
431* @return boolean, true if no more reference for TM QMP else false
432*/
433bool free_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
434 uint32_t uni_id, int tm_qmp_id) {
435 bool result;
436 sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
437 std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
438 bcmos_fastlock_lock(&data_lock);
439 if (it != sched_qmp_id_map.end()) {
440 sched_qmp_id_map.erase(it);
441 }
442 bcmos_fastlock_unlock(&data_lock, 0);
443
444 uint32_t tm_qmp_ref_count = 0;
445 std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it2 = sched_qmp_id_map.begin();
446 while(it2 != sched_qmp_id_map.end()) {
447 if(it2->second == tm_qmp_id) {
448 tm_qmp_ref_count++;
449 }
450 it2++;
451 }
452
453 if (tm_qmp_ref_count == 0) {
454 std::map<int, std::vector < uint32_t > >::const_iterator it3 = qmp_id_to_qmp_map.find(tm_qmp_id);
455 if (it3 != qmp_id_to_qmp_map.end()) {
456 bcmos_fastlock_lock(&data_lock);
457 tm_qmp_bitset[tm_qmp_id] = 0;
458 qmp_id_to_qmp_map.erase(it3);
459 bcmos_fastlock_unlock(&data_lock, 0);
460 OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So clearing it\n", \
461 tm_qmp_id, tm_qmp_ref_count);
462 result = true;
463 }
464 } else {
465 OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So not clearing it\n", \
466 tm_qmp_id, tm_qmp_ref_count);
467 result = false;
468 }
469 return result;
470}
471
472/**
473* Returns Scheduler/Queue direction as string
474*
475* @param direction as specified in tech_profile.proto
476*/
477std::string GetDirection(int direction) {
478 switch (direction)
479 {
480 case tech_profile::Direction::UPSTREAM: return upstream;
481 case tech_profile::Direction::DOWNSTREAM: return downstream;
482 default: OPENOLT_LOG(ERROR, openolt_log_id, "direction-not-supported %d\n", direction);
483 return "direction-not-supported";
484 }
485}
486
487inline const char *get_flow_acton_command(uint32_t command) {
488 char actions[200] = { };
489 char *s_actions_ptr = actions;
490 if (command & BCMOLT_ACTION_CMD_ID_ADD_OUTER_TAG) strcat(s_actions_ptr, "ADD_OUTER_TAG|");
491 if (command & BCMOLT_ACTION_CMD_ID_REMOVE_OUTER_TAG) strcat(s_actions_ptr, "REMOVE_OUTER_TAG|");
492 if (command & BCMOLT_ACTION_CMD_ID_XLATE_OUTER_TAG) strcat(s_actions_ptr, "TRANSLATE_OUTER_TAG|");
493 if (command & BCMOLT_ACTION_CMD_ID_ADD_INNER_TAG) strcat(s_actions_ptr, "ADD_INNTER_TAG|");
494 if (command & BCMOLT_ACTION_CMD_ID_REMOVE_INNER_TAG) strcat(s_actions_ptr, "REMOVE_INNER_TAG|");
495 if (command & BCMOLT_ACTION_CMD_ID_XLATE_INNER_TAG) strcat(s_actions_ptr, "TRANSLATE_INNER_TAG|");
496 if (command & BCMOLT_ACTION_CMD_ID_REMARK_OUTER_PBITS) strcat(s_actions_ptr, "REMOVE_OUTER_PBITS|");
497 if (command & BCMOLT_ACTION_CMD_ID_REMARK_INNER_PBITS) strcat(s_actions_ptr, "REMAKE_INNER_PBITS|");
498 return s_actions_ptr;
499}
500
501char* openolt_read_sysinfo(const char* field_name, char* field_val)
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800502{
503 FILE *fp;
504 /* Prepare the command*/
505 char command[150];
506
507 snprintf(command, sizeof command, "bash -l -c \"onlpdump -s\" | perl -ne 'print $1 if /%s: (\\S+)/'", field_name);
508 /* Open the command for reading. */
509 fp = popen(command, "r");
510 if (fp == NULL) {
511 /*The client has to check for a Null field value in this case*/
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000512 OPENOLT_LOG(INFO, openolt_log_id, "Failed to query the %s\n", field_name);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800513 return field_val;
514 }
515
516 /*Read the field value*/
517 if (fp) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000518 uint8_t ret;
519 ret = fread(field_val, OPENOLT_FIELD_LEN, 1, fp);
520 if (ret >= OPENOLT_FIELD_LEN)
521 OPENOLT_LOG(INFO, openolt_log_id, "Read data length %u\n", ret);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800522 pclose(fp);
523 }
524 return field_val;
525}
526
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400527Status GetDeviceInfo_(openolt::DeviceInfo* device_info) {
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500528 device_info->set_vendor(VENDOR_ID);
529 device_info->set_model(MODEL_ID);
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400530 device_info->set_hardware_version("");
531 device_info->set_firmware_version(firmware_version);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500532 device_info->set_technology(board_technology);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500533 device_info->set_pon_ports(num_of_pon_ports);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500534
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800535 char serial_number[OPENOLT_FIELD_LEN];
536 memset(serial_number, '\0', OPENOLT_FIELD_LEN);
537 openolt_read_sysinfo("Serial Number", serial_number);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000538 OPENOLT_LOG(INFO, openolt_log_id, "Fetched device serial number %s\n", serial_number);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800539 device_info->set_device_serial_number(serial_number);
540
Girish Gowdru771f9ff2019-07-24 12:02:10 -0700541 char device_id[OPENOLT_FIELD_LEN];
542 memset(device_id, '\0', OPENOLT_FIELD_LEN);
543 openolt_read_sysinfo("MAC", device_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000544 OPENOLT_LOG(INFO, openolt_log_id, "Fetched device mac address %s\n", device_id);
Girish Gowdru771f9ff2019-07-24 12:02:10 -0700545 device_info->set_device_id(device_id);
546
Craig Lutgenb2601f02018-10-23 13:04:31 -0500547 // Legacy, device-wide ranges. To be deprecated when adapter
548 // is upgraded to support per-interface ranges
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000549 if (board_technology == "XGS-PON") {
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500550 device_info->set_onu_id_start(1);
551 device_info->set_onu_id_end(255);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600552 device_info->set_alloc_id_start(MIN_ALLOC_ID_XGSPON);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500553 device_info->set_alloc_id_end(16383);
554 device_info->set_gemport_id_start(1024);
555 device_info->set_gemport_id_end(65535);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500556 device_info->set_flow_id_start(1);
557 device_info->set_flow_id_end(16383);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500558 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000559 else if (board_technology == "GPON") {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500560 device_info->set_onu_id_start(1);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500561 device_info->set_onu_id_end(127);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600562 device_info->set_alloc_id_start(MIN_ALLOC_ID_GPON);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500563 device_info->set_alloc_id_end(767);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500564 device_info->set_gemport_id_start(256);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500565 device_info->set_gemport_id_end(4095);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500566 device_info->set_flow_id_start(1);
567 device_info->set_flow_id_end(16383);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500568 }
Craig Lutgenb2601f02018-10-23 13:04:31 -0500569
570 std::map<std::string, openolt::DeviceInfo::DeviceResourceRanges*> ranges;
571 for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
572 std::string intf_technology = intf_technologies[intf_id];
573 openolt::DeviceInfo::DeviceResourceRanges *range = ranges[intf_technology];
574 if(range == nullptr) {
575 range = device_info->add_ranges();
576 ranges[intf_technology] = range;
577 range->set_technology(intf_technology);
578
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000579 if (intf_technology == "XGS-PON") {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500580 openolt::DeviceInfo::DeviceResourceRanges::Pool* pool;
581
582 pool = range->add_pools();
583 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ONU_ID);
584 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::DEDICATED_PER_INTF);
585 pool->set_start(1);
586 pool->set_end(255);
587
588 pool = range->add_pools();
589 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ALLOC_ID);
590 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_SAME_TECH);
591 pool->set_start(1024);
592 pool->set_end(16383);
593
594 pool = range->add_pools();
595 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::GEMPORT_ID);
596 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
597 pool->set_start(1024);
598 pool->set_end(65535);
599
600 pool = range->add_pools();
601 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::FLOW_ID);
602 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
603 pool->set_start(1);
604 pool->set_end(16383);
605 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000606 else if (intf_technology == "GPON") {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500607 openolt::DeviceInfo::DeviceResourceRanges::Pool* pool;
608
609 pool = range->add_pools();
610 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ONU_ID);
611 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::DEDICATED_PER_INTF);
612 pool->set_start(1);
613 pool->set_end(127);
614
615 pool = range->add_pools();
616 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ALLOC_ID);
617 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_SAME_TECH);
618 pool->set_start(256);
619 pool->set_end(757);
620
621 pool = range->add_pools();
622 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::GEMPORT_ID);
623 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
624 pool->set_start(256);
625 pool->set_end(4095);
626
627 pool = range->add_pools();
628 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::FLOW_ID);
629 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
630 pool->set_start(1);
631 pool->set_end(16383);
632 }
633 }
634
635 range->add_intf_ids(intf_id);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500636 }
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400637
638 // FIXME: Once dependency problem is fixed
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500639 // device_info->set_pon_ports(num_of_pon_ports);
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400640 // device_info->set_onu_id_end(XGPON_NUM_OF_ONUS - 1);
641 // device_info->set_alloc_id_start(1024);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500642 // device_info->set_alloc_id_end(XGPON_NUM_OF_ALLOC_IDS * num_of_pon_ports ? - 1);
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400643 // device_info->set_gemport_id_start(XGPON_MIN_BASE_SERVICE_PORT_ID);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500644 // device_info->set_gemport_id_end(XGPON_NUM_OF_GEM_PORT_IDS_PER_PON * num_of_pon_ports ? - 1);
645 // device_info->set_pon_ports(num_of_pon_ports);
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400646
647 return Status::OK;
648}
649
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000650Status pushOltOperInd(uint32_t intf_id, const char *type, const char *state)
651{
652 openolt::Indication ind;
653 openolt::IntfOperIndication* intf_oper_ind = new openolt::IntfOperIndication;
654
655 intf_oper_ind->set_type(type);
656 intf_oper_ind->set_intf_id(intf_id);
657 intf_oper_ind->set_oper_state(state);
658 ind.set_allocated_intf_oper_ind(intf_oper_ind);
659 oltIndQ.push(ind);
660 return Status::OK;
661}
662
663#define CLI_HOST_PROMPT_FORMAT "BCM.%u> "
664
665/* Build CLI prompt */
666static void openolt_cli_get_prompt_cb(bcmcli_session *session, char *buf, uint32_t max_len)
667{
668 snprintf(buf, max_len, CLI_HOST_PROMPT_FORMAT, dev_id);
669}
670
671static int _bal_apiend_cli_thread_handler(long data)
672{
673 char init_string[]="\n";
674 bcmcli_session *sess = current_session;
675 bcmos_task_parm bal_cli_task_p_dummy;
676
677 /* Switch to interactive mode if not stopped in the init script */
678 if (!bcmcli_is_stopped(sess))
679 {
680 /* Force a CLI command prompt
681 * The string passed into the parse function
682 * must be modifiable, so a string constant like
683 * bcmcli_parse(current_session, "\n") will not
684 * work.
685 */
686 bcmcli_parse(sess, init_string);
687
688 /* Process user input until EOF or quit command */
689 bcmcli_driver(sess);
690 };
691 OPENOLT_LOG(INFO, openolt_log_id, "BAL API End CLI terminated\n");
692
693 /* Cleanup */
694 bcmcli_session_close(current_session);
695 bcmcli_token_destroy(NULL);
696 return 0;
697}
698
699/* Init API CLI commands for the current device */
700bcmos_errno bcm_openolt_api_cli_init(bcmcli_entry *parent_dir, bcmcli_session *session)
701{
702 bcmos_errno rc;
703
704 api_parent_dir = parent_dir;
705
706 rc = bcm_api_cli_set_commands(session);
707
708#ifdef BCM_SUBSYSTEM_HOST
709 /* Subscribe for device change indication */
710 rc = rc ? rc : bcmolt_olt_sel_ind_register(_api_cli_olt_change_ind);
711#endif
712
713 return rc;
714}
715
716static bcmos_errno bcm_cli_quit(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
717{
718 bcmcli_stop(session);
719 bcmcli_session_print(session, "CLI terminated by 'Quit' command\n");
720 status_bcm_cli_quit = BCMOS_TRUE;
721
722 return BCM_ERR_OK;
723}
724
725int get_status_bcm_cli_quit(void) {
726 return status_bcm_cli_quit;
727}
728
729bcmos_errno bcmolt_apiend_cli_init() {
730 bcmos_errno ret;
731 bcmos_task_parm bal_cli_task_p = {};
732 bcmos_task_parm bal_cli_task_p_dummy;
733
734 /** before creating the task, check if it is already created by the other half of BAL i.e. Core side */
735 if (BCM_ERR_OK != bcmos_task_query(&bal_cli_thread, &bal_cli_task_p_dummy))
736 {
737 /* Create BAL CLI thread */
738 bal_cli_task_p.name = bal_cli_thread_name;
739 bal_cli_task_p.handler = _bal_apiend_cli_thread_handler;
740 bal_cli_task_p.priority = TASK_PRIORITY_CLI;
741
742 ret = bcmos_task_create(&bal_cli_thread, &bal_cli_task_p);
743 if (BCM_ERR_OK != ret)
744 {
745 bcmos_printf("Couldn't create BAL API end CLI thread\n");
746 return ret;
747 }
748 }
749}
750
Shad Ansari627b5782018-08-13 22:49:32 +0000751Status Enable_(int argc, char *argv[]) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000752 bcmos_errno err;
753 bcmolt_host_init_parms init_parms = {};
754 init_parms.transport.type = BCM_HOST_API_CONN_LOCAL;
755 unsigned int failed_enable_device_cnt = 0;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000756
Shad Ansariedef2132018-08-10 22:14:50 +0000757 if (!state.is_activated()) {
Shad Ansari627b5782018-08-13 22:49:32 +0000758
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500759 vendor_init();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000760 /* Initialize host subsystem */
761 err = bcmolt_host_init(&init_parms);
762 if (BCM_ERR_OK != err) {
763 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to init OLT\n");
764 return bcm_to_grpc_err(err, "Failed to init OLT");
765 }
766
767 bcmcli_session_parm mon_session_parm;
768 /* Create CLI session */
769 memset(&mon_session_parm, 0, sizeof(mon_session_parm));
770 mon_session_parm.get_prompt = openolt_cli_get_prompt_cb;
771 mon_session_parm.access_right = BCMCLI_ACCESS_ADMIN;
772 bcmos_errno rc = bcmcli_session_open(&mon_session_parm, &current_session);
773 BUG_ON(rc != BCM_ERR_OK);
774
775 /* API CLI */
776 bcm_openolt_api_cli_init(NULL, current_session);
777
778 /* Add quit command */
779 BCMCLI_MAKE_CMD_NOPARM(NULL, "quit", "Quit", bcm_cli_quit);
780
781 err = bcmolt_apiend_cli_init();
782 if (BCM_ERR_OK != err) {
783 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to add apiend init\n");
784 return bcm_to_grpc_err(err, "Failed to add apiend init");
785 }
786
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800787 bcmos_fastlock_init(&data_lock, 0);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000788 OPENOLT_LOG(INFO, openolt_log_id, "Enable OLT - %s-%s\n", VENDOR_ID, MODEL_ID);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600789
Jason Huangbf45ffb2019-10-30 17:29:02 +0800790 //check BCM daemon is connected or not
791 Status status = check_connection();
792 if (!status.ok())
793 return status;
794 else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000795 Status status = SubscribeIndication();
796 if (!status.ok()) {
797 OPENOLT_LOG(ERROR, openolt_log_id, "SubscribeIndication failed - %s : %s\n",
798 grpc_status_code_to_string(status.error_code()).c_str(),
799 status.error_message().c_str());
800 return status;
801 }
Jason Huangbf45ffb2019-10-30 17:29:02 +0800802
803 //check BAL state in initial stage
804 status = check_bal_ready();
805 if (!status.ok())
806 return status;
807 }
808
809 {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000810 bcmos_errno err;
811 bcmolt_odid dev;
812 OPENOLT_LOG(INFO, openolt_log_id, "Enabling PON %d Devices ... \n", BCM_MAX_DEVS_PER_LINE_CARD);
813 for (dev = 0; dev < BCM_MAX_DEVS_PER_LINE_CARD; dev++) {
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400814 bcmolt_device_cfg dev_cfg = { };
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000815 bcmolt_device_key dev_key = { };
816 dev_key.device_id = dev;
817 BCMOLT_CFG_INIT(&dev_cfg, device, dev_key);
818 BCMOLT_MSG_FIELD_GET(&dev_cfg, system_mode);
819 err = bcmolt_cfg_get(dev_id, &dev_cfg.hdr);
Jason Huangbf45ffb2019-10-30 17:29:02 +0800820 if (err == BCM_ERR_NOT_CONNECTED) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000821 bcmolt_device_key key = {.device_id = dev};
822 bcmolt_device_connect oper;
823 BCMOLT_OPER_INIT(&oper, device, connect, key);
824 if (MODEL_ID == "asfvolt16") {
825 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mode, BCMOLT_INNI_MODE_ALL_10_G_XFI);
826 BCMOLT_MSG_FIELD_SET (&oper, system_mode, BCMOLT_SYSTEM_MODE_XGS__2_X);
827 } else if (MODEL_ID == "asgvolt64") {
828 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mode, BCMOLT_INNI_MODE_ALL_10_G_XFI);
829 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mux, BCMOLT_INNI_MUX_FOUR_TO_ONE);
830 BCMOLT_MSG_FIELD_SET (&oper, system_mode, BCMOLT_SYSTEM_MODE_GPON__16_X);
831 }
832 err = bcmolt_oper_submit(dev_id, &oper.hdr);
833 if (err) {
834 failed_enable_device_cnt ++;
835 OPENOLT_LOG(ERROR, openolt_log_id, "Enable PON device %d failed, err %d\n", dev, err);
836 if (failed_enable_device_cnt == BCM_MAX_DEVS_PER_LINE_CARD) {
837 OPENOLT_LOG(ERROR, openolt_log_id, "failed to enable all the pon ports\n");
838 return Status(grpc::StatusCode::INTERNAL, "Failed to activate all PON ports");
839 }
840 }
841 bcmos_usleep(200000);
842 }
843 else {
844 OPENOLT_LOG(WARNING, openolt_log_id, "PON deivce %d already connected\n", dev);
845 state.activate();
846 }
847 }
848 init_stats();
Shad Ansari627b5782018-08-13 22:49:32 +0000849 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000850 }
Shad Ansariedef2132018-08-10 22:14:50 +0000851
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000852 /* Start CLI */
853 OPENOLT_LOG(INFO, def_log_id, "Starting CLI\n");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400854 //If already enabled, generate an extra indication ????
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000855 return Status::OK;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400856}
857
858Status Disable_() {
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400859 //In the earlier implementation Disabling olt is done by disabling the NNI port associated with that.
860 //In inband scenario instead of using management interface to establish connection with adapter ,NNI interface will be used.
861 //Disabling NNI port on olt disable causes connection loss between adapter and agent.
862 //To overcome this disable is implemented by disabling all the PON ports
863 //associated with the device so as to support both in-band
864 //and out of band scenarios.
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400865
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400866 Status status;
867 int failedCount = 0;
868 for (int i = 0; i < NumPonIf_(); i++) {
869 status = DisablePonIf_(i);
870 if (!status.ok()) {
871 failedCount+=1;
872 BCM_LOG(ERROR, openolt_log_id, "Failed to disable PON interface: %d\n", i);
873 }
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400874 }
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400875 if (failedCount == 0) {
876 state.deactivate();
877 openolt::Indication ind;
878 openolt::OltIndication* olt_ind = new openolt::OltIndication;
879 olt_ind->set_oper_state("down");
880 ind.set_allocated_olt_ind(olt_ind);
881 BCM_LOG(INFO, openolt_log_id, "Disable OLT, add an extra indication\n");
882 oltIndQ.push(ind);
883 return Status::OK;
884 }
885 if (failedCount ==NumPonIf_()){
886 return grpc::Status(grpc::StatusCode::INTERNAL, "failed to disable olt ,all the PON ports are still in enabled state");
887 }
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400888
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400889 return grpc::Status(grpc::StatusCode::UNKNOWN, "failed to disable olt ,few PON ports are still in enabled state");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400890}
891
892Status Reenable_() {
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400893 Status status;
894 int failedCount = 0;
895 for (int i = 0; i < NumPonIf_(); i++) {
896 status = EnablePonIf_(i);
897 if (!status.ok()) {
898 failedCount+=1;
899 BCM_LOG(ERROR, openolt_log_id, "Failed to enable PON interface: %d\n", i);
900 }
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400901 }
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400902 if (failedCount == 0){
903 state.activate();
904 openolt::Indication ind;
905 openolt::OltIndication* olt_ind = new openolt::OltIndication;
906 olt_ind->set_oper_state("up");
907 ind.set_allocated_olt_ind(olt_ind);
908 BCM_LOG(INFO, openolt_log_id, "Reenable OLT, add an extra indication\n");
909 oltIndQ.push(ind);
910 return Status::OK;
911 }
912 if (failedCount ==NumPonIf_()){
913 return grpc::Status(grpc::StatusCode::INTERNAL, "failed to re-enable olt ,all the PON ports are still in disabled state");
914 }
915 return grpc::Status(grpc::StatusCode::UNKNOWN, "failed to re-enable olt ,few PON ports are still in disabled state");
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000916}
917
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000918bcmos_errno get_pon_interface_status(bcmolt_interface pon_ni, bcmolt_interface_state *state) {
919 bcmos_errno err;
920 bcmolt_pon_interface_key pon_key;
921 bcmolt_pon_interface_cfg pon_cfg;
922 pon_key.pon_ni = pon_ni;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000923
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000924 BCMOLT_CFG_INIT(&pon_cfg, pon_interface, pon_key);
925 BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, state);
926 BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, itu);
927 err = bcmolt_cfg_get(dev_id, &pon_cfg.hdr);
928 *state = pon_cfg.data.state;
929 return err;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000930}
931
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000932inline uint64_t get_flow_status(uint16_t flow_id, uint16_t flow_type, uint16_t data_id) {
933 bcmos_errno err;
934 bcmolt_flow_key flow_key;
935 bcmolt_flow_cfg flow_cfg;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400936
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000937 flow_key.flow_id = flow_id;
938 flow_key.flow_type = (bcmolt_flow_type)flow_type;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400939
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000940 BCMOLT_CFG_INIT(&flow_cfg, flow, flow_key);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400941
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000942 switch (data_id) {
943 case ONU_ID: //onu_id
944 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, onu_id);
945 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
946 if (err) {
947 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get onu_id\n");
948 return err;
949 }
950 return flow_cfg.data.onu_id;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400951 case FLOW_TYPE:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000952 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
953 if (err) {
954 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get flow_type\n");
955 return err;
956 }
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400957 return flow_cfg.key.flow_type;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000958 case SVC_PORT_ID: //svc_port_id
959 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, svc_port_id);
960 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
961 if (err) {
962 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get svc_port_id\n");
963 return err;
964 }
965 return flow_cfg.data.svc_port_id;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400966 case PRIORITY:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000967 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, priority);
968 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
969 if (err) {
970 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get priority\n");
971 return err;
972 }
973 return flow_cfg.data.priority;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400974 case COOKIE: //cookie
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000975 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, cookie);
976 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
977 if (err) {
978 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get cookie\n");
979 return err;
980 }
981 return flow_cfg.data.cookie;
982 case INGRESS_INTF_TYPE: //ingress intf_type
983 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, ingress_intf);
984 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
985 if (err) {
986 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get ingress intf_type\n");
987 return err;
988 }
989 return flow_cfg.data.ingress_intf.intf_type;
990 case EGRESS_INTF_TYPE: //egress intf_type
991 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_intf);
992 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
993 if (err) {
994 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress intf_type\n");
995 return err;
996 }
997 return flow_cfg.data.egress_intf.intf_type;
998 case INGRESS_INTF_ID: //ingress intf_id
999 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, ingress_intf);
1000 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1001 if (err) {
1002 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get ingress intf_id\n");
1003 return err;
1004 }
1005 return flow_cfg.data.ingress_intf.intf_id;
1006 case EGRESS_INTF_ID: //egress intf_id
1007 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_intf);
1008 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1009 if (err) {
1010 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress intf_id\n");
1011 return err;
1012 }
1013 return flow_cfg.data.egress_intf.intf_id;
1014 case CLASSIFIER_O_VID:
1015 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1016 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1017 if (err) {
1018 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier o_vid\n");
1019 return err;
1020 }
1021 return flow_cfg.data.classifier.o_vid;
1022 case CLASSIFIER_O_PBITS:
1023 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1024 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1025 if (err) {
1026 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier o_pbits\n");
1027 return err;
1028 }
1029 return flow_cfg.data.classifier.o_pbits;
1030 case CLASSIFIER_I_VID:
1031 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1032 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1033 if (err) {
1034 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier i_vid\n");
1035 return err;
1036 }
1037 return flow_cfg.data.classifier.i_vid;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001038 case CLASSIFIER_I_PBITS:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001039 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1040 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1041 if (err) {
1042 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier i_pbits\n");
1043 return err;
1044 }
1045 return flow_cfg.data.classifier.i_pbits;
1046 case CLASSIFIER_ETHER_TYPE:
1047 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1048 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1049 if (err) {
1050 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier ether_type\n");
1051 return err;
1052 }
1053 return flow_cfg.data.classifier.ether_type;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001054 case CLASSIFIER_IP_PROTO:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001055 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1056 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1057 if (err) {
1058 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier ip_proto\n");
1059 return err;
1060 }
1061 return flow_cfg.data.classifier.ip_proto;
1062 case CLASSIFIER_SRC_PORT:
1063 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1064 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1065 if (err) {
1066 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier src_port\n");
1067 return err;
1068 }
1069 return flow_cfg.data.classifier.src_port;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001070 case CLASSIFIER_DST_PORT:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001071 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1072 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1073 if (err) {
1074 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier dst_port\n");
1075 return err;
1076 }
1077 return flow_cfg.data.classifier.dst_port;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001078 case CLASSIFIER_PKT_TAG_TYPE:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001079 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1080 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1081 if (err) {
1082 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier pkt_tag_type\n");
1083 return err;
1084 }
1085 return flow_cfg.data.classifier.pkt_tag_type;
1086 case EGRESS_QOS_TYPE:
1087 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
1088 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1089 if (err) {
1090 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos type\n");
1091 return err;
1092 }
1093 return flow_cfg.data.egress_qos.type;
1094 case EGRESS_QOS_QUEUE_ID:
1095 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
1096 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1097 if (err) {
1098 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos queue_id\n");
1099 return err;
1100 }
1101 switch (flow_cfg.data.egress_qos.type) {
1102 case BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE:
1103 return flow_cfg.data.egress_qos.u.fixed_queue.queue_id;
1104 case BCMOLT_EGRESS_QOS_TYPE_TC_TO_QUEUE:
1105 return flow_cfg.data.egress_qos.u.tc_to_queue.tc_to_queue_id;
1106 case BCMOLT_EGRESS_QOS_TYPE_PBIT_TO_TC:
1107 return flow_cfg.data.egress_qos.u.pbit_to_tc.tc_to_queue_id;
1108 case BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE:
1109 return flow_cfg.data.egress_qos.u.priority_to_queue.tm_q_set_id;
1110 case BCMOLT_EGRESS_QOS_TYPE_NONE:
1111 default:
1112 return -1;
1113 }
1114 case EGRESS_QOS_TM_SCHED_ID:
1115 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
1116 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1117 if (err) {
1118 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos tm_sched_id\n");
1119 return err;
1120 }
1121 return flow_cfg.data.egress_qos.tm_sched.id;
1122 case ACTION_CMDS_BITMASK:
1123 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1124 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1125 if (err) {
1126 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action cmds_bitmask\n");
1127 return err;
1128 }
1129 return flow_cfg.data.action.cmds_bitmask;
1130 case ACTION_O_VID:
1131 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1132 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1133 if (err) {
1134 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action o_vid\n");
1135 return err;
1136 }
1137 return flow_cfg.data.action.o_vid;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001138 case ACTION_O_PBITS:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001139 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1140 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1141 if (err) {
1142 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action o_pbits\n");
1143 return err;
1144 }
1145 return flow_cfg.data.action.o_pbits;
1146 case ACTION_I_VID:
1147 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1148 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1149 if (err) {
1150 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action i_vid\n");
1151 return err;
1152 }
1153 return flow_cfg.data.action.i_vid;
1154 case ACTION_I_PBITS:
1155 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1156 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1157 if (err) {
1158 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action i_pbits\n");
1159 return err;
1160 }
1161 return flow_cfg.data.action.i_pbits;
1162 case STATE:
1163 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, state);
1164 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1165 if (err) {
1166 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get state\n");
1167 return err;
1168 }
1169 return flow_cfg.data.state;
1170 default:
1171 return BCM_ERR_INTERNAL;
1172 }
1173
1174 return err;
1175}
1176
1177Status EnablePonIf_(uint32_t intf_id) {
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001178 bcmos_errno err = BCM_ERR_OK;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001179 bcmolt_pon_interface_cfg interface_obj;
1180 bcmolt_pon_interface_key intf_key = {.pon_ni = (bcmolt_interface)intf_id};
1181 bcmolt_pon_interface_set_pon_interface_state pon_interface_set_state;
1182 bcmolt_interface_state state;
1183
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001184 err = get_pon_interface_status((bcmolt_interface)intf_id, &state);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001185 if (err == BCM_ERR_OK) {
1186 if (state == BCMOLT_INTERFACE_STATE_ACTIVE_WORKING) {
Jason Huangbf45ffb2019-10-30 17:29:02 +08001187 OPENOLT_LOG(WARNING, openolt_log_id, "PON interface: %d already enabled\n", intf_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001188 return Status::OK;
1189 }
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001190 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001191 BCMOLT_CFG_INIT(&interface_obj, pon_interface, intf_key);
1192 BCMOLT_OPER_INIT(&pon_interface_set_state, pon_interface, set_pon_interface_state, intf_key);
1193 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.control, BCMOLT_CONTROL_STATE_ENABLE);
1194 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.interval, 5000);
1195 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.onu_post_discovery_mode,
1196 BCMOLT_ONU_POST_DISCOVERY_MODE_ACTIVATE);
1197 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.los, true);
1198 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.onu_alarms, true);
1199 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.tiwi, true);
1200 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.ack_timeout, true);
1201 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.sfi, true);
1202 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.loki, true);
1203 BCMOLT_FIELD_SET(&pon_interface_set_state.data, pon_interface_set_pon_interface_state_data,
1204 operation, BCMOLT_INTERFACE_OPERATION_ACTIVE_WORKING);
1205
1206 err = bcmolt_cfg_set(dev_id, &interface_obj.hdr);
1207 if (err != BCM_ERR_OK) {
1208 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to enable discovery onu, PON interface %d, err %d\n", intf_id, err);
1209 return bcm_to_grpc_err(err, "Failed to enable discovery onu");
1210 }
1211 err = bcmolt_oper_submit(dev_id, &pon_interface_set_state.hdr);
1212 if (err != BCM_ERR_OK) {
1213 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to enable PON interface: %d\n", intf_id);
1214 return bcm_to_grpc_err(err, "Failed to enable PON interface");
1215 }
1216 else {
1217 OPENOLT_LOG(INFO, openolt_log_id, "Successfully enabled PON interface: %d\n", intf_id);
1218 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for PON interface: %d\n", intf_id);
1219 CreateDefaultSched(intf_id, downstream);
1220 CreateDefaultQueue(intf_id, downstream);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001221 }
1222
1223 return Status::OK;
1224}
1225
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001226Status ProbeDeviceCapabilities_() {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001227 bcmos_errno err;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001228 bcmolt_device_cfg dev_cfg = { };
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001229 bcmolt_device_key dev_key = { };
1230 bcmolt_olt_cfg olt_cfg = { };
1231 bcmolt_olt_key olt_key = { };
1232 bcmolt_topology_map topo_map[BCM_MAX_PONS_PER_OLT] = { };
1233 bcmolt_topology topo = { };
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001234
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001235 topo.topology_maps.len = BCM_MAX_PONS_PER_OLT;
1236 topo.topology_maps.arr = &topo_map[0];
1237 BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
1238 BCMOLT_MSG_FIELD_GET(&olt_cfg, bal_state);
1239 BCMOLT_FIELD_SET_PRESENT(&olt_cfg.data, olt_cfg_data, topology);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001240 BCMOLT_CFG_LIST_BUF_SET(&olt_cfg, olt, topo.topology_maps.arr,
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001241 sizeof(bcmolt_topology_map) * topo.topology_maps.len);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001242 #ifdef TEST_MODE
1243 // It is impossible to mock the setting of olt_cfg.data.bal_state because
1244 // the actual bcmolt_cfg_get passes the address of olt_cfg.hdr and we cannot
1245 // set the olt_cfg.data.topology. So a new stub function is created and address
1246 // of olt_cfg is passed. This is one-of case where we need to test add specific
1247 // code in production code.
1248 err = bcmolt_cfg_get__olt_topology_stub(dev_id, &olt_cfg);
1249 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001250 err = bcmolt_cfg_get(dev_id, &olt_cfg.hdr);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001251 #endif
1252 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001253 OPENOLT_LOG(ERROR, openolt_log_id, "cfg: Failed to query OLT\n");
1254 return bcm_to_grpc_err(err, "cfg: Failed to query OLT");
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001255 }
1256
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001257 num_of_nni_ports = olt_cfg.data.topology.num_switch_ports;
1258 num_of_pon_ports = olt_cfg.data.topology.topology_maps.len;
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001259
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001260 OPENOLT_LOG(INFO, openolt_log_id, "OLT capabilitites, oper_state: %s\n",
1261 olt_cfg.data.bal_state == BCMOLT_BAL_STATE_BAL_AND_SWITCH_READY
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001262 ? "up" : "down");
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001263
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001264 OPENOLT_LOG(INFO, openolt_log_id, "topology nni: %d pon: %d dev: %d\n",
1265 num_of_nni_ports,
1266 num_of_pon_ports,
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001267 BCM_MAX_DEVS_PER_LINE_CARD);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001268
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001269 for (int devid = 0; devid < BCM_MAX_DEVS_PER_LINE_CARD; devid++) {
1270 dev_key.device_id = devid;
1271 BCMOLT_CFG_INIT(&dev_cfg, device, dev_key);
1272 BCMOLT_MSG_FIELD_GET(&dev_cfg, firmware_sw_version);
1273 BCMOLT_MSG_FIELD_GET(&dev_cfg, chip_family);
1274 BCMOLT_MSG_FIELD_GET(&dev_cfg, system_mode);
1275 err = bcmolt_cfg_get(dev_id, &dev_cfg.hdr);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001276 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001277 OPENOLT_LOG(ERROR, openolt_log_id, "device: Failed to query OLT\n");
1278 return bcm_to_grpc_err(err, "device: Failed to query OLT");
1279 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001280
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001281 std::string bal_version;
1282 bal_version += std::to_string(dev_cfg.data.firmware_sw_version.major)
1283 + "." + std::to_string(dev_cfg.data.firmware_sw_version.minor)
1284 + "." + std::to_string(dev_cfg.data.firmware_sw_version.revision);
1285 firmware_version = "BAL." + bal_version + "__" + firmware_version;
1286
1287 switch(dev_cfg.data.system_mode) {
1288 case 10: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*4,(devid+1)*4,"GPON"); break;
1289 case 11: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*8,(devid+1)*8,"GPON"); break;
1290 case 12: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"GPON"); break;
1291 case 13: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,"XGPON"); break;
1292 case 14: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*4,(devid+1)*4,"XGPON"); break;
1293 case 15: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*8,(devid+1)*8,"XGPON"); break;
1294 case 16: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"XGPON"); break;
1295 case 18: board_technology = "XGS-PON"; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,"XGS-PON"); break;
1296 case 19: board_technology = "XGS-PON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"XGS-PON"); break;
1297 case 20: board_technology = MIXED_TECH; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,MIXED_TECH); break;
1298 }
1299
1300 switch(dev_cfg.data.chip_family) {
1301 case BCMOLT_CHIP_FAMILY_CHIP_FAMILY_6862_X_: chip_family = "Maple"; break;
1302 case BCMOLT_CHIP_FAMILY_CHIP_FAMILY_6865_X_: chip_family = "Aspen"; break;
1303 }
1304
1305 OPENOLT_LOG(INFO, openolt_log_id, "device %d, pon: %d, version %s object model: %d, family: %s, board_technology: %s\n",
1306 devid, BCM_MAX_PONS_PER_DEV, bal_version.c_str(), BAL_API_VERSION, chip_family.c_str(), board_technology.c_str());
1307
1308 bcmos_usleep(500000);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001309 }
1310
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001311 return Status::OK;
1312}
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001313#if 0
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001314Status ProbePonIfTechnology_() {
1315 // Probe maximum extent possible as configured into BAL driver to determine
1316 // which are active in the current BAL topology. And for those
1317 // that are active, determine each port's access technology, i.e. "gpon" or "xgspon".
1318 for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001319 bcmolt_pon_interface_cfg interface_obj;
1320 bcmolt_pon_interface_key interface_key;
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001321
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001322 interface_key.pon_ni = intf_id;
1323 BCMOLT_CFG_INIT(&interface_obj, pon_interface, interface_key);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001324 if (board_technology == "XGS-PON"
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001325 BCMOLT_MSG_FIELD_GET(&interface_obj, xgs_ngpon2_trx);
1326 else if (board_technology == "GPON")
1327 BCMOLT_MSG_FIELD_GET(&interface_obj, gpon_trx);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001328
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001329 bcmos_errno err = bcmolt_cfg_get(dev_id, &interface_obj.hdr);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001330 if (err != BCM_ERR_OK) {
Craig Lutgenb2601f02018-10-23 13:04:31 -05001331 intf_technologies[intf_id] = UNKNOWN_TECH;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001332 if(err != BCM_ERR_RANGE) OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get PON config: %d err %d\n", intf_id, err);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001333 }
1334 else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001335 if (board_technology == "XGS-PON") {
1336 switch(interface_obj.data.xgpon_trx.transceiver_type) {
1337 case BCMOLT_XGPON_TRX_TYPE_LTH_7222_PC:
1338 case BCMOLT_XGPON_TRX_TYPE_WTD_RTXM266_702:
1339 case BCMOLT_XGPON_TRX_TYPE_LTH_7222_BC_PLUS:
1340 case BCMOLT_XGPON_TRX_TYPE_LTH_7226_PC:
1341 case BCMOLT_XGPON_TRX_TYPE_LTH_5302_PC:
1342 case BCMOLT_XGPON_TRX_TYPE_LTH_7226_A_PC_PLUS:
1343 case BCMOLT_XGPON_TRX_TYPE_D272RR_SSCB_DM:
1344 intf_technologies[intf_id] = "XGS-PON";
1345 break;
1346 }
1347 } else if (board_technology == "GPON") {
1348 switch(interface_obj.data.gpon_trx.transceiver_type) {
1349 case BCMOLT_TRX_TYPE_SPS_43_48_H_HP_CDE_SD_2013:
1350 case BCMOLT_TRX_TYPE_LTE_3680_M:
1351 case BCMOLT_TRX_TYPE_SOURCE_PHOTONICS:
1352 case BCMOLT_TRX_TYPE_LTE_3680_P_TYPE_C_PLUS:
1353 case BCMOLT_TRX_TYPE_LTE_3680_P_BC:
1354 intf_technologies[intf_id] = "GPON";
1355 break;
1356 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001357 }
Craig Lutgenb2601f02018-10-23 13:04:31 -05001358
1359 if (board_technology != UNKNOWN_TECH) {
1360 board_technology = intf_technologies[intf_id];
1361 } else if (board_technology != MIXED_TECH && board_technology != intf_technologies[intf_id]) {
1362 intf_technologies[intf_id] = MIXED_TECH;
1363 }
1364
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001365 }
1366 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001367 return Status::OK;
1368}
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001369#endif
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001370unsigned NumNniIf_() {return num_of_nni_ports;}
1371unsigned NumPonIf_() {return num_of_pon_ports;}
1372
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001373bcmos_errno get_nni_interface_status(bcmolt_interface id, bcmolt_interface_state *state) {
1374 bcmos_errno err;
1375 bcmolt_nni_interface_key nni_key;
1376 bcmolt_nni_interface_cfg nni_cfg;
1377 nni_key.id = id;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001378
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001379 BCMOLT_CFG_INIT(&nni_cfg, nni_interface, nni_key);
1380 BCMOLT_FIELD_SET_PRESENT(&nni_cfg.data, nni_interface_cfg_data, state);
1381 err = bcmolt_cfg_get(dev_id, &nni_cfg.hdr);
1382 *state = nni_cfg.data.state;
1383 return err;
1384}
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001385
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001386Status SetStateUplinkIf_(uint32_t intf_id, bool set_state) {
1387 bcmos_errno err = BCM_ERR_OK;
1388 bcmolt_nni_interface_key intf_key = {.id = (bcmolt_interface)intf_id};
1389 bcmolt_nni_interface_set_nni_state nni_interface_set_state;
1390 bcmolt_interface_state state;
Craig Lutgend0bae9b2018-10-18 18:02:07 -05001391
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001392 err = get_nni_interface_status((bcmolt_interface)intf_id, &state);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001393 if (err == BCM_ERR_OK) {
1394 if (set_state && state == BCMOLT_INTERFACE_STATE_ACTIVE_WORKING) {
Jason Huangbf45ffb2019-10-30 17:29:02 +08001395 OPENOLT_LOG(WARNING, openolt_log_id, "NNI interface: %d already enabled\n", intf_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001396 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for NNI interface: %d\n", intf_id);
1397 CreateDefaultSched(intf_id, upstream);
1398 CreateDefaultQueue(intf_id, upstream);
1399 return Status::OK;
1400 } else if (!set_state && state == BCMOLT_INTERFACE_STATE_INACTIVE) {
1401 OPENOLT_LOG(INFO, openolt_log_id, "NNI interface: %d already disabled\n", intf_id);
1402 return Status::OK;
1403 }
Craig Lutgend0bae9b2018-10-18 18:02:07 -05001404 }
1405
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001406 BCMOLT_OPER_INIT(&nni_interface_set_state, nni_interface, set_nni_state, intf_key);
1407 if (set_state) {
1408 BCMOLT_FIELD_SET(&nni_interface_set_state.data, nni_interface_set_nni_state_data,
1409 nni_state, BCMOLT_INTERFACE_OPERATION_ACTIVE_WORKING);
1410 } else {
1411 BCMOLT_FIELD_SET(&nni_interface_set_state.data, nni_interface_set_nni_state_data,
1412 nni_state, BCMOLT_INTERFACE_OPERATION_INACTIVE);
1413 }
1414 err = bcmolt_oper_submit(dev_id, &nni_interface_set_state.hdr);
1415 if (err != BCM_ERR_OK) {
1416 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to %s NNI interface: %d, err %d\n",
1417 (set_state)?"enable":"disable", intf_id, err);
1418 return bcm_to_grpc_err(err, "Failed to enable NNI interface");
1419 }
1420 else {
1421 OPENOLT_LOG(INFO, openolt_log_id, "Successfully %s NNI interface: %d\n", (set_state)?"enable":"disable", intf_id);
1422 if (set_state) {
1423 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for NNI interface: %d\n", intf_id);
1424 CreateDefaultSched(intf_id, upstream);
1425 CreateDefaultQueue(intf_id, upstream);
1426 }
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001427 }
1428
1429 return Status::OK;
1430}
1431
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001432Status DisablePonIf_(uint32_t intf_id) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001433 bcmolt_pon_interface_cfg interface_obj;
1434 bcmolt_pon_interface_key interface_key;
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001435
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001436 interface_key.pon_ni = intf_id;
1437 BCMOLT_CFG_INIT(&interface_obj, pon_interface, interface_key);
1438 BCMOLT_MSG_FIELD_GET(&interface_obj, state);
1439 bcmos_errno err = bcmolt_cfg_get(dev_id, &interface_obj.hdr);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001440 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001441 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to disable PON interface: %d\n", intf_id);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001442 return bcm_to_grpc_err(err, "Failed to disable PON interface");
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001443 }
1444
1445 return Status::OK;
1446}
1447
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001448Status ActivateOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001449 const char *vendor_id, const char *vendor_specific, uint32_t pir) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001450 bcmos_errno err = BCM_ERR_OK;
1451 bcmolt_onu_cfg onu_cfg;
1452 bcmolt_onu_key onu_key;
1453 bcmolt_serial_number serial_number; /**< ONU serial number */
1454 bcmolt_bin_str_36 registration_id; /**< ONU registration ID */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001455
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001456 onu_key.onu_id = onu_id;
1457 onu_key.pon_ni = intf_id;
1458 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
1459 BCMOLT_FIELD_SET_PRESENT(&onu_cfg.data, onu_cfg_data, onu_state);
1460 err = bcmolt_cfg_get(dev_id, &onu_cfg.hdr);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001461 if (err == BCM_ERR_OK) {
1462 if ((onu_cfg.data.onu_state == BCMOLT_ONU_STATE_PROCESSING ||
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001463 onu_cfg.data.onu_state == BCMOLT_ONU_STATE_ACTIVE) ||
1464 (onu_cfg.data.onu_state == BCMOLT_ONU_STATE_INACTIVE &&
1465 onu_cfg.data.onu_old_state == BCMOLT_ONU_STATE_NOT_CONFIGURED))
1466 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001467 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001468
1469 OPENOLT_LOG(INFO, openolt_log_id, "Enabling ONU %d on PON %d : vendor id %s, \
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001470vendor specific %s, pir %d\n", onu_id, intf_id, vendor_id,
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001471 vendor_specific_to_str(vendor_specific).c_str(), pir);
1472
1473 memcpy(serial_number.vendor_id.arr, vendor_id, 4);
1474 memcpy(serial_number.vendor_specific.arr, vendor_specific, 4);
1475 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
1476 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.serial_number, serial_number);
1477 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.auto_learning, BCMOS_TRUE);
1478 /*set burst and data profiles to fec disabled*/
1479 if (board_technology == "XGS-PON") {
1480 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.xgpon.ranging_burst_profile, 2);
1481 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.xgpon.data_burst_profile, 1);
1482 } else if (board_technology == "GPON") {
1483 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.gpon.ds_ber_reporting_interval, 1000000);
1484 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.gpon.omci_port_id, onu_id);
1485 }
1486 err = bcmolt_cfg_set(dev_id, &onu_cfg.hdr);
1487 if (err != BCM_ERR_OK) {
1488 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to set activate ONU %d on PON %d, err %d\n", onu_id, intf_id, err);
1489 return bcm_to_grpc_err(err, "Failed to activate ONU");
1490 }
1491
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001492 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001493}
1494
Jonathan Davis70c21812018-07-19 15:32:10 -04001495Status DeactivateOnu_(uint32_t intf_id, uint32_t onu_id,
1496 const char *vendor_id, const char *vendor_specific) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001497 bcmos_errno err = BCM_ERR_OK;
1498 bcmolt_onu_set_onu_state onu_oper; /* declare main API struct */
1499 bcmolt_onu_cfg onu_cfg;
1500 bcmolt_onu_key onu_key; /**< Object key. */
1501 bcmolt_onu_state onu_state;
Jonathan Davis70c21812018-07-19 15:32:10 -04001502
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001503 onu_key.onu_id = onu_id;
1504 onu_key.pon_ni = intf_id;
1505 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
1506 BCMOLT_FIELD_SET_PRESENT(&onu_cfg.data, onu_cfg_data, onu_state);
1507 err = bcmolt_cfg_get(dev_id, &onu_cfg.hdr);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001508 if (err == BCM_ERR_OK) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001509 switch (onu_state) {
1510 case BCMOLT_ONU_OPERATION_ACTIVE:
1511 BCMOLT_OPER_INIT(&onu_oper, onu, set_onu_state, onu_key);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001512 BCMOLT_FIELD_SET(&onu_oper.data, onu_set_onu_state_data,
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001513 onu_state, BCMOLT_ONU_OPERATION_INACTIVE);
1514 err = bcmolt_oper_submit(dev_id, &onu_oper.hdr);
1515 if (err != BCM_ERR_OK) {
1516 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to \
1517deactivate ONU %d on PON %d, err %d\n", onu_id, intf_id, err);
1518 return bcm_to_grpc_err(err, "Failed to deactivate ONU");
1519 }
1520 break;
1521 }
Jonathan Davis70c21812018-07-19 15:32:10 -04001522 }
1523
1524 return Status::OK;
1525}
1526
1527Status DeleteOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001528 const char *vendor_id, const char *vendor_specific) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001529
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001530 OPENOLT_LOG(INFO, openolt_log_id, "DeleteOnu ONU %d on PON %d : vendor id %s, vendor specific %s\n",
Craig Lutgend0bae9b2018-10-18 18:02:07 -05001531 onu_id, intf_id, vendor_id, vendor_specific_to_str(vendor_specific).c_str());
1532
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001533 // Need to deactivate before removing it (BAL rules)
1534
1535 DeactivateOnu_(intf_id, onu_id, vendor_id, vendor_specific);
1536 // Sleep to allow the state to propagate
1537 // We need the subscriber terminal object to be admin down before removal
1538 // Without sleep the race condition is lost by ~ 20 ms
1539 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1540
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001541 // TODO: Delete the schedulers and queues.
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001542
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001543 bcmolt_onu_cfg cfg_obj;
1544 bcmolt_onu_key key;
Jonathan Davis70c21812018-07-19 15:32:10 -04001545
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001546 OPENOLT_LOG(INFO, openolt_log_id, "Processing subscriber terminal cfg clear for sub_term_id %d and intf_id %d\n",
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001547 onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -04001548
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001549 key.onu_id = onu_id;
1550 key.pon_ni = intf_id;
1551 BCMOLT_CFG_INIT(&cfg_obj, onu, key);
Jonathan Davis70c21812018-07-19 15:32:10 -04001552
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001553 bcmos_errno err = bcmolt_cfg_clear(dev_id, &cfg_obj.hdr);
Jonathan Davis70c21812018-07-19 15:32:10 -04001554 if (err != BCM_ERR_OK)
1555 {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001556 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to clear information for BAL subscriber_terminal_id %d, Interface ID %d\n",
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001557 onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -04001558 return Status(grpc::StatusCode::INTERNAL, "Failed to delete ONU");
1559 }
1560
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001561 return Status::OK;
Jonathan Davis70c21812018-07-19 15:32:10 -04001562}
1563
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001564#define MAX_CHAR_LENGTH 20
1565#define MAX_OMCI_MSG_LENGTH 44
1566Status OmciMsgOut_(uint32_t intf_id, uint32_t onu_id, const std::string pkt) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001567 bcmolt_bin_str buf = {};
1568 bcmolt_onu_cpu_packets omci_cpu_packets;
1569 bcmolt_onu_key key;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001570
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001571 key.pon_ni = intf_id;
1572 key.onu_id = onu_id;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001573
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001574 BCMOLT_OPER_INIT(&omci_cpu_packets, onu, cpu_packets, key);
1575 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, packet_type, BCMOLT_PACKET_TYPE_OMCI);
1576 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, calc_crc, BCMOS_TRUE);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001577
1578 // ???
1579 if ((pkt.size()/2) > MAX_OMCI_MSG_LENGTH) {
1580 buf.len = MAX_OMCI_MSG_LENGTH;
1581 } else {
1582 buf.len = pkt.size()/2;
1583 }
1584
1585 /* Send the OMCI packet using the BAL remote proxy API */
1586 uint16_t idx1 = 0;
1587 uint16_t idx2 = 0;
1588 uint8_t arraySend[buf.len];
1589 char str1[MAX_CHAR_LENGTH];
1590 char str2[MAX_CHAR_LENGTH];
1591 memset(&arraySend, 0, buf.len);
1592
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001593 for (idx1=0,idx2=0; idx1<((buf.len)*2); idx1++,idx2++) {
1594 sprintf(str1,"%c", pkt[idx1]);
1595 sprintf(str2,"%c", pkt[++idx1]);
1596 strcat(str1,str2);
1597 arraySend[idx2] = strtol(str1, NULL, 16);
1598 }
1599
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001600 buf.arr = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
1601 memcpy(buf.arr, (uint8_t *)arraySend, buf.len);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001602
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001603 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, number_of_packets, 1);
1604 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, packet_size, buf.len);
1605 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, buffer, buf);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001606
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001607 bcmos_errno err = bcmolt_oper_submit(dev_id, &omci_cpu_packets.hdr);
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001608 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001609 OPENOLT_LOG(ERROR, omci_log_id, "Error sending OMCI message to ONU %d on PON %d\n", onu_id, intf_id);
1610 return bcm_to_grpc_err(err, "send OMCI failed");
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001611 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001612 OPENOLT_LOG(DEBUG, omci_log_id, "OMCI request msg of length %d sent to ONU %d on PON %d : %s\n",
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001613 buf.len, onu_id, intf_id, pkt.c_str());
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001614 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001615 free(buf.arr);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001616
1617 return Status::OK;
1618}
1619
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001620Status OnuPacketOut_(uint32_t intf_id, uint32_t onu_id, uint32_t port_no, uint32_t gemport_id, const std::string pkt) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001621 bcmolt_pon_interface_cpu_packets pon_interface_cpu_packets; /**< declare main API struct */
1622 bcmolt_pon_interface_key key = {.pon_ni = (bcmolt_interface)intf_id}; /**< declare key */
1623 bcmolt_bin_str buf = {};
1624 bcmolt_gem_port_id gem_port_id_array[1];
1625 bcmolt_gem_port_id_list_u8_max_16 gem_port_list = {};
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001626
Craig Lutgen967a1d02018-11-27 10:41:51 -06001627 if (port_no > 0) {
1628 bool found = false;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001629 if (gemport_id == 0) {
1630 bcmos_fastlock_lock(&data_lock);
1631 // Map the port_no to one of the flows that owns it to find a gemport_id for that flow.
1632 // Pick any flow that is mapped with the same port_no.
1633 std::map<uint32_t, std::set<uint32_t> >::const_iterator it = port_to_flows.find(port_no);
1634 if (it != port_to_flows.end() && !it->second.empty()) {
1635 uint32_t flow_id = *(it->second.begin()); // Pick any flow_id out of the bag set
1636 std::map<uint32_t, uint32_t>::const_iterator fit = flowid_to_gemport.find(flow_id);
1637 if (fit != flowid_to_gemport.end()) {
1638 found = true;
1639 gemport_id = fit->second;
1640 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001641 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001642 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001643
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001644 if (!found) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001645 OPENOLT_LOG(ERROR, openolt_log_id, "Packet out failed to find destination for ONU %d port_no %u on PON %d\n",
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001646 onu_id, port_no, intf_id);
1647 return grpc::Status(grpc::StatusCode::NOT_FOUND, "no flow for port_no");
1648 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001649 OPENOLT_LOG(INFO, openolt_log_id, "Gem port %u found for ONU %d port_no %u on PON %d\n",
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001650 gemport_id, onu_id, port_no, intf_id);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001651 }
1652
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001653 gem_port_id_array[0] = gemport_id;
1654 gem_port_list.len = 1;
1655 gem_port_list.arr = gem_port_id_array;
1656 buf.len = pkt.size();
1657 buf.arr = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
1658 memcpy(buf.arr, (uint8_t *)pkt.data(), buf.len);
1659
1660 /* init the API struct */
1661 BCMOLT_OPER_INIT(&pon_interface_cpu_packets, pon_interface, cpu_packets, key);
1662 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, packet_type, BCMOLT_PACKET_TYPE_ETH);
1663 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, calc_crc, BCMOS_TRUE);
1664 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, gem_port_list, gem_port_list);
1665 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, buffer, buf);
1666
1667 OPENOLT_LOG(INFO, openolt_log_id, "Packet out of length %d sent to gemport %d on pon %d port_no %u\n",
1668 (uint8_t)pkt.size(), gemport_id, intf_id, port_no);
1669
1670 /* call API */
1671 bcmolt_oper_submit(dev_id, &pon_interface_cpu_packets.hdr);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001672 }
1673 else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001674 //TODO: Port No is 0, it is coming sender requirement.
1675 OPENOLT_LOG(INFO, openolt_log_id, "port_no %d onu %d on pon %d\n",
1676 port_no, onu_id, intf_id);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001677 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001678 free(buf.arr);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001679
1680 return Status::OK;
1681}
1682
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001683Status UplinkPacketOut_(uint32_t intf_id, const std::string pkt) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001684 bcmolt_flow_key key = {}; /* declare key */
1685 bcmolt_bin_str buffer = {};
1686 bcmolt_flow_send_eth_packet oper; /* declare main API struct */
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001687
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001688 // TODO: flow_id is currently not passed in UplinkPacket message from voltha.
1689 bcmolt_flow_id flow_id = 0;
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001690
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001691 //validate flow_id and find flow_id/flow type: upstream/ingress type: PON/egress type: NNI
1692 if (get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, FLOW_TYPE) == BCMOLT_FLOW_TYPE_UPSTREAM && \
1693 get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, INGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_PON && \
1694 get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, EGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_NNI)
1695 key.flow_id = flow_id;
1696 else {
1697 if (flow_id_counters != 0) {
1698 for (int flowid=0; flowid < flow_id_counters; flowid++) {
1699 int flow_index = flow_id_data[flowid][0];
1700 if (get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, FLOW_TYPE) == BCMOLT_FLOW_TYPE_UPSTREAM && \
1701 get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, INGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_PON && \
1702 get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, EGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_NNI) {
1703 key.flow_id = flow_index;
1704 break;
1705 }
1706 }
1707 }
1708 else {
1709 return grpc::Status(grpc::StatusCode::NOT_FOUND, "no flow id found");
1710 }
1711 }
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001712
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001713 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM; /* send from uplink direction */
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001714
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001715 /* Initialize the API struct. */
1716 BCMOLT_OPER_INIT(&oper, flow, send_eth_packet, key);
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001717
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001718 buffer.len = pkt.size();
1719 buffer.arr = (uint8_t *)malloc((buffer.len)*sizeof(uint8_t));
1720 memcpy(buffer.arr, (uint8_t *)pkt.data(), buffer.len);
1721 if (buffer.arr == NULL) {
1722 OPENOLT_LOG(ERROR, openolt_log_id, "allocate packet buffer failed\n");
1723 return bcm_to_grpc_err(BCM_ERR_PARM, "allocate packet buffer failed");
1724 }
1725 BCMOLT_FIELD_SET(&oper.data, flow_send_eth_packet_data, buffer, buffer);
1726
1727 bcmos_errno err = bcmolt_oper_submit(dev_id, &oper.hdr);
1728 if (err) {
1729 OPENOLT_LOG(ERROR, openolt_log_id, "Error sending packets via nni port %d, flow_id %d err %d\n", intf_id, key.flow_id, err);
1730 } else {
1731 OPENOLT_LOG(INFO, openolt_log_id, "sent packets to port %d in upstream direction, flow_id %d \n", intf_id, key.flow_id);
1732 }
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001733
1734 return Status::OK;
1735}
1736
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001737uint32_t GetPortNum_(uint32_t flow_id) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001738 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001739 uint32_t port_no = 0;
1740 std::map<uint32_t, uint32_t >::const_iterator it = flowid_to_port.find(flow_id);
1741 if (it != flowid_to_port.end()) {
1742 port_no = it->second;
1743 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001744 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001745 return port_no;
1746}
1747
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001748#define FLOW_LOG(level,msg,err) \
1749 do { \
1750 OPENOLT_LOG(level, openolt_log_id, "--------> %s (flow_id %d) err: %d <--------\n", msg, key.flow_id, err); \
1751 OPENOLT_LOG(level, openolt_log_id, "intf_id %d, onu_id %d, uni_id %d, port_no %u, cookie %"PRIu64"\n", \
1752 access_intf_id, onu_id, uni_id, port_no, cookie); \
1753 OPENOLT_LOG(level, openolt_log_id, "flow_type %s, queue_id %d, sched_id %d\n", flow_type.c_str(), \
1754 cfg.data.egress_qos.u.fixed_queue.queue_id, cfg.data.egress_qos.tm_sched.id); \
1755 OPENOLT_LOG(level, openolt_log_id, "Ingress(intfd_type %s, intf_id %d), Egress(intf_type %s, intf_id %d)\n", \
1756 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), cfg.data.ingress_intf.intf_id, \
1757 GET_FLOW_INTERFACE_TYPE(cfg.data.egress_intf.intf_type), cfg.data.egress_intf.intf_id); \
1758 OPENOLT_LOG(level, openolt_log_id, "classifier(o_vid %d, o_pbits %d, i_vid %d, i_pbits %d, ether type 0x%x)\n", \
1759 c_val.o_vid, c_val.o_pbits, c_val.i_vid, c_val.i_pbits, classifier.eth_type()); \
1760 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", \
1761 c_val.ip_proto, gemport_id, c_val.src_port, c_val.dst_port, GET_PKT_TAG_TYPE(c_val.pkt_tag_type)); \
1762 OPENOLT_LOG(level, openolt_log_id, "action(cmds_bitmask %s, o_vid %d, o_pbits %d, i_vid %d, i_pbits %d)\n\n", \
1763 get_flow_acton_command(a_val.cmds_bitmask), a_val.o_vid, a_val.o_pbits, a_val.i_vid, a_val.i_pbits); \
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001764 } while(0)
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001765
1766#define FLOW_PARAM_LOG() \
1767 do { \
1768 OPENOLT_LOG(INFO, openolt_log_id, "--------> flow comparison (now before) <--------\n"); \
1769 OPENOLT_LOG(INFO, openolt_log_id, "flow_id (%d %d)\n", \
1770 key.flow_id, flow_index); \
1771 OPENOLT_LOG(INFO, openolt_log_id, "onu_id (%d %lu)\n", \
1772 cfg.data.onu_id , get_flow_status(flow_index, flow_id_data[flowid][1], ONU_ID)); \
1773 OPENOLT_LOG(INFO, openolt_log_id, "type (%d %lu)\n", \
1774 key.flow_type, get_flow_status(flow_index, flow_id_data[flowid][1], FLOW_TYPE)); \
1775 OPENOLT_LOG(INFO, openolt_log_id, "svc_port_id (%d %lu)\n", \
1776 cfg.data.svc_port_id, get_flow_status(flow_index, flow_id_data[flowid][1], SVC_PORT_ID)); \
1777 OPENOLT_LOG(INFO, openolt_log_id, "priority (%d %lu)\n", \
1778 cfg.data.priority, get_flow_status(flow_index, flow_id_data[flowid][1], PRIORITY)); \
1779 OPENOLT_LOG(INFO, openolt_log_id, "cookie (%lu %lu)\n", \
1780 cfg.data.cookie, get_flow_status(flow_index, flow_id_data[flowid][1], COOKIE)); \
1781 OPENOLT_LOG(INFO, openolt_log_id, "ingress intf_type (%s %s)\n", \
1782 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), \
1783 GET_FLOW_INTERFACE_TYPE(get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_TYPE))); \
1784 OPENOLT_LOG(INFO, openolt_log_id, "ingress intf id (%d %lu)\n", \
1785 cfg.data.ingress_intf.intf_id , get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_ID)); \
1786 OPENOLT_LOG(INFO, openolt_log_id, "egress intf_type (%d %lu)\n", \
1787 cfg.data.egress_intf.intf_type , get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_TYPE)); \
1788 OPENOLT_LOG(INFO, openolt_log_id, "egress intf_id (%d %lu)\n", \
1789 cfg.data.egress_intf.intf_id , get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_ID)); \
1790 OPENOLT_LOG(INFO, openolt_log_id, "classifier o_vid (%d %lu)\n", \
1791 c_val.o_vid , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_VID)); \
1792 OPENOLT_LOG(INFO, openolt_log_id, "classifier o_pbits (%d %lu)\n", \
1793 c_val.o_pbits , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_PBITS)); \
1794 OPENOLT_LOG(INFO, openolt_log_id, "classifier i_vid (%d %lu)\n", \
1795 c_val.i_vid , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_VID)); \
1796 OPENOLT_LOG(INFO, openolt_log_id, "classifier i_pbits (%d %lu)\n", \
1797 c_val.i_pbits , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_PBITS)); \
1798 OPENOLT_LOG(INFO, openolt_log_id, "classifier ether_type (0x%x 0x%lx)\n", \
1799 c_val.ether_type , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_ETHER_TYPE)); \
1800 OPENOLT_LOG(INFO, openolt_log_id, "classifier ip_proto (%d %lu)\n", \
1801 c_val.ip_proto , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_IP_PROTO)); \
1802 OPENOLT_LOG(INFO, openolt_log_id, "classifier src_port (%d %lu)\n", \
1803 c_val.src_port , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_SRC_PORT)); \
1804 OPENOLT_LOG(INFO, openolt_log_id, "classifier dst_port (%d %lu)\n", \
1805 c_val.dst_port , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_DST_PORT)); \
1806 OPENOLT_LOG(INFO, openolt_log_id, "classifier pkt_tag_type (%s %s)\n", \
1807 GET_PKT_TAG_TYPE(c_val.pkt_tag_type), \
1808 GET_PKT_TAG_TYPE(get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_PKT_TAG_TYPE))); \
1809 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos type (%d %lu)\n", \
1810 cfg.data.egress_qos.type , get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TYPE)); \
1811 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos queue_id (%d %lu)\n", \
1812 cfg.data.egress_qos.u.fixed_queue.queue_id, \
1813 get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_QUEUE_ID)); \
1814 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos sched_id (%d %lu)\n", \
1815 cfg.data.egress_qos.tm_sched.id, \
1816 get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TM_SCHED_ID)); \
1817 OPENOLT_LOG(INFO, openolt_log_id, "classifier cmds_bitmask (%s %s)\n", \
1818 get_flow_acton_command(a_val.cmds_bitmask), \
1819 get_flow_acton_command(get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_CMDS_BITMASK))); \
1820 OPENOLT_LOG(INFO, openolt_log_id, "action o_vid (%d %lu)\n", \
1821 a_val.o_vid , get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_VID)); \
1822 OPENOLT_LOG(INFO, openolt_log_id, "action i_vid (%d %lu)\n", \
1823 a_val.i_vid , get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_VID)); \
1824 OPENOLT_LOG(INFO, openolt_log_id, "action o_pbits (%d %lu)\n", \
1825 a_val.o_pbits , get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_PBITS)); \
1826 OPENOLT_LOG(INFO, openolt_log_id, "action i_pbits (%d %lu)\n\n", \
1827 a_val.i_pbits, get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_PBITS)); \
1828 } while(0)
1829
1830#define FLOW_CHECKER
1831//#define SHOW_FLOW_PARAM
1832
Craig Lutgen967a1d02018-11-27 10:41:51 -06001833Status FlowAdd_(int32_t access_intf_id, int32_t onu_id, int32_t uni_id, uint32_t port_no,
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001834 uint32_t flow_id, const std::string flow_type,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001835 int32_t alloc_id, int32_t network_intf_id,
1836 int32_t gemport_id, const ::openolt::Classifier& classifier,
Craig Lutgen967a1d02018-11-27 10:41:51 -06001837 const ::openolt::Action& action, int32_t priority_value, uint64_t cookie) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001838 bcmolt_flow_cfg cfg;
1839 bcmolt_flow_key key = { }; /**< Object key. */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001840 int32_t o_vid = -1;
1841 bool single_tag = false;
1842 uint32_t ether_type = 0;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001843 bcmolt_classifier c_val = { };
1844 bcmolt_action a_val = { };
1845 bcmolt_tm_queue_ref tm_val = { };
1846 int tm_qmp_id, tm_q_set_id;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001847
1848 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001849 if (flow_type.compare(upstream) == 0 ) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001850 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001851 } else if (flow_type.compare(downstream) == 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001852 key.flow_type = BCMOLT_FLOW_TYPE_DOWNSTREAM;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001853 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001854 OPENOLT_LOG(ERROR, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001855 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001856 }
1857
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001858 BCMOLT_CFG_INIT(&cfg, flow, key);
1859 BCMOLT_MSG_FIELD_SET(&cfg, cookie, cookie);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001860
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001861 if (access_intf_id >= 0 && network_intf_id >= 0) {
1862 if (key.flow_type == BCMOLT_FLOW_TYPE_UPSTREAM) { //upstream
1863 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_PON);
1864 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_id, access_intf_id);
1865 if (classifier.eth_type() == EAP_ETHER_TYPE || //EAPOL packet
1866 (classifier.ip_proto() == 17 && classifier.src_port() == 68 && classifier.dst_port() == 67)) { //DHCP packet
1867 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_HOST);
1868 } else {
1869 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_NNI);
1870 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_id, network_intf_id);
1871 }
1872 } else if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) { //downstream
1873 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_NNI);
1874 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_id, network_intf_id);
1875 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_PON);
1876 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_id, access_intf_id);
1877 }
1878 } else {
1879 OPENOLT_LOG(ERROR, openolt_log_id, "flow network setting invalid\n");
1880 return bcm_to_grpc_err(BCM_ERR_PARM, "flow network setting invalid");
1881 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001882
Shad Ansari39739bc2018-09-13 21:38:37 +00001883 if (onu_id >= 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001884 BCMOLT_MSG_FIELD_SET(&cfg, onu_id, onu_id);
Shad Ansari39739bc2018-09-13 21:38:37 +00001885 }
1886 if (gemport_id >= 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001887 BCMOLT_MSG_FIELD_SET(&cfg, svc_port_id, gemport_id);
Shad Ansari39739bc2018-09-13 21:38:37 +00001888 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001889 if (gemport_id >= 0 && port_no != 0) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001890 bcmos_fastlock_lock(&data_lock);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001891 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
Craig Lutgen967a1d02018-11-27 10:41:51 -06001892 port_to_flows[port_no].insert(key.flow_id);
1893 flowid_to_gemport[key.flow_id] = gemport_id;
1894 }
1895 else
1896 {
1897 flowid_to_port[key.flow_id] = port_no;
1898 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001899 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001900 }
Shad Ansari39739bc2018-09-13 21:38:37 +00001901 if (priority_value >= 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001902 BCMOLT_MSG_FIELD_SET(&cfg, priority, priority_value);
Shad Ansari39739bc2018-09-13 21:38:37 +00001903 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001904
1905 {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001906 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001907 if (classifier.o_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001908 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_tpid 0x%04x\n", classifier.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001909 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_tpid, classifier.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001910 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001911 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001912 if (classifier.o_vid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001913 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_vid %d\n", classifier.o_vid());
1914 BCMOLT_FIELD_SET(&c_val, classifier, o_vid, classifier.o_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001915 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001916 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001917 if (classifier.i_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001918 OPENOLT_LOG(DEBUG, openolt_log_id, "classify i_tpid 0x%04x\n", classifier.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001919 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, i_tpid, classifier.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001920 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001921 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001922 if (classifier.i_vid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001923 OPENOLT_LOG(DEBUG, openolt_log_id, "classify i_vid %d\n", classifier.i_vid());
1924 BCMOLT_FIELD_SET(&c_val, classifier, i_vid, classifier.i_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001925 }
1926
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001927 if (classifier.eth_type()) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001928 ether_type = classifier.eth_type();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001929 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ether_type 0x%04x\n", classifier.eth_type());
1930 BCMOLT_FIELD_SET(&c_val, classifier, ether_type, classifier.eth_type());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001931 }
1932
1933 /*
1934 if (classifier.dst_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001935 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_mac, classifier.dst_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001936 }
1937
1938 if (classifier.src_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001939 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_mac, classifier.src_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001940 }
1941 */
1942
1943 if (classifier.ip_proto()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001944 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ip_proto %d\n", classifier.ip_proto());
1945 BCMOLT_FIELD_SET(&c_val, classifier, ip_proto, classifier.ip_proto());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001946 }
1947
1948 /*
1949 if (classifier.dst_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001950 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_ip, classifier.dst_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001951 }
1952
1953 if (classifier.src_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001954 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_ip, classifier.src_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001955 }
1956 */
1957
1958 if (classifier.src_port()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001959 OPENOLT_LOG(DEBUG, openolt_log_id, "classify src_port %d\n", classifier.src_port());
1960 BCMOLT_FIELD_SET(&c_val, classifier, src_port, classifier.src_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001961 }
1962
1963 if (classifier.dst_port()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001964 OPENOLT_LOG(DEBUG, openolt_log_id, "classify dst_port %d\n", classifier.dst_port());
1965 BCMOLT_FIELD_SET(&c_val, classifier, dst_port, classifier.dst_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001966 }
1967
1968 if (!classifier.pkt_tag_type().empty()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001969 OPENOLT_LOG(DEBUG, openolt_log_id, "classify tag_type %s\n", classifier.pkt_tag_type().c_str());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001970 if (classifier.pkt_tag_type().compare("untagged") == 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001971 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_UNTAGGED);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001972 } else if (classifier.pkt_tag_type().compare("single_tag") == 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001973 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_SINGLE_TAG);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001974 single_tag = true;
1975
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001976 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1977 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, classifier.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001978 } else if (classifier.pkt_tag_type().compare("double_tag") == 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001979 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_DOUBLE_TAG);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001980
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001981 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1982 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, classifier.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001983 }
1984 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001985 BCMOLT_MSG_FIELD_SET(&cfg, classifier, c_val);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001986 }
1987
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001988 if (cfg.data.egress_intf.intf_type != BCMOLT_FLOW_INTERFACE_TYPE_HOST) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001989 const ::openolt::ActionCmd& cmd = action.cmd();
1990
1991 if (cmd.add_outer_tag()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001992 OPENOLT_LOG(DEBUG, openolt_log_id, "action add o_tag\n");
1993 BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, BCMOLT_ACTION_CMD_ID_ADD_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001994 }
1995
1996 if (cmd.remove_outer_tag()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001997 OPENOLT_LOG(DEBUG, openolt_log_id, "action pop o_tag\n");
1998 BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, BCMOLT_ACTION_CMD_ID_REMOVE_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001999 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002000 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002001 if (cmd.trap_to_host()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002002 OPENOLT_LOG(INFO, openolt_log_id, "action trap-to-host\n");
Craig Lutgen19512312018-11-02 10:14:46 -05002003 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, cmds_bitmask, BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002004 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002005 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002006 if (action.o_vid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002007 OPENOLT_LOG(DEBUG, openolt_log_id, "action o_vid=%d\n", action.o_vid());
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002008 o_vid = action.o_vid();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002009 BCMOLT_FIELD_SET(&a_val, action, o_vid, action.o_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002010 }
2011
2012 if (action.o_pbits()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002013 OPENOLT_LOG(DEBUG, openolt_log_id, "action o_pbits=0x%x\n", action.o_pbits());
2014 BCMOLT_FIELD_SET(&a_val, action, o_pbits, action.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002015 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002016 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002017 if (action.o_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002018 OPENOLT_LOG(INFO, openolt_log_id, "action o_tpid=0x%04x\n", action.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05002019 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, o_tpid, action.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002020 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002021 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002022 if (action.i_vid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002023 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_vid=%d\n", action.i_vid());
2024 BCMOLT_FIELD_SET(&a_val, action, i_vid, action.i_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002025 }
2026
2027 if (action.i_pbits()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002028 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_pbits=0x%x\n", action.i_pbits());
2029 BCMOLT_FIELD_SET(&a_val, action, i_pbits, action.i_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002030 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002031 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002032 if (action.i_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002033 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_tpid=0x%04x\n", action.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05002034 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, i_tpid, action.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002035 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002036 */
2037 BCMOLT_MSG_FIELD_SET(&cfg, action, a_val);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002038 }
2039
Shad Ansari39739bc2018-09-13 21:38:37 +00002040 if ((access_intf_id >= 0) && (onu_id >= 0)) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002041 if(single_tag && ether_type == EAP_ETHER_TYPE) {
2042 tm_val.sched_id = (flow_type.compare(upstream) == 0) ? \
2043 get_default_tm_sched_id(network_intf_id, upstream) : \
2044 get_default_tm_sched_id(access_intf_id, downstream);
2045 tm_val.queue_id = 0;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002046
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002047 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE);
2048 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2049 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002050
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002051 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2052 flow_type.c_str(), tm_val.queue_id, tm_val.sched_id, \
2053 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2054 } else {
2055 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
2056 tm_val.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, downstream);
2057
2058 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2059 // Queue 0 on DS subscriber scheduler
2060 tm_val.queue_id = 0;
2061
2062 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2063 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2064 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
2065
2066 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2067 downstream.c_str(), tm_val.queue_id, tm_val.sched_id, \
2068 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2069
2070 } else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2071 /* Fetch TM QMP ID mapped to DS subscriber scheduler */
2072 tm_qmp_id = tm_q_set_id = get_tm_qmp_id(tm_val.sched_id, access_intf_id, onu_id, uni_id);
2073
2074 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2075 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2076 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_qmp_id, tm_qmp_id);
2077 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_q_set_id, tm_q_set_id);
2078
2079 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, q_set_id = %d, sched_id = %d, intf_type %s\n", \
2080 downstream.c_str(), tm_q_set_id, tm_val.sched_id, \
2081 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2082 }
2083 } else if (key.flow_type == BCMOLT_FLOW_TYPE_UPSTREAM) {
2084 // NNI Scheduler ID
2085 tm_val.sched_id = get_default_tm_sched_id(network_intf_id, upstream);
2086 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2087 // Queue 0 on NNI scheduler
2088 tm_val.queue_id = 0;
2089 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2090 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2091 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
2092
2093 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2094 upstream.c_str(), tm_val.queue_id, tm_val.sched_id, \
2095 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2096
2097 } else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2098 /* Fetch TM QMP ID mapped to US NNI scheduler */
2099 tm_qmp_id = tm_q_set_id = get_tm_qmp_id(tm_val.sched_id, access_intf_id, onu_id, uni_id);
2100 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2101 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2102 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_qmp_id, tm_qmp_id);
2103 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_q_set_id, tm_q_set_id);
2104
2105 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, q_set_id = %d, sched_id = %d, intf_type %s\n", \
2106 upstream.c_str(), tm_q_set_id, tm_val.sched_id, \
2107 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2108 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002109 }
Shad Ansari39739bc2018-09-13 21:38:37 +00002110 }
Shad Ansari06101952018-07-25 00:22:09 +00002111 }
2112
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002113 BCMOLT_MSG_FIELD_SET(&cfg, state, BCMOLT_FLOW_STATE_ENABLE);
2114 BCMOLT_MSG_FIELD_SET(&cfg, statistics, BCMOLT_CONTROL_STATE_ENABLE);
2115#ifdef FLOW_CHECKER
2116 //Flow Checker, To avoid duplicate flow.
2117 if (flow_id_counters != 0) {
2118 bool b_duplicate_flow = false;
2119 for (int flowid=0; flowid < flow_id_counters; flowid++) {
2120 int flow_index = flow_id_data[flowid][0];
2121 b_duplicate_flow = (cfg.data.onu_id == get_flow_status(flow_index, flow_id_data[flowid][1], ONU_ID)) && \
2122 (key.flow_type == flow_id_data[flowid][1]) && \
2123 (cfg.data.svc_port_id == get_flow_status(flow_index, flow_id_data[flowid][1], SVC_PORT_ID)) && \
2124 (cfg.data.priority == get_flow_status(flow_index, flow_id_data[flowid][1], PRIORITY)) && \
2125 (cfg.data.cookie == get_flow_status(flow_index, flow_id_data[flowid][1], COOKIE)) && \
2126 (cfg.data.ingress_intf.intf_type == get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_TYPE)) && \
2127 (cfg.data.ingress_intf.intf_id == get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_ID)) && \
2128 (cfg.data.egress_intf.intf_type == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_TYPE)) && \
2129 (cfg.data.egress_intf.intf_id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_ID)) && \
2130 (c_val.o_vid == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_VID)) && \
2131 (c_val.o_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_PBITS)) && \
2132 (c_val.i_vid == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_VID)) && \
2133 (c_val.i_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_PBITS)) && \
2134 (c_val.ether_type == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_ETHER_TYPE)) && \
2135 (c_val.ip_proto == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_IP_PROTO)) && \
2136 (c_val.src_port == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_SRC_PORT)) && \
2137 (c_val.dst_port == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_DST_PORT)) && \
2138 (c_val.pkt_tag_type == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_PKT_TAG_TYPE)) && \
2139 (cfg.data.egress_qos.type == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TYPE)) && \
2140 (cfg.data.egress_qos.u.fixed_queue.queue_id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_QUEUE_ID)) && \
2141 (cfg.data.egress_qos.tm_sched.id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TM_SCHED_ID)) && \
2142 (a_val.cmds_bitmask == get_flow_status(flowid, flow_id_data[flowid][1], ACTION_CMDS_BITMASK)) && \
2143 (a_val.o_vid == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_VID)) && \
2144 (a_val.i_vid == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_VID)) && \
2145 (a_val.o_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_PBITS)) && \
2146 (a_val.i_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_PBITS)) && \
2147 (cfg.data.state == get_flow_status(flowid, flow_id_data[flowid][1], STATE));
2148#ifdef SHOW_FLOW_PARAM
2149 // Flow Parameter
2150 FLOW_PARAM_LOG();
2151#endif
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002152
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002153 if (b_duplicate_flow) {
2154 FLOW_LOG(WARNING, "Flow duplicate", 0);
2155 return bcm_to_grpc_err(BCM_ERR_ALREADY, "flow exists");
2156 }
2157 }
2158 }
2159#endif
2160
2161 bcmos_errno err = bcmolt_cfg_set(dev_id, &cfg.hdr);
2162 if (err) {
2163 FLOW_LOG(ERROR, "Flow add failed", err);
2164 return bcm_to_grpc_err(err, "flow add failed");
2165 } else {
2166 FLOW_LOG(INFO, "Flow add ok", err);
2167 bcmos_fastlock_lock(&data_lock);
2168 flow_id_data[flow_id_counters][0] = key.flow_id;
2169 flow_id_data[flow_id_counters][1] = key.flow_type;
2170 flow_id_counters += 1;
2171 bcmos_fastlock_unlock(&data_lock, 0);
2172 }
Nicolas Palpacuer0f19b1a2018-06-07 17:29:31 -04002173
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002174 return Status::OK;
2175}
2176
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002177Status FlowRemove_(uint32_t flow_id, const std::string flow_type) {
2178
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002179 bcmolt_flow_cfg cfg;
2180 bcmolt_flow_key key = { };
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002181
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002182 key.flow_id = (bcmolt_flow_id) flow_id;
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002183 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002184 if (flow_type.compare(upstream) == 0 ) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002185 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002186 } else if (flow_type.compare(downstream) == 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002187 key.flow_type = BCMOLT_FLOW_TYPE_DOWNSTREAM;
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002188 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002189 OPENOLT_LOG(WARNING, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002190 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
2191 }
2192
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002193 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002194 uint32_t port_no = flowid_to_port[key.flow_id];
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002195 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
Craig Lutgen967a1d02018-11-27 10:41:51 -06002196 flowid_to_gemport.erase(key.flow_id);
2197 port_to_flows[port_no].erase(key.flow_id);
2198 if (port_to_flows[port_no].empty()) port_to_flows.erase(port_no);
2199 }
2200 else
2201 {
2202 flowid_to_port.erase(key.flow_id);
2203 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002204 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002205
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002206 BCMOLT_CFG_INIT(&cfg, flow, key);
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002207
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002208 bcmos_errno err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002209 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002210 OPENOLT_LOG(ERROR, openolt_log_id, "Error %d while removing flow %d, %s\n",
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04002211 err, flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002212 return Status(grpc::StatusCode::INTERNAL, "Failed to remove flow");
2213 }
2214
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002215 bcmos_fastlock_lock(&data_lock);
2216 for (int flowid=0; flowid < flow_id_counters; flowid++) {
2217 if (flow_id_data[flowid][0] == flow_id && flow_id_data[flowid][1] == key.flow_type) {
2218 flow_id_counters -= 1;
2219 for (int i=flowid; i < flow_id_counters; i++) {
2220 flow_id_data[i][0] = flow_id_data[i + 1][0];
2221 flow_id_data[i][1] = flow_id_data[i + 1][1];
2222 }
2223 break;
2224 }
2225 }
2226 bcmos_fastlock_unlock(&data_lock, 0);
2227
2228 OPENOLT_LOG(INFO, openolt_log_id, "Flow %d, %s removed\n", flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002229 return Status::OK;
2230}
2231
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002232bcmos_errno CreateDefaultSched(uint32_t intf_id, const std::string direction) {
2233 bcmos_errno err;
2234 bcmolt_tm_sched_cfg tm_sched_cfg;
2235 bcmolt_tm_sched_key tm_sched_key = {.id = 1};
2236 tm_sched_key.id = get_default_tm_sched_id(intf_id, direction);
2237
Jason Huangbf45ffb2019-10-30 17:29:02 +08002238 //check TM scheduler has configured or not
2239 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
2240 BCMOLT_MSG_FIELD_GET(&tm_sched_cfg, state);
2241 err = bcmolt_cfg_get(dev_id, &tm_sched_cfg.hdr);
2242 if (err) {
2243 OPENOLT_LOG(ERROR, openolt_log_id, "cfg: Failed to query TM scheduler\n");
2244 return err;
2245 }
2246 else if (tm_sched_cfg.data.state == BCMOLT_CONFIG_STATE_CONFIGURED) {
2247 OPENOLT_LOG(WARNING, openolt_log_id, "tm scheduler default config has already with id %d\n", tm_sched_key.id);
2248 return BCM_ERR_OK;
2249 }
2250
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002251 // bcmbal_tm_sched_owner
2252 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
2253
2254 /**< The output of the tm_sched object instance */
2255 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.type, BCMOLT_TM_SCHED_OUTPUT_TYPE_INTERFACE);
2256
2257 if (direction.compare(upstream) == 0) {
2258 // In upstream it is NNI scheduler
2259 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_type, BCMOLT_INTERFACE_TYPE_NNI);
2260 } else if (direction.compare(downstream) == 0) {
2261 // In downstream it is PON scheduler
2262 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_type, BCMOLT_INTERFACE_TYPE_PON);
2263 }
2264
2265 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_id, intf_id);
2266
2267 // bcmbal_tm_sched_type
2268 // set the deafult policy to strict priority
2269 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, sched_type, BCMOLT_TM_SCHED_TYPE_SP);
2270
2271 // num_priorities: Max number of strict priority scheduling elements
2272 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, num_priorities, 8);
2273
2274 // bcmbal_tm_shaping
2275 uint32_t cir = 1000000;
2276 uint32_t pir = 1000000;
2277 uint32_t burst = 65536;
2278 OPENOLT_LOG(INFO, openolt_log_id, "applying traffic shaping in %s pir=%u, burst=%u\n",
2279 direction.c_str(), pir, burst);
2280 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, pir);
2281 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, burst);
2282 // FIXME: Setting CIR, results in BAL throwing error 'tm_sched minimum rate is not supported yet'
2283 // BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.cir, cir);
2284 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.pir, pir);
2285 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.burst, burst);
2286
2287 err = bcmolt_cfg_set(dev_id, &tm_sched_cfg.hdr);
2288 if (err) {
2289 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create %s scheduler, id %d, intf_id %d, err %d\n", \
2290 direction.c_str(), tm_sched_key.id, intf_id, err);
2291 return err;
2292 }
2293
2294 OPENOLT_LOG(INFO, openolt_log_id, "Create %s scheduler success, id %d, intf_id %d\n", \
2295 direction.c_str(), tm_sched_key.id, intf_id);
2296 return BCM_ERR_OK;
2297}
2298
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002299bcmos_errno CreateSched(std::string direction, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t port_no,
2300 uint32_t alloc_id, tech_profile::AdditionalBW additional_bw, uint32_t weight, uint32_t priority,
2301 tech_profile::SchedulingPolicy sched_policy, tech_profile::TrafficShapingInfo tf_sh_info) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002302
2303 bcmos_errno err;
2304
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002305 if (direction == downstream) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002306 bcmolt_tm_sched_cfg tm_sched_cfg;
2307 bcmolt_tm_sched_key tm_sched_key = {.id = 1};
2308 tm_sched_key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002309
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002310 // bcmbal_tm_sched_owner
2311 // In downstream it is sub_term scheduler
2312 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002313
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002314 /**< The output of the tm_sched object instance */
2315 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.type, BCMOLT_TM_SCHED_OUTPUT_TYPE_TM_SCHED);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002316
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002317 // bcmbal_tm_sched_parent
2318 // The parent for the sub_term scheduler is the PON scheduler in the downstream
2319 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.tm_sched.tm_sched_id, get_default_tm_sched_id(intf_id, direction));
2320 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.tm_sched.tm_sched_param.u.priority.priority, priority);
2321 /* removed by BAL v3.0, N/A - No direct attachment point of type ONU, same functionality may
2322 be achieved using the' virtual' type of attachment.
2323 tm_sched_owner.u.sub_term.intf_id = intf_id;
2324 tm_sched_owner.u.sub_term.sub_term_id = onu_id;
2325 */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002326
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002327 // bcmbal_tm_sched_type
2328 // set the deafult policy to strict priority
2329 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, sched_type, BCMOLT_TM_SCHED_TYPE_SP);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002330
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002331 // num_priorities: Max number of strict priority scheduling elements
2332 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, num_priorities, 8);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002333
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002334 // bcmbal_tm_shaping
2335 if (tf_sh_info.cir() >= 0 && tf_sh_info.pir() > 0) {
2336 uint32_t cir = tf_sh_info.cir();
2337 uint32_t pir = tf_sh_info.pir();
2338 uint32_t burst = tf_sh_info.pbs();
2339 OPENOLT_LOG(INFO, openolt_log_id, "applying traffic shaping in DL cir=%u, pir=%u, burst=%u\n",
2340 cir, pir, burst);
2341 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, pir);
2342 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, burst);
2343 // FIXME: Setting CIR, results in BAL throwing error 'tm_sched minimum rate is not supported yet'
2344 //BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.cir, cir);
2345 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.pir, pir);
2346 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.burst, burst);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002347 }
2348
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002349 err = bcmolt_cfg_set(dev_id, &tm_sched_cfg.hdr);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002350 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002351 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create downstream subscriber scheduler, id %d, \
2352intf_id %d, onu_id %d, uni_id %d, port_no %u\n", tm_sched_key.id, intf_id, onu_id, \
2353 uni_id, port_no);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002354 return err;
2355 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002356 OPENOLT_LOG(INFO, openolt_log_id, "Create downstream subscriber sched, id %d, intf_id %d, onu_id %d, \
2357uni_id %d, port_no %u\n", tm_sched_key.id, intf_id, onu_id, uni_id, port_no);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002358
2359 } else { //upstream
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002360 bcmolt_itupon_alloc_cfg cfg;
2361 bcmolt_itupon_alloc_key key = { };
2362 key.pon_ni = intf_id;
2363 key.alloc_id = alloc_id;
2364 int bw_granularity = (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY;
2365 int pir_bw = tf_sh_info.pir();
2366 int cir_bw = tf_sh_info.cir();
2367 //offset to match bandwidth granularity
2368 int offset_pir_bw = pir_bw%bw_granularity;
2369 int offset_cir_bw = cir_bw%bw_granularity;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002370
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002371 pir_bw = pir_bw - offset_pir_bw;
2372 cir_bw = cir_bw - offset_cir_bw;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002373
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002374 BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002375
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002376 switch (additional_bw) {
2377 case 2: //AdditionalBW_BestEffort
2378 if (pir_bw == 0) {
2379 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
2380%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
2381 } else if (pir_bw < cir_bw) {
2382 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2383bandwidth (%d)\n", pir_bw, cir_bw);
2384 return BCM_ERR_PARM;
2385 } else if (pir_bw == cir_bw) {
2386 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
2387bandwidth for additional bandwidth eligibility of type best_effort\n");
2388 return BCM_ERR_PARM;
2389 }
2390 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_BEST_EFFORT);
2391 break;
2392 case 1: //AdditionalBW_NA
2393 if (pir_bw == 0) {
2394 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
2395%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
2396 return BCM_ERR_PARM;
2397 } else if (cir_bw == 0) {
2398 OPENOLT_LOG(ERROR, openolt_log_id, "Guaranteed bandwidth must be greater than zero for \
2399additional bandwidth eligibility of type Non-Assured (NA)\n");
2400 return BCM_ERR_PARM;
2401 } else if (pir_bw < cir_bw) {
2402 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2403bandwidth (%d)\n", pir_bw, cir_bw);
2404 return BCM_ERR_PARM;
2405 } else if (pir_bw == cir_bw) {
2406 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
2407bandwidth for additional bandwidth eligibility of type non_assured\n");
2408 return BCM_ERR_PARM;
2409 }
2410 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NON_ASSURED);
2411 break;
2412 case 0: //AdditionalBW_None
2413 if (pir_bw == 0) {
2414 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
241516000 bytes/sec\n");
2416 return BCM_ERR_PARM;
2417 } else if (cir_bw == 0) {
2418 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
2419for additional bandwidth eligibility of type None\n");
2420 return BCM_ERR_PARM;
2421 } else if (pir_bw > cir_bw) {
2422 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
2423for additional bandwidth eligibility of type None\n");
2424 OPENOLT_LOG(ERROR, openolt_log_id, "set Maximum bandwidth (%d) to Guaranteed \
2425bandwidth in None eligibility\n", pir_bw);
2426 cir_bw = pir_bw;
2427 } else if (pir_bw < cir_bw) {
2428 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2429bandwidth (%d)\n", pir_bw, cir_bw);
2430 OPENOLT_LOG(ERROR, openolt_log_id, "set Maximum bandwidth (%d) to Guaranteed \
2431bandwidth in None eligibility\n", pir_bw);
2432 cir_bw = pir_bw;
2433 }
2434 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NONE);
2435 break;
2436 default:
2437 return BCM_ERR_PARM;
Girish Gowdrue075c642019-01-23 04:05:53 -08002438 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002439 /* CBR Real Time Bandwidth which require shaping of the bandwidth allocations
2440 in a fine granularity. */
2441 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_bw, 0);
2442 /* Fixed Bandwidth with no critical requirement of shaping */
2443 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_bw, 0);
2444 /* Dynamic bandwidth which the OLT is committed to allocate upon demand */
2445 BCMOLT_MSG_FIELD_SET(&cfg, sla.guaranteed_bw, cir_bw);
2446 /* Maximum allocated bandwidth allowed for this alloc ID */
2447 BCMOLT_MSG_FIELD_SET(&cfg, sla.maximum_bw, pir_bw);
2448 BCMOLT_MSG_FIELD_SET(&cfg, sla.alloc_type, BCMOLT_ALLOC_TYPE_NSR);
2449 /* Set to True for AllocID with CBR RT Bandwidth that requires compensation
2450 for skipped allocations during quiet window */
2451 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_compensation, BCMOS_FALSE);
2452 /**< Allocation Profile index for CBR non-RT Bandwidth */
2453 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_ap_index, 0);
2454 /**< Allocation Profile index for CBR RT Bandwidth */
2455 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_ap_index, 0);
2456 /**< Alloc ID Weight used in case of Extended DBA mode */
2457 BCMOLT_MSG_FIELD_SET(&cfg, sla.weight, 0);
2458 /**< Alloc ID Priority used in case of Extended DBA mode */
2459 BCMOLT_MSG_FIELD_SET(&cfg, sla.priority, 0);
2460 BCMOLT_MSG_FIELD_SET(&cfg, onu_id, onu_id);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002461
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002462 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002463 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002464 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d,\
2465port_no %u, alloc_id %d, err %d\n", intf_id, onu_id,uni_id,port_no,alloc_id, err);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002466 return err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002467 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002468 OPENOLT_LOG(INFO, openolt_log_id, "Create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d, port_no %u, \
2469alloc_id %d\n", intf_id,onu_id,uni_id,port_no,alloc_id);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002470 }
2471
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002472 return BCM_ERR_OK;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002473}
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002474
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002475Status CreateTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
2476 uint32_t intf_id = traffic_scheds->intf_id();
2477 uint32_t onu_id = traffic_scheds->onu_id();
2478 uint32_t uni_id = traffic_scheds->uni_id();
2479 uint32_t port_no = traffic_scheds->port_no();
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002480 std::string direction;
2481 unsigned int alloc_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002482 tech_profile::SchedulerConfig sched_config;
2483 tech_profile::AdditionalBW additional_bw;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002484 uint32_t priority;
2485 uint32_t weight;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002486 tech_profile::SchedulingPolicy sched_policy;
2487 tech_profile::TrafficShapingInfo traffic_shaping_info;
2488 bcmos_errno err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002489
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002490 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
2491 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002492
2493 direction = GetDirection(traffic_sched.direction());
2494 if (direction.compare("direction-not-supported") == 0)
2495 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2496
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002497 alloc_id = traffic_sched.alloc_id();
2498 sched_config = traffic_sched.scheduler();
2499 additional_bw = sched_config.additional_bw();
2500 priority = sched_config.priority();
2501 weight = sched_config.weight();
2502 sched_policy = sched_config.sched_policy();
2503 traffic_shaping_info = traffic_sched.traffic_shaping_info();
2504 err = CreateSched(direction, intf_id, onu_id, uni_id, port_no, alloc_id, additional_bw, weight, priority,
2505 sched_policy, traffic_shaping_info);
2506 if (err) {
2507 return bcm_to_grpc_err(err, "Failed to create scheduler");
2508 }
Girish Gowdru1cdf6ce2018-08-27 02:43:02 -07002509 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002510 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002511}
Jonathan Davis70c21812018-07-19 15:32:10 -04002512
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002513bcmos_errno RemoveSched(int intf_id, int onu_id, int uni_id, int alloc_id, std::string direction) {
Jonathan Davis70c21812018-07-19 15:32:10 -04002514
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002515 bcmos_errno err;
Jonathan Davis70c21812018-07-19 15:32:10 -04002516
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002517 if (direction == upstream) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002518 bcmolt_itupon_alloc_cfg cfg;
2519 bcmolt_itupon_alloc_key key = { };
2520 key.pon_ni = intf_id;
2521 key.alloc_id = alloc_id;
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002522
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002523 BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
2524 err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
2525 if (err) {
2526 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove scheduler sched, direction = %s, intf_id %d, alloc_id %d, err %d\n", \
2527 direction.c_str(), intf_id, alloc_id, err);
2528 return err;
2529 }
2530 OPENOLT_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, intf_id %d, alloc_id %d\n", \
2531 direction.c_str(), intf_id, alloc_id);
2532 } else if (direction == downstream) {
2533 bcmolt_tm_sched_cfg cfg;
2534 bcmolt_tm_sched_key key = { };
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002535
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002536 if (is_tm_sched_id_present(intf_id, onu_id, uni_id, direction)) {
2537 key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2538 } else {
2539 OPENOLT_LOG(INFO, openolt_log_id, "schduler not present in %s, err %d\n", direction.c_str(), err);
2540 return BCM_ERR_OK;
2541 }
2542 BCMOLT_CFG_INIT(&cfg, tm_sched, key);
2543 err = bcmolt_cfg_clear(dev_id, &(cfg.hdr));
2544 if (err) {
2545 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove scheduler, direction = %s, id %d, intf_id %d, onu_id %d\n", \
2546 direction.c_str(), key.id, intf_id, onu_id);
2547 return err;
2548 }
2549 OPENOLT_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, id %d, intf_id %d, onu_id %d\n", \
2550 direction.c_str(), key.id, intf_id, onu_id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002551 }
2552
2553 free_tm_sched_id(intf_id, onu_id, uni_id, direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002554 return BCM_ERR_OK;
2555}
2556
2557Status RemoveTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
2558 uint32_t intf_id = traffic_scheds->intf_id();
2559 uint32_t onu_id = traffic_scheds->onu_id();
2560 uint32_t uni_id = traffic_scheds->uni_id();
2561 std::string direction;
2562 bcmos_errno err;
2563
2564 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
2565 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002566
2567 direction = GetDirection(traffic_sched.direction());
2568 if (direction.compare("direction-not-supported") == 0)
2569 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2570
2571 int alloc_id = traffic_sched.alloc_id();
2572 err = RemoveSched(intf_id, onu_id, uni_id, alloc_id, direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002573 if (err) {
2574 return bcm_to_grpc_err(err, "error-removing-traffic-scheduler");
2575 }
2576 }
2577 return Status::OK;
2578}
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002579
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002580bcmos_errno CreateTrafficQueueMappingProfile(uint32_t sched_id, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, \
2581 std::string direction, std::vector<uint32_t> tmq_map_profile) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002582 bcmos_errno err;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002583 bcmolt_tm_qmp_cfg tm_qmp_cfg;
2584 bcmolt_tm_qmp_key tm_qmp_key;
2585 bcmolt_arr_u8_8 pbits_to_tmq_id = {0};
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002586
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002587 int tm_qmp_id = get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id, tmq_map_profile);
2588 if (tm_qmp_id == -1) {
2589 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create tm queue mapping profile. Max allowed profile count is 16.\n");
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002590 }
Girish Gowdruf26cf882019-05-01 23:47:58 -07002591
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002592 tm_qmp_key.id = tm_qmp_id;
2593 for (uint32_t priority=0; priority<tmq_map_profile.size(); priority++) {
2594 pbits_to_tmq_id.arr[priority] = tmq_map_profile[priority];
2595 }
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002596
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002597 BCMOLT_CFG_INIT(&tm_qmp_cfg, tm_qmp, tm_qmp_key);
2598 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, type, BCMOLT_TM_QMP_TYPE_PBITS);
2599 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, pbits_to_tmq_id, pbits_to_tmq_id);
2600 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, ref_count, 0);
2601 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, state, BCMOLT_CONFIG_STATE_CONFIGURED);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002602
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002603 err = bcmolt_cfg_set(dev_id, &tm_qmp_cfg.hdr);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002604 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002605 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create tm queue mapping profile, id %d\n", \
2606 tm_qmp_key.id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002607 return err;
2608 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06002609
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002610 OPENOLT_LOG(INFO, openolt_log_id, "Create tm queue mapping profile success, id %d\n", \
2611 tm_qmp_key.id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002612 return BCM_ERR_OK;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002613}
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002614
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002615bcmos_errno RemoveTrafficQueueMappingProfile(uint32_t tm_qmp_id) {
2616 bcmos_errno err;
2617 bcmolt_tm_qmp_cfg tm_qmp_cfg;
2618 bcmolt_tm_qmp_key tm_qmp_key;
2619 tm_qmp_key.id = tm_qmp_id;
2620
2621 BCMOLT_CFG_INIT(&tm_qmp_cfg, tm_qmp, tm_qmp_key);
2622 err = bcmolt_cfg_clear(dev_id, &tm_qmp_cfg.hdr);
2623 if (err) {
2624 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove tm queue mapping profile, id %d\n", \
2625 tm_qmp_key.id);
2626 return err;
2627 }
2628
2629 OPENOLT_LOG(INFO, openolt_log_id, "Remove tm queue mapping profile success, id %d\n", \
2630 tm_qmp_key.id);
2631 return BCM_ERR_OK;
2632}
2633
2634bcmos_errno CreateDefaultQueue(uint32_t intf_id, const std::string direction) {
2635 bcmos_errno err;
2636
2637 /* Create 4 Queues on given PON/NNI scheduler */
2638 for (int queue_id = 0; queue_id < 4; queue_id++) {
2639 bcmolt_tm_queue_cfg tm_queue_cfg;
2640 bcmolt_tm_queue_key tm_queue_key = {};
2641 tm_queue_key.sched_id = get_default_tm_sched_id(intf_id, direction);
2642 tm_queue_key.id = queue_id;
2643 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE)
2644 tm_queue_key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2645 else
2646 tm_queue_key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2647
2648 BCMOLT_CFG_INIT(&tm_queue_cfg, tm_queue, tm_queue_key);
2649 BCMOLT_MSG_FIELD_SET(&tm_queue_cfg, tm_sched_param.type, BCMOLT_TM_SCHED_PARAM_TYPE_PRIORITY);
2650 BCMOLT_MSG_FIELD_SET(&tm_queue_cfg, tm_sched_param.u.priority.priority, queue_id);
2651
2652 err = bcmolt_cfg_set(dev_id, &tm_queue_cfg.hdr);
2653 if (err) {
2654 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create %s tm queue, id %d, sched_id %d, tm_q_set_id %d\n", \
2655 direction.c_str(), tm_queue_key.id, tm_queue_key.sched_id, tm_queue_key.tm_q_set_id);
2656 return err;
2657 }
2658
2659 OPENOLT_LOG(INFO, openolt_log_id, "Create %s tm_queue success, id %d, sched_id %d, tm_q_set_id %d\n", \
2660 direction.c_str(), tm_queue_key.id, tm_queue_key.sched_id, tm_queue_key.tm_q_set_id);
2661 }
2662 return BCM_ERR_OK;
2663}
2664
2665bcmos_errno CreateQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
2666 uint32_t gemport_id) {
2667 bcmos_errno err;
2668 bcmolt_tm_queue_cfg cfg;
2669 bcmolt_tm_queue_key key = { };
2670 OPENOLT_LOG(INFO, openolt_log_id, "creating %s queue. access_intf_id = %d, onu_id = %d, uni_id = %d \
2671gemport_id = %d\n", direction.c_str(), access_intf_id, onu_id, uni_id, gemport_id);
2672
2673 key.sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2674 get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
2675
2676 if (priority > 7) {
2677 return BCM_ERR_RANGE;
2678 }
2679
2680 /* FIXME: The upstream queues have to be created once only.
2681 The upstream queues on the NNI scheduler are shared by all subscribers.
2682 When the first scheduler comes in, the queues get created, and are re-used by all others.
2683 Also, these queues should be present until the last subscriber exits the system.
2684 One solution is to have these queues always, i.e., create it as soon as OLT is enabled.
2685
2686 There is one queue per gem port and Queue ID is fetched based on priority_q configuration
2687 for each GEM in TECH PROFILE */
2688 key.id = queue_id_list[priority];
2689
2690 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2691 // Reset the Queue ID to 0, if it is fixed queue, i.e., there is only one queue for subscriber.
2692 key.id = 0;
2693 key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2694 }
2695 else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2696 key.tm_q_set_id = get_tm_qmp_id(key.sched_id, access_intf_id, onu_id, uni_id);
2697 }
2698 else {
2699 key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2700 }
2701
2702 OPENOLT_LOG(INFO, openolt_log_id, "queue assigned queue_id = %d\n", key.id);
2703
2704 BCMOLT_CFG_INIT(&cfg, tm_queue, key);
2705 BCMOLT_MSG_FIELD_SET(&cfg, tm_sched_param.u.priority.priority, priority);
2706
2707 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
2708 if (err) {
2709 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create subscriber tm queue, direction = %s, id %d, \
2710sched_id %d, tm_q_set_id %d, intf_id %d, onu_id %d, uni_id %d, err %d\n", \
2711 direction.c_str(), key.id, key.sched_id, key.tm_q_set_id, access_intf_id, onu_id, uni_id, err);
2712 return err;
2713 }
2714
2715 OPENOLT_LOG(INFO, openolt_log_id, "Created tm_queue, direction %s, id %d, sched_id %d, tm_q_set_id %d, \
2716intf_id %d, onu_id %d, uni_id %d\n", direction.c_str(), key.id, key.sched_id, key.tm_q_set_id, access_intf_id, onu_id, uni_id);
2717 return BCM_ERR_OK;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002718}
2719
2720Status CreateTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
2721 uint32_t intf_id = traffic_queues->intf_id();
2722 uint32_t onu_id = traffic_queues->onu_id();
2723 uint32_t uni_id = traffic_queues->uni_id();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002724 uint32_t sched_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002725 std::string direction;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002726 bcmos_errno err;
2727
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002728 qos_type = (traffic_queues->traffic_queues_size() > 1) ? \
2729 BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
2730
2731 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2732 uint32_t queues_priority_q[traffic_queues->traffic_queues_size()] = {0};
2733 std::string queues_pbit_map[traffic_queues->traffic_queues_size()];
2734 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2735 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
2736
2737 direction = GetDirection(traffic_queue.direction());
2738 if (direction.compare("direction-not-supported") == 0)
2739 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2740
2741 queues_priority_q[i] = traffic_queue.priority();
2742 queues_pbit_map[i] = traffic_queue.pbit_map();
2743 }
2744
2745 std::vector<uint32_t> tmq_map_profile(8, 0);
2746 tmq_map_profile = get_tmq_map_profile(get_valid_queues_pbit_map(queues_pbit_map, COUNT_OF(queues_pbit_map)), \
2747 queues_priority_q, COUNT_OF(queues_priority_q));
2748 sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2749 get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2750
2751 int tm_qmp_id = get_tm_qmp_id(tmq_map_profile);
2752 if (tm_qmp_id == -1) {
2753 CreateTrafficQueueMappingProfile(sched_id, intf_id, onu_id, uni_id, direction, tmq_map_profile);
2754 } else if (tm_qmp_id != -1 && get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id) == -1) {
2755 OPENOLT_LOG(INFO, openolt_log_id, "tm queue mapping profile present already with id %d\n", tm_qmp_id);
2756 update_sched_qmp_id_map(sched_id, intf_id, onu_id, uni_id, tm_qmp_id);
2757 }
2758 }
2759
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002760 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2761 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002762
2763 direction = GetDirection(traffic_queue.direction());
2764 if (direction.compare("direction-not-supported") == 0)
2765 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2766
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002767 err = CreateQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002768
Girish Gowdruf26cf882019-05-01 23:47:58 -07002769 // If the queue exists already, lets not return failure and break the loop.
2770 if (err && err != BCM_ERR_ALREADY) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002771 return bcm_to_grpc_err(err, "Failed to create queue");
2772 }
2773 }
2774 return Status::OK;
2775}
2776
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002777bcmos_errno RemoveQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
2778 uint32_t gemport_id) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002779 bcmolt_tm_queue_cfg cfg;
2780 bcmolt_tm_queue_key key = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002781 bcmos_errno err;
2782
2783 if (direction == downstream) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002784 if (is_tm_sched_id_present(access_intf_id, onu_id, uni_id, direction)) {
2785 key.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
2786 key.id = queue_id_list[priority];
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002787 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002788 OPENOLT_LOG(INFO, openolt_log_id, "queue not present in DS. Not clearing, access_intf_id %d, onu_id %d, uni_id %d, gemport_id %d, direction %s\n", access_intf_id, onu_id, uni_id, gemport_id, direction.c_str());
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002789 return BCM_ERR_OK;
2790 }
2791 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002792 /* In the upstream we use pre-created queues on the NNI scheduler that are used by all subscribers.
2793 They should not be removed. So, lets return OK. */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002794 return BCM_ERR_OK;
2795 }
2796
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002797 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2798 key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2799 // Reset the queue id to 0 when using fixed queue.
2800 key.id = 0;
2801 }
2802 else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2803 key.tm_q_set_id = get_tm_qmp_id(key.sched_id, access_intf_id, onu_id, uni_id);
2804 }
2805 else {
2806 key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2807 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002808
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002809 BCMOLT_CFG_INIT(&cfg, tm_queue, key);
2810 err = bcmolt_cfg_clear(dev_id, &(cfg.hdr));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002811 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002812 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove queue, direction = %s, id %d, sched_id %d, \
2813tm_q_set_id %d, intf_id %d, onu_id %d, uni_id %d\n",
2814 direction.c_str(), key.id, key.sched_id, key.tm_q_set_id, access_intf_id, onu_id, uni_id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002815 return err;
2816 }
2817
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002818 OPENOLT_LOG(INFO, openolt_log_id, "Removed tm_queue, direction %s, id %d, sched_id %d, tm_q_set_id %d, \
2819intf_id %d, onu_id %d, uni_id %d\n", direction.c_str(), key.id, key.sched_id, key.tm_q_set_id, access_intf_id, onu_id, uni_id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002820
2821 return BCM_ERR_OK;
2822}
2823
2824Status RemoveTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
2825 uint32_t intf_id = traffic_queues->intf_id();
2826 uint32_t onu_id = traffic_queues->onu_id();
2827 uint32_t uni_id = traffic_queues->uni_id();
2828 uint32_t port_no = traffic_queues->port_no();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002829 uint32_t sched_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002830 std::string direction;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002831 bcmos_errno err;
2832
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002833 qos_type = (traffic_queues->traffic_queues_size() > 1) ? \
2834 BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
2835
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002836 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2837 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002838
2839 direction = GetDirection(traffic_queue.direction());
2840 if (direction.compare("direction-not-supported") == 0)
2841 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2842
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002843 err = RemoveQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
2844 if (err) {
2845 return bcm_to_grpc_err(err, "Failed to remove queue");
2846 }
Jonathan Davis70c21812018-07-19 15:32:10 -04002847 }
2848
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002849 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE && (direction.compare(upstream) == 0 || direction.compare(downstream) == 0 && is_tm_sched_id_present(intf_id, onu_id, uni_id, direction))) {
2850 sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2851 get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2852
2853 int tm_qmp_id = get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id);
2854 if (free_tm_qmp_id(sched_id, intf_id, onu_id, uni_id, tm_qmp_id)) {
2855 RemoveTrafficQueueMappingProfile(tm_qmp_id);
2856 }
2857 }
Jonathan Davis70c21812018-07-19 15:32:10 -04002858 return Status::OK;
Jonathan Davis70c21812018-07-19 15:32:10 -04002859}
Jason Huangbf45ffb2019-10-30 17:29:02 +08002860
2861Status check_connection() {
2862 int maxTrials = 60;
2863 while (!bcmolt_api_conn_mgr_is_connected(dev_id)) {
2864 sleep(1);
2865 if (--maxTrials == 0)
2866 return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check connection failed");
2867 else
2868 OPENOLT_LOG(INFO, openolt_log_id, "waiting for daemon connection ...\n");
2869 }
2870 OPENOLT_LOG(INFO, openolt_log_id, "daemon is connected\n");
2871 return Status::OK;
2872}
2873
2874Status check_bal_ready() {
2875 bcmos_errno err;
2876 int maxTrials = 30;
2877 bcmolt_olt_cfg olt_cfg = { };
2878 bcmolt_olt_key olt_key = { };
2879
2880 BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
2881 BCMOLT_MSG_FIELD_GET(&olt_cfg, bal_state);
2882
2883 while (olt_cfg.data.bal_state != BCMOLT_BAL_STATE_BAL_AND_SWITCH_READY) {
2884 if (--maxTrials == 0)
2885 return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check bal ready failed");
2886 sleep(5);
2887 #ifdef TEST_MODE
2888 // It is impossible to mock the setting of olt_cfg.data.bal_state because
2889 // the actual bcmolt_cfg_get passes the address of olt_cfg.hdr and we cannot
2890 // set the olt_cfg.data.bal_state. So a new stub function is created and address
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04002891 // of olt_cfg is passed. This is one-of case where we need to add test specific
2892 // code in production code.
2893 if (bcmolt_cfg_get__bal_state_stub(dev_id, &olt_cfg)) {
Jason Huangbf45ffb2019-10-30 17:29:02 +08002894 #else
2895 if (bcmolt_cfg_get(dev_id, &olt_cfg.hdr)) {
2896 #endif
2897 continue;
2898 }
2899 else
2900 OPENOLT_LOG(INFO, openolt_log_id, "waiting for BAL ready ...\n");
2901 }
2902
2903 OPENOLT_LOG(INFO, openolt_log_id, "BAL is ready\n");
2904 return Status::OK;
2905}