static void get_wifi_iface_stats(wifi_iface_stat *stats, struct nlattr **tb_vendor) { struct nlattr *wmmInfo; wifi_wmm_ac_stat *pWmmStats; int i=0, rem; stats->beacon_rx = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX]); stats->mgmt_rx = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX]); stats->mgmt_action_rx = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX]); stats->mgmt_action_tx = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX]); stats->rssi_mgmt = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT]); stats->rssi_data = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA]); stats->rssi_ack = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK]); ALOGI("STATS IFACE: beaconRx : %u ", stats->beacon_rx); ALOGI("STATS IFACE: mgmtRx %u ", stats->mgmt_rx); ALOGI("STATS IFACE: mgmtActionRx %u ", stats->mgmt_action_rx); ALOGI("STATS IFACE: mgmtActionTx %u ", stats->mgmt_action_tx); ALOGI("STATS IFACE: rssiMgmt %u ", stats->rssi_mgmt); ALOGI("STATS IFACE: rssiData %u ", stats->rssi_data); ALOGI("STATS IFACE: rssiAck %u ", stats->rssi_ack); for (wmmInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO]); nla_ok(wmmInfo, rem); wmmInfo = nla_next(wmmInfo, &(rem))) { struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1]; pWmmStats = (wifi_wmm_ac_stat *) ((u8 *)stats->ac + (i * sizeof(wifi_wmm_ac_stat))); nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(wmmInfo), nla_len(wmmInfo), NULL); get_wifi_wmm_ac_stat(pWmmStats, tb2); } }
static void get_wifi_peer_info(wifi_peer_info *stats, struct nlattr **tb_vendor) { u32 i = 0, len = 0; int rem; wifi_rate_stat * pRateStats; struct nlattr *rateInfo; stats->type = (wifi_peer_type)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE]); len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS]); len = ((sizeof(stats->peer_mac_address) <= len) ? sizeof(stats->peer_mac_address) : len); memcpy((void *)&stats->peer_mac_address[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS]), len); stats->capabilities = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES]); stats->num_rate = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES]); ALOGI("STATS PEER_ALL : numPeers %u", stats->type); ALOGI("STATS PEER_ALL : peerMacAddress %0x:%0x:%0x:%0x:%0x:%0x ", stats->peer_mac_address[0], stats->peer_mac_address[1], stats->peer_mac_address[2],stats->peer_mac_address[3], stats->peer_mac_address[4],stats->peer_mac_address[5]); ALOGI("STATS PEER_ALL : capabilities %0x", stats->capabilities); ALOGI("STATS PEER_ALL : numRate %u", stats->num_rate); for (rateInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO]); nla_ok(rateInfo, rem); rateInfo = nla_next(rateInfo, &(rem))) { struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1]; pRateStats = (wifi_rate_stat *) ((u8 *)stats->rate_stats + (i++ * sizeof(wifi_rate_stat))); nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(rateInfo), nla_len(rateInfo), NULL); get_wifi_rate_stat(pRateStats, tb2); } }
static int sample(struct datapath *dp, struct sk_buff *skb, const struct nlattr *attr, struct ovs_key_ipv4_tunnel *tun_key) { const struct nlattr *acts_list = NULL; const struct nlattr *a; int rem; for (a = nla_data(attr), rem = nla_len(attr); rem > 0; a = nla_next(a, &rem)) { switch (nla_type(a)) { case OVS_SAMPLE_ATTR_PROBABILITY: if (net_random() >= nla_get_u32(a)) return 0; break; case OVS_SAMPLE_ATTR_ACTIONS: acts_list = a; break; } } return do_execute_actions(dp, skb, nla_data(acts_list), nla_len(acts_list), tun_key, true); }
static int validate_nla_stream(uint8_t *buf, size_t buflen) { struct nlattr *cur_attr; int remaining, attr_cnt = 0; cur_attr = (struct nlattr *) buf; remaining = buflen; while (nla_ok(cur_attr, remaining)) { attr_cnt++; cur_attr = nla_next(cur_attr, &remaining); } if (!attr_cnt) { LOG_ERR_("No valid attributes found in the input!\n"); return -EINVAL; } if (remaining) LOG_WARN_("%d invalid bytes at the end detected of the" " input. Skipping these..\n", remaining); LOG_NOTICE_("Found %d attributes in the input stream\n", attr_cnt); return 0; }
static int output_userspace(struct datapath *dp, struct sk_buff *skb, const struct nlattr *attr) { struct dp_upcall_info upcall; const struct nlattr *a; int rem; upcall.cmd = OVS_PACKET_CMD_ACTION; upcall.key = &OVS_CB(skb)->flow->key; upcall.userdata = NULL; upcall.pid = 0; for (a = nla_data(attr), rem = nla_len(attr); rem > 0; a = nla_next(a, &rem)) { switch (nla_type(a)) { case OVS_USERSPACE_ATTR_USERDATA: upcall.userdata = a; break; case OVS_USERSPACE_ATTR_PID: upcall.pid = nla_get_u32(a); break; } } return ovs_dp_upcall(dp, skb, &upcall); }
static int cb_handler(struct nl_msg * msg, void * arg) { * (int*) arg = 123; // cbarg struct nlmsghdr * hdr = nlmsg_hdr(msg); struct genlmsghdr * gnlh = nlmsg_data(hdr); int valid = genlmsg_validate(hdr, 0, DEMO_ATTR_MAX, demo_gnl_policy); printf("valid %d %s\n", valid, valid ? "ERROR" : "OK"); // one way struct nlattr * attrs[DEMO_ATTR_MAX + 1]; if (genlmsg_parse(hdr, 0, attrs, DEMO_ATTR_MAX, demo_gnl_policy) < 0) { printf("genlsmg_parse ERROR\n"); } else { printf("genlsmg_parse OK\n"); printf("attr1 %s\n", nla_get_string(attrs[DEMO_ATTR1_STRING])); printf("attr2 %x\n", nla_get_u16(attrs[DEMO_ATTR2_UINT16])); struct attr_custom * cp = (struct attr_custom *) nla_data(attrs[DEMO_ATTR3_CUSTOM]); printf("attr3 %d %ld %f %lf\n", cp->a, cp->b, cp->c,cp->d); } // another way printf("gnlh->cmd %d\n", gnlh->cmd); //--- DEMO_CMD_ECHO int remaining = genlmsg_attrlen(gnlh, 0); struct nlattr * attr = genlmsg_attrdata(gnlh, 0); while (nla_ok(attr, remaining)) { printf("remaining %d\n", remaining); printf("attr @ %p\n", attr); // nla_get_string(attr) attr = nla_next(attr, &remaining); } nl_msg_dump(msg, stderr); return NL_STOP; }
static void get_wifi_radio_stats(wifi_radio_stat *stats, struct nlattr **tb_vendor) { u32 i = 0; struct nlattr *chInfo; wifi_channel_stat *pChStats; int rem; printf("sunil %d : %s \n",__LINE__,__func__); stats->radio = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID]); printf("sunil %d : %s \n",__LINE__,__func__); stats->on_time = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME]); printf("sunil %d : %s \n",__LINE__,__func__); stats->tx_time = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME]); printf("sunil %d : %s \n",__LINE__,__func__); stats->rx_time = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME]); ALOGI("<<<< rxTime is %u ", stats->rx_time); stats->on_time_scan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN]); stats->on_time_nbd = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD]); stats->on_time_gscan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN]); stats->on_time_roam_scan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN]); stats->on_time_pno_scan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN]); stats->on_time_hs20 = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20]); stats->num_channels = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS]); for (chInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO]); nla_ok(chInfo, rem); chInfo = nla_next(chInfo, &(rem))) { struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1]; pChStats = (wifi_channel_stat *) ((u8 *)stats->channels + (i++ * (sizeof(wifi_channel_stat)))); nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(chInfo), nla_len(chInfo), NULL); pChStats->channel.width = (wifi_channel_width)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH]); pChStats->channel.center_freq = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ]); pChStats->channel.center_freq0 = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0]); pChStats->channel.center_freq1 = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1]); pChStats->on_time = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME]); pChStats->cca_busy_time = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME]); } }
/* Execute a list of actions against 'skb'. */ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, const struct nlattr *attr, int len, bool keep_skb) { /* Every output action needs a separate clone of 'skb', but the common * case is just a single output action, so that doing a clone and * then freeing the original skbuff is wasteful. So the following code * is slightly obscure just to avoid that. */ int prev_port = -1; const struct nlattr *a; int rem; for (a = attr, rem = len; rem > 0; a = nla_next(a, &rem)) { int err = 0; if (prev_port != -1) { do_output(dp, skb_clone(skb, GFP_ATOMIC), prev_port); prev_port = -1; } switch (nla_type(a)) { case OVS_ACTION_ATTR_OUTPUT: prev_port = nla_get_u32(a); break; case OVS_ACTION_ATTR_USERSPACE: output_userspace(dp, skb, a); break; case OVS_ACTION_ATTR_PUSH_VLAN: err = push_vlan(skb, nla_data(a)); if (unlikely(err)) /* skb already freed. */ return err; break; case OVS_ACTION_ATTR_POP_VLAN: err = pop_vlan(skb); break; case OVS_ACTION_ATTR_SET: err = execute_set_action(skb, nla_data(a)); break; case OVS_ACTION_ATTR_SAMPLE: err = sample(dp, skb, a); break; } if (unlikely(err)) { kfree_skb(skb); return err; } } if (prev_port != -1) { if (keep_skb) skb = skb_clone(skb, GFP_ATOMIC); do_output(dp, skb, prev_port); } else if (!keep_skb) consume_skb(skb); return 0; }
void process_neigh_msg(struct nlmsghdr *nlmsg, int type) { int hdrlen, attrlen; struct nlattr *attr; struct ndmsg *nbh; switchlink_mac_addr_t mac_addr; bool mac_addr_valid = false; bool ipaddr_valid = false; switchlink_ip_addr_t ipaddr; assert((type == RTM_NEWNEIGH) || (type == RTM_DELNEIGH)); nbh = nlmsg_data(nlmsg); hdrlen = sizeof(struct ndmsg); NL_LOG_DEBUG(("%sneigh: family = %d, ifindex = %d, state = 0x%x, " "flags = 0x%x, type = %d\n", ((type == RTM_NEWNEIGH) ? "new" : "del"), nbh->ndm_family, nbh->ndm_ifindex, nbh->ndm_state, nbh->ndm_flags, nbh->ndm_type)); switchlink_db_interface_info_t ifinfo; if (switchlink_db_interface_get_info(nbh->ndm_ifindex, &ifinfo) != SWITCHLINK_DB_STATUS_SUCCESS) { NL_LOG_DEBUG(("neigh: switchlink_db_interface_get_info failed\n")); return; } if (strncmp(ifinfo.ifname, SWITCHLINK_CPU_INTERFACE_NAME, SWITCHLINK_INTERFACE_NAME_LEN_MAX) == 0) { NL_LOG_DEBUG(("neigh: skipping neighbor on CPU interface\n")); return; } memset(&ipaddr, 0, sizeof(switchlink_ip_addr_t)); attrlen = nlmsg_attrlen(nlmsg, hdrlen); attr = nlmsg_attrdata(nlmsg, hdrlen); while (nla_ok(attr, attrlen)) { int attr_type = nla_type(attr); switch (attr_type) { case NDA_DST: ipaddr_valid = true; ipaddr.family = nbh->ndm_family; if (nbh->ndm_family == AF_INET) { ipaddr.ip.v4addr.s_addr = ntohl(nla_get_u32(attr)); ipaddr.prefix_len = 32; } else { memcpy(&(ipaddr.ip.v6addr), nla_data(attr), nla_len(attr)); ipaddr.prefix_len = 128; } break; case NDA_LLADDR: { uint64_t lladdr; mac_addr_valid = true; lladdr = nla_get_u64(attr); memcpy(mac_addr, &lladdr, 6); break; } default: NL_LOG_DEBUG(("neigh: skipping attr(%d)\n", attr_type)); break; } attr = nla_next(attr, &attrlen); } switchlink_handle_t intf_h = ifinfo.intf_h; switchlink_handle_t bridge_h = 0; if (ifinfo.intf_type == SWITCHLINK_INTF_TYPE_L2_ACCESS) { bridge_h = ifinfo.bridge_h; assert(bridge_h); } if (type == RTM_NEWNEIGH) { if (bridge_h && mac_addr_valid) { mac_create(mac_addr, bridge_h, intf_h); } if (ipaddr_valid) { if (mac_addr_valid) { neigh_create(g_default_vrf_h, &ipaddr, mac_addr, intf_h); } else { // mac address is not valid, remove the neighbor entry neigh_delete(g_default_vrf_h, &ipaddr, intf_h); } } } else { if (bridge_h && mac_addr_valid) { mac_delete(mac_addr, bridge_h); } if (ipaddr_valid) { neigh_delete(g_default_vrf_h, &ipaddr, intf_h); } } }
void process_address_msg(struct nlmsghdr *nlmsg, int type) { int hdrlen, attrlen; struct nlattr *attr; struct ifaddrmsg *addrmsg; bool addr_valid = false; switchlink_ip_addr_t addr; assert((type == RTM_NEWADDR) || (type == RTM_DELADDR)); addrmsg = nlmsg_data(nlmsg); hdrlen = sizeof(struct ifaddrmsg); NL_LOG_DEBUG(("%saddr: family = %d, prefixlen = %d, flags = 0x%x, " "scope = 0x%x ifindex = %d\n", ((type == RTM_NEWADDR) ? "new" : "del"), addrmsg->ifa_family, addrmsg->ifa_prefixlen, addrmsg->ifa_flags, addrmsg->ifa_scope, addrmsg->ifa_index)); if ((addrmsg->ifa_family != AF_INET) && (addrmsg->ifa_family != AF_INET6)) { // an address family that we are not interested in, skip return; } switchlink_db_status_t status; switchlink_intf_type_t intf_type = SWITCHLINK_INTF_TYPE_NONE; switchlink_handle_t intf_h = 0; bool create_l3vi = false; switchlink_db_interface_info_t ifinfo; status = switchlink_db_interface_get_info(addrmsg->ifa_index, &ifinfo); if (status == SWITCHLINK_DB_STATUS_SUCCESS) { intf_type = ifinfo.intf_type; intf_h = ifinfo.intf_h; } else { switchlink_db_bridge_info_t brinfo; status = switchlink_db_bridge_get_info(addrmsg->ifa_index, &brinfo); if (status == SWITCHLINK_DB_STATUS_SUCCESS) { create_l3vi = true; } else { // an interface that we are not interested in, skip return; } } if (strcmp(ifinfo.ifname, SWITCHLINK_CPU_INTERFACE_NAME) == 0) { // address on CPU interface, skip return; } attrlen = nlmsg_attrlen(nlmsg, hdrlen); attr = nlmsg_attrdata(nlmsg, hdrlen); while (nla_ok(attr, attrlen)) { int attr_type = nla_type(attr); switch (attr_type) { case IFA_ADDRESS: addr_valid = true; memset(&addr, 0, sizeof(switchlink_ip_addr_t)); addr.family = addrmsg->ifa_family; addr.prefix_len = addrmsg->ifa_prefixlen; if (addrmsg->ifa_family == AF_INET) { addr.ip.v4addr.s_addr = ntohl(nla_get_u32(attr)); } else { memcpy(&(addr.ip.v6addr), nla_data(attr), nla_len(attr)); } break; default: NL_LOG_DEBUG(("addr: skipping attr(%d)\n", attr_type)); break; } attr = nla_next(attr, &attrlen); } if (type == RTM_NEWADDR) { if ((addrmsg->ifa_family == AF_INET) || ((addrmsg->ifa_family == AF_INET6) && !IN6_IS_ADDR_LINKLOCAL(&(addr.ip.v6addr)))) { if (create_l3vi) { interface_create_l3vi(addrmsg->ifa_index); status = switchlink_db_interface_get_info(addrmsg->ifa_index, &ifinfo); assert(status == SWITCHLINK_DB_STATUS_SUCCESS); intf_h = ifinfo.intf_h; } else { if (intf_type == SWITCHLINK_INTF_TYPE_L2_ACCESS) { interface_change_type(addrmsg->ifa_index, SWITCHLINK_INTF_TYPE_L3); } } } if (addr_valid) { switchlink_ip_addr_t null_gateway; memset(&null_gateway, 0, sizeof(null_gateway)); null_gateway.family = addr.family; // add the subnet route route_create(g_default_vrf_h, &addr, &null_gateway, 0, intf_h); // add the interface route if (addrmsg->ifa_family == AF_INET) { addr.prefix_len = 32; } else { addr.prefix_len = 128; } route_create(g_default_vrf_h, &addr, &null_gateway, 0, intf_h); } } else { if (addr_valid) { // remove the subnet route route_delete(g_default_vrf_h, &addr); // remove the interface route if (addrmsg->ifa_family == AF_INET) { addr.prefix_len = 32; } else { addr.prefix_len = 128; } route_delete(g_default_vrf_h, &addr); } } }
/* This function will be the main handler for incoming (from driver) GSscan_SUBCMD. * Calls the appropriate callback handler after parsing the vendor data. */ int GScanCommandEventHandler::handleEvent(WifiEvent &event) { ALOGI("GScanCommandEventHandler::handleEvent: Got a GSCAN Event" " message from the Driver."); unsigned i=0; int ret = WIFI_SUCCESS; u32 status; wifi_scan_result *result = NULL; struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; WifiVendorCommand::handleEvent(event); nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, (struct nlattr *)mVendorData, mDataLen, NULL); switch(mSubcmd) { case QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT: { wifi_request_id reqId; u32 len = 0; u32 resultsBufSize = 0; u32 lengthOfInfoElements = 0; ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT " "received."); if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) { ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Exit.", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } reqId = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] ); /* If this is not for us, just ignore it. */ if (reqId != mRequestId) { ALOGE("%s: Event has Req. ID:%d <> Ours:%d, ignore it.", __func__, reqId, mRequestId); break; } /* Parse and extract the results. */ if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH ]) { ALOGE("%s:RESULTS_SCAN_RESULT_IE_LENGTH not found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } lengthOfInfoElements = nla_get_u32( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH]); ALOGI("%s: RESULTS_SCAN_RESULT_IE_LENGTH =%d", __func__, lengthOfInfoElements); resultsBufSize = lengthOfInfoElements + sizeof(wifi_scan_result); result = (wifi_scan_result *) malloc (resultsBufSize); if (!result) { ALOGE("%s: Failed to alloc memory for result struct. Exit.\n", __func__); ret = WIFI_ERROR_OUT_OF_MEMORY; break; } memset(result, 0, resultsBufSize); result->ie_length = lengthOfInfoElements; /* Extract and fill out the wifi_scan_result struct. */ if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP ]) { ALOGE("%s: RESULTS_SCAN_RESULT_TIME_STAMP not found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->ts = nla_get_u64( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP ]); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID ]) { ALOGE("%s: RESULTS_SCAN_RESULT_SSID not found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } len = nla_len(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]); len = sizeof(result->ssid) <= len ? sizeof(result->ssid) : len; memcpy((void *)&result->ssid, nla_data( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), len); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID ]) { ALOGE("%s: RESULTS_SCAN_RESULT_BSSID not found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } len = nla_len( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]); len = sizeof(result->bssid) <= len ? sizeof(result->bssid) : len; memcpy(&result->bssid, nla_data( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), len); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL ]) { ALOGE("%s: RESULTS_SCAN_RESULT_CHANNEL not found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->channel = nla_get_u32( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI ]) { ALOGE("%s: RESULTS_SCAN_RESULT_RSSI not found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->rssi = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI] ); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT ]) { ALOGE("%s: RESULTS_SCAN_RESULT_RTT not found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->rtt = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD ]) { ALOGE("%s: RESULTS_SCAN_RESULT_RTT_SD not found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->rtt_sd = nla_get_u32( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD]) { ALOGE("%s: RESULTS_SCAN_RESULT_BEACON_PERIOD not found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->beacon_period = nla_get_u16( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD]); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY ]) { ALOGE("%s: RESULTS_SCAN_RESULT_CAPABILITY not found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->capability = nla_get_u16( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY]); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA ]) { ALOGE("%s: RESULTS_SCAN_RESULT_IE_DATA not found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } memcpy(&(result->ie_data[0]), nla_data(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA]), lengthOfInfoElements); ALOGE("handleEvent:FULL_SCAN_RESULTS: ts %lld ", result->ts); ALOGE("handleEvent:FULL_SCAN_RESULTS: SSID %s ", result->ssid) ; ALOGE("handleEvent:FULL_SCAN_RESULTS: " "BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n", result->bssid[0], result->bssid[1], result->bssid[2], result->bssid[3], result->bssid[4], result->bssid[5]); ALOGE("handleEvent:FULL_SCAN_RESULTS: channel %d ", result->channel); ALOGE("handleEvent:FULL_SCAN_RESULTS: rssi %d ", result->rssi); ALOGE("handleEvent:FULL_SCAN_RESULTS: rtt %lld ", result->rtt); ALOGE("handleEvent:FULL_SCAN_RESULTS: rtt_sd %lld ", result->rtt_sd); ALOGE("handleEvent:FULL_SCAN_RESULTS: beacon period %d ", result->beacon_period); ALOGE("handleEvent:FULL_SCAN_RESULTS: capability %d ", result->capability); ALOGE("handleEvent:FULL_SCAN_RESULTS: IE length %d ", result->ie_length); ALOGE("%s: Invoking the callback. \n", __func__); if (mHandler.on_full_scan_result) { (*mHandler.on_full_scan_result)(reqId, result); /* Reset flag and num counter. */ free(result); result = NULL; } } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE: { wifi_request_id id; u32 numResults = 0; ALOGD("Event " "QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE " "received."); if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) { ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID" "not found. Exit", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } id = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] ); /* If this is not for us, then ignore it. */ if (id != mRequestId) { ALOGE("%s: Event has Req. ID:%d <> ours:%d", __func__, id, mRequestId); break; } if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) { ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } numResults = nla_get_u32(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]); ALOGE("%s: number of results:%d", __func__, numResults); /* Invoke the callback func to report the number of results. */ ALOGE("%s: Calling on_scan_results_available handler", __func__); if (!mHandler.on_scan_results_available) { break; } (*mHandler.on_scan_results_available)(id, numResults); } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND: { wifi_request_id id; u32 resultsBufSize = 0; u32 numResults = 0; u32 startingIndex, sizeOfObtainedResults; ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND " "received."); id = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] ); /* If this is not for us, just ignore it. */ if (id != mRequestId) { ALOGE("%s: Event has Req. ID:%d <> ours:%d", __func__, id, mRequestId); break; } if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) { ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } numResults = nla_get_u32(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]); ALOGE("%s: number of results:%d", __func__, numResults); /* Get the memory size of previous fragments, if any. */ sizeOfObtainedResults = mHotlistApFoundNumResults * sizeof(wifi_scan_result); mHotlistApFoundNumResults += numResults; resultsBufSize += mHotlistApFoundNumResults * sizeof(wifi_scan_result); /* Check if this chunck of scan results is a continuation of * a previous one. */ if (mHotlistApFoundMoreData) { mHotlistApFoundResults = (wifi_scan_result *) realloc (mHotlistApFoundResults, resultsBufSize); } else { mHotlistApFoundResults = (wifi_scan_result *) malloc (resultsBufSize); } if (!mHotlistApFoundResults) { ALOGE("%s: Failed to alloc memory for results array. Exit.\n", __func__); ret = WIFI_ERROR_OUT_OF_MEMORY; break; } /* Initialize the newly allocated memory area with 0. */ memset((u8 *)mHotlistApFoundResults + sizeOfObtainedResults, 0, resultsBufSize - sizeOfObtainedResults); ALOGE("%s: Num of AP FOUND results = %d. \n", __func__, mHotlistApFoundNumResults); /* To support fragmentation from firmware, monitor the * MORE_DTATA flag and cache results until MORE_DATA = 0. * Only then we can pass on the results to framework through * the callback function. */ if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) { ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA not" " found", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } else { mHotlistApFoundMoreData = nla_get_u8( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]); ALOGE("%s: More data = %d. \n", __func__, mHotlistApFoundMoreData); } ALOGE("%s: Extract hotlist_ap_found results.\n", __func__); startingIndex = mHotlistApFoundNumResults - numResults; ALOGE("%s: starting_index:%d", __func__, startingIndex); ret = gscan_get_hotlist_ap_found_results(numResults, mHotlistApFoundResults, startingIndex, tbVendor); /* If a parsing error occurred, exit and proceed for cleanup. */ if (ret) break; /* Send the results if no more result data fragments are expected. */ if (!mHotlistApFoundMoreData) { (*mHandler.on_hotlist_ap_found)(id, mHotlistApFoundNumResults, mHotlistApFoundResults); /* Reset flag and num counter. */ free(mHotlistApFoundResults); mHotlistApFoundResults = NULL; mHotlistApFoundMoreData = false; mHotlistApFoundNumResults = 0; } } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE: { wifi_request_id reqId; u32 numResults = 0, sizeOfObtainedResults; u32 startingIndex, index = 0; struct nlattr *scanResultsInfo; int rem = 0; ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE " "received."); if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) { ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Exit.", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } reqId = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] ); /* If this is not for us, just ignore it. */ if (reqId != mRequestId) { ALOGE("%s: Event has Req. ID:%d <> ours:%d", __func__, reqId, mRequestId); break; } if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) { ALOGE("%s: ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found." "Exit.", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } numResults = nla_get_u32(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]); /* Get the memory size of previous fragments, if any. */ sizeOfObtainedResults = sizeof(wifi_significant_change_result *) * mSignificantChangeNumResults; index = mSignificantChangeNumResults; mSignificantChangeNumResults += numResults; /* * Check if this chunck of wifi_significant_change results is a * continuation of a previous one. */ if (mSignificantChangeMoreData) { mSignificantChangeResults = (wifi_significant_change_result **) realloc (mSignificantChangeResults, sizeof(wifi_significant_change_result *) * mSignificantChangeNumResults); } else { mSignificantChangeResults = (wifi_significant_change_result **) malloc (sizeof(wifi_significant_change_result *) * mSignificantChangeNumResults); } if (!mSignificantChangeResults) { ALOGE("%s: Failed to alloc memory for results array. Exit.\n", __func__); ret = WIFI_ERROR_OUT_OF_MEMORY; break; } /* Initialize the newly allocated memory area with 0. */ memset((u8 *)mSignificantChangeResults + sizeOfObtainedResults, 0, sizeof(wifi_significant_change_result *) * numResults); ALOGD("%s: mSignificantChangeMoreData = %d", __func__, mSignificantChangeMoreData); for (scanResultsInfo = (struct nlattr *) nla_data(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]), rem = nla_len(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]); nla_ok(scanResultsInfo, rem); scanResultsInfo = nla_next(scanResultsInfo, &(rem))) { u32 num_rssi = 0; u32 resultsBufSize = 0; struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, (struct nlattr *) nla_data(scanResultsInfo), nla_len(scanResultsInfo), NULL); if (!tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI ]) { ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_" "SIGNIFICANT_CHANGE_RESULT_NUM_RSSI not found. " "Exit.", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } num_rssi = nla_get_u32(tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI ]); resultsBufSize = sizeof(wifi_significant_change_result) + num_rssi * sizeof(wifi_rssi); mSignificantChangeResults[index] = (wifi_significant_change_result *) malloc (resultsBufSize); if (!mSignificantChangeResults[index]) { ALOGE("%s: Failed to alloc memory for results array. Exit.\n", __func__); ret = WIFI_ERROR_OUT_OF_MEMORY; break; } /* Initialize the newly allocated memory area with 0. */ memset((u8 *)mSignificantChangeResults[index], 0, resultsBufSize); ALOGE("%s: For Significant Change results[%d], num_rssi:%d\n", __func__, index, num_rssi); index++; } ALOGE("%s: Extract significant change results.\n", __func__); startingIndex = mSignificantChangeNumResults - numResults; ret = gscan_get_significant_change_results(numResults, mSignificantChangeResults, startingIndex, tbVendor); /* If a parsing error occurred, exit and proceed for cleanup. */ if (ret) break; /* To support fragmentation from firmware, monitor the * MORE_DTATA flag and cache results until MORE_DATA = 0. * Only then we can pass on the results to framework through * the callback function. */ if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) { ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA not" " found. Stop parsing and exit.", __func__); break; } mSignificantChangeMoreData = nla_get_u8( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]); ALOGE("%s: More data = %d. \n", __func__, mSignificantChangeMoreData); /* Send the results if no more result fragments are expected */ if (!mSignificantChangeMoreData) { ALOGE("%s: Invoking the callback. \n", __func__); (*mHandler.on_significant_change)(reqId, mSignificantChangeNumResults, mSignificantChangeResults); /* Reset flag and num counter. */ for (index = 0; index < mSignificantChangeNumResults; index++) { free(mSignificantChangeResults[index]); mSignificantChangeResults[index] = NULL; } free(mSignificantChangeResults); mSignificantChangeResults = NULL; mSignificantChangeNumResults = 0; mSignificantChangeMoreData = false; } } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT: { wifi_scan_event scanEvent; u32 scanEventStatus = 0; wifi_request_id reqId; ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT " "received."); if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) { ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Exit.", __func__); ret = WIFI_ERROR_INVALID_ARGS; break; } reqId = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] ); /* If this is not for us, just ignore it. */ if (reqId != mRequestId) { ALOGE("%s: Event has Req. ID:%d <> ours:%d", __func__, reqId, mRequestId); break; } if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_TYPE]) { ALOGE("%s: GSCAN_RESULTS_SCAN_EVENT_TYPE not" " found. Stop parsing and exit.", __func__); break; } scanEvent = (wifi_scan_event) nla_get_u8(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_TYPE]); if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_STATUS]) { ALOGE("%s: GSCAN_RESULTS_SCAN_EVENT_STATUS not" " found. Stop parsing and exit.", __func__); break; } scanEventStatus = nla_get_u32(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_STATUS]); ALOGE("%s: Scan event type: %d, status = %d. \n", __func__, scanEvent, scanEventStatus); /* Send the results if no more result fragments are expected. */ (*mHandler.on_scan_event)(scanEvent, scanEventStatus); } break; default: /* Error case should not happen print log */ ALOGE("%s: Wrong GScan subcmd received %d", __func__, mSubcmd); } /* A parsing error occurred, do the cleanup of gscan result lists. */ if (ret) { switch(mSubcmd) { case QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT: { free(result); result = NULL; } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND: { /* Reset flag and num counter. */ free(mHotlistApFoundResults); mHotlistApFoundResults = NULL; mHotlistApFoundMoreData = false; mHotlistApFoundNumResults = 0; } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE: { for (i = 0; i < mSignificantChangeNumResults; i++) { if (mSignificantChangeResults[i]) { free(mSignificantChangeResults[i]); mSignificantChangeResults[i] = NULL; } } free(mSignificantChangeResults); mSignificantChangeResults = NULL; mSignificantChangeNumResults = 0; mSignificantChangeMoreData = false; } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE: break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT: break; default: ALOGE("%s: Parsing err handler: wrong GScan subcmd " "received %d", __func__, mSubcmd); } } return NL_SKIP; }
static wifi_error gscan_get_significant_change_results(u32 num_results, wifi_significant_change_result **results, u32 starting_index, struct nlattr **tb_vendor) { u32 i = starting_index; int j; int rem = 0; u32 len = 0; struct nlattr *scanResultsInfo; ALOGE("gscan_get_significant_change_results: starting counter: %d", i); for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]), rem = nla_len(tb_vendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]); nla_ok(scanResultsInfo, rem); scanResultsInfo = nla_next(scanResultsInfo, &(rem))) { struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, (struct nlattr *) nla_data(scanResultsInfo), nla_len(scanResultsInfo), NULL); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID ]) { ALOGE("gscan_get_significant_change_results: " "SIGNIFICANT_CHANGE_RESULT_BSSID not found"); return WIFI_ERROR_INVALID_ARGS; } len = nla_len( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID] ); len = sizeof(results[i]->bssid) <= len ? sizeof(results[i]->bssid) : len; memcpy(&results[i]->bssid[0], nla_data( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID]), len); ALOGI("\nsignificant_change_result:%d, BSSID:" "%02x:%02x:%02x:%02x:%02x:%02x \n", i, results[i]->bssid[0], results[i]->bssid[1], results[i]->bssid[2], results[i]->bssid[3], results[i]->bssid[4], results[i]->bssid[5]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL ]) { ALOGE("gscan_get_significant_change_results: " "SIGNIFICANT_CHANGE_RESULT_CHANNEL not found"); return WIFI_ERROR_INVALID_ARGS; } results[i]->channel = nla_get_u32( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL]); ALOGI("significant_change_result:%d, channel:%d.\n", i, results[i]->channel); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI ]) { ALOGE("gscan_get_significant_change_results: " "SIGNIFICANT_CHANGE_RESULT_NUM_RSSI not found"); return WIFI_ERROR_INVALID_ARGS; } results[i]->num_rssi = nla_get_u32( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI]); ALOGI("gscan_get_significant_change_results: " "significant_change_result:%d, num_rssi:%d.\n", i, results[i]->num_rssi); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST ]) { ALOGE("gscan_get_significant_change_results: " "SIGNIFICANT_CHANGE_RESULT_RSSI_LIST not found"); return WIFI_ERROR_INVALID_ARGS; } ALOGI("gscan_get_significant_change_results: before reading the RSSI " "list: num_rssi:%d, size_of_rssi:%d, total size:%d, ", results[i]->num_rssi, sizeof(wifi_rssi), results[i]->num_rssi * sizeof(wifi_rssi)); memcpy(&(results[i]->rssi[0]), nla_data( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST] ), results[i]->num_rssi * sizeof(wifi_rssi)); for (j = 0; j < results[i]->num_rssi; j++) ALOGI(" significant_change_result: %d, rssi[%d]:%d, ", i, j, results[i]->rssi[j]); /* Increment loop index to prase next record. */ i++; } return WIFI_SUCCESS; }
static wifi_error gscan_get_hotlist_ap_found_results(u32 num_results, wifi_scan_result *results, u32 starting_index, struct nlattr **tb_vendor) { u32 i = starting_index; struct nlattr *scanResultsInfo; int rem = 0; u32 len = 0; ALOGE("gscan_get_hotlist_ap_found_results: starting counter: %d", i); for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]), rem = nla_len(tb_vendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST ]); nla_ok(scanResultsInfo, rem); scanResultsInfo = nla_next(scanResultsInfo, &(rem))) { struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, (struct nlattr *) nla_data(scanResultsInfo), nla_len(scanResultsInfo), NULL); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP ]) { ALOGE("gscan_get_hotlist_ap_found_results: " "RESULTS_SCAN_RESULT_TIME_STAMP not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].ts = nla_get_u64( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP ]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID ]) { ALOGE("gscan_get_hotlist_ap_found_results: " "RESULTS_SCAN_RESULT_SSID not found"); return WIFI_ERROR_INVALID_ARGS; } len = nla_len(tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]); len = sizeof(results->ssid) <= len ? sizeof(results->ssid) : len; memcpy((void *)&results[i].ssid, nla_data( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), len); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID ]) { ALOGE("gscan_get_hotlist_ap_found_results: " "RESULTS_SCAN_RESULT_BSSID not found"); return WIFI_ERROR_INVALID_ARGS; } len = nla_len( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]); len = sizeof(results->bssid) <= len ? sizeof(results->bssid) : len; memcpy(&results[i].bssid, nla_data( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), len); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL ]) { ALOGE("gscan_get_hotlist_ap_found_results: " "RESULTS_SCAN_RESULT_CHANNEL not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].channel = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI ]) { ALOGE("gscan_get_hotlist_ap_found_results: " "RESULTS_SCAN_RESULT_RSSI not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].rssi = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT ]) { ALOGE("gscan_get_hotlist_ap_found_results: " "RESULTS_SCAN_RESULT_RTT not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].rtt = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD ]) { ALOGE("gscan_get_hotlist_ap_found_results: " "RESULTS_SCAN_RESULT_RTT_SD not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].rtt_sd = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]); ALOGE("gscan_get_hotlist_ap_found_results: ts %lld ", results[i].ts); ALOGE("gscan_get_hotlist_ap_found_results: SSID %s ", results[i].ssid) ; ALOGE("gscan_get_hotlist_ap_found_results: " "BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n", results[i].bssid[0], results[i].bssid[1], results[i].bssid[2], results[i].bssid[3], results[i].bssid[4], results[i].bssid[5]); ALOGE("gscan_get_hotlist_ap_found_results: channel %d ", results[i].channel); ALOGE("gscan_get_hotlist_ap_found_results: rssi %d ", results[i].rssi); ALOGE("gscan_get_hotlist_ap_found_results: rtt %lld ", results[i].rtt); ALOGE("gscan_get_hotlist_ap_found_results: rtt_sd %lld ", results[i].rtt_sd); /* Increment loop index for next record */ i++; } return WIFI_SUCCESS; }
void process_route_msg(struct nlmsghdr *nlmsg, int type) { int hdrlen, attrlen; struct nlattr *attr; struct rtmsg *rmsg; bool src_valid = false; bool dst_valid = false; bool gateway_valid = false; switchlink_handle_t ecmp_h = 0; switchlink_ip_addr_t src_addr; switchlink_ip_addr_t dst_addr; switchlink_ip_addr_t gateway_addr; switchlink_db_interface_info_t ifinfo; uint8_t af = AF_UNSPEC; bool oif_valid = false; uint32_t oif = 0; switchlink_handle_t oifl_h = 0; bool ip_multicast = false; bool iif_valid = false; uint32_t iif = 0; assert((type == RTM_NEWROUTE) || (type == RTM_DELROUTE)); rmsg = nlmsg_data(nlmsg); hdrlen = sizeof(struct rtmsg); NL_LOG_DEBUG(("%sroute: family = %d, dst_len = %d, src_len = %d, tos = %d, " "table = %d, proto = %d, scope = %d, type = %d, " "flags = 0x%x\n", ((type == RTM_NEWROUTE) ? "new" : "del"), rmsg->rtm_family, rmsg->rtm_dst_len, rmsg->rtm_src_len, rmsg->rtm_tos, rmsg->rtm_table, rmsg->rtm_protocol, rmsg->rtm_scope, rmsg->rtm_type, rmsg->rtm_flags)); if (rmsg->rtm_family > AF_MAX) { assert(rmsg->rtm_type == RTN_MULTICAST); if (rmsg->rtm_family == RTNL_FAMILY_IPMR) { af = AF_INET; } else if (rmsg->rtm_family == RTNL_FAMILY_IP6MR) { af = AF_INET6; } ip_multicast = true; } else { af = rmsg->rtm_family; } if ((af != AF_INET) && (af != AF_INET6)) { return; } memset(&dst_addr, 0, sizeof(switchlink_ip_addr_t)); memset(&gateway_addr, 0, sizeof(switchlink_ip_addr_t)); attrlen = nlmsg_attrlen(nlmsg, hdrlen); attr = nlmsg_attrdata(nlmsg, hdrlen); while (nla_ok(attr, attrlen)) { int attr_type = nla_type(attr); switch (attr_type) { case RTA_SRC: src_valid = true; memset(&src_addr, 0, sizeof(switchlink_ip_addr_t)); src_addr.family = af; src_addr.prefix_len = rmsg->rtm_src_len; if (src_addr.family == AF_INET) { src_addr.ip.v4addr.s_addr = ntohl(nla_get_u32(attr)); } else { memcpy(&(src_addr.ip.v6addr), nla_data(attr), nla_len(attr)); } break; case RTA_DST: dst_valid = true; memset(&dst_addr, 0, sizeof(switchlink_ip_addr_t)); dst_addr.family = af; dst_addr.prefix_len = rmsg->rtm_dst_len; if (dst_addr.family == AF_INET) { dst_addr.ip.v4addr.s_addr = ntohl(nla_get_u32(attr)); } else { memcpy(&(dst_addr.ip.v6addr), nla_data(attr), nla_len(attr)); } break; case RTA_GATEWAY: gateway_valid = true; memset(&gateway_addr, 0, sizeof(switchlink_ip_addr_t)); gateway_addr.family = rmsg->rtm_family; if (rmsg->rtm_family == AF_INET) { gateway_addr.ip.v4addr.s_addr = ntohl(nla_get_u32(attr)); gateway_addr.prefix_len = 32; } else { memcpy(&(gateway_addr.ip.v6addr), nla_data(attr), nla_len(attr)); gateway_addr.prefix_len = 128; } break; case RTA_MULTIPATH: if (ip_multicast) { oifl_h = process_oif_list(attr, g_default_vrf_h); } else { ecmp_h = process_ecmp(af, attr, g_default_vrf_h); } break; case RTA_OIF: oif_valid = true; oif = nla_get_u32(attr); break; case RTA_IIF: iif_valid = true; iif = nla_get_u32(attr); break; default: NL_LOG_DEBUG(("route: skipping attr(%d)\n", attr_type)); break; } attr = nla_next(attr, &attrlen); } if (rmsg->rtm_dst_len == 0) { dst_valid = true; memset(&dst_addr, 0, sizeof(switchlink_ip_addr_t)); dst_addr.family = af; dst_addr.prefix_len = 0; } if (!ip_multicast) { if (type == RTM_NEWROUTE) { memset(&ifinfo, 0, sizeof(ifinfo)); if (oif_valid) { switchlink_db_status_t status; status = switchlink_db_interface_get_info(oif, &ifinfo); if (status != SWITCHLINK_DB_STATUS_SUCCESS) { NL_LOG_DEBUG(("route: switchlink_db_interface_get_info " "(unicast) failed\n")); return; } } route_create(g_default_vrf_h, (dst_valid ? &dst_addr : NULL), (gateway_valid ? &gateway_addr : NULL), ecmp_h, ifinfo.intf_h); } else { route_delete(g_default_vrf_h, (dst_valid ? &dst_addr : NULL)); } } else { if (rmsg->rtm_src_len == 0) { src_valid = true; memset(&src_addr, 0, sizeof(switchlink_ip_addr_t)); src_addr.family = af; src_addr.prefix_len = 0; } if (type == RTM_NEWROUTE) { if (!iif_valid || !oifl_h) { // multicast route cache is not resolved yet return; } switchlink_db_status_t status; status = switchlink_db_interface_get_info(iif, &ifinfo); if (status != SWITCHLINK_DB_STATUS_SUCCESS) { NL_LOG_DEBUG(("route: switchlink_db_interface_get_info " "(multicast) failed\n")); return; } mroute_create(g_default_vrf_h, (src_valid ? &src_addr : NULL), (dst_valid ? &dst_addr : NULL), ifinfo.intf_h, oifl_h); } else { mroute_delete(g_default_vrf_h, (src_valid ? &src_addr : NULL), (dst_valid ? &dst_addr : NULL)); } } }
static int nl80211_freqlist_cb(struct nl_msg *msg, void *arg) { struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; struct genlmsghdr *gnlh = (struct genlmsghdr *) nlmsg_data(nlmsg_hdr(msg)); struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1]; struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1]; struct nlattr *nl_band, *nl_freq; int rem_band, rem_freq, num_freq = 0; uint32_t freq; struct nl80211_channel_block *chanb = (struct nl80211_channel_block *) arg; nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (!tb_msg[NL80211_ATTR_WIPHY_BANDS]) { return NL_SKIP; } if (tb_msg[NL80211_ATTR_WIPHY_NAME]) { if (strcmp(nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME]), chanb->phyname) != 0) { return NL_SKIP; } } // Count the number of channels for (nl_band = (struct nlattr *) nla_data(tb_msg[NL80211_ATTR_WIPHY_BANDS]), rem_band = nla_len(tb_msg[NL80211_ATTR_WIPHY_BANDS]); nla_ok(nl_band, rem_band); nl_band = (struct nlattr *) nla_next(nl_band, &rem_band)) { nla_parse(tb_band, NL80211_BAND_ATTR_MAX, (struct nlattr *) nla_data(nl_band), nla_len(nl_band), NULL); for (nl_freq = (struct nlattr *) nla_data(tb_band[NL80211_BAND_ATTR_FREQS]), rem_freq = nla_len(tb_band[NL80211_BAND_ATTR_FREQS]); nla_ok(nl_freq, rem_freq); nl_freq = (struct nlattr *) nla_next(nl_freq, &rem_freq)) { nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, (struct nlattr *) nla_data(nl_freq), nla_len(nl_freq), NULL); if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) continue; if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) continue; num_freq++; } } chanb->nfreqs = num_freq; chanb->channel_list = malloc(sizeof(int) * num_freq); num_freq = 0; // Assemble a return for (nl_band = (struct nlattr *) nla_data(tb_msg[NL80211_ATTR_WIPHY_BANDS]), rem_band = nla_len(tb_msg[NL80211_ATTR_WIPHY_BANDS]); nla_ok(nl_band, rem_band); nl_band = (struct nlattr *) nla_next(nl_band, &rem_band)) { nla_parse(tb_band, NL80211_BAND_ATTR_MAX, (struct nlattr *) nla_data(nl_band), nla_len(nl_band), NULL); for (nl_freq = (struct nlattr *) nla_data(tb_band[NL80211_BAND_ATTR_FREQS]), rem_freq = nla_len(tb_band[NL80211_BAND_ATTR_FREQS]); nla_ok(nl_freq, rem_freq); nl_freq = (struct nlattr *) nla_next(nl_freq, &rem_freq)) { nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, (struct nlattr *) nla_data(nl_freq), nla_len(nl_freq), NULL); if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) continue; if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) continue; freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); chanb->channel_list[num_freq++] = FreqToChan(freq); } } return NL_SKIP; }
static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, const struct nlattr *attr, int len, bool keep_skb) { /* */ int prev_port = -1; const struct nlattr *a; int rem; for (a = attr, rem = len; rem > 0; a = nla_next(a, &rem)) { int err = 0; if (prev_port != -1) { do_output(dp, skb_clone(skb, GFP_ATOMIC), prev_port); prev_port = -1; } switch (nla_type(a)) { case OVS_ACTION_ATTR_OUTPUT: prev_port = nla_get_u32(a); break; case OVS_ACTION_ATTR_USERSPACE: output_userspace(dp, skb, a); break; case OVS_ACTION_ATTR_PUSH_VLAN: err = push_vlan(skb, nla_data(a)); if (unlikely(err)) /* */ return err; break; case OVS_ACTION_ATTR_POP_VLAN: err = pop_vlan(skb); break; case OVS_ACTION_ATTR_SET: err = execute_set_action(skb, nla_data(a)); break; case OVS_ACTION_ATTR_SAMPLE: err = sample(dp, skb, a); break; } if (unlikely(err)) { kfree_skb(skb); return err; } } if (prev_port != -1) { if (keep_skb) skb = skb_clone(skb, GFP_ATOMIC); do_output(dp, skb, prev_port); } else if (!keep_skb) consume_skb(skb); return 0; }
// This function will be the main handler for incoming event LLStats_SUBCMD //Call the appropriate callback handler after parsing the vendor data. int LLStatsCommand::handleEvent(WifiEvent &event) { ALOGI("Got a LLStats message from Driver"); unsigned i=0; u32 status; WifiVendorCommand::handleEvent(event); // Parse the vendordata and get the attribute switch(mSubcmd) { case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS: { wifi_request_id id; u32 resultsBufSize = 0; struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX + 1]; int rem; nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *)mVendorData, mDataLen, NULL); resultsBufSize += (nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS]) * sizeof(wifi_channel_stat) + sizeof(wifi_radio_stat)); mResultsParams.radio_stat = (wifi_radio_stat *)malloc(resultsBufSize); memset(mResultsParams.radio_stat, 0, resultsBufSize); ALOGI(" rxTime is %u\n ", mResultsParams.radio_stat->rx_time); ALOGI(" NumChan is %d\n ", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS])); if(mResultsParams.radio_stat){ wifi_channel_stat *pWifiChannelStats; u32 i =0; printf("sunil %d : %s \n",__LINE__,__func__); get_wifi_radio_stats(mResultsParams.radio_stat, tb_vendor); ALOGI(" radio is %u ", mResultsParams.radio_stat->radio); ALOGI(" onTime is %u ", mResultsParams.radio_stat->on_time); ALOGI(" txTime is %u ", mResultsParams.radio_stat->tx_time); ALOGI(" rxTime is %u ", mResultsParams.radio_stat->rx_time); ALOGI(" onTimeScan is %u ", mResultsParams.radio_stat->on_time_scan); ALOGI(" onTimeNbd is %u ", mResultsParams.radio_stat->on_time_nbd); ALOGI(" onTimeGscan is %u ", mResultsParams.radio_stat->on_time_gscan); ALOGI(" onTimeRoamScan is %u", mResultsParams.radio_stat->on_time_roam_scan); ALOGI(" onTimePnoScan is %u ", mResultsParams.radio_stat->on_time_pno_scan); ALOGI(" onTimeHs20 is %u ", mResultsParams.radio_stat->on_time_hs20); ALOGI(" numChannels is %u ", mResultsParams.radio_stat->num_channels); for ( i=0; i < mResultsParams.radio_stat->num_channels; i++) { pWifiChannelStats = (wifi_channel_stat *) ((u8 *)mResultsParams.radio_stat->channels + (i * sizeof(wifi_channel_stat))); ALOGI(" width is %u ", pWifiChannelStats->channel.width); ALOGI(" CenterFreq %u ", pWifiChannelStats->channel.center_freq); ALOGI(" CenterFreq0 %u ", pWifiChannelStats->channel.center_freq0); ALOGI(" CenterFreq1 %u ", pWifiChannelStats->channel.center_freq1); ALOGI(" onTime %u ", pWifiChannelStats->on_time); ALOGI(" ccaBusyTime %u ", pWifiChannelStats->cca_busy_time); } ALOGI(" rxTime is %u in %s:%d\n", mResultsParams.radio_stat->rx_time, __func__, __LINE__); } } break; case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS: { wifi_request_id id; u32 resultsBufSize = 0; struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX + 1]; nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *)mVendorData, mDataLen, NULL); resultsBufSize = sizeof(wifi_iface_stat); // Do we need no.of peers here?? mResultsParams.iface_stat = (wifi_iface_stat *) malloc (sizeof (wifi_iface_stat)); get_wifi_interface_info(&mResultsParams.iface_stat->info, tb_vendor); get_wifi_iface_stats(mResultsParams.iface_stat, tb_vendor); } break; case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS: { wifi_request_id id; u32 resultsBufSize = 0, i=0, num_rates = 0; u32 numPeers; int rem; struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX + 1]; struct nlattr *peerInfo; wifi_iface_stat *pIfaceStat; nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *)mVendorData, mDataLen, NULL); ALOGI(" rxTime is %u in %s:%d\n", mResultsParams.radio_stat->rx_time, __func__, __LINE__); ALOGI(" numPeers is %u in %s:%d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS]), __func__, __LINE__); ALOGI(" rxTe is %u in %s:%d\n", mResultsParams.radio_stat->rx_time, __func__, __LINE__); if((numPeers = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])) > 0) { for (peerInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]); nla_ok(peerInfo, rem); peerInfo = nla_next(peerInfo, &(rem))) { struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1]; nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(peerInfo), nla_len(peerInfo), NULL); num_rates += nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES]); } resultsBufSize += (numPeers * sizeof(wifi_peer_info) + num_rates * sizeof(wifi_rate_stat) + sizeof (wifi_iface_stat)); pIfaceStat = (wifi_iface_stat *) malloc (resultsBufSize); if(pIfaceStat){ memcpy ( pIfaceStat, mResultsParams.iface_stat , sizeof(wifi_iface_stat)); wifi_peer_info *pPeerStats; pIfaceStat->num_peers = numPeers; for (peerInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]); nla_ok(peerInfo, rem); peerInfo = nla_next(peerInfo, &(rem))) { struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1]; pPeerStats = (wifi_peer_info *) ((u8 *)pIfaceStat->peer_info + (i++ * sizeof(wifi_peer_info))); nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(peerInfo), nla_len(peerInfo), NULL); get_wifi_peer_info(pPeerStats, tb2); } } if(mResultsParams.iface_stat) free (mResultsParams.iface_stat); mResultsParams.iface_stat = pIfaceStat; } // Number of Radios are 1 for now : TODO get this info from the driver mHandler.on_link_stats_results(mRequestId, mResultsParams.iface_stat, 1, mResultsParams.radio_stat); if(mResultsParams.radio_stat) { free(mResultsParams.radio_stat); mResultsParams.radio_stat = NULL; } if(mResultsParams.iface_stat) { free(mResultsParams.iface_stat); mResultsParams.iface_stat = NULL; } } break; default: //error case should not happen print log ALOGE("%s: Wrong LLStats subcmd received %d", __func__, mSubcmd); } return NL_SKIP; }