Skip to content

dhcp: add configurable backoff parameters for DHCPv4#593

Open
cjp256 wants to merge 1 commit into
NetworkConfiguration:masterfrom
cjp256:backoff
Open

dhcp: add configurable backoff parameters for DHCPv4#593
cjp256 wants to merge 1 commit into
NetworkConfiguration:masterfrom
cjp256:backoff

Conversation

@cjp256

@cjp256 cjp256 commented Mar 27, 2026

Copy link
Copy Markdown

In cloud and virtual environments the DHCP service is typically ready within hundreds of milliseconds of the interface coming up, and once ready, responds within single-digit milliseconds. The RFC 2131 defaults (4s initial interval, 64s backoff cap) are designed for congested broadcast networks and are unnecessarily conservative in this context.

Add three new configuration options to tune DHCPv4 retransmission:

initial_interval - initial retransmission interval (default 4s)
backoff_cutoff - exponential backoff cap (default 64s)
backoff_jitter - random jitter per retry (default ±1000ms)

Defaults match RFC 2131 so existing behaviour is unchanged. Option naming aligns with dhclient (initial-interval, backoff-cutoff). Minimum of 1 is enforced at parse time for interval and cutoff; invalid values are logged and the default is used.

These options are DHCPv4-only; DHCPv6 retransmission follows RFC 8415 constants and is not user-configurable.

A test harness (tests/backoff/test_backoff.c) was used to validate timing assumptions and correctness across multiple scenarios (defaults, min-latency, cloud-recommended) and to confirm rejection of invalid values. It requires root and network namespaces so may not be suitable for all CI environments. It can be removed if it doesn't have long-term value.

Example test output:

$ sudo ./tests/backoff/test_backoff -b ./src/dhcpcd -n 128
dhcpcd DHCPDISCOVER backoff integration test
=============================================
Binary: /home/cpatterson/git/dhcpcd/src/dhcpcd
Runs:   128 per test

--- defaults (N=128) ---
  dhcpcd.conf: timeout=75
  PASS: 128/128 runs produced data

  Retry     Expected    Min      Avg      Max      N     Result
  ------------------------------------------------------
  Init      1±1.0s      0.0s     0.9s     2.0s     128   PASS
  1         4±1.0s      3.0s     4.0s     5.0s     128   PASS
  2         8±1.0s      7.0s     8.0s     9.0s     128   PASS
  3         16±1.0s     15.0s    16.1s    17.0s    128   PASS
  4         32±1.0s     31.0s    32.0s    33.0s    128   PASS
  5         64±1.0s     63.0s    64.0s    65.0s    128   PASS
  Elapsed: 75.9s

--- min-latency (N=128) ---
  dhcpcd.conf: timeout=12, nodelay, initial_interval=1, backoff_cutoff=1, backoff_jitter=0
  PASS: 128/128 runs produced data

  Retry     Expected    Min      Avg      Max      N     Result
  ------------------------------------------------------
  Init      0           -        -        -        128   PASS
  1         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  2         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  3         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  4         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  5         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  6         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  7         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  8         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  9         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  10        1±0.0s      1.0s     1.0s     1.0s     128   PASS
  Elapsed: 13.0s

--- cloud (N=128) ---
  dhcpcd.conf: timeout=12, nodelay, initial_interval=1, backoff_cutoff=1, backoff_jitter=100
  PASS: 128/128 runs produced data

  Retry     Expected    Min      Avg      Max      N     Result
  ------------------------------------------------------
  Init      0           -        -        -        128   PASS
  1         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  2         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  3         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  4         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  5         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  6         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  7         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  8         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  9         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  10        1±0.1s      0.9s     1.0s     1.1s     128   PASS
  Elapsed: 13.0s

--- reject initial_interval=0 ---
  dhcpcd.conf: initial_interval 0 (expect rejection)
  PASS: dhcpcd rejected initial_interval 0 (exit=124)
    output: invalid initial interval: 0

--- reject backoff_cutoff=0 ---
  dhcpcd.conf: backoff_cutoff 0 (expect rejection)
  PASS: dhcpcd rejected backoff_cutoff 0 (exit=124)
    output: invalid backoff cutoff: 0

