blob: 8d65d213eace7ec82e37649475d7dbb39eff6557 [file] [log] [blame]
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001/*
Girish Gowdraa707e7c2019-11-07 11:36:13 +05302 * Copyright 2018-present Open Networking Foundation
Shad Ansarib7b0ced2018-05-11 21:53:32 +00003
Girish Gowdraa707e7c2019-11-07 11:36:13 +05304 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Shad Ansarib7b0ced2018-05-11 21:53:32 +00007
Girish Gowdraa707e7c2019-11-07 11:36:13 +05308 * http://www.apache.org/licenses/LICENSE-2.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00009
Girish Gowdraa707e7c2019-11-07 11:36:13 +053010 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +000016
17#include <iostream>
18#include <memory>
19#include <string>
20
21#include "Queue.h"
Shad Ansarib7b0ced2018-05-11 21:53:32 +000022#include <sstream>
Nicolas Palpacuer9c352082018-08-14 16:37:14 -040023#include <chrono>
24#include <thread>
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -080025#include <bitset>
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000026#include <inttypes.h>
Jason Huangbf45ffb2019-10-30 17:29:02 +080027#include <unistd.h>
Jason Huang09b73ea2020-01-08 17:52:05 +080028#include <sys/socket.h>
29#include <netinet/in.h>
30#include <arpa/inet.h>
Shad Ansarib7b0ced2018-05-11 21:53:32 +000031
Craig Lutgen88a22ad2018-10-04 12:30:46 -050032#include "device.h"
Shad Ansarib7b0ced2018-05-11 21:53:32 +000033#include "core.h"
34#include "indications.h"
Nicolas Palpacuer0f19b1a2018-06-07 17:29:31 -040035#include "stats_collection.h"
Nicolas Palpacuer73222e02018-07-16 12:20:26 -040036#include "error_format.h"
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -040037#include "state.h"
Craig Lutgen88a22ad2018-10-04 12:30:46 -050038#include "utils.h"
Shad Ansarib7b0ced2018-05-11 21:53:32 +000039
40extern "C"
41{
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000042#include <bcmolt_api.h>
43#include <bcmolt_host_api.h>
44#include <bcmolt_api_model_supporting_enums.h>
45
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000046#include <bcmolt_api_conn_mgr.h>
47//CLI header files
48#include <bcmcli_session.h>
49#include <bcmcli.h>
50#include <bcm_api_cli.h>
51
52#include <bcmos_common.h>
53#include <bcm_config.h>
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -040054// FIXME : dependency problem
55// #include <bcm_common_gpon.h>
Nicolas Palpacuer967438f2018-09-07 14:41:54 -040056// #include <bcm_dev_log_task.h>
Shad Ansarib7b0ced2018-05-11 21:53:32 +000057}
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000058
Nicolas Palpacuer967438f2018-09-07 14:41:54 -040059dev_log_id openolt_log_id = bcm_dev_log_id_register("OPENOLT", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
60dev_log_id omci_log_id = bcm_dev_log_id_register("OMCI", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
61
Craig Lutgen88a22ad2018-10-04 12:30:46 -050062#define BAL_RSC_MANAGER_BASE_TM_SCHED_ID 16384
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000063#define MAX_TM_QMP_ID 16
64#define TMQ_MAP_PROFILE_SIZE 8
65#define MAX_TM_SCHED_ID 1023
66#define MAX_SUBS_TM_SCHED_ID (MAX_SUPPORTED_PON == 16 ? MAX_TM_SCHED_ID-4-16 : MAX_TM_SCHED_ID-10-64)
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -080067#define EAP_ETHER_TYPE 34958
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000068#define XGS_BANDWIDTH_GRANULARITY 16000
69#define GPON_BANDWIDTH_GRANULARITY 32000
Burak Gurdagc78b9e12019-11-29 11:14:51 +000070#define NUM_OF_PRIORITIES 8
71#define NUMBER_OF_DEFAULT_INTERFACE_QUEUES 4 // <= NUM_OF_PRIORITIES
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000072#define FILL_ARRAY(ARRAY,START,END,VALUE) for(int i=START;i<END;ARRAY[i++]=VALUE);
73#define COUNT_OF(array) (sizeof(array) / sizeof(array[0]))
74
75#define GET_FLOW_INTERFACE_TYPE(type) \
76 (type == BCMOLT_FLOW_INTERFACE_TYPE_PON) ? "PON" : \
77 (type == BCMOLT_FLOW_INTERFACE_TYPE_NNI) ? "NNI" : \
78 (type == BCMOLT_FLOW_INTERFACE_TYPE_HOST) ? "HOST" : "unknown"
79#define GET_PKT_TAG_TYPE(type) \
80 (type == BCMOLT_PKT_TAG_TYPE_UNTAGGED) ? "UNTAG" : \
81 (type == BCMOLT_PKT_TAG_TYPE_SINGLE_TAG) ? "SINGLE_TAG" : \
82 (type == BCMOLT_PKT_TAG_TYPE_DOUBLE_TAG) ? "DOUBLE_TAG" : "unknown"
Jason Huang09b73ea2020-01-08 17:52:05 +080083#define GET_ACL_ACTION_TYPE(type) \
84 (type == BCMOLT_ACCESS_CONTROL_FWD_ACTION_TYPE_TRAP_TO_HOST) ? "trap_to_host" : \
85 (type == BCMOLT_ACCESS_CONTROL_FWD_ACTION_TYPE_DROP) ? "drop" : \
86 (type == BCMOLT_ACCESS_CONTROL_FWD_ACTION_TYPE_REDIRECT) ? "redirction" : "unknown"
87#define GET_ACL_MEMBERS_UPDATE_COMMAND(command) \
88 (command == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD) ? "add" : \
89 (command == BCMOLT_MEMBERS_UPDATE_COMMAND_REMOVE) ? "remove" : \
90 (command == BCMOLT_MEMBERS_UPDATE_COMMAND_SET) ? "set" : "unknown"
91#define GET_INTERFACE_TYPE(type) \
92 (type == BCMOLT_INTERFACE_TYPE_PON) ? "PON" : \
93 (type == BCMOLT_INTERFACE_TYPE_NNI) ? "NNI" : \
94 (type == BCMOLT_INTERFACE_TYPE_HOST) ? "HOST" : "unknown"
Nicolas Palpacuer967438f2018-09-07 14:41:54 -040095
Craig Lutgen88a22ad2018-10-04 12:30:46 -050096static unsigned int num_of_nni_ports = 0;
97static unsigned int num_of_pon_ports = 0;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +000098static std::string intf_technologies[MAX_SUPPORTED_PON];
Craig Lutgen88a22ad2018-10-04 12:30:46 -050099static const std::string UNKNOWN_TECH("unknown");
Craig Lutgenb2601f02018-10-23 13:04:31 -0500100static const std::string MIXED_TECH("mixed");
101static std::string board_technology(UNKNOWN_TECH);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000102static std::string chip_family(UNKNOWN_TECH);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800103static unsigned int OPENOLT_FIELD_LEN = 200;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000104static std::string firmware_version = "Openolt.2019.07.01";
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400105
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000106const uint32_t tm_upstream_sched_id_start = (MAX_SUPPORTED_PON == 16 ? \
107 MAX_TM_SCHED_ID-3 : MAX_TM_SCHED_ID-9);
108const uint32_t tm_downstream_sched_id_start = (MAX_SUPPORTED_PON == 16 ? \
109 tm_upstream_sched_id_start-16 : tm_upstream_sched_id_start-64);
110
111/* Max Queue ID supported is 7 so based on priority_q configured for GEMPORTS
112in TECH PROFILE respective Queue ID from this list will be used for both
113US and DS Queues*/
114const uint32_t queue_id_list[8] = {0, 1, 2, 3, 4, 5, 6, 7};
115
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700116const std::string upstream = "upstream";
117const std::string downstream = "downstream";
Burak Gurdagc78b9e12019-11-29 11:14:51 +0000118const std::string multicast = "multicast";
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000119bcmolt_oltid dev_id = 0;
120
Amit Ghoshfcad4d32019-11-13 10:24:55 +0000121/* Constants used for retrying some BAL APIs */
122const uint32_t BAL_API_RETRY_TIME_IN_USECS = 1000000;
123const uint32_t MAX_BAL_API_RETRY_COUNT = 5;
124
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000125/* Current session */
126static bcmcli_session *current_session;
127static bcmcli_entry *api_parent_dir;
128bcmos_bool status_bcm_cli_quit = BCMOS_FALSE;
129bcmos_task bal_cli_thread;
130const char *bal_cli_thread_name = "bal_cli_thread";
131uint16_t flow_id_counters = 0;
Shad Ansariedef2132018-08-10 22:14:50 +0000132State state;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -0400133
Craig Lutgen967a1d02018-11-27 10:41:51 -0600134static std::map<uint32_t, uint32_t> flowid_to_port; // For mapping upstream flows to logical ports
135static std::map<uint32_t, uint32_t> flowid_to_gemport; // For mapping downstream flows into gemports
136static 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 -0800137
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000138/* This represents the Key to 'sched_map' map.
139 Represents (pon_intf_id, onu_id, uni_id, direction) */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800140typedef std::tuple<uint32_t, uint32_t, uint32_t, std::string> sched_map_key_tuple;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000141/* 'sched_map' maps sched_map_key_tuple to DBA (Upstream) or
142 Subscriber (Downstream) Scheduler ID */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800143static std::map<sched_map_key_tuple, int> sched_map;
144
Jason Huang09b73ea2020-01-08 17:52:05 +0800145/* Flow control is for flow_id and flow_type */
146typedef std::pair<uint16_t, uint16_t> flow_pair;
147static std::map<flow_pair, int32_t> flow_map;
148
Thiyagarajan Subramani8154d932019-11-13 05:29:06 -0500149/* This represents the Key to 'qos_type_map' map.
150 Represents (pon_intf_id, onu_id, uni_id) */
151typedef std::tuple<uint32_t, uint32_t, uint32_t> qos_type_map_key_tuple;
152/* 'qos_type_map' maps qos_type_map_key_tuple to qos_type*/
153static std::map<qos_type_map_key_tuple, bcmolt_egress_qos_type> qos_type_map;
154
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000155/* This represents the Key to 'sched_qmp_id_map' map.
156Represents (sched_id, pon_intf_id, onu_id, uni_id) */
157typedef std::tuple<uint32_t, uint32_t, uint32_t, uint32_t> sched_qmp_id_map_key_tuple;
158/* 'sched_qmp_id_map' maps sched_qmp_id_map_key_tuple to TM Queue Mapping Profile ID */
159static std::map<sched_qmp_id_map_key_tuple, int> sched_qmp_id_map;
160/* 'qmp_id_to_qmp_map' maps TM Queue Mapping Profile ID to TM Queue Mapping Profile */
161static std::map<int, std::vector < uint32_t > > qmp_id_to_qmp_map;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800162
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -0500163// Flag used to watch whether mocked alloc_cfg_compltd_key is added to alloc_cfg_compltd_map
164#ifdef TEST_MODE
165bool ALLOC_CFG_FLAG = false;
166#endif
167
Girish Gowdra96461052019-11-22 20:13:59 +0530168#define ALLOC_CFG_COMPLETE_WAIT_TIMEOUT 1000 // in milli-seconds
169// Map used to track response from BAL for ITU PON Alloc Configuration.
170// The key is alloc_cfg_compltd_key and value is a concurrent thread-safe queue which is
171// used for pushing (from BAL) and popping (at application) the results.
172std::map<alloc_cfg_compltd_key, Queue<alloc_cfg_complete_result> *> alloc_cfg_compltd_map;
173// Lock to protect critical section data structure used for handling AllocObject configuration response.
174bcmos_fastlock alloc_cfg_wait_lock;
175
Jason Huang09b73ea2020-01-08 17:52:05 +0800176
177/*** ACL Handling related data start ***/
178
179static std::map<acl_classifier_key, uint16_t> acl_classifier_to_acl_id_map;
180
181bool operator<(const acl_classifier_key& a1, const acl_classifier_key& a2)
182{
183 return ((a1.ether_type + 2*a1.ip_proto + 3*a1.src_port + 4*a1.dst_port) <
184 (a2.ether_type + 2*a2.ip_proto + 3*a2.src_port + 4*a2.dst_port));
185}
186
187typedef std::tuple<uint16_t, std::string> flow_id_flow_direction;
188typedef std::tuple<int16_t, uint16_t, int32_t> acl_id_gem_id_intf_id;
189static std::map<flow_id_flow_direction, acl_id_gem_id_intf_id> flow_to_acl_map;
190
191// Keeps a reference count of how many flows are referencing a given ACL ID.
192// Key represents the ACL-ID and value is number of flows referencing the given ACL-ID.
193// When there is at least one flow referencing the ACL-ID, the ACL should be installed.
194// When there are no flows referencing the ACL-ID, the ACL should be removed.
195static std::map<uint16_t, uint16_t> acl_ref_cnt;
196
197typedef std::tuple<uint16_t, uint16_t> gem_id_intf_id; // key to gem_ref_cnt
198// Keeps a reference count of how many ACL related flows are referencing a given (gem-id, pon_intf_id).
199// When there is at least on flow, we should install the gem. When there are no flows
200// the gem should be removed.
201static std::map<gem_id_intf_id, uint16_t> gem_ref_cnt;
202
203// Needed to keep track of how many flows for a given acl_id, intf_id and intf_type are
204// installed. When there is at least on flow for this key, we should have interface registered
205// for the given ACL-ID. When there are no flows, the intf should unregister itself from
206// the ACL-ID.
207typedef std::tuple<uint16_t, uint8_t, std::string> acl_id_intf_id_intf_type;
208static std::map<acl_id_intf_id_intf_type, uint16_t> intf_acl_registration_ref_cnt;
209
210#define MAX_ACL_ID 33
211std::bitset<MAX_ACL_ID> acl_id_bitset;
212
213/*** ACL Handling related data end ***/
214
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800215std::bitset<MAX_TM_SCHED_ID> tm_sched_bitset;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000216std::bitset<MAX_TM_QMP_ID> tm_qmp_bitset;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800217
218static bcmos_fastlock data_lock;
Craig Lutgen967a1d02018-11-27 10:41:51 -0600219
Girish Gowdra96461052019-11-22 20:13:59 +0530220
Craig Lutgen967a1d02018-11-27 10:41:51 -0600221#define MIN_ALLOC_ID_GPON 256
222#define MIN_ALLOC_ID_XGSPON 1024
223
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800224static bcmos_errno CreateSched(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, \
225 uint32_t port_no, uint32_t alloc_id, tech_profile::AdditionalBW additional_bw, uint32_t weight, \
226 uint32_t priority, tech_profile::SchedulingPolicy sched_policy,
227 tech_profile::TrafficShapingInfo traffic_shaping_info);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000228static bcmos_errno RemoveSched(int intf_id, int onu_id, int uni_id, int alloc_id, std::string direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800229static bcmos_errno CreateQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, \
Thiyagarajan Subramani8154d932019-11-13 05:29:06 -0500230 bcmolt_egress_qos_type qos_type, uint32_t priority, uint32_t gemport_id);
231static bcmos_errno RemoveQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id, \
232 bcmolt_egress_qos_type qos_type, uint32_t priority, uint32_t gemport_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000233static bcmos_errno CreateDefaultSched(uint32_t intf_id, const std::string direction);
234static bcmos_errno CreateDefaultQueue(uint32_t intf_id, const std::string direction);
235
236uint16_t get_dev_id(void) {
237 return dev_id;
238}
Shad Ansari627b5782018-08-13 22:49:32 +0000239
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400240// Stubbed defntions of bcmolt_cfg_get required for unit-test
241#ifdef TEST_MODE
242extern bcmos_errno bcmolt_cfg_get__bal_state_stub(bcmolt_oltid olt_id, void* ptr);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -0500243extern bcmos_errno bcmolt_cfg_get__onu_state_stub(bcmolt_oltid olt_id, void* ptr);
244extern bcmos_errno bcmolt_cfg_get__tm_sched_stub(bcmolt_oltid olt_id, void* ptr);
245extern bcmos_errno bcmolt_cfg_get__pon_intf_stub(bcmolt_oltid olt_id, void* ptr);
246extern bcmos_errno bcmolt_cfg_get__nni_intf_stub(bcmolt_oltid olt_id, void* ptr);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400247extern bcmos_errno bcmolt_cfg_get__olt_topology_stub(bcmolt_oltid olt_id, void* ptr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -0500248extern bcmos_errno bcmolt_cfg_get__flow_stub(bcmolt_oltid olt_id, void* ptr);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -0400249#endif
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800250/**
251* Returns the default NNI (Upstream direction) or PON (Downstream direction) scheduler
252* Every NNI port and PON port have default scheduler.
253* The NNI0 default scheduler ID is 18432, and NNI1 is 18433 and so on.
254* Similarly, PON0 default scheduler ID is 16384. PON1 is 16385 and so on.
255*
256* @param intf_id NNI or PON interface ID
257* @param direction "upstream" or "downstream"
258*
259* @return default scheduler ID for the given interface.
260*/
261static inline int get_default_tm_sched_id(int intf_id, std::string direction) {
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700262 if (direction.compare(upstream) == 0) {
263 return tm_upstream_sched_id_start + intf_id;
264 } else if (direction.compare(downstream) == 0) {
265 return tm_downstream_sched_id_start + intf_id;
266 }
267 else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000268 OPENOLT_LOG(ERROR, openolt_log_id, "invalid direction - %s\n", direction.c_str());
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -0700269 return 0;
270 }
271}
272
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800273/**
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800274* Gets a unique tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
275* The tm_sched_id is locally cached in a map, so that it can rendered when necessary.
276* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
277*
278* @param intf_id NNI or PON intf ID
279* @param onu_id ONU ID
280* @param uni_id UNI ID
281* @param gemport_id GEM Port ID
282* @param direction Upstream or downstream
283*
284* @return tm_sched_id
285*/
286uint32_t get_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
287 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
288 int sched_id = -1;
289
290 std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
291 if (it != sched_map.end()) {
292 sched_id = it->second;
293 }
294 if (sched_id != -1) {
295 return sched_id;
296 }
297
298 bcmos_fastlock_lock(&data_lock);
299 // Complexity of O(n). Is there better way that can avoid linear search?
300 for (sched_id = 0; sched_id < MAX_TM_SCHED_ID; sched_id++) {
301 if (tm_sched_bitset[sched_id] == 0) {
302 tm_sched_bitset[sched_id] = 1;
303 break;
304 }
305 }
306 bcmos_fastlock_unlock(&data_lock, 0);
307
308 if (sched_id < MAX_TM_SCHED_ID) {
309 bcmos_fastlock_lock(&data_lock);
310 sched_map[key] = sched_id;
311 bcmos_fastlock_unlock(&data_lock, 0);
312 return sched_id;
313 } else {
314 return -1;
315 }
316}
317
318/**
319* Free tm_sched_id for a given intf_id, onu_id, uni_id, gemport_id, direction
320*
321* @param intf_id NNI or PON intf ID
322* @param onu_id ONU ID
323* @param uni_id UNI ID
324* @param gemport_id GEM Port ID
325* @param direction Upstream or downstream
326*/
327void free_tm_sched_id(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
328 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
329 std::map<sched_map_key_tuple, int>::const_iterator it;
330 bcmos_fastlock_lock(&data_lock);
331 it = sched_map.find(key);
332 if (it != sched_map.end()) {
333 tm_sched_bitset[it->second] = 0;
334 sched_map.erase(it);
335 }
336 bcmos_fastlock_unlock(&data_lock, 0);
337}
338
339bool is_tm_sched_id_present(int pon_intf_id, int onu_id, int uni_id, std::string direction) {
340 sched_map_key_tuple key(pon_intf_id, onu_id, uni_id, direction);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000341 std::map<sched_map_key_tuple, int>::const_iterator it = sched_map.find(key);
342 if (it != sched_map.end()) {
343 return true;
344 }
345 return false;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -0800346}
347
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000348/**
349* Check whether given two tm qmp profiles are equal or not
350*
351* @param tmq_map_profileA <vector> TM QUEUE MAPPING PROFILE
352* @param tmq_map_profileB <vector> TM QUEUE MAPPING PROFILE
353*
354* @return boolean, true if given tmq_map_profiles are equal else false
355*/
356
357bool check_tm_qmp_equality(std::vector<uint32_t> tmq_map_profileA, std::vector<uint32_t> tmq_map_profileB) {
358 for (uint32_t i = 0; i < TMQ_MAP_PROFILE_SIZE; i++) {
359 if (tmq_map_profileA[i] != tmq_map_profileB[i]) {
360 return false;
361 }
362 }
363 return true;
Shad Ansari627b5782018-08-13 22:49:32 +0000364}
365
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000366/**
367* Modifies given queues_pbit_map to parsable format
368* e.g: Modifes "0b00000101" to "10100000"
369*
370* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
371* @param size Queue count
372*
373* @return string queues_pbit_map
374*/
375std::string* get_valid_queues_pbit_map(std::string *queues_pbit_map, uint32_t size) {
376 for(uint32_t i=0; i < size; i++) {
377 /* Deletes 2 characters from index number 0 */
378 queues_pbit_map[i].erase(0, 2);
379 std::reverse(queues_pbit_map[i].begin(), queues_pbit_map[i].end());
380 }
381 return queues_pbit_map;
382}
383
384/**
385* Creates TM QUEUE MAPPING PROFILE for given queues_pbit_map and queues_priority_q
386*
387* @param queues_pbit_map PBIT MAP configured for each GEM in TECH PROFILE
388* @param queues_priority_q PRIORITY_Q configured for each GEM in TECH PROFILE
389* @param size Queue count
390*
391* @return <vector> TM QUEUE MAPPING PROFILE
392*/
393std::vector<uint32_t> get_tmq_map_profile(std::string *queues_pbit_map, uint32_t *queues_priority_q, uint32_t size) {
394 std::vector<uint32_t> tmq_map_profile(8,0);
395
396 for(uint32_t i=0; i < size; i++) {
397 for (uint32_t j = 0; j < queues_pbit_map[i].size(); j++) {
398 if (queues_pbit_map[i][j]=='1') {
399 tmq_map_profile.at(j) = queue_id_list[queues_priority_q[i]];
400 }
401 }
402 }
403 return tmq_map_profile;
404}
405
406/**
407* Gets corresponding tm_qmp_id for a given tmq_map_profile
408*
409* @param <vector> TM QUEUE MAPPING PROFILE
410*
411* @return tm_qmp_id
412*/
413int get_tm_qmp_id(std::vector<uint32_t> tmq_map_profile) {
414 int tm_qmp_id = -1;
415
416 std::map<int, std::vector < uint32_t > >::const_iterator it = qmp_id_to_qmp_map.begin();
417 while(it != qmp_id_to_qmp_map.end()) {
418 if(check_tm_qmp_equality(tmq_map_profile, it->second)) {
419 tm_qmp_id = it->first;
420 break;
421 }
422 it++;
423 }
424 return tm_qmp_id;
425}
426
427/**
428* Updates sched_qmp_id_map with given sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id
429*
430* @param upstream/downstream sched_id
431* @param PON intf ID
432* @param onu_id ONU ID
433* @param uni_id UNI ID
434* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
435*/
436void update_sched_qmp_id_map(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
437 uint32_t uni_id, int tm_qmp_id) {
438 bcmos_fastlock_lock(&data_lock);
439 sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
440 sched_qmp_id_map.insert(make_pair(key, tm_qmp_id));
441 bcmos_fastlock_unlock(&data_lock, 0);
442}
443
444/**
445* Gets corresponding tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
446*
447* @param upstream/downstream sched_id
448* @param PON intf ID
449* @param onu_id ONU ID
450* @param uni_id UNI ID
451*
452* @return tm_qmp_id
453*/
454int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id) {
455 sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
456 int tm_qmp_id = -1;
457
458 std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
459 if (it != sched_qmp_id_map.end()) {
460 tm_qmp_id = it->second;
461 }
462 return tm_qmp_id;
463}
464
465/**
466* Gets a unique tm_qmp_id for a given tmq_map_profile
467* The tm_qmp_id is locally cached in a map, so that it can be rendered when necessary.
468* VOLTHA replays whole configuration on OLT reboot, so caching locally is not a problem
469*
470* @param upstream/downstream sched_id
471* @param PON intf ID
472* @param onu_id ONU ID
473* @param uni_id UNI ID
474* @param <vector> TM QUEUE MAPPING PROFILE
475*
476* @return tm_qmp_id
477*/
478int get_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id, \
479 std::vector<uint32_t> tmq_map_profile) {
480 int tm_qmp_id;
481
482 bcmos_fastlock_lock(&data_lock);
483 /* Complexity of O(n). Is there better way that can avoid linear search? */
484 for (tm_qmp_id = 0; tm_qmp_id < MAX_TM_QMP_ID; tm_qmp_id++) {
485 if (tm_qmp_bitset[tm_qmp_id] == 0) {
486 tm_qmp_bitset[tm_qmp_id] = 1;
487 break;
488 }
489 }
490 bcmos_fastlock_unlock(&data_lock, 0);
491
492 if (tm_qmp_id < MAX_TM_QMP_ID) {
493 bcmos_fastlock_lock(&data_lock);
494 qmp_id_to_qmp_map.insert(make_pair(tm_qmp_id, tmq_map_profile));
495 bcmos_fastlock_unlock(&data_lock, 0);
496 update_sched_qmp_id_map(sched_id, pon_intf_id, onu_id, uni_id, tm_qmp_id);
497 return tm_qmp_id;
498 } else {
499 return -1;
500 }
501}
502
503/**
504* Free tm_qmp_id for a given sched_id, pon_intf_id, onu_id, uni_id
505*
506* @param upstream/downstream sched_id
507* @param PON intf ID
508* @param onu_id ONU ID
509* @param uni_id UNI ID
510* @param tm_qmp_id TM QUEUE MAPPING PROFILE ID
511*
512* @return boolean, true if no more reference for TM QMP else false
513*/
514bool free_tm_qmp_id(uint32_t sched_id,uint32_t pon_intf_id, uint32_t onu_id, \
515 uint32_t uni_id, int tm_qmp_id) {
516 bool result;
517 sched_qmp_id_map_key_tuple key(sched_id, pon_intf_id, onu_id, uni_id);
518 std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it = sched_qmp_id_map.find(key);
519 bcmos_fastlock_lock(&data_lock);
520 if (it != sched_qmp_id_map.end()) {
521 sched_qmp_id_map.erase(it);
522 }
523 bcmos_fastlock_unlock(&data_lock, 0);
524
525 uint32_t tm_qmp_ref_count = 0;
526 std::map<sched_qmp_id_map_key_tuple, int>::const_iterator it2 = sched_qmp_id_map.begin();
527 while(it2 != sched_qmp_id_map.end()) {
528 if(it2->second == tm_qmp_id) {
529 tm_qmp_ref_count++;
530 }
531 it2++;
532 }
533
534 if (tm_qmp_ref_count == 0) {
535 std::map<int, std::vector < uint32_t > >::const_iterator it3 = qmp_id_to_qmp_map.find(tm_qmp_id);
536 if (it3 != qmp_id_to_qmp_map.end()) {
537 bcmos_fastlock_lock(&data_lock);
538 tm_qmp_bitset[tm_qmp_id] = 0;
539 qmp_id_to_qmp_map.erase(it3);
540 bcmos_fastlock_unlock(&data_lock, 0);
541 OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So clearing it\n", \
542 tm_qmp_id, tm_qmp_ref_count);
543 result = true;
544 }
545 } else {
546 OPENOLT_LOG(INFO, openolt_log_id, "Reference count for tm qmp profile id %d is : %d. So not clearing it\n", \
547 tm_qmp_id, tm_qmp_ref_count);
548 result = false;
549 }
550 return result;
551}
552
Jason Huang09b73ea2020-01-08 17:52:05 +0800553// Gets free ACL ID if available, else -1
554int get_acl_id() {
555 int acl_id;
556 bcmos_fastlock_lock(&data_lock);
557 /* Complexity of O(n). Is there better way that can avoid linear search? */
558 for (acl_id = 0; acl_id < MAX_ACL_ID; acl_id++) {
559 if (acl_id_bitset[acl_id] == 0) {
560 acl_id_bitset[acl_id] = 1;
561 break;
562 }
563 }
564 bcmos_fastlock_unlock(&data_lock, 0);
565 if (acl_id < MAX_ACL_ID) {
566 return acl_id ;
567 } else {
568 return -1;
569 }
570}
571
572// Frees up the ACL ID.
573void free_acl_id (int acl_id) {
574 if (acl_id < MAX_ACL_ID) {
575 bcmos_fastlock_lock(&data_lock);
576 acl_id_bitset[acl_id] = 0;
577 bcmos_fastlock_unlock(&data_lock, 0);
578 }
579}
580
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000581/**
Thiyagarajan Subramani8154d932019-11-13 05:29:06 -0500582* Returns qos type as string
583*
584* @param qos_type bcmolt_egress_qos_type enum
585*/
586std::string get_qos_type_as_string(bcmolt_egress_qos_type qos_type) {
587 switch (qos_type)
588 {
589 case BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE: return "FIXED_QUEUE";
590 case BCMOLT_EGRESS_QOS_TYPE_TC_TO_QUEUE: return "TC_TO_QUEUE";
591 case BCMOLT_EGRESS_QOS_TYPE_PBIT_TO_TC: return "PBIT_TO_TC";
592 case BCMOLT_EGRESS_QOS_TYPE_NONE: return "NONE";
593 case BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE: return "PRIORITY_TO_QUEUE";
594 default: OPENOLT_LOG(ERROR, openolt_log_id, "qos-type-not-supported %d\n", qos_type);
595 return "qos-type-not-supported";
596 }
597}
598
599/**
600* Gets/Updates qos type for given pon_intf_id, onu_id, uni_id
601*
602* @param PON intf ID
603* @param onu_id ONU ID
604* @param uni_id UNI ID
605* @param queue_size TrafficQueues Size
606*
607* @return qos_type
608*/
609bcmolt_egress_qos_type get_qos_type(uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t queue_size = 0) {
610 qos_type_map_key_tuple key(pon_intf_id, onu_id, uni_id);
611 bcmolt_egress_qos_type egress_qos_type = BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
612 std::string qos_string;
613
614 std::map<qos_type_map_key_tuple, bcmolt_egress_qos_type>::const_iterator it = qos_type_map.find(key);
615 if (it != qos_type_map.end()) {
616 egress_qos_type = it->second;
617 qos_string = get_qos_type_as_string(egress_qos_type);
618 OPENOLT_LOG(INFO, openolt_log_id, "Qos-type for subscriber connected to pon_intf_id %d, onu_id %d and uni_id %d is %s\n", \
619 pon_intf_id, onu_id, uni_id, qos_string.c_str());
620 }
621 else {
622 /* QOS Type has been pre-defined as Fixed Queue but it will be updated based on number of GEMPORTS
623 associated for a given subscriber. If GEM count = 1 for a given subscriber, qos_type will be Fixed Queue
624 else Priority to Queue */
625 egress_qos_type = (queue_size > 1) ? \
626 BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE : BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE;
627 bcmos_fastlock_lock(&data_lock);
628 qos_type_map.insert(make_pair(key, egress_qos_type));
629 bcmos_fastlock_unlock(&data_lock, 0);
630 qos_string = get_qos_type_as_string(egress_qos_type);
631 OPENOLT_LOG(INFO, openolt_log_id, "Qos-type for subscriber connected to pon_intf_id %d, onu_id %d and uni_id %d is %s\n", \
632 pon_intf_id, onu_id, uni_id, qos_string.c_str());
633 }
634 return egress_qos_type;
635}
636
637/**
638* Clears qos type for given pon_intf_id, onu_id, uni_id
639*
640* @param PON intf ID
641* @param onu_id ONU ID
642* @param uni_id UNI ID
643*/
644void clear_qos_type(uint32_t pon_intf_id, uint32_t onu_id, uint32_t uni_id) {
645 qos_type_map_key_tuple key(pon_intf_id, onu_id, uni_id);
646 std::map<qos_type_map_key_tuple, bcmolt_egress_qos_type>::const_iterator it = qos_type_map.find(key);
647 bcmos_fastlock_lock(&data_lock);
648 if (it != qos_type_map.end()) {
649 qos_type_map.erase(it);
650 OPENOLT_LOG(INFO, openolt_log_id, "Cleared Qos-type for subscriber connected to pon_intf_id %d, onu_id %d and uni_id %d\n", \
651 pon_intf_id, onu_id, uni_id);
652 }
653 bcmos_fastlock_unlock(&data_lock, 0);
654}
655
656/**
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000657* Returns Scheduler/Queue direction as string
658*
659* @param direction as specified in tech_profile.proto
660*/
661std::string GetDirection(int direction) {
662 switch (direction)
663 {
664 case tech_profile::Direction::UPSTREAM: return upstream;
665 case tech_profile::Direction::DOWNSTREAM: return downstream;
666 default: OPENOLT_LOG(ERROR, openolt_log_id, "direction-not-supported %d\n", direction);
667 return "direction-not-supported";
668 }
669}
670
671inline const char *get_flow_acton_command(uint32_t command) {
672 char actions[200] = { };
673 char *s_actions_ptr = actions;
674 if (command & BCMOLT_ACTION_CMD_ID_ADD_OUTER_TAG) strcat(s_actions_ptr, "ADD_OUTER_TAG|");
675 if (command & BCMOLT_ACTION_CMD_ID_REMOVE_OUTER_TAG) strcat(s_actions_ptr, "REMOVE_OUTER_TAG|");
676 if (command & BCMOLT_ACTION_CMD_ID_XLATE_OUTER_TAG) strcat(s_actions_ptr, "TRANSLATE_OUTER_TAG|");
677 if (command & BCMOLT_ACTION_CMD_ID_ADD_INNER_TAG) strcat(s_actions_ptr, "ADD_INNTER_TAG|");
678 if (command & BCMOLT_ACTION_CMD_ID_REMOVE_INNER_TAG) strcat(s_actions_ptr, "REMOVE_INNER_TAG|");
679 if (command & BCMOLT_ACTION_CMD_ID_XLATE_INNER_TAG) strcat(s_actions_ptr, "TRANSLATE_INNER_TAG|");
680 if (command & BCMOLT_ACTION_CMD_ID_REMARK_OUTER_PBITS) strcat(s_actions_ptr, "REMOVE_OUTER_PBITS|");
681 if (command & BCMOLT_ACTION_CMD_ID_REMARK_INNER_PBITS) strcat(s_actions_ptr, "REMAKE_INNER_PBITS|");
682 return s_actions_ptr;
683}
684
Girish Gowdra96461052019-11-22 20:13:59 +0530685// This method handles waiting for AllocObject configuration.
686// Returns error if the AllocObject is not in the appropriate state based on action requested.
687bcmos_errno wait_for_alloc_action(uint32_t intf_id, uint32_t alloc_id, AllocCfgAction action) {
688 Queue<alloc_cfg_complete_result> cfg_result;
689 alloc_cfg_compltd_key k(intf_id, alloc_id);
690 alloc_cfg_compltd_map[k] = &cfg_result;
691 bcmos_errno err = BCM_ERR_OK;
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -0500692 #ifdef TEST_MODE
693 ALLOC_CFG_FLAG = true;
694 #endif
Girish Gowdra96461052019-11-22 20:13:59 +0530695
696 // Try to pop the result from BAL with a timeout of ALLOC_CFG_COMPLETE_WAIT_TIMEOUT ms
697 std::pair<alloc_cfg_complete_result, bool> result = cfg_result.pop(ALLOC_CFG_COMPLETE_WAIT_TIMEOUT);
698 if (result.second == false) {
699 OPENOLT_LOG(ERROR, openolt_log_id, "timeout waiting for alloc cfg complete indication intf_id %d, alloc_id %d\n",
700 intf_id, alloc_id);
701 // Invalidate the queue pointer.
702 bcmos_fastlock_lock(&alloc_cfg_wait_lock);
703 alloc_cfg_compltd_map[k] = NULL;
704 bcmos_fastlock_unlock(&alloc_cfg_wait_lock, 0);
705 err = BCM_ERR_INTERNAL;
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -0500706 #ifdef TEST_MODE
707 ALLOC_CFG_FLAG = false;
708 #endif
Girish Gowdra96461052019-11-22 20:13:59 +0530709 }
710 else if (result.first.status == ALLOC_CFG_STATUS_FAIL) {
711 OPENOLT_LOG(ERROR, openolt_log_id, "error processing alloc cfg request intf_id %d, alloc_id %d\n",
712 intf_id, alloc_id);
713 err = BCM_ERR_INTERNAL;
714 }
715
716 if (err == BCM_ERR_OK) {
717 if (action == ALLOC_OBJECT_CREATE) {
718 if (result.first.state != ALLOC_OBJECT_STATE_ACTIVE) {
719 OPENOLT_LOG(ERROR, openolt_log_id, "alloc object not in active state intf_id %d, alloc_id %d alloc_obj_state %d\n",
720 intf_id, alloc_id, result.first.state);
721 err = BCM_ERR_INTERNAL;
722 } else {
723 OPENOLT_LOG(INFO, openolt_log_id, "Create upstream bandwidth allocation success, intf_id %d, alloc_id %d\n",
724 intf_id, alloc_id);
725 }
726 } else { // ALLOC_OBJECT_DELETE
727 if (result.first.state != ALLOC_OBJECT_STATE_NOT_CONFIGURED) {
728 OPENOLT_LOG(ERROR, openolt_log_id, "alloc object is not reset intf_id %d, alloc_id %d alloc_obj_state %d\n",
729 intf_id, alloc_id, result.first.state);
730 err = BCM_ERR_INTERNAL;
731 } else {
732 OPENOLT_LOG(INFO, openolt_log_id, "Remove alloc object success, intf_id %d, alloc_id %d\n",
733 intf_id, alloc_id);
734 }
735 }
736 }
737
738 // Remove entry from map
739 bcmos_fastlock_lock(&alloc_cfg_wait_lock);
740 alloc_cfg_compltd_map.erase(k);
741 bcmos_fastlock_unlock(&alloc_cfg_wait_lock, 0);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -0500742 #ifdef TEST_MODE
743 ALLOC_CFG_FLAG = false;
744 #endif
Girish Gowdra96461052019-11-22 20:13:59 +0530745 return err;
746}
747
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000748char* openolt_read_sysinfo(const char* field_name, char* field_val)
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800749{
750 FILE *fp;
751 /* Prepare the command*/
752 char command[150];
753
754 snprintf(command, sizeof command, "bash -l -c \"onlpdump -s\" | perl -ne 'print $1 if /%s: (\\S+)/'", field_name);
755 /* Open the command for reading. */
756 fp = popen(command, "r");
757 if (fp == NULL) {
758 /*The client has to check for a Null field value in this case*/
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000759 OPENOLT_LOG(INFO, openolt_log_id, "Failed to query the %s\n", field_name);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800760 return field_val;
761 }
762
763 /*Read the field value*/
764 if (fp) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000765 uint8_t ret;
766 ret = fread(field_val, OPENOLT_FIELD_LEN, 1, fp);
767 if (ret >= OPENOLT_FIELD_LEN)
768 OPENOLT_LOG(INFO, openolt_log_id, "Read data length %u\n", ret);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800769 pclose(fp);
770 }
771 return field_val;
772}
773
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400774Status GetDeviceInfo_(openolt::DeviceInfo* device_info) {
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500775 device_info->set_vendor(VENDOR_ID);
776 device_info->set_model(MODEL_ID);
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400777 device_info->set_hardware_version("");
778 device_info->set_firmware_version(firmware_version);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500779 device_info->set_technology(board_technology);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500780 device_info->set_pon_ports(num_of_pon_ports);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500781
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800782 char serial_number[OPENOLT_FIELD_LEN];
783 memset(serial_number, '\0', OPENOLT_FIELD_LEN);
784 openolt_read_sysinfo("Serial Number", serial_number);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000785 OPENOLT_LOG(INFO, openolt_log_id, "Fetched device serial number %s\n", serial_number);
Thiyagarajan Subramani5e973532019-02-02 03:21:43 -0800786 device_info->set_device_serial_number(serial_number);
787
Girish Gowdru771f9ff2019-07-24 12:02:10 -0700788 char device_id[OPENOLT_FIELD_LEN];
789 memset(device_id, '\0', OPENOLT_FIELD_LEN);
790 openolt_read_sysinfo("MAC", device_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000791 OPENOLT_LOG(INFO, openolt_log_id, "Fetched device mac address %s\n", device_id);
Girish Gowdru771f9ff2019-07-24 12:02:10 -0700792 device_info->set_device_id(device_id);
793
Craig Lutgenb2601f02018-10-23 13:04:31 -0500794 // Legacy, device-wide ranges. To be deprecated when adapter
795 // is upgraded to support per-interface ranges
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000796 if (board_technology == "XGS-PON") {
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500797 device_info->set_onu_id_start(1);
798 device_info->set_onu_id_end(255);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600799 device_info->set_alloc_id_start(MIN_ALLOC_ID_XGSPON);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500800 device_info->set_alloc_id_end(16383);
801 device_info->set_gemport_id_start(1024);
802 device_info->set_gemport_id_end(65535);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500803 device_info->set_flow_id_start(1);
804 device_info->set_flow_id_end(16383);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500805 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000806 else if (board_technology == "GPON") {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500807 device_info->set_onu_id_start(1);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500808 device_info->set_onu_id_end(127);
Craig Lutgen967a1d02018-11-27 10:41:51 -0600809 device_info->set_alloc_id_start(MIN_ALLOC_ID_GPON);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500810 device_info->set_alloc_id_end(767);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500811 device_info->set_gemport_id_start(256);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500812 device_info->set_gemport_id_end(4095);
Craig Lutgenb2601f02018-10-23 13:04:31 -0500813 device_info->set_flow_id_start(1);
814 device_info->set_flow_id_end(16383);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500815 }
Craig Lutgenb2601f02018-10-23 13:04:31 -0500816
817 std::map<std::string, openolt::DeviceInfo::DeviceResourceRanges*> ranges;
818 for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
819 std::string intf_technology = intf_technologies[intf_id];
820 openolt::DeviceInfo::DeviceResourceRanges *range = ranges[intf_technology];
821 if(range == nullptr) {
822 range = device_info->add_ranges();
823 ranges[intf_technology] = range;
824 range->set_technology(intf_technology);
825
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000826 if (intf_technology == "XGS-PON") {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500827 openolt::DeviceInfo::DeviceResourceRanges::Pool* pool;
828
829 pool = range->add_pools();
830 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ONU_ID);
831 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::DEDICATED_PER_INTF);
832 pool->set_start(1);
833 pool->set_end(255);
834
835 pool = range->add_pools();
836 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ALLOC_ID);
837 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_SAME_TECH);
838 pool->set_start(1024);
839 pool->set_end(16383);
840
841 pool = range->add_pools();
842 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::GEMPORT_ID);
843 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
844 pool->set_start(1024);
845 pool->set_end(65535);
846
847 pool = range->add_pools();
848 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::FLOW_ID);
849 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
850 pool->set_start(1);
851 pool->set_end(16383);
852 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000853 else if (intf_technology == "GPON") {
Craig Lutgenb2601f02018-10-23 13:04:31 -0500854 openolt::DeviceInfo::DeviceResourceRanges::Pool* pool;
855
856 pool = range->add_pools();
857 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ONU_ID);
858 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::DEDICATED_PER_INTF);
859 pool->set_start(1);
860 pool->set_end(127);
861
862 pool = range->add_pools();
863 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::ALLOC_ID);
864 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_SAME_TECH);
865 pool->set_start(256);
866 pool->set_end(757);
867
868 pool = range->add_pools();
869 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::GEMPORT_ID);
870 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
871 pool->set_start(256);
872 pool->set_end(4095);
873
874 pool = range->add_pools();
875 pool->set_type(openolt::DeviceInfo::DeviceResourceRanges::Pool::FLOW_ID);
876 pool->set_sharing(openolt::DeviceInfo::DeviceResourceRanges::Pool::SHARED_BY_ALL_INTF_ALL_TECH);
877 pool->set_start(1);
878 pool->set_end(16383);
879 }
880 }
881
882 range->add_intf_ids(intf_id);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500883 }
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400884
885 // FIXME: Once dependency problem is fixed
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500886 // device_info->set_pon_ports(num_of_pon_ports);
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400887 // device_info->set_onu_id_end(XGPON_NUM_OF_ONUS - 1);
888 // device_info->set_alloc_id_start(1024);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500889 // device_info->set_alloc_id_end(XGPON_NUM_OF_ALLOC_IDS * num_of_pon_ports ? - 1);
Nicolas Palpacuerf0b02492018-09-10 10:21:29 -0400890 // device_info->set_gemport_id_start(XGPON_MIN_BASE_SERVICE_PORT_ID);
Craig Lutgen88a22ad2018-10-04 12:30:46 -0500891 // device_info->set_gemport_id_end(XGPON_NUM_OF_GEM_PORT_IDS_PER_PON * num_of_pon_ports ? - 1);
892 // device_info->set_pon_ports(num_of_pon_ports);
Nicolas Palpacuerdff96792018-09-06 14:59:32 -0400893
894 return Status::OK;
895}
896
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000897Status pushOltOperInd(uint32_t intf_id, const char *type, const char *state)
898{
899 openolt::Indication ind;
900 openolt::IntfOperIndication* intf_oper_ind = new openolt::IntfOperIndication;
901
902 intf_oper_ind->set_type(type);
903 intf_oper_ind->set_intf_id(intf_id);
904 intf_oper_ind->set_oper_state(state);
905 ind.set_allocated_intf_oper_ind(intf_oper_ind);
906 oltIndQ.push(ind);
907 return Status::OK;
908}
909
910#define CLI_HOST_PROMPT_FORMAT "BCM.%u> "
911
912/* Build CLI prompt */
913static void openolt_cli_get_prompt_cb(bcmcli_session *session, char *buf, uint32_t max_len)
914{
915 snprintf(buf, max_len, CLI_HOST_PROMPT_FORMAT, dev_id);
916}
917
918static int _bal_apiend_cli_thread_handler(long data)
919{
920 char init_string[]="\n";
921 bcmcli_session *sess = current_session;
922 bcmos_task_parm bal_cli_task_p_dummy;
923
924 /* Switch to interactive mode if not stopped in the init script */
Burak Gurdagc78b9e12019-11-29 11:14:51 +0000925 if (!bcmcli_is_stopped(sess)) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000926 /* Force a CLI command prompt
927 * The string passed into the parse function
928 * must be modifiable, so a string constant like
929 * bcmcli_parse(current_session, "\n") will not
930 * work.
931 */
932 bcmcli_parse(sess, init_string);
933
934 /* Process user input until EOF or quit command */
935 bcmcli_driver(sess);
Burak Gurdagc78b9e12019-11-29 11:14:51 +0000936 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000937 OPENOLT_LOG(INFO, openolt_log_id, "BAL API End CLI terminated\n");
938
939 /* Cleanup */
940 bcmcli_session_close(current_session);
941 bcmcli_token_destroy(NULL);
942 return 0;
943}
944
945/* Init API CLI commands for the current device */
946bcmos_errno bcm_openolt_api_cli_init(bcmcli_entry *parent_dir, bcmcli_session *session)
947{
948 bcmos_errno rc;
949
950 api_parent_dir = parent_dir;
951
952 rc = bcm_api_cli_set_commands(session);
953
954#ifdef BCM_SUBSYSTEM_HOST
955 /* Subscribe for device change indication */
956 rc = rc ? rc : bcmolt_olt_sel_ind_register(_api_cli_olt_change_ind);
957#endif
958
959 return rc;
960}
961
962static bcmos_errno bcm_cli_quit(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
963{
964 bcmcli_stop(session);
965 bcmcli_session_print(session, "CLI terminated by 'Quit' command\n");
966 status_bcm_cli_quit = BCMOS_TRUE;
967
968 return BCM_ERR_OK;
969}
970
971int get_status_bcm_cli_quit(void) {
972 return status_bcm_cli_quit;
973}
974
975bcmos_errno bcmolt_apiend_cli_init() {
976 bcmos_errno ret;
977 bcmos_task_parm bal_cli_task_p = {};
978 bcmos_task_parm bal_cli_task_p_dummy;
979
980 /** before creating the task, check if it is already created by the other half of BAL i.e. Core side */
Burak Gurdagc78b9e12019-11-29 11:14:51 +0000981 if (BCM_ERR_OK != bcmos_task_query(&bal_cli_thread, &bal_cli_task_p_dummy)) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000982 /* Create BAL CLI thread */
983 bal_cli_task_p.name = bal_cli_thread_name;
984 bal_cli_task_p.handler = _bal_apiend_cli_thread_handler;
985 bal_cli_task_p.priority = TASK_PRIORITY_CLI;
986
987 ret = bcmos_task_create(&bal_cli_thread, &bal_cli_task_p);
Burak Gurdagc78b9e12019-11-29 11:14:51 +0000988 if (BCM_ERR_OK != ret) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000989 bcmos_printf("Couldn't create BAL API end CLI thread\n");
990 return ret;
991 }
992 }
993}
994
Shad Ansari627b5782018-08-13 22:49:32 +0000995Status Enable_(int argc, char *argv[]) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +0000996 bcmos_errno err;
997 bcmolt_host_init_parms init_parms = {};
998 init_parms.transport.type = BCM_HOST_API_CONN_LOCAL;
999 unsigned int failed_enable_device_cnt = 0;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001000
Shad Ansariedef2132018-08-10 22:14:50 +00001001 if (!state.is_activated()) {
Shad Ansari627b5782018-08-13 22:49:32 +00001002
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001003 vendor_init();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001004 /* Initialize host subsystem */
1005 err = bcmolt_host_init(&init_parms);
1006 if (BCM_ERR_OK != err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001007 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to init OLT, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001008 return bcm_to_grpc_err(err, "Failed to init OLT");
1009 }
1010
1011 bcmcli_session_parm mon_session_parm;
1012 /* Create CLI session */
1013 memset(&mon_session_parm, 0, sizeof(mon_session_parm));
1014 mon_session_parm.get_prompt = openolt_cli_get_prompt_cb;
1015 mon_session_parm.access_right = BCMCLI_ACCESS_ADMIN;
1016 bcmos_errno rc = bcmcli_session_open(&mon_session_parm, &current_session);
1017 BUG_ON(rc != BCM_ERR_OK);
1018
1019 /* API CLI */
1020 bcm_openolt_api_cli_init(NULL, current_session);
1021
1022 /* Add quit command */
1023 BCMCLI_MAKE_CMD_NOPARM(NULL, "quit", "Quit", bcm_cli_quit);
1024
1025 err = bcmolt_apiend_cli_init();
1026 if (BCM_ERR_OK != err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001027 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to add apiend init, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001028 return bcm_to_grpc_err(err, "Failed to add apiend init");
1029 }
1030
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08001031 bcmos_fastlock_init(&data_lock, 0);
Girish Gowdra96461052019-11-22 20:13:59 +05301032 bcmos_fastlock_init(&alloc_cfg_wait_lock, 0);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001033 OPENOLT_LOG(INFO, openolt_log_id, "Enable OLT - %s-%s\n", VENDOR_ID, MODEL_ID);
Craig Lutgen967a1d02018-11-27 10:41:51 -06001034
Jason Huangbf45ffb2019-10-30 17:29:02 +08001035 //check BCM daemon is connected or not
1036 Status status = check_connection();
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001037 if (!status.ok()) {
Jason Huangbf45ffb2019-10-30 17:29:02 +08001038 return status;
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001039 }
Jason Huangbf45ffb2019-10-30 17:29:02 +08001040 else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001041 Status status = SubscribeIndication();
1042 if (!status.ok()) {
1043 OPENOLT_LOG(ERROR, openolt_log_id, "SubscribeIndication failed - %s : %s\n",
1044 grpc_status_code_to_string(status.error_code()).c_str(),
1045 status.error_message().c_str());
1046 return status;
1047 }
Jason Huangbf45ffb2019-10-30 17:29:02 +08001048
1049 //check BAL state in initial stage
1050 status = check_bal_ready();
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001051 if (!status.ok()) {
Jason Huangbf45ffb2019-10-30 17:29:02 +08001052 return status;
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001053 }
Jason Huangbf45ffb2019-10-30 17:29:02 +08001054 }
1055
1056 {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001057 bcmos_errno err;
1058 bcmolt_odid dev;
1059 OPENOLT_LOG(INFO, openolt_log_id, "Enabling PON %d Devices ... \n", BCM_MAX_DEVS_PER_LINE_CARD);
1060 for (dev = 0; dev < BCM_MAX_DEVS_PER_LINE_CARD; dev++) {
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001061 bcmolt_device_cfg dev_cfg = { };
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001062 bcmolt_device_key dev_key = { };
1063 dev_key.device_id = dev;
1064 BCMOLT_CFG_INIT(&dev_cfg, device, dev_key);
1065 BCMOLT_MSG_FIELD_GET(&dev_cfg, system_mode);
1066 err = bcmolt_cfg_get(dev_id, &dev_cfg.hdr);
Jason Huangbf45ffb2019-10-30 17:29:02 +08001067 if (err == BCM_ERR_NOT_CONNECTED) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001068 bcmolt_device_key key = {.device_id = dev};
1069 bcmolt_device_connect oper;
1070 BCMOLT_OPER_INIT(&oper, device, connect, key);
1071 if (MODEL_ID == "asfvolt16") {
1072 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mode, BCMOLT_INNI_MODE_ALL_10_G_XFI);
1073 BCMOLT_MSG_FIELD_SET (&oper, system_mode, BCMOLT_SYSTEM_MODE_XGS__2_X);
1074 } else if (MODEL_ID == "asgvolt64") {
1075 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mode, BCMOLT_INNI_MODE_ALL_10_G_XFI);
1076 BCMOLT_MSG_FIELD_SET(&oper, inni_config.mux, BCMOLT_INNI_MUX_FOUR_TO_ONE);
1077 BCMOLT_MSG_FIELD_SET (&oper, system_mode, BCMOLT_SYSTEM_MODE_GPON__16_X);
1078 }
1079 err = bcmolt_oper_submit(dev_id, &oper.hdr);
1080 if (err) {
1081 failed_enable_device_cnt ++;
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001082 OPENOLT_LOG(ERROR, openolt_log_id, "Enable PON device %d failed, err = %s\n", dev, bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001083 if (failed_enable_device_cnt == BCM_MAX_DEVS_PER_LINE_CARD) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001084 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to enable all the pon ports, err = %s\n", bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001085 return Status(grpc::StatusCode::INTERNAL, "Failed to activate all PON ports");
1086 }
1087 }
1088 bcmos_usleep(200000);
1089 }
1090 else {
1091 OPENOLT_LOG(WARNING, openolt_log_id, "PON deivce %d already connected\n", dev);
1092 state.activate();
1093 }
1094 }
1095 init_stats();
Shad Ansari627b5782018-08-13 22:49:32 +00001096 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001097 }
Shad Ansariedef2132018-08-10 22:14:50 +00001098
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001099 /* Start CLI */
1100 OPENOLT_LOG(INFO, def_log_id, "Starting CLI\n");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001101 //If already enabled, generate an extra indication ????
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001102 return Status::OK;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001103}
1104
1105Status Disable_() {
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001106 //In the earlier implementation Disabling olt is done by disabling the NNI port associated with that.
1107 //In inband scenario instead of using management interface to establish connection with adapter ,NNI interface will be used.
1108 //Disabling NNI port on olt disable causes connection loss between adapter and agent.
1109 //To overcome this disable is implemented by disabling all the PON ports
1110 //associated with the device so as to support both in-band
1111 //and out of band scenarios.
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001112
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001113 Status status;
1114 int failedCount = 0;
1115 for (int i = 0; i < NumPonIf_(); i++) {
1116 status = DisablePonIf_(i);
1117 if (!status.ok()) {
1118 failedCount+=1;
1119 BCM_LOG(ERROR, openolt_log_id, "Failed to disable PON interface: %d\n", i);
1120 }
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001121 }
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001122 if (failedCount == 0) {
1123 state.deactivate();
1124 openolt::Indication ind;
1125 openolt::OltIndication* olt_ind = new openolt::OltIndication;
1126 olt_ind->set_oper_state("down");
1127 ind.set_allocated_olt_ind(olt_ind);
1128 BCM_LOG(INFO, openolt_log_id, "Disable OLT, add an extra indication\n");
1129 oltIndQ.push(ind);
1130 return Status::OK;
1131 }
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001132 if (failedCount ==NumPonIf_()) {
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001133 return grpc::Status(grpc::StatusCode::INTERNAL, "failed to disable olt ,all the PON ports are still in enabled state");
1134 }
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001135
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001136 return grpc::Status(grpc::StatusCode::UNKNOWN, "failed to disable olt ,few PON ports are still in enabled state");
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001137}
1138
1139Status Reenable_() {
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001140 Status status;
1141 int failedCount = 0;
1142 for (int i = 0; i < NumPonIf_(); i++) {
1143 status = EnablePonIf_(i);
1144 if (!status.ok()) {
1145 failedCount+=1;
1146 BCM_LOG(ERROR, openolt_log_id, "Failed to enable PON interface: %d\n", i);
1147 }
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001148 }
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001149 if (failedCount == 0) {
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001150 state.activate();
1151 openolt::Indication ind;
1152 openolt::OltIndication* olt_ind = new openolt::OltIndication;
1153 olt_ind->set_oper_state("up");
1154 ind.set_allocated_olt_ind(olt_ind);
1155 BCM_LOG(INFO, openolt_log_id, "Reenable OLT, add an extra indication\n");
1156 oltIndQ.push(ind);
1157 return Status::OK;
1158 }
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001159 if (failedCount ==NumPonIf_()) {
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001160 return grpc::Status(grpc::StatusCode::INTERNAL, "failed to re-enable olt ,all the PON ports are still in disabled state");
1161 }
1162 return grpc::Status(grpc::StatusCode::UNKNOWN, "failed to re-enable olt ,few PON ports are still in disabled state");
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001163}
1164
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001165bcmos_errno get_pon_interface_status(bcmolt_interface pon_ni, bcmolt_interface_state *state) {
1166 bcmos_errno err;
1167 bcmolt_pon_interface_key pon_key;
1168 bcmolt_pon_interface_cfg pon_cfg;
1169 pon_key.pon_ni = pon_ni;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001170
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001171 BCMOLT_CFG_INIT(&pon_cfg, pon_interface, pon_key);
1172 BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, state);
1173 BCMOLT_FIELD_SET_PRESENT(&pon_cfg.data, pon_interface_cfg_data, itu);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05001174 #ifdef TEST_MODE
1175 // It is impossible to mock the setting of pon_cfg.data.state because
1176 // the actual bcmolt_cfg_get passes the address of pon_cfg.hdr and we cannot
1177 // set the pon_cfg.data.state. So a new stub function is created and address
1178 // of pon_cfg is passed. This is one-of case where we need to add test specific
1179 // code in production code.
1180 err = bcmolt_cfg_get__pon_intf_stub(dev_id, &pon_cfg);
1181 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001182 err = bcmolt_cfg_get(dev_id, &pon_cfg.hdr);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05001183 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001184 *state = pon_cfg.data.state;
1185 return err;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001186}
1187
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001188inline uint64_t get_flow_status(uint16_t flow_id, uint16_t flow_type, uint16_t data_id) {
1189 bcmos_errno err;
1190 bcmolt_flow_key flow_key;
1191 bcmolt_flow_cfg flow_cfg;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001192
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001193 flow_key.flow_id = flow_id;
1194 flow_key.flow_type = (bcmolt_flow_type)flow_type;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001195
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001196 BCMOLT_CFG_INIT(&flow_cfg, flow, flow_key);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001197
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001198 switch (data_id) {
1199 case ONU_ID: //onu_id
1200 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, onu_id);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001201 #ifdef TEST_MODE
1202 // It is impossible to mock the setting of flow_cfg.data.state because
1203 // the actual bcmolt_cfg_get passes the address of flow_cfg.hdr and we cannot
1204 // set the flow_cfg.data. So a new stub function is created and address
1205 // of flow_cfg is passed. This is one-of case where we need to add test specific
1206 // code in production code.
1207 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1208 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001209 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001210 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001211 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001212 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get onu_id, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001213 return err;
1214 }
1215 return flow_cfg.data.onu_id;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001216 case FLOW_TYPE:
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001217 #ifdef TEST_MODE
1218 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1219 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001220 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001221 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001222 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001223 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get flow_type, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001224 return err;
1225 }
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001226 return flow_cfg.key.flow_type;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001227 case SVC_PORT_ID: //svc_port_id
1228 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, svc_port_id);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001229 #ifdef TEST_MODE
1230 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1231 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001232 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001233 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001234 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001235 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get svc_port_id, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001236 return err;
1237 }
1238 return flow_cfg.data.svc_port_id;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001239 case PRIORITY:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001240 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, priority);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001241 #ifdef TEST_MODE
1242 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1243 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001244 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001245 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001246 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001247 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get priority, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001248 return err;
1249 }
1250 return flow_cfg.data.priority;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001251 case COOKIE: //cookie
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001252 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, cookie);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001253 #ifdef TEST_MODE
1254 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1255 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001256 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001257 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001258 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001259 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get cookie, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001260 return err;
1261 }
1262 return flow_cfg.data.cookie;
1263 case INGRESS_INTF_TYPE: //ingress intf_type
1264 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, ingress_intf);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001265 #ifdef TEST_MODE
1266 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1267 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001268 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001269 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001270 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001271 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get ingress intf_type, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001272 return err;
1273 }
1274 return flow_cfg.data.ingress_intf.intf_type;
1275 case EGRESS_INTF_TYPE: //egress intf_type
1276 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_intf);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001277 #ifdef TEST_MODE
1278 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1279 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001280 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001281 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001282 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001283 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress intf_type, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001284 return err;
1285 }
1286 return flow_cfg.data.egress_intf.intf_type;
1287 case INGRESS_INTF_ID: //ingress intf_id
1288 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, ingress_intf);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001289 #ifdef TEST_MODE
1290 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1291 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001292 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001293 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001294 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001295 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get ingress intf_id, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001296 return err;
1297 }
1298 return flow_cfg.data.ingress_intf.intf_id;
1299 case EGRESS_INTF_ID: //egress intf_id
1300 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_intf);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001301 #ifdef TEST_MODE
1302 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1303 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001304 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001305 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001306 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001307 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress intf_id, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001308 return err;
1309 }
1310 return flow_cfg.data.egress_intf.intf_id;
1311 case CLASSIFIER_O_VID:
1312 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001313 #ifdef TEST_MODE
1314 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1315 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001316 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001317 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001318 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001319 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier o_vid, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001320 return err;
1321 }
1322 return flow_cfg.data.classifier.o_vid;
1323 case CLASSIFIER_O_PBITS:
1324 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001325 #ifdef TEST_MODE
1326 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1327 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001328 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001329 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001330 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001331 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier o_pbits, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001332 return err;
1333 }
1334 return flow_cfg.data.classifier.o_pbits;
1335 case CLASSIFIER_I_VID:
1336 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001337 #ifdef TEST_MODE
1338 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1339 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001340 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001341 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001342 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001343 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier i_vid, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001344 return err;
1345 }
1346 return flow_cfg.data.classifier.i_vid;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001347 case CLASSIFIER_I_PBITS:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001348 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001349 #ifdef TEST_MODE
1350 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1351 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001352 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001353 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001354 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001355 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier i_pbits, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001356 return err;
1357 }
1358 return flow_cfg.data.classifier.i_pbits;
1359 case CLASSIFIER_ETHER_TYPE:
1360 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001361 #ifdef TEST_MODE
1362 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1363 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001364 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001365 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001366 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001367 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier ether_type, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001368 return err;
1369 }
1370 return flow_cfg.data.classifier.ether_type;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001371 case CLASSIFIER_IP_PROTO:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001372 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001373 #ifdef TEST_MODE
1374 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1375 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001376 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001377 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001378 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001379 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier ip_proto, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001380 return err;
1381 }
1382 return flow_cfg.data.classifier.ip_proto;
1383 case CLASSIFIER_SRC_PORT:
1384 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001385 #ifdef TEST_MODE
1386 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1387 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001388 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001389 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001390 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001391 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier src_port, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001392 return err;
1393 }
1394 return flow_cfg.data.classifier.src_port;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001395 case CLASSIFIER_DST_PORT:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001396 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001397 #ifdef TEST_MODE
1398 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1399 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001400 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001401 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001402 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001403 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier dst_port, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001404 return err;
1405 }
1406 return flow_cfg.data.classifier.dst_port;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001407 case CLASSIFIER_PKT_TAG_TYPE:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001408 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, classifier);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001409 #ifdef TEST_MODE
1410 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1411 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001412 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001413 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001414 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001415 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get classifier pkt_tag_type, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001416 return err;
1417 }
1418 return flow_cfg.data.classifier.pkt_tag_type;
1419 case EGRESS_QOS_TYPE:
1420 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001421 #ifdef TEST_MODE
1422 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1423 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001424 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001425 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001426 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001427 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos type, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001428 return err;
1429 }
1430 return flow_cfg.data.egress_qos.type;
1431 case EGRESS_QOS_QUEUE_ID:
1432 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001433 #ifdef TEST_MODE
1434 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1435 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001436 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001437 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001438 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001439 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos queue_id, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001440 return err;
1441 }
1442 switch (flow_cfg.data.egress_qos.type) {
1443 case BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE:
1444 return flow_cfg.data.egress_qos.u.fixed_queue.queue_id;
1445 case BCMOLT_EGRESS_QOS_TYPE_TC_TO_QUEUE:
1446 return flow_cfg.data.egress_qos.u.tc_to_queue.tc_to_queue_id;
1447 case BCMOLT_EGRESS_QOS_TYPE_PBIT_TO_TC:
1448 return flow_cfg.data.egress_qos.u.pbit_to_tc.tc_to_queue_id;
1449 case BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE:
1450 return flow_cfg.data.egress_qos.u.priority_to_queue.tm_q_set_id;
1451 case BCMOLT_EGRESS_QOS_TYPE_NONE:
1452 default:
1453 return -1;
1454 }
1455 case EGRESS_QOS_TM_SCHED_ID:
1456 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, egress_qos);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001457 #ifdef TEST_MODE
1458 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1459 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001460 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001461 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001462 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001463 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get egress_qos tm_sched_id, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001464 return err;
1465 }
1466 return flow_cfg.data.egress_qos.tm_sched.id;
1467 case ACTION_CMDS_BITMASK:
1468 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001469 #ifdef TEST_MODE
1470 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1471 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001472 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001473 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001474 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001475 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action cmds_bitmask, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001476 return err;
1477 }
1478 return flow_cfg.data.action.cmds_bitmask;
1479 case ACTION_O_VID:
1480 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001481 #ifdef TEST_MODE
1482 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1483 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001484 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001485 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001486 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001487 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action o_vid, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001488 return err;
1489 }
1490 return flow_cfg.data.action.o_vid;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001491 case ACTION_O_PBITS:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001492 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001493 #ifdef TEST_MODE
1494 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1495 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001496 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001497 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001498 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001499 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action o_pbits, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001500 return err;
1501 }
1502 return flow_cfg.data.action.o_pbits;
1503 case ACTION_I_VID:
1504 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001505 #ifdef TEST_MODE
1506 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1507 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001508 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001509 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001510 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001511 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action i_vid, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001512 return err;
1513 }
1514 return flow_cfg.data.action.i_vid;
1515 case ACTION_I_PBITS:
1516 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, action);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001517 #ifdef TEST_MODE
1518 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1519 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001520 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001521 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001522 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001523 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get action i_pbits, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001524 return err;
1525 }
1526 return flow_cfg.data.action.i_pbits;
1527 case STATE:
1528 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, state);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001529 #ifdef TEST_MODE
1530 err = bcmolt_cfg_get__flow_stub(dev_id, &flow_cfg);
1531 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001532 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05001533 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001534 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001535 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get state, err = %s\n",bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001536 return err;
1537 }
1538 return flow_cfg.data.state;
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001539 case GROUP_ID:
1540 BCMOLT_FIELD_SET_PRESENT(&flow_cfg.data, flow_cfg_data, group_id);
1541 err = bcmolt_cfg_get(dev_id, &flow_cfg.hdr);
1542 if (err) {
1543 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get group_id, err = %s\n",bcmos_strerror(err));
1544 return err;
1545 }
1546 return flow_cfg.data.group_id;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001547 default:
1548 return BCM_ERR_INTERNAL;
1549 }
1550
1551 return err;
1552}
1553
1554Status EnablePonIf_(uint32_t intf_id) {
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001555 bcmos_errno err = BCM_ERR_OK;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001556 bcmolt_pon_interface_cfg interface_obj;
1557 bcmolt_pon_interface_key intf_key = {.pon_ni = (bcmolt_interface)intf_id};
1558 bcmolt_pon_interface_set_pon_interface_state pon_interface_set_state;
1559 bcmolt_interface_state state;
1560
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001561 err = get_pon_interface_status((bcmolt_interface)intf_id, &state);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001562 if (err == BCM_ERR_OK) {
1563 if (state == BCMOLT_INTERFACE_STATE_ACTIVE_WORKING) {
Jason Huangbf45ffb2019-10-30 17:29:02 +08001564 OPENOLT_LOG(WARNING, openolt_log_id, "PON interface: %d already enabled\n", intf_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001565 return Status::OK;
1566 }
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001567 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001568 BCMOLT_CFG_INIT(&interface_obj, pon_interface, intf_key);
1569 BCMOLT_OPER_INIT(&pon_interface_set_state, pon_interface, set_pon_interface_state, intf_key);
1570 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.control, BCMOLT_CONTROL_STATE_ENABLE);
1571 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.interval, 5000);
1572 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.onu_post_discovery_mode,
1573 BCMOLT_ONU_POST_DISCOVERY_MODE_ACTIVATE);
1574 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.los, true);
1575 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.onu_alarms, true);
1576 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.tiwi, true);
1577 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.ack_timeout, true);
1578 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.sfi, true);
1579 BCMOLT_MSG_FIELD_SET(&interface_obj, itu.automatic_onu_deactivation.loki, true);
1580 BCMOLT_FIELD_SET(&pon_interface_set_state.data, pon_interface_set_pon_interface_state_data,
1581 operation, BCMOLT_INTERFACE_OPERATION_ACTIVE_WORKING);
1582
1583 err = bcmolt_cfg_set(dev_id, &interface_obj.hdr);
1584 if (err != BCM_ERR_OK) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001585 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to enable discovery onu, PON interface %d, err = %s\n", intf_id, bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001586 return bcm_to_grpc_err(err, "Failed to enable discovery onu");
1587 }
1588 err = bcmolt_oper_submit(dev_id, &pon_interface_set_state.hdr);
1589 if (err != BCM_ERR_OK) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001590 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to enable PON interface: %d, err = %s\n", intf_id, bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001591 return bcm_to_grpc_err(err, "Failed to enable PON interface");
1592 }
1593 else {
1594 OPENOLT_LOG(INFO, openolt_log_id, "Successfully enabled PON interface: %d\n", intf_id);
1595 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for PON interface: %d\n", intf_id);
1596 CreateDefaultSched(intf_id, downstream);
1597 CreateDefaultQueue(intf_id, downstream);
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001598 }
1599
1600 return Status::OK;
1601}
1602
Amit Ghoshfcad4d32019-11-13 10:24:55 +00001603/* Same as bcmolt_cfg_get but with added logic of retrying the API
1604 in case of some specific failures like timeout or object not yet ready
1605*/
1606bcmos_errno bcmolt_cfg_get_mult_retry(bcmolt_oltid olt, bcmolt_cfg *cfg) {
1607 bcmos_errno err;
1608 uint32_t current_try = 0;
1609
1610 while (current_try < MAX_BAL_API_RETRY_COUNT) {
1611 err = bcmolt_cfg_get(olt, cfg);
1612 current_try++;
1613
1614 if (err == BCM_ERR_STATE || err == BCM_ERR_TIMEOUT) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001615 OPENOLT_LOG(WARNING, openolt_log_id, "bcmolt_cfg_get: err = %s\n", bcmos_strerror(err));
Amit Ghoshfcad4d32019-11-13 10:24:55 +00001616 bcmos_usleep(BAL_API_RETRY_TIME_IN_USECS);
1617 continue;
1618 }
1619 else {
1620 break;
1621 }
1622 }
1623
1624 if (err != BCM_ERR_OK) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001625 OPENOLT_LOG(ERROR, openolt_log_id, "bcmolt_cfg_get tried (%d) times with retry time(%d usecs) err = %s\n",
Amit Ghoshfcad4d32019-11-13 10:24:55 +00001626 current_try,
1627 BAL_API_RETRY_TIME_IN_USECS,
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001628 bcmos_strerror(err));
Amit Ghoshfcad4d32019-11-13 10:24:55 +00001629 }
1630 return err;
1631}
1632
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001633Status ProbeDeviceCapabilities_() {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001634 bcmos_errno err;
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001635 bcmolt_device_cfg dev_cfg = { };
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001636 bcmolt_device_key dev_key = { };
1637 bcmolt_olt_cfg olt_cfg = { };
1638 bcmolt_olt_key olt_key = { };
1639 bcmolt_topology_map topo_map[BCM_MAX_PONS_PER_OLT] = { };
1640 bcmolt_topology topo = { };
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001641
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001642 topo.topology_maps.len = BCM_MAX_PONS_PER_OLT;
1643 topo.topology_maps.arr = &topo_map[0];
1644 BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
1645 BCMOLT_MSG_FIELD_GET(&olt_cfg, bal_state);
1646 BCMOLT_FIELD_SET_PRESENT(&olt_cfg.data, olt_cfg_data, topology);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001647 BCMOLT_CFG_LIST_BUF_SET(&olt_cfg, olt, topo.topology_maps.arr,
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001648 sizeof(bcmolt_topology_map) * topo.topology_maps.len);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001649 #ifdef TEST_MODE
1650 // It is impossible to mock the setting of olt_cfg.data.bal_state because
1651 // the actual bcmolt_cfg_get passes the address of olt_cfg.hdr and we cannot
1652 // set the olt_cfg.data.topology. So a new stub function is created and address
1653 // of olt_cfg is passed. This is one-of case where we need to test add specific
1654 // code in production code.
1655 err = bcmolt_cfg_get__olt_topology_stub(dev_id, &olt_cfg);
1656 #else
Amit Ghoshfcad4d32019-11-13 10:24:55 +00001657 err = bcmolt_cfg_get_mult_retry(dev_id, &olt_cfg.hdr);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001658 #endif
1659 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001660 OPENOLT_LOG(ERROR, openolt_log_id, "cfg: Failed to query OLT topology, err = %s\n", bcmos_strerror(err));
Amit Ghoshfcad4d32019-11-13 10:24:55 +00001661 return bcm_to_grpc_err(err, "cfg: Failed to query OLT topology");
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001662 }
1663
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001664 num_of_nni_ports = olt_cfg.data.topology.num_switch_ports;
1665 num_of_pon_ports = olt_cfg.data.topology.topology_maps.len;
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001666
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001667 OPENOLT_LOG(INFO, openolt_log_id, "OLT capabilitites, oper_state: %s\n",
1668 olt_cfg.data.bal_state == BCMOLT_BAL_STATE_BAL_AND_SWITCH_READY
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001669 ? "up" : "down");
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001670
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001671 OPENOLT_LOG(INFO, openolt_log_id, "topology nni: %d pon: %d dev: %d\n",
1672 num_of_nni_ports,
1673 num_of_pon_ports,
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001674 BCM_MAX_DEVS_PER_LINE_CARD);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001675
Amit Ghoshfcad4d32019-11-13 10:24:55 +00001676 uint32_t num_failed_cfg_gets = 0;
Jason Huang09b73ea2020-01-08 17:52:05 +08001677 static std::string openolt_version = firmware_version;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001678 for (int devid = 0; devid < BCM_MAX_DEVS_PER_LINE_CARD; devid++) {
1679 dev_key.device_id = devid;
1680 BCMOLT_CFG_INIT(&dev_cfg, device, dev_key);
1681 BCMOLT_MSG_FIELD_GET(&dev_cfg, firmware_sw_version);
1682 BCMOLT_MSG_FIELD_GET(&dev_cfg, chip_family);
1683 BCMOLT_MSG_FIELD_GET(&dev_cfg, system_mode);
Amit Ghoshfcad4d32019-11-13 10:24:55 +00001684 err = bcmolt_cfg_get_mult_retry(dev_id, &dev_cfg.hdr);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001685 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001686 OPENOLT_LOG(WARNING, openolt_log_id,"Failed to query PON MAC Device %d (errno = %s). Skipping the device.\n", devid, bcmos_strerror(err));
Amit Ghoshfcad4d32019-11-13 10:24:55 +00001687 num_failed_cfg_gets++;
1688 continue;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001689 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001690
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001691 std::string bal_version;
1692 bal_version += std::to_string(dev_cfg.data.firmware_sw_version.major)
1693 + "." + std::to_string(dev_cfg.data.firmware_sw_version.minor)
1694 + "." + std::to_string(dev_cfg.data.firmware_sw_version.revision);
Jason Huang09b73ea2020-01-08 17:52:05 +08001695 firmware_version = "BAL." + bal_version + "__" + openolt_version;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001696
1697 switch(dev_cfg.data.system_mode) {
1698 case 10: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*4,(devid+1)*4,"GPON"); break;
1699 case 11: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*8,(devid+1)*8,"GPON"); break;
1700 case 12: board_technology = "GPON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"GPON"); break;
1701 case 13: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,"XGPON"); break;
1702 case 14: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*4,(devid+1)*4,"XGPON"); break;
1703 case 15: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*8,(devid+1)*8,"XGPON"); break;
1704 case 16: board_technology = "XGPON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"XGPON"); break;
1705 case 18: board_technology = "XGS-PON"; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,"XGS-PON"); break;
1706 case 19: board_technology = "XGS-PON"; FILL_ARRAY(intf_technologies,devid*16,(devid+1)*16,"XGS-PON"); break;
1707 case 20: board_technology = MIXED_TECH; FILL_ARRAY(intf_technologies,devid*2,(devid+1)*2,MIXED_TECH); break;
1708 }
1709
1710 switch(dev_cfg.data.chip_family) {
Jason Huang09b73ea2020-01-08 17:52:05 +08001711 case BCMOLT_CHIP_FAMILY_CHIP_FAMILY_6862_X: chip_family = "Maple"; break;
1712 case BCMOLT_CHIP_FAMILY_CHIP_FAMILY_6865_X: chip_family = "Aspen"; break;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001713 }
1714
Jason Huang09b73ea2020-01-08 17:52:05 +08001715 OPENOLT_LOG(INFO, openolt_log_id, "device %d, pon: %d, version %s, family: %s, board_technology: %s\n",
1716 devid, BCM_MAX_PONS_PER_DEV, bal_version.c_str(), chip_family.c_str(), board_technology.c_str());
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001717
1718 bcmos_usleep(500000);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001719 }
1720
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001721 /* If all the devices returned errors then we tell the caller that this is an error else we work with
Amit Ghoshfcad4d32019-11-13 10:24:55 +00001722 only the devices that retured success*/
1723 if (num_failed_cfg_gets == BCM_MAX_DEVS_PER_LINE_CARD) {
1724 OPENOLT_LOG(ERROR, openolt_log_id, "device: Query of all the devices failed\n");
1725 return bcm_to_grpc_err(err, "device: All devices failed query");
1726 }
1727
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001728 return Status::OK;
1729}
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001730#if 0
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001731Status ProbePonIfTechnology_() {
1732 // Probe maximum extent possible as configured into BAL driver to determine
1733 // which are active in the current BAL topology. And for those
1734 // that are active, determine each port's access technology, i.e. "gpon" or "xgspon".
1735 for (uint32_t intf_id = 0; intf_id < num_of_pon_ports; ++intf_id) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001736 bcmolt_pon_interface_cfg interface_obj;
1737 bcmolt_pon_interface_key interface_key;
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001738
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001739 interface_key.pon_ni = intf_id;
1740 BCMOLT_CFG_INIT(&interface_obj, pon_interface, interface_key);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001741 if (board_technology == "XGS-PON"
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001742 BCMOLT_MSG_FIELD_GET(&interface_obj, xgs_ngpon2_trx);
1743 else if (board_technology == "GPON")
1744 BCMOLT_MSG_FIELD_GET(&interface_obj, gpon_trx);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001745
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001746 bcmos_errno err = bcmolt_cfg_get(dev_id, &interface_obj.hdr);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001747 if (err != BCM_ERR_OK) {
Craig Lutgenb2601f02018-10-23 13:04:31 -05001748 intf_technologies[intf_id] = UNKNOWN_TECH;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001749 if(err != BCM_ERR_RANGE) OPENOLT_LOG(ERROR, openolt_log_id, "Failed to get PON config: %d err %d\n", intf_id, err);
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001750 }
1751 else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001752 if (board_technology == "XGS-PON") {
1753 switch(interface_obj.data.xgpon_trx.transceiver_type) {
1754 case BCMOLT_XGPON_TRX_TYPE_LTH_7222_PC:
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001755 case BCMOLT_XGPON_TRX_TYPE_WTD_RTXM266_702:
1756 case BCMOLT_XGPON_TRX_TYPE_LTH_7222_BC_PLUS:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001757 case BCMOLT_XGPON_TRX_TYPE_LTH_7226_PC:
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001758 case BCMOLT_XGPON_TRX_TYPE_LTH_5302_PC:
1759 case BCMOLT_XGPON_TRX_TYPE_LTH_7226_A_PC_PLUS:
1760 case BCMOLT_XGPON_TRX_TYPE_D272RR_SSCB_DM:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001761 intf_technologies[intf_id] = "XGS-PON";
1762 break;
1763 }
1764 } else if (board_technology == "GPON") {
1765 switch(interface_obj.data.gpon_trx.transceiver_type) {
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001766 case BCMOLT_TRX_TYPE_SPS_43_48_H_HP_CDE_SD_2013:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001767 case BCMOLT_TRX_TYPE_LTE_3680_M:
1768 case BCMOLT_TRX_TYPE_SOURCE_PHOTONICS:
1769 case BCMOLT_TRX_TYPE_LTE_3680_P_TYPE_C_PLUS:
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001770 case BCMOLT_TRX_TYPE_LTE_3680_P_BC:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001771 intf_technologies[intf_id] = "GPON";
1772 break;
1773 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001774 }
Craig Lutgenb2601f02018-10-23 13:04:31 -05001775
1776 if (board_technology != UNKNOWN_TECH) {
1777 board_technology = intf_technologies[intf_id];
1778 } else if (board_technology != MIXED_TECH && board_technology != intf_technologies[intf_id]) {
1779 intf_technologies[intf_id] = MIXED_TECH;
1780 }
1781
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001782 }
1783 }
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001784 return Status::OK;
1785}
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001786#endif
Craig Lutgen88a22ad2018-10-04 12:30:46 -05001787unsigned NumNniIf_() {return num_of_nni_ports;}
1788unsigned NumPonIf_() {return num_of_pon_ports;}
1789
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001790bcmos_errno get_nni_interface_status(bcmolt_interface id, bcmolt_interface_state *state) {
1791 bcmos_errno err;
1792 bcmolt_nni_interface_key nni_key;
1793 bcmolt_nni_interface_cfg nni_cfg;
1794 nni_key.id = id;
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001795
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001796 BCMOLT_CFG_INIT(&nni_cfg, nni_interface, nni_key);
1797 BCMOLT_FIELD_SET_PRESENT(&nni_cfg.data, nni_interface_cfg_data, state);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05001798 #ifdef TEST_MODE
1799 // It is impossible to mock the setting of nni_cfg.data.state because
1800 // the actual bcmolt_cfg_get passes the address of nni_cfg.hdr and we cannot
1801 // set the nni_cfg.data.state. So a new stub function is created and address
1802 // of nni_cfg is passed. This is one-of case where we need to add test specific
1803 // code in production code.
1804 err = bcmolt_cfg_get__nni_intf_stub(dev_id, &nni_cfg);
1805 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001806 err = bcmolt_cfg_get(dev_id, &nni_cfg.hdr);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05001807 #endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001808 *state = nni_cfg.data.state;
1809 return err;
1810}
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001811
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001812Status SetStateUplinkIf_(uint32_t intf_id, bool set_state) {
Burak Gurdagc78b9e12019-11-29 11:14:51 +00001813 bcmos_errno err = BCM_ERR_OK;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001814 bcmolt_nni_interface_key intf_key = {.id = (bcmolt_interface)intf_id};
1815 bcmolt_nni_interface_set_nni_state nni_interface_set_state;
1816 bcmolt_interface_state state;
Craig Lutgend0bae9b2018-10-18 18:02:07 -05001817
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001818 err = get_nni_interface_status((bcmolt_interface)intf_id, &state);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001819 if (err == BCM_ERR_OK) {
1820 if (set_state && state == BCMOLT_INTERFACE_STATE_ACTIVE_WORKING) {
Jason Huangbf45ffb2019-10-30 17:29:02 +08001821 OPENOLT_LOG(WARNING, openolt_log_id, "NNI interface: %d already enabled\n", intf_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001822 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for NNI interface: %d\n", intf_id);
1823 CreateDefaultSched(intf_id, upstream);
1824 CreateDefaultQueue(intf_id, upstream);
1825 return Status::OK;
1826 } else if (!set_state && state == BCMOLT_INTERFACE_STATE_INACTIVE) {
1827 OPENOLT_LOG(INFO, openolt_log_id, "NNI interface: %d already disabled\n", intf_id);
1828 return Status::OK;
1829 }
Craig Lutgend0bae9b2018-10-18 18:02:07 -05001830 }
1831
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001832 BCMOLT_OPER_INIT(&nni_interface_set_state, nni_interface, set_nni_state, intf_key);
1833 if (set_state) {
1834 BCMOLT_FIELD_SET(&nni_interface_set_state.data, nni_interface_set_nni_state_data,
1835 nni_state, BCMOLT_INTERFACE_OPERATION_ACTIVE_WORKING);
1836 } else {
1837 BCMOLT_FIELD_SET(&nni_interface_set_state.data, nni_interface_set_nni_state_data,
1838 nni_state, BCMOLT_INTERFACE_OPERATION_INACTIVE);
1839 }
1840 err = bcmolt_oper_submit(dev_id, &nni_interface_set_state.hdr);
1841 if (err != BCM_ERR_OK) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001842 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to %s NNI interface: %d, err = %s\n",
1843 (set_state)?"enable":"disable", intf_id, bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001844 return bcm_to_grpc_err(err, "Failed to enable NNI interface");
1845 }
1846 else {
1847 OPENOLT_LOG(INFO, openolt_log_id, "Successfully %s NNI interface: %d\n", (set_state)?"enable":"disable", intf_id);
1848 if (set_state) {
1849 OPENOLT_LOG(INFO, openolt_log_id, "Initializing tm sched creation for NNI interface: %d\n", intf_id);
1850 CreateDefaultSched(intf_id, upstream);
1851 CreateDefaultQueue(intf_id, upstream);
1852 }
Nicolas Palpacuere3fc0d22018-08-02 16:51:05 -04001853 }
1854
1855 return Status::OK;
1856}
1857
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001858Status DisablePonIf_(uint32_t intf_id) {
Chaitrashree G S73e084d2019-11-20 16:18:59 -05001859 bcmos_errno err;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001860 bcmolt_pon_interface_cfg interface_obj;
Chaitrashree G S73e084d2019-11-20 16:18:59 -05001861 bcmolt_pon_interface_key intf_key = {.pon_ni = (bcmolt_interface)intf_id};
1862 bcmolt_pon_interface_set_pon_interface_state pon_interface_set_state;
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001863
Chaitrashree G S73e084d2019-11-20 16:18:59 -05001864 BCMOLT_CFG_INIT(&interface_obj, pon_interface, intf_key);
1865 BCMOLT_OPER_INIT(&pon_interface_set_state, pon_interface, set_pon_interface_state, intf_key);
1866 BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.control, BCMOLT_CONTROL_STATE_DISABLE);
1867
1868 err = bcmolt_cfg_set(dev_id, &interface_obj.hdr);
1869 if (err != BCM_ERR_OK) {
1870 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to disable discovery of onu, PON interface %d, err %d\n", intf_id, err);
1871 return bcm_to_grpc_err(err, "Failed to disable discovery of onu");
1872 }
1873
1874 BCMOLT_FIELD_SET(&pon_interface_set_state.data, pon_interface_set_pon_interface_state_data,
1875 operation, BCMOLT_INTERFACE_OPERATION_INACTIVE);
1876
1877 err = bcmolt_oper_submit(dev_id, &pon_interface_set_state.hdr);
1878 if (err != BCM_ERR_OK) {
1879 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to disable PON interface: %d\n , err %d\n", intf_id, err);
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04001880 return bcm_to_grpc_err(err, "Failed to disable PON interface");
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001881 }
1882
Chaitrashree G S73e084d2019-11-20 16:18:59 -05001883 OPENOLT_LOG(INFO, openolt_log_id, "Successfully disabled PON interface: %d\n", intf_id);
Nicolas Palpacuer05ea0ea2018-07-06 11:47:21 -04001884 return Status::OK;
1885}
1886
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001887Status ActivateOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001888 const char *vendor_id, const char *vendor_specific, uint32_t pir) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001889 bcmos_errno err = BCM_ERR_OK;
1890 bcmolt_onu_cfg onu_cfg;
1891 bcmolt_onu_key onu_key;
1892 bcmolt_serial_number serial_number; /**< ONU serial number */
1893 bcmolt_bin_str_36 registration_id; /**< ONU registration ID */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001894
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001895 onu_key.onu_id = onu_id;
1896 onu_key.pon_ni = intf_id;
1897 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
1898 BCMOLT_FIELD_SET_PRESENT(&onu_cfg.data, onu_cfg_data, onu_state);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05001899 #ifdef TEST_MODE
1900 // It is impossible to mock the setting of onu_cfg.data.onu_state because
1901 // the actual bcmolt_cfg_get passes the address of onu_cfg.hdr and we cannot
1902 // set the onu_cfg.data.onu_state. So a new stub function is created and address
1903 // of onu_cfg is passed. This is one-of case where we need to add test specific
1904 // code in production code.
1905 err = bcmolt_cfg_get__onu_state_stub(dev_id, &onu_cfg);
1906 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001907 err = bcmolt_cfg_get(dev_id, &onu_cfg.hdr);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05001908 #endif
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001909 if (err == BCM_ERR_OK) {
1910 if ((onu_cfg.data.onu_state == BCMOLT_ONU_STATE_PROCESSING ||
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001911 onu_cfg.data.onu_state == BCMOLT_ONU_STATE_ACTIVE) ||
1912 (onu_cfg.data.onu_state == BCMOLT_ONU_STATE_INACTIVE &&
1913 onu_cfg.data.onu_old_state == BCMOLT_ONU_STATE_NOT_CONFIGURED))
1914 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001915 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001916
1917 OPENOLT_LOG(INFO, openolt_log_id, "Enabling ONU %d on PON %d : vendor id %s, \
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001918vendor specific %s, pir %d\n", onu_id, intf_id, vendor_id,
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001919 vendor_specific_to_str(vendor_specific).c_str(), pir);
1920
1921 memcpy(serial_number.vendor_id.arr, vendor_id, 4);
1922 memcpy(serial_number.vendor_specific.arr, vendor_specific, 4);
1923 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
1924 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.serial_number, serial_number);
1925 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.auto_learning, BCMOS_TRUE);
1926 /*set burst and data profiles to fec disabled*/
1927 if (board_technology == "XGS-PON") {
1928 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.xgpon.ranging_burst_profile, 2);
1929 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.xgpon.data_burst_profile, 1);
1930 } else if (board_technology == "GPON") {
1931 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.gpon.ds_ber_reporting_interval, 1000000);
1932 BCMOLT_MSG_FIELD_SET(&onu_cfg, itu.gpon.omci_port_id, onu_id);
1933 }
1934 err = bcmolt_cfg_set(dev_id, &onu_cfg.hdr);
1935 if (err != BCM_ERR_OK) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001936 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to set activate ONU %d on PON %d, err = %s\n", onu_id, intf_id, bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001937 return bcm_to_grpc_err(err, "Failed to activate ONU");
1938 }
1939
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001940 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00001941}
1942
Jonathan Davis70c21812018-07-19 15:32:10 -04001943Status DeactivateOnu_(uint32_t intf_id, uint32_t onu_id,
1944 const char *vendor_id, const char *vendor_specific) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001945 bcmos_errno err = BCM_ERR_OK;
1946 bcmolt_onu_set_onu_state onu_oper; /* declare main API struct */
1947 bcmolt_onu_cfg onu_cfg;
1948 bcmolt_onu_key onu_key; /**< Object key. */
1949 bcmolt_onu_state onu_state;
Jonathan Davis70c21812018-07-19 15:32:10 -04001950
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001951 onu_key.onu_id = onu_id;
1952 onu_key.pon_ni = intf_id;
1953 BCMOLT_CFG_INIT(&onu_cfg, onu, onu_key);
1954 BCMOLT_FIELD_SET_PRESENT(&onu_cfg.data, onu_cfg_data, onu_state);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05001955 #ifdef TEST_MODE
1956 // It is impossible to mock the setting of onu_cfg.data.onu_state because
1957 // the actual bcmolt_cfg_get passes the address of onu_cfg.hdr and we cannot
1958 // set the onu_cfg.data.onu_state. So a new stub function is created and address
1959 // of onu_cfg is passed. This is one-of case where we need to add test specific
1960 // code in production code.
1961 err = bcmolt_cfg_get__onu_state_stub(dev_id, &onu_cfg);
1962 onu_state = onu_cfg.data.onu_state;
1963 #else
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001964 err = bcmolt_cfg_get(dev_id, &onu_cfg.hdr);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05001965 #endif
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001966 if (err == BCM_ERR_OK) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001967 switch (onu_state) {
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05001968 case BCMOLT_ONU_STATE_ACTIVE:
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001969 BCMOLT_OPER_INIT(&onu_oper, onu, set_onu_state, onu_key);
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04001970 BCMOLT_FIELD_SET(&onu_oper.data, onu_set_onu_state_data,
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001971 onu_state, BCMOLT_ONU_OPERATION_INACTIVE);
1972 err = bcmolt_oper_submit(dev_id, &onu_oper.hdr);
1973 if (err != BCM_ERR_OK) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05001974 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to deactivate ONU %d on PON %d, err = %s\n", onu_id, intf_id, bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001975 return bcm_to_grpc_err(err, "Failed to deactivate ONU");
1976 }
1977 break;
1978 }
Jonathan Davis70c21812018-07-19 15:32:10 -04001979 }
1980
1981 return Status::OK;
1982}
1983
1984Status DeleteOnu_(uint32_t intf_id, uint32_t onu_id,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001985 const char *vendor_id, const char *vendor_specific) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001986
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00001987 OPENOLT_LOG(INFO, openolt_log_id, "DeleteOnu ONU %d on PON %d : vendor id %s, vendor specific %s\n",
Craig Lutgend0bae9b2018-10-18 18:02:07 -05001988 onu_id, intf_id, vendor_id, vendor_specific_to_str(vendor_specific).c_str());
1989
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001990 // Need to deactivate before removing it (BAL rules)
1991
1992 DeactivateOnu_(intf_id, onu_id, vendor_id, vendor_specific);
1993 // Sleep to allow the state to propagate
1994 // We need the subscriber terminal object to be admin down before removal
1995 // Without sleep the race condition is lost by ~ 20 ms
1996 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1997
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07001998 // TODO: Delete the schedulers and queues.
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04001999
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002000 bcmolt_onu_cfg cfg_obj;
2001 bcmolt_onu_key key;
Jonathan Davis70c21812018-07-19 15:32:10 -04002002
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05002003 //OPENOLT_LOG(INFO, openolt_log_id, "Processing subscriber terminal cfg clear for sub_term_id %d and intf_id %d\n",
2004 // onu_id, intf_id);
2005 OPENOLT_LOG(INFO, openolt_log_id, "Processing onu cfg clear for onu_id %d and intf_id %d\n",
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04002006 onu_id, intf_id);
Jonathan Davis70c21812018-07-19 15:32:10 -04002007
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002008 key.onu_id = onu_id;
2009 key.pon_ni = intf_id;
2010 BCMOLT_CFG_INIT(&cfg_obj, onu, key);
Jonathan Davis70c21812018-07-19 15:32:10 -04002011
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002012 bcmos_errno err = bcmolt_cfg_clear(dev_id, &cfg_obj.hdr);
Jonathan Davis70c21812018-07-19 15:32:10 -04002013 if (err != BCM_ERR_OK)
2014 {
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05002015 //OPENOLT_LOG(ERROR, openolt_log_id, "Failed to clear information for BAL subscriber_terminal_id %d, Interface ID %d, err = %s\n", onu_id, intf_id, bcmos_strerror(err));
2016 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to clear information for BAL onu_id %d, Interface ID %d, err = %s\n", onu_id, intf_id, bcmos_strerror(err));
Jonathan Davis70c21812018-07-19 15:32:10 -04002017 return Status(grpc::StatusCode::INTERNAL, "Failed to delete ONU");
2018 }
2019
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002020 return Status::OK;
Jonathan Davis70c21812018-07-19 15:32:10 -04002021}
2022
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002023#define MAX_CHAR_LENGTH 20
2024#define MAX_OMCI_MSG_LENGTH 44
2025Status OmciMsgOut_(uint32_t intf_id, uint32_t onu_id, const std::string pkt) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002026 bcmolt_bin_str buf = {};
2027 bcmolt_onu_cpu_packets omci_cpu_packets;
2028 bcmolt_onu_key key;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002029
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002030 key.pon_ni = intf_id;
2031 key.onu_id = onu_id;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002032
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002033 BCMOLT_OPER_INIT(&omci_cpu_packets, onu, cpu_packets, key);
2034 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, packet_type, BCMOLT_PACKET_TYPE_OMCI);
2035 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, calc_crc, BCMOS_TRUE);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002036
2037 // ???
2038 if ((pkt.size()/2) > MAX_OMCI_MSG_LENGTH) {
2039 buf.len = MAX_OMCI_MSG_LENGTH;
2040 } else {
2041 buf.len = pkt.size()/2;
2042 }
2043
2044 /* Send the OMCI packet using the BAL remote proxy API */
2045 uint16_t idx1 = 0;
2046 uint16_t idx2 = 0;
2047 uint8_t arraySend[buf.len];
2048 char str1[MAX_CHAR_LENGTH];
2049 char str2[MAX_CHAR_LENGTH];
2050 memset(&arraySend, 0, buf.len);
2051
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002052 for (idx1=0,idx2=0; idx1<((buf.len)*2); idx1++,idx2++) {
2053 sprintf(str1,"%c", pkt[idx1]);
2054 sprintf(str2,"%c", pkt[++idx1]);
2055 strcat(str1,str2);
2056 arraySend[idx2] = strtol(str1, NULL, 16);
2057 }
2058
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002059 buf.arr = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
2060 memcpy(buf.arr, (uint8_t *)arraySend, buf.len);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002061
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002062 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, number_of_packets, 1);
2063 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, packet_size, buf.len);
2064 BCMOLT_MSG_FIELD_SET(&omci_cpu_packets, buffer, buf);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002065
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002066 bcmos_errno err = bcmolt_oper_submit(dev_id, &omci_cpu_packets.hdr);
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04002067 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05002068 OPENOLT_LOG(ERROR, openolt_log_id, "Error sending OMCI message to ONU %d on PON %d, err = %s\n", onu_id, intf_id, bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002069 return bcm_to_grpc_err(err, "send OMCI failed");
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04002070 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002071 OPENOLT_LOG(DEBUG, omci_log_id, "OMCI request msg of length %d sent to ONU %d on PON %d : %s\n",
Craig Lutgen88a22ad2018-10-04 12:30:46 -05002072 buf.len, onu_id, intf_id, pkt.c_str());
Nicolas Palpacuer967438f2018-09-07 14:41:54 -04002073 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002074 free(buf.arr);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002075
2076 return Status::OK;
2077}
2078
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002079Status OnuPacketOut_(uint32_t intf_id, uint32_t onu_id, uint32_t port_no, uint32_t gemport_id, const std::string pkt) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002080 bcmolt_pon_interface_cpu_packets pon_interface_cpu_packets; /**< declare main API struct */
2081 bcmolt_pon_interface_key key = {.pon_ni = (bcmolt_interface)intf_id}; /**< declare key */
2082 bcmolt_bin_str buf = {};
2083 bcmolt_gem_port_id gem_port_id_array[1];
2084 bcmolt_gem_port_id_list_u8_max_16 gem_port_list = {};
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002085
Craig Lutgen967a1d02018-11-27 10:41:51 -06002086 if (port_no > 0) {
2087 bool found = false;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002088 if (gemport_id == 0) {
2089 bcmos_fastlock_lock(&data_lock);
2090 // Map the port_no to one of the flows that owns it to find a gemport_id for that flow.
2091 // Pick any flow that is mapped with the same port_no.
2092 std::map<uint32_t, std::set<uint32_t> >::const_iterator it = port_to_flows.find(port_no);
2093 if (it != port_to_flows.end() && !it->second.empty()) {
2094 uint32_t flow_id = *(it->second.begin()); // Pick any flow_id out of the bag set
2095 std::map<uint32_t, uint32_t>::const_iterator fit = flowid_to_gemport.find(flow_id);
2096 if (fit != flowid_to_gemport.end()) {
2097 found = true;
2098 gemport_id = fit->second;
2099 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06002100 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002101 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002102
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002103 if (!found) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002104 OPENOLT_LOG(ERROR, openolt_log_id, "Packet out failed to find destination for ONU %d port_no %u on PON %d\n",
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002105 onu_id, port_no, intf_id);
2106 return grpc::Status(grpc::StatusCode::NOT_FOUND, "no flow for port_no");
2107 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002108 OPENOLT_LOG(INFO, openolt_log_id, "Gem port %u found for ONU %d port_no %u on PON %d\n",
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002109 gemport_id, onu_id, port_no, intf_id);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002110 }
2111
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002112 gem_port_id_array[0] = gemport_id;
2113 gem_port_list.len = 1;
2114 gem_port_list.arr = gem_port_id_array;
2115 buf.len = pkt.size();
2116 buf.arr = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
2117 memcpy(buf.arr, (uint8_t *)pkt.data(), buf.len);
2118
2119 /* init the API struct */
2120 BCMOLT_OPER_INIT(&pon_interface_cpu_packets, pon_interface, cpu_packets, key);
2121 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, packet_type, BCMOLT_PACKET_TYPE_ETH);
2122 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, calc_crc, BCMOS_TRUE);
2123 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, gem_port_list, gem_port_list);
2124 BCMOLT_MSG_FIELD_SET(&pon_interface_cpu_packets, buffer, buf);
2125
2126 OPENOLT_LOG(INFO, openolt_log_id, "Packet out of length %d sent to gemport %d on pon %d port_no %u\n",
2127 (uint8_t)pkt.size(), gemport_id, intf_id, port_no);
2128
2129 /* call API */
2130 bcmolt_oper_submit(dev_id, &pon_interface_cpu_packets.hdr);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002131 }
2132 else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002133 //TODO: Port No is 0, it is coming sender requirement.
2134 OPENOLT_LOG(INFO, openolt_log_id, "port_no %d onu %d on pon %d\n",
2135 port_no, onu_id, intf_id);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002136 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002137 free(buf.arr);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002138
2139 return Status::OK;
2140}
2141
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04002142Status UplinkPacketOut_(uint32_t intf_id, const std::string pkt) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002143 bcmolt_flow_key key = {}; /* declare key */
2144 bcmolt_bin_str buffer = {};
2145 bcmolt_flow_send_eth_packet oper; /* declare main API struct */
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04002146
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002147 // TODO: flow_id is currently not passed in UplinkPacket message from voltha.
2148 bcmolt_flow_id flow_id = 0;
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04002149
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002150 //validate flow_id and find flow_id/flow type: upstream/ingress type: PON/egress type: NNI
2151 if (get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, FLOW_TYPE) == BCMOLT_FLOW_TYPE_UPSTREAM && \
2152 get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, INGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_PON && \
2153 get_flow_status(flow_id, BCMOLT_FLOW_TYPE_UPSTREAM, EGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_NNI)
2154 key.flow_id = flow_id;
2155 else {
Jason Huang09b73ea2020-01-08 17:52:05 +08002156 if (flow_id_counters) {
2157 std::map<flow_pair, int>::iterator it;
2158 for(it = flow_map.begin(); it != flow_map.end(); it++) {
2159 int flow_index = it->first.first;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002160 if (get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, FLOW_TYPE) == BCMOLT_FLOW_TYPE_UPSTREAM && \
2161 get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, INGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_PON && \
2162 get_flow_status(flow_index, BCMOLT_FLOW_TYPE_UPSTREAM, EGRESS_INTF_TYPE) == BCMOLT_FLOW_INTERFACE_TYPE_NNI) {
2163 key.flow_id = flow_index;
2164 break;
2165 }
2166 }
2167 }
2168 else {
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05002169 OPENOLT_LOG(ERROR, openolt_log_id, "no flow id found for uplink packetout\n");
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002170 return grpc::Status(grpc::StatusCode::NOT_FOUND, "no flow id found");
2171 }
2172 }
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04002173
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002174 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM; /* send from uplink direction */
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04002175
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002176 /* Initialize the API struct. */
2177 BCMOLT_OPER_INIT(&oper, flow, send_eth_packet, key);
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04002178
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002179 buffer.len = pkt.size();
2180 buffer.arr = (uint8_t *)malloc((buffer.len)*sizeof(uint8_t));
2181 memcpy(buffer.arr, (uint8_t *)pkt.data(), buffer.len);
2182 if (buffer.arr == NULL) {
2183 OPENOLT_LOG(ERROR, openolt_log_id, "allocate packet buffer failed\n");
2184 return bcm_to_grpc_err(BCM_ERR_PARM, "allocate packet buffer failed");
2185 }
2186 BCMOLT_FIELD_SET(&oper.data, flow_send_eth_packet_data, buffer, buffer);
2187
2188 bcmos_errno err = bcmolt_oper_submit(dev_id, &oper.hdr);
2189 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05002190 OPENOLT_LOG(ERROR, openolt_log_id, "Error sending packets via nni port %d, flow_id %d, err = %s\n", intf_id, key.flow_id, bcmos_strerror(err));
Thiyagarajan Subramani81c56112019-12-19 08:29:55 -05002191 return bcm_to_grpc_err(BCM_ERR_SYSCALL_ERR, "Error sending packets via nni port");
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002192 } else {
2193 OPENOLT_LOG(INFO, openolt_log_id, "sent packets to port %d in upstream direction, flow_id %d \n", intf_id, key.flow_id);
2194 }
Nicolas Palpacuerb78def42018-06-07 12:55:26 -04002195
2196 return Status::OK;
2197}
2198
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002199uint32_t GetPortNum_(uint32_t flow_id) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002200 bcmos_fastlock_lock(&data_lock);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002201 uint32_t port_no = 0;
2202 std::map<uint32_t, uint32_t >::const_iterator it = flowid_to_port.find(flow_id);
2203 if (it != flowid_to_port.end()) {
2204 port_no = it->second;
2205 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002206 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002207 return port_no;
2208}
2209
Jason Huang09b73ea2020-01-08 17:52:05 +08002210#define ACL_LOG(level,msg,err) \
2211 do { \
2212 OPENOLT_LOG(level, openolt_log_id, "--------> %s (acl_id %d) err: %d <--------\n", msg, key.id, err); \
2213 OPENOLT_LOG(level, openolt_log_id, "action_type %s\n", \
2214 GET_ACL_ACTION_TYPE(action_type)); \
2215 OPENOLT_LOG(level, openolt_log_id, "classifier(ether type %d), ip_proto %d, src_port %d, dst_port %d\n", \
2216 acl_key.ether_type, acl_key.ip_proto, acl_key.src_port, acl_key.dst_port); \
2217 } while(0)
2218
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002219#define FLOW_LOG(level,msg,err) \
2220 do { \
2221 OPENOLT_LOG(level, openolt_log_id, "--------> %s (flow_id %d) err: %d <--------\n", msg, key.flow_id, err); \
2222 OPENOLT_LOG(level, openolt_log_id, "intf_id %d, onu_id %d, uni_id %d, port_no %u, cookie %"PRIu64"\n", \
2223 access_intf_id, onu_id, uni_id, port_no, cookie); \
2224 OPENOLT_LOG(level, openolt_log_id, "flow_type %s, queue_id %d, sched_id %d\n", flow_type.c_str(), \
2225 cfg.data.egress_qos.u.fixed_queue.queue_id, cfg.data.egress_qos.tm_sched.id); \
2226 OPENOLT_LOG(level, openolt_log_id, "Ingress(intfd_type %s, intf_id %d), Egress(intf_type %s, intf_id %d)\n", \
2227 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), cfg.data.ingress_intf.intf_id, \
2228 GET_FLOW_INTERFACE_TYPE(cfg.data.egress_intf.intf_type), cfg.data.egress_intf.intf_id); \
2229 OPENOLT_LOG(level, openolt_log_id, "classifier(o_vid %d, o_pbits %d, i_vid %d, i_pbits %d, ether type 0x%x)\n", \
2230 c_val.o_vid, c_val.o_pbits, c_val.i_vid, c_val.i_pbits, classifier.eth_type()); \
2231 OPENOLT_LOG(level, openolt_log_id, "classifier(ip_proto 0x%x, gemport_id %d, src_port %d, dst_port %d, pkt_tag_type %s)\n", \
2232 c_val.ip_proto, gemport_id, c_val.src_port, c_val.dst_port, GET_PKT_TAG_TYPE(c_val.pkt_tag_type)); \
2233 OPENOLT_LOG(level, openolt_log_id, "action(cmds_bitmask %s, o_vid %d, o_pbits %d, i_vid %d, i_pbits %d)\n\n", \
2234 get_flow_acton_command(a_val.cmds_bitmask), a_val.o_vid, a_val.o_pbits, a_val.i_vid, a_val.i_pbits); \
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04002235 } while(0)
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002236
2237#define FLOW_PARAM_LOG() \
2238 do { \
2239 OPENOLT_LOG(INFO, openolt_log_id, "--------> flow comparison (now before) <--------\n"); \
2240 OPENOLT_LOG(INFO, openolt_log_id, "flow_id (%d %d)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002241 key.flow_id, it->first.first); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002242 OPENOLT_LOG(INFO, openolt_log_id, "onu_id (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002243 cfg.data.onu_id , get_flow_status(it->first.first, it->first.second, ONU_ID)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002244 OPENOLT_LOG(INFO, openolt_log_id, "type (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002245 key.flow_type, get_flow_status(it->first.first, it->first.second, FLOW_TYPE)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002246 OPENOLT_LOG(INFO, openolt_log_id, "svc_port_id (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002247 cfg.data.svc_port_id, get_flow_status(it->first.first, it->first.second, SVC_PORT_ID)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002248 OPENOLT_LOG(INFO, openolt_log_id, "priority (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002249 cfg.data.priority, get_flow_status(it->first.first, it->first.second, PRIORITY)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002250 OPENOLT_LOG(INFO, openolt_log_id, "cookie (%lu %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002251 cfg.data.cookie, get_flow_status(it->first.first, it->first.second, COOKIE)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002252 OPENOLT_LOG(INFO, openolt_log_id, "ingress intf_type (%s %s)\n", \
2253 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type), \
Jason Huang09b73ea2020-01-08 17:52:05 +08002254 GET_FLOW_INTERFACE_TYPE(get_flow_status(it->first.first, it->first.second, INGRESS_INTF_TYPE))); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002255 OPENOLT_LOG(INFO, openolt_log_id, "ingress intf id (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002256 cfg.data.ingress_intf.intf_id , get_flow_status(it->first.first, it->first.second, INGRESS_INTF_ID)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002257 OPENOLT_LOG(INFO, openolt_log_id, "egress intf_type (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002258 cfg.data.egress_intf.intf_type , get_flow_status(it->first.first, it->first.second, EGRESS_INTF_TYPE)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002259 OPENOLT_LOG(INFO, openolt_log_id, "egress intf_id (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002260 cfg.data.egress_intf.intf_id , get_flow_status(it->first.first, it->first.second, EGRESS_INTF_ID)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002261 OPENOLT_LOG(INFO, openolt_log_id, "classifier o_vid (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002262 c_val.o_vid , get_flow_status(it->first.first, it->first.second, CLASSIFIER_O_VID)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002263 OPENOLT_LOG(INFO, openolt_log_id, "classifier o_pbits (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002264 c_val.o_pbits , get_flow_status(it->first.first, it->first.second, CLASSIFIER_O_PBITS)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002265 OPENOLT_LOG(INFO, openolt_log_id, "classifier i_vid (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002266 c_val.i_vid , get_flow_status(it->first.first, it->first.second, CLASSIFIER_I_VID)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002267 OPENOLT_LOG(INFO, openolt_log_id, "classifier i_pbits (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002268 c_val.i_pbits , get_flow_status(it->first.first, it->first.second, CLASSIFIER_I_PBITS)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002269 OPENOLT_LOG(INFO, openolt_log_id, "classifier ether_type (0x%x 0x%lx)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002270 c_val.ether_type , get_flow_status(it->first.first, it->first.second, CLASSIFIER_ETHER_TYPE)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002271 OPENOLT_LOG(INFO, openolt_log_id, "classifier ip_proto (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002272 c_val.ip_proto , get_flow_status(it->first.first, it->first.second, CLASSIFIER_IP_PROTO)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002273 OPENOLT_LOG(INFO, openolt_log_id, "classifier src_port (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002274 c_val.src_port , get_flow_status(it->first.first, it->first.second, CLASSIFIER_SRC_PORT)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002275 OPENOLT_LOG(INFO, openolt_log_id, "classifier dst_port (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002276 c_val.dst_port , get_flow_status(it->first.first, it->first.second, CLASSIFIER_DST_PORT)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002277 OPENOLT_LOG(INFO, openolt_log_id, "classifier pkt_tag_type (%s %s)\n", \
2278 GET_PKT_TAG_TYPE(c_val.pkt_tag_type), \
Jason Huang09b73ea2020-01-08 17:52:05 +08002279 GET_PKT_TAG_TYPE(get_flow_status(it->first.first, it->first.second, CLASSIFIER_PKT_TAG_TYPE))); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002280 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos type (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002281 cfg.data.egress_qos.type , get_flow_status(it->first.first, it->first.second, EGRESS_QOS_TYPE)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002282 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos queue_id (%d %lu)\n", \
2283 cfg.data.egress_qos.u.fixed_queue.queue_id, \
Jason Huang09b73ea2020-01-08 17:52:05 +08002284 get_flow_status(it->first.first, it->first.second, EGRESS_QOS_QUEUE_ID)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002285 OPENOLT_LOG(INFO, openolt_log_id, "classifier egress_qos sched_id (%d %lu)\n", \
2286 cfg.data.egress_qos.tm_sched.id, \
Jason Huang09b73ea2020-01-08 17:52:05 +08002287 get_flow_status(it->first.first, it->first.second, EGRESS_QOS_TM_SCHED_ID)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002288 OPENOLT_LOG(INFO, openolt_log_id, "classifier cmds_bitmask (%s %s)\n", \
2289 get_flow_acton_command(a_val.cmds_bitmask), \
Jason Huang09b73ea2020-01-08 17:52:05 +08002290 get_flow_acton_command(get_flow_status(it->first.first, it->first.second, ACTION_CMDS_BITMASK))); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002291 OPENOLT_LOG(INFO, openolt_log_id, "action o_vid (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002292 a_val.o_vid , get_flow_status(it->first.first, it->first.second, ACTION_O_VID)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002293 OPENOLT_LOG(INFO, openolt_log_id, "action i_vid (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002294 a_val.i_vid , get_flow_status(it->first.first, it->first.second, ACTION_I_VID)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002295 OPENOLT_LOG(INFO, openolt_log_id, "action o_pbits (%d %lu)\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002296 a_val.o_pbits , get_flow_status(it->first.first, it->first.second, ACTION_O_PBITS)); \
2297 OPENOLT_LOG(INFO, openolt_log_id, "action i_pbits (%d %lu)\n\n", \
2298 a_val.i_pbits, get_flow_status(it->first.first, it->first.second, ACTION_I_PBITS)); \
Burak Gurdagc78b9e12019-11-29 11:14:51 +00002299 OPENOLT_LOG(INFO, openolt_log_id, "group_id (%d %lu)\n\n", \
Jason Huang09b73ea2020-01-08 17:52:05 +08002300 a_val.group_id, get_flow_status(it->first.first, it->first.second, GROUP_ID)); \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002301 } while(0)
2302
2303#define FLOW_CHECKER
2304//#define SHOW_FLOW_PARAM
2305
Jason Huang09b73ea2020-01-08 17:52:05 +08002306Status install_gem_port(int32_t intf_id, int32_t onu_id, int32_t gemport_id) {
2307 bcmos_errno err;
2308 bcmolt_itupon_gem_cfg cfg; /* declare main API struct */
2309 bcmolt_itupon_gem_key key = {}; /* declare key */
2310 bcmolt_gem_port_configuration configuration = {};
2311
2312 key.pon_ni = intf_id;
2313 key.gem_port_id = gemport_id;
2314
2315 BCMOLT_CFG_INIT(&cfg, itupon_gem, key);
2316
2317 bcmolt_gem_port_direction configuration_direction;
2318 configuration_direction = BCMOLT_GEM_PORT_DIRECTION_BIDIRECTIONAL;
2319 BCMOLT_FIELD_SET(&configuration, gem_port_configuration, direction, configuration_direction);
2320
2321 bcmolt_gem_port_type configuration_type;
2322 configuration_type = BCMOLT_GEM_PORT_TYPE_UNICAST;
2323 BCMOLT_FIELD_SET(&configuration, gem_port_configuration, type, configuration_type);
2324
2325 BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, configuration, configuration);
2326
2327 BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, onu_id, onu_id);
2328
2329 bcmolt_control_state encryption_mode;
2330 encryption_mode = BCMOLT_CONTROL_STATE_DISABLE;
2331 BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, encryption_mode, encryption_mode);
2332
2333 bcmolt_us_gem_port_destination upstream_destination_queue;
2334 upstream_destination_queue = BCMOLT_US_GEM_PORT_DESTINATION_DATA;
2335 BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, upstream_destination_queue, upstream_destination_queue);
2336
2337 bcmolt_control_state control;
2338 control = BCMOLT_CONTROL_STATE_ENABLE;
2339 BCMOLT_FIELD_SET(&cfg.data, itupon_gem_cfg_data, control, control);
2340
2341 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
2342 if(err != BCM_ERR_OK) {
2343 OPENOLT_LOG(ERROR, openolt_log_id, "failed to install gem_port = %d\n", gemport_id);
2344 return bcm_to_grpc_err(err, "Access_Control set ITU PON Gem port failed");
2345 }
2346
2347 OPENOLT_LOG(INFO, openolt_log_id, "gem port installed successfully = %d\n", gemport_id);
2348
2349 return Status::OK;
2350}
2351
2352Status remove_gem_port(int32_t intf_id, int32_t gemport_id) {
2353 bcmolt_itupon_gem_cfg gem_cfg;
2354 bcmolt_itupon_gem_key key = {
2355 .pon_ni = (bcmolt_interface)intf_id,
2356 .gem_port_id = (bcmolt_gem_port_id)gemport_id
2357 };
2358 bcmos_errno err;
2359
2360 BCMOLT_CFG_INIT(&gem_cfg, itupon_gem, key);
2361 err = bcmolt_cfg_clear(dev_id, &gem_cfg.hdr);
2362 if (err != BCM_ERR_OK)
2363 {
2364 OPENOLT_LOG(ERROR, openolt_log_id, "failed to remove gem_port = %d err=%s\n", gemport_id, gem_cfg.hdr.hdr.err_text);
2365 return bcm_to_grpc_err(err, "Access_Control clear ITU PON Gem port failed");
2366 }
2367
2368 OPENOLT_LOG(INFO, openolt_log_id, "gem port removed successfully = %d\n", gemport_id);
2369
2370 return Status::OK;
2371}
2372
2373Status update_acl_interface(int32_t intf_id, bcmolt_interface_type intf_type, uint32_t access_control_id,
2374 bcmolt_members_update_command acl_cmd) {
2375 bcmos_errno err;
2376 bcmolt_access_control_interfaces_update oper; /* declare main API struct */
2377 bcmolt_access_control_key acl_key = {}; /* declare key */
2378 bcmolt_intf_ref interface_ref_list_elem = {};
2379 bcmolt_interface_type interface_ref_list_elem_intf_type;
2380 bcmolt_interface_id interface_ref_list_elem_intf_id;
2381 bcmolt_intf_ref_list_u8 interface_ref_list = {};
2382
2383 if (acl_cmd != BCMOLT_MEMBERS_UPDATE_COMMAND_ADD && acl_cmd != BCMOLT_MEMBERS_UPDATE_COMMAND_REMOVE) {
2384 OPENOLT_LOG(ERROR, openolt_log_id, "acl cmd = %d not supported currently\n", acl_cmd);
2385 return bcm_to_grpc_err(BCM_ERR_PARM, "unsupported acl cmd");
2386 }
2387 interface_ref_list.arr = (bcmolt_intf_ref*)bcmos_calloc(sizeof(bcmolt_intf_ref)*1);
2388
2389 if (interface_ref_list.arr == NULL)
2390 return bcm_to_grpc_err(BCM_ERR_PARM, "allocate interface_ref_list failed");
2391 OPENOLT_LOG(INFO, openolt_log_id, "update acl interface received for intf_id = %d, intf_type = %s, acl_id = %d, acl_cmd = %s\n",
2392 intf_id, intf_type == BCMOLT_INTERFACE_TYPE_PON? "pon": "nni", access_control_id,
2393 acl_cmd == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD? "add": "remove");
2394
2395 acl_key.id = access_control_id;
2396
2397 /* Initialize the API struct. */
2398 BCMOLT_OPER_INIT(&oper, access_control, interfaces_update, acl_key);
2399
2400 bcmolt_members_update_command command;
2401 command = acl_cmd;
2402 BCMOLT_FIELD_SET(&oper.data, access_control_interfaces_update_data, command, command);
2403
2404 interface_ref_list_elem_intf_type = intf_type;
2405 BCMOLT_FIELD_SET(&interface_ref_list_elem, intf_ref, intf_type, interface_ref_list_elem_intf_type);
2406
2407 interface_ref_list_elem_intf_id = intf_id;
2408 BCMOLT_FIELD_SET(&interface_ref_list_elem, intf_ref, intf_id, interface_ref_list_elem_intf_id);
2409
2410 interface_ref_list.len = 1;
2411 BCMOLT_ARRAY_ELEM_SET(&interface_ref_list, 0, interface_ref_list_elem);
2412
2413 BCMOLT_FIELD_SET(&oper.data, access_control_interfaces_update_data, interface_ref_list, interface_ref_list);
2414
2415 err = bcmolt_oper_submit(dev_id, &oper.hdr);
2416 if (err != BCM_ERR_OK) {
2417 OPENOLT_LOG(ERROR, openolt_log_id, "update acl interface fail for intf_id = %d, intf_type = %s, acl_id = %d, acl_cmd = %s\n",
2418 intf_id, intf_type == BCMOLT_INTERFACE_TYPE_PON? "pon": "nni", access_control_id,
2419 acl_cmd == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD? "add": "remove");
2420 return bcm_to_grpc_err(err, "Access_Control submit interface failed");
2421 }
2422
2423 bcmos_free(interface_ref_list.arr);
2424 OPENOLT_LOG(INFO, openolt_log_id, "update acl interface success for intf_id = %d, intf_type = %s, acl_id = %d, acl_cmd = %s\n",
2425 intf_id, intf_type == BCMOLT_INTERFACE_TYPE_PON? "pon": "nni", access_control_id,
2426 acl_cmd == BCMOLT_MEMBERS_UPDATE_COMMAND_ADD? "add": "remove");
2427
2428 return Status::OK;
2429}
2430
2431Status install_acl(const acl_classifier_key acl_key) {
2432
2433 bcmos_errno err;
2434 bcmolt_access_control_cfg cfg;
2435 bcmolt_access_control_key key = { };
2436 bcmolt_classifier c_val = { };
2437 // hardcode the action for now.
2438 bcmolt_access_control_fwd_action_type action_type = BCMOLT_ACCESS_CONTROL_FWD_ACTION_TYPE_TRAP_TO_HOST;
2439
2440 int acl_id = get_acl_id();
2441 if (acl_id < 0) {
2442 OPENOLT_LOG(ERROR, openolt_log_id, "exhausted acl_id for eth_type = %d, ip_proto = %d, src_port = %d, dst_port = %d\n",
2443 acl_key.ether_type, acl_key.ip_proto, acl_key.src_port, acl_key.dst_port);
2444 bcmos_fastlock_unlock(&data_lock, 0);
2445 return bcm_to_grpc_err(BCM_ERR_INTERNAL, "exhausted acl id");
2446 }
2447
2448 key.id = acl_id;
2449 /* config access control instance */
2450 BCMOLT_CFG_INIT(&cfg, access_control, key);
2451
2452 if (acl_key.ether_type > 0) {
2453 OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify ether_type 0x%04x\n", acl_key.ether_type);
2454 BCMOLT_FIELD_SET(&c_val, classifier, ether_type, acl_key.ether_type);
2455 }
2456
2457 if (acl_key.ip_proto > 0) {
2458 OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify ip_proto %d\n", acl_key.ip_proto);
2459 BCMOLT_FIELD_SET(&c_val, classifier, ip_proto, acl_key.ip_proto);
2460 }
2461
2462 if (acl_key.dst_port > 0) {
2463 OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify dst_port %d\n", acl_key.dst_port);
2464 BCMOLT_FIELD_SET(&c_val, classifier, dst_port, acl_key.dst_port);
2465 }
2466
2467 if (acl_key.src_port > 0) {
2468 OPENOLT_LOG(DEBUG, openolt_log_id, "Access_Control classify src_port %d\n", acl_key.src_port);
2469 BCMOLT_FIELD_SET(&c_val, classifier, src_port, acl_key.src_port);
2470 }
2471
2472 BCMOLT_MSG_FIELD_SET(&cfg, classifier, c_val);
2473 BCMOLT_MSG_FIELD_SET(&cfg, priority, 10000);
2474 BCMOLT_MSG_FIELD_SET(&cfg, statistics_control, BCMOLT_CONTROL_STATE_ENABLE);
2475
2476 BCMOLT_MSG_FIELD_SET(&cfg, forwarding_action.action, action_type);
2477
2478 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
2479 if (err != BCM_ERR_OK) {
2480 OPENOLT_LOG(ERROR, openolt_log_id, "Access_Control set configuration failed, Error %d\n", err);
2481 // Free the acl_id
2482 free_acl_id(acl_id);
2483 return bcm_to_grpc_err(err, "Access_Control set configuration failed");
2484 }
2485
2486 ACL_LOG(INFO, "ACL add ok", err);
2487
2488 // Update the map that we have installed an acl for the given classfier.
2489 acl_classifier_to_acl_id_map[acl_key] = acl_id;
2490 return Status::OK;
2491}
2492
2493Status remove_acl(int acl_id) {
2494 bcmos_errno err;
2495 bcmolt_access_control_cfg cfg; /* declare main API struct */
2496 bcmolt_access_control_key key = {}; /* declare key */
2497
2498 key.id = acl_id;
2499
2500 /* Initialize the API struct. */
2501 BCMOLT_CFG_INIT(&cfg, access_control, key);
2502 BCMOLT_FIELD_SET_PRESENT(&cfg.data, access_control_cfg_data, state);
2503 err = bcmolt_cfg_get(dev_id, &cfg.hdr);
2504 if (err != BCM_ERR_OK) {
2505 OPENOLT_LOG(ERROR, openolt_log_id, "Access_Control get state failed\n");
2506 return bcm_to_grpc_err(err, "Access_Control get state failed");
2507 }
2508
2509 if (cfg.data.state == BCMOLT_CONFIG_STATE_CONFIGURED) {
2510 key.id = acl_id;
2511 /* Initialize the API struct. */
2512 BCMOLT_CFG_INIT(&cfg, access_control, key);
2513
2514 err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
2515 if (err != BCM_ERR_OK) {
2516 // Should we free acl_id here ? We should ideally never land here..
2517 OPENOLT_LOG(ERROR, openolt_log_id, "Error %d while removing Access_Control rule ID %d\n",
2518 err, acl_id);
2519 return Status(grpc::StatusCode::INTERNAL, "Failed to remove Access_Control");
2520 }
2521 }
2522
2523 // Free up acl_id
2524 free_acl_id(acl_id);
2525
2526 OPENOLT_LOG(INFO, openolt_log_id, "acl removed successfully %d\n", acl_id);
2527
2528 return Status::OK;
2529}
2530
2531// Formulates ACL Classifier Key based on the following fields
2532// a. ether_type b. ip_proto c. src_port d. dst_port
2533// If any of the field is not available it is populated as -1.
2534void formulate_acl_classifier_key(acl_classifier_key *key, const ::openolt::Classifier& classifier) {
2535
2536 // TODO: Is 0 a valid value for any of the following classifiers?
2537 // because in the that case, the 'if' check would fail and -1 would be filled as value.
2538 //
2539 if (classifier.eth_type()) {
2540 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ether_type 0x%04x\n", classifier.eth_type());
2541 key->ether_type = classifier.eth_type();
2542 } else key->ether_type = -1;
2543
2544 if (classifier.ip_proto()) {
2545 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ip_proto %d\n", classifier.ip_proto());
2546 key->ip_proto = classifier.ip_proto();
2547 } else key->ip_proto = -1;
2548
2549
2550 if (classifier.src_port()) {
2551 OPENOLT_LOG(DEBUG, openolt_log_id, "classify src_port %d\n", classifier.src_port());
2552 key->src_port = classifier.src_port();
2553 } else key->src_port = -1;
2554
2555
2556 if (classifier.dst_port()) {
2557 OPENOLT_LOG(DEBUG, openolt_log_id, "classify dst_port %d\n", classifier.dst_port());
2558 key->dst_port = classifier.dst_port();
2559 } else key->dst_port = -1;
2560}
2561
2562Status handle_acl_rule_install(int32_t onu_id, uint32_t flow_id,
2563 const std::string flow_type, int32_t access_intf_id,
2564 int32_t network_intf_id, int32_t gemport_id,
2565 const ::openolt::Classifier& classifier) {
2566 int acl_id;
2567 int32_t intf_id = flow_type.compare(upstream) == 0? access_intf_id: network_intf_id;
2568 const std::string intf_type = flow_type.compare(upstream) == 0? "pon": "nni";
2569 bcmolt_interface_type olt_if_type = intf_type == "pon"? BCMOLT_INTERFACE_TYPE_PON: BCMOLT_INTERFACE_TYPE_NNI;
2570
2571 Status resp;
2572
2573 // few map keys we are going to use later.
2574 flow_id_flow_direction fl_id_fl_dir(flow_id, flow_type);
2575 gem_id_intf_id gem_intf(gemport_id, access_intf_id);
2576 acl_classifier_key acl_key;
2577 formulate_acl_classifier_key(&acl_key, classifier);
2578 const acl_classifier_key acl_key_const = {.ether_type=acl_key.ether_type, .ip_proto=acl_key.ip_proto,
2579 .src_port=acl_key.src_port, .dst_port=acl_key.dst_port};
2580
2581 bcmos_fastlock_lock(&data_lock);
2582
2583 // Check if the acl is already installed
2584 if (acl_classifier_to_acl_id_map.count(acl_key_const) > 0) {
2585 // retreive the acl_id
2586 acl_id = acl_classifier_to_acl_id_map[acl_key_const];
2587 acl_id_gem_id_intf_id ac_id_gm_id_if_id(acl_id, gemport_id, intf_id);
2588 if (flow_to_acl_map.count(fl_id_fl_dir)) {
2589 // coult happen if same trap flow is received again
2590 OPENOLT_LOG(INFO, openolt_log_id, "flow and related acl already handled, nothing more to do\n");
2591 bcmos_fastlock_unlock(&data_lock, 0);
2592 return Status::OK;
2593 }
2594
2595 OPENOLT_LOG(INFO, openolt_log_id, "Acl for flow_id=%u with eth_type = %d, ip_proto = %d, src_port = %d, dst_port = %d already installed with acl id = %u\n",
2596 flow_id, acl_key.ether_type, acl_key.ip_proto, acl_key.src_port, acl_key.dst_port, acl_id);
2597
2598 // The acl_ref_cnt is needed to know how many flows refer an ACL.
2599 // When the flow is removed, we decrement the reference count.
2600 // When the reference count becomes 0, we remove the ACL.
2601 if (acl_ref_cnt.count(acl_id) > 0) {
2602 acl_ref_cnt[acl_id] ++;
2603 } else {
2604 // We should ideally not land here. The acl_ref_cnt should have been
2605 // initialized the first time acl was installed.
2606 acl_ref_cnt[acl_id] = 1;
2607 }
2608
2609 } else {
2610 resp = install_acl(acl_key_const);
2611 if (!resp.ok()) {
2612 OPENOLT_LOG(ERROR, openolt_log_id, "Acl for flow_id=%u with eth_type = %d, ip_proto = %d, src_port = %d, dst_port = %d failed\n",
2613 flow_id, acl_key_const.ether_type, acl_key_const.ip_proto, acl_key_const.src_port, acl_key_const.dst_port);
2614 bcmos_fastlock_unlock(&data_lock, 0);
2615 return resp;
2616 }
2617
2618 acl_id = acl_classifier_to_acl_id_map[acl_key_const];
2619
2620 // Initialize the acl reference count
2621 acl_ref_cnt[acl_id] = 1;
2622
2623 OPENOLT_LOG(INFO, openolt_log_id, "acl add success for flow_id=%u with acl_id=%d\n", flow_id, acl_id);
2624 }
2625
2626 // Register the interface for the given acl
2627 acl_id_intf_id_intf_type ac_id_inf_id_inf_type(acl_id, intf_id, intf_type);
2628 // This is needed to keep a track of which interface (pon/nni) has registered for an ACL.
2629 // If it is registered, how many flows refer to it.
2630 if (intf_acl_registration_ref_cnt.count(ac_id_inf_id_inf_type) > 0) {
2631 intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type]++;
2632 } else {
2633 // The given interface is not registered for the ACL. We need to do it now.
2634 resp = update_acl_interface(intf_id, olt_if_type, acl_id, BCMOLT_MEMBERS_UPDATE_COMMAND_ADD);
2635 if (!resp.ok()){
2636 OPENOLT_LOG(ERROR, openolt_log_id, "failed to update acl interfaces intf_id=%d, intf_type=%s, acl_id=%d", intf_id, intf_type.c_str(), acl_id);
2637 // TODO: Ideally we should return error from hear and clean up other other stateful
2638 // counters we creaed earlier. Will leave it out for now.
2639 }
2640 intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type] = 1;
2641 }
2642
2643
2644 // Install the gem port if needed.
2645 if (gemport_id > 0 && access_intf_id >= 0) {
2646 if (gem_ref_cnt.count(gem_intf) > 0) {
2647 // The gem port is already installed
2648 // Increment the ref counter indicating number of flows referencing this gem port
2649 gem_ref_cnt[gem_intf]++;
2650 OPENOLT_LOG(DEBUG, openolt_log_id, "increment gem_ref_cnt in acl handler, ref_cnt=%d\n", gem_ref_cnt[gem_intf]);
2651
2652 } else {
2653 // We should ideally never land here. The gem port should have been created the
2654 // first time ACL was installed.
2655 // Install the gem port
2656 Status resp = install_gem_port(access_intf_id, onu_id, gemport_id);
2657 if (!resp.ok()) {
2658 // TODO: We might need to reverse all previous data, but leave it out for now.
2659 OPENOLT_LOG(ERROR, openolt_log_id, "failed to install the gemport=%d for acl_id=%d, intf_id=%d\n", gemport_id, acl_id, access_intf_id);
2660 bcmos_fastlock_unlock(&data_lock, 0);
2661 return resp;
2662 }
2663 // Initialize the refence count for the gemport.
2664 gem_ref_cnt[gem_intf] = 1;
2665 OPENOLT_LOG(DEBUG, openolt_log_id, "intialized gem ref count in acl handler\n");
2666 }
2667 } else {
2668 OPENOLT_LOG(DEBUG, openolt_log_id, "not incrementing gem_ref_cnt in acl handler flow_id=%d, gemport_id=%d, intf_id=%d\n", flow_id, gemport_id, access_intf_id);
2669 }
2670
2671 // Update the flow_to_acl_map
2672 // This info is needed during flow remove. We need to which ACL ID and GEM PORT ID
2673 // the flow was referring to.
2674 // After retrieving the ACL ID and GEM PORT ID, we decrement the corresponding
2675 // reference counters for those ACL ID and GEMPORT ID.
2676 acl_id_gem_id_intf_id ac_id_gm_id_if_id(acl_id, gemport_id, intf_id);
2677 flow_to_acl_map[fl_id_fl_dir] = ac_id_gm_id_if_id;
2678
2679 bcmos_fastlock_unlock(&data_lock, 0);
2680
2681 return Status::OK;
2682}
2683
Craig Lutgen967a1d02018-11-27 10:41:51 -06002684Status 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 +00002685 uint32_t flow_id, const std::string flow_type,
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07002686 int32_t alloc_id, int32_t network_intf_id,
2687 int32_t gemport_id, const ::openolt::Classifier& classifier,
Burak Gurdagc78b9e12019-11-29 11:14:51 +00002688 const ::openolt::Action& action, int32_t priority_value, uint64_t cookie,
2689 int32_t group_id) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002690 bcmolt_flow_cfg cfg;
2691 bcmolt_flow_key key = { }; /**< Object key. */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002692 int32_t o_vid = -1;
2693 bool single_tag = false;
2694 uint32_t ether_type = 0;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002695 bcmolt_classifier c_val = { };
2696 bcmolt_action a_val = { };
2697 bcmolt_tm_queue_ref tm_val = { };
2698 int tm_qmp_id, tm_q_set_id;
Thiyagarajan Subramani8154d932019-11-13 05:29:06 -05002699 bcmolt_egress_qos_type qos_type;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002700
Jason Huang09b73ea2020-01-08 17:52:05 +08002701 OPENOLT_LOG(INFO, openolt_log_id, "flow add received for flow_id=%u, flow_type=%s\n", flow_id, flow_type.c_str());
2702
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002703 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002704 if (flow_type.compare(upstream) == 0 ) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002705 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002706 } else if (flow_type.compare(downstream) == 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002707 key.flow_type = BCMOLT_FLOW_TYPE_DOWNSTREAM;
Burak Gurdagc78b9e12019-11-29 11:14:51 +00002708 } else if (flow_type.compare(multicast) == 0) {
2709 key.flow_type = BCMOLT_FLOW_TYPE_MULTICAST;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002710 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002711 OPENOLT_LOG(ERROR, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacuer73222e02018-07-16 12:20:26 -04002712 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002713 }
2714
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002715 BCMOLT_CFG_INIT(&cfg, flow, key);
2716 BCMOLT_MSG_FIELD_SET(&cfg, cookie, cookie);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002717
Jason Huang09b73ea2020-01-08 17:52:05 +08002718 if (action.cmd().trap_to_host()) {
2719 Status resp = handle_acl_rule_install(onu_id, flow_id, flow_type, access_intf_id,
2720 network_intf_id, gemport_id, classifier);
2721 return resp;
2722 }
Burak Gurdagc78b9e12019-11-29 11:14:51 +00002723
2724 if (key.flow_type != BCMOLT_FLOW_TYPE_MULTICAST) {
2725
2726 if (access_intf_id >= 0 && network_intf_id >= 0) {
2727 if (key.flow_type == BCMOLT_FLOW_TYPE_UPSTREAM) { //upstream
2728 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_PON);
2729 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_id, access_intf_id);
Jason Huang09b73ea2020-01-08 17:52:05 +08002730 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_NNI);
2731 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_id, network_intf_id);
Burak Gurdagc78b9e12019-11-29 11:14:51 +00002732 } else if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) { //downstream
2733 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_NNI);
2734 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_id, network_intf_id);
2735 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_PON);
2736 BCMOLT_MSG_FIELD_SET(&cfg, egress_intf.intf_id, access_intf_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002737 }
Burak Gurdagc78b9e12019-11-29 11:14:51 +00002738 } else {
2739 OPENOLT_LOG(ERROR, openolt_log_id, "flow network setting invalid\n");
2740 return bcm_to_grpc_err(BCM_ERR_PARM, "flow network setting invalid");
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002741 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06002742
Burak Gurdagc78b9e12019-11-29 11:14:51 +00002743 if (onu_id >= 0) {
2744 BCMOLT_MSG_FIELD_SET(&cfg, onu_id, onu_id);
2745 }
2746 if (gemport_id >= 0) {
2747 BCMOLT_MSG_FIELD_SET(&cfg, svc_port_id, gemport_id);
2748 }
2749 if (gemport_id >= 0 && port_no != 0) {
2750 bcmos_fastlock_lock(&data_lock);
2751 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
2752 port_to_flows[port_no].insert(key.flow_id);
2753 flowid_to_gemport[key.flow_id] = gemport_id;
2754 }
2755 else
2756 {
2757 flowid_to_port[key.flow_id] = port_no;
2758 }
2759 bcmos_fastlock_unlock(&data_lock, 0);
2760 }
Jason Huang09b73ea2020-01-08 17:52:05 +08002761 if (gemport_id >= 0 && access_intf_id >= 0) {
2762 // Update the flow_to_acl_map. Note that since this is a datapath flow, acl_id is -1
2763 // This info is needed during flow remove where we need to retrieve the gemport_id
2764 // and access_intf id for the given flow id and flow direction.
2765 // After retrieving the ACL ID and GEM PORT ID, we decrement the corresponding
2766 // reference counters for those ACL ID and GEMPORT ID.
2767 acl_id_gem_id_intf_id ac_id_gm_id_if_id(-1, gemport_id, access_intf_id);
2768 flow_id_flow_direction fl_id_fl_dir(flow_id, flow_type);
2769 bcmos_fastlock_lock(&data_lock);
2770 flow_to_acl_map[fl_id_fl_dir] = ac_id_gm_id_if_id;
2771 bcmos_fastlock_unlock(&data_lock, 0);
2772 }
Burak Gurdagc78b9e12019-11-29 11:14:51 +00002773 if (priority_value >= 0) {
2774 BCMOLT_MSG_FIELD_SET(&cfg, priority, priority_value);
2775 }
Girish Gowdra80b0fb92019-11-15 11:40:39 +05302776
Burak Gurdagc78b9e12019-11-29 11:14:51 +00002777 } else { // MULTICAST FLOW
2778 if (group_id >= 0) {
2779 BCMOLT_MSG_FIELD_SET(&cfg, group_id, group_id);
Craig Lutgen967a1d02018-11-27 10:41:51 -06002780 }
Burak Gurdagc78b9e12019-11-29 11:14:51 +00002781 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_type, BCMOLT_FLOW_INTERFACE_TYPE_NNI);
2782 BCMOLT_MSG_FIELD_SET(&cfg, ingress_intf.intf_id, network_intf_id);
Shad Ansari39739bc2018-09-13 21:38:37 +00002783 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002784
2785 {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002786 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002787 if (classifier.o_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002788 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_tpid 0x%04x\n", classifier.o_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05002789 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, o_tpid, classifier.o_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002790 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002791 */
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002792 /* removed by BAL v3.0
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002793 if (classifier.i_tpid()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002794 OPENOLT_LOG(DEBUG, openolt_log_id, "classify i_tpid 0x%04x\n", classifier.i_tpid());
Craig Lutgen19512312018-11-02 10:14:46 -05002795 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, i_tpid, classifier.i_tpid());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002796 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002797 */
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002798
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002799 if (classifier.eth_type()) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002800 ether_type = classifier.eth_type();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002801 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ether_type 0x%04x\n", classifier.eth_type());
2802 BCMOLT_FIELD_SET(&c_val, classifier, ether_type, classifier.eth_type());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002803 }
2804
Burak Gurdagc78b9e12019-11-29 11:14:51 +00002805 if (classifier.dst_mac().size() > 0) {
2806 bcmos_mac_address d_mac = {};
2807 bcmos_mac_address_init(&d_mac);
2808 memcpy(d_mac.u8, classifier.dst_mac().data(), sizeof(d_mac.u8));
2809 OPENOLT_LOG(DEBUG, openolt_log_id, "classify dst_mac %02x:%02x:%02x:%02x:%02x:%02x\n", d_mac.u8[0],
2810 d_mac.u8[1], d_mac.u8[2], d_mac.u8[3], d_mac.u8[4], d_mac.u8[5]);
2811 BCMOLT_FIELD_SET(&c_val, classifier, dst_mac, d_mac);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002812 }
2813
Burak Gurdagc78b9e12019-11-29 11:14:51 +00002814 /*
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002815 if (classifier.src_mac()) {
Craig Lutgen19512312018-11-02 10:14:46 -05002816 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_mac, classifier.src_mac());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002817 }
2818 */
2819
2820 if (classifier.ip_proto()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002821 OPENOLT_LOG(DEBUG, openolt_log_id, "classify ip_proto %d\n", classifier.ip_proto());
2822 BCMOLT_FIELD_SET(&c_val, classifier, ip_proto, classifier.ip_proto());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002823 }
2824
2825 /*
2826 if (classifier.dst_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05002827 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, dst_ip, classifier.dst_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002828 }
2829
2830 if (classifier.src_ip()) {
Craig Lutgen19512312018-11-02 10:14:46 -05002831 BCMBAL_ATTRIBUTE_PROP_SET(&val, classifier, src_ip, classifier.src_ip());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002832 }
2833 */
2834
2835 if (classifier.src_port()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002836 OPENOLT_LOG(DEBUG, openolt_log_id, "classify src_port %d\n", classifier.src_port());
2837 BCMOLT_FIELD_SET(&c_val, classifier, src_port, classifier.src_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002838 }
2839
2840 if (classifier.dst_port()) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002841 OPENOLT_LOG(DEBUG, openolt_log_id, "classify dst_port %d\n", classifier.dst_port());
2842 BCMOLT_FIELD_SET(&c_val, classifier, dst_port, classifier.dst_port());
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002843 }
2844
2845 if (!classifier.pkt_tag_type().empty()) {
Jason Huang09b73ea2020-01-08 17:52:05 +08002846 if (classifier.o_vid()) {
2847 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_vid %d\n", classifier.o_vid());
2848 BCMOLT_FIELD_SET(&c_val, classifier, o_vid, classifier.o_vid());
2849 }
2850
2851 if (classifier.i_vid()) {
2852 OPENOLT_LOG(DEBUG, openolt_log_id, "classify i_vid %d\n", classifier.i_vid());
2853 BCMOLT_FIELD_SET(&c_val, classifier, i_vid, classifier.i_vid());
2854 }
2855
2856 OPENOLT_LOG(DEBUG, openolt_log_id, "classify tag_type %s\n", classifier.pkt_tag_type().c_str());
2857 if (classifier.pkt_tag_type().compare("untagged") == 0) {
2858 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_UNTAGGED);
2859 } else if (classifier.pkt_tag_type().compare("single_tag") == 0) {
2860 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_SINGLE_TAG);
2861 single_tag = true;
2862
2863 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
2864 //According to makeOpenOltClassifierField in voltha-openolt-adapter, o_pbits 0xFF means PCP value 0.
2865 if(0xFF == classifier.o_pbits()){
2866 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, 0);
Girish Gowdra80b0fb92019-11-15 11:40:39 +05302867 }
Jason Huang09b73ea2020-01-08 17:52:05 +08002868 else{
2869 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, classifier.o_pbits());
Girish Gowdra80b0fb92019-11-15 11:40:39 +05302870 }
Jason Huang09b73ea2020-01-08 17:52:05 +08002871 } else if (classifier.pkt_tag_type().compare("double_tag") == 0) {
2872 BCMOLT_FIELD_SET(&c_val, classifier, pkt_tag_type, BCMOLT_PKT_TAG_TYPE_DOUBLE_TAG);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002873
Jason Huang09b73ea2020-01-08 17:52:05 +08002874 OPENOLT_LOG(DEBUG, openolt_log_id, "classify o_pbits 0x%x\n", classifier.o_pbits());
2875 if(0xFF == classifier.o_pbits()){
2876 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, 0);
2877 }
2878 else{
2879 BCMOLT_FIELD_SET(&c_val, classifier, o_pbits, classifier.o_pbits());
Girish Gowdra80b0fb92019-11-15 11:40:39 +05302880 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002881 }
2882 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002883 BCMOLT_MSG_FIELD_SET(&cfg, classifier, c_val);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002884 }
2885
Jason Huang09b73ea2020-01-08 17:52:05 +08002886 const ::openolt::ActionCmd& cmd = action.cmd();
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002887
Jason Huang09b73ea2020-01-08 17:52:05 +08002888 if (cmd.add_outer_tag()) {
2889 OPENOLT_LOG(DEBUG, openolt_log_id, "action add o_tag\n");
2890 BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, BCMOLT_ACTION_CMD_ID_ADD_OUTER_TAG);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002891 }
2892
Jason Huang09b73ea2020-01-08 17:52:05 +08002893 if (cmd.remove_outer_tag()) {
2894 OPENOLT_LOG(DEBUG, openolt_log_id, "action pop o_tag\n");
2895 BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, BCMOLT_ACTION_CMD_ID_REMOVE_OUTER_TAG);
2896 }
2897 /* removed by BAL v3.0
2898 if (cmd.trap_to_host()) {
2899 OPENOLT_LOG(INFO, openolt_log_id, "action trap-to-host\n");
2900 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, cmds_bitmask, BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST);
2901 }
2902 */
2903 if (action.o_vid()) {
2904 OPENOLT_LOG(DEBUG, openolt_log_id, "action o_vid=%d\n", action.o_vid());
2905 o_vid = action.o_vid();
2906 BCMOLT_FIELD_SET(&a_val, action, o_vid, action.o_vid());
2907 }
2908
2909 if (action.o_pbits()) {
2910 OPENOLT_LOG(DEBUG, openolt_log_id, "action o_pbits=0x%x\n", action.o_pbits());
2911 BCMOLT_FIELD_SET(&a_val, action, o_pbits, action.o_pbits());
2912 }
2913 /* removed by BAL v3.0
2914 if (action.o_tpid()) {
2915 OPENOLT_LOG(INFO, openolt_log_id, "action o_tpid=0x%04x\n", action.o_tpid());
2916 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, o_tpid, action.o_tpid());
2917 }
2918 */
2919 if (action.i_vid()) {
2920 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_vid=%d\n", action.i_vid());
2921 BCMOLT_FIELD_SET(&a_val, action, i_vid, action.i_vid());
2922 }
2923
2924 if (action.i_pbits()) {
2925 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_pbits=0x%x\n", action.i_pbits());
2926 BCMOLT_FIELD_SET(&a_val, action, i_pbits, action.i_pbits());
2927 }
2928 /* removed by BAL v3.0
2929 if (action.i_tpid()) {
2930 OPENOLT_LOG(DEBUG, openolt_log_id, "action i_tpid=0x%04x\n", action.i_tpid());
2931 BCMBAL_ATTRIBUTE_PROP_SET(&val, action, i_tpid, action.i_tpid());
2932 }
2933 */
2934 BCMOLT_MSG_FIELD_SET(&cfg, action, a_val);
2935
Shad Ansari39739bc2018-09-13 21:38:37 +00002936 if ((access_intf_id >= 0) && (onu_id >= 0)) {
Jason Huang09b73ea2020-01-08 17:52:05 +08002937 qos_type = get_qos_type(access_intf_id, onu_id, uni_id);
2938 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
2939 tm_val.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, downstream);
Shad Ansarib7b0ced2018-05-11 21:53:32 +00002940
Jason Huang09b73ea2020-01-08 17:52:05 +08002941 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2942 // Queue 0 on DS subscriber scheduler
2943 tm_val.queue_id = 0;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002944
Jason Huang09b73ea2020-01-08 17:52:05 +08002945 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2946 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2947 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002948
Jason Huang09b73ea2020-01-08 17:52:05 +08002949 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
2950 downstream.c_str(), tm_val.queue_id, tm_val.sched_id, \
2951 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002952
Jason Huang09b73ea2020-01-08 17:52:05 +08002953 } else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2954 /* Fetch TM QMP ID mapped to DS subscriber scheduler */
2955 tm_qmp_id = tm_q_set_id = get_tm_qmp_id(tm_val.sched_id, access_intf_id, onu_id, uni_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002956
Jason Huang09b73ea2020-01-08 17:52:05 +08002957 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2958 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2959 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_qmp_id, tm_qmp_id);
2960 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_q_set_id, tm_q_set_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002961
Jason Huang09b73ea2020-01-08 17:52:05 +08002962 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, q_set_id = %d, sched_id = %d, intf_type %s\n", \
2963 downstream.c_str(), tm_q_set_id, tm_val.sched_id, \
2964 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2965 }
2966 } else if (key.flow_type == BCMOLT_FLOW_TYPE_UPSTREAM) {
2967 // NNI Scheduler ID
2968 tm_val.sched_id = get_default_tm_sched_id(network_intf_id, upstream);
2969 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
2970 // Queue 0 on NNI scheduler
2971 tm_val.queue_id = 0;
2972 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2973 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2974 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002975
Jason Huang09b73ea2020-01-08 17:52:05 +08002976 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002977 upstream.c_str(), tm_val.queue_id, tm_val.sched_id, \
2978 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
2979
Jason Huang09b73ea2020-01-08 17:52:05 +08002980 } else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
2981 /* Fetch TM QMP ID mapped to US NNI scheduler */
2982 tm_qmp_id = tm_q_set_id = get_tm_qmp_id(tm_val.sched_id, access_intf_id, onu_id, uni_id);
2983 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, qos_type);
2984 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2985 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_qmp_id, tm_qmp_id);
2986 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.priority_to_queue.tm_q_set_id, tm_q_set_id);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002987
Jason Huang09b73ea2020-01-08 17:52:05 +08002988 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, q_set_id = %d, sched_id = %d, intf_type %s\n", \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00002989 upstream.c_str(), tm_q_set_id, tm_val.sched_id, \
2990 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08002991 }
Shad Ansari39739bc2018-09-13 21:38:37 +00002992 }
Girish Gowdra80b0fb92019-11-15 11:40:39 +05302993 } else {
2994 tm_val.sched_id = get_default_tm_sched_id(network_intf_id, upstream);
2995 tm_val.queue_id = 0;
2996
2997 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.type, BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE);
2998 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.tm_sched.id, tm_val.sched_id);
2999 BCMOLT_MSG_FIELD_SET(&cfg , egress_qos.u.fixed_queue.queue_id, tm_val.queue_id);
3000
3001 OPENOLT_LOG(DEBUG, openolt_log_id, "direction = %s, queue_id = %d, sched_id = %d, intf_type %s\n", \
3002 flow_type.c_str(), tm_val.queue_id, tm_val.sched_id, \
3003 GET_FLOW_INTERFACE_TYPE(cfg.data.ingress_intf.intf_type));
Shad Ansari06101952018-07-25 00:22:09 +00003004 }
3005
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003006 BCMOLT_MSG_FIELD_SET(&cfg, state, BCMOLT_FLOW_STATE_ENABLE);
Burak Gurdagc78b9e12019-11-29 11:14:51 +00003007
3008 // BAL 3.1 supports statistics only for unicast flows.
3009 if (key.flow_type != BCMOLT_FLOW_TYPE_MULTICAST) {
3010 BCMOLT_MSG_FIELD_SET(&cfg, statistics, BCMOLT_CONTROL_STATE_ENABLE);
3011 }
3012
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003013#ifdef FLOW_CHECKER
Burak Gurdagc78b9e12019-11-29 11:14:51 +00003014 //Flow Checker, To avoid duplicate flow.
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003015 if (flow_id_counters != 0) {
3016 bool b_duplicate_flow = false;
Jason Huang09b73ea2020-01-08 17:52:05 +08003017 std::map<flow_pair, int>::iterator it;
3018
3019 for(it = flow_map.begin(); it != flow_map.end(); it++) {
3020 b_duplicate_flow = (cfg.data.onu_id == get_flow_status(it->first.first, it->first.second, ONU_ID)) && \
3021 (key.flow_type == it->first.second) && \
3022 (cfg.data.svc_port_id == get_flow_status(it->first.first, it->first.second, SVC_PORT_ID)) && \
3023 (cfg.data.priority == get_flow_status(it->first.first, it->first.second, PRIORITY)) && \
3024 (cfg.data.cookie == get_flow_status(it->first.first, it->first.second, COOKIE)) && \
3025 (cfg.data.ingress_intf.intf_type == get_flow_status(it->first.first, it->first.second, INGRESS_INTF_TYPE)) && \
3026 (cfg.data.ingress_intf.intf_id == get_flow_status(it->first.first, it->first.second, INGRESS_INTF_ID)) && \
3027 (cfg.data.egress_intf.intf_type == get_flow_status(it->first.first, it->first.second, EGRESS_INTF_TYPE)) && \
3028 (cfg.data.egress_intf.intf_id == get_flow_status(it->first.first, it->first.second, EGRESS_INTF_ID)) && \
3029 (c_val.o_vid == get_flow_status(it->first.first, it->first.second, CLASSIFIER_O_VID)) && \
3030 (c_val.o_pbits == get_flow_status(it->first.first, it->first.second, CLASSIFIER_O_PBITS)) && \
3031 (c_val.i_vid == get_flow_status(it->first.first, it->first.second, CLASSIFIER_I_VID)) && \
3032 (c_val.i_pbits == get_flow_status(it->first.first, it->first.second, CLASSIFIER_I_PBITS)) && \
3033 (c_val.ether_type == get_flow_status(it->first.first, it->first.second, CLASSIFIER_ETHER_TYPE)) && \
3034 (c_val.ip_proto == get_flow_status(it->first.first, it->first.second, CLASSIFIER_IP_PROTO)) && \
3035 (c_val.src_port == get_flow_status(it->first.first, it->first.second, CLASSIFIER_SRC_PORT)) && \
3036 (c_val.dst_port == get_flow_status(it->first.first, it->first.second, CLASSIFIER_DST_PORT)) && \
3037 (c_val.pkt_tag_type == get_flow_status(it->first.first, it->first.second, CLASSIFIER_PKT_TAG_TYPE)) && \
3038 (cfg.data.egress_qos.type == get_flow_status(it->first.first, it->first.second, EGRESS_QOS_TYPE)) && \
3039 (cfg.data.egress_qos.u.fixed_queue.queue_id == get_flow_status(it->first.first, it->first.second, EGRESS_QOS_QUEUE_ID)) && \
3040 (cfg.data.egress_qos.tm_sched.id == get_flow_status(it->first.first, it->first.second, EGRESS_QOS_TM_SCHED_ID)) && \
3041 (a_val.cmds_bitmask == get_flow_status(it->first.first, it->first.second, ACTION_CMDS_BITMASK)) && \
3042 (a_val.o_vid == get_flow_status(it->first.first, it->first.second, ACTION_O_VID)) && \
3043 (a_val.i_vid == get_flow_status(it->first.first, it->first.second, ACTION_I_VID)) && \
3044 (a_val.o_pbits == get_flow_status(it->first.first, it->first.second, ACTION_O_PBITS)) && \
3045 (a_val.i_pbits == get_flow_status(it->first.first, it->first.second, ACTION_I_PBITS)) && \
3046 (cfg.data.state == get_flow_status(it->first.first, it->first.second, STATE)) && \
3047 (cfg.data.group_id == get_flow_status(it->first.first, it->first.second, GROUP_ID));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003048#ifdef SHOW_FLOW_PARAM
3049 // Flow Parameter
3050 FLOW_PARAM_LOG();
3051#endif
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003052 if (b_duplicate_flow) {
3053 FLOW_LOG(WARNING, "Flow duplicate", 0);
3054 return bcm_to_grpc_err(BCM_ERR_ALREADY, "flow exists");
3055 }
3056 }
3057 }
3058#endif
3059
3060 bcmos_errno err = bcmolt_cfg_set(dev_id, &cfg.hdr);
3061 if (err) {
3062 FLOW_LOG(ERROR, "Flow add failed", err);
3063 return bcm_to_grpc_err(err, "flow add failed");
3064 } else {
3065 FLOW_LOG(INFO, "Flow add ok", err);
3066 bcmos_fastlock_lock(&data_lock);
Jason Huang09b73ea2020-01-08 17:52:05 +08003067 flow_map[std::pair<int, int>(key.flow_id,key.flow_type)] = flow_map.size();
3068 flow_id_counters = flow_map.size();
3069 if (gemport_id > 0 && access_intf_id >= 0) {
3070 gem_id_intf_id gem_intf(gemport_id, access_intf_id);
3071 if (gem_ref_cnt.count(gem_intf) > 0) {
3072 // The gem port is already installed
3073 // Increment the ref counter indicating number of flows referencing this gem port
3074 gem_ref_cnt[gem_intf]++;
3075 OPENOLT_LOG(DEBUG, openolt_log_id, "incremented gem_ref_cnt, gem_ref_cnt=%d\n", gem_ref_cnt[gem_intf]);
3076 } else {
3077 // Initialize the refence count for the gemport.
3078 gem_ref_cnt[gem_intf] = 1;
3079 OPENOLT_LOG(DEBUG, openolt_log_id, "initialized gem_ref_cnt\n");
3080 }
3081 } else {
3082 OPENOLT_LOG(DEBUG, openolt_log_id, "not incrementing gem_ref_cnt flow_id=%d gemport_id=%d access_intf_id=%d\n", flow_id, gemport_id, access_intf_id);
3083 }
3084
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003085 bcmos_fastlock_unlock(&data_lock, 0);
3086 }
Nicolas Palpacuer0f19b1a2018-06-07 17:29:31 -04003087
Shad Ansarib7b0ced2018-05-11 21:53:32 +00003088 return Status::OK;
3089}
3090
Jason Huang09b73ea2020-01-08 17:52:05 +08003091void clear_gem_port(int gemport_id, int access_intf_id) {
3092 gem_id_intf_id gem_intf(gemport_id, access_intf_id);
3093 if (gemport_id > 0 && access_intf_id >= 0 && gem_ref_cnt.count(gem_intf) > 0) {
3094 OPENOLT_LOG(DEBUG, openolt_log_id, "decrementing gem_ref_cnt gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
3095 gem_ref_cnt[gem_intf]--;
3096 if (gem_ref_cnt[gem_intf] == 0) {
3097 // For datapath flow this may not be necessary (to be verified)
3098 remove_gem_port(access_intf_id, gemport_id);
3099 gem_ref_cnt.erase(gem_intf);
3100 OPENOLT_LOG(DEBUG, openolt_log_id, "removing gem_ref_cnt entry gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
3101 } else {
3102 OPENOLT_LOG(DEBUG, openolt_log_id, "gem_ref_cnt not zero yet gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
3103 }
3104 } else {
3105 OPENOLT_LOG(DEBUG, openolt_log_id, "not decrementing gem_ref_cnt gemport_id=%d access_intf_id=%d\n", gemport_id, access_intf_id);
3106 }
3107}
3108
3109Status handle_acl_rule_cleanup(int16_t acl_id, int32_t gemport_id, int32_t intf_id, const std::string flow_type) {
3110 const std::string intf_type= flow_type.compare(upstream) == 0 ? "pon": "nni";
3111 acl_id_intf_id_intf_type ac_id_inf_id_inf_type(acl_id, intf_id, intf_type);
3112 intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type]--;
3113 if (intf_acl_registration_ref_cnt[ac_id_inf_id_inf_type] == 0) {
3114 bcmolt_interface_type olt_if_type = intf_type == "pon"? BCMOLT_INTERFACE_TYPE_PON: BCMOLT_INTERFACE_TYPE_NNI;
3115 Status resp = update_acl_interface(intf_id, olt_if_type, acl_id, BCMOLT_MEMBERS_UPDATE_COMMAND_REMOVE);
3116 if (!resp.ok()){
3117 OPENOLT_LOG(ERROR, openolt_log_id, "failed to update acl interfaces intf_id=%d, intf_type=%s, acl_id=%d", intf_id, intf_type.c_str(), acl_id);
3118 }
3119 intf_acl_registration_ref_cnt.erase(ac_id_inf_id_inf_type);
3120 }
3121
3122 acl_ref_cnt[acl_id]--;
3123 if (acl_ref_cnt[acl_id] == 0) {
3124 remove_acl(acl_id);
3125 acl_ref_cnt.erase(acl_id);
3126 // Iterate acl_classifier_to_acl_id_map and delete classifier the key corresponding to acl_id
3127 std::map<acl_classifier_key, uint16_t>::iterator it;
3128 for (it=acl_classifier_to_acl_id_map.begin(); it!=acl_classifier_to_acl_id_map.end(); ++it) {
3129 if (it->second == acl_id) {
3130 OPENOLT_LOG(INFO, openolt_log_id, "cleared classifier key corresponding to acl_id = %d\n", acl_id);
3131 acl_classifier_to_acl_id_map.erase(it->first);
3132 break;
3133 }
3134 }
3135 }
3136
3137 clear_gem_port(gemport_id, intf_id);
3138
3139 return Status::OK;
3140}
3141
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04003142Status FlowRemove_(uint32_t flow_id, const std::string flow_type) {
3143
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003144 bcmolt_flow_cfg cfg;
3145 bcmolt_flow_key key = { };
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04003146
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003147 key.flow_id = (bcmolt_flow_id) flow_id;
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04003148 key.flow_id = flow_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003149 if (flow_type.compare(upstream) == 0 ) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003150 key.flow_type = BCMOLT_FLOW_TYPE_UPSTREAM;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003151 } else if (flow_type.compare(downstream) == 0) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003152 key.flow_type = BCMOLT_FLOW_TYPE_DOWNSTREAM;
Burak Gurdagc78b9e12019-11-29 11:14:51 +00003153 } else if(flow_type.compare(multicast) == 0) {
3154 key.flow_type = BCMOLT_FLOW_TYPE_MULTICAST;
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04003155 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003156 OPENOLT_LOG(WARNING, openolt_log_id, "Invalid flow type %s\n", flow_type.c_str());
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04003157 return bcm_to_grpc_err(BCM_ERR_PARM, "Invalid flow type");
3158 }
3159
Jason Huang09b73ea2020-01-08 17:52:05 +08003160 OPENOLT_LOG(INFO, openolt_log_id, "flow remove received for flow_id=%u, flow_type=%s\n",
3161 flow_id, flow_type.c_str());
3162
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003163 bcmos_fastlock_lock(&data_lock);
Jason Huang09b73ea2020-01-08 17:52:05 +08003164 flow_id_flow_direction fl_id_fl_dir(flow_id, flow_type);
3165 int32_t gemport_id = -1;
3166 int32_t intf_id = -1;
3167 int16_t acl_id = -1;
3168 if (flow_to_acl_map.count(fl_id_fl_dir) > 0) {
3169 acl_id_gem_id_intf_id ac_id_gm_id_if_id = flow_to_acl_map[fl_id_fl_dir];
3170 acl_id = std::get<0>(ac_id_gm_id_if_id);
3171 gemport_id = std::get<1>(ac_id_gm_id_if_id);
3172 intf_id = std::get<2>(ac_id_gm_id_if_id);
3173 // cleanup acl only if it is a valid acl. If not valid acl, it may be datapath flow.
3174 if (acl_id >= 0) {
3175 Status resp = handle_acl_rule_cleanup(acl_id, gemport_id, intf_id, flow_type);
3176 bcmos_fastlock_unlock(&data_lock, 0);
3177 if (resp.ok()) {
3178 OPENOLT_LOG(INFO, openolt_log_id, "acl removed ok for flow_id = %u with acl_id = %d\n", flow_id, acl_id);
3179 flow_to_acl_map.erase(fl_id_fl_dir);
3180 } else {
3181 OPENOLT_LOG(ERROR, openolt_log_id, "acl remove error for flow_id = %u with acl_id = %d\n", flow_id, acl_id);
3182 }
3183 return resp;
3184 }
3185 }
3186
Craig Lutgen967a1d02018-11-27 10:41:51 -06003187 uint32_t port_no = flowid_to_port[key.flow_id];
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003188 if (key.flow_type == BCMOLT_FLOW_TYPE_DOWNSTREAM) {
Craig Lutgen967a1d02018-11-27 10:41:51 -06003189 flowid_to_gemport.erase(key.flow_id);
3190 port_to_flows[port_no].erase(key.flow_id);
3191 if (port_to_flows[port_no].empty()) port_to_flows.erase(port_no);
3192 }
3193 else
3194 {
3195 flowid_to_port.erase(key.flow_id);
3196 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003197 bcmos_fastlock_unlock(&data_lock, 0);
Craig Lutgen967a1d02018-11-27 10:41:51 -06003198
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003199 BCMOLT_CFG_INIT(&cfg, flow, key);
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04003200
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003201 bcmos_errno err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04003202 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003203 OPENOLT_LOG(ERROR, openolt_log_id, "Error while removing %s flow, flow_id=%d, err = %s\n", flow_type.c_str(), flow_id, bcmos_strerror(err));
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04003204 return Status(grpc::StatusCode::INTERNAL, "Failed to remove flow");
3205 }
3206
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003207 bcmos_fastlock_lock(&data_lock);
Jason Huang09b73ea2020-01-08 17:52:05 +08003208 if (flow_id_counters != 0) {
3209 std::map<flow_pair, int>::iterator it;
3210 for(it = flow_map.begin(); it != flow_map.end(); it++) {
3211 if (it->first.first == flow_id && it->first.second == key.flow_type) {
3212 flow_id_counters -= 1;
3213 flow_map.erase(it);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003214 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003215 }
3216 }
Jason Huang09b73ea2020-01-08 17:52:05 +08003217 OPENOLT_LOG(INFO, openolt_log_id, "Flow %d, %s removed\n", flow_id, flow_type.c_str());
3218
3219 clear_gem_port(gemport_id, intf_id);
3220
3221 flow_to_acl_map.erase(fl_id_fl_dir);
3222
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003223 bcmos_fastlock_unlock(&data_lock, 0);
3224
Nicolas Palpacueredfaa0c2018-07-05 15:05:27 -04003225 return Status::OK;
3226}
3227
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003228bcmos_errno CreateDefaultSched(uint32_t intf_id, const std::string direction) {
3229 bcmos_errno err;
3230 bcmolt_tm_sched_cfg tm_sched_cfg;
3231 bcmolt_tm_sched_key tm_sched_key = {.id = 1};
3232 tm_sched_key.id = get_default_tm_sched_id(intf_id, direction);
3233
Jason Huangbf45ffb2019-10-30 17:29:02 +08003234 //check TM scheduler has configured or not
3235 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
3236 BCMOLT_MSG_FIELD_GET(&tm_sched_cfg, state);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05003237 #ifdef TEST_MODE
3238 // It is impossible to mock the setting of tm_sched_cfg.data.state because
3239 // the actual bcmolt_cfg_get passes the address of tm_sched_cfg.hdr and we cannot
3240 // set the tm_sched_cfg.data.state. So a new stub function is created and address
3241 // of tm_sched_cfg is passed. This is one-of case where we need to add test specific
3242 // code in production code.
3243 err = bcmolt_cfg_get__tm_sched_stub(dev_id, &tm_sched_cfg);
3244 #else
Jason Huangbf45ffb2019-10-30 17:29:02 +08003245 err = bcmolt_cfg_get(dev_id, &tm_sched_cfg.hdr);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05003246 #endif
Jason Huangbf45ffb2019-10-30 17:29:02 +08003247 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003248 OPENOLT_LOG(ERROR, openolt_log_id, "cfg: Failed to query TM scheduler, err = %s\n",bcmos_strerror(err));
Jason Huangbf45ffb2019-10-30 17:29:02 +08003249 return err;
3250 }
3251 else if (tm_sched_cfg.data.state == BCMOLT_CONFIG_STATE_CONFIGURED) {
3252 OPENOLT_LOG(WARNING, openolt_log_id, "tm scheduler default config has already with id %d\n", tm_sched_key.id);
3253 return BCM_ERR_OK;
3254 }
3255
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003256 // bcmbal_tm_sched_owner
3257 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
3258
3259 /**< The output of the tm_sched object instance */
3260 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.type, BCMOLT_TM_SCHED_OUTPUT_TYPE_INTERFACE);
3261
3262 if (direction.compare(upstream) == 0) {
3263 // In upstream it is NNI scheduler
3264 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_type, BCMOLT_INTERFACE_TYPE_NNI);
3265 } else if (direction.compare(downstream) == 0) {
3266 // In downstream it is PON scheduler
3267 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_type, BCMOLT_INTERFACE_TYPE_PON);
3268 }
3269
3270 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.interface.interface_ref.intf_id, intf_id);
3271
3272 // bcmbal_tm_sched_type
3273 // set the deafult policy to strict priority
3274 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, sched_type, BCMOLT_TM_SCHED_TYPE_SP);
3275
3276 // num_priorities: Max number of strict priority scheduling elements
Burak Gurdagc78b9e12019-11-29 11:14:51 +00003277 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, num_priorities, NUM_OF_PRIORITIES);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003278
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003279 err = bcmolt_cfg_set(dev_id, &tm_sched_cfg.hdr);
3280 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003281 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create %s scheduler, id %d, intf_id %d, err = %s\n",
3282 direction.c_str(), tm_sched_key.id, intf_id, bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003283 return err;
3284 }
3285
3286 OPENOLT_LOG(INFO, openolt_log_id, "Create %s scheduler success, id %d, intf_id %d\n", \
3287 direction.c_str(), tm_sched_key.id, intf_id);
3288 return BCM_ERR_OK;
3289}
3290
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003291bcmos_errno CreateSched(std::string direction, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, uint32_t port_no,
3292 uint32_t alloc_id, tech_profile::AdditionalBW additional_bw, uint32_t weight, uint32_t priority,
3293 tech_profile::SchedulingPolicy sched_policy, tech_profile::TrafficShapingInfo tf_sh_info) {
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04003294
3295 bcmos_errno err;
3296
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003297 if (direction == downstream) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003298 bcmolt_tm_sched_cfg tm_sched_cfg;
3299 bcmolt_tm_sched_key tm_sched_key = {.id = 1};
3300 tm_sched_key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04003301
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003302 // bcmbal_tm_sched_owner
3303 // In downstream it is sub_term scheduler
3304 BCMOLT_CFG_INIT(&tm_sched_cfg, tm_sched, tm_sched_key);
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04003305
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003306 /**< The output of the tm_sched object instance */
3307 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.type, BCMOLT_TM_SCHED_OUTPUT_TYPE_TM_SCHED);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003308
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003309 // bcmbal_tm_sched_parent
3310 // The parent for the sub_term scheduler is the PON scheduler in the downstream
3311 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.tm_sched.tm_sched_id, get_default_tm_sched_id(intf_id, direction));
3312 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, attachment_point.u.tm_sched.tm_sched_param.u.priority.priority, priority);
Burak Gurdagc78b9e12019-11-29 11:14:51 +00003313 /* removed by BAL v3.0, N/A - No direct attachment point of type ONU, same functionality may
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003314 be achieved using the' virtual' type of attachment.
3315 tm_sched_owner.u.sub_term.intf_id = intf_id;
3316 tm_sched_owner.u.sub_term.sub_term_id = onu_id;
3317 */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003318
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003319 // bcmbal_tm_sched_type
3320 // set the deafult policy to strict priority
3321 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, sched_type, BCMOLT_TM_SCHED_TYPE_SP);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003322
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003323 // num_priorities: Max number of strict priority scheduling elements
3324 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, num_priorities, 8);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003325
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003326 // bcmbal_tm_shaping
3327 if (tf_sh_info.cir() >= 0 && tf_sh_info.pir() > 0) {
3328 uint32_t cir = tf_sh_info.cir();
3329 uint32_t pir = tf_sh_info.pir();
3330 uint32_t burst = tf_sh_info.pbs();
3331 OPENOLT_LOG(INFO, openolt_log_id, "applying traffic shaping in DL cir=%u, pir=%u, burst=%u\n",
3332 cir, pir, burst);
3333 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, pir);
3334 BCMOLT_FIELD_SET_PRESENT(&tm_sched_cfg.data.rate, tm_shaping, burst);
3335 // FIXME: Setting CIR, results in BAL throwing error 'tm_sched minimum rate is not supported yet'
3336 //BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.cir, cir);
3337 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.pir, pir);
3338 BCMOLT_MSG_FIELD_SET(&tm_sched_cfg, rate.burst, burst);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003339 }
3340
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003341 err = bcmolt_cfg_set(dev_id, &tm_sched_cfg.hdr);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003342 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003343 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create downstream subscriber scheduler, id %d, \
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003344intf_id %d, onu_id %d, uni_id %d, port_no %u, err = %s\n", tm_sched_key.id, intf_id, onu_id, uni_id, \
3345port_no, bcmos_strerror(err));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003346 return err;
3347 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003348 OPENOLT_LOG(INFO, openolt_log_id, "Create downstream subscriber sched, id %d, intf_id %d, onu_id %d, \
3349uni_id %d, port_no %u\n", tm_sched_key.id, intf_id, onu_id, uni_id, port_no);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003350
3351 } else { //upstream
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003352 bcmolt_itupon_alloc_cfg cfg;
3353 bcmolt_itupon_alloc_key key = { };
3354 key.pon_ni = intf_id;
3355 key.alloc_id = alloc_id;
3356 int bw_granularity = (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY;
3357 int pir_bw = tf_sh_info.pir();
3358 int cir_bw = tf_sh_info.cir();
3359 //offset to match bandwidth granularity
3360 int offset_pir_bw = pir_bw%bw_granularity;
3361 int offset_cir_bw = cir_bw%bw_granularity;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003362
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003363 pir_bw = pir_bw - offset_pir_bw;
3364 cir_bw = cir_bw - offset_cir_bw;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07003365
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003366 BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07003367
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003368 switch (additional_bw) {
3369 case 2: //AdditionalBW_BestEffort
3370 if (pir_bw == 0) {
3371 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
3372%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05003373 return BCM_ERR_PARM;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003374 } else if (pir_bw < cir_bw) {
3375 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
3376bandwidth (%d)\n", pir_bw, cir_bw);
3377 return BCM_ERR_PARM;
3378 } else if (pir_bw == cir_bw) {
3379 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
3380bandwidth for additional bandwidth eligibility of type best_effort\n");
3381 return BCM_ERR_PARM;
3382 }
3383 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_BEST_EFFORT);
3384 break;
3385 case 1: //AdditionalBW_NA
3386 if (pir_bw == 0) {
3387 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
3388%d bytes/sec\n", (board_technology == "XGS-PON")?XGS_BANDWIDTH_GRANULARITY:GPON_BANDWIDTH_GRANULARITY);
3389 return BCM_ERR_PARM;
3390 } else if (cir_bw == 0) {
3391 OPENOLT_LOG(ERROR, openolt_log_id, "Guaranteed bandwidth must be greater than zero for \
3392additional bandwidth eligibility of type Non-Assured (NA)\n");
3393 return BCM_ERR_PARM;
3394 } else if (pir_bw < cir_bw) {
3395 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
3396bandwidth (%d)\n", pir_bw, cir_bw);
3397 return BCM_ERR_PARM;
3398 } else if (pir_bw == cir_bw) {
3399 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be greater than Guaranteed \
3400bandwidth for additional bandwidth eligibility of type non_assured\n");
3401 return BCM_ERR_PARM;
3402 }
3403 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NON_ASSURED);
3404 break;
3405 case 0: //AdditionalBW_None
3406 if (pir_bw == 0) {
3407 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth was set to 0, must be at least \
340816000 bytes/sec\n");
3409 return BCM_ERR_PARM;
3410 } else if (cir_bw == 0) {
3411 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
3412for additional bandwidth eligibility of type None\n");
3413 return BCM_ERR_PARM;
3414 } else if (pir_bw > cir_bw) {
3415 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth must be equal to Guaranteed bandwidth \
3416for additional bandwidth eligibility of type None\n");
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05003417 OPENOLT_LOG(ERROR, openolt_log_id, "Setting Maximum bandwidth (%d) to Guaranteed \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003418bandwidth in None eligibility\n", pir_bw);
3419 cir_bw = pir_bw;
3420 } else if (pir_bw < cir_bw) {
3421 OPENOLT_LOG(ERROR, openolt_log_id, "Maximum bandwidth (%d) can't be less than Guaranteed \
3422bandwidth (%d)\n", pir_bw, cir_bw);
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05003423 OPENOLT_LOG(ERROR, openolt_log_id, "Setting Maximum bandwidth (%d) to Guaranteed \
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003424bandwidth in None eligibility\n", pir_bw);
3425 cir_bw = pir_bw;
3426 }
3427 BCMOLT_MSG_FIELD_SET(&cfg, sla.additional_bw_eligibility, BCMOLT_ADDITIONAL_BW_ELIGIBILITY_NONE);
3428 break;
3429 default:
3430 return BCM_ERR_PARM;
Girish Gowdrue075c642019-01-23 04:05:53 -08003431 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003432 /* CBR Real Time Bandwidth which require shaping of the bandwidth allocations
3433 in a fine granularity. */
3434 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_bw, 0);
3435 /* Fixed Bandwidth with no critical requirement of shaping */
3436 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_bw, 0);
3437 /* Dynamic bandwidth which the OLT is committed to allocate upon demand */
3438 BCMOLT_MSG_FIELD_SET(&cfg, sla.guaranteed_bw, cir_bw);
3439 /* Maximum allocated bandwidth allowed for this alloc ID */
3440 BCMOLT_MSG_FIELD_SET(&cfg, sla.maximum_bw, pir_bw);
3441 BCMOLT_MSG_FIELD_SET(&cfg, sla.alloc_type, BCMOLT_ALLOC_TYPE_NSR);
Burak Gurdagc78b9e12019-11-29 11:14:51 +00003442 /* Set to True for AllocID with CBR RT Bandwidth that requires compensation
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003443 for skipped allocations during quiet window */
3444 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_compensation, BCMOS_FALSE);
3445 /**< Allocation Profile index for CBR non-RT Bandwidth */
3446 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_nrt_ap_index, 0);
3447 /**< Allocation Profile index for CBR RT Bandwidth */
3448 BCMOLT_MSG_FIELD_SET(&cfg, sla.cbr_rt_ap_index, 0);
3449 /**< Alloc ID Weight used in case of Extended DBA mode */
3450 BCMOLT_MSG_FIELD_SET(&cfg, sla.weight, 0);
3451 /**< Alloc ID Priority used in case of Extended DBA mode */
3452 BCMOLT_MSG_FIELD_SET(&cfg, sla.priority, 0);
3453 BCMOLT_MSG_FIELD_SET(&cfg, onu_id, onu_id);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07003454
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003455 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07003456 if (err) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003457 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d,\
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003458port_no %u, alloc_id %d, err = %s\n", intf_id, onu_id,uni_id,port_no,alloc_id, bcmos_strerror(err));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003459 return err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07003460 }
Girish Gowdra96461052019-11-22 20:13:59 +05303461
3462 err = wait_for_alloc_action(intf_id, alloc_id, ALLOC_OBJECT_CREATE);
3463 if (err) {
3464 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create upstream bandwidth allocation, intf_id %d, onu_id %d, uni_id %d,\
3465port_no %u, alloc_id %d, err = %s\n", intf_id, onu_id,uni_id,port_no,alloc_id, bcmos_strerror(err));
3466 return err;
3467 }
3468
3469 OPENOLT_LOG(INFO, openolt_log_id, "create upstream bandwidth allocation success, intf_id %d, onu_id %d, uni_id %d,\
3470port_no %u, alloc_id %d\n", intf_id, onu_id,uni_id,port_no,alloc_id);
3471
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04003472 }
3473
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003474 return BCM_ERR_OK;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07003475}
Shad Ansarib7b0ced2018-05-11 21:53:32 +00003476
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003477Status CreateTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
3478 uint32_t intf_id = traffic_scheds->intf_id();
3479 uint32_t onu_id = traffic_scheds->onu_id();
3480 uint32_t uni_id = traffic_scheds->uni_id();
3481 uint32_t port_no = traffic_scheds->port_no();
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07003482 std::string direction;
3483 unsigned int alloc_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003484 tech_profile::SchedulerConfig sched_config;
3485 tech_profile::AdditionalBW additional_bw;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07003486 uint32_t priority;
3487 uint32_t weight;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003488 tech_profile::SchedulingPolicy sched_policy;
3489 tech_profile::TrafficShapingInfo traffic_shaping_info;
3490 bcmos_errno err;
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07003491
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003492 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
3493 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003494
3495 direction = GetDirection(traffic_sched.direction());
3496 if (direction.compare("direction-not-supported") == 0)
3497 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
3498
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003499 alloc_id = traffic_sched.alloc_id();
3500 sched_config = traffic_sched.scheduler();
3501 additional_bw = sched_config.additional_bw();
3502 priority = sched_config.priority();
3503 weight = sched_config.weight();
3504 sched_policy = sched_config.sched_policy();
3505 traffic_shaping_info = traffic_sched.traffic_shaping_info();
3506 err = CreateSched(direction, intf_id, onu_id, uni_id, port_no, alloc_id, additional_bw, weight, priority,
3507 sched_policy, traffic_shaping_info);
3508 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003509 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create scheduler, err = %s\n", bcmos_strerror(err));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003510 return bcm_to_grpc_err(err, "Failed to create scheduler");
3511 }
Girish Gowdru1cdf6ce2018-08-27 02:43:02 -07003512 }
Shad Ansarib7b0ced2018-05-11 21:53:32 +00003513 return Status::OK;
Shad Ansarib7b0ced2018-05-11 21:53:32 +00003514}
Jonathan Davis70c21812018-07-19 15:32:10 -04003515
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003516bcmos_errno RemoveSched(int intf_id, int onu_id, int uni_id, int alloc_id, std::string direction) {
Jonathan Davis70c21812018-07-19 15:32:10 -04003517
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04003518 bcmos_errno err;
Girish Gowdra96461052019-11-22 20:13:59 +05303519 uint16_t sched_id;
Jonathan Davis70c21812018-07-19 15:32:10 -04003520
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003521 if (direction == upstream) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003522 bcmolt_itupon_alloc_cfg cfg;
3523 bcmolt_itupon_alloc_key key = { };
3524 key.pon_ni = intf_id;
3525 key.alloc_id = alloc_id;
Girish Gowdra96461052019-11-22 20:13:59 +05303526 sched_id = alloc_id;
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04003527
Burak Gurdagc78b9e12019-11-29 11:14:51 +00003528 BCMOLT_CFG_INIT(&cfg, itupon_alloc, key);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003529 err = bcmolt_cfg_clear(dev_id, &cfg.hdr);
3530 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003531 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove scheduler, direction = %s, intf_id %d, alloc_id %d, err = %s\n",
3532 direction.c_str(), intf_id, alloc_id, bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003533 return err;
3534 }
Girish Gowdra96461052019-11-22 20:13:59 +05303535
3536 err = wait_for_alloc_action(intf_id, alloc_id, ALLOC_OBJECT_DELETE);
3537 if (err) {
3538 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove scheduler, direction = %s, intf_id %d, alloc_id %d, err = %s\n",
3539 direction.c_str(), intf_id, alloc_id, bcmos_strerror(err));
3540 return err;
3541 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003542 } else if (direction == downstream) {
3543 bcmolt_tm_sched_cfg cfg;
3544 bcmolt_tm_sched_key key = { };
Nicolas Palpacuer9c352082018-08-14 16:37:14 -04003545
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003546 if (is_tm_sched_id_present(intf_id, onu_id, uni_id, direction)) {
3547 key.id = get_tm_sched_id(intf_id, onu_id, uni_id, direction);
Girish Gowdra96461052019-11-22 20:13:59 +05303548 sched_id = key.id;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003549 } else {
3550 OPENOLT_LOG(INFO, openolt_log_id, "schduler not present in %s, err %d\n", direction.c_str(), err);
3551 return BCM_ERR_OK;
3552 }
Girish Gowdra96461052019-11-22 20:13:59 +05303553
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003554 BCMOLT_CFG_INIT(&cfg, tm_sched, key);
3555 err = bcmolt_cfg_clear(dev_id, &(cfg.hdr));
3556 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003557 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove scheduler, direction = %s, sched_id %d, \
3558intf_id %d, onu_id %d, err = %s\n", direction.c_str(), key.id, intf_id, onu_id, bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003559 return err;
3560 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003561 }
3562
Girish Gowdra96461052019-11-22 20:13:59 +05303563 OPENOLT_LOG(INFO, openolt_log_id, "Removed sched, direction = %s, id %d, intf_id %d, onu_id %d\n",
3564 direction.c_str(), sched_id, intf_id, onu_id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003565 free_tm_sched_id(intf_id, onu_id, uni_id, direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003566 return BCM_ERR_OK;
3567}
3568
3569Status RemoveTrafficSchedulers_(const tech_profile::TrafficSchedulers *traffic_scheds) {
3570 uint32_t intf_id = traffic_scheds->intf_id();
3571 uint32_t onu_id = traffic_scheds->onu_id();
3572 uint32_t uni_id = traffic_scheds->uni_id();
3573 std::string direction;
3574 bcmos_errno err;
3575
3576 for (int i = 0; i < traffic_scheds->traffic_scheds_size(); i++) {
3577 tech_profile::TrafficScheduler traffic_sched = traffic_scheds->traffic_scheds(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003578
3579 direction = GetDirection(traffic_sched.direction());
3580 if (direction.compare("direction-not-supported") == 0)
3581 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
3582
3583 int alloc_id = traffic_sched.alloc_id();
3584 err = RemoveSched(intf_id, onu_id, uni_id, alloc_id, direction);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003585 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003586 OPENOLT_LOG(ERROR, openolt_log_id, "Error-removing-traffic-scheduler, err = %s\n",bcmos_strerror(err));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003587 return bcm_to_grpc_err(err, "error-removing-traffic-scheduler");
3588 }
3589 }
3590 return Status::OK;
3591}
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07003592
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003593bcmos_errno CreateTrafficQueueMappingProfile(uint32_t sched_id, uint32_t intf_id, uint32_t onu_id, uint32_t uni_id, \
3594 std::string direction, std::vector<uint32_t> tmq_map_profile) {
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003595 bcmos_errno err;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003596 bcmolt_tm_qmp_cfg tm_qmp_cfg;
3597 bcmolt_tm_qmp_key tm_qmp_key;
3598 bcmolt_arr_u8_8 pbits_to_tmq_id = {0};
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07003599
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003600 int tm_qmp_id = get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id, tmq_map_profile);
3601 if (tm_qmp_id == -1) {
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05003602 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create tm queue mapping profile. Max allowed tm queue mapping profile count is 16.\n");
3603 return BCM_ERR_RANGE;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003604 }
Girish Gowdruf26cf882019-05-01 23:47:58 -07003605
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003606 tm_qmp_key.id = tm_qmp_id;
3607 for (uint32_t priority=0; priority<tmq_map_profile.size(); priority++) {
3608 pbits_to_tmq_id.arr[priority] = tmq_map_profile[priority];
3609 }
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07003610
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003611 BCMOLT_CFG_INIT(&tm_qmp_cfg, tm_qmp, tm_qmp_key);
3612 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, type, BCMOLT_TM_QMP_TYPE_PBITS);
3613 BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, pbits_to_tmq_id, pbits_to_tmq_id);
Jason Huang09b73ea2020-01-08 17:52:05 +08003614 //BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, ref_count, 0);
3615 //BCMOLT_MSG_FIELD_SET(&tm_qmp_cfg, state, BCMOLT_CONFIG_STATE_CONFIGURED);
Girish Gowdru7c4ec2d2018-10-25 00:29:54 -07003616
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003617 err = bcmolt_cfg_set(dev_id, &tm_qmp_cfg.hdr);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003618 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003619 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create tm queue mapping profile, tm_qmp_id %d, err = %s\n",
3620 tm_qmp_key.id, bcmos_strerror(err));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003621 return err;
3622 }
Craig Lutgen967a1d02018-11-27 10:41:51 -06003623
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003624 OPENOLT_LOG(INFO, openolt_log_id, "Create tm queue mapping profile success, id %d\n", \
3625 tm_qmp_key.id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003626 return BCM_ERR_OK;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003627}
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003628
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003629bcmos_errno RemoveTrafficQueueMappingProfile(uint32_t tm_qmp_id) {
3630 bcmos_errno err;
3631 bcmolt_tm_qmp_cfg tm_qmp_cfg;
3632 bcmolt_tm_qmp_key tm_qmp_key;
3633 tm_qmp_key.id = tm_qmp_id;
3634
3635 BCMOLT_CFG_INIT(&tm_qmp_cfg, tm_qmp, tm_qmp_key);
3636 err = bcmolt_cfg_clear(dev_id, &tm_qmp_cfg.hdr);
3637 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003638 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove tm queue mapping profile, tm_qmp_id %d, err = %s\n",
3639 tm_qmp_key.id, bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003640 return err;
3641 }
3642
3643 OPENOLT_LOG(INFO, openolt_log_id, "Remove tm queue mapping profile success, id %d\n", \
3644 tm_qmp_key.id);
3645 return BCM_ERR_OK;
3646}
3647
3648bcmos_errno CreateDefaultQueue(uint32_t intf_id, const std::string direction) {
3649 bcmos_errno err;
3650
Burak Gurdagc78b9e12019-11-29 11:14:51 +00003651 /* Create default queues on the given PON/NNI scheduler */
3652 for (int queue_id = 0; queue_id < NUMBER_OF_DEFAULT_INTERFACE_QUEUES; queue_id++) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003653 bcmolt_tm_queue_cfg tm_queue_cfg;
3654 bcmolt_tm_queue_key tm_queue_key = {};
3655 tm_queue_key.sched_id = get_default_tm_sched_id(intf_id, direction);
3656 tm_queue_key.id = queue_id;
Thiyagarajan Subramani8154d932019-11-13 05:29:06 -05003657 /* DefaultQueues on PON/NNI schedulers are created with egress_qos_type as
3658 BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE - with tm_q_set_id 32768 */
3659 tm_queue_key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003660
3661 BCMOLT_CFG_INIT(&tm_queue_cfg, tm_queue, tm_queue_key);
3662 BCMOLT_MSG_FIELD_SET(&tm_queue_cfg, tm_sched_param.type, BCMOLT_TM_SCHED_PARAM_TYPE_PRIORITY);
3663 BCMOLT_MSG_FIELD_SET(&tm_queue_cfg, tm_sched_param.u.priority.priority, queue_id);
3664
3665 err = bcmolt_cfg_set(dev_id, &tm_queue_cfg.hdr);
3666 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003667 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create %s tm queue, id %d, sched_id %d, tm_q_set_id %d, err = %s\n", \
3668 direction.c_str(), tm_queue_key.id, tm_queue_key.sched_id, tm_queue_key.tm_q_set_id, bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003669 return err;
3670 }
3671
3672 OPENOLT_LOG(INFO, openolt_log_id, "Create %s tm_queue success, id %d, sched_id %d, tm_q_set_id %d\n", \
3673 direction.c_str(), tm_queue_key.id, tm_queue_key.sched_id, tm_queue_key.tm_q_set_id);
3674 }
3675 return BCM_ERR_OK;
3676}
3677
Thiyagarajan Subramani8154d932019-11-13 05:29:06 -05003678bcmos_errno CreateQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id,
3679 bcmolt_egress_qos_type qos_type, uint32_t priority, uint32_t gemport_id) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003680 bcmos_errno err;
3681 bcmolt_tm_queue_cfg cfg;
3682 bcmolt_tm_queue_key key = { };
3683 OPENOLT_LOG(INFO, openolt_log_id, "creating %s queue. access_intf_id = %d, onu_id = %d, uni_id = %d \
3684gemport_id = %d\n", direction.c_str(), access_intf_id, onu_id, uni_id, gemport_id);
3685
3686 key.sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
3687 get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
3688
3689 if (priority > 7) {
3690 return BCM_ERR_RANGE;
3691 }
3692
3693 /* FIXME: The upstream queues have to be created once only.
3694 The upstream queues on the NNI scheduler are shared by all subscribers.
3695 When the first scheduler comes in, the queues get created, and are re-used by all others.
3696 Also, these queues should be present until the last subscriber exits the system.
3697 One solution is to have these queues always, i.e., create it as soon as OLT is enabled.
3698
3699 There is one queue per gem port and Queue ID is fetched based on priority_q configuration
3700 for each GEM in TECH PROFILE */
3701 key.id = queue_id_list[priority];
3702
3703 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
3704 // Reset the Queue ID to 0, if it is fixed queue, i.e., there is only one queue for subscriber.
3705 key.id = 0;
3706 key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
3707 }
3708 else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
3709 key.tm_q_set_id = get_tm_qmp_id(key.sched_id, access_intf_id, onu_id, uni_id);
3710 }
3711 else {
3712 key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
3713 }
3714
3715 OPENOLT_LOG(INFO, openolt_log_id, "queue assigned queue_id = %d\n", key.id);
3716
3717 BCMOLT_CFG_INIT(&cfg, tm_queue, key);
3718 BCMOLT_MSG_FIELD_SET(&cfg, tm_sched_param.u.priority.priority, priority);
3719
3720 err = bcmolt_cfg_set(dev_id, &cfg.hdr);
3721 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003722 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create subscriber tm queue, direction = %s, queue_id %d, \
3723sched_id %d, tm_q_set_id %d, intf_id %d, onu_id %d, uni_id %d, err = %s\n", \
3724 direction.c_str(), key.id, key.sched_id, key.tm_q_set_id, access_intf_id, onu_id, uni_id, bcmos_strerror(err));
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003725 return err;
3726 }
3727
3728 OPENOLT_LOG(INFO, openolt_log_id, "Created tm_queue, direction %s, id %d, sched_id %d, tm_q_set_id %d, \
3729intf_id %d, onu_id %d, uni_id %d\n", direction.c_str(), key.id, key.sched_id, key.tm_q_set_id, access_intf_id, onu_id, uni_id);
3730 return BCM_ERR_OK;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003731}
3732
3733Status CreateTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
3734 uint32_t intf_id = traffic_queues->intf_id();
3735 uint32_t onu_id = traffic_queues->onu_id();
3736 uint32_t uni_id = traffic_queues->uni_id();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003737 uint32_t sched_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003738 std::string direction;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003739 bcmos_errno err;
Thiyagarajan Subramani8154d932019-11-13 05:29:06 -05003740 bcmolt_egress_qos_type qos_type = get_qos_type(intf_id, onu_id, uni_id, traffic_queues->traffic_queues_size());
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003741
3742 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
3743 uint32_t queues_priority_q[traffic_queues->traffic_queues_size()] = {0};
3744 std::string queues_pbit_map[traffic_queues->traffic_queues_size()];
3745 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
3746 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
3747
3748 direction = GetDirection(traffic_queue.direction());
3749 if (direction.compare("direction-not-supported") == 0)
3750 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
3751
3752 queues_priority_q[i] = traffic_queue.priority();
3753 queues_pbit_map[i] = traffic_queue.pbit_map();
3754 }
3755
3756 std::vector<uint32_t> tmq_map_profile(8, 0);
3757 tmq_map_profile = get_tmq_map_profile(get_valid_queues_pbit_map(queues_pbit_map, COUNT_OF(queues_pbit_map)), \
3758 queues_priority_q, COUNT_OF(queues_priority_q));
3759 sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
3760 get_tm_sched_id(intf_id, onu_id, uni_id, direction);
3761
3762 int tm_qmp_id = get_tm_qmp_id(tmq_map_profile);
3763 if (tm_qmp_id == -1) {
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05003764 err = CreateTrafficQueueMappingProfile(sched_id, intf_id, onu_id, uni_id, direction, tmq_map_profile);
3765 if (err != BCM_ERR_OK) {
3766 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create tm queue mapping profile, err = %s\n", bcmos_strerror(err));
3767 return bcm_to_grpc_err(err, "Failed to create tm queue mapping profile");
3768 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003769 } else if (tm_qmp_id != -1 && get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id) == -1) {
3770 OPENOLT_LOG(INFO, openolt_log_id, "tm queue mapping profile present already with id %d\n", tm_qmp_id);
3771 update_sched_qmp_id_map(sched_id, intf_id, onu_id, uni_id, tm_qmp_id);
3772 }
3773 }
3774
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003775 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
3776 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003777
3778 direction = GetDirection(traffic_queue.direction());
3779 if (direction.compare("direction-not-supported") == 0)
3780 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
3781
Thiyagarajan Subramani8154d932019-11-13 05:29:06 -05003782 err = CreateQueue(direction, intf_id, onu_id, uni_id, qos_type, traffic_queue.priority(), traffic_queue.gemport_id());
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003783
Girish Gowdruf26cf882019-05-01 23:47:58 -07003784 // If the queue exists already, lets not return failure and break the loop.
3785 if (err && err != BCM_ERR_ALREADY) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003786 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to create queue, err = %s\n",bcmos_strerror(err));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003787 return bcm_to_grpc_err(err, "Failed to create queue");
3788 }
3789 }
3790 return Status::OK;
3791}
3792
Thiyagarajan Subramani8154d932019-11-13 05:29:06 -05003793bcmos_errno RemoveQueue(std::string direction, uint32_t access_intf_id, uint32_t onu_id, uint32_t uni_id,
3794 bcmolt_egress_qos_type qos_type, uint32_t priority, uint32_t gemport_id) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003795 bcmolt_tm_queue_cfg cfg;
3796 bcmolt_tm_queue_key key = { };
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003797 bcmos_errno err;
3798
3799 if (direction == downstream) {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003800 if (is_tm_sched_id_present(access_intf_id, onu_id, uni_id, direction)) {
3801 key.sched_id = get_tm_sched_id(access_intf_id, onu_id, uni_id, direction);
3802 key.id = queue_id_list[priority];
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003803 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003804 OPENOLT_LOG(INFO, openolt_log_id, "queue not present in DS. Not clearing, access_intf_id %d, onu_id %d, uni_id %d, gemport_id %d, direction %s\n", access_intf_id, onu_id, uni_id, gemport_id, direction.c_str());
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003805 return BCM_ERR_OK;
3806 }
3807 } else {
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003808 /* In the upstream we use pre-created queues on the NNI scheduler that are used by all subscribers.
3809 They should not be removed. So, lets return OK. */
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003810 return BCM_ERR_OK;
3811 }
3812
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003813 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE) {
3814 key.tm_q_set_id = BCMOLT_TM_QUEUE_SET_ID_QSET_NOT_USE;
3815 // Reset the queue id to 0 when using fixed queue.
3816 key.id = 0;
3817 }
3818 else if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE) {
3819 key.tm_q_set_id = get_tm_qmp_id(key.sched_id, access_intf_id, onu_id, uni_id);
3820 }
3821 else {
3822 key.tm_q_set_id = BCMOLT_TM_QUEUE_KEY_TM_Q_SET_ID_DEFAULT;
3823 }
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003824
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003825 BCMOLT_CFG_INIT(&cfg, tm_queue, key);
3826 err = bcmolt_cfg_clear(dev_id, &(cfg.hdr));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003827 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003828 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove queue, direction = %s, queue_id %d, sched_id %d, \
3829tm_q_set_id %d, intf_id %d, onu_id %d, uni_id %d, err = %s\n",
3830 direction.c_str(), key.id, key.sched_id, key.tm_q_set_id, access_intf_id, onu_id, uni_id, bcmos_strerror(err));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003831 return err;
3832 }
3833
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003834 OPENOLT_LOG(INFO, openolt_log_id, "Removed tm_queue, direction %s, id %d, sched_id %d, tm_q_set_id %d, \
3835intf_id %d, onu_id %d, uni_id %d\n", direction.c_str(), key.id, key.sched_id, key.tm_q_set_id, access_intf_id, onu_id, uni_id);
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003836
3837 return BCM_ERR_OK;
3838}
3839
3840Status RemoveTrafficQueues_(const tech_profile::TrafficQueues *traffic_queues) {
3841 uint32_t intf_id = traffic_queues->intf_id();
3842 uint32_t onu_id = traffic_queues->onu_id();
3843 uint32_t uni_id = traffic_queues->uni_id();
3844 uint32_t port_no = traffic_queues->port_no();
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003845 uint32_t sched_id;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003846 std::string direction;
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003847 bcmos_errno err;
Thiyagarajan Subramani8154d932019-11-13 05:29:06 -05003848 bcmolt_egress_qos_type qos_type = get_qos_type(intf_id, onu_id, uni_id, traffic_queues->traffic_queues_size());
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003849
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003850 for (int i = 0; i < traffic_queues->traffic_queues_size(); i++) {
3851 tech_profile::TrafficQueue traffic_queue = traffic_queues->traffic_queues(i);
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003852
3853 direction = GetDirection(traffic_queue.direction());
3854 if (direction.compare("direction-not-supported") == 0)
3855 return bcm_to_grpc_err(BCM_ERR_PARM, "direction-not-supported");
3856
Thiyagarajan Subramani8154d932019-11-13 05:29:06 -05003857 err = RemoveQueue(direction, intf_id, onu_id, uni_id, qos_type, traffic_queue.priority(), traffic_queue.gemport_id());
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003858 if (err) {
Thiyagarajan Subramani0890b1f2019-11-22 07:52:47 -05003859 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove queue, err = %s\n",bcmos_strerror(err));
Girish Gowdruc8ed2ef2019-02-13 08:18:44 -08003860 return bcm_to_grpc_err(err, "Failed to remove queue");
3861 }
Jonathan Davis70c21812018-07-19 15:32:10 -04003862 }
3863
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003864 if (qos_type == BCMOLT_EGRESS_QOS_TYPE_PRIORITY_TO_QUEUE && (direction.compare(upstream) == 0 || direction.compare(downstream) == 0 && is_tm_sched_id_present(intf_id, onu_id, uni_id, direction))) {
3865 sched_id = (direction.compare(upstream) == 0) ? get_default_tm_sched_id(nni_intf_id, direction) : \
3866 get_tm_sched_id(intf_id, onu_id, uni_id, direction);
3867
3868 int tm_qmp_id = get_tm_qmp_id(sched_id, intf_id, onu_id, uni_id);
3869 if (free_tm_qmp_id(sched_id, intf_id, onu_id, uni_id, tm_qmp_id)) {
Thiyagarajan Subramani6dc20052019-12-05 09:06:36 -05003870 err = RemoveTrafficQueueMappingProfile(tm_qmp_id);
3871 if (err != BCM_ERR_OK) {
3872 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to remove tm queue mapping profile, err = %s\n", bcmos_strerror(err));
3873 return bcm_to_grpc_err(err, "Failed to remove tm queue mapping profile");
3874 }
Thiyagarajan Subramani89fffc02019-05-13 21:33:20 +00003875 }
3876 }
Thiyagarajan Subramani8154d932019-11-13 05:29:06 -05003877 clear_qos_type(intf_id, onu_id, uni_id);
Jonathan Davis70c21812018-07-19 15:32:10 -04003878 return Status::OK;
Jonathan Davis70c21812018-07-19 15:32:10 -04003879}
Jason Huangbf45ffb2019-10-30 17:29:02 +08003880
3881Status check_connection() {
3882 int maxTrials = 60;
3883 while (!bcmolt_api_conn_mgr_is_connected(dev_id)) {
3884 sleep(1);
3885 if (--maxTrials == 0)
3886 return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check connection failed");
3887 else
3888 OPENOLT_LOG(INFO, openolt_log_id, "waiting for daemon connection ...\n");
3889 }
3890 OPENOLT_LOG(INFO, openolt_log_id, "daemon is connected\n");
3891 return Status::OK;
3892}
3893
3894Status check_bal_ready() {
3895 bcmos_errno err;
3896 int maxTrials = 30;
3897 bcmolt_olt_cfg olt_cfg = { };
3898 bcmolt_olt_key olt_key = { };
3899
3900 BCMOLT_CFG_INIT(&olt_cfg, olt, olt_key);
3901 BCMOLT_MSG_FIELD_GET(&olt_cfg, bal_state);
3902
3903 while (olt_cfg.data.bal_state != BCMOLT_BAL_STATE_BAL_AND_SWITCH_READY) {
3904 if (--maxTrials == 0)
3905 return grpc::Status(grpc::StatusCode::UNAVAILABLE, "check bal ready failed");
3906 sleep(5);
3907 #ifdef TEST_MODE
3908 // It is impossible to mock the setting of olt_cfg.data.bal_state because
3909 // the actual bcmolt_cfg_get passes the address of olt_cfg.hdr and we cannot
3910 // set the olt_cfg.data.bal_state. So a new stub function is created and address
Chaitrashree G Sfd15c8c2019-09-09 18:46:15 -04003911 // of olt_cfg is passed. This is one-of case where we need to add test specific
3912 // code in production code.
3913 if (bcmolt_cfg_get__bal_state_stub(dev_id, &olt_cfg)) {
Jason Huangbf45ffb2019-10-30 17:29:02 +08003914 #else
3915 if (bcmolt_cfg_get(dev_id, &olt_cfg.hdr)) {
3916 #endif
3917 continue;
3918 }
3919 else
3920 OPENOLT_LOG(INFO, openolt_log_id, "waiting for BAL ready ...\n");
3921 }
3922
3923 OPENOLT_LOG(INFO, openolt_log_id, "BAL is ready\n");
3924 return Status::OK;
3925}
Burak Gurdagc78b9e12019-11-29 11:14:51 +00003926
3927Status PerformGroupOperation_(const openolt::Group *group_cfg) {
3928
3929 bcmos_errno err;
3930 bcmolt_group_key key = {};
3931 bcmolt_group_cfg grp_cfg_obj;
3932 bcmolt_group_members_update grp_mem_upd;
3933 bcmolt_members_update_command grp_mem_upd_cmd;
3934 bcmolt_group_member_info member_info = {};
3935 bcmolt_group_member_info_list_u8 members = {};
3936 bcmolt_intf_ref interface_ref = {};
3937 bcmolt_egress_qos egress_qos = {};
3938 bcmolt_tm_sched_ref tm_sched_ref = {};
3939 bcmolt_action a_val = {};
3940
3941 uint32_t group_id = group_cfg->group_id();
3942
3943 OPENOLT_LOG(INFO, openolt_log_id, "PerformGroupOperation request received for Group %d\n", group_id);
3944
3945 if (group_id >= 0) {
3946 key.id = group_id;
3947 }
3948 else {
3949 OPENOLT_LOG(ERROR, openolt_log_id, "Invalid group id %d.\n", group_id);
3950 return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Invalid group id");
3951 }
3952
3953 BCMOLT_CFG_INIT(&grp_cfg_obj, group, key);
3954 BCMOLT_FIELD_SET_PRESENT(&grp_cfg_obj.data, group_cfg_data, state);
3955
3956 OPENOLT_LOG(INFO, openolt_log_id, "Checking if Group %d exists...\n",group_id);
3957
3958 err = bcmolt_cfg_get(dev_id, &(grp_cfg_obj.hdr));
3959 if (err != BCM_ERR_OK) {
3960 OPENOLT_LOG(ERROR, openolt_log_id, "Error in querying Group %d, err = %s\n", group_id, bcmos_strerror(err));
3961 return bcm_to_grpc_err(err, "Error in querying group");
3962 }
3963
3964 members.len = group_cfg->members_size();
3965
3966 // IMPORTANT: A member cannot be added to a group if the group type is not determined.
3967 // Group type is determined after a flow is assigned to it.
3968 // Therefore, a group must be created first, then a flow (with multicast type) must be assigned to it.
3969 // Only then we can add members to the group.
3970
3971 // if group does not exist, create it and return.
3972 if (grp_cfg_obj.data.state == BCMOLT_GROUP_STATE_NOT_CONFIGURED) {
3973
3974 if (members.len != 0) {
3975 OPENOLT_LOG(ERROR, openolt_log_id, "Member list is not empty for non-existent Group %d. Members can be added only after a flow is assigned to this newly-created group.\n", group_id);
3976 return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Non-empty member list given for non-existent group");
3977 } else {
3978
3979 BCMOLT_CFG_INIT(&grp_cfg_obj, group, key);
3980 BCMOLT_MSG_FIELD_SET(&grp_cfg_obj, cookie, key.id);
3981
3982 /* Setting group actions and action parameters, if any.
3983 Only remove_outer_tag and translate_inner_tag actions and i_vid action parameter
3984 are supported for multicast groups in BAL 3.1.
3985 */
3986 const ::openolt::Action& action = group_cfg->action();
3987 const ::openolt::ActionCmd &cmd = action.cmd();
3988
3989 bcmolt_action_cmd_id cmd_bmask = BCMOLT_ACTION_CMD_ID_NONE;
3990 if (cmd.remove_outer_tag()) {
3991 OPENOLT_LOG(INFO, openolt_log_id, "Action remove_outer_tag applied to Group %d.\n", group_id);
3992 cmd_bmask = (bcmolt_action_cmd_id) (cmd_bmask | BCMOLT_ACTION_CMD_ID_REMOVE_OUTER_TAG);
3993 }
3994
3995 if (cmd.translate_inner_tag()) {
3996 OPENOLT_LOG(INFO, openolt_log_id, "Action translate_inner_tag applied to Group %d.\n", group_id);
3997 cmd_bmask = (bcmolt_action_cmd_id) (cmd_bmask | BCMOLT_ACTION_CMD_ID_XLATE_INNER_TAG);
3998 }
3999
4000 BCMOLT_FIELD_SET(&a_val, action, cmds_bitmask, cmd_bmask);
4001
4002 if (action.i_vid()) {
4003 OPENOLT_LOG(INFO, openolt_log_id, "Setting action parameter i_vid=%d for Group %d.\n", action.i_vid(), group_id);
4004 BCMOLT_FIELD_SET(&a_val, action, i_vid, action.i_vid());
4005 }
4006
4007 BCMOLT_MSG_FIELD_SET(&grp_cfg_obj, action, a_val);
4008
4009 // Create group
4010 err = bcmolt_cfg_set(dev_id, &(grp_cfg_obj.hdr));
4011
4012 if (BCM_ERR_OK != err) {
4013 BCM_LOG(ERROR, openolt_log_id, "Failed to create Group %d, err = %s (%d)\n", key.id, bcmos_strerror(err), err);
4014 return bcm_to_grpc_err(err, "Error in creating group");
4015 }
4016
4017 BCM_LOG(INFO, openolt_log_id, "Group %d has been created and configured with empty member list.\n", key.id);
4018 return Status::OK;
4019 }
4020 }
4021
4022 // The group already exists. Continue configuring it according to the update member command.
4023
4024 OPENOLT_LOG(INFO, openolt_log_id, "Configuring existing Group %d.\n",group_id);
4025
4026 // MEMBER LIST CONSTRUCTION
4027 // Note that members.len can be 0 here. if the group already exists and the command is SET then sending
4028 // empty list to the group is a legit operation and this actually empties the member list.
4029 members.arr = (bcmolt_group_member_info*)bcmos_calloc((members.len)*sizeof(bcmolt_group_member_info));
4030
4031 if (!members.arr) {
4032 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to allocate memory for group member list.\n");
4033 return grpc::Status(grpc::StatusCode::RESOURCE_EXHAUSTED, "Memory exhausted during member list creation");
4034 }
4035
4036 /* SET GROUP MEMBERS UPDATE COMMAND */
4037 openolt::Group::GroupMembersCommand command = group_cfg->command();
4038 switch(command) {
4039 case openolt::Group::SET_MEMBERS :
4040 grp_mem_upd_cmd = BCMOLT_MEMBERS_UPDATE_COMMAND_SET;
4041 OPENOLT_LOG(INFO, openolt_log_id, "Setting %d members for Group %d.\n", members.len, group_id);
4042 break;
4043 case openolt::Group::ADD_MEMBERS :
4044 grp_mem_upd_cmd = BCMOLT_MEMBERS_UPDATE_COMMAND_ADD;
4045 OPENOLT_LOG(INFO, openolt_log_id, "Adding %d members to Group %d.\n", members.len, group_id);
4046 break;
4047 case openolt::Group::REMOVE_MEMBERS :
4048 grp_mem_upd_cmd = BCMOLT_MEMBERS_UPDATE_COMMAND_REMOVE;
4049 OPENOLT_LOG(INFO, openolt_log_id, "Removing %d members from Group %d.\n", members.len, group_id);
4050 break;
4051 default :
4052 OPENOLT_LOG(ERROR, openolt_log_id, "Invalid value %d for group member command.\n", command);
4053 bcmos_free(members.arr);
4054 return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Invalid group member command");
4055 }
4056
4057 // SET MEMBERS LIST
4058 for (int i = 0; i < members.len; i++) {
4059
4060 if (command == openolt::Group::REMOVE_MEMBERS) {
4061 OPENOLT_LOG(INFO, openolt_log_id, "Removing group member %d from group %d\n",i,key.id);
4062 } else {
4063 OPENOLT_LOG(INFO, openolt_log_id, "Adding group member %d to group %d\n",i,key.id);
4064 }
4065
4066 openolt::GroupMember *member = (openolt::GroupMember *) &group_cfg->members()[i];
4067
4068 // Set member interface type
4069 openolt::GroupMember::InterfaceType if_type = member->interface_type();
4070 switch(if_type){
4071 case openolt::GroupMember::PON :
4072 BCMOLT_FIELD_SET(&interface_ref, intf_ref, intf_type, BCMOLT_INTERFACE_TYPE_PON);
4073 OPENOLT_LOG(INFO, openolt_log_id, "Interface type PON is assigned to GroupMember %d\n",i);
4074 break;
4075 case openolt::GroupMember::EPON_1G_PATH :
4076 BCMOLT_FIELD_SET(&interface_ref, intf_ref, intf_type, BCMOLT_INTERFACE_TYPE_EPON_1_G);
4077 OPENOLT_LOG(INFO, openolt_log_id, "Interface type EPON_1G is assigned to GroupMember %d\n",i);
4078 break;
4079 case openolt::GroupMember::EPON_10G_PATH :
4080 BCMOLT_FIELD_SET(&interface_ref, intf_ref, intf_type, BCMOLT_INTERFACE_TYPE_EPON_10_G);
4081 OPENOLT_LOG(INFO, openolt_log_id, "Interface type EPON_10G is assigned to GroupMember %d\n",i);
4082 break;
4083 default :
4084 OPENOLT_LOG(ERROR, openolt_log_id, "Invalid interface type value %d for GroupMember %d.\n",if_type,i);
4085 bcmos_free(members.arr);
4086 return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Invalid interface type for a group member");
4087 }
4088
4089 // Set member interface id
4090 if (member->interface_id() >= 0) {
4091 BCMOLT_FIELD_SET(&interface_ref, intf_ref, intf_id, member->interface_id());
4092 OPENOLT_LOG(INFO, openolt_log_id, "Interface %d is assigned to GroupMember %d\n", member->interface_id(), i);
4093 } else {
4094 bcmos_free(members.arr);
4095 return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Invalid interface id for a group member");
4096 }
4097
4098 // Set member interface_ref
4099 BCMOLT_FIELD_SET(&member_info, group_member_info, intf, interface_ref);
4100
4101 // Set member gem_port_id. This must be a multicast gemport.
4102 if (member->gem_port_id() >= 0) {
4103 BCMOLT_FIELD_SET(&member_info, group_member_info, svc_port_id, member->gem_port_id());
4104 OPENOLT_LOG(INFO, openolt_log_id, "GEM Port %d is assigned to GroupMember %d\n", member->gem_port_id(), i);
4105 } else {
4106 bcmos_free(members.arr);
4107 return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Invalid gem port id for a group member");
4108 }
4109
4110 // Set member scheduler id and queue_id
4111 uint32_t tm_sched_id = get_default_tm_sched_id(member->interface_id(), downstream);
4112 OPENOLT_LOG(INFO, openolt_log_id, "Scheduler %d is assigned to GroupMember %d\n", tm_sched_id, i);
4113 BCMOLT_FIELD_SET(&tm_sched_ref, tm_sched_ref, id, tm_sched_id);
4114 BCMOLT_FIELD_SET(&egress_qos, egress_qos, tm_sched, tm_sched_ref);
4115
4116 // We assume that all multicast traffic destined to a PON port is using the same fixed queue.
4117 uint32_t tm_queue_id;
4118 if (member->priority() >= 0 && member->priority() < NUMBER_OF_DEFAULT_INTERFACE_QUEUES) {
4119 tm_queue_id = queue_id_list[member->priority()];
4120 OPENOLT_LOG(INFO, openolt_log_id, "Queue %d is assigned to GroupMember %d\n", tm_queue_id, i);
4121 BCMOLT_FIELD_SET(&egress_qos, egress_qos, type, BCMOLT_EGRESS_QOS_TYPE_FIXED_QUEUE);
4122 BCMOLT_FIELD_SET(&egress_qos.u.fixed_queue, egress_qos_fixed_queue, queue_id, tm_queue_id);
4123 } else {
4124 OPENOLT_LOG(ERROR, openolt_log_id, "Invalid fixed queue priority/ID %d for GroupMember %d\n", member->priority(), i);
4125 bcmos_free(members.arr);
4126 return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Invalid queue priority for a group member");
4127 }
4128
4129 BCMOLT_FIELD_SET(&member_info, group_member_info, egress_qos, egress_qos);
4130 BCMOLT_ARRAY_ELEM_SET(&(members), i, member_info);
4131 }
4132
4133 BCMOLT_OPER_INIT(&grp_mem_upd, group, members_update, key);
4134 BCMOLT_MSG_FIELD_SET(&grp_mem_upd, members_cmd.members, members);
4135 BCMOLT_MSG_FIELD_SET(&grp_mem_upd, members_cmd.command, grp_mem_upd_cmd);
4136
4137 err = bcmolt_oper_submit(dev_id, &(grp_mem_upd.hdr));
4138 bcmos_free(members.arr);
4139
4140 if (BCM_ERR_OK != err) {
4141 OPENOLT_LOG(ERROR, openolt_log_id, "Failed to submit members update operation for Group %d err = %s (%d)\n", key.id, bcmos_strerror(err), err);
4142 return bcm_to_grpc_err(err, "Failed to submit members update operation for the group");
4143 }
4144
4145 OPENOLT_LOG(INFO, openolt_log_id, "Successfully submitted members update operation for Group %d\n", key.id);
4146
4147 return Status::OK;
4148}