Skip to content

netif: add functions to get and get by identifier #12738

Merged
miri64 merged 3 commits intoRIOT-OS:masterfrom
miri64:netif/enh/id-functions
Jun 9, 2020
Merged

netif: add functions to get and get by identifier #12738
miri64 merged 3 commits intoRIOT-OS:masterfrom
miri64:netif/enh/id-functions

Conversation

@miri64
Copy link
Copy Markdown
Member

@miri64 miri64 commented Nov 18, 2019

Contribution description

This is a proof-of-concept implementation for a stack-independent interface identifiers.

Testing procedure

None yet, but will add some if we agree on the concept.

Issues/PRs references

A proposed solution for #12680.

In 77a7aed the API moved from an
identifier-based approach to a pointer based approach. The documentation
does not reflect this yet.
@miri64 miri64 added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation Area: network Area: Networking State: demonstrator State: This PR (loosely) demonstrates a concept and is not necessarily meant to be merged. labels Nov 18, 2019
@miri64 miri64 changed the title Netif/enh/id functions @miri64 netif: add functions to get and get by identifier Nov 18, 2019
@miri64 miri64 changed the title @miri64 netif: add functions to get and get by identifier netif: add functions to get and get by identifier Nov 18, 2019
@kaspar030
Copy link
Copy Markdown
Contributor

This'll traverse the netif list on every call (in O(N) time). IMO, for something that might be called multiple times per packet, that's not acceptable. Think benchmarks having different results depending on the number of configured network devices.

Why not an extra field in netif_t for the numerical id (for netif_get_id()), and a mapping array (for netif_by_id())?

@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Nov 18, 2019

This'll traverse the netif list on every call (in O(N) time). IMO, for something that might be called multiple times per packet, that's not acceptable. Think benchmarks having different results depending on the number of configured network devices.

I don't think it will be called multiple times per packet. I expect netif_get_id() to be called at most once per end-point initialization and netif_get_by_pid() once in the translation.

Why not an extra field in netif_t for the numerical id (for netif_get_id()), and a mapping array (for netif_by_id())?

I try to prevent topping the number of network interfaces at compile time. We currently actively go away from that.

@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Nov 18, 2019

