* [PATCH v5 0/3] Enable use of L2CAP_MODE_EXT_FLOWCTL @ 2020-03-23 20:34 Luiz Augusto von Dentz 2020-03-23 20:34 ` [PATCH v5 1/3] Bluetooth: L2CAP: Add get_peer_pid callback Luiz Augusto von Dentz ` (2 more replies) 0 siblings, 3 replies; 10+ messages in thread From: Luiz Augusto von Dentz @ 2020-03-23 20:34 UTC (permalink / raw) To: linux-bluetooth From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> This enables use of BT_MODE_EXT_FLOWCTL with BT_MODE socketopt, in addition to that add support for DEFER_SETUP to be used with client sockets so they can be grouped and sent together. BT_MODE is not compatible with L2CAP_OPTIONS so attempting to use them both will cause an error to be returned to the applicatio. This has been tested by introducing support for L2CAP_MODE_EXT_FLOWCTL into l2cap-tester which now produces the following trace: Enable ecred PDUs: #echo 1 > /sys/module/bluetooth/parameters/enable_ecred #sudo tools/l2cap-tester -p "L2CAP Ext-Flowctl" L2CAP Ext-Flowctl Client - Success - init Read Index List callback Status: 0x00 New hciemu instance created Index Added callback Index: 0x0000 Read Info callback Status: 0x00 Address: 00:AA:01:00:00:00 Version: 0x09 Manufacturer: 0x003f Supported settings: 0x0001be1b Current settings: 0x00000200 Class: 0x000000 Name: Short name: L2CAP Ext-Flowctl Client - Success - setup Powering on controller Controller powered on Client set connectable status 0x00 L2CAP Ext-Flowctl Client - Success - setup complete L2CAP Ext-Flowctl Client - Success - run Connect in progress Successfully connected L2CAP Ext-Flowctl Client - Success - test passed L2CAP Ext-Flowctl Client - Success - teardown Index Removed callback Index: 0x0000 L2CAP Ext-Flowctl Client - Success - teardown complete L2CAP Ext-Flowctl Client - Success - done L2CAP Ext-Flowctl Client, Direct Advertising - Success - init Read Index List callback Status: 0x00 New hciemu instance created Index Added callback Index: 0x0000 Read Info callback Status: 0x00 Address: 00:AA:01:00:00:00 Version: 0x09 Manufacturer: 0x003f Supported settings: 0x0001be1b Current settings: 0x00000200 Class: 0x000000 Name: Short name: L2CAP Ext-Flowctl Client, Direct Advertising - Success - setup Powering on controller Controller powered on Client set connectable status 0x00 L2CAP Ext-Flowctl Client, Direct Advertising - Success - setup complete L2CAP Ext-Flowctl Client, Direct Advertising - Success - run Connect in progress Received advertising parameters HCI command L2CAP Ext-Flowctl Client, Direct Advertising - Success - test passed L2CAP Ext-Flowctl Client, Direct Advertising - Success - teardown Index Removed callback Index: 0x0000 L2CAP Ext-Flowctl Client, Direct Advertising - Success - teardown complete L2CAP Ext-Flowctl Client, Direct Advertising - Success - done L2CAP Ext-Flowctl Client SMP - Success - init Read Index List callback Status: 0x00 New hciemu instance created Index Added callback Index: 0x0000 Read Info callback Status: 0x00 Address: 00:AA:01:00:00:00 Version: 0x09 Manufacturer: 0x003f Supported settings: 0x0001be1b Current settings: 0x00000200 Class: 0x000000 Name: Short name: L2CAP Ext-Flowctl Client SMP - Success - setup Powering on controller Controller powered on Client set connectable status 0x00 L2CAP Ext-Flowctl Client SMP - Success - setup complete L2CAP Ext-Flowctl Client SMP - Success - run Connect in progress Successfully connected L2CAP Ext-Flowctl Client SMP - Success - test passed L2CAP Ext-Flowctl Client SMP - Success - teardown Index Removed callback Index: 0x0000 L2CAP Ext-Flowctl Client SMP - Success - teardown complete L2CAP Ext-Flowctl Client SMP - Success - done L2CAP Ext-Flowctl Client - Command Reject - init Read Index List callback Status: 0x00 New hciemu instance created Index Added callback Index: 0x0000 Read Info callback Status: 0x00 Address: 00:AA:01:00:00:00 Version: 0x09 Manufacturer: 0x003f Supported settings: 0x0001be1b Current settings: 0x00000200 Class: 0x000000 Name: Short name: L2CAP Ext-Flowctl Client - Command Reject - setup Powering on controller Controller powered on Client set connectable status 0x00 L2CAP Ext-Flowctl Client - Command Reject - setup complete L2CAP Ext-Flowctl Client - Command Reject - run Connect in progress New connection with handle 0x002a Connect failed: Connection refused (111) L2CAP Ext-Flowctl Client - Command Reject - test passed L2CAP Ext-Flowctl Client - Command Reject - teardown Index Removed callback Index: 0x0000 L2CAP Ext-Flowctl Client - Command Reject - teardown complete L2CAP Ext-Flowctl Client - Command Reject - done L2CAP Ext-Flowctl Client - Open two sockets - init Read Index List callback Status: 0x00 New hciemu instance created Index Added callback Index: 0x0000 Read Info callback Status: 0x00 Address: 00:AA:01:00:00:00 Version: 0x09 Manufacturer: 0x003f Supported settings: 0x0001be1b Current settings: 0x00000200 Class: 0x000000 Name: Short name: L2CAP Ext-Flowctl Client - Open two sockets - setup Powering on controller Controller powered on L2CAP Ext-Flowctl Client - Open two sockets - setup complete L2CAP Ext-Flowctl Client - Open two sockets - run Connect in progress, sk = 19 (deferred) HCI Command 0x200b length 7 HCI Command 0x200c length 2 Connect in progress, sk = 20 Client set connectable status 0x00 HCI Command 0x200c length 2 HCI Command 0x200d length 25 HCI Command 0x2016 length 2 Successfully connected Successfully connected L2CAP Ext-Flowctl Client - Open two sockets - test passed L2CAP Ext-Flowctl Client - Open two sockets - teardown Index Removed callback Index: 0x0000 L2CAP Ext-Flowctl Client - Open two sockets - teardown complete L2CAP Ext-Flowctl Client - Open two sockets - done L2CAP Ext-Flowctl Client - Open two sockets close one - init Read Index List callback Status: 0x00 New hciemu instance created Index Added callback Index: 0x0000 Read Info callback Status: 0x00 Address: 00:AA:01:00:00:00 Version: 0x09 Manufacturer: 0x003f Supported settings: 0x0001be1b Current settings: 0x00000200 Class: 0x000000 Name: Short name: L2CAP Ext-Flowctl Client - Open two sockets close one - setup Powering on controller Controller powered on L2CAP Ext-Flowctl Client - Open two sockets close one - setup complete L2CAP Ext-Flowctl Client - Open two sockets close one - run Connect in progress, sk = 19 (deferred) HCI Command 0x200b length 7 HCI Command 0x200c length 2 Connect in progress, sk = 20 Closing first socket! -1 Client set connectable status 0x00 HCI Command 0x200c length 2 HCI Command 0x200d length 25 HCI Command 0x2016 length 2 Successfully connected L2CAP Ext-Flowctl Client - Open two sockets close one - test passed L2CAP Ext-Flowctl Client - Open two sockets close one - teardown Index Removed callback Index: 0x0000 L2CAP Ext-Flowctl Client - Open two sockets close one - teardown complete L2CAP Ext-Flowctl Client - Open two sockets close one - done Test Summary ------------ L2CAP Ext-Flowctl Client - Success Passed 0.068 seconds L2CAP Ext-Flowctl Client, Direct Advertising - Success Passed 0.023 seconds L2CAP Ext-Flowctl Client SMP - Success Passed 0.027 seconds L2CAP Ext-Flowctl Client - Command Reject Passed 0.046 seconds L2CAP Ext-Flowctl Client - Open two sockets Passed 0.014 seconds L2CAP Ext-Flowctl Client - Open two sockets close one Passed 0.066 seconds Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.247 seconds Luiz Augusto von Dentz (3): Bluetooth: L2CAP: Add get_peer_pid callback Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections Bluetooth: Add BT_MODE socket option include/net/bluetooth/bluetooth.h | 11 +++ include/net/bluetooth/l2cap.h | 5 ++ net/bluetooth/l2cap_core.c | 136 +++++++++++++++++++++++++++--- net/bluetooth/l2cap_sock.c | 104 +++++++++++++++++++++++ 4 files changed, 246 insertions(+), 10 deletions(-) -- 2.21.1 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 1/3] Bluetooth: L2CAP: Add get_peer_pid callback 2020-03-23 20:34 [PATCH v5 0/3] Enable use of L2CAP_MODE_EXT_FLOWCTL Luiz Augusto von Dentz @ 2020-03-23 20:34 ` Luiz Augusto von Dentz 2020-03-24 8:48 ` Marcel Holtmann 2020-03-23 20:34 ` [PATCH v5 2/3] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections Luiz Augusto von Dentz 2020-03-23 20:34 ` [PATCH v5 3/3] Bluetooth: Add BT_MODE socket option Luiz Augusto von Dentz 2 siblings, 1 reply; 10+ messages in thread From: Luiz Augusto von Dentz @ 2020-03-23 20:34 UTC (permalink / raw) To: linux-bluetooth From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> This adds a callback to read the socket pid. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> --- include/net/bluetooth/l2cap.h | 1 + net/bluetooth/l2cap_sock.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 537aaead259f..2d7d28474d34 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -660,6 +660,7 @@ struct l2cap_ops { void (*suspend) (struct l2cap_chan *chan); void (*set_shutdown) (struct l2cap_chan *chan); long (*get_sndtimeo) (struct l2cap_chan *chan); + struct pid *(*get_peer_pid) (struct l2cap_chan *chan); struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, unsigned long hdr_len, unsigned long len, int nb); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 40fb10b591bd..117ba20ea194 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1504,6 +1504,13 @@ static long l2cap_sock_get_sndtimeo_cb(struct l2cap_chan *chan) return sk->sk_sndtimeo; } +static struct pid *l2cap_sock_get_peer_pid_cb(struct l2cap_chan *chan) +{ + struct sock *sk = chan->data; + + return sk->sk_peer_pid; +} + static void l2cap_sock_suspend_cb(struct l2cap_chan *chan) { struct sock *sk = chan->data; @@ -1525,6 +1532,7 @@ static const struct l2cap_ops l2cap_chan_ops = { .suspend = l2cap_sock_suspend_cb, .set_shutdown = l2cap_sock_set_shutdown_cb, .get_sndtimeo = l2cap_sock_get_sndtimeo_cb, + .get_peer_pid = l2cap_sock_get_peer_pid_cb, .alloc_skb = l2cap_sock_alloc_skb_cb, }; -- 2.21.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v5 1/3] Bluetooth: L2CAP: Add get_peer_pid callback 2020-03-23 20:34 ` [PATCH v5 1/3] Bluetooth: L2CAP: Add get_peer_pid callback Luiz Augusto von Dentz @ 2020-03-24 8:48 ` Marcel Holtmann 0 siblings, 0 replies; 10+ messages in thread From: Marcel Holtmann @ 2020-03-24 8:48 UTC (permalink / raw) To: Luiz Augusto von Dentz; +Cc: linux-bluetooth Hi Luiz, > This adds a callback to read the socket pid. > > Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> > --- > include/net/bluetooth/l2cap.h | 1 + > net/bluetooth/l2cap_sock.c | 8 ++++++++ > 2 files changed, 9 insertions(+) patch has been applied to bluetooth-next tree. Regards Marcel ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 2/3] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections 2020-03-23 20:34 [PATCH v5 0/3] Enable use of L2CAP_MODE_EXT_FLOWCTL Luiz Augusto von Dentz 2020-03-23 20:34 ` [PATCH v5 1/3] Bluetooth: L2CAP: Add get_peer_pid callback Luiz Augusto von Dentz @ 2020-03-23 20:34 ` Luiz Augusto von Dentz 2020-03-24 8:47 ` Marcel Holtmann 2020-03-23 20:34 ` [PATCH v5 3/3] Bluetooth: Add BT_MODE socket option Luiz Augusto von Dentz 2 siblings, 1 reply; 10+ messages in thread From: Luiz Augusto von Dentz @ 2020-03-23 20:34 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 | 136 +++++++++++++++++++++++++++++++--- 2 files changed, 130 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 5e6e35ab44dd..9f699d09d973 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); + + /* 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); - 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); + 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) @@ -7694,6 +7767,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) { @@ -7813,6 +7913,22 @@ 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 = 0; + + 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 - 1)) { + 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] 10+ messages in thread
* Re: [PATCH v5 2/3] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections 2020-03-23 20:34 ` [PATCH v5 2/3] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections Luiz Augusto von Dentz @ 2020-03-24 8:47 ` Marcel Holtmann 2020-03-24 23:10 ` Luiz Augusto von Dentz 0 siblings, 1 reply; 10+ messages in thread From: Marcel Holtmann @ 2020-03-24 8:47 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 | 136 +++++++++++++++++++++++++++++++--- > 2 files changed, 130 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 5e6e35ab44dd..9f699d09d973 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); > + > + /* 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); > > - 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); > + 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) > @@ -7694,6 +7767,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) > { > @@ -7813,6 +7913,22 @@ 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 = 0; > + > + l2cap_chan_list(conn, l2cap_chan_by_pid, &data); Put an empty line after this. It gives emphasis to the comment. > + /* Check if there isn't too many channels being connected */ > + if (!(data.count < L2CAP_ECRED_CONN_SCID_MAX - 1)) { If (data.count > L2CAP_ECRED_CONN_SCID_MIX) ??? > + hci_conn_drop(hcon); > + err = -EPROTO; > + goto done; > + } > + } > + > mutex_lock(&conn->chan_lock); > l2cap_chan_lock(chan); Regards Marcel ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v5 2/3] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections 2020-03-24 8:47 ` Marcel Holtmann @ 2020-03-24 23:10 ` Luiz Augusto von Dentz 0 siblings, 0 replies; 10+ messages in thread From: Luiz Augusto von Dentz @ 2020-03-24 23:10 UTC (permalink / raw) To: Marcel Holtmann; +Cc: linux-bluetooth Hi Marcel, On Tue, Mar 24, 2020 at 1:47 AM Marcel Holtmann <marcel@holtmann.org> wrote: > > 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 | 136 +++++++++++++++++++++++++++++++--- > > 2 files changed, 130 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 5e6e35ab44dd..9f699d09d973 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); > > + > > + /* 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); > > > > - 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); > > + 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) > > @@ -7694,6 +7767,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) > > { > > @@ -7813,6 +7913,22 @@ 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 = 0; > > + > > + l2cap_chan_list(conn, l2cap_chan_by_pid, &data); > > Put an empty line after this. It gives emphasis to the comment. > > > + /* Check if there isn't too many channels being connected */ > > + if (!(data.count < L2CAP_ECRED_CONN_SCID_MAX - 1)) { > > If (data.count > L2CAP_ECRED_CONN_SCID_MIX) ??? We need to take into account the chan itself is not part of the list yet, so that means data.count + 1 or we initialize the it as 1 a couple lines before, I will change the logic to use > operation. > > + hci_conn_drop(hcon); > > + err = -EPROTO; > > + goto done; > > + } > > + } > > + > > mutex_lock(&conn->chan_lock); > > l2cap_chan_lock(chan); > > Regards > > Marcel > -- Luiz Augusto von Dentz ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 3/3] Bluetooth: Add BT_MODE socket option 2020-03-23 20:34 [PATCH v5 0/3] Enable use of L2CAP_MODE_EXT_FLOWCTL Luiz Augusto von Dentz 2020-03-23 20:34 ` [PATCH v5 1/3] Bluetooth: L2CAP: Add get_peer_pid callback Luiz Augusto von Dentz 2020-03-23 20:34 ` [PATCH v5 2/3] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections Luiz Augusto von Dentz @ 2020-03-23 20:34 ` Luiz Augusto von Dentz 2020-03-24 8:44 ` Marcel Holtmann 2 siblings, 1 reply; 10+ messages in thread From: Luiz Augusto von Dentz @ 2020-03-23 20:34 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 ++ include/net/bluetooth/l2cap.h | 6 ++ net/bluetooth/l2cap_sock.c | 124 ++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+) 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/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index dada14d0622c..56f727ba23bd 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -720,9 +720,15 @@ struct l2cap_user { /* ----- L2CAP socket info ----- */ #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) +#define L2CAP_PI_OPTION_UNSET 0x00 +#define L2CAP_PI_OPTION_LEGACY 0x01 +#define L2CAP_PI_OPTION_BT_MODE 0x02 + struct l2cap_pinfo { struct bt_sock bt; struct l2cap_chan *chan; + u8 option; + u8 bt_mode; struct sk_buff *rx_busy_skb; }; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 117ba20ea194..0a57101fe273 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -424,6 +424,14 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, break; } + /* Check if BT_MODE was used which is not compatible with + * L2CAP_OPTIONS. + */ + if (l2cap_pi(sk)->option == L2CAP_PI_OPTION_BT_MODE) { + err = -EINVAL; + break; + } + memset(&opts, 0, sizeof(opts)); opts.imtu = chan->imtu; opts.omtu = chan->omtu; @@ -624,6 +632,29 @@ 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; + } + + /* Check if L2CAP_OPTIONS was used which is not compatible with + * BT_MODE. + */ + if (l2cap_pi(sk)->option == L2CAP_PI_OPTION_LEGACY) { + err = -EINVAL; + break; + } + + if (put_user(l2cap_pi(sk)->bt_mode, (u8 __user *) optval)) + err = -EFAULT; + break; + default: err = -ENOPROTOOPT; break; @@ -674,6 +705,14 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, break; } + /* Check if BT_MODE was used which is not compatible with + * L2CAP_OPTIONS. + */ + if (l2cap_pi(sk)->option == L2CAP_PI_OPTION_BT_MODE) { + err = -EINVAL; + break; + } + opts.imtu = chan->imtu; opts.omtu = chan->omtu; opts.flush_to = chan->flush_to; @@ -715,6 +754,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, break; } + l2cap_pi(sk)->option = L2CAP_PI_OPTION_LEGACY; + BT_DBG("mode 0x%2.2x", chan->mode); chan->imtu = opts.imtu; @@ -763,6 +804,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 +1048,50 @@ 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; + } + + /* Check if L2CAP_OPTIONS was used which is not compatible with + * BT_MODE. + */ + if (l2cap_pi(sk)->option == L2CAP_PI_OPTION_LEGACY) { + 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; + + l2cap_pi(sk)->option = L2CAP_PI_OPTION_BT_MODE; + l2cap_pi(sk)->bt_mode = opt; + + BT_DBG("mode 0x%2.2x", chan->mode); + + break; + default: err = -ENOPROTOOPT; break; -- 2.21.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v5 3/3] Bluetooth: Add BT_MODE socket option 2020-03-23 20:34 ` [PATCH v5 3/3] Bluetooth: Add BT_MODE socket option Luiz Augusto von Dentz @ 2020-03-24 8:44 ` Marcel Holtmann 2020-03-24 16:56 ` Luiz Augusto von Dentz 0 siblings, 1 reply; 10+ messages in thread From: Marcel Holtmann @ 2020-03-24 8:44 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 ++ > include/net/bluetooth/l2cap.h | 6 ++ > net/bluetooth/l2cap_sock.c | 124 ++++++++++++++++++++++++++++++ > 3 files changed, 138 insertions(+) > > 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/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h > index dada14d0622c..56f727ba23bd 100644 > --- a/include/net/bluetooth/l2cap.h > +++ b/include/net/bluetooth/l2cap.h > @@ -720,9 +720,15 @@ struct l2cap_user { > /* ----- L2CAP socket info ----- */ > #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) > > +#define L2CAP_PI_OPTION_UNSET 0x00 > +#define L2CAP_PI_OPTION_LEGACY 0x01 > +#define L2CAP_PI_OPTION_BT_MODE 0x02 > + > struct l2cap_pinfo { > struct bt_sock bt; > struct l2cap_chan *chan; > + u8 option; > + u8 bt_mode; > struct sk_buff *rx_busy_skb; > }; why do you want to store bt_mode here. Whatever we have in l2cap_chan should be plenty. I also looked at l2cap_sock_setsockopt_old and if you use L2CAP_OPTIONS and want to read BT_MODE, then everything should be fine. Same as setting BT_MODE (except EXT_FLOWCTL) and then reading L2CAP_OPTIONS is fine as well. We can all translate this properly and with have EINVAL return errors for not supported / disabled modes. So the only time L2CAP_OPTIONS read should fail is if you use BT_MODE with EXT_FLOWCTL as mode. So you can just check the mode set in l2cap_chan. And we start using our new mode definition there and then convert it for L2CAP_OPTIONS. Regards Marcel ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v5 3/3] Bluetooth: Add BT_MODE socket option 2020-03-24 8:44 ` Marcel Holtmann @ 2020-03-24 16:56 ` Luiz Augusto von Dentz 2020-03-24 18:37 ` Marcel Holtmann 0 siblings, 1 reply; 10+ messages in thread From: Luiz Augusto von Dentz @ 2020-03-24 16:56 UTC (permalink / raw) To: Marcel Holtmann; +Cc: linux-bluetooth Hi Marcel, On Tue, Mar 24, 2020 at 1:44 AM 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 ++ > > include/net/bluetooth/l2cap.h | 6 ++ > > net/bluetooth/l2cap_sock.c | 124 ++++++++++++++++++++++++++++++ > > 3 files changed, 138 insertions(+) > > > > 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/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h > > index dada14d0622c..56f727ba23bd 100644 > > --- a/include/net/bluetooth/l2cap.h > > +++ b/include/net/bluetooth/l2cap.h > > @@ -720,9 +720,15 @@ struct l2cap_user { > > /* ----- L2CAP socket info ----- */ > > #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) > > > > +#define L2CAP_PI_OPTION_UNSET 0x00 > > +#define L2CAP_PI_OPTION_LEGACY 0x01 > > +#define L2CAP_PI_OPTION_BT_MODE 0x02 > > + > > struct l2cap_pinfo { > > struct bt_sock bt; > > struct l2cap_chan *chan; > > + u8 option; > > + u8 bt_mode; > > struct sk_buff *rx_busy_skb; > > }; > > why do you want to store bt_mode here. Whatever we have in l2cap_chan should be plenty. Ive thought it would be cleaner to mess with types that comes from the spec itself so l2cap_chan would continue to use them. > I also looked at l2cap_sock_setsockopt_old and if you use L2CAP_OPTIONS and want to read BT_MODE, then everything should be fine. Same as setting BT_MODE (except EXT_FLOWCTL) and then reading L2CAP_OPTIONS is fine as well. We can all translate this properly and with have EINVAL return errors for not supported / disabled modes. > > So the only time L2CAP_OPTIONS read should fail is if you use BT_MODE with EXT_FLOWCTL as mode. So you can just check the mode set in l2cap_chan. And we start using our new mode definition there and then convert it for L2CAP_OPTIONS. Sure, I thought it would be more efficient to not have conversions back and forth but Im fine either way. > Regards > > Marcel > -- Luiz Augusto von Dentz ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v5 3/3] Bluetooth: Add BT_MODE socket option 2020-03-24 16:56 ` Luiz Augusto von Dentz @ 2020-03-24 18:37 ` Marcel Holtmann 0 siblings, 0 replies; 10+ messages in thread From: Marcel Holtmann @ 2020-03-24 18:37 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 ++ >>> include/net/bluetooth/l2cap.h | 6 ++ >>> net/bluetooth/l2cap_sock.c | 124 ++++++++++++++++++++++++++++++ >>> 3 files changed, 138 insertions(+) >>> >>> 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/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h >>> index dada14d0622c..56f727ba23bd 100644 >>> --- a/include/net/bluetooth/l2cap.h >>> +++ b/include/net/bluetooth/l2cap.h >>> @@ -720,9 +720,15 @@ struct l2cap_user { >>> /* ----- L2CAP socket info ----- */ >>> #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) >>> >>> +#define L2CAP_PI_OPTION_UNSET 0x00 >>> +#define L2CAP_PI_OPTION_LEGACY 0x01 >>> +#define L2CAP_PI_OPTION_BT_MODE 0x02 >>> + >>> struct l2cap_pinfo { >>> struct bt_sock bt; >>> struct l2cap_chan *chan; >>> + u8 option; >>> + u8 bt_mode; >>> struct sk_buff *rx_busy_skb; >>> }; >> >> why do you want to store bt_mode here. Whatever we have in l2cap_chan should be plenty. > > Ive thought it would be cleaner to mess with types that comes from the > spec itself so l2cap_chan would continue to use them. Actually the LE_FLOWCTL and EXT_FLOWCTL are not spec values either. Frankly I don’t care which ones we store right now. I am fine keeping the spec one for now and just translate it to BT_MODE. >> I also looked at l2cap_sock_setsockopt_old and if you use L2CAP_OPTIONS and want to read BT_MODE, then everything should be fine. Same as setting BT_MODE (except EXT_FLOWCTL) and then reading L2CAP_OPTIONS is fine as well. We can all translate this properly and with have EINVAL return errors for not supported / disabled modes. >> >> So the only time L2CAP_OPTIONS read should fail is if you use BT_MODE with EXT_FLOWCTL as mode. So you can just check the mode set in l2cap_chan. And we start using our new mode definition there and then convert it for L2CAP_OPTIONS. > > Sure, I thought it would be more efficient to not have conversions > back and forth but Im fine either way. In the end it makes the code simpler to just do the conversion. And once we add a kernel option to disable setsockopt_old, we have less code. Regards Marcel ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2020-03-24 23:10 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-03-23 20:34 [PATCH v5 0/3] Enable use of L2CAP_MODE_EXT_FLOWCTL Luiz Augusto von Dentz 2020-03-23 20:34 ` [PATCH v5 1/3] Bluetooth: L2CAP: Add get_peer_pid callback Luiz Augusto von Dentz 2020-03-24 8:48 ` Marcel Holtmann 2020-03-23 20:34 ` [PATCH v5 2/3] Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections Luiz Augusto von Dentz 2020-03-24 8:47 ` Marcel Holtmann 2020-03-24 23:10 ` Luiz Augusto von Dentz 2020-03-23 20:34 ` [PATCH v5 3/3] Bluetooth: Add BT_MODE socket option Luiz Augusto von Dentz 2020-03-24 8:44 ` Marcel Holtmann 2020-03-24 16:56 ` Luiz Augusto von Dentz 2020-03-24 18:37 ` 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.