Bluetooth: Controller: Restrict Extended Adv Report to max data length

Add implementation to limit Extended Scanned data to a
configurable maximum length when generating HCI reports.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2021-12-01 21:01:23 +05:30 committed by Carles Cufí
commit 8a5f0b50eb
2 changed files with 61 additions and 3 deletions

View file

@ -5741,6 +5741,7 @@ static void ext_adv_pdu_frag(uint8_t evt_type, uint8_t phy, uint8_t sec_phy,
const uint8_t data_len_frag = MIN(*data_len, data_len_max);
do {
/* Prepare a fragment of PDU data in a HCI event */
ext_adv_info_fill(evt_type, phy, sec_phy, adv_addr_type,
adv_addr, direct_addr_type, direct_addr,
rl_idx, tx_pwr, rssi, interval_le16, adi,
@ -5752,6 +5753,10 @@ static void ext_adv_pdu_frag(uint8_t evt_type, uint8_t phy, uint8_t sec_phy,
*evt_buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
net_buf_frag_add(buf, *evt_buf);
/* Continue to fragment until last partial PDU data fragment,
* remainder PDU data's HCI event will be prepare by caller.
*/
} while (*data_len > data_len_max);
}
@ -5771,15 +5776,24 @@ static void ext_adv_data_frag(const struct node_rx_pdu *node_rx_data,
evt_type |= (BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL << 5);
do {
/* Fragment the PDU data */
ext_adv_pdu_frag(evt_type, phy, *sec_phy, adv_addr_type,
adv_addr, direct_addr_type, direct_addr,
rl_idx, tx_pwr, rssi, interval_le16, adi,
data_len_max, &data_len_total, data_len,
data, buf, evt_buf);
/* Check if more PDUs in the list */
node_rx_data = node_rx_data->hdr.rx_ftr.extra;
if (node_rx_data) {
if (*data_len) {
if (*data_len >= data_len_total) {
/* Last fragment restricted to maximum scan
* data length, caller will prepare the last
* HCI fragment event.
*/
break;
} else if (*data_len) {
/* Last fragment of current PDU data */
ext_adv_pdu_frag(evt_type, phy, *sec_phy,
adv_addr_type, adv_addr,
direct_addr_type, direct_addr,
@ -5789,9 +5803,20 @@ static void ext_adv_data_frag(const struct node_rx_pdu *node_rx_data,
data_len, data, buf, evt_buf);
}
/* Get next PDU data in list */
*data_len = ext_adv_data_get(node_rx_data, sec_phy,
data);
/* Restrict PDU data to maximum scan data length */
if (*data_len > data_len_total) {
*data_len = data_len_total;
}
}
/* Continue to fragment if current PDU data length less than
* total data length or current PDU data length greater than
* HCI event max length.
*/
} while ((*data_len < data_len_total) || (*data_len > data_len_max));
}
@ -6139,6 +6164,16 @@ no_ext_hdr:
}
}
/* Restrict data length to maximum scan data length */
if (data_len_total > CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX) {
data_len_total = CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX;
if (data_len > data_len_total) {
data_len = data_len_total;
}
data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE;
}
/* Set directed advertising bit */
if (direct_addr) {
evt_type |= BT_HCI_LE_ADV_EVT_TYPE_DIRECT;
@ -6151,6 +6186,9 @@ no_ext_hdr:
sizeof(struct bt_hci_evt_le_ext_advertising_report) -
sizeof(struct bt_hci_evt_le_ext_advertising_info);
/* If PDU data length less than total data length or PDU data length
* greater than maximum HCI event data length, then fragment.
*/
if ((data_len < data_len_total) || (data_len > data_len_max)) {
ext_adv_data_frag(node_rx_data, evt_type, phy, &sec_phy,
adv_addr_type, adv_addr, direct_addr_type,
@ -6163,7 +6201,7 @@ no_ext_hdr:
/* Set data status bits */
evt_type |= (data_status << 5);
/* Start constructing the adv event */
/* Start constructing the adv event for remainder of the PDU data */
ext_adv_info_fill(evt_type, phy, sec_phy, adv_addr_type, adv_addr,
direct_addr_type, direct_addr, rl_idx, tx_pwr, rssi,
interval_le16, adi, data_len, data, evt_buf);
@ -6175,6 +6213,16 @@ no_ext_hdr:
return;
}
/* Restrict scan response data length to maximum scan data length */
if (scan_data_len_total > CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX) {
scan_data_len_total = CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX;
if (scan_data_len > scan_data_len_total) {
scan_data_len = scan_data_len_total;
}
scan_data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE;
}
/* Set scan response bit */
evt_type |= BT_HCI_LE_ADV_EVT_TYPE_SCAN_RSP;
@ -6187,6 +6235,9 @@ no_ext_hdr:
evt_buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
net_buf_frag_add(buf, evt_buf);
/* If PDU data length less than total data length or PDU data length
* greater than maximum HCI event data length, then fragment.
*/
if ((scan_data_len < scan_data_len_total) ||
(scan_data_len > data_len_max)) {
ext_adv_data_frag(node_rx_scan_data, evt_type, phy,
@ -6200,7 +6251,7 @@ no_ext_hdr:
/* set scan data status bits */
evt_type |= (scan_data_status << 5);
/* Start constructing the event */
/* Start constructing the event for remainder of the PDU data */
ext_adv_info_fill(evt_type, phy, sec_phy_scan, adv_addr_type, adv_addr,
direct_addr_type, direct_addr, rl_idx, tx_pwr, rssi,
interval_le16, adi, scan_data_len, scan_data,