2020-11-24 17:33:35

by Daniel Winkler

[permalink] [raw]
Subject: [Bluez PATCH 0/2] Add mgmt-tester coverage for new advertising MGMT APIs

Dear Maintainers,

This patch adds a collection of 10 new mgmt-tester test cases to provide
coverage for the new MGMT APIs as part of the extended advertising work.
I split the tests into two patches, one for the new Read Controller
Capabilities MGMT command, and the other for the new Extended Params and
Extended Data commands. I hope this coverage will be satisfactory to
land the extended advertising features in kernel.

The new tests have been verified running Ubuntu and a kernel with the
proposed advertising changes.

Best regards,
Daniel Winkler



Daniel Winkler (2):
tools/mgmt-tester: Add mgmt-tester coverage for controller
capabilities
tools/mgmt-tester: Add tests for individual ext adv MGMT commands

tools/mgmt-tester.c | 369 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 369 insertions(+)

--
2.29.2.454.gaff20da3a2-goog


2020-11-24 17:33:35

by Daniel Winkler

[permalink] [raw]
Subject: [Bluez PATCH 2/2] tools/mgmt-tester: Add tests for individual ext adv MGMT commands

The new extended advertising MGMT commands are paired, requiring both a
Set Parameters and Set Data command to configure a new advertisement.
This patch adds the following new tests to test these APIs:

1. Verify that if the adapter is unpowered, MGMT_OP_ADD_EXT_ADV_PARAMS
will return a rejected status.

2. Verify that MGMT_OP_ADD_EXT_ADV_PARAMS will return an invalid
parameters status if the data payload is malformed.

3. Verify that MGMT_OP_ADD_EXT_ADV_PARAMS is successful on BT4 if
request is valid by checking MGMT return value.

4. Verify that MGMT_OP_ADD_EXT_ADV_PARAMS is successful on BT5 if
request is valid by checking MGMT return value and that HCI traffic
contains a correct advertising parameters request.

5. Verify that if a MGMT_OP_ADD_EXT_ADV_DATA request is received for an
advertising instance that is unknown, i.e. MGMT_OP_ADD_EXT_ADV_PARAMS
was not yet called, an invalid parameters status is returned.

Tests 6-8 first call MGMT_OP_ADD_EXT_ADV_PARAMS successfully in setup to
then validate the contents of the subsequent MGMT_OP_ADD_EXT_ADV_DATA
call.

6. Verify that if MGMT_OP_ADD_EXT_ADV_DATA is passed an invalid tlv
structure, an invalid parameters status is returned.

7. Verify that if MGMT_OP_ADD_EXT_ADV_DATA contains a valid structure,
the hci traffic contain a correctly formed Adv Data hci request.

8. Verify that if MGMT_OP_ADD_EXT_ADV_DATA contains a valid structure,
the hci traffic contain a correctly formed Adv Scan Response hci
request.

Reviewed-by: Manish Mandlik <[email protected]>
---

tools/mgmt-tester.c | 293 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 293 insertions(+)

diff --git a/tools/mgmt-tester.c b/tools/mgmt-tester.c
index 79e653e9e..bef506134 100644
--- a/tools/mgmt-tester.c
+++ b/tools/mgmt-tester.c
@@ -5282,6 +5282,195 @@ static const struct generic_data read_controller_cap_success = {
.expect_status = MGMT_STATUS_SUCCESS,
};

+static const char ext_adv_params_valid[] = {
+ 0x01, /* instance */
+ 0x00, 0xC0, 0x00, 0x00, /* flags, use tx power and intervals */
+ 0x00, 0x00, /* duration */
+ 0x00, 0x00, /* timeout */
+ 0xA0, 0x00, 0x00, 0x00, /* min_interval */
+ 0xA0, 0x00, 0x00, 0x00, /* max_interval */
+ 0x7f, /* tx_power */
+};
+
+static const char ext_adv_hci_params_valid[] = {
+ 0x01, /* handle */
+ 0x10, 0x00, /* evt_properties */
+ 0xA0, 0x00, 0x00, /* min_interval */
+ 0xA0, 0x00, 0x00, /* max_interval */
+ 0x07, /* channel_map */
+ 0x01, /* own_addr_type */
+ 0x00, /* peer_addr_type */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* peer_addr */
+ 0x00, /* filter_policy */
+ 0x7f, /* tx_power */
+ 0x01, /* primary_phy */
+ 0x00, /* secondary_max_skip */
+ 0x01, /* secondary_phy */
+ 0x00, /* sid */
+ 0x00, /* notif_enable */
+};
+
+static const char ext_adv_params_mgmt_rsp_valid_50[] = {
+ 0x01, /* instance */
+ 0x00, /* tx_power defaults to 0 on BT5 platform*/
+ 0x1f, /* max_adv_data_len */
+ 0x1f, /* max_scan_rsp_len */
+};
+
+static const char ext_adv_params_mgmt_rsp_valid[] = {
+ 0x01, /* instance */
+ 0x7f, /* tx_power */
+ 0x1f, /* max_adv_data_len */
+ 0x1f, /* max_scan_rsp_len */
+};
+
+static const char ext_adv_data_mgmt_rsp_valid[] = {
+ 0x01, /* instance */
+};
+
+static const uint8_t ext_adv_data_valid[] = {
+ 0x01, /* instance */
+ 0x04, /* Ad data len */
+ 0x06, /* Scan response data len */
+ 0x03, /* Section length */
+ 0x19, /* GAP Appearance */
+ 0x01,
+ 0x23,
+ 0x05, /* Section length */
+ 0x08, /* ad type Short Name */
+ 't',
+ 'e',
+ 's',
+ 't',
+};
+
+static const char ext_adv_hci_ad_data_valid[] = {
+ 0x01, /* handle */
+ 0x03, /* operation */
+ 0x01, /* minimize fragmentation */
+ 0x04, /* data length */
+ 0x03, /* Section length */
+ 0x19, /* GAP Appearance */
+ 0x01,
+ 0x23,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const char ext_adv_hci_scan_rsp_data_valid[] = {
+ 0x01, /* handle */
+ 0x03, /* operation */
+ 0x01, /* minimize fragmentation */
+ 0x06,
+ 0x05, /* Section length */
+ 0x08, /* ad type Short Name */
+ 't',
+ 'e',
+ 's',
+ 't',
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const uint8_t ext_adv_data_invalid[] = {
+ 0x01, /* instance */
+ 0x04, /* Ad data len */
+ 0x06, /* Scan response data len */
+ 0x03, /* Section length */
+ 0x19, /* GAP Appearance */
+ 0x01,
+ 0x23,
+ 0x07, /* Section length purposefully two octets too long */
+ 0x08, /* ad type Short Name */
+ 't',
+ 'e',
+ 's',
+ 't',
+};
+
+static const struct generic_data adv_params_fail_unpowered = {
+ .setup_settings = settings_le, /* Unpowered */
+ .send_opcode = MGMT_OP_ADD_EXT_ADV_PARAMS,
+ .send_param = ext_adv_params_valid,
+ .send_len = sizeof(ext_adv_params_valid),
+ .expect_status = MGMT_STATUS_REJECTED,
+};
+
+static const struct generic_data adv_params_fail_invalid_params = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_EXT_ADV_PARAMS,
+ .send_param = dummy_data,
+ .send_len = sizeof(dummy_data),
+ .expect_status = MGMT_STATUS_INVALID_PARAMS,
+};
+
+static const struct generic_data adv_params_success = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_EXT_ADV_PARAMS,
+ .send_param = ext_adv_params_valid,
+ .send_len = sizeof(ext_adv_params_valid),
+ .expect_param = ext_adv_params_mgmt_rsp_valid,
+ .expect_len = sizeof(ext_adv_params_mgmt_rsp_valid),
+ .expect_status = MGMT_STATUS_SUCCESS,
+};
+
+static const struct generic_data adv_params_success_50 = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_EXT_ADV_PARAMS,
+ .send_param = ext_adv_params_valid,
+ .send_len = sizeof(ext_adv_params_valid),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = ext_adv_params_mgmt_rsp_valid_50,
+ .expect_len = sizeof(ext_adv_params_mgmt_rsp_valid_50),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = ext_adv_hci_params_valid,
+ .expect_hci_len = sizeof(ext_adv_hci_params_valid),
+};
+
+static const struct generic_data adv_data_fail_no_params = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_EXT_ADV_DATA,
+ .send_param = ext_adv_data_valid,
+ .send_len = sizeof(ext_adv_data_valid),
+ .expect_status = MGMT_STATUS_INVALID_PARAMS,
+};
+
+static const struct generic_data adv_data_success = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_EXT_ADV_DATA,
+ .send_param = ext_adv_data_valid,
+ .send_len = sizeof(ext_adv_data_valid),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = ext_adv_data_mgmt_rsp_valid,
+ .expect_len = sizeof(ext_adv_data_mgmt_rsp_valid),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_DATA,
+ .expect_hci_param = ext_adv_hci_ad_data_valid,
+ .expect_hci_len = sizeof(ext_adv_hci_ad_data_valid),
+};
+
+static const struct generic_data adv_scan_rsp_success = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_EXT_ADV_DATA,
+ .send_param = ext_adv_data_valid,
+ .send_len = sizeof(ext_adv_data_valid),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = ext_adv_data_mgmt_rsp_valid,
+ .expect_len = sizeof(ext_adv_data_mgmt_rsp_valid),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_RSP_DATA,
+ .expect_hci_param = ext_adv_hci_scan_rsp_data_valid,
+ .expect_hci_len = sizeof(ext_adv_hci_scan_rsp_data_valid),
+};
+
+static const struct generic_data adv_data_invalid_params = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_EXT_ADV_DATA,
+ .send_param = ext_adv_data_invalid,
+ .send_len = sizeof(ext_adv_data_invalid),
+ .expect_status = MGMT_STATUS_INVALID_PARAMS,
+};
+
static void client_cmd_complete(uint16_t opcode, uint8_t status,
const void *param, uint8_t len,
void *user_data)
@@ -6027,6 +6216,74 @@ static void setup_complete(uint8_t status, uint16_t length,
setup_bthost();
}

