2020-02-29 10:11:22

by Emil Lenngren

[permalink] [raw]
Subject: Get negotiated ATT MTU?

Hi. I have a feature request that the negotiated ATT MTU should be
exposed as a property in the org.bluez.Device1 interface.

For some applications it's good to know or required how much data that
can be written / read / notified in each packet, and it's not always
desired or possible to use AcquireNotify / AcquireWrite.

/Emil


2020-03-01 06:48:40

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: Get negotiated ATT MTU?

Hi Emil,

On Sat, Feb 29, 2020 at 2:13 AM Emil Lenngren <[email protected]> wrote:
>
> Hi. I have a feature request that the negotiated ATT MTU should be
> exposed as a property in the org.bluez.Device1 interface.
>
> For some applications it's good to know or required how much data that
> can be written / read / notified in each packet, and it's not always
> desired or possible to use AcquireNotify / AcquireWrite.

We already negotiate a fairly big MTU maximum by default, and you can
just use AcquireWrite/AcquireNotify just to discover it and the close
the fd immediately, so I suppose we cover much of what the feature is,
except perhaps if the application requires something bellow the
default MTU bluetoothd but that can be a problem if other application
would start requiring their own MTU as well, so even if we introduce a
Property that would have to be read-only but there may be races if the
application start writing/reading too fast or the remote end do
trigger its own exchange for some reason.

--
Luiz Augusto von Dentz

2020-03-01 19:16:32

by Emil Lenngren

[permalink] [raw]
Subject: Re: Get negotiated ATT MTU?

Hi Luiz,

Den sön 1 mars 2020 kl 07:46 skrev Luiz Augusto von Dentz
<[email protected]>:
>
> Hi Emil,
>
> On Sat, Feb 29, 2020 at 2:13 AM Emil Lenngren <[email protected]> wrote:
> >
> > Hi. I have a feature request that the negotiated ATT MTU should be
> > exposed as a property in the org.bluez.Device1 interface.
> >
> > For some applications it's good to know or required how much data that
> > can be written / read / notified in each packet, and it's not always
> > desired or possible to use AcquireNotify / AcquireWrite.
>
> We already negotiate a fairly big MTU maximum by default, and you can
> just use AcquireWrite/AcquireNotify just to discover it and the close
> the fd immediately, so I suppose we cover much of what the feature is,

I was considering having a solution implementable by for example
Web-Bluetooth. This "workaround" wouldn't always work since it's not
guaranteed to exist a characteristic with the 'write-without-response'
or 'notify' property. I think there could also be a "race condition"
here if two apps do the same thing (although the time window is pretty
small): one app might get that the acquire operation returned "busy".
And is it even possible to use AcquireNotify/AcquiceWrite if the d-bus
runs over tcp or the programming language doesn't support d-bus file
descriptors? An ATT MTU property would be so much simpler and
straight-forward.

> except perhaps if the application requires something bellow the
> default MTU bluetoothd but that can be a problem if other application
> would start requiring their own MTU as well, so even if we introduce a
> Property that would have to be read-only

Yes! The idea was to have it read-only. It's sane to let the BT stack
negotiate (a big value on non-embedded systems like Linux/BlueZ)
immediately after the connection has been established. There should be
no reason for an application using BlueZ to negotiate a smaller MTU
than a "big" one, which BlueZ already selects.

> but there may be races if the
> application start writing/reading too fast or the remote end do
> trigger its own exchange for some reason.

It's already not possible to write anything after "Connected" has
become true but before "ServicesResolved" becomes true (I get
"org.bluez.Error.Failed: Not connected" in that case). I assume MTU is
guaranteed to have been exchanged at this point, so there shouldn't be
any problem for this case. Another possibility would also be to add a
boolean "ATT MTU exchanged" property which is set to true when the MTU
property becomes valid, if waiting for "ServicesResolved" wouldn't be
enough.

It should be fine also if the remote end sends an Exchange MTU request
at the beginning of the connection since we can then immediately send
a response and assign the MTU property without waiting for the
Exchange MTU response (that corresponds to our request).

In the case when the remote end sends a notification before it
receives our Exchange MTU request, then the MTU property would
correctly be 23 since the MTU Exchange hasn't finished yet.

The list of five rules in Bluetooth Core specification Vol 3 Part F
3.4.2.2 (ATT_EXCHANGE_MTU_RSP) should also prevent most "race
conditions".

Let me know if you think I've missed some edge case...

/Emil

2020-03-04 10:55:30

by Jamie Mccrae

[permalink] [raw]
Subject: RE: Get negotiated ATT MTU?

Hi,
> It should be fine also if the remote end sends an Exchange MTU request
> at the beginning of the connection since we can then immediately send
> a response and assign the MTU property without waiting for the
> Exchange MTU response (that corresponds to our request).
>
> Let me know if you think I've missed some edge case...

In the core specification 5.2 volume 3 part A, there is a command, L2CAP_CREDIT_BASED_RECONFIGURE_REQ, which allows for the MTU to be changed after it has been established. This requires an enhanced ATT service however, but it means that the initial MTU is subject to change.
Thanks,
Jamie


THIS MESSAGE, ANY ATTACHMENT(S), AND THE INFORMATION CONTAINED HEREIN MAY BE PROPRIETARY TO LAIRD CONNECTIVITY, INC. AND/OR ANOTHER PARTY, AND MAY FURTHER BE INTENDED TO BE KEPT CONFIDENTIAL. IF YOU ARE NOT THE INTENDED RECIPIENT, PLEASE DELETE THE EMAIL AND ANY ATTACHMENTS, AND IMMEDIATELY NOTIFY THE SENDER BY RETURN EMAIL. THIS MESSAGE AND ITS CONTENTS ARE THE PROPERTY OF LAIRD CONNECTIVITY, INC. AND MAY NOT BE REPRODUCED OR USED WITHOUT THE EXPRESS WRITTEN CONSENT OF LAIRD CONNECTIVITY, INC.

2020-03-04 15:57:13

by Emil Lenngren

[permalink] [raw]
Subject: Re: Get negotiated ATT MTU?

Hi,

Den ons 4 mars 2020 kl 11:55 skrev Jamie Mccrae <[email protected]>:
>
> Hi,
> > It should be fine also if the remote end sends an Exchange MTU request
> > at the beginning of the connection since we can then immediately send
> > a response and assign the MTU property without waiting for the
> > Exchange MTU response (that corresponds to our request).
> >
> > Let me know if you think I've missed some edge case...
>
> In the core specification 5.2 volume 3 part A, there is a command, L2CAP_CREDIT_BASED_RECONFIGURE_REQ, which allows for the MTU to be changed after it has been established. This requires an enhanced ATT service however, but it means that the initial MTU is subject to change.

I just read the L2CAP/ATT/GATT parts in the new spec. Is EATT
implemented yet for the dbus-api, and will it affect the API? Anyway,
for EATT it's a requirement that the MTU can only increase, never
decrease, which shouldn't cause issues for apps. But change my "ATT
MTU exchanged" property name proposal to "Initial ATT MTU exchanged"
then, if waiting for the ServicesResolved wouldn't be enough, and set
it true immediately if EATT is used and after an Exchange MTU
procedure for unenhanced ATT. Then update the ATT MTU property when
the MTU is increased.

/Emil

2020-03-04 18:37:07

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: Get negotiated ATT MTU?

Hi Emil,

On Wed, Mar 4, 2020 at 7:56 AM Emil Lenngren <[email protected]> wrote:
>
> Hi,
>
> Den ons 4 mars 2020 kl 11:55 skrev Jamie Mccrae <[email protected]>:
> >
> > Hi,
> > > It should be fine also if the remote end sends an Exchange MTU request
> > > at the beginning of the connection since we can then immediately send
> > > a response and assign the MTU property without waiting for the
> > > Exchange MTU response (that corresponds to our request).
> > >
> > > Let me know if you think I've missed some edge case...
> >
> > In the core specification 5.2 volume 3 part A, there is a command, L2CAP_CREDIT_BASED_RECONFIGURE_REQ, which allows for the MTU to be changed after it has been established. This requires an enhanced ATT service however, but it means that the initial MTU is subject to change.
>
> I just read the L2CAP/ATT/GATT parts in the new spec. Is EATT
> implemented yet for the dbus-api, and will it affect the API? Anyway,
> for EATT it's a requirement that the MTU can only increase, never
> decrease, which shouldn't cause issues for apps. But change my "ATT
> MTU exchanged" property name proposal to "Initial ATT MTU exchanged"
> then, if waiting for the ServicesResolved wouldn't be enough, and set
> it true immediately if EATT is used and after an Exchange MTU
> procedure for unenhanced ATT. Then update the ATT MTU property when
> the MTU is increased.

It completely transparent to D-Bus, so if we do expose the MTU it
should probably be reporting the biggest MTU of all connected channel,
while it is possible to reconfigre the MTU with
L2CAP_CREDIT_BASED_RECONFIGURE_REQ I doubt we would be exposing this
sort of operation to applications, we have to keep in mind multiple
application can request a change for their own needs so like Exchange
MTU bluetoothd will be taking care of setting the MTU, that said with
EATT incoming and outgoing MTUs don't need to be symmetric like the
unenhanced bearer.

--
Luiz Augusto von Dentz

2020-03-04 18:48:17

by Emil Lenngren

[permalink] [raw]
Subject: Re: Get negotiated ATT MTU?

Hi,

Den ons 4 mars 2020 kl 18:36 skrev Luiz Augusto von Dentz
<[email protected]>:
>
> Hi Emil,
>
> On Wed, Mar 4, 2020 at 7:56 AM Emil Lenngren <[email protected]> wrote:
> >
> > Hi,
> >
> > Den ons 4 mars 2020 kl 11:55 skrev Jamie Mccrae <[email protected]>:
> > >
> > > Hi,
> > > > It should be fine also if the remote end sends an Exchange MTU request
> > > > at the beginning of the connection since we can then immediately send
> > > > a response and assign the MTU property without waiting for the
> > > > Exchange MTU response (that corresponds to our request).
> > > >
> > > > Let me know if you think I've missed some edge case...
> > >
> > > In the core specification 5.2 volume 3 part A, there is a command, L2CAP_CREDIT_BASED_RECONFIGURE_REQ, which allows for the MTU to be changed after it has been established. This requires an enhanced ATT service however, but it means that the initial MTU is subject to change.
> >
> > I just read the L2CAP/ATT/GATT parts in the new spec. Is EATT
> > implemented yet for the dbus-api, and will it affect the API? Anyway,
> > for EATT it's a requirement that the MTU can only increase, never
> > decrease, which shouldn't cause issues for apps. But change my "ATT
> > MTU exchanged" property name proposal to "Initial ATT MTU exchanged"
> > then, if waiting for the ServicesResolved wouldn't be enough, and set
> > it true immediately if EATT is used and after an Exchange MTU
> > procedure for unenhanced ATT. Then update the ATT MTU property when
> > the MTU is increased.
>
> It completely transparent to D-Bus, so if we do expose the MTU it
> should probably be reporting the biggest MTU of all connected channel,

Is there ever any reason for one application to have more than one ATT
bearer? I thought the idea of EATT was to allow one ATT bearer per
application.

> while it is possible to reconfigre the MTU with
> L2CAP_CREDIT_BASED_RECONFIGURE_REQ I doubt we would be exposing this
> sort of operation to applications, we have to keep in mind multiple
> application can request a change for their own needs so like Exchange
> MTU bluetoothd will be taking care of setting the MTU,

I think it's fine that bluetoothd chooses the MTU. I don't see any
reason that the application should choose MTU (assuming bluetoothd
sets a big value).

> that said with
> EATT incoming and outgoing MTUs don't need to be symmetric like the
> unenhanced bearer.

While that is true on the L2CAP layer, it's not true on the GATT layer:

Vol 3 Part G section 5.3.1:
"The ATT_MTU for the Enhanced ATT bearer shall be set to the minimum of the
MTU field values of the two devices; these values come from the L2CAP_-
CREDIT_BASED_CONNECTION_REQ and L2CAP_CREDIT_BASED_-
CONNECTION_RSP signaling packets or the latest L2CAP_CREDIT_-
BASED_RECONFIGURE_REQ packets."

So if the peripheral sets its receive MTU to 48 and the central sets
its receive MTU to 517, then 48 will be used in both directions.

/Emil

2020-03-04 18:50:28

by Emil Lenngren

[permalink] [raw]
Subject: Re: Get negotiated ATT MTU?

Den ons 4 mars 2020 kl 18:47 skrev Emil Lenngren <[email protected]>:

> So if the peripheral sets its receive MTU to 48 and the central sets
> its receive MTU to 517, then 48 will be used in both directions.

Or 64 here, since 64 apparently is the minimum allowed.

2020-03-04 20:44:30

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: Get negotiated ATT MTU?

Hi Emil,

On Wed, Mar 4, 2020 at 10:47 AM Emil Lenngren <[email protected]> wrote:
>
> Hi,
>
> Den ons 4 mars 2020 kl 18:36 skrev Luiz Augusto von Dentz
> <[email protected]>:
> >
> > Hi Emil,
> >
> > On Wed, Mar 4, 2020 at 7:56 AM Emil Lenngren <[email protected]> wrote:
> > >
> > > Hi,
> > >
> > > Den ons 4 mars 2020 kl 11:55 skrev Jamie Mccrae <[email protected]>:
> > > >
> > > > Hi,
> > > > > It should be fine also if the remote end sends an Exchange MTU request
> > > > > at the beginning of the connection since we can then immediately send
> > > > > a response and assign the MTU property without waiting for the
> > > > > Exchange MTU response (that corresponds to our request).
> > > > >
> > > > > Let me know if you think I've missed some edge case...
> > > >
> > > > In the core specification 5.2 volume 3 part A, there is a command, L2CAP_CREDIT_BASED_RECONFIGURE_REQ, which allows for the MTU to be changed after it has been established. This requires an enhanced ATT service however, but it means that the initial MTU is subject to change.
> > >
> > > I just read the L2CAP/ATT/GATT parts in the new spec. Is EATT
> > > implemented yet for the dbus-api, and will it affect the API? Anyway,
> > > for EATT it's a requirement that the MTU can only increase, never
> > > decrease, which shouldn't cause issues for apps. But change my "ATT
> > > MTU exchanged" property name proposal to "Initial ATT MTU exchanged"
> > > then, if waiting for the ServicesResolved wouldn't be enough, and set
> > > it true immediately if EATT is used and after an Exchange MTU
> > > procedure for unenhanced ATT. Then update the ATT MTU property when
> > > the MTU is increased.
> >
> > It completely transparent to D-Bus, so if we do expose the MTU it
> > should probably be reporting the biggest MTU of all connected channel,
>
> Is there ever any reason for one application to have more than one ATT
> bearer? I thought the idea of EATT was to allow one ATT bearer per
> application.

EATT is meant to allow multiple outstanding requests, it probably
would not escale if we would add an API to have a bearer per
application so we just use the extra bearers as a pool.

> > while it is possible to reconfigre the MTU with
> > L2CAP_CREDIT_BASED_RECONFIGURE_REQ I doubt we would be exposing this
> > sort of operation to applications, we have to keep in mind multiple
> > application can request a change for their own needs so like Exchange
> > MTU bluetoothd will be taking care of setting the MTU,
>
> I think it's fine that bluetoothd chooses the MTU. I don't see any
> reason that the application should choose MTU (assuming bluetoothd
> sets a big value).
>
> > that said with
> > EATT incoming and outgoing MTUs don't need to be symmetric like the
> > unenhanced bearer.
>
> While that is true on the L2CAP layer, it's not true on the GATT layer:
>
> Vol 3 Part G section 5.3.1:
> "The ATT_MTU for the Enhanced ATT bearer shall be set to the minimum of the
> MTU field values of the two devices; these values come from the L2CAP_-
> CREDIT_BASED_CONNECTION_REQ and L2CAP_CREDIT_BASED_-
> CONNECTION_RSP signaling packets or the latest L2CAP_CREDIT_-
> BASED_RECONFIGURE_REQ packets."
>
> So if the peripheral sets its receive MTU to 48 and the central sets
> its receive MTU to 517, then 48 will be used in both directions.

This is kind of an artificial limitation that the author decided to
impose on the bearer, but if it was adopted like that so be it.


--
Luiz Augusto von Dentz

2020-03-04 22:41:34

by Emil Lenngren

[permalink] [raw]
Subject: Re: Get negotiated ATT MTU?

Hi Luiz,

Den ons 4 mars 2020 kl 20:44 skrev Luiz Augusto von Dentz
<[email protected]>:
> > > It completely transparent to D-Bus, so if we do expose the MTU it
> > > should probably be reporting the biggest MTU of all connected channel,
> >
> > Is there ever any reason for one application to have more than one ATT
> > bearer? I thought the idea of EATT was to allow one ATT bearer per
> > application.
>
> EATT is meant to allow multiple outstanding requests, it probably
> would not escale if we would add an API to have a bearer per
> application so we just use the extra bearers as a pool.

I just read the 5.2 overview and 5.2 specification again and I see now
that the overview suggests that a pool of bearers should be used, as
you mentioned. So yes in that case the maximum ATT_MTU of the bearers
seems reasonable to report (if they for some reason would differ). But
by having a pool like this, I hope implementations will make sure that
multiple Write Without Response values or notifications from the same
application are sent on a single bearer, to avoid reorderings.

/Emil

2020-03-04 23:02:52

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: Get negotiated ATT MTU?

Hi Emil,

On Wed, Mar 4, 2020 at 2:41 PM Emil Lenngren <[email protected]> wrote:
>
> Hi Luiz,
>
> Den ons 4 mars 2020 kl 20:44 skrev Luiz Augusto von Dentz
> <[email protected]>:
> > > > It completely transparent to D-Bus, so if we do expose the MTU it
> > > > should probably be reporting the biggest MTU of all connected channel,
> > >
> > > Is there ever any reason for one application to have more than one ATT
> > > bearer? I thought the idea of EATT was to allow one ATT bearer per
> > > application.
> >
> > EATT is meant to allow multiple outstanding requests, it probably
> > would not escale if we would add an API to have a bearer per
> > application so we just use the extra bearers as a pool.
>
> I just read the 5.2 overview and 5.2 specification again and I see now
> that the overview suggests that a pool of bearers should be used, as
> you mentioned. So yes in that case the maximum ATT_MTU of the bearers
> seems reasonable to report (if they for some reason would differ). But
> by having a pool like this, I hope implementations will make sure that
> multiple Write Without Response values or notifications from the same
> application are sent on a single bearer, to avoid reorderings.

Commands don't need a response so in theory one should just use the
unenhanced bearer or the first one EATT bearer regardless, in the
current implementation I just pick the first bearer that allow sending
all the data in one shot given that the MTU can be different.

--
Luiz Augusto von Dentz