about summary refs log tree commit diff
path: root/src/core/dhcp/README.next.md
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2024-05-05 00:07:30 +0200
committerMichael Biebl <biebl@debian.org>2024-05-05 00:07:30 +0200
commit34bb501be08aa2b313d88e67d6e0a7e0a3f9cfa6 (patch)
tree4e6220877828be4c6f261de09ec0cb2d80e32389 /src/core/dhcp/README.next.md
parentbba2e4b4de668db525cbfdfc35292e5a0b51671a (diff)
New upstream version 1.47.90 upstream/1.47.90
Diffstat (limited to 'src/core/dhcp/README.next.md')
-rw-r--r--src/core/dhcp/README.next.md103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/core/dhcp/README.next.md b/src/core/dhcp/README.next.md
new file mode 100644
index 00000000..88fa6683
--- /dev/null
+++ b/src/core/dhcp/README.next.md
@@ -0,0 +1,103 @@
+`NMDhcpClient`
+==============
+
+Using `NMDhcpClient` still requires a lot of logic in `NMDevice`. The main goal
+is to simplify `NMDevice`, so `NMDhcpClient` must become more complicated to
+provide a simpler (but robust) API.
+
+NMDevice has basically two timeouts (talking about IPv4, but it applies
+similarly to IPv6): `ipv4.dhcp-timeout` and `ipv4.required-timeout`. They
+control how long NMDevice is willing to try, before failing the activation
+altogether. Note that with `ipv4.may-fail=yes`, we may very well never want to
+fail the activation entirely, regardless how DHCP is doing. In that case we
+want to stay up, but also constantly retrying whether we cannot get a lease and
+recover.
+
+Currently, if `NMDhcpClient` signals a failure, then it's basically up to
+`NMDevice` to schedule and retry. That is complicated, and we should move the
+complexity out of `NMDevice`.
+
+`NMDhcpClient` should have a simpler API:
+
+- `nm_dhcp_manager_start_ip[46]()`: creates (and starts) a `NMDhcpClient`
+  instance. The difference is, this function tries really hard not to fail
+  to create an `NMDhcpClient`. There is no explicit `start()`, but note that the
+  instance must not emit any signals before the next maincontext iteration. That is,
+  it only will call back the user after a timeout/idle or some other IO event, which
+  happens during a future iteration of the maincontext.
+
+- `nm_dhcp_client_stop()`: when `NMDevice` is done with the `NMDhcpClient`
+  instance, it will stop it and throw it away. This method exists because
+  `NMDhcpClient` is a `GObject` and ref-counted. Thus, we don't want to rely on
+  the last unref to stop the instance, but have an explicit stop. After stop, the
+  instance is defunct and won't emit any signals anymore. The class does not need
+  to support restarting a stopped instance. If `NMDevice` wants to restart DHCP, it
+  should create a new one. `NMDevice` would only want to do that, if the parameters
+  change, hence a new instance is in order (and no need for the complexity of
+  restart in `NMDhcpClient`).
+
+- as already now, `NMDhcpClient` is not very configurable. You provide most
+  (all) parameters during `nm_dhcp_manager_start_ip[46]()`, and then it keeps
+  running until stop.
+
+- `NMDhcpClient` exposes a simple state to the user:
+
+   1. "no lease, but good". When starting, there is no lease, but we are
+      optimistic to get one. This is the inital state, but we can also get back to
+      this state after we had a lease (which might expire).
+
+   1. "has a lease". Here there is no need to distinguish whether the current
+      lease was the first we received, or whether this was an update. In this state,
+      the instance has a lease and we are good.
+
+   1. "no lease, but bad". `NMDhcpClient` tries really hard, and "bad" does not
+      mean that it gave up. It will keep retrying, it's just that there is little
+      hope of getting a new lease. This happens, when you try to run DHCP on a Layer3
+      link (WireGuard). There is little hope to succeed, but `NMDhcpClient`
+      (theoretically) will retry and may recover from this. Another example is when
+      we fail to start dhclient because it's not installed. In that case, we are not
+      optimistic to recover, however `NMDhcpDhclient` will retry (with backoff
+      timeout) and might still recover from this. For most cases, `NMDevice` will
+      treat the no-lease cases the same, but in case of "bad" it might give up
+      earlier.
+
+When a lease expires, that does not necessarily mean that we are now in a bad
+state. It might mean that the DHCP server is temporarily down, but we might
+recover from that easily. "bad" really means, something is wrong on our side
+which prevents us from getting a lease. Also, imagine `dhclient` dies (we would
+try to restart, but assume that fails too), but we still have a valid lease,
+then possibly `NMDhcpClient` should still pretend all is good and we still have
+a lease until it expires. It may be we can recover before that happens. The
+point of all of this, is to hide errors as much as possibly and automatically
+recover. `NMDevice` will decide to tear down, if we didn't get a lease after
+`ipv4.dhcp-timeout`. That's the main criteria, and it might not even
+distinguish between "no lease, but good" and "no lease, but bad".
+
+- `NMDhcpClient` will also take care of the `ipv4.dhcp-timeout` grace period.
+  That timeout is provided during start, and starts ticking whenever there is
+  no lease. When it expires, a timeout signal gets emitted. That's it. This is
+  independent from the 3 states above, and only saves `NMDevice` from scheduling
+  this timer themselves.
+  This is NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT notification.
+
+- for nettools, `nm_dhcp_client_can_accept()` indicates that when we receive a
+  lease, we need to accept/decline it first. In that case, `NMDevice`
+optionally does ACD first, then configures the IP address first and calls
+`nm_dhcp_client_accept()`. In case of ACD conflict, it will call
+`nm_dhcp_client_decline()` (which optimally causes `NMDhcpClient` to get a
+different lease). With this, the above state "has a lease" has actually three
+flavors: "has a lease but not yet ACD probed" and "has a lease but
+accepted/declined" (but `NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED` gets only emitted
+when we get the lease, not when we accept/decline it). With `dhclient`, when we
+receive a lease, it means  "has a lease but accepted" right away.
+
+- for IPv6 prefix delegation, there is also `needed_prefixes` and
+  `NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED`. Currently `needed_prefixes` needs
+  to be specified during start (which simplifies things). Maybe `needed_prefixes`
+  should be changable at runtime. Otherwise, whether we have prefixes is similar
+  to whether we have a lease, and the simple 3 states apply.
+
+When NetworkManager quits, it may want to leave the interface up. In that case,
+we still always want to stop the DHCP client, but possibly not deconfiguring
+the interface. I don't think that this concerns `NMDhcpClient`, because `NMDhcpClient`
+only provides the lease information and `NMDevice` is responsible to configure it.