+static void setup_set_unpowered_callback(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ if (status != MGMT_STATUS_SUCCESS) {
+ tester_setup_failed();
+ return;
+ }
+
+ setup_bthost();
+}
+
+static void setup_set_le_callback(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+ unsigned char power_param[] = { 0x00 };
+
+ if (status != MGMT_STATUS_SUCCESS) {
+ tester_setup_failed();
+ return;
+ }
+
+ tester_print("Disabling power");
+
+ mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index,
+ sizeof(power_param),
+ &power_param,
+ setup_set_unpowered_callback,
+ NULL, NULL);
+}
+
+static void setup_ext_adv_not_powered(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+ unsigned char param[] = { 0x01 };
+
+ tester_print("Enabling LE");
+
+ mgmt_send(data->mgmt, MGMT_OP_SET_LE, data->mgmt_index,
+ sizeof(param), &param,
+ setup_set_le_callback,
+ NULL, NULL);
+}
+
+static void setup_set_ext_adv_params_callback(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ if (status != MGMT_STATUS_SUCCESS) {
+ tester_setup_failed();
+ return;
+ }
+
+ setup_bthost();
+}
+
+static void setup_ext_adv_params(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+
+ tester_print("Setting Extended Adv Params");
+
+ mgmt_send(data->mgmt, MGMT_OP_ADD_EXT_ADV_PARAMS, data->mgmt_index,
+ sizeof(ext_adv_params_valid),
+ &ext_adv_params_valid,
+ setup_set_ext_adv_params_callback,
+ NULL, NULL);
+}
+
static void pin_code_request_callback(uint16_t index, uint16_t length,
const void *param, void *user_data)
{
@@ -10292,5 +10549,41 @@ int main(int argc, char *argv[])
&read_controller_cap_success,
NULL, test_50_controller_cap_response);

+ test_bredrle("Ext Adv MGMT Params - Unpowered",
+ &adv_params_fail_unpowered,
+ setup_ext_adv_not_powered,
+ test_command_generic);
+
+ test_bredrle("Ext Adv MGMT Params - Invalid parameters",
+ &adv_params_fail_invalid_params,
+ NULL, test_command_generic);
+
+ test_bredrle("Ext Adv MGMT Params - Success",
+ &adv_params_success,
+ NULL, test_command_generic);
+
+ test_bredrle50("Ext Adv MGMT Params - (5.0) Success",
+ &adv_params_success_50,
+ NULL, test_command_generic);
+
+ test_bredrle("Ext Adv MGMT - Data set without Params",
+ &adv_data_fail_no_params,
+ NULL, test_command_generic);
+
+ test_bredrle50("Ext Adv MGMT - AD Data (5.0) Invalid parameters",
+ &adv_data_invalid_params,
+ setup_ext_adv_params,
+ test_command_generic);
+
+ test_bredrle50("Ext Adv MGMT - AD Data (5.0) Success",
+ &adv_data_success,
+ setup_ext_adv_params,
+ test_command_generic);
+
+ test_bredrle50("Ext Adv MGMT - AD Scan Response (5.0) Success",
+ &adv_scan_rsp_success,
+ setup_ext_adv_params,
+ test_command_generic);
+
return tester_run();
}
--
2.29.2.454.gaff20da3a2-goog

