diff mbox series

[v4,5/6] tools/l2cap-tester: Add test for Ext-Flowctl mode

Message ID 20200320204038.11799-5-luiz.dentz@gmail.com (mailing list archive)
State New, archived
Headers show
Series [v4,1/6] lib: Add definitions for Enhanced Credits Based Mode | expand

Commit Message

Luiz Augusto von Dentz March 20, 2020, 8:40 p.m. UTC
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds tests for Ext-Flowctl which uses ECRED PDUs.
---
 tools/l2cap-tester.c | 174 +++++++++++++++++++++++++++++++++----------
 1 file changed, 136 insertions(+), 38 deletions(-)
diff mbox series

Patch

diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
index 945f82caf..329bf65c8 100644
--- a/tools/l2cap-tester.c
+++ b/tools/l2cap-tester.c
@@ -61,6 +61,7 @@  struct l2cap_data {
 	uint16_t client_psm;
 	uint16_t server_psm;
 	uint16_t cid;
+	uint8_t mode;
 	int expect_err;
 
 	uint8_t send_cmd_code;
@@ -91,7 +92,7 @@  struct l2cap_data {
 	uint8_t *client_bdaddr;
 	bool server_not_advertising;
 	bool direct_advertising;
-	bool close_one_socket;
+	bool close_1;
 };
 
 static void mgmt_debug(const char *str, void *user_data)
@@ -474,17 +475,17 @@  static const struct l2cap_data le_client_close_socket_test_2 = {
 	.server_not_advertising = true,
 };
 
-static const struct l2cap_data le_client_two_sockets_same_client = {
+static const struct l2cap_data le_client_2_same_client = {
 	.client_psm = 0x0080,
 	.server_psm = 0x0080,
 	.server_not_advertising = true,
 };
 
-static const struct l2cap_data le_client_two_sockets_close_one = {
+static const struct l2cap_data le_client_2_close_1 = {
 	.client_psm = 0x0080,
 	.server_psm = 0x0080,
 	.server_not_advertising = true,
-	.close_one_socket = true,
+	.close_1 = true,
 };
 
 static const struct l2cap_data le_client_connect_nval_psm_test = {
@@ -549,6 +550,49 @@  static const struct l2cap_data le_att_server_success_test_1 = {
 	.cid = 0x0004,
 };
 
+static const struct l2cap_data ext_flowctl_client_connect_success_test_1 = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+};
+
+static const struct l2cap_data ext_flowctl_client_connect_adv_success_test_1 = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.direct_advertising = true,
+};
+
+static const struct l2cap_data ext_flowctl_client_connect_success_test_2 = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.sec_level  = BT_SECURITY_MEDIUM,
+};
+
+static const struct l2cap_data ext_flowctl_client_connect_reject_test_1 = {
+	.client_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.send_cmd = cmd_reject_rsp,
+	.send_cmd_len = sizeof(cmd_reject_rsp),
+	.expect_err = ECONNREFUSED,
+};
+
+static const struct l2cap_data ext_flowctl_client_2 = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.server_not_advertising = true,
+};
+
+static const struct l2cap_data ext_flowctl_client_2_close_1 = {
+	.client_psm = 0x0080,
+	.server_psm = 0x0080,
+	.mode = BT_MODE_EXT_FLOWCTL,
+	.server_not_advertising = true,
+	.close_1 = true,
+};
+
 static void client_cmd_complete(uint16_t opcode, uint8_t status,
 					const void *param, uint8_t len,
 					void *user_data)
@@ -1031,7 +1075,7 @@  failed:
 }
 
 static int create_l2cap_sock(struct test_data *data, uint16_t psm,
-						uint16_t cid, int sec_level)
+				uint16_t cid, int sec_level, uint8_t mode)
 {
 	const struct l2cap_data *l2data = data->test_data;
 	const uint8_t *master_bdaddr;
@@ -1091,6 +1135,17 @@  static int create_l2cap_sock(struct test_data *data, uint16_t psm,
 		}
 	}
 
+	if (mode) {
+		if (setsockopt(sk, SOL_BLUETOOTH, BT_MODE, &mode,
+							sizeof(mode)) < 0) {
+			err = -errno;
+			tester_warn("Can't set mode: %s (%d)", strerror(errno),
+									errno);
+			close(sk);
+			return err;
+		}
+	}
+
 	return sk;
 }
 
@@ -1212,7 +1267,8 @@  static void test_connect(const void *test_data)
 		hciemu_add_master_post_command_hook(data->hciemu,
 						direct_adv_cmd_complete, NULL);
 
