# Configure Can Acceptance Filters in multi thread app

**URL:** <https://forum.opencyphal.org/t/configure-can-acceptance-filters-in-multi-thread-app/709>\
**Category:** LibCyphal\
**Created:** [December 11, 2019, 7:34pm UTC](https://forum.opencyphal.org/t/configure-can-acceptance-filters-in-multi-thread-app/709 "2019-12-11T19:34:16Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![deekay](https://forum.opencyphal.org/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@deekay](https://forum.opencyphal.org/u/deekay)\
**Post date:** [December 11, 2019, 7:34pm UTC](https://forum.opencyphal.org/t/configure-can-acceptance-filters-in-multi-thread-app/709/1 "2019-12-11T19:34:16Z")

</div>

Hi!

I am building a Node and SubNode application, similar to example in repo.  
Does it matter in what thread the configureCanAcceptanceFilters() is called, assuming all subscribers etc. has been setup in each thread at the point of function call?

Regards

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [December 11, 2019, 7:56pm UTC](https://forum.opencyphal.org/t/configure-can-acceptance-filters-in-multi-thread-app/709/2 "2019-12-11T19:56:35Z")

</div>

You have an interesting edge case. You will need to configure your acceptance filters manually.

Invoking `configureCanAcceptanceFilters()` in the sub-node will have no effect and result in `ErrDriver`. This is because the required CAN acceptance filter configuration functionality is not implemented in the virtual driver (the following code is taken from the [Multithreading tutorial](https://uavcan.org/Implementations/Libuavcan/Tutorials/12._Multithreading/)):

```auto
    /**
     * Stubs for uavcan::ICanDriver. Will be invoked by the sub-node.
     * These methods are meaningless for a virtual interface.
     */
    std::int16_t configureFilters(const uavcan::CanFilterConfig*, std::uint16_t) override { return -uavcan::ErrDriver; }
    std::uint16_t getNumFilters() const override { return 0; }

```

Invocation of `configureCanAcceptanceFilters()` on the physical node will succeed, but the method will not be aware about the subscriptions implemented in the virtual node because it is separated at a very low level of abstraction and the subscription information is not shared between the physical node and the virtual node. As a result, the applied acceptance filter configuration may reject CAN frames that are needed for the virtual node.

What you need is to take the subscription list from both nodes (physical and virtual) and compute the acceptance filter configuration from that yourself. Basically you need to repeat this loop once per node:

> <https://github.com/UAVCAN/libuavcan/blob/8913f14d11ceb558fdabc5cdbe1cc6a866ac4c67/libuavcan/src/transport/uc_can_acceptance_filter_configurator.cpp#L41-L52>

---

<div class="post-metadata">

**Author:** ![deekay](https://forum.opencyphal.org/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@deekay](https://forum.opencyphal.org/u/deekay)\
**Post date:** [December 12, 2019, 8:52am UTC](https://forum.opencyphal.org/t/configure-can-acceptance-filters-in-multi-thread-app/709/3 "2019-12-12T08:52:18Z")

</div>

Makes sense!

Very good, thanks for the info. I will try…

Kind regards

---

<div class="post-metadata">

**Author:** ![deekay](https://forum.opencyphal.org/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@deekay](https://forum.opencyphal.org/u/deekay)\
**Post date:** [December 19, 2019, 1:07pm UTC](https://forum.opencyphal.org/t/configure-can-acceptance-filters-in-multi-thread-app/709/5 "2019-12-19T13:07:18Z")

</div>

This solution seems to work.

In subnode thread I manually create CanFilterConfig, as above, and sends the configs to main node thread via queue:

```auto
const TransferListener* p = node->getDispatcher().getListOfMessageListeners().get();
while (p != UAVCAN_NULLPTR)
{
    CanFilterConfig cfg;
    cfg.id = (static_cast<uint32_t>(p->getDataTypeDescriptor().getID().get()) << 8) | CanFrame::FlagEFF;
					cfg.mask = 0xFFFF80 | CanFrame::FlagEFF | CanFrame::FlagRTR | CanFrame::FlagERR;
					thread_exchange.filter.push(cfg); //Mutex protected queue					
					p = p->getNextListNode();
}

```

The above snippet is executed when sub node has subscribed to all broadcasts needed and setup the provided services.

In the main thread, before main loop, a config is setup

```auto
CanAcceptanceFilterConfigurator main_node_conf(*node);
main_node_conf.computeConfiguration();

```

In the main loop, the queue is pop:ed and filter is added:

```auto
if(thread_exchange.filter.pop(filter))
{
    main_node_conf.addFilterConfig(filter);
    main_node_conf.applyConfiguration();
}

```

As I understand, addFilterCOnfig() and applyConfiguration() shall be enough? Even if new subscribers or services are added later?

Regards

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [December 19, 2019, 11:09pm UTC](https://forum.opencyphal.org/t/configure-can-acceptance-filters-in-multi-thread-app/709/6 "2019-12-19T23:09:12Z")

</div>

This should be OK.