--- reject initial_interval above max ---
  dhcpcd.conf: initial_interval 5 (expect rejection)
  PASS: dhcpcd rejected initial_interval 5 (exit=124)
    output: invalid initial interval: 5

--- reject backoff_cutoff above max ---
  dhcpcd.conf: backoff_cutoff 65 (expect rejection)
  PASS: dhcpcd rejected backoff_cutoff 65 (exit=124)
    output: invalid backoff cutoff: 65

--- reject backoff_jitter above max ---
  dhcpcd.conf: backoff_jitter 1001 (expect rejection)
  PASS: dhcpcd rejected backoff_jitter 1001 (exit=124)
    output: invalid backoff jitter: 1001

=============================================
All tests passed.

Closes #406

@cjp256 cjp256 force-pushed the backoff branch 2 times, most recently from de88396 to d5f27da Compare March 27, 2026 20:44
@coderabbitai

coderabbitai Bot commented Mar 27, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f2ee50f0-7f7d-45d3-8a78-99d11472ccb7

📥 Commits

Reviewing files that changed from the base of the PR and between d194732 and 902dec7.

📒 Files selected for processing (4)
  • src/dhcp.c
  • src/dhcpcd.conf.5.in
  • src/if-options.c
  • src/if-options.h
✅ Files skipped from review due to trivial changes (1)
  • src/dhcpcd.conf.5.in
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/if-options.h
  • src/if-options.c

Walkthrough

Three new DHCPv4-only retransmission timing directives (initial_interval, backoff_cutoff, backoff_jitter) are added. The struct if_options is extended with matching uint32_t fields and defaults; parse_option() validates and stores them; finish_config() enforces backoff_cutoff >= initial_interval; send_message() uses these values for exponential backoff and jitter; the manpage documents all three.

Changes

Configurable DHCP Backoff Timing

Layer / File(s) Summary
Configuration contract and defaults
src/if-options.h
Adds DEFAULT_INITIAL_INTERVAL, DEFAULT_BACKOFF_CUTOFF, DEFAULT_BACKOFF_JITTER macros; three O_BASE-derived option ID constants; and three uint32_t fields (initial_interval, backoff_cutoff, backoff_jitter) in struct if_options.
Configuration parsing and validation
src/if-options.c
Registers the three new directives in cf_options. parse_option() validates each with strtou() and bounds checks. finish_config() clamps backoff_cutoff up to initial_interval with a warning. default_config() seeds all three from DEFAULT_* constants.
DHCP retransmit scheduler
src/dhcp.c
Replaces hardcoded constants in send_message() with ifo->initial_interval, ifo->backoff_cutoff, and ifo->backoff_jitter. Interval initializes from initial_interval, doubles each retry, is capped by backoff_cutoff, and the timeout RT adds a zero-centered jitter via arc4random_uniform(jitter * 2) - jitter.
Manpage documentation
src/dhcpcd.conf.5.in
Documents all three DHCPv4-only directives with allowed ranges, defaults, the exponential backoff cap interaction (including the 1/1 edge case), jitter behavior (0 disables), DHCPv6 scope exclusion (RFC 8415), and mutual See Also cross-references.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding configurable backoff parameters for DHCPv4 retransmission.
Description check ✅ Passed The description comprehensively explains the rationale, features, and validation of the three new DHCPv4 configuration options.
Linked Issues check ✅ Passed The PR fully addresses issue #406 by implementing configurable backoff-cutoff time and related parameters that were requested.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the three new DHCPv4 backoff configuration options as required by the objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/dhcp.c`:
- Around line 1867-1880: The jitter subtraction currently happens in unsigned
space causing wrap; change the jitter computation to use a signed/wider integer:
compute a signed jitter_offset =
(int64_t)arc4random_uniform((uint32_t)ifo->backoff_jitter * 2) -
(int64_t)ifo->backoff_jitter, clamp jitter_offset to a reasonable range if
needed, then compute RT using signed/wider arithmetic as RT =
(int64_t)state->interval * MSEC_PER_SEC + jitter_offset and assign back ensuring
types match (use explicit casts) to avoid unsigned wrap; update the code around
variables jitter, state->interval, RT and the arc4random_uniform call.

