Skip to content

Add support for get_link_state #32

Open
laundrei wants to merge 3 commits intorust-netlink:mainfrom
laundrei:get_link_state
Open

Add support for get_link_state #32
laundrei wants to merge 3 commits intorust-netlink:mainfrom
laundrei:get_link_state

Conversation

@laundrei
Copy link
Contributor

followed the example of the other get commands and the documentation here

https://docs.kernel.org/networking/ethtool-netlink.html#linkstate-get

tested with cargo run --example dump_link_state

@gemini-code-assist
Copy link

Summary of Changes

Hello @laundrei, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the ethtool crate by integrating functionality to retrieve network interface link state. It establishes the necessary infrastructure, including new modules, data types, and request mechanisms, to interact with the kernel's ethtool-netlink interface for link state queries. The changes align with existing patterns within the crate for other ethtool commands, providing a consistent API for developers. A practical example is also provided to showcase the usage of this new capability.

Highlights

  • New Feature: Link State Retrieval: Added comprehensive support for querying network interface link state information using the ethtool-netlink protocol.
  • New Data Structures and Request Handlers: Introduced EthtoolLinkStateAttr for representing link state attributes, EthtoolLinkStateGetRequest for building and executing link state queries, and EthtoolLinkStateHandle to manage these operations.
  • Example Implementation: Included a new example (dump_link_state.rs) to demonstrate how to fetch and display link state details for a specified network interface.
Changelog
  • examples/dump_link_state.rs
    • Added a new example to demonstrate fetching and printing network interface link state.
  • src/handle.rs
    • Imported the new EthtoolLinkStateHandle.
    • Exposed a link_state() method on EthtoolHandle to access link state operations.
  • src/lib.rs
    • Declared the new link_state module.
    • Re-exported public types related to link state for external use.
  • src/link_state/attr.rs
    • Defined the EthtoolLinkStateAttr enum to represent various link state attributes.
    • Implemented parsing logic for EthtoolLinkStateAttr from Netlink Attribute buffers.
  • src/link_state/get.rs
    • Implemented EthtoolLinkStateGetRequest to construct and execute requests for retrieving link state information.
  • src/link_state/handle.rs
    • Created EthtoolLinkStateHandle to manage link state requests.
    • Provided a get method within EthtoolLinkStateHandle to initiate link state queries.
  • src/link_state/mod.rs
    • Organized the link_state module by declaring its sub-modules (attr, get, handle).
    • Re-exported necessary types from its sub-modules.
  • src/message.rs
    • Integrated the new link_state module's parsing functions.
    • Added ETHTOOL_MSG_LINKSTATE_GET and ETHTOOL_MSG_LINKSTATE_GET_REPLY constants.
    • Added LinkStateGet and LinkStateGetReply variants to EthtoolCmd.
    • Defined EthtoolAttr::LinkState variant.
    • Implemented new_link_state_get method for creating link state request messages.
    • Added parsing logic for link state reply messages.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request adds support for get_link_state, following the existing patterns in the crate. A new link_state module is introduced, along with an example to demonstrate its usage. The changes are well-structured. I've identified a few areas for improvement related to code clarity, efficiency, and robustness, and have provided suggestions to address them.

Comment on lines +53 to +59
fn emit_value(&self, buffer: &mut [u8]) {
match self {
Self::Header(ref nlas) => nlas.as_slice().emit(buffer),
Self::Other(ref attr) => attr.emit(buffer),
_ => todo!("Does not support changing link state"),
}
}

Choose a reason for hiding this comment

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

medium

Using todo! here will cause a panic if any code attempts to serialize EthtoolLinkStateAttr variants other than Header or Other. While this is not the case for get_link_state, it could be an unexpected trap for future developers using this crate, especially if set functionality is added. It would be better to use unimplemented! which is more idiomatic for this situation. This makes the intent clearer that this path is not yet supported for emission.

Suggested change
fn emit_value(&self, buffer: &mut [u8]) {
match self {
Self::Header(ref nlas) => nlas.as_slice().emit(buffer),
Self::Other(ref attr) => attr.emit(buffer),
_ => todo!("Does not support changing link state"),
}
}
fn emit_value(&self, buffer: &mut [u8]) {
match self {
Self::Header(ref nlas) => nlas.as_slice().emit(buffer),
Self::Other(ref attr) => attr.emit(buffer),
_ => unimplemented!("Does not support changing link state"),
}
}

Comment on lines +118 to +125
for nla in NlasIterator::new(buffer) {
let error_msg = format!(
"Failed to parse ethtool link state message attribute {nla:?}"
);
let nla = &nla.context(error_msg.clone())?;
let parsed = EthtoolLinkStateAttr::parse(nla).context(error_msg)?;
nlas.push(EthtoolAttr::LinkState(parsed));
}

Choose a reason for hiding this comment

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

medium

The current implementation for parsing NLAs is a bit inefficient and the error message can be confusing:

  • It calls format! and clone() on each iteration, which is not performant.
  • The nla variable in format! is a Result, so the error message will contain Ok(...) which is not ideal.

A cleaner and more performant approach would be to handle the Result from the iterator first, and then parse the NlaBuffer. This avoids unnecessary allocations and provides clearer error messages.

    for nla in NlasIterator::new(buffer) {
        let nla = nla.context("Failed to parse link state NLA header")?;
        let parsed = EthtoolLinkStateAttr::parse(&nla)
            .context(format!("Failed to parse link state NLA: {nla:?}"))?;
        nlas.push(EthtoolAttr::LinkState(parsed));
    }

src/message.rs Outdated
Comment on lines +365 to +376
let nlas = match iface_name {
Some(s) => {
vec![EthtoolAttr::LinkState(EthtoolLinkStateAttr::Header(
vec![EthtoolHeader::DevName(s.to_string())],
))]
}
None => {
vec![EthtoolAttr::LinkState(EthtoolLinkStateAttr::Header(
vec![],
))]
}
};

Choose a reason for hiding this comment

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

medium

The match statement contains duplicated code. This can be simplified to be more concise and easier to maintain by handling the Option more idiomatically.

        let nlas = vec![EthtoolAttr::LinkState(EthtoolLinkStateAttr::Header(
            iface_name
                .map(|s| vec![EthtoolHeader::DevName(s.to_string())])
                .unwrap_or_default(),
        ))];

…L_FLAG_STATS to get additional stats from LINKSTATE_GET
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.

1 participant