Skip to content

feat(network): Use ip= parameter for configuring networking - #2638

Open
Gelbpunkt wants to merge 5 commits into
hermit-os:mainfrom
Gelbpunkt:parse-ip-param
Open

feat(network): Use ip= parameter for configuring networking#2638
Gelbpunkt wants to merge 5 commits into
hermit-os:mainfrom
Gelbpunkt:parse-ip-param

Conversation

@Gelbpunkt

Copy link
Copy Markdown
Member

This is a breaking change and replaces HERMIT_IP, HERMIT_MASK, HERMIT_GATEWAY, HERMIT_DNS1 and HERMIT_DNS2 with a single command-line parameter, ip=, which is heavily inspired by Linux.

The kernel will fall back to DHCP if it is enabled, otherwise it will now also no longer fall back to "magic" IPs, instead it will leave the interface unconfigured. Instead, only xtask contains the default static IP configuration that used to reside there and in the kernel.

This is in preparation for adding IPv6 support, which we decided against introducing new variables for. The same mechanism introduced here can be used to support IPv6 with minimal changes.

@mkroening

Copy link
Copy Markdown
Member

@jounathaen and @sarahspberrypi are okay with the concept. Is this also ok for you, @stlankes?

@Gelbpunkt
Gelbpunkt force-pushed the parse-ip-param branch 4 times, most recently from 57eb68d to af2377c Compare August 13, 2026 17:19

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Benchmark Results

Details
Benchmark Current: a31d0f6 Previous: 2e23902 Performance Ratio
startup_benchmark Build Time 93.64 s 80.34 s 1.17
startup_benchmark File Size 0.79 MB 0.80 MB 1.00
Startup Time - 1 core 0.73 s (±0.02 s) 0.75 s (±0.02 s) 0.98
Startup Time - 2 cores 0.75 s (±0.02 s) 0.74 s (±0.02 s) 1.02
Startup Time - 4 cores 0.74 s (±0.03 s) 0.74 s (±0.02 s) 1.00
multithreaded_benchmark Build Time 91.20 s 82.11 s 1.11
multithreaded_benchmark File Size 0.85 MB 0.86 MB 0.99
Multithreaded Pi Efficiency - 2 Threads 88.33 % (±8.61 %) 85.89 % (±6.61 %) 1.03
Multithreaded Pi Efficiency - 4 Threads 43.89 % (±2.85 %) 43.43 % (±2.56 %) 1.01
Multithreaded Pi Efficiency - 8 Threads 25.81 % (±1.36 %) 25.76 % (±1.53 %) 1.00
micro_benchmarks Build Time 94.55 s 80.40 s 1.18
micro_benchmarks File Size 0.85 MB 0.86 MB 0.99
Scheduling time - 1 thread 65.02 ticks (±3.18 ticks) 62.65 ticks (±4.06 ticks) 1.04
Scheduling time - 2 threads 36.70 ticks (±5.23 ticks) 34.08 ticks (±4.10 ticks) 1.08
Micro - Time for syscall (getpid) 3.84 ticks (±0.68 ticks) 3.45 ticks (±0.58 ticks) 1.11
Memcpy speed - (built_in) block size 4096 75002.94 MByte/s (±52303.87 MByte/s) 82448.38 MByte/s (±56997.13 MByte/s) 0.91
Memcpy speed - (built_in) block size 1048576 29806.02 MByte/s (±24065.08 MByte/s) 30585.98 MByte/s (±24707.84 MByte/s) 0.97
Memcpy speed - (built_in) block size 16777216 25275.77 MByte/s (±21053.65 MByte/s) 26340.06 MByte/s (±21720.96 MByte/s) 0.96
Memset speed - (built_in) block size 4096 75308.21 MByte/s (±52474.73 MByte/s) 82292.76 MByte/s (±56891.50 MByte/s) 0.92
Memset speed - (built_in) block size 1048576 30521.12 MByte/s (±24479.60 MByte/s) 31323.85 MByte/s (±25145.86 MByte/s) 0.97
Memset speed - (built_in) block size 16777216 26027.22 MByte/s (±21539.56 MByte/s) 27104.68 MByte/s (±22209.94 MByte/s) 0.96
Memcpy speed - (rust) block size 4096 70089.66 MByte/s (±48829.74 MByte/s) 74097.96 MByte/s (±51811.44 MByte/s) 0.95
Memcpy speed - (rust) block size 1048576 29790.64 MByte/s (±24199.62 MByte/s) 30361.60 MByte/s (±24602.37 MByte/s) 0.98
Memcpy speed - (rust) block size 16777216 25762.17 MByte/s (±21334.69 MByte/s) 27625.34 MByte/s (±22806.88 MByte/s) 0.93
Memset speed - (rust) block size 4096 70547.19 MByte/s (±49114.03 MByte/s) 74373.47 MByte/s (±51976.48 MByte/s) 0.95
Memset speed - (rust) block size 1048576 30518.38 MByte/s (±24610.51 MByte/s) 31110.89 MByte/s (±25033.24 MByte/s) 0.98
Memset speed - (rust) block size 16777216 26512.01 MByte/s (±21807.80 MByte/s) 28386.93 MByte/s (±23265.03 MByte/s) 0.93
alloc_benchmarks Build Time 84.28 s 74.76 s 1.13
alloc_benchmarks File Size 0.87 MB 0.87 MB 1.00
Allocations - Allocation success 91.38 % 91.31 % 1.00
Allocations - Deallocation success 100.00 % 100.00 % 1
Allocations - Pre-fail Allocations 61.60 % 61.44 % 1.00
Allocations - Average Allocation time 9076.84 Ticks (±139.95 Ticks) 5860.58 Ticks (±98.43 Ticks) 1.55
Allocations - Average Allocation time (no fail) 9652.81 Ticks (±232.80 Ticks) 6554.81 Ticks (±92.86 Ticks) 1.47
Allocations - Average Deallocation time 2711.21 Ticks (±540.82 Ticks) 1805.01 Ticks (±250.35 Ticks) 1.50
mutex_benchmark Build Time 84.81 s 79.82 s 1.06
mutex_benchmark File Size 0.85 MB 0.86 MB 0.99
Mutex Stress Test Average Time per Iteration - 1 Threads 12.94 ns (±0.42 ns) 12.10 ns (±0.41 ns) 1.07
Mutex Stress Test Average Time per Iteration - 2 Threads 87.58 ns (±3.11 ns) 40.26 ns (±1.68 ns) 2.18

