blob: c1a381a315fc10b8523c5664bbc3c4a7688dee0c [file] [log] [blame]
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001/*
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04002 Copyright (C) 2018 Open Networking Foundation
Shad Ansarib7b0ced2018-05-11 21:53:32 +00003
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include <iostream>
19#include <memory>
20#include <string>
21
22#include "Queue.h"
Shad Ansarib7b0ced2018-05-11 21:53:32 +000023#include <sstream>
Nicolas Palpacuer9c352082018-08-14 16:37:14 -040024#include <chrono>
25#include <thread>
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -080026#include <bitset>
Jason Huangd33b4d82019-05-15 18:22:57 +080027#include <inttypes.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{
Jason Huangd33b4d82019-05-15 18:22:57 +080039#include <bcmolt_api.h>
40#include <bcmolt_host_api.h>
41#include <bcmolt_api_model_supporting_enums.h>
Girish Gowdrae538dfd2019-09-30 11:07:30 +053042
Jason Huangd33b4d82019-05-15 18:22:57 +080043#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>
Girish Gowdrae538dfd2019-09-30 11:07:30 +053049
Jason Huangd33b4d82019-05-15 18:22:57 +080050#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}
Girish Gowdrae538dfd2019-09-30 11:07:30 +053056
57
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 Subramani1f1280b2019-08-13 18:41:19 +080063#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
Jason Huangb6843dc2019-07-22 17:46:06 +080068#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);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +080071#define COUNT_OF(array) (sizeof(array) / sizeof(array[0]))
Jason Huangb6843dc2019-07-22 17:46:06 +080072
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 Subramani1f1280b2019-08-13 18:41:19 +080084static 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);
Jason Huangd33b4d82019-05-15 18:22:57 +080088static std::string chip_family(UNKNOWN_TECH);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -080089static unsigned int OPENOLT_FIELD_LEN = 200;
Jason Huangb6843dc2019-07-22 17:46:06 +080090static std::string firmware_version = "Openolt.2019.07.01";
Nicolas Palpacuerdff96792018-09-06 14:59:32 -040091
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +080092const 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";
Jason Huangd33b4d82019-05-15 18:22:57 +0800104bcmolt_oltid dev_id = 0;
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +0800105
Jason Huangd33b4d82019-05-15 18:22:57 +0800106/* 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";
Jason Huangb6843dc2019-07-22 17:46:06 +0800112uint16_t flow_id_counters = 0;
113int flow_id_data[16384][2];
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700114
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +0800115/* 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;
119
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 Subramani1f1280b2019-08-13 18:41:19 +0800126/* 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 Subramani1f1280b2019-08-13 18:41:19 +0800129/* '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 Subramani1f1280b2019-08-13 18:41:19 +0800133/* 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 Subramani1f1280b2019-08-13 18:41:19 +0800142std::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);
Jason Huangb6843dc2019-07-22 17:46:06 +0800153static 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 Subramani1f1280b2019-08-13 18:41:19 +0800157static bcmos_errno CreateDefaultSched(uint32_t intf_id, const std::string direction);
158static bcmos_errno CreateDefaultQueue(uint32_t intf_id, const std::string direction);
Shad Ansari627b5782018-08-13 22:49:32 +0000159
Jason Huangd33b4d82019-05-15 18:22:57 +0800160uint16_t get_dev_id(void) {
161 return dev_id;
162}
163
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800164/**
165* Returns the default NNI (Upstream direction) or PON (Downstream direction) scheduler
166* Every NNI port and PON port have default scheduler.
167* The NNI0 default scheduler ID is 18432, and NNI1 is 18433 and so on.
168* Similarly, PON0 default scheduler ID is 16384. PON1 is 16385 and so on.
169*
170* @param intf_id NNI or PON interface ID
171* @param direction "upstream" or "downstream"
172*
173* @return default scheduler ID for the given interface.
174*/
175static inline int get_default_tm_sched_id(int intf_id, std::string direction) {
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700176 if (direction.compare(upstream) == 0) {
177 return tm_upstream_sched_id_start + intf_id;
178 } else if (direction.compare(downstream) == 0) {
179 return tm_downstream_sched_id_start + intf_id;
180 }
181 else {
Jason Huangb6843dc2019-07-22 17:46:06 +0800182 OPENOLT_LOG(ERROR, openolt_log_id, "invalid direction - %s\n", direction.c_str());
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700183 return 0;
184 }
185}
186
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800187/**
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800188* Gets a unique tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
189* The tm_sched_id is locally cached in a map, so that it can rendered when necessary.
190* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
191*
192* @param intf_id NNI or PON intf ID
193* @param onu_id ONU ID
194* @param uni_id UNI ID
195* @param gemport_id GEM Port ID
196* @param direction Upstream or downstream
197*
198* @return tm_sched_id
199*/
200uint32_t get_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
201 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
202 int sched_id = -1;
203
204 std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
205 if (it != sched_map.end()) {
206 sched_id = it->second;
207 }
208 if (sched_id != -1) {
209 return sched_id;
210 }
211
212 bcmos_fastlock_lock(&data_lock);
213 // Complexity of O(n). Is there better way that can avoid linear search?
214 for (sched_id = 0; sched_id < MAX_TM_SCHED_ID; sched_id++) {
215 if (tm_sched_bitset[sched_id] == 0) {
216 tm_sched_bitset[sched_id] = 1;
217 break;
218 }
219 }
220 bcmos_fastlock_unlock(&data_lock, 0);
221
222 if (sched_id < MAX_TM_SCHED_ID) {
223 bcmos_fastlock_lock(&data_lock);
224 sched_map[key] = sched_id;
225 bcmos_fastlock_unlock(&data_lock, 0);
226 return sched_id;
227 } else {
228 return -1;
229 }
230}
231
232/**
233* Free tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
234*
235* @param intf_id NNI or PON intf ID
236* @param onu_id ONU ID
237* @param uni_id UNI ID
238* @param gemport_id GEM Port ID
239* @param direction Upstream or downstream
240*/
241void free_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
242 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
243 std::map<sched_map_key_tuple, int>::const_iterator it;
244 bcmos_fastlock_lock(&data_lock);
245 it = sched_map.find(key);
246 if (it != sched_map.end()) {
247 tm_sched_bitset[it->second] = 0;
248 sched_map.erase(it);
249 }
250 bcmos_fastlock_unlock(&data_lock, 0);
251}
252
253bool is_tm_sched_id_present(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
254 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +0800255 std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
256 if (it != sched_map.end()) {
257 return true;
258 }
259 return false;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800260}
261
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +0800262/**
263* Check whether given two tm qmp profiles are equal or not
264*
265* @param tmq_map_profileA <vector> TM QUEUE MAPPING PROFILE
266* @param tmq_map_profileB <vector> TM QUEUE MAPPING PROFILE
267*
268* @return boolean, true if given tmq_map_profiles are equal else false
269*/
270
271bool check_tm_qmp_equality(std::vector<uint32_t> tmq_map_profileA, std::vector<uint32_t> tmq_map_profileB) {
272 for (uint32_t i = 0; i < TMQ_MAP_PROFILE_SIZE; i++) {
273 if (tmq_map_profileA[i] != tmq_map_profileB[i]) {
274 return false;
275 }
276 }
277 return true;
278}
279
280/**
281* Modifies given queues_pbit_map to parsable format
282* e.g: Modifes "0b00000101" to "10100000"
283*
284* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
285* @param size Queue count
286*
287* @return string queues_pbit_map
288*/
289std::string* get_valid_queues_pbit_map(std::string *queues_pbit_map, uint32_t size) {
290 for(uint32_t i=0; i < size; i++) {
291 /* Deletes 2 characters from index number 0 */
292 queues_pbit_map[i].erase(0, 2);
293 std::reverse(queues_pbit_map[i].begin(), queues_pbit_map[i].end());
294 }
295 return queues_pbit_map;
296}
297
298/**
299* Creates TM QUEUE MAPPING PROFILE for given queues_pbit_map and queues_priority_q
300*
301* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
302* @param queues_priority_q PRIORITY_Q configured for each GEM in TECH PROFILE
303* @param size Queue count
304*
305* @return <vector> TM QUEUE MAPPING PROFILE
306*/
307std::vector<uint32_t> get_tmq_map_profile(std::string *queues_pbit_map, uint32_t *queues_priority_q, uint32_t size) {
308 std::vector<uint32_t> tmq_map_profile(8,0);
309
310 for(uint32_t i=0; i < size; i++) {
311 for (uint32_t j = 0; j < queues_pbit_map[i].size(); j++) {
312 if (queues_pbit_map[i][j]=='1') {
313 tmq_map_profile.at(j) = queue_id_list[queues_priority_q[i]];
314 }
315 }
316 }
317 return tmq_map_profile;
318}
319
320/**
321* Gets corresponding tm_qmp_id for a given tmq_map_profile
322*
323* @param <vector> TM QUEUE MAPPING PROFILE
324*
325* @return tm_qmp_id
326*/
327int get_tm_qmp_id(std::vector<uint32_t> tmq_map_profile) {
328 int tm_qmp_id = -1;
329
330 std::map<int, std::vector < uint32_t > >::const_iterator it = qmp_id_to_qmp_map.begin();
331 while(it != qmp_id_to_qmp_map.end()) {
332 if(check_tm_qmp_equality(tmq_map_profile, it->second)) {
333 tm_qmp_id = it->first;
334 break;
335 }
336 it++;
337 }
338 return tm_qmp_id;
339}
340
341/**
342* Updates sched_qmp_id_map with given sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id
343*
344* @param upstream/downstream sched_id
345* @param PON intf ID
346* @param onu_id ONU ID
347* @param uni_id UNI ID
348* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
349*/
350void update_sched_qmp_id_map(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
351 uint32_t uni_id, int tm_qmp_id) {
352 bcmos_fastlock_lock(&data_lock);
353 sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
354 sched_qmp_id_map.insert(make_pair(key, tm_qmp_id));
355 bcmos_fastlock_unlock(&data_lock, 0);
356}
357
358/**
359* Gets corresponding tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
360*
361* @param upstream/downstream sched_id
362* @param PON intf ID
363* @param onu_id ONU ID
364* @param uni_id UNI ID
365*
366* @return tm_qmp_id
367*/
368int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id) {
369 sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
370 int tm_qmp_id = -1;
371
372 std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
373 if (it != sched_qmp_id_map.end()) {
374 tm_qmp_id = it->second;
375 }
376 return tm_qmp_id;
377}
378
379/**
380* Gets a unique tm_qmp_id for a given tmq_map_profile
381* The tm_qmp_id is locally cached in a map, so that it can be rendered when necessary.
382* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
383*
384* @param upstream/downstream sched_id
385* @param PON intf ID
386* @param onu_id ONU ID
387* @param uni_id UNI ID
388* @param <vector> TM QUEUE MAPPING PROFILE
389*
390* @return tm_qmp_id
391*/
392int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id, \
393 std::vector<uint32_t> tmq_map_profile) {
394 int tm_qmp_id;
395
396 bcmos_fastlock_lock(&data_lock);
397 /* Complexity of O(n). Is there better way that can avoid linear search? */
398 for (tm_qmp_id = 0; tm_qmp_id < MAX_TM_QMP_ID; tm_qmp_id++) {
399 if (tm_qmp_bitset[tm_qmp_id] == 0) {
400 tm_qmp_bitset[tm_qmp_id] = 1;
401 break;
402 }
403 }
404 bcmos_fastlock_unlock(&data_lock, 0);
405
406 if (tm_qmp_id < MAX_TM_QMP_ID) {
407 bcmos_fastlock_lock(&data_lock);
408 qmp_id_to_qmp_map.insert(make_pair(tm_qmp_id, tmq_map_profile));
409 bcmos_fastlock_unlock(&data_lock, 0);
410 update_sched_qmp_id_map(sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id);
411 return tm_qmp_id;
412 } else {
413 return -1;
414 }
415}
416
417/**
418* Free tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
419*
420* @param upstream/downstream sched_id
421* @param PON intf ID
422* @param onu_id ONU ID
423* @param uni_id UNI ID
424* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
425*
426* @return boolean, true if no more reference for TM QMP else false
427*/
428bool free_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
429 uint32_t uni_id, int tm_qmp_id) {
430 bool result;
431 sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
432 std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
433 bcmos_fastlock_lock(&data_lock);
434 if (it != sched_qmp_id_map.end()) {
435 sched_qmp_id_map.erase(it);
436 }
437 bcmos_fastlock_unlock(&data_lock, 0);
438
439 uint32_t tm_qmp_ref_count = 0;
440 std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it2 = sched_qmp_id_map.begin();
441 while(it2 != sched_qmp_id_map.end()) {
442 if(it2->second == tm_qmp_id) {
443 tm_qmp_ref_count++;
444 }
445 it2++;
446 }
447
448 if (tm_qmp_ref_count == 0) {
449 std::map<int, std::vector < uint32_t > >::const_iterator it3 = qmp_id_to_qmp_map.find(tm_qmp_id);
450 if (it3 != qmp_id_to_qmp_map.end()) {
451 bcmos_fastlock_lock(&data_lock);
452 tm_qmp_bitset[tm_qmp_id] = 0;
453 qmp_id_to_qmp_map.erase(it3);
454 bcmos_fastlock_unlock(&data_lock, 0);
455 OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So clearing it\n", \
456 tm_qmp_id, tm_qmp_ref_count);
457 result = true;
458 }
459 } else {
460 OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So not clearing it\n", \
461 tm_qmp_id, tm_qmp_ref_count);
462 result = false;
463 }
464 return result;
465}
466
467/**
468* Returns Scheduler/Queue direction as string
469*
470* @param direction as specified in tech_profile.proto
471*/
472std::string GetDirection(int direction) {
473 switch (direction)
474 {
475 case tech_profile::Direction::UPSTREAM: return upstream;
476 case tech_profile::Direction::DOWNSTREAM: return downstream;
477 default: OPENOLT_LOG(ERROR, openolt_log_id, "direction-not-supported %d\n", direction);
478 return "direction-not-supported";
479 }
Shad Ansari627b5782018-08-13 22:49:32 +0000480}
481
Jason Huangb6843dc2019-07-22 17:46:06 +0800482inline const char *get_flow_acton_command(uint32_t command) {
483 char actions[200] = { };
484 char *s_actions_ptr = actions;
485 if (command & BCMOLT_ACTION_CMD_ID_ADD_OUTER_TAG) strcat(s_actions_ptr, "ADD_OUTER_TAG|");
486 if (command & BCMOLT_ACTION_CMD_ID_REMOVE_OUTER_TAG) strcat(s_actions_ptr, "REMOVE_OUTER_TAG|");
487 if (command & BCMOLT_ACTION_CMD_ID_XLATE_OUTER_TAG) strcat(s_actions_ptr, "TRANSLATE_OUTER_TAG|");
488 if (command & BCMOLT_ACTION_CMD_ID_ADD_INNER_TAG) strcat(s_actions_ptr, "ADD_INNTER_TAG|");
489 if (command & BCMOLT_ACTION_CMD_ID_REMOVE_INNER_TAG) strcat(s_actions_ptr, "REMOVE_INNER_TAG|");
490 if (command & BCMOLT_ACTION_CMD_ID_XLATE_INNER_TAG) strcat(s_actions_ptr, "TRANSLATE_INNER_TAG|");
491 if (command & BCMOLT_ACTION_CMD_ID_REMARK_OUTER_PBITS) strcat(s_actions_ptr, "REMOVE_OUTER_PBITS|");
492 if (command & BCMOLT_ACTION_CMD_ID_REMARK_INNER_PBITS) strcat(s_actions_ptr, "REMAKE_INNER_PBITS|");
493 return s_actions_ptr;
494}
495
Jason Huang88795222019-06-13 19:28:44 +0800496char* openolt_read_sysinfo(const char* field_name, char* field_val)
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800497{
498 FILE *fp;
499 /* Prepare the command*/
500 char command[150];
501
502 snprintf(command, sizeof command, "bash -l -c \"onlpdump -s\" | perl -ne 'print $1 if /%s: (\\S+)/'", field_name);
503 /* Open the command for reading. */
504 fp = popen(command, "r");
505 if (fp == NULL) {
506 /*The client has to check for a Null field value in this case*/
Jason Huangb6843dc2019-07-22 17:46:06 +0800507 OPENOLT_LOG(INFO, openolt_log_id, "Failed to query the %s\n", field_name);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800508 return field_val;
509 }
510
511 /*Read the field value*/
512 if (fp) {
Jason Huangd33b4d82019-05-15 18:22:57 +0800513 uint8_t ret;
514 ret = fread(field_val, OPENOLT_FIELD_LEN, 1, fp);
515 if (ret >= OPENOLT_FIELD_LEN)
Jason Huangb6843dc2019-07-22 17:46:06 +0800516 OPENOLT_LOG(INFO, openolt_log_id, "Read data length %u\n", ret);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800517 pclose(fp);
518 }
519 return field_val;
520}
521
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400522Status GetDeviceInfo_(openolt::DeviceInfo* device_info) {
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500523 device_info->set_vendor(VENDOR_ID);
524 device_info->set_model(MODEL_ID);
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400525 device_info->set_hardware_version("");
526 device_info->set_firmware_version(firmware_version);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500527 device_info->set_technology(board_technology);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500528 device_info->set_pon_ports(num_of_pon_ports);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500529
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800530 char serial_number[OPENOLT_FIELD_LEN];
531 memset(serial_number, '\0', OPENOLT_FIELD_LEN);
532 openolt_read_sysinfo("Serial Number", serial_number);
Jason Huangb6843dc2019-07-22 17:46:06 +0800533 OPENOLT_LOG(INFO, openolt_log_id, "Fetched device serial number %s\n", serial_number);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800534 device_info->set_device_serial_number(serial_number);
535
Craig Lutgenb2601f02018-10-23 13:04:31 -0500536 // Legacy, device-wide ranges. To be deprecated when adapter
537 // is upgraded to support per-interface ranges
Jason Huangb1fad572019-05-28 19:02:30 +0800538 if (board_technology == "XGS-PON") {
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500539 device_info->set_onu_id_start(1);
540 device_info->set_onu_id_end(255);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600541 device_info->set_alloc_id_start(MIN_ALLOC_ID_XGSPON);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500542 device_info->set_alloc_id_end(16383);
543 device_info->set_gemport_id_start(1024);
544 device_info->set_gemport_id_end(65535);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500545 device_info->set_flow_id_start(1);
546 device_info->set_flow_id_end(16383);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500547 }
Jason Huangd33b4d82019-05-15 18:22:57 +0800548 else if (board_technology == "GPON") {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500549 device_info->set_onu_id_start(1);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500550 device_info->set_onu_id_end(127);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600551 device_info->set_alloc_id_start(MIN_ALLOC_ID_GPON);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500552 device_info->set_alloc_id_end(767);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500553 device_info->set_gemport_id_start(256);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500554 device_info->set_gemport_id_end(4095);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500555 device_info->set_flow_id_start(1);
556 device_info->set_flow_id_end(16383);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500557 }
Craig Lutgenb2601f02018-10-23 13:04:31 -0500558
559 std::map<std::string, openolt::DeviceInfo::DeviceResourceRanges*> ranges;
560 for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
561 std::string intf_technology = intf_technologies[intf_id];
562 openolt::DeviceInfo::DeviceResourceRanges *range = ranges[intf_technology];
563 if(range == nullptr) {
564 range = device_info->add_ranges();
565 ranges[intf_technology] = range;
566 range->set_technology(intf_technology);
567
Jason Huangb6843dc2019-07-22 17:46:06 +0800568 if (intf_technology == "XGS-PON") {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500569 openolt::DeviceInfo::DeviceResourceRanges::Pool* pool;
570
571 pool = range->add_pools();
572 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ONU_ID);
573 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::DEDICATED_PER_INTF);
574 pool->set_start(1);
575 pool->set_end(255);
576
577 pool = range->add_pools();
578 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ALLOC_ID);
579 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_SAME_TECH);
580 pool->set_start(1024);
581 pool->set_end(16383);
582
583 pool = range->add_pools();
584 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::GEMPORT_ID);
585 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
586 pool->set_start(1024);
587 pool->set_end(65535);
588
589 pool = range->add_pools();
590 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::FLOW_ID);
591 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
592 pool->set_start(1);
593 pool->set_end(16383);
594 }
Jason Huangb6843dc2019-07-22 17:46:06 +0800595 else if (intf_technology == "GPON") {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500596 openolt::DeviceInfo::DeviceResourceRanges::Pool* pool;
597
598 pool = range->add_pools();
599 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ONU_ID);
600 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::DEDICATED_PER_INTF);
601 pool->set_start(1);
602 pool->set_end(127);
603
604 pool = range->add_pools();
605 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ALLOC_ID);
606 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_SAME_TECH);
607 pool->set_start(256);
608 pool->set_end(757);
609
610 pool = range->add_pools();
611 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::GEMPORT_ID);
612 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
613 pool->set_start(256);
614 pool->set_end(4095);
615
616 pool = range->add_pools();
617 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::FLOW_ID);
618 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
619 pool->set_start(1);
620 pool->set_end(16383);
621 }
622 }
623
624 range->add_intf_ids(intf_id);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500625 }
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400626
627 // FIXME: Once dependency problem is fixed
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500628 // device_info->set_pon_ports(num_of_pon_ports);
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400629 // device_info->set_onu_id_end(XGPON_NUM_OF_ONUS - 1);
630 // device_info->set_alloc_id_start(1024);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500631 // device_info->set_alloc_id_end(XGPON_NUM_OF_ALLOC_IDS * num_of_pon_ports ? - 1);
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400632 // device_info->set_gemport_id_start(XGPON_MIN_BASE_SERVICE_PORT_ID);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500633 // device_info->set_gemport_id_end(XGPON_NUM_OF_GEM_PORT_IDS_PER_PON * num_of_pon_ports ? - 1);
634 // device_info->set_pon_ports(num_of_pon_ports);
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400635
636 return Status::OK;
637}
638
Jason Huang88795222019-06-13 19:28:44 +0800639Status pushOltOperInd(uint32_t intf_id, const char *type, const char *state)
640{
Jason Huangb6843dc2019-07-22 17:46:06 +0800641 openolt::Indication ind;
642 openolt::IntfOperIndication* intf_oper_ind = new openolt::IntfOperIndication;
Jason Huang88795222019-06-13 19:28:44 +0800643
Jason Huangb6843dc2019-07-22 17:46:06 +0800644 intf_oper_ind->set_type(type);
645 intf_oper_ind->set_intf_id(intf_id);
646 intf_oper_ind->set_oper_state(state);
647 ind.set_allocated_intf_oper_ind(intf_oper_ind);
648 oltIndQ.push(ind);
Jason Huang88795222019-06-13 19:28:44 +0800649 return Status::OK;
650}
651
Jason Huangd33b4d82019-05-15 18:22:57 +0800652#define CLI_HOST_PROMPT_FORMAT "BCM.%u> "
653
654/* Build CLI prompt */
655static void openolt_cli_get_prompt_cb(bcmcli_session *session, char *buf, uint32_t max_len)
656{
657 snprintf(buf, max_len, CLI_HOST_PROMPT_FORMAT, dev_id);
658}
659
660static int _bal_apiend_cli_thread_handler(long data)
661{
662 char init_string[]="\n";
663 bcmcli_session *sess = current_session;
664 bcmos_task_parm bal_cli_task_p_dummy;
Jason Huangb6843dc2019-07-22 17:46:06 +0800665
Jason Huangd33b4d82019-05-15 18:22:57 +0800666 /* Switch to interactive mode if not stopped in the init script */
667 if (!bcmcli_is_stopped(sess))
668 {
669 /* Force a CLI command prompt
670 * The string passed into the parse function
671 * must be modifiable, so a string constant like
672 * bcmcli_parse(current_session, "\n") will not
673 * work.
674 */
675 bcmcli_parse(sess, init_string);
Jason Huangb6843dc2019-07-22 17:46:06 +0800676
Jason Huangd33b4d82019-05-15 18:22:57 +0800677 /* Process user input until EOF or quit command */
678 bcmcli_driver(sess);
679 };
Jason Huangb6843dc2019-07-22 17:46:06 +0800680 OPENOLT_LOG(INFO, openolt_log_id, "BAL API End CLI terminated\n");
Jason Huangd33b4d82019-05-15 18:22:57 +0800681
682 /* Cleanup */
683 bcmcli_session_close(current_session);
Jason Huangb6843dc2019-07-22 17:46:06 +0800684 bcmcli_token_destroy(NULL);
Jason Huangd33b4d82019-05-15 18:22:57 +0800685 return 0;
686}
687
688/* Init API CLI commands for the current device */
689bcmos_errno bcm_openolt_api_cli_init(bcmcli_entry *parent_dir, bcmcli_session *session)
690{
691 bcmos_errno rc;
692
693 api_parent_dir = parent_dir;
694
695 rc = bcm_api_cli_set_commands(session);
696
697#ifdef BCM_SUBSYSTEM_HOST
698 /* Subscribe for device change indication */
699 rc = rc ? rc : bcmolt_olt_sel_ind_register(_api_cli_olt_change_ind);
700#endif
701
702 return rc;
703}
704
705static bcmos_errno bcm_cli_quit(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
706{
707 bcmcli_stop(session);
708 bcmcli_session_print(session, "CLI terminated by 'Quit' command\n");
709 status_bcm_cli_quit = BCMOS_TRUE;
710
711 return BCM_ERR_OK;
712}
713
714int get_status_bcm_cli_quit(void) {
715 return status_bcm_cli_quit;
716}
717
718bcmos_errno bcmolt_apiend_cli_init() {
719 bcmos_errno ret;
720 bcmos_task_parm bal_cli_task_p = {};
721 bcmos_task_parm bal_cli_task_p_dummy;
722
723 /** before creating the task, check if it is already created by the other half of BAL i.e. Core side */
724 if (BCM_ERR_OK != bcmos_task_query(&bal_cli_thread, &bal_cli_task_p_dummy))
725 {
726 /* Create BAL CLI thread */
727 bal_cli_task_p.name = bal_cli_thread_name;
728 bal_cli_task_p.handler = _bal_apiend_cli_thread_handler;
729 bal_cli_task_p.priority = TASK_PRIORITY_CLI;
Jason Huangb6843dc2019-07-22 17:46:06 +0800730
Jason Huangd33b4d82019-05-15 18:22:57 +0800731 ret = bcmos_task_create(&bal_cli_thread, &bal_cli_task_p);
732 if (BCM_ERR_OK != ret)
733 {
734 bcmos_printf("Couldn't create BAL API end CLI thread\n");
735 return ret;
736 }
737 }
738}
739
Shad Ansari627b5782018-08-13 22:49:32 +0000740Status Enable_(int argc, char *argv[]) {
Jason Huangd33b4d82019-05-15 18:22:57 +0800741 bcmos_errno err;
742 bcmolt_host_init_parms init_parms = {};
743 init_parms.transport.type = BCM_HOST_API_CONN_LOCAL;
Girish Gowdrad18f0d32019-10-11 20:46:15 +0530744 unsigned int failed_enable_device_cnt = 0;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000745
Shad Ansariedef2132018-08-10 22:14:50 +0000746 if (!state.is_activated()) {
Shad Ansari627b5782018-08-13 22:49:32 +0000747
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500748 vendor_init();
Jason Huangd33b4d82019-05-15 18:22:57 +0800749 /* Initialize host subsystem */
750 err = bcmolt_host_init(&init_parms);
751 if (BCM_ERR_OK != err) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800752 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to init OLT\n");
Jason Huangd33b4d82019-05-15 18:22:57 +0800753 return bcm_to_grpc_err(err, "Failed to init OLT");
754 }
Craig Lutgen967a1d02018-11-27 10:41:51 -0600755
Girish Gowdrae538dfd2019-09-30 11:07:30 +0530756 bcmcli_session_parm mon_session_parm;
Jason Huangd33b4d82019-05-15 18:22:57 +0800757 /* Create CLI session */
758 memset(&mon_session_parm, 0, sizeof(mon_session_parm));
759 mon_session_parm.get_prompt = openolt_cli_get_prompt_cb;
760 mon_session_parm.access_right = BCMCLI_ACCESS_ADMIN;
761 bcmos_errno rc = bcmcli_session_open(&mon_session_parm, &current_session);
762 BUG_ON(rc != BCM_ERR_OK);
763
764 /* API CLI */
765 bcm_openolt_api_cli_init(NULL, current_session);
766
767 /* Add quit command */
768 BCMCLI_MAKE_CMD_NOPARM(NULL, "quit", "Quit", bcm_cli_quit);
769
770 err = bcmolt_apiend_cli_init();
771 if (BCM_ERR_OK != err) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800772 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to add apiend init\n");
Jason Huangd33b4d82019-05-15 18:22:57 +0800773 return bcm_to_grpc_err(err, "Failed to add apiend init");
774 }
775
776 bcmos_fastlock_init(&data_lock, 0);
Jason Huangb6843dc2019-07-22 17:46:06 +0800777 OPENOLT_LOG(INFO, openolt_log_id, "Enable OLT - %s-%s\n", VENDOR_ID, MODEL_ID);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500778
Jason Huangd33b4d82019-05-15 18:22:57 +0800779 if (bcmolt_api_conn_mgr_is_connected(dev_id))
780 {
781 Status status = SubscribeIndication();
782 if (!status.ok()) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800783 OPENOLT_LOG(ERROR, openolt_log_id, "SubscribeIndication failed - %s : %s\n",
Jason Huangd33b4d82019-05-15 18:22:57 +0800784 grpc_status_code_to_string(status.error_code()).c_str(),
785 status.error_message().c_str());
Jason Huangd33b4d82019-05-15 18:22:57 +0800786 return status;
787 }
788 bcmos_errno err;
789 bcmolt_odid dev;
Jason Huangb6843dc2019-07-22 17:46:06 +0800790 OPENOLT_LOG(INFO, openolt_log_id, "Enabling PON %d Devices ... \n", BCM_MAX_DEVS_PER_LINE_CARD);
Jason Huangd33b4d82019-05-15 18:22:57 +0800791 for (dev = 0; dev < BCM_MAX_DEVS_PER_LINE_CARD; dev++) {
792 bcmolt_device_cfg dev_cfg = { };
793 bcmolt_device_key dev_key = { };
794 dev_key.device_id = dev;
795 BCMOLT_CFG_INIT(&dev_cfg, device, dev_key);
796 BCMOLT_MSG_FIELD_GET(&dev_cfg, system_mode);
797 err = bcmolt_cfg_get(dev_id, &dev_cfg.hdr);
798 if (err == BCM_ERR_NOT_CONNECTED) {
799 bcmolt_device_key key = {.device_id = dev};
800 bcmolt_device_connect oper;
Jason Huangd33b4d82019-05-15 18:22:57 +0800801 BCMOLT_OPER_INIT(&oper, device, connect, key);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +0800802 if (MODEL_ID == "asfvolt16") {
803 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mode, BCMOLT_INNI_MODE_ALL_10_G_XFI);
804 BCMOLT_MSG_FIELD_SET (&oper, system_mode, BCMOLT_SYSTEM_MODE_XGS__2_X);
805 } else if (MODEL_ID == "asgvolt64") {
806 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mode, BCMOLT_INNI_MODE_ALL_10_G_XFI);
807 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mux, BCMOLT_INNI_MUX_FOUR_TO_ONE);
808 BCMOLT_MSG_FIELD_SET (&oper, system_mode, BCMOLT_SYSTEM_MODE_GPON__16_X);
809 }
Jason Huangd33b4d82019-05-15 18:22:57 +0800810 err = bcmolt_oper_submit(dev_id, &oper.hdr);
Girish Gowdrae538dfd2019-09-30 11:07:30 +0530811 if (err) {
Girish Gowdrad18f0d32019-10-11 20:46:15 +0530812 failed_enable_device_cnt ++;
Girish Gowdrae538dfd2019-09-30 11:07:30 +0530813 OPENOLT_LOG(ERROR, openolt_log_id, "Enable PON device %d failed, err %d\n", dev, err);
Girish Gowdrad18f0d32019-10-11 20:46:15 +0530814 if (failed_enable_device_cnt == BCM_MAX_DEVS_PER_LINE_CARD) {
815 OPENOLT_LOG(ERROR, openolt_log_id, "failed to enable all the pon ports\n");
816 return Status(grpc::StatusCode::INTERNAL, "Failed to activate all PON ports");
817 }
Girish Gowdrae538dfd2019-09-30 11:07:30 +0530818 }
Jason Huangd33b4d82019-05-15 18:22:57 +0800819 bcmos_usleep(200000);
820 }
Jason Huangb1fad572019-05-28 19:02:30 +0800821 else {
Jason Huangb6843dc2019-07-22 17:46:06 +0800822 OPENOLT_LOG(WARNING, openolt_log_id, "PON deivce %d already connected\n", dev);
Jason Huangb1fad572019-05-28 19:02:30 +0800823 state.activate();
824 }
Jason Huangd33b4d82019-05-15 18:22:57 +0800825 }
826 init_stats();
Shad Ansari627b5782018-08-13 22:49:32 +0000827 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000828 }
Shad Ansariedef2132018-08-10 22:14:50 +0000829
Jason Huangd33b4d82019-05-15 18:22:57 +0800830 /* Start CLI */
Jason Huangb6843dc2019-07-22 17:46:06 +0800831 OPENOLT_LOG(INFO, def_log_id, "Starting CLI\n");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400832 //If already enabled, generate an extra indication ????
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000833 return Status::OK;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400834}
835
836Status Disable_() {
837 // bcmbal_access_terminal_cfg acc_term_obj;
838 // bcmbal_access_terminal_key key = { };
839 //
840 // if (state::is_activated) {
841 // std::cout << "Disable OLT" << std::endl;
842 // key.access_term_id = DEFAULT_ATERM_ID;
843 // BCMBAL_CFG_INIT(&acc_term_obj, access_terminal, key);
844 // BCMBAL_CFG_PROP_SET(&acc_term_obj, access_terminal, admin_state, BCMBAL_STATE_DOWN);
845 // bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(acc_term_obj.hdr));
846 // if (err) {
847 // std::cout << "ERROR: Failed to disable OLT" << std::endl;
848 // return bcm_to_grpc_err(err, "Failed to disable OLT");
849 // }
850 // }
851 // //If already disabled, generate an extra indication ????
852 // return Status::OK;
853 //This fails with Operation Not Supported, bug ???
854
855 //TEMPORARY WORK AROUND
Jason Huangb6843dc2019-07-22 17:46:06 +0800856 Status status = SetStateUplinkIf_(nni_intf_id, false);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400857 if (status.ok()) {
Shad Ansariedef2132018-08-10 22:14:50 +0000858 state.deactivate();
Jason Huangb6843dc2019-07-22 17:46:06 +0800859 OPENOLT_LOG(INFO, openolt_log_id, "Disable OLT, add an extra indication\n");
Jason Huang88795222019-06-13 19:28:44 +0800860 pushOltOperInd(nni_intf_id, "nni", "up");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400861 }
862 return status;
863
864}
865
866Status Reenable_() {
Jason Huangb6843dc2019-07-22 17:46:06 +0800867 Status status = SetStateUplinkIf_(0, true);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400868 if (status.ok()) {
Shad Ansariedef2132018-08-10 22:14:50 +0000869 state.activate();
Jason Huangb6843dc2019-07-22 17:46:06 +0800870 OPENOLT_LOG(INFO, openolt_log_id, "Reenable OLT, add an extra indication\n");
Jason Huang88795222019-06-13 19:28:44 +0800871 pushOltOperInd(0, "nni", "up");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400872 }
873 return status;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000874}
875
Jason Huangd33b4d82019-05-15 18:22:57 +0800876bcmos_errno get_pon_interface_status(bcmolt_interface pon_ni, bcmolt_interface_state *state) {
877 bcmos_errno err;
878 bcmolt_pon_interface_key pon_key;
879 bcmolt_pon_interface_cfg pon_cfg;
880 pon_key.pon_ni = pon_ni;
881
882 BCMOLT_CFG_INIT(&pon_cfg, pon_interface, pon_key);
883 BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, state);
884 BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, itu);
885 err = bcmolt_cfg_get(dev_id, &pon_cfg.hdr);
886 *state = pon_cfg.data.state;
887 return err;
888}
889
Jason Huangb6843dc2019-07-22 17:46:06 +0800890inline uint64_t get_flow_status(uint16_t flow_id, uint16_t flow_type, uint16_t data_id) {
Jason Huang439d24f2019-06-26 03:25:05 +0800891 bcmos_errno err;
892 bcmolt_flow_key flow_key;
893 bcmolt_flow_cfg flow_cfg;
894
895 flow_key.flow_id = flow_id;
Jason Huangb6843dc2019-07-22 17:46:06 +0800896 flow_key.flow_type = (bcmolt_flow_type)flow_type;
Jason Huang439d24f2019-06-26 03:25:05 +0800897
898 BCMOLT_CFG_INIT(&flow_cfg, flow, flow_key);
899
900 switch (data_id) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800901 case ONU_ID: //onu_id
902 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, onu_id);
Jason Huang439d24f2019-06-26 03:25:05 +0800903 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
904 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800905 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get onu_id\n");
Jason Huang439d24f2019-06-26 03:25:05 +0800906 return err;
907 }
Jason Huangb6843dc2019-07-22 17:46:06 +0800908 return flow_cfg.data.onu_id;
909 case FLOW_TYPE:
Jason Huang439d24f2019-06-26 03:25:05 +0800910 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
911 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800912 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get flow_type\n");
Jason Huang439d24f2019-06-26 03:25:05 +0800913 return err;
914 }
Jason Huangb6843dc2019-07-22 17:46:06 +0800915 return flow_cfg.key.flow_type;
Jason Huang439d24f2019-06-26 03:25:05 +0800916 case SVC_PORT_ID: //svc_port_id
917 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, svc_port_id);
918 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
919 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800920 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get svc_port_id\n");
Jason Huang439d24f2019-06-26 03:25:05 +0800921 return err;
922 }
923 return flow_cfg.data.svc_port_id;
Jason Huangb6843dc2019-07-22 17:46:06 +0800924 case PRIORITY:
925 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, priority);
926 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
927 if (err) {
928 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get priority\n");
929 return err;
930 }
931 return flow_cfg.data.priority;
Jason Huang439d24f2019-06-26 03:25:05 +0800932 case COOKIE: //cookie
933 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, cookie);
934 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
935 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800936 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get cookie\n");
Jason Huang439d24f2019-06-26 03:25:05 +0800937 return err;
938 }
939 return flow_cfg.data.cookie;
Jason Huangb6843dc2019-07-22 17:46:06 +0800940 case INGRESS_INTF_TYPE: //ingress intf_type
941 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, ingress_intf);
942 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
943 if (err) {
944 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get ingress intf_type\n");
945 return err;
946 }
947 return flow_cfg.data.ingress_intf.intf_type;
948 case EGRESS_INTF_TYPE: //egress intf_type
949 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_intf);
950 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
951 if (err) {
952 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress intf_type\n");
953 return err;
954 }
955 return flow_cfg.data.egress_intf.intf_type;
956 case INGRESS_INTF_ID: //ingress intf_id
957 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, ingress_intf);
958 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
959 if (err) {
960 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get ingress intf_id\n");
961 return err;
962 }
963 return flow_cfg.data.ingress_intf.intf_id;
964 case EGRESS_INTF_ID: //egress intf_id
965 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_intf);
966 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
967 if (err) {
968 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress intf_id\n");
969 return err;
970 }
971 return flow_cfg.data.egress_intf.intf_id;
972 case CLASSIFIER_O_VID:
973 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
974 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
975 if (err) {
976 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier o_vid\n");
977 return err;
978 }
979 return flow_cfg.data.classifier.o_vid;
980 case CLASSIFIER_O_PBITS:
981 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
982 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
983 if (err) {
984 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier o_pbits\n");
985 return err;
986 }
987 return flow_cfg.data.classifier.o_pbits;
988 case CLASSIFIER_I_VID:
989 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
990 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
991 if (err) {
992 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier i_vid\n");
993 return err;
994 }
995 return flow_cfg.data.classifier.i_vid;
996 case CLASSIFIER_I_PBITS:
997 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
998 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
999 if (err) {
1000 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier i_pbits\n");
1001 return err;
1002 }
1003 return flow_cfg.data.classifier.i_pbits;
1004 case CLASSIFIER_ETHER_TYPE:
1005 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1006 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1007 if (err) {
1008 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier ether_type\n");
1009 return err;
1010 }
1011 return flow_cfg.data.classifier.ether_type;
1012 case CLASSIFIER_IP_PROTO:
1013 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1014 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1015 if (err) {
1016 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier ip_proto\n");
1017 return err;
1018 }
1019 return flow_cfg.data.classifier.ip_proto;
1020 case CLASSIFIER_SRC_PORT:
1021 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1022 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1023 if (err) {
1024 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier src_port\n");
1025 return err;
1026 }
1027 return flow_cfg.data.classifier.src_port;
1028 case CLASSIFIER_DST_PORT:
1029 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1030 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1031 if (err) {
1032 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier dst_port\n");
1033 return err;
1034 }
1035 return flow_cfg.data.classifier.dst_port;
1036 case CLASSIFIER_PKT_TAG_TYPE:
1037 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1038 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1039 if (err) {
1040 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier pkt_tag_type\n");
1041 return err;
1042 }
1043 return flow_cfg.data.classifier.pkt_tag_type;
1044 case EGRESS_QOS_TYPE:
1045 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
1046 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1047 if (err) {
1048 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos type\n");
1049 return err;
1050 }
1051 return flow_cfg.data.egress_qos.type;
1052 case EGRESS_QOS_QUEUE_ID:
1053 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
1054 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1055 if (err) {
1056 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos queue_id\n");
1057 return err;
1058 }
1059 switch (flow_cfg.data.egress_qos.type) {
1060 case BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE:
1061 return flow_cfg.data.egress_qos.u.fixed_queue.queue_id;
1062 case BCMOLT_EGRESS_QOS_TYPE_TC_TO_QUEUE:
1063 return flow_cfg.data.egress_qos.u.tc_to_queue.tc_to_queue_id;
1064 case BCMOLT_EGRESS_QOS_TYPE_PBIT_TO_TC:
1065 return flow_cfg.data.egress_qos.u.pbit_to_tc.tc_to_queue_id;
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001066 case BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE:
1067 return flow_cfg.data.egress_qos.u.priority_to_queue.tm_q_set_id;
Jason Huangb6843dc2019-07-22 17:46:06 +08001068 case BCMOLT_EGRESS_QOS_TYPE_NONE:
1069 default:
1070 return -1;
1071 }
1072 case EGRESS_QOS_TM_SCHED_ID:
1073 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
1074 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1075 if (err) {
1076 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos tm_sched_id\n");
1077 return err;
1078 }
1079 return flow_cfg.data.egress_qos.tm_sched.id;
1080 case ACTION_CMDS_BITMASK:
1081 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1082 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1083 if (err) {
1084 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action cmds_bitmask\n");
1085 return err;
1086 }
1087 return flow_cfg.data.action.cmds_bitmask;
1088 case ACTION_O_VID:
1089 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1090 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1091 if (err) {
1092 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action o_vid\n");
1093 return err;
1094 }
1095 return flow_cfg.data.action.o_vid;
1096 case ACTION_O_PBITS:
1097 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1098 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1099 if (err) {
1100 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action o_pbits\n");
1101 return err;
1102 }
1103 return flow_cfg.data.action.o_pbits;
1104 case ACTION_I_VID:
1105 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1106 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1107 if (err) {
1108 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action i_vid\n");
1109 return err;
1110 }
1111 return flow_cfg.data.action.i_vid;
1112 case ACTION_I_PBITS:
1113 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1114 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1115 if (err) {
1116 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action i_pbits\n");
1117 return err;
1118 }
1119 return flow_cfg.data.action.i_pbits;
1120 case STATE:
1121 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, state);
1122 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1123 if (err) {
1124 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get state\n");
1125 return err;
1126 }
1127 return flow_cfg.data.state;
Jason Huang439d24f2019-06-26 03:25:05 +08001128 default:
1129 return BCM_ERR_INTERNAL;
1130 }
1131
Jason Huangb6843dc2019-07-22 17:46:06 +08001132 return err;
Jason Huang439d24f2019-06-26 03:25:05 +08001133}
1134
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001135Status EnablePonIf_(uint32_t intf_id) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001136 bcmos_errno err = BCM_ERR_OK;
Jason Huangb1fad572019-05-28 19:02:30 +08001137 bcmolt_pon_interface_cfg interface_obj;
Jason Huangd33b4d82019-05-15 18:22:57 +08001138 bcmolt_pon_interface_key intf_key = {.pon_ni = (bcmolt_interface)intf_id};
1139 bcmolt_pon_interface_set_pon_interface_state pon_interface_set_state;
1140 bcmolt_interface_state state;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001141
Jason Huangd33b4d82019-05-15 18:22:57 +08001142 err = get_pon_interface_status((bcmolt_interface)intf_id, &state);
1143 if (err == BCM_ERR_OK) {
1144 if (state == BCMOLT_INTERFACE_STATE_ACTIVE_WORKING) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001145 OPENOLT_LOG(INFO, openolt_log_id, "PON interface: %d already enabled\n", intf_id);
Jason Huangd33b4d82019-05-15 18:22:57 +08001146 return Status::OK;
1147 }
1148 }
Jason Huangb1fad572019-05-28 19:02:30 +08001149 BCMOLT_CFG_INIT(&interface_obj, pon_interface, intf_key);
Jason Huangd33b4d82019-05-15 18:22:57 +08001150 BCMOLT_OPER_INIT(&pon_interface_set_state, pon_interface, set_pon_interface_state, intf_key);
Jason Huangb1fad572019-05-28 19:02:30 +08001151 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.control, BCMOLT_CONTROL_STATE_ENABLE);
1152 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.interval, 5000);
1153 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.onu_post_discovery_mode,
1154 BCMOLT_ONU_POST_DISCOVERY_MODE_ACTIVATE);
Jason Huangb6843dc2019-07-22 17:46:06 +08001155 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.los, true);
1156 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.onu_alarms, true);
1157 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.tiwi, true);
1158 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.ack_timeout, true);
1159 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.sfi, true);
1160 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.loki, true);
Jason Huangd33b4d82019-05-15 18:22:57 +08001161 BCMOLT_FIELD_SET(&pon_interface_set_state.data, pon_interface_set_pon_interface_state_data,
1162 operation, BCMOLT_INTERFACE_OPERATION_ACTIVE_WORKING);
Jason Huangb1fad572019-05-28 19:02:30 +08001163
1164 err = bcmolt_cfg_set(dev_id, &interface_obj.hdr);
1165 if (err != BCM_ERR_OK) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001166 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to enable discovery onu, PON interface %d, err %d\n", intf_id, err);
Jason Huangb1fad572019-05-28 19:02:30 +08001167 return bcm_to_grpc_err(err, "Failed to enable discovery onu");
1168 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001169 err = bcmolt_oper_submit(dev_id, &pon_interface_set_state.hdr);
1170 if (err != BCM_ERR_OK) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001171 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to enable PON interface: %d\n", intf_id);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001172 return bcm_to_grpc_err(err, "Failed to enable PON interface");
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001173 }
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07001174 else {
Jason Huangb6843dc2019-07-22 17:46:06 +08001175 OPENOLT_LOG(INFO, openolt_log_id, "Successfully enabled PON interface: %d\n", intf_id);
1176 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for PON interface: %d\n", intf_id);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001177 CreateDefaultSched(intf_id, downstream);
1178 CreateDefaultQueue(intf_id, downstream);
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07001179 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001180
1181 return Status::OK;
1182}
1183
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001184Status ProbeDeviceCapabilities_() {
Jason Huangd33b4d82019-05-15 18:22:57 +08001185 bcmos_errno err;
1186 bcmolt_device_cfg dev_cfg = { };
1187 bcmolt_device_key dev_key = { };
1188 bcmolt_olt_cfg olt_cfg = { };
1189 bcmolt_olt_key olt_key = { };
Jason Huangd33b4d82019-05-15 18:22:57 +08001190 bcmolt_topology_map topo_map[BCM_MAX_PONS_PER_OLT] = { };
1191 bcmolt_topology topo = { };
Jason Huangb6843dc2019-07-22 17:46:06 +08001192
Jason Huangd33b4d82019-05-15 18:22:57 +08001193 topo.topology_maps.len = BCM_MAX_PONS_PER_OLT;
1194 topo.topology_maps.arr = &topo_map[0];
1195 BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
1196 BCMOLT_MSG_FIELD_GET(&olt_cfg, bal_state);
1197 BCMOLT_FIELD_SET_PRESENT(&olt_cfg.data, olt_cfg_data, topology);
1198 BCMOLT_CFG_LIST_BUF_SET(&olt_cfg, olt, topo.topology_maps.arr,
1199 sizeof(bcmolt_topology_map) * topo.topology_maps.len);
1200 err = bcmolt_cfg_get(dev_id, &olt_cfg.hdr);
1201 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001202 OPENOLT_LOG(ERROR, openolt_log_id, "cfg: Failed to query OLT\n");
Jason Huangd33b4d82019-05-15 18:22:57 +08001203 return bcm_to_grpc_err(err, "cfg: Failed to query OLT");
1204 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001205
Jason Huangd33b4d82019-05-15 18:22:57 +08001206 num_of_nni_ports = olt_cfg.data.topology.num_switch_ports;
1207 num_of_pon_ports = olt_cfg.data.topology.topology_maps.len;
1208
Jason Huangb6843dc2019-07-22 17:46:06 +08001209 OPENOLT_LOG(INFO, openolt_log_id, "OLT capabilitites, oper_state: %s\n",
Jason Huangd33b4d82019-05-15 18:22:57 +08001210 olt_cfg.data.bal_state == BCMOLT_BAL_STATE_BAL_AND_SWITCH_READY
1211 ? "up" : "down");
1212
Jason Huangb6843dc2019-07-22 17:46:06 +08001213 OPENOLT_LOG(INFO, openolt_log_id, "topology nni: %d pon: %d dev: %d\n",
Jason Huangd33b4d82019-05-15 18:22:57 +08001214 num_of_nni_ports,
1215 num_of_pon_ports,
Jason Huangb6843dc2019-07-22 17:46:06 +08001216 BCM_MAX_DEVS_PER_LINE_CARD);
Jason Huangd33b4d82019-05-15 18:22:57 +08001217
Jason Huangb6843dc2019-07-22 17:46:06 +08001218 for (int devid = 0; devid < BCM_MAX_DEVS_PER_LINE_CARD; devid++) {
1219 dev_key.device_id = devid;
1220 BCMOLT_CFG_INIT(&dev_cfg, device, dev_key);
1221 BCMOLT_MSG_FIELD_GET(&dev_cfg, firmware_sw_version);
1222 BCMOLT_MSG_FIELD_GET(&dev_cfg, chip_family);
1223 BCMOLT_MSG_FIELD_GET(&dev_cfg, system_mode);
1224 err = bcmolt_cfg_get(dev_id, &dev_cfg.hdr);
1225 if (err) {
1226 OPENOLT_LOG(ERROR, openolt_log_id, "device: Failed to query OLT\n");
1227 return bcm_to_grpc_err(err, "device: Failed to query OLT");
1228 }
1229
1230 std::string bal_version;
1231 bal_version += std::to_string(dev_cfg.data.firmware_sw_version.major)
1232 + "." + std::to_string(dev_cfg.data.firmware_sw_version.minor)
1233 + "." + std::to_string(dev_cfg.data.firmware_sw_version.revision);
1234 firmware_version = "BAL." + bal_version + "__" + firmware_version;
1235
1236 switch(dev_cfg.data.system_mode) {
1237 case 10: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*4,(devid+1)*4,"GPON"); break;
1238 case 11: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*8,(devid+1)*8,"GPON"); break;
1239 case 12: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"GPON"); break;
1240 case 13: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,"XGPON"); break;
1241 case 14: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*4,(devid+1)*4,"XGPON"); break;
1242 case 15: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*8,(devid+1)*8,"XGPON"); break;
1243 case 16: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"XGPON"); break;
1244 case 18: board_technology = "XGS-PON"; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,"XGS-PON"); break;
1245 case 19: board_technology = "XGS-PON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"XGS-PON"); break;
1246 case 20: board_technology = MIXED_TECH; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,MIXED_TECH); break;
1247 }
1248
1249 switch(dev_cfg.data.chip_family) {
1250 case BCMOLT_CHIP_FAMILY_CHIP_FAMILY_6862_X_: chip_family = "Maple"; break;
1251 case BCMOLT_CHIP_FAMILY_CHIP_FAMILY_6865_X_: chip_family = "Aspen"; break;
1252 }
1253
1254 OPENOLT_LOG(INFO, openolt_log_id, "device %d, pon: %d, version %s object model: %d, family: %s, board_technology: %s\n",
1255 devid, BCM_MAX_PONS_PER_DEV, bal_version.c_str(), BAL_API_VERSION, chip_family.c_str(), board_technology.c_str());
1256
1257 bcmos_usleep(500000);
1258 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001259
1260 return Status::OK;
1261}
Jason Huangb6843dc2019-07-22 17:46:06 +08001262#if 0
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001263Status ProbePonIfTechnology_() {
1264 // Probe maximum extent possible as configured into BAL driver to determine
1265 // which are active in the current BAL topology. And for those
1266 // that are active, determine each port's access technology, i.e. "gpon" or "xgspon".
1267 for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001268 bcmolt_pon_interface_cfg interface_obj;
1269 bcmolt_pon_interface_key interface_key;
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001270
Jason Huangd33b4d82019-05-15 18:22:57 +08001271 interface_key.pon_ni = intf_id;
1272 BCMOLT_CFG_INIT(&interface_obj, pon_interface, interface_key);
Jason Huangb6843dc2019-07-22 17:46:06 +08001273 if (board_technology == "XGS-PON")
1274 BCMOLT_MSG_FIELD_GET(&interface_obj, xgs_ngpon2_trx);
1275 else if (board_technology == "GPON")
1276 BCMOLT_MSG_FIELD_GET(&interface_obj, gpon_trx);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001277
Jason Huangd33b4d82019-05-15 18:22:57 +08001278 bcmos_errno err = bcmolt_cfg_get(dev_id, &interface_obj.hdr);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001279 if (err != BCM_ERR_OK) {
Craig Lutgenb2601f02018-10-23 13:04:31 -05001280 intf_technologies[intf_id] = UNKNOWN_TECH;
Jason Huangb6843dc2019-07-22 17:46:06 +08001281 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 -05001282 }
1283 else {
Jason Huangb1fad572019-05-28 19:02:30 +08001284 if (board_technology == "XGS-PON") {
Jason Huangd33b4d82019-05-15 18:22:57 +08001285 switch(interface_obj.data.xgpon_trx.transceiver_type) {
1286 case BCMOLT_XGPON_TRX_TYPE_LTH_7222_PC:
1287 case BCMOLT_XGPON_TRX_TYPE_WTD_RTXM266_702:
1288 case BCMOLT_XGPON_TRX_TYPE_LTH_7222_BC_PLUS:
1289 case BCMOLT_XGPON_TRX_TYPE_LTH_7226_PC:
1290 case BCMOLT_XGPON_TRX_TYPE_LTH_5302_PC:
1291 case BCMOLT_XGPON_TRX_TYPE_LTH_7226_A_PC_PLUS:
1292 case BCMOLT_XGPON_TRX_TYPE_D272RR_SSCB_DM:
Jason Huangb1fad572019-05-28 19:02:30 +08001293 intf_technologies[intf_id] = "XGS-PON";
Jason Huangd33b4d82019-05-15 18:22:57 +08001294 break;
1295 }
1296 } else if (board_technology == "GPON") {
1297 switch(interface_obj.data.gpon_trx.transceiver_type) {
1298 case BCMOLT_TRX_TYPE_SPS_43_48_H_HP_CDE_SD_2013:
1299 case BCMOLT_TRX_TYPE_LTE_3680_M:
1300 case BCMOLT_TRX_TYPE_SOURCE_PHOTONICS:
1301 case BCMOLT_TRX_TYPE_LTE_3680_P_TYPE_C_PLUS:
Jason Huangb6843dc2019-07-22 17:46:06 +08001302 case BCMOLT_TRX_TYPE_LTE_3680_P_BC:
Jason Huangd33b4d82019-05-15 18:22:57 +08001303 intf_technologies[intf_id] = "GPON";
1304 break;
1305 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001306 }
Craig Lutgenb2601f02018-10-23 13:04:31 -05001307
1308 if (board_technology != UNKNOWN_TECH) {
1309 board_technology = intf_technologies[intf_id];
1310 } else if (board_technology != MIXED_TECH && board_technology != intf_technologies[intf_id]) {
1311 intf_technologies[intf_id] = MIXED_TECH;
1312 }
1313
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001314 }
1315 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001316 return Status::OK;
1317}
Jason Huangb6843dc2019-07-22 17:46:06 +08001318#endif
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001319unsigned NumNniIf_() {return num_of_nni_ports;}
1320unsigned NumPonIf_() {return num_of_pon_ports;}
1321
Jason Huangd33b4d82019-05-15 18:22:57 +08001322bcmos_errno get_nni_interface_status(bcmolt_interface id, bcmolt_interface_state *state) {
1323 bcmos_errno err;
1324 bcmolt_nni_interface_key nni_key;
1325 bcmolt_nni_interface_cfg nni_cfg;
1326 nni_key.id = id;
1327
1328 BCMOLT_CFG_INIT(&nni_cfg, nni_interface, nni_key);
1329 BCMOLT_FIELD_SET_PRESENT(&nni_cfg.data, nni_interface_cfg_data, state);
1330 err = bcmolt_cfg_get(dev_id, &nni_cfg.hdr);
1331 *state = nni_cfg.data.state;
1332 return err;
1333}
1334
Jason Huangb6843dc2019-07-22 17:46:06 +08001335Status SetStateUplinkIf_(uint32_t intf_id, bool set_state) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001336 bcmos_errno err = BCM_ERR_OK;
1337 bcmolt_nni_interface_key intf_key = {.id = (bcmolt_interface)intf_id};
1338 bcmolt_nni_interface_set_nni_state nni_interface_set_state;
1339 bcmolt_interface_state state;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001340
Jason Huangd33b4d82019-05-15 18:22:57 +08001341 err = get_nni_interface_status((bcmolt_interface)intf_id, &state);
1342 if (err == BCM_ERR_OK) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001343 if (set_state && state == BCMOLT_INTERFACE_STATE_ACTIVE_WORKING) {
1344 OPENOLT_LOG(INFO, openolt_log_id, "NNI interface: %d already enabled\n", intf_id);
1345 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for NNI interface: %d\n", intf_id);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001346 CreateDefaultSched(intf_id, upstream);
1347 CreateDefaultQueue(intf_id, upstream);
Jason Huangd33b4d82019-05-15 18:22:57 +08001348 return Status::OK;
Jason Huangb6843dc2019-07-22 17:46:06 +08001349 } else if (!set_state && state == BCMOLT_INTERFACE_STATE_INACTIVE) {
1350 OPENOLT_LOG(INFO, openolt_log_id, "NNI interface: %d already disabled\n", intf_id);
1351 return Status::OK;
Jason Huangd33b4d82019-05-15 18:22:57 +08001352 }
Craig Lutgend0bae9b2018-10-18 18:02:07 -05001353 }
1354
Jason Huangd33b4d82019-05-15 18:22:57 +08001355 BCMOLT_OPER_INIT(&nni_interface_set_state, nni_interface, set_nni_state, intf_key);
Jason Huangb6843dc2019-07-22 17:46:06 +08001356 if (set_state) {
1357 BCMOLT_FIELD_SET(&nni_interface_set_state.data, nni_interface_set_nni_state_data,
1358 nni_state, BCMOLT_INTERFACE_OPERATION_ACTIVE_WORKING);
1359 } else {
1360 BCMOLT_FIELD_SET(&nni_interface_set_state.data, nni_interface_set_nni_state_data,
1361 nni_state, BCMOLT_INTERFACE_OPERATION_INACTIVE);
1362 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001363 err = bcmolt_oper_submit(dev_id, &nni_interface_set_state.hdr);
1364 if (err != BCM_ERR_OK) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001365 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to %s NNI interface: %d, err %d\n",
1366 (set_state)?"enable":"disable", intf_id, err);
Jason Huangd33b4d82019-05-15 18:22:57 +08001367 return bcm_to_grpc_err(err, "Failed to enable NNI interface");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001368 }
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07001369 else {
Jason Huangb6843dc2019-07-22 17:46:06 +08001370 OPENOLT_LOG(INFO, openolt_log_id, "Successfully %s NNI interface: %d\n", (set_state)?"enable":"disable", intf_id);
1371 if (set_state) {
1372 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for NNI interface: %d\n", intf_id);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001373 CreateDefaultSched(intf_id, upstream);
1374 CreateDefaultQueue(intf_id, upstream);
Jason Huangb6843dc2019-07-22 17:46:06 +08001375 }
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07001376 }
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001377
1378 return Status::OK;
1379}
1380
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001381Status DisablePonIf_(uint32_t intf_id) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001382 bcmolt_pon_interface_cfg interface_obj;
1383 bcmolt_pon_interface_key interface_key;
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001384
Jason Huangd33b4d82019-05-15 18:22:57 +08001385 interface_key.pon_ni = intf_id;
1386 BCMOLT_CFG_INIT(&interface_obj, pon_interface, interface_key);
1387 BCMOLT_MSG_FIELD_GET(&interface_obj, state);
1388 bcmos_errno err = bcmolt_cfg_get(dev_id, &interface_obj.hdr);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001389 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001390 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to disable PON interface: %d\n", intf_id);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001391 return bcm_to_grpc_err(err, "Failed to disable PON interface");
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001392 }
1393
1394 return Status::OK;
1395}
1396
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001397Status ActivateOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001398 const char *vendor_id, const char *vendor_specific, uint32_t pir) {
Jason Huangb1fad572019-05-28 19:02:30 +08001399 bcmos_errno err = BCM_ERR_OK;
1400 bcmolt_onu_cfg onu_cfg;
1401 bcmolt_onu_key onu_key;
Jason Huangd33b4d82019-05-15 18:22:57 +08001402 bcmolt_serial_number serial_number; /**< ONU serial number */
1403 bcmolt_bin_str_36 registration_id; /**< ONU registration ID */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001404
Jason Huangb1fad572019-05-28 19:02:30 +08001405 onu_key.onu_id = onu_id;
1406 onu_key.pon_ni = intf_id;
1407 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
1408 BCMOLT_FIELD_SET_PRESENT(&onu_cfg.data, onu_cfg_data, onu_state);
1409 err = bcmolt_cfg_get(dev_id, &onu_cfg.hdr);
1410 if (err == BCM_ERR_OK) {
1411 if ((onu_cfg.data.onu_state == BCMOLT_ONU_STATE_PROCESSING ||
1412 onu_cfg.data.onu_state == BCMOLT_ONU_STATE_ACTIVE) ||
1413 (onu_cfg.data.onu_state == BCMOLT_ONU_STATE_INACTIVE &&
Jason Huangb6843dc2019-07-22 17:46:06 +08001414 onu_cfg.data.onu_old_state == BCMOLT_ONU_STATE_NOT_CONFIGURED))
Jason Huangb1fad572019-05-28 19:02:30 +08001415 return Status::OK;
1416 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001417
Jason Huangb6843dc2019-07-22 17:46:06 +08001418 OPENOLT_LOG(INFO, openolt_log_id, "Enabling ONU %d on PON %d : vendor id %s, \
1419vendor specific %s, pir %d\n", onu_id, intf_id, vendor_id,
Jason Huangb1fad572019-05-28 19:02:30 +08001420 vendor_specific_to_str(vendor_specific).c_str(), pir);
1421
Jason Huangd33b4d82019-05-15 18:22:57 +08001422 memcpy(serial_number.vendor_id.arr, vendor_id, 4);
1423 memcpy(serial_number.vendor_specific.arr, vendor_specific, 4);
Jason Huangb1fad572019-05-28 19:02:30 +08001424 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
Jason Huangb1fad572019-05-28 19:02:30 +08001425 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.serial_number, serial_number);
1426 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.auto_learning, BCMOS_TRUE);
1427 /*set burst and data profiles to fec disabled*/
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001428 if (board_technology == "XGS-PON") {
1429 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.xgpon.ranging_burst_profile, 2);
1430 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.xgpon.data_burst_profile, 1);
1431 } else if (board_technology == "GPON") {
1432 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.gpon.ds_ber_reporting_interval, 1000000);
1433 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.gpon.omci_port_id, onu_id);
1434 }
Jason Huangb6843dc2019-07-22 17:46:06 +08001435 err = bcmolt_cfg_set(dev_id, &onu_cfg.hdr);
Jason Huangb1fad572019-05-28 19:02:30 +08001436 if (err != BCM_ERR_OK) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001437 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to set activate ONU %d on PON %d, err %d\n", onu_id, intf_id, err);
Jason Huangb1fad572019-05-28 19:02:30 +08001438 return bcm_to_grpc_err(err, "Failed to activate ONU");
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001439 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001440
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001441 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001442}
1443
Jonathan Davis70c21812018-07-19 15:32:10 -04001444Status DeactivateOnu_(uint32_t intf_id, uint32_t onu_id,
1445 const char *vendor_id, const char *vendor_specific) {
Jason Huangb1fad572019-05-28 19:02:30 +08001446 bcmos_errno err = BCM_ERR_OK;
1447 bcmolt_onu_set_onu_state onu_oper; /* declare main API struct */
1448 bcmolt_onu_cfg onu_cfg;
1449 bcmolt_onu_key onu_key; /**< Object key. */
1450 bcmolt_onu_state onu_state;
Jonathan Davis70c21812018-07-19 15:32:10 -04001451
Jason Huangb1fad572019-05-28 19:02:30 +08001452 onu_key.onu_id = onu_id;
1453 onu_key.pon_ni = intf_id;
1454 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
1455 BCMOLT_FIELD_SET_PRESENT(&onu_cfg.data, onu_cfg_data, onu_state);
1456 err = bcmolt_cfg_get(dev_id, &onu_cfg.hdr);
1457 if (err == BCM_ERR_OK) {
1458 switch (onu_state) {
1459 case BCMOLT_ONU_OPERATION_ACTIVE:
1460 BCMOLT_OPER_INIT(&onu_oper, onu, set_onu_state, onu_key);
1461 BCMOLT_FIELD_SET(&onu_oper.data, onu_set_onu_state_data,
1462 onu_state, BCMOLT_ONU_OPERATION_INACTIVE);
1463 err = bcmolt_oper_submit(dev_id, &onu_oper.hdr);
1464 if (err != BCM_ERR_OK) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001465 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to \
1466deactivate ONU %d on PON %d, err %d\n", onu_id, intf_id, err);
Jason Huangb1fad572019-05-28 19:02:30 +08001467 return bcm_to_grpc_err(err, "Failed to deactivate ONU");
1468 }
1469 break;
1470 }
Jonathan Davis70c21812018-07-19 15:32:10 -04001471 }
1472
1473 return Status::OK;
1474}
1475
1476Status DeleteOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001477 const char *vendor_id, const char *vendor_specific) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001478
Jason Huangb6843dc2019-07-22 17:46:06 +08001479 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 -05001480 onu_id, intf_id, vendor_id, vendor_specific_to_str(vendor_specific).c_str());
1481
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001482 // Need to deactivate before removing it (BAL rules)
1483
1484 DeactivateOnu_(intf_id, onu_id, vendor_id, vendor_specific);
1485 // Sleep to allow the state to propagate
1486 // We need the subscriber terminal object to be admin down before removal
1487 // Without sleep the race condition is lost by ~ 20 ms
1488 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1489
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001490 // TODO: Delete the schedulers and queues.
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001491
Jason Huangd33b4d82019-05-15 18:22:57 +08001492 bcmolt_onu_cfg cfg_obj;
1493 bcmolt_onu_key key;
Jonathan Davis70c21812018-07-19 15:32:10 -04001494
Jason Huangb6843dc2019-07-22 17:46:06 +08001495 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 -04001496 onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -04001497
Jason Huangd33b4d82019-05-15 18:22:57 +08001498 key.onu_id = onu_id;
1499 key.pon_ni = intf_id;
1500 BCMOLT_CFG_INIT(&cfg_obj, onu, key);
Jonathan Davis70c21812018-07-19 15:32:10 -04001501
Jason Huangb6843dc2019-07-22 17:46:06 +08001502 bcmos_errno err = bcmolt_cfg_clear(dev_id, &cfg_obj.hdr);
Jonathan Davis70c21812018-07-19 15:32:10 -04001503 if (err != BCM_ERR_OK)
1504 {
Jason Huangb6843dc2019-07-22 17:46:06 +08001505 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 -04001506 onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -04001507 return Status(grpc::StatusCode::INTERNAL, "Failed to delete ONU");
1508 }
1509
Jason Huangd33b4d82019-05-15 18:22:57 +08001510 return Status::OK;
Jonathan Davis70c21812018-07-19 15:32:10 -04001511}
1512
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001513#define MAX_CHAR_LENGTH 20
1514#define MAX_OMCI_MSG_LENGTH 44
1515Status OmciMsgOut_(uint32_t intf_id, uint32_t onu_id, const std::string pkt) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001516 bcmolt_bin_str buf = {};
1517 bcmolt_onu_cpu_packets omci_cpu_packets;
1518 bcmolt_onu_key key;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001519
Jason Huangd33b4d82019-05-15 18:22:57 +08001520 key.pon_ni = intf_id;
1521 key.onu_id = onu_id;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001522
Jason Huangd33b4d82019-05-15 18:22:57 +08001523 BCMOLT_OPER_INIT(&omci_cpu_packets, onu, cpu_packets, key);
1524 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, packet_type, BCMOLT_PACKET_TYPE_OMCI);
1525 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, calc_crc, BCMOS_TRUE);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001526
1527 // ???
1528 if ((pkt.size()/2) > MAX_OMCI_MSG_LENGTH) {
1529 buf.len = MAX_OMCI_MSG_LENGTH;
1530 } else {
1531 buf.len = pkt.size()/2;
1532 }
1533
1534 /* Send the OMCI packet using the BAL remote proxy API */
1535 uint16_t idx1 = 0;
1536 uint16_t idx2 = 0;
1537 uint8_t arraySend[buf.len];
1538 char str1[MAX_CHAR_LENGTH];
1539 char str2[MAX_CHAR_LENGTH];
1540 memset(&arraySend, 0, buf.len);
1541
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001542 for (idx1=0,idx2=0; idx1<((buf.len)*2); idx1++,idx2++) {
1543 sprintf(str1,"%c", pkt[idx1]);
1544 sprintf(str2,"%c", pkt[++idx1]);
1545 strcat(str1,str2);
1546 arraySend[idx2] = strtol(str1, NULL, 16);
1547 }
1548
Jason Huangd33b4d82019-05-15 18:22:57 +08001549 buf.arr = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
1550 memcpy(buf.arr, (uint8_t *)arraySend, buf.len);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001551
Jason Huangd33b4d82019-05-15 18:22:57 +08001552 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, number_of_packets, 1);
1553 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, packet_size, buf.len);
1554 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, buffer, buf);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001555
Jason Huangd33b4d82019-05-15 18:22:57 +08001556 bcmos_errno err = bcmolt_oper_submit(dev_id, &omci_cpu_packets.hdr);
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001557 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001558 OPENOLT_LOG(ERROR, omci_log_id, "Error sending OMCI message to ONU %d on PON %d\n", onu_id, intf_id);
1559 return bcm_to_grpc_err(err, "send OMCI failed");
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001560 } else {
Jason Huangb6843dc2019-07-22 17:46:06 +08001561 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 -05001562 buf.len, onu_id, intf_id, pkt.c_str());
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001563 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001564 free(buf.arr);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001565
1566 return Status::OK;
1567}
1568
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001569Status OnuPacketOut_(uint32_t intf_id, uint32_t onu_id, uint32_t port_no, uint32_t gemport_id, const std::string pkt) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001570 bcmolt_pon_interface_cpu_packets pon_interface_cpu_packets; /**< declare main API struct */
1571 bcmolt_pon_interface_key key = {.pon_ni = (bcmolt_interface)intf_id}; /**< declare key */
1572 bcmolt_bin_str buf = {};
1573 bcmolt_gem_port_id gem_port_id_array[1];
1574 bcmolt_gem_port_id_list_u8_max_16 gem_port_list = {};
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001575
Craig Lutgen967a1d02018-11-27 10:41:51 -06001576 if (port_no > 0) {
1577 bool found = false;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001578 if (gemport_id == 0) {
1579 bcmos_fastlock_lock(&data_lock);
1580 // Map the port_no to one of the flows that owns it to find a gemport_id for that flow.
1581 // Pick any flow that is mapped with the same port_no.
1582 std::map<uint32_t, std::set<uint32_t> >::const_iterator it = port_to_flows.find(port_no);
1583 if (it != port_to_flows.end() && !it->second.empty()) {
1584 uint32_t flow_id = *(it->second.begin()); // Pick any flow_id out of the bag set
1585 std::map<uint32_t, uint32_t>::const_iterator fit = flowid_to_gemport.find(flow_id);
1586 if (fit != flowid_to_gemport.end()) {
1587 found = true;
1588 gemport_id = fit->second;
1589 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001590 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001591 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001592
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001593 if (!found) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001594 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 -08001595 onu_id, port_no, intf_id);
1596 return grpc::Status(grpc::StatusCode::NOT_FOUND, "no flow for port_no");
1597 }
Jason Huangb6843dc2019-07-22 17:46:06 +08001598 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 -08001599 gemport_id, onu_id, port_no, intf_id);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001600 }
1601
Jason Huangd33b4d82019-05-15 18:22:57 +08001602 gem_port_id_array[0] = gemport_id;
1603 gem_port_list.len = 1;
1604 gem_port_list.arr = gem_port_id_array;
1605 buf.len = pkt.size();
1606 buf.arr = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
1607 memcpy(buf.arr, (uint8_t *)pkt.data(), buf.len);
1608
1609 /* init the API struct */
1610 BCMOLT_OPER_INIT(&pon_interface_cpu_packets, pon_interface, cpu_packets, key);
1611 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, packet_type, BCMOLT_PACKET_TYPE_ETH);
1612 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, calc_crc, BCMOS_TRUE);
1613 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, gem_port_list, gem_port_list);
1614 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, buffer, buf);
1615
Jason Huangb6843dc2019-07-22 17:46:06 +08001616 OPENOLT_LOG(INFO, openolt_log_id, "Packet out of length %d sent to gemport %d on pon %d port_no %u\n",
Jason Huangd33b4d82019-05-15 18:22:57 +08001617 (uint8_t)pkt.size(), gemport_id, intf_id, port_no);
1618
1619 /* call API */
Jason Huangb6843dc2019-07-22 17:46:06 +08001620 bcmolt_oper_submit(dev_id, &pon_interface_cpu_packets.hdr);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001621 }
1622 else {
Jason Huangd33b4d82019-05-15 18:22:57 +08001623 //TODO: Port No is 0, it is coming sender requirement.
Jason Huangb6843dc2019-07-22 17:46:06 +08001624 OPENOLT_LOG(INFO, openolt_log_id, "port_no %d onu %d on pon %d\n",
Jason Huangd33b4d82019-05-15 18:22:57 +08001625 port_no, onu_id, intf_id);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001626 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001627 free(buf.arr);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001628
1629 return Status::OK;
1630}
1631
Girish Gowdra897f5ab2019-10-17 17:05:31 +05301632Status UplinkPacketOut_(uint32_t intf_id, const std::string pkt) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001633 bcmolt_flow_key key = {}; /* declare key */
1634 bcmolt_bin_str buffer = {};
1635 bcmolt_flow_send_eth_packet oper; /* declare main API struct */
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001636
Girish Gowdra897f5ab2019-10-17 17:05:31 +05301637 // TODO: flow_id is currently not passed in UplinkPacket message from voltha.
1638 bcmolt_flow_id flow_id = 0;
1639
Jason Huangb6843dc2019-07-22 17:46:06 +08001640 //validate flow_id and find flow_id/flow type: upstream/ingress type: PON/egress type: NNI
1641 if (get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, FLOW_TYPE) == BCMOLT_FLOW_TYPE_UPSTREAM && \
1642 get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, INGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_PON && \
1643 get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, EGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_NNI)
1644 key.flow_id = flow_id;
1645 else {
1646 if (flow_id_counters != 0) {
1647 for (int flowid=0; flowid < flow_id_counters; flowid++) {
1648 int flow_index = flow_id_data[flowid][0];
1649 if (get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, FLOW_TYPE) == BCMOLT_FLOW_TYPE_UPSTREAM && \
1650 get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, INGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_PON && \
1651 get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, EGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_NNI) {
1652 key.flow_id = flow_index;
1653 break;
1654 }
1655 }
1656 }
Girish Gowdra897f5ab2019-10-17 17:05:31 +05301657 else {
Jason Huangb6843dc2019-07-22 17:46:06 +08001658 return grpc::Status(grpc::StatusCode::NOT_FOUND, "no flow id found");
Girish Gowdra897f5ab2019-10-17 17:05:31 +05301659 }
Jason Huangb6843dc2019-07-22 17:46:06 +08001660 }
1661
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07001662 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM; /* send from uplink direction */
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001663
Jason Huangd33b4d82019-05-15 18:22:57 +08001664 /* Initialize the API struct. */
1665 BCMOLT_OPER_INIT(&oper, flow, send_eth_packet, key);
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001666
Jason Huangd33b4d82019-05-15 18:22:57 +08001667 buffer.len = pkt.size();
1668 buffer.arr = (uint8_t *)malloc((buffer.len)*sizeof(uint8_t));
1669 memcpy(buffer.arr, (uint8_t *)pkt.data(), buffer.len);
1670 if (buffer.arr == NULL) {
Girish Gowdra897f5ab2019-10-17 17:05:31 +05301671 OPENOLT_LOG(ERROR, openolt_log_id, "allocate packet buffer failed\n");
1672 return bcm_to_grpc_err(BCM_ERR_PARM, "allocate packet buffer failed");
Jason Huangd33b4d82019-05-15 18:22:57 +08001673 }
1674 BCMOLT_FIELD_SET(&oper.data, flow_send_eth_packet_data, buffer, buffer);
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001675
Jason Huangd33b4d82019-05-15 18:22:57 +08001676 bcmos_errno err = bcmolt_oper_submit(dev_id, &oper.hdr);
Jason Huangb6843dc2019-07-22 17:46:06 +08001677 if (err) {
Girish Gowdra897f5ab2019-10-17 17:05:31 +05301678 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);
Jason Huangb6843dc2019-07-22 17:46:06 +08001679 } else {
Girish Gowdra897f5ab2019-10-17 17:05:31 +05301680 OPENOLT_LOG(INFO, openolt_log_id, "sent packets to port %d in upstream direction, flow_id %d \n", intf_id, key.flow_id);
Jason Huangb6843dc2019-07-22 17:46:06 +08001681 }
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001682
1683 return Status::OK;
1684}
1685
Jason Huangd33b4d82019-05-15 18:22:57 +08001686uint32_t GetPortNum_(uint32_t flow_id) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001687 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001688 uint32_t port_no = 0;
1689 std::map<uint32_t, uint32_t >::const_iterator it = flowid_to_port.find(flow_id);
1690 if (it != flowid_to_port.end()) {
1691 port_no = it->second;
1692 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001693 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001694 return port_no;
1695}
1696
Jason Huangb6843dc2019-07-22 17:46:06 +08001697#define FLOW_LOG(level,msg,err) \
1698 do { \
1699 OPENOLT_LOG(level, openolt_log_id, "--------> %s (flow_id %d) err: %d <--------\n", msg, key.flow_id, err); \
1700 OPENOLT_LOG(level, openolt_log_id, "intf_id %d, onu_id %d, uni_id %d, port_no %u, cookie %"PRIu64"\n", \
1701 access_intf_id, onu_id, uni_id, port_no, cookie); \
1702 OPENOLT_LOG(level, openolt_log_id, "flow_type %s, queue_id %d, sched_id %d\n", flow_type.c_str(), \
1703 cfg.data.egress_qos.u.fixed_queue.queue_id, cfg.data.egress_qos.tm_sched.id); \
1704 OPENOLT_LOG(level, openolt_log_id, "Ingress(intfd_type %s, intf_id %d), Egress(intf_type %s, intf_id %d)\n", \
1705 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), cfg.data.ingress_intf.intf_id, \
1706 GET_FLOW_INTERFACE_TYPE(cfg.data.egress_intf.intf_type), cfg.data.egress_intf.intf_id); \
1707 OPENOLT_LOG(level, openolt_log_id, "classifier(o_vid %d, o_pbits %d, i_vid %d, i_pbits %d, ether type 0x%x)\n", \
1708 c_val.o_vid, c_val.o_pbits, c_val.i_vid, c_val.i_pbits, classifier.eth_type()); \
1709 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", \
1710 c_val.ip_proto, gemport_id, c_val.src_port, c_val.dst_port, GET_PKT_TAG_TYPE(c_val.pkt_tag_type)); \
1711 OPENOLT_LOG(level, openolt_log_id, "action(cmds_bitmask %s, o_vid %d, o_pbits %d, i_vid %d, i_pbits %d)\n\n", \
1712 get_flow_acton_command(a_val.cmds_bitmask), a_val.o_vid, a_val.o_pbits, a_val.i_vid, a_val.i_pbits); \
1713 } while(0)
1714
1715#define FLOW_PARAM_LOG() \
1716 do { \
1717 OPENOLT_LOG(INFO, openolt_log_id, "--------> flow comparison (now before) <--------\n"); \
1718 OPENOLT_LOG(INFO, openolt_log_id, "flow_id (%d %d)\n", \
1719 key.flow_id, flow_index); \
1720 OPENOLT_LOG(INFO, openolt_log_id, "onu_id (%d %lu)\n", \
1721 cfg.data.onu_id , get_flow_status(flow_index, flow_id_data[flowid][1], ONU_ID)); \
1722 OPENOLT_LOG(INFO, openolt_log_id, "type (%d %lu)\n", \
1723 key.flow_type, get_flow_status(flow_index, flow_id_data[flowid][1], FLOW_TYPE)); \
1724 OPENOLT_LOG(INFO, openolt_log_id, "svc_port_id (%d %lu)\n", \
1725 cfg.data.svc_port_id, get_flow_status(flow_index, flow_id_data[flowid][1], SVC_PORT_ID)); \
1726 OPENOLT_LOG(INFO, openolt_log_id, "priority (%d %lu)\n", \
1727 cfg.data.priority, get_flow_status(flow_index, flow_id_data[flowid][1], PRIORITY)); \
1728 OPENOLT_LOG(INFO, openolt_log_id, "cookie (%lu %lu)\n", \
1729 cfg.data.cookie, get_flow_status(flow_index, flow_id_data[flowid][1], COOKIE)); \
1730 OPENOLT_LOG(INFO, openolt_log_id, "ingress intf_type (%s %s)\n", \
1731 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), \
1732 GET_FLOW_INTERFACE_TYPE(get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_TYPE))); \
1733 OPENOLT_LOG(INFO, openolt_log_id, "ingress intf id (%d %lu)\n", \
1734 cfg.data.ingress_intf.intf_id , get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_ID)); \
1735 OPENOLT_LOG(INFO, openolt_log_id, "egress intf_type (%d %lu)\n", \
1736 cfg.data.egress_intf.intf_type , get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_TYPE)); \
1737 OPENOLT_LOG(INFO, openolt_log_id, "egress intf_id (%d %lu)\n", \
1738 cfg.data.egress_intf.intf_id , get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_ID)); \
1739 OPENOLT_LOG(INFO, openolt_log_id, "classifier o_vid (%d %lu)\n", \
1740 c_val.o_vid , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_VID)); \
1741 OPENOLT_LOG(INFO, openolt_log_id, "classifier o_pbits (%d %lu)\n", \
1742 c_val.o_pbits , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_PBITS)); \
1743 OPENOLT_LOG(INFO, openolt_log_id, "classifier i_vid (%d %lu)\n", \
1744 c_val.i_vid , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_VID)); \
1745 OPENOLT_LOG(INFO, openolt_log_id, "classifier i_pbits (%d %lu)\n", \
1746 c_val.i_pbits , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_PBITS)); \
1747 OPENOLT_LOG(INFO, openolt_log_id, "classifier ether_type (0x%x 0x%lx)\n", \
1748 c_val.ether_type , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_ETHER_TYPE)); \
1749 OPENOLT_LOG(INFO, openolt_log_id, "classifier ip_proto (%d %lu)\n", \
1750 c_val.ip_proto , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_IP_PROTO)); \
1751 OPENOLT_LOG(INFO, openolt_log_id, "classifier src_port (%d %lu)\n", \
1752 c_val.src_port , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_SRC_PORT)); \
1753 OPENOLT_LOG(INFO, openolt_log_id, "classifier dst_port (%d %lu)\n", \
1754 c_val.dst_port , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_DST_PORT)); \
1755 OPENOLT_LOG(INFO, openolt_log_id, "classifier pkt_tag_type (%s %s)\n", \
1756 GET_PKT_TAG_TYPE(c_val.pkt_tag_type), \
1757 GET_PKT_TAG_TYPE(get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_PKT_TAG_TYPE))); \
1758 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos type (%d %lu)\n", \
1759 cfg.data.egress_qos.type , get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TYPE)); \
1760 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos queue_id (%d %lu)\n", \
1761 cfg.data.egress_qos.u.fixed_queue.queue_id, \
1762 get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_QUEUE_ID)); \
1763 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos sched_id (%d %lu)\n", \
1764 cfg.data.egress_qos.tm_sched.id, \
1765 get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TM_SCHED_ID)); \
1766 OPENOLT_LOG(INFO, openolt_log_id, "classifier cmds_bitmask (%s %s)\n", \
1767 get_flow_acton_command(a_val.cmds_bitmask), \
1768 get_flow_acton_command(get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_CMDS_BITMASK))); \
1769 OPENOLT_LOG(INFO, openolt_log_id, "action o_vid (%d %lu)\n", \
1770 a_val.o_vid , get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_VID)); \
1771 OPENOLT_LOG(INFO, openolt_log_id, "action i_vid (%d %lu)\n", \
1772 a_val.i_vid , get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_VID)); \
1773 OPENOLT_LOG(INFO, openolt_log_id, "action o_pbits (%d %lu)\n", \
1774 a_val.o_pbits , get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_PBITS)); \
1775 OPENOLT_LOG(INFO, openolt_log_id, "action i_pbits (%d %lu)\n\n", \
1776 a_val.i_pbits, get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_PBITS)); \
1777 } while(0)
1778
1779#define FLOW_CHECKER
1780//#define SHOW_FLOW_PARAM
1781
Craig Lutgen967a1d02018-11-27 10:41:51 -06001782Status 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 +00001783 uint32_t flow_id, const std::string flow_type,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001784 int32_t alloc_id, int32_t network_intf_id,
1785 int32_t gemport_id, const ::openolt::Classifier& classifier,
Craig Lutgen967a1d02018-11-27 10:41:51 -06001786 const ::openolt::Action& action, int32_t priority_value, uint64_t cookie) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001787 bcmolt_flow_cfg cfg;
1788 bcmolt_flow_key key = { }; /**< Object key. */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001789 int32_t o_vid = -1;
1790 bool single_tag = false;
1791 uint32_t ether_type = 0;
Jason Huangb6843dc2019-07-22 17:46:06 +08001792 bcmolt_classifier c_val = { };
1793 bcmolt_action a_val = { };
1794 bcmolt_tm_queue_ref tm_val = { };
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001795 int tm_qmp_id, tm_q_set_id;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001796
1797 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001798 if (flow_type.compare(upstream) == 0 ) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001799 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001800 } else if (flow_type.compare(downstream) == 0) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001801 key.flow_type = BCMOLT_FLOW_TYPE_DOWNSTREAM;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001802 } else {
Jason Huangb6843dc2019-07-22 17:46:06 +08001803 OPENOLT_LOG(ERROR, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001804 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001805 }
1806
Jason Huangd33b4d82019-05-15 18:22:57 +08001807 BCMOLT_CFG_INIT(&cfg, flow, key);
1808 BCMOLT_MSG_FIELD_SET(&cfg, cookie, cookie);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001809
Jason Huangb6843dc2019-07-22 17:46:06 +08001810 if (access_intf_id >= 0 && network_intf_id >= 0) {
1811 if (key.flow_type == BCMOLT_FLOW_TYPE_UPSTREAM) { //upstream
Jason Huangd33b4d82019-05-15 18:22:57 +08001812 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_PON);
1813 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_id, access_intf_id);
Jason Huangb6843dc2019-07-22 17:46:06 +08001814 if (classifier.eth_type() == EAP_ETHER_TYPE || //EAPOL packet
1815 (classifier.ip_proto() == 17 && classifier.src_port() == 68 && classifier.dst_port() == 67)) { //DHCP packet
1816 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_HOST);
1817 } else {
1818 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_NNI);
1819 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_id, network_intf_id);
1820 }
1821 } else if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) { //downstream
1822 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_NNI);
1823 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_id, network_intf_id);
Jason Huangd33b4d82019-05-15 18:22:57 +08001824 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_PON);
1825 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_id, access_intf_id);
1826 }
Jason Huangb6843dc2019-07-22 17:46:06 +08001827 } else {
1828 OPENOLT_LOG(ERROR, openolt_log_id, "flow network setting invalid\n");
1829 return bcm_to_grpc_err(BCM_ERR_PARM, "flow network setting invalid");
Shad Ansari39739bc2018-09-13 21:38:37 +00001830 }
Jason Huangb6843dc2019-07-22 17:46:06 +08001831
Shad Ansari39739bc2018-09-13 21:38:37 +00001832 if (onu_id >= 0) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001833 BCMOLT_MSG_FIELD_SET(&cfg, onu_id, onu_id);
Shad Ansari39739bc2018-09-13 21:38:37 +00001834 }
1835 if (gemport_id >= 0) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001836 BCMOLT_MSG_FIELD_SET(&cfg, svc_port_id, gemport_id);
Shad Ansari39739bc2018-09-13 21:38:37 +00001837 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001838 if (gemport_id >= 0 && port_no != 0) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001839 bcmos_fastlock_lock(&data_lock);
Jason Huangd33b4d82019-05-15 18:22:57 +08001840 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
Craig Lutgen967a1d02018-11-27 10:41:51 -06001841 port_to_flows[port_no].insert(key.flow_id);
1842 flowid_to_gemport[key.flow_id] = gemport_id;
1843 }
1844 else
1845 {
1846 flowid_to_port[key.flow_id] = port_no;
1847 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001848 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001849 }
Shad Ansari39739bc2018-09-13 21:38:37 +00001850 if (priority_value >= 0) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001851 BCMOLT_MSG_FIELD_SET(&cfg, priority, priority_value);
Shad Ansari39739bc2018-09-13 21:38:37 +00001852 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001853
1854 {
Jason Huangd33b4d82019-05-15 18:22:57 +08001855 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001856 if (classifier.o_tpid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001857 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_tpid 0x%04x\n", classifier.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001858 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_tpid, classifier.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001859 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001860 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001861 if (classifier.o_vid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001862 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_vid %d\n", classifier.o_vid());
1863 BCMOLT_FIELD_SET(&c_val, classifier, o_vid, classifier.o_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001864 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001865 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001866 if (classifier.i_tpid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001867 OPENOLT_LOG(DEBUG, openolt_log_id, "classify i_tpid 0x%04x\n", classifier.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001868 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, i_tpid, classifier.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001869 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001870 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001871 if (classifier.i_vid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001872 OPENOLT_LOG(DEBUG, openolt_log_id, "classify i_vid %d\n", classifier.i_vid());
1873 BCMOLT_FIELD_SET(&c_val, classifier, i_vid, classifier.i_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001874 }
1875
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001876 if (classifier.eth_type()) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001877 ether_type = classifier.eth_type();
Jason Huangb6843dc2019-07-22 17:46:06 +08001878 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ether_type 0x%04x\n", classifier.eth_type());
1879 BCMOLT_FIELD_SET(&c_val, classifier, ether_type, classifier.eth_type());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001880 }
1881
1882 /*
1883 if (classifier.dst_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001884 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_mac, classifier.dst_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001885 }
1886
1887 if (classifier.src_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001888 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_mac, classifier.src_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001889 }
1890 */
1891
1892 if (classifier.ip_proto()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001893 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ip_proto %d\n", classifier.ip_proto());
1894 BCMOLT_FIELD_SET(&c_val, classifier, ip_proto, classifier.ip_proto());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001895 }
1896
1897 /*
1898 if (classifier.dst_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001899 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_ip, classifier.dst_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001900 }
1901
1902 if (classifier.src_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001903 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_ip, classifier.src_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001904 }
1905 */
1906
1907 if (classifier.src_port()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001908 OPENOLT_LOG(DEBUG, openolt_log_id, "classify src_port %d\n", classifier.src_port());
1909 BCMOLT_FIELD_SET(&c_val, classifier, src_port, classifier.src_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001910 }
1911
1912 if (classifier.dst_port()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001913 OPENOLT_LOG(DEBUG, openolt_log_id, "classify dst_port %d\n", classifier.dst_port());
1914 BCMOLT_FIELD_SET(&c_val, classifier, dst_port, classifier.dst_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001915 }
1916
1917 if (!classifier.pkt_tag_type().empty()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001918 OPENOLT_LOG(DEBUG, openolt_log_id, "classify tag_type %s\n", classifier.pkt_tag_type().c_str());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001919 if (classifier.pkt_tag_type().compare("untagged") == 0) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001920 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_UNTAGGED);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001921 } else if (classifier.pkt_tag_type().compare("single_tag") == 0) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001922 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_SINGLE_TAG);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001923 single_tag = true;
1924
Jason Huangb6843dc2019-07-22 17:46:06 +08001925 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1926 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, classifier.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001927 } else if (classifier.pkt_tag_type().compare("double_tag") == 0) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001928 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_DOUBLE_TAG);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001929
Jason Huangb6843dc2019-07-22 17:46:06 +08001930 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1931 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, classifier.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001932 }
1933 }
Jason Huangb6843dc2019-07-22 17:46:06 +08001934 BCMOLT_MSG_FIELD_SET(&cfg, classifier, c_val);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001935 }
1936
Jason Huangb6843dc2019-07-22 17:46:06 +08001937 if (cfg.data.egress_intf.intf_type != BCMOLT_FLOW_INTERFACE_TYPE_HOST) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001938 const ::openolt::ActionCmd& cmd = action.cmd();
1939
1940 if (cmd.add_outer_tag()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001941 OPENOLT_LOG(DEBUG, openolt_log_id, "action add o_tag\n");
1942 BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, BCMOLT_ACTION_CMD_ID_ADD_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001943 }
1944
1945 if (cmd.remove_outer_tag()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001946 OPENOLT_LOG(DEBUG, openolt_log_id, "action pop o_tag\n");
1947 BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, BCMOLT_ACTION_CMD_ID_REMOVE_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001948 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001949 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001950 if (cmd.trap_to_host()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001951 OPENOLT_LOG(INFO, openolt_log_id, "action trap-to-host\n");
Craig Lutgen19512312018-11-02 10:14:46 -05001952 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, cmds_bitmask, BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001953 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001954 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001955 if (action.o_vid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001956 OPENOLT_LOG(DEBUG, openolt_log_id, "action o_vid=%d\n", action.o_vid());
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001957 o_vid = action.o_vid();
Jason Huangb6843dc2019-07-22 17:46:06 +08001958 BCMOLT_FIELD_SET(&a_val, action, o_vid, action.o_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001959 }
1960
1961 if (action.o_pbits()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001962 OPENOLT_LOG(DEBUG, openolt_log_id, "action o_pbits=0x%x\n", action.o_pbits());
1963 BCMOLT_FIELD_SET(&a_val, action, o_pbits, action.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001964 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001965 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001966 if (action.o_tpid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001967 OPENOLT_LOG(INFO, openolt_log_id, "action o_tpid=0x%04x\n", action.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001968 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, o_tpid, action.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001969 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001970 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001971 if (action.i_vid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001972 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_vid=%d\n", action.i_vid());
1973 BCMOLT_FIELD_SET(&a_val, action, i_vid, action.i_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001974 }
1975
1976 if (action.i_pbits()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001977 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_pbits=0x%x\n", action.i_pbits());
1978 BCMOLT_FIELD_SET(&a_val, action, i_pbits, action.i_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001979 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001980 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001981 if (action.i_tpid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001982 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_tpid=0x%04x\n", action.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001983 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, i_tpid, action.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001984 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001985 */
Jason Huangb6843dc2019-07-22 17:46:06 +08001986 BCMOLT_MSG_FIELD_SET(&cfg, action, a_val);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001987 }
1988
Shad Ansari39739bc2018-09-13 21:38:37 +00001989 if ((access_intf_id >= 0) && (onu_id >= 0)) {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001990 if(single_tag && ether_type == EAP_ETHER_TYPE) {
1991 tm_val.sched_id = (flow_type.compare(upstream) == 0) ? \
1992 get_default_tm_sched_id(network_intf_id, upstream) : \
1993 get_default_tm_sched_id(access_intf_id, downstream);
1994 tm_val.queue_id = 0;
Jason Huangd33b4d82019-05-15 18:22:57 +08001995
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001996 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE);
Jason Huangb6843dc2019-07-22 17:46:06 +08001997 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
1998 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001999
2000 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2001 flow_type.c_str(), tm_val.queue_id, tm_val.sched_id, \
2002 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2003 } else {
2004 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
2005 tm_val.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, downstream);
2006
2007 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2008 // Queue 0 on DS subscriber scheduler
2009 tm_val.queue_id = 0;
2010
2011 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2012 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2013 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
2014
2015 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2016 downstream.c_str(), tm_val.queue_id, tm_val.sched_id, \
2017 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2018
2019 } else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2020 /* Fetch TM QMP ID mapped to DS subscriber scheduler */
2021 tm_qmp_id = tm_q_set_id = get_tm_qmp_id(tm_val.sched_id, access_intf_id, onu_id, uni_id);
2022
2023 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2024 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2025 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_qmp_id, tm_qmp_id);
2026 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_q_set_id, tm_q_set_id);
2027
2028 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, q_set_id = %d, sched_id = %d, intf_type %s\n", \
2029 downstream.c_str(), tm_q_set_id, tm_val.sched_id, \
2030 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2031 }
2032 } else if (key.flow_type == BCMOLT_FLOW_TYPE_UPSTREAM) {
2033 // NNI Scheduler ID
2034 tm_val.sched_id = get_default_tm_sched_id(network_intf_id, upstream);
2035 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2036 // Queue 0 on NNI scheduler
2037 tm_val.queue_id = 0;
2038 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2039 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2040 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
2041
2042 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2043 upstream.c_str(), tm_val.queue_id, tm_val.sched_id, \
2044 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2045
2046 } else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2047 /* Fetch TM QMP ID mapped to US NNI scheduler */
2048 tm_qmp_id = tm_q_set_id = get_tm_qmp_id(tm_val.sched_id, access_intf_id, onu_id, uni_id);
2049 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2050 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2051 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_qmp_id, tm_qmp_id);
2052 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_q_set_id, tm_q_set_id);
2053
2054 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, q_set_id = %d, sched_id = %d, intf_type %s\n", \
2055 upstream.c_str(), tm_q_set_id, tm_val.sched_id, \
2056 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2057 }
2058 }
Shad Ansari39739bc2018-09-13 21:38:37 +00002059 }
Shad Ansari06101952018-07-25 00:22:09 +00002060 }
2061
Jason Huangd33b4d82019-05-15 18:22:57 +08002062 BCMOLT_MSG_FIELD_SET(&cfg, state, BCMOLT_FLOW_STATE_ENABLE);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002063 BCMOLT_MSG_FIELD_SET(&cfg, statistics, BCMOLT_CONTROL_STATE_ENABLE);
Jason Huangb6843dc2019-07-22 17:46:06 +08002064#ifdef FLOW_CHECKER
2065 //Flow Checker, To avoid duplicate flow.
2066 if (flow_id_counters != 0) {
2067 bool b_duplicate_flow = false;
2068 for (int flowid=0; flowid < flow_id_counters; flowid++) {
2069 int flow_index = flow_id_data[flowid][0];
2070 b_duplicate_flow = (cfg.data.onu_id == get_flow_status(flow_index, flow_id_data[flowid][1], ONU_ID)) && \
2071 (key.flow_type == flow_id_data[flowid][1]) && \
2072 (cfg.data.svc_port_id == get_flow_status(flow_index, flow_id_data[flowid][1], SVC_PORT_ID)) && \
2073 (cfg.data.priority == get_flow_status(flow_index, flow_id_data[flowid][1], PRIORITY)) && \
2074 (cfg.data.cookie == get_flow_status(flow_index, flow_id_data[flowid][1], COOKIE)) && \
2075 (cfg.data.ingress_intf.intf_type == get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_TYPE)) && \
2076 (cfg.data.ingress_intf.intf_id == get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_ID)) && \
2077 (cfg.data.egress_intf.intf_type == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_TYPE)) && \
2078 (cfg.data.egress_intf.intf_id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_ID)) && \
2079 (c_val.o_vid == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_VID)) && \
2080 (c_val.o_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_PBITS)) && \
2081 (c_val.i_vid == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_VID)) && \
2082 (c_val.i_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_PBITS)) && \
2083 (c_val.ether_type == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_ETHER_TYPE)) && \
2084 (c_val.ip_proto == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_IP_PROTO)) && \
2085 (c_val.src_port == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_SRC_PORT)) && \
2086 (c_val.dst_port == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_DST_PORT)) && \
2087 (c_val.pkt_tag_type == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_PKT_TAG_TYPE)) && \
2088 (cfg.data.egress_qos.type == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TYPE)) && \
2089 (cfg.data.egress_qos.u.fixed_queue.queue_id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_QUEUE_ID)) && \
2090 (cfg.data.egress_qos.tm_sched.id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TM_SCHED_ID)) && \
2091 (a_val.cmds_bitmask == get_flow_status(flowid, flow_id_data[flowid][1], ACTION_CMDS_BITMASK)) && \
2092 (a_val.o_vid == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_VID)) && \
2093 (a_val.i_vid == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_VID)) && \
2094 (a_val.o_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_PBITS)) && \
2095 (a_val.i_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_PBITS)) && \
2096 (cfg.data.state == get_flow_status(flowid, flow_id_data[flowid][1], STATE));
2097#ifdef SHOW_FLOW_PARAM
2098 // Flow Parameter
2099 FLOW_PARAM_LOG();
2100#endif
2101
2102 if (b_duplicate_flow) {
2103 FLOW_LOG(WARNING, "Flow duplicate", 0);
2104 return bcm_to_grpc_err(BCM_ERR_ALREADY, "flow exists");
2105 }
2106 }
2107 }
2108#endif
2109
Jason Huangd33b4d82019-05-15 18:22:57 +08002110 bcmos_errno err = bcmolt_cfg_set(dev_id, &cfg.hdr);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04002111 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08002112 FLOW_LOG(ERROR, "Flow add failed", err);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04002113 return bcm_to_grpc_err(err, "flow add failed");
Jason Huangb6843dc2019-07-22 17:46:06 +08002114 } else {
2115 FLOW_LOG(INFO, "Flow add ok", err);
2116 bcmos_fastlock_lock(&data_lock);
2117 flow_id_data[flow_id_counters][0] = key.flow_id;
2118 flow_id_data[flow_id_counters][1] = key.flow_type;
2119 flow_id_counters += 1;
2120 bcmos_fastlock_unlock(&data_lock, 0);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002121 }
2122
2123 return Status::OK;
2124}
2125
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002126Status FlowRemove_(uint32_t flow_id, const std::string flow_type) {
2127
Jason Huangd33b4d82019-05-15 18:22:57 +08002128 bcmolt_flow_cfg cfg;
2129 bcmolt_flow_key key = { };
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002130
Jason Huangd33b4d82019-05-15 18:22:57 +08002131 key.flow_id = (bcmolt_flow_id) flow_id;
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002132 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002133 if (flow_type.compare(upstream) == 0 ) {
Jason Huangd33b4d82019-05-15 18:22:57 +08002134 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002135 } else if (flow_type.compare(downstream) == 0) {
Jason Huangd33b4d82019-05-15 18:22:57 +08002136 key.flow_type = BCMOLT_FLOW_TYPE_DOWNSTREAM;
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002137 } else {
Jason Huangb6843dc2019-07-22 17:46:06 +08002138 OPENOLT_LOG(WARNING, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002139 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
2140 }
2141
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002142 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002143 uint32_t port_no = flowid_to_port[key.flow_id];
Jason Huangd33b4d82019-05-15 18:22:57 +08002144 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
Craig Lutgen967a1d02018-11-27 10:41:51 -06002145 flowid_to_gemport.erase(key.flow_id);
2146 port_to_flows[port_no].erase(key.flow_id);
2147 if (port_to_flows[port_no].empty()) port_to_flows.erase(port_no);
2148 }
2149 else
2150 {
2151 flowid_to_port.erase(key.flow_id);
2152 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002153 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002154
Jason Huangd33b4d82019-05-15 18:22:57 +08002155 BCMOLT_CFG_INIT(&cfg, flow, key);
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002156
Jason Huangd33b4d82019-05-15 18:22:57 +08002157 bcmos_errno err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002158 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08002159 OPENOLT_LOG(ERROR, openolt_log_id, "Error %d while removing flow %d, %s\n",
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04002160 err, flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002161 return Status(grpc::StatusCode::INTERNAL, "Failed to remove flow");
2162 }
2163
Jason Huangb6843dc2019-07-22 17:46:06 +08002164 bcmos_fastlock_lock(&data_lock);
2165 for (int flowid=0; flowid < flow_id_counters; flowid++) {
2166 if (flow_id_data[flowid][0] == flow_id && flow_id_data[flowid][1] == key.flow_type) {
2167 flow_id_counters -= 1;
2168 for (int i=flowid; i < flow_id_counters; i++) {
2169 flow_id_data[i][0] = flow_id_data[i + 1][0];
2170 flow_id_data[i][1] = flow_id_data[i + 1][1];
2171 }
2172 break;
2173 }
2174 }
2175 bcmos_fastlock_unlock(&data_lock, 0);
2176
2177 OPENOLT_LOG(INFO, openolt_log_id, "Flow %d, %s removed\n", flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002178 return Status::OK;
2179}
2180
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002181bcmos_errno CreateDefaultSched(uint32_t intf_id, const std::string direction) {
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002182 bcmos_errno err;
2183 bcmolt_tm_sched_cfg tm_sched_cfg;
2184 bcmolt_tm_sched_key tm_sched_key = {.id = 1};
2185 tm_sched_key.id = get_default_tm_sched_id(intf_id, direction);
2186
2187 // bcmbal_tm_sched_owner
2188 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
2189
2190 /**< The output of the tm_sched object instance */
2191 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.type, BCMOLT_TM_SCHED_OUTPUT_TYPE_INTERFACE);
2192
2193 if (direction.compare(upstream) == 0) {
2194 // In upstream it is NNI scheduler
2195 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_type, BCMOLT_INTERFACE_TYPE_NNI);
2196 } else if (direction.compare(downstream) == 0) {
2197 // In downstream it is PON scheduler
2198 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_type, BCMOLT_INTERFACE_TYPE_PON);
2199 }
2200
2201 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_id, intf_id);
2202
2203 // bcmbal_tm_sched_type
2204 // set the deafult policy to strict priority
2205 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, sched_type, BCMOLT_TM_SCHED_TYPE_SP);
2206
2207 // num_priorities: Max number of strict priority scheduling elements
Jason Huangb6843dc2019-07-22 17:46:06 +08002208 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, num_priorities, 8);
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002209
2210 // bcmbal_tm_shaping
2211 uint32_t cir = 1000000;
2212 uint32_t pir = 1000000;
2213 uint32_t burst = 65536;
Jason Huangb6843dc2019-07-22 17:46:06 +08002214 OPENOLT_LOG(INFO, openolt_log_id, "applying traffic shaping in %s pir=%u, burst=%u\n",
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002215 direction.c_str(), pir, burst);
2216 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, pir);
2217 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, burst);
2218 // FIXME: Setting CIR, results in BAL throwing error 'tm_sched minimum rate is not supported yet'
2219 // BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.cir, cir);
2220 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.pir, pir);
2221 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.burst, burst);
2222
2223 err = bcmolt_cfg_set(dev_id, &tm_sched_cfg.hdr);
2224 if (err) {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002225 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create %s scheduler, id %d, intf_id %d, err %d\n", \
2226 direction.c_str(), tm_sched_key.id, intf_id, err);
2227 return err;
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002228 }
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002229
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002230 OPENOLT_LOG(INFO, openolt_log_id, "Create %s scheduler success, id %d, intf_id %d\n", \
2231 direction.c_str(), tm_sched_key.id, intf_id);
2232 return BCM_ERR_OK;
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002233}
2234
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002235bcmos_errno CreateSched(std::string direction, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t port_no,
2236 uint32_t alloc_id, tech_profile::AdditionalBW additional_bw, uint32_t weight, uint32_t priority,
2237 tech_profile::SchedulingPolicy sched_policy, tech_profile::TrafficShapingInfo tf_sh_info) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002238
2239 bcmos_errno err;
2240
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002241 if (direction == downstream) {
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002242 bcmolt_tm_sched_cfg tm_sched_cfg;
2243 bcmolt_tm_sched_key tm_sched_key = {.id = 1};
2244 tm_sched_key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002245
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002246 // bcmbal_tm_sched_owner
2247 // In downstream it is sub_term scheduler
2248 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002249
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002250 /**< The output of the tm_sched object instance */
2251 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.type, BCMOLT_TM_SCHED_OUTPUT_TYPE_TM_SCHED);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002252
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002253 // bcmbal_tm_sched_parent
2254 // The parent for the sub_term scheduler is the PON scheduler in the downstream
2255 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.tm_sched.tm_sched_id, get_default_tm_sched_id(intf_id, direction));
2256 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.tm_sched.tm_sched_param.u.priority.priority, priority);
2257 /* removed by BAL v3.0, N/A - No direct attachment point of type ONU, same functionality may
2258 be achieved using the' virtual' type of attachment.
2259 tm_sched_owner.u.sub_term.intf_id = intf_id;
2260 tm_sched_owner.u.sub_term.sub_term_id = onu_id;
2261 */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002262
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002263 // bcmbal_tm_sched_type
2264 // set the deafult policy to strict priority
2265 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, sched_type, BCMOLT_TM_SCHED_TYPE_SP);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002266
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002267 // num_priorities: Max number of strict priority scheduling elements
2268 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, num_priorities, 8);
Jason Huangd33b4d82019-05-15 18:22:57 +08002269
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002270 // bcmbal_tm_shaping
2271 if (tf_sh_info.cir() >= 0 && tf_sh_info.pir() > 0) {
2272 uint32_t cir = tf_sh_info.cir();
2273 uint32_t pir = tf_sh_info.pir();
2274 uint32_t burst = tf_sh_info.pbs();
Jason Huangb6843dc2019-07-22 17:46:06 +08002275 OPENOLT_LOG(INFO, openolt_log_id, "applying traffic shaping in DL cir=%u, pir=%u, burst=%u\n",
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002276 cir, pir, burst);
2277 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, pir);
2278 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, burst);
2279 // FIXME: Setting CIR, results in BAL throwing error 'tm_sched minimum rate is not supported yet'
2280 //BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.cir, cir);
2281 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.pir, pir);
2282 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.burst, burst);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002283 }
2284
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002285 err = bcmolt_cfg_set(dev_id, &tm_sched_cfg.hdr);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002286 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08002287 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create downstream subscriber scheduler, id %d, \
2288intf_id %d, onu_id %d, uni_id %d, port_no %u\n", tm_sched_key.id, intf_id, onu_id, \
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002289 uni_id, port_no);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002290 return err;
2291 }
Jason Huangb6843dc2019-07-22 17:46:06 +08002292 OPENOLT_LOG(INFO, openolt_log_id, "Create downstream subscriber sched, id %d, intf_id %d, onu_id %d, \
2293uni_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 -08002294
2295 } else { //upstream
Jason Huangd33b4d82019-05-15 18:22:57 +08002296 bcmolt_itupon_alloc_cfg cfg;
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002297 bcmolt_itupon_alloc_key key = { };
Jason Huangd33b4d82019-05-15 18:22:57 +08002298 key.pon_ni = intf_id;
2299 key.alloc_id = alloc_id;
Jason Huangb6843dc2019-07-22 17:46:06 +08002300 int bw_granularity = (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY;
2301 int pir_bw = tf_sh_info.pir();
2302 int cir_bw = tf_sh_info.cir();
2303 //offset to match bandwidth granularity
2304 int offset_pir_bw = pir_bw%bw_granularity;
2305 int offset_cir_bw = cir_bw%bw_granularity;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002306
Jason Huangb6843dc2019-07-22 17:46:06 +08002307 pir_bw = pir_bw - offset_pir_bw;
2308 cir_bw = cir_bw - offset_cir_bw;
2309
2310 BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
2311
2312 switch (additional_bw) {
2313 case 2: //AdditionalBW_BestEffort
2314 if (pir_bw == 0) {
2315 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
2316%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
2317 } else if (pir_bw < cir_bw) {
2318 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2319bandwidth (%d)\n", pir_bw, cir_bw);
2320 return BCM_ERR_PARM;
2321 } else if (pir_bw == cir_bw) {
2322 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
2323bandwidth for additional bandwidth eligibility of type best_effort\n");
2324 return BCM_ERR_PARM;
2325 }
2326 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_BEST_EFFORT);
2327 break;
2328 case 1: //AdditionalBW_NA
2329 if (pir_bw == 0) {
2330 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
2331%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
2332 return BCM_ERR_PARM;
2333 } else if (cir_bw == 0) {
2334 OPENOLT_LOG(ERROR, openolt_log_id, "Guaranteed bandwidth must be greater than zero for \
2335additional bandwidth eligibility of type Non-Assured (NA)\n");
2336 return BCM_ERR_PARM;
2337 } else if (pir_bw < cir_bw) {
2338 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2339bandwidth (%d)\n", pir_bw, cir_bw);
2340 return BCM_ERR_PARM;
2341 } else if (pir_bw == cir_bw) {
2342 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
2343bandwidth for additional bandwidth eligibility of type non_assured\n");
2344 return BCM_ERR_PARM;
2345 }
2346 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NON_ASSURED);
2347 break;
2348 case 0: //AdditionalBW_None
2349 if (pir_bw == 0) {
2350 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
235116000 bytes/sec\n");
2352 return BCM_ERR_PARM;
2353 } else if (cir_bw == 0) {
2354 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
2355for additional bandwidth eligibility of type None\n");
2356 return BCM_ERR_PARM;
2357 } else if (pir_bw > cir_bw) {
2358 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
2359for additional bandwidth eligibility of type None\n");
2360 OPENOLT_LOG(ERROR, openolt_log_id, "set Maximum bandwidth (%d) to Guaranteed \
2361bandwidth in None eligibility\n", pir_bw);
2362 cir_bw = pir_bw;
2363 } else if (pir_bw < cir_bw) {
2364 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2365bandwidth (%d)\n", pir_bw, cir_bw);
2366 OPENOLT_LOG(ERROR, openolt_log_id, "set Maximum bandwidth (%d) to Guaranteed \
2367bandwidth in None eligibility\n", pir_bw);
2368 cir_bw = pir_bw;
2369 }
2370 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NONE);
2371 break;
2372 default:
2373 return BCM_ERR_PARM;
2374 }
2375 /* CBR Real Time Bandwidth which require shaping of the bandwidth allocations
Jason Huangd33b4d82019-05-15 18:22:57 +08002376 in a fine granularity. */
2377 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_bw, 0);
2378 /* Fixed Bandwidth with no critical requirement of shaping */
2379 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_bw, 0);
2380 /* Dynamic bandwidth which the OLT is committed to allocate upon demand */
Jason Huangb6843dc2019-07-22 17:46:06 +08002381 BCMOLT_MSG_FIELD_SET(&cfg, sla.guaranteed_bw, cir_bw);
Jason Huangd33b4d82019-05-15 18:22:57 +08002382 /* Maximum allocated bandwidth allowed for this alloc ID */
Jason Huangb6843dc2019-07-22 17:46:06 +08002383 BCMOLT_MSG_FIELD_SET(&cfg, sla.maximum_bw, pir_bw);
Jason Huangd33b4d82019-05-15 18:22:57 +08002384 BCMOLT_MSG_FIELD_SET(&cfg, sla.alloc_type, BCMOLT_ALLOC_TYPE_NSR);
2385 /* Set to True for AllocID with CBR RT Bandwidth that requires compensation
2386 for skipped allocations during quiet window */
2387 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_compensation, BCMOS_FALSE);
2388 /**< Allocation Profile index for CBR non-RT Bandwidth */
2389 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_ap_index, 0);
2390 /**< Allocation Profile index for CBR RT Bandwidth */
2391 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_ap_index, 0);
2392 /**< Alloc ID Weight used in case of Extended DBA mode */
2393 BCMOLT_MSG_FIELD_SET(&cfg, sla.weight, 0);
2394 /**< Alloc ID Priority used in case of Extended DBA mode */
2395 BCMOLT_MSG_FIELD_SET(&cfg, sla.priority, 0);
Jason Huangb6843dc2019-07-22 17:46:06 +08002396 BCMOLT_MSG_FIELD_SET(&cfg, onu_id, onu_id);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002397
Jason Huangb6843dc2019-07-22 17:46:06 +08002398 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002399 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08002400 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d,\
2401port_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 -08002402 return err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002403 }
Jason Huangb6843dc2019-07-22 17:46:06 +08002404 OPENOLT_LOG(INFO, openolt_log_id, "Create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d, port_no %u, \
2405alloc_id %d\n", intf_id,onu_id,uni_id,port_no,alloc_id);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002406 }
2407
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002408 return BCM_ERR_OK;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002409}
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002410
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002411Status CreateTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
2412 uint32_t intf_id = traffic_scheds->intf_id();
2413 uint32_t onu_id = traffic_scheds->onu_id();
2414 uint32_t uni_id = traffic_scheds->uni_id();
2415 uint32_t port_no = traffic_scheds->port_no();
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002416 std::string direction;
2417 unsigned int alloc_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002418 tech_profile::SchedulerConfig sched_config;
2419 tech_profile::AdditionalBW additional_bw;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002420 uint32_t priority;
2421 uint32_t weight;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002422 tech_profile::SchedulingPolicy sched_policy;
2423 tech_profile::TrafficShapingInfo traffic_shaping_info;
2424 bcmos_errno err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002425
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002426 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
2427 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002428
2429 direction = GetDirection(traffic_sched.direction());
2430 if (direction.compare("direction-not-supported") == 0)
2431 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2432
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002433 alloc_id = traffic_sched.alloc_id();
2434 sched_config = traffic_sched.scheduler();
2435 additional_bw = sched_config.additional_bw();
2436 priority = sched_config.priority();
2437 weight = sched_config.weight();
2438 sched_policy = sched_config.sched_policy();
2439 traffic_shaping_info = traffic_sched.traffic_shaping_info();
2440 err = CreateSched(direction, intf_id, onu_id, uni_id, port_no, alloc_id, additional_bw, weight, priority,
2441 sched_policy, traffic_shaping_info);
2442 if (err) {
2443 return bcm_to_grpc_err(err, "Failed to create scheduler");
2444 }
Girish Gowdru1cdf6ce2018-08-27 02:43:02 -07002445 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002446 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002447}
Jonathan Davis70c21812018-07-19 15:32:10 -04002448
Jason Huangb6843dc2019-07-22 17:46:06 +08002449bcmos_errno RemoveSched(int intf_id, int onu_id, int uni_id, int alloc_id, std::string direction) {
Jonathan Davis70c21812018-07-19 15:32:10 -04002450
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002451 bcmos_errno err;
Jason Huangb6843dc2019-07-22 17:46:06 +08002452
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002453 if (direction == upstream) {
Jason Huangd33b4d82019-05-15 18:22:57 +08002454 bcmolt_itupon_alloc_cfg cfg;
2455 bcmolt_itupon_alloc_key key = { };
2456 key.pon_ni = intf_id;
Jason Huangb6843dc2019-07-22 17:46:06 +08002457 key.alloc_id = alloc_id;
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002458
Jason Huangd33b4d82019-05-15 18:22:57 +08002459 BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
Jason Huangb6843dc2019-07-22 17:46:06 +08002460 err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
Jason Huangd33b4d82019-05-15 18:22:57 +08002461 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08002462 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove scheduler sched, direction = %s, intf_id %d, alloc_id %d, err %d\n", \
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002463 direction.c_str(), intf_id, alloc_id, err);
Jason Huangd33b4d82019-05-15 18:22:57 +08002464 return err;
2465 }
Jason Huangb6843dc2019-07-22 17:46:06 +08002466 OPENOLT_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, intf_id %d, alloc_id %d\n", \
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002467 direction.c_str(), intf_id, alloc_id);
Jason Huangd33b4d82019-05-15 18:22:57 +08002468 } else if (direction == downstream) {
2469 bcmolt_tm_sched_cfg cfg;
2470 bcmolt_tm_sched_key key = { };
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002471
Jason Huangd33b4d82019-05-15 18:22:57 +08002472 if (is_tm_sched_id_present(intf_id, onu_id, uni_id, direction)) {
2473 key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2474 } else {
Jason Huangb6843dc2019-07-22 17:46:06 +08002475 OPENOLT_LOG(INFO, openolt_log_id, "schduler not present in %s, err %d\n", direction.c_str(), err);
Jason Huangd33b4d82019-05-15 18:22:57 +08002476 return BCM_ERR_OK;
2477 }
2478 BCMOLT_CFG_INIT(&cfg, tm_sched, key);
2479 err = bcmolt_cfg_clear(dev_id, &(cfg.hdr));
2480 if (err) {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002481 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove scheduler, direction = %s, id %d, intf_id %d, onu_id %d\n", \
2482 direction.c_str(), key.id, intf_id, onu_id);
Jason Huangd33b4d82019-05-15 18:22:57 +08002483 return err;
2484 }
Jason Huangb6843dc2019-07-22 17:46:06 +08002485 OPENOLT_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, id %d, intf_id %d, onu_id %d\n", \
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002486 direction.c_str(), key.id, intf_id, onu_id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002487 }
2488
2489 free_tm_sched_id(intf_id, onu_id, uni_id, direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002490 return BCM_ERR_OK;
2491}
2492
2493Status RemoveTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
2494 uint32_t intf_id = traffic_scheds->intf_id();
2495 uint32_t onu_id = traffic_scheds->onu_id();
2496 uint32_t uni_id = traffic_scheds->uni_id();
2497 std::string direction;
2498 bcmos_errno err;
2499
2500 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
2501 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002502
2503 direction = GetDirection(traffic_sched.direction());
2504 if (direction.compare("direction-not-supported") == 0)
2505 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2506
Jason Huangb6843dc2019-07-22 17:46:06 +08002507 int alloc_id = traffic_sched.alloc_id();
2508 err = RemoveSched(intf_id, onu_id, uni_id, alloc_id, direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002509 if (err) {
2510 return bcm_to_grpc_err(err, "error-removing-traffic-scheduler");
2511 }
2512 }
2513 return Status::OK;
2514}
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002515
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002516bcmos_errno CreateTrafficQueueMappingProfile(uint32_t sched_id, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, \
2517 std::string direction, std::vector<uint32_t> tmq_map_profile) {
2518 bcmos_errno err;
2519 bcmolt_tm_qmp_cfg tm_qmp_cfg;
2520 bcmolt_tm_qmp_key tm_qmp_key;
2521 bcmolt_arr_u8_8 pbits_to_tmq_id = {0};
2522
2523 int tm_qmp_id = get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id, tmq_map_profile);
2524 if (tm_qmp_id == -1) {
2525 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create tm queue mapping profile. Max allowed profile count is 16.\n");
2526 }
2527
2528 tm_qmp_key.id = tm_qmp_id;
2529 for (uint32_t priority=0; priority<tmq_map_profile.size(); priority++) {
2530 pbits_to_tmq_id.arr[priority] = tmq_map_profile[priority];
2531 }
2532
2533 BCMOLT_CFG_INIT(&tm_qmp_cfg, tm_qmp, tm_qmp_key);
2534 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, type, BCMOLT_TM_QMP_TYPE_PBITS);
2535 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, pbits_to_tmq_id, pbits_to_tmq_id);
2536 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, ref_count, 0);
2537 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, state, BCMOLT_CONFIG_STATE_CONFIGURED);
2538
2539 err = bcmolt_cfg_set(dev_id, &tm_qmp_cfg.hdr);
2540 if (err) {
2541 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create tm queue mapping profile, id %d\n", \
2542 tm_qmp_key.id);
2543 return err;
2544 }
2545
2546 OPENOLT_LOG(INFO, openolt_log_id, "Create tm queue mapping profile success, id %d\n", \
2547 tm_qmp_key.id);
2548 return BCM_ERR_OK;
2549}
2550
2551bcmos_errno RemoveTrafficQueueMappingProfile(uint32_t tm_qmp_id) {
2552 bcmos_errno err;
2553 bcmolt_tm_qmp_cfg tm_qmp_cfg;
2554 bcmolt_tm_qmp_key tm_qmp_key;
2555 tm_qmp_key.id = tm_qmp_id;
2556
2557 BCMOLT_CFG_INIT(&tm_qmp_cfg, tm_qmp, tm_qmp_key);
2558 err = bcmolt_cfg_clear(dev_id, &tm_qmp_cfg.hdr);
2559 if (err) {
2560 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove tm queue mapping profile, id %d\n", \
2561 tm_qmp_key.id);
2562 return err;
2563 }
2564
2565 OPENOLT_LOG(INFO, openolt_log_id, "Remove tm queue mapping profile success, id %d\n", \
2566 tm_qmp_key.id);
2567 return BCM_ERR_OK;
2568}
2569
2570bcmos_errno CreateDefaultQueue(uint32_t intf_id, const std::string direction) {
2571 bcmos_errno err;
2572
2573 /* Create 4 Queues on given PON/NNI scheduler */
2574 for (int queue_id = 0; queue_id < 4; queue_id++) {
2575 bcmolt_tm_queue_cfg tm_queue_cfg;
2576 bcmolt_tm_queue_key tm_queue_key = {};
2577 tm_queue_key.sched_id = get_default_tm_sched_id(intf_id, direction);
2578 tm_queue_key.id = queue_id;
2579 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE)
2580 tm_queue_key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2581 else
2582 tm_queue_key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2583
2584 BCMOLT_CFG_INIT(&tm_queue_cfg, tm_queue, tm_queue_key);
2585 BCMOLT_MSG_FIELD_SET(&tm_queue_cfg, tm_sched_param.type, BCMOLT_TM_SCHED_PARAM_TYPE_PRIORITY);
2586 BCMOLT_MSG_FIELD_SET(&tm_queue_cfg, tm_sched_param.u.priority.priority, queue_id);
2587
2588 err = bcmolt_cfg_set(dev_id, &tm_queue_cfg.hdr);
2589 if (err) {
2590 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create %s tm queue, id %d, sched_id %d, tm_q_set_id %d\n", \
2591 direction.c_str(), tm_queue_key.id, tm_queue_key.sched_id, tm_queue_key.tm_q_set_id);
2592 return err;
2593 }
2594
2595 OPENOLT_LOG(INFO, openolt_log_id, "Create %s tm_queue success, id %d, sched_id %d, tm_q_set_id %d\n", \
2596 direction.c_str(), tm_queue_key.id, tm_queue_key.sched_id, tm_queue_key.tm_q_set_id);
2597 }
2598 return BCM_ERR_OK;
2599}
2600
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002601bcmos_errno CreateQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
2602 uint32_t gemport_id) {
2603 bcmos_errno err;
Jason Huangd33b4d82019-05-15 18:22:57 +08002604 bcmolt_tm_queue_cfg cfg;
2605 bcmolt_tm_queue_key key = { };
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002606 OPENOLT_LOG(INFO, openolt_log_id, "creating %s queue. access_intf_id = %d, onu_id = %d, uni_id = %d \
2607gemport_id = %d\n", direction.c_str(), access_intf_id, onu_id, uni_id, gemport_id);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002608
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002609 key.sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2610 get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
2611
2612 if (priority > 7) {
2613 return BCM_ERR_RANGE;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002614 }
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002615
2616 /* FIXME: The upstream queues have to be created once only.
2617 The upstream queues on the NNI scheduler are shared by all subscribers.
2618 When the first scheduler comes in, the queues get created, and are re-used by all others.
2619 Also, these queues should be present until the last subscriber exits the system.
2620 One solution is to have these queues always, i.e., create it as soon as OLT is enabled.
2621
2622 There is one queue per gem port and Queue ID is fetched based on priority_q configuration
2623 for each GEM in TECH PROFILE */
2624 key.id = queue_id_list[priority];
2625
Jason Huangb6843dc2019-07-22 17:46:06 +08002626 OPENOLT_LOG(INFO, openolt_log_id, "queue assigned queue_id = %d\n", key.id);
Girish Gowdru36501552019-05-01 23:47:58 -07002627
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002628 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE)
2629 key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2630 else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE)
2631 key.tm_q_set_id = get_tm_qmp_id(key.sched_id, access_intf_id, onu_id, uni_id);
2632 else
2633 key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2634
Jason Huangd33b4d82019-05-15 18:22:57 +08002635 BCMOLT_CFG_INIT(&cfg, tm_queue, key);
2636 BCMOLT_MSG_FIELD_SET(&cfg, tm_sched_param.u.priority.priority, priority);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002637
Jason Huangd33b4d82019-05-15 18:22:57 +08002638 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002639 if (err) {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002640 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create subscriber tm queue, direction = %s, id %d, \
2641sched_id %d, tm_q_set_id %d, intf_id %d, onu_id %d, uni_id %d, err %d\n", \
2642 direction.c_str(), key.id, key.sched_id, key.tm_q_set_id, access_intf_id, onu_id, uni_id, err);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002643 return err;
2644 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06002645
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002646 OPENOLT_LOG(INFO, openolt_log_id, "Created tm_queue, direction %s, id %d, sched_id %d, tm_q_set_id %d, \
2647intf_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 -08002648 return BCM_ERR_OK;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002649}
2650
2651Status CreateTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
2652 uint32_t intf_id = traffic_queues->intf_id();
2653 uint32_t onu_id = traffic_queues->onu_id();
2654 uint32_t uni_id = traffic_queues->uni_id();
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002655 uint32_t sched_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002656 std::string direction;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002657 bcmos_errno err;
2658
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002659 qos_type = (traffic_queues->traffic_queues_size() > 1) ? \
2660 BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
2661
2662 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2663 uint32_t queues_priority_q[traffic_queues->traffic_queues_size()] = {0};
2664 std::string queues_pbit_map[traffic_queues->traffic_queues_size()];
2665 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2666 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
2667
2668 direction = GetDirection(traffic_queue.direction());
2669 if (direction.compare("direction-not-supported") == 0)
2670 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2671
2672 queues_priority_q[i] = traffic_queue.priority();
2673 queues_pbit_map[i] = traffic_queue.pbit_map();
2674 }
2675
2676 std::vector<uint32_t> tmq_map_profile(8, 0);
2677 tmq_map_profile = get_tmq_map_profile(get_valid_queues_pbit_map(queues_pbit_map, COUNT_OF(queues_pbit_map)), \
2678 queues_priority_q, COUNT_OF(queues_priority_q));
2679 sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2680 get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2681
2682 int tm_qmp_id = get_tm_qmp_id(tmq_map_profile);
2683 if (tm_qmp_id == -1) {
2684 CreateTrafficQueueMappingProfile(sched_id, intf_id, onu_id, uni_id, direction, tmq_map_profile);
2685 } else if (tm_qmp_id != -1 && get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id) == -1) {
2686 OPENOLT_LOG(INFO, openolt_log_id, "tm queue mapping profile present already with id %d\n", tm_qmp_id);
2687 update_sched_qmp_id_map(sched_id, intf_id, onu_id, uni_id, tm_qmp_id);
2688 }
2689 }
2690
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002691 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2692 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002693
2694 direction = GetDirection(traffic_queue.direction());
2695 if (direction.compare("direction-not-supported") == 0)
2696 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2697
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002698 err = CreateQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002699
Girish Gowdru36501552019-05-01 23:47:58 -07002700 // If the queue exists already, lets not return failure and break the loop.
2701 if (err && err != BCM_ERR_ALREADY) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002702 return bcm_to_grpc_err(err, "Failed to create queue");
2703 }
2704 }
2705 return Status::OK;
2706}
2707
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002708bcmos_errno RemoveQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
2709 uint32_t gemport_id) {
Jason Huangd33b4d82019-05-15 18:22:57 +08002710 bcmolt_tm_queue_cfg cfg;
2711 bcmolt_tm_queue_key key = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002712 bcmos_errno err;
2713
2714 if (direction == downstream) {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002715 if (is_tm_sched_id_present(access_intf_id, onu_id, uni_id, direction)) {
Jason Huangd33b4d82019-05-15 18:22:57 +08002716 key.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002717 key.id = queue_id_list[priority];
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002718 } else {
Jason Huangb6843dc2019-07-22 17:46:06 +08002719 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 -08002720 return BCM_ERR_OK;
2721 }
2722 } else {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002723 /* In the upstream we use pre-created queues on the NNI scheduler that are used by all subscribers.
2724 They should not be removed. So, lets return OK. */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002725 return BCM_ERR_OK;
2726 }
2727
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002728 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE)
2729 key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2730 else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE)
2731 key.tm_q_set_id = get_tm_qmp_id(key.sched_id, access_intf_id, onu_id, uni_id);
2732 else
2733 key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2734
Jason Huangd33b4d82019-05-15 18:22:57 +08002735 BCMOLT_CFG_INIT(&cfg, tm_queue, key);
Jason Huangd33b4d82019-05-15 18:22:57 +08002736 err = bcmolt_cfg_clear(dev_id, &(cfg.hdr));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002737 if (err) {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002738 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove queue, direction = %s, id %d, sched_id %d, \
2739tm_q_set_id %d, intf_id %d, onu_id %d, uni_id %d\n",
2740 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 -08002741 return err;
2742 }
2743
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002744 OPENOLT_LOG(INFO, openolt_log_id, "Removed tm_queue, direction %s, id %d, sched_id %d, tm_q_set_id %d, \
2745intf_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 -08002746
2747 return BCM_ERR_OK;
2748}
2749
2750Status RemoveTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
2751 uint32_t intf_id = traffic_queues->intf_id();
2752 uint32_t onu_id = traffic_queues->onu_id();
2753 uint32_t uni_id = traffic_queues->uni_id();
2754 uint32_t port_no = traffic_queues->port_no();
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002755 uint32_t sched_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002756 std::string direction;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002757 bcmos_errno err;
2758
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002759 qos_type = (traffic_queues->traffic_queues_size() > 1) ? \
2760 BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
2761
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002762 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2763 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002764
2765 direction = GetDirection(traffic_queue.direction());
2766 if (direction.compare("direction-not-supported") == 0)
2767 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2768
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002769 err = RemoveQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
2770 if (err) {
2771 return bcm_to_grpc_err(err, "Failed to remove queue");
2772 }
Jonathan Davis70c21812018-07-19 15:32:10 -04002773 }
2774
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002775 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))) {
2776 sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2777 get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2778
2779 int tm_qmp_id = get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id);
2780 if (free_tm_qmp_id(sched_id, intf_id, onu_id, uni_id, tm_qmp_id)) {
2781 RemoveTrafficQueueMappingProfile(tm_qmp_id);
2782 }
2783 }
Jonathan Davis70c21812018-07-19 15:32:10 -04002784 return Status::OK;
Jonathan Davis70c21812018-07-19 15:32:10 -04002785}