Skip to content
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

netdev_new_api: allow .send() to return > 0 to signal synchronos send #21012

Merged
merged 2 commits into from
Nov 21, 2024

Conversation

benpicco
Copy link
Contributor

Contribution description

The new netdev API makes implementing drivers where .send is inherently synchronous (slip, dose, ethos) kind of awkward. They need to memorize the frame size, generate an event, and return the frame size in .confirm_send to signal completion.

However, the new netdev API does not use .send return values that are > 0. We can use those to signal that send is complete already and no further action is needed.

This makes writing and understanding synchronos drivers much easier, the code changes to support this in GNRC and LWIP are minimal.

Testing procedure

You can test with SLIP with is now trivial to convert:

slip.patch
--- a/drivers/slipdev/Makefile.dep
+++ b/drivers/slipdev/Makefile.dep
@@ -1,6 +1,6 @@
 USEMODULE += chunked_ringbuffer
 USEMODULE += eui_provider
-USEMODULE += netdev_legacy_api
+USEMODULE += netdev_new_api
 USEMODULE += netdev_register
 FEATURES_REQUIRED += periph_uart
 
diff --git a/drivers/slipdev/slipdev.c b/drivers/slipdev/slipdev.c
index ff6880a5b6..b0c0c827ff 100644
--- a/drivers/slipdev/slipdev.c
+++ b/drivers/slipdev/slipdev.c
@@ -234,10 +234,6 @@ static int _send(netdev_t *netdev, const iolist_t *iolist)
     slipdev_write_byte(dev->config.uart, SLIPDEV_END);
     slipdev_unlock();
 
-    if (netdev->event_callback) {
-        netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);
-    }
-
     return bytes;
 }
 
@@ -327,9 +323,6 @@ static int _get(netdev_t *netdev, netopt_t opt, void *value, size_t max_len)
             assert(max_len == sizeof(uint16_t));
             *((uint16_t *)value) = NETDEV_TYPE_SLIP;
             return sizeof(uint16_t);
-        case NETOPT_TX_END_IRQ:
-            *((netopt_enable_t *)value) = NETOPT_ENABLE;
-            return sizeof(netopt_enable_t);
 #if IS_USED(MODULE_SLIPDEV_L2ADDR)
         case NETOPT_ADDRESS_LONG:
             assert(max_len == sizeof(eui64_t));
@@ -341,12 +334,20 @@ static int _get(netdev_t *netdev, netopt_t opt, void *value, size_t max_len)
     }
 }
 
