Skip to content

Conversation

@cathay4t
Copy link

@cathay4t cathay4t commented Oct 15, 2025

Highlights for mozim 0.3:

  • Full tokio based rewrite which does not require standalone thread for
    Future wakeup.
  • Removed nispor as dependency.

Summary by Sourcery

Upgrade the DHCP proxy to use mozim v0.3.0 with its async client API, switch to a full Tokio-based runtime for timeouts and signal handling, remove nispor, and update build features accordingly.

Enhancements:

  • Upgrade mozim dependency to v0.3.0 and adapt to its new async API and lease field names
  • Migrate DHCP proxy service and client to a full Tokio-based implementation using async timeouts and signal handling
  • Refactor dhcp_proxy module imports, code layout, and async release_lease teardown logic

Build:

  • Add Tokio "time" feature and bump mozim version in Cargo.toml

Chores:

  • Remove nispor dependency

@sourcery-ai
Copy link

sourcery-ai bot commented Oct 15, 2025

Reviewer's Guide

This PR upgrades the DHCP proxy implementation to mozim 0.3.0 by adopting its new Tokio-based async API and state machine (replacing DhcpV4ClientAsync with DhcpV4Client and moving to an async run() loop), renames lease fields to match the new mozim types, reorganizes imports and formatting for consistency, and updates runtime features and dependencies to enable the new time-based APIs.

Sequence diagram for DHCP lease acquisition with new mozim async API

sequenceDiagram
    participant Client
    participant NetavarkProxyService
    participant DhcpV4Service
    participant DhcpV4Client
    Client->>NetavarkProxyService: setup(NetworkConfig)
    NetavarkProxyService->>DhcpV4Service: new(NetworkConfig, timeout)
    DhcpV4Service->>DhcpV4Client: init(config)
    NetavarkProxyService->>DhcpV4Service: get_lease()
    loop until lease acquired or error
        DhcpV4Service->>DhcpV4Client: run()
        DhcpV4Client-->>DhcpV4Service: DhcpV4State (Done(lease) or other)
    end
    DhcpV4Service-->>NetavarkProxyService: NetavarkLease
    NetavarkProxyService-->>Client: Lease response
Loading

Sequence diagram for releasing DHCP lease with async release

sequenceDiagram
    participant Client
    participant NetavarkProxyService
    participant DhcpV4Service
    participant DhcpV4Client
    Client->>NetavarkProxyService: teardown(NetworkConfig)
    NetavarkProxyService->>DhcpV4Service: release_lease()
    DhcpV4Service->>DhcpV4Client: release(lease)
    DhcpV4Client-->>DhcpV4Service: (async result)
    DhcpV4Service-->>NetavarkProxyService: Result
    NetavarkProxyService-->>Client: OperationResponse
Loading

ER diagram for updated Lease and DhcpV4Lease fields

erDiagram
    NetavarkLease {
        t1 u32
        t2 u32
        lease_time u32
        mtu u32
        domain_name string
        mac_address string
    }
    MozimV4Lease {
        t1_sec u32
        t2_sec u32
        lease_time_sec u32
        siaddr string
        yiaddr string
        srv_id string
        subnet_mask string
        broadcast_addr string
    }
    NetavarkLease ||--o{ MozimV4Lease : "from() conversion"
    MozimV4Lease {
        t1_sec u32
        t2_sec u32
        lease_time_sec u32
    }
    NetavarkLease {
        t1 u32
        t2 u32
        lease_time u32
    }
Loading

Class diagram for updated DhcpV4Service and related types

classDiagram
    class DhcpV4Service {
        +DhcpV4Client client
        +NetworkConfig network_config
        +Option<MozimV4Lease> previous_lease
        +async new(nc: NetworkConfig, timeout: u32) Result<Self, DhcpServiceError>
        +async get_lease() Result<NetavarkLease, DhcpServiceError>
        +async release_lease() Result<(), DhcpServiceError>
    }
    class DhcpV4Client {
        +async run() Result<DhcpV4State, mozim::Error>
        +async release(lease: MozimV4Lease)
    }
    class MozimV4Lease {
        +t1_sec: u32
        +t2_sec: u32
        +lease_time_sec: u32
        +siaddr: Ipv4Addr
        +yiaddr: Ipv4Addr
        +srv_id: Ipv4Addr
        +subnet_mask: Ipv4Addr
        +broadcast_addr: Ipv4Addr
    }
    class NetavarkLease {
        +t1: u32
        +t2: u32
        +lease_time: u32
        +mtu: u32
        +domain_name: String
        +mac_address: String
        +add_domain_name(domain: &str)
        +add_mac_address(mac: &str)
    }
    DhcpV4Service --> DhcpV4Client
    DhcpV4Service --> NetworkConfig
    DhcpV4Service --> MozimV4Lease
    NetavarkLease <.. MozimV4Lease : from()
    DhcpV4Client --> MozimV4Lease
Loading

File-Level Changes

Change Details Files
Migrate to mozim 0.3 async state machine
  • Replaced DhcpV4ClientAsync with DhcpV4Client and made initialization async
  • Replaced .next() stream iteration with client.run().await looping over DhcpV4State
  • Updated release_lease and process_client_stream to async .await calls
  • Adjusted setup/teardown to await new async methods
src/dhcp_proxy/dhcp_service.rs
src/commands/dhcp_proxy.rs
Update gRPC lease mapping to use new field names
  • Renamed lease mapping fields from t1, t2, lease_time to t1_sec, t2_sec, lease_time_sec
  • Adjusted From and to/from conversions accordingly
src/dhcp_proxy/lib.rs
Refactor imports and formatting
  • Grouped std and crate imports into coherent blocks
  • Re-wrapped long import lists and block comments for readability
  • Added trailing commas and consistent indentation across multi-line statements
src/commands/dhcp_proxy.rs
src/dhcp_proxy/dhcp_service.rs
Update dependencies and enable time feature
  • Added "time" feature to tokio in Cargo.toml and bumped mozim to 0.3.0
  • Enabled .enable_time() in Tokio runtime builder for network/dhcp.rs
  • Updated Cargo.toml features to support new timeout APIs
Cargo.toml
src/network/dhcp.rs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@cathay4t
Copy link
Author

I have habit of run rustfmt in my VIM. So sorry for the formatting changes.

I don't know how to test it, please review carefully.

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `src/dhcp_proxy/dhcp_service.rs:53-62` </location>
<code_context>
 impl DhcpV4Service {
-    pub fn new(nc: NetworkConfig, timeout: u32) -> Result<Self, DhcpServiceError> {
-        let mut config = DhcpV4Config::new_proxy(&nc.host_iface, &nc.container_mac_addr);
-        config.set_timeout(timeout);
+    pub async fn new(
+        nc: NetworkConfig,
+        timeout: u32,
+    ) -> Result<Self, DhcpServiceError> {
+        let mut config =
+            DhcpV4Config::new_proxy(&nc.host_iface, &nc.container_mac_addr)
+                .map_err(|e| {
+                    DhcpServiceError::new(InvalidArgument, e.to_string())
+                })?;
+        config.set_timeout_sec(timeout);

-        // Sending the hostname to the DHCP server is optional but it can be useful
</code_context>

<issue_to_address>
**issue (bug_risk):** set_timeout_sec replaces set_timeout; verify units and semantic equivalence.

Ensure the timeout value is correctly converted to seconds to prevent unintended changes in behavior.
</issue_to_address>

### Comment 2
<location> `src/dhcp_proxy/dhcp_service.rs:96` </location>
<code_context>
+    /// * `client`: a IPv4 mozim dhcp client. When this method is called, it
+    ///   takes ownership of client.
     ///
-    pub async fn get_lease(&mut self) -> Result<NetavarkLease, DhcpServiceError> {
-        if let Some(lease_result) = self.client.next().await {
-            match lease_result {
</code_context>

<issue_to_address>
**suggestion (bug_risk):** get_lease now loops on client.run; check for infinite loop or starvation.

Consider adding a maximum iteration count or timeout to prevent infinite loops or starvation if the DHCP server is unresponsive or returns unexpected states.

Suggested implementation:

```rust
    /// Performs a DHCP DORA on a ipv4 network configuration.
    /// # Arguments
    ///
    /// * `client`: a IPv4 mozim dhcp client. When this method is called, it
    ///   takes ownership of client.
    /// * The method will attempt to obtain a lease up to MAX_ATTEMPTS times to prevent infinite loops or starvation.
    ///
    /// returns: Result<Lease, DhcpSearchError>. Either finds a lease
    /// successfully, finds no lease, or fails
    pub async fn get_lease(
        &mut self,
    ) -> Result<NetavarkLease, DhcpServiceError> {
        const MAX_ATTEMPTS: usize = 100;
        let mut attempts = 0;
        loop {
            if attempts >= MAX_ATTEMPTS {
                return Err(DhcpServiceError::Timeout);
            }
            attempts += 1;
            let state = self.client.run().await;
            match state {
                Ok(DhcpV4State::Done(lease)) => {

```

You may need to ensure that `DhcpServiceError::Timeout` exists. If not, add a suitable variant to the `DhcpServiceError` enum, e.g.:
```rust
Timeout,
```
and implement its `Display`/`Error` traits as needed.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Member

@Luap99 Luap99 left a comment

Choose a reason for hiding this comment

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

Thanks! I was looking at this yesterday, the new API does indeed look nicer and using tokio makes a lot of sense.

You need to cargo fmt the code here, at least validate is complaining, I need to look at the integration test failure to see what is wrong with that.

client.network_config.container_mac_addr
);
}
Err(err) => {
Copy link
Member

Choose a reason for hiding this comment

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

Based on your docs

Repeat run() after error will emit the same error again until [DhcpV4Client::clean_up] been invoked.

So should the error branch do this here? Otherwise we loop on the error forever which seems pointless and could that busy spin then?

Copy link
Member

Choose a reason for hiding this comment

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

Ok that is causing the integration test failure in the "release after timeout" test as it get stucked into the error loop here and needs the cleanup, when adding it locally it passes.

FYI, for testing the dhcp parts sudo bats test-dhcp/ should work.

Copy link
Author

Choose a reason for hiding this comment

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

Changed the patch to run clean up and retry the DHCPv4 process. Is it correct?

Copy link
Author

Choose a reason for hiding this comment

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

the sudo bats test-dhcp/ passed in my VM.

@cathay4t
Copy link
Author

We don't have .rustfmt.toml file in this repo. Which rule should I use to run cargo fmt.

My preference:

max_width = 80
wrap_comments = true
reorder_imports = true
format_strings = true
group_imports = "StdExternalCrate"
imports_granularity = "Crate"
edition = "2024"

@Luap99
Copy link
Member

Luap99 commented Oct 17, 2025

We don't have .rustfmt.toml file in this repo. Which rule should I use to run cargo fmt.

My preference:

max_width = 80
wrap_comments = true
reorder_imports = true
format_strings = true
group_imports = "StdExternalCrate"
imports_granularity = "Crate"
edition = "2024"

We use whatever the defaults are without a config, we have never really cared about customizing the formatting here.
Just running cargo fmt in the repo should make it pass validate I would assume.

@cathay4t
Copy link
Author

If you don't have config, it will inherent the one in your $HOME folder.

Anyway, let me amend the patch.

@packit-as-a-service
Copy link

Ephemeral COPR build failed. @containers/packit-build please check.

5 similar comments
@packit-as-a-service
Copy link

Ephemeral COPR build failed. @containers/packit-build please check.

@packit-as-a-service
Copy link

Ephemeral COPR build failed. @containers/packit-build please check.

@packit-as-a-service
Copy link

Ephemeral COPR build failed. @containers/packit-build please check.

@packit-as-a-service
Copy link

Ephemeral COPR build failed. @containers/packit-build please check.

@packit-as-a-service
Copy link

Ephemeral COPR build failed. @containers/packit-build please check.

Highlights for mozim 0.3:
 * Full tokio based rewrite which does not require standalone thread for
   Future wakeup.
 * Removed `nispor` as dependency.

Signed-off-by: Gris Ge <[email protected]>
Copy link
Member

@Luap99 Luap99 left a comment

Choose a reason for hiding this comment

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

LGTM, thank you
@mheon @baude PTAL

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Oct 22, 2025

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: cathay4t, Luap99, sourcery-ai[bot]

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

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.

3 participants