blob: 35396d729ff16b44492ab2d6effd044546df37ed [file] [log] [blame]
/*
* wl bssload command module
*
* Broadcom Proprietary and Confidential. Copyright (C) 2017,
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
* the contents of this file may not be disclosed to third parties, copied
* or duplicated in any form, in whole or in part, without the prior
* written permission of Broadcom.
*
*
* <<Broadcom-WL-IPTag/Proprietary:>>
*
* $Id: wluc_bssload.c 458728 2014-02-27 18:15:25Z $
*/
#ifdef WIN32
#include <windows.h>
#endif
#include <wlioctl.h>
#if defined(DONGLEBUILD)
#include <typedefs.h>
#include <osl.h>
#endif
/* Because IL_BIGENDIAN was removed there are few warnings that need
* to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
* Hence these warnings were not seen earlier.
* For now ignore the following warnings
*/
#ifdef WIN32
#pragma warning(push)
#pragma warning(disable : 4244)
#pragma warning(disable : 4761)
#endif
#include <bcmutils.h>
#include <bcmendian.h>
#include "wlu_common.h"
#include "wlu.h"
#ifdef LINUX
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <linux/if_packet.h>
#endif /* LINUX */
static int wl_bssload_static(void *wl, cmd_t *cmd, char **argv);
#if defined(WLBSSLOAD_REPORT)
static int wl_bssload_report(void *wl, cmd_t *cmd, char **argv);
static int wl_bssload_report_event(void *wl, cmd_t *cmd, char **argv);
#if defined(linux)
static cmd_func_t wl_bssload_event_check;
#endif /* linux */
#endif /* WLBSSLOAD_REPORT */
static cmd_t wl_bssload_cmds[] = {
{ "bssload_static", wl_bssload_static, WLC_GET_VAR, WLC_SET_VAR,
"get or set static BSS load\n"
"\tusage: wl bssload_static [off | <sta_count> <chan_util> <acc>]"},
#if defined(WLBSSLOAD_REPORT)
{ "bssload_report", wl_bssload_report, WLC_GET_VAR, -1,
"Get the latest BSS Load IE data from the associated AP's beacon\n"
"\tUsage: bssload_report"
},
{ "bssload_report_event", wl_bssload_report_event, WLC_GET_VAR, WLC_SET_VAR,
"Get/Set BSS load threshold for sending WLC_E_BSS_LOAD event\n"
"\tUsage: wl bssload_report_event [rate_limit_msec] [level] [level] ...\n"
"\t\t[level] is a 0...255 channel utilization value.\n"
"\t\tUp to 8 levels in increasing order may be specified."
},
#if defined(linux)
{ "bssload_event_check", wl_bssload_event_check, -1, -1,
"Listens forever for BSS Load events and prints them.\n"
"\tUsage: wl bssload_event_check"
},
#endif /* linux */
#endif /* WLBSSLOAD_REPORT */
{ NULL, NULL, 0, 0, NULL }
};
static char *buf;
/* module initialization */
void
wluc_bssload_module_init(void)
{
/* get the global buf */
buf = wl_get_buf();
/* register bssload commands */
wl_module_cmds_register(wl_bssload_cmds);
}
static int
wl_bssload_static(void *wl, cmd_t *cmd, char **argv)
{
int err = -1;
wl_bssload_static_t bssload;
UNUSED_PARAMETER(cmd);
/* get */
if (!argv[1]) {
if ((err = wlu_iovar_get(wl, cmd->name, &bssload, sizeof(bssload))) < 0)
return err;
if (bssload.is_static) {
printf("station count: %d\n", dtoh16(bssload.sta_count));
printf("channel utilization: %d\n", bssload.chan_util);
printf("avail admission capacity: %d\n", dtoh16(bssload.aac));
}
}
else {
/* set */
argv++;
memset(&bssload, 0, sizeof(bssload));
if (!stricmp(*argv, "off")) {
bssload.is_static = FALSE;
}
else {
bssload.sta_count = htod16(strtoul(*argv, NULL, 0));
if (*++argv == NULL) {
printf("wl_bssload_static: "
"channel utilization not provided\n");
return -1;
}
bssload.chan_util = strtoul(*argv, NULL, 0);
if (*++argv == NULL) {
printf("wl_bssload_static: "
"avail admission capacity not provided\n");
return -1;
}
bssload.aac = htod16(strtoul(*argv, NULL, 0));
bssload.is_static = TRUE;
}
err = wlu_iovar_set(wl, cmd->name, &bssload, sizeof(bssload));
}
return err;
}
#if defined(WLBSSLOAD_REPORT)
static int
wl_bssload_report(void *wl, cmd_t *cmd, char **argv)
{
int ret = 0;
wl_bssload_t *bssload = NULL;
/* If any arguments are given, print help */
if (ARGCNT(argv) > 1)
goto usage;
/* Get and print the current BSS Load values */
if ((ret = wlu_var_getbuf_sm(wl, cmd->name, NULL, 0, (void*)&bssload)))
return ret;
if (bssload == NULL)
return BCME_ERROR;
printf("BSS Load from associated AP beacon:\n");
printf("station count : %u\n", dtoh16(bssload->sta_count));
printf("channel utilization : %u\n", bssload->chan_util);
printf("available admission capacity: %u\n", dtoh16(bssload->aac));
return 0;
usage:
return -1;
}
static int
wl_bssload_report_event(void *wl, cmd_t *cmd, char **argv)
{
int ret;
wl_bssload_cfg_t blcfg;
(void) wl;
if (!*++argv) {
/* get */
void *ptr = NULL;
uint i;
if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
return ret;
memcpy(&blcfg, ptr, sizeof(blcfg));
blcfg.rate_limit_msec = dtoh32(blcfg.rate_limit_msec);
printf("rate_limit_msec: %d\n", blcfg.rate_limit_msec);
printf("%d channel utilization levels:", blcfg.num_util_levels);
for (i = 0; i < blcfg.num_util_levels; i++) {
printf(" %d", blcfg.util_levels[i]);
}
printf("\n");
} else {
/* set */
memset(&blcfg, 0, sizeof(wl_bssload_cfg_t));
blcfg.rate_limit_msec = atoi(*argv);
while (*++argv && blcfg.num_util_levels < MAX_BSSLOAD_LEVELS) {
blcfg.util_levels[blcfg.num_util_levels++] = atoi(*argv);
if (blcfg.num_util_levels > 1 &&
blcfg.util_levels[blcfg.num_util_levels - 1] <=
blcfg.util_levels[blcfg.num_util_levels - 2]) {
printf("Channel utilization level %u was <= level %u.\n",
blcfg.util_levels[blcfg.num_util_levels - 1],
blcfg.util_levels[blcfg.num_util_levels - 2]);
goto usage;
}
}
if (*argv) {
printf("Too many parameters.\n");
goto usage;
}
blcfg.rate_limit_msec = htod32(blcfg.rate_limit_msec);
ret = wlu_var_setbuf(wl, cmd->name, &blcfg, sizeof(blcfg));
}
return ret;
usage:
return -1;
}
#if defined(linux)
static void
wl_bssload_event_cb(int event_type, bcm_event_t *bcm_event)
{
struct timeval tv;
uint32 sec, msec;
int ret;
wl_bssload_t *data = (wl_bssload_t *) (bcm_event + 1);
if (event_type == WLC_E_BSS_LOAD) {
/* Print a timestamp */
ret = gettimeofday(&tv, NULL);
if (ret == 0) {
sec = (uint32) (tv.tv_sec % 10000);
msec = (uint32) tv.tv_usec / 1000;
printf("%04d.%03d\n", sec, msec);
}
printf("WLC_E_BSS_LOAD: chan_util = %u\n", data->chan_util);
printf(" sta_count = %u\n", dtoh16(data->sta_count));
printf(" aac = %u\n", dtoh16(data->aac));
}
}
static int
wl_bssload_event_check(void *wl, cmd_t *cmd, char **argv)
{
if (argv[1] && argv[1][0] == '-') {
wl_cmd_usage(stderr, cmd);
return -1;
}
return wl_wait_for_event(wl, argv, WLC_E_BSS_LOAD, 2048, wl_bssload_event_cb);
}
#endif /* linux */
#endif /* WLBSSLOAD_REPORT */