blob: 83bd99a2f82d2ab024bf126938ff652b0e434294 [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
Girish Gowdru771f9ff2019-07-24 12:02:10 -0700339 char device_id[OPENOLT_FIELD_LEN];
340 memset(device_id, '\0', OPENOLT_FIELD_LEN);
341 openolt_read_sysinfo("MAC", device_id);
342 BCM_LOG(INFO, openolt_log_id, "Fetched device mac address %s\n", device_id);
343 device_info->set_device_id(device_id);
344
Craig Lutgenb2601f02018-10-23 13:04:31 -0500345 // Legacy, device-wide ranges. To be deprecated when adapter
346 // is upgraded to support per-interface ranges
347 if (board_technology == "xgspon") {
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500348 device_info->set_onu_id_start(1);
349 device_info->set_onu_id_end(255);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600350 device_info->set_alloc_id_start(MIN_ALLOC_ID_XGSPON);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500351 device_info->set_alloc_id_end(16383);
352 device_info->set_gemport_id_start(1024);
353 device_info->set_gemport_id_end(65535);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500354 device_info->set_flow_id_start(1);
355 device_info->set_flow_id_end(16383);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500356 }
Craig Lutgenb2601f02018-10-23 13:04:31 -0500357 else if (board_technology == "gpon") {
358 device_info->set_onu_id_start(1);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500359 device_info->set_onu_id_end(127);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600360 device_info->set_alloc_id_start(MIN_ALLOC_ID_GPON);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500361 device_info->set_alloc_id_end(767);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500362 device_info->set_gemport_id_start(256);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500363 device_info->set_gemport_id_end(4095);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500364 device_info->set_flow_id_start(1);
365 device_info->set_flow_id_end(16383);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500366 }
Craig Lutgenb2601f02018-10-23 13:04:31 -0500367
368 std::map<std::string, openolt::DeviceInfo::DeviceResourceRanges*> ranges;
369 for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
370 std::string intf_technology = intf_technologies[intf_id];
371 openolt::DeviceInfo::DeviceResourceRanges *range = ranges[intf_technology];
372 if(range == nullptr) {
373 range = device_info->add_ranges();
374 ranges[intf_technology] = range;
375 range->set_technology(intf_technology);
376
377 if (intf_technology == "xgspon") {
378 openolt::DeviceInfo::DeviceResourceRanges::Pool* pool;
379
380 pool = range->add_pools();
381 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ONU_ID);
382 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::DEDICATED_PER_INTF);
383 pool->set_start(1);
384 pool->set_end(255);
385
386 pool = range->add_pools();
387 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ALLOC_ID);
388 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_SAME_TECH);
389 pool->set_start(1024);
390 pool->set_end(16383);
391
392 pool = range->add_pools();
393 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::GEMPORT_ID);
394 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
395 pool->set_start(1024);
396 pool->set_end(65535);
397
398 pool = range->add_pools();
399 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::FLOW_ID);
400 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
401 pool->set_start(1);
402 pool->set_end(16383);
403 }
404 else if (intf_technology == "gpon") {
405 openolt::DeviceInfo::DeviceResourceRanges::Pool* pool;
406
407 pool = range->add_pools();
408 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ONU_ID);
409 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::DEDICATED_PER_INTF);
410 pool->set_start(1);
411 pool->set_end(127);
412
413 pool = range->add_pools();
414 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ALLOC_ID);
415 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_SAME_TECH);
416 pool->set_start(256);
417 pool->set_end(757);
418
419 pool = range->add_pools();
420 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::GEMPORT_ID);
421 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
422 pool->set_start(256);
423 pool->set_end(4095);
424
425 pool = range->add_pools();
426 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::FLOW_ID);
427 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
428 pool->set_start(1);
429 pool->set_end(16383);
430 }
431 }
432
433 range->add_intf_ids(intf_id);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500434 }
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400435
436 // FIXME: Once dependency problem is fixed
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500437 // device_info->set_pon_ports(num_of_pon_ports);
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400438 // device_info->set_onu_id_end(XGPON_NUM_OF_ONUS - 1);
439 // device_info->set_alloc_id_start(1024);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500440 // device_info->set_alloc_id_end(XGPON_NUM_OF_ALLOC_IDS * num_of_pon_ports ? - 1);
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400441 // device_info->set_gemport_id_start(XGPON_MIN_BASE_SERVICE_PORT_ID);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500442 // device_info->set_gemport_id_end(XGPON_NUM_OF_GEM_PORT_IDS_PER_PON * num_of_pon_ports ? - 1);
443 // device_info->set_pon_ports(num_of_pon_ports);
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400444
445 return Status::OK;
446}
447
Shad Ansari627b5782018-08-13 22:49:32 +0000448Status Enable_(int argc, char *argv[]) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000449 bcmbal_access_terminal_cfg acc_term_obj;
450 bcmbal_access_terminal_key key = { };
451
Shad Ansariedef2132018-08-10 22:14:50 +0000452 if (!state.is_activated()) {
Shad Ansari627b5782018-08-13 22:49:32 +0000453
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500454 vendor_init();
Shad Ansari627b5782018-08-13 22:49:32 +0000455 bcmbal_init(argc, argv, NULL);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800456 bcmos_fastlock_init(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600457
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500458 BCM_LOG(INFO, openolt_log_id, "Enable OLT - %s-%s\n", VENDOR_ID, MODEL_ID);
459
Shad Ansari627b5782018-08-13 22:49:32 +0000460 Status status = SubscribeIndication();
461 if (!status.ok()) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400462 BCM_LOG(ERROR, openolt_log_id, "SubscribeIndication failed - %s : %s\n",
463 grpc_status_code_to_string(status.error_code()).c_str(),
464 status.error_message().c_str());
465
Shad Ansari627b5782018-08-13 22:49:32 +0000466 return status;
467 }
468
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000469 key.access_term_id = DEFAULT_ATERM_ID;
470 BCMBAL_CFG_INIT(&acc_term_obj, access_terminal, key);
471 BCMBAL_CFG_PROP_SET(&acc_term_obj, access_terminal, admin_state, BCMBAL_STATE_UP);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400472 bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(acc_term_obj.hdr));
473 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400474 BCM_LOG(ERROR, openolt_log_id, "Failed to enable OLT\n");
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400475 return bcm_to_grpc_err(err, "Failed to enable OLT");
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000476 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500477
Shad Ansariedef2132018-08-10 22:14:50 +0000478 init_stats();
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000479 }
Shad Ansariedef2132018-08-10 22:14:50 +0000480
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400481 //If already enabled, generate an extra indication ????
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000482 return Status::OK;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400483}
484
485Status Disable_() {
486 // bcmbal_access_terminal_cfg acc_term_obj;
487 // bcmbal_access_terminal_key key = { };
488 //
489 // if (state::is_activated) {
490 // std::cout << "Disable OLT" << std::endl;
491 // key.access_term_id = DEFAULT_ATERM_ID;
492 // BCMBAL_CFG_INIT(&acc_term_obj, access_terminal, key);
493 // BCMBAL_CFG_PROP_SET(&acc_term_obj, access_terminal, admin_state, BCMBAL_STATE_DOWN);
494 // bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(acc_term_obj.hdr));
495 // if (err) {
496 // std::cout << "ERROR: Failed to disable OLT" << std::endl;
497 // return bcm_to_grpc_err(err, "Failed to disable OLT");
498 // }
499 // }
500 // //If already disabled, generate an extra indication ????
501 // return Status::OK;
502 //This fails with Operation Not Supported, bug ???
503
504 //TEMPORARY WORK AROUND
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800505 Status status = DisableUplinkIf_(nni_intf_id);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400506 if (status.ok()) {
Shad Ansariedef2132018-08-10 22:14:50 +0000507 state.deactivate();
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400508 openolt::Indication ind;
509 openolt::OltIndication* olt_ind = new openolt::OltIndication;
510 olt_ind->set_oper_state("down");
511 ind.set_allocated_olt_ind(olt_ind);
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400512 BCM_LOG(INFO, openolt_log_id, "Disable OLT, add an extra indication\n");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400513 oltIndQ.push(ind);
514 }
515 return status;
516
517}
518
519Status Reenable_() {
520 Status status = EnableUplinkIf_(0);
521 if (status.ok()) {
Shad Ansariedef2132018-08-10 22:14:50 +0000522 state.activate();
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400523 openolt::Indication ind;
524 openolt::OltIndication* olt_ind = new openolt::OltIndication;
525 olt_ind->set_oper_state("up");
526 ind.set_allocated_olt_ind(olt_ind);
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400527 BCM_LOG(INFO, openolt_log_id, "Reenable OLT, add an extra indication\n");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400528 oltIndQ.push(ind);
529 }
530 return status;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000531}
532
533Status EnablePonIf_(uint32_t intf_id) {
534 bcmbal_interface_cfg interface_obj;
535 bcmbal_interface_key interface_key;
536
537 interface_key.intf_id = intf_id;
538 interface_key.intf_type = BCMBAL_INTF_TYPE_PON;
539
540 BCMBAL_CFG_INIT(&interface_obj, interface, interface_key);
Craig Lutgend0bae9b2018-10-18 18:02:07 -0500541
542 BCMBAL_CFG_PROP_GET(&interface_obj, interface, admin_state);
543 bcmos_errno err = bcmbal_cfg_get(DEFAULT_ATERM_ID, &(interface_obj.hdr));
544 if (err == BCM_ERR_OK && interface_obj.data.admin_state == BCMBAL_STATE_UP) {
545 BCM_LOG(DEBUG, openolt_log_id, "PON interface: %d already enabled\n", intf_id);
546 return Status::OK;
547 }
548
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000549 BCMBAL_CFG_PROP_SET(&interface_obj, interface, admin_state, BCMBAL_STATE_UP);
550
Craig Lutgend0bae9b2018-10-18 18:02:07 -0500551 err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(interface_obj.hdr));
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400552 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400553 BCM_LOG(ERROR, openolt_log_id, "Failed to enable PON interface: %d\n", intf_id);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400554 return bcm_to_grpc_err(err, "Failed to enable PON interface");
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000555 }
556
557 return Status::OK;
558}
559
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400560Status DisableUplinkIf_(uint32_t intf_id) {
561 bcmbal_interface_cfg interface_obj;
562 bcmbal_interface_key interface_key;
563
564 interface_key.intf_id = intf_id;
565 interface_key.intf_type = BCMBAL_INTF_TYPE_NNI;
566
567 BCMBAL_CFG_INIT(&interface_obj, interface, interface_key);
568 BCMBAL_CFG_PROP_SET(&interface_obj, interface, admin_state, BCMBAL_STATE_DOWN);
569
570 bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(interface_obj.hdr));
571 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400572 BCM_LOG(ERROR, openolt_log_id, "Failed to disable Uplink interface: %d\n", intf_id);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400573 return bcm_to_grpc_err(err, "Failed to disable Uplink interface");
574 }
575
576 return Status::OK;
577}
578
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500579Status ProbeDeviceCapabilities_() {
580 bcmbal_access_terminal_cfg acc_term_obj;
581 bcmbal_access_terminal_key key = { };
582
583 key.access_term_id = DEFAULT_ATERM_ID;
584 BCMBAL_CFG_INIT(&acc_term_obj, access_terminal, key);
585 BCMBAL_CFG_PROP_GET(&acc_term_obj, access_terminal, admin_state);
586 BCMBAL_CFG_PROP_GET(&acc_term_obj, access_terminal, oper_status);
587 BCMBAL_CFG_PROP_GET(&acc_term_obj, access_terminal, topology);
588 BCMBAL_CFG_PROP_GET(&acc_term_obj, access_terminal, sw_version);
589 BCMBAL_CFG_PROP_GET(&acc_term_obj, access_terminal, conn_id);
590 bcmos_errno err = bcmbal_cfg_get(DEFAULT_ATERM_ID, &(acc_term_obj.hdr));
591 if (err) {
592 BCM_LOG(ERROR, openolt_log_id, "Failed to query OLT\n");
593 return bcm_to_grpc_err(err, "Failed to query OLT");
594 }
595
596 BCM_LOG(INFO, openolt_log_id, "OLT capabilitites, admin_state: %s oper_state: %s\n",
597 acc_term_obj.data.admin_state == BCMBAL_STATE_UP ? "up" : "down",
598 acc_term_obj.data.oper_status == BCMBAL_STATUS_UP ? "up" : "down");
599
600 std::string bal_version;
601 bal_version += std::to_string(acc_term_obj.data.sw_version.major_rev)
602 + "." + std::to_string(acc_term_obj.data.sw_version.minor_rev)
603 + "." + std::to_string(acc_term_obj.data.sw_version.release_rev);
604 firmware_version = "BAL." + bal_version + "__" + firmware_version;
605
606 BCM_LOG(INFO, openolt_log_id, "--------------- version %s object model: %d\n", bal_version.c_str(),
607 acc_term_obj.data.sw_version.om_version);
608
609 BCM_LOG(INFO, openolt_log_id, "--------------- topology nni:%d pon:%d dev:%d ppd:%d family: %d:%d\n",
610 acc_term_obj.data.topology.num_of_nni_ports,
611 acc_term_obj.data.topology.num_of_pon_ports,
612 acc_term_obj.data.topology.num_of_mac_devs,
613 acc_term_obj.data.topology.num_of_pons_per_mac_dev,
614 acc_term_obj.data.topology.pon_family,
615 acc_term_obj.data.topology.pon_sub_family
616 );
617
618 switch(acc_term_obj.data.topology.pon_sub_family)
619 {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500620 case BCMBAL_PON_SUB_FAMILY_GPON: board_technology = "gpon"; break;
621 case BCMBAL_PON_SUB_FAMILY_XGS: board_technology = "xgspon"; break;
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500622 }
623
624 num_of_nni_ports = acc_term_obj.data.topology.num_of_nni_ports;
625 num_of_pon_ports = acc_term_obj.data.topology.num_of_pon_ports;
626
Craig Lutgenb2601f02018-10-23 13:04:31 -0500627 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 -0500628
629 return Status::OK;
630}
631
632Status ProbePonIfTechnology_() {
633 // Probe maximum extent possible as configured into BAL driver to determine
634 // which are active in the current BAL topology. And for those
635 // that are active, determine each port's access technology, i.e. "gpon" or "xgspon".
636 for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
637 bcmbal_interface_cfg interface_obj;
638 bcmbal_interface_key interface_key;
639
640 interface_key.intf_id = intf_id;
641 interface_key.intf_type = BCMBAL_INTF_TYPE_PON;
642
643 BCMBAL_CFG_INIT(&interface_obj, interface, interface_key);
644 BCMBAL_CFG_PROP_GET(&interface_obj, interface, admin_state);
645 BCMBAL_CFG_PROP_GET(&interface_obj, interface, transceiver_type);
646
647 bcmos_errno err = bcmbal_cfg_get(DEFAULT_ATERM_ID, &(interface_obj.hdr));
648 if (err != BCM_ERR_OK) {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500649 intf_technologies[intf_id] = UNKNOWN_TECH;
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500650 if(err != BCM_ERR_RANGE) BCM_LOG(ERROR, openolt_log_id, "Failed to get PON config: %d\n", intf_id);
651 }
652 else {
653 switch(interface_obj.data.transceiver_type) {
654 case BCMBAL_TRX_TYPE_GPON_SPS_43_48:
655 case BCMBAL_TRX_TYPE_GPON_SPS_SOG_4321:
656 case BCMBAL_TRX_TYPE_GPON_LTE_3680_M:
657 case BCMBAL_TRX_TYPE_GPON_SOURCE_PHOTONICS:
658 case BCMBAL_TRX_TYPE_GPON_LTE_3680_P:
Craig Lutgenb2601f02018-10-23 13:04:31 -0500659 intf_technologies[intf_id] = "gpon";
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500660 break;
661 default:
Craig Lutgenb2601f02018-10-23 13:04:31 -0500662 intf_technologies[intf_id] = "xgspon";
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500663 break;
664 }
Craig Lutgenb2601f02018-10-23 13:04:31 -0500665 BCM_LOG(INFO, openolt_log_id, "PON intf_id: %d intf_technologies: %d:%s\n", intf_id,
666 interface_obj.data.transceiver_type, intf_technologies[intf_id].c_str());
667
668 if (board_technology != UNKNOWN_TECH) {
669 board_technology = intf_technologies[intf_id];
670 } else if (board_technology != MIXED_TECH && board_technology != intf_technologies[intf_id]) {
671 intf_technologies[intf_id] = MIXED_TECH;
672 }
673
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500674 }
675 }
676
677 return Status::OK;
678}
679
680unsigned NumNniIf_() {return num_of_nni_ports;}
681unsigned NumPonIf_() {return num_of_pon_ports;}
682
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400683Status EnableUplinkIf_(uint32_t intf_id) {
684 bcmbal_interface_cfg interface_obj;
685 bcmbal_interface_key interface_key;
686
687 interface_key.intf_id = intf_id;
688 interface_key.intf_type = BCMBAL_INTF_TYPE_NNI;
689
690 BCMBAL_CFG_INIT(&interface_obj, interface, interface_key);
Craig Lutgend0bae9b2018-10-18 18:02:07 -0500691
692 BCMBAL_CFG_PROP_GET(&interface_obj, interface, admin_state);
693 bcmos_errno err = bcmbal_cfg_get(DEFAULT_ATERM_ID, &(interface_obj.hdr));
694 if (err == BCM_ERR_OK && interface_obj.data.admin_state == BCMBAL_STATE_UP) {
695 BCM_LOG(DEBUG, openolt_log_id, "Uplink interface: %d already enabled\n", intf_id);
696 return Status::OK;
697 }
698
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400699 BCMBAL_CFG_PROP_SET(&interface_obj, interface, admin_state, BCMBAL_STATE_UP);
700
Craig Lutgend0bae9b2018-10-18 18:02:07 -0500701 err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(interface_obj.hdr));
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400702 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400703 BCM_LOG(ERROR, openolt_log_id, "Failed to enable Uplink interface: %d\n", intf_id);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400704 return bcm_to_grpc_err(err, "Failed to enable Uplink interface");
705 }
706
707 return Status::OK;
708}
709
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -0400710Status DisablePonIf_(uint32_t intf_id) {
711 bcmbal_interface_cfg interface_obj;
712 bcmbal_interface_key interface_key;
713
714 interface_key.intf_id = intf_id;
715 interface_key.intf_type = BCMBAL_INTF_TYPE_PON;
716
717 BCMBAL_CFG_INIT(&interface_obj, interface, interface_key);
718 BCMBAL_CFG_PROP_SET(&interface_obj, interface, admin_state, BCMBAL_STATE_DOWN);
719
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400720 bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(interface_obj.hdr));
721 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400722 BCM_LOG(ERROR, openolt_log_id, "Failed to disable PON interface: %d\n", intf_id);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400723 return bcm_to_grpc_err(err, "Failed to disable PON interface");
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -0400724 }
725
726 return Status::OK;
727}
728
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000729Status ActivateOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700730 const char *vendor_id, const char *vendor_specific, uint32_t pir) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000731
732 bcmbal_subscriber_terminal_cfg sub_term_obj = {};
733 bcmbal_subscriber_terminal_key subs_terminal_key;
734 bcmbal_serial_number serial_num = {};
735 bcmbal_registration_id registration_id = {};
736
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700737 BCM_LOG(INFO, openolt_log_id, "Enabling ONU %d on PON %d : vendor id %s, vendor specific %s, pir %d\n",
738 onu_id, intf_id, vendor_id, vendor_specific_to_str(vendor_specific).c_str(), pir);
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000739
740 subs_terminal_key.sub_term_id = onu_id;
741 subs_terminal_key.intf_id = intf_id;
742 BCMBAL_CFG_INIT(&sub_term_obj, subscriber_terminal, subs_terminal_key);
743
744 memcpy(serial_num.vendor_id, vendor_id, 4);
745 memcpy(serial_num.vendor_specific, vendor_specific, 4);
746 BCMBAL_CFG_PROP_SET(&sub_term_obj, subscriber_terminal, serial_number, serial_num);
747
Shad Ansaricb004c52018-05-30 18:07:23 +0000748#if 0
749 // Commenting out as this is causing issues with onu activation
750 // with BAL 2.6 (Broadcom CS5248819).
751
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000752 // FIXME - Use a default (all zeros) registration id.
753 memset(registration_id.arr, 0, sizeof(registration_id.arr));
754 BCMBAL_CFG_PROP_SET(&sub_term_obj, subscriber_terminal, registration_id, registration_id);
Shad Ansaricb004c52018-05-30 18:07:23 +0000755#endif
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000756
757 BCMBAL_CFG_PROP_SET(&sub_term_obj, subscriber_terminal, admin_state, BCMBAL_STATE_UP);
758
Nicolas Palpacuer73222e02018-07-16 12:20:26 -0400759 bcmos_errno err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(sub_term_obj.hdr));
760 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400761 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 -0400762 return bcm_to_grpc_err(err, "Failed to enable ONU");
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000763 }
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700764 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000765}
766
Jonathan Davis70c21812018-07-19 15:32:10 -0400767Status DeactivateOnu_(uint32_t intf_id, uint32_t onu_id,
768 const char *vendor_id, const char *vendor_specific) {
769
Jonathan Davis70c21812018-07-19 15:32:10 -0400770 bcmbal_subscriber_terminal_cfg sub_term_obj = {};
771 bcmbal_subscriber_terminal_key subs_terminal_key;
772
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400773 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 -0500774 onu_id, intf_id, vendor_id, vendor_specific_to_str(vendor_specific).c_str());
Jonathan Davis70c21812018-07-19 15:32:10 -0400775
776 subs_terminal_key.sub_term_id = onu_id;
777 subs_terminal_key.intf_id = intf_id;
778 BCMBAL_CFG_INIT(&sub_term_obj, subscriber_terminal, subs_terminal_key);
779
780 BCMBAL_CFG_PROP_SET(&sub_term_obj, subscriber_terminal, admin_state, BCMBAL_STATE_DOWN);
781
782 if (bcmbal_cfg_set(DEFAULT_ATERM_ID, &(sub_term_obj.hdr))) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400783 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 -0400784 return Status(grpc::StatusCode::INTERNAL, "Failed to deactivate ONU");
785 }
786
787 return Status::OK;
788}
789
790Status DeleteOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700791 const char *vendor_id, const char *vendor_specific) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -0400792
Craig Lutgend0bae9b2018-10-18 18:02:07 -0500793 BCM_LOG(INFO, openolt_log_id, "DeleteOnu ONU %d on PON %d : vendor id %s, vendor specific %s\n",
794 onu_id, intf_id, vendor_id, vendor_specific_to_str(vendor_specific).c_str());
795
Nicolas Palpacuer9c352082018-08-14 16:37:14 -0400796 // Need to deactivate before removing it (BAL rules)
797
798 DeactivateOnu_(intf_id, onu_id, vendor_id, vendor_specific);
799 // Sleep to allow the state to propagate
800 // We need the subscriber terminal object to be admin down before removal
801 // Without sleep the race condition is lost by ~ 20 ms
802 std::this_thread::sleep_for(std::chrono::milliseconds(100));
803
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700804 // TODO: Delete the schedulers and queues.
Nicolas Palpacuer9c352082018-08-14 16:37:14 -0400805
Jonathan Davis70c21812018-07-19 15:32:10 -0400806 bcmos_errno err = BCM_ERR_OK;
807 bcmbal_subscriber_terminal_cfg cfg;
808 bcmbal_subscriber_terminal_key key = { };
809
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400810 BCM_LOG(INFO, openolt_log_id, "Processing subscriber terminal cfg clear for sub_term_id %d and intf_id %d\n",
811 onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -0400812
813 key.sub_term_id = onu_id ;
814 key.intf_id = intf_id ;
815
816 if (0 == key.sub_term_id)
817 {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800818 BCM_LOG(INFO, openolt_log_id,"Invalid Key to handle subscriber terminal clear subscriber_terminal_id %d, \
819 Interface ID %d\n", onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -0400820 return Status(grpc::StatusCode::INTERNAL, "Failed to delete ONU");
821 }
822
823 BCMBAL_CFG_INIT(&cfg, subscriber_terminal, key);
824
825 err = bcmbal_cfg_clear(DEFAULT_ATERM_ID, &cfg.hdr);
826 if (err != BCM_ERR_OK)
827 {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400828 BCM_LOG(ERROR, openolt_log_id, "Failed to clear information for BAL subscriber_terminal_id %d, Interface ID %d\n",
829 onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -0400830 return Status(grpc::StatusCode::INTERNAL, "Failed to delete ONU");
831 }
832
833 return Status::OK;;
834}
835
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000836#define MAX_CHAR_LENGTH 20
837#define MAX_OMCI_MSG_LENGTH 44
838Status OmciMsgOut_(uint32_t intf_id, uint32_t onu_id, const std::string pkt) {
839 bcmbal_u8_list_u32_max_2048 buf; /* A structure with a msg pointer and length value */
840 bcmos_errno err = BCM_ERR_OK;
841
842 /* The destination of the OMCI packet is a registered ONU on the OLT PON interface */
843 bcmbal_dest proxy_pkt_dest;
844
845 proxy_pkt_dest.type = BCMBAL_DEST_TYPE_ITU_OMCI_CHANNEL;
846 proxy_pkt_dest.u.itu_omci_channel.sub_term_id = onu_id;
847 proxy_pkt_dest.u.itu_omci_channel.intf_id = intf_id;
848
849 // ???
850 if ((pkt.size()/2) > MAX_OMCI_MSG_LENGTH) {
851 buf.len = MAX_OMCI_MSG_LENGTH;
852 } else {
853 buf.len = pkt.size()/2;
854 }
855
856 /* Send the OMCI packet using the BAL remote proxy API */
857 uint16_t idx1 = 0;
858 uint16_t idx2 = 0;
859 uint8_t arraySend[buf.len];
860 char str1[MAX_CHAR_LENGTH];
861 char str2[MAX_CHAR_LENGTH];
862 memset(&arraySend, 0, buf.len);
863
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000864 for (idx1=0,idx2=0; idx1<((buf.len)*2); idx1++,idx2++) {
865 sprintf(str1,"%c", pkt[idx1]);
866 sprintf(str2,"%c", pkt[++idx1]);
867 strcat(str1,str2);
868 arraySend[idx2] = strtol(str1, NULL, 16);
869 }
870
871 buf.val = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
872 memcpy(buf.val, (uint8_t *)arraySend, buf.len);
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000873
874 err = bcmbal_pkt_send(0, proxy_pkt_dest, (const char *)(buf.val), buf.len);
875
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400876 if (err) {
877 BCM_LOG(ERROR, omci_log_id, "Error sending OMCI message to ONU %d on PON %d\n", onu_id, intf_id);
878 } else {
879 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 -0500880 buf.len, onu_id, intf_id, pkt.c_str());
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400881 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000882
883 free(buf.val);
884
885 return Status::OK;
886}
887
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800888Status 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 +0000889 bcmos_errno err = BCM_ERR_OK;
890 bcmbal_dest proxy_pkt_dest;
891 bcmbal_u8_list_u32_max_2048 buf;
892
Craig Lutgen967a1d02018-11-27 10:41:51 -0600893 if (port_no > 0) {
894 bool found = false;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800895 if (gemport_id == 0) {
896 bcmos_fastlock_lock(&data_lock);
897 // Map the port_no to one of the flows that owns it to find a gemport_id for that flow.
898 // Pick any flow that is mapped with the same port_no.
899 std::map<uint32_t, std::set<uint32_t> >::const_iterator it = port_to_flows.find(port_no);
900 if (it != port_to_flows.end() && !it->second.empty()) {
901 uint32_t flow_id = *(it->second.begin()); // Pick any flow_id out of the bag set
902 std::map<uint32_t, uint32_t>::const_iterator fit = flowid_to_gemport.find(flow_id);
903 if (fit != flowid_to_gemport.end()) {
904 found = true;
905 gemport_id = fit->second;
906 }
Craig Lutgen967a1d02018-11-27 10:41:51 -0600907 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800908 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600909
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800910 if (!found) {
911 BCM_LOG(ERROR, openolt_log_id, "Packet out failed to find destination for ONU %d port_no %u on PON %d\n",
912 onu_id, port_no, intf_id);
913 return grpc::Status(grpc::StatusCode::NOT_FOUND, "no flow for port_no");
914 }
915 BCM_LOG(INFO, openolt_log_id, "Gem port %u found for ONU %d port_no %u on PON %d\n",
916 gemport_id, onu_id, port_no, intf_id);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600917 }
918
919 proxy_pkt_dest.type = BCMBAL_DEST_TYPE_SVC_PORT;
920 proxy_pkt_dest.u.svc_port.svc_port_id = gemport_id;
921 proxy_pkt_dest.u.svc_port.intf_id = intf_id;
922 BCM_LOG(INFO, openolt_log_id, "Packet out of length %d sent to gemport %d on pon %d port_no %u\n",
923 pkt.size(), gemport_id, intf_id, port_no);
924 }
925 else {
926 proxy_pkt_dest.type = BCMBAL_DEST_TYPE_SUB_TERM,
927 proxy_pkt_dest.u.sub_term.sub_term_id = onu_id;
928 proxy_pkt_dest.u.sub_term.intf_id = intf_id;
929 BCM_LOG(INFO, openolt_log_id, "Packet out of length %d sent to onu %d on pon %d\n",
930 pkt.size(), onu_id, intf_id);
931 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000932
933 buf.len = pkt.size();
934 buf.val = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
935 memcpy(buf.val, (uint8_t *)pkt.data(), buf.len);
936
937 err = bcmbal_pkt_send(0, proxy_pkt_dest, (const char *)(buf.val), buf.len);
938
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000939 free(buf.val);
940
941 return Status::OK;
942}
943
Nicolas Palpacuerb78def42018-06-07 12:55:26 -0400944Status UplinkPacketOut_(uint32_t intf_id, const std::string pkt) {
945 bcmos_errno err = BCM_ERR_OK;
946 bcmbal_dest proxy_pkt_dest;
947 bcmbal_u8_list_u32_max_2048 buf;
948
949 proxy_pkt_dest.type = BCMBAL_DEST_TYPE_NNI,
950 proxy_pkt_dest.u.nni.intf_id = intf_id;
951
952 buf.len = pkt.size();
953 buf.val = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
954 memcpy(buf.val, (uint8_t *)pkt.data(), buf.len);
955
956 err = bcmbal_pkt_send(0, proxy_pkt_dest, (const char *)(buf.val), buf.len);
957
Nicolas Palpacuer967438f2018-09-07 14:41:54 -0400958 BCM_LOG(INFO, openolt_log_id, "Packet out of length %d sent through uplink port %d\n",
959 buf.len, intf_id);
Nicolas Palpacuerb78def42018-06-07 12:55:26 -0400960
961 free(buf.val);
962
963 return Status::OK;
964}
965
Craig Lutgen967a1d02018-11-27 10:41:51 -0600966uint32_t GetPortNum_(uint32_t flow_id)
967{
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800968 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600969 uint32_t port_no = 0;
970 std::map<uint32_t, uint32_t >::const_iterator it = flowid_to_port.find(flow_id);
971 if (it != flowid_to_port.end()) {
972 port_no = it->second;
973 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800974 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600975 return port_no;
976}
977
978Status 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 +0000979 uint32_t flow_id, const std::string flow_type,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700980 int32_t alloc_id, int32_t network_intf_id,
981 int32_t gemport_id, const ::openolt::Classifier& classifier,
Craig Lutgen967a1d02018-11-27 10:41:51 -0600982 const ::openolt::Action& action, int32_t priority_value, uint64_t cookie) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000983 bcmos_errno err;
984 bcmbal_flow_cfg cfg;
985 bcmbal_flow_key key = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800986 int32_t o_vid = -1;
987 bool single_tag = false;
988 uint32_t ether_type = 0;
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000989
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800990 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, \
991 gemport_id %d, network_intf_id %d, cookie %llu\n", \
992 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 +0000993
994 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800995 if (flow_type.compare(upstream) == 0 ) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000996 key.flow_type = BCMBAL_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800997 } else if (flow_type.compare(downstream) == 0) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +0000998 key.flow_type = BCMBAL_FLOW_TYPE_DOWNSTREAM;
999 } else {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001000 BCM_LOG(WARNING, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001001 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001002 }
1003
1004 BCMBAL_CFG_INIT(&cfg, flow, key);
1005
1006 BCMBAL_CFG_PROP_SET(&cfg, flow, admin_state, BCMBAL_STATE_UP);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001007 BCMBAL_CFG_PROP_SET(&cfg, flow, cookie, cookie);
1008
Shad Ansari39739bc2018-09-13 21:38:37 +00001009 if (access_intf_id >= 0) {
1010 BCMBAL_CFG_PROP_SET(&cfg, flow, access_int_id, access_intf_id);
1011 }
1012 if (network_intf_id >= 0) {
1013 BCMBAL_CFG_PROP_SET(&cfg, flow, network_int_id, network_intf_id);
1014 }
1015 if (onu_id >= 0) {
1016 BCMBAL_CFG_PROP_SET(&cfg, flow, sub_term_id, onu_id);
1017 }
1018 if (gemport_id >= 0) {
1019 BCMBAL_CFG_PROP_SET(&cfg, flow, svc_port_id, gemport_id);
1020 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001021 if (gemport_id >= 0 && port_no != 0) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001022 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001023 if (key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM) {
1024 port_to_flows[port_no].insert(key.flow_id);
1025 flowid_to_gemport[key.flow_id] = gemport_id;
1026 }
1027 else
1028 {
1029 flowid_to_port[key.flow_id] = port_no;
1030 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001031 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001032 }
Shad Ansari39739bc2018-09-13 21:38:37 +00001033 if (priority_value >= 0) {
1034 BCMBAL_CFG_PROP_SET(&cfg, flow, priority, priority_value);
1035 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001036
1037 {
1038 bcmbal_classifier val = { };
1039
1040 if (classifier.o_tpid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001041 BCM_LOG(DEBUG, openolt_log_id, "classify o_tpid 0x%04x\n", classifier.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001042 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_tpid, classifier.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001043 }
1044
1045 if (classifier.o_vid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001046 BCM_LOG(DEBUG, openolt_log_id, "classify o_vid %d\n", classifier.o_vid());
Craig Lutgen19512312018-11-02 10:14:46 -05001047 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_vid, classifier.o_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001048 }
1049
1050 if (classifier.i_tpid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001051 BCM_LOG(DEBUG, openolt_log_id, "classify i_tpid 0x%04x\n", classifier.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001052 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, i_tpid, classifier.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001053 }
1054
1055 if (classifier.i_vid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001056 BCM_LOG(DEBUG, openolt_log_id, "classify i_vid %d\n", classifier.i_vid());
Craig Lutgen19512312018-11-02 10:14:46 -05001057 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, i_vid, classifier.i_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001058 }
1059
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001060 if (classifier.eth_type()) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001061 ether_type = classifier.eth_type();
Craig Lutgenecd353a2018-12-12 22:33:17 -06001062 BCM_LOG(DEBUG, openolt_log_id, "classify ether_type 0x%04x\n", classifier.eth_type());
Craig Lutgen19512312018-11-02 10:14:46 -05001063 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, ether_type, classifier.eth_type());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001064 }
1065
1066 /*
1067 if (classifier.dst_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001068 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_mac, classifier.dst_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001069 }
1070
1071 if (classifier.src_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001072 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_mac, classifier.src_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001073 }
1074 */
1075
1076 if (classifier.ip_proto()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001077 BCM_LOG(DEBUG, openolt_log_id, "classify ip_proto %d\n", classifier.ip_proto());
Craig Lutgen19512312018-11-02 10:14:46 -05001078 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, ip_proto, classifier.ip_proto());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001079 }
1080
1081 /*
1082 if (classifier.dst_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001083 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_ip, classifier.dst_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001084 }
1085
1086 if (classifier.src_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05001087 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_ip, classifier.src_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001088 }
1089 */
1090
1091 if (classifier.src_port()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001092 BCM_LOG(DEBUG, openolt_log_id, "classify src_port %d\n", classifier.src_port());
Craig Lutgen19512312018-11-02 10:14:46 -05001093 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_port, classifier.src_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001094 }
1095
1096 if (classifier.dst_port()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001097 BCM_LOG(DEBUG, openolt_log_id, "classify dst_port %d\n", classifier.dst_port());
Craig Lutgen19512312018-11-02 10:14:46 -05001098 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_port, classifier.dst_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001099 }
1100
1101 if (!classifier.pkt_tag_type().empty()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001102 BCM_LOG(DEBUG, openolt_log_id, "classify tag_type %s\n", classifier.pkt_tag_type().c_str());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001103 if (classifier.pkt_tag_type().compare("untagged") == 0) {
Craig Lutgen19512312018-11-02 10:14:46 -05001104 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, pkt_tag_type, BCMBAL_PKT_TAG_TYPE_UNTAGGED);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001105 } else if (classifier.pkt_tag_type().compare("single_tag") == 0) {
Craig Lutgen19512312018-11-02 10:14:46 -05001106 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, pkt_tag_type, BCMBAL_PKT_TAG_TYPE_SINGLE_TAG);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001107 single_tag = true;
1108
1109 BCM_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1110 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_pbits, classifier.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001111 } else if (classifier.pkt_tag_type().compare("double_tag") == 0) {
Craig Lutgen19512312018-11-02 10:14:46 -05001112 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, pkt_tag_type, BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001113
1114 BCM_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
1115 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_pbits, classifier.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001116 }
1117 }
1118
1119 BCMBAL_CFG_PROP_SET(&cfg, flow, classifier, val);
1120 }
1121
1122 {
1123 bcmbal_action val = { };
1124
1125 const ::openolt::ActionCmd& cmd = action.cmd();
1126
1127 if (cmd.add_outer_tag()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001128 BCM_LOG(INFO, openolt_log_id, "action add o_tag\n");
Craig Lutgen19512312018-11-02 10:14:46 -05001129 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, cmds_bitmask, BCMBAL_ACTION_CMD_ID_ADD_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001130 }
1131
1132 if (cmd.remove_outer_tag()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001133 BCM_LOG(INFO, openolt_log_id, "action pop o_tag\n");
Craig Lutgen19512312018-11-02 10:14:46 -05001134 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, cmds_bitmask, BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001135 }
1136
1137 if (cmd.trap_to_host()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001138 BCM_LOG(INFO, openolt_log_id, "action trap-to-host\n");
Craig Lutgen19512312018-11-02 10:14:46 -05001139 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, cmds_bitmask, BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001140 }
1141
1142 if (action.o_vid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001143 BCM_LOG(INFO, openolt_log_id, "action o_vid=%d\n", action.o_vid());
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001144 o_vid = action.o_vid();
Craig Lutgen19512312018-11-02 10:14:46 -05001145 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, o_vid, action.o_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001146 }
1147
1148 if (action.o_pbits()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001149 BCM_LOG(INFO, openolt_log_id, "action o_pbits=0x%x\n", action.o_pbits());
Craig Lutgen19512312018-11-02 10:14:46 -05001150 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, o_pbits, action.o_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001151 }
1152
1153 if (action.o_tpid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001154 BCM_LOG(INFO, openolt_log_id, "action o_tpid=0x%04x\n", action.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001155 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, o_tpid, action.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001156 }
1157
1158 if (action.i_vid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001159 BCM_LOG(INFO, openolt_log_id, "action i_vid=%d\n", action.i_vid());
Craig Lutgen19512312018-11-02 10:14:46 -05001160 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, i_vid, action.i_vid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001161 }
1162
1163 if (action.i_pbits()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001164 BCM_LOG(DEBUG, openolt_log_id, "action i_pbits=0x%x\n", action.i_pbits());
Craig Lutgen19512312018-11-02 10:14:46 -05001165 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, i_pbits, action.i_pbits());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001166 }
1167
1168 if (action.i_tpid()) {
Craig Lutgenecd353a2018-12-12 22:33:17 -06001169 BCM_LOG(DEBUG, openolt_log_id, "action i_tpid=0x%04x\n", action.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05001170 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, i_tpid, action.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001171 }
1172
1173 BCMBAL_CFG_PROP_SET(&cfg, flow, action, val);
1174 }
1175
Shad Ansari39739bc2018-09-13 21:38:37 +00001176 if ((access_intf_id >= 0) && (onu_id >= 0)) {
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001177
Shad Ansari39739bc2018-09-13 21:38:37 +00001178 if (key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM) {
1179 bcmbal_tm_queue_ref val = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001180 if (single_tag && ether_type == EAP_ETHER_TYPE) {
1181 val.sched_id = get_default_tm_sched_id(access_intf_id, downstream);
1182 val.queue_id = 0;
1183
1184 } else {
1185 val.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, downstream); // Subscriber Scheduler
1186 val.queue_id = get_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, downstream);
1187 }
Girish Gowdruf26cf882019-05-01 23:47:58 -07001188 BCM_LOG(INFO, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d\n", \
1189 downstream.c_str(), val.queue_id, val.sched_id);
Shad Ansari39739bc2018-09-13 21:38:37 +00001190 BCMBAL_CFG_PROP_SET(&cfg, flow, queue, val);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001191 } else if (key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM) {
1192 bcmbal_tm_sched_id val1;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001193 val1 = get_tm_sched_id(access_intf_id, onu_id, uni_id, upstream); // DBA Scheduler ID
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001194 BCMBAL_CFG_PROP_SET(&cfg, flow, dba_tm_sched_id, val1);
1195
1196 bcmbal_tm_queue_ref val2 = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001197 val2.sched_id = get_default_tm_sched_id(network_intf_id, upstream); // NNI Scheduler ID
Girish Gowdrue1b5d562019-04-18 22:43:32 -07001198 val2.queue_id = get_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, upstream); // Queue on NNI
Girish Gowdruf26cf882019-05-01 23:47:58 -07001199 BCM_LOG(INFO, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d\n", \
1200 upstream.c_str(), val2.queue_id, val2.sched_id);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001201 BCMBAL_CFG_PROP_SET(&cfg, flow, queue, val2);
Shad Ansari39739bc2018-09-13 21:38:37 +00001202 }
Shad Ansari06101952018-07-25 00:22:09 +00001203 }
1204
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001205 err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(cfg.hdr));
1206 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001207 BCM_LOG(ERROR, openolt_log_id, "Flow add failed\n");
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001208 return bcm_to_grpc_err(err, "flow add failed");
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001209 }
1210
Nicolas Palpacuer6a63ea92018-09-05 17:21:37 -04001211 // register_new_flow(key);
Nicolas Palpacuer0f19b1a2018-06-07 17:29:31 -04001212
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001213 return Status::OK;
1214}
1215
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001216Status FlowRemove_(uint32_t flow_id, const std::string flow_type) {
1217
1218 bcmbal_flow_cfg cfg;
1219 bcmbal_flow_key key = { };
1220
1221 key.flow_id = (bcmbal_flow_id) flow_id;
1222 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001223 if (flow_type.compare(upstream) == 0 ) {
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001224 key.flow_type = BCMBAL_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001225 } else if (flow_type.compare(downstream) == 0) {
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001226 key.flow_type = BCMBAL_FLOW_TYPE_DOWNSTREAM;
1227 } else {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001228 BCM_LOG(WARNING, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001229 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
1230 }
1231
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001232 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001233 uint32_t port_no = flowid_to_port[key.flow_id];
1234 if (key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM) {
1235 flowid_to_gemport.erase(key.flow_id);
1236 port_to_flows[port_no].erase(key.flow_id);
1237 if (port_to_flows[port_no].empty()) port_to_flows.erase(port_no);
1238 }
1239 else
1240 {
1241 flowid_to_port.erase(key.flow_id);
1242 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001243 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001244
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001245 BCMBAL_CFG_INIT(&cfg, flow, key);
1246
1247
1248 bcmos_errno err = bcmbal_cfg_clear(DEFAULT_ATERM_ID, &cfg.hdr);
1249 if (err) {
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001250 BCM_LOG(ERROR, openolt_log_id, "Error %d while removing flow %d, %s\n",
1251 err, flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001252 return Status(grpc::StatusCode::INTERNAL, "Failed to remove flow");
1253 }
1254
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04001255 BCM_LOG(INFO, openolt_log_id, "Flow %d, %s removed\n", flow_id, flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04001256 return Status::OK;
1257}
1258
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001259bcmos_errno CreateSched(std::string direction, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t port_no,
1260 uint32_t alloc_id, tech_profile::AdditionalBW additional_bw, uint32_t weight, uint32_t priority,
1261 tech_profile::SchedulingPolicy sched_policy, tech_profile::TrafficShapingInfo tf_sh_info) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001262
1263 bcmos_errno err;
1264
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001265 if (direction == downstream) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001266
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001267 bcmbal_tm_sched_cfg cfg;
1268 bcmbal_tm_sched_key key = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001269 key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
1270 key.dir = BCMBAL_TM_SCHED_DIR_DS;
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001271
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001272 BCMBAL_CFG_INIT(&cfg, tm_sched, key);
1273
1274 {
1275 // bcmbal_tm_sched_owner
1276 // In downstream it is sub_term scheduler
1277 bcmbal_tm_sched_owner tm_sched_owner = { };
1278 tm_sched_owner.type = BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM;
1279 tm_sched_owner.u.sub_term.intf_id = intf_id;
1280 tm_sched_owner.u.sub_term.sub_term_id = onu_id;
1281 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, owner, tm_sched_owner);
1282
1283 // bcmbal_tm_sched_type
1284 // set the deafult policy to strict priority
1285 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, sched_type, BCMBAL_TM_SCHED_TYPE_SP);
1286
1287 // bcmbal_tm_sched_parent
1288 // The parent for the sub_term scheduler is the PON scheduler in the downstream
1289 bcmbal_tm_sched_parent tm_sched_parent = { };
1290 tm_sched_parent.presence_mask |= (BCMBAL_TM_SCHED_PARENT_ID_SCHED_ID);
1291 tm_sched_parent.sched_id = get_default_tm_sched_id(intf_id, downstream);
1292 tm_sched_parent.presence_mask |= (BCMBAL_TM_SCHED_PARENT_ID_PRIORITY);
1293 tm_sched_parent.priority = 1; // TODO: Hardcoded priority as 1
1294 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, sched_parent, tm_sched_parent);
1295
1296 // num_priorities: Max number of strict priority scheduling elements
1297 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, num_priorities, 8); // TODO: hardcoded 8 priorities.
1298
1299 // bcmbal_tm_shaping
1300 if (tf_sh_info.cir() >= 0 && tf_sh_info.pir() > 0) {
1301 bcmbal_tm_shaping rate = {};
1302 uint32_t cir = tf_sh_info.cir();
1303 uint32_t pir = tf_sh_info.pir();
1304 uint32_t burst = tf_sh_info.pbs();
1305 BCM_LOG(INFO, openolt_log_id, "applying traffic shaping in DL cir=%u, pir=%u, burst=%u\n",
1306 cir, pir, burst);
1307 rate.presence_mask = BCMBAL_TM_SHAPING_ID_NONE;
1308 rate.presence_mask |= BCMBAL_TM_SHAPING_ID_PIR;
1309 rate.presence_mask |= BCMBAL_TM_SHAPING_ID_BURST;
1310 // FIXME: Setting CIR, results in BAL throwing error 'tm_sched minimum rate is not supported yet'
1311 // rate.cir = cir;
1312 rate.pir = pir;
1313 rate.burst = burst;
1314
Girish Gowdrue1b5d562019-04-18 22:43:32 -07001315 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, rate, rate);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001316 }
1317
1318 // creation_mode
1319 // BCMBAL_CFG_PROP_SET(&cfg, tm_sched, creation_mode, BCMBAL_TM_CREATION_MODE_MANUAL);
1320 }
1321
1322 err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(cfg.hdr));
1323 if (err) {
1324 BCM_LOG(ERROR, openolt_log_id, "Failed to create downstream subscriber scheduler, id %d, intf_id %d, \
1325 onu_id %d, uni_id %d, port_no %u\n", key.id, intf_id, onu_id,uni_id,port_no);
1326 return err;
1327 }
1328 BCM_LOG(INFO, openolt_log_id, "Create downstream subscriber sched, id %d, intf_id %d, onu_id %d, \
1329 uni_id %d, port_no %u\n", key.id,intf_id,onu_id,uni_id,port_no);
1330
1331 } else { //upstream
1332 bcmbal_tm_sched_cfg cfg;
1333 bcmbal_tm_sched_key key = { };
1334
1335 key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001336 key.dir = BCMBAL_TM_SCHED_DIR_US;
1337
1338 BCMBAL_CFG_INIT(&cfg, tm_sched, key);
1339
1340 {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001341 // bcmbal_tm_sched_owner: AGG PORT
1342 bcmbal_tm_sched_owner tm_sched_owner = { };
1343 tm_sched_owner.type = BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT;
1344 tm_sched_owner.u.agg_port.presence_mask |= bcmbal_tm_sched_owner_agg_port_id_all;
1345 tm_sched_owner.u.agg_port.intf_id = intf_id;
1346 tm_sched_owner.u.agg_port.sub_term_id = onu_id;
1347 tm_sched_owner.u.agg_port.agg_port_id = alloc_id;
1348 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, owner, tm_sched_owner);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001349
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001350 // bcmbal_tm_shaping
1351 if (tf_sh_info.cir() >= 0 && tf_sh_info.pir() > 0) {
1352 bcmbal_tm_shaping rate = {};
1353 uint32_t cir = tf_sh_info.cir();
1354 uint32_t pir = tf_sh_info.pir();
1355 uint32_t burst = tf_sh_info.pbs();
1356 BCM_LOG(INFO, openolt_log_id, "applying traffic shaping in UL cir=%u, pir=%u, burst=%u\n",
1357 cir, pir, burst);
1358 rate.presence_mask = BCMBAL_TM_SHAPING_ID_ALL;
1359 rate.cir = cir;
1360 rate.pir = pir;
1361 rate.burst = burst;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001362
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001363 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, rate, rate);
1364 }
Girish Gowdrue075c642019-01-23 04:05:53 -08001365 }
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001366
1367 err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &(cfg.hdr));
1368 if (err) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001369 BCM_LOG(ERROR, openolt_log_id, "Failed to create upstream DBA sched, id %d, intf_id %d, onu_id %d, uni_id %d,\
1370 port_no %u, alloc_id %d\n", key.id, intf_id, onu_id,uni_id,port_no,alloc_id);
1371 return err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001372 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001373 BCM_LOG(INFO, openolt_log_id, "Create upstream DBA sched, id %d, intf_id %d, onu_id %d, uni_id %d, port_no %u, \
1374 alloc_id %d\n", key.id,intf_id,onu_id,uni_id,port_no,alloc_id);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001375 }
1376
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001377 return BCM_ERR_OK;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001378}
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001379
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001380Status CreateTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
1381 uint32_t intf_id = traffic_scheds->intf_id();
1382 uint32_t onu_id = traffic_scheds->onu_id();
1383 uint32_t uni_id = traffic_scheds->uni_id();
1384 uint32_t port_no = traffic_scheds->port_no();
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001385 std::string direction;
1386 unsigned int alloc_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001387 tech_profile::SchedulerConfig sched_config;
1388 tech_profile::AdditionalBW additional_bw;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001389 uint32_t priority;
1390 uint32_t weight;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001391 tech_profile::SchedulingPolicy sched_policy;
1392 tech_profile::TrafficShapingInfo traffic_shaping_info;
1393 bcmos_errno err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001394
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001395 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
1396 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
1397 if (traffic_sched.direction() == tech_profile::Direction::UPSTREAM) {
1398 direction = upstream;
1399 } else if (traffic_sched.direction() == tech_profile::Direction::DOWNSTREAM) {
1400 direction = downstream;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001401 }
1402 else {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001403 BCM_LOG(ERROR, openolt_log_id, "direction-not-supported %d", traffic_sched.direction());
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001404 return Status::CANCELLED;
1405 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001406 alloc_id = traffic_sched.alloc_id();
1407 sched_config = traffic_sched.scheduler();
1408 additional_bw = sched_config.additional_bw();
1409 priority = sched_config.priority();
1410 weight = sched_config.weight();
1411 sched_policy = sched_config.sched_policy();
1412 traffic_shaping_info = traffic_sched.traffic_shaping_info();
1413 err = CreateSched(direction, intf_id, onu_id, uni_id, port_no, alloc_id, additional_bw, weight, priority,
1414 sched_policy, traffic_shaping_info);
1415 if (err) {
1416 return bcm_to_grpc_err(err, "Failed to create scheduler");
1417 }
Girish Gowdru1cdf6ce2018-08-27 02:43:02 -07001418 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001419 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001420}
Jonathan Davis70c21812018-07-19 15:32:10 -04001421
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001422bcmos_errno RemoveSched(int intf_id, int onu_id, int uni_id, std::string direction) {
Jonathan Davis70c21812018-07-19 15:32:10 -04001423
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001424 bcmos_errno err;
Jonathan Davis70c21812018-07-19 15:32:10 -04001425
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001426 bcmbal_tm_sched_cfg tm_cfg_us;
1427 bcmbal_tm_sched_key tm_key_us = { };
Jonathan Davis70c21812018-07-19 15:32:10 -04001428
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001429 if (is_tm_sched_id_present(intf_id, onu_id, uni_id, direction)) {
1430 tm_key_us.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
1431 } else {
1432 BCM_LOG(INFO, openolt_log_id, "schduler not present in %s\n", direction.c_str());
1433 return BCM_ERR_OK;
1434 }
1435 if (direction == upstream) {
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001436 tm_key_us.dir = BCMBAL_TM_SCHED_DIR_US;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001437 } else {
1438 tm_key_us.dir = BCMBAL_TM_SCHED_DIR_DS;
1439 }
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001440
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001441 BCMBAL_CFG_INIT(&tm_cfg_us, tm_sched, tm_key_us);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001442
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001443 err = bcmbal_cfg_clear(DEFAULT_ATERM_ID, &(tm_cfg_us.hdr));
1444 if (err) {
1445 BCM_LOG(ERROR, openolt_log_id, "Failed to remove scheduler sched, direction = %s, id %d, intf_id %d, onu_id %d\n", \
1446 direction.c_str(), tm_key_us.id, intf_id, onu_id);
1447 return err;
1448 }
1449
1450 free_tm_sched_id(intf_id, onu_id, uni_id, direction);
1451
1452 BCM_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, id %d, intf_id %d, onu_id %d\n", \
1453 direction.c_str(), tm_key_us.id, intf_id, onu_id);
1454
1455 return BCM_ERR_OK;
1456}
1457
1458Status RemoveTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
1459 uint32_t intf_id = traffic_scheds->intf_id();
1460 uint32_t onu_id = traffic_scheds->onu_id();
1461 uint32_t uni_id = traffic_scheds->uni_id();
1462 std::string direction;
1463 bcmos_errno err;
1464
1465 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
1466 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
1467 if (traffic_sched.direction() == tech_profile::Direction::UPSTREAM) {
1468 direction = upstream;
1469 } else if (traffic_sched.direction() == tech_profile::Direction::DOWNSTREAM) {
1470 direction = downstream;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001471 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001472 else {
1473 BCM_LOG(ERROR, openolt_log_id, "direction-not-supported %d", traffic_sched.direction());
1474 return Status::CANCELLED;
1475 }
1476 err = RemoveSched(intf_id, onu_id, uni_id, direction);
1477 if (err) {
1478 return bcm_to_grpc_err(err, "error-removing-traffic-scheduler");
1479 }
1480 }
1481 return Status::OK;
1482}
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001483
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001484bcmos_errno CreateQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
1485 uint32_t gemport_id) {
1486 bcmos_errno err;
1487 bcmbal_tm_queue_cfg cfg;
1488 bcmbal_tm_queue_key key = { };
Girish Gowdruf26cf882019-05-01 23:47:58 -07001489 BCM_LOG(INFO, openolt_log_id, "creating queue. access_intf_id = %d, onu_id = %d, uni_id = %d \
1490 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 -08001491 if (direction == downstream) {
1492 // In the downstream, the queues are on the 'sub term' scheduler
1493 // There is one queue per gem port
1494 key.sched_dir = BCMBAL_TM_SCHED_DIR_DS;
1495 key.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
1496 key.id = get_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, direction);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001497
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001498 } else {
1499 queue_map_key_tuple map_key(access_intf_id, onu_id, uni_id, gemport_id, direction);
1500 if (queue_map.count(map_key) > 0) {
1501 BCM_LOG(INFO, openolt_log_id, "upstream queue exists for intf_id %d, onu_id %d, uni_id %d\n. Not re-creating", \
1502 access_intf_id, onu_id, uni_id);
1503 return BCM_ERR_OK;
1504 }
1505 key.sched_dir = BCMBAL_TM_SCHED_DIR_US;
1506 key.sched_id = get_default_tm_sched_id(nni_intf_id, direction);
1507 if (priority > 7) {
1508 return BCM_ERR_RANGE;
1509 }
1510 // There are 8 queues (one per p-bit)
1511 key.id = us_fixed_queue_id_list[priority];
1512 update_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, direction, key.id);
1513 // FIXME: The upstream queues have to be created once only.
1514 // The upstream queues on the NNI scheduler are shared by all subscribers.
1515 // When the first scheduler comes in, the queues get created, and are re-used by all others.
1516 // Also, these queues should be present until the last subscriber exits the system.
1517 // One solution is to have these queues always, i.e., create it as soon as OLT is enabled.
1518 }
Girish Gowdruf26cf882019-05-01 23:47:58 -07001519 BCM_LOG(INFO, openolt_log_id, "queue assigned queue_id = %d\n", key.id);
1520
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001521 BCMBAL_CFG_INIT(&cfg, tm_queue, key);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001522
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001523 BCMBAL_CFG_PROP_SET(&cfg, tm_queue, priority, priority);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001524
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001525 // BCMBAL_CFG_PROP_SET(&cfg, tm_queue, creation_mode, BCMBAL_TM_CREATION_MODE_MANUAL);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001526
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001527
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001528 err = bcmbal_cfg_set(DEFAULT_ATERM_ID, &cfg.hdr);
1529 if (err) {
1530 BCM_LOG(ERROR, openolt_log_id, "Failed to create subscriber tm queue, direction = %s, id %d, sched_id %d, \
1531 intf_id %d, onu_id %d, uni_id %d\n", \
1532 direction.c_str(), key.id, key.sched_id, access_intf_id, onu_id, uni_id);
1533 return err;
1534 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06001535
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001536 BCM_LOG(INFO, openolt_log_id, "Created tm_queue, direction %s, id %d, intf_id %d, onu_id %d, uni_id %d", \
1537 direction.c_str(), key.id, access_intf_id, onu_id, uni_id);
1538
1539 return BCM_ERR_OK;
1540
1541}
1542
1543Status CreateTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
1544 uint32_t intf_id = traffic_queues->intf_id();
1545 uint32_t onu_id = traffic_queues->onu_id();
1546 uint32_t uni_id = traffic_queues->uni_id();
1547 std::string direction;
1548 unsigned int alloc_id;
1549 bcmos_errno err;
1550
1551 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
1552 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
1553 if (traffic_queue.direction() == tech_profile::Direction::UPSTREAM) {
1554 direction = upstream;
1555 } else if (traffic_queue.direction() == tech_profile::Direction::DOWNSTREAM) {
1556 direction = downstream;
1557 }
1558 else {
1559 BCM_LOG(ERROR, openolt_log_id, "direction-not-supported %d", traffic_queue.direction());
1560 return Status::CANCELLED;
1561 }
1562 err = CreateQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
Girish Gowdruf26cf882019-05-01 23:47:58 -07001563 // If the queue exists already, lets not return failure and break the loop.
1564 if (err && err != BCM_ERR_ALREADY) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001565 return bcm_to_grpc_err(err, "Failed to create queue");
1566 }
1567 }
1568 return Status::OK;
1569}
1570
1571
1572bcmos_errno RemoveQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t priority,
1573 uint32_t gemport_id) {
1574 bcmbal_tm_queue_cfg queue_cfg;
1575 bcmbal_tm_queue_key queue_key = { };
1576 bcmos_errno err;
1577
1578 if (direction == downstream) {
1579 queue_key.sched_dir = BCMBAL_TM_SCHED_DIR_DS;
1580 if (is_tm_queue_id_present(access_intf_id, onu_id, uni_id, gemport_id, direction) && \
1581 is_tm_sched_id_present(access_intf_id, onu_id, uni_id, direction)) {
1582 queue_key.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
1583 queue_key.id = get_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, direction);
1584 } else {
1585 BCM_LOG(INFO, openolt_log_id, "queue not present in DS. Not clearing");
1586 return BCM_ERR_OK;
1587 }
1588 } else {
1589 free_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, direction);
1590 // In the upstream we use pre-created queues on the NNI scheduler that are used by all subscribers.
1591 // They should not be removed. So, lets return OK.
1592 return BCM_ERR_OK;
1593 }
1594
1595 BCMBAL_CFG_INIT(&queue_cfg, tm_queue, queue_key);
1596
1597 err = bcmbal_cfg_clear(DEFAULT_ATERM_ID, &(queue_cfg.hdr));
1598
1599 if (err) {
1600 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",
1601 direction.c_str(), queue_key.id, queue_key.sched_id, access_intf_id, onu_id, uni_id);
1602 return err;
1603 }
1604
1605 free_tm_queue_id(access_intf_id, onu_id, uni_id, gemport_id, direction);
1606
1607 return BCM_ERR_OK;
1608}
1609
1610Status RemoveTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
1611 uint32_t intf_id = traffic_queues->intf_id();
1612 uint32_t onu_id = traffic_queues->onu_id();
1613 uint32_t uni_id = traffic_queues->uni_id();
1614 uint32_t port_no = traffic_queues->port_no();
1615 std::string direction;
1616 unsigned int alloc_id;
1617 bcmos_errno err;
1618
1619 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
1620 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
1621 if (traffic_queue.direction() == tech_profile::Direction::UPSTREAM) {
1622 direction = upstream;
1623 } else if (traffic_queue.direction() == tech_profile::Direction::DOWNSTREAM) {
1624 direction = downstream;
1625 } else {
1626 BCM_LOG(ERROR, openolt_log_id, "direction-not-supported %d", traffic_queue.direction());
1627 return Status::CANCELLED;
1628 }
1629 err = RemoveQueue(direction, intf_id, onu_id, uni_id, traffic_queue.priority(), traffic_queue.gemport_id());
1630 if (err) {
1631 return bcm_to_grpc_err(err, "Failed to remove queue");
1632 }
Jonathan Davis70c21812018-07-19 15:32:10 -04001633 }
1634
Jonathan Davis70c21812018-07-19 15:32:10 -04001635 return Status::OK;
Jonathan Davis70c21812018-07-19 15:32:10 -04001636}