In `@src/if-options.c`:
- Around line 2586-2603: The new options backoff_cutoff and initial_interval
must be validated together in finish_config(): after parsing, check if
ifo->backoff_cutoff is less than ifo->initial_interval and either clamp
backoff_cutoff to initial_interval or return an error; update finish_config() to
perform this comparison and adjust or reject the configuration (modify the
function that finalizes options, e.g., finish_config()) and provide a clear
logerrx or warning message indicating the clamp or failure including both
values.

In `@tests/backoff/test_backoff.c`:
- Around line 847-859: The test currently tears down host dhcpcd state by
calling run_cmd("pkill -9 dhcpcd ...") and manipulating /var/run/dhcpcd and
/var/db/dhcpcd; change this to operate only inside the per-test temporary
directory created via tmpdir/mkdtemp: remove the pkill and any run_cmd
invocations that create/delete /var/run/dhcpcd or /var/db/dhcpcd, and instead
create and use equivalent per-test directories under tmpdir (e.g., snprintf
paths under tmpdir and call run_cmd or mkdir -p on those) so cleanup is limited
to tmpdir and the host daemon is not affected; update any code that expects
global paths to point to the tmpdir equivalents so the timing/reject case stays
isolated.
- Around line 730-742: Help text for the -n option is incorrect: update the
fprintf format string in tests/backoff/test_backoff.c (the multi-line usage
string passed to fprintf) so the "-n N" line shows the actual default of
num_runs (128) instead of 1 (e.g., change "(default: 1, max: %d)" to "(default:
128, max: %d)"). Ensure the format still uses MAX_RUNS for the max placeholder
and that the rest of the usage string remains unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1a842ef5-281a-42bd-a4e0-68df4153f8f5

📥 Commits

Reviewing files that changed from the base of the PR and between 0edb765 and d5f27da.

📒 Files selected for processing (7)
  • src/dhcp.c
  • src/dhcpcd.conf.5.in
  • src/if-options.c
  • src/if-options.h
  • tests/Makefile
  • tests/backoff/Makefile
  • tests/backoff/test_backoff.c

Comment thread src/dhcp.c Outdated
Comment thread src/if-options.c
Comment thread tests/backoff/test_backoff.c Outdated
Comment thread tests/backoff/test_backoff.c Outdated

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/backoff/test_backoff.c`:
- Around line 685-696: The snprintf command in the test initialization does not
establish private mount propagation within the new namespace created by unshare,
which can allow bind mounts to leak back to the host. After the `unshare --mount
--net --uts --ipc --pid --fork sh -c '` portion enters the namespace, add a
`mount --make-private /var` command before the `mkdir -p /var/run/dhcpcd
/var/db/dhcpcd` operation to ensure mount propagation is explicitly set to
private, preventing host pollution and achieving proper namespace isolation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8ae92c47-55d3-4256-9ef3-7ac93eed899f

📥 Commits

Reviewing files that changed from the base of the PR and between d5f27da and 972523b.

📒 Files selected for processing (4)
  • src/dhcp.c
  • src/dhcpcd.conf.5.in
  • src/if-options.c
  • tests/backoff/test_backoff.c
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/dhcpcd.conf.5.in
  • src/if-options.c
  • src/dhcp.c

Comment thread tests/backoff/test_backoff.c Outdated

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/dhcp.c`:
- Around line 1826-1841: The retransmit timeout calculation in the RT assignment
performs potentially unsafe multiplications that can overflow before being cast
to signed integers. Specifically, state->interval * MSEC_PER_SEC and jitter * 2
can overflow when calculated with unsigned arithmetic. Refactor the calculation
to use overflow-safe arithmetic by either checking for potential overflow before
performing the multiplications, using intermediate variables with appropriate
type conversions to prevent overflow, or leveraging a safe multiplication
utility function that validates the operands before multiplying. Ensure that
both the state->interval scaling and the jitter doubling operations are
protected against overflow to produce valid retry delays.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2869ca84-ff93-4b44-bf3e-aeafa7d0127b

📥 Commits

Reviewing files that changed from the base of the PR and between 972523b and 18bc749.

📒 Files selected for processing (7)
  • src/dhcp.c
  • src/dhcpcd.conf.5.in
  • src/if-options.c
  • src/if-options.h
  • tests/Makefile
  • tests/backoff/Makefile
  • tests/backoff/test_backoff.c
💤 Files with no reviewable changes (3)
  • tests/backoff/Makefile
  • tests/Makefile
  • tests/backoff/test_backoff.c
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/if-options.h

Comment thread src/dhcp.c Outdated

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

♻️ Duplicate comments (1)
tests/backoff/test_backoff.c (1)

847-847: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add NULL check after strdup().

strdup() can return NULL on allocation failure. Subsequent use of dhcpcd_bin at line 854 and later would dereference NULL.

Proposed fix
 	dhcpcd_bin = strdup(resolved);
+	if (dhcpcd_bin == NULL) {
+		fprintf(stderr, "ERROR: strdup: %s\n", strerror(errno));
+		return 1;
+	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/backoff/test_backoff.c` at line 847, The strdup() call that assigns to
dhcpcd_bin can return NULL on memory allocation failure, but this return value
is not checked before the variable is subsequently used. Add a NULL check
immediately after the strdup(resolved) assignment to dhcpcd_bin, and handle the
failure case appropriately (such as by returning an error, logging, and exiting,
or freeing resources as needed before returning).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/backoff/Makefile`:
- Around line 7-18: Add a `.PHONY` declaration near the beginning of the
Makefile to declare that the targets `all`, `test`, `clean`, and `distclean` are
phony (command targets, not files). This prevents Make from treating these
targets as regular files and skipping them when files with those names exist.
The `.PHONY` declaration should list all four targets and be placed near line 7,
before the rule definitions.

---

Duplicate comments:
In `@tests/backoff/test_backoff.c`:
- Line 847: The strdup() call that assigns to dhcpcd_bin can return NULL on
memory allocation failure, but this return value is not checked before the
variable is subsequently used. Add a NULL check immediately after the
strdup(resolved) assignment to dhcpcd_bin, and handle the failure case
appropriately (such as by returning an error, logging, and exiting, or freeing
resources as needed before returning).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ad2829ad-d3c3-42e3-bf6c-d93a2594800a

📥 Commits

Reviewing files that changed from the base of the PR and between 18bc749 and e9326e3.

📒 Files selected for processing (7)
  • src/dhcp.c
  • src/dhcpcd.conf.5.in
  • src/if-options.c
  • src/if-options.h
  • tests/Makefile
  • tests/backoff/Makefile
  • tests/backoff/test_backoff.c
✅ Files skipped from review due to trivial changes (2)
  • src/dhcpcd.conf.5.in
  • tests/Makefile
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/dhcp.c
  • src/if-options.h
  • src/if-options.c

Comment thread tests/backoff/Makefile Outdated
@cjp256

cjp256 commented Jun 15, 2026

Copy link
Copy Markdown
Author

@rsmarples is this something you'll consider?

Comment thread src/if-options.c Outdated
case O_BACKOFF_JITTER:
ARG_REQUIRED;
ifo->backoff_jitter =
(uint32_t)strtou(arg, NULL, 0, 0, MAX_BACKOFF_JITTER, &e);

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.

Jitter must be a positive value, otherwise a value of zero would be no delay at all which would be bad.

@cjp256 cjp256 Jun 16, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

If jitter=0, the delay would be the interval, which is minimum of 1s. I have tests for jitter = 0, 100, and default (1000).

--- defaults (N=128) ---
  dhcpcd.conf: timeout=75
  PASS: 128/128 runs produced data

  Retry     Expected    Min      Avg      Max      N     Result
  ------------------------------------------------------
  Init      1±1.0s      0.0s     0.9s     2.0s     128   PASS
  1         4±1.0s      3.0s     4.0s     5.0s     128   PASS
  2         8±1.0s      7.0s     8.0s     9.0s     128   PASS
  3         16±1.0s     15.0s    16.1s    17.0s    128   PASS
  4         32±1.0s     31.0s    32.0s    33.0s    128   PASS
  5         64±1.0s     63.0s    64.0s    65.0s    128   PASS
  Elapsed: 75.9s

--- min-latency (N=128) ---
  dhcpcd.conf: timeout=12, nodelay, initial_interval=1, backoff_cutoff=1, backoff_jitter=0
  PASS: 128/128 runs produced data

  Retry     Expected    Min      Avg      Max      N     Result
  ------------------------------------------------------
  Init      0           -        -        -        128   PASS
  1         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  2         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  3         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  4         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  5         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  6         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  7         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  8         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  9         1±0.0s      1.0s     1.0s     1.0s     128   PASS
  10        1±0.0s      1.0s     1.0s     1.0s     128   PASS
  Elapsed: 13.0s

--- cloud (N=128) ---
  dhcpcd.conf: timeout=12, nodelay, initial_interval=1, backoff_cutoff=1, backoff_jitter=100
  PASS: 128/128 runs produced data

  Retry     Expected    Min      Avg      Max      N     Result
  ------------------------------------------------------
  Init      0           -        -        -        128   PASS
  1         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  2         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  3         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  4         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  5         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  6         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  7         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  8         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  9         1±0.1s      0.9s     1.0s     1.1s     128   PASS
  10        1±0.1s      0.9s     1.0s     1.1s     128   PASS
  Elapsed: 13.0s

I'll update the strtou calls with range checks.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Or do you mean for the initial attempt? Is no delay really bad in that case?

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.

With a jitter of zero there is no randomisation and no backoff. Whilst I can entertain adjusting RFC values I would like to keep the spirit of why a backoff is needed. ie, if there is no DHCP response, don't constantly hammer the network.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

With a jitter of zero there is no randomisation and no backoff.

There's definitely a back off, jitter is just some (relatively) minor variance.

The initial_interval (initial retransmission interval, default 4s, max 4s) controls the initial and subsequent retries.

The backoff_cutoff (exponential backoff cap, default 64s, max 64s) controls the upper bound of retries.

The backoff_jitter (random jitter per retry, default ±1000ms, max 1000ms) is just a randomized delay on top of interval>>cutoff base.

The backoff is still exponential starting with initial interval. The defaults maintain current behavior today.

With initial_interval=1, backoff_cutoff=64, backoff_jitter=0, we can see the back-off working clearly:

Retry Expected Min Avg Max N Result
Init 0 (nodelay) 64 PASS
1 1±0.0s 1.0s 1.0s 1.0s 64 PASS
2 2±0.0s 2.0s 2.0s 2.0s 64 PASS
3 4±0.0s 4.0s 4.0s 4.0s 64 PASS
4 8±0.0s 8.0s 8.0s 8.0s 64 PASS
5 16±0.0s 16.0s 16.0s 16.0s 64 PASS
6 32±0.0s 32.0s 32.0s 32.0s 64 PASS
7 64±0.0s 64.0s 64.0s 64.0s 64 PASS
8 64±0.0s 64.0s 64.0s 64.0s 64 PASS

All tests passed — elapsed 130.7s. The sequence doubles (1→2→4→8→16→32→64) and caps at backoff_cutoff=64, with zero variance from backoff_jitter=0.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

(and the defaults remain to match current behavior)

@rsmarples

Copy link
Copy Markdown
Member

@rsmarples is this something you'll consider?

Yes I'm happy to consider this.
But please supply some minimum values as well as maximum values - you can use them in the strtou calls as they have range checks there.

In cloud and virtual environments the DHCP service is typically
ready within hundreds of milliseconds of the interface coming up,
and once ready, responds within single-digit milliseconds.  The
RFC 2131 defaults (4s initial interval, 64s backoff cap) are
designed for congested broadcast networks and are unnecessarily
conservative in this context.

Add three new configuration options to tune DHCPv4 retransmission:

  initial_interval  - initial retransmission interval (default 4s)
  backoff_cutoff    - exponential backoff cap (default 64s)
  backoff_jitter    - random jitter per retry (default ±1000ms)

Defaults match RFC 2131 so existing behaviour is unchanged.
Option naming aligns with dhclient (initial-interval, backoff-cutoff).
Minimum of 1 is enforced at parse time for interval and cutoff;
invalid values are logged and the default is used.

These options are DHCPv4-only; DHCPv6 retransmission follows
RFC 8415 constants and is not user-configurable.

Closes NetworkConfiguration#406

Signed-off-by: Chris Patterson <cpatterson@microsoft.com>

@ColinMcInnes ColinMcInnes 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.

Looks good to me.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

backoff-cutoff time; equivalant in dhcpcd.conf

3 participants