jaypipes / ghw

Go HardWare discovery/inspection library
Apache License 2.0
1.62k stars 174 forks source link

Add NICLinkInfo to each NIC #335

Closed jak3kaj closed 1 year ago

jak3kaj commented 1 year ago

Default to parsing the output of ethtool, but fall back to reading a few parameters from the /sys/class/net// directory. Information such as interface Speed, Duplex, Link Detected, and Auto Negotiation will be available for each NIC.

The gwh.NICLinkInfo struct contains the following fields:

ffromani commented 1 year ago

@jak3kaj thanks for this PR! Helpful and appreciated I think the project should gradually reduce the dependencies to external tools. How complex/hard would be to NOT depend on ethtool at all and just read data from /sys/class/net? I think that simplifying the code path (there's preferred + fallback no more, just one flow) should bring some advantages at last.

I'll review the PR shortly.

jaypipes commented 1 year ago

Indeed, thank you for this great PR @jak3kaj! I'm halfway through a full review. Currently at Kubernetes contributor summit in Amsterdam so responses might be a bit delayed :)

ffromani commented 1 year ago

Did a quick pass. Besides the other high-level concern I already shared (it would be very nice to NOT depend on external tools in new code if we can help it), we need to check two more things:

  1. how much detail do we want to expose? This PR exposes a lot of data. Should we start leaner? I don't have a clear idea yet
  2. there COULD be some potential overlap between the new struct and the existing capabilityinfo we report. I'll doublecheck later
jak3kaj commented 1 year ago

Regarding dependence on ethtool.

I agree it would be better to not depend on an external tool. There are some minimal distros where ethtool is not installed by default, so yes, this should be avoided.

I am actually pulling out all of the useful info from the /sys/class/net filesystem, unfortunately it isn't very comprehensive.

While doing this work, I did notice that there are actually two ethtool projects that are being used. The latest one is 100% Go; which gave me the crazy idea to implement some of the ethtool functions directly in my code. Doing a little more research I found someone may have done this already, since there is a go ethtool library. So this is a possibilty. I can't commit to refactoring this patch to use a native Go implementation of ethtool at the moment, but I agree it is a better way to do this.

jak3kaj commented 1 year ago

OK, I've had a little time to digest this and I think I would prefer the following:

  1. For the following things, make them NICCapability objects:
  • AutoNegotiation (string value of auto-negotiation)
  • PauseFrameUse (string value of pause-frame-use)

So, in other words, instead of having individual fields called AutoNegotiation, SupportedPauseFrameUse and SupportsAutoNegotiation you would append a NICCapability struct to the NIC.Capabilities collection that represents that particular feature's enablement and supportability.

Sure, Makes sense to me too.

  1. Put the following fields directly on the NIC struct:
  • Speed
  • Duplex
  • SupportedLinkModes
  • SupportedPorts
  • SupportedFECModes
  • AdvertisedLinkModes
  • AdvertisedFECModes

Cool, I like these fields being easier to access.

I'd like to see LinkDetected (bool) here as well.

  1. Put these new fields directly on the NIC struct:
  • SupportedWakeOnModes ([]string)
  • AdvertisedWakeOnModes ([]string)

WakeOn is not a boolean, it's a string containing the supported wake on modes... and so best to have this in a separate []string field.

Both of those fields are string types, so I'll convert them to []string so its more obvious that each letter represents a different feature.

  1. For now, ignore all the other fields that you have in your NICLinkInfo struct. I'd be happy to discuss those other fields in a future PR. I'd also be happy to see totally separate PRs for 1) , 2) and 3) above :)

So we will ignore Port, PHYAD, Transceiver, MDIX, LinkDetected, and NETIFMsgLevel.

Most of those give inconsistent/useless output and/or have been obsolete for 20 years; but the LinkDetected field is consistent and seems useful to me.

Happy to discuss this further!

Best, -jay

Thanks Jay. I appreciate your feedback. I'll make these changes and submit 3 PRs for 1), 2) and 3). Let me know what you think about LinkDetected.

Jacob

jaypipes commented 1 year ago

OK, I've had a little time to digest this and I think I would prefer the following:

  1. For the following things, make them NICCapability objects:
  • AutoNegotiation (string value of auto-negotiation)
  • PauseFrameUse (string value of pause-frame-use)

So, in other words, instead of having individual fields called AutoNegotiation, SupportedPauseFrameUse and SupportsAutoNegotiation you would append a NICCapability struct to the NIC.Capabilities collection that represents that particular feature's enablement and supportability.

Sure, Makes sense to me too.

  1. Put the following fields directly on the NIC struct:
  • Speed
  • Duplex
  • SupportedLinkModes
  • SupportedPorts
  • SupportedFECModes
  • AdvertisedLinkModes
  • AdvertisedFECModes

Cool, I like these fields being easier to access.

I'd like to see LinkDetected (bool) here as well.

  1. Put these new fields directly on the NIC struct:
  • SupportedWakeOnModes ([]string)
  • AdvertisedWakeOnModes ([]string)

WakeOn is not a boolean, it's a string containing the supported wake on modes... and so best to have this in a separate []string field.

Both of those fields are string types, so I'll convert them to []string so its more obvious that each letter represents a different feature.

:+1: Alternately, you could create long-form string constants instead of the single-letter strings. Up to you! :)

  1. For now, ignore all the other fields that you have in your NICLinkInfo struct. I'd be happy to discuss those other fields in a future PR. I'd also be happy to see totally separate PRs for 1) , 2) and 3) above :)

So we will ignore Port, PHYAD, Transceiver, MDIX, LinkDetected, and NETIFMsgLevel.

Most of those give inconsistent/useless output and/or have been obsolete for 20 years; but the LinkDetected field is consistent and seems useful to me.

For this particular PR, let's leave LinkDetected out. I'd like to do that one in a followup PR after discussing a little further.

My primary concern with LinkDetected is that it is a field that mutates often (think of a WLAN-connected interface for a laptop that is moving in between tech conference hallways; this is top-of-mind since I'm currently at kubeconEU ;) ). ghw has traditionally been for discovery of resource quantities and capabilities that don't change often and that don't represent a point-in-time amount like amount of memory currently in use, etc.

That said, I'd like to hear from @ffromani to see what his take on this is. Adding support for LinkDetected would bring ghw into more use cases such as network monitoring tools that will periodically poll for device status information. This would be expanding ghw's traditional scope but I'm OK doing that if we'd like to.

jak3kaj commented 1 year ago

Closing out in favor of rebased code in #338 and #342