2020-11-24 17:36:09

by Daniel Winkler

[permalink] [raw]
Subject: [Bluez PATCH 1/2] tools/mgmt-tester: Add mgmt-tester coverage for controller capabilities

This patch adds two test cases for the new Read Controller
Capabilities MGMT command. Since the command itself is simple, the test
cases are simple as well:

1. Ensures that providing invalid parameters to the request will result
in a failed MGMT response.

2. Ensures that if the controller is BT5 compliant, the Read Controller
Capabilities command will return a valid TX power range as expected,
otherwise fail.

Reviewed-by: Manish Mandlik <[email protected]>
---

tools/mgmt-tester.c | 76 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)

diff --git a/tools/mgmt-tester.c b/tools/mgmt-tester.c
index 0540efafc..79e653e9e 100644
--- a/tools/mgmt-tester.c
+++ b/tools/mgmt-tester.c
@@ -5269,6 +5269,19 @@ static const struct generic_data read_ext_ctrl_info5 = {
.expect_len = sizeof(ext_ctrl_info5),
};

+static const struct generic_data read_controller_cap_invalid_param_test = {
+ .send_opcode = MGMT_OP_READ_CONTROLLER_CAP,
+ .send_param = dummy_data,
+ .send_len = sizeof(dummy_data),
+ .expect_status = MGMT_STATUS_INVALID_PARAMS,
+};
+
+static const struct generic_data read_controller_cap_success = {
+ .send_opcode = MGMT_OP_READ_CONTROLLER_CAP,
+ .expect_ignore_param = true,
+ .expect_status = MGMT_STATUS_SUCCESS,
+};
+
static void client_cmd_complete(uint16_t opcode, uint8_t status,
const void *param, uint8_t len,
void *user_data)
@@ -8762,6 +8775,61 @@ static void test_connected_and_advertising(const void *test_data)
data, NULL);
}

+static void read_50_controller_cap_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ struct test_data *data = user_data;
+ const struct mgmt_rp_read_controller_cap *rp = param;
+ const uint8_t *ptr = rp->cap;
+ size_t offset = 0;
+ uint8_t tag_len;
+ uint8_t tag_type;
+
+ if (status || !param) {
+ tester_warn("Failed to read advertising features: %s (0x%02x)",
+ mgmt_errstr(status), status);
+ tester_test_failed();
+ }
+
+ if (sizeof(rp->cap_len) + rp->cap_len != length) {
+ tester_warn("Controller capabilities malformed, size %lu != %u",
+ sizeof(rp->cap_len) + rp->cap_len, length);
+ tester_test_failed();
+ }
+
+ while (offset < rp->cap_len) {
+ tag_len = ptr[offset++];
+ tag_type = ptr[offset++];
+
+ switch (tag_type) {
+ case MGMT_CAP_LE_TX_PWR:
+ if ((tag_len - sizeof(tag_type)) != 2) {
+ tester_warn("TX power had unexpected length %d",
+ tag_len);
+ break;
+ }
+ tester_print("Expected Tx Power discovered: %d-%d",
+ ptr[offset], ptr[offset+1]);
+ test_condition_complete(data);
+ }
+
+ /* Step to the next entry */
+ offset += (tag_len - sizeof(tag_type));
+ }
+}
+
+static void test_50_controller_cap_response(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+
+ test_add_condition(data);
+
+ mgmt_send(data->mgmt_alt, MGMT_OP_READ_CONTROLLER_CAP, data->mgmt_index,
+ 0, NULL,
+ read_50_controller_cap_complete,
+ data, NULL);
+}
+
int main(int argc, char *argv[])
{
tester_init(&argc, &argv);
@@ -10216,5 +10284,13 @@ int main(int argc, char *argv[])
setup_advertise_while_connected,
test_connected_and_advertising, 10);

+ test_bredrle("Read Controller Capabilities - Invalid parameters",
+ &read_controller_cap_invalid_param_test,
+ NULL, test_command_generic);
+
+ test_bredrle50("Read Controller Capabilities - (5.0) Success",
+ &read_controller_cap_success,
+ NULL, test_50_controller_cap_response);
+
return tester_run();
}
--
2.29.2.454.gaff20da3a2-goog