blob: 43ce76f02d69face6bba6a4aaeb0d08e69b2df4d [file] [log] [blame]
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001/*
Girish Gowdraa707e7c2019-11-07 11:36:13 +05302 * Copyright 2018-present Open Networking Foundation
Shad Ansarib7b0ced2018-05-11 21:53:32 +00003
Girish Gowdraa707e7c2019-11-07 11:36:13 +05304 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Shad Ansarib7b0ced2018-05-11 21:53:32 +00007
Girish Gowdraa707e7c2019-11-07 11:36:13 +05308 * http://www.apache.org/licenses/LICENSE-2.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00009
Girish Gowdraa707e7c2019-11-07 11:36:13 +053010 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +000016
17#include <iostream>
18#include <memory>
19#include <string>
20
21#include "Queue.h"
Shad Ansarib7b0ced2018-05-11 21:53:32 +000022#include <sstream>
Nicolas Palpacuer9c352082018-08-14 16:37:14 -040023#include <chrono>
24#include <thread>
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -080025#include <bitset>
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000026#include <inttypes.h>
Jason Huangbf45ffb2019-10-30 17:29:02 +080027#include <unistd.h>
Shad Ansarib7b0ced2018-05-11 21:53:32 +000028
Craig Lutgen88a22ad2018-10-04 12:30:46 -050029#include "device.h"
Shad Ansarib7b0ced2018-05-11 21:53:32 +000030#include "core.h"
31#include "indications.h"
Nicolas Palpacuer0f19b1a2018-06-07 17:29:31 -040032#include "stats_collection.h"
Nicolas Palpacuer73222e02018-07-16 12:20:26 -040033#include "error_format.h"
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -040034#include "state.h"
Craig Lutgen88a22ad2018-10-04 12:30:46 -050035#include "utils.h"
Shad Ansarib7b0ced2018-05-11 21:53:32 +000036
37extern "C"
38{
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000039#include <bcmolt_api.h>
40#include <bcmolt_host_api.h>
41#include <bcmolt_api_model_supporting_enums.h>
42
43#include <bal_version.h>
44#include <bcmolt_api_conn_mgr.h>
45//CLI header files
46#include <bcmcli_session.h>
47#include <bcmcli.h>
48#include <bcm_api_cli.h>
49
50#include <bcmos_common.h>
51#include <bcm_config.h>
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -040052// FIXME : dependency problem
53// #include <bcm_common_gpon.h>
Nicolas Palpacuer967438f2018-09-07 14:41:54 -040054// #include <bcm_dev_log_task.h>
Shad Ansarib7b0ced2018-05-11 21:53:32 +000055}
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000056
Shad Ansarib7b0ced2018-05-11 21:53:32 +000057
Nicolas Palpacuer967438f2018-09-07 14:41:54 -040058dev_log_id openolt_log_id = bcm_dev_log_id_register("OPENOLT", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
59dev_log_id omci_log_id = bcm_dev_log_id_register("OMCI", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
60
Craig Lutgen88a22ad2018-10-04 12:30:46 -050061#define BAL_RSC_MANAGER_BASE_TM_SCHED_ID 16384
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -080062#define MAX_TM_QUEUE_ID 8192
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000063#define MAX_TM_QMP_ID 16
64#define TMQ_MAP_PROFILE_SIZE 8
65#define MAX_TM_SCHED_ID 1023
66#define MAX_SUBS_TM_SCHED_ID (MAX_SUPPORTED_PON == 16 ? MAX_TM_SCHED_ID-4-16 : MAX_TM_SCHED_ID-10-64)
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -080067#define EAP_ETHER_TYPE 34958
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000068#define XGS_BANDWIDTH_GRANULARITY 16000
69#define GPON_BANDWIDTH_GRANULARITY 32000
70#define FILL_ARRAY(ARRAY,START,END,VALUE) for(int i=START;i<END;ARRAY[i++]=VALUE);
71#define COUNT_OF(array) (sizeof(array) / sizeof(array[0]))
72
73#define GET_FLOW_INTERFACE_TYPE(type) \
74 (type == BCMOLT_FLOW_INTERFACE_TYPE_PON) ? "PON" : \
75 (type == BCMOLT_FLOW_INTERFACE_TYPE_NNI) ? "NNI" : \
76 (type == BCMOLT_FLOW_INTERFACE_TYPE_HOST) ? "HOST" : "unknown"
77#define GET_PKT_TAG_TYPE(type) \
78 (type == BCMOLT_PKT_TAG_TYPE_UNTAGGED) ? "UNTAG" : \
79 (type == BCMOLT_PKT_TAG_TYPE_SINGLE_TAG) ? "SINGLE_TAG" : \
80 (type == BCMOLT_PKT_TAG_TYPE_DOUBLE_TAG) ? "DOUBLE_TAG" : "unknown"
Nicolas Palpacuer967438f2018-09-07 14:41:54 -040081
Craig Lutgen88a22ad2018-10-04 12:30:46 -050082static unsigned int num_of_nni_ports = 0;
83static unsigned int num_of_pon_ports = 0;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000084static std::string intf_technologies[MAX_SUPPORTED_PON];
Craig Lutgen88a22ad2018-10-04 12:30:46 -050085static const std::string UNKNOWN_TECH("unknown");
Craig Lutgenb2601f02018-10-23 13:04:31 -050086static const std::string MIXED_TECH("mixed");
87static std::string board_technology(UNKNOWN_TECH);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000088static std::string chip_family(UNKNOWN_TECH);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -080089static unsigned int OPENOLT_FIELD_LEN = 200;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000090static std::string firmware_version = "Openolt.2019.07.01";
Nicolas Palpacuerdff96792018-09-06 14:59:32 -040091
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000092const uint32_t tm_upstream_sched_id_start = (MAX_SUPPORTED_PON == 16 ? \
93 MAX_TM_SCHED_ID-3 : MAX_TM_SCHED_ID-9);
94const uint32_t tm_downstream_sched_id_start = (MAX_SUPPORTED_PON == 16 ? \
95 tm_upstream_sched_id_start-16 : tm_upstream_sched_id_start-64);
96
97/* Max Queue ID supported is 7 so based on priority_q configured for GEMPORTS
98in TECH PROFILE respective Queue ID from this list will be used for both
99US and DS Queues*/
100const uint32_t queue_id_list[8] = {0, 1, 2, 3, 4, 5, 6, 7};
101
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700102const std::string upstream = "upstream";
103const std::string downstream = "downstream";
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000104bcmolt_oltid dev_id = 0;
105
106/* Current session */
107static bcmcli_session *current_session;
108static bcmcli_entry *api_parent_dir;
109bcmos_bool status_bcm_cli_quit = BCMOS_FALSE;
110bcmos_task bal_cli_thread;
111const char *bal_cli_thread_name = "bal_cli_thread";
112uint16_t flow_id_counters = 0;
113int flow_id_data[16384][2];
114
115/* QOS Type has been pre-defined as Fixed Queue but it will be updated based on number of GEMPORTS
116 associated for a given subscriber. If GEM count = 1 for a given subscriber, qos_type will be Fixed Queue
117 else Priority to Queue */
118bcmolt_egress_qos_type qos_type = BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700119
Shad Ansariedef2132018-08-10 22:14:50 +0000120State state;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400121
Craig Lutgen967a1d02018-11-27 10:41:51 -0600122static std::map<uint32_t, uint32_t> flowid_to_port; // For mapping upstream flows to logical ports
123static std::map<uint32_t, uint32_t> flowid_to_gemport; // For mapping downstream flows into gemports
124static std::map<uint32_t, std::set<uint32_t> > port_to_flows; // For mapping logical ports to downstream flows
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800125
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000126/* This represents the Key to 'sched_map' map.
127 Represents (pon_intf_id, onu_id, uni_id, direction) */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800128typedef std::tuple<uint32_t, uint32_t, uint32_t, std::string> sched_map_key_tuple;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000129/* 'sched_map' maps sched_map_key_tuple to DBA (Upstream) or
130 Subscriber (Downstream) Scheduler ID */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800131static std::map<sched_map_key_tuple, int> sched_map;
132
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000133/* This represents the Key to 'sched_qmp_id_map' map.
134Represents (sched_id, pon_intf_id, onu_id, uni_id) */
135typedef std::tuple<uint32_t, uint32_t, uint32_t, uint32_t> sched_qmp_id_map_key_tuple;
136/* 'sched_qmp_id_map' maps sched_qmp_id_map_key_tuple to TM Queue Mapping Profile ID */
137static std::map<sched_qmp_id_map_key_tuple, int> sched_qmp_id_map;
138/* 'qmp_id_to_qmp_map' maps TM Queue Mapping Profile ID to TM Queue Mapping Profile */
139static std::map<int, std::vector < uint32_t > > qmp_id_to_qmp_map;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800140
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800141std::bitset<MAX_TM_SCHED_ID> tm_sched_bitset;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000142std::bitset<MAX_TM_QMP_ID> tm_qmp_bitset;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800143
144static bcmos_fastlock data_lock;
Craig Lutgen967a1d02018-11-27 10:41:51 -0600145
146#define MIN_ALLOC_ID_GPON 256
147#define MIN_ALLOC_ID_XGSPON 1024
148
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800149static bcmos_errno CreateSched(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, \
150 uint32_t port_no, uint32_t alloc_id, tech_profile::AdditionalBW additional_bw, uint32_t weight, \
151 uint32_t priority, tech_profile::SchedulingPolicy sched_policy,
152 tech_profile::TrafficShapingInfo traffic_shaping_info);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000153static bcmos_errno RemoveSched(int intf_id, int onu_id, int uni_id, int alloc_id, std::string direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800154static bcmos_errno CreateQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, \
155 uint32_t priority, uint32_t gemport_id);
156static bcmos_errno RemoveQueue(std::string direction, int intf_id, int onu_id, int uni_id, uint32_t port_no, int alloc_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000157static bcmos_errno CreateDefaultSched(uint32_t intf_id, const std::string direction);
158static bcmos_errno CreateDefaultQueue(uint32_t intf_id, const std::string direction);
159
160uint16_t get_dev_id(void) {
161 return dev_id;
162}
Shad Ansari627b5782018-08-13 22:49:32 +0000163
Jason Huangbf45ffb2019-10-30 17:29:02 +0800164// Stubbed defntion of bcmolt_cfg_get required for unit-test
165extern bcmos_errno bcmolt_cfg_get_stub(bcmolt_oltid olt_id, void* ptr);
166
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800167/**
168* Returns the default NNI (Upstream direction) or PON (Downstream direction) scheduler
169* Every NNI port and PON port have default scheduler.
170* The NNI0 default scheduler ID is 18432, and NNI1 is 18433 and so on.
171* Similarly, PON0 default scheduler ID is 16384. PON1 is 16385 and so on.
172*
173* @param intf_id NNI or PON interface ID
174* @param direction "upstream" or "downstream"
175*
176* @return default scheduler ID for the given interface.
177*/
178static inline int get_default_tm_sched_id(int intf_id, std::string direction) {
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700179 if (direction.compare(upstream) == 0) {
180 return tm_upstream_sched_id_start + intf_id;
181 } else if (direction.compare(downstream) == 0) {
182 return tm_downstream_sched_id_start + intf_id;
183 }
184 else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000185 OPENOLT_LOG(ERROR, openolt_log_id, "invalid direction - %s\n", direction.c_str());
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700186 return 0;
187 }
188}
189
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800190/**
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800191* Gets a unique tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
192* The tm_sched_id is locally cached in a map, so that it can rendered when necessary.
193* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
194*
195* @param intf_id NNI or PON intf ID
196* @param onu_id ONU ID
197* @param uni_id UNI ID
198* @param gemport_id GEM Port ID
199* @param direction Upstream or downstream
200*
201* @return tm_sched_id
202*/
203uint32_t get_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
204 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
205 int sched_id = -1;
206
207 std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
208 if (it != sched_map.end()) {
209 sched_id = it->second;
210 }
211 if (sched_id != -1) {
212 return sched_id;
213 }
214
215 bcmos_fastlock_lock(&data_lock);
216 // Complexity of O(n). Is there better way that can avoid linear search?
217 for (sched_id = 0; sched_id < MAX_TM_SCHED_ID; sched_id++) {
218 if (tm_sched_bitset[sched_id] == 0) {
219 tm_sched_bitset[sched_id] = 1;
220 break;
221 }
222 }
223 bcmos_fastlock_unlock(&data_lock, 0);
224
225 if (sched_id < MAX_TM_SCHED_ID) {
226 bcmos_fastlock_lock(&data_lock);
227 sched_map[key] = sched_id;
228 bcmos_fastlock_unlock(&data_lock, 0);
229 return sched_id;
230 } else {
231 return -1;
232 }
233}
234
235/**
236* Free tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
237*
238* @param intf_id NNI or PON intf ID
239* @param onu_id ONU ID
240* @param uni_id UNI ID
241* @param gemport_id GEM Port ID
242* @param direction Upstream or downstream
243*/
244void free_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
245 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
246 std::map<sched_map_key_tuple, int>::const_iterator it;
247 bcmos_fastlock_lock(&data_lock);
248 it = sched_map.find(key);
249 if (it != sched_map.end()) {
250 tm_sched_bitset[it->second] = 0;
251 sched_map.erase(it);
252 }
253 bcmos_fastlock_unlock(&data_lock, 0);
254}
255
256bool is_tm_sched_id_present(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
257 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000258 std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
259 if (it != sched_map.end()) {
260 return true;
261 }
262 return false;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800263}
264
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000265/**
266* Check whether given two tm qmp profiles are equal or not
267*
268* @param tmq_map_profileA <vector> TM QUEUE MAPPING PROFILE
269* @param tmq_map_profileB <vector> TM QUEUE MAPPING PROFILE
270*
271* @return boolean, true if given tmq_map_profiles are equal else false
272*/
273
274bool check_tm_qmp_equality(std::vector<uint32_t> tmq_map_profileA, std::vector<uint32_t> tmq_map_profileB) {
275 for (uint32_t i = 0; i < TMQ_MAP_PROFILE_SIZE; i++) {
276 if (tmq_map_profileA[i] != tmq_map_profileB[i]) {
277 return false;
278 }
279 }
280 return true;
Shad Ansari627b5782018-08-13 22:49:32 +0000281}
282
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000283/**
284* Modifies given queues_pbit_map to parsable format
285* e.g: Modifes "0b00000101" to "10100000"
286*
287* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
288* @param size Queue count
289*
290* @return string queues_pbit_map
291*/
292std::string* get_valid_queues_pbit_map(std::string *queues_pbit_map, uint32_t size) {
293 for(uint32_t i=0; i < size; i++) {
294 /* Deletes 2 characters from index number 0 */
295 queues_pbit_map[i].erase(0, 2);
296 std::reverse(queues_pbit_map[i].begin(), queues_pbit_map[i].end());
297 }
298 return queues_pbit_map;
299}
300
301/**
302* Creates TM QUEUE MAPPING PROFILE for given queues_pbit_map and queues_priority_q
303*
304* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
305* @param queues_priority_q PRIORITY_Q configured for each GEM in TECH PROFILE
306* @param size Queue count
307*
308* @return <vector> TM QUEUE MAPPING PROFILE
309*/
310std::vector<uint32_t> get_tmq_map_profile(std::string *queues_pbit_map, uint32_t *queues_priority_q, uint32_t size) {
311 std::vector<uint32_t> tmq_map_profile(8,0);
312
313 for(uint32_t i=0; i < size; i++) {
314 for (uint32_t j = 0; j < queues_pbit_map[i].size(); j++) {
315 if (queues_pbit_map[i][j]=='1') {
316 tmq_map_profile.at(j) = queue_id_list[queues_priority_q[i]];
317 }
318 }
319 }
320 return tmq_map_profile;
321}
322
323/**
324* Gets corresponding tm_qmp_id for a given tmq_map_profile
325*
326* @param <vector> TM QUEUE MAPPING PROFILE
327*
328* @return tm_qmp_id
329*/
330int get_tm_qmp_id(std::vector<uint32_t> tmq_map_profile) {
331 int tm_qmp_id = -1;
332
333 std::map<int, std::vector < uint32_t > >::const_iterator it = qmp_id_to_qmp_map.begin();
334 while(it != qmp_id_to_qmp_map.end()) {
335 if(check_tm_qmp_equality(tmq_map_profile, it->second)) {
336 tm_qmp_id = it->first;
337 break;
338 }
339 it++;
340 }
341 return tm_qmp_id;
342}
343
344/**
345* Updates sched_qmp_id_map with given sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id
346*
347* @param upstream/downstream sched_id
348* @param PON intf ID
349* @param onu_id ONU ID
350* @param uni_id UNI ID
351* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
352*/
353void update_sched_qmp_id_map(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
354 uint32_t uni_id, int tm_qmp_id) {
355 bcmos_fastlock_lock(&data_lock);
356 sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
357 sched_qmp_id_map.insert(make_pair(key, tm_qmp_id));
358 bcmos_fastlock_unlock(&data_lock, 0);
359}
360
361/**
362* Gets corresponding tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
363*
364* @param upstream/downstream sched_id
365* @param PON intf ID
366* @param onu_id ONU ID
367* @param uni_id UNI ID
368*
369* @return tm_qmp_id
370*/
371int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id) {
372 sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
373 int tm_qmp_id = -1;
374
375 std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
376 if (it != sched_qmp_id_map.end()) {
377 tm_qmp_id = it->second;
378 }
379 return tm_qmp_id;
380}
381
382/**
383* Gets a unique tm_qmp_id for a given tmq_map_profile
384* The tm_qmp_id is locally cached in a map, so that it can be rendered when necessary.
385* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
386*
387* @param upstream/downstream sched_id
388* @param PON intf ID
389* @param onu_id ONU ID
390* @param uni_id UNI ID
391* @param <vector> TM QUEUE MAPPING PROFILE
392*
393* @return tm_qmp_id
394*/
395int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id, \
396 std::vector<uint32_t> tmq_map_profile) {
397 int tm_qmp_id;
398
399 bcmos_fastlock_lock(&data_lock);
400 /* Complexity of O(n). Is there better way that can avoid linear search? */
401 for (tm_qmp_id = 0; tm_qmp_id < MAX_TM_QMP_ID; tm_qmp_id++) {
402 if (tm_qmp_bitset[tm_qmp_id] == 0) {
403 tm_qmp_bitset[tm_qmp_id] = 1;
404 break;
405 }
406 }
407 bcmos_fastlock_unlock(&data_lock, 0);
408
409 if (tm_qmp_id < MAX_TM_QMP_ID) {
410 bcmos_fastlock_lock(&data_lock);
411 qmp_id_to_qmp_map.insert(make_pair(tm_qmp_id, tmq_map_profile));
412 bcmos_fastlock_unlock(&data_lock, 0);
413 update_sched_qmp_id_map(sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id);
414 return tm_qmp_id;
415 } else {
416 return -1;
417 }
418}
419
420/**
421* Free tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
422*
423* @param upstream/downstream sched_id
424* @param PON intf ID
425* @param onu_id ONU ID
426* @param uni_id UNI ID
427* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
428*
429* @return boolean, true if no more reference for TM QMP else false
430*/
431bool free_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
432 uint32_t uni_id, int tm_qmp_id) {
433 bool result;
434 sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
435 std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
436 bcmos_fastlock_lock(&data_lock);
437 if (it != sched_qmp_id_map.end()) {
438 sched_qmp_id_map.erase(it);
439 }
440 bcmos_fastlock_unlock(&data_lock, 0);
441
442 uint32_t tm_qmp_ref_count = 0;
443 std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it2 = sched_qmp_id_map.begin();
444 while(it2 != sched_qmp_id_map.end()) {
445 if(it2->second == tm_qmp_id) {
446 tm_qmp_ref_count++;
447 }
448 it2++;
449 }
450
451 if (tm_qmp_ref_count == 0) {
452 std::map<int, std::vector < uint32_t > >::const_iterator it3 = qmp_id_to_qmp_map.find(tm_qmp_id);
453 if (it3 != qmp_id_to_qmp_map.end()) {
454 bcmos_fastlock_lock(&data_lock);
455 tm_qmp_bitset[tm_qmp_id] = 0;
456 qmp_id_to_qmp_map.erase(it3);
457 bcmos_fastlock_unlock(&data_lock, 0);
458 OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So clearing it\n", \
459 tm_qmp_id, tm_qmp_ref_count);
460 result = true;
461 }
462 } else {
463 OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So not clearing it\n", \
464 tm_qmp_id, tm_qmp_ref_count);
465 result = false;
466 }
467 return result;
468}
469
470/**
471* Returns Scheduler/Queue direction as string
472*
473* @param direction as specified in tech_profile.proto
474*/
475std::string GetDirection(int direction) {
476 switch (direction)
477 {
478 case tech_profile::Direction::UPSTREAM: return upstream;
479 case tech_profile::Direction::DOWNSTREAM: return downstream;
480 default: OPENOLT_LOG(ERROR, openolt_log_id, "direction-not-supported %d\n", direction);
481 return "direction-not-supported";
482 }
483}
484
485inline const char *get_flow_acton_command(uint32_t command) {
486 char actions[200] = { };
487 char *s_actions_ptr = actions;
488 if (command & BCMOLT_ACTION_CMD_ID_ADD_OUTER_TAG) strcat(s_actions_ptr, "ADD_OUTER_TAG|");
489 if (command & BCMOLT_ACTION_CMD_ID_REMOVE_OUTER_TAG) strcat(s_actions_ptr, "REMOVE_OUTER_TAG|");
490 if (command & BCMOLT_ACTION_CMD_ID_XLATE_OUTER_TAG) strcat(s_actions_ptr, "TRANSLATE_OUTER_TAG|");
491 if (command & BCMOLT_ACTION_CMD_ID_ADD_INNER_TAG) strcat(s_actions_ptr, "ADD_INNTER_TAG|");
492 if (command & BCMOLT_ACTION_CMD_ID_REMOVE_INNER_TAG) strcat(s_actions_ptr, "REMOVE_INNER_TAG|");
493 if (command & BCMOLT_ACTION_CMD_ID_XLATE_INNER_TAG) strcat(s_actions_ptr, "TRANSLATE_INNER_TAG|");
494 if (command & BCMOLT_ACTION_CMD_ID_REMARK_OUTER_PBITS) strcat(s_actions_ptr, "REMOVE_OUTER_PBITS|");
495 if (command & BCMOLT_ACTION_CMD_ID_REMARK_INNER_PBITS) strcat(s_actions_ptr, "REMAKE_INNER_PBITS|");
496 return s_actions_ptr;
497}
498
499char* openolt_read_sysinfo(const char* field_name, char* field_val)
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800500{
501 FILE *fp;
502 /* Prepare the command*/
503 char command[150];
504
505 snprintf(command, sizeof command, "bash -l -c \"onlpdump -s\" | perl -ne 'print $1 if /%s: (\\S+)/'", field_name);
506 /* Open the command for reading. */
507 fp = popen(command, "r");
508 if (fp == NULL) {
509 /*The client has to check for a Null field value in this case*/
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000510 OPENOLT_LOG(INFO, openolt_log_id, "Failed to query the %s\n", field_name);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800511 return field_val;
512 }
513
514 /*Read the field value*/
515 if (fp) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000516 uint8_t ret;
517 ret = fread(field_val, OPENOLT_FIELD_LEN, 1, fp);
518 if (ret >= OPENOLT_FIELD_LEN)
519 OPENOLT_LOG(INFO, openolt_log_id, "Read data length %u\n", ret);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800520 pclose(fp);
521 }
522 return field_val;
523}
524
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400525Status GetDeviceInfo_(openolt::DeviceInfo* device_info) {
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500526 device_info->set_vendor(VENDOR_ID);
527 device_info->set_model(MODEL_ID);
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400528 device_info->set_hardware_version("");
529 device_info->set_firmware_version(firmware_version);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500530 device_info->set_technology(board_technology);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500531 device_info->set_pon_ports(num_of_pon_ports);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500532
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800533 char serial_number[OPENOLT_FIELD_LEN];
534 memset(serial_number, '\0', OPENOLT_FIELD_LEN);
535 openolt_read_sysinfo("Serial Number", serial_number);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000536 OPENOLT_LOG(INFO, openolt_log_id, "Fetched device serial number %s\n", serial_number);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800537 device_info->set_device_serial_number(serial_number);
538
Girish Gowdru771f9ff2019-07-24 12:02:10 -0700539 char device_id[OPENOLT_FIELD_LEN];
540 memset(device_id, '\0', OPENOLT_FIELD_LEN);
541 openolt_read_sysinfo("MAC", device_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000542 OPENOLT_LOG(INFO, openolt_log_id, "Fetched device mac address %s\n", device_id);
Girish Gowdru771f9ff2019-07-24 12:02:10 -0700543 device_info->set_device_id(device_id);
544
Craig Lutgenb2601f02018-10-23 13:04:31 -0500545 // Legacy, device-wide ranges. To be deprecated when adapter
546 // is upgraded to support per-interface ranges
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000547 if (board_technology == "XGS-PON") {
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500548 device_info->set_onu_id_start(1);
549 device_info->set_onu_id_end(255);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600550 device_info->set_alloc_id_start(MIN_ALLOC_ID_XGSPON);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500551 device_info->set_alloc_id_end(16383);
552 device_info->set_gemport_id_start(1024);
553 device_info->set_gemport_id_end(65535);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500554 device_info->set_flow_id_start(1);
555 device_info->set_flow_id_end(16383);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500556 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000557 else if (board_technology == "GPON") {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500558 device_info->set_onu_id_start(1);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500559 device_info->set_onu_id_end(127);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600560 device_info->set_alloc_id_start(MIN_ALLOC_ID_GPON);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500561 device_info->set_alloc_id_end(767);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500562 device_info->set_gemport_id_start(256);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500563 device_info->set_gemport_id_end(4095);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500564 device_info->set_flow_id_start(1);
565 device_info->set_flow_id_end(16383);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500566 }
Craig Lutgenb2601f02018-10-23 13:04:31 -0500567
568 std::map<std::string, openolt::DeviceInfo::DeviceResourceRanges*> ranges;
569 for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
570 std::string intf_technology = intf_technologies[intf_id];
571 openolt::DeviceInfo::DeviceResourceRanges *range = ranges[intf_technology];
572 if(range == nullptr) {
573 range = device_info->add_ranges();
574 ranges[intf_technology] = range;
575 range->set_technology(intf_technology);
576
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000577 if (intf_technology == "XGS-PON") {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500578 openolt::DeviceInfo::DeviceResourceRanges::Pool* pool;
579
580 pool = range->add_pools();
581 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ONU_ID);
582 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::DEDICATED_PER_INTF);
583 pool->set_start(1);
584 pool->set_end(255);
585
586 pool = range->add_pools();
587 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ALLOC_ID);
588 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_SAME_TECH);
589 pool->set_start(1024);
590 pool->set_end(16383);
591
592 pool = range->add_pools();
593 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::GEMPORT_ID);
594 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
595 pool->set_start(1024);
596 pool->set_end(65535);
597
598 pool = range->add_pools();
599 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::FLOW_ID);
600 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
601 pool->set_start(1);
602 pool->set_end(16383);
603 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000604 else if (intf_technology == "GPON") {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500605 openolt::DeviceInfo::DeviceResourceRanges::Pool* pool;
606
607 pool = range->add_pools();
608 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ONU_ID);
609 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::DEDICATED_PER_INTF);
610 pool->set_start(1);
611 pool->set_end(127);
612
613 pool = range->add_pools();
614 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ALLOC_ID);
615 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_SAME_TECH);
616 pool->set_start(256);
617 pool->set_end(757);
618
619 pool = range->add_pools();
620 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::GEMPORT_ID);
621 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
622 pool->set_start(256);
623 pool->set_end(4095);
624
625 pool = range->add_pools();
626 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::FLOW_ID);
627 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
628 pool->set_start(1);
629 pool->set_end(16383);
630 }
631 }
632
633 range->add_intf_ids(intf_id);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500634 }
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400635
636 // FIXME: Once dependency problem is fixed
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500637 // device_info->set_pon_ports(num_of_pon_ports);
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400638 // device_info->set_onu_id_end(XGPON_NUM_OF_ONUS - 1);
639 // device_info->set_alloc_id_start(1024);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500640 // device_info->set_alloc_id_end(XGPON_NUM_OF_ALLOC_IDS * num_of_pon_ports ? - 1);
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400641 // device_info->set_gemport_id_start(XGPON_MIN_BASE_SERVICE_PORT_ID);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500642 // device_info->set_gemport_id_end(XGPON_NUM_OF_GEM_PORT_IDS_PER_PON * num_of_pon_ports ? - 1);
643 // device_info->set_pon_ports(num_of_pon_ports);
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400644
645 return Status::OK;
646}
647
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000648Status pushOltOperInd(uint32_t intf_id, const char *type, const char *state)
649{
650 openolt::Indication ind;
651 openolt::IntfOperIndication* intf_oper_ind = new openolt::IntfOperIndication;
652
653 intf_oper_ind->set_type(type);
654 intf_oper_ind->set_intf_id(intf_id);
655 intf_oper_ind->set_oper_state(state);
656 ind.set_allocated_intf_oper_ind(intf_oper_ind);
657 oltIndQ.push(ind);
658 return Status::OK;
659}
660
661#define CLI_HOST_PROMPT_FORMAT "BCM.%u> "
662
663/* Build CLI prompt */
664static void openolt_cli_get_prompt_cb(bcmcli_session *session, char *buf, uint32_t max_len)
665{
666 snprintf(buf, max_len, CLI_HOST_PROMPT_FORMAT, dev_id);
667}
668
669static int _bal_apiend_cli_thread_handler(long data)
670{
671 char init_string[]="\n";
672 bcmcli_session *sess = current_session;
673 bcmos_task_parm bal_cli_task_p_dummy;
674
675 /* Switch to interactive mode if not stopped in the init script */
676 if (!bcmcli_is_stopped(sess))
677 {
678 /* Force a CLI command prompt
679 * The string passed into the parse function
680 * must be modifiable, so a string constant like
681 * bcmcli_parse(current_session, "\n") will not
682 * work.
683 */
684 bcmcli_parse(sess, init_string);
685
686 /* Process user input until EOF or quit command */
687 bcmcli_driver(sess);
688 };
689 OPENOLT_LOG(INFO, openolt_log_id, "BAL API End CLI terminated\n");
690
691 /* Cleanup */
692 bcmcli_session_close(current_session);
693 bcmcli_token_destroy(NULL);
694 return 0;
695}
696
697/* Init API CLI commands for the current device */
698bcmos_errno bcm_openolt_api_cli_init(bcmcli_entry *parent_dir, bcmcli_session *session)
699{
700 bcmos_errno rc;
701
702 api_parent_dir = parent_dir;
703
704 rc = bcm_api_cli_set_commands(session);
705
706#ifdef BCM_SUBSYSTEM_HOST
707 /* Subscribe for device change indication */
708 rc = rc ? rc : bcmolt_olt_sel_ind_register(_api_cli_olt_change_ind);
709#endif
710
711 return rc;
712}
713
714static bcmos_errno bcm_cli_quit(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
715{
716 bcmcli_stop(session);
717 bcmcli_session_print(session, "CLI terminated by 'Quit' command\n");
718 status_bcm_cli_quit = BCMOS_TRUE;
719
720 return BCM_ERR_OK;
721}
722
723int get_status_bcm_cli_quit(void) {
724 return status_bcm_cli_quit;
725}
726
727bcmos_errno bcmolt_apiend_cli_init() {
728 bcmos_errno ret;
729 bcmos_task_parm bal_cli_task_p = {};
730 bcmos_task_parm bal_cli_task_p_dummy;
731
732 /** before creating the task, check if it is already created by the other half of BAL i.e. Core side */
733 if (BCM_ERR_OK != bcmos_task_query(&bal_cli_thread, &bal_cli_task_p_dummy))
734 {
735 /* Create BAL CLI thread */
736 bal_cli_task_p.name = bal_cli_thread_name;
737 bal_cli_task_p.handler = _bal_apiend_cli_thread_handler;
738 bal_cli_task_p.priority = TASK_PRIORITY_CLI;
739
740 ret = bcmos_task_create(&bal_cli_thread, &bal_cli_task_p);
741 if (BCM_ERR_OK != ret)
742 {
743 bcmos_printf("Couldn't create BAL API end CLI thread\n");
744 return ret;
745 }
746 }
747}
748
Shad Ansari627b5782018-08-13 22:49:32 +0000749Status Enable_(int argc, char *argv[]) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000750 bcmos_errno err;
751 bcmolt_host_init_parms init_parms = {};
752 init_parms.transport.type = BCM_HOST_API_CONN_LOCAL;
753 unsigned int failed_enable_device_cnt = 0;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000754
Shad Ansariedef2132018-08-10 22:14:50 +0000755 if (!state.is_activated()) {
Shad Ansari627b5782018-08-13 22:49:32 +0000756
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500757 vendor_init();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000758 /* Initialize host subsystem */
759 err = bcmolt_host_init(&init_parms);
760 if (BCM_ERR_OK != err) {
761 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to init OLT\n");
762 return bcm_to_grpc_err(err, "Failed to init OLT");
763 }
764
765 bcmcli_session_parm mon_session_parm;
766 /* Create CLI session */
767 memset(&mon_session_parm, 0, sizeof(mon_session_parm));
768 mon_session_parm.get_prompt = openolt_cli_get_prompt_cb;
769 mon_session_parm.access_right = BCMCLI_ACCESS_ADMIN;
770 bcmos_errno rc = bcmcli_session_open(&mon_session_parm, &current_session);
771 BUG_ON(rc != BCM_ERR_OK);
772
773 /* API CLI */
774 bcm_openolt_api_cli_init(NULL, current_session);
775
776 /* Add quit command */
777 BCMCLI_MAKE_CMD_NOPARM(NULL, "quit", "Quit", bcm_cli_quit);
778
779 err = bcmolt_apiend_cli_init();
780 if (BCM_ERR_OK != err) {
781 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to add apiend init\n");
782 return bcm_to_grpc_err(err, "Failed to add apiend init");
783 }
784
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800785 bcmos_fastlock_init(&data_lock, 0);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000786 OPENOLT_LOG(INFO, openolt_log_id, "Enable OLT - %s-%s\n", VENDOR_ID, MODEL_ID);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600787
Jason Huangbf45ffb2019-10-30 17:29:02 +0800788 //check BCM daemon is connected or not
789 Status status = check_connection();
790 if (!status.ok())
791 return status;
792 else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000793 Status status = SubscribeIndication();
794 if (!status.ok()) {
795 OPENOLT_LOG(ERROR, openolt_log_id, "SubscribeIndication failed - %s : %s\n",
796 grpc_status_code_to_string(status.error_code()).c_str(),
797 status.error_message().c_str());
798 return status;
799 }
Jason Huangbf45ffb2019-10-30 17:29:02 +0800800
801 //check BAL state in initial stage
802 status = check_bal_ready();
803 if (!status.ok())
804 return status;
805 }
806
807 {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000808 bcmos_errno err;
809 bcmolt_odid dev;
810 OPENOLT_LOG(INFO, openolt_log_id, "Enabling PON %d Devices ... \n", BCM_MAX_DEVS_PER_LINE_CARD);
811 for (dev = 0; dev < BCM_MAX_DEVS_PER_LINE_CARD; dev++) {
812 bcmolt_device_cfg dev_cfg = { };
813 bcmolt_device_key dev_key = { };
814 dev_key.device_id = dev;
815 BCMOLT_CFG_INIT(&dev_cfg, device, dev_key);
816 BCMOLT_MSG_FIELD_GET(&dev_cfg, system_mode);
817 err = bcmolt_cfg_get(dev_id, &dev_cfg.hdr);
Jason Huangbf45ffb2019-10-30 17:29:02 +0800818 if (err == BCM_ERR_NOT_CONNECTED) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000819 bcmolt_device_key key = {.device_id = dev};
820 bcmolt_device_connect oper;
821 BCMOLT_OPER_INIT(&oper, device, connect, key);
822 if (MODEL_ID == "asfvolt16") {
823 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mode, BCMOLT_INNI_MODE_ALL_10_G_XFI);
824 BCMOLT_MSG_FIELD_SET (&oper, system_mode, BCMOLT_SYSTEM_MODE_XGS__2_X);
825 } else if (MODEL_ID == "asgvolt64") {
826 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mode, BCMOLT_INNI_MODE_ALL_10_G_XFI);
827 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mux, BCMOLT_INNI_MUX_FOUR_TO_ONE);
828 BCMOLT_MSG_FIELD_SET (&oper, system_mode, BCMOLT_SYSTEM_MODE_GPON__16_X);
829 }
830 err = bcmolt_oper_submit(dev_id, &oper.hdr);
831 if (err) {
832 failed_enable_device_cnt ++;
833 OPENOLT_LOG(ERROR, openolt_log_id, "Enable PON device %d failed, err %d\n", dev, err);
834 if (failed_enable_device_cnt == BCM_MAX_DEVS_PER_LINE_CARD) {
835 OPENOLT_LOG(ERROR, openolt_log_id, "failed to enable all the pon ports\n");
836 return Status(grpc::StatusCode::INTERNAL, "Failed to activate all PON ports");
837 }
838 }
839 bcmos_usleep(200000);
840 }
841 else {
842 OPENOLT_LOG(WARNING, openolt_log_id, "PON deivce %d already connected\n", dev);
843 state.activate();
844 }
845 }
846 init_stats();
Shad Ansari627b5782018-08-13 22:49:32 +0000847 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000848 }
Shad Ansariedef2132018-08-10 22:14:50 +0000849
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000850 /* Start CLI */
851 OPENOLT_LOG(INFO, def_log_id, "Starting CLI\n");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400852 //If already enabled, generate an extra indication ????
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000853 return Status::OK;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400854}
855
856Status Disable_() {
857 // bcmbal_access_terminal_cfg acc_term_obj;
858 // bcmbal_access_terminal_key key = { };
859 //
860 // if (state::is_activated) {
861 // std::cout << "Disable OLT" << std::endl;
862 // key.access_term_id = DEFAULT_ATERM_ID;
863 // BCMBAL_CFG_INIT(&acc_term_obj, access_terminal, key);
864 // BCMBAL_CFG_PROP_SET(&acc_term_obj, access_terminal, admin_state, BCMBAL_STATE_DOWN);
865 // bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(acc_term_obj.hdr));
866 // if (err) {
867 // std::cout << "ERROR: Failed to disable OLT" << std::endl;
868 // return bcm_to_grpc_err(err, "Failed to disable OLT");
869 // }
870 // }
871 // //If already disabled, generate an extra indication ????
872 // return Status::OK;
873 //This fails with Operation Not Supported, bug ???
874
875 //TEMPORARY WORK AROUND
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000876 Status status = SetStateUplinkIf_(nni_intf_id, false);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400877 if (status.ok()) {
Shad Ansariedef2132018-08-10 22:14:50 +0000878 state.deactivate();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000879 OPENOLT_LOG(INFO, openolt_log_id, "Disable OLT, add an extra indication\n");
880 pushOltOperInd(nni_intf_id, "nni", "up");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400881 }
882 return status;
883
884}
885
886Status Reenable_() {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000887 Status status = SetStateUplinkIf_(0, true);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400888 if (status.ok()) {
Shad Ansariedef2132018-08-10 22:14:50 +0000889 state.activate();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000890 OPENOLT_LOG(INFO, openolt_log_id, "Reenable OLT, add an extra indication\n");
891 pushOltOperInd(0, "nni", "up");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400892 }
893 return status;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000894}
895
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000896bcmos_errno get_pon_interface_status(bcmolt_interface pon_ni, bcmolt_interface_state *state) {
897 bcmos_errno err;
898 bcmolt_pon_interface_key pon_key;
899 bcmolt_pon_interface_cfg pon_cfg;
900 pon_key.pon_ni = pon_ni;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000901
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000902 BCMOLT_CFG_INIT(&pon_cfg, pon_interface, pon_key);
903 BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, state);
904 BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, itu);
905 err = bcmolt_cfg_get(dev_id, &pon_cfg.hdr);
906 *state = pon_cfg.data.state;
907 return err;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000908}
909
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000910inline uint64_t get_flow_status(uint16_t flow_id, uint16_t flow_type, uint16_t data_id) {
911 bcmos_errno err;
912 bcmolt_flow_key flow_key;
913 bcmolt_flow_cfg flow_cfg;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400914
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000915 flow_key.flow_id = flow_id;
916 flow_key.flow_type = (bcmolt_flow_type)flow_type;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400917
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000918 BCMOLT_CFG_INIT(&flow_cfg, flow, flow_key);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400919
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000920 switch (data_id) {
921 case ONU_ID: //onu_id
922 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, onu_id);
923 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
924 if (err) {
925 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get onu_id\n");
926 return err;
927 }
928 return flow_cfg.data.onu_id;
929 case FLOW_TYPE:
930 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
931 if (err) {
932 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get flow_type\n");
933 return err;
934 }
935 return flow_cfg.key.flow_type;
936 case SVC_PORT_ID: //svc_port_id
937 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, svc_port_id);
938 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
939 if (err) {
940 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get svc_port_id\n");
941 return err;
942 }
943 return flow_cfg.data.svc_port_id;
944 case PRIORITY:
945 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, priority);
946 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
947 if (err) {
948 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get priority\n");
949 return err;
950 }
951 return flow_cfg.data.priority;
952 case COOKIE: //cookie
953 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, cookie);
954 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
955 if (err) {
956 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get cookie\n");
957 return err;
958 }
959 return flow_cfg.data.cookie;
960 case INGRESS_INTF_TYPE: //ingress intf_type
961 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, ingress_intf);
962 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
963 if (err) {
964 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get ingress intf_type\n");
965 return err;
966 }
967 return flow_cfg.data.ingress_intf.intf_type;
968 case EGRESS_INTF_TYPE: //egress intf_type
969 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_intf);
970 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
971 if (err) {
972 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress intf_type\n");
973 return err;
974 }
975 return flow_cfg.data.egress_intf.intf_type;
976 case INGRESS_INTF_ID: //ingress intf_id
977 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, ingress_intf);
978 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
979 if (err) {
980 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get ingress intf_id\n");
981 return err;
982 }
983 return flow_cfg.data.ingress_intf.intf_id;
984 case EGRESS_INTF_ID: //egress intf_id
985 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_intf);
986 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
987 if (err) {
988 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress intf_id\n");
989 return err;
990 }
991 return flow_cfg.data.egress_intf.intf_id;
992 case CLASSIFIER_O_VID:
993 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
994 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
995 if (err) {
996 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier o_vid\n");
997 return err;
998 }
999 return flow_cfg.data.classifier.o_vid;
1000 case CLASSIFIER_O_PBITS:
1001 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1002 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1003 if (err) {
1004 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier o_pbits\n");
1005 return err;
1006 }
1007 return flow_cfg.data.classifier.o_pbits;
1008 case CLASSIFIER_I_VID:
1009 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1010 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1011 if (err) {
1012 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier i_vid\n");
1013 return err;
1014 }
1015 return flow_cfg.data.classifier.i_vid;
1016 case CLASSIFIER_I_PBITS:
1017 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1018 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1019 if (err) {
1020 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier i_pbits\n");
1021 return err;
1022 }
1023 return flow_cfg.data.classifier.i_pbits;
1024 case CLASSIFIER_ETHER_TYPE:
1025 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1026 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1027 if (err) {
1028 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier ether_type\n");
1029 return err;
1030 }
1031 return flow_cfg.data.classifier.ether_type;
1032 case CLASSIFIER_IP_PROTO:
1033 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1034 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1035 if (err) {
1036 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier ip_proto\n");
1037 return err;
1038 }
1039 return flow_cfg.data.classifier.ip_proto;
1040 case CLASSIFIER_SRC_PORT:
1041 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1042 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1043 if (err) {
1044 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier src_port\n");
1045 return err;
1046 }
1047 return flow_cfg.data.classifier.src_port;
1048 case CLASSIFIER_DST_PORT:
1049 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1050 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1051 if (err) {
1052 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier dst_port\n");
1053 return err;
1054 }
1055 return flow_cfg.data.classifier.dst_port;
1056 case CLASSIFIER_PKT_TAG_TYPE:
1057 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
1058 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1059 if (err) {
1060 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier pkt_tag_type\n");
1061 return err;
1062 }
1063 return flow_cfg.data.classifier.pkt_tag_type;
1064 case EGRESS_QOS_TYPE:
1065 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
1066 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1067 if (err) {
1068 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos type\n");
1069 return err;
1070 }
1071 return flow_cfg.data.egress_qos.type;
1072 case EGRESS_QOS_QUEUE_ID:
1073 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
1074 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1075 if (err) {
1076 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos queue_id\n");
1077 return err;
1078 }
1079 switch (flow_cfg.data.egress_qos.type) {
1080 case BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE:
1081 return flow_cfg.data.egress_qos.u.fixed_queue.queue_id;
1082 case BCMOLT_EGRESS_QOS_TYPE_TC_TO_QUEUE:
1083 return flow_cfg.data.egress_qos.u.tc_to_queue.tc_to_queue_id;
1084 case BCMOLT_EGRESS_QOS_TYPE_PBIT_TO_TC:
1085 return flow_cfg.data.egress_qos.u.pbit_to_tc.tc_to_queue_id;
1086 case BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE:
1087 return flow_cfg.data.egress_qos.u.priority_to_queue.tm_q_set_id;
1088 case BCMOLT_EGRESS_QOS_TYPE_NONE:
1089 default:
1090 return -1;
1091 }
1092 case EGRESS_QOS_TM_SCHED_ID:
1093 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
1094 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1095 if (err) {
1096 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos tm_sched_id\n");
1097 return err;
1098 }
1099 return flow_cfg.data.egress_qos.tm_sched.id;
1100 case ACTION_CMDS_BITMASK:
1101 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1102 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1103 if (err) {
1104 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action cmds_bitmask\n");
1105 return err;
1106 }
1107 return flow_cfg.data.action.cmds_bitmask;
1108 case ACTION_O_VID:
1109 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1110 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1111 if (err) {
1112 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action o_vid\n");
1113 return err;
1114 }
1115 return flow_cfg.data.action.o_vid;
1116 case ACTION_O_PBITS:
1117 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1118 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1119 if (err) {
1120 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action o_pbits\n");
1121 return err;
1122 }
1123 return flow_cfg.data.action.o_pbits;
1124 case ACTION_I_VID:
1125 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1126 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1127 if (err) {
1128 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action i_vid\n");
1129 return err;
1130 }
1131 return flow_cfg.data.action.i_vid;
1132 case ACTION_I_PBITS:
1133 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
1134 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1135 if (err) {
1136 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action i_pbits\n");
1137 return err;
1138 }
1139 return flow_cfg.data.action.i_pbits;
1140 case STATE:
1141 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, state);
1142 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1143 if (err) {
1144 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get state\n");
1145 return err;
1146 }
1147 return flow_cfg.data.state;
1148 default:
1149 return BCM_ERR_INTERNAL;
1150 }
1151
1152 return err;
1153}
1154
1155Status EnablePonIf_(uint32_t intf_id) {
1156 bcmos_errno err = BCM_ERR_OK;
1157 bcmolt_pon_interface_cfg interface_obj;
1158 bcmolt_pon_interface_key intf_key = {.pon_ni = (bcmolt_interface)intf_id};
1159 bcmolt_pon_interface_set_pon_interface_state pon_interface_set_state;
1160 bcmolt_interface_state state;
1161
1162 err = get_pon_interface_status((bcmolt_interface)intf_id, &state);
1163 if (err == BCM_ERR_OK) {
1164 if (state == BCMOLT_INTERFACE_STATE_ACTIVE_WORKING) {
Jason Huangbf45ffb2019-10-30 17:29:02 +08001165 OPENOLT_LOG(WARNING, openolt_log_id, "PON interface: %d already enabled\n", intf_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001166 return Status::OK;
1167 }
1168 }
1169 BCMOLT_CFG_INIT(&interface_obj, pon_interface, intf_key);
1170 BCMOLT_OPER_INIT(&pon_interface_set_state, pon_interface, set_pon_interface_state, intf_key);
1171 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.control, BCMOLT_CONTROL_STATE_ENABLE);
1172 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.interval, 5000);
1173 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.onu_post_discovery_mode,
1174 BCMOLT_ONU_POST_DISCOVERY_MODE_ACTIVATE);
1175 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.los, true);
1176 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.onu_alarms, true);
1177 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.tiwi, true);
1178 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.ack_timeout, true);
1179 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.sfi, true);
1180 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.loki, true);
1181 BCMOLT_FIELD_SET(&pon_interface_set_state.data, pon_interface_set_pon_interface_state_data,
1182 operation, BCMOLT_INTERFACE_OPERATION_ACTIVE_WORKING);
1183
1184 err = bcmolt_cfg_set(dev_id, &interface_obj.hdr);
1185 if (err != BCM_ERR_OK) {
1186 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to enable discovery onu, PON interface %d, err %d\n", intf_id, err);
1187 return bcm_to_grpc_err(err, "Failed to enable discovery onu");
1188 }
1189 err = bcmolt_oper_submit(dev_id, &pon_interface_set_state.hdr);
1190 if (err != BCM_ERR_OK) {
1191 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to enable PON interface: %d\n", intf_id);
1192 return bcm_to_grpc_err(err, "Failed to enable PON interface");
1193 }
1194 else {
1195 OPENOLT_LOG(INFO, openolt_log_id, "Successfully enabled PON interface: %d\n", intf_id);
1196 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for PON interface: %d\n", intf_id);
1197 CreateDefaultSched(intf_id, downstream);
1198 CreateDefaultQueue(intf_id, downstream);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001199 }
1200
1201 return Status::OK;
1202}
1203
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001204Status ProbeDeviceCapabilities_() {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001205 bcmos_errno err;
1206 bcmolt_device_cfg dev_cfg = { };
1207 bcmolt_device_key dev_key = { };
1208 bcmolt_olt_cfg olt_cfg = { };
1209 bcmolt_olt_key olt_key = { };
1210 bcmolt_topology_map topo_map[BCM_MAX_PONS_PER_OLT] = { };
1211 bcmolt_topology topo = { };
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001212
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001213 topo.topology_maps.len = BCM_MAX_PONS_PER_OLT;
1214 topo.topology_maps.arr = &topo_map[0];
1215 BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
1216 BCMOLT_MSG_FIELD_GET(&olt_cfg, bal_state);
1217 BCMOLT_FIELD_SET_PRESENT(&olt_cfg.data, olt_cfg_data, topology);
1218 BCMOLT_CFG_LIST_BUF_SET(&olt_cfg, olt, topo.topology_maps.arr,
1219 sizeof(bcmolt_topology_map) * topo.topology_maps.len);
1220 err = bcmolt_cfg_get(dev_id, &olt_cfg.hdr);
1221 if (err) {
1222 OPENOLT_LOG(ERROR, openolt_log_id, "cfg: Failed to query OLT\n");
1223 return bcm_to_grpc_err(err, "cfg: Failed to query OLT");
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001224 }
1225
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001226 num_of_nni_ports = olt_cfg.data.topology.num_switch_ports;
1227 num_of_pon_ports = olt_cfg.data.topology.topology_maps.len;
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001228
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001229 OPENOLT_LOG(INFO, openolt_log_id, "OLT capabilitites, oper_state: %s\n",
1230 olt_cfg.data.bal_state == BCMOLT_BAL_STATE_BAL_AND_SWITCH_READY
1231 ? "up" : "down");
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001232
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001233 OPENOLT_LOG(INFO, openolt_log_id, "topology nni: %d pon: %d dev: %d\n",
1234 num_of_nni_ports,
1235 num_of_pon_ports,
1236 BCM_MAX_DEVS_PER_LINE_CARD);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001237
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001238 for (int devid = 0; devid < BCM_MAX_DEVS_PER_LINE_CARD; devid++) {
1239 dev_key.device_id = devid;
1240 BCMOLT_CFG_INIT(&dev_cfg, device, dev_key);
1241 BCMOLT_MSG_FIELD_GET(&dev_cfg, firmware_sw_version);
1242 BCMOLT_MSG_FIELD_GET(&dev_cfg, chip_family);
1243 BCMOLT_MSG_FIELD_GET(&dev_cfg, system_mode);
1244 err = bcmolt_cfg_get(dev_id, &dev_cfg.hdr);
1245 if (err) {
1246 OPENOLT_LOG(ERROR, openolt_log_id, "device: Failed to query OLT\n");
1247 return bcm_to_grpc_err(err, "device: Failed to query OLT");
1248 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001249
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001250 std::string bal_version;
1251 bal_version += std::to_string(dev_cfg.data.firmware_sw_version.major)
1252 + "." + std::to_string(dev_cfg.data.firmware_sw_version.minor)
1253 + "." + std::to_string(dev_cfg.data.firmware_sw_version.revision);
1254 firmware_version = "BAL." + bal_version + "__" + firmware_version;
1255
1256 switch(dev_cfg.data.system_mode) {
1257 case 10: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*4,(devid+1)*4,"GPON"); break;
1258 case 11: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*8,(devid+1)*8,"GPON"); break;
1259 case 12: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"GPON"); break;
1260 case 13: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,"XGPON"); break;
1261 case 14: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*4,(devid+1)*4,"XGPON"); break;
1262 case 15: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*8,(devid+1)*8,"XGPON"); break;
1263 case 16: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"XGPON"); break;
1264 case 18: board_technology = "XGS-PON"; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,"XGS-PON"); break;
1265 case 19: board_technology = "XGS-PON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"XGS-PON"); break;
1266 case 20: board_technology = MIXED_TECH; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,MIXED_TECH); break;
1267 }
1268
1269 switch(dev_cfg.data.chip_family) {
1270 case BCMOLT_CHIP_FAMILY_CHIP_FAMILY_6862_X_: chip_family = "Maple"; break;
1271 case BCMOLT_CHIP_FAMILY_CHIP_FAMILY_6865_X_: chip_family = "Aspen"; break;
1272 }
1273
1274 OPENOLT_LOG(INFO, openolt_log_id, "device %d, pon: %d, version %s object model: %d, family: %s, board_technology: %s\n",
1275 devid, BCM_MAX_PONS_PER_DEV, bal_version.c_str(), BAL_API_VERSION, chip_family.c_str(), board_technology.c_str());
1276
1277 bcmos_usleep(500000);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001278 }
1279
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001280 return Status::OK;
1281}
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001282#if 0
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001283Status ProbePonIfTechnology_() {
1284 // Probe maximum extent possible as configured into BAL driver to determine
1285 // which are active in the current BAL topology. And for those
1286 // that are active, determine each port's access technology, i.e. "gpon" or "xgspon".
1287 for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001288 bcmolt_pon_interface_cfg interface_obj;
1289 bcmolt_pon_interface_key interface_key;
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001290
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001291 interface_key.pon_ni = intf_id;
1292 BCMOLT_CFG_INIT(&interface_obj, pon_interface, interface_key);
1293 if (board_technology == "XGS-PON")
1294 BCMOLT_MSG_FIELD_GET(&interface_obj, xgs_ngpon2_trx);
1295 else if (board_technology == "GPON")
1296 BCMOLT_MSG_FIELD_GET(&interface_obj, gpon_trx);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001297
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001298 bcmos_errno err = bcmolt_cfg_get(dev_id, &interface_obj.hdr);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001299 if (err != BCM_ERR_OK) {
Craig Lutgenb2601f02018-10-23 13:04:31 -05001300 intf_technologies[intf_id] = UNKNOWN_TECH;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001301 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 -05001302 }
1303 else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001304 if (board_technology == "XGS-PON") {
1305 switch(interface_obj.data.xgpon_trx.transceiver_type) {
1306 case BCMOLT_XGPON_TRX_TYPE_LTH_7222_PC:
1307 case BCMOLT_XGPON_TRX_TYPE_WTD_RTXM266_702:
1308 case BCMOLT_XGPON_TRX_TYPE_LTH_7222_BC_PLUS:
1309 case BCMOLT_XGPON_TRX_TYPE_LTH_7226_PC:
1310 case BCMOLT_XGPON_TRX_TYPE_LTH_5302_PC:
1311 case BCMOLT_XGPON_TRX_TYPE_LTH_7226_A_PC_PLUS:
1312 case BCMOLT_XGPON_TRX_TYPE_D272RR_SSCB_DM:
1313 intf_technologies[intf_id] = "XGS-PON";
1314 break;
1315 }
1316 } else if (board_technology == "GPON") {
1317 switch(interface_obj.data.gpon_trx.transceiver_type) {
1318 case BCMOLT_TRX_TYPE_SPS_43_48_H_HP_CDE_SD_2013:
1319 case BCMOLT_TRX_TYPE_LTE_3680_M:
1320 case BCMOLT_TRX_TYPE_SOURCE_PHOTONICS:
1321 case BCMOLT_TRX_TYPE_LTE_3680_P_TYPE_C_PLUS:
1322 case BCMOLT_TRX_TYPE_LTE_3680_P_BC:
1323 intf_technologies[intf_id] = "GPON";
1324 break;
1325 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001326 }
Craig Lutgenb2601f02018-10-23 13:04:31 -05001327
1328 if (board_technology != UNKNOWN_TECH) {
1329 board_technology = intf_technologies[intf_id];
1330 } else if (board_technology != MIXED_TECH && board_technology != intf_technologies[intf_id]) {
1331 intf_technologies[intf_id] = MIXED_TECH;
1332 }
1333
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001334 }
1335 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001336 return Status::OK;
1337}
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001338#endif
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001339unsigned NumNniIf_() {return num_of_nni_ports;}
1340unsigned NumPonIf_() {return num_of_pon_ports;}
1341
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001342bcmos_errno get_nni_interface_status(bcmolt_interface id, bcmolt_interface_state *state) {
1343 bcmos_errno err;
1344 bcmolt_nni_interface_key nni_key;
1345 bcmolt_nni_interface_cfg nni_cfg;
1346 nni_key.id = id;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001347
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001348 BCMOLT_CFG_INIT(&nni_cfg, nni_interface, nni_key);
1349 BCMOLT_FIELD_SET_PRESENT(&nni_cfg.data, nni_interface_cfg_data, state);
1350 err = bcmolt_cfg_get(dev_id, &nni_cfg.hdr);
1351 *state = nni_cfg.data.state;
1352 return err;
1353}
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001354
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001355Status SetStateUplinkIf_(uint32_t intf_id, bool set_state) {
1356 bcmos_errno err = BCM_ERR_OK;
1357 bcmolt_nni_interface_key intf_key = {.id = (bcmolt_interface)intf_id};
1358 bcmolt_nni_interface_set_nni_state nni_interface_set_state;
1359 bcmolt_interface_state state;
Craig Lutgend0bae9b2018-10-18 18:02:07 -05001360
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001361 err = get_nni_interface_status((bcmolt_interface)intf_id, &state);
1362 if (err == BCM_ERR_OK) {
1363 if (set_state && state == BCMOLT_INTERFACE_STATE_ACTIVE_WORKING) {
Jason Huangbf45ffb2019-10-30 17:29:02 +08001364 OPENOLT_LOG(WARNING, openolt_log_id, "NNI interface: %d already enabled\n", intf_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001365 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for NNI interface: %d\n", intf_id);
1366 CreateDefaultSched(intf_id, upstream);
1367 CreateDefaultQueue(intf_id, upstream);
1368 return Status::OK;
1369 } else if (!set_state && state == BCMOLT_INTERFACE_STATE_INACTIVE) {
1370 OPENOLT_LOG(INFO, openolt_log_id, "NNI interface: %d already disabled\n", intf_id);
1371 return Status::OK;
1372 }
Craig Lutgend0bae9b2018-10-18 18:02:07 -05001373 }
1374
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001375 BCMOLT_OPER_INIT(&nni_interface_set_state, nni_interface, set_nni_state, intf_key);
1376 if (set_state) {
1377 BCMOLT_FIELD_SET(&nni_interface_set_state.data, nni_interface_set_nni_state_data,
1378 nni_state, BCMOLT_INTERFACE_OPERATION_ACTIVE_WORKING);
1379 } else {
1380 BCMOLT_FIELD_SET(&nni_interface_set_state.data, nni_interface_set_nni_state_data,
1381 nni_state, BCMOLT_INTERFACE_OPERATION_INACTIVE);
1382 }
1383 err = bcmolt_oper_submit(dev_id, &nni_interface_set_state.hdr);
1384 if (err != BCM_ERR_OK) {
1385 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to %s NNI interface: %d, err %d\n",
1386 (set_state)?"enable":"disable", intf_id, err);
1387 return bcm_to_grpc_err(err, "Failed to enable NNI interface");
1388 }
1389 else {
1390 OPENOLT_LOG(INFO, openolt_log_id, "Successfully %s NNI interface: %d\n", (set_state)?"enable":"disable", intf_id);
1391 if (set_state) {
1392 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for NNI interface: %d\n", intf_id);
1393 CreateDefaultSched(intf_id, upstream);
1394 CreateDefaultQueue(intf_id, upstream);
1395 }
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001396 }
1397
1398 return Status::OK;
1399}
1400
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001401Status DisablePonIf_(uint32_t intf_id) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001402 bcmolt_pon_interface_cfg interface_obj;
1403 bcmolt_pon_interface_key interface_key;
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001404
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001405 interface_key.pon_ni = intf_id;
1406 BCMOLT_CFG_INIT(&interface_obj, pon_interface, interface_key);
1407 BCMOLT_MSG_FIELD_GET(&interface_obj, state);
1408 bcmos_errno err = bcmolt_cfg_get(dev_id, &interface_obj.hdr);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001409 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001410 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to disable PON interface: %d\n", intf_id);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001411 return bcm_to_grpc_err(err, "Failed to disable PON interface");
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001412 }
1413
1414 return Status::OK;
1415}
1416
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001417Status ActivateOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001418 const char *vendor_id, const char *vendor_specific, uint32_t pir) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001419 bcmos_errno err = BCM_ERR_OK;
1420 bcmolt_onu_cfg onu_cfg;
1421 bcmolt_onu_key onu_key;
1422 bcmolt_serial_number serial_number; /**< ONU serial number */
1423 bcmolt_bin_str_36 registration_id; /**< ONU registration ID */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001424
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001425 onu_key.onu_id = onu_id;
1426 onu_key.pon_ni = intf_id;
1427 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
1428 BCMOLT_FIELD_SET_PRESENT(&onu_cfg.data, onu_cfg_data, onu_state);
1429 err = bcmolt_cfg_get(dev_id, &onu_cfg.hdr);
1430 if (err == BCM_ERR_OK) {
1431 if ((onu_cfg.data.onu_state == BCMOLT_ONU_STATE_PROCESSING ||
1432 onu_cfg.data.onu_state == BCMOLT_ONU_STATE_ACTIVE) ||
1433 (onu_cfg.data.onu_state == BCMOLT_ONU_STATE_INACTIVE &&
1434 onu_cfg.data.onu_old_state == BCMOLT_ONU_STATE_NOT_CONFIGURED))
1435 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001436 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001437
1438 OPENOLT_LOG(INFO, openolt_log_id, "Enabling ONU %d on PON %d : vendor id %s, \
1439vendor specific %s, pir %d\n", onu_id, intf_id, vendor_id,
1440 vendor_specific_to_str(vendor_specific).c_str(), pir);
1441
1442 memcpy(serial_number.vendor_id.arr, vendor_id, 4);
1443 memcpy(serial_number.vendor_specific.arr, vendor_specific, 4);
1444 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
1445 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.serial_number, serial_number);
1446 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.auto_learning, BCMOS_TRUE);
1447 /*set burst and data profiles to fec disabled*/
1448 if (board_technology == "XGS-PON") {
1449 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.xgpon.ranging_burst_profile, 2);
1450 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.xgpon.data_burst_profile, 1);
1451 } else if (board_technology == "GPON") {
1452 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.gpon.ds_ber_reporting_interval, 1000000);
1453 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.gpon.omci_port_id, onu_id);
1454 }
1455 err = bcmolt_cfg_set(dev_id, &onu_cfg.hdr);
1456 if (err != BCM_ERR_OK) {
1457 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to set activate ONU %d on PON %d, err %d\n", onu_id, intf_id, err);
1458 return bcm_to_grpc_err(err, "Failed to activate ONU");
1459 }
1460
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001461 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001462}
1463
Jonathan Davis70c21812018-07-19 15:32:10 -04001464Status DeactivateOnu_(uint32_t intf_id, uint32_t onu_id,
1465 const char *vendor_id, const char *vendor_specific) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001466 bcmos_errno err = BCM_ERR_OK;
1467 bcmolt_onu_set_onu_state onu_oper; /* declare main API struct */
1468 bcmolt_onu_cfg onu_cfg;
1469 bcmolt_onu_key onu_key; /**< Object key. */
1470 bcmolt_onu_state onu_state;
Jonathan Davis70c21812018-07-19 15:32:10 -04001471
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001472 onu_key.onu_id = onu_id;
1473 onu_key.pon_ni = intf_id;
1474 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
1475 BCMOLT_FIELD_SET_PRESENT(&onu_cfg.data, onu_cfg_data, onu_state);
1476 err = bcmolt_cfg_get(dev_id, &onu_cfg.hdr);
1477 if (err == BCM_ERR_OK) {
1478 switch (onu_state) {
1479 case BCMOLT_ONU_OPERATION_ACTIVE:
1480 BCMOLT_OPER_INIT(&onu_oper, onu, set_onu_state, onu_key);
1481 BCMOLT_FIELD_SET(&onu_oper.data, onu_set_onu_state_data,
1482 onu_state, BCMOLT_ONU_OPERATION_INACTIVE);
1483 err = bcmolt_oper_submit(dev_id, &onu_oper.hdr);
1484 if (err != BCM_ERR_OK) {
1485 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to \
1486deactivate ONU %d on PON %d, err %d\n", onu_id, intf_id, err);
1487 return bcm_to_grpc_err(err, "Failed to deactivate ONU");
1488 }
1489 break;
1490 }
Jonathan Davis70c21812018-07-19 15:32:10 -04001491 }
1492
1493 return Status::OK;
1494}
1495
1496Status DeleteOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001497 const char *vendor_id, const char *vendor_specific) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001498
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001499 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 -05001500 onu_id, intf_id, vendor_id, vendor_specific_to_str(vendor_specific).c_str());
1501
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001502 // Need to deactivate before removing it (BAL rules)
1503
1504 DeactivateOnu_(intf_id, onu_id, vendor_id, vendor_specific);
1505 // Sleep to allow the state to propagate
1506 // We need the subscriber terminal object to be admin down before removal
1507 // Without sleep the race condition is lost by ~ 20 ms
1508 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1509
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001510 // TODO: Delete the schedulers and queues.
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001511
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001512 bcmolt_onu_cfg cfg_obj;
1513 bcmolt_onu_key key;
Jonathan Davis70c21812018-07-19 15:32:10 -04001514
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001515 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 -04001516 onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -04001517
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001518 key.onu_id = onu_id;
1519 key.pon_ni = intf_id;
1520 BCMOLT_CFG_INIT(&cfg_obj, onu, key);
Jonathan Davis70c21812018-07-19 15:32:10 -04001521
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001522 bcmos_errno err = bcmolt_cfg_clear(dev_id, &cfg_obj.hdr);
Jonathan Davis70c21812018-07-19 15:32:10 -04001523 if (err != BCM_ERR_OK)
1524 {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001525 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 -04001526 onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -04001527 return Status(grpc::StatusCode::INTERNAL, "Failed to delete ONU");
1528 }
1529
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001530 return Status::OK;
Jonathan Davis70c21812018-07-19 15:32:10 -04001531}
1532
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001533#define MAX_CHAR_LENGTH 20
1534#define MAX_OMCI_MSG_LENGTH 44
1535Status OmciMsgOut_(uint32_t intf_id, uint32_t onu_id, const std::string pkt) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001536 bcmolt_bin_str buf = {};
1537 bcmolt_onu_cpu_packets omci_cpu_packets;
1538 bcmolt_onu_key key;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001539
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001540 key.pon_ni = intf_id;
1541 key.onu_id = onu_id;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001542
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001543 BCMOLT_OPER_INIT(&omci_cpu_packets, onu, cpu_packets, key);
1544 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, packet_type, BCMOLT_PACKET_TYPE_OMCI);
1545 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, calc_crc, BCMOS_TRUE);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001546
1547 // ???
1548 if ((pkt.size()/2) > MAX_OMCI_MSG_LENGTH) {
1549 buf.len = MAX_OMCI_MSG_LENGTH;
1550 } else {
1551 buf.len = pkt.size()/2;
1552 }
1553
1554 /* Send the OMCI packet using the BAL remote proxy API */
1555 uint16_t idx1 = 0;
1556 uint16_t idx2 = 0;
1557 uint8_t arraySend[buf.len];
1558 char str1[MAX_CHAR_LENGTH];
1559 char str2[MAX_CHAR_LENGTH];
1560 memset(&arraySend, 0, buf.len);
1561
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001562 for (idx1=0,idx2=0; idx1<((buf.len)*2); idx1++,idx2++) {
1563 sprintf(str1,"%c", pkt[idx1]);
1564 sprintf(str2,"%c", pkt[++idx1]);
1565 strcat(str1,str2);
1566 arraySend[idx2] = strtol(str1, NULL, 16);
1567 }
1568
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001569 buf.arr = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
1570 memcpy(buf.arr, (uint8_t *)arraySend, buf.len);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001571
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001572 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, number_of_packets, 1);
1573 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, packet_size, buf.len);
1574 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, buffer, buf);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001575
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001576 bcmos_errno err = bcmolt_oper_submit(dev_id, &omci_cpu_packets.hdr);
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001577 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001578 OPENOLT_LOG(ERROR, omci_log_id, "Error sending OMCI message to ONU %d on PON %d\n", onu_id, intf_id);
1579 return bcm_to_grpc_err(err, "send OMCI failed");
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001580 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001581 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 -05001582 buf.len, onu_id, intf_id, pkt.c_str());
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001583 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001584 free(buf.arr);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001585
1586 return Status::OK;
1587}
1588
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001589Status OnuPacketOut_(uint32_t intf_id, uint32_t onu_id, uint32_t port_no, uint32_t gemport_id, const std::string pkt) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001590 bcmolt_pon_interface_cpu_packets pon_interface_cpu_packets; /**< declare main API struct */
1591 bcmolt_pon_interface_key key = {.pon_ni = (bcmolt_interface)intf_id}; /**< declare key */
1592 bcmolt_bin_str buf = {};
1593 bcmolt_gem_port_id gem_port_id_array[1];
1594 bcmolt_gem_port_id_list_u8_max_16 gem_port_list = {};
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001595
Craig Lutgen967a1d02018-11-27 10:41:51 -06001596 if (port_no > 0) {
1597 bool found = false;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001598 if (gemport_id == 0) {
1599 bcmos_fastlock_lock(&data_lock);
1600 // Map the port_no to one of the flows that owns it to find a gemport_id for that flow.
1601 // Pick any flow that is mapped with the same port_no.
1602 std::map<uint32_t, std::set<uint32_t> >::const_iterator it = port_to_flows.find(port_no);
1603 if (it != port_to_flows.end() && !it->second.empty()) {
1604 uint32_t flow_id = *(it->second.begin()); // Pick any flow_id out of the bag set
1605 std::map<uint32_t, uint32_t>::const_iterator fit = flowid_to_gemport.find(flow_id);
1606 if (fit != flowid_to_gemport.end()) {
1607 found = true;
1608 gemport_id = fit->second;
1609 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001610 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001611 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001612
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001613 if (!found) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001614 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 -08001615 onu_id, port_no, intf_id);
1616 return grpc::Status(grpc::StatusCode::NOT_FOUND, "no flow for port_no");
1617 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001618 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 -08001619 gemport_id, onu_id, port_no, intf_id);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001620 }
1621
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001622 gem_port_id_array[0] = gemport_id;
1623 gem_port_list.len = 1;
1624 gem_port_list.arr = gem_port_id_array;
1625 buf.len = pkt.size();
1626 buf.arr = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
1627 memcpy(buf.arr, (uint8_t *)pkt.data(), buf.len);
1628
1629 /* init the API struct */
1630 BCMOLT_OPER_INIT(&pon_interface_cpu_packets, pon_interface, cpu_packets, key);
1631 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, packet_type, BCMOLT_PACKET_TYPE_ETH);
1632 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, calc_crc, BCMOS_TRUE);
1633 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, gem_port_list, gem_port_list);
1634 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, buffer, buf);
1635
1636 OPENOLT_LOG(INFO, openolt_log_id, "Packet out of length %d sent to gemport %d on pon %d port_no %u\n",
1637 (uint8_t)pkt.size(), gemport_id, intf_id, port_no);
1638
1639 /* call API */
1640 bcmolt_oper_submit(dev_id, &pon_interface_cpu_packets.hdr);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001641 }
1642 else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001643 //TODO: Port No is 0, it is coming sender requirement.
1644 OPENOLT_LOG(INFO, openolt_log_id, "port_no %d onu %d on pon %d\n",
1645 port_no, onu_id, intf_id);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001646 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001647 free(buf.arr);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001648
1649 return Status::OK;
1650}
1651
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001652Status UplinkPacketOut_(uint32_t intf_id, const std::string pkt) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001653 bcmolt_flow_key key = {}; /* declare key */
1654 bcmolt_bin_str buffer = {};
1655 bcmolt_flow_send_eth_packet oper; /* declare main API struct */
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001656
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001657 // TODO: flow_id is currently not passed in UplinkPacket message from voltha.
1658 bcmolt_flow_id flow_id = 0;
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001659
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001660 //validate flow_id and find flow_id/flow type: upstream/ingress type: PON/egress type: NNI
1661 if (get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, FLOW_TYPE) == BCMOLT_FLOW_TYPE_UPSTREAM && \
1662 get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, INGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_PON && \
1663 get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, EGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_NNI)
1664 key.flow_id = flow_id;
1665 else {
1666 if (flow_id_counters != 0) {
1667 for (int flowid=0; flowid < flow_id_counters; flowid++) {
1668 int flow_index = flow_id_data[flowid][0];
1669 if (get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, FLOW_TYPE) == BCMOLT_FLOW_TYPE_UPSTREAM && \
1670 get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, INGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_PON && \
1671 get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, EGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_NNI) {
1672 key.flow_id = flow_index;
1673 break;
1674 }
1675 }
1676 }
1677 else {
1678 return grpc::Status(grpc::StatusCode::NOT_FOUND, "no flow id found");
1679 }
1680 }
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001681
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001682 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM; /* send from uplink direction */
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001683
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001684 /* Initialize the API struct. */
1685 BCMOLT_OPER_INIT(&oper, flow, send_eth_packet, key);
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001686
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001687 buffer.len = pkt.size();
1688 buffer.arr = (uint8_t *)malloc((buffer.len)*sizeof(uint8_t));
1689 memcpy(buffer.arr, (uint8_t *)pkt.data(), buffer.len);
1690 if (buffer.arr == NULL) {
1691 OPENOLT_LOG(ERROR, openolt_log_id, "allocate packet buffer failed\n");
1692 return bcm_to_grpc_err(BCM_ERR_PARM, "allocate packet buffer failed");
1693 }
1694 BCMOLT_FIELD_SET(&oper.data, flow_send_eth_packet_data, buffer, buffer);
1695
1696 bcmos_errno err = bcmolt_oper_submit(dev_id, &oper.hdr);
1697 if (err) {
1698 OPENOLT_LOG(ERROR, openolt_log_id, "Error sending packets via nni port %d, flow_id %d err %d\n", intf_id, key.flow_id, err);
1699 } else {
1700 OPENOLT_LOG(INFO, openolt_log_id, "sent packets to port %d in upstream direction, flow_id %d \n", intf_id, key.flow_id);
1701 }
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04001702
1703 return Status::OK;
1704}
1705
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001706uint32_t GetPortNum_(uint32_t flow_id) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001707 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001708 uint32_t port_no = 0;
1709 std::map<uint32_t, uint32_t >::const_iterator it = flowid_to_port.find(flow_id);
1710 if (it != flowid_to_port.end()) {
1711 port_no = it->second;
1712 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001713 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001714 return port_no;
1715}
1716
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001717#define FLOW_LOG(level,msg,err) \
1718 do { \
1719 OPENOLT_LOG(level, openolt_log_id, "--------> %s (flow_id %d) err: %d <--------\n", msg, key.flow_id, err); \
1720 OPENOLT_LOG(level, openolt_log_id, "intf_id %d, onu_id %d, uni_id %d, port_no %u, cookie %"PRIu64"\n", \
1721 access_intf_id, onu_id, uni_id, port_no, cookie); \
1722 OPENOLT_LOG(level, openolt_log_id, "flow_type %s, queue_id %d, sched_id %d\n", flow_type.c_str(), \
1723 cfg.data.egress_qos.u.fixed_queue.queue_id, cfg.data.egress_qos.tm_sched.id); \
1724 OPENOLT_LOG(level, openolt_log_id, "Ingress(intfd_type %s, intf_id %d), Egress(intf_type %s, intf_id %d)\n", \
1725 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), cfg.data.ingress_intf.intf_id, \
1726 GET_FLOW_INTERFACE_TYPE(cfg.data.egress_intf.intf_type), cfg.data.egress_intf.intf_id); \
1727 OPENOLT_LOG(level, openolt_log_id, "classifier(o_vid %d, o_pbits %d, i_vid %d, i_pbits %d, ether type 0x%x)\n", \
1728 c_val.o_vid, c_val.o_pbits, c_val.i_vid, c_val.i_pbits, classifier.eth_type()); \
1729 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", \
1730 c_val.ip_proto, gemport_id, c_val.src_port, c_val.dst_port, GET_PKT_TAG_TYPE(c_val.pkt_tag_type)); \
1731 OPENOLT_LOG(level, openolt_log_id, "action(cmds_bitmask %s, o_vid %d, o_pbits %d, i_vid %d, i_pbits %d)\n\n", \
1732 get_flow_acton_command(a_val.cmds_bitmask), a_val.o_vid, a_val.o_pbits, a_val.i_vid, a_val.i_pbits); \
1733 } while(0)
1734
1735#define FLOW_PARAM_LOG() \
1736 do { \
1737 OPENOLT_LOG(INFO, openolt_log_id, "--------> flow comparison (now before) <--------\n"); \
1738 OPENOLT_LOG(INFO, openolt_log_id, "flow_id (%d %d)\n", \
1739 key.flow_id, flow_index); \
1740 OPENOLT_LOG(INFO, openolt_log_id, "onu_id (%d %lu)\n", \
1741 cfg.data.onu_id , get_flow_status(flow_index, flow_id_data[flowid][1], ONU_ID)); \
1742 OPENOLT_LOG(INFO, openolt_log_id, "type (%d %lu)\n", \
1743 key.flow_type, get_flow_status(flow_index, flow_id_data[flowid][1], FLOW_TYPE)); \
1744 OPENOLT_LOG(INFO, openolt_log_id, "svc_port_id (%d %lu)\n", \
1745 cfg.data.svc_port_id, get_flow_status(flow_index, flow_id_data[flowid][1], SVC_PORT_ID)); \
1746 OPENOLT_LOG(INFO, openolt_log_id, "priority (%d %lu)\n", \
1747 cfg.data.priority, get_flow_status(flow_index, flow_id_data[flowid][1], PRIORITY)); \
1748 OPENOLT_LOG(INFO, openolt_log_id, "cookie (%lu %lu)\n", \
1749 cfg.data.cookie, get_flow_status(flow_index, flow_id_data[flowid][1], COOKIE)); \
1750 OPENOLT_LOG(INFO, openolt_log_id, "ingress intf_type (%s %s)\n", \
1751 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), \
1752 GET_FLOW_INTERFACE_TYPE(get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_TYPE))); \
1753 OPENOLT_LOG(INFO, openolt_log_id, "ingress intf id (%d %lu)\n", \
1754 cfg.data.ingress_intf.intf_id , get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_ID)); \
1755 OPENOLT_LOG(INFO, openolt_log_id, "egress intf_type (%d %lu)\n", \
1756 cfg.data.egress_intf.intf_type , get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_TYPE)); \
1757 OPENOLT_LOG(INFO, openolt_log_id, "egress intf_id (%d %lu)\n", \
1758 cfg.data.egress_intf.intf_id , get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_ID)); \
1759 OPENOLT_LOG(INFO, openolt_log_id, "classifier o_vid (%d %lu)\n", \
1760 c_val.o_vid , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_VID)); \
1761 OPENOLT_LOG(INFO, openolt_log_id, "classifier o_pbits (%d %lu)\n", \
1762 c_val.o_pbits , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_PBITS)); \
1763 OPENOLT_LOG(INFO, openolt_log_id, "classifier i_vid (%d %lu)\n", \
1764 c_val.i_vid , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_VID)); \
1765 OPENOLT_LOG(INFO, openolt_log_id, "classifier i_pbits (%d %lu)\n", \
1766 c_val.i_pbits , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_PBITS)); \
1767 OPENOLT_LOG(INFO, openolt_log_id, "classifier ether_type (0x%x 0x%lx)\n", \
1768 c_val.ether_type , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_ETHER_TYPE)); \
1769 OPENOLT_LOG(INFO, openolt_log_id, "classifier ip_proto (%d %lu)\n", \
1770 c_val.ip_proto , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_IP_PROTO)); \
1771 OPENOLT_LOG(INFO, openolt_log_id, "classifier src_port (%d %lu)\n", \
1772 c_val.src_port , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_SRC_PORT)); \
1773 OPENOLT_LOG(INFO, openolt_log_id, "classifier dst_port (%d %lu)\n", \
1774 c_val.dst_port , get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_DST_PORT)); \
1775 OPENOLT_LOG(INFO, openolt_log_id, "classifier pkt_tag_type (%s %s)\n", \
1776 GET_PKT_TAG_TYPE(c_val.pkt_tag_type), \
1777 GET_PKT_TAG_TYPE(get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_PKT_TAG_TYPE))); \
1778 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos type (%d %lu)\n", \
1779 cfg.data.egress_qos.type , get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TYPE)); \
1780 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos queue_id (%d %lu)\n", \
1781 cfg.data.egress_qos.u.fixed_queue.queue_id, \
1782 get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_QUEUE_ID)); \
1783 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos sched_id (%d %lu)\n", \
1784 cfg.data.egress_qos.tm_sched.id, \
1785 get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TM_SCHED_ID)); \
1786 OPENOLT_LOG(INFO, openolt_log_id, "classifier cmds_bitmask (%s %s)\n", \
1787 get_flow_acton_command(a_val.cmds_bitmask), \
1788 get_flow_acton_command(get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_CMDS_BITMASK))); \
1789 OPENOLT_LOG(INFO, openolt_log_id, "action o_vid (%d %lu)\n", \
1790 a_val.o_vid , get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_VID)); \
1791 OPENOLT_LOG(INFO, openolt_log_id, "action i_vid (%d %lu)\n", \
1792 a_val.i_vid , get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_VID)); \
1793 OPENOLT_LOG(INFO, openolt_log_id, "action o_pbits (%d %lu)\n", \
1794 a_val.o_pbits , get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_PBITS)); \
1795 OPENOLT_LOG(INFO, openolt_log_id, "action i_pbits (%d %lu)\n\n", \
1796 a_val.i_pbits, get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_PBITS)); \
1797 } while(0)
1798
1799#define FLOW_CHECKER
1800//#define SHOW_FLOW_PARAM
1801
Craig Lutgen967a1d02018-11-27 10:41:51 -06001802Status 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 +00001803 uint32_t flow_id, const std::string flow_type,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001804 int32_t alloc_id, int32_t network_intf_id,
1805 int32_t gemport_id, const ::openolt::Classifier& classifier,
Craig Lutgen967a1d02018-11-27 10:41:51 -06001806 const ::openolt::Action& action, int32_t priority_value, uint64_t cookie) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001807 bcmolt_flow_cfg cfg;
1808 bcmolt_flow_key key = { }; /**< Object key. */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001809 int32_t o_vid = -1;
1810 bool single_tag = false;
1811 uint32_t ether_type = 0;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001812 bcmolt_classifier c_val = { };
1813 bcmolt_action a_val = { };
1814 bcmolt_tm_queue_ref tm_val = { };
1815 int tm_qmp_id, tm_q_set_id;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001816
1817 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001818 if (flow_type.compare(upstream) == 0 ) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001819 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001820 } else if (flow_type.compare(downstream) == 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001821 key.flow_type = BCMOLT_FLOW_TYPE_DOWNSTREAM;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001822 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001823 OPENOLT_LOG(ERROR, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001824 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001825 }
1826
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001827 BCMOLT_CFG_INIT(&cfg, flow, key);
1828 BCMOLT_MSG_FIELD_SET(&cfg, cookie, cookie);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001829
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001830 if (access_intf_id >= 0 && network_intf_id >= 0) {
1831 if (key.flow_type == BCMOLT_FLOW_TYPE_UPSTREAM) { //upstream
1832 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_PON);
1833 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_id, access_intf_id);
1834 if (classifier.eth_type() == EAP_ETHER_TYPE || //EAPOL packet
1835 (classifier.ip_proto() == 17 && classifier.src_port() == 68 && classifier.dst_port() == 67)) { //DHCP packet
1836 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_HOST);
1837 } else {
1838 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_NNI);
1839 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_id, network_intf_id);
1840 }
1841 } else if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) { //downstream
1842 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_NNI);
1843 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_id, network_intf_id);
1844 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_PON);
1845 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_id, access_intf_id);
1846 }
1847 } else {
1848 OPENOLT_LOG(ERROR, openolt_log_id, "flow network setting invalid\n");
1849 return bcm_to_grpc_err(BCM_ERR_PARM, "flow network setting invalid");
1850 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001851
Shad Ansari39739bc2018-09-13 21:38:37 +00001852 if (onu_id >= 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001853 BCMOLT_MSG_FIELD_SET(&cfg, onu_id, onu_id);
Shad Ansari39739bc2018-09-13 21:38:37 +00001854 }
1855 if (gemport_id >= 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001856 BCMOLT_MSG_FIELD_SET(&cfg, svc_port_id, gemport_id);
Shad Ansari39739bc2018-09-13 21:38:37 +00001857 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001858 if (gemport_id >= 0 && port_no != 0) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001859 bcmos_fastlock_lock(&data_lock);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001860 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
Craig Lutgen967a1d02018-11-27 10:41:51 -06001861 port_to_flows[port_no].insert(key.flow_id);
1862 flowid_to_gemport[key.flow_id] = gemport_id;
1863 }
1864 else
1865 {
1866 flowid_to_port[key.flow_id] = port_no;
1867 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001868 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001869 }
Shad Ansari39739bc2018-09-13 21:38:37 +00001870 if (priority_value >= 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001871 BCMOLT_MSG_FIELD_SET(&cfg, priority, priority_value);
Shad Ansari39739bc2018-09-13 21:38:37 +00001872 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001873
1874 {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001875 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001876 if (classifier.o_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001877 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_tpid 0x%04x\n", classifier.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001878 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_tpid, classifier.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001879 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001880 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001881 if (classifier.o_vid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001882 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_vid %d\n", classifier.o_vid());
1883 BCMOLT_FIELD_SET(&c_val, classifier, o_vid, classifier.o_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001884 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001885 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001886 if (classifier.i_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001887 OPENOLT_LOG(DEBUG, openolt_log_id, "classify i_tpid 0x%04x\n", classifier.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001888 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, i_tpid, classifier.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001889 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001890 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001891 if (classifier.i_vid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001892 OPENOLT_LOG(DEBUG, openolt_log_id, "classify i_vid %d\n", classifier.i_vid());
1893 BCMOLT_FIELD_SET(&c_val, classifier, i_vid, classifier.i_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001894 }
1895
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001896 if (classifier.eth_type()) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001897 ether_type = classifier.eth_type();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001898 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ether_type 0x%04x\n", classifier.eth_type());
1899 BCMOLT_FIELD_SET(&c_val, classifier, ether_type, classifier.eth_type());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001900 }
1901
1902 /*
1903 if (classifier.dst_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001904 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_mac, classifier.dst_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001905 }
1906
1907 if (classifier.src_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001908 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_mac, classifier.src_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001909 }
1910 */
1911
1912 if (classifier.ip_proto()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001913 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ip_proto %d\n", classifier.ip_proto());
1914 BCMOLT_FIELD_SET(&c_val, classifier, ip_proto, classifier.ip_proto());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001915 }
1916
1917 /*
1918 if (classifier.dst_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001919 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_ip, classifier.dst_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001920 }
1921
1922 if (classifier.src_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001923 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_ip, classifier.src_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001924 }
1925 */
1926
1927 if (classifier.src_port()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001928 OPENOLT_LOG(DEBUG, openolt_log_id, "classify src_port %d\n", classifier.src_port());
1929 BCMOLT_FIELD_SET(&c_val, classifier, src_port, classifier.src_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001930 }
1931
1932 if (classifier.dst_port()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001933 OPENOLT_LOG(DEBUG, openolt_log_id, "classify dst_port %d\n", classifier.dst_port());
1934 BCMOLT_FIELD_SET(&c_val, classifier, dst_port, classifier.dst_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001935 }
1936
1937 if (!classifier.pkt_tag_type().empty()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001938 OPENOLT_LOG(DEBUG, openolt_log_id, "classify tag_type %s\n", classifier.pkt_tag_type().c_str());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001939 if (classifier.pkt_tag_type().compare("untagged") == 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001940 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_UNTAGGED);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001941 } else if (classifier.pkt_tag_type().compare("single_tag") == 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001942 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_SINGLE_TAG);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001943 single_tag = true;
1944
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001945 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1946 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, classifier.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001947 } else if (classifier.pkt_tag_type().compare("double_tag") == 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001948 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_DOUBLE_TAG);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001949
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001950 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1951 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, classifier.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001952 }
1953 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001954 BCMOLT_MSG_FIELD_SET(&cfg, classifier, c_val);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001955 }
1956
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001957 if (cfg.data.egress_intf.intf_type != BCMOLT_FLOW_INTERFACE_TYPE_HOST) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001958 const ::openolt::ActionCmd& cmd = action.cmd();
1959
1960 if (cmd.add_outer_tag()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001961 OPENOLT_LOG(DEBUG, openolt_log_id, "action add o_tag\n");
1962 BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, BCMOLT_ACTION_CMD_ID_ADD_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001963 }
1964
1965 if (cmd.remove_outer_tag()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001966 OPENOLT_LOG(DEBUG, openolt_log_id, "action pop o_tag\n");
1967 BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, BCMOLT_ACTION_CMD_ID_REMOVE_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001968 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001969 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001970 if (cmd.trap_to_host()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001971 OPENOLT_LOG(INFO, openolt_log_id, "action trap-to-host\n");
Craig Lutgen19512312018-11-02 10:14:46 -05001972 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, cmds_bitmask, BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001973 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001974 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001975 if (action.o_vid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001976 OPENOLT_LOG(DEBUG, openolt_log_id, "action o_vid=%d\n", action.o_vid());
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001977 o_vid = action.o_vid();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001978 BCMOLT_FIELD_SET(&a_val, action, o_vid, action.o_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001979 }
1980
1981 if (action.o_pbits()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001982 OPENOLT_LOG(DEBUG, openolt_log_id, "action o_pbits=0x%x\n", action.o_pbits());
1983 BCMOLT_FIELD_SET(&a_val, action, o_pbits, action.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001984 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001985 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001986 if (action.o_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001987 OPENOLT_LOG(INFO, openolt_log_id, "action o_tpid=0x%04x\n", action.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001988 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, o_tpid, action.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001989 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001990 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001991 if (action.i_vid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001992 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_vid=%d\n", action.i_vid());
1993 BCMOLT_FIELD_SET(&a_val, action, i_vid, action.i_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001994 }
1995
1996 if (action.i_pbits()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001997 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_pbits=0x%x\n", action.i_pbits());
1998 BCMOLT_FIELD_SET(&a_val, action, i_pbits, action.i_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001999 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002000 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002001 if (action.i_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002002 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_tpid=0x%04x\n", action.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05002003 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, i_tpid, action.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002004 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002005 */
2006 BCMOLT_MSG_FIELD_SET(&cfg, action, a_val);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002007 }
2008
Shad Ansari39739bc2018-09-13 21:38:37 +00002009 if ((access_intf_id >= 0) && (onu_id >= 0)) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002010 if(single_tag && ether_type == EAP_ETHER_TYPE) {
2011 tm_val.sched_id = (flow_type.compare(upstream) == 0) ? \
2012 get_default_tm_sched_id(network_intf_id, upstream) : \
2013 get_default_tm_sched_id(access_intf_id, downstream);
2014 tm_val.queue_id = 0;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002015
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002016 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE);
2017 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2018 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002019
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002020 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2021 flow_type.c_str(), tm_val.queue_id, tm_val.sched_id, \
2022 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2023 } else {
2024 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
2025 tm_val.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, downstream);
2026
2027 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2028 // Queue 0 on DS subscriber scheduler
2029 tm_val.queue_id = 0;
2030
2031 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2032 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2033 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
2034
2035 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2036 downstream.c_str(), tm_val.queue_id, tm_val.sched_id, \
2037 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2038
2039 } else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2040 /* Fetch TM QMP ID mapped to DS subscriber scheduler */
2041 tm_qmp_id = tm_q_set_id = get_tm_qmp_id(tm_val.sched_id, access_intf_id, onu_id, uni_id);
2042
2043 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2044 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2045 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_qmp_id, tm_qmp_id);
2046 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_q_set_id, tm_q_set_id);
2047
2048 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, q_set_id = %d, sched_id = %d, intf_type %s\n", \
2049 downstream.c_str(), tm_q_set_id, tm_val.sched_id, \
2050 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2051 }
2052 } else if (key.flow_type == BCMOLT_FLOW_TYPE_UPSTREAM) {
2053 // NNI Scheduler ID
2054 tm_val.sched_id = get_default_tm_sched_id(network_intf_id, upstream);
2055 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2056 // Queue 0 on NNI scheduler
2057 tm_val.queue_id = 0;
2058 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2059 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2060 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
2061
2062 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2063 upstream.c_str(), tm_val.queue_id, tm_val.sched_id, \
2064 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2065
2066 } else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2067 /* Fetch TM QMP ID mapped to US NNI scheduler */
2068 tm_qmp_id = tm_q_set_id = get_tm_qmp_id(tm_val.sched_id, access_intf_id, onu_id, uni_id);
2069 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2070 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2071 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_qmp_id, tm_qmp_id);
2072 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_q_set_id, tm_q_set_id);
2073
2074 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, q_set_id = %d, sched_id = %d, intf_type %s\n", \
2075 upstream.c_str(), tm_q_set_id, tm_val.sched_id, \
2076 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2077 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002078 }
Shad Ansari39739bc2018-09-13 21:38:37 +00002079 }
Shad Ansari06101952018-07-25 00:22:09 +00002080 }
2081
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002082 BCMOLT_MSG_FIELD_SET(&cfg, state, BCMOLT_FLOW_STATE_ENABLE);
2083 BCMOLT_MSG_FIELD_SET(&cfg, statistics, BCMOLT_CONTROL_STATE_ENABLE);
2084#ifdef FLOW_CHECKER
2085 //Flow Checker, To avoid duplicate flow.
2086 if (flow_id_counters != 0) {
2087 bool b_duplicate_flow = false;
2088 for (int flowid=0; flowid < flow_id_counters; flowid++) {
2089 int flow_index = flow_id_data[flowid][0];
2090 b_duplicate_flow = (cfg.data.onu_id == get_flow_status(flow_index, flow_id_data[flowid][1], ONU_ID)) && \
2091 (key.flow_type == flow_id_data[flowid][1]) && \
2092 (cfg.data.svc_port_id == get_flow_status(flow_index, flow_id_data[flowid][1], SVC_PORT_ID)) && \
2093 (cfg.data.priority == get_flow_status(flow_index, flow_id_data[flowid][1], PRIORITY)) && \
2094 (cfg.data.cookie == get_flow_status(flow_index, flow_id_data[flowid][1], COOKIE)) && \
2095 (cfg.data.ingress_intf.intf_type == get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_TYPE)) && \
2096 (cfg.data.ingress_intf.intf_id == get_flow_status(flow_index, flow_id_data[flowid][1], INGRESS_INTF_ID)) && \
2097 (cfg.data.egress_intf.intf_type == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_TYPE)) && \
2098 (cfg.data.egress_intf.intf_id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_INTF_ID)) && \
2099 (c_val.o_vid == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_VID)) && \
2100 (c_val.o_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_O_PBITS)) && \
2101 (c_val.i_vid == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_VID)) && \
2102 (c_val.i_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_I_PBITS)) && \
2103 (c_val.ether_type == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_ETHER_TYPE)) && \
2104 (c_val.ip_proto == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_IP_PROTO)) && \
2105 (c_val.src_port == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_SRC_PORT)) && \
2106 (c_val.dst_port == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_DST_PORT)) && \
2107 (c_val.pkt_tag_type == get_flow_status(flow_index, flow_id_data[flowid][1], CLASSIFIER_PKT_TAG_TYPE)) && \
2108 (cfg.data.egress_qos.type == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TYPE)) && \
2109 (cfg.data.egress_qos.u.fixed_queue.queue_id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_QUEUE_ID)) && \
2110 (cfg.data.egress_qos.tm_sched.id == get_flow_status(flow_index, flow_id_data[flowid][1], EGRESS_QOS_TM_SCHED_ID)) && \
2111 (a_val.cmds_bitmask == get_flow_status(flowid, flow_id_data[flowid][1], ACTION_CMDS_BITMASK)) && \
2112 (a_val.o_vid == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_VID)) && \
2113 (a_val.i_vid == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_VID)) && \
2114 (a_val.o_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_O_PBITS)) && \
2115 (a_val.i_pbits == get_flow_status(flow_index, flow_id_data[flowid][1], ACTION_I_PBITS)) && \
2116 (cfg.data.state == get_flow_status(flowid, flow_id_data[flowid][1], STATE));
2117#ifdef SHOW_FLOW_PARAM
2118 // Flow Parameter
2119 FLOW_PARAM_LOG();
2120#endif
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002121
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002122 if (b_duplicate_flow) {
2123 FLOW_LOG(WARNING, "Flow duplicate", 0);
2124 return bcm_to_grpc_err(BCM_ERR_ALREADY, "flow exists");
2125 }
2126 }
2127 }
2128#endif
2129
2130 bcmos_errno err = bcmolt_cfg_set(dev_id, &cfg.hdr);
2131 if (err) {
2132 FLOW_LOG(ERROR, "Flow add failed", err);
2133 return bcm_to_grpc_err(err, "flow add failed");
2134 } else {
2135 FLOW_LOG(INFO, "Flow add ok", err);
2136 bcmos_fastlock_lock(&data_lock);
2137 flow_id_data[flow_id_counters][0] = key.flow_id;
2138 flow_id_data[flow_id_counters][1] = key.flow_type;
2139 flow_id_counters += 1;
2140 bcmos_fastlock_unlock(&data_lock, 0);
2141 }
Nicolas Palpacuer0f19b1a2018-06-07 17:29:31 -04002142
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002143 return Status::OK;
2144}
2145
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002146Status FlowRemove_(uint32_t flow_id, const std::string flow_type) {
2147
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002148 bcmolt_flow_cfg cfg;
2149 bcmolt_flow_key key = { };
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002150
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002151 key.flow_id = (bcmolt_flow_id) flow_id;
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002152 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002153 if (flow_type.compare(upstream) == 0 ) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002154 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002155 } else if (flow_type.compare(downstream) == 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002156 key.flow_type = BCMOLT_FLOW_TYPE_DOWNSTREAM;
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002157 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002158 OPENOLT_LOG(WARNING, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002159 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
2160 }
2161
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002162 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002163 uint32_t port_no = flowid_to_port[key.flow_id];
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002164 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
Craig Lutgen967a1d02018-11-27 10:41:51 -06002165 flowid_to_gemport.erase(key.flow_id);
2166 port_to_flows[port_no].erase(key.flow_id);
2167 if (port_to_flows[port_no].empty()) port_to_flows.erase(port_no);
2168 }
2169 else
2170 {
2171 flowid_to_port.erase(key.flow_id);
2172 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002173 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002174
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002175 BCMOLT_CFG_INIT(&cfg, flow, key);
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002176
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002177 bcmos_errno err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002178 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002179 OPENOLT_LOG(ERROR, openolt_log_id, "Error %d while removing flow %d, %s\n",
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04002180 err, flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002181 return Status(grpc::StatusCode::INTERNAL, "Failed to remove flow");
2182 }
2183
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002184 bcmos_fastlock_lock(&data_lock);
2185 for (int flowid=0; flowid < flow_id_counters; flowid++) {
2186 if (flow_id_data[flowid][0] == flow_id && flow_id_data[flowid][1] == key.flow_type) {
2187 flow_id_counters -= 1;
2188 for (int i=flowid; i < flow_id_counters; i++) {
2189 flow_id_data[i][0] = flow_id_data[i + 1][0];
2190 flow_id_data[i][1] = flow_id_data[i + 1][1];
2191 }
2192 break;
2193 }
2194 }
2195 bcmos_fastlock_unlock(&data_lock, 0);
2196
2197 OPENOLT_LOG(INFO, openolt_log_id, "Flow %d, %s removed\n", flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04002198 return Status::OK;
2199}
2200
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002201bcmos_errno CreateDefaultSched(uint32_t intf_id, const std::string direction) {
2202 bcmos_errno err;
2203 bcmolt_tm_sched_cfg tm_sched_cfg;
2204 bcmolt_tm_sched_key tm_sched_key = {.id = 1};
2205 tm_sched_key.id = get_default_tm_sched_id(intf_id, direction);
2206
Jason Huangbf45ffb2019-10-30 17:29:02 +08002207 //check TM scheduler has configured or not
2208 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
2209 BCMOLT_MSG_FIELD_GET(&tm_sched_cfg, state);
2210 err = bcmolt_cfg_get(dev_id, &tm_sched_cfg.hdr);
2211 if (err) {
2212 OPENOLT_LOG(ERROR, openolt_log_id, "cfg: Failed to query TM scheduler\n");
2213 return err;
2214 }
2215 else if (tm_sched_cfg.data.state == BCMOLT_CONFIG_STATE_CONFIGURED) {
2216 OPENOLT_LOG(WARNING, openolt_log_id, "tm scheduler default config has already with id %d\n", tm_sched_key.id);
2217 return BCM_ERR_OK;
2218 }
2219
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002220 // bcmbal_tm_sched_owner
2221 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
2222
2223 /**< The output of the tm_sched object instance */
2224 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.type, BCMOLT_TM_SCHED_OUTPUT_TYPE_INTERFACE);
2225
2226 if (direction.compare(upstream) == 0) {
2227 // In upstream it is NNI scheduler
2228 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_type, BCMOLT_INTERFACE_TYPE_NNI);
2229 } else if (direction.compare(downstream) == 0) {
2230 // In downstream it is PON scheduler
2231 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_type, BCMOLT_INTERFACE_TYPE_PON);
2232 }
2233
2234 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_id, intf_id);
2235
2236 // bcmbal_tm_sched_type
2237 // set the deafult policy to strict priority
2238 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, sched_type, BCMOLT_TM_SCHED_TYPE_SP);
2239
2240 // num_priorities: Max number of strict priority scheduling elements
2241 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, num_priorities, 8);
2242
2243 // bcmbal_tm_shaping
2244 uint32_t cir = 1000000;
2245 uint32_t pir = 1000000;
2246 uint32_t burst = 65536;
2247 OPENOLT_LOG(INFO, openolt_log_id, "applying traffic shaping in %s pir=%u, burst=%u\n",
2248 direction.c_str(), pir, burst);
2249 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, pir);
2250 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, burst);
2251 // FIXME: Setting CIR, results in BAL throwing error 'tm_sched minimum rate is not supported yet'
2252 // BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.cir, cir);
2253 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.pir, pir);
2254 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.burst, burst);
2255
2256 err = bcmolt_cfg_set(dev_id, &tm_sched_cfg.hdr);
2257 if (err) {
2258 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create %s scheduler, id %d, intf_id %d, err %d\n", \
2259 direction.c_str(), tm_sched_key.id, intf_id, err);
2260 return err;
2261 }
2262
2263 OPENOLT_LOG(INFO, openolt_log_id, "Create %s scheduler success, id %d, intf_id %d\n", \
2264 direction.c_str(), tm_sched_key.id, intf_id);
2265 return BCM_ERR_OK;
2266}
2267
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002268bcmos_errno CreateSched(std::string direction, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t port_no,
2269 uint32_t alloc_id, tech_profile::AdditionalBW additional_bw, uint32_t weight, uint32_t priority,
2270 tech_profile::SchedulingPolicy sched_policy, tech_profile::TrafficShapingInfo tf_sh_info) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002271
2272 bcmos_errno err;
2273
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002274 if (direction == downstream) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002275 bcmolt_tm_sched_cfg tm_sched_cfg;
2276 bcmolt_tm_sched_key tm_sched_key = {.id = 1};
2277 tm_sched_key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002278
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002279 // bcmbal_tm_sched_owner
2280 // In downstream it is sub_term scheduler
2281 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002282
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002283 /**< The output of the tm_sched object instance */
2284 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.type, BCMOLT_TM_SCHED_OUTPUT_TYPE_TM_SCHED);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002285
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002286 // bcmbal_tm_sched_parent
2287 // The parent for the sub_term scheduler is the PON scheduler in the downstream
2288 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.tm_sched.tm_sched_id, get_default_tm_sched_id(intf_id, direction));
2289 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.tm_sched.tm_sched_param.u.priority.priority, priority);
2290 /* removed by BAL v3.0, N/A - No direct attachment point of type ONU, same functionality may
2291 be achieved using the' virtual' type of attachment.
2292 tm_sched_owner.u.sub_term.intf_id = intf_id;
2293 tm_sched_owner.u.sub_term.sub_term_id = onu_id;
2294 */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002295
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002296 // bcmbal_tm_sched_type
2297 // set the deafult policy to strict priority
2298 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, sched_type, BCMOLT_TM_SCHED_TYPE_SP);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002299
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002300 // num_priorities: Max number of strict priority scheduling elements
2301 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, num_priorities, 8);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002302
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002303 // bcmbal_tm_shaping
2304 if (tf_sh_info.cir() >= 0 && tf_sh_info.pir() > 0) {
2305 uint32_t cir = tf_sh_info.cir();
2306 uint32_t pir = tf_sh_info.pir();
2307 uint32_t burst = tf_sh_info.pbs();
2308 OPENOLT_LOG(INFO, openolt_log_id, "applying traffic shaping in DL cir=%u, pir=%u, burst=%u\n",
2309 cir, pir, burst);
2310 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, pir);
2311 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, burst);
2312 // FIXME: Setting CIR, results in BAL throwing error 'tm_sched minimum rate is not supported yet'
2313 //BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.cir, cir);
2314 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.pir, pir);
2315 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.burst, burst);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002316 }
2317
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002318 err = bcmolt_cfg_set(dev_id, &tm_sched_cfg.hdr);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002319 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002320 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create downstream subscriber scheduler, id %d, \
2321intf_id %d, onu_id %d, uni_id %d, port_no %u\n", tm_sched_key.id, intf_id, onu_id, \
2322 uni_id, port_no);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002323 return err;
2324 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002325 OPENOLT_LOG(INFO, openolt_log_id, "Create downstream subscriber sched, id %d, intf_id %d, onu_id %d, \
2326uni_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 -08002327
2328 } else { //upstream
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002329 bcmolt_itupon_alloc_cfg cfg;
2330 bcmolt_itupon_alloc_key key = { };
2331 key.pon_ni = intf_id;
2332 key.alloc_id = alloc_id;
2333 int bw_granularity = (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY;
2334 int pir_bw = tf_sh_info.pir();
2335 int cir_bw = tf_sh_info.cir();
2336 //offset to match bandwidth granularity
2337 int offset_pir_bw = pir_bw%bw_granularity;
2338 int offset_cir_bw = cir_bw%bw_granularity;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002339
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002340 pir_bw = pir_bw - offset_pir_bw;
2341 cir_bw = cir_bw - offset_cir_bw;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002342
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002343 BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002344
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002345 switch (additional_bw) {
2346 case 2: //AdditionalBW_BestEffort
2347 if (pir_bw == 0) {
2348 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
2349%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
2350 } else if (pir_bw < cir_bw) {
2351 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2352bandwidth (%d)\n", pir_bw, cir_bw);
2353 return BCM_ERR_PARM;
2354 } else if (pir_bw == cir_bw) {
2355 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
2356bandwidth for additional bandwidth eligibility of type best_effort\n");
2357 return BCM_ERR_PARM;
2358 }
2359 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_BEST_EFFORT);
2360 break;
2361 case 1: //AdditionalBW_NA
2362 if (pir_bw == 0) {
2363 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
2364%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
2365 return BCM_ERR_PARM;
2366 } else if (cir_bw == 0) {
2367 OPENOLT_LOG(ERROR, openolt_log_id, "Guaranteed bandwidth must be greater than zero for \
2368additional bandwidth eligibility of type Non-Assured (NA)\n");
2369 return BCM_ERR_PARM;
2370 } else if (pir_bw < cir_bw) {
2371 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2372bandwidth (%d)\n", pir_bw, cir_bw);
2373 return BCM_ERR_PARM;
2374 } else if (pir_bw == cir_bw) {
2375 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
2376bandwidth for additional bandwidth eligibility of type non_assured\n");
2377 return BCM_ERR_PARM;
2378 }
2379 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NON_ASSURED);
2380 break;
2381 case 0: //AdditionalBW_None
2382 if (pir_bw == 0) {
2383 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
238416000 bytes/sec\n");
2385 return BCM_ERR_PARM;
2386 } else if (cir_bw == 0) {
2387 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
2388for additional bandwidth eligibility of type None\n");
2389 return BCM_ERR_PARM;
2390 } else if (pir_bw > cir_bw) {
2391 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
2392for additional bandwidth eligibility of type None\n");
2393 OPENOLT_LOG(ERROR, openolt_log_id, "set Maximum bandwidth (%d) to Guaranteed \
2394bandwidth in None eligibility\n", pir_bw);
2395 cir_bw = pir_bw;
2396 } else if (pir_bw < cir_bw) {
2397 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
2398bandwidth (%d)\n", pir_bw, cir_bw);
2399 OPENOLT_LOG(ERROR, openolt_log_id, "set Maximum bandwidth (%d) to Guaranteed \
2400bandwidth in None eligibility\n", pir_bw);
2401 cir_bw = pir_bw;
2402 }
2403 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NONE);
2404 break;
2405 default:
2406 return BCM_ERR_PARM;
Girish Gowdrue075c642019-01-23 04:05:53 -08002407 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002408 /* CBR Real Time Bandwidth which require shaping of the bandwidth allocations
2409 in a fine granularity. */
2410 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_bw, 0);
2411 /* Fixed Bandwidth with no critical requirement of shaping */
2412 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_bw, 0);
2413 /* Dynamic bandwidth which the OLT is committed to allocate upon demand */
2414 BCMOLT_MSG_FIELD_SET(&cfg, sla.guaranteed_bw, cir_bw);
2415 /* Maximum allocated bandwidth allowed for this alloc ID */
2416 BCMOLT_MSG_FIELD_SET(&cfg, sla.maximum_bw, pir_bw);
2417 BCMOLT_MSG_FIELD_SET(&cfg, sla.alloc_type, BCMOLT_ALLOC_TYPE_NSR);
2418 /* Set to True for AllocID with CBR RT Bandwidth that requires compensation
2419 for skipped allocations during quiet window */
2420 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_compensation, BCMOS_FALSE);
2421 /**< Allocation Profile index for CBR non-RT Bandwidth */
2422 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_ap_index, 0);
2423 /**< Allocation Profile index for CBR RT Bandwidth */
2424 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_ap_index, 0);
2425 /**< Alloc ID Weight used in case of Extended DBA mode */
2426 BCMOLT_MSG_FIELD_SET(&cfg, sla.weight, 0);
2427 /**< Alloc ID Priority used in case of Extended DBA mode */
2428 BCMOLT_MSG_FIELD_SET(&cfg, sla.priority, 0);
2429 BCMOLT_MSG_FIELD_SET(&cfg, onu_id, onu_id);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002430
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002431 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002432 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002433 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d,\
2434port_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 -08002435 return err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002436 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002437 OPENOLT_LOG(INFO, openolt_log_id, "Create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d, port_no %u, \
2438alloc_id %d\n", intf_id,onu_id,uni_id,port_no,alloc_id);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002439 }
2440
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002441 return BCM_ERR_OK;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002442}
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002443
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002444Status CreateTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
2445 uint32_t intf_id = traffic_scheds->intf_id();
2446 uint32_t onu_id = traffic_scheds->onu_id();
2447 uint32_t uni_id = traffic_scheds->uni_id();
2448 uint32_t port_no = traffic_scheds->port_no();
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002449 std::string direction;
2450 unsigned int alloc_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002451 tech_profile::SchedulerConfig sched_config;
2452 tech_profile::AdditionalBW additional_bw;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002453 uint32_t priority;
2454 uint32_t weight;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002455 tech_profile::SchedulingPolicy sched_policy;
2456 tech_profile::TrafficShapingInfo traffic_shaping_info;
2457 bcmos_errno err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002458
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002459 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
2460 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002461
2462 direction = GetDirection(traffic_sched.direction());
2463 if (direction.compare("direction-not-supported") == 0)
2464 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2465
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002466 alloc_id = traffic_sched.alloc_id();
2467 sched_config = traffic_sched.scheduler();
2468 additional_bw = sched_config.additional_bw();
2469 priority = sched_config.priority();
2470 weight = sched_config.weight();
2471 sched_policy = sched_config.sched_policy();
2472 traffic_shaping_info = traffic_sched.traffic_shaping_info();
2473 err = CreateSched(direction, intf_id, onu_id, uni_id, port_no, alloc_id, additional_bw, weight, priority,
2474 sched_policy, traffic_shaping_info);
2475 if (err) {
2476 return bcm_to_grpc_err(err, "Failed to create scheduler");
2477 }
Girish Gowdru1cdf6ce2018-08-27 02:43:02 -07002478 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002479 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002480}
Jonathan Davis70c21812018-07-19 15:32:10 -04002481
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002482bcmos_errno RemoveSched(int intf_id, int onu_id, int uni_id, int alloc_id, std::string direction) {
Jonathan Davis70c21812018-07-19 15:32:10 -04002483
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002484 bcmos_errno err;
Jonathan Davis70c21812018-07-19 15:32:10 -04002485
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002486 if (direction == upstream) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002487 bcmolt_itupon_alloc_cfg cfg;
2488 bcmolt_itupon_alloc_key key = { };
2489 key.pon_ni = intf_id;
2490 key.alloc_id = alloc_id;
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002491
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002492 BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
2493 err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
2494 if (err) {
2495 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove scheduler sched, direction = %s, intf_id %d, alloc_id %d, err %d\n", \
2496 direction.c_str(), intf_id, alloc_id, err);
2497 return err;
2498 }
2499 OPENOLT_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, intf_id %d, alloc_id %d\n", \
2500 direction.c_str(), intf_id, alloc_id);
2501 } else if (direction == downstream) {
2502 bcmolt_tm_sched_cfg cfg;
2503 bcmolt_tm_sched_key key = { };
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04002504
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002505 if (is_tm_sched_id_present(intf_id, onu_id, uni_id, direction)) {
2506 key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2507 } else {
2508 OPENOLT_LOG(INFO, openolt_log_id, "schduler not present in %s, err %d\n", direction.c_str(), err);
2509 return BCM_ERR_OK;
2510 }
2511 BCMOLT_CFG_INIT(&cfg, tm_sched, key);
2512 err = bcmolt_cfg_clear(dev_id, &(cfg.hdr));
2513 if (err) {
2514 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove scheduler, direction = %s, id %d, intf_id %d, onu_id %d\n", \
2515 direction.c_str(), key.id, intf_id, onu_id);
2516 return err;
2517 }
2518 OPENOLT_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, id %d, intf_id %d, onu_id %d\n", \
2519 direction.c_str(), key.id, intf_id, onu_id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002520 }
2521
2522 free_tm_sched_id(intf_id, onu_id, uni_id, direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002523 return BCM_ERR_OK;
2524}
2525
2526Status RemoveTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
2527 uint32_t intf_id = traffic_scheds->intf_id();
2528 uint32_t onu_id = traffic_scheds->onu_id();
2529 uint32_t uni_id = traffic_scheds->uni_id();
2530 std::string direction;
2531 bcmos_errno err;
2532
2533 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
2534 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002535
2536 direction = GetDirection(traffic_sched.direction());
2537 if (direction.compare("direction-not-supported") == 0)
2538 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2539
2540 int alloc_id = traffic_sched.alloc_id();
2541 err = RemoveSched(intf_id, onu_id, uni_id, alloc_id, direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002542 if (err) {
2543 return bcm_to_grpc_err(err, "error-removing-traffic-scheduler");
2544 }
2545 }
2546 return Status::OK;
2547}
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002548
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002549bcmos_errno CreateTrafficQueueMappingProfile(uint32_t sched_id, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, \
2550 std::string direction, std::vector<uint32_t> tmq_map_profile) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002551 bcmos_errno err;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002552 bcmolt_tm_qmp_cfg tm_qmp_cfg;
2553 bcmolt_tm_qmp_key tm_qmp_key;
2554 bcmolt_arr_u8_8 pbits_to_tmq_id = {0};
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002555
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002556 int tm_qmp_id = get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id, tmq_map_profile);
2557 if (tm_qmp_id == -1) {
2558 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create tm queue mapping profile. Max allowed profile count is 16.\n");
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002559 }
Girish Gowdruf26cf882019-05-01 23:47:58 -07002560
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002561 tm_qmp_key.id = tm_qmp_id;
2562 for (uint32_t priority=0; priority<tmq_map_profile.size(); priority++) {
2563 pbits_to_tmq_id.arr[priority] = tmq_map_profile[priority];
2564 }
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002565
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002566 BCMOLT_CFG_INIT(&tm_qmp_cfg, tm_qmp, tm_qmp_key);
2567 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, type, BCMOLT_TM_QMP_TYPE_PBITS);
2568 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, pbits_to_tmq_id, pbits_to_tmq_id);
2569 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, ref_count, 0);
2570 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, state, BCMOLT_CONFIG_STATE_CONFIGURED);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002571
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002572 err = bcmolt_cfg_set(dev_id, &tm_qmp_cfg.hdr);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002573 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002574 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create tm queue mapping profile, id %d\n", \
2575 tm_qmp_key.id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002576 return err;
2577 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06002578
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002579 OPENOLT_LOG(INFO, openolt_log_id, "Create tm queue mapping profile success, id %d\n", \
2580 tm_qmp_key.id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002581 return BCM_ERR_OK;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002582}
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002583
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002584bcmos_errno RemoveTrafficQueueMappingProfile(uint32_t tm_qmp_id) {
2585 bcmos_errno err;
2586 bcmolt_tm_qmp_cfg tm_qmp_cfg;
2587 bcmolt_tm_qmp_key tm_qmp_key;
2588 tm_qmp_key.id = tm_qmp_id;
2589
2590 BCMOLT_CFG_INIT(&tm_qmp_cfg, tm_qmp, tm_qmp_key);
2591 err = bcmolt_cfg_clear(dev_id, &tm_qmp_cfg.hdr);
2592 if (err) {
2593 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove tm queue mapping profile, id %d\n", \
2594 tm_qmp_key.id);
2595 return err;
2596 }
2597
2598 OPENOLT_LOG(INFO, openolt_log_id, "Remove tm queue mapping profile success, id %d\n", \
2599 tm_qmp_key.id);
2600 return BCM_ERR_OK;
2601}
2602
2603bcmos_errno CreateDefaultQueue(uint32_t intf_id, const std::string direction) {
2604 bcmos_errno err;
2605
2606 /* Create 4 Queues on given PON/NNI scheduler */
2607 for (int queue_id = 0; queue_id < 4; queue_id++) {
2608 bcmolt_tm_queue_cfg tm_queue_cfg;
2609 bcmolt_tm_queue_key tm_queue_key = {};
2610 tm_queue_key.sched_id = get_default_tm_sched_id(intf_id, direction);
2611 tm_queue_key.id = queue_id;
2612 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE)
2613 tm_queue_key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2614 else
2615 tm_queue_key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2616
2617 BCMOLT_CFG_INIT(&tm_queue_cfg, tm_queue, tm_queue_key);
2618 BCMOLT_MSG_FIELD_SET(&tm_queue_cfg, tm_sched_param.type, BCMOLT_TM_SCHED_PARAM_TYPE_PRIORITY);
2619 BCMOLT_MSG_FIELD_SET(&tm_queue_cfg, tm_sched_param.u.priority.priority, queue_id);
2620
2621 err = bcmolt_cfg_set(dev_id, &tm_queue_cfg.hdr);
2622 if (err) {
2623 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create %s tm queue, id %d, sched_id %d, tm_q_set_id %d\n", \
2624 direction.c_str(), tm_queue_key.id, tm_queue_key.sched_id, tm_queue_key.tm_q_set_id);
2625 return err;
2626 }
2627
2628 OPENOLT_LOG(INFO, openolt_log_id, "Create %s tm_queue success, id %d, sched_id %d, tm_q_set_id %d\n", \
2629 direction.c_str(), tm_queue_key.id, tm_queue_key.sched_id, tm_queue_key.tm_q_set_id);
2630 }
2631 return BCM_ERR_OK;
2632}
2633
2634bcmos_errno CreateQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
2635 uint32_t gemport_id) {
2636 bcmos_errno err;
2637 bcmolt_tm_queue_cfg cfg;
2638 bcmolt_tm_queue_key key = { };
2639 OPENOLT_LOG(INFO, openolt_log_id, "creating %s queue. access_intf_id = %d, onu_id = %d, uni_id = %d \
2640gemport_id = %d\n", direction.c_str(), access_intf_id, onu_id, uni_id, gemport_id);
2641
2642 key.sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2643 get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
2644
2645 if (priority > 7) {
2646 return BCM_ERR_RANGE;
2647 }
2648
2649 /* FIXME: The upstream queues have to be created once only.
2650 The upstream queues on the NNI scheduler are shared by all subscribers.
2651 When the first scheduler comes in, the queues get created, and are re-used by all others.
2652 Also, these queues should be present until the last subscriber exits the system.
2653 One solution is to have these queues always, i.e., create it as soon as OLT is enabled.
2654
2655 There is one queue per gem port and Queue ID is fetched based on priority_q configuration
2656 for each GEM in TECH PROFILE */
2657 key.id = queue_id_list[priority];
2658
2659 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2660 // Reset the Queue ID to 0, if it is fixed queue, i.e., there is only one queue for subscriber.
2661 key.id = 0;
2662 key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2663 }
2664 else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2665 key.tm_q_set_id = get_tm_qmp_id(key.sched_id, access_intf_id, onu_id, uni_id);
2666 }
2667 else {
2668 key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2669 }
2670
2671 OPENOLT_LOG(INFO, openolt_log_id, "queue assigned queue_id = %d\n", key.id);
2672
2673 BCMOLT_CFG_INIT(&cfg, tm_queue, key);
2674 BCMOLT_MSG_FIELD_SET(&cfg, tm_sched_param.u.priority.priority, priority);
2675
2676 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
2677 if (err) {
2678 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create subscriber tm queue, direction = %s, id %d, \
2679sched_id %d, tm_q_set_id %d, intf_id %d, onu_id %d, uni_id %d, err %d\n", \
2680 direction.c_str(), key.id, key.sched_id, key.tm_q_set_id, access_intf_id, onu_id, uni_id, err);
2681 return err;
2682 }
2683
2684 OPENOLT_LOG(INFO, openolt_log_id, "Created tm_queue, direction %s, id %d, sched_id %d, tm_q_set_id %d, \
2685intf_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);
2686 return BCM_ERR_OK;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002687}
2688
2689Status CreateTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
2690 uint32_t intf_id = traffic_queues->intf_id();
2691 uint32_t onu_id = traffic_queues->onu_id();
2692 uint32_t uni_id = traffic_queues->uni_id();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002693 uint32_t sched_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002694 std::string direction;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002695 bcmos_errno err;
2696
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002697 qos_type = (traffic_queues->traffic_queues_size() > 1) ? \
2698 BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
2699
2700 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2701 uint32_t queues_priority_q[traffic_queues->traffic_queues_size()] = {0};
2702 std::string queues_pbit_map[traffic_queues->traffic_queues_size()];
2703 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2704 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
2705
2706 direction = GetDirection(traffic_queue.direction());
2707 if (direction.compare("direction-not-supported") == 0)
2708 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2709
2710 queues_priority_q[i] = traffic_queue.priority();
2711 queues_pbit_map[i] = traffic_queue.pbit_map();
2712 }
2713
2714 std::vector<uint32_t> tmq_map_profile(8, 0);
2715 tmq_map_profile = get_tmq_map_profile(get_valid_queues_pbit_map(queues_pbit_map, COUNT_OF(queues_pbit_map)), \
2716 queues_priority_q, COUNT_OF(queues_priority_q));
2717 sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2718 get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2719
2720 int tm_qmp_id = get_tm_qmp_id(tmq_map_profile);
2721 if (tm_qmp_id == -1) {
2722 CreateTrafficQueueMappingProfile(sched_id, intf_id, onu_id, uni_id, direction, tmq_map_profile);
2723 } else if (tm_qmp_id != -1 && get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id) == -1) {
2724 OPENOLT_LOG(INFO, openolt_log_id, "tm queue mapping profile present already with id %d\n", tm_qmp_id);
2725 update_sched_qmp_id_map(sched_id, intf_id, onu_id, uni_id, tm_qmp_id);
2726 }
2727 }
2728
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002729 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2730 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002731
2732 direction = GetDirection(traffic_queue.direction());
2733 if (direction.compare("direction-not-supported") == 0)
2734 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2735
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002736 err = CreateQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002737
Girish Gowdruf26cf882019-05-01 23:47:58 -07002738 // If the queue exists already, lets not return failure and break the loop.
2739 if (err && err != BCM_ERR_ALREADY) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002740 return bcm_to_grpc_err(err, "Failed to create queue");
2741 }
2742 }
2743 return Status::OK;
2744}
2745
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002746bcmos_errno RemoveQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
2747 uint32_t gemport_id) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002748 bcmolt_tm_queue_cfg cfg;
2749 bcmolt_tm_queue_key key = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002750 bcmos_errno err;
2751
2752 if (direction == downstream) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002753 if (is_tm_sched_id_present(access_intf_id, onu_id, uni_id, direction)) {
2754 key.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
2755 key.id = queue_id_list[priority];
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002756 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002757 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 -08002758 return BCM_ERR_OK;
2759 }
2760 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002761 /* In the upstream we use pre-created queues on the NNI scheduler that are used by all subscribers.
2762 They should not be removed. So, lets return OK. */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002763 return BCM_ERR_OK;
2764 }
2765
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002766 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2767 key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
2768 // Reset the queue id to 0 when using fixed queue.
2769 key.id = 0;
2770 }
2771 else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2772 key.tm_q_set_id = get_tm_qmp_id(key.sched_id, access_intf_id, onu_id, uni_id);
2773 }
2774 else {
2775 key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
2776 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002777
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002778 BCMOLT_CFG_INIT(&cfg, tm_queue, key);
2779 err = bcmolt_cfg_clear(dev_id, &(cfg.hdr));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002780 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002781 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove queue, direction = %s, id %d, sched_id %d, \
2782tm_q_set_id %d, intf_id %d, onu_id %d, uni_id %d\n",
2783 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 -08002784 return err;
2785 }
2786
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002787 OPENOLT_LOG(INFO, openolt_log_id, "Removed tm_queue, direction %s, id %d, sched_id %d, tm_q_set_id %d, \
2788intf_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 -08002789
2790 return BCM_ERR_OK;
2791}
2792
2793Status RemoveTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
2794 uint32_t intf_id = traffic_queues->intf_id();
2795 uint32_t onu_id = traffic_queues->onu_id();
2796 uint32_t uni_id = traffic_queues->uni_id();
2797 uint32_t port_no = traffic_queues->port_no();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002798 uint32_t sched_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002799 std::string direction;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002800 bcmos_errno err;
2801
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002802 qos_type = (traffic_queues->traffic_queues_size() > 1) ? \
2803 BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
2804
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002805 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
2806 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002807
2808 direction = GetDirection(traffic_queue.direction());
2809 if (direction.compare("direction-not-supported") == 0)
2810 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
2811
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002812 err = RemoveQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
2813 if (err) {
2814 return bcm_to_grpc_err(err, "Failed to remove queue");
2815 }
Jonathan Davis70c21812018-07-19 15:32:10 -04002816 }
2817
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002818 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))) {
2819 sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
2820 get_tm_sched_id(intf_id, onu_id, uni_id, direction);
2821
2822 int tm_qmp_id = get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id);
2823 if (free_tm_qmp_id(sched_id, intf_id, onu_id, uni_id, tm_qmp_id)) {
2824 RemoveTrafficQueueMappingProfile(tm_qmp_id);
2825 }
2826 }
Jonathan Davis70c21812018-07-19 15:32:10 -04002827 return Status::OK;
Jonathan Davis70c21812018-07-19 15:32:10 -04002828}
Jason Huangbf45ffb2019-10-30 17:29:02 +08002829
2830Status check_connection() {
2831 int maxTrials = 60;
2832 while (!bcmolt_api_conn_mgr_is_connected(dev_id)) {
2833 sleep(1);
2834 if (--maxTrials == 0)
2835 return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check connection failed");
2836 else
2837 OPENOLT_LOG(INFO, openolt_log_id, "waiting for daemon connection ...\n");
2838 }
2839 OPENOLT_LOG(INFO, openolt_log_id, "daemon is connected\n");
2840 return Status::OK;
2841}
2842
2843Status check_bal_ready() {
2844 bcmos_errno err;
2845 int maxTrials = 30;
2846 bcmolt_olt_cfg olt_cfg = { };
2847 bcmolt_olt_key olt_key = { };
2848
2849 BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
2850 BCMOLT_MSG_FIELD_GET(&olt_cfg, bal_state);
2851
2852 while (olt_cfg.data.bal_state != BCMOLT_BAL_STATE_BAL_AND_SWITCH_READY) {
2853 if (--maxTrials == 0)
2854 return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check bal ready failed");
2855 sleep(5);
2856 #ifdef TEST_MODE
2857 // It is impossible to mock the setting of olt_cfg.data.bal_state because
2858 // the actual bcmolt_cfg_get passes the address of olt_cfg.hdr and we cannot
2859 // set the olt_cfg.data.bal_state. So a new stub function is created and address
2860 // of olt_cfg is passed. This is one-of case where we need to add specific
2861 // code in product code.
2862 if (bcmolt_cfg_get_stub(dev_id, &olt_cfg)) {
2863 #else
2864 if (bcmolt_cfg_get(dev_id, &olt_cfg.hdr)) {
2865 #endif
2866 continue;
2867 }
2868 else
2869 OPENOLT_LOG(INFO, openolt_log_id, "waiting for BAL ready ...\n");
2870 }
2871
2872 OPENOLT_LOG(INFO, openolt_log_id, "BAL is ready\n");
2873 return Status::OK;
2874}