blob: 311e41f497f01eeb96c0fbd3fde939c54b367dec [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 }
Girish Gowdra80b0fb92019-11-15 11:40:39 +05301878 } else if (access_intf_id < 0 ) {
1879 // This is the case for packet trap from NNI flow.
1880 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_NNI);
1881 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_id, network_intf_id);
1882 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_HOST);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001883 } else {
1884 OPENOLT_LOG(ERROR, openolt_log_id, "flow network setting invalid\n");
1885 return bcm_to_grpc_err(BCM_ERR_PARM, "flow network setting invalid");
1886 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001887
Girish Gowdra80b0fb92019-11-15 11:40:39 +05301888
Shad Ansari39739bc2018-09-13 21:38:37 +00001889 if (onu_id >= 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001890 BCMOLT_MSG_FIELD_SET(&cfg, onu_id, onu_id);
Shad Ansari39739bc2018-09-13 21:38:37 +00001891 }
1892 if (gemport_id >= 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001893 BCMOLT_MSG_FIELD_SET(&cfg, svc_port_id, gemport_id);
Shad Ansari39739bc2018-09-13 21:38:37 +00001894 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001895 if (gemport_id >= 0 && port_no != 0) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001896 bcmos_fastlock_lock(&data_lock);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001897 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
Craig Lutgen967a1d02018-11-27 10:41:51 -06001898 port_to_flows[port_no].insert(key.flow_id);
1899 flowid_to_gemport[key.flow_id] = gemport_id;
1900 }
1901 else
1902 {
1903 flowid_to_port[key.flow_id] = port_no;
1904 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001905 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001906 }
Shad Ansari39739bc2018-09-13 21:38:37 +00001907 if (priority_value >= 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001908 BCMOLT_MSG_FIELD_SET(&cfg, priority, priority_value);
Shad Ansari39739bc2018-09-13 21:38:37 +00001909 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001910
1911 {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001912 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001913 if (classifier.o_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001914 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_tpid 0x%04x\n", classifier.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001915 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_tpid, classifier.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001916 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001917 */
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001918 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001919 if (classifier.i_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001920 OPENOLT_LOG(DEBUG, openolt_log_id, "classify i_tpid 0x%04x\n", classifier.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001921 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, i_tpid, classifier.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001922 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001923 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001924
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001925 if (classifier.eth_type()) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001926 ether_type = classifier.eth_type();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001927 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ether_type 0x%04x\n", classifier.eth_type());
1928 BCMOLT_FIELD_SET(&c_val, classifier, ether_type, classifier.eth_type());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001929 }
1930
1931 /*
1932 if (classifier.dst_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001933 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_mac, classifier.dst_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001934 }
1935
1936 if (classifier.src_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001937 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_mac, classifier.src_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001938 }
1939 */
1940
1941 if (classifier.ip_proto()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001942 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ip_proto %d\n", classifier.ip_proto());
1943 BCMOLT_FIELD_SET(&c_val, classifier, ip_proto, classifier.ip_proto());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001944 }
1945
1946 /*
1947 if (classifier.dst_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001948 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_ip, classifier.dst_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001949 }
1950
1951 if (classifier.src_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001952 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_ip, classifier.src_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001953 }
1954 */
1955
1956 if (classifier.src_port()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001957 OPENOLT_LOG(DEBUG, openolt_log_id, "classify src_port %d\n", classifier.src_port());
1958 BCMOLT_FIELD_SET(&c_val, classifier, src_port, classifier.src_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001959 }
1960
1961 if (classifier.dst_port()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001962 OPENOLT_LOG(DEBUG, openolt_log_id, "classify dst_port %d\n", classifier.dst_port());
1963 BCMOLT_FIELD_SET(&c_val, classifier, dst_port, classifier.dst_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001964 }
1965
1966 if (!classifier.pkt_tag_type().empty()) {
Girish Gowdra80b0fb92019-11-15 11:40:39 +05301967 if (cfg.data.ingress_intf.intf_type == BCMOLT_FLOW_INTERFACE_TYPE_NNI && \
1968 cfg.data.egress_intf.intf_type == BCMOLT_FLOW_INTERFACE_TYPE_HOST) {
1969 // This is case where packet traps from NNI port. As per Broadcom workaround
1970 // suggested in CS8839882, the packet_tag_type has to be 'untagged' irrespective
1971 // of what the actual tag type is. Otherwise, packet trap from NNI wont work.
1972 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_UNTAGGED);
1973 } else {
1974 if (classifier.o_vid()) {
1975 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_vid %d\n", classifier.o_vid());
1976 BCMOLT_FIELD_SET(&c_val, classifier, o_vid, classifier.o_vid());
1977 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001978
Girish Gowdra80b0fb92019-11-15 11:40:39 +05301979 if (classifier.i_vid()) {
1980 OPENOLT_LOG(DEBUG, openolt_log_id, "classify i_vid %d\n", classifier.i_vid());
1981 BCMOLT_FIELD_SET(&c_val, classifier, i_vid, classifier.i_vid());
1982 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001983
Girish Gowdra80b0fb92019-11-15 11:40:39 +05301984 OPENOLT_LOG(DEBUG, openolt_log_id, "classify tag_type %s\n", classifier.pkt_tag_type().c_str());
1985 if (classifier.pkt_tag_type().compare("untagged") == 0) {
1986 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_UNTAGGED);
1987 } else if (classifier.pkt_tag_type().compare("single_tag") == 0) {
1988 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_SINGLE_TAG);
1989 single_tag = true;
1990
1991 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1992 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, classifier.o_pbits());
1993 } else if (classifier.pkt_tag_type().compare("double_tag") == 0) {
1994 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_DOUBLE_TAG);
1995
1996 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1997 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, classifier.o_pbits());
1998 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001999 }
2000 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002001 BCMOLT_MSG_FIELD_SET(&cfg, classifier, c_val);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002002 }
2003
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002004 if (cfg.data.egress_intf.intf_type != BCMOLT_FLOW_INTERFACE_TYPE_HOST) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002005 const ::openolt::ActionCmd& cmd = action.cmd();
2006
2007 if (cmd.add_outer_tag()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002008 OPENOLT_LOG(DEBUG, openolt_log_id, "action add o_tag\n");
2009 BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, BCMOLT_ACTION_CMD_ID_ADD_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002010 }
2011
2012 if (cmd.remove_outer_tag()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002013 OPENOLT_LOG(DEBUG, openolt_log_id, "action pop o_tag\n");
2014 BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, BCMOLT_ACTION_CMD_ID_REMOVE_OUTER_TAG);
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 (cmd.trap_to_host()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002018 OPENOLT_LOG(INFO, openolt_log_id, "action trap-to-host\n");
Craig Lutgen19512312018-11-02 10:14:46 -05002019 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, cmds_bitmask, BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST);
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.o_vid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002023 OPENOLT_LOG(DEBUG, openolt_log_id, "action o_vid=%d\n", action.o_vid());
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002024 o_vid = action.o_vid();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002025 BCMOLT_FIELD_SET(&a_val, action, o_vid, action.o_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002026 }
2027
2028 if (action.o_pbits()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002029 OPENOLT_LOG(DEBUG, openolt_log_id, "action o_pbits=0x%x\n", action.o_pbits());
2030 BCMOLT_FIELD_SET(&a_val, action, o_pbits, action.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002031 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002032 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002033 if (action.o_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002034 OPENOLT_LOG(INFO, openolt_log_id, "action o_tpid=0x%04x\n", action.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05002035 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, o_tpid, action.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002036 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002037 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002038 if (action.i_vid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002039 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_vid=%d\n", action.i_vid());
2040 BCMOLT_FIELD_SET(&a_val, action, i_vid, action.i_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002041 }
2042
2043 if (action.i_pbits()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002044 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_pbits=0x%x\n", action.i_pbits());
2045 BCMOLT_FIELD_SET(&a_val, action, i_pbits, action.i_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002046 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002047 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002048 if (action.i_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002049 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_tpid=0x%04x\n", action.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05002050 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, i_tpid, action.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002051 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002052 */
2053 BCMOLT_MSG_FIELD_SET(&cfg, action, a_val);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002054 }
2055
Shad Ansari39739bc2018-09-13 21:38:37 +00002056 if ((access_intf_id >= 0) && (onu_id >= 0)) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002057 if(single_tag && ether_type == EAP_ETHER_TYPE) {
2058 tm_val.sched_id = (flow_type.compare(upstream) == 0) ? \
2059 get_default_tm_sched_id(network_intf_id, upstream) : \
2060 get_default_tm_sched_id(access_intf_id, downstream);
2061 tm_val.queue_id = 0;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002062
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002063 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE);
2064 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2065 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002066
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002067 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2068 flow_type.c_str(), tm_val.queue_id, tm_val.sched_id, \
2069 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2070 } else {
2071 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
2072 tm_val.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, downstream);
2073
2074 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2075 // Queue 0 on DS subscriber scheduler
2076 tm_val.queue_id = 0;
2077
2078 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2079 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2080 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
2081
2082 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2083 downstream.c_str(), tm_val.queue_id, tm_val.sched_id, \
2084 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2085
2086 } else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2087 /* Fetch TM QMP ID mapped to DS subscriber scheduler */
2088 tm_qmp_id = tm_q_set_id = get_tm_qmp_id(tm_val.sched_id, access_intf_id, onu_id, uni_id);
2089
2090 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2091 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2092 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_qmp_id, tm_qmp_id);
2093 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_q_set_id, tm_q_set_id);
2094
2095 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, q_set_id = %d, sched_id = %d, intf_type %s\n", \
2096 downstream.c_str(), tm_q_set_id, tm_val.sched_id, \
2097 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2098 }
2099 } else if (key.flow_type == BCMOLT_FLOW_TYPE_UPSTREAM) {
2100 // NNI Scheduler ID
2101 tm_val.sched_id = get_default_tm_sched_id(network_intf_id, upstream);
2102 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2103 // Queue 0 on NNI scheduler
2104 tm_val.queue_id = 0;
2105 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2106 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2107 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
2108
2109 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2110 upstream.c_str(), tm_val.queue_id, tm_val.sched_id, \
2111 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2112
2113 } else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2114 /* Fetch TM QMP ID mapped to US NNI scheduler */
2115 tm_qmp_id = tm_q_set_id = get_tm_qmp_id(tm_val.sched_id, access_intf_id, onu_id, uni_id);
2116 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2117 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2118 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_qmp_id, tm_qmp_id);
2119 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_q_set_id, tm_q_set_id);
2120
2121 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, q_set_id = %d, sched_id = %d, intf_type %s\n", \
2122 upstream.c_str(), tm_q_set_id, tm_val.sched_id, \
2123 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2124 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002125 }
Shad Ansari39739bc2018-09-13 21:38:37 +00002126 }
Girish Gowdra80b0fb92019-11-15 11:40:39 +05302127 } else {
2128 tm_val.sched_id = get_default_tm_sched_id(network_intf_id, upstream);
2129 tm_val.queue_id = 0;
2130
2131 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE);
2132 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2133 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
2134
2135 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2136 flow_type.c_str(), tm_val.queue_id, tm_val.sched_id, \
2137 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
Shad Ansari06101952018-07-25 00:22:09 +00002138 }
2139
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002140 BCMOLT_MSG_FIELD_SET(&cfg, state, BCMOLT_FLOW_STATE_ENABLE);
2141 BCMOLT_MSG_FIELD_SET(&cfg, statistics, BCMOLT_CONTROL_STATE_ENABLE);
2142#ifdef FLOW_CHECKER
2143 //Flow Checker, To avoid duplicate flow.
2144 if (flow_id_counters != 0) {
2145 bool b_duplicate_flow = false;
2146 for (int flowid=0; flowid < flow_id_counters; flowid++) {
2147 int flow_index = flow_id_data[flowid][0];
2148 b_duplicate_flow = (cfg.data.onu_id == get_flow_status(flow_index, flow_id_data[flowid][1], ONU_ID)) && \
2149 (key.flow_type == flow_id_data[flowid][1]) && \
2150 (cfg.data.svc_port_id == get_flow_status(flow_index, flow_id_data[flowid][1], SVC_PORT_ID)) && \
2151 (cfg.data.priority == get_flow_status(flow_index, flow_id_data[flowid][1], PRIORITY)) && \
2152 (cfg.data.cookie == get_flow_status(flow_index, flow_id_data[flowid][1], COOKIE)) && \
2153 (cfg.data.ingress_intf.intf_type == get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_TYPE)) && \
2154 (cfg.data.ingress_intf.intf_id == get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_ID)) && \
2155 (cfg.data.egress_intf.intf_type == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_TYPE)) && \
2156 (cfg.data.egress_intf.intf_id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_ID)) && \
2157 (c_val.o_vid == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_VID)) && \
2158 (c_val.o_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_PBITS)) && \
2159 (c_val.i_vid == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_VID)) && \
2160 (c_val.i_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_PBITS)) && \
2161 (c_val.ether_type == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_ETHER_TYPE)) && \
2162 (c_val.ip_proto == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_IP_PROTO)) && \
2163 (c_val.src_port == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_SRC_PORT)) && \
2164 (c_val.dst_port == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_DST_PORT)) && \
2165 (c_val.pkt_tag_type == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_PKT_TAG_TYPE)) && \
2166 (cfg.data.egress_qos.type == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TYPE)) && \
2167 (cfg.data.egress_qos.u.fixed_queue.queue_id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_QUEUE_ID)) && \
2168 (cfg.data.egress_qos.tm_sched.id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TM_SCHED_ID)) && \
2169 (a_val.cmds_bitmask == get_flow_status(flowid, flow_id_data[flowid][1], ACTION_CMDS_BITMASK)) && \
2170 (a_val.o_vid == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_VID)) && \
2171 (a_val.i_vid == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_VID)) && \
2172 (a_val.o_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_PBITS)) && \
2173 (a_val.i_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_PBITS)) && \
2174 (cfg.data.state == get_flow_status(flowid, flow_id_data[flowid][1], STATE));
2175#ifdef SHOW_FLOW_PARAM
2176 // Flow Parameter
2177 FLOW_PARAM_LOG();
2178#endif
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002179
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002180 if (b_duplicate_flow) {
2181 FLOW_LOG(WARNING, "Flow duplicate", 0);
2182 return bcm_to_grpc_err(BCM_ERR_ALREADY, "flow exists");
2183 }
2184 }
2185 }
2186#endif
2187
2188 bcmos_errno err = bcmolt_cfg_set(dev_id, &cfg.hdr);
2189 if (err) {
2190 FLOW_LOG(ERROR, "Flow add failed", err);
2191 return bcm_to_grpc_err(err, "flow add failed");
2192 } else {
2193 FLOW_LOG(INFO, "Flow add ok", err);
2194 bcmos_fastlock_lock(&data_lock);
2195 flow_id_data[flow_id_counters][0] = key.flow_id;
2196 flow_id_data[flow_id_counters][1] = key.flow_type;
2197 flow_id_counters += 1;
2198 bcmos_fastlock_unlock(&data_lock, 0);
2199 }
Nicolas Palpacuer0f19b1a2018-06-07 17:29:31 -04002200
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002201 return Status::OK;
2202}
2203
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002204Status FlowRemove_(uint32_t flow_id, const std::string flow_type) {
2205
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002206 bcmolt_flow_cfg cfg;
2207 bcmolt_flow_key key = { };
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002208
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002209 key.flow_id = (bcmolt_flow_id) flow_id;
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002210 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002211 if (flow_type.compare(upstream) == 0 ) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002212 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002213 } else if (flow_type.compare(downstream) == 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002214 key.flow_type = BCMOLT_FLOW_TYPE_DOWNSTREAM;
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002215 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002216 OPENOLT_LOG(WARNING, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002217 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
2218 }
2219
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002220 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002221 uint32_t port_no = flowid_to_port[key.flow_id];
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002222 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
Craig Lutgen967a1d02018-11-27 10:41:51 -06002223 flowid_to_gemport.erase(key.flow_id);
2224 port_to_flows[port_no].erase(key.flow_id);
2225 if (port_to_flows[port_no].empty()) port_to_flows.erase(port_no);
2226 }
2227 else
2228 {
2229 flowid_to_port.erase(key.flow_id);
2230 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002231 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002232
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002233 BCMOLT_CFG_INIT(&cfg, flow, key);
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002234
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002235 bcmos_errno err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002236 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002237 OPENOLT_LOG(ERROR, openolt_log_id, "Error %d while removing flow %d, %s\n",
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04002238 err, flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002239 return Status(grpc::StatusCode::INTERNAL, "Failed to remove flow");
2240 }
2241
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002242 bcmos_fastlock_lock(&data_lock);
2243 for (int flowid=0; flowid < flow_id_counters; flowid++) {
2244 if (flow_id_data[flowid][0] == flow_id && flow_id_data[flowid][1] == key.flow_type) {
2245 flow_id_counters -= 1;
2246 for (int i=flowid; i < flow_id_counters; i++) {
2247 flow_id_data[i][0] = flow_id_data[i + 1][0];
2248 flow_id_data[i][1] = flow_id_data[i + 1][1];
2249 }
2250 break;
2251 }
2252 }
2253 bcmos_fastlock_unlock(&data_lock, 0);
2254
2255 OPENOLT_LOG(INFO, openolt_log_id, "Flow %d, %s removed\n", flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002256 return Status::OK;
2257}
2258
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002259bcmos_errno CreateDefaultSched(uint32_t intf_id, const std::string direction) {
2260 bcmos_errno err;
2261 bcmolt_tm_sched_cfg tm_sched_cfg;
2262 bcmolt_tm_sched_key tm_sched_key = {.id = 1};
2263 tm_sched_key.id = get_default_tm_sched_id(intf_id, direction);
2264
Jason Huangbf45ffb2019-10-30 17:29:02 +08002265 //check TM scheduler has configured or not
2266 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
2267 BCMOLT_MSG_FIELD_GET(&tm_sched_cfg, state);
2268 err = bcmolt_cfg_get(dev_id, &tm_sched_cfg.hdr);
2269 if (err) {
2270 OPENOLT_LOG(ERROR, openolt_log_id, "cfg: Failed to query TM scheduler\n");
2271 return err;
2272 }
2273 else if (tm_sched_cfg.data.state == BCMOLT_CONFIG_STATE_CONFIGURED) {
2274 OPENOLT_LOG(WARNING, openolt_log_id, "tm scheduler default config has already with id %d\n", tm_sched_key.id);
2275 return BCM_ERR_OK;
2276 }
2277
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002278 // bcmbal_tm_sched_owner
2279 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
2280
2281 /**< The output of the tm_sched object instance */
2282 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.type, BCMOLT_TM_SCHED_OUTPUT_TYPE_INTERFACE);
2283
2284 if (direction.compare(upstream) == 0) {
2285 // In upstream it is NNI scheduler
2286 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_type, BCMOLT_INTERFACE_TYPE_NNI);
2287 } else if (direction.compare(downstream) == 0) {
2288 // In downstream it is PON scheduler
2289 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_type, BCMOLT_INTERFACE_TYPE_PON);
2290 }
2291
2292 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_id, intf_id);
2293
2294 // bcmbal_tm_sched_type
2295 // set the deafult policy to strict priority
2296 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, sched_type, BCMOLT_TM_SCHED_TYPE_SP);
2297
2298 // num_priorities: Max number of strict priority scheduling elements
2299 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, num_priorities, 8);
2300
2301 // bcmbal_tm_shaping
2302 uint32_t cir = 1000000;
2303 uint32_t pir = 1000000;
2304 uint32_t burst = 65536;
2305 OPENOLT_LOG(INFO, openolt_log_id, "applying traffic shaping in %s pir=%u, burst=%u\n",
2306 direction.c_str(), pir, burst);
2307 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, pir);
2308 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, burst);
2309 // FIXME: Setting CIR, results in BAL throwing error 'tm_sched minimum rate is not supported yet'
2310 // BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.cir, cir);
2311 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.pir, pir);
2312 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.burst, burst);
2313
2314 err = bcmolt_cfg_set(dev_id, &tm_sched_cfg.hdr);
2315 if (err) {
2316 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create %s scheduler, id %d, intf_id %d, err %d\n", \
2317 direction.c_str(), tm_sched_key.id, intf_id, err);
2318 return err;
2319 }
2320
2321 OPENOLT_LOG(INFO, openolt_log_id, "Create %s scheduler success, id %d, intf_id %d\n", \
2322 direction.c_str(), tm_sched_key.id, intf_id);
2323 return BCM_ERR_OK;
2324}
2325
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002326bcmos_errno CreateSched(std::string direction, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t port_no,
2327 uint32_t alloc_id, tech_profile::AdditionalBW additional_bw, uint32_t weight, uint32_t priority,
2328 tech_profile::SchedulingPolicy sched_policy, tech_profile::TrafficShapingInfo tf_sh_info) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002329
2330 bcmos_errno err;
2331
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002332 if (direction == downstream) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002333 bcmolt_tm_sched_cfg tm_sched_cfg;
2334 bcmolt_tm_sched_key tm_sched_key = {.id = 1};
2335 tm_sched_key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002336
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002337 // bcmbal_tm_sched_owner
2338 // In downstream it is sub_term scheduler
2339 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002340
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002341 /**< The output of the tm_sched object instance */
2342 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.type, BCMOLT_TM_SCHED_OUTPUT_TYPE_TM_SCHED);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002343
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002344 // bcmbal_tm_sched_parent
2345 // The parent for the sub_term scheduler is the PON scheduler in the downstream
2346 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.tm_sched.tm_sched_id, get_default_tm_sched_id(intf_id, direction));
2347 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.tm_sched.tm_sched_param.u.priority.priority, priority);
2348 /* removed by BAL v3.0, N/A - No direct attachment point of type ONU, same functionality may
2349 be achieved using the' virtual' type of attachment.
2350 tm_sched_owner.u.sub_term.intf_id = intf_id;
2351 tm_sched_owner.u.sub_term.sub_term_id = onu_id;
2352 */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002353
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002354 // bcmbal_tm_sched_type
2355 // set the deafult policy to strict priority
2356 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, sched_type, BCMOLT_TM_SCHED_TYPE_SP);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002357
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002358 // num_priorities: Max number of strict priority scheduling elements
2359 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, num_priorities, 8);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002360
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002361 // bcmbal_tm_shaping
2362 if (tf_sh_info.cir() >= 0 && tf_sh_info.pir() > 0) {
2363 uint32_t cir = tf_sh_info.cir();
2364 uint32_t pir = tf_sh_info.pir();
2365 uint32_t burst = tf_sh_info.pbs();
2366 OPENOLT_LOG(INFO, openolt_log_id, "applying traffic shaping in DL cir=%u, pir=%u, burst=%u\n",
2367 cir, pir, burst);
2368 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, pir);
2369 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, burst);
2370 // FIXME: Setting CIR, results in BAL throwing error 'tm_sched minimum rate is not supported yet'
2371 //BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.cir, cir);
2372 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.pir, pir);
2373 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.burst, burst);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002374 }
2375
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002376 err = bcmolt_cfg_set(dev_id, &tm_sched_cfg.hdr);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002377 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002378 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create downstream subscriber scheduler, id %d, \
2379intf_id %d, onu_id %d, uni_id %d, port_no %u\n", tm_sched_key.id, intf_id, onu_id, \
2380 uni_id, port_no);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002381 return err;
2382 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002383 OPENOLT_LOG(INFO, openolt_log_id, "Create downstream subscriber sched, id %d, intf_id %d, onu_id %d, \
2384uni_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 -08002385
2386 } else { //upstream
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002387 bcmolt_itupon_alloc_cfg cfg;
2388 bcmolt_itupon_alloc_key key = { };
2389 key.pon_ni = intf_id;
2390 key.alloc_id = alloc_id;
2391 int bw_granularity = (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY;
2392 int pir_bw = tf_sh_info.pir();
2393 int cir_bw = tf_sh_info.cir();
2394 //offset to match bandwidth granularity
2395 int offset_pir_bw = pir_bw%bw_granularity;
2396 int offset_cir_bw = cir_bw%bw_granularity;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002397
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002398 pir_bw = pir_bw - offset_pir_bw;
2399 cir_bw = cir_bw - offset_cir_bw;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002400
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002401 BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002402
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002403 switch (additional_bw) {
2404 case 2: //AdditionalBW_BestEffort
2405 if (pir_bw == 0) {
2406 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
2407%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
2408 } else if (pir_bw < cir_bw) {
2409 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2410bandwidth (%d)\n", pir_bw, cir_bw);
2411 return BCM_ERR_PARM;
2412 } else if (pir_bw == cir_bw) {
2413 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
2414bandwidth for additional bandwidth eligibility of type best_effort\n");
2415 return BCM_ERR_PARM;
2416 }
2417 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_BEST_EFFORT);
2418 break;
2419 case 1: //AdditionalBW_NA
2420 if (pir_bw == 0) {
2421 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
2422%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
2423 return BCM_ERR_PARM;
2424 } else if (cir_bw == 0) {
2425 OPENOLT_LOG(ERROR, openolt_log_id, "Guaranteed bandwidth must be greater than zero for \
2426additional bandwidth eligibility of type Non-Assured (NA)\n");
2427 return BCM_ERR_PARM;
2428 } else if (pir_bw < cir_bw) {
2429 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2430bandwidth (%d)\n", pir_bw, cir_bw);
2431 return BCM_ERR_PARM;
2432 } else if (pir_bw == cir_bw) {
2433 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
2434bandwidth for additional bandwidth eligibility of type non_assured\n");
2435 return BCM_ERR_PARM;
2436 }
2437 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NON_ASSURED);
2438 break;
2439 case 0: //AdditionalBW_None
2440 if (pir_bw == 0) {
2441 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
244216000 bytes/sec\n");
2443 return BCM_ERR_PARM;
2444 } else if (cir_bw == 0) {
2445 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
2446for additional bandwidth eligibility of type None\n");
2447 return BCM_ERR_PARM;
2448 } else if (pir_bw > cir_bw) {
2449 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
2450for additional bandwidth eligibility of type None\n");
2451 OPENOLT_LOG(ERROR, openolt_log_id, "set Maximum bandwidth (%d) to Guaranteed \
2452bandwidth in None eligibility\n", pir_bw);
2453 cir_bw = pir_bw;
2454 } else if (pir_bw < cir_bw) {
2455 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2456bandwidth (%d)\n", pir_bw, cir_bw);
2457 OPENOLT_LOG(ERROR, openolt_log_id, "set Maximum bandwidth (%d) to Guaranteed \
2458bandwidth in None eligibility\n", pir_bw);
2459 cir_bw = pir_bw;
2460 }
2461 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NONE);
2462 break;
2463 default:
2464 return BCM_ERR_PARM;
Girish Gowdrue075c642019-01-23 04:05:53 -08002465 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002466 /* CBR Real Time Bandwidth which require shaping of the bandwidth allocations
2467 in a fine granularity. */
2468 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_bw, 0);
2469 /* Fixed Bandwidth with no critical requirement of shaping */
2470 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_bw, 0);
2471 /* Dynamic bandwidth which the OLT is committed to allocate upon demand */
2472 BCMOLT_MSG_FIELD_SET(&cfg, sla.guaranteed_bw, cir_bw);
2473 /* Maximum allocated bandwidth allowed for this alloc ID */
2474 BCMOLT_MSG_FIELD_SET(&cfg, sla.maximum_bw, pir_bw);
2475 BCMOLT_MSG_FIELD_SET(&cfg, sla.alloc_type, BCMOLT_ALLOC_TYPE_NSR);
2476 /* Set to True for AllocID with CBR RT Bandwidth that requires compensation
2477 for skipped allocations during quiet window */
2478 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_compensation, BCMOS_FALSE);
2479 /**< Allocation Profile index for CBR non-RT Bandwidth */
2480 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_ap_index, 0);
2481 /**< Allocation Profile index for CBR RT Bandwidth */
2482 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_ap_index, 0);
2483 /**< Alloc ID Weight used in case of Extended DBA mode */
2484 BCMOLT_MSG_FIELD_SET(&cfg, sla.weight, 0);
2485 /**< Alloc ID Priority used in case of Extended DBA mode */
2486 BCMOLT_MSG_FIELD_SET(&cfg, sla.priority, 0);
2487 BCMOLT_MSG_FIELD_SET(&cfg, onu_id, onu_id);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002488
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002489 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002490 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002491 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d,\
2492port_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 -08002493 return err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002494 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002495 OPENOLT_LOG(INFO, openolt_log_id, "Create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d, port_no %u, \
2496alloc_id %d\n", intf_id,onu_id,uni_id,port_no,alloc_id);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002497 }
2498
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002499 return BCM_ERR_OK;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002500}
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002501
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002502Status CreateTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
2503 uint32_t intf_id = traffic_scheds->intf_id();
2504 uint32_t onu_id = traffic_scheds->onu_id();
2505 uint32_t uni_id = traffic_scheds->uni_id();
2506 uint32_t port_no = traffic_scheds->port_no();
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002507 std::string direction;
2508 unsigned int alloc_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002509 tech_profile::SchedulerConfig sched_config;
2510 tech_profile::AdditionalBW additional_bw;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002511 uint32_t priority;
2512 uint32_t weight;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002513 tech_profile::SchedulingPolicy sched_policy;
2514 tech_profile::TrafficShapingInfo traffic_shaping_info;
2515 bcmos_errno err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002516
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002517 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
2518 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002519
2520 direction = GetDirection(traffic_sched.direction());
2521 if (direction.compare("direction-not-supported") == 0)
2522 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2523
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002524 alloc_id = traffic_sched.alloc_id();
2525 sched_config = traffic_sched.scheduler();
2526 additional_bw = sched_config.additional_bw();
2527 priority = sched_config.priority();
2528 weight = sched_config.weight();
2529 sched_policy = sched_config.sched_policy();
2530 traffic_shaping_info = traffic_sched.traffic_shaping_info();
2531 err = CreateSched(direction, intf_id, onu_id, uni_id, port_no, alloc_id, additional_bw, weight, priority,
2532 sched_policy, traffic_shaping_info);
2533 if (err) {
2534 return bcm_to_grpc_err(err, "Failed to create scheduler");
2535 }
Girish Gowdru1cdf6ce2018-08-27 02:43:02 -07002536 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002537 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002538}
Jonathan Davis70c21812018-07-19 15:32:10 -04002539
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002540bcmos_errno RemoveSched(int intf_id, int onu_id, int uni_id, int alloc_id, std::string direction) {
Jonathan Davis70c21812018-07-19 15:32:10 -04002541
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002542 bcmos_errno err;
Jonathan Davis70c21812018-07-19 15:32:10 -04002543
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002544 if (direction == upstream) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002545 bcmolt_itupon_alloc_cfg cfg;
2546 bcmolt_itupon_alloc_key key = { };
2547 key.pon_ni = intf_id;
2548 key.alloc_id = alloc_id;
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002549
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002550 BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
2551 err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
2552 if (err) {
2553 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove scheduler sched, direction = %s, intf_id %d, alloc_id %d, err %d\n", \
2554 direction.c_str(), intf_id, alloc_id, err);
2555 return err;
2556 }
2557 OPENOLT_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, intf_id %d, alloc_id %d\n", \
2558 direction.c_str(), intf_id, alloc_id);
2559 } else if (direction == downstream) {
2560 bcmolt_tm_sched_cfg cfg;
2561 bcmolt_tm_sched_key key = { };
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002562
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002563 if (is_tm_sched_id_present(intf_id, onu_id, uni_id, direction)) {
2564 key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2565 } else {
2566 OPENOLT_LOG(INFO, openolt_log_id, "schduler not present in %s, err %d\n", direction.c_str(), err);
2567 return BCM_ERR_OK;
2568 }
2569 BCMOLT_CFG_INIT(&cfg, tm_sched, key);
2570 err = bcmolt_cfg_clear(dev_id, &(cfg.hdr));
2571 if (err) {
2572 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove scheduler, direction = %s, id %d, intf_id %d, onu_id %d\n", \
2573 direction.c_str(), key.id, intf_id, onu_id);
2574 return err;
2575 }
2576 OPENOLT_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, id %d, intf_id %d, onu_id %d\n", \
2577 direction.c_str(), key.id, intf_id, onu_id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002578 }
2579
2580 free_tm_sched_id(intf_id, onu_id, uni_id, direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002581 return BCM_ERR_OK;
2582}
2583
2584Status RemoveTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
2585 uint32_t intf_id = traffic_scheds->intf_id();
2586 uint32_t onu_id = traffic_scheds->onu_id();
2587 uint32_t uni_id = traffic_scheds->uni_id();
2588 std::string direction;
2589 bcmos_errno err;
2590
2591 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
2592 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002593
2594 direction = GetDirection(traffic_sched.direction());
2595 if (direction.compare("direction-not-supported") == 0)
2596 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2597
2598 int alloc_id = traffic_sched.alloc_id();
2599 err = RemoveSched(intf_id, onu_id, uni_id, alloc_id, direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002600 if (err) {
2601 return bcm_to_grpc_err(err, "error-removing-traffic-scheduler");
2602 }
2603 }
2604 return Status::OK;
2605}
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002606
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002607bcmos_errno CreateTrafficQueueMappingProfile(uint32_t sched_id, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, \
2608 std::string direction, std::vector<uint32_t> tmq_map_profile) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002609 bcmos_errno err;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002610 bcmolt_tm_qmp_cfg tm_qmp_cfg;
2611 bcmolt_tm_qmp_key tm_qmp_key;
2612 bcmolt_arr_u8_8 pbits_to_tmq_id = {0};
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002613
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002614 int tm_qmp_id = get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id, tmq_map_profile);
2615 if (tm_qmp_id == -1) {
2616 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 -08002617 }
Girish Gowdruf26cf882019-05-01 23:47:58 -07002618
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002619 tm_qmp_key.id = tm_qmp_id;
2620 for (uint32_t priority=0; priority<tmq_map_profile.size(); priority++) {
2621 pbits_to_tmq_id.arr[priority] = tmq_map_profile[priority];
2622 }
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002623
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002624 BCMOLT_CFG_INIT(&tm_qmp_cfg, tm_qmp, tm_qmp_key);
2625 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, type, BCMOLT_TM_QMP_TYPE_PBITS);
2626 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, pbits_to_tmq_id, pbits_to_tmq_id);
2627 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, ref_count, 0);
2628 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, state, BCMOLT_CONFIG_STATE_CONFIGURED);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002629
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002630 err = bcmolt_cfg_set(dev_id, &tm_qmp_cfg.hdr);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002631 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002632 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create tm queue mapping profile, id %d\n", \
2633 tm_qmp_key.id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002634 return err;
2635 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06002636
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002637 OPENOLT_LOG(INFO, openolt_log_id, "Create tm queue mapping profile success, id %d\n", \
2638 tm_qmp_key.id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002639 return BCM_ERR_OK;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002640}
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002641
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002642bcmos_errno RemoveTrafficQueueMappingProfile(uint32_t tm_qmp_id) {
2643 bcmos_errno err;
2644 bcmolt_tm_qmp_cfg tm_qmp_cfg;
2645 bcmolt_tm_qmp_key tm_qmp_key;
2646 tm_qmp_key.id = tm_qmp_id;
2647
2648 BCMOLT_CFG_INIT(&tm_qmp_cfg, tm_qmp, tm_qmp_key);
2649 err = bcmolt_cfg_clear(dev_id, &tm_qmp_cfg.hdr);
2650 if (err) {
2651 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove tm queue mapping profile, id %d\n", \
2652 tm_qmp_key.id);
2653 return err;
2654 }
2655
2656 OPENOLT_LOG(INFO, openolt_log_id, "Remove tm queue mapping profile success, id %d\n", \
2657 tm_qmp_key.id);
2658 return BCM_ERR_OK;
2659}
2660
2661bcmos_errno CreateDefaultQueue(uint32_t intf_id, const std::string direction) {
2662 bcmos_errno err;
2663
2664 /* Create 4 Queues on given PON/NNI scheduler */
2665 for (int queue_id = 0; queue_id < 4; queue_id++) {
2666 bcmolt_tm_queue_cfg tm_queue_cfg;
2667 bcmolt_tm_queue_key tm_queue_key = {};
2668 tm_queue_key.sched_id = get_default_tm_sched_id(intf_id, direction);
2669 tm_queue_key.id = queue_id;
2670 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE)
2671 tm_queue_key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2672 else
2673 tm_queue_key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2674
2675 BCMOLT_CFG_INIT(&tm_queue_cfg, tm_queue, tm_queue_key);
2676 BCMOLT_MSG_FIELD_SET(&tm_queue_cfg, tm_sched_param.type, BCMOLT_TM_SCHED_PARAM_TYPE_PRIORITY);
2677 BCMOLT_MSG_FIELD_SET(&tm_queue_cfg, tm_sched_param.u.priority.priority, queue_id);
2678
2679 err = bcmolt_cfg_set(dev_id, &tm_queue_cfg.hdr);
2680 if (err) {
2681 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create %s tm queue, id %d, sched_id %d, tm_q_set_id %d\n", \
2682 direction.c_str(), tm_queue_key.id, tm_queue_key.sched_id, tm_queue_key.tm_q_set_id);
2683 return err;
2684 }
2685
2686 OPENOLT_LOG(INFO, openolt_log_id, "Create %s tm_queue success, id %d, sched_id %d, tm_q_set_id %d\n", \
2687 direction.c_str(), tm_queue_key.id, tm_queue_key.sched_id, tm_queue_key.tm_q_set_id);
2688 }
2689 return BCM_ERR_OK;
2690}
2691
2692bcmos_errno CreateQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
2693 uint32_t gemport_id) {
2694 bcmos_errno err;
2695 bcmolt_tm_queue_cfg cfg;
2696 bcmolt_tm_queue_key key = { };
2697 OPENOLT_LOG(INFO, openolt_log_id, "creating %s queue. access_intf_id = %d, onu_id = %d, uni_id = %d \
2698gemport_id = %d\n", direction.c_str(), access_intf_id, onu_id, uni_id, gemport_id);
2699
2700 key.sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2701 get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
2702
2703 if (priority > 7) {
2704 return BCM_ERR_RANGE;
2705 }
2706
2707 /* FIXME: The upstream queues have to be created once only.
2708 The upstream queues on the NNI scheduler are shared by all subscribers.
2709 When the first scheduler comes in, the queues get created, and are re-used by all others.
2710 Also, these queues should be present until the last subscriber exits the system.
2711 One solution is to have these queues always, i.e., create it as soon as OLT is enabled.
2712
2713 There is one queue per gem port and Queue ID is fetched based on priority_q configuration
2714 for each GEM in TECH PROFILE */
2715 key.id = queue_id_list[priority];
2716
2717 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2718 // Reset the Queue ID to 0, if it is fixed queue, i.e., there is only one queue for subscriber.
2719 key.id = 0;
2720 key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2721 }
2722 else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2723 key.tm_q_set_id = get_tm_qmp_id(key.sched_id, access_intf_id, onu_id, uni_id);
2724 }
2725 else {
2726 key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2727 }
2728
2729 OPENOLT_LOG(INFO, openolt_log_id, "queue assigned queue_id = %d\n", key.id);
2730
2731 BCMOLT_CFG_INIT(&cfg, tm_queue, key);
2732 BCMOLT_MSG_FIELD_SET(&cfg, tm_sched_param.u.priority.priority, priority);
2733
2734 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
2735 if (err) {
2736 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create subscriber tm queue, direction = %s, id %d, \
2737sched_id %d, tm_q_set_id %d, intf_id %d, onu_id %d, uni_id %d, err %d\n", \
2738 direction.c_str(), key.id, key.sched_id, key.tm_q_set_id, access_intf_id, onu_id, uni_id, err);
2739 return err;
2740 }
2741
2742 OPENOLT_LOG(INFO, openolt_log_id, "Created tm_queue, direction %s, id %d, sched_id %d, tm_q_set_id %d, \
2743intf_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);
2744 return BCM_ERR_OK;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002745}
2746
2747Status CreateTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
2748 uint32_t intf_id = traffic_queues->intf_id();
2749 uint32_t onu_id = traffic_queues->onu_id();
2750 uint32_t uni_id = traffic_queues->uni_id();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002751 uint32_t sched_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002752 std::string direction;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002753 bcmos_errno err;
2754
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002755 qos_type = (traffic_queues->traffic_queues_size() > 1) ? \
2756 BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
2757
2758 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2759 uint32_t queues_priority_q[traffic_queues->traffic_queues_size()] = {0};
2760 std::string queues_pbit_map[traffic_queues->traffic_queues_size()];
2761 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2762 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
2763
2764 direction = GetDirection(traffic_queue.direction());
2765 if (direction.compare("direction-not-supported") == 0)
2766 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2767
2768 queues_priority_q[i] = traffic_queue.priority();
2769 queues_pbit_map[i] = traffic_queue.pbit_map();
2770 }
2771
2772 std::vector<uint32_t> tmq_map_profile(8, 0);
2773 tmq_map_profile = get_tmq_map_profile(get_valid_queues_pbit_map(queues_pbit_map, COUNT_OF(queues_pbit_map)), \
2774 queues_priority_q, COUNT_OF(queues_priority_q));
2775 sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2776 get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2777
2778 int tm_qmp_id = get_tm_qmp_id(tmq_map_profile);
2779 if (tm_qmp_id == -1) {
2780 CreateTrafficQueueMappingProfile(sched_id, intf_id, onu_id, uni_id, direction, tmq_map_profile);
2781 } else if (tm_qmp_id != -1 && get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id) == -1) {
2782 OPENOLT_LOG(INFO, openolt_log_id, "tm queue mapping profile present already with id %d\n", tm_qmp_id);
2783 update_sched_qmp_id_map(sched_id, intf_id, onu_id, uni_id, tm_qmp_id);
2784 }
2785 }
2786
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002787 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2788 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002789
2790 direction = GetDirection(traffic_queue.direction());
2791 if (direction.compare("direction-not-supported") == 0)
2792 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2793
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002794 err = CreateQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002795
Girish Gowdruf26cf882019-05-01 23:47:58 -07002796 // If the queue exists already, lets not return failure and break the loop.
2797 if (err && err != BCM_ERR_ALREADY) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002798 return bcm_to_grpc_err(err, "Failed to create queue");
2799 }
2800 }
2801 return Status::OK;
2802}
2803
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002804bcmos_errno RemoveQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
2805 uint32_t gemport_id) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002806 bcmolt_tm_queue_cfg cfg;
2807 bcmolt_tm_queue_key key = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002808 bcmos_errno err;
2809
2810 if (direction == downstream) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002811 if (is_tm_sched_id_present(access_intf_id, onu_id, uni_id, direction)) {
2812 key.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
2813 key.id = queue_id_list[priority];
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002814 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002815 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 -08002816 return BCM_ERR_OK;
2817 }
2818 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002819 /* In the upstream we use pre-created queues on the NNI scheduler that are used by all subscribers.
2820 They should not be removed. So, lets return OK. */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002821 return BCM_ERR_OK;
2822 }
2823
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002824 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2825 key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2826 // Reset the queue id to 0 when using fixed queue.
2827 key.id = 0;
2828 }
2829 else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2830 key.tm_q_set_id = get_tm_qmp_id(key.sched_id, access_intf_id, onu_id, uni_id);
2831 }
2832 else {
2833 key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2834 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002835
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002836 BCMOLT_CFG_INIT(&cfg, tm_queue, key);
2837 err = bcmolt_cfg_clear(dev_id, &(cfg.hdr));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002838 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002839 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove queue, direction = %s, id %d, sched_id %d, \
2840tm_q_set_id %d, intf_id %d, onu_id %d, uni_id %d\n",
2841 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 -08002842 return err;
2843 }
2844
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002845 OPENOLT_LOG(INFO, openolt_log_id, "Removed tm_queue, direction %s, id %d, sched_id %d, tm_q_set_id %d, \
2846intf_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 -08002847
2848 return BCM_ERR_OK;
2849}
2850
2851Status RemoveTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
2852 uint32_t intf_id = traffic_queues->intf_id();
2853 uint32_t onu_id = traffic_queues->onu_id();
2854 uint32_t uni_id = traffic_queues->uni_id();
2855 uint32_t port_no = traffic_queues->port_no();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002856 uint32_t sched_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002857 std::string direction;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002858 bcmos_errno err;
2859
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002860 qos_type = (traffic_queues->traffic_queues_size() > 1) ? \
2861 BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
2862
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002863 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2864 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002865
2866 direction = GetDirection(traffic_queue.direction());
2867 if (direction.compare("direction-not-supported") == 0)
2868 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2869
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002870 err = RemoveQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
2871 if (err) {
2872 return bcm_to_grpc_err(err, "Failed to remove queue");
2873 }
Jonathan Davis70c21812018-07-19 15:32:10 -04002874 }
2875
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002876 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))) {
2877 sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2878 get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2879
2880 int tm_qmp_id = get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id);
2881 if (free_tm_qmp_id(sched_id, intf_id, onu_id, uni_id, tm_qmp_id)) {
2882 RemoveTrafficQueueMappingProfile(tm_qmp_id);
2883 }
2884 }
Jonathan Davis70c21812018-07-19 15:32:10 -04002885 return Status::OK;
Jonathan Davis70c21812018-07-19 15:32:10 -04002886}
Jason Huangbf45ffb2019-10-30 17:29:02 +08002887
2888Status check_connection() {
2889 int maxTrials = 60;
2890 while (!bcmolt_api_conn_mgr_is_connected(dev_id)) {
2891 sleep(1);
2892 if (--maxTrials == 0)
2893 return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check connection failed");
2894 else
2895 OPENOLT_LOG(INFO, openolt_log_id, "waiting for daemon connection ...\n");
2896 }
2897 OPENOLT_LOG(INFO, openolt_log_id, "daemon is connected\n");
2898 return Status::OK;
2899}
2900
2901Status check_bal_ready() {
2902 bcmos_errno err;
2903 int maxTrials = 30;
2904 bcmolt_olt_cfg olt_cfg = { };
2905 bcmolt_olt_key olt_key = { };
2906
2907 BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
2908 BCMOLT_MSG_FIELD_GET(&olt_cfg, bal_state);
2909
2910 while (olt_cfg.data.bal_state != BCMOLT_BAL_STATE_BAL_AND_SWITCH_READY) {
2911 if (--maxTrials == 0)
2912 return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check bal ready failed");
2913 sleep(5);
2914 #ifdef TEST_MODE
2915 // It is impossible to mock the setting of olt_cfg.data.bal_state because
2916 // the actual bcmolt_cfg_get passes the address of olt_cfg.hdr and we cannot
2917 // set the olt_cfg.data.bal_state. So a new stub function is created and address
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04002918 // of olt_cfg is passed. This is one-of case where we need to add test specific
2919 // code in production code.
2920 if (bcmolt_cfg_get__bal_state_stub(dev_id, &olt_cfg)) {
Jason Huangbf45ffb2019-10-30 17:29:02 +08002921 #else
2922 if (bcmolt_cfg_get(dev_id, &olt_cfg.hdr)) {
2923 #endif
2924 continue;
2925 }
2926 else
2927 OPENOLT_LOG(INFO, openolt_log_id, "waiting for BAL ready ...\n");
2928 }
2929
2930 OPENOLT_LOG(INFO, openolt_log_id, "BAL is ready\n");
2931 return Status::OK;
2932}