netifapi limitations

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

netifapi limitations

Jonathan Larmour
Hi all, popping my head round the door after a bit of a while :-).

I've noticed a limitation in the netifapi (not the netif API!) : Many of the
functions require a struct netif* argument, however the netifapi is intended
to be used outside of the TCPIP thread.

The main problem is that there is no way to obtain a netif using the netifapi.
You can convert to/from indexes and names, but can't get the netif itself,
except arguably 'netif_default', but that won't help those with multiple
interfaces. Perhaps we could add a function to look up and return a struct
netif* based on a name/index? But that doesn't seem very safe to me given what
the netifapi is for: resilience against netifs being added/removed in another
thread.

Perhaps it could be argued that keeping lwIP simple means making compromises,
and maybe this is a compromise to make. But overall IMHO, the netif API would
be better off removing all mentions of struct netif* entirely. Instead each
function should take an if index.

That brings me to a second issue, netif_find() assumes that the netif name is
exactly three chars long, the third being the if number from 0-9. The number
is assigned in netif_add() by incrementing a local static variable each time.
The problem here is that this means you can only ever have added 10 interfaces
before the API breaks, even if you have removed netifs in the meantime. Even
if we parsed the name argument as a normal NUL-terminated string, the index is
a u8_t. If there is a possibility that people can be adding/removing netif's
dynamically and repeatedly (think USB or PPP), this can't work long. The index
probably wants to be u32_t for safety given how long embedded devices can be
up for, and netif_find() needs to accept a normal NUL-terminated string and
use strtoul() on the number component.

Next, if the numbers are part of the name, but are assigned by lwIP, how can
netif API users even find an interface except in the most simple static cases,
and making assumptions about interface initialisation order? It makes me think
we need an iterator function in netifapi to report the next used index (which
in practice just traverses the netif list). For example:

  err_t err = 0;
  /* NETIFAPI_GET_FIRST_INDEX is a magic value to get index of first netif */
  for ( index = NETIFAPI_GET_FIRST_INDEX;
        ;
        index = next_index )
  {
    err = netifapi_get_next_index(index, &next_index);
    if ( err != 0 )
      break;
    ... Do stuff with interface 'next_index' ...
  }

I don't know how official the netif api is, so whether it is okay to break the
API this much, but I can't really see it being correct or particularly usable
even at the moment.

Comments? I'm prepared to put in some work to make this happen.

Jifl
--
------["Si fractum non sit, noli id reficere"]------       Opinions==mine

_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

Sylvain Rochet
Hi Jonathan,


On Fri, Mar 16, 2018 at 02:23:02AM +0000, Jonathan Larmour wrote:

> Hi all, popping my head round the door after a bit of a while :-).
>
> I've noticed a limitation in the netifapi (not the netif API!) : Many of the
> functions require a struct netif* argument, however the netifapi is intended
> to be used outside of the TCPIP thread.
>
> The main problem is that there is no way to obtain a netif using the netifapi.
> You can convert to/from indexes and names, but can't get the netif itself,
> except arguably 'netif_default', but that won't help those with multiple
> interfaces. Perhaps we could add a function to look up and return a struct
> netif* based on a name/index? But that doesn't seem very safe to me given what
> the netifapi is for: resilience against netifs being added/removed in another
> thread.
>
> Perhaps it could be argued that keeping lwIP simple means making compromises,
> and maybe this is a compromise to make. But overall IMHO, the netif API would
> be better off removing all mentions of struct netif* entirely. Instead each
> function should take an if index.
>

> That brings me to a second issue, netif_find() assumes that the netif
> name is exactly three chars long, the third being the if number from
> 0-9.

Which version of lwIP are you using ? It doesn't seem to be the case.
http://git.savannah.nongnu.org/cgit/lwip.git/tree/src/core/netif.c?id=6070a7ef6a9c1fd4f9b7d2dd16b412110a466244#n1656


> The number is assigned in netif_add() by incrementing a local
> static variable each time. The problem here is that this means you can
> only ever have added 10 interfaces before the API breaks, even if you
> have removed netifs in the meantime. Even if we parsed the name
> argument as a normal NUL-terminated string, the index is a u8_t. If
> there is a possibility that people can be adding/removing netif's
> dynamically and repeatedly (think USB or PPP), this can't work long.

We take care of this issue in netif_add() by iterating over the netif
list to find a free entry if necessary.
http://git.savannah.nongnu.org/cgit/lwip.git/tree/src/core/netif.c?id=6070a7ef6a9c1fd4f9b7d2dd16b412110a466244#n367


> The index probably wants to be u32_t for safety given how long
> embedded devices can be up for, and netif_find() needs to accept a
> normal NUL-terminated string and use strtoul() on the number
> component.

Same here, this is exactly what netif_find() is doing.


