All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 1/2] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections
@ 2020-03-25 19:37 Luiz Augusto von Dentz
  2020-03-25 19:37 ` [PATCH v5 2/2] Bluetooth: Add BT_MODE socket option Luiz Augusto von Dentz
  2020-03-25 21:17 ` [PATCH v5 1/2] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections Marcel Holtmann
  0 siblings, 2 replies; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2020-03-25 19:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This uses the DEFER_SETUP flag to group channels with
L2CAP_CREDIT_BASED_CONNECTION_REQ.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 include/net/bluetooth/l2cap.h |   4 +
 net/bluetooth/l2cap_core.c    | 137 +++++++++++++++++++++++++++++++---
 2 files changed, 131 insertions(+), 10 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 2d7d28474d34..dada14d0622c 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -47,6 +47,7 @@
 #define L2CAP_DEFAULT_ACC_LAT		0xFFFFFFFF
 #define L2CAP_BREDR_MAX_PAYLOAD		1019    /* 3-DH5 packet */
 #define L2CAP_LE_MIN_MTU		23
+#define L2CAP_ECRED_CONN_SCID_MAX	5
 
 #define L2CAP_DISC_TIMEOUT		msecs_to_jiffies(100)
 #define L2CAP_DISC_REJ_TIMEOUT		msecs_to_jiffies(5000)
@@ -984,6 +985,9 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan);
 int l2cap_ertm_init(struct l2cap_chan *chan);
 void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
 void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
+typedef void (*l2cap_chan_func_t)(struct l2cap_chan *chan, void *data);
+void l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
+		     void *data);
 void l2cap_chan_del(struct l2cap_chan *chan, int err);
 void l2cap_send_conn_req(struct l2cap_chan *chan);
 void l2cap_move_start(struct l2cap_chan *chan);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 8b0fca39989d..fd9d0d08f9c9 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -678,6 +678,29 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
 }
 EXPORT_SYMBOL_GPL(l2cap_chan_del);
 
+static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
+			      void *data)
+{
+	struct l2cap_chan *chan;
+
+	list_for_each_entry(chan, &conn->chan_l, list) {
+		func(chan, data);
+	}
+}
+
+void l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
+		     void *data)
+{
+	if (!conn)
+		return;
+
+	mutex_lock(&conn->chan_lock);
+	__l2cap_chan_list(conn, func, data);
+	mutex_unlock(&conn->chan_lock);
+}
+
+EXPORT_SYMBOL_GPL(l2cap_chan_list);
+
 static void l2cap_conn_update_id_addr(struct work_struct *work)
 {
 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
@@ -1356,29 +1379,79 @@ static void l2cap_le_connect(struct l2cap_chan *chan)
 		       sizeof(req), &req);
 }
 
-static void l2cap_ecred_connect(struct l2cap_chan *chan)
-{
-	struct l2cap_conn *conn = chan->conn;
+struct l2cap_ecred_conn_data {
 	struct {
 		struct l2cap_ecred_conn_req req;
-		__le16 scid;
+		__le16 scid[5];
 	} __packed pdu;
+	struct l2cap_chan *chan;
+	struct pid *pid;
+	int count;
+};
+
+static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data)
+{
+	struct l2cap_ecred_conn_data *conn = data;
+	struct pid *pid;
+
+	if (chan == conn->chan)
+		return;
+
+	if (!test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags))
+		return;
+
+	pid = chan->ops->get_peer_pid(chan);
+
+	/* Only add deferred channels with the same PID/PSM */
+	if (conn->pid != pid || chan->psm != conn->chan->psm || chan->ident ||
+	    chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
+		return;
 
 	if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
 		return;
 
 	l2cap_ecred_init(chan, 0);
 
-	pdu.req.psm     = chan->psm;
-	pdu.req.mtu     = cpu_to_le16(chan->imtu);
-	pdu.req.mps     = cpu_to_le16(chan->mps);
-	pdu.req.credits = cpu_to_le16(chan->rx_credits);
-	pdu.scid        = cpu_to_le16(chan->scid);
+	/* Set the same ident so we can match on the rsp */
+	chan->ident = conn->chan->ident;
+
+	/* Include all channels deferred */
+	conn->pdu.scid[conn->count] = cpu_to_le16(chan->scid);
+
+	conn->count++;
+}
+
+static void l2cap_ecred_connect(struct l2cap_chan *chan)
+{
+	struct l2cap_conn *conn = chan->conn;
+	struct l2cap_ecred_conn_data data;
+
+	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
+		return;
+
+	if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
+		return;
+
+	l2cap_ecred_init(chan, 0);
+
+	data.pdu.req.psm     = chan->psm;
+	data.pdu.req.mtu     = cpu_to_le16(chan->imtu);
+	data.pdu.req.mps     = cpu_to_le16(chan->mps);
+	data.pdu.req.credits = cpu_to_le16(chan->rx_credits);
+	data.pdu.scid[0]     = cpu_to_le16(chan->scid);
 
 	chan->ident = l2cap_get_ident(conn);
+	data.pid = chan->ops->get_peer_pid(chan);
+
+	data.count = 1;
+	data.chan = chan;
+	data.pid = chan->ops->get_peer_pid(chan);
+
+	__l2cap_chan_list(conn, l2cap_ecred_defer_connect, &data);
 
 	l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_CONN_REQ,
-		       sizeof(pdu), &pdu);
+		       sizeof(data.pdu.req) + data.count * sizeof(__le16),
+		       &data.pdu);
 }
 
 static void l2cap_le_start(struct l2cap_chan *chan)
@@ -7693,6 +7766,33 @@ static bool is_valid_psm(u16 psm, u8 dst_type) {
 	return ((psm & 0x0101) == 0x0001);
 }
 
+struct l2cap_chan_data {
+	struct l2cap_chan *chan;
+	struct pid *pid;
+	int count;
+};
+
+static void l2cap_chan_by_pid(struct l2cap_chan *chan, void *data)
+{
+	struct l2cap_chan_data *d = data;
+	struct pid *pid;
+
+	if (chan == d->chan)
+		return;
+
+	if (!test_bit(FLAG_DEFER_SETUP, &chan->flags))
+		return;
+
+	pid = chan->ops->get_peer_pid(chan);
+
+	/* Only count deferred channels with the same PID/PSM */
+	if (d->pid != pid || chan->psm != d->chan->psm || chan->ident ||
+	    chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
+		return;
+
+	d->count++;
+}
+
 int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 		       bdaddr_t *dst, u8 dst_type)
 {
@@ -7812,6 +7912,23 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 		goto done;
 	}
 
+	if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) {
+		struct l2cap_chan_data data;
+
+		data.chan = chan;
+		data.pid = chan->ops->get_peer_pid(chan);
+		data.count = 1;
+
+		l2cap_chan_list(conn, l2cap_chan_by_pid, &data);
+
+		/* Check if there isn't too many channels being connected */
+		if (data.count > L2CAP_ECRED_CONN_SCID_MAX) {
+			hci_conn_drop(hcon);
+			err = -EPROTO;
+			goto done;
+		}
+	}
+
 	mutex_lock(&conn->chan_lock);
 	l2cap_chan_lock(chan);
 
-- 
2.21.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v5 2/2] Bluetooth: Add BT_MODE socket option
  2020-03-25 19:37 [PATCH v5 1/2] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections Luiz Augusto von Dentz
@ 2020-03-25 19:37 ` Luiz Augusto von Dentz
  2020-03-25 21:14   ` Marcel Holtmann
  2020-03-25 21:17 ` [PATCH v5 1/2] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections Marcel Holtmann
  1 sibling, 1 reply; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2020-03-25 19:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds BT_MODE socket option which can be used to set L2CAP modes,
including modes only supported over LE which were not supported using
the L2CAP_OPTIONS.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 include/net/bluetooth/bluetooth.h |   8 ++
 net/bluetooth/l2cap_sock.c        | 120 +++++++++++++++++++++++++++++-
 2 files changed, 127 insertions(+), 1 deletion(-)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 1576353a2773..3fa7b1e3c5d9 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -139,6 +139,14 @@ struct bt_voice {
 #define BT_PHY_LE_CODED_TX	0x00002000
 #define BT_PHY_LE_CODED_RX	0x00004000
 
+#define BT_MODE			15
+
+#define BT_MODE_BASIC		0x00
+#define BT_MODE_ERTM		0x01
+#define BT_MODE_STREAMING	0x02
+#define BT_MODE_LE_FLOWCTL	0x03
+#define BT_MODE_EXT_FLOWCTL	0x04
+
 __printf(1, 2)
 void bt_info(const char *fmt, ...);
 __printf(1, 2)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 117ba20ea194..07f8d60953f2 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -395,6 +395,24 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr,
 	return sizeof(struct sockaddr_l2);
 }
 
+static int l2cap_get_mode(struct l2cap_chan *chan)
+{
+	switch (chan->mode) {
+	case L2CAP_MODE_BASIC:
+		return BT_MODE_BASIC;
+	case L2CAP_MODE_ERTM:
+		return BT_MODE_ERTM;
+	case L2CAP_MODE_STREAMING:
+		return BT_MODE_STREAMING;
+	case L2CAP_MODE_LE_FLOWCTL:
+		return BT_MODE_LE_FLOWCTL;
+	case L2CAP_MODE_EXT_FLOWCTL:
+		return BT_MODE_EXT_FLOWCTL;
+	}
+
+	return -EINVAL;
+}
+
 static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
 				     char __user *optval, int __user *optlen)
 {
@@ -424,6 +442,13 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
 			break;
 		}
 
+		/* L2CAP_MODE_LE_FLOWCTL and L2CAP_MODE_EXT_FLOWCTL are not
+		 * supported by L2CAP_OPTIONS.
+		 */
+		if (chan->mode == L2CAP_MODE_LE_FLOWCTL ||
+				chan->mode == L2CAP_MODE_EXT_FLOWCTL)
+			return -EINVAL;
+
 		memset(&opts, 0, sizeof(opts));
 		opts.imtu     = chan->imtu;
 		opts.omtu     = chan->omtu;
@@ -508,7 +533,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
 	struct bt_security sec;
 	struct bt_power pwr;
 	u32 phys;
-	int len, err = 0;
+	int len, mode, err = 0;
 
 	BT_DBG("sk %p", sk);
 
@@ -624,6 +649,27 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
 			err = -EFAULT;
 		break;
 
+	case BT_MODE:
+		if (!enable_ecred) {
+			err = -ENOPROTOOPT;
+			break;
+		}
+
+		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
+			err = -EINVAL;
+			break;
+		}
+
+		mode = l2cap_get_mode(chan);
+		if (mode < 0) {
+			err = mode;
+			break;
+		}
+
+		if (put_user(mode, (u8 __user *) optval))
+			err = -EFAULT;
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -763,6 +809,45 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
 	return err;
 }
 
+static int l2cap_set_mode(struct l2cap_chan *chan, u8 mode)
+{
+	switch (mode) {
+	case BT_MODE_BASIC:
+		if (bdaddr_type_is_le(chan->src_type))
+			return -EINVAL;
+		mode = L2CAP_MODE_BASIC;
+		clear_bit(CONF_STATE2_DEVICE, &chan->conf_state);
+		break;
+	case BT_MODE_ERTM:
+		if (!disable_ertm || bdaddr_type_is_le(chan->src_type))
+			return -EINVAL;
+		mode = L2CAP_MODE_ERTM;
+		break;
+	case BT_MODE_STREAMING:
+		if (!disable_ertm || bdaddr_type_is_le(chan->src_type))
+			return -EINVAL;
+		mode = L2CAP_MODE_STREAMING;
+		break;
+	case BT_MODE_LE_FLOWCTL:
+		if (!bdaddr_type_is_le(chan->src_type))
+			return -EINVAL;
+		mode = L2CAP_MODE_LE_FLOWCTL;
+		break;
+	case BT_MODE_EXT_FLOWCTL:
+		/* TODO: Add support for ECRED PDUs to BR/EDR */
+		if (!bdaddr_type_is_le(chan->src_type))
+			return -EINVAL;
+		mode = L2CAP_MODE_EXT_FLOWCTL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	chan->mode = mode;
+
+	return 0;
+}
+
 static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
 				 char __user *optval, unsigned int optlen)
 {
@@ -968,6 +1053,39 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
 
 		break;
 
+	case BT_MODE:
+		if (!enable_ecred) {
+			err = -ENOPROTOOPT;
+			break;
+		}
+
+		BT_DBG("sk->sk_state %u", sk->sk_state);
+
+		if (sk->sk_state != BT_BOUND) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (get_user(opt, (u8 __user *) optval)) {
+			err = -EFAULT;
+			break;
+		}
+
+		BT_DBG("opt %u", opt);
+
+		err = l2cap_set_mode(chan, opt);
+		if (err)
+			break;
+
+		BT_DBG("mode 0x%2.2x", chan->mode);
+
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
-- 
2.21.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v5 2/2] Bluetooth: Add BT_MODE socket option
  2020-03-25 19:37 ` [PATCH v5 2/2] Bluetooth: Add BT_MODE socket option Luiz Augusto von Dentz
@ 2020-03-25 21:14   ` Marcel Holtmann
  2020-03-25 23:39     ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 5+ messages in thread
From: Marcel Holtmann @ 2020-03-25 21:14 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

> This adds BT_MODE socket option which can be used to set L2CAP modes,
> including modes only supported over LE which were not supported using
> the L2CAP_OPTIONS.
> 
> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> ---
> include/net/bluetooth/bluetooth.h |   8 ++
> net/bluetooth/l2cap_sock.c        | 120 +++++++++++++++++++++++++++++-
> 2 files changed, 127 insertions(+), 1 deletion(-)
> 
> diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> index 1576353a2773..3fa7b1e3c5d9 100644
> --- a/include/net/bluetooth/bluetooth.h
> +++ b/include/net/bluetooth/bluetooth.h
> @@ -139,6 +139,14 @@ struct bt_voice {
> #define BT_PHY_LE_CODED_TX	0x00002000
> #define BT_PHY_LE_CODED_RX	0x00004000
> 
> +#define BT_MODE			15
> +
> +#define BT_MODE_BASIC		0x00
> +#define BT_MODE_ERTM		0x01
> +#define BT_MODE_STREAMING	0x02
> +#define BT_MODE_LE_FLOWCTL	0x03
> +#define BT_MODE_EXT_FLOWCTL	0x04
> +
> __printf(1, 2)
> void bt_info(const char *fmt, ...);
> __printf(1, 2)
> diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> index 117ba20ea194..07f8d60953f2 100644
> --- a/net/bluetooth/l2cap_sock.c
> +++ b/net/bluetooth/l2cap_sock.c
> @@ -395,6 +395,24 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr,
> 	return sizeof(struct sockaddr_l2);
> }
> 
> +static int l2cap_get_mode(struct l2cap_chan *chan)
> +{
> +	switch (chan->mode) {
> +	case L2CAP_MODE_BASIC:
> +		return BT_MODE_BASIC;
> +	case L2CAP_MODE_ERTM:
> +		return BT_MODE_ERTM;
> +	case L2CAP_MODE_STREAMING:
> +		return BT_MODE_STREAMING;
> +	case L2CAP_MODE_LE_FLOWCTL:
> +		return BT_MODE_LE_FLOWCTL;
> +	case L2CAP_MODE_EXT_FLOWCTL:
> +		return BT_MODE_EXT_FLOWCTL;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
> 				     char __user *optval, int __user *optlen)
> {
> @@ -424,6 +442,13 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
> 			break;
> 		}
> 
> +		/* L2CAP_MODE_LE_FLOWCTL and L2CAP_MODE_EXT_FLOWCTL are not
> +		 * supported by L2CAP_OPTIONS.
> +		 */
> +		if (chan->mode == L2CAP_MODE_LE_FLOWCTL ||
> +				chan->mode == L2CAP_MODE_EXT_FLOWCTL)

this is the wrong kernel indentation.

> +			return -EINVAL;
> +
> 		memset(&opts, 0, sizeof(opts));
> 		opts.imtu     = chan->imtu;
> 		opts.omtu     = chan->omtu;
> @@ -508,7 +533,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
> 	struct bt_security sec;
> 	struct bt_power pwr;
> 	u32 phys;
> -	int len, err = 0;
> +	int len, mode, err = 0;
> 
> 	BT_DBG("sk %p", sk);
> 
> @@ -624,6 +649,27 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
> 			err = -EFAULT;
> 		break;
> 
> +	case BT_MODE:
> +		if (!enable_ecred) {
> +			err = -ENOPROTOOPT;
> +			break;
> +		}
> +
> +		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
> +			err = -EINVAL;
> +			break;
> +		}
> +
> +		mode = l2cap_get_mode(chan);
> +		if (mode < 0) {
> +			err = mode;
> +			break;
> +		}
> +
> +		if (put_user(mode, (u8 __user *) optval))
> +			err = -EFAULT;
> +		break;
> +
> 	default:
> 		err = -ENOPROTOOPT;
> 		break;
> @@ -763,6 +809,45 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
> 	return err;
> }
> 
> +static int l2cap_set_mode(struct l2cap_chan *chan, u8 mode)
> +{
> +	switch (mode) {
> +	case BT_MODE_BASIC:
> +		if (bdaddr_type_is_le(chan->src_type))
> +			return -EINVAL;
> +		mode = L2CAP_MODE_BASIC;
> +		clear_bit(CONF_STATE2_DEVICE, &chan->conf_state);
> +		break;
> +	case BT_MODE_ERTM:
> +		if (!disable_ertm || bdaddr_type_is_le(chan->src_type))
> +			return -EINVAL;
> +		mode = L2CAP_MODE_ERTM;
> +		break;
> +	case BT_MODE_STREAMING:
> +		if (!disable_ertm || bdaddr_type_is_le(chan->src_type))
> +			return -EINVAL;
> +		mode = L2CAP_MODE_STREAMING;
> +		break;
> +	case BT_MODE_LE_FLOWCTL:
> +		if (!bdaddr_type_is_le(chan->src_type))
> +			return -EINVAL;
> +		mode = L2CAP_MODE_LE_FLOWCTL;
> +		break;
> +	case BT_MODE_EXT_FLOWCTL:
> +		/* TODO: Add support for ECRED PDUs to BR/EDR */
> +		if (!bdaddr_type_is_le(chan->src_type))
> +			return -EINVAL;
> +		mode = L2CAP_MODE_EXT_FLOWCTL;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	chan->mode = mode;
> +
> +	return 0;
> +}
> +
> static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
> 				 char __user *optval, unsigned int optlen)
> {
> @@ -968,6 +1053,39 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
> 
> 		break;
> 
> +	case BT_MODE:
> +		if (!enable_ecred) {
> +			err = -ENOPROTOOPT;
> +			break;
> +		}
> +
> +		BT_DBG("sk->sk_state %u", sk->sk_state);
> +
> +		if (sk->sk_state != BT_BOUND) {
> +			err = -EINVAL;
> +			break;
> +		}
> +
> +		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
> +			err = -EINVAL;
> +			break;
> +		}
> +
> +		if (get_user(opt, (u8 __user *) optval)) {
> +			err = -EFAULT;
> +			break;
> +		}
> +
> +		BT_DBG("opt %u", opt);
> +
> +		err = l2cap_set_mode(chan, opt);
> +		if (err)
> +			break;
> +
> +		BT_DBG("mode 0x%2.2x", chan->mode);
> +
> +		break;
> +

So do we want BT_MODE as u8 or just simply as int?

Regards

Marcel


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v5 1/2] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections
  2020-03-25 19:37 [PATCH v5 1/2] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections Luiz Augusto von Dentz
  2020-03-25 19:37 ` [PATCH v5 2/2] Bluetooth: Add BT_MODE socket option Luiz Augusto von Dentz
@ 2020-03-25 21:17 ` Marcel Holtmann
  1 sibling, 0 replies; 5+ messages in thread
From: Marcel Holtmann @ 2020-03-25 21:17 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

> This uses the DEFER_SETUP flag to group channels with
> L2CAP_CREDIT_BASED_CONNECTION_REQ.
> 
> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> ---
> include/net/bluetooth/l2cap.h |   4 +
> net/bluetooth/l2cap_core.c    | 137 +++++++++++++++++++++++++++++++---
> 2 files changed, 131 insertions(+), 10 deletions(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v5 2/2] Bluetooth: Add BT_MODE socket option
  2020-03-25 21:14   ` Marcel Holtmann
@ 2020-03-25 23:39     ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2020-03-25 23:39 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth

Hi Marcel,

On Wed, Mar 25, 2020 at 2:15 PM Marcel Holtmann <marcel@holtmann.org> wrote:
>
> Hi Luiz,
>
> > This adds BT_MODE socket option which can be used to set L2CAP modes,
> > including modes only supported over LE which were not supported using
> > the L2CAP_OPTIONS.
> >
> > Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> > ---
> > include/net/bluetooth/bluetooth.h |   8 ++
> > net/bluetooth/l2cap_sock.c        | 120 +++++++++++++++++++++++++++++-
> > 2 files changed, 127 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> > index 1576353a2773..3fa7b1e3c5d9 100644
> > --- a/include/net/bluetooth/bluetooth.h
> > +++ b/include/net/bluetooth/bluetooth.h
> > @@ -139,6 +139,14 @@ struct bt_voice {
> > #define BT_PHY_LE_CODED_TX    0x00002000
> > #define BT_PHY_LE_CODED_RX    0x00004000
> >
> > +#define BT_MODE                      15
> > +
> > +#define BT_MODE_BASIC                0x00
> > +#define BT_MODE_ERTM         0x01
> > +#define BT_MODE_STREAMING    0x02
> > +#define BT_MODE_LE_FLOWCTL   0x03
> > +#define BT_MODE_EXT_FLOWCTL  0x04
> > +
> > __printf(1, 2)
> > void bt_info(const char *fmt, ...);
> > __printf(1, 2)
> > diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> > index 117ba20ea194..07f8d60953f2 100644
> > --- a/net/bluetooth/l2cap_sock.c
> > +++ b/net/bluetooth/l2cap_sock.c
> > @@ -395,6 +395,24 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr,
> >       return sizeof(struct sockaddr_l2);
> > }
> >
> > +static int l2cap_get_mode(struct l2cap_chan *chan)
> > +{
> > +     switch (chan->mode) {
> > +     case L2CAP_MODE_BASIC:
> > +             return BT_MODE_BASIC;
> > +     case L2CAP_MODE_ERTM:
> > +             return BT_MODE_ERTM;
> > +     case L2CAP_MODE_STREAMING:
> > +             return BT_MODE_STREAMING;
> > +     case L2CAP_MODE_LE_FLOWCTL:
> > +             return BT_MODE_LE_FLOWCTL;
> > +     case L2CAP_MODE_EXT_FLOWCTL:
> > +             return BT_MODE_EXT_FLOWCTL;
> > +     }
> > +
> > +     return -EINVAL;
> > +}
> > +
> > static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
> >                                    char __user *optval, int __user *optlen)
> > {
> > @@ -424,6 +442,13 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
> >                       break;
> >               }
> >
> > +             /* L2CAP_MODE_LE_FLOWCTL and L2CAP_MODE_EXT_FLOWCTL are not
> > +              * supported by L2CAP_OPTIONS.
> > +              */
> > +             if (chan->mode == L2CAP_MODE_LE_FLOWCTL ||
> > +                             chan->mode == L2CAP_MODE_EXT_FLOWCTL)
>
> this is the wrong kernel indentation.

Fixed

> > +                     return -EINVAL;
> > +
> >               memset(&opts, 0, sizeof(opts));
> >               opts.imtu     = chan->imtu;
> >               opts.omtu     = chan->omtu;
> > @@ -508,7 +533,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
> >       struct bt_security sec;
> >       struct bt_power pwr;
> >       u32 phys;
> > -     int len, err = 0;
> > +     int len, mode, err = 0;
> >
> >       BT_DBG("sk %p", sk);
> >
> > @@ -624,6 +649,27 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
> >                       err = -EFAULT;
> >               break;
> >
> > +     case BT_MODE:
> > +             if (!enable_ecred) {
> > +                     err = -ENOPROTOOPT;
> > +                     break;
> > +             }
> > +
> > +             if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
> > +                     err = -EINVAL;
> > +                     break;
> > +             }
> > +
> > +             mode = l2cap_get_mode(chan);
> > +             if (mode < 0) {
> > +                     err = mode;
> > +                     break;
> > +             }
> > +
> > +             if (put_user(mode, (u8 __user *) optval))
> > +                     err = -EFAULT;
> > +             break;
> > +
> >       default:
> >               err = -ENOPROTOOPT;
> >               break;
> > @@ -763,6 +809,45 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
> >       return err;
> > }
> >
> > +static int l2cap_set_mode(struct l2cap_chan *chan, u8 mode)
> > +{
> > +     switch (mode) {
> > +     case BT_MODE_BASIC:
> > +             if (bdaddr_type_is_le(chan->src_type))
> > +                     return -EINVAL;
> > +             mode = L2CAP_MODE_BASIC;
> > +             clear_bit(CONF_STATE2_DEVICE, &chan->conf_state);
> > +             break;
> > +     case BT_MODE_ERTM:
> > +             if (!disable_ertm || bdaddr_type_is_le(chan->src_type))
> > +                     return -EINVAL;
> > +             mode = L2CAP_MODE_ERTM;
> > +             break;
> > +     case BT_MODE_STREAMING:
> > +             if (!disable_ertm || bdaddr_type_is_le(chan->src_type))
> > +                     return -EINVAL;
> > +             mode = L2CAP_MODE_STREAMING;
> > +             break;
> > +     case BT_MODE_LE_FLOWCTL:
> > +             if (!bdaddr_type_is_le(chan->src_type))
> > +                     return -EINVAL;
> > +             mode = L2CAP_MODE_LE_FLOWCTL;
> > +             break;
> > +     case BT_MODE_EXT_FLOWCTL:
> > +             /* TODO: Add support for ECRED PDUs to BR/EDR */
> > +             if (!bdaddr_type_is_le(chan->src_type))
> > +                     return -EINVAL;
> > +             mode = L2CAP_MODE_EXT_FLOWCTL;
> > +             break;
> > +     default:
> > +             return -EINVAL;
> > +     }
> > +
> > +     chan->mode = mode;
> > +
> > +     return 0;
> > +}
> > +
> > static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
> >                                char __user *optval, unsigned int optlen)
> > {
> > @@ -968,6 +1053,39 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
> >
> >               break;
> >
> > +     case BT_MODE:
> > +             if (!enable_ecred) {
> > +                     err = -ENOPROTOOPT;
> > +                     break;
> > +             }
> > +
> > +             BT_DBG("sk->sk_state %u", sk->sk_state);
> > +
> > +             if (sk->sk_state != BT_BOUND) {
> > +                     err = -EINVAL;
> > +                     break;
> > +             }
> > +
> > +             if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
> > +                     err = -EINVAL;
> > +                     break;
> > +             }
> > +
> > +             if (get_user(opt, (u8 __user *) optval)) {
> > +                     err = -EFAULT;
> > +                     break;
> > +             }
> > +
> > +             BT_DBG("opt %u", opt);
> > +
> > +             err = l2cap_set_mode(chan, opt);
> > +             if (err)
> > +                     break;
> > +
> > +             BT_DBG("mode 0x%2.2x", chan->mode);
> > +
> > +             break;
> > +
>
> So do we want BT_MODE as u8 or just simply as int?

For the mode alone I guess it would be fine, the question is if we
want to leave space to add other fields later but I guess we could do
that with use of new options instead.

> Regards
>
> Marcel
>


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-03-25 23:39 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-25 19:37 [PATCH v5 1/2] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections Luiz Augusto von Dentz
2020-03-25 19:37 ` [PATCH v5 2/2] Bluetooth: Add BT_MODE socket option Luiz Augusto von Dentz
2020-03-25 21:14   ` Marcel Holtmann
2020-03-25 23:39     ` Luiz Augusto von Dentz
2020-03-25 21:17 ` [PATCH v5 1/2] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections Marcel Holtmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.