+static int _confirm_send(netdev_t *netdev, void *info)
+{
+    (void)netdev;
+    (void)info;
+    return 0;
+}
+
 static const netdev_driver_t slip_driver = {
     .send = _send,
     .recv = _recv,
     .init = _init,
     .isr = _isr,
     .get = _get,
+    .confirm_send = _confirm_send,
 #if IS_USED(MODULE_SLIPDEV_STDIO)
     .set = netdev_set_notsup,
 #else

Issues/PRs references

@benpicco benpicco requested review from maribu and removed request for miri64 and PeterKietzmann November 20, 2024 15:47
@github-actions github-actions bot added Area: network Area: Networking Area: pkg Area: External package ports Area: drivers Area: Device drivers Area: sys Area: System labels Nov 20, 2024
@benpicco benpicco changed the title drivers/netdev: allow .send() to return > 0 to signal synchronos send drivers/netdev: allow .send() to return > 0 to signal synchronos send Nov 20, 2024
@benpicco benpicco added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Process: API change Integration Process: PR contains or issue proposes an API change. Should be handled with care. labels Nov 20, 2024
@benpicco benpicco requested a review from miri64 November 20, 2024 15:48
@benpicco benpicco changed the title drivers/netdev: allow .send() to return > 0 to signal synchronos send drivers/netdev_new_api: allow .send() to return > 0 to signal synchronos send Nov 20, 2024
@benpicco benpicco changed the title drivers/netdev_new_api: allow .send() to return > 0 to signal synchronos send netdev_new_api: allow .send() to return > 0 to signal synchronos send Nov 20, 2024
@riot-ci
Copy link

riot-ci commented Nov 20, 2024

Murdock results

✔️ PASSED

4eb1c35 cpu/sam0_eth: fix return values of sam0_eth_send()

Success Failures Total Runtime
10249 0 10249 17m:28s

Artifacts

@maribu
Copy link
Member

maribu commented Nov 20, 2024

where .send is inherently synchronous (slip, dose, ethos) kind of awkward.

It is not actually inherently synchronous, e.g. with DMA it is possible and in fact quite sensible to have UART asynchronous. Even if only an TX done IRQ is available, providing an async UART interface would be possible with the ISR feeding the data into the UART while allowing the CPU to do other things in between the ISR.

I wonder if we are here digging in deeper into the whole of the synchronous periph APIs.

Copy link
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

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

Let's rather revert the slip netdev to the legacy API. No need to add a third case, as this matches behaviour of the legacy API already.

@benpicco
Copy link
Contributor Author

benpicco commented Nov 20, 2024

If the driver becomes async, it can easily be converted to return 0 on send - but e.g. dose will likely always be synchronous as it does handle collision detection and retransmissions.

Let's rather revert the slip netdev to the legacy API. No need to add a third case, as this matches behaviour of the legacy API already.

The nice thing about the new API is the change in memory ownership and that we can be a lot more strict about how it behaves. e.g. in the synchronous send case we don't need to generate an event, the legacy API would just generate events 'just in case' - or not, depending on what the driver author felt like.

The goal would be to get rid of all the netdev_legacy_api cases eventually.

Copy link
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

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

OK, makes sense

@github-actions github-actions bot added Platform: ARM Platform: This PR/issue effects ARM-based platforms Area: cpu Area: CPU/MCU ports labels Nov 20, 2024
@benpicco benpicco added this pull request to the merge queue Nov 20, 2024
Merged via the queue into RIOT-OS:master with commit 2bce94a Nov 21, 2024
25 checks passed
@benpicco benpicco deleted the netdev_new_api-relax branch November 21, 2024 10:16
maribu added a commit to maribu/RIOT that referenced this pull request Dec 16, 2024
Since RIOT-OS#21012 a netdev in the new API
can return > 0 directly in netdev_driver_t::send() to indicate the
driver is naturally synchronous and has already completed the
transmission.

This adapts lwIP to handle this case explicitly. With it, lwIP will
work again on `native`, rather than blocking for a signal that TX has
completed that never arrives.
maribu added a commit to maribu/RIOT that referenced this pull request Dec 16, 2024
Since RIOT-OS#21012 a netdev in the new API
can return > 0 directly in netdev_driver_t::send() to indicate the
driver is naturally synchronous and has already completed the
transmission.

This adapts lwIP to handle this case explicitly. With it, lwIP will
work again on `native`, rather than blocking for a signal that TX has
completed that never arrives.
maribu added a commit to maribu/RIOT that referenced this pull request Dec 16, 2024
Since RIOT-OS#21012 a netdev in the new API
can return > 0 directly in netdev_driver_t::send() to indicate the
driver is naturally synchronous and has already completed the
transmission.

The adaption of lwIP to that API change contained a bug: It handled the
case after the thread is already blocked waiting for the signal that
is never going to arrive. This is now fixed.
maribu added a commit to maribu/RIOT that referenced this pull request Dec 16, 2024
Since RIOT-OS#21012 a netdev in the new API
can return > 0 directly in netdev_driver_t::send() to indicate the
driver is naturally synchronous and has already completed the
transmission.

The adaption of lwIP to that API change contained a bug: It handled the
case after the thread is already blocked waiting for the signal that
is never going to arrive. This is now fixed.
@MrKevinWeiss MrKevinWeiss added this to the Release 2025.01 milestone Jan 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: cpu Area: CPU/MCU ports Area: drivers Area: Device drivers Area: network Area: Networking Area: pkg Area: External package ports Area: sys Area: System CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ARM Platform: This PR/issue effects ARM-based platforms Process: API change Integration Process: PR contains or issue proposes an API change. Should be handled with care.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants