Code arrangement
authorsaerome.kim <saerome.kim@samsung.com>
Fri, 30 Jun 2017 03:51:16 +0000 (12:51 +0900)
committersaerome.kim <saerome.kim@samsung.com>
Mon, 17 Jul 2017 02:35:37 +0000 (11:35 +0900)
- Arrange netlink library functions

Signed-off-by: saerome.kim <saerome.kim@samsung.com>
src/mesh-netlink.c

index 9e2f82f..9311fc3 100644 (file)
@@ -545,48 +545,53 @@ static char *get_chain_signal(struct nlattr *attr_list)
 static int parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen)
 {
        int rate = 0;
-       char *pos = buf;
-       struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
+       int pos = 0;
+       char str_rate[32] = { 0, };
+       char str_buf[128] = { 0, };
+       struct nlattr *rate_info[NL80211_RATE_INFO_MAX + 1];
        static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
                [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
-               [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 },
                [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
                [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
                [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
+               [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 },
        };
 
-       if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, bitrate_attr, rate_policy)) {
-               snprintf(buf, buflen, "failed to parse nested rate attributes!");
+       if (nla_parse_nested(rate_info, NL80211_RATE_INFO_MAX, bitrate_attr, rate_policy)) {
+               if (buf)
+                       snprintf(buf, buflen, "failed to parse nested rate attributes!");
                return 0;
        }
 
-       if (rinfo[NL80211_RATE_INFO_BITRATE32])
-               rate = nla_get_u32(rinfo[NL80211_RATE_INFO_BITRATE32]);
-       else if (rinfo[NL80211_RATE_INFO_BITRATE])
-               rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
+       if (rate_info[NL80211_RATE_INFO_MCS])
+               pos += snprintf(str_buf + pos, 128 - pos,
+                               " MCS %d", nla_get_u8(rate_info[NL80211_RATE_INFO_MCS]));
+       if (rate_info[NL80211_RATE_INFO_40_MHZ_WIDTH])
+               pos += snprintf(str_buf + pos, 128 - pos, " 40MHz");
+       if (rate_info[NL80211_RATE_INFO_SHORT_GI])
+               pos += snprintf(str_buf + pos, 128 - pos, " short GI");
+       if (rate_info[NL80211_RATE_INFO_VHT_MCS])
+               pos += snprintf(str_buf + pos, 128 - pos,
+                               " VHT-MCS %d", nla_get_u8(rate_info[NL80211_RATE_INFO_VHT_MCS]));
+       if (rate_info[NL80211_RATE_INFO_VHT_NSS])
+               pos += snprintf(str_buf + pos, 128 - pos,
+                               " VHT-NSS %d", nla_get_u8(rate_info[NL80211_RATE_INFO_VHT_NSS]));
+       if (rate_info[NL80211_RATE_INFO_80_MHZ_WIDTH])
+               pos += snprintf(str_buf + pos, 128 - pos, " 80MHz");
+       if (rate_info[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
+               pos += snprintf(str_buf + pos, 128 - pos, " 80P80MHz");
+       if (rate_info[NL80211_RATE_INFO_160_MHZ_WIDTH])
+               pos += snprintf(str_buf + pos, 128 - pos, " 160MHz");
+
+       if (rate_info[NL80211_RATE_INFO_BITRATE32])
+               rate = nla_get_u32(rate_info[NL80211_RATE_INFO_BITRATE32]);
+       else if (rate_info[NL80211_RATE_INFO_BITRATE])
+               rate = nla_get_u16(rate_info[NL80211_RATE_INFO_BITRATE]);
        if (rate > 0)
-               pos += snprintf(pos, buflen - (pos - buf),
-                               "%d.%d MBit/s", rate / 10, rate % 10);
-
-       if (rinfo[NL80211_RATE_INFO_MCS])
-               pos += snprintf(pos, buflen - (pos - buf),
-                               " MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]));
-       if (rinfo[NL80211_RATE_INFO_VHT_MCS])
-               pos += snprintf(pos, buflen - (pos - buf),
-                               " VHT-MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_MCS]));
-       if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
-               pos += snprintf(pos, buflen - (pos - buf), " 40MHz");
-       if (rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
-               pos += snprintf(pos, buflen - (pos - buf), " 80MHz");
-       if (rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
-               pos += snprintf(pos, buflen - (pos - buf), " 80P80MHz");
-       if (rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
-               pos += snprintf(pos, buflen - (pos - buf), " 160MHz");
-       if (rinfo[NL80211_RATE_INFO_SHORT_GI])
-               pos += snprintf(pos, buflen - (pos - buf), " short GI");
-       if (rinfo[NL80211_RATE_INFO_VHT_NSS])
-               pos += snprintf(pos, buflen - (pos - buf),
-                               " VHT-NSS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]));
+               snprintf(str_rate, 32, "%d.%d MBit/s", rate / 10, rate % 10);
+
+       if (buf)
+               snprintf(buf, buflen, "%s%s", str_rate, str_buf);
 
        return rate;
 }
@@ -672,193 +677,127 @@ static void print_power_mode(struct nlattr *a)
 
 static int _on_receive_station_info(struct nl_msg *msg, void *arg)
 {
-       struct nlattr *tb[NL80211_ATTR_MAX + 1];
        struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
-       struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
+       struct nlattr *sta_info[NL80211_STA_INFO_MAX + 1];
+       struct nlattr *attr_info[NL80211_ATTR_MAX + 1];
        struct nl80211_sta_flag_update *sta_flags;
        static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
                [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
                [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
                [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
-               [NL80211_STA_INFO_RX_BYTES64] = { .type = NLA_U64 },
-               [NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 },
-               [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
-               [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
-               [NL80211_STA_INFO_BEACON_RX] = { .type = NLA_U64},
-               [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
-               [NL80211_STA_INFO_T_OFFSET] = { .type = NLA_U64 },
-               [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
-               [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
                [NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
                [NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
                [NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
+               [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
+               [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
+               [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
+               [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
                [NL80211_STA_INFO_TX_RETRIES] = { .type = NLA_U32 },
                [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
-               [NL80211_STA_INFO_BEACON_LOSS] = { .type = NLA_U32},
-               [NL80211_STA_INFO_RX_DROP_MISC] = { .type = NLA_U64},
+               [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
+               [NL80211_STA_INFO_BSS_PARAM] = { .type = NLA_NESTED },
                [NL80211_STA_INFO_STA_FLAGS] = { .minlen = sizeof(struct nl80211_sta_flag_update) },
-               [NL80211_STA_INFO_LOCAL_PM] = { .type = NLA_U32},
-               [NL80211_STA_INFO_PEER_PM] = { .type = NLA_U32},
-               [NL80211_STA_INFO_NONPEER_PM] = { .type = NLA_U32},
+               [NL80211_STA_INFO_BEACON_LOSS] = { .type = NLA_U32},
+               [NL80211_STA_INFO_T_OFFSET] = { .type = NLA_U64 },
+               [NL80211_STA_INFO_LOCAL_PM] = { .type = NLA_U32 },
+               [NL80211_STA_INFO_PEER_PM] = { .type = NLA_U32 },
+               [NL80211_STA_INFO_NONPEER_PM] = { .type = NLA_U32 },
+               [NL80211_STA_INFO_RX_BYTES64] = { .type = NLA_U64 },
+               [NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 },
                [NL80211_STA_INFO_CHAIN_SIGNAL] = { .type = NLA_NESTED },
                [NL80211_STA_INFO_CHAIN_SIGNAL_AVG] = { .type = NLA_NESTED },
+               [NL80211_STA_INFO_RX_DROP_MISC] = { .type = NLA_U64 },
+               [NL80211_STA_INFO_BEACON_RX] = { .type = NLA_U64 },
                [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
-               [NL80211_STA_INFO_BSS_PARAM] = { .type = NLA_NESTED },
                [NL80211_STA_INFO_RX_DURATION] = { .type = NLA_U64 },
        };
-       char mac_addr[MAX_MAC_ADDR_LEN], state_name[10], dev[20];
+       char mac_addr[MAX_MAC_ADDR_LEN], dev[IF_NAMESIZE];
        char *chain;
+       char *attr_mac = NULL;
        mesh_nl_state *state = (mesh_nl_state *)arg;
        mesh_station_info_s *station_info = NULL;
 
-       nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
-                       genlmsg_attrlen(gnlh, 0), NULL);
-
-       /*
-        * TODO: validate the interface and mac address!
-        * Otherwise, there's a race condition as soon as
-        * the kernel starts sending station notifications.
-        */
+       nla_parse(attr_info, NL80211_ATTR_MAX,
+                       genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
 
-       if (!tb[NL80211_ATTR_STA_INFO]) {
-               MESH_LOGE("missing station stats !");
+       if (!attr_info[NL80211_ATTR_STA_INFO]) {
+               MESH_LOGE("[Station] missing station stats !");
                return NL_SKIP;
        }
-       if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
-                               tb[NL80211_ATTR_STA_INFO],
-                               stats_policy)) {
-               MESH_LOGE("failed to parse nested attributes!");
+
+       if (nla_parse_nested(sta_info, NL80211_STA_INFO_MAX,
+                               attr_info[NL80211_ATTR_STA_INFO], stats_policy)) {
+               MESH_LOGE("[Station] Failed to parse nested attributes!");
                return NL_SKIP;
        }
 
+       /* Allocation */
        station_info = g_try_new0(mesh_station_info_s, 1);
        if (NULL == station_info) {
                MESH_LOGE("Failed to allocate station info !");
                return NL_SKIP;
        }
 
-       mac_addr_n2a(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
-       if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
-       MESH_LOGD("Station %s (on %s)", mac_addr, dev);
+       /* BSSID */
+       attr_mac = nla_data(attr_info[NL80211_ATTR_MAC]);
+       snprintf(mac_addr, MAX_MAC_ADDR_LEN, "%02X:%02X:%02X:%02X:%02X:%02X",
+                       attr_mac[0], attr_mac[1], attr_mac[2],
+                       attr_mac[3], attr_mac[4], attr_mac[5]);
+       if_indextoname(nla_get_u32(attr_info[NL80211_ATTR_IFINDEX]), dev);
        station_info->bssid = g_strdup(mac_addr);
+       MESH_LOGD("Station %s [dev %s]", station_info->bssid, dev);
 
-       if (sinfo[NL80211_STA_INFO_INACTIVE_TIME]) {
+       /* Inactive time */
+       if (0 != sta_info[NL80211_STA_INFO_INACTIVE_TIME]) {
                station_info->inactive_time =
-                       nla_get_u32(sinfo[NL80211_STA_INFO_INACTIVE_TIME]);
+                       nla_get_u32(sta_info[NL80211_STA_INFO_INACTIVE_TIME]);
                MESH_LOGE("    inactive time:\t%u ms", station_info->inactive_time);
        }
 
-       if (sinfo[NL80211_STA_INFO_RX_BYTES64]) {
-               station_info->rx_bytes =
-                       (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
-               MESH_LOGE("    rx bytes:\t%llu", station_info->rx_bytes);
-       } else if (sinfo[NL80211_STA_INFO_RX_BYTES]) {
+       /* RX Bytes */
+       if (0 != sta_info[NL80211_STA_INFO_RX_BYTES]) {
                station_info->rx_bytes =
-                               nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
+                               nla_get_u32(sta_info[NL80211_STA_INFO_RX_BYTES]);
                MESH_LOGD("    rx bytes:\t%u", station_info->rx_bytes);
+       } else if (0 != sta_info[NL80211_STA_INFO_RX_BYTES64]) {
+               station_info->rx_bytes =
+                       (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_RX_BYTES64]);
+               MESH_LOGE("    rx bytes:\t%llu", station_info->rx_bytes);
        }
-       if (sinfo[NL80211_STA_INFO_RX_PACKETS]) {
+
+       /* RX Packets */
+       if (0 != sta_info[NL80211_STA_INFO_RX_PACKETS]) {
                station_info->rx_packets =
-                               nla_get_u32(sinfo[NL80211_STA_INFO_RX_PACKETS]);
+                               nla_get_u32(sta_info[NL80211_STA_INFO_RX_PACKETS]);
                MESH_LOGD("    rx packets:\t%u", station_info->rx_packets);
        }
 
-       if (sinfo[NL80211_STA_INFO_TX_BYTES64]) {
-               station_info->tx_bytes =
-                               (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
-               MESH_LOGD("    tx bytes:\t%llu", station_info->rx_packets);
-       } else if (sinfo[NL80211_STA_INFO_TX_BYTES]) {
+       /* TX Bytes */
+       if (0 != sta_info[NL80211_STA_INFO_TX_BYTES]) {
                station_info->tx_bytes =
-                               nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
+                               nla_get_u32(sta_info[NL80211_STA_INFO_TX_BYTES]);
                MESH_LOGD("    tx bytes:\t%u", station_info->tx_bytes);
-       }
-       if (sinfo[NL80211_STA_INFO_TX_PACKETS]) {
-               station_info->tx_packets =
-                               nla_get_u32(sinfo[NL80211_STA_INFO_TX_PACKETS]);
-               MESH_LOGD("    tx packets:\t%u", station_info->tx_packets);
-       }
-       if (sinfo[NL80211_STA_INFO_TX_RETRIES]) {
-               station_info->tx_retries =
-                               nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
-               MESH_LOGD("    tx retries:\t%u", station_info->tx_retries);
-       }
-       if (sinfo[NL80211_STA_INFO_TX_FAILED]) {
-               station_info->tx_failed =
-                               nla_get_u32(sinfo[NL80211_STA_INFO_TX_FAILED]);
-               MESH_LOGD("    tx failed:\t%u", station_info->tx_failed);
-       }
-       if (sinfo[NL80211_STA_INFO_BEACON_LOSS]) {
-               station_info->beacon_loss =
-                               nla_get_u32(sinfo[NL80211_STA_INFO_BEACON_LOSS]);
-               MESH_LOGD("    beacon loss:\t%u", station_info->beacon_loss);
-       }
-       if (sinfo[NL80211_STA_INFO_BEACON_RX]) {
-               station_info->beacon_rx =
-                               (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_BEACON_RX]);
-               MESH_LOGD("    beacon rx:\t%llu", station_info->beacon_rx);
-       }
-       if (sinfo[NL80211_STA_INFO_RX_DROP_MISC]) {
-               station_info->rx_drop_misc =
-                       (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_RX_DROP_MISC]);
-               MESH_LOGD("    rx drop misc:\t%llu", station_info->rx_drop_misc);
-       }
-
-       chain = get_chain_signal(sinfo[NL80211_STA_INFO_CHAIN_SIGNAL]);
-       if (sinfo[NL80211_STA_INFO_SIGNAL]) {
-               station_info->rssi =
-                               (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
-               MESH_LOGD("    signal:  \t%d %sdBm", station_info->rssi, chain);
-       }
-
-       chain = get_chain_signal(sinfo[NL80211_STA_INFO_CHAIN_SIGNAL_AVG]);
-       if (sinfo[NL80211_STA_INFO_SIGNAL_AVG]) {
-               station_info->rssi_avg =
-                               (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
-               MESH_LOGD("    signal avg:\t%d %sdBm", station_info->rssi_avg, chain);
-       }
-
-       if (sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG]) {
-               station_info->beacon_signal_avg =
-                               nla_get_u8(sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG]);
-               MESH_LOGD("    beacon signal avg:\t%d dBm", station_info->beacon_signal_avg);
-       }
-       if (sinfo[NL80211_STA_INFO_T_OFFSET]) {
-               station_info->t_offset =
-                       (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_T_OFFSET]);
-               MESH_LOGD("    Toffset:\t%llu us", station_info->t_offset);
-       }
-
-       if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
-               char buf[100];
-               station_info->tx_bitrate =
-                       parse_bitrate(sinfo[NL80211_STA_INFO_TX_BITRATE], buf, sizeof(buf));
-               MESH_LOGD("    tx bitrate:\t%s", buf);
-       }
-
-       if (sinfo[NL80211_STA_INFO_RX_BITRATE]) {
-               char buf[100];
-               station_info->rx_bitrate =
-                       parse_bitrate(sinfo[NL80211_STA_INFO_RX_BITRATE], buf, sizeof(buf));
-               MESH_LOGD("    rx bitrate:\t%s", buf);
-       }
-
-       if (sinfo[NL80211_STA_INFO_RX_DURATION]) {
-               station_info->rx_duration =
-                       (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_RX_DURATION]);
-               MESH_LOGD("    rx duration:\t%lld us", station_info->rx_duration);
+       } else if (0 != sta_info[NL80211_STA_INFO_TX_BYTES64]) {
+               station_info->tx_bytes =
+                               (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_TX_BYTES64]);
+               MESH_LOGD("    tx bytes:\t%llu", station_info->rx_packets);
        }
 
-       if (sinfo[NL80211_STA_INFO_LLID]) {
-               station_info->llid = nla_get_u16(sinfo[NL80211_STA_INFO_LLID]);
+       /* LLID, PLID */
+       if (0 != sta_info[NL80211_STA_INFO_LLID]) {
+               station_info->llid = nla_get_u16(sta_info[NL80211_STA_INFO_LLID]);
                MESH_LOGD("    mesh llid:\t%d", station_info->llid);
        }
-       if (sinfo[NL80211_STA_INFO_PLID]) {
-               station_info->llid = nla_get_u16(sinfo[NL80211_STA_INFO_PLID]);
+       if (0 != sta_info[NL80211_STA_INFO_PLID]) {
+               station_info->llid = nla_get_u16(sta_info[NL80211_STA_INFO_PLID]);
                MESH_LOGD("    mesh plid:\t%d", station_info->plid);
        }
-       if (sinfo[NL80211_STA_INFO_PLINK_STATE]) {
+
+       /* Plink state */
+       if (0 != sta_info[NL80211_STA_INFO_PLINK_STATE]) {
+               char state_name[10];
                station_info->mesh_plink =
-                               nla_get_u8(sinfo[NL80211_STA_INFO_PLINK_STATE]);
+                               nla_get_u8(sta_info[NL80211_STA_INFO_PLINK_STATE]);
                switch (station_info->mesh_plink) {
                case LISTEN:
                        snprintf(state_name, 10, "%s", "LISTEN");
@@ -887,28 +826,66 @@ static int _on_receive_station_info(struct nl_msg *msg, void *arg)
                }
                MESH_LOGD("    mesh plink:\t%s", state_name);
        }
-       if (sinfo[NL80211_STA_INFO_LOCAL_PM]) {
-               station_info->local_ps_mode =
-                               nla_get_u32(sinfo[NL80211_STA_INFO_LOCAL_PM]);
-               MESH_LOGD("    mesh local PS mode:\t");
-               print_power_mode(sinfo[NL80211_STA_INFO_LOCAL_PM]);
+
+       /* RSSI Signal */
+       chain = get_chain_signal(sta_info[NL80211_STA_INFO_CHAIN_SIGNAL]);
+       if (0 != sta_info[NL80211_STA_INFO_SIGNAL]) {
+               station_info->rssi =
+                               (int8_t)nla_get_u8(sta_info[NL80211_STA_INFO_SIGNAL]);
+               MESH_LOGD("    signal:  \t%d %sdBm", station_info->rssi, chain);
        }
-       if (sinfo[NL80211_STA_INFO_PEER_PM]) {
-               station_info->peer_ps_mode =
-                               nla_get_u32(sinfo[NL80211_STA_INFO_PEER_PM]);
-               MESH_LOGD("    mesh peer PS mode:\t");
-               print_power_mode(sinfo[NL80211_STA_INFO_PEER_PM]);
+
+       /* TX Bitrate */
+       if (0 != sta_info[NL80211_STA_INFO_TX_BITRATE]) {
+               char buf[100];
+               station_info->tx_bitrate =
+                       parse_bitrate(sta_info[NL80211_STA_INFO_TX_BITRATE], buf, sizeof(buf));
+               MESH_LOGD("    tx bitrate:\t%s", buf);
        }
-       if (sinfo[NL80211_STA_INFO_NONPEER_PM]) {
-               station_info->non_peer_ps_mode =
-                               nla_get_u32(sinfo[NL80211_STA_INFO_NONPEER_PM]);
-               MESH_LOGD("    mesh non-peer PS mode:\t");
-               print_power_mode(sinfo[NL80211_STA_INFO_NONPEER_PM]);
+
+       if (0 != sta_info[NL80211_STA_INFO_TX_PACKETS]) {
+               station_info->tx_packets =
+                               nla_get_u32(sta_info[NL80211_STA_INFO_TX_PACKETS]);
+               MESH_LOGD("    tx packets:\t%u", station_info->tx_packets);
+       }
+       if (0 != sta_info[NL80211_STA_INFO_TX_RETRIES]) {
+               station_info->tx_retries =
+                               nla_get_u32(sta_info[NL80211_STA_INFO_TX_RETRIES]);
+               MESH_LOGD("    tx retries:\t%u", station_info->tx_retries);
+       }
+       if (0 != sta_info[NL80211_STA_INFO_TX_FAILED]) {
+               station_info->tx_failed =
+                               nla_get_u32(sta_info[NL80211_STA_INFO_TX_FAILED]);
+               MESH_LOGD("    tx failed:\t%u", station_info->tx_failed);
+       }
+
+       /* Signal average */
+       chain = get_chain_signal(sta_info[NL80211_STA_INFO_CHAIN_SIGNAL_AVG]);
+       if (0 != sta_info[NL80211_STA_INFO_SIGNAL_AVG]) {
+               station_info->rssi_avg =
+                               (int8_t)nla_get_u8(sta_info[NL80211_STA_INFO_SIGNAL_AVG]);
+               MESH_LOGD("    signal avg:\t%d %sdBm", station_info->rssi_avg, chain);
+       }
+
+       if (0 != sta_info[NL80211_STA_INFO_RX_BITRATE]) {
+               char buf[100];
+               station_info->rx_bitrate =
+                       parse_bitrate(sta_info[NL80211_STA_INFO_RX_BITRATE], buf, sizeof(buf));
+               MESH_LOGD("    rx bitrate:\t%s", buf);
+       }
+
+       if (0 != sta_info[NL80211_STA_INFO_BSS_PARAM])
+               parse_bss_param(sta_info[NL80211_STA_INFO_BSS_PARAM], station_info);
+
+       if (0 != sta_info[NL80211_STA_INFO_CONNECTED_TIME]) {
+               station_info->connected_time =
+                               nla_get_u32(sta_info[NL80211_STA_INFO_CONNECTED_TIME]);
+               MESH_LOGD("    connected time:\t%u seconds", station_info->connected_time);
        }
 
-       if (sinfo[NL80211_STA_INFO_STA_FLAGS]) {
+       if (0 != sta_info[NL80211_STA_INFO_STA_FLAGS]) {
                sta_flags = (struct nl80211_sta_flag_update *)
-                           nla_data(sinfo[NL80211_STA_INFO_STA_FLAGS]);
+                           nla_data(sta_info[NL80211_STA_INFO_STA_FLAGS]);
 
                if (sta_flags->mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
                        MESH_LOGD("    authorized:");
@@ -988,12 +965,59 @@ static int _on_receive_station_info(struct nl_msg *msg, void *arg)
                }
        }
 
-       if (sinfo[NL80211_STA_INFO_BSS_PARAM])
-               parse_bss_param(sinfo[NL80211_STA_INFO_BSS_PARAM], station_info);
-       if (sinfo[NL80211_STA_INFO_CONNECTED_TIME]) {
-               station_info->connected_time =
-                               nla_get_u32(sinfo[NL80211_STA_INFO_CONNECTED_TIME]);
-               MESH_LOGD("    connected time:\t%u seconds", station_info->connected_time);
+       if (0 != sta_info[NL80211_STA_INFO_BEACON_LOSS]) {
+               station_info->beacon_loss =
+                               nla_get_u32(sta_info[NL80211_STA_INFO_BEACON_LOSS]);
+               MESH_LOGD("    beacon loss:\t%u", station_info->beacon_loss);
+       }
+
+       if (0 != sta_info[NL80211_STA_INFO_T_OFFSET]) {
+               station_info->t_offset =
+                       (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_T_OFFSET]);
+               MESH_LOGD("    Toffset:\t%llu us", station_info->t_offset);
+       }
+
+       if (0 != sta_info[NL80211_STA_INFO_LOCAL_PM]) {
+               station_info->local_ps_mode =
+                               nla_get_u32(sta_info[NL80211_STA_INFO_LOCAL_PM]);
+               MESH_LOGD("    mesh local PS mode:\t");
+               print_power_mode(sta_info[NL80211_STA_INFO_LOCAL_PM]);
+       }
+       if (0 != sta_info[NL80211_STA_INFO_PEER_PM]) {
+               station_info->peer_ps_mode =
+                               nla_get_u32(sta_info[NL80211_STA_INFO_PEER_PM]);
+               MESH_LOGD("    mesh peer PS mode:\t");
+               print_power_mode(sta_info[NL80211_STA_INFO_PEER_PM]);
+       }
+       if (0 != sta_info[NL80211_STA_INFO_NONPEER_PM]) {
+               station_info->non_peer_ps_mode =
+                               nla_get_u32(sta_info[NL80211_STA_INFO_NONPEER_PM]);
+               MESH_LOGD("    mesh non-peer PS mode:\t");
+               print_power_mode(sta_info[NL80211_STA_INFO_NONPEER_PM]);
+       }
+
+       if (0 != sta_info[NL80211_STA_INFO_RX_DROP_MISC]) {
+               station_info->rx_drop_misc =
+                       (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_RX_DROP_MISC]);
+               MESH_LOGD("    rx drop misc:\t%llu", station_info->rx_drop_misc);
+       }
+
+       if (0 != sta_info[NL80211_STA_INFO_BEACON_RX]) {
+               station_info->beacon_rx =
+                               (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_BEACON_RX]);
+               MESH_LOGD("    beacon rx:\t%llu", station_info->beacon_rx);
+       }
+
+       if (0 != sta_info[NL80211_STA_INFO_BEACON_SIGNAL_AVG]) {
+               station_info->beacon_signal_avg =
+                               nla_get_u8(sta_info[NL80211_STA_INFO_BEACON_SIGNAL_AVG]);
+               MESH_LOGD("    beacon signal avg:\t%d dBm", station_info->beacon_signal_avg);
+       }
+
+       if (0 != sta_info[NL80211_STA_INFO_RX_DURATION]) {
+               station_info->rx_duration =
+                       (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_RX_DURATION]);
+               MESH_LOGD("    rx duration:\t%lld us", station_info->rx_duration);
        }
 
        MESH_LOGD("");