> Next, if the numbers are part of the name, but are assigned by lwIP, how can
> netif API users even find an interface except in the most simple static cases,
> and making assumptions about interface initialisation order? It makes me think
> we need an iterator function in netifapi to report the next used index (which
> in practice just traverses the netif list). For example:
>
>   err_t err = 0;
>   /* NETIFAPI_GET_FIRST_INDEX is a magic value to get index of first netif */
>   for ( index = NETIFAPI_GET_FIRST_INDEX;
>         ;
>         index = next_index )
>   {
>     err = netifapi_get_next_index(index, &next_index);
>     if ( err != 0 )
>       break;
>     ... Do stuff with interface 'next_index' ...
>   }
>
> I don't know how official the netif api is, so whether it is okay to break the
> API this much, but I can't really see it being correct or particularly usable
> even at the moment.
>
> Comments? I'm prepared to put in some work to make this happen.
Since netif struct is not allocated/freed by the stack itself, how is
getting a netif pointer a problem at all ?


Sylvain

_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel

signature.asc (188 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

Joel Cunningham-2
In reply to this post by Jonathan Larmour


On 03/15/2018 09:23 PM, Jonathan Larmour wrote:

> Hi all, popping my head round the door after a bit of a while :-).
>
> I've noticed a limitation in the netifapi (not the netif API!) : Many of the
> functions require a struct netif* argument, however the netifapi is intended
> to be used outside of the TCPIP thread.
>
> The main problem is that there is no way to obtain a netif using the netifapi.
> You can convert to/from indexes and names, but can't get the netif itself,
> except arguably 'netif_default', but that won't help those with multiple
> interfaces. Perhaps we could add a function to look up and return a struct
> netif* based on a name/index? But that doesn't seem very safe to me given what
> the netifapi is for: resilience against netifs being added/removed in another
> thread.
This is definitely a limitation that has been discussed before on the
list (see https://savannah.nongnu.org/task/index.php?14724). To me, the
netif and netifapis are really only useful from code that manages a
struct netif (owns the allocation/reference, so it can safely pass
pointers). I think of this as link layer management code, which
typically adds/removes the neift, applies configuration settings and not
network application code that lives above the stack.

I think for network application code, additional APIs are needed to get
things like get address information, list of interfaces.  LwIP doesn't
have any of the normal things like getifaddrs and in my projects, I've
got custom code to do these lookups in a safe way.

We made some progress implementing ifnametoindex/ifindextoname, but
encountered some implementation issues with if_nameindex (which
enumerates all interfaces).  See
https://savannah.nongnu.org/task/?func=detailitem&item_id=14314

>
> Perhaps it could be argued that keeping lwIP simple means making compromises,
> and maybe this is a compromise to make. But overall IMHO, the netif API would
> be better off removing all mentions of struct netif* entirely. Instead each
> function should take an if index.
>
> That brings me to a second issue, netif_find() assumes that the netif name is
> exactly three chars long, the third being the if number from 0-9. The number
> is assigned in netif_add() by incrementing a local static variable each time.
> The problem here is that this means you can only ever have added 10 interfaces
> before the API breaks, even if you have removed netifs in the meantime. Even
> if we parsed the name argument as a normal NUL-terminated string, the index is
> a u8_t. If there is a possibility that people can be adding/removing netif's
> dynamically and repeatedly (think USB or PPP), this can't work long. The index
> probably wants to be u32_t for safety given how long embedded devices can be
> up for, and netif_find() needs to accept a normal NUL-terminated string and
> use strtoul() on the number component.
>
> Next, if the numbers are part of the name, but are assigned by lwIP, how can
> netif API users even find an interface except in the most simple static cases,
> and making assumptions about interface initialisation order? It makes me think
> we need an iterator function in netifapi to report the next used index (which
> in practice just traverses the netif list). For example:
Given how it's implemented on git master with the index, you're right
the resulting name is non-deterministic. If we had something like
getifaddrs/if_nameindex, we could enumerate the names, but I think
having names which can be hardcoded into applications isn't a good practice.

>
>    err_t err = 0;
>    /* NETIFAPI_GET_FIRST_INDEX is a magic value to get index of first netif */
>    for ( index = NETIFAPI_GET_FIRST_INDEX;
>          ;
>          index = next_index )
>    {
>      err = netifapi_get_next_index(index, &next_index);
>      if ( err != 0 )
>        break;
>      ... Do stuff with interface 'next_index' ...
>    }
>
> I don't know how official the netif api is, so whether it is okay to break the
> API this much, but I can't really see it being correct or particularly usable
> even at the moment.
>
> Comments? I'm prepared to put in some work to make this happen.
I'm also interested in getting some standard APIs implemented that can
be used in application code.

Joel


_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

Jonathan Larmour
In reply to this post by Sylvain Rochet
Hi Sylvain,

On 16/03/18 10:46, Sylvain Rochet wrote:
> On Fri, Mar 16, 2018 at 02:23:02AM +0000, Jonathan Larmour wrote:
>> I've noticed a limitation in the netifapi (not the netif API!) :
[snip]
>> That brings me to a second issue, netif_find() assumes that the netif
>> name is exactly three chars long, the third being the if number from
>> 0-9.
>
> Which version of lwIP are you using ? It doesn't seem to be the case.
> http://git.savannah.nongnu.org/cgit/lwip.git/tree/src/core/netif.c?id=6070a7ef6a9c1fd4f9b7d2dd16b412110a466244#n1656

Aah,
>
>
>
>
>
>
you're right, I'd been looking at the STABLE-2_0_0 branch rather than
head. That's great that there are improvements here.

>> The number is assigned in netif_add() by incrementing a local static
>> variable each time. [snip]
>
> We take care of this issue in netif_add() by iterating over the netif
> list to find a free entry if necessary.
> http://git.savannah.nongnu.org/cgit/lwip.git/tree/src/core/netif.c?id=6070a7ef6a9c1fd4f9b7d2dd16b412110a466244#n367

Again
>
>
>
>
>
>
an improvement over 2.x.


[snip]
>> Next, if the numbers are part of the name, but are assigned by lwIP,
>> how can netif API users even find an interface except in the most
>> simple static cases, and making assumptions about interface
>> initialisation order? It makes me think we need an iterator function
>> in netifapi to report the next used index (which in practice just
>> traverses the netif list). For example:
>>
[snip]
> Since netif struct is not allocated/freed by the stack itself, how is
> getting a netif pointer a problem at all ?

You can't safely modify the netif list using netif_add()/netif_remove()
outside of the tcpip thread context, and they would probably only be
added/removed by driver code anyway, in which case it would be in the tcpip
thread context.

If you're saying that it's okay to have a big layer violation between
application and net driver, then while obviously lwIP is all about layer
violations for efficiency :-), at the same time it does make it harder to
write reusable and portable higher layer code, which is one of the biggest
motivations for the existence of the netifapi really.

But as Joel pointed out, there have been thoughts about this already in
https://savannah.nongnu.org/task/?func=detailitem&item_id=14314 . I'll reply
to Joel about that.

Jifl
--
eCosCentric Limited      http://www.eCosCentric.com/     The eCos experts
Barnwell House, Barnwell Drive, Cambridge, UK.       Tel: +44 1223 245571
Registered in England and Wales: Reg No 4422071.
------["Si fractum non sit, noli id reficere"]------       Opinions==mine


_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

Jonathan Larmour
In reply to this post by Joel Cunningham-2
Thanks for the reply Joel.

On 16/03/18 13:48, Joel Cunningham wrote:

>
> On 03/15/2018 09:23 PM, Jonathan Larmour wrote:
>> I've noticed a limitation in the netifapi (not the netif API!) : [snip]
>
> This is definitely a limitation that has been discussed before on the list
> (see https://savannah.nongnu.org/task/index.php?14724). To me, the netif and
> netifapis are really only useful from code that manages a struct netif (owns
> the allocation/reference, so it can safely pass pointers). I think of this as
> link layer management code, which typically adds/removes the neift, applies
> configuration settings and not network application code that lives above the
> stack.

But it's not potentially just application code but higher layer protocol code.
Think of the requirements for

> I think for network application code, additional APIs are needed to get things
> like get address information, list of interfaces.  LwIP doesn't have any of
> the normal things like getifaddrs and in my projects, I've got custom code to
> do these lookups in a safe way.
>
> We made some progress implementing ifnametoindex/ifindextoname, but
> encountered some implementation issues with if_nameindex (which enumerates all
> interfaces).  See https://savannah.nongnu.org/task/?func=detailitem&item_id=14314
>
>>
>> Perhaps it could be argued that keeping lwIP simple means making compromises,
>> and maybe this is a compromise to make. But overall IMHO, the netif API would
>> be better off removing all mentions of struct netif* entirely. Instead each
>> function should take an if index.
>>
>> That brings me to a second issue, netif_find() assumes that the netif name is
>> exactly three chars long, the third being the if number from 0-9. The number
>> is assigned in netif_add() by incrementing a local static variable each time.
>> The problem here is that this means you can only ever have added 10 interfaces
>> before the API breaks, even if you have removed netifs in the meantime. Even
>> if we parsed the name argument as a normal NUL-terminated string, the index is
>> a u8_t. If there is a possibility that people can be adding/removing netif's
>> dynamically and repeatedly (think USB or PPP), this can't work long. The index
>> probably wants to be u32_t for safety given how long embedded devices can be
>> up for, and netif_find() needs to accept a normal NUL-terminated string and
>> use strtoul() on the number component.
>>
>> Next, if the numbers are part of the name, but are assigned by lwIP, how can
>> netif API users even find an interface except in the most simple static cases,
>> and making assumptions about interface initialisation order? It makes me think
>> we need an iterator function in netifapi to report the next used index (which
>> in practice just traverses the netif list). For example:
> Given how it's implemented on git master with the index, you're right the
> resulting name is non-deterministic. If we had something like
> getifaddrs/if_nameindex, we could enumerate the names, but I think having
> names which can be hardcoded into applications isn't a good practice.




--
eCosCentric Limited      http://www.eCosCentric.com/     The eCos experts
Barnwell House, Barnwell Drive, Cambridge, UK.       Tel: +44 1223 245571
Registered in England and Wales: Reg No 4422071.
------["Si fractum non sit, noli id reficere"]------       Opinions==mine

_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

Jonathan Larmour
In reply to this post by Joel Cunningham-2
[ Gah, stupid Enigmail managed to muck up the formatting of the reply to
Sylvain, as well as sending a mail prematurely. Sorry about the previous junk...]

Thanks for the reply Joel.

On 16/03/18 13:48, Joel Cunningham wrote:

>
> On 03/15/2018 09:23 PM, Jonathan Larmour wrote:
>> I've noticed a limitation in the netifapi (not the netif API!) : [snip]
>
> This is definitely a limitation that has been discussed before on the list
> (see https://savannah.nongnu.org/task/index.php?14724). To me, the netif and
> netifapis are really only useful from code that manages a struct netif (owns
> the allocation/reference, so it can safely pass pointers). I think of this as
> link layer management code, which typically adds/removes the neift, applies
> configuration settings and not network application code that lives above the
> stack.

But it's not potentially just application code but higher layer protocol code.
Think of something like mDNS, which ought to sit on top of lwIP, but would
need access to data which at the moment is only accessible in a netif.

Now, I'm not intending at this point to provide an all-singing all-dancing
abstraction and API to do that, but it would be good to be making steps in the
right direction and at the moment having the netifapi take 'struct netif *'
seems like it would store up problems for the future, in which case it's
better to address it sooner and switch to an index before things become too
hard to change.

> I think for network application code, additional APIs are needed to get things
> like get address information, list of interfaces.  LwIP doesn't have any of
> the normal things like getifaddrs and in my projects, I've got custom code to
> do these lookups in a safe way.

It's exactly the sort of thing netifapi should be able to do though, maybe not
immediately, but having the right sort of API for the future.

> We made some progress implementing ifnametoindex/ifindextoname, but
> encountered some implementation issues with if_nameindex (which enumerates all
> interfaces).  See https://savannah.nongnu.org/task/?func=detailitem&item_id=14314

Thanks, I hadn't seen that.

I assume it's
https://savannah.nongnu.org/task/?func=detailitem&item_id=14314#comment45 in
particular. I think the lwIP philosophy in general is make the "native"
interface be simple and low overhead. Anything that wants to add a
standards-compliant veneer that would add overheads should be the place for
taking a hit in space/efficiency.

So that implies to me we should either have a netifapi function as an iterator
(my preference - lower memory and doesn't need dynamic mem alloc), or a
function parallel to if_nameindex() but using netif types. The if_nameindex()
veneer would use the underlying netifapi, but entail a bit more overhead. This
fits with the lwIP philosophy in my mind.

>> Next, if the numbers are part of the name, but are assigned by lwIP, how can
>> netif API users even find an interface except in the most simple static cases,
>> and making assumptions about interface initialisation order? It makes me think
>> we need an iterator function in netifapi to report the next used index (which
>> in practice just traverses the netif list). For example:
> Given how it's implemented on git master with the index, you're right the
> resulting name is non-deterministic. If we had something like
> getifaddrs/if_nameindex, we could enumerate the names, but I think having
> names which can be hardcoded into applications isn't a good practice.

I'm not sure it's about hardcoding names necessarily[1], but being able to
find information about all available netif's, whatever they are. The current
situation is worse than a hardcoded name though - you need a hard-coded
reference to a specific netif structure.

Jifl

[1] Although existing practice on UNIX-y systems shows that having a naming
convention for names can be useful in practice, even if only a prefix, not a
number.
--
eCosCentric Limited      http://www.eCosCentric.com/     The eCos experts
Barnwell House, Barnwell Drive, Cambridge, UK.       Tel: +44 1223 245571
Registered in England and Wales: Reg No 4422071.
------["Si fractum non sit, noli id reficere"]------       Opinions==mine

_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

Sylvain Rochet
In reply to this post by Jonathan Larmour
Hi Jonathan,

On Sat, Mar 17, 2018 at 03:43:35PM +0000, Jonathan Larmour wrote:

> On 16/03/18 10:46, Sylvain Rochet wrote:
> >
> > Since netif struct is not allocated/freed by the stack itself, how is
> > getting a netif pointer a problem at all ?
>
> You can't safely modify the netif list using netif_add()/netif_remove()
> outside of the tcpip thread context, and they would probably only be
> added/removed by driver code anyway, in which case it would be in the tcpip
> thread context.
>
> If you're saying that it's okay to have a big layer violation between
> application and net driver, then while obviously lwIP is all about layer
> violations for efficiency :-), at the same time it does make it harder to
> write reusable and portable higher layer code, which is one of the biggest
> motivations for the existence of the netifapi really.
Well, I guess I just don't understand the issue here. For me netifapi is
just a wrapper to call netif_* functions inside the tcpip core thread.
(e.g. netifapi_netif_add() and netifapi_netif_remove() to call,
respectively, netif_add() and netif_remove() inside the tcpip thread.)

Other than that, netif struct allocation is done by application code so
using it in the netif/netifapi APIs should not be an issue, lwIP itself
is never going to change netif references. This is even true for PPP,
application code have to provide its own netif struct to ppp_new().

Sylvain

_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel

signature.asc (188 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

Joel Cunningham-2


On 03/19/2018 06:19 AM, Sylvain Rochet wrote:

> Hi Jonathan,
>
> On Sat, Mar 17, 2018 at 03:43:35PM +0000, Jonathan Larmour wrote:
>> On 16/03/18 10:46, Sylvain Rochet wrote:
>>> Since netif struct is not allocated/freed by the stack itself, how is
>>> getting a netif pointer a problem at all ?
>> You can't safely modify the netif list using netif_add()/netif_remove()
>> outside of the tcpip thread context, and they would probably only be
>> added/removed by driver code anyway, in which case it would be in the tcpip
>> thread context.
>>
>> If you're saying that it's okay to have a big layer violation between
>> application and net driver, then while obviously lwIP is all about layer
>> violations for efficiency :-), at the same time it does make it harder to
>> write reusable and portable higher layer code, which is one of the biggest
>> motivations for the existence of the netifapi really.
> Well, I guess I just don't understand the issue here. For me netifapi is
> just a wrapper to call netif_* functions inside the tcpip core thread.
> (e.g. netifapi_netif_add() and netifapi_netif_remove() to call,
> respectively, netif_add() and netif_remove() inside the tcpip thread.)
I kind of feel the same way that netifapi is just the netif API that can
be used outside the LwIP core context.  The level of APIs I'm looking
for (and I think is the same for Jonathan) largely don't exist except
if_nametoindex and if_indextoname.
>
> Other than that, netif struct allocation is done by application code so
> using it in the netif/netifapi APIs should not be an issue, lwIP itself
> is never going to change netif references. This is even true for PPP,
> application code have to provide its own netif struct to ppp_new().
I also agree here that code allocating the netif struct is what should
be using netifap/netif, but that is also not the same level of code
we've been discussing.

I've got a number of applications that use the sockets interface which
need things like getifaddrs/ioctl(...SIOCGIFCONF) which I've had to
write custom code which is effectively grabbing the core lock, then
iterating the netif list and returning configuration. The application
code doesn't do anything with LwIP's struct netif, nor would it have a
way to since the code managing struct netif is in a completely different
part of the system (what I refer to as link layer management code).

Joel






_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

Joel Cunningham-2
In reply to this post by Jonathan Larmour


On 03/17/2018 11:16 AM, Jonathan Larmour wrote:

> [ Gah, stupid Enigmail managed to muck up the formatting of the reply to
> Sylvain, as well as sending a mail prematurely. Sorry about the previous junk...]
>
> Thanks for the reply Joel.
>
> On 16/03/18 13:48, Joel Cunningham wrote:
>> On 03/15/2018 09:23 PM, Jonathan Larmour wrote:
>>> I've noticed a limitation in the netifapi (not the netif API!) : [snip]
>> This is definitely a limitation that has been discussed before on the list
>> (see https://savannah.nongnu.org/task/index.php?14724). To me, the netif and
>> netifapis are really only useful from code that manages a struct netif (owns
>> the allocation/reference, so it can safely pass pointers). I think of this as
>> link layer management code, which typically adds/removes the neift, applies
>> configuration settings and not network application code that lives above the
>> stack.
> But it's not potentially just application code but higher layer protocol code.
> Think of something like mDNS, which ought to sit on top of lwIP, but would
> need access to data which at the moment is only accessible in a netif.
>
> Now, I'm not intending at this point to provide an all-singing all-dancing
> abstraction and API to do that, but it would be good to be making steps in the
> right direction and at the moment having the netifapi take 'struct netif *'
> seems like it would store up problems for the future, in which case it's
> better to address it sooner and switch to an index before things become too
> hard to change.
I'm not sure I'm for changing netifapi since code managing the struct
netif can safely use these.  I think I'd be more in favor of a new set
of APIs.
>> I think for network application code, additional APIs are needed to get things
>> like get address information, list of interfaces.  LwIP doesn't have any of
>> the normal things like getifaddrs and in my projects, I've got custom code to
>> do these lookups in a safe way.
> It's exactly the sort of thing netifapi should be able to do though, maybe not
> immediately, but having the right sort of API for the future.
I agree we should have APIs that do this, but I don't have strong
feelings that it should be netifapi. I will eventually want to implement
things at the socket levels so I can re-enable interface code in some
common OSS applications that I've currently had to disable (use of
getifaddrs for example).

When we originally added if_nametoindex and if_indextoname, the only
reason netifapi was used was to avoid creating another API abstraction
that dealt with the non-core locking case and the MPU support.  This
secondary non-core locking + MPU case is a big pain to support and in
newer development, we've just said the non-core locking isn't supported
for this feature.

>
>> We made some progress implementing ifnametoindex/ifindextoname, but
>> encountered some implementation issues with if_nameindex (which enumerates all
>> interfaces).  See https://savannah.nongnu.org/task/?func=detailitem&item_id=14314
> Thanks, I hadn't seen that.
>
> I assume it's
> https://savannah.nongnu.org/task/?func=detailitem&item_id=14314#comment45 in
> particular. I think the lwIP philosophy in general is make the "native"
> interface be simple and low overhead. Anything that wants to add a
> standards-compliant veneer that would add overheads should be the place for
> taking a hit in space/efficiency.
>
> So that implies to me we should either have a netifapi function as an iterator
> (my preference - lower memory and doesn't need dynamic mem alloc), or a
> function parallel to if_nameindex() but using netif types. The if_nameindex()
> veneer would use the underlying netifapi, but entail a bit more overhead. This
> fits with the lwIP philosophy in my mind.
The problem with an iterator is the inherent race in trying to iterate
while leaving the LwIP core for each iteration. A netif_add/remove could
happen during an iteration and cause a bunch of nasty cases.  I'm more
in fan of a single call that returns an atomic snapshot of the
interfaces at the time of the call, but this requires a dynamic memory
allocation within netifapi

The other thing limiting the implementation was that back at that time:
support the non-core locking + MPU case. Now that we've set precedence
that we don't have to support that case, we could implement
if_nameindex() exclusively in if_api.c, but only for the core locking case.

>>> Next, if the numbers are part of the name, but are assigned by lwIP, how can
>>> netif API users even find an interface except in the most simple static cases,
>>> and making assumptions about interface initialisation order? It makes me think
>>> we need an iterator function in netifapi to report the next used index (which
>>> in practice just traverses the netif list). For example:
>> Given how it's implemented on git master with the index, you're right the
>> resulting name is non-deterministic. If we had something like
>> getifaddrs/if_nameindex, we could enumerate the names, but I think having
>> names which can be hardcoded into applications isn't a good practice.
> I'm not sure it's about hardcoding names necessarily[1], but being able to
> find information about all available netif's, whatever they are. The current
> situation is worse than a hardcoded name though - you need a hard-coded
> reference to a specific netif structure.
Agree, holding a reference to struct netif in code that doesn't own that
instance is very dangerous.
>
> Jifl
>
> [1] Although existing practice on UNIX-y systems shows that having a naming
> convention for names can be useful in practice, even if only a prefix, not a
> number.
I need to spin up more on naming under Linux, but I've seen kernel
features for different kinds of names depending on the driver, i.e.
predictable vs unpredictable naming. At least on my Ubuntu 17.10 box,
it's renaming the devices to have long numbers, appears to be based off MAC:

$ ifconfig -a

wlx6466b31999f5: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
         ether 64:66:b3:19:99:f5  txqueuelen 1000  (Ethernet)
         RX packets 0  bytes 0 (0.0 B)
         RX errors 0  dropped 0  overruns 0  frame 0
         TX packets 0  bytes 0 (0.0 B)
         TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Joel


_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

Jonathan Larmour
In reply to this post by Sylvain Rochet
Thanks for replying Sylvain,

On 19/03/18 11:19, Sylvain Rochet wrote:

> On Sat, Mar 17, 2018 at 03:43:35PM +0000, Jonathan Larmour wrote:
>>
>> If you're saying that it's okay to have a big layer violation between
>> application and net driver, then while obviously lwIP is all about
>> layer violations for efficiency :-), at the same time it does make it
>> harder to write reusable and portable higher layer code, which is one
>> of the biggest motivations for the existence of the netifapi really.
>
> Well, I guess I just don't understand the issue here. For me netifapi is
>  just a wrapper to call netif_* functions inside the tcpip core thread.
> (e.g. netifapi_netif_add() and netifapi_netif_remove() to call,
> respectively, netif_add() and netif_remove() inside the tcpip thread.)

There are two scenarios I'm thinking of: one is that there isn't always a
strict divide between lwIP on one side and application on the other - there
can be higher level subsystems, modules or protocol implementations, which
sit between lwIP itself and the application. The second is simply code
reusability: someone wants to write code that will work on this product, and
doesn't need magic to be changed to work on the next just because it uses
e.g. a different ethernet driver. Having to build directly in to such code
knowledge of specific netif's would not be good practice.

> Other than that, netif struct allocation is done by application code so
> using it in the netif/netifapi APIs should not be an issue, lwIP itself
> is never going to change netif references.

I know you are interpreting "application" as "anything not lwIP", but I'm
trying to say that there is more to it than that :-).

Take as an example: lower level hardware-specific code can bring up one or
possibly many interfaces. This code conceptually sits underneath even lwIP.
But higher layer code (above lwIP) may want to provide a web server with
management interface to allow users of this product to do things like switch
between DHCP or static IP settings on whatever interfaces are available.

Now it is certainly possible for supposedly reusable high level code to
bypass lwIP and have fingers in the low level code in order to access the
netifs - you have the source so anything is possible. But it is poor design
practice and leads to unportable code. And gets complicated when there could
be things like USB ethernet devices which can be plugged and unplugged at
any time. I don't think that is a good thing and instead is the sort of
thing the netifapi should be solving and _can_ solve. lwIP should be acting
as the intermediary between high level code using lwIP and hardware drivers
underneath lwIP.

Another possibility I guess is to retain the existing functions which take
'struct netif*' arguments, but also add variants which take if index
arguments. e.g. netifapi_dhcp_start() and netifapi_dhcp_start_by_index().
[Note, these shouldn't just be wrappers for e.g. netifapi_dhcp_start()
because I would be concerned about netif pointers going stale if a netif did
happen to get removed by code elsewhere at the same time - think USB eth
again]. But it would be easy to tweak struct netifapi_msg to support an
index instead of netif and netifapi_api_common do the right thing with it.

Does this sort of thing sound like a step forward?

Jifl
--
------["Si fractum non sit, noli id reficere"]------       Opinions==mine

_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

Jonathan Larmour
In reply to this post by Joel Cunningham-2
On 19/03/18 22:07, Joel Cunningham wrote:
> On 03/17/2018 11:16 AM, Jonathan Larmour wrote:
>> On 16/03/18 13:48, Joel Cunningham wrote:
>>> On 03/15/2018 09:23 PM, Jonathan Larmour wrote:
>> It's exactly the sort of thing netifapi should be able to do though, maybe not
>> immediately, but having the right sort of API for the future.
> I agree we should have APIs that do this, but I don't have strong feelings
> that it should be netifapi. I will eventually want to implement things at the
> socket levels so I can re-enable interface code in some common OSS
> applications that I've currently had to disable (use of getifaddrs for example).

Having variants which take interfaces would help here, as per my reply to Sylvain.

>> I assume it's
>> https://savannah.nongnu.org/task/?func=detailitem&item_id=14314#comment45 in
>> particular. I think the lwIP philosophy in general is make the "native"
>> interface be simple and low overhead. Anything that wants to add a
>> standards-compliant veneer that would add overheads should be the place for
>> taking a hit in space/efficiency.
>>
>> So that implies to me we should either have a netifapi function as an iterator
>> (my preference - lower memory and doesn't need dynamic mem alloc), or a
>> function parallel to if_nameindex() but using netif types. The if_nameindex()
>> veneer would use the underlying netifapi, but entail a bit more overhead. This
>> fits with the lwIP philosophy in my mind.
> The problem with an iterator is the inherent race in trying to iterate while
> leaving the LwIP core for each iteration. A netif_add/remove could happen
> during an iteration and cause a bunch of nasty cases.

Yes, you're right.

> I'm more in fan of a
> single call that returns an atomic snapshot of the interfaces at the time of
> the call, but this requires a dynamic memory allocation within netifapi

An alternative is that we require the caller pass in an array of (index,name)
tuples, along with the number of entries in that array. This covers well the
scenario that the caller will probably know exactly how big to make that array
anyway; and if they don't know exactly, it's up to them not lwIP to decide
what they consider the maximum. A return code could indicate if there were
more netif's than would fit. Each name member would be IF_NAMESIZE bytes
(currently 6).

An implementation of if_nameindex() could easily wrap this by dynamically
allocating that array and passing in the size-1 to allow for the final entry
needing to be (0,NULL).

>> [1] Although existing practice on UNIX-y systems shows that having a naming
>> convention for names can be useful in practice, even if only a prefix, not a
>> number.
> I need to spin up more on naming under Linux, but I've seen kernel features
> for different kinds of names depending on the driver, i.e. predictable vs
> unpredictable naming. At least on my Ubuntu 17.10 box, it's renaming the
> devices to have long numbers, appears to be based off MAC:
>
> $ ifconfig -a
>
> wlx6466b31999f5: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
>         ether 64:66:b3:19:99:f5  txqueuelen 1000  (Ethernet)
>         RX packets 0  bytes 0 (0.0 B)
>         RX errors 0  dropped 0  overruns 0  frame 0
>         TX packets 0  bytes 0 (0.0 B)
>         TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Long suffix yes, but looks from the prefix that it's a Broadcom wireless lan
(wl) driver :-). More relevant is that Linux knows the device class is
Ethernet, but I'd rather not have that in lwIP as it would just take up space
permanently in a netif for something few users would need.

Jifl
--
eCosCentric Limited      http://www.eCosCentric.com/     The eCos experts
Barnwell House, Barnwell Drive, Cambridge, UK.       Tel: +44 1223 245571
Registered in England and Wales: Reg No 4422071.
------["Si fractum non sit, noli id reficere"]------       Opinions==mine

_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

Sylvain Rochet
In reply to this post by Joel Cunningham-2
Hi Joel,

On Mon, Mar 19, 2018 at 05:07:20PM -0500, Joel Cunningham wrote:
>
> I need to spin up more on naming under Linux, but I've seen kernel features
> for different kinds of names depending on the driver, i.e. predictable vs
> unpredictable naming. At least on my Ubuntu 17.10 box, it's renaming the
> devices to have long numbers, appears to be based off MAC:
>
> $ ifconfig -a
>
> wlx6466b31999f5: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500

Actually it isn't a kernel feature, this is systemd predictable network
interface names feature. Having that is very welcome for network
configurators.

https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/

Sylvain

_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel

signature.asc (188 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

Joel Cunningham-2


On 03/20/2018 04:34 AM, Sylvain Rochet wrote:

> Hi Joel,
>
> On Mon, Mar 19, 2018 at 05:07:20PM -0500, Joel Cunningham wrote:
>> I need to spin up more on naming under Linux, but I've seen kernel features
>> for different kinds of names depending on the driver, i.e. predictable vs
>> unpredictable naming. At least on my Ubuntu 17.10 box, it's renaming the
>> devices to have long numbers, appears to be based off MAC:
>>
>> $ ifconfig -a
>>
>> wlx6466b31999f5: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
> Actually it isn't a kernel feature, this is systemd predictable network
> interface names feature. Having that is very welcome for network
> configurators.
>
> https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/
The background on the systemd page was very helpful, thanks!

There is some kernel side support in netdev, see
https://github.com/torvalds/linux/commit/685343fc3ba61a1f6eef361b786601123db16c28

Joel


_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

Joel Cunningham-2
In reply to this post by Jonathan Larmour


On 03/19/2018 07:44 PM, Jonathan Larmour wrote:

> On 19/03/18 22:07, Joel Cunningham wrote:
>> On 03/17/2018 11:16 AM, Jonathan Larmour wrote:
>>> On 16/03/18 13:48, Joel Cunningham wrote:
>>>> On 03/15/2018 09:23 PM, Jonathan Larmour wrote:
>>> It's exactly the sort of thing netifapi should be able to do though, maybe not
>>> immediately, but having the right sort of API for the future.
>> I agree we should have APIs that do this, but I don't have strong feelings
>> that it should be netifapi. I will eventually want to implement things at the
>> socket levels so I can re-enable interface code in some common OSS
>> applications that I've currently had to disable (use of getifaddrs for example).
> Having variants which take interfaces would help here, as per my reply to Sylvain.
>
>>> I assume it's
>>> https://savannah.nongnu.org/task/?func=detailitem&item_id=14314#comment45 in
>>> particular. I think the lwIP philosophy in general is make the "native"
>>> interface be simple and low overhead. Anything that wants to add a
>>> standards-compliant veneer that would add overheads should be the place for
>>> taking a hit in space/efficiency.
>>>
>>> So that implies to me we should either have a netifapi function as an iterator
>>> (my preference - lower memory and doesn't need dynamic mem alloc), or a
>>> function parallel to if_nameindex() but using netif types. The if_nameindex()
>>> veneer would use the underlying netifapi, but entail a bit more overhead. This
>>> fits with the lwIP philosophy in my mind.
>> The problem with an iterator is the inherent race in trying to iterate while
>> leaving the LwIP core for each iteration. A netif_add/remove could happen
>> during an iteration and cause a bunch of nasty cases.
> Yes, you're right.
>
>> I'm more in fan of a
>> single call that returns an atomic snapshot of the interfaces at the time of
>> the call, but this requires a dynamic memory allocation within netifapi
> An alternative is that we require the caller pass in an array of (index,name)
> tuples, along with the number of entries in that array. This covers well the
> scenario that the caller will probably know exactly how big to make that array
> anyway; and if they don't know exactly, it's up to them not lwIP to decide
> what they consider the maximum. A return code could indicate if there were
> more netif's than would fit. Each name member would be IF_NAMESIZE bytes
> (currently 6).
>
> An implementation of if_nameindex() could easily wrap this by dynamically
> allocating that array and passing in the size-1 to allow for the final entry
> needing to be (0,NULL).

That's a good idea, keeps the netifapi "lightweight" while having the
dynamic behavior in if_nametoindex().  I don't have much free time to
work on this for the next foreseeable weeks, but when I do, maybe I can
dust off my old prototype and take a stab at this.

>
>>> [1] Although existing practice on UNIX-y systems shows that having a naming
>>> convention for names can be useful in practice, even if only a prefix, not a
>>> number.
>> I need to spin up more on naming under Linux, but I've seen kernel features
>> for different kinds of names depending on the driver, i.e. predictable vs
>> unpredictable naming. At least on my Ubuntu 17.10 box, it's renaming the
>> devices to have long numbers, appears to be based off MAC:
>>
>> $ ifconfig -a
>>
>> wlx6466b31999f5: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
>>          ether 64:66:b3:19:99:f5  txqueuelen 1000  (Ethernet)
>>          RX packets 0  bytes 0 (0.0 B)
>>          RX errors 0  dropped 0  overruns 0  frame 0
>>          TX packets 0  bytes 0 (0.0 B)
>>          TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
> Long suffix yes, but looks from the prefix that it's a Broadcom wireless lan
> (wl) driver :-). More relevant is that Linux knows the device class is
> Ethernet, but I'd rather not have that in lwIP as it would just take up space
> permanently in a netif for something few users would need.

Joel


_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

Re: netifapi limitations

goldsimon@gmx.de
Joel Cunningham wrote:
> On 03/19/2018 07:44 PM, Jonathan Larmour wrote:
> > On 19/03/18 22:07, Joel Cunningham wrote:
> >> On 03/17/2018 11:16 AM, Jonathan Larmour wrote:
> >>> On 16/03/18 13:48, Joel Cunningham wrote:
> >>>> On 03/15/2018 09:23 PM, Jonathan Larmour wrote:
> >>> [..]

After being quite offline for a while, I just wanted to let you know
my opinion on this:

I think the current netifapi has its valid users. Adding a new API
somewhere around the socket API is a better idea, I think.

Thanks,
Simon

_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel