All of lore.kernel.org
 help / color / mirror / Atom feed
* Determine ATT MTU size over DBUS
@ 2018-07-02 23:31 David Krauser
  2018-07-03 11:00 ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 8+ messages in thread
From: David Krauser @ 2018-07-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth

Hi,

I'm working on an application that uses the bluez D-Bus bindings to registe=
r a GATT service and characteristic, but I'm having two issues:

1. I can't figure out how to get the negotiated MTU size for reads/writes t=
o my characteristic.

I saw that the AcquireNotify and AcquireWrite calls provide an MTU in the o=
ptions dictionary, but there's no MTU provided for the WriteValue or ReadVa=
lue calls.

2. I can't figure out how to dynamically change the max MTU size to use wit=
h my service.

I saw that you could change the max MTU size by changing some #define's in =
the bluez source code, but I couldn't find a way to change it dynamically (=
like how you can change the ACL/SCO MTU sizes).

Is there something I'm missing? If not, would you all be open to a patch th=
at adds the negotiated MTU size to the options dictionary on calls to ReadV=
alue and WriteValue?

Or even better, I could add a new method to the GattCharacteristic1 interfa=
ce that is called during MTU negotiation. It would receive the requested MT=
U size as an input, and the developer could choose to use that size, or ret=
urn a different size to use.

Thanks,

- dk

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

* Re: Determine ATT MTU size over DBUS
  2018-07-02 23:31 Determine ATT MTU size over DBUS David Krauser
@ 2018-07-03 11:00 ` Luiz Augusto von Dentz
  2018-07-05 14:52   ` David Krauser
  0 siblings, 1 reply; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2018-07-03 11:00 UTC (permalink / raw)
  To: David Krauser; +Cc: linux-bluetooth

Hi David,

On Tue, Jul 3, 2018 at 2:31 AM, David Krauser <david@krauser.org> wrote:
> Hi,
>
> I'm working on an application that uses the bluez D-Bus bindings to register a GATT service and characteristic, but I'm having two issues:
>
> 1. I can't figure out how to get the negotiated MTU size for reads/writes to my characteristic.
>
> I saw that the AcquireNotify and AcquireWrite calls provide an MTU in the options dictionary, but there's no MTU provided for the WriteValue or ReadValue calls.

The MTU is negotiated automatically to the maximum value possible but
it doesn't really matter with WriteValue and ReadValue since they will
fragment and reassemble the data automatically, with Acquire* you will
get a file description which you can use to read or write.

> 2. I can't figure out how to dynamically change the max MTU size to use with my service.

You are not suppose to change the MTU more than once:

BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G
page 2248

'4.3.1 Exchange MTU
This sub-procedure is used by the client to set the ATT_MTU to the maximum
possible value that can be supported by both devices when the client supports
a value greater than the default ATT_MTU for the Attribute Protocol. This sub-
procedure shall only be initiated once during a connection.'

> I saw that you could change the max MTU size by changing some #define's in the bluez source code, but I couldn't find a way to change it dynamically (like how you can change the ACL/SCO MTU sizes).
>
> Is there something I'm missing? If not, would you all be open to a patch that adds the negotiated MTU size to the options dictionary on calls to ReadValue and WriteValue?

We could only negotiate it once, besides exposing this to applications
may impact other profiles, so the only option I see here is to have a
setting in the main.conf saying what is the preferred MTU for
GATT/ATT, provided your system only do have a single purpose for
Bluetooth you may change without affecting anything else. Anyway I
don't think this would have the result you expect since the default is
already the maximum allowed for an attribute, but perhaps we could
allow breaking the limit but the remote would have to agree on that
(see bellow).

> Or even better, I could add a new method to the GattCharacteristic1 interface that is called during MTU negotiation. It would receive the requested MTU size as an input, and the developer could choose to use that size, or return a different size to use.

We can do it only once and it is per connection not per
characteristic/attribute, also the MTU needs to be symmetric which
means the other side has to agree on the actual MTU to be used:

BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F
page 2185

'1. A device's Exchange MTU Request shall contain the same MTU as the
device's Exchange MTU Response (i.e. the MTU shall be symmetric).
2. If MTU is exchanged in one direction, that is sufficient for both directions.
3. It is permitted, (but not necessary - see 2.) to exchange MTU in both
directions, but the MTUs shall be the same in each direction (see 1.)'

All these limitations just means that GATT/ATT is not really meant to
be used as a serial/socket/pipe, and in fact that is why L2CAP CoC
exists so you could have your own dedicated socket with its own MTU
without messing around with GATT/ATT, L2CAP CoC should be supported by
most OSes nowadays.

> Thanks,
>
> - dk
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Luiz Augusto von Dentz

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

* Re: Determine ATT MTU size over DBUS
  2018-07-03 11:00 ` Luiz Augusto von Dentz
@ 2018-07-05 14:52   ` David Krauser
  2018-07-05 18:49     ` David Krauser
  0 siblings, 1 reply; 8+ messages in thread
From: David Krauser @ 2018-07-05 14:52 UTC (permalink / raw)
  To: linux-bluetooth

On July 3, 2018 7:00 AM, Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrot=
e:
> The MTU is negotiated automatically to the maximum value possible but
> it doesn't really matter with WriteValue and ReadValue since they will
> fragment and reassemble the data automatically, with Acquire* you will
> get a file description which you can use to read or write.

The characteristic that I've implemented pulls data from a buffer that is l=
arger than the max value length, so I use the MTU size to determine how man=
y bytes have been read. L2CAP CoC would probably be a better way to do this=
, but I'm working with platforms that don't support it, unfortunately :-(

> may impact other profiles, so the only option I see here is to have a
> setting in the main.conf saying what is the preferred MTU for
> GATT/ATT [...]

I like this idea. I've attached a patch below that implements this.

Thanks for the suggestions - really helpful.

- dk

diff --git a/src/device.c b/src/device.c
index 4f1af7012..75340cabe 100644
--- a/src/device.c
+++ b/src/device.c
@@ -4986,7 +4986,7 @@ bool device_attach_att(struct btd_device *dev, GIOCha=
nnel *io)
 =09=09}
 =09}
=20
-=09dev->att_mtu =3D MIN(mtu, BT_ATT_MAX_LE_MTU);
+=09dev->att_mtu =3D MIN(mtu, main_opts.gatt_max_le_mtu);
 =09attrib =3D g_attrib_new(io,
 =09=09=09cid =3D=3D ATT_CID ? BT_ATT_DEFAULT_LE_MTU : dev->att_mtu,
 =09=09=09false);
diff --git a/src/hcid.h b/src/hcid.h
index 2c2b89d9c..bcb077dde 100644
--- a/src/hcid.h
+++ b/src/hcid.h
@@ -54,6 +54,7 @@ struct main_opts {
=20
 =09bt_mode_t=09mode;
 =09bt_gatt_cache_t gatt_cache;
+=09uint16_t=09gatt_max_le_mtu;
=20
 =09uint8_t=09=09min_enc_key_size;
 };
diff --git a/src/main.c b/src/main.c
index 7e6af42cd..8ddd4875f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -50,6 +50,7 @@
 #include "log.h"
 #include "backtrace.h"
=20
+#include "shared/att-types.h"
 #include "lib/uuid.h"
 #include "hcid.h"
 #include "sdpd.h"
@@ -104,6 +105,7 @@ static const char *policy_options[] =3D {
 static const char *gatt_options[] =3D {
 =09"Cache",
 =09"MinEncKeySize",
+ =09"MaxLeMtu",
 =09NULL
 };
=20
@@ -419,6 +421,18 @@ static void parse_config(GKeyFile *config)
 =09=09if (val >=3D7 && val <=3D 16)
 =09=09=09main_opts.min_enc_key_size =3D val;
 =09}
+
+=09val =3D g_key_file_get_integer(config, "GATT",
+=09=09=09=09=09=09"MaxLeMtu", &err);
+=09if (err) {
+=09=09g_clear_error(&err);
+=09} else {
+=09=09/* Ensure the mtu is within a valid range. */
+=09=09val =3D MIN(val, BT_ATT_MAX_LE_MTU);
+=09=09val =3D MAX(val, BT_ATT_DEFAULT_LE_MTU);
+=09=09DBG("gatt_max_le_mtu=3D%d", val);
+=09=09main_opts.gatt_max_le_mtu =3D val;
+=09}
 }
=20
 static void init_defaults(void)
@@ -442,6 +456,8 @@ static void init_defaults(void)
 =09main_opts.did_vendor =3D 0x1d6b;=09=09/* Linux Foundation */
 =09main_opts.did_product =3D 0x0246;=09=09/* BlueZ */
 =09main_opts.did_version =3D (major << 8 | minor);
+
+=09main_opts.gatt_max_le_mtu =3D BT_ATT_MAX_LE_MTU;
 }
=20
 static void log_handler(const gchar *log_domain, GLogLevelFlags log_level,
diff --git a/src/main.conf b/src/main.conf
index cbae32ec5..a22d685b2 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -82,6 +82,11 @@
 # Defaults to 0
 # MinEncKeySize =3D 0
=20
+# Maximum MTU size.
+# Possible values: 23-517
+# Defaults to 517
+# MaxLeMtu =3D 517
+
 [Policy]
 #
 # The ReconnectUUIDs defines the set of remote services that should try

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

* Re: Determine ATT MTU size over DBUS
  2018-07-05 14:52   ` David Krauser
@ 2018-07-05 18:49     ` David Krauser
  2018-07-05 20:49       ` David Krauser
  2018-07-06 10:25       ` Marcel Holtmann
  0 siblings, 2 replies; 8+ messages in thread
From: David Krauser @ 2018-07-05 18:49 UTC (permalink / raw)
  To: linux-bluetooth

And here's a patch that lets the user know the MTU size over DBus:

diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
index 2a8da75b0..a0db65383 100644
--- a/doc/gatt-api.txt
+++ b/doc/gatt-api.txt
@@ -68,6 +68,7 @@ Methods=09=09array{byte} ReadValue(dict options)
 =09=09=09operation was successful.
=20
 =09=09=09Possible options: "offset": uint16 offset
+=09=09=09=09=09  "MTU": Exchanged MTU (Server only)
 =09=09=09=09=09  "device": Object Device (Server only)
=20
 =09=09=09Possible Errors: org.bluez.Error.Failed
@@ -83,6 +84,7 @@ Methods=09=09array{byte} ReadValue(dict options)
 =09=09=09characteristic.
=20
 =09=09=09Possible options: "offset": Start offset
+=09=09=09=09=09  "MTU": Exchanged MTU (Server only)
 =09=09=09=09=09  "device": Device path (Server only)
 =09=09=09=09=09  "link": Link type (Server only)
 =09=09=09=09=09  "prepare-authorize": boolean Is prepare
diff --git a/src/gatt-database.c b/src/gatt-database.c
index 99c8ea231..c34da2d71 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -1932,7 +1932,9 @@ static void append_options(DBusMessageIter *iter, voi=
d *user_data)
 {
 =09struct pending_op *op =3D user_data;
 =09const char *path =3D device_get_path(op->device);
+=09struct bt_gatt_server *server;
 =09const char *link;
+=09uint16_t mtu;
=20
 =09switch (op->link_type) {
 =09case BT_ATT_LINK_BREDR:
@@ -1955,6 +1957,11 @@ static void append_options(DBusMessageIter *iter, vo=
id *user_data)
 =09if (op->prep_authorize)
 =09=09dict_append_entry(iter, "prepare-authorize", DBUS_TYPE_BOOLEAN,
 =09=09=09=09=09=09=09&op->prep_authorize);
+
+=09server =3D btd_device_get_gatt_server(op->device);
+=09mtu =3D bt_gatt_server_get_mtu(server);
+
+=09dict_append_entry(iter, "MTU", DBUS_TYPE_UINT16, &mtu);
 }
=20
 static void read_setup_cb(DBusMessageIter *iter, void *user_data)
@@ -2234,8 +2241,6 @@ static void acquire_write_setup(DBusMessageIter *iter=
, void *user_data)
 {
 =09struct pending_op *op =3D user_data;
 =09DBusMessageIter dict;
-=09struct bt_gatt_server *server;
-=09uint16_t mtu;
=20
 =09dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
 =09=09=09=09=09DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
@@ -2246,12 +2251,6 @@ static void acquire_write_setup(DBusMessageIter *ite=
r, void *user_data)
=20
 =09append_options(&dict, op);
=20
-=09server =3D btd_device_get_gatt_server(op->device);
-
-=09mtu =3D bt_gatt_server_get_mtu(server);
-
-=09dict_append_entry(&dict, "MTU", DBUS_TYPE_UINT16, &mtu);
-
 =09dbus_message_iter_close_container(iter, &dict);
 }
=20
@@ -2320,8 +2319,6 @@ static void acquire_notify_setup(DBusMessageIter *ite=
r, void *user_data)
 {
 =09DBusMessageIter dict;
 =09struct pending_op *op =3D user_data;
-=09struct bt_gatt_server *server;
-=09uint16_t mtu;
=20
 =09dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
 =09=09=09=09=09DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
@@ -2332,12 +2329,6 @@ static void acquire_notify_setup(DBusMessageIter *it=
er, void *user_data)
=20
 =09append_options(&dict, op);
=20
-=09server =3D btd_device_get_gatt_server(op->device);
-
-=09mtu =3D bt_gatt_server_get_mtu(server);
-
-=09dict_append_entry(&dict, "MTU", DBUS_TYPE_UINT16, &mtu);
-
 =09dbus_message_iter_close_container(iter, &dict);
 }




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

* Re: Determine ATT MTU size over DBUS
  2018-07-05 18:49     ` David Krauser
@ 2018-07-05 20:49       ` David Krauser
  2018-07-06 10:25       ` Marcel Holtmann
  1 sibling, 0 replies; 8+ messages in thread
From: David Krauser @ 2018-07-05 20:49 UTC (permalink / raw)
  To: linux-bluetooth

Sorry all, just realized that I didn't submit these patches in the proper f=
ashion outlined in HACKING. Please forgive my mistake and disregard my prev=
ious two emails.

I will submit them properly shortly.

Thanks,=20

- dk

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

* Re: Determine ATT MTU size over DBUS
  2018-07-05 18:49     ` David Krauser
  2018-07-05 20:49       ` David Krauser
@ 2018-07-06 10:25       ` Marcel Holtmann
  2018-07-06 13:34         ` David Krauser
  1 sibling, 1 reply; 8+ messages in thread
From: Marcel Holtmann @ 2018-07-06 10:25 UTC (permalink / raw)
  To: David Krauser; +Cc: linux-bluetooth

Hi David,

> And here's a patch that lets the user know the MTU size over DBus:
> 
> diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
> index 2a8da75b0..a0db65383 100644
> --- a/doc/gatt-api.txt
> +++ b/doc/gatt-api.txt
> @@ -68,6 +68,7 @@ Methods		array{byte} ReadValue(dict options)
> 			operation was successful.
> 
> 			Possible options: "offset": uint16 offset
> +					  "MTU": Exchanged MTU (Server only)
> 					  "device": Object Device (Server only)
> 
> 			Possible Errors: org.bluez.Error.Failed
> @@ -83,6 +84,7 @@ Methods		array{byte} ReadValue(dict options)
> 			characteristic.
> 
> 			Possible options: "offset": Start offset
> +					  "MTU": Exchanged MTU (Server only)

I prefer "mtu" as option name here. We kept them all lowercase. Other option is to use "max-transfer-unit".

Regards

Marcel


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

* Re: Determine ATT MTU size over DBUS
  2018-07-06 10:25       ` Marcel Holtmann
@ 2018-07-06 13:34         ` David Krauser
  2018-07-06 17:14           ` Marcel Holtmann
  0 siblings, 1 reply; 8+ messages in thread
From: David Krauser @ 2018-07-06 13:34 UTC (permalink / raw)
  To: linux-bluetooth

Hi Marcel,

On July 6, 2018 6:25 AM, Marcel Holtmann <marcel@holtmann.org> wrote:
> I prefer "mtu" as option name here. We kept them all lowercase. Other opt=
ion is to use "max-transfer-unit".

I agree; however, the AcquireWrite and AcquireNotify already provide "MTU" =
as an option, and I figured it'd be better to be consistent with those. I c=
ould change those to be lowercase, but don't want to break existing users.

- dk

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

* Re: Determine ATT MTU size over DBUS
  2018-07-06 13:34         ` David Krauser
@ 2018-07-06 17:14           ` Marcel Holtmann
  0 siblings, 0 replies; 8+ messages in thread
From: Marcel Holtmann @ 2018-07-06 17:14 UTC (permalink / raw)
  To: David Krauser; +Cc: linux-bluetooth

Hi David,

>> I prefer "mtu" as option name here. We kept them all lowercase. Other option is to use "max-transfer-unit".
> 
> I agree; however, the AcquireWrite and AcquireNotify already provide "MTU" as an option, and I figured it'd be better to be consistent with those. I could change those to be lowercase, but don't want to break existing users.

I prefer to fix it there as well then. We can deprecate that option.

Regards

Marcel


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

end of thread, other threads:[~2018-07-06 17:14 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-02 23:31 Determine ATT MTU size over DBUS David Krauser
2018-07-03 11:00 ` Luiz Augusto von Dentz
2018-07-05 14:52   ` David Krauser
2018-07-05 18:49     ` David Krauser
2018-07-05 20:49       ` David Krauser
2018-07-06 10:25       ` Marcel Holtmann
2018-07-06 13:34         ` David Krauser
2018-07-06 17:14           ` 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.