-	sk = create_l2cap_sock(data, 0, l2data->cid, l2data->sec_level);
+	sk = create_l2cap_sock(data, 0, l2data->cid, l2data->sec_level,
+							l2data->mode);
 	if (sk < 0) {
 		tester_test_failed();
 		return;
@@ -1241,7 +1297,8 @@  static void test_connect_reject(const void *test_data)
 	const struct l2cap_data *l2data = data->test_data;
 	int sk;
 
-	sk = create_l2cap_sock(data, 0, l2data->cid, l2data->sec_level);
+	sk = create_l2cap_sock(data, 0, l2data->cid, l2data->sec_level,
+							l2data->mode);
 	if (sk < 0) {
 		tester_test_failed();
 		return;
@@ -1256,29 +1313,40 @@  static void test_connect_reject(const void *test_data)
 	close(sk);
 }
 
-static void connect_socket(const uint8_t *client_bdaddr, int *sk_holder,
-							GIOFunc connect_cb)
+static int connect_socket(const uint8_t *client_bdaddr, GIOFunc connect_cb,
+								bool defer)
 {
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
 	GIOChannel *io;
 	int sk;
 
-	sk = create_l2cap_sock(data, 0, l2data->cid, l2data->sec_level);
+	sk = create_l2cap_sock(data, 0, l2data->cid, l2data->sec_level,
+							l2data->mode);
 	if (sk < 0) {
 		tester_print("Error in create_l2cap_sock");
 		tester_test_failed();
-		return;
+		return -1;
 	}
 
-	*sk_holder = sk;
+	if (defer) {
+		int opt = 1;
+
+		if (setsockopt(sk, SOL_BLUETOOTH, BT_DEFER_SETUP, &opt,
+							sizeof(opt)) < 0) {
+			tester_print("Can't enable deferred setup: %s (%d)",
+						strerror(errno), errno);
+			tester_test_failed();
+			return -1;
+		}
+	}
 
 	if (connect_l2cap_impl(sk, client_bdaddr, BDADDR_LE_PUBLIC,
 			l2data->client_psm, l2data->cid) < 0) {
 		tester_print("Error in connect_l2cap_sock");
 		close(sk);
 		tester_test_failed();
-		return;
+		return -1;
 	}
 
 	if (connect_cb) {
@@ -1290,7 +1358,10 @@  static void connect_socket(const uint8_t *client_bdaddr, int *sk_holder,
 		g_io_channel_unref(io);
 	}
 
-	tester_print("Connect in progress, sk = %d", sk);
+	tester_print("Connect in progress, sk = %d %s", sk,
+				defer ? "(deferred)" : "");
+
+	return sk;
 }
 
 static gboolean test_close_socket_1_part_3(gpointer arg)
@@ -1457,11 +1528,11 @@  static void test_close_socket(const void *test_data)
 	else
 		client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
 
-	connect_socket(client_bdaddr, &data->sk, NULL);
+	data->sk = connect_socket(client_bdaddr, NULL, false);
 }
 
-static uint8_t test_two_sockets_connect_cb_cnt;
-static gboolean test_two_sockets_connect_cb(GIOChannel *io, GIOCondition cond,
+static uint8_t test_2_connect_cb_cnt;
+static gboolean test_2_connect_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
 	struct test_data *data = tester_get_data();
@@ -1485,15 +1556,15 @@  static gboolean test_two_sockets_connect_cb(GIOChannel *io, GIOCondition cond,
 	}
 
 	tester_print("Successfully connected");
-	test_two_sockets_connect_cb_cnt++;
+	test_2_connect_cb_cnt++;
 
-	if (test_two_sockets_connect_cb_cnt == 2) {
+	if (test_2_connect_cb_cnt == 2) {
 		close(data->sk);
 		close(data->sk2);
 		tester_test_passed();
 	}
 
-	if (l2data->close_one_socket && test_two_sockets_connect_cb_cnt == 1) {
+	if (l2data->close_1 && test_2_connect_cb_cnt == 1) {
 		close(data->sk2);
 		tester_test_passed();
 	}
@@ -1510,16 +1581,16 @@  static gboolean enable_advertising(gpointer args)
 	return FALSE;
 }
 
-static void test_connect_two_sockets_part_2(void)
+static void test_connect_2_part_2(void)
 {
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
 	const uint8_t *client_bdaddr;
 
 	client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
-	connect_socket(client_bdaddr, &data->sk2, test_two_sockets_connect_cb);
+	data->sk2 = connect_socket(client_bdaddr, test_2_connect_cb, false);
 
-	if (l2data->close_one_socket) {
+	if (l2data->close_1) {
 		tester_print("Closing first socket! %d", data->sk);
 		close(data->sk);
 	}
@@ -1528,7 +1599,7 @@  static void test_connect_two_sockets_part_2(void)
 }
 
 static uint8_t test_scan_enable_counter;
-static void test_connect_two_sockets_router(uint16_t opcode, const void *param,
+static void test_connect_2_router(uint16_t opcode, const void *param,
 					uint8_t length, void *user_data)
 {
 	const struct bt_hci_cmd_le_set_scan_enable *scan_params = param;
@@ -1538,23 +1609,24 @@  static void test_connect_two_sockets_router(uint16_t opcode, const void *param,
 						scan_params->enable == true) {
 		test_scan_enable_counter++;
 		if (test_scan_enable_counter == 1)
-			test_connect_two_sockets_part_2();
+			test_connect_2_part_2();
 		else if (test_scan_enable_counter == 2)
 			g_idle_add(enable_advertising, NULL);
 	}
 }
 
-static void test_connect_two_sockets(const void *test_data)
+static void test_connect_2(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
 	const uint8_t *client_bdaddr;
+	bool defer;
 
-	test_two_sockets_connect_cb_cnt = 0;
+	test_2_connect_cb_cnt = 0;
 	test_scan_enable_counter = 0;
 
 	hciemu_add_master_post_command_hook(data->hciemu,
-				test_connect_two_sockets_router, data);
+				test_connect_2_router, data);
 
 	if (l2data->server_psm) {
 		struct bthost *bthost = hciemu_client_get_host(data->hciemu);
@@ -1564,12 +1636,14 @@  static void test_connect_two_sockets(const void *test_data)
 						NULL, NULL);
 	}
 
+	defer = (l2data->mode == BT_MODE_EXT_FLOWCTL);
+
 	client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
-	if (l2data->close_one_socket)
-		connect_socket(client_bdaddr, &data->sk, NULL);
+	if (l2data->close_1)
+		data->sk = connect_socket(client_bdaddr, NULL, defer);
 	else
-		connect_socket(client_bdaddr, &data->sk,
-						test_two_sockets_connect_cb);
+		data->sk = connect_socket(client_bdaddr, test_2_connect_cb,
+								defer);
 }
 
 static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
@@ -1727,7 +1801,8 @@  static void test_server(const void *test_data)
 
 	if (l2data->server_psm || l2data->cid) {
 		sk = create_l2cap_sock(data, l2data->server_psm,
-					l2data->cid, l2data->sec_level);
+					l2data->cid, l2data->sec_level,
+					l2data->mode);
 		if (sk < 0) {
 			tester_test_failed();
 			return;
@@ -1776,7 +1851,7 @@  static void test_getpeername_not_connected(const void *test_data)
 	socklen_t len;
 	int sk;
 
-	sk = create_l2cap_sock(data, 0, 0, 0);
+	sk = create_l2cap_sock(data, 0, 0, 0, 0);
 	if (sk < 0) {
 		tester_test_failed();
 		return;
@@ -1902,14 +1977,14 @@  int main(int argc, char *argv[])
 				test_close_socket);
 
 	test_l2cap_le("L2CAP LE Client - Open two sockets",
-				&le_client_two_sockets_same_client,
+				&le_client_2_same_client,
 				setup_powered_client,
-				test_connect_two_sockets);
+				test_connect_2);
 
 	test_l2cap_le("L2CAP LE Client - Open two sockets close one",
-				&le_client_two_sockets_close_one,
+				&le_client_2_close_1,
 				setup_powered_client,
-				test_connect_two_sockets);
+				test_connect_2);
 
 	test_l2cap_le("L2CAP LE Client - Invalid PSM",
 					&le_client_connect_nval_psm_test,
@@ -1920,6 +1995,29 @@  int main(int argc, char *argv[])
 					setup_powered_server, test_server);
 
 
+	test_l2cap_le("L2CAP Ext-Flowctl Client - Success",
+				&ext_flowctl_client_connect_success_test_1,
+				setup_powered_client, test_connect);
+	test_l2cap_le("L2CAP Ext-Flowctl Client, Direct Advertising - Success",
+				&ext_flowctl_client_connect_adv_success_test_1,
+				setup_powered_client, test_connect);
+	test_l2cap_le("L2CAP Ext-Flowctl Client SMP - Success",
+				&ext_flowctl_client_connect_success_test_2,
+				setup_powered_client, test_connect);
+	test_l2cap_le("L2CAP Ext-Flowctl Client - Command Reject",
+				&ext_flowctl_client_connect_reject_test_1,
+				setup_powered_client, test_connect);
+
+	test_l2cap_le("L2CAP Ext-Flowctl Client - Open two sockets",
+				&ext_flowctl_client_2,
+				setup_powered_client,
+				test_connect_2);
+
+	test_l2cap_le("L2CAP Ext-Flowctl Client - Open two sockets close one",
+				&ext_flowctl_client_2_close_1,
+				setup_powered_client,
+				test_connect_2);
+
 	test_l2cap_le("L2CAP LE ATT Client - Success",
 				&le_att_client_connect_success_test_1,
 				setup_powered_client, test_connect);