Skip to content

Conversation

@vChavezB
Copy link
Contributor

@vChavezB vChavezB commented Aug 22, 2023

After conducting tests with a a virtual Bluetooth controller over TCP it was noticed that some HCI packets may arrive on the same buffer if sent over a short period of time.
This update ensures the hci packets are parsed correctly in the case multiple packets are in the same recieving buffer according to how HCI packets are decoded in the Bluetooth Spec v5.2 Part E.

This should fix #61762

Open for suggestions and discussion on how to address this the best way.

@vChavezB vChavezB force-pushed the bt_userchan_hci_packet_fix branch 9 times, most recently from 1afe8e4 to 40bd425 Compare August 22, 2023 22:28
@vChavezB vChavezB marked this pull request as ready for review August 26, 2023 08:34
@zephyrbot zephyrbot added area: Bluetooth Host Bluetooth Host (excluding BR/EDR) area: Bluetooth labels Aug 26, 2023
@vChavezB vChavezB force-pushed the bt_userchan_hci_packet_fix branch 6 times, most recently from e35b5ca to 35cc0d2 Compare August 28, 2023 13:25
@vChavezB vChavezB force-pushed the bt_userchan_hci_packet_fix branch 2 times, most recently from 49a7616 to e6f3dda Compare August 28, 2023 14:22
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem correct. You have the packet type as the first byte and the packet-specific header comes after that. In all other cases you read &packet_buff[1] but here you read &packet_buff[0]. Actually, I don't see any reason why you need two parameters to this function. Just pass the original buffer and inside the function you can then do uint8_t type = buf[0];.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sorry mistake on my part while changing to the suggestions of the other reviewer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This generates unnecessarily complicated code. Just do size = sys_le16_to_cpu(hdr->len);. The structs are packed, so accessing the struct members generates automatically alignment-safe code (if needed by the CPU architecture).

Copy link
Contributor Author

@vChavezB vChavezB Aug 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the packed attribute deal with endianness ? Thats the reason I thought parts like these ones are needed in the current bluetooth stack

https://github.com/zephyrproject-rtos/zephyr/blob/2d65acca3a76b968657c2e796512558e93f2ed23/drivers/bluetooth/hci/h4.c#L127C3-L127C3

https://github.com/zephyrproject-rtos/zephyr/blob/2d65acca3a76b968657c2e796512558e93f2ed23/drivers/bluetooth/hci/h4.c#L140C2-L140C2

Edit: I read again your comment, ok are you only referring to changing the name of the variable from payload size to size ?

Copy link
Contributor Author

@vChavezB vChavezB Aug 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the other review comments accordingly but this one is still is not clear to me.

Could you be more specific on your suggestion?

Just do size = sys_le16_to_cpu(hdr->len)

I understood either:

  1. Change the name of the variable payload_len to size ?
  2. Obtain the size of the payload via size = sys_le16_to_cpu(hdr->len); before the switch case? Its a trivial change and only the edge case for the struct bt_hci_cmd_hdr has to be taken into account (param_len).

Sorry for the misunderstanding on my part, looking forward for your comments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I think I overthought the comment. Changed to using sys_le16_to_cpu instead of sys_get_le16 and the lenght member of the respective hci header struct instead of the address.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like an unnecessary variable (doesn't add much to readability, and the way you've named it it's even longer thansizeof(packet_type).

Copy link
Contributor Author

@vChavezB vChavezB Aug 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have changed it to now use it directly in the the return statement of the function.

Comment on lines 106 to 107
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call these len instead of size.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd just call this function packet_len()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

Comment on lines 41 to 44
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow the same struct alignment style as elsewhere in the headers, so that the struct member names are aligned. That means two spaces after uint8_t but only one after uint16_t.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

@vChavezB vChavezB force-pushed the bt_userchan_hci_packet_fix branch 2 times, most recently from dd35ea2 to 57fdff7 Compare August 28, 2023 15:27
@vChavezB vChavezB force-pushed the bt_userchan_hci_packet_fix branch 2 times, most recently from 4ff40fd to 0f51a22 Compare August 28, 2023 20:16
Thalley
Thalley previously approved these changes Aug 28, 2023
Thalley
Thalley previously approved these changes Aug 28, 2023
Copy link
Member

@jhedberg jhedberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more review round (thanks for your patience!). After that I think this is ready to be merged.

I think it'd also make sense to split the hci_types.h changes into its own commit (still in this same PR) before the userchan.c commit, since those changes are not strictly related to the userchan driver.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if this is getting a bit overly pedantic, but I'd prefer if we stick to existing variable naming conventions and also avoid unnecessarily long names. This helps keep the code more readable (for someone who has read a lot of other Bluetooth subsystem code). and also avoids excessively long lines.

Just call the input parameter const uint8_t *buf

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh no problem, I am aware that style and naming conventions are highly dependent on organisations policies. As I am still not that familiar with the codebase of Zephyr I know this could come up.

Comment on lines 108 to 109
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const uint8_t type = buf[0];
const uint8_t hdr = &buf[sizeof(type)];

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const struct bt_hci_cmd_hdr *cmd = (const struct bt_hci_cmd_hdr *)hdr;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const struct bt_hci_acl_hdr *acl = (const struct bt_hci_acl_hdr *)hdr;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const struct bt_hci_sco_hdr *sco = (const struct bt_hci_sco_hdr *)hdr;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const struct bt_hci_evt_hdr *evt = (const struct bt_hci_evt_hdr *)hdr;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const struct bt_hci_iso_hdr *iso = (const struct bt_hci_iso_hdr *)hdr;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

Comment on lines 152 to 155
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might make sense to add a LOG_WRN("Unknown packet type 0x%02x", type) before the return.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other connection header structs (ACL & ISO) use simply handle here, so I'd stick to that for consistency (unless the HCI spec is actually fundamentally different in its naming conventions for these headers)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I just checked and the HCI spec uses Connection_Handle both for SCO and ISO, but just Handle for ACL. However, since the ISO struct already uses simply handle I'd follow that convention for SCO as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

@vChavezB
Copy link
Contributor Author

Added last suggestions. Pending separation of commits...

@vChavezB vChavezB force-pushed the bt_userchan_hci_packet_fix branch from 758d0f8 to 05d08cf Compare August 29, 2023 10:27
Added HCI SCO header definition and included comments
that refer to the Bluetooth core spec sections for
the other HCI header types.

Signed-off-by: Victor Chavez <[email protected]>
@vChavezB vChavezB force-pushed the bt_userchan_hci_packet_fix branch from 05d08cf to 22b5012 Compare August 29, 2023 10:29
@vChavezB
Copy link
Contributor Author

I have separated the commits.

@vChavezB vChavezB force-pushed the bt_userchan_hci_packet_fix branch from b5a6c51 to 5deee69 Compare August 29, 2023 11:09
Comment on lines 148 to 151
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
payload_len = bt_iso_hdr_len(sys_le16_to_cpu(iso->len));
header_len = BT_HCI_ISO_HDR_SIZE;
}
payload_len = bt_iso_hdr_len(sys_le16_to_cpu(iso->len));
header_len = BT_HCI_ISO_HDR_SIZE;
break;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for noticing this, have been changing different parts that I must have deleted the break while refactoring.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it existed earlier :D

After conducting tests with a a virtual Bluetooth controller
over TCP it was noticed that some HCI packets may arrive on the
same buffer if sent over a short period of time.
This update ensures the hci packets are parsed correctly in the case
multiple packets are in the same recieving buffer according to
the Bluetooth Spec v5.4 Part E.

Signed-off-by: Victor Chavez <[email protected]>
@vChavezB vChavezB force-pushed the bt_userchan_hci_packet_fix branch from 5deee69 to fee9dc4 Compare August 29, 2023 11:15
@carlescufi carlescufi merged commit 80d4c76 into zephyrproject-rtos:main Aug 30, 2023
@vChavezB vChavezB deleted the bt_userchan_hci_packet_fix branch August 8, 2024 21:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: Bluetooth Host Bluetooth Host (excluding BR/EDR) area: Bluetooth

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Can not decode multiple hci packets on the virtual TCP controller

5 participants