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);
    }
}
Exemple #3
0
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);
}
Exemple #4
0
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);
}
Exemple #6
0
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));
        }
    }
}
Exemple #15
0
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;
}