This comment was automatically generated by workflow using github-action-benchmark.

@mkroening mkroening self-assigned this Aug 15, 2026

@mkroening mkroening left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for taking care of this! :)

Does the format also work well with IPv6 addresses? I assume we would do something like ip=[2001:db8::8a2e:370:7334]:[2001:db8::8a2e:370:7334], right?

Comment thread src/env/mod.rs
Comment on lines -70 to -81
"-ip" => {
let ip = expect_arg(words.next(), word.as_str());
env_vars.insert(String::from("HERMIT_IP"), ip);
}
"-mask" => {
let mask = expect_arg(words.next(), word.as_str());
env_vars.insert(String::from("HERMIT_MASK"), mask);
}
"-gateway" => {
let gateway = expect_arg(words.next(), word.as_str());
env_vars.insert(String::from("HERMIT_GATEWAY"), gateway);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you add a warning that these are no longer supported and ip= should be used instead? Same thing for the corresponding hermit_var!(...)s, which are commonly set at compile time at the moment.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done, wasn't so sure about the warning messages but I hope this is fine

Comment thread src/env/ip_configuration.rs Outdated
Comment thread src/env/ip_configuration.rs Outdated
/// This is heavily inspired by the Linux kernel's parameter of the same name:
/// <https://docs.kernel.org/admin-guide/nfs/nfsroot.html#kernel-command-line>
#[derive(Clone, Copy, Debug, Default)]
pub struct IpConfiguration {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: Move the most important type to the top of the file and the helpers down to help readers with discoverability.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think I ordered them in a sensible order now, please take a look :)

…MASK

Setting just HERMIT_IP=10.0.5.3/24 is much more convenient than
HERMIT_IP=10.0.5.3 and HERMIT_MASK=255.255.255.0 and lets us avoid
variable hell once we end up adding proper IPv6 support.
This is heavily inspired by Linux' ip= parameter, see
https://docs.kernel.org/admin-guide/nfs/nfsroot.html#kernel-command-line

The facilities are currently unused and will be replacing HERMIT_IP and
HERMIT_GATEWAY in a followup commit.
@Gelbpunkt

Copy link
Copy Markdown
Member Author

Does the format also work well with IPv6 addresses? I assume we would do something like ip=[2001:db8::8a2e:370:7334]:[2001:db8::8a2e:370:7334], right?

Yes, this is roughly what I had in mind. It will work just fine with IPv6 addresses once we do a tiny bit of modifications (since this currently hardcodes IPv4 types, but that's a trivial change later).

I believe dhcp should just imply both dhcpv4 and dhcpv6 eventually if both are available and if we want to use both IPv6 and IPv4 networking on the same interface, we can pass ip= simply twice, once for configuring IPv4 and once for IPv6. Alternatively we could rename dhcp to dhcpv4 and make it explicit.

@mkroening mkroening left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good to me. 👍

Let's wait for @stlankes's opinion in a week. :)

@mkroening mkroening assigned stlankes and unassigned mkroening Aug 31, 2026
@stlankes
stlankes self-requested a review September 13, 2026 20:21

@stlankes stlankes left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I have a few questions...

If I the invalid ip ip=10.0.5.4/64, I got following panic:

[0][PANIC] panicked at /Users/stefan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/smoltcp-0.14.0/src/wire/ipv4.rs:101:9:
assertion failed: prefix_len <= 32

Also an empty gateway panics. For instance, ip=10.0.5.3/24:: creates following panic.

[0][PANIC] panicked at src/env/mod.rs:86:31:
Could not parse configuration for default interface: invalid gateway IP address

Should we panic on invalid input, or just log a warning?

But I like the PR!

@stlankes

Copy link
Copy Markdown
Contributor

@Gelbpunkt I hope that I fix merge conflicts correctly

@stlankes

Copy link
Copy Markdown
Contributor

I talked to @mkroening and now I am finde with the PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants