Skip to content

Commit

Permalink
Add Speed, Duplex, SupportedLinkModes, SupportedPorts,
Browse files Browse the repository at this point in the history
SupportedFECModes, AdvertisedLinkModes, AdvertisedFECModes to NIC
struct.
Update test case to validate new fields.
Update README.

Signed-off-by: Jacob Young <[email protected]>
  • Loading branch information
Jacob Young committed May 11, 2023
1 parent 29cf834 commit d0b5715
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 25 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,20 @@ Each `ghw.NIC` struct contains the following fields:
* `ghw.NIC.PCIAddress` is the PCI device address of the device backing the NIC.
this is not-nil only if the backing device is indeed a PCI device; more backing
devices (e.g. USB) will be added in future versions.
* `ghw.NIC.Speed` is a string showing the current link speed. This
field will be present even if ethtool is not available.
* `ghw.NIC.Duplex` is a string showing the current link duplex. This
field will be present even if ethtool is not available.
* `ghw.NIC.SupportedLinkModes` is a string slice containing a list of
supported link modes
* `ghw.NIC.SupportedPorts` is a string slice containing the list of
supported port types (MII, TP, FIBRE)
* `ghw.NIC.SupportedFECModes` is a string slice containing a list of
supported FEC Modes.
* `ghw.NIC.AdvertisedLinkModes` is a string slice containing the
link modes being advertised during auto negotiation.
* `ghw.NIC.AdvertisedFECModes` is a string slice containing the FEC
modes advertised during auto negotiation.

The `ghw.NICCapability` struct contains the following fields:

Expand Down
19 changes: 14 additions & 5 deletions pkg/net/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,20 @@ type NICCapability struct {
}

type NIC struct {
Name string `json:"name"`
MacAddress string `json:"mac_address"`
IsVirtual bool `json:"is_virtual"`
Capabilities []*NICCapability `json:"capabilities"`
PCIAddress *string `json:"pci_address,omitempty"`
Name string `json:"name"`
MacAddress string `json:"mac_address"`
IsVirtual bool `json:"is_virtual"`
Capabilities []*NICCapability `json:"capabilities"`
PCIAddress *string `json:"pci_address,omitempty"`
Speed string `json:"speed"`
Duplex string `json:"duplex"`
SupportedLinkModes []string `json:"supported_link_modes,omitempty"`
SupportedPorts []string `json:"supported_ports,omitempty"`
SupportedFECModes []string `json:"supported_fec_modes,omitempty"`
AdvertisedLinkModes []string `json:"advertised_link_modes,omitempty"`
AdvertisedFECModes []string `json:"advertised_fec_modes,omitempty"`
SupportedWakeOnModes []string `json:"supported_wake_on_modes,omitempty"`
AdvertisedWakeOnModes []string `json:"advertised_wake_on_modes,omitempty"`
// TODO(fromani): add other hw addresses (USB) when we support them
}