Or we do it like I proposed originally (see latest fixup). This would be O(1) but also relies on some assumptions (all netif_t instances can be distinguished by the same 16-bit address suffix and netif_get_id() is only called for existing network interfaces.

@miri64 miri64 force-pushed the netif/enh/id-functions branch from 6aef44e to c3cab1c Compare November 18, 2019 14:18
@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Dec 6, 2019

Ping?

@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Mar 18, 2020

Ping @leandrolanzieri @jia200x?

@leandrolanzieri
Copy link
Copy Markdown
Contributor

I don't think it will be called multiple times per packet. I expect netif_get_id() to be called at most once per end-point initialization and netif_get_by_pid() once in the translation.

If this is the case, it seems to me that the cleaner approach is the one proposed in 4ef741f.

I try to prevent topping the number of network interfaces at compile time. We currently actively go away from that.

+1!

@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Mar 19, 2020

I don't think it will be called multiple times per packet. I expect netif_get_id() to be called at most once per end-point initialization and netif_get_by_pid() once in the translation.

If this is the case, it seems to me that the cleaner approach is the one proposed in 4ef741f.

Okay, I reverted c3cab1c

benpicco
benpicco previously approved these changes Mar 26, 2020
Copy link
Copy Markdown
Contributor

@benpicco benpicco left a comment

Choose a reason for hiding this comment

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

This is a very simple addition.
And considering that on type of devices we have you can count the number of interfaces on one hand, I don't think O(n) is too bad here.

We can still optimize later if this API turns out be be used in hot paths, but +1 for getting the API in place.

@benpicco
Copy link
Copy Markdown
Contributor

IMHO you can squash.

@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Mar 28, 2020

I squashed the changes so far, but, and I know this PR was already ack'd, I got an idea, how to keep the id thing downwards compatible, when used with sock: Make the definitions introduced here weak and override them in GNRC with the PID equivalent (netif->pid for netif_get_id() and gnrc_netif_get_by_id() for netif_get_by_id(). Let me know what you think.

@miri64 miri64 force-pushed the netif/enh/id-functions branch from 69b4612 to 2ef62bb Compare March 28, 2020 10:57
@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Mar 28, 2020

I tested if this works with the following patch

diff --git a/examples/gnrc_networking/main.c b/examples/gnrc_networking/main.c
index 6301f4291..3d5cc9c63 100644
--- a/examples/gnrc_networking/main.c
+++ b/examples/gnrc_networking/main.c
@@ -22,6 +22,7 @@
 
 #include "shell.h"
 #include "msg.h"
+#include "net/netif.h"
 
 #define MAIN_QUEUE_SIZE     (8)
 static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
@@ -35,11 +36,15 @@ static const shell_command_t shell_commands[] = {
 
 int main(void)
 {
+    netif_t *netif = NULL;
     /* we need a message queue for the thread running the shell in order to
      * receive potentially fast incoming networking packets */
     msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
     puts("RIOT network stack example application");
 
+    while ((netif = netif_iter(netif))) {
+        printf("netif %i\n", netif_get_id(netif));
+    }
     /* start shell */
     puts("All up, running the shell now");
     char line_buf[SHELL_DEFAULT_BUFSIZE];

@benpicco benpicco dismissed their stale review March 28, 2020 11:05

The behavior of the ID changed.

@benpicco
Copy link
Copy Markdown
Contributor

But now the ID is not predictable anymore.
I liked this PR because it enabled pid-independent IDs for interfaces.

Now it will again change based on what modules are used, so it can not be used to attach information to IDs on the board level.

@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Mar 28, 2020

But now the ID is not predictable anymore.
I liked this PR because it enabled pid-independent IDs for interfaces.

Now it will again change based on what modules are used, so it can not be used to attach information to IDs on the board level.

With the current approach however we can slowly phase over to that instead of having to change over in a huge, hardly testable, push.

@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Mar 28, 2020

IMHO: since sock is a very stable API, that is expected to be used outside of the main repo, this is the more desirable option.

@benpicco
Copy link
Copy Markdown
Contributor

But changing the behavior of netif_get_id() depending on what stack is used sounds like a bad idea.

How about leaving netif_get_id() as is and instead provide a stack-dependent wrapper function?

static inline int16_t gnrc_netif_get_id(const gnrc_netif_t *netif)
{
    return netif->pid;
}

static inline int16_t lwip_netif_get_id(const netif_t *netif)
{
    return netif_get_id(netif);
}

@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Mar 28, 2020

But changing the behavior of netif_get_id() depending on what stack is used sounds like a bad idea.

The fallback (or previous general approach) is also stack dependent, because it is dependent in which order the interfaces are initialized (which at the moment the stacks do).

How about leaving netif_get_id() as is and instead provide a stack-dependent wrapper function?

That would defeat the purpose of a generalized API used with sock. Because then we would need do something like this in the transition period:

#if IS_USED(MODULE_GNRC)
    int16_t id = gnrc_netif_get_id(netif);
#elif IS_USED(MODULE_LWIP)
    int16_t id = lwip_netif_get_id(netif);
#endif
    local_ep->netif = id;

Then I rather don't introduce this function at all until we are transition and splatter this all over the code base ;-P:

#if IS_USED(MODULE_GNRC)
    int16_t id = ((gnrc_netif_t *)netif)->pid;
#elif IS_USED(MODULE_LWIP)
    int16_t id = ((struct netif *)netif)->num;
#endif
    local_ep->netif = id;

@benpicco
Copy link
Copy Markdown
Contributor

benpicco commented Mar 28, 2020

Hm and what I was trying to do wouldn't work anyway since there is currently no stack-independent way to get the netif_t * corresponding to a netdev_t * 😕

@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Mar 30, 2020

Yes, we are still a bit away from compile-time-unique identifiers. But this was not the point of this PR anyway (this as the OP says is more a user-level API), but with this we might become closer.

Copy link
Copy Markdown
Contributor

@benpicco benpicco left a comment

Choose a reason for hiding this comment

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

Well it still makes the code cleaner and allows for unification between lwip and GNRC - please squash.

@miri64 miri64 force-pushed the netif/enh/id-functions branch from 2ef62bb to 652276f Compare April 17, 2020 14:59
@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Apr 17, 2020

Squashed

@miri64 miri64 added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Apr 18, 2020
@aabadie aabadie added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels May 14, 2020
@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Jun 8, 2020

@benpicco @miri64 is this one still mergeable ?

@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Jun 9, 2020

IMHO, yes.

@miri64 miri64 added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Jun 9, 2020
@miri64
Copy link
Copy Markdown
Member Author

miri64 commented Jun 9, 2020

I give it another rebuild though.

@miri64 miri64 merged commit f9bed00 into RIOT-OS:master Jun 9, 2020
@miri64 miri64 deleted the netif/enh/id-functions branch June 9, 2020 13:12
@miri64 miri64 added this to the Release 2020.07 milestone Jun 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: network Area: Networking CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR State: demonstrator State: This PR (loosely) demonstrates a concept and is not necessarily meant to be merged. Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants