Hi,
This patch contains revision 2 of initial documentation describing proposed
BT Mesh user space/kernel interface.
The idea behind this interface is to divide mesh functionality between
user space and kernel in order to utilize kernel's finer timing mechanisms
and provide efficient filtering of mesh-specific packets.
Feedback is appreciated.
Inga Stotland (1):
Add initial doc describing Bluetooth Mesh API
doc/mesh-api.txt | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 269 insertions(+)
create mode 100644 doc/mesh-api.txt
--
2.13.6
Hi Brian,
>>>> ---
>>> Mesh Command
>>> ============
>>>
>>> Command Code: 0x0043
>>> Controller Index: <controller index>
>>> Command Parameters: Opcode (1 Octet)
>>> Command parameters (Variable)
>>> Return Parameters: Status (1 Octet)
>>> Opcode (1 Octet)
>>> Return parameters (Variable)
>>>
>>> Mesh Event
>>> ==========
>>>
>>> Event Code: 0x0026
>>> Controller Index: <controller index>
>>> Event Parameters: Subevent (1 Octet)
>>> Even parameters (variable)
>>>
>>> This would map 1:1 to the HCI mesh commands and events with the tiny
>>> modification that the event prefix is stripped from the Mesh Event
>>> and not provided and with the Mesh Get Options command issued it
>>> would be mapped to event prefix length of zero.
>>>
>>> And then only a settings 16 Mesh would be needed. Or we make the
>>> command and event only available when HCI mesh commands are actually
>>> supported. That is something that would needs to be discussing. In
>>> general, we have not had limited commands based on hardware
>>> functionality, but these two would be special since they are vendor
>>> specific commands in the first place.
>>>
>>> For the kernel side we only have the the driver provide the mesh HCI
>>> opcode and run Mesh Get Options once to retrieve the firmwares event
>>> prefix so that it can be zeroed out by the MGMT commands and events.
>>>
>>> With that comments? Thoughts?
>>
>> Well, while this approach could work. The advantage is the access to
>> command complete and comand status events. But then having an
>> independent mesh daemon (also ell based) may become problematic.
>> Also, putting actual mesh access layer messages via management socket
>> is a bit questionable: my understanding is that mgmt socket is mainly
>> for control and configuration messsages.
>>
>
> I think if we arrive at a position where we need "Command Complete" style feedback to User Space (if/when we get Controllers natively aware of Mesh), we should use an Ancillary (CMSG) response with an Empty Payload message on the same socket. This "Single Socket" model allows us to keep "Sequence of Events" better than using the MGMT interface... and as Inga noted, with a separate Mesh Daemon, we make it possible to have a much leaner "Mesh Only" usage model, without the User Space baggage of BR/EDR/LP infrastructure.
the command complete is really just for flow control and return parameter transport. And we can still have a separate mesh daemon even with mgmt. Meaning you would still open a separate mgmt socket. And you need to do that anyway to list all available controllers and find the one that supports mesh.
Regards
Marcel
Hi Inga,
>>> ---
>>> doc/mesh-api.txt | 269
>>> +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>> 1 file changed, 269 insertions(+)
>>> create mode 100644 doc/mesh-api.txt
>>>
>>> diff --git a/doc/mesh-api.txt b/doc/mesh-api.txt
>>> new file mode 100644
>>> index 000000000..87311faba
>>> --- /dev/null
>>> +++ b/doc/mesh-api.txt
>>> @@ -0,0 +1,269 @@
>>> +Bluetooth Mesh Socket API
>>> +*************************
>>> +
>>> +Copyright (C) 2018 Intel Corporation. All rights reserved.
>>> +
>>> +This document decribes the data format that is used for
>>> communication with
>>> +the kernel via Bluetooth Mesh socket. The data that are passed
>>> over this
>>> +type of a socket is specific to Bluetooth Mesh Profile.
>>> +
>>> +The Bluetooth Mesh socket is implemented as part of PF_BLUETOOTH
>>> family
>>> +and can be created by opening a raw HCI socket with hci_channel
>>> set to
>>> +HCI_CHANNEL_BTMESH. The mesh socket requires the creating process
>>> to have
>>
>> call this HCI_CHANNEL_MESH. There is no point in adding BT* here.
>>
>>> +CAP_NET_ADMIN capability.
>>> +
>>> +===================================================
>>> +Packet Structure: user space to/from kernel (Tx/Rx)
>>> +===================================================
>>> +
>>> +Each packet to or from the Over-the-Air interface is sent between
>>> the user
>>> +space and the kernel must be of nonzero length, and start with the
>>> AD_Type,
>>> +followed by a variable amount of additional payload.
>>> +
>>> + 0 8
>>> + +---------------+------------------------------------
>>> + | AD_Type | Mesh Packet
>>> + +---------------+——————————————————
>>> +
>>
>> Actually I would have really preferred that we followed the Proxy PDU
>> format.
>>
>> 2 Bits reserved
>> 6 Bits packet type
>> Variable data payload
>>
>> I think that we really need the 0x02 type for configuration between
>> the kernel and userspace.
>
> The idea is to allow the data payload to be identical to the mesh
> message that would go over the air. Hence, everything that is not part
> of the actual mesh message ends up in either cmsg or sockopt.
> Introducing 0x2 "configuration" type will break this paradigm since the
> configuration for mesh does not map directly to configuration for
> Proxy.
>
>
>>> +AD_Type (1 octet -- Defined by the Bluetooth SIG)
>>> +=================
>>> +
>>> +Provisioning: 0x29 - The payload contains a Mesh
>>> Provisioning message
>>> +Network: 0x2A - The payload contains a Mesh
>>> Data Packet
>>> +Beacon: 0x2B - The payload contains a Mesh
>>> Beacon
>>> +
>>> +The AD_Type values correspond to AD types introduced in Mesh
>>> Profile
>>> +specification. The API is designed to support additional types.
>>> +
>>> +
>>> +A packet with empty (Zero-Length) payload may be sent over the
>>> socket in case
>>> +when only Control ancillary data is needed (e.g., Flush or Scan,
>>> defined below).
>>> +
>>> +===============
>>> +Socket Options
>>> +===============
>>> +
>>> +HCI Mesh Scan Filter
>>> +====================
>>> + Code: 0x05
>>> +
>>> + Filter_Id (1 octet)
>>> + Duplicates (1 octet)
>>> + Filter (variable length)
>>> +
>>> +Read/write socket option used to setup scan filters for mesh
>>> specific packets.
>>> +First octet of filter must include at least the AD_Type but may be
>>> longer to
>>> +include NIDs or other known data.
>>
>> These ones look more like type 0x02 PDU packets. And this in
>> particular I would have done as Add Network ID and Remove Network ID
>> and let the kernel deal with deciding if it chooses a more global
>> filter (since not enough filters are available) or if it can be more
>> precise with the filtering.
>>
>
> This is a once in awhile operation, so It felt like socket option seems
> like a better place for it. It could be made more user friendly at the
> expense of losing flexibility in future of adding filtering on
> additional AD Types.
>
>>> +
>>> +HCI Mesh Default Tx Power
>>> +=========================
>>> + Code: 0x06
>>> +
>>> + Tx_Power (1 octet)
>>> +
>>> +Read/write socket option for setting default Tx power.
>>
>> Leave this out for now. I assume initially we will always use 127 for
>> do not care. If we think it is valuable for testing, then via
>> debugfs.
>>
>
> I agree. No use for this at the moment.
>
>>> +
>>> +HCI Mesh Default Cahnnel Map
>>> +============================
>>> + Code: 0x07
>>> +
>>> + Chan_map (1 octet)
>>> +
>>> +Read/write socket option for setting default channel map.
>>
>> Also irrelevant and only for fine tuning and testing. Can be exposed
>> via debugfs.
>>
>
> Agreed.
>
>>> +
>>> +HCI Mesh Accuracy
>>> +=================
>>> + Code: 0x08
>>> +
>>> + Accuracy (1 octet)
>>> +
>>> +Read-only socket option to obtain the value of the smallest number
>>> of
>>> +milliseconds that a Mesh Friendship Offer Window can be, for
>>> guaranteed
>>> +Poll Response transmission within that window.
>>
>> I still would have done this via type 0x02 and a PDU exchange
>> protocol. Mainly because then it also becomes traceable via btmon. So
>> yes, I want the mesh channel also be included in btmon.
>>
>>> +
>>> +==================
>>> +Tx Ancillary Data
>>> +==================
>>> +
>>> +The information about which timing settings to use when sending a
>>> mesh
>>> +packet is contained in mandatory ancillary data accompanying the
>>> +payload. Exactly one of the following (mutually exclusive)
>>> ancillary
>>> +data types must be present with nonzero length Tx payload:
>>> +
>>> +Mesh Transmit Info
>>> +===================
>>> +
>>> +cmsg_level cmsg_type cmsg_data[]
>>> +--------------------------------------------------
>>> +SOL_BLUETOOTH BTMESH_TX_INFO Parameters
>>
>> General format we started using is BT_* and so this should be
>> BT_MESH_*
>>
>>> +
>>> + Code: 0x01
>>> + Parameters:
>>> + Count (1 octet)
>>> + Interval: (2 octets)
>>> + Min_Random_Delay: (1 octet)
>>> + Max_Random_Delay: (1 octet)
>>> +
>>> +The retransmission parameters for a regular outgoing mesh message.
>>> +
>>> +Count is the total number of times to Tx. A Zero means Tx Until
>>> Canceled.
>>> +
>>> +Interval is the number of milliseconds between each Tx.
>>> +
>>> +Random Delay is milliseconds added before first Tx.
>>> +
>>> +Mesh Poll Transmit Info
>>> +=======================
>>> +
>>> +cmsg_level cmsg_type cmsg_data[]
>>> +---------------------------------------------------
>>> +SOL_BLUETOOTH BTMESH_POLL_TX_INFO Parameters
>>> +
>>> + Code: 0x02
>>> + Parameters:
>>> + Scan_Delay (1 octet)
>>> + Scan_Duration (1 octet)
>>> + Filter_Ids[2] (2 octets)
>>> + Min_Random_Delay: (1 octet)
>>> + Max_Random_Delay: (1 octet)
>>> +
>>> +Scan_Delay describes the wait period to begin scanning after the
>>> Poll message
>>> +is sent.
>>> +
>>> +Filter_Ids contain IDs of two filters that account for two
>>> possible values of
>>> +IV Update bit in expected Poll response.
>>> +
>>> +Random Delay is milliseconds added before Tx.
>>> +
>>> +Mesh Poll Response Transmit Info
>>> +================================
>>> +
>>> +cmsg_level cmsg_type cmsg_data[]
>>> +-----------------------------------------------------
>>> +SOL_BLUETOOTH BTMESH_POLL_RSP_TX_INFO Parameters
>>> +
>>> + Code: 0x03
>>> + Parameters:
>>> + Instant (4 octets)
>>> + Delay (1 octet)
>>> +
>>> +The timing parameters for sending a friend poll response.
>>> +
>>> +Instant is a 4-octet opaque value that corresponds to the instant
>>> an
>>> +associated incoming mesh message was recieved, for timing
>>> purposes.
>>> +
>>> +Delay defines number of milliseconds after the corresponding
>>> Instant
>>> +to wait before sending this Tx.
>>> +
>>> +__________________________________________________________________
>>> __
>>> +
>>> +The following ancillary types are optional with nonzero length Tx
>>> payload:
>>> +
>>> +Transmit Power
>>> +==============
>>> +
>>> +cmsg_level cmsg_type cmsg_data[]
>>> +---------------------------------------------------------------
>>> +SOL_BLUETOOTH BTMESH_TX_POWER_INFO Parameters
>>> +
>>> + Code: 0x04
>>> + Parameters:
>>> + Tx_Power (1 octet)
>>> +
>>> +Transmit power setting can be used for finer control on the
>>> outbound messages.
>>> +If not present, use default value (builtin or configured as socket
>>> options).
>>> +
>>> +Transmit Channel
>>> +================
>>> +cmsg_level cmsg_type cmsg_data[]
>>> +---------------------------------------------------------------
>>> +SOL_BLUETOOTH BTMESH_TX_CHANNEL_INFO Parameters
>>> +
>>> + Code: 0x05
>>> + Parameters:
>>> + Tx_Channel (1 octet)
>>> +
>>> +The presence of this option specifies transmit channel and allows
>>> +for better control, e.g., to respond on the same
>>> +channel as the one on which incoming message has been received.
>>> +If not present, the default value will be used (builtin or
>>> configured as
>>> +socket options).
>>
>> Don’t bother with these two at the moment. I think they have no use
>> for us except for allowing some testing via debugfs. They needed to
>> be in the HCI spec for completeness and because you can also use the
>> HCI spec to build a mesh sniffer.
>>
>>> +
>>> +
>>> +Additional the ancillary data portion may contain Control type
>>> information.
>>> +
>>> +The following are Control ancillary data types, that me be sent
>>> with or
>>> +without payloads:
>>> +
>>> +Scan
>>> +=======
>>> +cmsg_level cmsg_type cmsg_data[]
>>> +---------------------------------------------------------------
>>> +SOL_BLUETOOTH BTMESH_SCAN Parameters
>>> +
>>> + Code: 0x06
>>> + Parameters:
>>> + Filter_Ids[] (variable)
>>> +
>>> +To enable/disable scanning of Mesh packets.
>>> +
>>> +If Filter_Ids array is nonzero length, start scanning with the
>>> specified
>>> +filters (filters are initialized via socket options mechanism).
>>> This array
>>> +replaces any prior filters.
>>> +
>>> +If no filter IDs are present (i.e., zero array length), stop
>>> scanning.
>>
>> I dislike this. We should have a type 0x02 command that tells us what
>> kind of role we are operating in. And based on that scanning is
>> enabled by binding the socket and closing it. Or changing the role.
>> The whole filter id exposure seems a bit odd to me. I realize that
>> this might look simple, but a few things should be done by the
>> kernel. And managing the scanning filters is one of them. So we need
>> to feed the kernel enough details that it can do that efficiently.
>> Swapping filters around from userspace is painful.
>>
>
> Adding filters should remain dynamic, e.g., when a new network key is
> added (or looking forward, new AD Type).
>
>> Otherwise we could just expose HCI_CHANNEL_MESH as HCI mesh commands.
>> They are all multiplexed via a single opcode anyway and have a single
>> event with and event prefix. So if you want this detailed control of
>> the HCI commands, then don’t try to put too much kernel in between.
>> Just do path through of them.
>>
>> We could do just that and then leave the kernel portion for this
>> alone. Maybe it is worth while to debate pros and cons for this. It
>> is actually not the worst idea to give exclusive access to the mesh
>> commands. It would be similar to HCI_CHANNEL_USER, but only for the
>> mesh commands and we would strip the HCI command header and HCI event
>> header + event prefix off it so that you just have to deal with mesh
>> opcode and mesh subevent code.
>>
>> Hmmm .. it gets a bit tricky for the command complete portion of it.
>> So it might have to be the full HCI anyway, but restricted to one
>> opcode and only matching events being forwarded.
>>
>> Actually if I spin my train of thoughts further now, we might want to
>> put HCI_CHANNEL_MESH on ice and leave that for some future version. I
>> think providing some sort of abstraction and automatic handling of
>> scanning filters etc. is a good abstraction for the kernel, but it
>> might be something that will take a while to be defined and working
>> correctly. Doing the HCI mesh commands directly on a socket has the
>> command complete problem as stated above and having yet another
>> variation of HCI_CHANNEL_RAW with mesh HCI filters seems wrong as
>> well. Especially since eventually I want to have an option to disable
>> HCI_CHANNEL_RAW. In addition it would have been exclusive access to
>> make sure nothing goes wrong.
>>
>> So maybe we just expose HCI mesh commands as MGMT command and MGMT
>> event.
>>
>> Mesh Command
>> ============
>>
>> Command Code: 0x0043
>> Controller Index: <controller index>
>> Command Parameters: Opcode (1 Octet)
>> Command parameters (Variable)
>> Return Parameters: Status (1 Octet)
>> Opcode (1 Octet)
>> Return parameters (Variable)
>>
>> Mesh Event
>> ==========
>>
>> Event Code: 0x0026
>> Controller Index: <controller index>
>> Event Parameters: Subevent (1 Octet)
>> Even parameters (variable)
>>
>> This would map 1:1 to the HCI mesh commands and events with the tiny
>> modification that the event prefix is stripped from the Mesh Event
>> and not provided and with the Mesh Get Options command issued it
>> would be mapped to event prefix length of zero.
>>
>> And then only a settings 16 Mesh would be needed. Or we make the
>> command and event only available when HCI mesh commands are actually
>> supported. That is something that would needs to be discussing. In
>> general, we have not had limited commands based on hardware
>> functionality, but these two would be special since they are vendor
>> specific commands in the first place.
>>
>> For the kernel side we only have the the driver provide the mesh HCI
>> opcode and run Mesh Get Options once to retrieve the firmwares event
>> prefix so that it can be zeroed out by the MGMT commands and events.
>>
>> With that comments? Thoughts?
>
> Well, while this approach could work. The advantage is the access to
> command complete and comand status events. But then having an
> independent mesh daemon (also ell based) may become problematic.
> Also, putting actual mesh access layer messages via management socket
> is a bit questionable: my understanding is that mgmt socket is mainly
> for control and configuration messsages.
putting it in a separate daemon is not a problem actually. The kernel will handle that just fine. We can easily have two control sockets open at the same. We might want to add an extra handling that mesh events only go to one specific socket and not all of them. I will think about this for a bit, but we have done that before with the extended controller events and the kernel can already handle that nicely. That code is already present.
The only reason why this might be useful is that we decide to use the HCI mesh commands / events as a base interface. And this comes mainly from the comments that the mesh daemon will require tight control over the filters. If the kernel turns into a passthrough anyway, then way not make it really simple for the kernel code. So mgmt API is suppose to be parts of GAP and handle certain things that are transactional on HCI. I can convince myself that with HCI mesh API this is the same, but that there is just nothing to do except figure out the event prefix. So it would become super lightweight for the kernel.
If we base everything around the HCI mesh commands / events, then switching from Mesh MGMT to HCI_CHANNEL_USER is dead simple and only needs a minimal shim for transport abstraction. Maybe this is actually an advantage.
One thing that I really like is that mgmt is already include in btmon tracing. So we would get that for free. The one thing that I didn’t consider enough is that with CMSG usage, we loose an easy way of being able to trace all the packets and parameters. It is such a powerful feature, that I am not in favor of missing it.
Regards
Marcel
SGkgSW5nYSwgTWFyY2VsLA0KDQo+IEZyb206IGxpbnV4LWJsdWV0b290aC1vd25lckB2Z2VyLmtl
cm5lbC5vcmcgW21haWx0bzpsaW51eC1ibHVldG9vdGgtDQo+IA0KPiBIaSBNYXJjZWwsDQo+IA0K
PiBPbiBNb24sIDIwMTgtMDItMjYgYXQgMTQ6NDkgKzAxMDAsIE1hcmNlbCBIb2x0bWFubiB3cm90
ZToNCj4gPiBIaSBJbmdhLA0KPiA+DQo+ID4gPiAtLS0NCj4gPiBNZXNoIENvbW1hbmQNCj4gPiA9
PT09PT09PT09PT0NCj4gPg0KPiA+IAlDb21tYW5kIENvZGU6CQkweDAwNDMNCj4gPiAJQ29udHJv
bGxlciBJbmRleDoJPGNvbnRyb2xsZXIgaW5kZXg+DQo+ID4gCUNvbW1hbmQgUGFyYW1ldGVyczoJ
T3Bjb2RlICgxIE9jdGV0KQ0KPiA+IAkJCQlDb21tYW5kIHBhcmFtZXRlcnMgKFZhcmlhYmxlKQ0K
PiA+IAlSZXR1cm4gUGFyYW1ldGVyczoJU3RhdHVzICgxIE9jdGV0KQ0KPiA+IAkJCQlPcGNvZGUg
KDEgT2N0ZXQpDQo+ID4gCQkJCVJldHVybiBwYXJhbWV0ZXJzIChWYXJpYWJsZSkNCj4gPg0KPiA+
IE1lc2ggRXZlbnQNCj4gPiA9PT09PT09PT09DQo+ID4NCj4gPiAJRXZlbnQgQ29kZToJCTB4MDAy
Ng0KPiA+IAlDb250cm9sbGVyIEluZGV4Ogk8Y29udHJvbGxlciBpbmRleD4NCj4gPiAJRXZlbnQg
UGFyYW1ldGVyczoJU3ViZXZlbnQgKDEgT2N0ZXQpDQo+ID4gCQkJCUV2ZW4gcGFyYW1ldGVycyAo
dmFyaWFibGUpDQo+ID4NCj4gPiBUaGlzIHdvdWxkIG1hcCAxOjEgdG8gdGhlIEhDSSBtZXNoIGNv
bW1hbmRzIGFuZCBldmVudHMgd2l0aCB0aGUgdGlueQ0KPiA+IG1vZGlmaWNhdGlvbiB0aGF0IHRo
ZSBldmVudCBwcmVmaXggaXMgc3RyaXBwZWQgZnJvbSB0aGUgTWVzaCBFdmVudA0KPiA+IGFuZCBu
b3QgcHJvdmlkZWQgYW5kIHdpdGggdGhlIE1lc2ggR2V0IE9wdGlvbnMgY29tbWFuZCBpc3N1ZWQg
aXQNCj4gPiB3b3VsZCBiZSBtYXBwZWQgdG8gZXZlbnQgcHJlZml4IGxlbmd0aCBvZiB6ZXJvLg0K
PiA+DQo+ID4gQW5kIHRoZW4gb25seSBhIHNldHRpbmdzIDE2IE1lc2ggd291bGQgYmUgbmVlZGVk
LiBPciB3ZSBtYWtlIHRoZQ0KPiA+IGNvbW1hbmQgYW5kIGV2ZW50IG9ubHkgYXZhaWxhYmxlIHdo
ZW4gSENJIG1lc2ggY29tbWFuZHMgYXJlIGFjdHVhbGx5DQo+ID4gc3VwcG9ydGVkLiBUaGF0IGlz
IHNvbWV0aGluZyB0aGF0IHdvdWxkIG5lZWRzIHRvIGJlIGRpc2N1c3NpbmcuIEluDQo+ID4gZ2Vu
ZXJhbCwgd2UgaGF2ZSBub3QgaGFkIGxpbWl0ZWQgY29tbWFuZHMgYmFzZWQgb24gaGFyZHdhcmUN
Cj4gPiBmdW5jdGlvbmFsaXR5LCBidXQgdGhlc2UgdHdvIHdvdWxkIGJlIHNwZWNpYWwgc2luY2Ug
dGhleSBhcmUgdmVuZG9yDQo+ID4gc3BlY2lmaWMgY29tbWFuZHMgaW4gdGhlIGZpcnN0IHBsYWNl
Lg0KPiA+DQo+ID4gRm9yIHRoZSBrZXJuZWwgc2lkZSB3ZSBvbmx5IGhhdmUgdGhlIHRoZSBkcml2
ZXIgcHJvdmlkZSB0aGUgbWVzaCBIQ0kNCj4gPiBvcGNvZGUgYW5kIHJ1biBNZXNoIEdldCBPcHRp
b25zIG9uY2UgdG8gcmV0cmlldmUgdGhlIGZpcm13YXJlcyBldmVudA0KPiA+IHByZWZpeCBzbyB0
aGF0IGl0IGNhbiBiZSB6ZXJvZWQgb3V0IGJ5IHRoZSBNR01UIGNvbW1hbmRzIGFuZCBldmVudHMu
DQo+ID4NCj4gPiBXaXRoIHRoYXQgY29tbWVudHM/IFRob3VnaHRzPw0KPiANCj4gV2VsbCwgd2hp
bGUgdGhpcyBhcHByb2FjaCBjb3VsZCB3b3JrLiBUaGUgYWR2YW50YWdlIGlzIHRoZSBhY2Nlc3Mg
dG8NCj4gY29tbWFuZCBjb21wbGV0ZSBhbmQgY29tYW5kIHN0YXR1cyBldmVudHMuIEJ1dCB0aGVu
IGhhdmluZyBhbg0KPiBpbmRlcGVuZGVudCBtZXNoIGRhZW1vbiAoYWxzbyBlbGwgYmFzZWQpIG1h
eSBiZWNvbWUgcHJvYmxlbWF0aWMuDQo+IEFsc28sIHB1dHRpbmcgYWN0dWFsIG1lc2ggYWNjZXNz
IGxheWVyIG1lc3NhZ2VzIHZpYSBtYW5hZ2VtZW50IHNvY2tldA0KPiBpcyBhIGJpdCBxdWVzdGlv
bmFibGU6IG15IHVuZGVyc3RhbmRpbmcgaXMgdGhhdCBtZ210IHNvY2tldCBpcyBtYWlubHkNCj4g
Zm9yIGNvbnRyb2wgYW5kIGNvbmZpZ3VyYXRpb24gbWVzc3NhZ2VzLg0KPiANCg0KSSB0aGluayBp
ZiB3ZSBhcnJpdmUgYXQgYSBwb3NpdGlvbiB3aGVyZSB3ZSBuZWVkICJDb21tYW5kIENvbXBsZXRl
IiBzdHlsZSBmZWVkYmFjayB0byBVc2VyIFNwYWNlIChpZi93aGVuIHdlIGdldCBDb250cm9sbGVy
cyBuYXRpdmVseSBhd2FyZSBvZiBNZXNoKSwgd2Ugc2hvdWxkIHVzZSBhbiBBbmNpbGxhcnkgKENN
U0cpIHJlc3BvbnNlIHdpdGggYW4gRW1wdHkgUGF5bG9hZCBtZXNzYWdlIG9uIHRoZSBzYW1lIHNv
Y2tldC4gIFRoaXMgIlNpbmdsZSBTb2NrZXQiIG1vZGVsIGFsbG93cyB1cyB0byBrZWVwICJTZXF1
ZW5jZSBvZiBFdmVudHMiIGJldHRlciB0aGFuIHVzaW5nIHRoZSBNR01UIGludGVyZmFjZS4uLiBh
bmQgYXMgSW5nYSBub3RlZCwgd2l0aCBhIHNlcGFyYXRlIE1lc2ggRGFlbW9uLCB3ZSBtYWtlIGl0
IHBvc3NpYmxlIHRvIGhhdmUgYSBtdWNoIGxlYW5lciAiTWVzaCBPbmx5IiB1c2FnZSBtb2RlbCwg
d2l0aG91dCB0aGUgVXNlciBTcGFjZSBiYWdnYWdlIG9mIEJSL0VEUi9MUCBpbmZyYXN0cnVjdHVy
ZS4NCiANCg0KLS1Ccmlhbg0K
Hi Marcel,
On Mon, 2018-02-26 at 14:49 +0100, Marcel Holtmann wrote:
> Hi Inga,
>
> > ---
> > doc/mesh-api.txt | 269
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 269 insertions(+)
> > create mode 100644 doc/mesh-api.txt
> >
> > diff --git a/doc/mesh-api.txt b/doc/mesh-api.txt
> > new file mode 100644
> > index 000000000..87311faba
> > --- /dev/null
> > +++ b/doc/mesh-api.txt
> > @@ -0,0 +1,269 @@
> > +Bluetooth Mesh Socket API
> > +*************************
> > +
> > +Copyright (C) 2018 Intel Corporation. All rights reserved.
> > +
> > +This document decribes the data format that is used for
> > communication with
> > +the kernel via Bluetooth Mesh socket. The data that are passed
> > over this
> > +type of a socket is specific to Bluetooth Mesh Profile.
> > +
> > +The Bluetooth Mesh socket is implemented as part of PF_BLUETOOTH
> > family
> > +and can be created by opening a raw HCI socket with hci_channel
> > set to
> > +HCI_CHANNEL_BTMESH. The mesh socket requires the creating process
> > to have
>
> call this HCI_CHANNEL_MESH. There is no point in adding BT* here.
>
> > +CAP_NET_ADMIN capability.
> > +
> > +===================================================
> > +Packet Structure: user space to/from kernel (Tx/Rx)
> > +===================================================
> > +
> > +Each packet to or from the Over-the-Air interface is sent between
> > the user
> > +space and the kernel must be of nonzero length, and start with the
> > AD_Type,
> > +followed by a variable amount of additional payload.
> > +
> > + 0 8
> > + +---------------+------------------------------------
> > + | AD_Type | Mesh Packet
> > + +---------------+——————————————————
> > +
>
> Actually I would have really preferred that we followed the Proxy PDU
> format.
>
> 2 Bits reserved
> 6 Bits packet type
> Variable data payload
>
> I think that we really need the 0x02 type for configuration between
> the kernel and userspace.
The idea is to allow the data payload to be identical to the mesh
message that would go over the air. Hence, everything that is not part
of the actual mesh message ends up in either cmsg or sockopt.
Introducing 0x2 "configuration" type will break this paradigm since the
configuration for mesh does not map directly to configuration for
Proxy.
> > +AD_Type (1 octet -- Defined by the Bluetooth SIG)
> > +=================
> > +
> > +Provisioning: 0x29 - The payload contains a Mesh
> > Provisioning message
> > +Network: 0x2A - The payload contains a Mesh
> > Data Packet
> > +Beacon: 0x2B - The payload contains a Mesh
> > Beacon
> > +
> > +The AD_Type values correspond to AD types introduced in Mesh
> > Profile
> > +specification. The API is designed to support additional types.
> > +
> > +
> > +A packet with empty (Zero-Length) payload may be sent over the
> > socket in case
> > +when only Control ancillary data is needed (e.g., Flush or Scan,
> > defined below).
> > +
> > +===============
> > +Socket Options
> > +===============
> > +
> > +HCI Mesh Scan Filter
> > +====================
> > + Code: 0x05
> > +
> > + Filter_Id (1 octet)
> > + Duplicates (1 octet)
> > + Filter (variable length)
> > +
> > +Read/write socket option used to setup scan filters for mesh
> > specific packets.
> > +First octet of filter must include at least the AD_Type but may be
> > longer to
> > +include NIDs or other known data.
>
> These ones look more like type 0x02 PDU packets. And this in
> particular I would have done as Add Network ID and Remove Network ID
> and let the kernel deal with deciding if it chooses a more global
> filter (since not enough filters are available) or if it can be more
> precise with the filtering.
>
This is a once in awhile operation, so It felt like socket option seems
like a better place for it. It could be made more user friendly at the
expense of losing flexibility in future of adding filtering on
additional AD Types.
> > +
> > +HCI Mesh Default Tx Power
> > +=========================
> > + Code: 0x06
> > +
> > + Tx_Power (1 octet)
> > +
> > +Read/write socket option for setting default Tx power.
>
> Leave this out for now. I assume initially we will always use 127 for
> do not care. If we think it is valuable for testing, then via
> debugfs.
>
I agree. No use for this at the moment.
> > +
> > +HCI Mesh Default Cahnnel Map
> > +============================
> > + Code: 0x07
> > +
> > + Chan_map (1 octet)
> > +
> > +Read/write socket option for setting default channel map.
>
> Also irrelevant and only for fine tuning and testing. Can be exposed
> via debugfs.
>
Agreed.
> > +
> > +HCI Mesh Accuracy
> > +=================
> > + Code: 0x08
> > +
> > + Accuracy (1 octet)
> > +
> > +Read-only socket option to obtain the value of the smallest number
> > of
> > +milliseconds that a Mesh Friendship Offer Window can be, for
> > guaranteed
> > +Poll Response transmission within that window.
>
> I still would have done this via type 0x02 and a PDU exchange
> protocol. Mainly because then it also becomes traceable via btmon. So
> yes, I want the mesh channel also be included in btmon.
>
> > +
> > +==================
> > +Tx Ancillary Data
> > +==================
> > +
> > +The information about which timing settings to use when sending a
> > mesh
> > +packet is contained in mandatory ancillary data accompanying the
> > +payload. Exactly one of the following (mutually exclusive)
> > ancillary
> > +data types must be present with nonzero length Tx payload:
> > +
> > +Mesh Transmit Info
> > +===================
> > +
> > +cmsg_level cmsg_type cmsg_data[]
> > +--------------------------------------------------
> > +SOL_BLUETOOTH BTMESH_TX_INFO Parameters
>
> General format we started using is BT_* and so this should be
> BT_MESH_*
>
> > +
> > + Code: 0x01
> > + Parameters:
> > + Count (1 octet)
> > + Interval: (2 octets)
> > + Min_Random_Delay: (1 octet)
> > + Max_Random_Delay: (1 octet)
> > +
> > +The retransmission parameters for a regular outgoing mesh message.
> > +
> > +Count is the total number of times to Tx. A Zero means Tx Until
> > Canceled.
> > +
> > +Interval is the number of milliseconds between each Tx.
> > +
> > +Random Delay is milliseconds added before first Tx.
> > +
> > +Mesh Poll Transmit Info
> > +=======================
> > +
> > +cmsg_level cmsg_type cmsg_data[]
> > +---------------------------------------------------
> > +SOL_BLUETOOTH BTMESH_POLL_TX_INFO Parameters
> > +
> > + Code: 0x02
> > + Parameters:
> > + Scan_Delay (1 octet)
> > + Scan_Duration (1 octet)
> > + Filter_Ids[2] (2 octets)
> > + Min_Random_Delay: (1 octet)
> > + Max_Random_Delay: (1 octet)
> > +
> > +Scan_Delay describes the wait period to begin scanning after the
> > Poll message
> > +is sent.
> > +
> > +Filter_Ids contain IDs of two filters that account for two
> > possible values of
> > +IV Update bit in expected Poll response.
> > +
> > +Random Delay is milliseconds added before Tx.
> > +
> > +Mesh Poll Response Transmit Info
> > +================================
> > +
> > +cmsg_level cmsg_type cmsg_data[]
> > +-----------------------------------------------------
> > +SOL_BLUETOOTH BTMESH_POLL_RSP_TX_INFO Parameters
> > +
> > + Code: 0x03
> > + Parameters:
> > + Instant (4 octets)
> > + Delay (1 octet)
> > +
> > +The timing parameters for sending a friend poll response.
> > +
> > +Instant is a 4-octet opaque value that corresponds to the instant
> > an
> > +associated incoming mesh message was recieved, for timing
> > purposes.
> > +
> > +Delay defines number of milliseconds after the corresponding
> > Instant
> > +to wait before sending this Tx.
> > +
> > +__________________________________________________________________
> > __
> > +
> > +The following ancillary types are optional with nonzero length Tx
> > payload:
> > +
> > +Transmit Power
> > +==============
> > +
> > +cmsg_level cmsg_type cmsg_data[]
> > +---------------------------------------------------------------
> > +SOL_BLUETOOTH BTMESH_TX_POWER_INFO Parameters
> > +
> > + Code: 0x04
> > + Parameters:
> > + Tx_Power (1 octet)
> > +
> > +Transmit power setting can be used for finer control on the
> > outbound messages.
> > +If not present, use default value (builtin or configured as socket
> > options).
> > +
> > +Transmit Channel
> > +================
> > +cmsg_level cmsg_type cmsg_data[]
> > +---------------------------------------------------------------
> > +SOL_BLUETOOTH BTMESH_TX_CHANNEL_INFO Parameters
> > +
> > + Code: 0x05
> > + Parameters:
> > + Tx_Channel (1 octet)
> > +
> > +The presence of this option specifies transmit channel and allows
> > +for better control, e.g., to respond on the same
> > +channel as the one on which incoming message has been received.
> > +If not present, the default value will be used (builtin or
> > configured as
> > +socket options).
>
> Don’t bother with these two at the moment. I think they have no use
> for us except for allowing some testing via debugfs. They needed to
> be in the HCI spec for completeness and because you can also use the
> HCI spec to build a mesh sniffer.
>
> > +
> > +
> > +Additional the ancillary data portion may contain Control type
> > information.
> > +
> > +The following are Control ancillary data types, that me be sent
> > with or
> > +without payloads:
> > +
> > +Scan
> > +=======
> > +cmsg_level cmsg_type cmsg_data[]
> > +---------------------------------------------------------------
> > +SOL_BLUETOOTH BTMESH_SCAN Parameters
> > +
> > + Code: 0x06
> > + Parameters:
> > + Filter_Ids[] (variable)
> > +
> > +To enable/disable scanning of Mesh packets.
> > +
> > +If Filter_Ids array is nonzero length, start scanning with the
> > specified
> > +filters (filters are initialized via socket options mechanism).
> > This array
> > +replaces any prior filters.
> > +
> > +If no filter IDs are present (i.e., zero array length), stop
> > scanning.
>
> I dislike this. We should have a type 0x02 command that tells us what
> kind of role we are operating in. And based on that scanning is
> enabled by binding the socket and closing it. Or changing the role.
> The whole filter id exposure seems a bit odd to me. I realize that
> this might look simple, but a few things should be done by the
> kernel. And managing the scanning filters is one of them. So we need
> to feed the kernel enough details that it can do that efficiently.
> Swapping filters around from userspace is painful.
>
Adding filters should remain dynamic, e.g., when a new network key is
added (or looking forward, new AD Type).
> Otherwise we could just expose HCI_CHANNEL_MESH as HCI mesh commands.
> They are all multiplexed via a single opcode anyway and have a single
> event with and event prefix. So if you want this detailed control of
> the HCI commands, then don’t try to put too much kernel in between.
> Just do path through of them.
>
> We could do just that and then leave the kernel portion for this
> alone. Maybe it is worth while to debate pros and cons for this. It
> is actually not the worst idea to give exclusive access to the mesh
> commands. It would be similar to HCI_CHANNEL_USER, but only for the
> mesh commands and we would strip the HCI command header and HCI event
> header + event prefix off it so that you just have to deal with mesh
> opcode and mesh subevent code.
>
> Hmmm .. it gets a bit tricky for the command complete portion of it.
> So it might have to be the full HCI anyway, but restricted to one
> opcode and only matching events being forwarded.
>
> Actually if I spin my train of thoughts further now, we might want to
> put HCI_CHANNEL_MESH on ice and leave that for some future version. I
> think providing some sort of abstraction and automatic handling of
> scanning filters etc. is a good abstraction for the kernel, but it
> might be something that will take a while to be defined and working
> correctly. Doing the HCI mesh commands directly on a socket has the
> command complete problem as stated above and having yet another
> variation of HCI_CHANNEL_RAW with mesh HCI filters seems wrong as
> well. Especially since eventually I want to have an option to disable
> HCI_CHANNEL_RAW. In addition it would have been exclusive access to
> make sure nothing goes wrong.
>
> So maybe we just expose HCI mesh commands as MGMT command and MGMT
> event.
>
> Mesh Command
> ============
>
> Command Code: 0x0043
> Controller Index: <controller index>
> Command Parameters: Opcode (1 Octet)
> Command parameters (Variable)
> Return Parameters: Status (1 Octet)
> Opcode (1 Octet)
> Return parameters (Variable)
>
> Mesh Event
> ==========
>
> Event Code: 0x0026
> Controller Index: <controller index>
> Event Parameters: Subevent (1 Octet)
> Even parameters (variable)
>
> This would map 1:1 to the HCI mesh commands and events with the tiny
> modification that the event prefix is stripped from the Mesh Event
> and not provided and with the Mesh Get Options command issued it
> would be mapped to event prefix length of zero.
>
> And then only a settings 16 Mesh would be needed. Or we make the
> command and event only available when HCI mesh commands are actually
> supported. That is something that would needs to be discussing. In
> general, we have not had limited commands based on hardware
> functionality, but these two would be special since they are vendor
> specific commands in the first place.
>
> For the kernel side we only have the the driver provide the mesh HCI
> opcode and run Mesh Get Options once to retrieve the firmwares event
> prefix so that it can be zeroed out by the MGMT commands and events.
>
> With that comments? Thoughts?
Well, while this approach could work. The advantage is the access to
command complete and comand status events. But then having an
independent mesh daemon (also ell based) may become problematic.
Also, putting actual mesh access layer messages via management socket
is a bit questionable: my understanding is that mgmt socket is mainly
for control and configuration messsages.
>
> Regards
>
> Marcel
>
Hi Brian,
<snip>
I am focusing first on the later part of the comments.
>> I dislike this. We should have a type 0x02 command that tells us what kind of
>> role we are operating in. And based on that scanning is enabled by binding
>> the socket and closing it. Or changing the role. The whole filter id exposure
>> seems a bit odd to me. I realize that this might look simple, but a few things
>> should be done by the kernel. And managing the scanning filters is one of
>> them. So we need to feed the kernel enough details that it can do that
>> efficiently. Swapping filters around from userspace is painful.
>
> In my opinion, User space control of the filters is essential. Unless the kernel is
> handling Crypto, there is no way to know NIDs, Provisioning Session IDs etc. While
> the Kernel handles the discrete timing for individual packets, only User space knows
> enough about the current state of the Mesh to know what filters are required
> at any given time.
If we really think that userspace should control the filters, then I am really tempted to say that the HCI mesh commands is the API from userspace to the kernel to the controller. So the kernel just plays a little bit of path through and nothing else.
>> Otherwise we could just expose HCI_CHANNEL_MESH as HCI mesh
>> commands. They are all multiplexed via a single opcode anyway and have a
>> single event with and event prefix. So if you want this detailed control of the
>> HCI commands, then don’t try to put too much kernel in between. Just do
>> path through of them.
>>
>> We could do just that and then leave the kernel portion for this alone.
>> Maybe it is worth while to debate pros and cons for this. It is actually not the
>> worst idea to give exclusive access to the mesh commands. It would be
>> similar to HCI_CHANNEL_USER, but only for the mesh commands and we
>> would strip the HCI command header and HCI event header + event prefix
>> off it so that you just have to deal with mesh opcode and mesh subevent
>> code.
>
> Are current plan is to just pass packets we want sent with a requested timing,
> and filter incoming packets during designated Scan windows
>
>>
>> Hmmm .. it gets a bit tricky for the command complete portion of it. So it
>> might have to be the full HCI anyway, but restricted to one opcode and only
>> matching events being forwarded.
>
> We are not doing *anything* like Command Complete, and I strongly argue against
> anything like it. In Mesh everything is *Best Effort* whether we like it or not. Command
> Completes may guarantee that a Controller has done what we ask, but whether it has
> done what we ask is 100% immaterial, unless you have a use-case demonstrating how
> it can be useful in a Mesh environment. The only thing we care about is whether a
> remote device has received our packets, or whether we receive theirs. All reliability
> is built into the User-Space Network and Access layers... unlike ACL based systems.
>
> All feedback from Kernel --> User space can be handled with Status codes returned from
> socket writes, or set sock options.
Don’t read too much into command complete. That is just flow control handling so you know when the controller has accepted the command and is a way to return status or other return parameters.
Regards
Marcel
SGkgTWFyY2VsLA0KDQo+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+IEZyb206IGxpbnV4
LWJsdWV0b290aC1vd25lckB2Z2VyLmtlcm5lbC5vcmcgW21haWx0bzpsaW51eC1ibHVldG9vdGgt
DQo+IG93bmVyQHZnZXIua2VybmVsLm9yZ10gT24gQmVoYWxmIE9mIE1hcmNlbCBIb2x0bWFubg0K
PiBTZW50OiBNb25kYXksIEZlYnJ1YXJ5IDI2LCAyMDE4IDU6NTAgQU0NCj4gVG86IFN0b3RsYW5k
LCBJbmdhIDxpbmdhLnN0b3RsYW5kQGludGVsLmNvbT4NCj4gQ2M6IGxpbnV4LWJsdWV0b290aEB2
Z2VyLmtlcm5lbC5vcmcNCj4gU3ViamVjdDogUmU6IFtQQVRDSCBCbHVlWiAxLzEgdjJdIEFkZCBp
bml0aWFsIGRvYyBkZXNjcmliaW5nIEJsdWV0b290aCBNZXNoDQo+IEFQSQ0KPiANCj4gSGkgSW5n
YSwNCj4gDQo+ID4gLS0tDQo+ID4gZG9jL21lc2gtYXBpLnR4dCB8IDI2OQ0KPiA+ICsrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysNCj4gPiAxIGZp
bGUgY2hhbmdlZCwgMjY5IGluc2VydGlvbnMoKykNCj4gPiBjcmVhdGUgbW9kZSAxMDA2NDQgZG9j
L21lc2gtYXBpLnR4dA0KPiA+DQo+ID4gZGlmZiAtLWdpdCBhL2RvYy9tZXNoLWFwaS50eHQgYi9k
b2MvbWVzaC1hcGkudHh0IG5ldyBmaWxlIG1vZGUgMTAwNjQ0DQo+ID4gaW5kZXggMDAwMDAwMDAw
Li44NzMxMWZhYmENCj4gPiAtLS0gL2Rldi9udWxsDQo+ID4gKysrIGIvZG9jL21lc2gtYXBpLnR4
dA0KPiA+IEBAIC0wLDAgKzEsMjY5IEBADQo+ID4gK0JsdWV0b290aCBNZXNoIFNvY2tldCBBUEkN
Cj4gPiArKioqKioqKioqKioqKioqKioqKioqKioqKg0KPiA+ICsNCj4gPiArQ29weXJpZ2h0IChD
KSAyMDE4IEludGVsIENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KPiA+ICsNCj4g
PiArVGhpcyBkb2N1bWVudCBkZWNyaWJlcyB0aGUgZGF0YSBmb3JtYXQgdGhhdCBpcyB1c2VkIGZv
ciBjb21tdW5pY2F0aW9uDQo+ID4gK3dpdGggdGhlIGtlcm5lbCB2aWEgQmx1ZXRvb3RoIE1lc2gg
c29ja2V0LiBUaGUgZGF0YSB0aGF0IGFyZSBwYXNzZWQNCj4gPiArb3ZlciB0aGlzIHR5cGUgb2Yg
YSBzb2NrZXQgaXMgc3BlY2lmaWMgdG8gQmx1ZXRvb3RoIE1lc2ggUHJvZmlsZS4NCj4gPiArDQo+
ID4gK1RoZSBCbHVldG9vdGggTWVzaCBzb2NrZXQgaXMgaW1wbGVtZW50ZWQgYXMgcGFydCBvZiBQ
Rl9CTFVFVE9PVEgNCj4gPiArZmFtaWx5IGFuZCBjYW4gYmUgY3JlYXRlZCBieSBvcGVuaW5nIGEg
cmF3IEhDSSBzb2NrZXQgd2l0aA0KPiA+ICtoY2lfY2hhbm5lbCBzZXQgdG8gSENJX0NIQU5ORUxf
QlRNRVNILiBUaGUgbWVzaCBzb2NrZXQgcmVxdWlyZXMgdGhlDQo+ID4gK2NyZWF0aW5nIHByb2Nl
c3MgdG8gaGF2ZQ0KPiANCj4gY2FsbCB0aGlzIEhDSV9DSEFOTkVMX01FU0guIFRoZXJlIGlzIG5v
IHBvaW50IGluIGFkZGluZyBCVCogaGVyZS4NCj4gDQo+ID4gK0NBUF9ORVRfQURNSU4gY2FwYWJp
bGl0eS4NCj4gPiArDQo+ID4gKz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PQ0KPiA+ICtQYWNrZXQgU3RydWN0dXJlOiB1c2VyIHNwYWNlIHRvL2Zyb20g
a2VybmVsIChUeC9SeCkNCj4gPiArPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09DQo+ID4gKw0KPiA+ICtFYWNoIHBhY2tldCB0byBvciBmcm9tIHRoZSBP
dmVyLXRoZS1BaXIgaW50ZXJmYWNlIGlzIHNlbnQgYmV0d2VlbiB0aGUNCj4gPiArdXNlciBzcGFj
ZSBhbmQgdGhlIGtlcm5lbCBtdXN0IGJlIG9mIG5vbnplcm8gbGVuZ3RoLCBhbmQgc3RhcnQgd2l0
aA0KPiA+ICt0aGUgQURfVHlwZSwgZm9sbG93ZWQgYnkgYSB2YXJpYWJsZSBhbW91bnQgb2YgYWRk
aXRpb25hbCBwYXlsb2FkLg0KPiA+ICsNCj4gPiArCTAgICAgICAgICAgICAgICA4DQo+ID4gKwkr
LS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KPiA+
ICsJfCAgQURfVHlwZSAgICAgIHwgTWVzaCBQYWNrZXQNCj4gPiArCSstLS0tLS0tLS0tLS0tLS0r
4oCU4oCU4oCU4oCU4oCU4oCU4oCU4oCU4oCU4oCU4oCU4oCU4oCU4oCU4oCU4oCU4oCU4oCUDQo+
ID4gKw0KPiANCj4gQWN0dWFsbHkgSSB3b3VsZCBoYXZlIHJlYWxseSBwcmVmZXJyZWQgdGhhdCB3
ZSBmb2xsb3dlZCB0aGUgUHJveHkgUERVDQo+IGZvcm1hdC4NCj4gDQo+IAkyIEJpdHMgcmVzZXJ2
ZWQNCj4gCTYgQml0cyBwYWNrZXQgdHlwZQ0KPiAJVmFyaWFibGUgZGF0YSBwYXlsb2FkDQoNClNv
IHdlIHRhbGtlZCBhYm91dCB0aGlzIGVhcmxpZXIsIHRoYXQgaXQgd291bGQgbWFrZSBzZW5zZSB0
byBtYWtlIHRoZSBLZXJuZWwgYXMgYWdub3N0aWMgYXMgcG9zc2libGUgd2hlbiBpdCBjb21lcyB0
bw0KTWVzaCwgc28gdGhhdCB0aGUgaW50cm9kdWN0aW9uIG9mIG5ldyBPVEEgTWVzaCBwYXlsb2Fk
cyBjb3VsZCBiZSBpbmNvcnBvcmF0ZWQgd2l0aCBtaW5pbWFsIGtlcm5lbCByZXdyaXRlcy4NCg0K
UGFydCBvZiB0aGlzIGFnbm9zdGljaXNtIGluY2x1ZGVzIHRoZSBBRF9UeXBlcy4gTWVzaCBQYWNr
ZXRzIGFyZSBpbmRpc3Rpbmd1aXNoYWJsZSBmcm9tIGFueSBvdGhlciBBZHZlcnRpc2VkIGRhdGEg
ZXhjZXB0DQpmb3Igd2hhdCB0aGUgQlQgU0lHIGRlY2lkZXMgdG8gYXNzaWduIGFzIHRoZSBBRF9U
eXBlIGZvciBlYWNoIE1lc2ggUGFja2V0IFR5cGUuICBXZSBrbm93IHRoYXQgd2UgKndpbGwqIGJl
IGFkZGluZyBuZXcNCkFEIFR5cGVzIGluIHRoZSBmdXR1cmUgZm9yIE1lc2gsIGFuZCBpZiB3ZSBk
b24ndCBrZWVwIGl0IGFnbm9zdGljLCB3ZSB3aWxsIGhhdmUgdG8gYXQgbGVhc3QgYWRkIG1hcHBp
bmcgaW4gYmV0d2VlbiB0aGUgUGFja2V0DQpUeXBlcyBQcm94eSB1c2VzIHRvIHRoZSBBRCBUeXBl
cy4uLi4gIFRoYXQgd291bGQgYmUgYSBzbWFsbCBjaGFuZ2UsIHRvIGJlIHN1cmUsIHlldCBpbiBt
eSBvcGluaW9uIHVubmVjZXNzYXJ5Lg0KDQpBZGRpdGlvbmFsbHksIHdlIG5lZWQgdG8gY29uc2lk
ZXIgdGhlIEFEIFR5cGVzIHdoZW4gZmlsdGVyaW5nIGF0IGVpdGhlciB0aGUgS2VybmVsIGxldmVs
LCBvciBpbiB0aGUgZnV0dXJlLCBhdCB0aGUgQ29udHJvbGVyIGxldmVsLg0KVGhpcyBtZWFucyBl
aXRoZXI6DQoqIFVzaW5nIHRoZSBQcm94eSB0eXBlcyBmb3IgT3V0Z29pbmcgYW5kIEluY29taW5n
IG1lc3NhZ2VzICAgYnV0IG5vdCB0aGUgRmlsdGVyaW5nIC1vci0NCiogVXNpbmcgdGhlIFByb3h5
IHR5cGVzIGZvciB0aGUgZmlsdGVycyB0b28sIGFuZCBtYXBwaW5nIHRoZW0gaW4gdGhlIGtlcm5l
bCB0byBBRCBUeXBlcyAobWFraW5nIGFkZGl0aW9uYWwgQUQgVHlwZSBkZXBlbmRlbmN5IGluIHRo
ZSBLZXJuZWwgTWVzaCBjb2RlKQ0KDQpJIGFtIG5vIGxvbmdlciBpbiBsb3ZlIHdpdGggc2hvZS1o
b3JuaW5nIHRoaXMgaW50byB0aGUgUHJveHkgcGFja2V0Og0KKiBBRCBUeXBlcyBhcmUgaW4gYW4g
OC1iaXQgbmFtZXNwYWNlDQoqIFByb3h5IHByb2JhYmx5IGRvZXNuJ3QgbmVlZCBhbnkgb2YgdGhl
IHVwY29taW5nIHBhY2tldCB0eXBlcy4NCiogVGhpcyBiZWFyZXIgZG9lc24ndCBuZWVkIHRoZSAi
MiBSZXNlcnZlZCBCaXRzIiwgYW5kIGV2ZW4gaWYgd2UgZGlkIHVzZSB0aGVtIGZvciBzb21ldGhp
bmcsIGl0IHdvdWxkIGNlcnRhaW5seSBiZSAqdG90YWxseSogZGlmZmVyZW50IGZyb20gdGhlIFBy
b3h5LVNBUg0KKiBUaGUgUHJveHkgZm9ybWF0IGlzIGludGVuZGVkIHRvIGJlIHVzZWQgYmV0d2Vl
biB0byBwZWVycyB0aGF0IGhhdmUgYWxsIHRoZSBNZXNoIGNyeXB0byBmdW5jdGlvbmFsaXR5DQoN
CldlIG9yaWdpbmFsbHkgdHJpZWQgdG8gdXNlIENvbnRyb2wgYml0cyB0byBkaWZmZXJlbnRpYXRl
IGJldHdlZW4gVGltaW5nL0NvdW50L0ludGVydmFsIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIHZh
cmlvdXMga2luZHMgb2YgTWVzaCBUcmFmZmljLCBidXQgdGhhdCBxdWlja2x5IG92ZXJ3aGVsbWVk
IHRoZSBjb250cm9sIGJpdHMuLi4gIFdoaWNoIGlzIHdoeSAqYWxsKiB0aW1pbmcvY291bnQvaW50
ZXJ2YWwgaW5mbyBpcyBub3cgaGFuZGxlZCBhcyBBbmNpbGxhcnkgZGF0YSwgYW5kIHRoZSBLZXJu
ZWwgZG9lc24ndCBuZWVkIHRvIGtub3cgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBEYXRhLCBCZWFj
b24sIG9yIFByb3Zpc2lvbmluZyBwYWNrZXRzIGJ5IHRoZSBQYXlsb2FkLi4uICBUaGV5IGp1c3Qg
aGF2ZSBkaWZmZXJlbnQgQW5jaWxsYXJ5IGRhdGEuIChGb3IgaW5zdGFuY2UsIHRoZXJlIGRvZXNu
J3QgbmVlZCB0byBiZSBhIGRpZmZlcmVuY2UgYmV0d2VlbiBhIEJlYWNvbiBzZW50IG9uY2UgYW5k
IGEgc3RhbmRhcmQgRGF0YSBwYWNrZXQgc2VudCBvbmNlKQ0KDQoNCj4gDQo+IEkgdGhpbmsgdGhh
dCB3ZSByZWFsbHkgbmVlZCB0aGUgMHgwMiB0eXBlIGZvciBjb25maWd1cmF0aW9uIGJldHdlZW4g
dGhlDQo+IGtlcm5lbCBhbmQgdXNlcnNwYWNlLg0KPiANCg0KV2hhdCB3b3VsZCB0aGUgdXNlIGNh
c2UgYmUsIGFuZCBob3cgd291bGQgdGhpcyBpbXByb3ZlIHVwb24gdGhlIFNvY2sgT3B0aW9ucyBt
ZXRob2Q/ICBUaGUgb25seSByZWFsIGNvbmZpZ3VyYXRpb24gd2UgbmVlZCB0byBkbyB3aXRoIGFu
IGFnbm9zdGljIHN5c3RlbSBpcyB0aGUgRmlsdGVycy4gIEFuZCB0aGUgU2NhbiBlbmFibGUvZGlz
YWJsZSBhcyBBbmNpbGxhcnkgZGF0YSBhcHBlYXJzIHRvIHdvcmsgd2VsbCwgYW5kIHdoZW4gY29t
YmluZWQgd2l0aCB0aGUgcmVxdWlyZW1lbnQgZm9yIExQTnMgdGhhdCBTY2FuIG5lZWRzIHRvIGJl
IHRlbXBvcmFyaWx5IHR1cm5lZCBvbiB3aXRoIHNwZWNpZmljIHRpbWluZyB0aWVkIHRvIGEgc3Bl
Y2lmaWMgUE9MTCBwYXlsb2FkLCBpdCB3b3VsZCBiZSBjb25mdXNpbmcgdG8gc29tZXRpbWVzIGhh
bmRsZSBTY2FuIHNldHVwIHZpYSBhIENvbmZpZ3VyYXRpb24gbWVzc2FnZSwgYW5kIHNvbWV0aW1l
cyBhcyBBbmNpbGxhcnkgZGF0YS4gDQoNCg0KPiA+ICtBRF9UeXBlICgxIG9jdGV0IC0tIERlZmlu
ZWQgYnkgdGhlIEJsdWV0b290aCBTSUcpID09PT09PT09PT09PT09PT09DQo+ID4gKw0KPiA+ICtQ
cm92aXNpb25pbmc6CTB4MjkgLQlUaGUgcGF5bG9hZCBjb250YWlucyBhIE1lc2ggUHJvdmlzaW9u
aW5nDQo+IG1lc3NhZ2UNCj4gPiArTmV0d29yazoJCTB4MkEgLQlUaGUgcGF5bG9hZCBjb250YWlu
cyBhIE1lc2ggRGF0YSBQYWNrZXQNCj4gPiArQmVhY29uOgkJMHgyQiAtCVRoZSBwYXlsb2FkIGNv
bnRhaW5zIGEgTWVzaCBCZWFjb24NCj4gPiArDQo+ID4gK1RoZSBBRF9UeXBlIHZhbHVlcyBjb3Jy
ZXNwb25kIHRvIEFEIHR5cGVzIGludHJvZHVjZWQgaW4gTWVzaCBQcm9maWxlDQo+ID4gK3NwZWNp
ZmljYXRpb24uIFRoZSBBUEkgaXMgZGVzaWduZWQgdG8gc3VwcG9ydCBhZGRpdGlvbmFsIHR5cGVz
Lg0KPiA+ICsNCj4gPiArDQo+ID4gK0EgcGFja2V0IHdpdGggZW1wdHkgKFplcm8tTGVuZ3RoKSBw
YXlsb2FkIG1heSBiZSBzZW50IG92ZXIgdGhlIHNvY2tldA0KPiA+ICtpbiBjYXNlIHdoZW4gb25s
eSBDb250cm9sIGFuY2lsbGFyeSBkYXRhIGlzIG5lZWRlZCAoZS5nLiwgRmx1c2ggb3IgU2NhbiwN
Cj4gZGVmaW5lZCBiZWxvdykuDQo+ID4gKw0KPiA+ICs9PT09PT09PT09PT09PT0NCj4gPiArU29j
a2V0IE9wdGlvbnMNCj4gPiArPT09PT09PT09PT09PT09DQo+ID4gKw0KPiA+ICtIQ0kgTWVzaCBT
Y2FuIEZpbHRlcg0KPiA+ICs9PT09PT09PT09PT09PT09PT09PQ0KPiA+ICsJQ29kZToJMHgwNQ0K
PiA+ICsNCj4gPiArCUZpbHRlcl9JZAkJKDEgb2N0ZXQpDQo+ID4gKwlEdXBsaWNhdGVzCQkoMSBv
Y3RldCkNCj4gPiArCUZpbHRlcgkJCSh2YXJpYWJsZSBsZW5ndGgpDQo+ID4gKw0KPiA+ICtSZWFk
L3dyaXRlIHNvY2tldCBvcHRpb24gdXNlZCB0byBzZXR1cCBzY2FuIGZpbHRlcnMgZm9yIG1lc2gg
c3BlY2lmaWMNCj4gcGFja2V0cy4NCj4gPiArRmlyc3Qgb2N0ZXQgb2YgZmlsdGVyIG11c3QgaW5j
bHVkZSBhdCBsZWFzdCB0aGUgQURfVHlwZSBidXQgbWF5IGJlDQo+ID4gK2xvbmdlciB0byBpbmNs
dWRlIE5JRHMgb3Igb3RoZXIga25vd24gZGF0YS4NCj4gDQo+IFRoZXNlIG9uZXMgbG9vayBtb3Jl
IGxpa2UgdHlwZSAweDAyIFBEVSBwYWNrZXRzLiBBbmQgdGhpcyBpbiBwYXJ0aWN1bGFyIEkNCj4g
d291bGQgaGF2ZSBkb25lIGFzIEFkZCBOZXR3b3JrIElEIGFuZCBSZW1vdmUgTmV0d29yayBJRCBh
bmQgbGV0IHRoZQ0KPiBrZXJuZWwgZGVhbCB3aXRoIGRlY2lkaW5nIGlmIGl0IGNob29zZXMgYSBt
b3JlIGdsb2JhbCBmaWx0ZXIgKHNpbmNlIG5vdCBlbm91Z2gNCj4gZmlsdGVycyBhcmUgYXZhaWxh
YmxlKSBvciBpZiBpdCBjYW4gYmUgbW9yZSBwcmVjaXNlIHdpdGggdGhlIGZpbHRlcmluZy4NCg0K
UmVtZW1iZXIgdGhhdCB3ZSBuZWVkIHRvIG5vdCBvbmx5IGJlIGZpbHRlcmluZyBvbiBOSUQsIGJ1
dCBhbHNvIFBST1YgYW5kIEJFQUNPTiBwYWNrZXRzLCB3aGljaCBkb24ndCBpbmNsdWRlIE5JRCB0
eXBlIHBhY2tldHMuDQpBbHNvIHRoaXMgd291bGQgYmUgKnZlcnkqIGRpZmZlcmVudCBmcm9tIFBy
b3h5LCBiZWNhdXNlIHdlIGFyZW4ndCB0YWxraW5nIHRvIGEgY3J5cHRvIHBlZXIgYmV0d2VlbiBi
bHVleiBhbmQga2VybmVsLg0KDQo+IA0KPiA+ICsNCj4gPiArSENJIE1lc2ggRGVmYXVsdCBUeCBQ
b3dlcg0KPiA+ICs9PT09PT09PT09PT09PT09PT09PT09PT09DQo+ID4gKwlDb2RlOgkweDA2DQo+
ID4gKw0KPiA+ICsJVHhfUG93ZXIJCSgxIG9jdGV0KQ0KPiA+ICsNCj4gPiArUmVhZC93cml0ZSBz
b2NrZXQgb3B0aW9uIGZvciBzZXR0aW5nIGRlZmF1bHQgVHggcG93ZXIuDQo+IA0KPiBMZWF2ZSB0
aGlzIG91dCBmb3Igbm93LiBJIGFzc3VtZSBpbml0aWFsbHkgd2Ugd2lsbCBhbHdheXMgdXNlIDEy
NyBmb3IgZG8gbm90DQo+IGNhcmUuIElmIHdlIHRoaW5rIGl0IGlzIHZhbHVhYmxlIGZvciB0ZXN0
aW5nLCB0aGVuIHZpYSBkZWJ1Z2ZzLg0KPiANCj4gPiArDQo+ID4gK0hDSSBNZXNoIERlZmF1bHQg
Q2Fobm5lbCBNYXANCj4gPiArPT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KPiA+ICsJQ29k
ZToJMHgwNw0KPiA+ICsNCj4gPiArCUNoYW5fbWFwCQkoMSBvY3RldCkNCj4gPiArDQo+ID4gK1Jl
YWQvd3JpdGUgc29ja2V0IG9wdGlvbiBmb3Igc2V0dGluZyBkZWZhdWx0IGNoYW5uZWwgbWFwLg0K
PiANCj4gQWxzbyBpcnJlbGV2YW50IGFuZCBvbmx5IGZvciBmaW5lIHR1bmluZyBhbmQgdGVzdGlu
Zy4gQ2FuIGJlIGV4cG9zZWQgdmlhDQo+IGRlYnVnZnMuDQo+IA0KPiA+ICsNCj4gPiArSENJIE1l
c2ggQWNjdXJhY3kNCj4gPiArPT09PT09PT09PT09PT09PT0NCj4gPiArCUNvZGU6CTB4MDgNCj4g
PiArDQo+ID4gKwlBY2N1cmFjeQkJKDEgb2N0ZXQpDQo+ID4gKw0KPiA+ICtSZWFkLW9ubHkgc29j
a2V0IG9wdGlvbiB0byBvYnRhaW4gdGhlIHZhbHVlIG9mIHRoZSBzbWFsbGVzdCBudW1iZXIgb2YN
Cj4gPiArbWlsbGlzZWNvbmRzIHRoYXQgYSBNZXNoIEZyaWVuZHNoaXAgT2ZmZXIgV2luZG93IGNh
biBiZSwgZm9yDQo+ID4gK2d1YXJhbnRlZWQgUG9sbCBSZXNwb25zZSB0cmFuc21pc3Npb24gd2l0
aGluIHRoYXQgd2luZG93Lg0KPiANCj4gSSBzdGlsbCB3b3VsZCBoYXZlIGRvbmUgdGhpcyB2aWEg
dHlwZSAweDAyIGFuZCBhIFBEVSBleGNoYW5nZSBwcm90b2NvbC4NCj4gTWFpbmx5IGJlY2F1c2Ug
dGhlbiBpdCBhbHNvIGJlY29tZXMgdHJhY2VhYmxlIHZpYSBidG1vbi4gU28geWVzLCBJIHdhbnQg
dGhlDQo+IG1lc2ggY2hhbm5lbCBhbHNvIGJlIGluY2x1ZGVkIGluIGJ0bW9uLg0KPiANCg0KSSB3
b3VsZCB2ZXJ5IG11Y2ggbGlrZSB0byB0YWxrIGFib3V0IHRoaXMgb25lIG92ZXIgYSBDQy4gIFRo
aXMgdmFsdWUgd2lsbCBub3QgYmUgc29tZXRoaW5nDQpzdWJqZWN0IHRvIGNoYW5nZSBvdmVyIHRo
ZSBsaWZlIG9mIHRoZSBzZXNzaW9uLCBhbmQgaWYgaXQgZG9lcyBjaGFuZ2UsIHdpbGwgd3JlYWsg
aGF2b2Mgd2l0aA0KZXhpc3RpbmcgZnJpZW5kc2hpcHMuIChUaGV5IHdpbGwgbmVlZCB0byBiZSBk
cm9wcGVkLCByZS1uZWdvdGlhdGVkLCBjYXVzaW5nIExQTnMgdG8gbG9zZSBhbGwNCm1lc3NhZ2Vz
IHF1ZXVlZCBhdCB0aGUgRnJpZW5kIGluIHRoZSBtZWFudGltZSkNCg0KPiA+ICsNCj4gPiArPT09
PT09PT09PT09PT09PT09DQo+ID4gK1R4IEFuY2lsbGFyeSBEYXRhDQo+ID4gKz09PT09PT09PT09
PT09PT09PQ0KPiA+ICsNCj4gPiArVGhlIGluZm9ybWF0aW9uIGFib3V0IHdoaWNoIHRpbWluZyBz
ZXR0aW5ncyB0byB1c2Ugd2hlbiBzZW5kaW5nIGENCj4gPiArbWVzaCBwYWNrZXQgaXMgY29udGFp
bmVkIGluIG1hbmRhdG9yeSBhbmNpbGxhcnkgZGF0YSBhY2NvbXBhbnlpbmcgdGhlDQo+ID4gK3Bh
eWxvYWQuIEV4YWN0bHkgb25lIG9mIHRoZSBmb2xsb3dpbmcgKG11dHVhbGx5IGV4Y2x1c2l2ZSkg
YW5jaWxsYXJ5DQo+ID4gK2RhdGEgdHlwZXMgbXVzdCBiZSBwcmVzZW50IHdpdGggbm9uemVybyBs
ZW5ndGggVHggcGF5bG9hZDoNCj4gPiArDQo+ID4gK01lc2ggVHJhbnNtaXQgSW5mbw0KPiA+ICs9
PT09PT09PT09PT09PT09PT09DQo+ID4gKw0KPiA+ICtjbXNnX2xldmVsICAgICBjbXNnX3R5cGUg
ICAgICAgICAgICAgY21zZ19kYXRhW10NCj4gPiArLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCj4gPiArU09MX0JMVUVUT09USCAgQlRNRVNIX1RYX0lO
Rk8gICAgICAgIFBhcmFtZXRlcnMNCj4gDQo+IEdlbmVyYWwgZm9ybWF0IHdlIHN0YXJ0ZWQgdXNp
bmcgaXMgQlRfKiBhbmQgc28gdGhpcyBzaG91bGQgYmUgQlRfTUVTSF8qDQo+IA0KPiA+ICsNCj4g
PiArCUNvZGU6CTB4MDENCj4gPiArCVBhcmFtZXRlcnM6DQo+ID4gKwkJQ291bnQJCQkoMSBvY3Rl
dCkNCj4gPiArCQlJbnRlcnZhbDoJCSgyIG9jdGV0cykNCj4gPiArCQlNaW5fUmFuZG9tX0RlbGF5
OgkoMSBvY3RldCkNCj4gPiArCQlNYXhfUmFuZG9tX0RlbGF5OgkoMSBvY3RldCkNCj4gPiArDQo+
ID4gK1RoZSByZXRyYW5zbWlzc2lvbiBwYXJhbWV0ZXJzIGZvciBhIHJlZ3VsYXIgb3V0Z29pbmcg
bWVzaCBtZXNzYWdlLg0KPiA+ICsNCj4gPiArQ291bnQgaXMgdGhlIHRvdGFsIG51bWJlciBvZiB0
aW1lcyB0byBUeC4gQSBaZXJvIG1lYW5zIFR4IFVudGlsIENhbmNlbGVkLg0KPiA+ICsNCj4gPiAr
SW50ZXJ2YWwgaXMgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgYmV0d2VlbiBlYWNoIFR4Lg0K
PiA+ICsNCj4gPiArUmFuZG9tIERlbGF5IGlzIG1pbGxpc2Vjb25kcyBhZGRlZCBiZWZvcmUgZmly
c3QgVHguDQo+ID4gKw0KPiA+ICtNZXNoIFBvbGwgVHJhbnNtaXQgSW5mbw0KPiA+ICs9PT09PT09
PT09PT09PT09PT09PT09PQ0KPiA+ICsNCj4gPiArY21zZ19sZXZlbCAgICAgY21zZ190eXBlICAg
ICAgICAgICAgICBjbXNnX2RhdGFbXQ0KPiA+ICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCj4gPiArU09MX0JMVUVUT09USCAgQlRNRVNIX1BPTExf
VFhfSU5GTyAgICBQYXJhbWV0ZXJzDQo+ID4gKw0KPiA+ICsJQ29kZToJMHgwMg0KPiA+ICsJUGFy
YW1ldGVyczoNCj4gPiArCQlTY2FuX0RlbGF5CQkoMSBvY3RldCkNCj4gPiArCQlTY2FuX0R1cmF0
aW9uCQkoMSBvY3RldCkNCj4gPiArCQlGaWx0ZXJfSWRzWzJdCQkoMiBvY3RldHMpDQo+ID4gKwkJ
TWluX1JhbmRvbV9EZWxheToJKDEgb2N0ZXQpDQo+ID4gKwkJTWF4X1JhbmRvbV9EZWxheToJKDEg
b2N0ZXQpDQo+ID4gKw0KPiA+ICtTY2FuX0RlbGF5IGRlc2NyaWJlcyB0aGUgd2FpdCBwZXJpb2Qg
dG8gYmVnaW4gc2Nhbm5pbmcgYWZ0ZXIgdGhlIFBvbGwNCj4gPiArbWVzc2FnZSBpcyBzZW50Lg0K
PiA+ICsNCj4gPiArRmlsdGVyX0lkcyBjb250YWluIElEcyBvZiB0d28gZmlsdGVycyB0aGF0IGFj
Y291bnQgZm9yIHR3byBwb3NzaWJsZQ0KPiA+ICt2YWx1ZXMgb2YgSVYgVXBkYXRlIGJpdCBpbiBl
eHBlY3RlZCBQb2xsIHJlc3BvbnNlLg0KPiA+ICsNCj4gPiArUmFuZG9tIERlbGF5IGlzIG1pbGxp
c2Vjb25kcyBhZGRlZCBiZWZvcmUgVHguDQo+ID4gKw0KPiA+ICtNZXNoIFBvbGwgUmVzcG9uc2Ug
VHJhbnNtaXQgSW5mbw0KPiA+ICs9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KPiA+
ICsNCj4gPiArY21zZ19sZXZlbCAgICAgY21zZ190eXBlICAgICAgICAgICAgICAgIGNtc2dfZGF0
YVtdDQo+ID4gKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tDQo+ID4gK1NPTF9CTFVFVE9PVEggIEJUTUVTSF9QT0xMX1JTUF9UWF9JTkZPICBQYXJh
bWV0ZXJzDQo+ID4gKw0KPiA+ICsJQ29kZToJMHgwMw0KPiA+ICsJUGFyYW1ldGVyczoNCj4gPiAr
CQlJbnN0YW50CQkoNCBvY3RldHMpDQo+ID4gKwkJRGVsYXkJCSgxIG9jdGV0KQ0KPiA+ICsNCj4g
PiArVGhlIHRpbWluZyBwYXJhbWV0ZXJzIGZvciBzZW5kaW5nIGEgZnJpZW5kIHBvbGwgcmVzcG9u
c2UuDQo+ID4gKw0KPiA+ICtJbnN0YW50IGlzIGEgNC1vY3RldCBvcGFxdWUgdmFsdWUgdGhhdCBj
b3JyZXNwb25kcyB0byB0aGUgaW5zdGFudCBhbg0KPiA+ICthc3NvY2lhdGVkIGluY29taW5nIG1l
c2ggbWVzc2FnZSB3YXMgcmVjaWV2ZWQsIGZvciB0aW1pbmcgcHVycG9zZXMuDQo+ID4gKw0KPiA+
ICtEZWxheSBkZWZpbmVzIG51bWJlciBvZiBtaWxsaXNlY29uZHMgYWZ0ZXIgdGhlIGNvcnJlc3Bv
bmRpbmcgSW5zdGFudA0KPiA+ICt0byB3YWl0IGJlZm9yZSBzZW5kaW5nIHRoaXMgVHguDQo+ID4g
Kw0KPiA+DQo+ICtfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX18NCj4gX19fX19fX19fX18NCj4gPiArDQo+ID4gK1RoZSBmb2xsb3dpbmcgYW5j
aWxsYXJ5IHR5cGVzIGFyZSBvcHRpb25hbCB3aXRoIG5vbnplcm8gbGVuZ3RoIFR4IHBheWxvYWQ6
DQo+ID4gKw0KPiA+ICtUcmFuc21pdCBQb3dlcg0KPiA+ICs9PT09PT09PT09PT09PQ0KPiA+ICsN
Cj4gPiArY21zZ19sZXZlbCAgICAgY21zZ190eXBlICAgICAgICAgICAgIGNtc2dfZGF0YVtdDQo+
ID4gKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLQ0KPiA+ICtTT0xfQkxVRVRPT1RIICBCVE1FU0hfVFhfUE9XRVJfSU5GTyAgUGFy
YW1ldGVycw0KPiA+ICsNCj4gPiArCUNvZGU6CTB4MDQNCj4gPiArCVBhcmFtZXRlcnM6DQo+ID4g
KwkJVHhfUG93ZXIJKDEgb2N0ZXQpDQo+ID4gKw0KPiA+ICtUcmFuc21pdCBwb3dlciBzZXR0aW5n
IGNhbiBiZSB1c2VkIGZvciBmaW5lciBjb250cm9sIG9uIHRoZSBvdXRib3VuZA0KPiBtZXNzYWdl
cy4NCj4gPiArSWYgbm90IHByZXNlbnQsIHVzZSBkZWZhdWx0IHZhbHVlIChidWlsdGluIG9yIGNv
bmZpZ3VyZWQgYXMgc29ja2V0IG9wdGlvbnMpLg0KPiA+ICsNCj4gPiArVHJhbnNtaXQgQ2hhbm5l
bA0KPiA+ICs9PT09PT09PT09PT09PT09DQo+ID4gK2Ntc2dfbGV2ZWwgICAgIGNtc2dfdHlwZSAg
ICAgICAgICAgICAgIGNtc2dfZGF0YVtdDQo+ID4gKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KPiA+ICtTT0xfQkxVRVRPT1RI
ICBCVE1FU0hfVFhfQ0hBTk5FTF9JTkZPICBQYXJhbWV0ZXJzDQo+ID4gKw0KPiA+ICsJQ29kZToJ
MHgwNQ0KPiA+ICsJUGFyYW1ldGVyczoNCj4gPiArCQlUeF9DaGFubmVsCSgxIG9jdGV0KQ0KPiA+
ICsNCj4gPiArVGhlIHByZXNlbmNlIG9mIHRoaXMgb3B0aW9uIHNwZWNpZmllcyB0cmFuc21pdCBj
aGFubmVsIGFuZCBhbGxvd3MgZm9yDQo+ID4gK2JldHRlciBjb250cm9sLCBlLmcuLCB0byByZXNw
b25kIG9uIHRoZSBzYW1lIGNoYW5uZWwgYXMgdGhlIG9uZSBvbg0KPiA+ICt3aGljaCBpbmNvbWlu
ZyBtZXNzYWdlIGhhcyBiZWVuIHJlY2VpdmVkLg0KPiA+ICtJZiBub3QgcHJlc2VudCwgdGhlIGRl
ZmF1bHQgdmFsdWUgd2lsbCBiZSB1c2VkIChidWlsdGluIG9yIGNvbmZpZ3VyZWQNCj4gPiArYXMg
c29ja2V0IG9wdGlvbnMpLg0KPiANCj4gRG9u4oCZdCBib3RoZXIgd2l0aCB0aGVzZSB0d28gYXQg
dGhlIG1vbWVudC4gSSB0aGluayB0aGV5IGhhdmUgbm8gdXNlIGZvciB1cw0KPiBleGNlcHQgZm9y
IGFsbG93aW5nIHNvbWUgdGVzdGluZyB2aWEgZGVidWdmcy4gVGhleSBuZWVkZWQgdG8gYmUgaW4g
dGhlIEhDSQ0KPiBzcGVjIGZvciBjb21wbGV0ZW5lc3MgYW5kIGJlY2F1c2UgeW91IGNhbiBhbHNv
IHVzZSB0aGUgSENJIHNwZWMgdG8gYnVpbGQgYQ0KPiBtZXNoIHNuaWZmZXIuDQoNCkkgYW0gZmlu
ZSBub3QgaW5jbHVkaW5nIFR4IFBvd2VyIGFuZCBDaGFubmVsIHNldHRpbmdzIGZvciBub3csIGJ1
dCB3ZSBpbmNsdWRlZCB0aGVtDQppbiBjYXNlIHdlIHdhbnRlZCAiRmluZSBDb250cm9sIiBvdmVy
IHRoZW0gaW4gdGhlIGZ1dHVyZS4uLiAgQnV0IHRoZXkgYXJlIGlnbm9yZWQgdG9kYXkuDQoNCj4g
DQo+ID4gKw0KPiA+ICsNCj4gPiArQWRkaXRpb25hbCB0aGUgYW5jaWxsYXJ5IGRhdGEgcG9ydGlv
biBtYXkgY29udGFpbiBDb250cm9sIHR5cGUgaW5mb3JtYXRpb24uDQo+ID4gKw0KPiA+ICtUaGUg
Zm9sbG93aW5nIGFyZSBDb250cm9sIGFuY2lsbGFyeSBkYXRhIHR5cGVzLCB0aGF0IG1lIGJlIHNl
bnQgd2l0aA0KPiA+ICtvciB3aXRob3V0IHBheWxvYWRzOg0KPiA+ICsNCj4gPiArU2Nhbg0KPiA+
ICs9PT09PT09DQo+ID4gK2Ntc2dfbGV2ZWwgICAgIGNtc2dfdHlwZSAgICAgICAgICAgICBjbXNn
X2RhdGFbXQ0KPiA+ICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0NCj4gPiArU09MX0JMVUVUT09USCAgQlRNRVNIX1NDQU4gICAg
ICAgICAgIFBhcmFtZXRlcnMNCj4gPiArDQo+ID4gKwlDb2RlOgkweDA2DQo+ID4gKwlQYXJhbWV0
ZXJzOg0KPiA+ICsJCUZpbHRlcl9JZHNbXQkodmFyaWFibGUpDQo+ID4gKw0KPiA+ICtUbyBlbmFi
bGUvZGlzYWJsZSBzY2FubmluZyBvZiBNZXNoIHBhY2tldHMuDQo+ID4gKw0KPiA+ICtJZiBGaWx0
ZXJfSWRzIGFycmF5IGlzIG5vbnplcm8gbGVuZ3RoLCBzdGFydCBzY2FubmluZyB3aXRoIHRoZQ0K
PiA+ICtzcGVjaWZpZWQgZmlsdGVycyAoZmlsdGVycyBhcmUgaW5pdGlhbGl6ZWQgdmlhIHNvY2tl
dCBvcHRpb25zDQo+ID4gK21lY2hhbmlzbSkuIFRoaXMgYXJyYXkgcmVwbGFjZXMgYW55IHByaW9y
IGZpbHRlcnMuDQo+ID4gKw0KPiA+ICtJZiBubyBmaWx0ZXIgSURzIGFyZSBwcmVzZW50IChpLmUu
LCB6ZXJvIGFycmF5IGxlbmd0aCksIHN0b3Agc2Nhbm5pbmcuDQo+IA0KPiBJIGRpc2xpa2UgdGhp
cy4gV2Ugc2hvdWxkIGhhdmUgYSB0eXBlIDB4MDIgY29tbWFuZCB0aGF0IHRlbGxzIHVzIHdoYXQg
a2luZCBvZg0KPiByb2xlIHdlIGFyZSBvcGVyYXRpbmcgaW4uIEFuZCBiYXNlZCBvbiB0aGF0IHNj
YW5uaW5nIGlzIGVuYWJsZWQgYnkgYmluZGluZw0KPiB0aGUgc29ja2V0IGFuZCBjbG9zaW5nIGl0
LiBPciBjaGFuZ2luZyB0aGUgcm9sZS4gVGhlIHdob2xlIGZpbHRlciBpZCBleHBvc3VyZQ0KPiBz
ZWVtcyBhIGJpdCBvZGQgdG8gbWUuIEkgcmVhbGl6ZSB0aGF0IHRoaXMgbWlnaHQgbG9vayBzaW1w
bGUsIGJ1dCBhIGZldyB0aGluZ3MNCj4gc2hvdWxkIGJlIGRvbmUgYnkgdGhlIGtlcm5lbC4gQW5k
IG1hbmFnaW5nIHRoZSBzY2FubmluZyBmaWx0ZXJzIGlzIG9uZSBvZg0KPiB0aGVtLiBTbyB3ZSBu
ZWVkIHRvIGZlZWQgdGhlIGtlcm5lbCBlbm91Z2ggZGV0YWlscyB0aGF0IGl0IGNhbiBkbyB0aGF0
DQo+IGVmZmljaWVudGx5LiBTd2FwcGluZyBmaWx0ZXJzIGFyb3VuZCBmcm9tIHVzZXJzcGFjZSBp
cyBwYWluZnVsLg0KDQpJbiBteSBvcGluaW9uLCBVc2VyIHNwYWNlIGNvbnRyb2wgb2YgdGhlIGZp
bHRlcnMgaXMgZXNzZW50aWFsLiBVbmxlc3MgdGhlIGtlcm5lbCBpcw0KaGFuZGxpbmcgQ3J5cHRv
LCB0aGVyZSBpcyBubyB3YXkgdG8ga25vdyBOSURzLCBQcm92aXNpb25pbmcgU2Vzc2lvbiBJRHMg
ZXRjLiBXaGlsZQ0KdGhlIEtlcm5lbCBoYW5kbGVzIHRoZSBkaXNjcmV0ZSB0aW1pbmcgZm9yIGlu
ZGl2aWR1YWwgcGFja2V0cywgb25seSBVc2VyIHNwYWNlIGtub3dzDQplbm91Z2ggYWJvdXQgdGhl
IGN1cnJlbnQgc3RhdGUgb2YgdGhlIE1lc2ggdG8ga25vdyB3aGF0IGZpbHRlcnMgYXJlIHJlcXVp
cmVkDQphdCBhbnkgZ2l2ZW4gdGltZS4NCg0KDQo+IA0KPiBPdGhlcndpc2Ugd2UgY291bGQganVz
dCBleHBvc2UgSENJX0NIQU5ORUxfTUVTSCBhcyBIQ0kgbWVzaA0KPiBjb21tYW5kcy4gVGhleSBh
cmUgYWxsIG11bHRpcGxleGVkIHZpYSBhIHNpbmdsZSBvcGNvZGUgYW55d2F5IGFuZCBoYXZlIGEN
Cj4gc2luZ2xlIGV2ZW50IHdpdGggYW5kIGV2ZW50IHByZWZpeC4gU28gaWYgeW91IHdhbnQgdGhp
cyBkZXRhaWxlZCBjb250cm9sIG9mIHRoZQ0KPiBIQ0kgY29tbWFuZHMsIHRoZW4gZG9u4oCZdCB0
cnkgdG8gcHV0IHRvbyBtdWNoIGtlcm5lbCBpbiBiZXR3ZWVuLiBKdXN0IGRvDQo+IHBhdGggdGhy
b3VnaCBvZiB0aGVtLg0KPiANCj4gV2UgY291bGQgZG8ganVzdCB0aGF0IGFuZCB0aGVuIGxlYXZl
IHRoZSBrZXJuZWwgcG9ydGlvbiBmb3IgdGhpcyBhbG9uZS4NCj4gTWF5YmUgaXQgaXMgd29ydGgg
d2hpbGUgdG8gZGViYXRlIHByb3MgYW5kIGNvbnMgZm9yIHRoaXMuIEl0IGlzIGFjdHVhbGx5IG5v
dCB0aGUNCj4gd29yc3QgaWRlYSB0byBnaXZlIGV4Y2x1c2l2ZSBhY2Nlc3MgdG8gdGhlIG1lc2gg
Y29tbWFuZHMuIEl0IHdvdWxkIGJlDQo+IHNpbWlsYXIgdG8gSENJX0NIQU5ORUxfVVNFUiwgYnV0
IG9ubHkgZm9yIHRoZSBtZXNoIGNvbW1hbmRzIGFuZCB3ZQ0KPiB3b3VsZCBzdHJpcCB0aGUgSENJ
IGNvbW1hbmQgaGVhZGVyIGFuZCBIQ0kgZXZlbnQgaGVhZGVyICsgZXZlbnQgcHJlZml4DQo+IG9m
ZiBpdCBzbyB0aGF0IHlvdSBqdXN0IGhhdmUgdG8gZGVhbCB3aXRoIG1lc2ggb3Bjb2RlIGFuZCBt
ZXNoIHN1YmV2ZW50DQo+IGNvZGUuDQoNCkFyZSBjdXJyZW50IHBsYW4gaXMgdG8ganVzdCBwYXNz
IHBhY2tldHMgd2Ugd2FudCBzZW50IHdpdGggYSByZXF1ZXN0ZWQgdGltaW5nLA0KYW5kIGZpbHRl
ciBpbmNvbWluZyBwYWNrZXRzIGR1cmluZyBkZXNpZ25hdGVkIFNjYW4gd2luZG93cw0KDQo+IA0K
PiBIbW1tIC4uIGl0IGdldHMgYSBiaXQgdHJpY2t5IGZvciB0aGUgY29tbWFuZCBjb21wbGV0ZSBw
b3J0aW9uIG9mIGl0LiBTbyBpdA0KPiBtaWdodCBoYXZlIHRvIGJlIHRoZSBmdWxsIEhDSSBhbnl3
YXksIGJ1dCByZXN0cmljdGVkIHRvIG9uZSBvcGNvZGUgYW5kIG9ubHkNCj4gbWF0Y2hpbmcgZXZl
bnRzIGJlaW5nIGZvcndhcmRlZC4NCg0KV2UgYXJlIG5vdCBkb2luZyAqYW55dGhpbmcqIGxpa2Ug
Q29tbWFuZCBDb21wbGV0ZSwgYW5kIEkgc3Ryb25nbHkgYXJndWUgYWdhaW5zdA0KYW55dGhpbmcg
bGlrZSBpdC4gSW4gTWVzaCBldmVyeXRoaW5nIGlzICpCZXN0IEVmZm9ydCogd2hldGhlciB3ZSBs
aWtlIGl0IG9yIG5vdC4gIENvbW1hbmQNCkNvbXBsZXRlcyBtYXkgZ3VhcmFudGVlIHRoYXQgYSBD
b250cm9sbGVyIGhhcyBkb25lIHdoYXQgd2UgYXNrLCBidXQgd2hldGhlciBpdCBoYXMNCmRvbmUg
d2hhdCB3ZSBhc2sgaXMgMTAwJSBpbW1hdGVyaWFsLCB1bmxlc3MgeW91IGhhdmUgYSB1c2UtY2Fz
ZSBkZW1vbnN0cmF0aW5nIGhvdw0KaXQgY2FuIGJlIHVzZWZ1bCBpbiBhIE1lc2ggZW52aXJvbm1l
bnQuICBUaGUgb25seSB0aGluZyB3ZSBjYXJlIGFib3V0IGlzIHdoZXRoZXIgYQ0KcmVtb3RlIGRl
dmljZSBoYXMgcmVjZWl2ZWQgb3VyIHBhY2tldHMsIG9yIHdoZXRoZXIgd2UgcmVjZWl2ZSB0aGVp
cnMuIEFsbCByZWxpYWJpbGl0eQ0KaXMgYnVpbHQgaW50byB0aGUgVXNlci1TcGFjZSBOZXR3b3Jr
IGFuZCBBY2Nlc3MgbGF5ZXJzLi4uIHVubGlrZSBBQ0wgYmFzZWQgc3lzdGVtcy4NCg0KQWxsIGZl
ZWRiYWNrIGZyb20gS2VybmVsIC0tPiBVc2VyIHNwYWNlIGNhbiBiZSBoYW5kbGVkIHdpdGggU3Rh
dHVzIGNvZGVzIHJldHVybmVkIGZyb20NCnNvY2tldCB3cml0ZXMsIG9yIHNldCBzb2NrIG9wdGlv
bnMuDQoNCg0KPiANCj4gQWN0dWFsbHkgaWYgSSBzcGluIG15IHRyYWluIG9mIHRob3VnaHRzIGZ1
cnRoZXIgbm93LCB3ZSBtaWdodCB3YW50IHRvIHB1dA0KPiBIQ0lfQ0hBTk5FTF9NRVNIIG9uIGlj
ZSBhbmQgbGVhdmUgdGhhdCBmb3Igc29tZSBmdXR1cmUgdmVyc2lvbi4gSSB0aGluaw0KPiBwcm92
aWRpbmcgc29tZSBzb3J0IG9mIGFic3RyYWN0aW9uIGFuZCBhdXRvbWF0aWMgaGFuZGxpbmcgb2Yg
c2Nhbm5pbmcgZmlsdGVycw0KPiBldGMuIGlzIGEgZ29vZCBhYnN0cmFjdGlvbiBmb3IgdGhlIGtl
cm5lbCwgYnV0IGl0IG1pZ2h0IGJlIHNvbWV0aGluZyB0aGF0IHdpbGwNCj4gdGFrZSBhIHdoaWxl
IHRvIGJlIGRlZmluZWQgYW5kIHdvcmtpbmcgY29ycmVjdGx5LiBEb2luZyB0aGUgSENJIG1lc2gN
Cj4gY29tbWFuZHMgZGlyZWN0bHkgb24gYSBzb2NrZXQgaGFzIHRoZSBjb21tYW5kIGNvbXBsZXRl
IHByb2JsZW0gYXMNCj4gc3RhdGVkIGFib3ZlIGFuZCBoYXZpbmcgeWV0IGFub3RoZXIgdmFyaWF0
aW9uIG9mIEhDSV9DSEFOTkVMX1JBVyB3aXRoDQo+IG1lc2ggSENJIGZpbHRlcnMgc2VlbXMgd3Jv
bmcgYXMgd2VsbC4gRXNwZWNpYWxseSBzaW5jZSBldmVudHVhbGx5IEkgd2FudCB0bw0KPiBoYXZl
IGFuIG9wdGlvbiB0byBkaXNhYmxlIEhDSV9DSEFOTkVMX1JBVy4gSW4gYWRkaXRpb24gaXQgd291
bGQgaGF2ZQ0KPiBiZWVuIGV4Y2x1c2l2ZSBhY2Nlc3MgdG8gbWFrZSBzdXJlIG5vdGhpbmcgZ29l
cyB3cm9uZy4NCj4gDQo+IFNvIG1heWJlIHdlIGp1c3QgZXhwb3NlIEhDSSBtZXNoIGNvbW1hbmRz
IGFzIE1HTVQgY29tbWFuZCBhbmQNCj4gTUdNVCBldmVudC4NCj4gDQo+IE1lc2ggQ29tbWFuZA0K
PiA9PT09PT09PT09PT0NCj4gDQo+IAlDb21tYW5kIENvZGU6CQkweDAwNDMNCj4gCUNvbnRyb2xs
ZXIgSW5kZXg6CTxjb250cm9sbGVyIGluZGV4Pg0KPiAJQ29tbWFuZCBQYXJhbWV0ZXJzOglPcGNv
ZGUgKDEgT2N0ZXQpDQo+IAkJCQlDb21tYW5kIHBhcmFtZXRlcnMgKFZhcmlhYmxlKQ0KPiAJUmV0
dXJuIFBhcmFtZXRlcnM6CVN0YXR1cyAoMSBPY3RldCkNCj4gCQkJCU9wY29kZSAoMSBPY3RldCkN
Cj4gCQkJCVJldHVybiBwYXJhbWV0ZXJzIChWYXJpYWJsZSkNCj4gDQo+IE1lc2ggRXZlbnQNCj4g
PT09PT09PT09PQ0KPiANCj4gCUV2ZW50IENvZGU6CQkweDAwMjYNCj4gCUNvbnRyb2xsZXIgSW5k
ZXg6CTxjb250cm9sbGVyIGluZGV4Pg0KPiAJRXZlbnQgUGFyYW1ldGVyczoJU3ViZXZlbnQgKDEg
T2N0ZXQpDQo+IAkJCQlFdmVuIHBhcmFtZXRlcnMgKHZhcmlhYmxlKQ0KPiANCj4gVGhpcyB3b3Vs
ZCBtYXAgMToxIHRvIHRoZSBIQ0kgbWVzaCBjb21tYW5kcyBhbmQgZXZlbnRzIHdpdGggdGhlIHRp
bnkNCj4gbW9kaWZpY2F0aW9uIHRoYXQgdGhlIGV2ZW50IHByZWZpeCBpcyBzdHJpcHBlZCBmcm9t
IHRoZSBNZXNoIEV2ZW50IGFuZCBub3QNCj4gcHJvdmlkZWQgYW5kIHdpdGggdGhlIE1lc2ggR2V0
IE9wdGlvbnMgY29tbWFuZCBpc3N1ZWQgaXQgd291bGQgYmUNCj4gbWFwcGVkIHRvIGV2ZW50IHBy
ZWZpeCBsZW5ndGggb2YgemVyby4NCj4gDQo+IEFuZCB0aGVuIG9ubHkgYSBzZXR0aW5ncyAxNiBN
ZXNoIHdvdWxkIGJlIG5lZWRlZC4gT3Igd2UgbWFrZSB0aGUNCj4gY29tbWFuZCBhbmQgZXZlbnQg
b25seSBhdmFpbGFibGUgd2hlbiBIQ0kgbWVzaCBjb21tYW5kcyBhcmUgYWN0dWFsbHkNCj4gc3Vw
cG9ydGVkLiBUaGF0IGlzIHNvbWV0aGluZyB0aGF0IHdvdWxkIG5lZWRzIHRvIGJlIGRpc2N1c3Np
bmcuIEluIGdlbmVyYWwsDQo+IHdlIGhhdmUgbm90IGhhZCBsaW1pdGVkIGNvbW1hbmRzIGJhc2Vk
IG9uIGhhcmR3YXJlIGZ1bmN0aW9uYWxpdHksIGJ1dA0KPiB0aGVzZSB0d28gd291bGQgYmUgc3Bl
Y2lhbCBzaW5jZSB0aGV5IGFyZSB2ZW5kb3Igc3BlY2lmaWMgY29tbWFuZHMgaW4gdGhlDQo+IGZp
cnN0IHBsYWNlLg0KPiANCj4gRm9yIHRoZSBrZXJuZWwgc2lkZSB3ZSBvbmx5IGhhdmUgdGhlIHRo
ZSBkcml2ZXIgcHJvdmlkZSB0aGUgbWVzaCBIQ0kgb3Bjb2RlDQo+IGFuZCBydW4gTWVzaCBHZXQg
T3B0aW9ucyBvbmNlIHRvIHJldHJpZXZlIHRoZSBmaXJtd2FyZXMgZXZlbnQgcHJlZml4IHNvDQo+
IHRoYXQgaXQgY2FuIGJlIHplcm9lZCBvdXQgYnkgdGhlIE1HTVQgY29tbWFuZHMgYW5kIGV2ZW50
cy4NCj4gDQo+IFdpdGggdGhhdCBjb21tZW50cz8gVGhvdWdodHM/DQo+IA0KPiBSZWdhcmRzDQo+
IA0KPiBNYXJjZWwNCj4gDQo+IC0tDQo+IFRvIHVuc3Vic2NyaWJlIGZyb20gdGhpcyBsaXN0OiBz
ZW5kIHRoZSBsaW5lICJ1bnN1YnNjcmliZSBsaW51eC1ibHVldG9vdGgiIGluDQo+IHRoZSBib2R5
IG9mIGEgbWVzc2FnZSB0byBtYWpvcmRvbW9Admdlci5rZXJuZWwub3JnIE1vcmUgbWFqb3Jkb21v
DQo+IGluZm8gYXQgIGh0dHA6Ly92Z2VyLmtlcm5lbC5vcmcvbWFqb3Jkb21vLWluZm8uaHRtbA0K
Hi Inga,
> ---
> doc/mesh-api.txt | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 269 insertions(+)
> create mode 100644 doc/mesh-api.txt
>
> diff --git a/doc/mesh-api.txt b/doc/mesh-api.txt
> new file mode 100644
> index 000000000..87311faba
> --- /dev/null
> +++ b/doc/mesh-api.txt
> @@ -0,0 +1,269 @@
> +Bluetooth Mesh Socket API
> +*************************
> +
> +Copyright (C) 2018 Intel Corporation. All rights reserved.
> +
> +This document decribes the data format that is used for communication with
> +the kernel via Bluetooth Mesh socket. The data that are passed over this
> +type of a socket is specific to Bluetooth Mesh Profile.
> +
> +The Bluetooth Mesh socket is implemented as part of PF_BLUETOOTH family
> +and can be created by opening a raw HCI socket with hci_channel set to
> +HCI_CHANNEL_BTMESH. The mesh socket requires the creating process to have
call this HCI_CHANNEL_MESH. There is no point in adding BT* here.
> +CAP_NET_ADMIN capability.
> +
> +===================================================
> +Packet Structure: user space to/from kernel (Tx/Rx)
> +===================================================
> +
> +Each packet to or from the Over-the-Air interface is sent between the user
> +space and the kernel must be of nonzero length, and start with the AD_Type,
> +followed by a variable amount of additional payload.
> +
> + 0 8
> + +---------------+------------------------------------
> + | AD_Type | Mesh Packet
> + +---------------+——————————————————
> +
Actually I would have really preferred that we followed the Proxy PDU format.
2 Bits reserved
6 Bits packet type
Variable data payload
I think that we really need the 0x02 type for configuration between the kernel and userspace.
> +AD_Type (1 octet -- Defined by the Bluetooth SIG)
> +=================
> +
> +Provisioning: 0x29 - The payload contains a Mesh Provisioning message
> +Network: 0x2A - The payload contains a Mesh Data Packet
> +Beacon: 0x2B - The payload contains a Mesh Beacon
> +
> +The AD_Type values correspond to AD types introduced in Mesh Profile
> +specification. The API is designed to support additional types.
> +
> +
> +A packet with empty (Zero-Length) payload may be sent over the socket in case
> +when only Control ancillary data is needed (e.g., Flush or Scan, defined below).
> +
> +===============
> +Socket Options
> +===============
> +
> +HCI Mesh Scan Filter
> +====================
> + Code: 0x05
> +
> + Filter_Id (1 octet)
> + Duplicates (1 octet)
> + Filter (variable length)
> +
> +Read/write socket option used to setup scan filters for mesh specific packets.
> +First octet of filter must include at least the AD_Type but may be longer to
> +include NIDs or other known data.
These ones look more like type 0x02 PDU packets. And this in particular I would have done as Add Network ID and Remove Network ID and let the kernel deal with deciding if it chooses a more global filter (since not enough filters are available) or if it can be more precise with the filtering.
> +
> +HCI Mesh Default Tx Power
> +=========================
> + Code: 0x06
> +
> + Tx_Power (1 octet)
> +
> +Read/write socket option for setting default Tx power.
Leave this out for now. I assume initially we will always use 127 for do not care. If we think it is valuable for testing, then via debugfs.
> +
> +HCI Mesh Default Cahnnel Map
> +============================
> + Code: 0x07
> +
> + Chan_map (1 octet)
> +
> +Read/write socket option for setting default channel map.
Also irrelevant and only for fine tuning and testing. Can be exposed via debugfs.
> +
> +HCI Mesh Accuracy
> +=================
> + Code: 0x08
> +
> + Accuracy (1 octet)
> +
> +Read-only socket option to obtain the value of the smallest number of
> +milliseconds that a Mesh Friendship Offer Window can be, for guaranteed
> +Poll Response transmission within that window.
I still would have done this via type 0x02 and a PDU exchange protocol. Mainly because then it also becomes traceable via btmon. So yes, I want the mesh channel also be included in btmon.
> +
> +==================
> +Tx Ancillary Data
> +==================
> +
> +The information about which timing settings to use when sending a mesh
> +packet is contained in mandatory ancillary data accompanying the
> +payload. Exactly one of the following (mutually exclusive) ancillary
> +data types must be present with nonzero length Tx payload:
> +
> +Mesh Transmit Info
> +===================
> +
> +cmsg_level cmsg_type cmsg_data[]
> +--------------------------------------------------
> +SOL_BLUETOOTH BTMESH_TX_INFO Parameters
General format we started using is BT_* and so this should be BT_MESH_*
> +
> + Code: 0x01
> + Parameters:
> + Count (1 octet)
> + Interval: (2 octets)
> + Min_Random_Delay: (1 octet)
> + Max_Random_Delay: (1 octet)
> +
> +The retransmission parameters for a regular outgoing mesh message.
> +
> +Count is the total number of times to Tx. A Zero means Tx Until Canceled.
> +
> +Interval is the number of milliseconds between each Tx.
> +
> +Random Delay is milliseconds added before first Tx.
> +
> +Mesh Poll Transmit Info
> +=======================
> +
> +cmsg_level cmsg_type cmsg_data[]
> +---------------------------------------------------
> +SOL_BLUETOOTH BTMESH_POLL_TX_INFO Parameters
> +
> + Code: 0x02
> + Parameters:
> + Scan_Delay (1 octet)
> + Scan_Duration (1 octet)
> + Filter_Ids[2] (2 octets)
> + Min_Random_Delay: (1 octet)
> + Max_Random_Delay: (1 octet)
> +
> +Scan_Delay describes the wait period to begin scanning after the Poll message
> +is sent.
> +
> +Filter_Ids contain IDs of two filters that account for two possible values of
> +IV Update bit in expected Poll response.
> +
> +Random Delay is milliseconds added before Tx.
> +
> +Mesh Poll Response Transmit Info
> +================================
> +
> +cmsg_level cmsg_type cmsg_data[]
> +-----------------------------------------------------
> +SOL_BLUETOOTH BTMESH_POLL_RSP_TX_INFO Parameters
> +
> + Code: 0x03
> + Parameters:
> + Instant (4 octets)
> + Delay (1 octet)
> +
> +The timing parameters for sending a friend poll response.
> +
> +Instant is a 4-octet opaque value that corresponds to the instant an
> +associated incoming mesh message was recieved, for timing purposes.
> +
> +Delay defines number of milliseconds after the corresponding Instant
> +to wait before sending this Tx.
> +
> +____________________________________________________________________
> +
> +The following ancillary types are optional with nonzero length Tx payload:
> +
> +Transmit Power
> +==============
> +
> +cmsg_level cmsg_type cmsg_data[]
> +---------------------------------------------------------------
> +SOL_BLUETOOTH BTMESH_TX_POWER_INFO Parameters
> +
> + Code: 0x04
> + Parameters:
> + Tx_Power (1 octet)
> +
> +Transmit power setting can be used for finer control on the outbound messages.
> +If not present, use default value (builtin or configured as socket options).
> +
> +Transmit Channel
> +================
> +cmsg_level cmsg_type cmsg_data[]
> +---------------------------------------------------------------
> +SOL_BLUETOOTH BTMESH_TX_CHANNEL_INFO Parameters
> +
> + Code: 0x05
> + Parameters:
> + Tx_Channel (1 octet)
> +
> +The presence of this option specifies transmit channel and allows
> +for better control, e.g., to respond on the same
> +channel as the one on which incoming message has been received.
> +If not present, the default value will be used (builtin or configured as
> +socket options).
Don’t bother with these two at the moment. I think they have no use for us except for allowing some testing via debugfs. They needed to be in the HCI spec for completeness and because you can also use the HCI spec to build a mesh sniffer.
> +
> +
> +Additional the ancillary data portion may contain Control type information.
> +
> +The following are Control ancillary data types, that me be sent with or
> +without payloads:
> +
> +Scan
> +=======
> +cmsg_level cmsg_type cmsg_data[]
> +---------------------------------------------------------------
> +SOL_BLUETOOTH BTMESH_SCAN Parameters
> +
> + Code: 0x06
> + Parameters:
> + Filter_Ids[] (variable)
> +
> +To enable/disable scanning of Mesh packets.
> +
> +If Filter_Ids array is nonzero length, start scanning with the specified
> +filters (filters are initialized via socket options mechanism). This array
> +replaces any prior filters.
> +
> +If no filter IDs are present (i.e., zero array length), stop scanning.
I dislike this. We should have a type 0x02 command that tells us what kind of role we are operating in. And based on that scanning is enabled by binding the socket and closing it. Or changing the role. The whole filter id exposure seems a bit odd to me. I realize that this might look simple, but a few things should be done by the kernel. And managing the scanning filters is one of them. So we need to feed the kernel enough details that it can do that efficiently. Swapping filters around from userspace is painful.
Otherwise we could just expose HCI_CHANNEL_MESH as HCI mesh commands. They are all multiplexed via a single opcode anyway and have a single event with and event prefix. So if you want this detailed control of the HCI commands, then don’t try to put too much kernel in between. Just do path through of them.
We could do just that and then leave the kernel portion for this alone. Maybe it is worth while to debate pros and cons for this. It is actually not the worst idea to give exclusive access to the mesh commands. It would be similar to HCI_CHANNEL_USER, but only for the mesh commands and we would strip the HCI command header and HCI event header + event prefix off it so that you just have to deal with mesh opcode and mesh subevent code.
Hmmm .. it gets a bit tricky for the command complete portion of it. So it might have to be the full HCI anyway, but restricted to one opcode and only matching events being forwarded.
Actually if I spin my train of thoughts further now, we might want to put HCI_CHANNEL_MESH on ice and leave that for some future version. I think providing some sort of abstraction and automatic handling of scanning filters etc. is a good abstraction for the kernel, but it might be something that will take a while to be defined and working correctly. Doing the HCI mesh commands directly on a socket has the command complete problem as stated above and having yet another variation of HCI_CHANNEL_RAW with mesh HCI filters seems wrong as well. Especially since eventually I want to have an option to disable HCI_CHANNEL_RAW. In addition it would have been exclusive access to make sure nothing goes wrong.
So maybe we just expose HCI mesh commands as MGMT command and MGMT event.
Mesh Command
============
Command Code: 0x0043
Controller Index: <controller index>
Command Parameters: Opcode (1 Octet)
Command parameters (Variable)
Return Parameters: Status (1 Octet)
Opcode (1 Octet)
Return parameters (Variable)
Mesh Event
==========
Event Code: 0x0026
Controller Index: <controller index>
Event Parameters: Subevent (1 Octet)
Even parameters (variable)
This would map 1:1 to the HCI mesh commands and events with the tiny modification that the event prefix is stripped from the Mesh Event and not provided and with the Mesh Get Options command issued it would be mapped to event prefix length of zero.
And then only a settings 16 Mesh would be needed. Or we make the command and event only available when HCI mesh commands are actually supported. That is something that would needs to be discussing. In general, we have not had limited commands based on hardware functionality, but these two would be special since they are vendor specific commands in the first place.
For the kernel side we only have the the driver provide the mesh HCI opcode and run Mesh Get Options once to retrieve the firmwares event prefix so that it can be zeroed out by the MGMT commands and events.
With that comments? Thoughts?
Regards
Marcel
---
doc/mesh-api.txt | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 269 insertions(+)
create mode 100644 doc/mesh-api.txt
diff --git a/doc/mesh-api.txt b/doc/mesh-api.txt
new file mode 100644
index 000000000..87311faba
--- /dev/null
+++ b/doc/mesh-api.txt
@@ -0,0 +1,269 @@
+Bluetooth Mesh Socket API
+*************************
+
+Copyright (C) 2018 Intel Corporation. All rights reserved.
+
+This document decribes the data format that is used for communication with
+the kernel via Bluetooth Mesh socket. The data that are passed over this
+type of a socket is specific to Bluetooth Mesh Profile.
+
+The Bluetooth Mesh socket is implemented as part of PF_BLUETOOTH family
+and can be created by opening a raw HCI socket with hci_channel set to
+HCI_CHANNEL_BTMESH. The mesh socket requires the creating process to have
+CAP_NET_ADMIN capability.
+
+===================================================
+Packet Structure: user space to/from kernel (Tx/Rx)
+===================================================
+
+Each packet to or from the Over-the-Air interface is sent between the user
+space and the kernel must be of nonzero length, and start with the AD_Type,
+followed by a variable amount of additional payload.
+
+ 0 8
+ +---------------+------------------------------------
+ | AD_Type | Mesh Packet
+ +---------------+------------------------------------
+
+AD_Type (1 octet -- Defined by the Bluetooth SIG)
+=================
+
+Provisioning: 0x29 - The payload contains a Mesh Provisioning message
+Network: 0x2A - The payload contains a Mesh Data Packet
+Beacon: 0x2B - The payload contains a Mesh Beacon
+
+The AD_Type values correspond to AD types introduced in Mesh Profile
+specification. The API is designed to support additional types.
+
+
+A packet with empty (Zero-Length) payload may be sent over the socket in case
+when only Control ancillary data is needed (e.g., Flush or Scan, defined below).
+
+===============
+Socket Options
+===============
+
+HCI Mesh Scan Filter
+====================
+ Code: 0x05
+
+ Filter_Id (1 octet)
+ Duplicates (1 octet)
+ Filter (variable length)
+
+Read/write socket option used to setup scan filters for mesh specific packets.
+First octet of filter must include at least the AD_Type but may be longer to
+include NIDs or other known data.
+
+HCI Mesh Default Tx Power
+=========================
+ Code: 0x06
+
+ Tx_Power (1 octet)
+
+Read/write socket option for setting default Tx power.
+
+HCI Mesh Default Cahnnel Map
+============================
+ Code: 0x07
+
+ Chan_map (1 octet)
+
+Read/write socket option for setting default channel map.
+
+HCI Mesh Accuracy
+=================
+ Code: 0x08
+
+ Accuracy (1 octet)
+
+Read-only socket option to obtain the value of the smallest number of
+milliseconds that a Mesh Friendship Offer Window can be, for guaranteed
+Poll Response transmission within that window.
+
+==================
+Tx Ancillary Data
+==================
+
+The information about which timing settings to use when sending a mesh
+packet is contained in mandatory ancillary data accompanying the
+payload. Exactly one of the following (mutually exclusive) ancillary
+data types must be present with nonzero length Tx payload:
+
+Mesh Transmit Info
+===================
+
+cmsg_level cmsg_type cmsg_data[]
+--------------------------------------------------
+SOL_BLUETOOTH BTMESH_TX_INFO Parameters
+
+ Code: 0x01
+ Parameters:
+ Count (1 octet)
+ Interval: (2 octets)
+ Min_Random_Delay: (1 octet)
+ Max_Random_Delay: (1 octet)
+
+The retransmission parameters for a regular outgoing mesh message.
+
+Count is the total number of times to Tx. A Zero means Tx Until Canceled.
+
+Interval is the number of milliseconds between each Tx.
+
+Random Delay is milliseconds added before first Tx.
+
+Mesh Poll Transmit Info
+=======================
+
+cmsg_level cmsg_type cmsg_data[]
+---------------------------------------------------
+SOL_BLUETOOTH BTMESH_POLL_TX_INFO Parameters
+
+ Code: 0x02
+ Parameters:
+ Scan_Delay (1 octet)
+ Scan_Duration (1 octet)
+ Filter_Ids[2] (2 octets)
+ Min_Random_Delay: (1 octet)
+ Max_Random_Delay: (1 octet)
+
+Scan_Delay describes the wait period to begin scanning after the Poll message
+is sent.
+
+Filter_Ids contain IDs of two filters that account for two possible values of
+IV Update bit in expected Poll response.
+
+Random Delay is milliseconds added before Tx.
+
+Mesh Poll Response Transmit Info
+================================
+
+cmsg_level cmsg_type cmsg_data[]
+-----------------------------------------------------
+SOL_BLUETOOTH BTMESH_POLL_RSP_TX_INFO Parameters
+
+ Code: 0x03
+ Parameters:
+ Instant (4 octets)
+ Delay (1 octet)
+
+The timing parameters for sending a friend poll response.
+
+Instant is a 4-octet opaque value that corresponds to the instant an
+associated incoming mesh message was recieved, for timing purposes.
+
+Delay defines number of milliseconds after the corresponding Instant
+to wait before sending this Tx.
+
+____________________________________________________________________
+
+The following ancillary types are optional with nonzero length Tx payload:
+
+Transmit Power
+==============
+
+cmsg_level cmsg_type cmsg_data[]
+---------------------------------------------------------------
+SOL_BLUETOOTH BTMESH_TX_POWER_INFO Parameters
+
+ Code: 0x04
+ Parameters:
+ Tx_Power (1 octet)
+
+Transmit power setting can be used for finer control on the outbound messages.
+If not present, use default value (builtin or configured as socket options).
+
+Transmit Channel
+================
+cmsg_level cmsg_type cmsg_data[]
+---------------------------------------------------------------
+SOL_BLUETOOTH BTMESH_TX_CHANNEL_INFO Parameters
+
+ Code: 0x05
+ Parameters:
+ Tx_Channel (1 octet)
+
+The presence of this option specifies transmit channel and allows
+for better control, e.g., to respond on the same
+channel as the one on which incoming message has been received.
+If not present, the default value will be used (builtin or configured as
+socket options).
+
+
+Additional the ancillary data portion may contain Control type information.
+
+The following are Control ancillary data types, that me be sent with or
+without payloads:
+
+Scan
+=======
+cmsg_level cmsg_type cmsg_data[]
+---------------------------------------------------------------
+SOL_BLUETOOTH BTMESH_SCAN Parameters
+
+ Code: 0x06
+ Parameters:
+ Filter_Ids[] (variable)
+
+To enable/disable scanning of Mesh packets.
+
+If Filter_Ids array is nonzero length, start scanning with the specified
+filters (filters are initialized via socket options mechanism). This array
+replaces any prior filters.
+
+If no filter IDs are present (i.e., zero array length), stop scanning.
+
+
+Flush
+=======
+cmsg_level cmsg_type cmsg_data[]
+---------------------------------------------------------------
+SOL_BLUETOOTH BTMESH_TX_FLUSH Parameters
+
+ Code: 0x06
+ Parameters:
+ Pattern (variable)
+
+Cancel and Flush all the pending Tx mesh packets that match the specified
+pattern, including the AD Type.
+
+If only the AD Type is present, all outgoing packets of that type will
+be flushed.
+
+If no pattern is present (i.e., zero pattern length), flush all pending Tx
+packets.
+
+
+=================
+Rx Ancillary Data
+=================
+
+Receive Message Info
+====================
+
+cmsg_level cmsg_type cmsg_data[]
+------------------------------------------------------------------------
+SOL_BLUETOOTH BTMESH_RECV_MSG_INFO (Recv Message Info Parameters)
+
+ Code: 0x04
+ Parameters:
+ Instant (4 octets)
+ Channel (1 octet)
+ RSSI (1 octet)
+
+
+Instant is an opaque 4-octet value that can be included in
+BTMESH_POLL_RSP_TX_INFO ancilary data to accurately time Poll
+Response delays
+
+Channel indicates which channel packet received on or Zero if unknown
+
+RSSI indicates the signal strength of the received packet
+
+--------------------------------------------------------------------------
+
+The socket API follows "best effort" approach for user space / kernel interface:
+there is no asynchronous feedback on status of the data sent over the socket.
+
+All multi-octet fields are in little-endian byte order (least significant byte
+first).
--
2.13.6
Hi Marcel,
On Wed, 2018-02-28 at 21:51 +0100, Marcel Holtmann wrote:
> Hi Inga,
>
> > > > ---
> > > > doc/mesh-api.txt | 269
> > > > +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > 1 file changed, 269 insertions(+)
> > > > create mode 100644 doc/mesh-api.txt
> > > >
> > > > diff --git a/doc/mesh-api.txt b/doc/mesh-api.txt
> > > > new file mode 100644
> > > > index 000000000..87311faba
> > > > --- /dev/null
> > > > +++ b/doc/mesh-api.txt
> > > > @@ -0,0 +1,269 @@
> > > > +Bluetooth Mesh Socket API
> > > > +*************************
> > > > +
> > > > +Copyright (C) 2018 Intel Corporation. All rights reserved.
> > > > +
> > > > +This document decribes the data format that is used for
> > > > communication with
> > > > +the kernel via Bluetooth Mesh socket. The data that are passed
> > > > over this
> > > > +type of a socket is specific to Bluetooth Mesh Profile.
> > > > +
> > > > +The Bluetooth Mesh socket is implemented as part of
> > > > PF_BLUETOOTH
> > > > family
> > > > +and can be created by opening a raw HCI socket with
> > > > hci_channel
> > > > set to
> > > > +HCI_CHANNEL_BTMESH. The mesh socket requires the creating
> > > > process
> > > > to have
> > >
> > > call this HCI_CHANNEL_MESH. There is no point in adding BT* here.
> > >
> > > > +CAP_NET_ADMIN capability.
> > > > +
> > > > +===================================================
> > > > +Packet Structure: user space to/from kernel (Tx/Rx)
> > > > +===================================================
> > > > +
> > > > +Each packet to or from the Over-the-Air interface is sent
> > > > between
> > > > the user
> > > > +space and the kernel must be of nonzero length, and start with
> > > > the
> > > > AD_Type,
> > > > +followed by a variable amount of additional payload.
> > > > +
> > > > + 0 8
> > > > + +---------------+------------------------------------
> > > > + | AD_Type | Mesh Packet
> > > > + +---------------+——————————————————
> > > > +
> > >
> > > Actually I would have really preferred that we followed the Proxy
> > > PDU
> > > format.
> > >
> > > 2 Bits reserved
> > > 6 Bits packet type
> > > Variable data payload
> > >
> > > I think that we really need the 0x02 type for configuration
> > > between
> > > the kernel and userspace.
> >
> > The idea is to allow the data payload to be identical to the mesh
> > message that would go over the air. Hence, everything that is not
> > part
> > of the actual mesh message ends up in either cmsg or sockopt.
> > Introducing 0x2 "configuration" type will break this paradigm since
> > the
> > configuration for mesh does not map directly to configuration for
> > Proxy.
> >
> >
> > > > +AD_Type (1 octet -- Defined by the Bluetooth SIG)
> > > > +=================
> > > > +
> > > > +Provisioning: 0x29 - The payload contains a Mesh
> > > > Provisioning message
> > > > +Network: 0x2A - The payload contains a
> > > > Mesh
> > > > Data Packet
> > > > +Beacon: 0x2B - The payload contains a
> > > > Mesh
> > > > Beacon
> > > > +
> > > > +The AD_Type values correspond to AD types introduced in Mesh
> > > > Profile
> > > > +specification. The API is designed to support additional
> > > > types.
> > > > +
> > > > +
> > > > +A packet with empty (Zero-Length) payload may be sent over the
> > > > socket in case
> > > > +when only Control ancillary data is needed (e.g., Flush or
> > > > Scan,
> > > > defined below).
> > > > +
> > > > +===============
> > > > +Socket Options
> > > > +===============
> > > > +
> > > > +HCI Mesh Scan Filter
> > > > +====================
> > > > + Code: 0x05
> > > > +
> > > > + Filter_Id (1 octet)
> > > > + Duplicates (1 octet)
> > > > + Filter (variable length)
> > > > +
> > > > +Read/write socket option used to setup scan filters for mesh
> > > > specific packets.
> > > > +First octet of filter must include at least the AD_Type but
> > > > may be
> > > > longer to
> > > > +include NIDs or other known data.
> > >
> > > These ones look more like type 0x02 PDU packets. And this in
> > > particular I would have done as Add Network ID and Remove Network
> > > ID
> > > and let the kernel deal with deciding if it chooses a more global
> > > filter (since not enough filters are available) or if it can be
> > > more
> > > precise with the filtering.
> > >
> >
> > This is a once in awhile operation, so It felt like socket option
> > seems
> > like a better place for it. It could be made more user friendly at
> > the
> > expense of losing flexibility in future of adding filtering on
> > additional AD Types.
> >
> > > > +
> > > > +HCI Mesh Default Tx Power
> > > > +=========================
> > > > + Code: 0x06
> > > > +
> > > > + Tx_Power (1 octet)
> > > > +
> > > > +Read/write socket option for setting default Tx power.
> > >
> > > Leave this out for now. I assume initially we will always use 127
> > > for
> > > do not care. If we think it is valuable for testing, then via
> > > debugfs.
> > >
> >
> > I agree. No use for this at the moment.
> >
> > > > +
> > > > +HCI Mesh Default Cahnnel Map
> > > > +============================
> > > > + Code: 0x07
> > > > +
> > > > + Chan_map (1 octet)
> > > > +
> > > > +Read/write socket option for setting default channel map.
> > >
> > > Also irrelevant and only for fine tuning and testing. Can be
> > > exposed
> > > via debugfs.
> > >
> >
> > Agreed.
> >
> > > > +
> > > > +HCI Mesh Accuracy
> > > > +=================
> > > > + Code: 0x08
> > > > +
> > > > + Accuracy (1 octet)
> > > > +
> > > > +Read-only socket option to obtain the value of the smallest
> > > > number
> > > > of
> > > > +milliseconds that a Mesh Friendship Offer Window can be, for
> > > > guaranteed
> > > > +Poll Response transmission within that window.
> > >
> > > I still would have done this via type 0x02 and a PDU exchange
> > > protocol. Mainly because then it also becomes traceable via
> > > btmon. So
> > > yes, I want the mesh channel also be included in btmon.
> > >
> > > > +
> > > > +==================
> > > > +Tx Ancillary Data
> > > > +==================
> > > > +
> > > > +The information about which timing settings to use when
> > > > sending a
> > > > mesh
> > > > +packet is contained in mandatory ancillary data accompanying
> > > > the
> > > > +payload. Exactly one of the following (mutually exclusive)
> > > > ancillary
> > > > +data types must be present with nonzero length Tx payload:
> > > > +
> > > > +Mesh Transmit Info
> > > > +===================
> > > > +
> > > > +cmsg_level cmsg_type cmsg_data[]
> > > > +--------------------------------------------------
> > > > +SOL_BLUETOOTH BTMESH_TX_INFO Parameters
> > >
> > > General format we started using is BT_* and so this should be
> > > BT_MESH_*
> > >
> > > > +
> > > > + Code: 0x01
> > > > + Parameters:
> > > > + Count (1 octet)
> > > > + Interval: (2 octets)
> > > > + Min_Random_Delay: (1 octet)
> > > > + Max_Random_Delay: (1 octet)
> > > > +
> > > > +The retransmission parameters for a regular outgoing mesh
> > > > message.
> > > > +
> > > > +Count is the total number of times to Tx. A Zero means Tx
> > > > Until
> > > > Canceled.
> > > > +
> > > > +Interval is the number of milliseconds between each Tx.
> > > > +
> > > > +Random Delay is milliseconds added before first Tx.
> > > > +
> > > > +Mesh Poll Transmit Info
> > > > +=======================
> > > > +
> > > > +cmsg_level cmsg_type cmsg_data[]
> > > > +---------------------------------------------------
> > > > +SOL_BLUETOOTH BTMESH_POLL_TX_INFO Parameters
> > > > +
> > > > + Code: 0x02
> > > > + Parameters:
> > > > + Scan_Delay (1 octet)
> > > > + Scan_Duration (1 octet)
> > > > + Filter_Ids[2] (2 octets)
> > > > + Min_Random_Delay: (1 octet)
> > > > + Max_Random_Delay: (1 octet)
> > > > +
> > > > +Scan_Delay describes the wait period to begin scanning after
> > > > the
> > > > Poll message
> > > > +is sent.
> > > > +
> > > > +Filter_Ids contain IDs of two filters that account for two
> > > > possible values of
> > > > +IV Update bit in expected Poll response.
> > > > +
> > > > +Random Delay is milliseconds added before Tx.
> > > > +
> > > > +Mesh Poll Response Transmit Info
> > > > +================================
> > > > +
> > > > +cmsg_level cmsg_type cmsg_data[]
> > > > +-----------------------------------------------------
> > > > +SOL_BLUETOOTH BTMESH_POLL_RSP_TX_INFO Parameters
> > > > +
> > > > + Code: 0x03
> > > > + Parameters:
> > > > + Instant (4 octets)
> > > > + Delay (1 octet)
> > > > +
> > > > +The timing parameters for sending a friend poll response.
> > > > +
> > > > +Instant is a 4-octet opaque value that corresponds to the
> > > > instant
> > > > an
> > > > +associated incoming mesh message was recieved, for timing
> > > > purposes.
> > > > +
> > > > +Delay defines number of milliseconds after the corresponding
> > > > Instant
> > > > +to wait before sending this Tx.
> > > > +
> > > > +______________________________________________________________
> > > > ____
> > > > __
> > > > +
> > > > +The following ancillary types are optional with nonzero length
> > > > Tx
> > > > payload:
> > > > +
> > > > +Transmit Power
> > > > +==============
> > > > +
> > > > +cmsg_level cmsg_type cmsg_data[]
> > > > +------------------------------------------------------------
> > > > ---
> > > > +SOL_BLUETOOTH BTMESH_TX_POWER_INFO Parameters
> > > > +
> > > > + Code: 0x04
> > > > + Parameters:
> > > > + Tx_Power (1 octet)
> > > > +
> > > > +Transmit power setting can be used for finer control on the
> > > > outbound messages.
> > > > +If not present, use default value (builtin or configured as
> > > > socket
> > > > options).
> > > > +
> > > > +Transmit Channel
> > > > +================
> > > > +cmsg_level cmsg_type cmsg_data[]
> > > > +------------------------------------------------------------
> > > > ---
> > > > +SOL_BLUETOOTH BTMESH_TX_CHANNEL_INFO Parameters
> > > > +
> > > > + Code: 0x05
> > > > + Parameters:
> > > > + Tx_Channel (1 octet)
> > > > +
> > > > +The presence of this option specifies transmit channel and
> > > > allows
> > > > +for better control, e.g., to respond on the same
> > > > +channel as the one on which incoming message has been
> > > > received.
> > > > +If not present, the default value will be used (builtin or
> > > > configured as
> > > > +socket options).
> > >
> > > Don’t bother with these two at the moment. I think they have no
> > > use
> > > for us except for allowing some testing via debugfs. They needed
> > > to
> > > be in the HCI spec for completeness and because you can also use
> > > the
> > > HCI spec to build a mesh sniffer.
> > >
> > > > +
> > > > +
> > > > +Additional the ancillary data portion may contain Control type
> > > > information.
> > > > +
> > > > +The following are Control ancillary data types, that me be
> > > > sent
> > > > with or
> > > > +without payloads:
> > > > +
> > > > +Scan
> > > > +=======
> > > > +cmsg_level cmsg_type cmsg_data[]
> > > > +------------------------------------------------------------
> > > > ---
> > > > +SOL_BLUETOOTH BTMESH_SCAN Parameters
> > > > +
> > > > + Code: 0x06
> > > > + Parameters:
> > > > + Filter_Ids[] (variable)
> > > > +
> > > > +To enable/disable scanning of Mesh packets.
> > > > +
> > > > +If Filter_Ids array is nonzero length, start scanning with the
> > > > specified
> > > > +filters (filters are initialized via socket options
> > > > mechanism).
> > > > This array
> > > > +replaces any prior filters.
> > > > +
> > > > +If no filter IDs are present (i.e., zero array length), stop
> > > > scanning.
> > >
> > > I dislike this. We should have a type 0x02 command that tells us
> > > what
> > > kind of role we are operating in. And based on that scanning is
> > > enabled by binding the socket and closing it. Or changing the
> > > role.
> > > The whole filter id exposure seems a bit odd to me. I realize
> > > that
> > > this might look simple, but a few things should be done by the
> > > kernel. And managing the scanning filters is one of them. So we
> > > need
> > > to feed the kernel enough details that it can do that
> > > efficiently.
> > > Swapping filters around from userspace is painful.
> > >
> >
> > Adding filters should remain dynamic, e.g., when a new network key
> > is
> > added (or looking forward, new AD Type).
> >
> > > Otherwise we could just expose HCI_CHANNEL_MESH as HCI mesh
> > > commands.
> > > They are all multiplexed via a single opcode anyway and have a
> > > single
> > > event with and event prefix. So if you want this detailed control
> > > of
> > > the HCI commands, then don’t try to put too much kernel in
> > > between.
> > > Just do path through of them.
> > >
> > > We could do just that and then leave the kernel portion for this
> > > alone. Maybe it is worth while to debate pros and cons for this.
> > > It
> > > is actually not the worst idea to give exclusive access to the
> > > mesh
> > > commands. It would be similar to HCI_CHANNEL_USER, but only for
> > > the
> > > mesh commands and we would strip the HCI command header and HCI
> > > event
> > > header + event prefix off it so that you just have to deal with
> > > mesh
> > > opcode and mesh subevent code.
> > >
> > > Hmmm .. it gets a bit tricky for the command complete portion of
> > > it.
> > > So it might have to be the full HCI anyway, but restricted to one
> > > opcode and only matching events being forwarded.
> > >
> > > Actually if I spin my train of thoughts further now, we might
> > > want to
> > > put HCI_CHANNEL_MESH on ice and leave that for some future
> > > version. I
> > > think providing some sort of abstraction and automatic handling
> > > of
> > > scanning filters etc. is a good abstraction for the kernel, but
> > > it
> > > might be something that will take a while to be defined and
> > > working
> > > correctly. Doing the HCI mesh commands directly on a socket has
> > > the
> > > command complete problem as stated above and having yet another
> > > variation of HCI_CHANNEL_RAW with mesh HCI filters seems wrong as
> > > well. Especially since eventually I want to have an option to
> > > disable
> > > HCI_CHANNEL_RAW. In addition it would have been exclusive access
> > > to
> > > make sure nothing goes wrong.
> > >
> > > So maybe we just expose HCI mesh commands as MGMT command and
> > > MGMT
> > > event.
> > >
> > > Mesh Command
> > > ============
> > >
> > > Command Code: 0x0043
> > > Controller Index: <controller index>
> > > Command Parameters: Opcode (1 Octet)
> > > Command parameters (Variable)
> > > Return Parameters: Status (1 Octet)
> > > Opcode (1 Octet)
> > > Return parameters (Variable)
> > >
> > > Mesh Event
> > > ==========
> > >
> > > Event Code: 0x0026
> > > Controller Index: <controller index>
> > > Event Parameters: Subevent (1 Octet)
> > > Even parameters (variable)
> > >
> > > This would map 1:1 to the HCI mesh commands and events with the
> > > tiny
> > > modification that the event prefix is stripped from the Mesh
> > > Event
> > > and not provided and with the Mesh Get Options command issued it
> > > would be mapped to event prefix length of zero.
> > >
> > > And then only a settings 16 Mesh would be needed. Or we make the
> > > command and event only available when HCI mesh commands are
> > > actually
> > > supported. That is something that would needs to be discussing.
> > > In
> > > general, we have not had limited commands based on hardware
> > > functionality, but these two would be special since they are
> > > vendor
> > > specific commands in the first place.
> > >
> > > For the kernel side we only have the the driver provide the mesh
> > > HCI
> > > opcode and run Mesh Get Options once to retrieve the firmwares
> > > event
> > > prefix so that it can be zeroed out by the MGMT commands and
> > > events.
> > >
> > > With that comments? Thoughts?
> >
> > Well, while this approach could work. The advantage is the access
> > to
> > command complete and comand status events. But then having an
> > independent mesh daemon (also ell based) may become problematic.
> > Also, putting actual mesh access layer messages via management
> > socket
> > is a bit questionable: my understanding is that mgmt socket is
> > mainly
> > for control and configuration messsages.
>
> putting it in a separate daemon is not a problem actually. The kernel
> will handle that just fine. We can easily have two control sockets
> open at the same. We might want to add an extra handling that mesh
> events only go to one specific socket and not all of them. I will
> think about this for a bit, but we have done that before with the
> extended controller events and the kernel can already handle that
> nicely. That code is already present.
>
> The only reason why this might be useful is that we decide to use the
> HCI mesh commands / events as a base interface. And this comes mainly
> from the comments that the mesh daemon will require tight control
> over the filters. If the kernel turns into a passthrough anyway, then
> way not make it really simple for the kernel code. So mgmt API is
> suppose to be parts of GAP and handle certain things that are
> transactional on HCI. I can convince myself that with HCI mesh API
> this is the same, but that there is just nothing to do except figure
> out the event prefix. So it would become super lightweight for the
> kernel.
>
> If we base everything around the HCI mesh commands / events, then
> switching from Mesh MGMT to HCI_CHANNEL_USER is dead simple and only
> needs a minimal shim for transport abstraction. Maybe this is
> actually an advantage.
>
> One thing that I really like is that mgmt is already include in btmon
> tracing. So we would get that for free. The one thing that I didn’t
> consider enough is that with CMSG usage, we loose an easy way of
> being able to trace all the packets and parameters. It is such a
> powerful feature, that I am not in favor of missing it.
>
> Regards
>
> Marcel
>
We could move scan, add filters and flush into mgmt socket since these
are really control commands. I am still very much in favor of having a
separate socket with HCI_CHANNEL_MESH for actual mesh data tx/rx: CMSG
mechanism is well suited for having timing tightly coupled with the
data payload.
As for btmon tracing, we can add prefixes for cmd mesh packet.
Capturing mesh event will require extra processing in any case, which
is doable.
Regards,
Inga