-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Bluetooth: controller: Add initial support for chaining in periodic advertising #31875
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
be033c0 to
3fdc868
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to see a use of the AUX_CHAIN_IND in a set advertising data procedure. I'm especially interested about handling of data update procedure.
It would required to create complete chain from scratch. In such situation we have to take extended advertising header from last used chain PDUs and move them to new chain. During that process we have to incorporate new periodic advertising data. Am I correct?
Is it possible to see sample application that uses the functionality?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please setup a code walk-through meeting to sync-up on the design.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not need this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use singly linked list. Do not need these implementation.
|
@wopu-ot Please provide your design thoughts. I had decide during the introduction of 255 byte Advertising PDU to maintain the double buffering design for the advertising PDUs. For chaining, my proposal is to use singly linked list, wherein:
Repeated call to
|
3fdc868 to
8d162f0
Compare
|
There are some new helpers to manage PDUs, e.g. duplicate them or create new one based on old one. Not sure if this is the best approach but we need something to conveniently create/duplicate PDUs and link them into chains - I don't think This also does not yet allow to accept fragmented data from host, AD is only allowed in 1st PDU as previously but chain can be preserved when updating AD after CTEInfo was added. |
|
I think I addressed comments that were still relevant after changing to new chaining design as proposed by Vinayak. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently there will be no next switch attempt because caller will just assert, as it does without linking. So we can assume this is ok as there always should be enough free slots in mfifo or we can add handling in caller later, i.e. it will skip an event.
Alternatively we can put only 1st PDU in mfifo with all linked PDUs and let ULL deal with it, i.e. it will dequeue this PDU and use it, then release linked PDUs directly to pool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work. Minor request to re-use sw_switch, otherwise lets meet for "one last time" to review change requested by @ppryga and settle for a list of pending changes to be reworked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| struct pdu_adv *last_pdu; | |
| #if defined(CONFIG_BT_CTLR_ADV_PDU_LINK) | |
| struct pdu_adv *last_pdu; | |
| #endif /* CONFIG_BT_CTLR_ADV_PDU_LINK */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why sw_switch can not be re-used? What is the difference?
is this because of sw_switch assuming its always tx-to-rx or rx-to-tx?
If that is the difference, then change sw_switch to:
static void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t flags_curr, uint8_t phy_next, uint8_t flags_next)
based on dir_curr and dir_next use the right chain delay and ready delay. sw_switch can be reused to piggyback receptions too.
Pass constants to these dir_curr and dir_next parameters at the callers of this functions in LLL files, compiler will optimize call paths not exercised by constant value parameter passed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something that I am trying to use for BIS subevents: #33118
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sw_switch is not inlined so it will not be optimized (unless I misunderstood what you meant) for new case, but regardless reusing sw_switch as in mentioned PR works for me since it's just a single extra branch so not much of a difference. I initially thought that there will be more to change there thus I created a copy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about BT_CTLR_ADV_SYNC_PDU_BACK2BACK?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| void radio_switch_complete_and_pback(uint8_t phy, uint8_t flags) | |
| void radio_switch_complete_and_b2b_tx(uint8_t phy, uint8_t flags) |
i.e. if using the term back-to-back is ok? That is what is happening in reality. I am ok with piggyback/pback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
back2back sounds better, will use it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BT_CTLR_ADV_SYNC_PDU_BACK2BACK for me sounds better. If this is changed to BACK2BACK then I suggest to change API names with suffixes _pback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why check value provided by ext_hdr_flags by ext_hdr?
Probably it would be optimized by compiler but in my humble opinion it is easier to spot that it depends on function parameter than search for assignment to ext_hdr.
It seems to me that ext_hrd may be removed at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can change this but I guess this is just a matter of preference. The way I read this code is that I check flags inside PDU which is initialized earlier using ext_hdr_flags, thus I do not check that parameter explicitly since.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me it makes the code more unclear.
efde59d to
1598c89
Compare
|
I included b2b radio interface from #33118 instead of previous implementation, works fine. |
|
@andrzej-kaczmarek I've provided a PR to your fork repository that includes some commits that suggest fixes for issues I've found while testing the implementation provided by this PR. (for ref. to others here is link to mentioned PR: andrzej-kaczmarek#1). I've got two additional things:
Thanks to re-use of existing chain we save a lot of memory. To handle CTE (max number of PDUs is 16) we need ~4K of RAM. |
Would be better if we stick to traditional GitHub way and have comments here. It's not quite easy to figure out which parts of that PR are purely fixes and which are added for CTE.
I think the main question here whether we want to have one big function like
I can update set data to reuse old PDUs.
That could be improved if we have pools of different buffer sizes so small PDUs do not waste memory. |
@andrzej-kaczmarek Please refer to this discussion, and lets align, so we dont have redundancy in our efforts. #32622 (comment) |
@cvinayak does it mean that |
|
@andrzej-kaczmarek I am open to a discussion and settle on a solution based on pros and cons. This will have to be a group meeting after the Easter vacations. @wopu-ot Could you please include this as a action item that we can settle ASAP (just after Easter vacations) ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| } else if ((hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) || | |
| } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) || |
This is an error that is available from first implementation of the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ULL_ADV_PDU_HDR_FIELD_CTE_INFO, | |
| 0, NULL); | |
| 0, | |
| ULL_ADV_PDU_HDR_FIELD_CTE_INFO, NULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| static uint8_t adv_sync_pdu_init(struct pdu_adv *pdu, uint8_t ext_hdr_flags) | |
| static void adv_sync_pdu_init(struct pdu_adv *pdu, uint8_t ext_hdr_flags) |
It always returns zero.
6715590 to
2f0e49f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quick ack, do not have any strong objections, overall design was previously agreed. Any rework if any would be minor, can be taken up in subsequent PRs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| #define ULL_ADV_PDU_HDR_FIELD_TX_POWER BIT(7) | |
| #define ULL_ADV_PDU_HDR_FIELD_TX_POWER BIT(6) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will fix this in one of my subsequent PRs.
|
Removed part of code responsible for setting address timeout, it should not be configured in |
|
@wopu-ot This PR has changed the way extended advertising PDU is allocated, this is conflicting my BIS work, and wish to have the changes here upstreamed before I continue with rework on my PRs. Please do the needful to review this PR. |
Advertising channel packets do not have MIC, there's no need to have extra parameter which always has to be set to 0 anyway. Signed-off-by: Andrzej Kaczmarek <[email protected]>
This adds helper to always allocate advertising PDU either from memory pool or pdu_free queue and does not reuse existing PDU in adv_pdu. Signed-off-by: Andrzej Kaczmarek <[email protected]>
This function is the same as lll_adv_pdu_alloc except it also allocates extra data at the end - it can just use lll_adv_pdu_alloc call to avoid extensive c&p. Signed-off-by: Andrzej Kaczmarek <[email protected]>
This adds support to allow advertising PDUs to be linked which is required to send advertising trains, i.e. AUX_CHAIN_IND. PDUs are linked with a simple single-linked list, the pointer to next PDU is stored at the very end of PDU buffer. This prevents it from being overwritten if PDU is modified and allows for build time offset calculation. There are few helpers added to make handling easier, e.g.: - get next linked PDU - get last linked PDU - link one PDU to another - link PDU at the end - release all linked PDUs (except for 1st) Signed-off-by: Andrzej Kaczmarek <[email protected]>
This enables chaining ota for periodic advertising. AUX_CHAIN_IND PDUs will be sent automatically if AuxPtr is detected in preceding PDU. AuxPtr offset is always set to achieve minimal required frame spacing, i.e. 300us (T_mafs). AuxPtr in all PDUs in advertising train are updated on enqueue since PDU spacing is already known at that time so we do not need to waste time in LLL. Signed-off-by: Andrzej Kaczmarek <[email protected]>
This adds adv_sync_pdu_init helper which initializes pdu_adv buffer with contents of AUX_SYNC_IND/AUX_CHAIN_IND PDU. Extended header flags can be specified to reserve required space for corresponding fields if necessary. Signed-off-by: Andrzej Kaczmarek <[email protected]>
This adds some initial support to update AD in chain. We still only support placing AD in 1st PDU, but this will properly copy any linked PDUs that may be added due to e.g. CTEInfo present. Signed-off-by: Andrzej Kaczmarek <[email protected]>
This adds simple helper to update CTEInfo. It assumes proper periodic adv PDU as input to simplify code. Signed-off-by: Andrzej Kaczmarek <[email protected]>
adv_sync_hdr_set_clear was just wrapped by ull_adv_sync_pdu_set_clear so we can merge both into single function. Signed-off-by: Andrzej Kaczmarek <[email protected]>
|
@ppryga I have rebased to upstream/main and pushed. |
|
@nashif, @galak, @carlescufi could one of you merge the PR? CI is green. |
This adds initial support for chaining in periodic advertising, i.e. we can send AUX_SYNC_IND followed by sequence of AUX_CHAIN_IND.
New set of APIs to manage chains instead of single PDUs in advertising set is described in relevant commit. AUX_CHAIN_IND packets are not scheduled as they should be, instead they are just sent one after another at constant offset (T_MAFS) on best effort basis since there's no reservation done for complete train. There's no code that can do fragmentation of data coming from host so I added a temporary commit which will add single chain whenever periodic advertising data is changed on a set.