@@ -369,12 +369,163 @@ int wifi_setApRetrylimit(void *priv)
369369 return 0 ;
370370}
371371
372+ static int get_channel_stats_handler (struct nl_msg * msg , void * arg )
373+ {
374+ int i , rem ;
375+ unsigned int freq ;
376+ unsigned char channel ;
377+ struct nlattr * tb [NL80211_ATTR_MAX + 1 ];
378+ struct nlattr * survey_info [NL80211_SURVEY_INFO_MAX + 1 ];
379+ struct genlmsghdr * gnlh = nlmsg_data (nlmsg_hdr (msg ));
380+ static struct nla_policy survey_policy [NL80211_SURVEY_INFO_MAX + 1 ] = {
381+ [NL80211_SURVEY_INFO_FREQUENCY ] = { .type = NLA_U32 },
382+ [NL80211_SURVEY_INFO_NOISE ] = { .type = NLA_S32 },
383+ [NL80211_SURVEY_INFO_TIME ] = { .type = NLA_U64 },
384+ [NL80211_SURVEY_INFO_TIME_BUSY ] = { .type = NLA_U64 },
385+ [NL80211_SURVEY_INFO_TIME_EXT_BUSY ] = { .type = NLA_U64 },
386+ [NL80211_SURVEY_INFO_TIME_RX ] = { .type = NLA_U64 },
387+ [NL80211_SURVEY_INFO_TIME_TX ] = { .type = NLA_U64 },
388+ [NL80211_SURVEY_INFO_TIME_SCAN ] = { .type = NLA_U64 },
389+ [NL80211_SURVEY_INFO_TIME_BSS_RX ] = { .type = NLA_U64 },
390+ };
391+ channel_stats_arr_t * stats = (channel_stats_arr_t * )arg ;
392+
393+ for (i = 0 ; i < stats -> arr_size ; i ++ ) {
394+ wifi_hal_dbg_print ("%s:%d stats->arr[%d].ch_number : %d\n" , __func__ , __LINE__ ,
395+ i , stats -> arr [i ].ch_number );
396+ }
397+
398+
399+ if (nla_parse (tb , NL80211_ATTR_MAX , genlmsg_attrdata (gnlh , 0 ),genlmsg_attrlen (gnlh , 0 ),
400+ NULL ) < 0 ) {
401+ wifi_hal_error_print ("%s:%d Failed to parse survey data\n" , __func__ , __LINE__ );
402+ return NL_SKIP ;
403+ }
404+
405+ if (!tb [NL80211_ATTR_SURVEY_INFO ]) {
406+ wifi_hal_error_print ("%s:%d Failed to get survey info attribute\n" , __func__ , __LINE__ );
407+ return NL_SKIP ;
408+ }
409+
410+ if (nla_parse_nested (survey_info , NL80211_SURVEY_INFO_MAX , tb [NL80211_ATTR_SURVEY_INFO ], survey_policy )) {
411+ wifi_hal_error_print ("%s:%d Failed to parse nested attributes\n" , __func__ , __LINE__ );
412+ return NL_SKIP ;
413+ }
414+
415+ for (i = 0 ; i <= NL80211_SURVEY_INFO_MAX ; i ++ ) {
416+ if (survey_policy [i ].type != 0 && survey_info [i ] == NULL ) {
417+ wifi_hal_stats_error_print ("%s:%d Survey info attribute %d is missing\n" , __func__ ,
418+ __LINE__ , i );
419+ }
420+ }
421+
422+ freq = nla_get_u32 (survey_info [NL80211_SURVEY_INFO_FREQUENCY ]);
423+ if (ieee80211_freq_to_chan (freq , & channel ) == NUM_HOSTAPD_MODES ) {
424+ wifi_hal_stats_error_print ("%s:%d Failed to convert frequency %u to channel\n" , __func__ ,
425+ __LINE__ , freq );
426+ return NL_SKIP ;
427+ }
428+
429+ for (i = 0 ; i < stats -> arr_size && stats -> arr [i ].ch_number != channel ; i ++ );
430+ if (i == stats -> arr_size ) {
431+ //continue;
432+ wifi_hal_dbg_print ("%s:%d continue - return\n" , __func__ , __LINE__ );
433+ return NL_SKIP ;
434+ }
435+
436+ if (survey_info [NL80211_SURVEY_INFO_FREQUENCY ]) {
437+ wifi_hal_dbg_print ("%s:%d FREQUENCY: %u MHz\n" , __func__ , __LINE__ ,
438+ nla_get_u32 (survey_info [NL80211_SURVEY_INFO_FREQUENCY ]));
439+ }
440+ if (survey_info [NL80211_SURVEY_INFO_NOISE ]) {
441+ stats -> arr [i ].ch_noise =
442+ nla_get_s32 (survey_info [NL80211_SURVEY_INFO_NOISE ]);
443+ }
444+ if (survey_info [NL80211_SURVEY_INFO_TIME ]) {
445+ stats -> arr [i ].ch_utilization_total =
446+ nla_get_u64 (survey_info [NL80211_SURVEY_INFO_TIME ]);
447+ }
448+ if (survey_info [NL80211_SURVEY_INFO_TIME_BUSY ]) {
449+ stats -> arr [i ].ch_utilization_busy =
450+ nla_get_u64 (survey_info [NL80211_SURVEY_INFO_TIME_BUSY ]);
451+ }
452+
453+ if (survey_info [NL80211_SURVEY_INFO_TIME_TX ]) {
454+ stats -> arr [i ].ch_utilization_busy_tx =
455+ nla_get_u64 (survey_info [NL80211_SURVEY_INFO_TIME_TX ]);
456+ }
457+
458+ if (survey_info [NL80211_SURVEY_INFO_TIME_EXT_BUSY ]) {
459+ stats -> arr [i ].ch_utilization_busy_ext =
460+ nla_get_u64 (survey_info [NL80211_SURVEY_INFO_TIME_EXT_BUSY ]);
461+ }
462+
463+ if (survey_info [NL80211_SURVEY_INFO_TIME_RX ]) {
464+ stats -> arr [i ].ch_utilization_busy_rx =
465+ nla_get_u64 (survey_info [NL80211_SURVEY_INFO_TIME_RX ]);
466+ }
467+
468+ if (survey_info [NL80211_SURVEY_INFO_TIME_SCAN ]) {
469+ }
470+
471+ if (survey_info [NL80211_SURVEY_INFO_TIME_BSS_RX ]) {
472+ }
473+
474+ return NL_SKIP ;
475+ }
476+
477+ static int get_channel_stats (wifi_interface_info_t * interface ,
478+ wifi_channelStats_t * channel_stats_arr , int channel_stats_arr_size )
479+ {
480+ struct nl_msg * msg ;
481+ int ret = RETURN_ERR ;
482+ channel_stats_arr_t stats = { .arr = channel_stats_arr , .arr_size = channel_stats_arr_size };
483+
484+ msg = nl80211_drv_cmd_msg (g_wifi_hal .nl80211_id , interface , NLM_F_DUMP , NL80211_CMD_GET_SURVEY );
485+ if (msg == NULL ) {
486+ wifi_hal_stats_error_print ("%s:%d Failed to create NL command\n" , __func__ , __LINE__ );
487+ return RETURN_ERR ;
488+ }
489+
490+ ret = nl80211_send_and_recv (msg , get_channel_stats_handler , & stats , NULL , NULL );
491+ if (ret ) {
492+ wifi_hal_stats_error_print ("%s:%d Failed to send NL message\n" , __func__ , __LINE__ );
493+ return RETURN_ERR ;
494+ }
495+
496+ return RETURN_OK ;
497+ }
372498
373499INT wifi_getRadioChannelStats (INT radioIndex , wifi_channelStats_t * input_output_channelStats_array ,
374500 INT array_size )
375501{
502+ wifi_radio_info_t * radio ;
503+ wifi_interface_info_t * interface ;
504+
505+ wifi_hal_stats_dbg_print ("%s:%d: Get radio stats for index: %d\n" , __func__ , __LINE__ ,
506+ radioIndex );
507+
508+ radio = get_radio_by_rdk_index (radioIndex );
509+ if (radio == NULL ) {
510+ wifi_hal_stats_error_print ("%s:%d: Failed to get radio for index: %d\n" , __func__ , __LINE__ ,
511+ radioIndex );
512+ return RETURN_ERR ;
513+ }
514+
515+ interface = get_primary_interface (radio );
516+ if (interface == NULL ) {
517+ wifi_hal_stats_error_print ("%s:%d: Failed to get interface for radio index: %d\n" , __func__ ,
518+ __LINE__ , radioIndex );
519+ return RETURN_ERR ;
520+ }
521+ if (get_channel_stats (interface , input_output_channelStats_array , array_size )) {
522+ wifi_hal_stats_error_print ("%s:%d: Failed to get channel stats for radio index: %d\n" , __func__ ,
523+ __LINE__ , radioIndex );
524+ return RETURN_ERR ;
525+ }
376526 return RETURN_OK ;
377527}
528+
378529//--------------------------------------------------------------------------------------------------
379530INT wifi_getApEnable (INT apIndex , BOOL * output_bool )
380531{
@@ -518,43 +669,78 @@ static int get_sta_stats_handler(struct nl_msg *msg, void *arg)
518669 }
519670
520671 if (nla_parse_nested (stats , NL80211_STA_INFO_MAX , tb [NL80211_ATTR_STA_INFO ], stats_policy )) {
521- wifi_hal_error_print ("%s:%d Failed to parse nested attributes\n" , __func__ , __LINE__ );
672+ wifi_hal_error_print ("%s:%d Failed to parse nested attributes\n" , __func__ , __LINE__ );
522673 return NL_SKIP ;
523674 }
524675
525676 if (stats [NL80211_STA_INFO_RX_BYTES ]) {
677+ wifi_hal_dbg_print ("%s:%d cli_BytesReceived: %d\n" , __func__ , __LINE__ , nla_get_u32 (stats [NL80211_STA_INFO_RX_BYTES ]));
526678 dev -> cli_BytesReceived = nla_get_u32 (stats [NL80211_STA_INFO_RX_BYTES ]);
527679 }
528680 if (stats [NL80211_STA_INFO_TX_BYTES ]) {
681+ wifi_hal_dbg_print ("%s:%d cli_BytesSent: %d\n" , __func__ , __LINE__ , nla_get_u32 (stats [NL80211_STA_INFO_TX_BYTES ]));
529682 dev -> cli_BytesSent = nla_get_u32 (stats [NL80211_STA_INFO_TX_BYTES ]);
530683 }
531684 if (stats [NL80211_STA_INFO_RX_PACKETS ]) {
685+ wifi_hal_dbg_print ("%s:%d cli_PacketsReceived: %d\n" , __func__ , __LINE__ , nla_get_u32 (stats [NL80211_STA_INFO_RX_PACKETS ]));
532686 dev -> cli_PacketsReceived = nla_get_u32 (stats [NL80211_STA_INFO_RX_PACKETS ]);
533687 }
534688 if (stats [NL80211_STA_INFO_TX_PACKETS ]) {
689+ wifi_hal_dbg_print ("%s:%d cli_PacketsSent: %d\n" , __func__ , __LINE__ , nla_get_u32 (stats [NL80211_STA_INFO_TX_PACKETS ]));
535690 dev -> cli_PacketsSent = nla_get_u32 (stats [NL80211_STA_INFO_TX_PACKETS ]);
536691 }
537692 if (stats [NL80211_STA_INFO_TX_FAILED ]) {
693+ wifi_hal_dbg_print ("%s:%d cli_ErrorsSent: %d\n" , __func__ , __LINE__ , nla_get_u32 (stats [NL80211_STA_INFO_TX_FAILED ]));
538694 dev -> cli_ErrorsSent = nla_get_u32 (stats [NL80211_STA_INFO_TX_FAILED ]);
539695 }
540696
697+ if (stats [NL80211_STA_INFO_RX_DROP_MISC ]) {
698+ dev -> cli_RxErrors = nla_get_u32 (stats [NL80211_STA_INFO_RX_DROP_MISC ]);
699+ wifi_hal_dbg_print ("%s:%d cli_RxErrors: %d\n" , __func__ , __LINE__ , dev -> cli_RxErrors );
700+ }
701+
702+ if (stats [NL80211_STA_INFO_TX_RETRIES ]) {
703+ dev -> cli_RetransCount = nla_get_s32 (stats [NL80211_STA_INFO_TX_RETRIES ]);
704+ wifi_hal_dbg_print ("%s:%d cli_RetransCount: %d\n" , __func__ , __LINE__ , dev -> cli_RetransCount );
705+ }
706+
707+ if (stats [NL80211_STA_INFO_SIGNAL_AVG ]) {
708+ dev -> cli_RSSI = nla_get_s32 (stats [NL80211_STA_INFO_SIGNAL_AVG ]);
709+ dev -> cli_SignalStrength = dev -> cli_RSSI ;
710+ wifi_hal_dbg_print ("%s:%d cli_RSSI: %d\n" , __func__ , __LINE__ , dev -> cli_RSSI );
711+ }
712+
541713 if (stats [NL80211_STA_INFO_TX_BITRATE ] &&
542714 nla_parse_nested (rate , NL80211_RATE_INFO_MAX , stats [NL80211_STA_INFO_TX_BITRATE ], rate_policy ) == 0 ) {
543715 if (rate [NL80211_RATE_INFO_BITRATE32 ]){
544- dev -> cli_LastDataDownlinkRate = nla_get_u32 (rate [NL80211_RATE_INFO_BITRATE32 ]) * 100 ;
716+ wifi_hal_dbg_print ("%s:%d cli_LastDataDownlinkRate: %d\n" , __func__ , __LINE__ , nla_get_u32 (rate [NL80211_RATE_INFO_BITRATE32 ]));
717+ dev -> cli_LastDataDownlinkRate = nla_get_u32 (rate [NL80211_RATE_INFO_BITRATE32 ]) * 1000 ;
545718 }
546719 }
720+
547721 if (stats [NL80211_STA_INFO_RX_BITRATE ] &&
548722 nla_parse_nested (rate , NL80211_RATE_INFO_MAX , stats [NL80211_STA_INFO_RX_BITRATE ], rate_policy ) == 0 ) {
549723 if (rate [NL80211_RATE_INFO_BITRATE32 ]) {
550- dev -> cli_LastDataUplinkRate = nla_get_u32 (rate [NL80211_RATE_INFO_BITRATE32 ]) * 100 ;
724+ wifi_hal_dbg_print ("%s:%d cli_LastDataUplinkRate: %d\n" , __func__ , __LINE__ , nla_get_u32 (rate [NL80211_RATE_INFO_BITRATE32 ]));
725+ dev -> cli_LastDataUplinkRate = nla_get_u32 (rate [NL80211_RATE_INFO_BITRATE32 ]) * 1000 ;
551726 }
552727 }
553728
729+ if (stats [NL80211_STA_INFO_TX_DURATION ]) {
730+ wifi_hal_dbg_print ("%s:%d tx duration: %d\n" , __func__ , __LINE__ , nla_get_u32 (stats [NL80211_STA_INFO_TX_DURATION ]));
731+ dev -> cli_tx_duration = nla_get_u32 (stats [NL80211_STA_INFO_TX_DURATION ]);
732+ }
733+
734+ if (stats [NL80211_STA_INFO_RX_DURATION ]) {
735+ wifi_hal_dbg_print ("%s:%d rx duration: %d\n" , __func__ , __LINE__ , nla_get_u32 (stats [NL80211_STA_INFO_RX_DURATION ]));
736+ dev -> cli_rx_duration = nla_get_u32 (stats [NL80211_STA_INFO_RX_DURATION ]);
737+ }
738+
554739 if (stats [NL80211_STA_INFO_STA_FLAGS ]) {
555740 sta_flags = nla_data (stats [NL80211_STA_INFO_STA_FLAGS ]);
556741 dev -> cli_AuthenticationState = sta_flags -> mask & (1 << NL80211_STA_FLAG_AUTHORIZED ) &&
557742 sta_flags -> set & (1 << NL80211_STA_FLAG_AUTHORIZED );
743+ wifi_hal_dbg_print ("%s:%d cli_AuthenticationState: %d\n" , __func__ , __LINE__ , dev -> cli_AuthenticationState );
558744 }
559745
560746 return NL_OK ;
0 commit comments