blob: 9f30bde9917dcaaefb154349d86283bf4a63f9c4 [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;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000744
Shad Ansariedef2132018-08-10 22:14:50 +0000745 if (!state.is_activated()) {
Shad Ansari627b5782018-08-13 22:49:32 +0000746
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500747 vendor_init();
Jason Huangd33b4d82019-05-15 18:22:57 +0800748 /* Initialize host subsystem */
749 err = bcmolt_host_init(&init_parms);
750 if (BCM_ERR_OK != err) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800751 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to init OLT\n");
Jason Huangd33b4d82019-05-15 18:22:57 +0800752 return bcm_to_grpc_err(err, "Failed to init OLT");
753 }
Craig Lutgen967a1d02018-11-27 10:41:51 -0600754
Girish Gowdrae538dfd2019-09-30 11:07:30 +0530755 bcmcli_session_parm mon_session_parm;
Jason Huangd33b4d82019-05-15 18:22:57 +0800756 /* Create CLI session */
757 memset(&mon_session_parm, 0, sizeof(mon_session_parm));
758 mon_session_parm.get_prompt = openolt_cli_get_prompt_cb;
759 mon_session_parm.access_right = BCMCLI_ACCESS_ADMIN;
760 bcmos_errno rc = bcmcli_session_open(&mon_session_parm, &current_session);
761 BUG_ON(rc != BCM_ERR_OK);
762
763 /* API CLI */
764 bcm_openolt_api_cli_init(NULL, current_session);
765
766 /* Add quit command */
767 BCMCLI_MAKE_CMD_NOPARM(NULL, "quit", "Quit", bcm_cli_quit);
768
769 err = bcmolt_apiend_cli_init();
770 if (BCM_ERR_OK != err) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800771 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to add apiend init\n");
Jason Huangd33b4d82019-05-15 18:22:57 +0800772 return bcm_to_grpc_err(err, "Failed to add apiend init");
773 }
774
775 bcmos_fastlock_init(&data_lock, 0);
Jason Huangb6843dc2019-07-22 17:46:06 +0800776 OPENOLT_LOG(INFO, openolt_log_id, "Enable OLT - %s-%s\n", VENDOR_ID, MODEL_ID);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500777
Jason Huangd33b4d82019-05-15 18:22:57 +0800778 if (bcmolt_api_conn_mgr_is_connected(dev_id))
779 {
780 Status status = SubscribeIndication();
781 if (!status.ok()) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800782 OPENOLT_LOG(ERROR, openolt_log_id, "SubscribeIndication failed - %s : %s\n",
Jason Huangd33b4d82019-05-15 18:22:57 +0800783 grpc_status_code_to_string(status.error_code()).c_str(),
784 status.error_message().c_str());
Jason Huangd33b4d82019-05-15 18:22:57 +0800785 return status;
786 }
787 bcmos_errno err;
788 bcmolt_odid dev;
Jason Huangb6843dc2019-07-22 17:46:06 +0800789 OPENOLT_LOG(INFO, openolt_log_id, "Enabling PON %d Devices ... \n", BCM_MAX_DEVS_PER_LINE_CARD);
Jason Huangd33b4d82019-05-15 18:22:57 +0800790 for (dev = 0; dev < BCM_MAX_DEVS_PER_LINE_CARD; dev++) {
791 bcmolt_device_cfg dev_cfg = { };
792 bcmolt_device_key dev_key = { };
793 dev_key.device_id = dev;
794 BCMOLT_CFG_INIT(&dev_cfg, device, dev_key);
795 BCMOLT_MSG_FIELD_GET(&dev_cfg, system_mode);
796 err = bcmolt_cfg_get(dev_id, &dev_cfg.hdr);
797 if (err == BCM_ERR_NOT_CONNECTED) {
798 bcmolt_device_key key = {.device_id = dev};
799 bcmolt_device_connect oper;
Jason Huangd33b4d82019-05-15 18:22:57 +0800800 BCMOLT_OPER_INIT(&oper, device, connect, key);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +0800801 if (MODEL_ID == "asfvolt16") {
802 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mode, BCMOLT_INNI_MODE_ALL_10_G_XFI);
803 BCMOLT_MSG_FIELD_SET (&oper, system_mode, BCMOLT_SYSTEM_MODE_XGS__2_X);
804 } else if (MODEL_ID == "asgvolt64") {
805 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mode, BCMOLT_INNI_MODE_ALL_10_G_XFI);
806 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mux, BCMOLT_INNI_MUX_FOUR_TO_ONE);
807 BCMOLT_MSG_FIELD_SET (&oper, system_mode, BCMOLT_SYSTEM_MODE_GPON__16_X);
808 }
Jason Huangd33b4d82019-05-15 18:22:57 +0800809 err = bcmolt_oper_submit(dev_id, &oper.hdr);
Girish Gowdrae538dfd2019-09-30 11:07:30 +0530810 if (err) {
811 OPENOLT_LOG(ERROR, openolt_log_id, "Enable PON device %d failed, err %d\n", dev, err);
812 }
Jason Huangd33b4d82019-05-15 18:22:57 +0800813 bcmos_usleep(200000);
814 }
Jason Huangb1fad572019-05-28 19:02:30 +0800815 else {
Jason Huangb6843dc2019-07-22 17:46:06 +0800816 OPENOLT_LOG(WARNING, openolt_log_id, "PON deivce %d already connected\n", dev);
Jason Huangb1fad572019-05-28 19:02:30 +0800817 state.activate();
818 }
Jason Huangd33b4d82019-05-15 18:22:57 +0800819 }
820 init_stats();
Shad Ansari627b5782018-08-13 22:49:32 +0000821 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000822 }
Shad Ansariedef2132018-08-10 22:14:50 +0000823
Jason Huangd33b4d82019-05-15 18:22:57 +0800824 /* Start CLI */
Jason Huangb6843dc2019-07-22 17:46:06 +0800825 OPENOLT_LOG(INFO, def_log_id, "Starting CLI\n");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400826 //If already enabled, generate an extra indication ????
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000827 return Status::OK;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400828}
829
830Status Disable_() {
831 // bcmbal_access_terminal_cfg acc_term_obj;
832 // bcmbal_access_terminal_key key = { };
833 //
834 // if (state::is_activated) {
835 // std::cout << "Disable OLT" << std::endl;
836 // key.access_term_id = DEFAULT_ATERM_ID;
837 // BCMBAL_CFG_INIT(&acc_term_obj, access_terminal, key);
838 // BCMBAL_CFG_PROP_SET(&acc_term_obj, access_terminal, admin_state, BCMBAL_STATE_DOWN);
839 // bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(acc_term_obj.hdr));
840 // if (err) {
841 // std::cout << "ERROR: Failed to disable OLT" << std::endl;
842 // return bcm_to_grpc_err(err, "Failed to disable OLT");
843 // }
844 // }
845 // //If already disabled, generate an extra indication ????
846 // return Status::OK;
847 //This fails with Operation Not Supported, bug ???
848
849 //TEMPORARY WORK AROUND
Jason Huangb6843dc2019-07-22 17:46:06 +0800850 Status status = SetStateUplinkIf_(nni_intf_id, false);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400851 if (status.ok()) {
Shad Ansariedef2132018-08-10 22:14:50 +0000852 state.deactivate();
Jason Huangb6843dc2019-07-22 17:46:06 +0800853 OPENOLT_LOG(INFO, openolt_log_id, "Disable OLT, add an extra indication\n");
Jason Huang88795222019-06-13 19:28:44 +0800854 pushOltOperInd(nni_intf_id, "nni", "up");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400855 }
856 return status;
857
858}
859
860Status Reenable_() {
Jason Huangb6843dc2019-07-22 17:46:06 +0800861 Status status = SetStateUplinkIf_(0, true);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400862 if (status.ok()) {
Shad Ansariedef2132018-08-10 22:14:50 +0000863 state.activate();
Jason Huangb6843dc2019-07-22 17:46:06 +0800864 OPENOLT_LOG(INFO, openolt_log_id, "Reenable OLT, add an extra indication\n");
Jason Huang88795222019-06-13 19:28:44 +0800865 pushOltOperInd(0, "nni", "up");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400866 }
867 return status;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000868}
869
Jason Huangd33b4d82019-05-15 18:22:57 +0800870bcmos_errno get_pon_interface_status(bcmolt_interface pon_ni, bcmolt_interface_state *state) {
871 bcmos_errno err;
872 bcmolt_pon_interface_key pon_key;
873 bcmolt_pon_interface_cfg pon_cfg;
874 pon_key.pon_ni = pon_ni;
875
876 BCMOLT_CFG_INIT(&pon_cfg, pon_interface, pon_key);
877 BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, state);
878 BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, itu);
879 err = bcmolt_cfg_get(dev_id, &pon_cfg.hdr);
880 *state = pon_cfg.data.state;
881 return err;
882}
883
Jason Huangb6843dc2019-07-22 17:46:06 +0800884inline uint64_t get_flow_status(uint16_t flow_id, uint16_t flow_type, uint16_t data_id) {
Jason Huang439d24f2019-06-26 03:25:05 +0800885 bcmos_errno err;
886 bcmolt_flow_key flow_key;
887 bcmolt_flow_cfg flow_cfg;
888
889 flow_key.flow_id = flow_id;
Jason Huangb6843dc2019-07-22 17:46:06 +0800890 flow_key.flow_type = (bcmolt_flow_type)flow_type;
Jason Huang439d24f2019-06-26 03:25:05 +0800891
892 BCMOLT_CFG_INIT(&flow_cfg, flow, flow_key);
893
894 switch (data_id) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800895 case ONU_ID: //onu_id
896 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, onu_id);
Jason Huang439d24f2019-06-26 03:25:05 +0800897 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
898 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800899 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get onu_id\n");
Jason Huang439d24f2019-06-26 03:25:05 +0800900 return err;
901 }
Jason Huangb6843dc2019-07-22 17:46:06 +0800902 return flow_cfg.data.onu_id;
903 case FLOW_TYPE:
Jason Huang439d24f2019-06-26 03:25:05 +0800904 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
905 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800906 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get flow_type\n");
Jason Huang439d24f2019-06-26 03:25:05 +0800907 return err;
908 }
Jason Huangb6843dc2019-07-22 17:46:06 +0800909 return flow_cfg.key.flow_type;
Jason Huang439d24f2019-06-26 03:25:05 +0800910 case SVC_PORT_ID: //svc_port_id
911 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, svc_port_id);
912 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
913 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800914 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get svc_port_id\n");
Jason Huang439d24f2019-06-26 03:25:05 +0800915 return err;
916 }
917 return flow_cfg.data.svc_port_id;
Jason Huangb6843dc2019-07-22 17:46:06 +0800918 case PRIORITY:
919 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, priority);
920 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
921 if (err) {
922 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get priority\n");
923 return err;
924 }
925 return flow_cfg.data.priority;
Jason Huang439d24f2019-06-26 03:25:05 +0800926 case COOKIE: //cookie
927 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, cookie);
928 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
929 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +0800930 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get cookie\n");
Jason Huang439d24f2019-06-26 03:25:05 +0800931 return err;
932 }
933 return flow_cfg.data.cookie;
Jason Huangb6843dc2019-07-22 17:46:06 +0800934 case INGRESS_INTF_TYPE: //ingress intf_type
935 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, ingress_intf);
936 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
937 if (err) {
938 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get ingress intf_type\n");
939 return err;
940 }
941 return flow_cfg.data.ingress_intf.intf_type;
942 case EGRESS_INTF_TYPE: //egress intf_type
943 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_intf);
944 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
945 if (err) {
946 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress intf_type\n");
947 return err;
948 }
949 return flow_cfg.data.egress_intf.intf_type;
950 case INGRESS_INTF_ID: //ingress intf_id
951 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, ingress_intf);
952 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
953 if (err) {
954 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get ingress intf_id\n");
955 return err;
956 }
957 return flow_cfg.data.ingress_intf.intf_id;
958 case EGRESS_INTF_ID: //egress intf_id
959 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_intf);
960 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
961 if (err) {
962 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress intf_id\n");
963 return err;
964 }
965 return flow_cfg.data.egress_intf.intf_id;
966 case CLASSIFIER_O_VID:
967 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
968 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
969 if (err) {
970 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier o_vid\n");
971 return err;
972 }
973 return flow_cfg.data.classifier.o_vid;
974 case CLASSIFIER_O_PBITS:
975 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
976 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
977 if (err) {
978 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier o_pbits\n");
979 return err;
980 }
981 return flow_cfg.data.classifier.o_pbits;
982 case CLASSIFIER_I_VID:
983 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
984 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
985 if (err) {
986 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier i_vid\n");
987 return err;
988 }
989 return flow_cfg.data.classifier.i_vid;
990 case CLASSIFIER_I_PBITS:
991 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
992 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
993 if (err) {
994 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier i_pbits\n");
995 return err;
996 }
997 return flow_cfg.data.classifier.i_pbits;
998 case CLASSIFIER_ETHER_TYPE:
999 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1000 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1001 if (err) {
1002 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier ether_type\n");
1003 return err;
1004 }
1005 return flow_cfg.data.classifier.ether_type;
1006 case CLASSIFIER_IP_PROTO:
1007 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1008 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1009 if (err) {
1010 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier ip_proto\n");
1011 return err;
1012 }
1013 return flow_cfg.data.classifier.ip_proto;
1014 case CLASSIFIER_SRC_PORT:
1015 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1016 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1017 if (err) {
1018 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier src_port\n");
1019 return err;
1020 }
1021 return flow_cfg.data.classifier.src_port;
1022 case CLASSIFIER_DST_PORT:
1023 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1024 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1025 if (err) {
1026 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier dst_port\n");
1027 return err;
1028 }
1029 return flow_cfg.data.classifier.dst_port;
1030 case CLASSIFIER_PKT_TAG_TYPE:
1031 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1032 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1033 if (err) {
1034 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier pkt_tag_type\n");
1035 return err;
1036 }
1037 return flow_cfg.data.classifier.pkt_tag_type;
1038 case EGRESS_QOS_TYPE:
1039 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
1040 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1041 if (err) {
1042 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos type\n");
1043 return err;
1044 }
1045 return flow_cfg.data.egress_qos.type;
1046 case EGRESS_QOS_QUEUE_ID:
1047 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
1048 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1049 if (err) {
1050 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos queue_id\n");
1051 return err;
1052 }
1053 switch (flow_cfg.data.egress_qos.type) {
1054 case BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE:
1055 return flow_cfg.data.egress_qos.u.fixed_queue.queue_id;
1056 case BCMOLT_EGRESS_QOS_TYPE_TC_TO_QUEUE:
1057 return flow_cfg.data.egress_qos.u.tc_to_queue.tc_to_queue_id;
1058 case BCMOLT_EGRESS_QOS_TYPE_PBIT_TO_TC:
1059 return flow_cfg.data.egress_qos.u.pbit_to_tc.tc_to_queue_id;
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001060 case BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE:
1061 return flow_cfg.data.egress_qos.u.priority_to_queue.tm_q_set_id;
Jason Huangb6843dc2019-07-22 17:46:06 +08001062 case BCMOLT_EGRESS_QOS_TYPE_NONE:
1063 default:
1064 return -1;
1065 }
1066 case EGRESS_QOS_TM_SCHED_ID:
1067 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
1068 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1069 if (err) {
1070 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos tm_sched_id\n");
1071 return err;
1072 }
1073 return flow_cfg.data.egress_qos.tm_sched.id;
1074 case ACTION_CMDS_BITMASK:
1075 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1076 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1077 if (err) {
1078 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action cmds_bitmask\n");
1079 return err;
1080 }
1081 return flow_cfg.data.action.cmds_bitmask;
1082 case ACTION_O_VID:
1083 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1084 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1085 if (err) {
1086 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action o_vid\n");
1087 return err;
1088 }
1089 return flow_cfg.data.action.o_vid;
1090 case ACTION_O_PBITS:
1091 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1092 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1093 if (err) {
1094 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action o_pbits\n");
1095 return err;
1096 }
1097 return flow_cfg.data.action.o_pbits;
1098 case ACTION_I_VID:
1099 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1100 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1101 if (err) {
1102 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action i_vid\n");
1103 return err;
1104 }
1105 return flow_cfg.data.action.i_vid;
1106 case ACTION_I_PBITS:
1107 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1108 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1109 if (err) {
1110 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action i_pbits\n");
1111 return err;
1112 }
1113 return flow_cfg.data.action.i_pbits;
1114 case STATE:
1115 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, state);
1116 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1117 if (err) {
1118 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get state\n");
1119 return err;
1120 }
1121 return flow_cfg.data.state;
Jason Huang439d24f2019-06-26 03:25:05 +08001122 default:
1123 return BCM_ERR_INTERNAL;
1124 }
1125
Jason Huangb6843dc2019-07-22 17:46:06 +08001126 return err;
Jason Huang439d24f2019-06-26 03:25:05 +08001127}
1128
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001129Status EnablePonIf_(uint32_t intf_id) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001130 bcmos_errno err = BCM_ERR_OK;
Jason Huangb1fad572019-05-28 19:02:30 +08001131 bcmolt_pon_interface_cfg interface_obj;
Jason Huangd33b4d82019-05-15 18:22:57 +08001132 bcmolt_pon_interface_key intf_key = {.pon_ni = (bcmolt_interface)intf_id};
1133 bcmolt_pon_interface_set_pon_interface_state pon_interface_set_state;
1134 bcmolt_interface_state state;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001135
Jason Huangd33b4d82019-05-15 18:22:57 +08001136 err = get_pon_interface_status((bcmolt_interface)intf_id, &state);
1137 if (err == BCM_ERR_OK) {
1138 if (state == BCMOLT_INTERFACE_STATE_ACTIVE_WORKING) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001139 OPENOLT_LOG(INFO, openolt_log_id, "PON interface: %d already enabled\n", intf_id);
Jason Huangd33b4d82019-05-15 18:22:57 +08001140 return Status::OK;
1141 }
1142 }
Jason Huangb1fad572019-05-28 19:02:30 +08001143 BCMOLT_CFG_INIT(&interface_obj, pon_interface, intf_key);
Jason Huangd33b4d82019-05-15 18:22:57 +08001144 BCMOLT_OPER_INIT(&pon_interface_set_state, pon_interface, set_pon_interface_state, intf_key);
Jason Huangb1fad572019-05-28 19:02:30 +08001145 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.control, BCMOLT_CONTROL_STATE_ENABLE);
1146 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.interval, 5000);
1147 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.onu_post_discovery_mode,
1148 BCMOLT_ONU_POST_DISCOVERY_MODE_ACTIVATE);
Jason Huangb6843dc2019-07-22 17:46:06 +08001149 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.los, true);
1150 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.onu_alarms, true);
1151 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.tiwi, true);
1152 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.ack_timeout, true);
1153 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.sfi, true);
1154 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.loki, true);
Jason Huangd33b4d82019-05-15 18:22:57 +08001155 BCMOLT_FIELD_SET(&pon_interface_set_state.data, pon_interface_set_pon_interface_state_data,
1156 operation, BCMOLT_INTERFACE_OPERATION_ACTIVE_WORKING);
Jason Huangb1fad572019-05-28 19:02:30 +08001157
1158 err = bcmolt_cfg_set(dev_id, &interface_obj.hdr);
1159 if (err != BCM_ERR_OK) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001160 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 +08001161 return bcm_to_grpc_err(err, "Failed to enable discovery onu");
1162 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001163 err = bcmolt_oper_submit(dev_id, &pon_interface_set_state.hdr);
1164 if (err != BCM_ERR_OK) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001165 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to enable PON interface: %d\n", intf_id);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001166 return bcm_to_grpc_err(err, "Failed to enable PON interface");
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001167 }
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07001168 else {
Jason Huangb6843dc2019-07-22 17:46:06 +08001169 OPENOLT_LOG(INFO, openolt_log_id, "Successfully enabled PON interface: %d\n", intf_id);
1170 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for PON interface: %d\n", intf_id);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001171 CreateDefaultSched(intf_id, downstream);
1172 CreateDefaultQueue(intf_id, downstream);
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07001173 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001174
1175 return Status::OK;
1176}
1177
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001178Status ProbeDeviceCapabilities_() {
Jason Huangd33b4d82019-05-15 18:22:57 +08001179 bcmos_errno err;
1180 bcmolt_device_cfg dev_cfg = { };
1181 bcmolt_device_key dev_key = { };
1182 bcmolt_olt_cfg olt_cfg = { };
1183 bcmolt_olt_key olt_key = { };
Jason Huangd33b4d82019-05-15 18:22:57 +08001184 bcmolt_topology_map topo_map[BCM_MAX_PONS_PER_OLT] = { };
1185 bcmolt_topology topo = { };
Jason Huangb6843dc2019-07-22 17:46:06 +08001186
Jason Huangd33b4d82019-05-15 18:22:57 +08001187 topo.topology_maps.len = BCM_MAX_PONS_PER_OLT;
1188 topo.topology_maps.arr = &topo_map[0];
1189 BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
1190 BCMOLT_MSG_FIELD_GET(&olt_cfg, bal_state);
1191 BCMOLT_FIELD_SET_PRESENT(&olt_cfg.data, olt_cfg_data, topology);
1192 BCMOLT_CFG_LIST_BUF_SET(&olt_cfg, olt, topo.topology_maps.arr,
1193 sizeof(bcmolt_topology_map) * topo.topology_maps.len);
1194 err = bcmolt_cfg_get(dev_id, &olt_cfg.hdr);
1195 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001196 OPENOLT_LOG(ERROR, openolt_log_id, "cfg: Failed to query OLT\n");
Jason Huangd33b4d82019-05-15 18:22:57 +08001197 return bcm_to_grpc_err(err, "cfg: Failed to query OLT");
1198 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001199
Jason Huangd33b4d82019-05-15 18:22:57 +08001200 num_of_nni_ports = olt_cfg.data.topology.num_switch_ports;
1201 num_of_pon_ports = olt_cfg.data.topology.topology_maps.len;
1202
Jason Huangb6843dc2019-07-22 17:46:06 +08001203 OPENOLT_LOG(INFO, openolt_log_id, "OLT capabilitites, oper_state: %s\n",
Jason Huangd33b4d82019-05-15 18:22:57 +08001204 olt_cfg.data.bal_state == BCMOLT_BAL_STATE_BAL_AND_SWITCH_READY
1205 ? "up" : "down");
1206
Jason Huangb6843dc2019-07-22 17:46:06 +08001207 OPENOLT_LOG(INFO, openolt_log_id, "topology nni: %d pon: %d dev: %d\n",
Jason Huangd33b4d82019-05-15 18:22:57 +08001208 num_of_nni_ports,
1209 num_of_pon_ports,
Jason Huangb6843dc2019-07-22 17:46:06 +08001210 BCM_MAX_DEVS_PER_LINE_CARD);
Jason Huangd33b4d82019-05-15 18:22:57 +08001211
Jason Huangb6843dc2019-07-22 17:46:06 +08001212 for (int devid = 0; devid < BCM_MAX_DEVS_PER_LINE_CARD; devid++) {
1213 dev_key.device_id = devid;
1214 BCMOLT_CFG_INIT(&dev_cfg, device, dev_key);
1215 BCMOLT_MSG_FIELD_GET(&dev_cfg, firmware_sw_version);
1216 BCMOLT_MSG_FIELD_GET(&dev_cfg, chip_family);
1217 BCMOLT_MSG_FIELD_GET(&dev_cfg, system_mode);
1218 err = bcmolt_cfg_get(dev_id, &dev_cfg.hdr);
1219 if (err) {
1220 OPENOLT_LOG(ERROR, openolt_log_id, "device: Failed to query OLT\n");
1221 return bcm_to_grpc_err(err, "device: Failed to query OLT");
1222 }
1223
1224 std::string bal_version;
1225 bal_version += std::to_string(dev_cfg.data.firmware_sw_version.major)
1226 + "." + std::to_string(dev_cfg.data.firmware_sw_version.minor)
1227 + "." + std::to_string(dev_cfg.data.firmware_sw_version.revision);
1228 firmware_version = "BAL." + bal_version + "__" + firmware_version;
1229
1230 switch(dev_cfg.data.system_mode) {
1231 case 10: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*4,(devid+1)*4,"GPON"); break;
1232 case 11: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*8,(devid+1)*8,"GPON"); break;
1233 case 12: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"GPON"); break;
1234 case 13: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,"XGPON"); break;
1235 case 14: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*4,(devid+1)*4,"XGPON"); break;
1236 case 15: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*8,(devid+1)*8,"XGPON"); break;
1237 case 16: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"XGPON"); break;
1238 case 18: board_technology = "XGS-PON"; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,"XGS-PON"); break;
1239 case 19: board_technology = "XGS-PON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"XGS-PON"); break;
1240 case 20: board_technology = MIXED_TECH; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,MIXED_TECH); break;
1241 }
1242
1243 switch(dev_cfg.data.chip_family) {
1244 case BCMOLT_CHIP_FAMILY_CHIP_FAMILY_6862_X_: chip_family = "Maple"; break;
1245 case BCMOLT_CHIP_FAMILY_CHIP_FAMILY_6865_X_: chip_family = "Aspen"; break;
1246 }
1247
1248 OPENOLT_LOG(INFO, openolt_log_id, "device %d, pon: %d, version %s object model: %d, family: %s, board_technology: %s\n",
1249 devid, BCM_MAX_PONS_PER_DEV, bal_version.c_str(), BAL_API_VERSION, chip_family.c_str(), board_technology.c_str());
1250
1251 bcmos_usleep(500000);
1252 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001253
1254 return Status::OK;
1255}
Jason Huangb6843dc2019-07-22 17:46:06 +08001256#if 0
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001257Status ProbePonIfTechnology_() {
1258 // Probe maximum extent possible as configured into BAL driver to determine
1259 // which are active in the current BAL topology. And for those
1260 // that are active, determine each port's access technology, i.e. "gpon" or "xgspon".
1261 for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001262 bcmolt_pon_interface_cfg interface_obj;
1263 bcmolt_pon_interface_key interface_key;
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001264
Jason Huangd33b4d82019-05-15 18:22:57 +08001265 interface_key.pon_ni = intf_id;
1266 BCMOLT_CFG_INIT(&interface_obj, pon_interface, interface_key);
Jason Huangb6843dc2019-07-22 17:46:06 +08001267 if (board_technology == "XGS-PON")
1268 BCMOLT_MSG_FIELD_GET(&interface_obj, xgs_ngpon2_trx);
1269 else if (board_technology == "GPON")
1270 BCMOLT_MSG_FIELD_GET(&interface_obj, gpon_trx);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001271
Jason Huangd33b4d82019-05-15 18:22:57 +08001272 bcmos_errno err = bcmolt_cfg_get(dev_id, &interface_obj.hdr);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001273 if (err != BCM_ERR_OK) {
Craig Lutgenb2601f02018-10-23 13:04:31 -05001274 intf_technologies[intf_id] = UNKNOWN_TECH;
Jason Huangb6843dc2019-07-22 17:46:06 +08001275 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 -05001276 }
1277 else {
Jason Huangb1fad572019-05-28 19:02:30 +08001278 if (board_technology == "XGS-PON") {
Jason Huangd33b4d82019-05-15 18:22:57 +08001279 switch(interface_obj.data.xgpon_trx.transceiver_type) {
1280 case BCMOLT_XGPON_TRX_TYPE_LTH_7222_PC:
1281 case BCMOLT_XGPON_TRX_TYPE_WTD_RTXM266_702:
1282 case BCMOLT_XGPON_TRX_TYPE_LTH_7222_BC_PLUS:
1283 case BCMOLT_XGPON_TRX_TYPE_LTH_7226_PC:
1284 case BCMOLT_XGPON_TRX_TYPE_LTH_5302_PC:
1285 case BCMOLT_XGPON_TRX_TYPE_LTH_7226_A_PC_PLUS:
1286 case BCMOLT_XGPON_TRX_TYPE_D272RR_SSCB_DM:
Jason Huangb1fad572019-05-28 19:02:30 +08001287 intf_technologies[intf_id] = "XGS-PON";
Jason Huangd33b4d82019-05-15 18:22:57 +08001288 break;
1289 }
1290 } else if (board_technology == "GPON") {
1291 switch(interface_obj.data.gpon_trx.transceiver_type) {
1292 case BCMOLT_TRX_TYPE_SPS_43_48_H_HP_CDE_SD_2013:
1293 case BCMOLT_TRX_TYPE_LTE_3680_M:
1294 case BCMOLT_TRX_TYPE_SOURCE_PHOTONICS:
1295 case BCMOLT_TRX_TYPE_LTE_3680_P_TYPE_C_PLUS:
Jason Huangb6843dc2019-07-22 17:46:06 +08001296 case BCMOLT_TRX_TYPE_LTE_3680_P_BC:
Jason Huangd33b4d82019-05-15 18:22:57 +08001297 intf_technologies[intf_id] = "GPON";
1298 break;
1299 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001300 }
Craig Lutgenb2601f02018-10-23 13:04:31 -05001301
1302 if (board_technology != UNKNOWN_TECH) {
1303 board_technology = intf_technologies[intf_id];
1304 } else if (board_technology != MIXED_TECH && board_technology != intf_technologies[intf_id]) {
1305 intf_technologies[intf_id] = MIXED_TECH;
1306 }
1307
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001308 }
1309 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001310 return Status::OK;
1311}
Jason Huangb6843dc2019-07-22 17:46:06 +08001312#endif
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001313unsigned NumNniIf_() {return num_of_nni_ports;}
1314unsigned NumPonIf_() {return num_of_pon_ports;}
1315
Jason Huangd33b4d82019-05-15 18:22:57 +08001316bcmos_errno get_nni_interface_status(bcmolt_interface id, bcmolt_interface_state *state) {
1317 bcmos_errno err;
1318 bcmolt_nni_interface_key nni_key;
1319 bcmolt_nni_interface_cfg nni_cfg;
1320 nni_key.id = id;
1321
1322 BCMOLT_CFG_INIT(&nni_cfg, nni_interface, nni_key);
1323 BCMOLT_FIELD_SET_PRESENT(&nni_cfg.data, nni_interface_cfg_data, state);
1324 err = bcmolt_cfg_get(dev_id, &nni_cfg.hdr);
1325 *state = nni_cfg.data.state;
1326 return err;
1327}
1328
Jason Huangb6843dc2019-07-22 17:46:06 +08001329Status SetStateUplinkIf_(uint32_t intf_id, bool set_state) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001330 bcmos_errno err = BCM_ERR_OK;
1331 bcmolt_nni_interface_key intf_key = {.id = (bcmolt_interface)intf_id};
1332 bcmolt_nni_interface_set_nni_state nni_interface_set_state;
1333 bcmolt_interface_state state;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001334
Jason Huangd33b4d82019-05-15 18:22:57 +08001335 err = get_nni_interface_status((bcmolt_interface)intf_id, &state);
1336 if (err == BCM_ERR_OK) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001337 if (set_state && state == BCMOLT_INTERFACE_STATE_ACTIVE_WORKING) {
1338 OPENOLT_LOG(INFO, openolt_log_id, "NNI interface: %d already enabled\n", intf_id);
1339 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for NNI interface: %d\n", intf_id);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001340 CreateDefaultSched(intf_id, upstream);
1341 CreateDefaultQueue(intf_id, upstream);
Jason Huangd33b4d82019-05-15 18:22:57 +08001342 return Status::OK;
Jason Huangb6843dc2019-07-22 17:46:06 +08001343 } else if (!set_state && state == BCMOLT_INTERFACE_STATE_INACTIVE) {
1344 OPENOLT_LOG(INFO, openolt_log_id, "NNI interface: %d already disabled\n", intf_id);
1345 return Status::OK;
Jason Huangd33b4d82019-05-15 18:22:57 +08001346 }
Craig Lutgend0bae9b2018-10-18 18:02:07 -05001347 }
1348
Jason Huangd33b4d82019-05-15 18:22:57 +08001349 BCMOLT_OPER_INIT(&nni_interface_set_state, nni_interface, set_nni_state, intf_key);
Jason Huangb6843dc2019-07-22 17:46:06 +08001350 if (set_state) {
1351 BCMOLT_FIELD_SET(&nni_interface_set_state.data, nni_interface_set_nni_state_data,
1352 nni_state, BCMOLT_INTERFACE_OPERATION_ACTIVE_WORKING);
1353 } else {
1354 BCMOLT_FIELD_SET(&nni_interface_set_state.data, nni_interface_set_nni_state_data,
1355 nni_state, BCMOLT_INTERFACE_OPERATION_INACTIVE);
1356 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001357 err = bcmolt_oper_submit(dev_id, &nni_interface_set_state.hdr);
1358 if (err != BCM_ERR_OK) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001359 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to %s NNI interface: %d, err %d\n",
1360 (set_state)?"enable":"disable", intf_id, err);
Jason Huangd33b4d82019-05-15 18:22:57 +08001361 return bcm_to_grpc_err(err, "Failed to enable NNI interface");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001362 }
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07001363 else {
Jason Huangb6843dc2019-07-22 17:46:06 +08001364 OPENOLT_LOG(INFO, openolt_log_id, "Successfully %s NNI interface: %d\n", (set_state)?"enable":"disable", intf_id);
1365 if (set_state) {
1366 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for NNI interface: %d\n", intf_id);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001367 CreateDefaultSched(intf_id, upstream);
1368 CreateDefaultQueue(intf_id, upstream);
Jason Huangb6843dc2019-07-22 17:46:06 +08001369 }
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07001370 }
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001371
1372 return Status::OK;
1373}
1374
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001375Status DisablePonIf_(uint32_t intf_id) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001376 bcmolt_pon_interface_cfg interface_obj;
1377 bcmolt_pon_interface_key interface_key;
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001378
Jason Huangd33b4d82019-05-15 18:22:57 +08001379 interface_key.pon_ni = intf_id;
1380 BCMOLT_CFG_INIT(&interface_obj, pon_interface, interface_key);
1381 BCMOLT_MSG_FIELD_GET(&interface_obj, state);
1382 bcmos_errno err = bcmolt_cfg_get(dev_id, &interface_obj.hdr);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001383 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001384 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to disable PON interface: %d\n", intf_id);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001385 return bcm_to_grpc_err(err, "Failed to disable PON interface");
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001386 }
1387
1388 return Status::OK;
1389}
1390
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001391Status ActivateOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001392 const char *vendor_id, const char *vendor_specific, uint32_t pir) {
Jason Huangb1fad572019-05-28 19:02:30 +08001393 bcmos_errno err = BCM_ERR_OK;
1394 bcmolt_onu_cfg onu_cfg;
1395 bcmolt_onu_key onu_key;
Jason Huangd33b4d82019-05-15 18:22:57 +08001396 bcmolt_serial_number serial_number; /**< ONU serial number */
1397 bcmolt_bin_str_36 registration_id; /**< ONU registration ID */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001398
Jason Huangb1fad572019-05-28 19:02:30 +08001399 onu_key.onu_id = onu_id;
1400 onu_key.pon_ni = intf_id;
1401 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
1402 BCMOLT_FIELD_SET_PRESENT(&onu_cfg.data, onu_cfg_data, onu_state);
1403 err = bcmolt_cfg_get(dev_id, &onu_cfg.hdr);
1404 if (err == BCM_ERR_OK) {
1405 if ((onu_cfg.data.onu_state == BCMOLT_ONU_STATE_PROCESSING ||
1406 onu_cfg.data.onu_state == BCMOLT_ONU_STATE_ACTIVE) ||
1407 (onu_cfg.data.onu_state == BCMOLT_ONU_STATE_INACTIVE &&
Jason Huangb6843dc2019-07-22 17:46:06 +08001408 onu_cfg.data.onu_old_state == BCMOLT_ONU_STATE_NOT_CONFIGURED))
Jason Huangb1fad572019-05-28 19:02:30 +08001409 return Status::OK;
1410 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001411
Jason Huangb6843dc2019-07-22 17:46:06 +08001412 OPENOLT_LOG(INFO, openolt_log_id, "Enabling ONU %d on PON %d : vendor id %s, \
1413vendor specific %s, pir %d\n", onu_id, intf_id, vendor_id,
Jason Huangb1fad572019-05-28 19:02:30 +08001414 vendor_specific_to_str(vendor_specific).c_str(), pir);
1415
Jason Huangd33b4d82019-05-15 18:22:57 +08001416 memcpy(serial_number.vendor_id.arr, vendor_id, 4);
1417 memcpy(serial_number.vendor_specific.arr, vendor_specific, 4);
Jason Huangb1fad572019-05-28 19:02:30 +08001418 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
Jason Huangb1fad572019-05-28 19:02:30 +08001419 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.serial_number, serial_number);
1420 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.auto_learning, BCMOS_TRUE);
1421 /*set burst and data profiles to fec disabled*/
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001422 if (board_technology == "XGS-PON") {
1423 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.xgpon.ranging_burst_profile, 2);
1424 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.xgpon.data_burst_profile, 1);
1425 } else if (board_technology == "GPON") {
1426 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.gpon.ds_ber_reporting_interval, 1000000);
1427 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.gpon.omci_port_id, onu_id);
1428 }
Jason Huangb6843dc2019-07-22 17:46:06 +08001429 err = bcmolt_cfg_set(dev_id, &onu_cfg.hdr);
Jason Huangb1fad572019-05-28 19:02:30 +08001430 if (err != BCM_ERR_OK) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001431 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 +08001432 return bcm_to_grpc_err(err, "Failed to activate ONU");
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001433 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001434
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001435 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001436}
1437
Jonathan Davis70c21812018-07-19 15:32:10 -04001438Status DeactivateOnu_(uint32_t intf_id, uint32_t onu_id,
1439 const char *vendor_id, const char *vendor_specific) {
Jason Huangb1fad572019-05-28 19:02:30 +08001440 bcmos_errno err = BCM_ERR_OK;
1441 bcmolt_onu_set_onu_state onu_oper; /* declare main API struct */
1442 bcmolt_onu_cfg onu_cfg;
1443 bcmolt_onu_key onu_key; /**< Object key. */
1444 bcmolt_onu_state onu_state;
Jonathan Davis70c21812018-07-19 15:32:10 -04001445
Jason Huangb1fad572019-05-28 19:02:30 +08001446 onu_key.onu_id = onu_id;
1447 onu_key.pon_ni = intf_id;
1448 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
1449 BCMOLT_FIELD_SET_PRESENT(&onu_cfg.data, onu_cfg_data, onu_state);
1450 err = bcmolt_cfg_get(dev_id, &onu_cfg.hdr);
1451 if (err == BCM_ERR_OK) {
1452 switch (onu_state) {
1453 case BCMOLT_ONU_OPERATION_ACTIVE:
1454 BCMOLT_OPER_INIT(&onu_oper, onu, set_onu_state, onu_key);
1455 BCMOLT_FIELD_SET(&onu_oper.data, onu_set_onu_state_data,
1456 onu_state, BCMOLT_ONU_OPERATION_INACTIVE);
1457 err = bcmolt_oper_submit(dev_id, &onu_oper.hdr);
1458 if (err != BCM_ERR_OK) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001459 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to \
1460deactivate ONU %d on PON %d, err %d\n", onu_id, intf_id, err);
Jason Huangb1fad572019-05-28 19:02:30 +08001461 return bcm_to_grpc_err(err, "Failed to deactivate ONU");
1462 }
1463 break;
1464 }
Jonathan Davis70c21812018-07-19 15:32:10 -04001465 }
1466
1467 return Status::OK;
1468}
1469
1470Status DeleteOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001471 const char *vendor_id, const char *vendor_specific) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001472
Jason Huangb6843dc2019-07-22 17:46:06 +08001473 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 -05001474 onu_id, intf_id, vendor_id, vendor_specific_to_str(vendor_specific).c_str());
1475
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001476 // Need to deactivate before removing it (BAL rules)
1477
1478 DeactivateOnu_(intf_id, onu_id, vendor_id, vendor_specific);
1479 // Sleep to allow the state to propagate
1480 // We need the subscriber terminal object to be admin down before removal
1481 // Without sleep the race condition is lost by ~ 20 ms
1482 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1483
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001484 // TODO: Delete the schedulers and queues.
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001485
Jason Huangd33b4d82019-05-15 18:22:57 +08001486 bcmolt_onu_cfg cfg_obj;
1487 bcmolt_onu_key key;
Jonathan Davis70c21812018-07-19 15:32:10 -04001488
Jason Huangb6843dc2019-07-22 17:46:06 +08001489 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 -04001490 onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -04001491
Jason Huangd33b4d82019-05-15 18:22:57 +08001492 key.onu_id = onu_id;
1493 key.pon_ni = intf_id;
1494 BCMOLT_CFG_INIT(&cfg_obj, onu, key);
Jonathan Davis70c21812018-07-19 15:32:10 -04001495
Jason Huangb6843dc2019-07-22 17:46:06 +08001496 bcmos_errno err = bcmolt_cfg_clear(dev_id, &cfg_obj.hdr);
Jonathan Davis70c21812018-07-19 15:32:10 -04001497 if (err != BCM_ERR_OK)
1498 {
Jason Huangb6843dc2019-07-22 17:46:06 +08001499 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 -04001500 onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -04001501 return Status(grpc::StatusCode::INTERNAL, "Failed to delete ONU");
1502 }
1503
Jason Huangd33b4d82019-05-15 18:22:57 +08001504 return Status::OK;
Jonathan Davis70c21812018-07-19 15:32:10 -04001505}
1506
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001507#define MAX_CHAR_LENGTH 20
1508#define MAX_OMCI_MSG_LENGTH 44
1509Status OmciMsgOut_(uint32_t intf_id, uint32_t onu_id, const std::string pkt) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001510 bcmolt_bin_str buf = {};
1511 bcmolt_onu_cpu_packets omci_cpu_packets;
1512 bcmolt_onu_key key;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001513
Jason Huangd33b4d82019-05-15 18:22:57 +08001514 key.pon_ni = intf_id;
1515 key.onu_id = onu_id;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001516
Jason Huangd33b4d82019-05-15 18:22:57 +08001517 BCMOLT_OPER_INIT(&omci_cpu_packets, onu, cpu_packets, key);
1518 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, packet_type, BCMOLT_PACKET_TYPE_OMCI);
1519 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, calc_crc, BCMOS_TRUE);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001520
1521 // ???
1522 if ((pkt.size()/2) > MAX_OMCI_MSG_LENGTH) {
1523 buf.len = MAX_OMCI_MSG_LENGTH;
1524 } else {
1525 buf.len = pkt.size()/2;
1526 }
1527
1528 /* Send the OMCI packet using the BAL remote proxy API */
1529 uint16_t idx1 = 0;
1530 uint16_t idx2 = 0;
1531 uint8_t arraySend[buf.len];
1532 char str1[MAX_CHAR_LENGTH];
1533 char str2[MAX_CHAR_LENGTH];
1534 memset(&arraySend, 0, buf.len);
1535
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001536 for (idx1=0,idx2=0; idx1<((buf.len)*2); idx1++,idx2++) {
1537 sprintf(str1,"%c", pkt[idx1]);
1538 sprintf(str2,"%c", pkt[++idx1]);
1539 strcat(str1,str2);
1540 arraySend[idx2] = strtol(str1, NULL, 16);
1541 }
1542
Jason Huangd33b4d82019-05-15 18:22:57 +08001543 buf.arr = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
1544 memcpy(buf.arr, (uint8_t *)arraySend, buf.len);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001545
Jason Huangd33b4d82019-05-15 18:22:57 +08001546 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, number_of_packets, 1);
1547 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, packet_size, buf.len);
1548 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, buffer, buf);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001549
Jason Huangd33b4d82019-05-15 18:22:57 +08001550 bcmos_errno err = bcmolt_oper_submit(dev_id, &omci_cpu_packets.hdr);
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001551 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001552 OPENOLT_LOG(ERROR, omci_log_id, "Error sending OMCI message to ONU %d on PON %d\n", onu_id, intf_id);
1553 return bcm_to_grpc_err(err, "send OMCI failed");
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001554 } else {
Jason Huangb6843dc2019-07-22 17:46:06 +08001555 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 -05001556 buf.len, onu_id, intf_id, pkt.c_str());
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001557 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001558 free(buf.arr);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001559
1560 return Status::OK;
1561}
1562
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001563Status 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 +08001564 bcmolt_pon_interface_cpu_packets pon_interface_cpu_packets; /**< declare main API struct */
1565 bcmolt_pon_interface_key key = {.pon_ni = (bcmolt_interface)intf_id}; /**< declare key */
1566 bcmolt_bin_str buf = {};
1567 bcmolt_gem_port_id gem_port_id_array[1];
1568 bcmolt_gem_port_id_list_u8_max_16 gem_port_list = {};
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001569
Craig Lutgen967a1d02018-11-27 10:41:51 -06001570 if (port_no > 0) {
1571 bool found = false;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001572 if (gemport_id == 0) {
1573 bcmos_fastlock_lock(&data_lock);
1574 // Map the port_no to one of the flows that owns it to find a gemport_id for that flow.
1575 // Pick any flow that is mapped with the same port_no.
1576 std::map<uint32_t, std::set<uint32_t> >::const_iterator it = port_to_flows.find(port_no);
1577 if (it != port_to_flows.end() && !it->second.empty()) {
1578 uint32_t flow_id = *(it->second.begin()); // Pick any flow_id out of the bag set
1579 std::map<uint32_t, uint32_t>::const_iterator fit = flowid_to_gemport.find(flow_id);
1580 if (fit != flowid_to_gemport.end()) {
1581 found = true;
1582 gemport_id = fit->second;
1583 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001584 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001585 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001586
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001587 if (!found) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001588 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 -08001589 onu_id, port_no, intf_id);
1590 return grpc::Status(grpc::StatusCode::NOT_FOUND, "no flow for port_no");
1591 }
Jason Huangb6843dc2019-07-22 17:46:06 +08001592 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 -08001593 gemport_id, onu_id, port_no, intf_id);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001594 }
1595
Jason Huangd33b4d82019-05-15 18:22:57 +08001596 gem_port_id_array[0] = gemport_id;
1597 gem_port_list.len = 1;
1598 gem_port_list.arr = gem_port_id_array;
1599 buf.len = pkt.size();
1600 buf.arr = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
1601 memcpy(buf.arr, (uint8_t *)pkt.data(), buf.len);
1602
1603 /* init the API struct */
1604 BCMOLT_OPER_INIT(&pon_interface_cpu_packets, pon_interface, cpu_packets, key);
1605 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, packet_type, BCMOLT_PACKET_TYPE_ETH);
1606 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, calc_crc, BCMOS_TRUE);
1607 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, gem_port_list, gem_port_list);
1608 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, buffer, buf);
1609
Jason Huangb6843dc2019-07-22 17:46:06 +08001610 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 +08001611 (uint8_t)pkt.size(), gemport_id, intf_id, port_no);
1612
1613 /* call API */
Jason Huangb6843dc2019-07-22 17:46:06 +08001614 bcmolt_oper_submit(dev_id, &pon_interface_cpu_packets.hdr);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001615 }
1616 else {
Jason Huangd33b4d82019-05-15 18:22:57 +08001617 //TODO: Port No is 0, it is coming sender requirement.
Jason Huangb6843dc2019-07-22 17:46:06 +08001618 OPENOLT_LOG(INFO, openolt_log_id, "port_no %d onu %d on pon %d\n",
Jason Huangd33b4d82019-05-15 18:22:57 +08001619 port_no, onu_id, intf_id);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001620 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001621 free(buf.arr);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001622
1623 return Status::OK;
1624}
1625
Jason Huangd33b4d82019-05-15 18:22:57 +08001626Status UplinkPacketOut_(uint32_t intf_id, const std::string pkt, bcmolt_flow_id flow_id) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001627 bcmolt_flow_key key = {}; /* declare key */
1628 bcmolt_bin_str buffer = {};
1629 bcmolt_flow_send_eth_packet oper; /* declare main API struct */
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001630
Jason Huangb6843dc2019-07-22 17:46:06 +08001631 //validate flow_id and find flow_id/flow type: upstream/ingress type: PON/egress type: NNI
1632 if (get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, FLOW_TYPE) == BCMOLT_FLOW_TYPE_UPSTREAM && \
1633 get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, INGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_PON && \
1634 get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, EGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_NNI)
1635 key.flow_id = flow_id;
1636 else {
1637 if (flow_id_counters != 0) {
1638 for (int flowid=0; flowid < flow_id_counters; flowid++) {
1639 int flow_index = flow_id_data[flowid][0];
1640 if (get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, FLOW_TYPE) == BCMOLT_FLOW_TYPE_UPSTREAM && \
1641 get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, INGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_PON && \
1642 get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, EGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_NNI) {
1643 key.flow_id = flow_index;
1644 break;
1645 }
1646 }
1647 }
1648 else
1649 return grpc::Status(grpc::StatusCode::NOT_FOUND, "no flow id found");
1650 }
1651
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07001652 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM; /* send from uplink direction */
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001653
Jason Huangd33b4d82019-05-15 18:22:57 +08001654 /* Initialize the API struct. */
1655 BCMOLT_OPER_INIT(&oper, flow, send_eth_packet, key);
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001656
Jason Huangd33b4d82019-05-15 18:22:57 +08001657 buffer.len = pkt.size();
1658 buffer.arr = (uint8_t *)malloc((buffer.len)*sizeof(uint8_t));
1659 memcpy(buffer.arr, (uint8_t *)pkt.data(), buffer.len);
1660 if (buffer.arr == NULL) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001661 OPENOLT_LOG(ERROR, openolt_log_id, "allocate pakcet buffer failed\n");
Jason Huangd33b4d82019-05-15 18:22:57 +08001662 return bcm_to_grpc_err(BCM_ERR_PARM, "allocate pakcet buffer failed");
1663 }
1664 BCMOLT_FIELD_SET(&oper.data, flow_send_eth_packet_data, buffer, buffer);
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001665
Jason Huangd33b4d82019-05-15 18:22:57 +08001666 bcmos_errno err = bcmolt_oper_submit(dev_id, &oper.hdr);
Jason Huangb6843dc2019-07-22 17:46:06 +08001667 if (err) {
1668 OPENOLT_LOG(ERROR, openolt_log_id, "Error sending packets to port %d, flow_id %d, err %d\n", intf_id, key.flow_id, err);
1669 } else {
1670 OPENOLT_LOG(INFO, openolt_log_id, "sent packets to port %d in upstream direction (flow_id %d)\n", intf_id, key.flow_id);
1671 }
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001672
1673 return Status::OK;
1674}
1675
Jason Huangd33b4d82019-05-15 18:22:57 +08001676uint32_t GetPortNum_(uint32_t flow_id) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001677 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001678 uint32_t port_no = 0;
1679 std::map<uint32_t, uint32_t >::const_iterator it = flowid_to_port.find(flow_id);
1680 if (it != flowid_to_port.end()) {
1681 port_no = it->second;
1682 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001683 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001684 return port_no;
1685}
1686
Jason Huangb6843dc2019-07-22 17:46:06 +08001687#define FLOW_LOG(level,msg,err) \
1688 do { \
1689 OPENOLT_LOG(level, openolt_log_id, "--------> %s (flow_id %d) err: %d <--------\n", msg, key.flow_id, err); \
1690 OPENOLT_LOG(level, openolt_log_id, "intf_id %d, onu_id %d, uni_id %d, port_no %u, cookie %"PRIu64"\n", \
1691 access_intf_id, onu_id, uni_id, port_no, cookie); \
1692 OPENOLT_LOG(level, openolt_log_id, "flow_type %s, queue_id %d, sched_id %d\n", flow_type.c_str(), \
1693 cfg.data.egress_qos.u.fixed_queue.queue_id, cfg.data.egress_qos.tm_sched.id); \
1694 OPENOLT_LOG(level, openolt_log_id, "Ingress(intfd_type %s, intf_id %d), Egress(intf_type %s, intf_id %d)\n", \
1695 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), cfg.data.ingress_intf.intf_id, \
1696 GET_FLOW_INTERFACE_TYPE(cfg.data.egress_intf.intf_type), cfg.data.egress_intf.intf_id); \
1697 OPENOLT_LOG(level, openolt_log_id, "classifier(o_vid %d, o_pbits %d, i_vid %d, i_pbits %d, ether type 0x%x)\n", \
1698 c_val.o_vid, c_val.o_pbits, c_val.i_vid, c_val.i_pbits, classifier.eth_type()); \
1699 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", \
1700 c_val.ip_proto, gemport_id, c_val.src_port, c_val.dst_port, GET_PKT_TAG_TYPE(c_val.pkt_tag_type)); \
1701 OPENOLT_LOG(level, openolt_log_id, "action(cmds_bitmask %s, o_vid %d, o_pbits %d, i_vid %d, i_pbits %d)\n\n", \
1702 get_flow_acton_command(a_val.cmds_bitmask), a_val.o_vid, a_val.o_pbits, a_val.i_vid, a_val.i_pbits); \
1703 } while(0)
1704
1705#define FLOW_PARAM_LOG() \
1706 do { \
1707 OPENOLT_LOG(INFO, openolt_log_id, "--------> flow comparison (now before) <--------\n"); \
1708 OPENOLT_LOG(INFO, openolt_log_id, "flow_id (%d %d)\n", \
1709 key.flow_id, flow_index); \
1710 OPENOLT_LOG(INFO, openolt_log_id, "onu_id (%d %lu)\n", \
1711 cfg.data.onu_id , get_flow_status(flow_index, flow_id_data[flowid][1], ONU_ID)); \
1712 OPENOLT_LOG(INFO, openolt_log_id, "type (%d %lu)\n", \
1713 key.flow_type, get_flow_status(flow_index, flow_id_data[flowid][1], FLOW_TYPE)); \
1714 OPENOLT_LOG(INFO, openolt_log_id, "svc_port_id (%d %lu)\n", \
1715 cfg.data.svc_port_id, get_flow_status(flow_index, flow_id_data[flowid][1], SVC_PORT_ID)); \
1716 OPENOLT_LOG(INFO, openolt_log_id, "priority (%d %lu)\n", \
1717 cfg.data.priority, get_flow_status(flow_index, flow_id_data[flowid][1], PRIORITY)); \
1718 OPENOLT_LOG(INFO, openolt_log_id, "cookie (%lu %lu)\n", \
1719 cfg.data.cookie, get_flow_status(flow_index, flow_id_data[flowid][1], COOKIE)); \
1720 OPENOLT_LOG(INFO, openolt_log_id, "ingress intf_type (%s %s)\n", \
1721 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), \
1722 GET_FLOW_INTERFACE_TYPE(get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_TYPE))); \
1723 OPENOLT_LOG(INFO, openolt_log_id, "ingress intf id (%d %lu)\n", \
1724 cfg.data.ingress_intf.intf_id , get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_ID)); \
1725 OPENOLT_LOG(INFO, openolt_log_id, "egress intf_type (%d %lu)\n", \
1726 cfg.data.egress_intf.intf_type , get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_TYPE)); \
1727 OPENOLT_LOG(INFO, openolt_log_id, "egress intf_id (%d %lu)\n", \
1728 cfg.data.egress_intf.intf_id , get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_ID)); \
1729 OPENOLT_LOG(INFO, openolt_log_id, "classifier o_vid (%d %lu)\n", \
1730 c_val.o_vid , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_VID)); \
1731 OPENOLT_LOG(INFO, openolt_log_id, "classifier o_pbits (%d %lu)\n", \
1732 c_val.o_pbits , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_PBITS)); \
1733 OPENOLT_LOG(INFO, openolt_log_id, "classifier i_vid (%d %lu)\n", \
1734 c_val.i_vid , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_VID)); \
1735 OPENOLT_LOG(INFO, openolt_log_id, "classifier i_pbits (%d %lu)\n", \
1736 c_val.i_pbits , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_PBITS)); \
1737 OPENOLT_LOG(INFO, openolt_log_id, "classifier ether_type (0x%x 0x%lx)\n", \
1738 c_val.ether_type , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_ETHER_TYPE)); \
1739 OPENOLT_LOG(INFO, openolt_log_id, "classifier ip_proto (%d %lu)\n", \
1740 c_val.ip_proto , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_IP_PROTO)); \
1741 OPENOLT_LOG(INFO, openolt_log_id, "classifier src_port (%d %lu)\n", \
1742 c_val.src_port , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_SRC_PORT)); \
1743 OPENOLT_LOG(INFO, openolt_log_id, "classifier dst_port (%d %lu)\n", \
1744 c_val.dst_port , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_DST_PORT)); \
1745 OPENOLT_LOG(INFO, openolt_log_id, "classifier pkt_tag_type (%s %s)\n", \
1746 GET_PKT_TAG_TYPE(c_val.pkt_tag_type), \
1747 GET_PKT_TAG_TYPE(get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_PKT_TAG_TYPE))); \
1748 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos type (%d %lu)\n", \
1749 cfg.data.egress_qos.type , get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TYPE)); \
1750 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos queue_id (%d %lu)\n", \
1751 cfg.data.egress_qos.u.fixed_queue.queue_id, \
1752 get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_QUEUE_ID)); \
1753 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos sched_id (%d %lu)\n", \
1754 cfg.data.egress_qos.tm_sched.id, \
1755 get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TM_SCHED_ID)); \
1756 OPENOLT_LOG(INFO, openolt_log_id, "classifier cmds_bitmask (%s %s)\n", \
1757 get_flow_acton_command(a_val.cmds_bitmask), \
1758 get_flow_acton_command(get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_CMDS_BITMASK))); \
1759 OPENOLT_LOG(INFO, openolt_log_id, "action o_vid (%d %lu)\n", \
1760 a_val.o_vid , get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_VID)); \
1761 OPENOLT_LOG(INFO, openolt_log_id, "action i_vid (%d %lu)\n", \
1762 a_val.i_vid , get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_VID)); \
1763 OPENOLT_LOG(INFO, openolt_log_id, "action o_pbits (%d %lu)\n", \
1764 a_val.o_pbits , get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_PBITS)); \
1765 OPENOLT_LOG(INFO, openolt_log_id, "action i_pbits (%d %lu)\n\n", \
1766 a_val.i_pbits, get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_PBITS)); \
1767 } while(0)
1768
1769#define FLOW_CHECKER
1770//#define SHOW_FLOW_PARAM
1771
Craig Lutgen967a1d02018-11-27 10:41:51 -06001772Status 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 +00001773 uint32_t flow_id, const std::string flow_type,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001774 int32_t alloc_id, int32_t network_intf_id,
1775 int32_t gemport_id, const ::openolt::Classifier& classifier,
Craig Lutgen967a1d02018-11-27 10:41:51 -06001776 const ::openolt::Action& action, int32_t priority_value, uint64_t cookie) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001777 bcmolt_flow_cfg cfg;
1778 bcmolt_flow_key key = { }; /**< Object key. */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001779 int32_t o_vid = -1;
1780 bool single_tag = false;
1781 uint32_t ether_type = 0;
Jason Huangb6843dc2019-07-22 17:46:06 +08001782 bcmolt_classifier c_val = { };
1783 bcmolt_action a_val = { };
1784 bcmolt_tm_queue_ref tm_val = { };
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001785 int tm_qmp_id, tm_q_set_id;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001786
1787 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001788 if (flow_type.compare(upstream) == 0 ) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001789 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001790 } else if (flow_type.compare(downstream) == 0) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001791 key.flow_type = BCMOLT_FLOW_TYPE_DOWNSTREAM;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001792 } else {
Jason Huangb6843dc2019-07-22 17:46:06 +08001793 OPENOLT_LOG(ERROR, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001794 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001795 }
1796
Jason Huangd33b4d82019-05-15 18:22:57 +08001797 BCMOLT_CFG_INIT(&cfg, flow, key);
1798 BCMOLT_MSG_FIELD_SET(&cfg, cookie, cookie);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001799
Jason Huangb6843dc2019-07-22 17:46:06 +08001800 if (access_intf_id >= 0 && network_intf_id >= 0) {
1801 if (key.flow_type == BCMOLT_FLOW_TYPE_UPSTREAM) { //upstream
Jason Huangd33b4d82019-05-15 18:22:57 +08001802 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_PON);
1803 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_id, access_intf_id);
Jason Huangb6843dc2019-07-22 17:46:06 +08001804 if (classifier.eth_type() == EAP_ETHER_TYPE || //EAPOL packet
1805 (classifier.ip_proto() == 17 && classifier.src_port() == 68 && classifier.dst_port() == 67)) { //DHCP packet
1806 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_HOST);
1807 } else {
1808 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_NNI);
1809 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_id, network_intf_id);
1810 }
1811 } else if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) { //downstream
1812 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_NNI);
1813 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_id, network_intf_id);
Jason Huangd33b4d82019-05-15 18:22:57 +08001814 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_PON);
1815 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_id, access_intf_id);
1816 }
Jason Huangb6843dc2019-07-22 17:46:06 +08001817 } else {
1818 OPENOLT_LOG(ERROR, openolt_log_id, "flow network setting invalid\n");
1819 return bcm_to_grpc_err(BCM_ERR_PARM, "flow network setting invalid");
Shad Ansari39739bc2018-09-13 21:38:37 +00001820 }
Jason Huangb6843dc2019-07-22 17:46:06 +08001821
Shad Ansari39739bc2018-09-13 21:38:37 +00001822 if (onu_id >= 0) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001823 BCMOLT_MSG_FIELD_SET(&cfg, onu_id, onu_id);
Shad Ansari39739bc2018-09-13 21:38:37 +00001824 }
1825 if (gemport_id >= 0) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001826 BCMOLT_MSG_FIELD_SET(&cfg, svc_port_id, gemport_id);
Shad Ansari39739bc2018-09-13 21:38:37 +00001827 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001828 if (gemport_id >= 0 && port_no != 0) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001829 bcmos_fastlock_lock(&data_lock);
Jason Huangd33b4d82019-05-15 18:22:57 +08001830 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
Craig Lutgen967a1d02018-11-27 10:41:51 -06001831 port_to_flows[port_no].insert(key.flow_id);
1832 flowid_to_gemport[key.flow_id] = gemport_id;
1833 }
1834 else
1835 {
1836 flowid_to_port[key.flow_id] = port_no;
1837 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001838 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001839 }
Shad Ansari39739bc2018-09-13 21:38:37 +00001840 if (priority_value >= 0) {
Jason Huangd33b4d82019-05-15 18:22:57 +08001841 BCMOLT_MSG_FIELD_SET(&cfg, priority, priority_value);
Shad Ansari39739bc2018-09-13 21:38:37 +00001842 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001843
1844 {
Jason Huangd33b4d82019-05-15 18:22:57 +08001845 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001846 if (classifier.o_tpid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001847 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_tpid 0x%04x\n", classifier.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001848 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_tpid, classifier.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001849 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001850 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001851 if (classifier.o_vid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001852 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_vid %d\n", classifier.o_vid());
1853 BCMOLT_FIELD_SET(&c_val, classifier, o_vid, classifier.o_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001854 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001855 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001856 if (classifier.i_tpid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001857 OPENOLT_LOG(DEBUG, openolt_log_id, "classify i_tpid 0x%04x\n", classifier.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001858 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, i_tpid, classifier.i_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.i_vid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001862 OPENOLT_LOG(DEBUG, openolt_log_id, "classify i_vid %d\n", classifier.i_vid());
1863 BCMOLT_FIELD_SET(&c_val, classifier, i_vid, classifier.i_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001864 }
1865
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001866 if (classifier.eth_type()) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001867 ether_type = classifier.eth_type();
Jason Huangb6843dc2019-07-22 17:46:06 +08001868 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ether_type 0x%04x\n", classifier.eth_type());
1869 BCMOLT_FIELD_SET(&c_val, classifier, ether_type, classifier.eth_type());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001870 }
1871
1872 /*
1873 if (classifier.dst_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001874 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_mac, classifier.dst_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001875 }
1876
1877 if (classifier.src_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001878 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_mac, classifier.src_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001879 }
1880 */
1881
1882 if (classifier.ip_proto()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001883 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ip_proto %d\n", classifier.ip_proto());
1884 BCMOLT_FIELD_SET(&c_val, classifier, ip_proto, classifier.ip_proto());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001885 }
1886
1887 /*
1888 if (classifier.dst_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001889 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_ip, classifier.dst_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001890 }
1891
1892 if (classifier.src_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001893 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_ip, classifier.src_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001894 }
1895 */
1896
1897 if (classifier.src_port()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001898 OPENOLT_LOG(DEBUG, openolt_log_id, "classify src_port %d\n", classifier.src_port());
1899 BCMOLT_FIELD_SET(&c_val, classifier, src_port, classifier.src_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001900 }
1901
1902 if (classifier.dst_port()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001903 OPENOLT_LOG(DEBUG, openolt_log_id, "classify dst_port %d\n", classifier.dst_port());
1904 BCMOLT_FIELD_SET(&c_val, classifier, dst_port, classifier.dst_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001905 }
1906
1907 if (!classifier.pkt_tag_type().empty()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001908 OPENOLT_LOG(DEBUG, openolt_log_id, "classify tag_type %s\n", classifier.pkt_tag_type().c_str());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001909 if (classifier.pkt_tag_type().compare("untagged") == 0) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001910 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_UNTAGGED);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001911 } else if (classifier.pkt_tag_type().compare("single_tag") == 0) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001912 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_SINGLE_TAG);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001913 single_tag = true;
1914
Jason Huangb6843dc2019-07-22 17:46:06 +08001915 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1916 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, classifier.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001917 } else if (classifier.pkt_tag_type().compare("double_tag") == 0) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001918 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_DOUBLE_TAG);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001919
Jason Huangb6843dc2019-07-22 17:46:06 +08001920 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1921 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, classifier.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001922 }
1923 }
Jason Huangb6843dc2019-07-22 17:46:06 +08001924 BCMOLT_MSG_FIELD_SET(&cfg, classifier, c_val);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001925 }
1926
Jason Huangb6843dc2019-07-22 17:46:06 +08001927 if (cfg.data.egress_intf.intf_type != BCMOLT_FLOW_INTERFACE_TYPE_HOST) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001928 const ::openolt::ActionCmd& cmd = action.cmd();
1929
1930 if (cmd.add_outer_tag()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001931 OPENOLT_LOG(DEBUG, openolt_log_id, "action add o_tag\n");
1932 BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, BCMOLT_ACTION_CMD_ID_ADD_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001933 }
1934
1935 if (cmd.remove_outer_tag()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001936 OPENOLT_LOG(DEBUG, openolt_log_id, "action pop o_tag\n");
1937 BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, BCMOLT_ACTION_CMD_ID_REMOVE_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001938 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001939 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001940 if (cmd.trap_to_host()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001941 OPENOLT_LOG(INFO, openolt_log_id, "action trap-to-host\n");
Craig Lutgen19512312018-11-02 10:14:46 -05001942 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, cmds_bitmask, BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001943 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001944 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001945 if (action.o_vid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001946 OPENOLT_LOG(DEBUG, openolt_log_id, "action o_vid=%d\n", action.o_vid());
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001947 o_vid = action.o_vid();
Jason Huangb6843dc2019-07-22 17:46:06 +08001948 BCMOLT_FIELD_SET(&a_val, action, o_vid, action.o_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001949 }
1950
1951 if (action.o_pbits()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001952 OPENOLT_LOG(DEBUG, openolt_log_id, "action o_pbits=0x%x\n", action.o_pbits());
1953 BCMOLT_FIELD_SET(&a_val, action, o_pbits, action.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001954 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001955 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001956 if (action.o_tpid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001957 OPENOLT_LOG(INFO, openolt_log_id, "action o_tpid=0x%04x\n", action.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001958 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, o_tpid, action.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001959 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001960 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001961 if (action.i_vid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001962 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_vid=%d\n", action.i_vid());
1963 BCMOLT_FIELD_SET(&a_val, action, i_vid, action.i_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001964 }
1965
1966 if (action.i_pbits()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001967 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_pbits=0x%x\n", action.i_pbits());
1968 BCMOLT_FIELD_SET(&a_val, action, i_pbits, action.i_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001969 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001970 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001971 if (action.i_tpid()) {
Jason Huangb6843dc2019-07-22 17:46:06 +08001972 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_tpid=0x%04x\n", action.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001973 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, i_tpid, action.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001974 }
Jason Huangd33b4d82019-05-15 18:22:57 +08001975 */
Jason Huangb6843dc2019-07-22 17:46:06 +08001976 BCMOLT_MSG_FIELD_SET(&cfg, action, a_val);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001977 }
1978
Shad Ansari39739bc2018-09-13 21:38:37 +00001979 if ((access_intf_id >= 0) && (onu_id >= 0)) {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001980 if(single_tag && ether_type == EAP_ETHER_TYPE) {
1981 tm_val.sched_id = (flow_type.compare(upstream) == 0) ? \
1982 get_default_tm_sched_id(network_intf_id, upstream) : \
1983 get_default_tm_sched_id(access_intf_id, downstream);
1984 tm_val.queue_id = 0;
Jason Huangd33b4d82019-05-15 18:22:57 +08001985
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001986 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE);
Jason Huangb6843dc2019-07-22 17:46:06 +08001987 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
1988 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08001989
1990 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
1991 flow_type.c_str(), tm_val.queue_id, tm_val.sched_id, \
1992 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
1993 } else {
1994 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
1995 tm_val.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, downstream);
1996
1997 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
1998 // Queue 0 on DS subscriber scheduler
1999 tm_val.queue_id = 0;
2000
2001 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2002 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2003 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
2004
2005 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2006 downstream.c_str(), tm_val.queue_id, tm_val.sched_id, \
2007 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2008
2009 } else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2010 /* Fetch TM QMP ID mapped to DS subscriber scheduler */
2011 tm_qmp_id = tm_q_set_id = get_tm_qmp_id(tm_val.sched_id, access_intf_id, onu_id, uni_id);
2012
2013 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2014 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2015 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_qmp_id, tm_qmp_id);
2016 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_q_set_id, tm_q_set_id);
2017
2018 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, q_set_id = %d, sched_id = %d, intf_type %s\n", \
2019 downstream.c_str(), tm_q_set_id, tm_val.sched_id, \
2020 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2021 }
2022 } else if (key.flow_type == BCMOLT_FLOW_TYPE_UPSTREAM) {
2023 // NNI Scheduler ID
2024 tm_val.sched_id = get_default_tm_sched_id(network_intf_id, upstream);
2025 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2026 // Queue 0 on NNI scheduler
2027 tm_val.queue_id = 0;
2028 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2029 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2030 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
2031
2032 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2033 upstream.c_str(), tm_val.queue_id, tm_val.sched_id, \
2034 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2035
2036 } else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2037 /* Fetch TM QMP ID mapped to US NNI scheduler */
2038 tm_qmp_id = tm_q_set_id = get_tm_qmp_id(tm_val.sched_id, access_intf_id, onu_id, uni_id);
2039 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2040 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2041 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_qmp_id, tm_qmp_id);
2042 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_q_set_id, tm_q_set_id);
2043
2044 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, q_set_id = %d, sched_id = %d, intf_type %s\n", \
2045 upstream.c_str(), tm_q_set_id, tm_val.sched_id, \
2046 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2047 }
2048 }
Shad Ansari39739bc2018-09-13 21:38:37 +00002049 }
Shad Ansari06101952018-07-25 00:22:09 +00002050 }
2051
Jason Huangd33b4d82019-05-15 18:22:57 +08002052 BCMOLT_MSG_FIELD_SET(&cfg, state, BCMOLT_FLOW_STATE_ENABLE);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002053 BCMOLT_MSG_FIELD_SET(&cfg, statistics, BCMOLT_CONTROL_STATE_ENABLE);
Jason Huangb6843dc2019-07-22 17:46:06 +08002054#ifdef FLOW_CHECKER
2055 //Flow Checker, To avoid duplicate flow.
2056 if (flow_id_counters != 0) {
2057 bool b_duplicate_flow = false;
2058 for (int flowid=0; flowid < flow_id_counters; flowid++) {
2059 int flow_index = flow_id_data[flowid][0];
2060 b_duplicate_flow = (cfg.data.onu_id == get_flow_status(flow_index, flow_id_data[flowid][1], ONU_ID)) && \
2061 (key.flow_type == flow_id_data[flowid][1]) && \
2062 (cfg.data.svc_port_id == get_flow_status(flow_index, flow_id_data[flowid][1], SVC_PORT_ID)) && \
2063 (cfg.data.priority == get_flow_status(flow_index, flow_id_data[flowid][1], PRIORITY)) && \
2064 (cfg.data.cookie == get_flow_status(flow_index, flow_id_data[flowid][1], COOKIE)) && \
2065 (cfg.data.ingress_intf.intf_type == get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_TYPE)) && \
2066 (cfg.data.ingress_intf.intf_id == get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_ID)) && \
2067 (cfg.data.egress_intf.intf_type == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_TYPE)) && \
2068 (cfg.data.egress_intf.intf_id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_ID)) && \
2069 (c_val.o_vid == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_VID)) && \
2070 (c_val.o_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_PBITS)) && \
2071 (c_val.i_vid == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_VID)) && \
2072 (c_val.i_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_PBITS)) && \
2073 (c_val.ether_type == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_ETHER_TYPE)) && \
2074 (c_val.ip_proto == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_IP_PROTO)) && \
2075 (c_val.src_port == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_SRC_PORT)) && \
2076 (c_val.dst_port == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_DST_PORT)) && \
2077 (c_val.pkt_tag_type == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_PKT_TAG_TYPE)) && \
2078 (cfg.data.egress_qos.type == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TYPE)) && \
2079 (cfg.data.egress_qos.u.fixed_queue.queue_id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_QUEUE_ID)) && \
2080 (cfg.data.egress_qos.tm_sched.id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TM_SCHED_ID)) && \
2081 (a_val.cmds_bitmask == get_flow_status(flowid, flow_id_data[flowid][1], ACTION_CMDS_BITMASK)) && \
2082 (a_val.o_vid == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_VID)) && \
2083 (a_val.i_vid == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_VID)) && \
2084 (a_val.o_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_PBITS)) && \
2085 (a_val.i_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_PBITS)) && \
2086 (cfg.data.state == get_flow_status(flowid, flow_id_data[flowid][1], STATE));
2087#ifdef SHOW_FLOW_PARAM
2088 // Flow Parameter
2089 FLOW_PARAM_LOG();
2090#endif
2091
2092 if (b_duplicate_flow) {
2093 FLOW_LOG(WARNING, "Flow duplicate", 0);
2094 return bcm_to_grpc_err(BCM_ERR_ALREADY, "flow exists");
2095 }
2096 }
2097 }
2098#endif
2099
Jason Huangd33b4d82019-05-15 18:22:57 +08002100 bcmos_errno err = bcmolt_cfg_set(dev_id, &cfg.hdr);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04002101 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08002102 FLOW_LOG(ERROR, "Flow add failed", err);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04002103 return bcm_to_grpc_err(err, "flow add failed");
Jason Huangb6843dc2019-07-22 17:46:06 +08002104 } else {
2105 FLOW_LOG(INFO, "Flow add ok", err);
2106 bcmos_fastlock_lock(&data_lock);
2107 flow_id_data[flow_id_counters][0] = key.flow_id;
2108 flow_id_data[flow_id_counters][1] = key.flow_type;
2109 flow_id_counters += 1;
2110 bcmos_fastlock_unlock(&data_lock, 0);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002111 }
2112
2113 return Status::OK;
2114}
2115
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002116Status FlowRemove_(uint32_t flow_id, const std::string flow_type) {
2117
Jason Huangd33b4d82019-05-15 18:22:57 +08002118 bcmolt_flow_cfg cfg;
2119 bcmolt_flow_key key = { };
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002120
Jason Huangd33b4d82019-05-15 18:22:57 +08002121 key.flow_id = (bcmolt_flow_id) flow_id;
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002122 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002123 if (flow_type.compare(upstream) == 0 ) {
Jason Huangd33b4d82019-05-15 18:22:57 +08002124 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002125 } else if (flow_type.compare(downstream) == 0) {
Jason Huangd33b4d82019-05-15 18:22:57 +08002126 key.flow_type = BCMOLT_FLOW_TYPE_DOWNSTREAM;
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002127 } else {
Jason Huangb6843dc2019-07-22 17:46:06 +08002128 OPENOLT_LOG(WARNING, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002129 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
2130 }
2131
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002132 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002133 uint32_t port_no = flowid_to_port[key.flow_id];
Jason Huangd33b4d82019-05-15 18:22:57 +08002134 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
Craig Lutgen967a1d02018-11-27 10:41:51 -06002135 flowid_to_gemport.erase(key.flow_id);
2136 port_to_flows[port_no].erase(key.flow_id);
2137 if (port_to_flows[port_no].empty()) port_to_flows.erase(port_no);
2138 }
2139 else
2140 {
2141 flowid_to_port.erase(key.flow_id);
2142 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002143 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002144
Jason Huangd33b4d82019-05-15 18:22:57 +08002145 BCMOLT_CFG_INIT(&cfg, flow, key);
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002146
Jason Huangd33b4d82019-05-15 18:22:57 +08002147 bcmos_errno err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002148 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08002149 OPENOLT_LOG(ERROR, openolt_log_id, "Error %d while removing flow %d, %s\n",
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04002150 err, flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002151 return Status(grpc::StatusCode::INTERNAL, "Failed to remove flow");
2152 }
2153
Jason Huangb6843dc2019-07-22 17:46:06 +08002154 bcmos_fastlock_lock(&data_lock);
2155 for (int flowid=0; flowid < flow_id_counters; flowid++) {
2156 if (flow_id_data[flowid][0] == flow_id && flow_id_data[flowid][1] == key.flow_type) {
2157 flow_id_counters -= 1;
2158 for (int i=flowid; i < flow_id_counters; i++) {
2159 flow_id_data[i][0] = flow_id_data[i + 1][0];
2160 flow_id_data[i][1] = flow_id_data[i + 1][1];
2161 }
2162 break;
2163 }
2164 }
2165 bcmos_fastlock_unlock(&data_lock, 0);
2166
2167 OPENOLT_LOG(INFO, openolt_log_id, "Flow %d, %s removed\n", flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002168 return Status::OK;
2169}
2170
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002171bcmos_errno CreateDefaultSched(uint32_t intf_id, const std::string direction) {
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002172 bcmos_errno err;
2173 bcmolt_tm_sched_cfg tm_sched_cfg;
2174 bcmolt_tm_sched_key tm_sched_key = {.id = 1};
2175 tm_sched_key.id = get_default_tm_sched_id(intf_id, direction);
2176
2177 // bcmbal_tm_sched_owner
2178 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
2179
2180 /**< The output of the tm_sched object instance */
2181 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.type, BCMOLT_TM_SCHED_OUTPUT_TYPE_INTERFACE);
2182
2183 if (direction.compare(upstream) == 0) {
2184 // In upstream it is NNI scheduler
2185 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_type, BCMOLT_INTERFACE_TYPE_NNI);
2186 } else if (direction.compare(downstream) == 0) {
2187 // In downstream it is PON scheduler
2188 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_type, BCMOLT_INTERFACE_TYPE_PON);
2189 }
2190
2191 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_id, intf_id);
2192
2193 // bcmbal_tm_sched_type
2194 // set the deafult policy to strict priority
2195 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, sched_type, BCMOLT_TM_SCHED_TYPE_SP);
2196
2197 // num_priorities: Max number of strict priority scheduling elements
Jason Huangb6843dc2019-07-22 17:46:06 +08002198 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, num_priorities, 8);
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002199
2200 // bcmbal_tm_shaping
2201 uint32_t cir = 1000000;
2202 uint32_t pir = 1000000;
2203 uint32_t burst = 65536;
Jason Huangb6843dc2019-07-22 17:46:06 +08002204 OPENOLT_LOG(INFO, openolt_log_id, "applying traffic shaping in %s pir=%u, burst=%u\n",
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002205 direction.c_str(), pir, burst);
2206 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, pir);
2207 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, burst);
2208 // FIXME: Setting CIR, results in BAL throwing error 'tm_sched minimum rate is not supported yet'
2209 // BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.cir, cir);
2210 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.pir, pir);
2211 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.burst, burst);
2212
2213 err = bcmolt_cfg_set(dev_id, &tm_sched_cfg.hdr);
2214 if (err) {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002215 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create %s scheduler, id %d, intf_id %d, err %d\n", \
2216 direction.c_str(), tm_sched_key.id, intf_id, err);
2217 return err;
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002218 }
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002219
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002220 OPENOLT_LOG(INFO, openolt_log_id, "Create %s scheduler success, id %d, intf_id %d\n", \
2221 direction.c_str(), tm_sched_key.id, intf_id);
2222 return BCM_ERR_OK;
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002223}
2224
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002225bcmos_errno CreateSched(std::string direction, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t port_no,
2226 uint32_t alloc_id, tech_profile::AdditionalBW additional_bw, uint32_t weight, uint32_t priority,
2227 tech_profile::SchedulingPolicy sched_policy, tech_profile::TrafficShapingInfo tf_sh_info) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002228
2229 bcmos_errno err;
2230
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002231 if (direction == downstream) {
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002232 bcmolt_tm_sched_cfg tm_sched_cfg;
2233 bcmolt_tm_sched_key tm_sched_key = {.id = 1};
2234 tm_sched_key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002235
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002236 // bcmbal_tm_sched_owner
2237 // In downstream it is sub_term scheduler
2238 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002239
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002240 /**< The output of the tm_sched object instance */
2241 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.type, BCMOLT_TM_SCHED_OUTPUT_TYPE_TM_SCHED);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002242
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002243 // bcmbal_tm_sched_parent
2244 // The parent for the sub_term scheduler is the PON scheduler in the downstream
2245 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.tm_sched.tm_sched_id, get_default_tm_sched_id(intf_id, direction));
2246 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.tm_sched.tm_sched_param.u.priority.priority, priority);
2247 /* removed by BAL v3.0, N/A - No direct attachment point of type ONU, same functionality may
2248 be achieved using the' virtual' type of attachment.
2249 tm_sched_owner.u.sub_term.intf_id = intf_id;
2250 tm_sched_owner.u.sub_term.sub_term_id = onu_id;
2251 */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002252
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002253 // bcmbal_tm_sched_type
2254 // set the deafult policy to strict priority
2255 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, sched_type, BCMOLT_TM_SCHED_TYPE_SP);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002256
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002257 // num_priorities: Max number of strict priority scheduling elements
2258 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, num_priorities, 8);
Jason Huangd33b4d82019-05-15 18:22:57 +08002259
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002260 // bcmbal_tm_shaping
2261 if (tf_sh_info.cir() >= 0 && tf_sh_info.pir() > 0) {
2262 uint32_t cir = tf_sh_info.cir();
2263 uint32_t pir = tf_sh_info.pir();
2264 uint32_t burst = tf_sh_info.pbs();
Jason Huangb6843dc2019-07-22 17:46:06 +08002265 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 -07002266 cir, pir, burst);
2267 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, pir);
2268 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, burst);
2269 // FIXME: Setting CIR, results in BAL throwing error 'tm_sched minimum rate is not supported yet'
2270 //BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.cir, cir);
2271 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.pir, pir);
2272 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.burst, burst);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002273 }
2274
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002275 err = bcmolt_cfg_set(dev_id, &tm_sched_cfg.hdr);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002276 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08002277 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create downstream subscriber scheduler, id %d, \
2278intf_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 -07002279 uni_id, port_no);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002280 return err;
2281 }
Jason Huangb6843dc2019-07-22 17:46:06 +08002282 OPENOLT_LOG(INFO, openolt_log_id, "Create downstream subscriber sched, id %d, intf_id %d, onu_id %d, \
2283uni_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 -08002284
2285 } else { //upstream
Jason Huangd33b4d82019-05-15 18:22:57 +08002286 bcmolt_itupon_alloc_cfg cfg;
Thiyagarajan Subramani0695c982019-06-05 07:30:50 -07002287 bcmolt_itupon_alloc_key key = { };
Jason Huangd33b4d82019-05-15 18:22:57 +08002288 key.pon_ni = intf_id;
2289 key.alloc_id = alloc_id;
Jason Huangb6843dc2019-07-22 17:46:06 +08002290 int bw_granularity = (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY;
2291 int pir_bw = tf_sh_info.pir();
2292 int cir_bw = tf_sh_info.cir();
2293 //offset to match bandwidth granularity
2294 int offset_pir_bw = pir_bw%bw_granularity;
2295 int offset_cir_bw = cir_bw%bw_granularity;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002296
Jason Huangb6843dc2019-07-22 17:46:06 +08002297 pir_bw = pir_bw - offset_pir_bw;
2298 cir_bw = cir_bw - offset_cir_bw;
2299
2300 BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
2301
2302 switch (additional_bw) {
2303 case 2: //AdditionalBW_BestEffort
2304 if (pir_bw == 0) {
2305 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
2306%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
2307 } else if (pir_bw < cir_bw) {
2308 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2309bandwidth (%d)\n", pir_bw, cir_bw);
2310 return BCM_ERR_PARM;
2311 } else if (pir_bw == cir_bw) {
2312 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
2313bandwidth for additional bandwidth eligibility of type best_effort\n");
2314 return BCM_ERR_PARM;
2315 }
2316 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_BEST_EFFORT);
2317 break;
2318 case 1: //AdditionalBW_NA
2319 if (pir_bw == 0) {
2320 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
2321%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
2322 return BCM_ERR_PARM;
2323 } else if (cir_bw == 0) {
2324 OPENOLT_LOG(ERROR, openolt_log_id, "Guaranteed bandwidth must be greater than zero for \
2325additional bandwidth eligibility of type Non-Assured (NA)\n");
2326 return BCM_ERR_PARM;
2327 } else if (pir_bw < cir_bw) {
2328 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2329bandwidth (%d)\n", pir_bw, cir_bw);
2330 return BCM_ERR_PARM;
2331 } else if (pir_bw == cir_bw) {
2332 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
2333bandwidth for additional bandwidth eligibility of type non_assured\n");
2334 return BCM_ERR_PARM;
2335 }
2336 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NON_ASSURED);
2337 break;
2338 case 0: //AdditionalBW_None
2339 if (pir_bw == 0) {
2340 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
234116000 bytes/sec\n");
2342 return BCM_ERR_PARM;
2343 } else if (cir_bw == 0) {
2344 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
2345for additional bandwidth eligibility of type None\n");
2346 return BCM_ERR_PARM;
2347 } else if (pir_bw > cir_bw) {
2348 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
2349for additional bandwidth eligibility of type None\n");
2350 OPENOLT_LOG(ERROR, openolt_log_id, "set Maximum bandwidth (%d) to Guaranteed \
2351bandwidth in None eligibility\n", pir_bw);
2352 cir_bw = pir_bw;
2353 } else if (pir_bw < cir_bw) {
2354 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2355bandwidth (%d)\n", pir_bw, cir_bw);
2356 OPENOLT_LOG(ERROR, openolt_log_id, "set Maximum bandwidth (%d) to Guaranteed \
2357bandwidth in None eligibility\n", pir_bw);
2358 cir_bw = pir_bw;
2359 }
2360 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NONE);
2361 break;
2362 default:
2363 return BCM_ERR_PARM;
2364 }
2365 /* CBR Real Time Bandwidth which require shaping of the bandwidth allocations
Jason Huangd33b4d82019-05-15 18:22:57 +08002366 in a fine granularity. */
2367 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_bw, 0);
2368 /* Fixed Bandwidth with no critical requirement of shaping */
2369 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_bw, 0);
2370 /* Dynamic bandwidth which the OLT is committed to allocate upon demand */
Jason Huangb6843dc2019-07-22 17:46:06 +08002371 BCMOLT_MSG_FIELD_SET(&cfg, sla.guaranteed_bw, cir_bw);
Jason Huangd33b4d82019-05-15 18:22:57 +08002372 /* Maximum allocated bandwidth allowed for this alloc ID */
Jason Huangb6843dc2019-07-22 17:46:06 +08002373 BCMOLT_MSG_FIELD_SET(&cfg, sla.maximum_bw, pir_bw);
Jason Huangd33b4d82019-05-15 18:22:57 +08002374 BCMOLT_MSG_FIELD_SET(&cfg, sla.alloc_type, BCMOLT_ALLOC_TYPE_NSR);
2375 /* Set to True for AllocID with CBR RT Bandwidth that requires compensation
2376 for skipped allocations during quiet window */
2377 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_compensation, BCMOS_FALSE);
2378 /**< Allocation Profile index for CBR non-RT Bandwidth */
2379 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_ap_index, 0);
2380 /**< Allocation Profile index for CBR RT Bandwidth */
2381 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_ap_index, 0);
2382 /**< Alloc ID Weight used in case of Extended DBA mode */
2383 BCMOLT_MSG_FIELD_SET(&cfg, sla.weight, 0);
2384 /**< Alloc ID Priority used in case of Extended DBA mode */
2385 BCMOLT_MSG_FIELD_SET(&cfg, sla.priority, 0);
Jason Huangb6843dc2019-07-22 17:46:06 +08002386 BCMOLT_MSG_FIELD_SET(&cfg, onu_id, onu_id);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002387
Jason Huangb6843dc2019-07-22 17:46:06 +08002388 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002389 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08002390 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d,\
2391port_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 -08002392 return err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002393 }
Jason Huangb6843dc2019-07-22 17:46:06 +08002394 OPENOLT_LOG(INFO, openolt_log_id, "Create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d, port_no %u, \
2395alloc_id %d\n", intf_id,onu_id,uni_id,port_no,alloc_id);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002396 }
2397
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002398 return BCM_ERR_OK;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002399}
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002400
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002401Status CreateTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
2402 uint32_t intf_id = traffic_scheds->intf_id();
2403 uint32_t onu_id = traffic_scheds->onu_id();
2404 uint32_t uni_id = traffic_scheds->uni_id();
2405 uint32_t port_no = traffic_scheds->port_no();
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002406 std::string direction;
2407 unsigned int alloc_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002408 tech_profile::SchedulerConfig sched_config;
2409 tech_profile::AdditionalBW additional_bw;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002410 uint32_t priority;
2411 uint32_t weight;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002412 tech_profile::SchedulingPolicy sched_policy;
2413 tech_profile::TrafficShapingInfo traffic_shaping_info;
2414 bcmos_errno err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002415
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002416 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
2417 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002418
2419 direction = GetDirection(traffic_sched.direction());
2420 if (direction.compare("direction-not-supported") == 0)
2421 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2422
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002423 alloc_id = traffic_sched.alloc_id();
2424 sched_config = traffic_sched.scheduler();
2425 additional_bw = sched_config.additional_bw();
2426 priority = sched_config.priority();
2427 weight = sched_config.weight();
2428 sched_policy = sched_config.sched_policy();
2429 traffic_shaping_info = traffic_sched.traffic_shaping_info();
2430 err = CreateSched(direction, intf_id, onu_id, uni_id, port_no, alloc_id, additional_bw, weight, priority,
2431 sched_policy, traffic_shaping_info);
2432 if (err) {
2433 return bcm_to_grpc_err(err, "Failed to create scheduler");
2434 }
Girish Gowdru1cdf6ce2018-08-27 02:43:02 -07002435 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002436 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002437}
Jonathan Davis70c21812018-07-19 15:32:10 -04002438
Jason Huangb6843dc2019-07-22 17:46:06 +08002439bcmos_errno RemoveSched(int intf_id, int onu_id, int uni_id, int alloc_id, std::string direction) {
Jonathan Davis70c21812018-07-19 15:32:10 -04002440
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002441 bcmos_errno err;
Jason Huangb6843dc2019-07-22 17:46:06 +08002442
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002443 if (direction == upstream) {
Jason Huangd33b4d82019-05-15 18:22:57 +08002444 bcmolt_itupon_alloc_cfg cfg;
2445 bcmolt_itupon_alloc_key key = { };
2446 key.pon_ni = intf_id;
Jason Huangb6843dc2019-07-22 17:46:06 +08002447 key.alloc_id = alloc_id;
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002448
Jason Huangd33b4d82019-05-15 18:22:57 +08002449 BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
Jason Huangb6843dc2019-07-22 17:46:06 +08002450 err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
Jason Huangd33b4d82019-05-15 18:22:57 +08002451 if (err) {
Jason Huangb6843dc2019-07-22 17:46:06 +08002452 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 +08002453 direction.c_str(), intf_id, alloc_id, err);
Jason Huangd33b4d82019-05-15 18:22:57 +08002454 return err;
2455 }
Jason Huangb6843dc2019-07-22 17:46:06 +08002456 OPENOLT_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, intf_id %d, alloc_id %d\n", \
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002457 direction.c_str(), intf_id, alloc_id);
Jason Huangd33b4d82019-05-15 18:22:57 +08002458 } else if (direction == downstream) {
2459 bcmolt_tm_sched_cfg cfg;
2460 bcmolt_tm_sched_key key = { };
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002461
Jason Huangd33b4d82019-05-15 18:22:57 +08002462 if (is_tm_sched_id_present(intf_id, onu_id, uni_id, direction)) {
2463 key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2464 } else {
Jason Huangb6843dc2019-07-22 17:46:06 +08002465 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 +08002466 return BCM_ERR_OK;
2467 }
2468 BCMOLT_CFG_INIT(&cfg, tm_sched, key);
2469 err = bcmolt_cfg_clear(dev_id, &(cfg.hdr));
2470 if (err) {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002471 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove scheduler, direction = %s, id %d, intf_id %d, onu_id %d\n", \
2472 direction.c_str(), key.id, intf_id, onu_id);
Jason Huangd33b4d82019-05-15 18:22:57 +08002473 return err;
2474 }
Jason Huangb6843dc2019-07-22 17:46:06 +08002475 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 +08002476 direction.c_str(), key.id, intf_id, onu_id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002477 }
2478
2479 free_tm_sched_id(intf_id, onu_id, uni_id, direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002480 return BCM_ERR_OK;
2481}
2482
2483Status RemoveTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
2484 uint32_t intf_id = traffic_scheds->intf_id();
2485 uint32_t onu_id = traffic_scheds->onu_id();
2486 uint32_t uni_id = traffic_scheds->uni_id();
2487 std::string direction;
2488 bcmos_errno err;
2489
2490 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
2491 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002492
2493 direction = GetDirection(traffic_sched.direction());
2494 if (direction.compare("direction-not-supported") == 0)
2495 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2496
Jason Huangb6843dc2019-07-22 17:46:06 +08002497 int alloc_id = traffic_sched.alloc_id();
2498 err = RemoveSched(intf_id, onu_id, uni_id, alloc_id, direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002499 if (err) {
2500 return bcm_to_grpc_err(err, "error-removing-traffic-scheduler");
2501 }
2502 }
2503 return Status::OK;
2504}
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002505
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002506bcmos_errno CreateTrafficQueueMappingProfile(uint32_t sched_id, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, \
2507 std::string direction, std::vector<uint32_t> tmq_map_profile) {
2508 bcmos_errno err;
2509 bcmolt_tm_qmp_cfg tm_qmp_cfg;
2510 bcmolt_tm_qmp_key tm_qmp_key;
2511 bcmolt_arr_u8_8 pbits_to_tmq_id = {0};
2512
2513 int tm_qmp_id = get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id, tmq_map_profile);
2514 if (tm_qmp_id == -1) {
2515 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create tm queue mapping profile. Max allowed profile count is 16.\n");
2516 }
2517
2518 tm_qmp_key.id = tm_qmp_id;
2519 for (uint32_t priority=0; priority<tmq_map_profile.size(); priority++) {
2520 pbits_to_tmq_id.arr[priority] = tmq_map_profile[priority];
2521 }
2522
2523 BCMOLT_CFG_INIT(&tm_qmp_cfg, tm_qmp, tm_qmp_key);
2524 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, type, BCMOLT_TM_QMP_TYPE_PBITS);
2525 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, pbits_to_tmq_id, pbits_to_tmq_id);
2526 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, ref_count, 0);
2527 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, state, BCMOLT_CONFIG_STATE_CONFIGURED);
2528
2529 err = bcmolt_cfg_set(dev_id, &tm_qmp_cfg.hdr);
2530 if (err) {
2531 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create tm queue mapping profile, id %d\n", \
2532 tm_qmp_key.id);
2533 return err;
2534 }
2535
2536 OPENOLT_LOG(INFO, openolt_log_id, "Create tm queue mapping profile success, id %d\n", \
2537 tm_qmp_key.id);
2538 return BCM_ERR_OK;
2539}
2540
2541bcmos_errno RemoveTrafficQueueMappingProfile(uint32_t tm_qmp_id) {
2542 bcmos_errno err;
2543 bcmolt_tm_qmp_cfg tm_qmp_cfg;
2544 bcmolt_tm_qmp_key tm_qmp_key;
2545 tm_qmp_key.id = tm_qmp_id;
2546
2547 BCMOLT_CFG_INIT(&tm_qmp_cfg, tm_qmp, tm_qmp_key);
2548 err = bcmolt_cfg_clear(dev_id, &tm_qmp_cfg.hdr);
2549 if (err) {
2550 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove tm queue mapping profile, id %d\n", \
2551 tm_qmp_key.id);
2552 return err;
2553 }
2554
2555 OPENOLT_LOG(INFO, openolt_log_id, "Remove tm queue mapping profile success, id %d\n", \
2556 tm_qmp_key.id);
2557 return BCM_ERR_OK;
2558}
2559
2560bcmos_errno CreateDefaultQueue(uint32_t intf_id, const std::string direction) {
2561 bcmos_errno err;
2562
2563 /* Create 4 Queues on given PON/NNI scheduler */
2564 for (int queue_id = 0; queue_id < 4; queue_id++) {
2565 bcmolt_tm_queue_cfg tm_queue_cfg;
2566 bcmolt_tm_queue_key tm_queue_key = {};
2567 tm_queue_key.sched_id = get_default_tm_sched_id(intf_id, direction);
2568 tm_queue_key.id = queue_id;
2569 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE)
2570 tm_queue_key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2571 else
2572 tm_queue_key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2573
2574 BCMOLT_CFG_INIT(&tm_queue_cfg, tm_queue, tm_queue_key);
2575 BCMOLT_MSG_FIELD_SET(&tm_queue_cfg, tm_sched_param.type, BCMOLT_TM_SCHED_PARAM_TYPE_PRIORITY);
2576 BCMOLT_MSG_FIELD_SET(&tm_queue_cfg, tm_sched_param.u.priority.priority, queue_id);
2577
2578 err = bcmolt_cfg_set(dev_id, &tm_queue_cfg.hdr);
2579 if (err) {
2580 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create %s tm queue, id %d, sched_id %d, tm_q_set_id %d\n", \
2581 direction.c_str(), tm_queue_key.id, tm_queue_key.sched_id, tm_queue_key.tm_q_set_id);
2582 return err;
2583 }
2584
2585 OPENOLT_LOG(INFO, openolt_log_id, "Create %s tm_queue success, id %d, sched_id %d, tm_q_set_id %d\n", \
2586 direction.c_str(), tm_queue_key.id, tm_queue_key.sched_id, tm_queue_key.tm_q_set_id);
2587 }
2588 return BCM_ERR_OK;
2589}
2590
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002591bcmos_errno CreateQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
2592 uint32_t gemport_id) {
2593 bcmos_errno err;
Jason Huangd33b4d82019-05-15 18:22:57 +08002594 bcmolt_tm_queue_cfg cfg;
2595 bcmolt_tm_queue_key key = { };
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002596 OPENOLT_LOG(INFO, openolt_log_id, "creating %s queue. access_intf_id = %d, onu_id = %d, uni_id = %d \
2597gemport_id = %d\n", direction.c_str(), access_intf_id, onu_id, uni_id, gemport_id);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002598
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002599 key.sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2600 get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
2601
2602 if (priority > 7) {
2603 return BCM_ERR_RANGE;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002604 }
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002605
2606 /* FIXME: The upstream queues have to be created once only.
2607 The upstream queues on the NNI scheduler are shared by all subscribers.
2608 When the first scheduler comes in, the queues get created, and are re-used by all others.
2609 Also, these queues should be present until the last subscriber exits the system.
2610 One solution is to have these queues always, i.e., create it as soon as OLT is enabled.
2611
2612 There is one queue per gem port and Queue ID is fetched based on priority_q configuration
2613 for each GEM in TECH PROFILE */
2614 key.id = queue_id_list[priority];
2615
Jason Huangb6843dc2019-07-22 17:46:06 +08002616 OPENOLT_LOG(INFO, openolt_log_id, "queue assigned queue_id = %d\n", key.id);
Girish Gowdru36501552019-05-01 23:47:58 -07002617
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002618 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE)
2619 key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2620 else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE)
2621 key.tm_q_set_id = get_tm_qmp_id(key.sched_id, access_intf_id, onu_id, uni_id);
2622 else
2623 key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2624
Jason Huangd33b4d82019-05-15 18:22:57 +08002625 BCMOLT_CFG_INIT(&cfg, tm_queue, key);
2626 BCMOLT_MSG_FIELD_SET(&cfg, tm_sched_param.u.priority.priority, priority);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002627
Jason Huangd33b4d82019-05-15 18:22:57 +08002628 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002629 if (err) {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002630 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create subscriber tm queue, direction = %s, id %d, \
2631sched_id %d, tm_q_set_id %d, intf_id %d, onu_id %d, uni_id %d, err %d\n", \
2632 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 -08002633 return err;
2634 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06002635
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002636 OPENOLT_LOG(INFO, openolt_log_id, "Created tm_queue, direction %s, id %d, sched_id %d, tm_q_set_id %d, \
2637intf_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 -08002638 return BCM_ERR_OK;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002639}
2640
2641Status CreateTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
2642 uint32_t intf_id = traffic_queues->intf_id();
2643 uint32_t onu_id = traffic_queues->onu_id();
2644 uint32_t uni_id = traffic_queues->uni_id();
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002645 uint32_t sched_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002646 std::string direction;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002647 bcmos_errno err;
2648
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002649 qos_type = (traffic_queues->traffic_queues_size() > 1) ? \
2650 BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
2651
2652 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2653 uint32_t queues_priority_q[traffic_queues->traffic_queues_size()] = {0};
2654 std::string queues_pbit_map[traffic_queues->traffic_queues_size()];
2655 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2656 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
2657
2658 direction = GetDirection(traffic_queue.direction());
2659 if (direction.compare("direction-not-supported") == 0)
2660 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2661
2662 queues_priority_q[i] = traffic_queue.priority();
2663 queues_pbit_map[i] = traffic_queue.pbit_map();
2664 }
2665
2666 std::vector<uint32_t> tmq_map_profile(8, 0);
2667 tmq_map_profile = get_tmq_map_profile(get_valid_queues_pbit_map(queues_pbit_map, COUNT_OF(queues_pbit_map)), \
2668 queues_priority_q, COUNT_OF(queues_priority_q));
2669 sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2670 get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2671
2672 int tm_qmp_id = get_tm_qmp_id(tmq_map_profile);
2673 if (tm_qmp_id == -1) {
2674 CreateTrafficQueueMappingProfile(sched_id, intf_id, onu_id, uni_id, direction, tmq_map_profile);
2675 } else if (tm_qmp_id != -1 && get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id) == -1) {
2676 OPENOLT_LOG(INFO, openolt_log_id, "tm queue mapping profile present already with id %d\n", tm_qmp_id);
2677 update_sched_qmp_id_map(sched_id, intf_id, onu_id, uni_id, tm_qmp_id);
2678 }
2679 }
2680
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002681 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2682 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002683
2684 direction = GetDirection(traffic_queue.direction());
2685 if (direction.compare("direction-not-supported") == 0)
2686 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2687
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002688 err = CreateQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002689
Girish Gowdru36501552019-05-01 23:47:58 -07002690 // If the queue exists already, lets not return failure and break the loop.
2691 if (err && err != BCM_ERR_ALREADY) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002692 return bcm_to_grpc_err(err, "Failed to create queue");
2693 }
2694 }
2695 return Status::OK;
2696}
2697
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002698bcmos_errno RemoveQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
2699 uint32_t gemport_id) {
Jason Huangd33b4d82019-05-15 18:22:57 +08002700 bcmolt_tm_queue_cfg cfg;
2701 bcmolt_tm_queue_key key = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002702 bcmos_errno err;
2703
2704 if (direction == downstream) {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002705 if (is_tm_sched_id_present(access_intf_id, onu_id, uni_id, direction)) {
Jason Huangd33b4d82019-05-15 18:22:57 +08002706 key.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002707 key.id = queue_id_list[priority];
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002708 } else {
Jason Huangb6843dc2019-07-22 17:46:06 +08002709 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 -08002710 return BCM_ERR_OK;
2711 }
2712 } else {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002713 /* In the upstream we use pre-created queues on the NNI scheduler that are used by all subscribers.
2714 They should not be removed. So, lets return OK. */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002715 return BCM_ERR_OK;
2716 }
2717
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002718 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE)
2719 key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2720 else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE)
2721 key.tm_q_set_id = get_tm_qmp_id(key.sched_id, access_intf_id, onu_id, uni_id);
2722 else
2723 key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2724
Jason Huangd33b4d82019-05-15 18:22:57 +08002725 BCMOLT_CFG_INIT(&cfg, tm_queue, key);
Jason Huangd33b4d82019-05-15 18:22:57 +08002726 err = bcmolt_cfg_clear(dev_id, &(cfg.hdr));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002727 if (err) {
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002728 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove queue, direction = %s, id %d, sched_id %d, \
2729tm_q_set_id %d, intf_id %d, onu_id %d, uni_id %d\n",
2730 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 -08002731 return err;
2732 }
2733
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002734 OPENOLT_LOG(INFO, openolt_log_id, "Removed tm_queue, direction %s, id %d, sched_id %d, tm_q_set_id %d, \
2735intf_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 -08002736
2737 return BCM_ERR_OK;
2738}
2739
2740Status RemoveTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
2741 uint32_t intf_id = traffic_queues->intf_id();
2742 uint32_t onu_id = traffic_queues->onu_id();
2743 uint32_t uni_id = traffic_queues->uni_id();
2744 uint32_t port_no = traffic_queues->port_no();
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002745 uint32_t sched_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002746 std::string direction;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002747 bcmos_errno err;
2748
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002749 qos_type = (traffic_queues->traffic_queues_size() > 1) ? \
2750 BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
2751
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002752 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2753 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002754
2755 direction = GetDirection(traffic_queue.direction());
2756 if (direction.compare("direction-not-supported") == 0)
2757 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2758
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002759 err = RemoveQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
2760 if (err) {
2761 return bcm_to_grpc_err(err, "Failed to remove queue");
2762 }
Jonathan Davis70c21812018-07-19 15:32:10 -04002763 }
2764
Thiyagarajan Subramani1f1280b2019-08-13 18:41:19 +08002765 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))) {
2766 sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2767 get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2768
2769 int tm_qmp_id = get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id);
2770 if (free_tm_qmp_id(sched_id, intf_id, onu_id, uni_id, tm_qmp_id)) {
2771 RemoveTrafficQueueMappingProfile(tm_qmp_id);
2772 }
2773 }
Jonathan Davis70c21812018-07-19 15:32:10 -04002774 return Status::OK;
Jonathan Davis70c21812018-07-19 15:32:10 -04002775}