blob: 6db7d824fe247f4a34b6caa9e27ad6d34a709553 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2<:copyright-BRCM:2016:DUAL/GPL:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7Unless you and Broadcom execute a separate written software license
8agreement governing use of this software, this software is licensed
9to you under the terms of the GNU General Public License version 2
10(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11with the following added to such license:
12
13 As a special exception, the copyright holders of this software give
14 you permission to link this software with independent modules, and
15 to copy and distribute the resulting executable under terms of your
16 choice, provided that you also meet, for each linked independent
17 module, the terms and conditions of the license of that module.
18 An independent module is a module which is not derived from this
19 software. The special exception does not apply to any modifications
20 of the software.
21
22Not withstanding the above, under no circumstances may you combine
23this software in any way with any other Broadcom software provided
24under a license other than the GPL, without Broadcom's express prior
25written consent.
26
27:>
28 */
29
30#include <bcmos_system.h>
31#include <bcmtr_debug.h>
32#include <bcmtr_debug_cli.h>
33#include <bcm_api_cli_helpers.h>
34#ifdef BCM_SUBSYSTEM_HOST
35#include <bcmolt_dev_selector.h>
36#endif
37
38#define BCMTR_CLD_CAST_DISCARD_CONST(p, type) (type)((long)(p))
39
40static bcmcli_entry *cld_cli_dir;
41
42static bcmos_errno _bcmtr_cld_cli_create(void);
43static void _bcmtr_cld_cli_destroy(void);
44
45/*
46 * CLI handlers
47 */
48
49static bcmos_errno _bcmtr_cld_cli_setget_level(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
50{
51 bcmcli_number obj = bcmcli_parm_get(session, "object")->value.number;
52 bcmcli_cmd_parm *grp_parm = bcmcli_parm_get(session, "group");
53 bcmcli_number group = grp_parm ? grp_parm->value.number : -1;
54 bcmcli_cmd_parm *subgrp_parm = bcmcli_parm_get(session, "subgroup");
55 bcmcli_number subgroup = subgrp_parm ? subgrp_parm->value.number : -1;
56 bcmtr_cld_type level = bcmcli_parm_get(session, "level")->value.number;
57 bcmtr_cld_filter filter = {};
58 bcmos_errno rc;
59
60 if (obj == -1 || !bcmcli_parm_is_set(session, bcmcli_parm_get(session, "object")))
61 {
62 filter.object = BCMOLT_OBJECT_ANY;
63 }
64 else
65 {
66 filter.object = obj;
67 }
68
69 if (group == -1 || !grp_parm || !bcmcli_parm_is_set(session, grp_parm))
70 {
71 filter.group = BCMOLT_MGT_GROUP_ANY;
72 }
73 else
74 {
75 filter.group = group;
76 }
77
78 if (subgroup == -1 || !subgrp_parm || !bcmcli_parm_is_set(session, subgrp_parm))
79 {
80 filter.subgroup = BCMOLT_SUBGROUP_ANY;
81 }
82 else
83 {
84 filter.subgroup = subgroup;
85 }
86
87 /* Get or set level ? */
88 if (bcmcli_parm_is_set(session, bcmcli_parm_get(session, "level")))
89 {
90 rc = bcmtr_cld_level_set(current_device, &filter, level);
91 }
92 else
93 {
94 rc = bcmtr_cld_level_get(current_device, &filter, &level);
95 if (rc == BCM_ERR_OK)
96 {
97 bcmcli_session_print(session, "capture:%s log:%s dump:%s\n",
98 (level & BCMTR_CLD_CAPTURE) ? "on" : "off",
99 (level & BCMTR_CLD_LOG) ? "on" : "off",
100 ((level & BCMTR_CLD_DUMP) == BCMTR_CLD_DUMP) ? "all" :
101 (level & BCMTR_CLD_DUMP_HDR) ? "headers" : "off");
102 }
103 }
104
105 return rc;
106}
107
108static bcmos_errno _bcmtr_cld_cli_capture_init(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
109{
110 bcmcli_number size = bcmcli_parm_get(session, "size")->value.number;
111 bcmos_bool stop_on_full = bcmcli_parm_get(session, "stop_on_full")->value.number;
112 bcmos_bool autostart = bcmcli_parm_get(session, "autostart")->value.number;
113 bcmtr_capture_parm p = {};
114
115 p.size = size;
116 p.stop_on_full = stop_on_full;
117 p.activate = autostart;
118
119 return bcmtr_capture_init(current_device, &p);
120}
121
122static bcmos_errno _bcmtr_cld_cli_capture_delete(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
123{
124 bcmtr_capture_destroy(current_device);
125 return BCM_ERR_OK;
126}
127
128static bcmos_errno _bcmtr_cld_cli_capture_start(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
129{
130 return bcmtr_capture_start_stop(current_device, BCMOS_TRUE);
131}
132
133static bcmos_errno _bcmtr_cld_cli_capture_stop(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
134{
135 return bcmtr_capture_start_stop(current_device, BCMOS_FALSE);
136}
137
138static bcmos_errno _bcmtr_cld_cli_capture_dump(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
139{
140 uint32_t nmsgs;
141 bcmos_errno rc;
142
143 rc = bcmtr_capture_dump(session, current_device, &nmsgs);
144 if (!rc)
145 {
146 bcmcli_session_print(session, "Dumped %u messages\n", nmsgs);
147 }
148
149 return BCM_ERR_OK;
150}
151
152static bcmos_errno _bcmtr_cld_cli_capture_info(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
153{
154 bcmtr_capture_info info;
155 bcmos_errno rc;
156
157 rc = bcmtr_capture_info_get(current_device, &info);
158 if (!rc)
159 {
160 bcmcli_session_print(session, "Buffer: size=%u used=%u. Events: recorded=%u lost=%d. Wraps around:%u\n",
161 info.size, info.used, info.msgs, info.lost, info.wa);
162 }
163
164 return BCM_ERR_OK;
165}
166
167
168#ifdef BCM_SUBSYSTEM_HOST
169/* Current device change indication */
170static void _bcmtr_cld_device_change_ind(bcmcli_session *session, bcmolt_devid dev)
171{
172 bcmcli_entry *cur_dir = bcmcli_dir_get(session);
173 bcmos_bool is_cld_cur_dir = (cur_dir && cur_dir == cld_cli_dir);
174 bcmos_errno rc;
175
176 /* Destroy and re-create CLD CLI directory */
177 _bcmtr_cld_cli_destroy();
178 rc = _bcmtr_cld_cli_create();
179
180 /* Restore current CLI directory to CLD */
181 if (!rc && is_cld_cur_dir)
182 bcmcli_dir_set(session, cld_cli_dir);
183}
184#endif
185
186/* allocate memory for name and description and copy to to parm */
187static bcmos_errno _bcmtr_cld_copy_parm_name(bcmcli_cmd_parm *parm, const char *name, const char *descr)
188{
189 parm->name = bcmos_alloc(strlen(name) + 1);
190 parm->description = bcmos_alloc(strlen(descr) + 1);
191 if ((parm->name == NULL) || (parm->description == NULL))
192 {
193 /* Successful allocation if any will be released by common cleanup
194 * along with the rest of dynamic parameter fields */
195 return BCM_ERR_NOMEM;
196 }
197 strcpy(BCMTR_CLD_CAST_DISCARD_CONST(parm->name, void *), name);
198 strcpy(BCMTR_CLD_CAST_DISCARD_CONST(parm->description, void *), descr);
199 return BCM_ERR_OK;
200}
201
202/* Free "level" command parameters. both name and description are allocated dynamically */
203static void _bcmtr_cld_free_level_parms(bcmcli_cmd_parm *parms)
204{
205 bcmcli_cmd_parm *p = parms;
206
207 while (p->name)
208 {
209 if (p->type == BCMCLI_PARM_ENUM && p->enum_table)
210 {
211 if ((p->flags & BCMCLI_PARM_FLAG_SELECTOR))
212 {
213 bcmcli_enum_val *e = p->enum_table;
214 while(e->name)
215 {
216 if (e->parms)
217 {
218 _bcmtr_cld_free_level_parms(e->parms);
219 }
220 ++e;
221 }
222 }
223 bcmos_free(p->enum_table);
224 }
225 if (p->description)
226 bcmos_free(BCMTR_CLD_CAST_DISCARD_CONST(p->description, void *));
227 if (p->name)
228 bcmos_free(BCMTR_CLD_CAST_DISCARD_CONST(p->name, void *));
229
230 ++p;
231 }
232 bcmos_free(parms);
233}
234
235/* Add "level" command */
236static bcmos_errno _bcmtr_cld_add_level_cmd(bcmcli_entry *dir)
237{
238 /* object: *all, object list
239 * group: selector: *all, group list
240 * subgroup: *all, subgroup list
241 * level: bitmask
242 */
243 bcmcli_cmd_extra_parm cmd_extras = { .free_parms = _bcmtr_cld_free_level_parms };
244 bcmcli_enum_val *obj_selector;
245 bcmcli_cmd_parm *cmd_parms;
246 static const char *all_name = "*all";
247 bcmolt_system_mode current_system_mode;
248 int n_obj = 0;
249 bcmolt_obj_id o;
250 bcmos_errno rc = BCM_ERR_NOMEM;
251
252 /* Allocate top level parameters: object selector, level, terminator */
253 cmd_parms = bcmos_calloc(sizeof(bcmcli_cmd_parm) * 3);
254 if (!cmd_parms)
255 {
256 return BCM_ERR_NOMEM;
257 }
258
259 /* Allocate object enum table. 2 extra entries for *all and terminator */
260 obj_selector = bcmos_calloc(sizeof(bcmcli_enum_val) * (BCMOLT_OBJ_ID__NUM_OF + 2));
261 if (!obj_selector)
262 {
263 goto cleanup;
264 }
265
266 /* Fill up parameters */
267 rc = _bcmtr_cld_copy_parm_name(&cmd_parms[0], "object", "Object Name");
268 cmd_parms[0].type = BCMCLI_PARM_ENUM;
269 cmd_parms[0].flags = BCMCLI_PARM_FLAG_SELECTOR;
270 cmd_parms[0].enum_table = obj_selector;
271
272 rc = rc ? rc : _bcmtr_cld_copy_parm_name(&cmd_parms[1], "level", "Level bitmask: 1=capture,2=log,4=print hdr,8=print body");
273 cmd_parms[1].type = BCMCLI_PARM_DECIMAL;
274 cmd_parms[1].flags = BCMCLI_PARM_FLAG_OPTIONAL;
275
276 /* obj_selector[0] is reserved for *all */
277 obj_selector[0].name = all_name;
278 obj_selector[0].val = -1;
279
280 /* Go over objects */
281 bcmolt_system_mode_get(current_device, &current_system_mode);
282 for (o = 0; o < BCMOLT_OBJ_ID__NUM_OF; o++)
283 {
284 bcmcli_enum_val *grp_selector;
285 bcmcli_cmd_parm *grp_parm;
286 bcmolt_mgt_group g;
287 int n_grp = 0;
288
289 if (!bcmolt_object_is_supported(current_system_mode, o))
290 continue;
291
292 /* Allocate group parameter and selector */
293 ++n_obj;
294 obj_selector[n_obj].val = o;
295 rc = api_cli_object_name(o, &obj_selector[n_obj].name, NULL);
296 if (rc != BCM_ERR_OK)
297 goto cleanup;
298
299 obj_selector[n_obj].parms = grp_parm = bcmos_calloc(sizeof(bcmcli_cmd_parm)*2);
300 if (!grp_parm)
301 goto cleanup;
302 rc = _bcmtr_cld_copy_parm_name(grp_parm, "group", "Message group");
303 grp_parm->type = BCMCLI_PARM_ENUM;
304 grp_parm->flags = BCMCLI_PARM_FLAG_SELECTOR;
305 grp_parm->enum_table = grp_selector = bcmos_calloc(sizeof(bcmcli_enum_val) * (BCMOLT_MGT_GROUP__NUM_OF + 1));
306 if (!grp_selector)
307 goto cleanup;
308
309 /* Selector 0 is reserved for *all */
310 grp_selector[0].name = all_name;
311 grp_selector[0].val = -1;
312
313 /* Go over groups */
314 for (g = 1; g < BCMOLT_MGT_GROUP__NUM_OF; g++)
315 {
316 uint16_t subgroup_count = api_cli_get_subgroup_count(o, g);
317 bcmcli_enum_val *subgrp_table;
318 bcmcli_cmd_parm *subgrp_parm;
319 uint16_t s;
320 int sg_table_idx;
321
322 if (subgroup_count == 0)
323 continue;
324
325 ++n_grp;
326 grp_selector[n_grp].name = apicli_mgt_group_to_str(g);
327 grp_selector[n_grp].val = g;
328
329 /* Skip subgroup selector for groups that don't support it */
330 if (g != BCMOLT_MGT_GROUP_AUTO &&
331 g != BCMOLT_MGT_GROUP_OPER &&
332 g != BCMOLT_MGT_GROUP_PROXY &&
333 g != BCMOLT_MGT_GROUP_PROXY_RX)
334 {
335 continue;
336 }
337
338 grp_selector[n_grp].parms = subgrp_parm = bcmos_calloc(sizeof(bcmcli_cmd_parm)*2);
339 if (!subgrp_parm)
340 goto cleanup;
341 rc = rc ? rc : _bcmtr_cld_copy_parm_name(subgrp_parm, "subgroup", "Message sub-group");
342 subgrp_parm->type = BCMCLI_PARM_ENUM;
343 subgrp_parm->enum_table = subgrp_table = bcmos_calloc(sizeof(bcmcli_enum_val) * (subgroup_count + 2));
344 if (!subgrp_table)
345 goto cleanup;
346 subgrp_table[0].name = all_name;
347 subgrp_table[0].val = -1;
348
349 sg_table_idx = 1;
350 for (s = 0; s < subgroup_count; s++)
351 {
352 if (api_cli_object_subgroup_name(o, g, s, &subgrp_table[sg_table_idx].name, NULL) == BCM_ERR_OK)
353 {
354 subgrp_table[sg_table_idx].val = s;
355 ++sg_table_idx;
356 }
357 }
358 }
359 }
360
361 /* Finally add command */
362 rc = bcmcli_cmd_add(dir, "level", _bcmtr_cld_cli_setget_level, "Set/get cld level", BCMCLI_ACCESS_ADMIN,
363 &cmd_extras, cmd_parms);
364 if (rc)
365 goto cleanup;
366 return BCM_ERR_OK;
367
368cleanup:
369 _bcmtr_cld_free_level_parms(cmd_parms);
370 return rc;
371}
372
373/* Create CLI commands */
374static bcmos_errno _bcmtr_cld_cli_create(void)
375{
376 bcmcli_entry *dir;
377 bcmos_errno err;
378
379 dir = bcmcli_dir_add(NULL, "cld", "Transport Capture, Log, Debug", BCMCLI_ACCESS_ADMIN, NULL);
380 BCMOS_CHECK_RETURN_ERROR(dir == NULL, BCM_ERR_NOMEM);
381
382 err = _bcmtr_cld_add_level_cmd(dir);
383 if (err)
384 return err;
385
386 BCMCLI_MAKE_CMD(dir, "init", "Initialize capture buffer", _bcmtr_cld_cli_capture_init,
387 BCMCLI_MAKE_PARM("size", "Buffer size (bytes)", BCMCLI_PARM_UDECIMAL, 0),
388 BCMCLI_MAKE_PARM_ENUM("stop_on_full", "Stop capture when buffer is full (yes) or wrap-around (no)",
389 bcmcli_enum_bool_table, 0),
390 BCMCLI_MAKE_PARM_ENUM("autostart", "Autostart", bcmcli_enum_bool_table, 0) );
391
392 BCMCLI_MAKE_CMD_NOPARM(dir, "delete", "Destroy buffer", _bcmtr_cld_cli_capture_delete);
393
394 BCMCLI_MAKE_CMD_NOPARM(dir, "start", "Start capture", _bcmtr_cld_cli_capture_start);
395
396 BCMCLI_MAKE_CMD_NOPARM(dir, "stop", "Stop capture", _bcmtr_cld_cli_capture_stop);
397
398 BCMCLI_MAKE_CMD_NOPARM(dir, "dump", "Dump capture buffer", _bcmtr_cld_cli_capture_dump);
399
400 BCMCLI_MAKE_CMD_NOPARM(dir, "info", "Capture info", _bcmtr_cld_cli_capture_info);
401
402 cld_cli_dir = dir;
403
404 return BCM_ERR_OK;
405
406}
407
408/* Destroy CLI commands */
409static void _bcmtr_cld_cli_destroy(void)
410{
411 if (cld_cli_dir)
412 {
413 bcmcli_token_destroy(cld_cli_dir);
414 cld_cli_dir = NULL;
415 }
416}
417
418
419/** Initialize CLD CLI commands
420 * \returns BCM_ERR_OK (0) if successful
421 */
422bcmos_errno bcmtr_cld_cli_init(void)
423{
424 bcmos_errno err = BCM_ERR_OK;
425
426#ifdef BCM_SUBSYSTEM_HOST
427 /* Subscribe for device change indication */
428 err = bcmolt_dev_sel_ind_register(_bcmtr_cld_device_change_ind);
429#endif
430
431 err = err ? err : _bcmtr_cld_cli_create();
432
433 return err;
434}
435
436/** Clean-up CLD CLI commands */
437void bcmtr_cld_cli_exit(void)
438{
439 _bcmtr_cld_cli_destroy();
440}