blob: cf44cd42246de965cac952ef5e33e5ec4064ad7c [file] [log] [blame]
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001/*
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04002 Copyright (C) 2018 Open Networking Foundation
Shad Ansarib7b0ced2018-05-11 21:53:32 +00003
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include <iostream>
19#include <memory>
20#include <string>
21
22#include "Queue.h"
23#include <iostream>
24#include <sstream>
Nicolas Palpacuer9c352082018-08-14 16:37:14 -040025#include <chrono>
26#include <thread>
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -080027#include <bitset>
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{
39#include <bcmos_system.h>
40#include <bal_api.h>
41#include <bal_api_end.h>
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -040042// FIXME : dependency problem
43// #include <bcm_common_gpon.h>
Nicolas Palpacuer967438f2018-09-07 14:41:54 -040044// #include <bcm_dev_log_task.h>
Shad Ansarib7b0ced2018-05-11 21:53:32 +000045}
Craig Lutgen19512312018-11-02 10:14:46 -050046// These need patched into bal_model_types.h directly. But, with above extern "C", it cannot be done
47inline bcmbal_action_cmd_id& operator|=(bcmbal_action_cmd_id& a, bcmbal_action_cmd_id b) {return a = static_cast<bcmbal_action_cmd_id>(static_cast<int>(a) | static_cast<int>(b));}
48inline bcmbal_action_id& operator|=(bcmbal_action_id& a, bcmbal_action_id b) {return a = static_cast<bcmbal_action_id>(static_cast<int>(a) | static_cast<int>(b));}
49inline bcmbal_classifier_id& operator|=(bcmbal_classifier_id& a, bcmbal_classifier_id b) {return a = static_cast<bcmbal_classifier_id>(static_cast<int>(a) | static_cast<int>(b));}
50inline bcmbal_tm_sched_owner_agg_port_id& operator|=(bcmbal_tm_sched_owner_agg_port_id& a, bcmbal_tm_sched_owner_agg_port_id b) {return a = static_cast<bcmbal_tm_sched_owner_agg_port_id>(static_cast<int>(a) | static_cast<int>(b));}
51inline bcmbal_tm_sched_parent_id& operator|=(bcmbal_tm_sched_parent_id& a, bcmbal_tm_sched_parent_id b) {return a = static_cast<bcmbal_tm_sched_parent_id>(static_cast<int>(a) | static_cast<int>(b));}
52inline bcmbal_tm_shaping_id& operator|=(bcmbal_tm_shaping_id& a, bcmbal_tm_shaping_id b) {return a = static_cast<bcmbal_tm_shaping_id>(static_cast<int>(a) | static_cast<int>(b));}
Shad Ansarib7b0ced2018-05-11 21:53:32 +000053
Nicolas Palpacuer967438f2018-09-07 14:41:54 -040054dev_log_id openolt_log_id = bcm_dev_log_id_register("OPENOLT", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
55dev_log_id omci_log_id = bcm_dev_log_id_register("OMCI", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
56
Craig Lutgen88a22ad2018-10-04 12:30:46 -050057#define MAX_SUPPORTED_INTF 16
58#define BAL_RSC_MANAGER_BASE_TM_SCHED_ID 16384
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -080059#define MAX_TM_QUEUE_ID 8192
60#define MAX_TM_SCHED_ID 16384
61#define EAP_ETHER_TYPE 34958
Nicolas Palpacuer967438f2018-09-07 14:41:54 -040062
Craig Lutgen88a22ad2018-10-04 12:30:46 -050063static unsigned int num_of_nni_ports = 0;
64static unsigned int num_of_pon_ports = 0;
Craig Lutgenb2601f02018-10-23 13:04:31 -050065static std::string intf_technologies[MAX_SUPPORTED_INTF];
Craig Lutgen88a22ad2018-10-04 12:30:46 -050066static const std::string UNKNOWN_TECH("unknown");
Craig Lutgenb2601f02018-10-23 13:04:31 -050067static const std::string MIXED_TECH("mixed");
68static std::string board_technology(UNKNOWN_TECH);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -080069static unsigned int OPENOLT_FIELD_LEN = 200;
Craig Lutgen88a22ad2018-10-04 12:30:46 -050070static std::string firmware_version = "Openolt.2018.10.04";
Nicolas Palpacuerdff96792018-09-06 14:59:32 -040071
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -070072const uint32_t tm_upstream_sched_id_start = 18432;
73const uint32_t tm_downstream_sched_id_start = 16384;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -080074//0 to 3 are default queues. Lets not use them.
75const uint32_t tm_queue_id_start = 4;
76// Upto 8 fixed Upstream. Queue id 0 to 3 are pre-created, lets not use them.
77const uint32_t us_fixed_queue_id_list[8] = {4, 5, 6, 7, 8, 9, 10, 11};
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -070078const std::string upstream = "upstream";
79const std::string downstream = "downstream";
80
Shad Ansariedef2132018-08-10 22:14:50 +000081State state;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -040082
Craig Lutgen967a1d02018-11-27 10:41:51 -060083static std::map<uint32_t, uint32_t> flowid_to_port; // For mapping upstream flows to logical ports
84static std::map<uint32_t, uint32_t> flowid_to_gemport; // For mapping downstream flows into gemports
85static 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 -080086
87// This represents the Key to 'queue_map' map.
88// Represents (pon_intf_id, onu_id, uni_id, gemport_id, direction)
89typedef std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, std::string> queue_map_key_tuple;
90// 'queue_map' maps queue_map_key_tuple to downstream queue id present
91// on the Subscriber Scheduler
92static std::map<queue_map_key_tuple, int> queue_map;
93// This represents the Key to 'sched_map' map.
94// Represents (pon_intf_id, onu_id, uni_id, direction)
95
96typedef std::tuple<uint32_t, uint32_t, uint32_t, std::string> sched_map_key_tuple;
97// 'sched_map' maps sched_map_key_tuple to DBA (Upstream) or
98// Subscriber (Downstream) Scheduler ID
99static std::map<sched_map_key_tuple, int> sched_map;
100
101
102std::bitset<MAX_TM_QUEUE_ID> tm_queue_bitset;
103std::bitset<MAX_TM_SCHED_ID> tm_sched_bitset;
104
105static bcmos_fastlock data_lock;
Craig Lutgen967a1d02018-11-27 10:41:51 -0600106
107#define MIN_ALLOC_ID_GPON 256
108#define MIN_ALLOC_ID_XGSPON 1024
109
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800110static bcmos_errno CreateSched(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, \
111 uint32_t port_no, uint32_t alloc_id, tech_profile::AdditionalBW additional_bw, uint32_t weight, \
112 uint32_t priority, tech_profile::SchedulingPolicy sched_policy,
113 tech_profile::TrafficShapingInfo traffic_shaping_info);
114static bcmos_errno RemoveSched(int intf_id, int onu_id, int uni_id, std::string direction);
115static bcmos_errno CreateQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, \
116 uint32_t priority, uint32_t gemport_id);
117static bcmos_errno RemoveQueue(std::string direction, int intf_id, int onu_id, int uni_id, uint32_t port_no, int alloc_id);
Shad Ansari627b5782018-08-13 22:49:32 +0000118
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800119/**
120* Returns the default NNI (Upstream direction) or PON (Downstream direction) scheduler
121* Every NNI port and PON port have default scheduler.
122* The NNI0 default scheduler ID is 18432, and NNI1 is 18433 and so on.
123* Similarly, PON0 default scheduler ID is 16384. PON1 is 16385 and so on.
124*
125* @param intf_id NNI or PON interface ID
126* @param direction "upstream" or "downstream"
127*
128* @return default scheduler ID for the given interface.
129*/
130static inline int get_default_tm_sched_id(int intf_id, std::string direction) {
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700131 if (direction.compare(upstream) == 0) {
132 return tm_upstream_sched_id_start + intf_id;
133 } else if (direction.compare(downstream) == 0) {
134 return tm_downstream_sched_id_start + intf_id;
135 }
136 else {
137 BCM_LOG(ERROR, openolt_log_id, "invalid direction - %s\n", direction.c_str());
138 return 0;
139 }
140}
141
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800142/**
143* Gets a unique tm_queue_id for a given intf_id, onu_id, uni_id, gemport_id, direction
144* The tm_queue_id is locally cached in a map, so that it can rendered when necessary.
145* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
146*
147* @param intf_id NNI or PON intf ID
148* @param onu_id ONU ID
149* @param uni_id UNI ID
150* @param gemport_id GEM Port ID
151* @param direction Upstream or downstream
152*
153* @return tm_queue_id
154*/
155int get_tm_queue_id(int intf_id, int onu_id, int uni_id, int gemport_id, std::string direction) {
156 queue_map_key_tuple key(intf_id, onu_id, uni_id, gemport_id, direction);
157 int queue_id = -1;
Craig Lutgen967a1d02018-11-27 10:41:51 -0600158
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800159 std::map<queue_map_key_tuple, int>::const_iterator it = queue_map.find(key);
160 if (it != queue_map.end()) {
161 queue_id = it->second;
162 }
163 if (queue_id != -1) {
164 return queue_id;
165 }
166
167 bcmos_fastlock_lock(&data_lock);
168 // Complexity of O(n). Is there better way that can avoid linear search?
169 for (queue_id = 0; queue_id < MAX_TM_QUEUE_ID; queue_id++) {
170 if (tm_queue_bitset[queue_id] == 0) {
171 tm_queue_bitset[queue_id] = 1;
172 break;
173 }
174 }
175 bcmos_fastlock_unlock(&data_lock, 0);
176
177 if (queue_id < MAX_TM_QUEUE_ID) {
178 bcmos_fastlock_lock(&data_lock);
179 queue_map[key] = queue_id;
180 bcmos_fastlock_unlock(&data_lock, 0);
181 return queue_id;
182 } else {
183 return -1;
184 }
Shad Ansari627b5782018-08-13 22:49:32 +0000185}
186
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800187/**
188* Update tm_queue_id for a given intf_id, onu_id, uni_id, gemport_id, direction
189*
190* @param intf_id NNI or PON intf ID
191* @param onu_id ONU ID
192* @param uni_id UNI ID
193* @param gemport_id GEM Port ID
194* @param direction Upstream or downstream
195* @param tm_queue_id tm_queue_id
196*/
197void update_tm_queue_id(int pon_intf_id, int onu_id, int uni_id, int gemport_id, std::string direction,
198 uint32_t queue_id) {
199 queue_map_key_tuple key(pon_intf_id, onu_id, uni_id, gemport_id, direction);
200 bcmos_fastlock_lock(&data_lock);
201 queue_map[key] = queue_id;
202 bcmos_fastlock_unlock(&data_lock, 0);
203}
204
205/**
206* Free tm_queue_id for a given intf_id, onu_id, uni_id, gemport_id, direction
207*
208* @param intf_id NNI or PON intf ID
209* @param onu_id ONU ID
210* @param uni_id UNI ID
211* @param gemport_id GEM Port ID
212* @param direction Upstream or downstream
213*/
214void free_tm_queue_id(int pon_intf_id, int onu_id, int uni_id, int gemport_id, std::string direction) {
215 queue_map_key_tuple key(pon_intf_id, onu_id, uni_id, gemport_id, direction);
216 std::map<queue_map_key_tuple, int>::const_iterator it;
217 bcmos_fastlock_lock(&data_lock);
218 it = queue_map.find(key);
219 if (it != queue_map.end()) {
220 tm_queue_bitset[it->second] = 0;
221 queue_map.erase(it);
222 }
223 bcmos_fastlock_unlock(&data_lock, 0);
224}
225
226/**
227* Gets a unique tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
228* The tm_sched_id is locally cached in a map, so that it can rendered when necessary.
229* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
230*
231* @param intf_id NNI or PON intf ID
232* @param onu_id ONU ID
233* @param uni_id UNI ID
234* @param gemport_id GEM Port ID
235* @param direction Upstream or downstream
236*
237* @return tm_sched_id
238*/
239uint32_t get_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
240 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
241 int sched_id = -1;
242
243 std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
244 if (it != sched_map.end()) {
245 sched_id = it->second;
246 }
247 if (sched_id != -1) {
248 return sched_id;
249 }
250
251 bcmos_fastlock_lock(&data_lock);
252 // Complexity of O(n). Is there better way that can avoid linear search?
253 for (sched_id = 0; sched_id < MAX_TM_SCHED_ID; sched_id++) {
254 if (tm_sched_bitset[sched_id] == 0) {
255 tm_sched_bitset[sched_id] = 1;
256 break;
257 }
258 }
259 bcmos_fastlock_unlock(&data_lock, 0);
260
261 if (sched_id < MAX_TM_SCHED_ID) {
262 bcmos_fastlock_lock(&data_lock);
263 sched_map[key] = sched_id;
264 bcmos_fastlock_unlock(&data_lock, 0);
265 return sched_id;
266 } else {
267 return -1;
268 }
269}
270
271/**
272* Free tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
273*
274* @param intf_id NNI or PON intf ID
275* @param onu_id ONU ID
276* @param uni_id UNI ID
277* @param gemport_id GEM Port ID
278* @param direction Upstream or downstream
279*/
280void free_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
281 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
282 std::map<sched_map_key_tuple, int>::const_iterator it;
283 bcmos_fastlock_lock(&data_lock);
284 it = sched_map.find(key);
285 if (it != sched_map.end()) {
286 tm_sched_bitset[it->second] = 0;
287 sched_map.erase(it);
288 }
289 bcmos_fastlock_unlock(&data_lock, 0);
290}
291
292bool is_tm_sched_id_present(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
293 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
294 return sched_map.count(key) > 0 ? true: false;
295}
296
297bool is_tm_queue_id_present(int pon_intf_id, int onu_id, int uni_id, int gemport_id, std::string direction) {
298 queue_map_key_tuple key(pon_intf_id, onu_id, uni_id, gemport_id, direction);
299 return queue_map.count(key) > 0 ? true: false;
Shad Ansari627b5782018-08-13 22:49:32 +0000300}
301
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800302char* openolt_read_sysinfo(char* field_name, char* field_val)
303{
304 FILE *fp;
305 /* Prepare the command*/
306 char command[150];
307
308 snprintf(command, sizeof command, "bash -l -c \"onlpdump -s\" | perl -ne 'print $1 if /%s: (\\S+)/'", field_name);
309 /* Open the command for reading. */
310 fp = popen(command, "r");
311 if (fp == NULL) {
312 /*The client has to check for a Null field value in this case*/
313 BCM_LOG(INFO, openolt_log_id, "Failed to query the %s\n", field_name);
314 return field_val;
315 }
316
317 /*Read the field value*/
318 if (fp) {
319 fread(field_val, OPENOLT_FIELD_LEN, 1, fp);
320 pclose(fp);
321 }
322 return field_val;
323}
324
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400325Status GetDeviceInfo_(openolt::DeviceInfo* device_info) {
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500326 device_info->set_vendor(VENDOR_ID);
327 device_info->set_model(MODEL_ID);
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400328 device_info->set_hardware_version("");
329 device_info->set_firmware_version(firmware_version);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500330 device_info->set_technology(board_technology);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500331 device_info->set_pon_ports(num_of_pon_ports);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500332
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800333 char serial_number[OPENOLT_FIELD_LEN];
334 memset(serial_number, '\0', OPENOLT_FIELD_LEN);
335 openolt_read_sysinfo("Serial Number", serial_number);
336 BCM_LOG(INFO, openolt_log_id, "Fetched device serial number %s\n", serial_number);
337 device_info->set_device_serial_number(serial_number);
338
Craig Lutgenb2601f02018-10-23 13:04:31 -0500339 // Legacy, device-wide ranges. To be deprecated when adapter
340 // is upgraded to support per-interface ranges
341 if (board_technology == "xgspon") {
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500342 device_info->set_onu_id_start(1);
343 device_info->set_onu_id_end(255);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600344 device_info->set_alloc_id_start(MIN_ALLOC_ID_XGSPON);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500345 device_info->set_alloc_id_end(16383);
346 device_info->set_gemport_id_start(1024);
347 device_info->set_gemport_id_end(65535);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500348 device_info->set_flow_id_start(1);
349 device_info->set_flow_id_end(16383);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500350 }
Craig Lutgenb2601f02018-10-23 13:04:31 -0500351 else if (board_technology == "gpon") {
352 device_info->set_onu_id_start(1);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500353 device_info->set_onu_id_end(127);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600354 device_info->set_alloc_id_start(MIN_ALLOC_ID_GPON);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500355 device_info->set_alloc_id_end(767);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500356 device_info->set_gemport_id_start(256);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500357 device_info->set_gemport_id_end(4095);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500358 device_info->set_flow_id_start(1);
359 device_info->set_flow_id_end(16383);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500360 }
Craig Lutgenb2601f02018-10-23 13:04:31 -0500361
362 std::map<std::string, openolt::DeviceInfo::DeviceResourceRanges*> ranges;
363 for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
364 std::string intf_technology = intf_technologies[intf_id];
365 openolt::DeviceInfo::DeviceResourceRanges *range = ranges[intf_technology];
366 if(range == nullptr) {
367 range = device_info->add_ranges();
368 ranges[intf_technology] = range;
369 range->set_technology(intf_technology);
370
371 if (intf_technology == "xgspon") {
372 openolt::DeviceInfo::DeviceResourceRanges::Pool* pool;
373
374 pool = range->add_pools();
375 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ONU_ID);
376 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::DEDICATED_PER_INTF);
377 pool->set_start(1);
378 pool->set_end(255);
379
380 pool = range->add_pools();
381 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ALLOC_ID);
382 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_SAME_TECH);
383 pool->set_start(1024);
384 pool->set_end(16383);
385
386 pool = range->add_pools();
387 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::GEMPORT_ID);
388 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
389 pool->set_start(1024);
390 pool->set_end(65535);
391
392 pool = range->add_pools();
393 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::FLOW_ID);
394 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
395 pool->set_start(1);
396 pool->set_end(16383);
397 }
398 else if (intf_technology == "gpon") {
399 openolt::DeviceInfo::DeviceResourceRanges::Pool* pool;
400
401 pool = range->add_pools();
402 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ONU_ID);
403 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::DEDICATED_PER_INTF);
404 pool->set_start(1);
405 pool->set_end(127);
406
407 pool = range->add_pools();
408 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ALLOC_ID);
409 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_SAME_TECH);
410 pool->set_start(256);
411 pool->set_end(757);
412
413 pool = range->add_pools();
414 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::GEMPORT_ID);
415 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
416 pool->set_start(256);
417 pool->set_end(4095);
418
419 pool = range->add_pools();
420 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::FLOW_ID);
421 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
422 pool->set_start(1);
423 pool->set_end(16383);
424 }
425 }
426
427 range->add_intf_ids(intf_id);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500428 }
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400429
430 // FIXME: Once dependency problem is fixed
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500431 // device_info->set_pon_ports(num_of_pon_ports);
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400432 // device_info->set_onu_id_end(XGPON_NUM_OF_ONUS - 1);
433 // device_info->set_alloc_id_start(1024);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500434 // device_info->set_alloc_id_end(XGPON_NUM_OF_ALLOC_IDS * num_of_pon_ports ? - 1);
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400435 // device_info->set_gemport_id_start(XGPON_MIN_BASE_SERVICE_PORT_ID);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500436 // device_info->set_gemport_id_end(XGPON_NUM_OF_GEM_PORT_IDS_PER_PON * num_of_pon_ports ? - 1);
437 // device_info->set_pon_ports(num_of_pon_ports);
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400438
439 return Status::OK;
440}
441
Shad Ansari627b5782018-08-13 22:49:32 +0000442Status Enable_(int argc, char *argv[]) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000443 bcmbal_access_terminal_cfg acc_term_obj;
444 bcmbal_access_terminal_key key = { };
445
Shad Ansariedef2132018-08-10 22:14:50 +0000446 if (!state.is_activated()) {
Shad Ansari627b5782018-08-13 22:49:32 +0000447
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500448 vendor_init();
Shad Ansari627b5782018-08-13 22:49:32 +0000449 bcmbal_init(argc, argv, NULL);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800450 bcmos_fastlock_init(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600451
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500452 BCM_LOG(INFO, openolt_log_id, "Enable OLT - %s-%s\n", VENDOR_ID, MODEL_ID);
453
Shad Ansari627b5782018-08-13 22:49:32 +0000454 Status status = SubscribeIndication();
455 if (!status.ok()) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400456 BCM_LOG(ERROR, openolt_log_id, "SubscribeIndication failed - %s : %s\n",
457 grpc_status_code_to_string(status.error_code()).c_str(),
458 status.error_message().c_str());
459
Shad Ansari627b5782018-08-13 22:49:32 +0000460 return status;
461 }
462
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000463 key.access_term_id = DEFAULT_ATERM_ID;
464 BCMBAL_CFG_INIT(&acc_term_obj, access_terminal, key);
465 BCMBAL_CFG_PROP_SET(&acc_term_obj, access_terminal, admin_state, BCMBAL_STATE_UP);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400466 bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(acc_term_obj.hdr));
467 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400468 BCM_LOG(ERROR, openolt_log_id, "Failed to enable OLT\n");
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400469 return bcm_to_grpc_err(err, "Failed to enable OLT");
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000470 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500471
Shad Ansariedef2132018-08-10 22:14:50 +0000472 init_stats();
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000473 }
Shad Ansariedef2132018-08-10 22:14:50 +0000474
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400475 //If already enabled, generate an extra indication ????
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000476 return Status::OK;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400477}
478
479Status Disable_() {
480 // bcmbal_access_terminal_cfg acc_term_obj;
481 // bcmbal_access_terminal_key key = { };
482 //
483 // if (state::is_activated) {
484 // std::cout << "Disable OLT" << std::endl;
485 // key.access_term_id = DEFAULT_ATERM_ID;
486 // BCMBAL_CFG_INIT(&acc_term_obj, access_terminal, key);
487 // BCMBAL_CFG_PROP_SET(&acc_term_obj, access_terminal, admin_state, BCMBAL_STATE_DOWN);
488 // bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(acc_term_obj.hdr));
489 // if (err) {
490 // std::cout << "ERROR: Failed to disable OLT" << std::endl;
491 // return bcm_to_grpc_err(err, "Failed to disable OLT");
492 // }
493 // }
494 // //If already disabled, generate an extra indication ????
495 // return Status::OK;
496 //This fails with Operation Not Supported, bug ???
497
498 //TEMPORARY WORK AROUND
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800499 Status status = DisableUplinkIf_(nni_intf_id);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400500 if (status.ok()) {
Shad Ansariedef2132018-08-10 22:14:50 +0000501 state.deactivate();
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400502 openolt::Indication ind;
503 openolt::OltIndication* olt_ind = new openolt::OltIndication;
504 olt_ind->set_oper_state("down");
505 ind.set_allocated_olt_ind(olt_ind);
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400506 BCM_LOG(INFO, openolt_log_id, "Disable OLT, add an extra indication\n");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400507 oltIndQ.push(ind);
508 }
509 return status;
510
511}
512
513Status Reenable_() {
514 Status status = EnableUplinkIf_(0);
515 if (status.ok()) {
Shad Ansariedef2132018-08-10 22:14:50 +0000516 state.activate();
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400517 openolt::Indication ind;
518 openolt::OltIndication* olt_ind = new openolt::OltIndication;
519 olt_ind->set_oper_state("up");
520 ind.set_allocated_olt_ind(olt_ind);
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400521 BCM_LOG(INFO, openolt_log_id, "Reenable OLT, add an extra indication\n");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400522 oltIndQ.push(ind);
523 }
524 return status;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000525}
526
527Status EnablePonIf_(uint32_t intf_id) {
528 bcmbal_interface_cfg interface_obj;
529 bcmbal_interface_key interface_key;
530
531 interface_key.intf_id = intf_id;
532 interface_key.intf_type = BCMBAL_INTF_TYPE_PON;
533
534 BCMBAL_CFG_INIT(&interface_obj, interface, interface_key);
Craig Lutgend0bae9b2018-10-18 18:02:07 -0500535
536 BCMBAL_CFG_PROP_GET(&interface_obj, interface, admin_state);
537 bcmos_errno err = bcmbal_cfg_get(DEFAULT_ATERM_ID, &(interface_obj.hdr));
538 if (err == BCM_ERR_OK && interface_obj.data.admin_state == BCMBAL_STATE_UP) {
539 BCM_LOG(DEBUG, openolt_log_id, "PON interface: %d already enabled\n", intf_id);
540 return Status::OK;
541 }
542
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000543 BCMBAL_CFG_PROP_SET(&interface_obj, interface, admin_state, BCMBAL_STATE_UP);
544
Craig Lutgend0bae9b2018-10-18 18:02:07 -0500545 err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(interface_obj.hdr));
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400546 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400547 BCM_LOG(ERROR, openolt_log_id, "Failed to enable PON interface: %d\n", intf_id);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400548 return bcm_to_grpc_err(err, "Failed to enable PON interface");
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000549 }
550
551 return Status::OK;
552}
553
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400554Status DisableUplinkIf_(uint32_t intf_id) {
555 bcmbal_interface_cfg interface_obj;
556 bcmbal_interface_key interface_key;
557
558 interface_key.intf_id = intf_id;
559 interface_key.intf_type = BCMBAL_INTF_TYPE_NNI;
560
561 BCMBAL_CFG_INIT(&interface_obj, interface, interface_key);
562 BCMBAL_CFG_PROP_SET(&interface_obj, interface, admin_state, BCMBAL_STATE_DOWN);
563
564 bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(interface_obj.hdr));
565 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400566 BCM_LOG(ERROR, openolt_log_id, "Failed to disable Uplink interface: %d\n", intf_id);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400567 return bcm_to_grpc_err(err, "Failed to disable Uplink interface");
568 }
569
570 return Status::OK;
571}
572
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500573Status ProbeDeviceCapabilities_() {
574 bcmbal_access_terminal_cfg acc_term_obj;
575 bcmbal_access_terminal_key key = { };
576
577 key.access_term_id = DEFAULT_ATERM_ID;
578 BCMBAL_CFG_INIT(&acc_term_obj, access_terminal, key);
579 BCMBAL_CFG_PROP_GET(&acc_term_obj, access_terminal, admin_state);
580 BCMBAL_CFG_PROP_GET(&acc_term_obj, access_terminal, oper_status);
581 BCMBAL_CFG_PROP_GET(&acc_term_obj, access_terminal, topology);
582 BCMBAL_CFG_PROP_GET(&acc_term_obj, access_terminal, sw_version);
583 BCMBAL_CFG_PROP_GET(&acc_term_obj, access_terminal, conn_id);
584 bcmos_errno err = bcmbal_cfg_get(DEFAULT_ATERM_ID, &(acc_term_obj.hdr));
585 if (err) {
586 BCM_LOG(ERROR, openolt_log_id, "Failed to query OLT\n");
587 return bcm_to_grpc_err(err, "Failed to query OLT");
588 }
589
590 BCM_LOG(INFO, openolt_log_id, "OLT capabilitites, admin_state: %s oper_state: %s\n",
591 acc_term_obj.data.admin_state == BCMBAL_STATE_UP ? "up" : "down",
592 acc_term_obj.data.oper_status == BCMBAL_STATUS_UP ? "up" : "down");
593
594 std::string bal_version;
595 bal_version += std::to_string(acc_term_obj.data.sw_version.major_rev)
596 + "." + std::to_string(acc_term_obj.data.sw_version.minor_rev)
597 + "." + std::to_string(acc_term_obj.data.sw_version.release_rev);
598 firmware_version = "BAL." + bal_version + "__" + firmware_version;
599
600 BCM_LOG(INFO, openolt_log_id, "--------------- version %s object model: %d\n", bal_version.c_str(),
601 acc_term_obj.data.sw_version.om_version);
602
603 BCM_LOG(INFO, openolt_log_id, "--------------- topology nni:%d pon:%d dev:%d ppd:%d family: %d:%d\n",
604 acc_term_obj.data.topology.num_of_nni_ports,
605 acc_term_obj.data.topology.num_of_pon_ports,
606 acc_term_obj.data.topology.num_of_mac_devs,
607 acc_term_obj.data.topology.num_of_pons_per_mac_dev,
608 acc_term_obj.data.topology.pon_family,
609 acc_term_obj.data.topology.pon_sub_family
610 );
611
612 switch(acc_term_obj.data.topology.pon_sub_family)
613 {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500614 case BCMBAL_PON_SUB_FAMILY_GPON: board_technology = "gpon"; break;
615 case BCMBAL_PON_SUB_FAMILY_XGS: board_technology = "xgspon"; break;
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500616 }
617
618 num_of_nni_ports = acc_term_obj.data.topology.num_of_nni_ports;
619 num_of_pon_ports = acc_term_obj.data.topology.num_of_pon_ports;
620
Craig Lutgenb2601f02018-10-23 13:04:31 -0500621 BCM_LOG(INFO, openolt_log_id, "PON num_intfs: %d global board_technology: %s\n", num_of_pon_ports, board_technology.c_str());
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500622
623 return Status::OK;
624}
625
626Status ProbePonIfTechnology_() {
627 // Probe maximum extent possible as configured into BAL driver to determine
628 // which are active in the current BAL topology. And for those
629 // that are active, determine each port's access technology, i.e. "gpon" or "xgspon".
630 for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
631 bcmbal_interface_cfg interface_obj;
632 bcmbal_interface_key interface_key;
633
634 interface_key.intf_id = intf_id;
635 interface_key.intf_type = BCMBAL_INTF_TYPE_PON;
636
637 BCMBAL_CFG_INIT(&interface_obj, interface, interface_key);
638 BCMBAL_CFG_PROP_GET(&interface_obj, interface, admin_state);
639 BCMBAL_CFG_PROP_GET(&interface_obj, interface, transceiver_type);
640
641 bcmos_errno err = bcmbal_cfg_get(DEFAULT_ATERM_ID, &(interface_obj.hdr));
642 if (err != BCM_ERR_OK) {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500643 intf_technologies[intf_id] = UNKNOWN_TECH;
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500644 if(err != BCM_ERR_RANGE) BCM_LOG(ERROR, openolt_log_id, "Failed to get PON config: %d\n", intf_id);
645 }
646 else {
647 switch(interface_obj.data.transceiver_type) {
648 case BCMBAL_TRX_TYPE_GPON_SPS_43_48:
649 case BCMBAL_TRX_TYPE_GPON_SPS_SOG_4321:
650 case BCMBAL_TRX_TYPE_GPON_LTE_3680_M:
651 case BCMBAL_TRX_TYPE_GPON_SOURCE_PHOTONICS:
652 case BCMBAL_TRX_TYPE_GPON_LTE_3680_P:
Craig Lutgenb2601f02018-10-23 13:04:31 -0500653 intf_technologies[intf_id] = "gpon";
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500654 break;
655 default:
Craig Lutgenb2601f02018-10-23 13:04:31 -0500656 intf_technologies[intf_id] = "xgspon";
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500657 break;
658 }
Craig Lutgenb2601f02018-10-23 13:04:31 -0500659 BCM_LOG(INFO, openolt_log_id, "PON intf_id: %d intf_technologies: %d:%s\n", intf_id,
660 interface_obj.data.transceiver_type, intf_technologies[intf_id].c_str());
661
662 if (board_technology != UNKNOWN_TECH) {
663 board_technology = intf_technologies[intf_id];
664 } else if (board_technology != MIXED_TECH && board_technology != intf_technologies[intf_id]) {
665 intf_technologies[intf_id] = MIXED_TECH;
666 }
667
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500668 }
669 }
670
671 return Status::OK;
672}
673
674unsigned NumNniIf_() {return num_of_nni_ports;}
675unsigned NumPonIf_() {return num_of_pon_ports;}
676
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400677Status EnableUplinkIf_(uint32_t intf_id) {
678 bcmbal_interface_cfg interface_obj;
679 bcmbal_interface_key interface_key;
680
681 interface_key.intf_id = intf_id;
682 interface_key.intf_type = BCMBAL_INTF_TYPE_NNI;
683
684 BCMBAL_CFG_INIT(&interface_obj, interface, interface_key);
Craig Lutgend0bae9b2018-10-18 18:02:07 -0500685
686 BCMBAL_CFG_PROP_GET(&interface_obj, interface, admin_state);
687 bcmos_errno err = bcmbal_cfg_get(DEFAULT_ATERM_ID, &(interface_obj.hdr));
688 if (err == BCM_ERR_OK && interface_obj.data.admin_state == BCMBAL_STATE_UP) {
689 BCM_LOG(DEBUG, openolt_log_id, "Uplink interface: %d already enabled\n", intf_id);
690 return Status::OK;
691 }
692
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400693 BCMBAL_CFG_PROP_SET(&interface_obj, interface, admin_state, BCMBAL_STATE_UP);
694
Craig Lutgend0bae9b2018-10-18 18:02:07 -0500695 err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(interface_obj.hdr));
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400696 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400697 BCM_LOG(ERROR, openolt_log_id, "Failed to enable Uplink interface: %d\n", intf_id);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400698 return bcm_to_grpc_err(err, "Failed to enable Uplink interface");
699 }
700
701 return Status::OK;
702}
703
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -0400704Status DisablePonIf_(uint32_t intf_id) {
705 bcmbal_interface_cfg interface_obj;
706 bcmbal_interface_key interface_key;
707
708 interface_key.intf_id = intf_id;
709 interface_key.intf_type = BCMBAL_INTF_TYPE_PON;
710
711 BCMBAL_CFG_INIT(&interface_obj, interface, interface_key);
712 BCMBAL_CFG_PROP_SET(&interface_obj, interface, admin_state, BCMBAL_STATE_DOWN);
713
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400714 bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(interface_obj.hdr));
715 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400716 BCM_LOG(ERROR, openolt_log_id, "Failed to disable PON interface: %d\n", intf_id);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400717 return bcm_to_grpc_err(err, "Failed to disable PON interface");
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -0400718 }
719
720 return Status::OK;
721}
722
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000723Status ActivateOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700724 const char *vendor_id, const char *vendor_specific, uint32_t pir) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000725
726 bcmbal_subscriber_terminal_cfg sub_term_obj = {};
727 bcmbal_subscriber_terminal_key subs_terminal_key;
728 bcmbal_serial_number serial_num = {};
729 bcmbal_registration_id registration_id = {};
730
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700731 BCM_LOG(INFO, openolt_log_id, "Enabling ONU %d on PON %d : vendor id %s, vendor specific %s, pir %d\n",
732 onu_id, intf_id, vendor_id, vendor_specific_to_str(vendor_specific).c_str(), pir);
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000733
734 subs_terminal_key.sub_term_id = onu_id;
735 subs_terminal_key.intf_id = intf_id;
736 BCMBAL_CFG_INIT(&sub_term_obj, subscriber_terminal, subs_terminal_key);
737
738 memcpy(serial_num.vendor_id, vendor_id, 4);
739 memcpy(serial_num.vendor_specific, vendor_specific, 4);
740 BCMBAL_CFG_PROP_SET(&sub_term_obj, subscriber_terminal, serial_number, serial_num);
741
Shad Ansaricb004c52018-05-30 18:07:23 +0000742#if 0
743 // Commenting out as this is causing issues with onu activation
744 // with BAL 2.6 (Broadcom CS5248819).
745
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000746 // FIXME - Use a default (all zeros) registration id.
747 memset(registration_id.arr, 0, sizeof(registration_id.arr));
748 BCMBAL_CFG_PROP_SET(&sub_term_obj, subscriber_terminal, registration_id, registration_id);
Shad Ansaricb004c52018-05-30 18:07:23 +0000749#endif
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000750
751 BCMBAL_CFG_PROP_SET(&sub_term_obj, subscriber_terminal, admin_state, BCMBAL_STATE_UP);
752
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400753 bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(sub_term_obj.hdr));
754 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400755 BCM_LOG(ERROR, openolt_log_id, "Failed to enable ONU %d on PON %d\n", onu_id, intf_id);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400756 return bcm_to_grpc_err(err, "Failed to enable ONU");
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000757 }
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700758 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000759}
760
Jonathan Davis70c21812018-07-19 15:32:10 -0400761Status DeactivateOnu_(uint32_t intf_id, uint32_t onu_id,
762 const char *vendor_id, const char *vendor_specific) {
763
Jonathan Davis70c21812018-07-19 15:32:10 -0400764 bcmbal_subscriber_terminal_cfg sub_term_obj = {};
765 bcmbal_subscriber_terminal_key subs_terminal_key;
766
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400767 BCM_LOG(INFO, openolt_log_id, "Deactivating ONU %d on PON %d : vendor id %s, vendor specific %s\n",
Craig Lutgend0bae9b2018-10-18 18:02:07 -0500768 onu_id, intf_id, vendor_id, vendor_specific_to_str(vendor_specific).c_str());
Jonathan Davis70c21812018-07-19 15:32:10 -0400769
770 subs_terminal_key.sub_term_id = onu_id;
771 subs_terminal_key.intf_id = intf_id;
772 BCMBAL_CFG_INIT(&sub_term_obj, subscriber_terminal, subs_terminal_key);
773
774 BCMBAL_CFG_PROP_SET(&sub_term_obj, subscriber_terminal, admin_state, BCMBAL_STATE_DOWN);
775
776 if (bcmbal_cfg_set(DEFAULT_ATERM_ID, &(sub_term_obj.hdr))) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400777 BCM_LOG(ERROR, openolt_log_id, "Failed to deactivate ONU %d on PON %d\n", onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -0400778 return Status(grpc::StatusCode::INTERNAL, "Failed to deactivate ONU");
779 }
780
781 return Status::OK;
782}
783
784Status DeleteOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700785 const char *vendor_id, const char *vendor_specific) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -0400786
Craig Lutgend0bae9b2018-10-18 18:02:07 -0500787 BCM_LOG(INFO, openolt_log_id, "DeleteOnu ONU %d on PON %d : vendor id %s, vendor specific %s\n",
788 onu_id, intf_id, vendor_id, vendor_specific_to_str(vendor_specific).c_str());
789
Nicolas Palpacuer9c352082018-08-14 16:37:14 -0400790 // Need to deactivate before removing it (BAL rules)
791
792 DeactivateOnu_(intf_id, onu_id, vendor_id, vendor_specific);
793 // Sleep to allow the state to propagate
794 // We need the subscriber terminal object to be admin down before removal
795 // Without sleep the race condition is lost by ~ 20 ms
796 std::this_thread::sleep_for(std::chrono::milliseconds(100));
797
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700798 // TODO: Delete the schedulers and queues.
Nicolas Palpacuer9c352082018-08-14 16:37:14 -0400799
Jonathan Davis70c21812018-07-19 15:32:10 -0400800 bcmos_errno err = BCM_ERR_OK;
801 bcmbal_subscriber_terminal_cfg cfg;
802 bcmbal_subscriber_terminal_key key = { };
803
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400804 BCM_LOG(INFO, openolt_log_id, "Processing subscriber terminal cfg clear for sub_term_id %d and intf_id %d\n",
805 onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -0400806
807 key.sub_term_id = onu_id ;
808 key.intf_id = intf_id ;
809
810 if (0 == key.sub_term_id)
811 {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800812 BCM_LOG(INFO, openolt_log_id,"Invalid Key to handle subscriber terminal clear subscriber_terminal_id %d, \
813 Interface ID %d\n", onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -0400814 return Status(grpc::StatusCode::INTERNAL, "Failed to delete ONU");
815 }
816
817 BCMBAL_CFG_INIT(&cfg, subscriber_terminal, key);
818
819 err = bcmbal_cfg_clear(DEFAULT_ATERM_ID, &cfg.hdr);
820 if (err != BCM_ERR_OK)
821 {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400822 BCM_LOG(ERROR, openolt_log_id, "Failed to clear information for BAL subscriber_terminal_id %d, Interface ID %d\n",
823 onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -0400824 return Status(grpc::StatusCode::INTERNAL, "Failed to delete ONU");
825 }
826
827 return Status::OK;;
828}
829
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000830#define MAX_CHAR_LENGTH 20
831#define MAX_OMCI_MSG_LENGTH 44
832Status OmciMsgOut_(uint32_t intf_id, uint32_t onu_id, const std::string pkt) {
833 bcmbal_u8_list_u32_max_2048 buf; /* A structure with a msg pointer and length value */
834 bcmos_errno err = BCM_ERR_OK;
835
836 /* The destination of the OMCI packet is a registered ONU on the OLT PON interface */
837 bcmbal_dest proxy_pkt_dest;
838
839 proxy_pkt_dest.type = BCMBAL_DEST_TYPE_ITU_OMCI_CHANNEL;
840 proxy_pkt_dest.u.itu_omci_channel.sub_term_id = onu_id;
841 proxy_pkt_dest.u.itu_omci_channel.intf_id = intf_id;
842
843 // ???
844 if ((pkt.size()/2) > MAX_OMCI_MSG_LENGTH) {
845 buf.len = MAX_OMCI_MSG_LENGTH;
846 } else {
847 buf.len = pkt.size()/2;
848 }
849
850 /* Send the OMCI packet using the BAL remote proxy API */
851 uint16_t idx1 = 0;
852 uint16_t idx2 = 0;
853 uint8_t arraySend[buf.len];
854 char str1[MAX_CHAR_LENGTH];
855 char str2[MAX_CHAR_LENGTH];
856 memset(&arraySend, 0, buf.len);
857
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000858 for (idx1=0,idx2=0; idx1<((buf.len)*2); idx1++,idx2++) {
859 sprintf(str1,"%c", pkt[idx1]);
860 sprintf(str2,"%c", pkt[++idx1]);
861 strcat(str1,str2);
862 arraySend[idx2] = strtol(str1, NULL, 16);
863 }
864
865 buf.val = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
866 memcpy(buf.val, (uint8_t *)arraySend, buf.len);
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000867
868 err = bcmbal_pkt_send(0, proxy_pkt_dest, (const char *)(buf.val), buf.len);
869
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400870 if (err) {
871 BCM_LOG(ERROR, omci_log_id, "Error sending OMCI message to ONU %d on PON %d\n", onu_id, intf_id);
872 } else {
873 BCM_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 -0500874 buf.len, onu_id, intf_id, pkt.c_str());
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400875 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000876
877 free(buf.val);
878
879 return Status::OK;
880}
881
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800882Status OnuPacketOut_(uint32_t intf_id, uint32_t onu_id, uint32_t port_no, uint32_t gemport_id, const std::string pkt) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000883 bcmos_errno err = BCM_ERR_OK;
884 bcmbal_dest proxy_pkt_dest;
885 bcmbal_u8_list_u32_max_2048 buf;
886
Craig Lutgen967a1d02018-11-27 10:41:51 -0600887 if (port_no > 0) {
888 bool found = false;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800889 if (gemport_id == 0) {
890 bcmos_fastlock_lock(&data_lock);
891 // Map the port_no to one of the flows that owns it to find a gemport_id for that flow.
892 // Pick any flow that is mapped with the same port_no.
893 std::map<uint32_t, std::set<uint32_t> >::const_iterator it = port_to_flows.find(port_no);
894 if (it != port_to_flows.end() && !it->second.empty()) {
895 uint32_t flow_id = *(it->second.begin()); // Pick any flow_id out of the bag set
896 std::map<uint32_t, uint32_t>::const_iterator fit = flowid_to_gemport.find(flow_id);
897 if (fit != flowid_to_gemport.end()) {
898 found = true;
899 gemport_id = fit->second;
900 }
Craig Lutgen967a1d02018-11-27 10:41:51 -0600901 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800902 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600903
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800904 if (!found) {
905 BCM_LOG(ERROR, openolt_log_id, "Packet out failed to find destination for ONU %d port_no %u on PON %d\n",
906 onu_id, port_no, intf_id);
907 return grpc::Status(grpc::StatusCode::NOT_FOUND, "no flow for port_no");
908 }
909 BCM_LOG(INFO, openolt_log_id, "Gem port %u found for ONU %d port_no %u on PON %d\n",
910 gemport_id, onu_id, port_no, intf_id);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600911 }
912
913 proxy_pkt_dest.type = BCMBAL_DEST_TYPE_SVC_PORT;
914 proxy_pkt_dest.u.svc_port.svc_port_id = gemport_id;
915 proxy_pkt_dest.u.svc_port.intf_id = intf_id;
916 BCM_LOG(INFO, openolt_log_id, "Packet out of length %d sent to gemport %d on pon %d port_no %u\n",
917 pkt.size(), gemport_id, intf_id, port_no);
918 }
919 else {
920 proxy_pkt_dest.type = BCMBAL_DEST_TYPE_SUB_TERM,
921 proxy_pkt_dest.u.sub_term.sub_term_id = onu_id;
922 proxy_pkt_dest.u.sub_term.intf_id = intf_id;
923 BCM_LOG(INFO, openolt_log_id, "Packet out of length %d sent to onu %d on pon %d\n",
924 pkt.size(), onu_id, intf_id);
925 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000926
927 buf.len = pkt.size();
928 buf.val = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
929 memcpy(buf.val, (uint8_t *)pkt.data(), buf.len);
930
931 err = bcmbal_pkt_send(0, proxy_pkt_dest, (const char *)(buf.val), buf.len);
932
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000933 free(buf.val);
934
935 return Status::OK;
936}
937
Nicolas Palpacuerb78def42018-06-07 12:55:26 -0400938Status UplinkPacketOut_(uint32_t intf_id, const std::string pkt) {
939 bcmos_errno err = BCM_ERR_OK;
940 bcmbal_dest proxy_pkt_dest;
941 bcmbal_u8_list_u32_max_2048 buf;
942
943 proxy_pkt_dest.type = BCMBAL_DEST_TYPE_NNI,
944 proxy_pkt_dest.u.nni.intf_id = intf_id;
945
946 buf.len = pkt.size();
947 buf.val = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
948 memcpy(buf.val, (uint8_t *)pkt.data(), buf.len);
949
950 err = bcmbal_pkt_send(0, proxy_pkt_dest, (const char *)(buf.val), buf.len);
951
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400952 BCM_LOG(INFO, openolt_log_id, "Packet out of length %d sent through uplink port %d\n",
953 buf.len, intf_id);
Nicolas Palpacuerb78def42018-06-07 12:55:26 -0400954
955 free(buf.val);
956
957 return Status::OK;
958}
959
Craig Lutgen967a1d02018-11-27 10:41:51 -0600960uint32_t GetPortNum_(uint32_t flow_id)
961{
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800962 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600963 uint32_t port_no = 0;
964 std::map<uint32_t, uint32_t >::const_iterator it = flowid_to_port.find(flow_id);
965 if (it != flowid_to_port.end()) {
966 port_no = it->second;
967 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800968 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600969 return port_no;
970}
971
972Status 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 +0000973 uint32_t flow_id, const std::string flow_type,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700974 int32_t alloc_id, int32_t network_intf_id,
975 int32_t gemport_id, const ::openolt::Classifier& classifier,
Craig Lutgen967a1d02018-11-27 10:41:51 -0600976 const ::openolt::Action& action, int32_t priority_value, uint64_t cookie) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000977 bcmos_errno err;
978 bcmbal_flow_cfg cfg;
979 bcmbal_flow_key key = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800980 int32_t o_vid = -1;
981 bool single_tag = false;
982 uint32_t ether_type = 0;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000983
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800984 BCM_LOG(INFO, openolt_log_id, "flow add - intf_id %d, onu_id %d, uni_id %d, port_no %u, flow_id %d, flow_type %s, \
985 gemport_id %d, network_intf_id %d, cookie %llu\n", \
986 access_intf_id, onu_id, uni_id, port_no, flow_id, flow_type.c_str(), gemport_id, network_intf_id, cookie);
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000987
988 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800989 if (flow_type.compare(upstream) == 0 ) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000990 key.flow_type = BCMBAL_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800991 } else if (flow_type.compare(downstream) == 0) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000992 key.flow_type = BCMBAL_FLOW_TYPE_DOWNSTREAM;
993 } else {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400994 BCM_LOG(WARNING, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400995 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000996 }
997
998 BCMBAL_CFG_INIT(&cfg, flow, key);
999
1000 BCMBAL_CFG_PROP_SET(&cfg, flow, admin_state, BCMBAL_STATE_UP);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001001 BCMBAL_CFG_PROP_SET(&cfg, flow, cookie, cookie);
1002
Shad Ansari39739bc2018-09-13 21:38:37 +00001003 if (access_intf_id >= 0) {
1004 BCMBAL_CFG_PROP_SET(&cfg, flow, access_int_id, access_intf_id);
1005 }
1006 if (network_intf_id >= 0) {
1007 BCMBAL_CFG_PROP_SET(&cfg, flow, network_int_id, network_intf_id);
1008 }
1009 if (onu_id >= 0) {
1010 BCMBAL_CFG_PROP_SET(&cfg, flow, sub_term_id, onu_id);
1011 }
1012 if (gemport_id >= 0) {
1013 BCMBAL_CFG_PROP_SET(&cfg, flow, svc_port_id, gemport_id);
1014 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001015 if (gemport_id >= 0 && port_no != 0) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001016 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001017 if (key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM) {
1018 port_to_flows[port_no].insert(key.flow_id);
1019 flowid_to_gemport[key.flow_id] = gemport_id;
1020 }
1021 else
1022 {
1023 flowid_to_port[key.flow_id] = port_no;
1024 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001025 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001026 }
Shad Ansari39739bc2018-09-13 21:38:37 +00001027 if (priority_value >= 0) {
1028 BCMBAL_CFG_PROP_SET(&cfg, flow, priority, priority_value);
1029 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001030
1031 {
1032 bcmbal_classifier val = { };
1033
1034 if (classifier.o_tpid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001035 BCM_LOG(DEBUG, openolt_log_id, "classify o_tpid 0x%04x\n", classifier.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001036 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_tpid, classifier.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001037 }
1038
1039 if (classifier.o_vid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001040 BCM_LOG(DEBUG, openolt_log_id, "classify o_vid %d\n", classifier.o_vid());
Craig Lutgen19512312018-11-02 10:14:46 -05001041 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_vid, classifier.o_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001042 }
1043
1044 if (classifier.i_tpid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001045 BCM_LOG(DEBUG, openolt_log_id, "classify i_tpid 0x%04x\n", classifier.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001046 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, i_tpid, classifier.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001047 }
1048
1049 if (classifier.i_vid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001050 BCM_LOG(DEBUG, openolt_log_id, "classify i_vid %d\n", classifier.i_vid());
Craig Lutgen19512312018-11-02 10:14:46 -05001051 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, i_vid, classifier.i_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001052 }
1053
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001054 if (classifier.eth_type()) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001055 ether_type = classifier.eth_type();
Craig Lutgenecd353a2018-12-12 22:33:17 -06001056 BCM_LOG(DEBUG, openolt_log_id, "classify ether_type 0x%04x\n", classifier.eth_type());
Craig Lutgen19512312018-11-02 10:14:46 -05001057 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, ether_type, classifier.eth_type());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001058 }
1059
1060 /*
1061 if (classifier.dst_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001062 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_mac, classifier.dst_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001063 }
1064
1065 if (classifier.src_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001066 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_mac, classifier.src_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001067 }
1068 */
1069
1070 if (classifier.ip_proto()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001071 BCM_LOG(DEBUG, openolt_log_id, "classify ip_proto %d\n", classifier.ip_proto());
Craig Lutgen19512312018-11-02 10:14:46 -05001072 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, ip_proto, classifier.ip_proto());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001073 }
1074
1075 /*
1076 if (classifier.dst_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001077 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_ip, classifier.dst_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001078 }
1079
1080 if (classifier.src_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001081 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_ip, classifier.src_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001082 }
1083 */
1084
1085 if (classifier.src_port()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001086 BCM_LOG(DEBUG, openolt_log_id, "classify src_port %d\n", classifier.src_port());
Craig Lutgen19512312018-11-02 10:14:46 -05001087 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_port, classifier.src_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001088 }
1089
1090 if (classifier.dst_port()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001091 BCM_LOG(DEBUG, openolt_log_id, "classify dst_port %d\n", classifier.dst_port());
Craig Lutgen19512312018-11-02 10:14:46 -05001092 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_port, classifier.dst_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001093 }
1094
1095 if (!classifier.pkt_tag_type().empty()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001096 BCM_LOG(DEBUG, openolt_log_id, "classify tag_type %s\n", classifier.pkt_tag_type().c_str());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001097 if (classifier.pkt_tag_type().compare("untagged") == 0) {
Craig Lutgen19512312018-11-02 10:14:46 -05001098 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, pkt_tag_type, BCMBAL_PKT_TAG_TYPE_UNTAGGED);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001099 } else if (classifier.pkt_tag_type().compare("single_tag") == 0) {
Craig Lutgen19512312018-11-02 10:14:46 -05001100 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, pkt_tag_type, BCMBAL_PKT_TAG_TYPE_SINGLE_TAG);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001101 single_tag = true;
1102
1103 BCM_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1104 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_pbits, classifier.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001105 } else if (classifier.pkt_tag_type().compare("double_tag") == 0) {
Craig Lutgen19512312018-11-02 10:14:46 -05001106 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, pkt_tag_type, BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001107
1108 BCM_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1109 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_pbits, classifier.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001110 }
1111 }
1112
1113 BCMBAL_CFG_PROP_SET(&cfg, flow, classifier, val);
1114 }
1115
1116 {
1117 bcmbal_action val = { };
1118
1119 const ::openolt::ActionCmd& cmd = action.cmd();
1120
1121 if (cmd.add_outer_tag()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001122 BCM_LOG(INFO, openolt_log_id, "action add o_tag\n");
Craig Lutgen19512312018-11-02 10:14:46 -05001123 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, cmds_bitmask, BCMBAL_ACTION_CMD_ID_ADD_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001124 }
1125
1126 if (cmd.remove_outer_tag()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001127 BCM_LOG(INFO, openolt_log_id, "action pop o_tag\n");
Craig Lutgen19512312018-11-02 10:14:46 -05001128 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, cmds_bitmask, BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001129 }
1130
1131 if (cmd.trap_to_host()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001132 BCM_LOG(INFO, openolt_log_id, "action trap-to-host\n");
Craig Lutgen19512312018-11-02 10:14:46 -05001133 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, cmds_bitmask, BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001134 }
1135
1136 if (action.o_vid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001137 BCM_LOG(INFO, openolt_log_id, "action o_vid=%d\n", action.o_vid());
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001138 o_vid = action.o_vid();
Craig Lutgen19512312018-11-02 10:14:46 -05001139 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, o_vid, action.o_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001140 }
1141
1142 if (action.o_pbits()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001143 BCM_LOG(INFO, openolt_log_id, "action o_pbits=0x%x\n", action.o_pbits());
Craig Lutgen19512312018-11-02 10:14:46 -05001144 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, o_pbits, action.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001145 }
1146
1147 if (action.o_tpid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001148 BCM_LOG(INFO, openolt_log_id, "action o_tpid=0x%04x\n", action.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001149 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, o_tpid, action.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001150 }
1151
1152 if (action.i_vid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001153 BCM_LOG(INFO, openolt_log_id, "action i_vid=%d\n", action.i_vid());
Craig Lutgen19512312018-11-02 10:14:46 -05001154 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, i_vid, action.i_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001155 }
1156
1157 if (action.i_pbits()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001158 BCM_LOG(DEBUG, openolt_log_id, "action i_pbits=0x%x\n", action.i_pbits());
Craig Lutgen19512312018-11-02 10:14:46 -05001159 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, i_pbits, action.i_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001160 }
1161
1162 if (action.i_tpid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001163 BCM_LOG(DEBUG, openolt_log_id, "action i_tpid=0x%04x\n", action.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001164 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, i_tpid, action.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001165 }
1166
1167 BCMBAL_CFG_PROP_SET(&cfg, flow, action, val);
1168 }
1169
Shad Ansari39739bc2018-09-13 21:38:37 +00001170 if ((access_intf_id >= 0) && (onu_id >= 0)) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001171
Shad Ansari39739bc2018-09-13 21:38:37 +00001172 if (key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM) {
1173 bcmbal_tm_queue_ref val = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001174 if (single_tag && ether_type == EAP_ETHER_TYPE) {
1175 val.sched_id = get_default_tm_sched_id(access_intf_id, downstream);
1176 val.queue_id = 0;
1177
1178 } else {
1179 val.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, downstream); // Subscriber Scheduler
1180 val.queue_id = get_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, downstream);
1181 }
Girish Gowdru76a6af92019-05-01 23:47:58 -07001182 BCM_LOG(INFO, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d\n", \
1183 downstream.c_str(), val.queue_id, val.sched_id);
Shad Ansari39739bc2018-09-13 21:38:37 +00001184 BCMBAL_CFG_PROP_SET(&cfg, flow, queue, val);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001185 } else if (key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM) {
1186 bcmbal_tm_sched_id val1;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001187 val1 = get_tm_sched_id(access_intf_id, onu_id, uni_id, upstream); // DBA Scheduler ID
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001188 BCMBAL_CFG_PROP_SET(&cfg, flow, dba_tm_sched_id, val1);
1189
1190 bcmbal_tm_queue_ref val2 = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001191 val2.sched_id = get_default_tm_sched_id(network_intf_id, upstream); // NNI Scheduler ID
Girish Gowdrue1b5d562019-04-18 22:43:32 -07001192 val2.queue_id = get_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, upstream); // Queue on NNI
Girish Gowdru76a6af92019-05-01 23:47:58 -07001193 BCM_LOG(INFO, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d\n", \
1194 upstream.c_str(), val2.queue_id, val2.sched_id);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001195 BCMBAL_CFG_PROP_SET(&cfg, flow, queue, val2);
Shad Ansari39739bc2018-09-13 21:38:37 +00001196 }
Shad Ansari06101952018-07-25 00:22:09 +00001197 }
1198
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001199 err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(cfg.hdr));
1200 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001201 BCM_LOG(ERROR, openolt_log_id, "Flow add failed\n");
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001202 return bcm_to_grpc_err(err, "flow add failed");
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001203 }
1204
Nicolas Palpacuer6a63ea92018-09-05 17:21:37 -04001205 // register_new_flow(key);
Nicolas Palpacuer0f19b1a2018-06-07 17:29:31 -04001206
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001207 return Status::OK;
1208}
1209
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001210Status FlowRemove_(uint32_t flow_id, const std::string flow_type) {
1211
1212 bcmbal_flow_cfg cfg;
1213 bcmbal_flow_key key = { };
1214
1215 key.flow_id = (bcmbal_flow_id) flow_id;
1216 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001217 if (flow_type.compare(upstream) == 0 ) {
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001218 key.flow_type = BCMBAL_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001219 } else if (flow_type.compare(downstream) == 0) {
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001220 key.flow_type = BCMBAL_FLOW_TYPE_DOWNSTREAM;
1221 } else {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001222 BCM_LOG(WARNING, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001223 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
1224 }
1225
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001226 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001227 uint32_t port_no = flowid_to_port[key.flow_id];
1228 if (key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM) {
1229 flowid_to_gemport.erase(key.flow_id);
1230 port_to_flows[port_no].erase(key.flow_id);
1231 if (port_to_flows[port_no].empty()) port_to_flows.erase(port_no);
1232 }
1233 else
1234 {
1235 flowid_to_port.erase(key.flow_id);
1236 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001237 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001238
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001239 BCMBAL_CFG_INIT(&cfg, flow, key);
1240
1241
1242 bcmos_errno err = bcmbal_cfg_clear(DEFAULT_ATERM_ID, &cfg.hdr);
1243 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001244 BCM_LOG(ERROR, openolt_log_id, "Error %d while removing flow %d, %s\n",
1245 err, flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001246 return Status(grpc::StatusCode::INTERNAL, "Failed to remove flow");
1247 }
1248
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001249 BCM_LOG(INFO, openolt_log_id, "Flow %d, %s removed\n", flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001250 return Status::OK;
1251}
1252
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001253bcmos_errno CreateSched(std::string direction, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t port_no,
1254 uint32_t alloc_id, tech_profile::AdditionalBW additional_bw, uint32_t weight, uint32_t priority,
1255 tech_profile::SchedulingPolicy sched_policy, tech_profile::TrafficShapingInfo tf_sh_info) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001256
1257 bcmos_errno err;
1258
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001259 if (direction == downstream) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001260
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001261 bcmbal_tm_sched_cfg cfg;
1262 bcmbal_tm_sched_key key = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001263 key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
1264 key.dir = BCMBAL_TM_SCHED_DIR_DS;
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001265
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001266 BCMBAL_CFG_INIT(&cfg, tm_sched, key);
1267
1268 {
1269 // bcmbal_tm_sched_owner
1270 // In downstream it is sub_term scheduler
1271 bcmbal_tm_sched_owner tm_sched_owner = { };
1272 tm_sched_owner.type = BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM;
1273 tm_sched_owner.u.sub_term.intf_id = intf_id;
1274 tm_sched_owner.u.sub_term.sub_term_id = onu_id;
1275 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, owner, tm_sched_owner);
1276
1277 // bcmbal_tm_sched_type
1278 // set the deafult policy to strict priority
1279 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, sched_type, BCMBAL_TM_SCHED_TYPE_SP);
1280
1281 // bcmbal_tm_sched_parent
1282 // The parent for the sub_term scheduler is the PON scheduler in the downstream
1283 bcmbal_tm_sched_parent tm_sched_parent = { };
1284 tm_sched_parent.presence_mask |= (BCMBAL_TM_SCHED_PARENT_ID_SCHED_ID);
1285 tm_sched_parent.sched_id = get_default_tm_sched_id(intf_id, downstream);
1286 tm_sched_parent.presence_mask |= (BCMBAL_TM_SCHED_PARENT_ID_PRIORITY);
1287 tm_sched_parent.priority = 1; // TODO: Hardcoded priority as 1
1288 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, sched_parent, tm_sched_parent);
1289
1290 // num_priorities: Max number of strict priority scheduling elements
1291 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, num_priorities, 8); // TODO: hardcoded 8 priorities.
1292
1293 // bcmbal_tm_shaping
1294 if (tf_sh_info.cir() >= 0 && tf_sh_info.pir() > 0) {
1295 bcmbal_tm_shaping rate = {};
1296 uint32_t cir = tf_sh_info.cir();
1297 uint32_t pir = tf_sh_info.pir();
1298 uint32_t burst = tf_sh_info.pbs();
1299 BCM_LOG(INFO, openolt_log_id, "applying traffic shaping in DL cir=%u, pir=%u, burst=%u\n",
1300 cir, pir, burst);
1301 rate.presence_mask = BCMBAL_TM_SHAPING_ID_NONE;
1302 rate.presence_mask |= BCMBAL_TM_SHAPING_ID_PIR;
1303 rate.presence_mask |= BCMBAL_TM_SHAPING_ID_BURST;
1304 // FIXME: Setting CIR, results in BAL throwing error 'tm_sched minimum rate is not supported yet'
1305 // rate.cir = cir;
1306 rate.pir = pir;
1307 rate.burst = burst;
1308
Girish Gowdrue1b5d562019-04-18 22:43:32 -07001309 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, rate, rate);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001310 }
1311
1312 // creation_mode
1313 // BCMBAL_CFG_PROP_SET(&cfg, tm_sched, creation_mode, BCMBAL_TM_CREATION_MODE_MANUAL);
1314 }
1315
1316 err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(cfg.hdr));
1317 if (err) {
1318 BCM_LOG(ERROR, openolt_log_id, "Failed to create downstream subscriber scheduler, id %d, intf_id %d, \
1319 onu_id %d, uni_id %d, port_no %u\n", key.id, intf_id, onu_id,uni_id,port_no);
1320 return err;
1321 }
1322 BCM_LOG(INFO, openolt_log_id, "Create downstream subscriber sched, id %d, intf_id %d, onu_id %d, \
1323 uni_id %d, port_no %u\n", key.id,intf_id,onu_id,uni_id,port_no);
1324
1325 } else { //upstream
1326 bcmbal_tm_sched_cfg cfg;
1327 bcmbal_tm_sched_key key = { };
1328
1329 key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001330 key.dir = BCMBAL_TM_SCHED_DIR_US;
1331
1332 BCMBAL_CFG_INIT(&cfg, tm_sched, key);
1333
1334 {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001335 // bcmbal_tm_sched_owner: AGG PORT
1336 bcmbal_tm_sched_owner tm_sched_owner = { };
1337 tm_sched_owner.type = BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT;
1338 tm_sched_owner.u.agg_port.presence_mask |= bcmbal_tm_sched_owner_agg_port_id_all;
1339 tm_sched_owner.u.agg_port.intf_id = intf_id;
1340 tm_sched_owner.u.agg_port.sub_term_id = onu_id;
1341 tm_sched_owner.u.agg_port.agg_port_id = alloc_id;
1342 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, owner, tm_sched_owner);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001343
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001344 // bcmbal_tm_shaping
1345 if (tf_sh_info.cir() >= 0 && tf_sh_info.pir() > 0) {
1346 bcmbal_tm_shaping rate = {};
1347 uint32_t cir = tf_sh_info.cir();
1348 uint32_t pir = tf_sh_info.pir();
1349 uint32_t burst = tf_sh_info.pbs();
1350 BCM_LOG(INFO, openolt_log_id, "applying traffic shaping in UL cir=%u, pir=%u, burst=%u\n",
1351 cir, pir, burst);
1352 rate.presence_mask = BCMBAL_TM_SHAPING_ID_ALL;
1353 rate.cir = cir;
1354 rate.pir = pir;
1355 rate.burst = burst;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001356
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001357 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, rate, rate);
1358 }
Girish Gowdrue075c642019-01-23 04:05:53 -08001359 }
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001360
1361 err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(cfg.hdr));
1362 if (err) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001363 BCM_LOG(ERROR, openolt_log_id, "Failed to create upstream DBA sched, id %d, intf_id %d, onu_id %d, uni_id %d,\
1364 port_no %u, alloc_id %d\n", key.id, intf_id, onu_id,uni_id,port_no,alloc_id);
1365 return err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001366 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001367 BCM_LOG(INFO, openolt_log_id, "Create upstream DBA sched, id %d, intf_id %d, onu_id %d, uni_id %d, port_no %u, \
1368 alloc_id %d\n", key.id,intf_id,onu_id,uni_id,port_no,alloc_id);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001369 }
1370
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001371 return BCM_ERR_OK;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001372}
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001373
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001374Status CreateTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
1375 uint32_t intf_id = traffic_scheds->intf_id();
1376 uint32_t onu_id = traffic_scheds->onu_id();
1377 uint32_t uni_id = traffic_scheds->uni_id();
1378 uint32_t port_no = traffic_scheds->port_no();
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001379 std::string direction;
1380 unsigned int alloc_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001381 tech_profile::SchedulerConfig sched_config;
1382 tech_profile::AdditionalBW additional_bw;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001383 uint32_t priority;
1384 uint32_t weight;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001385 tech_profile::SchedulingPolicy sched_policy;
1386 tech_profile::TrafficShapingInfo traffic_shaping_info;
1387 bcmos_errno err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001388
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001389 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
1390 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
1391 if (traffic_sched.direction() == tech_profile::Direction::UPSTREAM) {
1392 direction = upstream;
1393 } else if (traffic_sched.direction() == tech_profile::Direction::DOWNSTREAM) {
1394 direction = downstream;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001395 }
1396 else {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001397 BCM_LOG(ERROR, openolt_log_id, "direction-not-supported %d", traffic_sched.direction());
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001398 return Status::CANCELLED;
1399 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001400 alloc_id = traffic_sched.alloc_id();
1401 sched_config = traffic_sched.scheduler();
1402 additional_bw = sched_config.additional_bw();
1403 priority = sched_config.priority();
1404 weight = sched_config.weight();
1405 sched_policy = sched_config.sched_policy();
1406 traffic_shaping_info = traffic_sched.traffic_shaping_info();
1407 err = CreateSched(direction, intf_id, onu_id, uni_id, port_no, alloc_id, additional_bw, weight, priority,
1408 sched_policy, traffic_shaping_info);
1409 if (err) {
1410 return bcm_to_grpc_err(err, "Failed to create scheduler");
1411 }
Girish Gowdru1cdf6ce2018-08-27 02:43:02 -07001412 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001413 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001414}
Jonathan Davis70c21812018-07-19 15:32:10 -04001415
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001416bcmos_errno RemoveSched(int intf_id, int onu_id, int uni_id, std::string direction) {
Jonathan Davis70c21812018-07-19 15:32:10 -04001417
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001418 bcmos_errno err;
Jonathan Davis70c21812018-07-19 15:32:10 -04001419
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001420 bcmbal_tm_sched_cfg tm_cfg_us;
1421 bcmbal_tm_sched_key tm_key_us = { };
Jonathan Davis70c21812018-07-19 15:32:10 -04001422
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001423 if (is_tm_sched_id_present(intf_id, onu_id, uni_id, direction)) {
1424 tm_key_us.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
1425 } else {
1426 BCM_LOG(INFO, openolt_log_id, "schduler not present in %s\n", direction.c_str());
1427 return BCM_ERR_OK;
1428 }
1429 if (direction == upstream) {
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001430 tm_key_us.dir = BCMBAL_TM_SCHED_DIR_US;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001431 } else {
1432 tm_key_us.dir = BCMBAL_TM_SCHED_DIR_DS;
1433 }
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001434
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001435 BCMBAL_CFG_INIT(&tm_cfg_us, tm_sched, tm_key_us);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001436
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001437 err = bcmbal_cfg_clear(DEFAULT_ATERM_ID, &(tm_cfg_us.hdr));
1438 if (err) {
1439 BCM_LOG(ERROR, openolt_log_id, "Failed to remove scheduler sched, direction = %s, id %d, intf_id %d, onu_id %d\n", \
1440 direction.c_str(), tm_key_us.id, intf_id, onu_id);
1441 return err;
1442 }
1443
1444 free_tm_sched_id(intf_id, onu_id, uni_id, direction);
1445
1446 BCM_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, id %d, intf_id %d, onu_id %d\n", \
1447 direction.c_str(), tm_key_us.id, intf_id, onu_id);
1448
1449 return BCM_ERR_OK;
1450}
1451
1452Status RemoveTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
1453 uint32_t intf_id = traffic_scheds->intf_id();
1454 uint32_t onu_id = traffic_scheds->onu_id();
1455 uint32_t uni_id = traffic_scheds->uni_id();
1456 std::string direction;
1457 bcmos_errno err;
1458
1459 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
1460 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
1461 if (traffic_sched.direction() == tech_profile::Direction::UPSTREAM) {
1462 direction = upstream;
1463 } else if (traffic_sched.direction() == tech_profile::Direction::DOWNSTREAM) {
1464 direction = downstream;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001465 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001466 else {
1467 BCM_LOG(ERROR, openolt_log_id, "direction-not-supported %d", traffic_sched.direction());
1468 return Status::CANCELLED;
1469 }
1470 err = RemoveSched(intf_id, onu_id, uni_id, direction);
1471 if (err) {
1472 return bcm_to_grpc_err(err, "error-removing-traffic-scheduler");
1473 }
1474 }
1475 return Status::OK;
1476}
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001477
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001478bcmos_errno CreateQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
1479 uint32_t gemport_id) {
1480 bcmos_errno err;
1481 bcmbal_tm_queue_cfg cfg;
1482 bcmbal_tm_queue_key key = { };
Girish Gowdru76a6af92019-05-01 23:47:58 -07001483 BCM_LOG(INFO, openolt_log_id, "creating queue. access_intf_id = %d, onu_id = %d, uni_id = %d \
1484 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 -08001485 if (direction == downstream) {
1486 // In the downstream, the queues are on the 'sub term' scheduler
1487 // There is one queue per gem port
1488 key.sched_dir = BCMBAL_TM_SCHED_DIR_DS;
1489 key.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
1490 key.id = get_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, direction);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001491
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001492 } else {
1493 queue_map_key_tuple map_key(access_intf_id, onu_id, uni_id, gemport_id, direction);
1494 if (queue_map.count(map_key) > 0) {
1495 BCM_LOG(INFO, openolt_log_id, "upstream queue exists for intf_id %d, onu_id %d, uni_id %d\n. Not re-creating", \
1496 access_intf_id, onu_id, uni_id);
1497 return BCM_ERR_OK;
1498 }
1499 key.sched_dir = BCMBAL_TM_SCHED_DIR_US;
1500 key.sched_id = get_default_tm_sched_id(nni_intf_id, direction);
1501 if (priority > 7) {
1502 return BCM_ERR_RANGE;
1503 }
1504 // There are 8 queues (one per p-bit)
1505 key.id = us_fixed_queue_id_list[priority];
1506 update_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, direction, key.id);
1507 // FIXME: The upstream queues have to be created once only.
1508 // The upstream queues on the NNI scheduler are shared by all subscribers.
1509 // When the first scheduler comes in, the queues get created, and are re-used by all others.
1510 // Also, these queues should be present until the last subscriber exits the system.
1511 // One solution is to have these queues always, i.e., create it as soon as OLT is enabled.
1512 }
Girish Gowdru76a6af92019-05-01 23:47:58 -07001513 BCM_LOG(INFO, openolt_log_id, "queue assigned queue_id = %d\n", key.id);
1514
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001515 BCMBAL_CFG_INIT(&cfg, tm_queue, key);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001516
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001517 BCMBAL_CFG_PROP_SET(&cfg, tm_queue, priority, priority);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001518
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001519 // BCMBAL_CFG_PROP_SET(&cfg, tm_queue, creation_mode, BCMBAL_TM_CREATION_MODE_MANUAL);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001520
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001521
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001522 err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &cfg.hdr);
1523 if (err) {
1524 BCM_LOG(ERROR, openolt_log_id, "Failed to create subscriber tm queue, direction = %s, id %d, sched_id %d, \
1525 intf_id %d, onu_id %d, uni_id %d\n", \
1526 direction.c_str(), key.id, key.sched_id, access_intf_id, onu_id, uni_id);
1527 return err;
1528 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001529
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001530 BCM_LOG(INFO, openolt_log_id, "Created tm_queue, direction %s, id %d, intf_id %d, onu_id %d, uni_id %d", \
1531 direction.c_str(), key.id, access_intf_id, onu_id, uni_id);
1532
1533 return BCM_ERR_OK;
1534
1535}
1536
1537Status CreateTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
1538 uint32_t intf_id = traffic_queues->intf_id();
1539 uint32_t onu_id = traffic_queues->onu_id();
1540 uint32_t uni_id = traffic_queues->uni_id();
1541 std::string direction;
1542 unsigned int alloc_id;
1543 bcmos_errno err;
1544
1545 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
1546 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
1547 if (traffic_queue.direction() == tech_profile::Direction::UPSTREAM) {
1548 direction = upstream;
1549 } else if (traffic_queue.direction() == tech_profile::Direction::DOWNSTREAM) {
1550 direction = downstream;
1551 }
1552 else {
1553 BCM_LOG(ERROR, openolt_log_id, "direction-not-supported %d", traffic_queue.direction());
1554 return Status::CANCELLED;
1555 }
1556 err = CreateQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
Girish Gowdru76a6af92019-05-01 23:47:58 -07001557 // If the queue exists already, lets not return failure and break the loop.
1558 if (err && err != BCM_ERR_ALREADY) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001559 return bcm_to_grpc_err(err, "Failed to create queue");
1560 }
1561 }
1562 return Status::OK;
1563}
1564
1565
1566bcmos_errno RemoveQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
1567 uint32_t gemport_id) {
1568 bcmbal_tm_queue_cfg queue_cfg;
1569 bcmbal_tm_queue_key queue_key = { };
1570 bcmos_errno err;
1571
1572 if (direction == downstream) {
1573 queue_key.sched_dir = BCMBAL_TM_SCHED_DIR_DS;
1574 if (is_tm_queue_id_present(access_intf_id, onu_id, uni_id, gemport_id, direction) && \
1575 is_tm_sched_id_present(access_intf_id, onu_id, uni_id, direction)) {
1576 queue_key.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
1577 queue_key.id = get_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, direction);
1578 } else {
1579 BCM_LOG(INFO, openolt_log_id, "queue not present in DS. Not clearing");
1580 return BCM_ERR_OK;
1581 }
1582 } else {
1583 free_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, direction);
1584 // In the upstream we use pre-created queues on the NNI scheduler that are used by all subscribers.
1585 // They should not be removed. So, lets return OK.
1586 return BCM_ERR_OK;
1587 }
1588
1589 BCMBAL_CFG_INIT(&queue_cfg, tm_queue, queue_key);
1590
1591 err = bcmbal_cfg_clear(DEFAULT_ATERM_ID, &(queue_cfg.hdr));
1592
1593 if (err) {
1594 BCM_LOG(ERROR, openolt_log_id, "Failed to remove queue, direction = %s, id %d, sched_id %d, intf_id %d, onu_id %d, uni_id %d\n",
1595 direction.c_str(), queue_key.id, queue_key.sched_id, access_intf_id, onu_id, uni_id);
1596 return err;
1597 }
1598
1599 free_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, direction);
1600
1601 return BCM_ERR_OK;
1602}
1603
1604Status RemoveTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
1605 uint32_t intf_id = traffic_queues->intf_id();
1606 uint32_t onu_id = traffic_queues->onu_id();
1607 uint32_t uni_id = traffic_queues->uni_id();
1608 uint32_t port_no = traffic_queues->port_no();
1609 std::string direction;
1610 unsigned int alloc_id;
1611 bcmos_errno err;
1612
1613 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
1614 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
1615 if (traffic_queue.direction() == tech_profile::Direction::UPSTREAM) {
1616 direction = upstream;
1617 } else if (traffic_queue.direction() == tech_profile::Direction::DOWNSTREAM) {
1618 direction = downstream;
1619 } else {
1620 BCM_LOG(ERROR, openolt_log_id, "direction-not-supported %d", traffic_queue.direction());
1621 return Status::CANCELLED;
1622 }
1623 err = RemoveQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
1624 if (err) {
1625 return bcm_to_grpc_err(err, "Failed to remove queue");
1626 }
Jonathan Davis70c21812018-07-19 15:32:10 -04001627 }
1628
Jonathan Davis70c21812018-07-19 15:32:10 -04001629 return Status::OK;
Jonathan Davis70c21812018-07-19 15:32:10 -04001630}