qcacld-3.0: Fix Reported Frame Body Frag ID and last beacon report

Add changes to implement the correct Reported Frame Body Frag ID and
last beacon report indication sub-elements for beacon report action
frame

Change-Id: I3776a239c2e0b04d35c2adb58598016b927154c6
CRs-Fixed: 2342678
This commit is contained in:
Vignesh Viswanathan 2018-08-14 22:04:36 +05:30 • committed by nshrivas
commit 09bd8f46dd
8 changed files with 218 additions and 139 deletions

View file

@ -134,7 +134,6 @@ uint8_t ccp_rsn_oui_90[HDD_RSN_OUI_SIZE] = {0x00, 0x0F, 0xAC, 0x09};
#define FT_ASSOC_RSP_IES_OFFSET 6 /* Capability(2) + AID(2) + Status Code(2) */
#define FT_ASSOC_REQ_IES_OFFSET 4 /* Capability(2) + LI(2) */
#define BEACON_FRAME_IES_OFFSET 12
#define HDD_PEER_AUTHORIZE_WAIT 10
/**

View file

@ -1996,6 +1996,43 @@ typedef struct sSirMacLinkReport {
} tSirMacLinkReport, *tpSirMacLinkReport;
#define BEACON_REPORT_MAX_IES 224 /* Refer IEEE 802.11k-2008, Table 7-31d */
/* Max number of beacon reports per channel supported in the driver */
#define MAX_BEACON_REPORTS 8
/* Offset of IEs after Fixed Fields in Beacon Frame */
#define BEACON_FRAME_IES_OFFSET 12
/**
* struct bcn_report_frame_body_frag_id - beacon report reported frame body
* fragment ID sub element params
* @id: report ID
* @frag_id: fragment ID
* @more_frags: more frags present or not present
*/
struct bcn_report_frame_body_frag_id {
uint8_t id;
uint8_t frag_id;
bool more_frags;
};
/**
* struct sSirMacBeaconReport - Beacon Report Structure
* @regClass: Regulatory Class
* @channel: Channel for which the current report is being sent
* @measStartTime: RRM scan start time for this report
* @measDuration: Scan duration for the current channel
* @phyType: Condensed Phy Type
* @bcnProbeRsp: Beacon or probe response being reported
* @rsni: Received signal-to-noise indication
* @rcpi: Received Channel Power indication
* @bssid: BSSID of the AP requesting the beacon report
* @antennaId: Number of Antennas used for measurement
* @parentTSF: measuring STA's TSF timer value
* @numIes: Number of IEs included in the beacon frames
* @last_bcn_report_ind_support: Support for Last beacon report indication
* @is_last_bcn_report: Is the current report last or more reports present
* @frame_body_frag_id: Reported Frame Body Frag Id sub-element params
* @Ies: IEs included in the beacon report
*/
typedef struct sSirMacBeaconReport {
uint8_t regClass;
uint8_t channel;
@ -2009,6 +2046,9 @@ typedef struct sSirMacBeaconReport {
uint8_t antennaId;
uint32_t parentTSF;
uint8_t numIes;
uint8_t last_bcn_report_ind_support;
uint8_t is_last_bcn_report;
struct bcn_report_frame_body_frag_id frame_body_frag_id;
uint8_t Ies[BEACON_REPORT_MAX_IES];
} tSirMacBeaconReport, *tpSirMacBeaconReport;

View file

@ -743,7 +743,7 @@ populate_dot11f_ext_supp_rates(tpAniSirGlobal pMac,
* @pMac: Pointer to the global MAC context
* @pDot11f: Pointer to the measurement report structure
* @pBeaconReport: Pointer to the Beacon Report structure
* @last_beacon_report_params: Last Beacon Report indication params
* @is_last_frame: is the current report last or more reports to follow
*
* Return: Ret Status
*/
@ -751,8 +751,7 @@ QDF_STATUS
populate_dot11f_beacon_report(tpAniSirGlobal pMac,
tDot11fIEMeasurementReport *pDot11f,
tSirMacBeaconReport *pBeaconReport,
struct rrm_beacon_report_last_beacon_params
*last_beacon_report_params);
bool is_last_frame);
/**
* \brief Populate a tDot11fIEExtSuppRates

View file

@ -160,20 +160,6 @@ typedef struct sRRMReq {
uint8_t sendEmptyBcnRpt;
} tRRMReq, *tpRRMReq;
/**
* rrm_beacon_report_last_beacon_params - Last Beacon Report Indication params
* @last_beacon_ind: flag for whether last beacon indication is required
* @report_id: Report ID of the corresponding Beacon Report Request
* @frag_id: Current fragment's Fragment ID
* @num_frags: Total number of fragments in the Beacon Report
*/
struct rrm_beacon_report_last_beacon_params {
uint8_t last_beacon_ind;
uint8_t report_id;
uint8_t frag_id;
uint8_t num_frags;
};
typedef struct sRRMCaps {
uint8_t LinkMeasurement:1;
uint8_t NeighborRpt:1;

View file

@ -4339,8 +4339,7 @@ QDF_STATUS
lim_send_radio_measure_report_action_frame(tpAniSirGlobal pMac,
uint8_t dialog_token,
uint8_t num_report,
struct rrm_beacon_report_last_beacon_params
*last_beacon_report_params,
bool is_last_frame,
tpSirMacRadioMeasureReport pRRMReport,
tSirMacAddr peer,
tpPESession psessionEntry)
@ -4368,8 +4367,8 @@ lim_send_radio_measure_report_action_frame(tpAniSirGlobal pMac,
smeSessionId = psessionEntry->smeSessionId;
pe_debug("dialog_token %d num_report %d",
dialog_token, num_report);
pe_debug("dialog_token %d num_report %d is_last_frame %d",
dialog_token, num_report, is_last_frame);
frm->Category.category = SIR_MAC_ACTION_RRM;
frm->Action.action = SIR_MAC_RRM_RADIO_MEASURE_RPT;
@ -4390,7 +4389,7 @@ lim_send_radio_measure_report_action_frame(tpAniSirGlobal pMac,
&frm->MeasurementReport[i],
&pRRMReport[i].report.
beaconReport,
last_beacon_report_params);
is_last_frame);
frm->MeasurementReport[i].incapable =
pRRMReport[i].incapable;
frm->MeasurementReport[i].refused =

View file

@ -656,7 +656,7 @@ QDF_STATUS lim_send_link_report_action_frame(tpAniSirGlobal, tpSirMacLinkReport,
* @pMac: pointer to global MAC context
* @dialog_token: Dialog token to be used in the action frame
* @num_report: number of reports in pRRMReport
* @last_beacon_report_params: Last Beacon Report indication params
* @is_last_frame: is the current report last or more reports to follow
* @pRRMReport: Pointer to the RRM report structure
* @peer: MAC address of the peer
* @psessionEntry: Pointer to the PE session entry
@ -667,8 +667,7 @@ QDF_STATUS
lim_send_radio_measure_report_action_frame(tpAniSirGlobal pMac,
uint8_t dialog_token,
uint8_t num_report,
struct rrm_beacon_report_last_beacon_params
*last_beacon_report_params,
bool is_last_frame,
tpSirMacRadioMeasureReport pRRMReport,
tSirMacAddr peer,
tpPESession psessionEntry);

View file

@ -681,67 +681,113 @@ rrm_process_beacon_report_req(tpAniSirGlobal pMac,
* @param pIesMaxSize - Max size of the buffer pIes.
* @param eids - pointer to array of eids. If NULL, all ies will be populated.
* @param numEids - number of elements in array eids.
* @start_offset: Offset from where the IEs in the bss_desc should be parsed
* @param pBssDesc - pointer to Bss Description.
* @return None
*
* Returns: Remaining length of IEs in current bss_desc which are not included
* in pIes.
*/
static void
static uint8_t
rrm_fill_beacon_ies(tpAniSirGlobal pMac,
uint8_t *pIes, uint8_t *pNumIes, uint8_t pIesMaxSize,
uint8_t *eids, uint8_t numEids, tpSirBssDescription pBssDesc)
uint8_t *eids, uint8_t numEids, uint8_t start_offset,
tpSirBssDescription pBssDesc)
{
uint8_t len, *pBcnIes, count = 0, i;
uint16_t BcnNumIes;
uint16_t BcnNumIes, total_ies_len;
uint8_t rem_len = 0;
if ((pIes == NULL) || (pNumIes == NULL) || (pBssDesc == NULL)) {
pe_err("Invalid parameters");
return;
return 0;
}
/* Make sure that if eid is null, numEids is set to zero. */
numEids = (eids == NULL) ? 0 : numEids;
total_ies_len = GET_IE_LEN_IN_BSS(pBssDesc->length);
BcnNumIes = total_ies_len;
if (start_offset > BcnNumIes) {
pe_err("Invalid start offset %d Bcn IE len %d",
start_offset, total_ies_len);
return 0;
}
pBcnIes = (uint8_t *) &pBssDesc->ieFields[0];
BcnNumIes = GET_IE_LEN_IN_BSS(pBssDesc->length);
pBcnIes += start_offset;
BcnNumIes = BcnNumIes - start_offset;
*pNumIes = 0;
*((uint32_t *) pIes) = pBssDesc->timeStamp[0];
*pNumIes += sizeof(uint32_t);
pIes += sizeof(uint32_t);
*((uint32_t *) pIes) = pBssDesc->timeStamp[1];
*pNumIes += sizeof(uint32_t);
pIes += sizeof(uint32_t);
*((uint16_t *) pIes) = pBssDesc->beaconInterval;
*pNumIes += sizeof(uint16_t);
pIes += sizeof(uint16_t);
*((uint16_t *) pIes) = pBssDesc->capabilityInfo;
*pNumIes += sizeof(uint16_t);
pIes += sizeof(uint16_t);
/*
* If start_offset is 0, this is the first fragment of the current
* beacon. Include the Beacon Fixed Fields of length 12 bytes
* (BEACON_FRAME_IES_OFFSET) in the first fragment.
*/
if (start_offset == 0) {
*((uint32_t *)pIes) = pBssDesc->timeStamp[0];
*pNumIes += sizeof(uint32_t);
pIes += sizeof(uint32_t);
*((uint32_t *)pIes) = pBssDesc->timeStamp[1];
*pNumIes += sizeof(uint32_t);
pIes += sizeof(uint32_t);
*((uint16_t *)pIes) = pBssDesc->beaconInterval;
*pNumIes += sizeof(uint16_t);
pIes += sizeof(uint16_t);
*((uint16_t *)pIes) = pBssDesc->capabilityInfo;
*pNumIes += sizeof(uint16_t);
pIes += sizeof(uint16_t);
}
while (BcnNumIes > 0) {
len = *(pBcnIes + 1) + 2; /* element id + length. */
pe_debug("EID = %d, len = %d total = %d",
*pBcnIes, *(pBcnIes + 1), len);
if (!len) {
pe_err("Invalid length");
break;
}
i = 0;
do {
if (((eids == NULL) || (*pBcnIes == eids[i])) &&
((*pNumIes) + len) < pIesMaxSize) {
pe_debug("Adding Eid %d, len=%d",
*pBcnIes, len);
if ((!eids) || (*pBcnIes == eids[i])) {
if (((*pNumIes) + len) < pIesMaxSize) {
pe_debug("Adding Eid %d, len=%d",
*pBcnIes, len);
qdf_mem_copy(pIes, pBcnIes, len);
pIes += len;
*pNumIes += len;
count++;
qdf_mem_copy(pIes, pBcnIes, len);
pIes += len;
*pNumIes += len;
count++;
} else {
/*
* If max size of fragment is reached,
* calculate the remaining length and
* break. For first fragment, account
* for the fixed fields also.
*/
rem_len = total_ies_len - *pNumIes;
if (start_offset == 0)
rem_len = rem_len +
BEACON_FRAME_IES_OFFSET;
pe_debug("rem_len %d ies added %d",
rem_len, *pNumIes);
}
break;
}
i++;
} while (i < numEids);
if (rem_len)
break;
pBcnIes += len;
BcnNumIes -= len;
}
pe_debug("Total length of Ies added = %d", *pNumIes);
pe_debug("Total length of Ies added = %d rem_len %d",
*pNumIes, rem_len);
return rem_len;
}
/**
@ -763,10 +809,13 @@ rrm_process_beacon_report_xmit(tpAniSirGlobal mac_ctx,
tpSirBssDescription bss_desc;
tpRRMReq curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq;
tpPESession session_entry;
struct rrm_beacon_report_last_beacon_params last_beacon_report_params;
uint8_t session_id, counter;
uint8_t i, j, offset = 0;
uint8_t bss_desc_count = 0;
uint8_t report_index = 0;
uint8_t rem_len = 0;
uint8_t frag_id = 0;
uint8_t num_frames, num_reports_in_frame;
pe_debug("Received beacon report xmit indication");
@ -794,29 +843,31 @@ rrm_process_beacon_report_xmit(tpAniSirGlobal mac_ctx,
goto end;
}
report = qdf_mem_malloc(beacon_xmit_ind->numBssDesc *
sizeof(*report));
report = qdf_mem_malloc(MAX_BEACON_REPORTS * sizeof(*report));
if (!report) {
pe_err("RRM Report is NULL, allocation failed");
status = QDF_STATUS_E_NOMEM;
goto end;
}
for (bss_desc_count = 0; bss_desc_count <
beacon_xmit_ind->numBssDesc; bss_desc_count++) {
for (i = 0; i < MAX_BEACON_REPORTS &&
bss_desc_count < beacon_xmit_ind->numBssDesc; i++) {
beacon_report =
&report[bss_desc_count].report.beaconReport;
&report[i].report.beaconReport;
/*
* If the scan result is NULL then send report request
* with option subelement as NULL.
*/
pe_debug("report %d bss %d", i, bss_desc_count);
bss_desc = beacon_xmit_ind->
pBssDescription[bss_desc_count];
/* Prepare the beacon report and send it to the peer.*/
report[bss_desc_count].token =
report[i].token =
beacon_xmit_ind->uDialogToken;
report[bss_desc_count].refused = 0;
report[bss_desc_count].incapable = 0;
report[bss_desc_count].type = SIR_MAC_RRM_BEACON_TYPE;
report[i].refused = 0;
report[i].incapable = 0;
report[i].type = SIR_MAC_RRM_BEACON_TYPE;
/*
* Valid response is included if the size of
@ -851,70 +902,82 @@ rrm_process_beacon_report_xmit(tpAniSirGlobal mac_ctx,
/* 1: Include all FFs and Requested Ies. */
pe_debug("Only requested IEs in reporting detail requested");
if (bss_desc) {
rrm_fill_beacon_ies(mac_ctx,
(uint8_t *) &beacon_report->Ies[0],
(uint8_t *) &beacon_report->numIes,
if (!bss_desc)
break;
rem_len = rrm_fill_beacon_ies(mac_ctx,
(uint8_t *)&beacon_report->Ies[0],
(uint8_t *)&beacon_report->numIes,
BEACON_REPORT_MAX_IES,
curr_req->request.Beacon.reqIes.
pElementIds,
curr_req->request.Beacon.reqIes.num,
bss_desc);
}
offset, bss_desc);
break;
case BEACON_REPORTING_DETAIL_ALL_FF_IE:
/* 2: default - Include all FFs and all Ies. */
default:
pe_debug("Default all IEs and FFs");
if (bss_desc) {
rrm_fill_beacon_ies(mac_ctx,
if (!bss_desc)
break;
rem_len = rrm_fill_beacon_ies(mac_ctx,
(uint8_t *) &beacon_report->Ies[0],
(uint8_t *) &beacon_report->numIes,
BEACON_REPORT_MAX_IES,
NULL,
0,
bss_desc);
}
offset, bss_desc);
break;
}
beacon_report->frame_body_frag_id.id = bss_desc_count;
beacon_report->frame_body_frag_id.frag_id = frag_id;
/*
* If remaining length is non-zero, the beacon needs to
* be fragmented only if the current request supports
* last beacon report indication.
* If last beacon report indication is not supported,
* truncate and move on to the next beacon.
*/
if (rem_len &&
curr_req->request.Beacon.
last_beacon_report_indication) {
offset = GET_IE_LEN_IN_BSS(
bss_desc->length) - rem_len;
pe_debug("offset %d ie_len %lu rem_len %d frag_id %d",
offset,
GET_IE_LEN_IN_BSS(bss_desc->length),
rem_len, frag_id);
frag_id++;
beacon_report->frame_body_frag_id.more_frags =
true;
} else {
offset = 0;
beacon_report->frame_body_frag_id.more_frags =
false;
frag_id = 0;
bss_desc_count++;
pe_debug("No remaining IEs");
}
}
pe_debug("Total reports filled %d", i);
num_frames = i / RADIO_REPORTS_MAX_IN_A_FRAME;
if (i % RADIO_REPORTS_MAX_IN_A_FRAME)
num_frames++;
qdf_mem_zero(&last_beacon_report_params,
sizeof(last_beacon_report_params));
/*
* Each frame can hold RADIO_REPORTS_MAX_IN_A_FRAME reports.
* Multiple frames may be sent if bss_desc_count is larger.
* Count the total number of frames to be sent first
*/
for (j = 0; j < num_frames; j++) {
num_reports_in_frame = QDF_MIN((i - report_index),
RADIO_REPORTS_MAX_IN_A_FRAME);
last_beacon_report_params.last_beacon_ind =
curr_req->request.Beacon.last_beacon_report_indication;
last_beacon_report_params.num_frags =
(bss_desc_count / RADIO_REPORTS_MAX_IN_A_FRAME);
if (bss_desc_count % RADIO_REPORTS_MAX_IN_A_FRAME)
last_beacon_report_params.num_frags++;
pe_debug("last_beacon_report_ind required %d num_frags %d bss_count %d",
last_beacon_report_params.last_beacon_ind,
last_beacon_report_params.num_frags,
bss_desc_count);
while (report_index < bss_desc_count) {
int m_count;
m_count = QDF_MIN((bss_desc_count - report_index),
RADIO_REPORTS_MAX_IN_A_FRAME);
pe_info("Sending Action frame with %d bss info frag_id %d",
m_count, last_beacon_report_params.frag_id);
pe_debug("Sending Action frame number %d",
num_reports_in_frame);
lim_send_radio_measure_report_action_frame(mac_ctx,
curr_req->dialog_token, m_count,
&last_beacon_report_params,
curr_req->dialog_token, num_reports_in_frame,
(j == num_frames - 1) ? true : false,
&report[report_index],
beacon_xmit_ind->bssId, session_entry);
report_index += m_count;
last_beacon_report_params.frag_id++;
report_index += num_reports_in_frame;
}
curr_req->sendEmptyBcnRpt = false;
}
@ -966,7 +1029,7 @@ static void rrm_process_beacon_request_failure(tpAniSirGlobal pMac,
lim_send_radio_measure_report_action_frame(pMac,
pCurrentReq->dialog_token,
1, NULL,
1, true,
pReport, peer,
pSessionEntry);
@ -1114,7 +1177,7 @@ rrm_process_radio_measurement_request(tpAniSirGlobal mac_ctx,
report->incapable = 1;
num_report = 1;
lim_send_radio_measure_report_action_frame(mac_ctx,
rrm_req->DialogToken.token, num_report, NULL,
rrm_req->DialogToken.token, num_report, true,
report, peer, session_entry);
qdf_mem_free(report);
return QDF_STATUS_E_FAILURE;
@ -1165,7 +1228,7 @@ rrm_process_radio_measurement_request(tpAniSirGlobal mac_ctx,
end:
if (report) {
lim_send_radio_measure_report_action_frame(mac_ctx,
rrm_req->DialogToken.token, num_report, NULL,
rrm_req->DialogToken.token, num_report, true,
report, peer, session_entry);
qdf_mem_free(report);
}

View file

@ -5670,9 +5670,9 @@ QDF_STATUS
populate_dot11f_beacon_report(tpAniSirGlobal pMac,
tDot11fIEMeasurementReport *pDot11f,
tSirMacBeaconReport *pBeaconReport,
struct rrm_beacon_report_last_beacon_params
*last_beacon_report_params)
bool is_last_frame)
{
tDot11fIEbeacon_report_frm_body_fragment_id *frm_body_frag_id;
pDot11f->report.Beacon.regClass = pBeaconReport->regClass;
pDot11f->report.Beacon.channel = pBeaconReport->channel;
@ -5699,35 +5699,29 @@ populate_dot11f_beacon_report(tpAniSirGlobal pMac,
pBeaconReport->numIes;
}
if (last_beacon_report_params &&
last_beacon_report_params->last_beacon_ind) {
pe_debug("Including Last Beacon Report in RRM Frame, report_id %d, frag_id %d",
last_beacon_report_params->report_id,
last_beacon_report_params->frag_id);
pDot11f->report.Beacon.beacon_report_frm_body_fragment_id.
present = 1;
pDot11f->report.Beacon.beacon_report_frm_body_fragment_id.
beacon_report_id = last_beacon_report_params->report_id;
pDot11f->report.Beacon.beacon_report_frm_body_fragment_id.
fragment_id_number = last_beacon_report_params->frag_id;
if (pBeaconReport->last_bcn_report_ind_support) {
pe_debug("Including Last Beacon Report in RRM Frame");
frm_body_frag_id = &pDot11f->report.Beacon.
beacon_report_frm_body_fragment_id;
pDot11f->report.Beacon.last_beacon_report_indication.present = 1;
frm_body_frag_id->present = 1;
frm_body_frag_id->beacon_report_id =
pBeaconReport->frame_body_frag_id.id;
frm_body_frag_id->fragment_id_number =
pBeaconReport->frame_body_frag_id.frag_id;
frm_body_frag_id->more_fragments =
pBeaconReport->frame_body_frag_id.more_frags;
if (last_beacon_report_params->frag_id ==
(last_beacon_report_params->num_frags - 1)) {
pDot11f->report.Beacon.
beacon_report_frm_body_fragment_id.
more_fragments = 0;
pDot11f->report.Beacon.last_beacon_report_indication.
last_fragment = 1;
pe_debug("Last Fragment");
} else {
pDot11f->report.Beacon.
beacon_report_frm_body_fragment_id.
more_fragments = 1;
pDot11f->report.Beacon.last_beacon_report_indication.
last_fragment = 0;
}
pDot11f->report.Beacon.last_beacon_report_indication.present =
1;
pDot11f->report.Beacon.last_beacon_report_indication.
last_fragment = is_last_frame;
pe_debug("id %d frag_id %d more_frags %d is_last_frame %d",
frm_body_frag_id->beacon_report_id,
frm_body_frag_id->fragment_id_number,
frm_body_frag_id->more_fragments,
is_last_frame);
}
return QDF_STATUS_SUCCESS;