Expand Down
23 changes: 16 additions & 7 deletions pkg/net/net_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func nics(ctx *context.Context) []*NIC {
mac := netDeviceMacAddress(paths, filename)
nic.MacAddress = mac
if etAvailable {
nic.Capabilities = netDeviceCapabilities(ctx, filename)
nic.netDeviceParseEthtool(ctx, filename)
} else {
nic.Capabilities = []*NICCapability{}
}
Expand Down Expand Up @@ -106,19 +106,29 @@ func ethtoolInstalled() bool {
return err == nil
}

func netDeviceCapabilities(ctx *context.Context, dev string) []*NICCapability {
caps := make([]*NICCapability, 0)
func (n *NIC) netDeviceParseEthtool(ctx *context.Context, dev string) {
var out bytes.Buffer
path, _ := exec.LookPath("ethtool")

// Get auto-negotiation and pause-frame-use capabilities from "ethtool" (with no options)
// Populate Speed, Duplex, SupportedLinkModes, SupportedPorts, SupportedFECModes,
// AdvertisedLinkModes, and AdvertisedFECModes attributes from "ethtool" output.
cmd := exec.Command(path, dev)
cmd.Stdout = &out
err := cmd.Run()
if err == nil {
m := parseNicAttrEthtool(&out)
caps = append(caps, autoNegCap(m))
caps = append(caps, pauseFrameUseCap(m))
n.Capabilities = append(n.Capabilities, autoNegCap(m))
n.Capabilities = append(n.Capabilities, pauseFrameUseCap(m))

// Update NIC Attributes with ethtool output
n.Speed = strings.Join(m["Speed"], "")
n.Duplex = strings.Join(m["Duplex"], "")
n.SupportedLinkModes = m["Supported link modes"]
n.SupportedPorts = m["Supported ports"]
n.SupportedFECModes = m["Supported FEC modes"]
n.AdvertisedLinkModes = m["Advertised link modes"]
n.AdvertisedFECModes = m["Advertised FEC modes"]
} else {
msg := fmt.Sprintf("could not grab NIC link info for %s: %s", dev, err)
ctx.Warn(msg)
Expand Down Expand Up @@ -154,15 +164,14 @@ func netDeviceCapabilities(ctx *context.Context, dev string) []*NICCapability {
scanner.Scan()
for scanner.Scan() {
line := strings.TrimPrefix(scanner.Text(), "\t")
caps = append(caps, netParseEthtoolFeature(line))
n.Capabilities = append(n.Capabilities, netParseEthtoolFeature(line))
}

} else {
msg := fmt.Sprintf("could not grab NIC capabilities for %s: %s", dev, err)
ctx.Warn(msg)
}

return caps

}

Expand Down
52 changes: 39 additions & 13 deletions pkg/net/net_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func TestParseNicAttrEthtool(t *testing.T) {

tests := []struct {
input string
expected []*NICCapability
expected *NIC
}{
{
input: `Settings for eth0:
Expand Down Expand Up @@ -96,26 +96,52 @@ func TestParseNicAttrEthtool(t *testing.T) {
drv probe link
Link detected: yes
`,
expected: []*NICCapability{
{
Name: "auto-negotiation",
IsEnabled: true,
CanEnable: true,
expected: &NIC{
Speed: "1000Mb/s",
Duplex: "Full",
SupportedPorts: []string{"TP"},
AdvertisedLinkModes: []string{
"10baseT/Half",
"10baseT/Full",
"100baseT/Half",
"100baseT/Full",
"1000baseT/Full",
},
{
Name: "pause-frame-use",
IsEnabled: false,
CanEnable: false,
SupportedLinkModes: []string{
"10baseT/Half",
"10baseT/Full",
"100baseT/Half",
"100baseT/Full",
"1000baseT/Full",
},
Capabilities: []*NICCapability{
{
Name: "auto-negotiation",
IsEnabled: true,
CanEnable: true,
},
{
Name: "pause-frame-use",
IsEnabled: false,
CanEnable: false,
},
},
},
},
}

for x, test := range tests {
m := parseNicAttrEthtool(bytes.NewBufferString(test.input))
actual := make([]*NICCapability, 0)
actual = append(actual, autoNegCap(m))
actual = append(actual, pauseFrameUseCap(m))
actual := &NIC{}
actual.Speed = strings.Join(m["Speed"], "")
actual.Duplex = strings.Join(m["Duplex"], "")
actual.SupportedLinkModes = m["Supported link modes"]
actual.SupportedPorts = m["Supported ports"]
actual.SupportedFECModes = m["Supported FEC modes"]
actual.AdvertisedLinkModes = m["Advertised link modes"]
actual.AdvertisedFECModes = m["Advertised FEC modes"]
actual.Capabilities = append(actual.Capabilities, autoNegCap(m))
actual.Capabilities = append(actual.Capabilities, pauseFrameUseCap(m))
if !reflect.DeepEqual(test.expected, actual) {
t.Fatalf("In test %d\nExpected:\n%+v\nActual:\n%+v\n", x, test.expected, actual)
}
Expand Down

0 comments on commit d0b5715

Please sign in to comment.