Skip to content

ports/rp2: Enable ipv6 per default for rp2. #15422

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

Merged
merged 1 commit into from
Jul 24, 2024

Conversation

felixdoerre
Copy link
Contributor

Summary

Having IPv6 support is important, especially for IoT-Devices which might be many, requiring individual IP-addresses. In particular direct access via link-local addresses and having deterministic SLAAC-addresses can be quite convenient. Also in IPv6-only networks or for connecting to IPv6-only services, this is very useful.

I believe that for the Raspberry Pico W, there is enough flash and RAM that enabling IPv6 by default is the right choice.

Testing

I'm using this change on a Raspberry Pico W for nearly 2 years now and haven't experienced any problems.

Trade-offs and Alternatives

Should IPv6 support in a network exist (i.e. there are Router Advertisements), but not provide connectivity, connecting by domain name should not be a problem, as DNS will default to return the IPv4-address, if existent, unless reconfigured at runtime to prefer IPv6.

In any case a user can disable obtaining SLAAC-addresses with <nic>.ipconfig(autoconf6=False).

Copy link

github-actions bot commented Jul 7, 2024

Code size report:

   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:    +0 +0.000% standard
      stm32:    +0 +0.000% PYBV10
     mimxrt:    +0 +0.000% TEENSY40
        rp2: +27916 +3.185% RPI_PICO_W[incl +3020(bss)]
       samd:    +0 +0.000% ADAFRUIT_ITSYBITSY_M4_EXPRESS

@dpgeorge
Copy link
Member

dpgeorge commented Jul 8, 2024

Thanks for this.

We can see from the CI how much flash and RAM it takes:

rp2: +28492 +3.251% RPI_PICO_W[incl +3476(bss)]

So that's 25016 bytes of flash and 3476 bytes of RAM. That's quite a lot more than I expected. The flash increase is acceptable, but the RAM usage... that will decrease the amount of MicroPython heap and may impact existing applications.

Are there any settings to tune down the amount of RAM needed by IPv6?

@felixdoerre
Copy link
Contributor Author

I think I've identified the 2 main chunks of that increase:

  1. ND6 neighbor and IPv6 routing tables:
#define LWIP_ND6_NUM_NEIGHBORS          10
neighbor_cache -> 440
#define LWIP_ND6_NUM_PREFIXES           5
prefix_list -> 140
#define LWIP_ND6_NUM_DESTINATIONS       10
destination_cache -> 480
#define LWIP_ND6_NUM_ROUTERS            3
default_router_list 36

They total 1096 bytes, and their sizes (in entries) match the sizes of corresponding IPv4/ARP tables.

  1. LWIP memory pools: LWIP maintains pools for objects for various purposes, like TCP-pcbs, and others:
memp_memory_*_base old: 16879 -> 18601 (+1722)

This increase can be split in two parts:

new tables:
  memp_memory_IP6_REASSDATA_base +163
  memp_memory_MLD6_GROUP_base +131
  memp_memory_ND6_QUEUE_base +163
increase in existing tables (due to ip addresses now being larger in size): 1265

For the remaining 858 bytes I wasn't able to pinpoint a particular source. But they seem to stem from more individual pointers, realignment, and probably more increasing of the ip_addr-type. For plain comparison I patched around locally, to make micropython compile ipv6-only and ended up with +2251 bytes (compared to v4 only).

So I don't think there is much to tune here. We could tune down (half?) NUM_NEIGHBORS and NUM_DESTINATIONS, that would save around 460 bytes. Compared to the ARP table, that's 10 entries large with 24 bytes each, I am not sure that the reduced functionality that comes with the reduced tables is worth it.

@dpgeorge
Copy link
Member

Thanks for looking into the RAM size increase.

increase in existing tables (due to ip addresses now being larger in size): 1265

This looks like the biggest culprit, and there's not much we can do about it. You simply need more bytes to store larger addresses.

So I don't think there is much to tune here. We could tune down (half?) NUM_NEIGHBORS and NUM_DESTINATIONS, that would save around 460 bytes

That seems kind of reasonable. I don't really know enough about IPv6 to understand if 10 neighbours/destinations is large or not. Is it really going to impact things reducing that? Will reducing it just lead to less performance, or will it mean some packets can no longer be routed?

Note that the GC heap size on Pico W will decrease by the amount of extra RAM used by lwIP, so this will be noticed by users.

@felixdoerre
Copy link
Contributor Author

Is it really going to impact things reducing that? Will reducing it just lead to less performance, or will it mean some packets can no longer be routed?

This table is essentially the same as the ARP table for ipv4 (also currently at 10 entries). It should above/around the number of local network devices you expect to communicate with. So the bare minimum is maybe around 3. And reducing to 5 might be sensible, but, of course, this depends on the needs of the network and application.

Basically, if you want to send an IP packet to a local address, you need the mac address so you know how to address the ethernet packet around it. For IPv4 you'll do an ARP request, for IPv6 you'll do a neighbor solicitation. If you're constantly connected with more than (currently) 10 clients in the local network, the cache will get evicted and you'll need to re-request their address (sending packets, causing delays). I'd argue that if we tune down down NUM_NEIGHBORS (for IPv6) we should also tune down ARP_TABLE_SIZE (for IPv4), to have similar eviction behavior.

Tuning down NUM_DESTINATIONS feels less intrusive to me. Looking at the code it seems to have 2 consequences:

  • lwip needs to re-calculate the next hop when sending packets to that destination. I think the impact for that should be negligible.
  • Handle/Store the adjustments for ICMP6_TYPE_RD an ICMP6_TYPE_PTB. I think that these will only happen very, very rarely and the corresponding IPv4 features are not even implemented (and on "big" systems often deactivated). I would even argue that we don't need that feature at all, however there does not seem to be a lwip flag to turn it off.

@dpgeorge dpgeorge added this to the release-1.24.0 milestone Jul 22, 2024
@dpgeorge
Copy link
Member

Tuning down NUM_DESTINATIONS feels less intrusive to me.

OK, how about we turn that down to 4?

I also looked at the following:

  • memp_memory_IP6_REASSDATA_base - this setting is MEMP_NUM_REASSDATA and is the same for the IP4, so we can't change this (don't want to change the IP4 setting)
  • memp_memory_MLD6_GROUP_base - this defaults to MEMP_NUM_MLD6_GROUP = 4 and that seems like a reasonable value, wouldn't really want to go less than that, especially if MDNS is in use
  • memp_memory_ND6_QUEUE_base - this defaults to MEMP_NUM_ND6_QUEUE = 20 and I think we can tune that down, maybe to 10? Or we could even disable that feature entirely via disabling LWIP_ND6_QUEUEING. Do we need that feature?

@felixdoerre
Copy link
Contributor Author

Tuning down NUM_DESTINATIONS feels less intrusive to me.

OK, how about we turn that down to 4?

Sounds good to me.

disabling LWIP_ND6_QUEUEING. Do we need that feature?

Given that the corresponding v4 feature (ARP_QUEUEING) is disabled by default, I think we can disable that.

@dpgeorge
Copy link
Member

OK, can you please make the above two config tweaks to this PR?

Having IPv6 support is important, especially for IoT-Devices which might be
many, requiring individual IP-addresses. In particular direct access via
link-local addresses and having deterministic SLAAC-addresses can be quite
convenient. Also in IPv6-only networks or for connecting to IPv6-only
services, this is very useful.

For the Pico W, there is enough flash and RAM that enabling IPv6 by default
is the right choice.

Should IPv6 support in a network exist (i.e. there are Router
Advertisements), but not provide connectivity, connecting by domain name
should not be a problem as DNS will default to return the IPv4-address (if
that exists), unless reconfigured at runtime to prefer IPv6.

In any case a user can disable obtaining SLAAC-addresses with:

    <nic>.ipconfig(autoconf6=False)

Signed-off-by: Felix Dörre <[email protected]>
@dpgeorge dpgeorge merged commit 7fe8f03 into micropython:master Jul 24, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants