Bug 266973 - [e1000] incorrect behavior when media and mediaopt are set to 100BaseTX full-duplex
Summary: [e1000] incorrect behavior when media and mediaopt are set to 100BaseTX full-...
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 13.1-STABLE
Hardware: Any Any
: --- Affects Many People
Assignee: freebsd-net (Nobody)
URL:
Keywords: IntelNetworking
Depends on:
Blocks:
 
Reported: 2022-10-11 16:45 UTC by Thomas Pasqualini
Modified: 2023-02-07 10:29 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Pasqualini 2022-10-11 16:45:43 UTC
Using the e1000 driver, when a igb interface is configured with:

  `media 100BaseTX mediaopt full-duplex`

and connected to a switchport which is configured accordingly with

  autonegotiation disabled
  speed = 100Mbps
  duplex = full

and connected with a straight cable (as it should), the resulting interface status is `no carrier`, while it should not.

I am able to reproduce this behavior with both Cisco and Netgear switches.

Switching back the igb to `media auto` entails the status to become active, but with a duplex resolved to `half`, as it is expected in this case.

Switching the igb to `media 100BaseTX mediaopt full-duplex`, and the switchport to autoneg, entails both side to be up (ie igb status: active), but the duplex to be resolved as `full` on the switch side, while it should be resolved to 'half' instead in this case.

To be clean the configuration should be either set to autoneg on both sides, either forced to 100-full on both sides. In this second case, when an igb interface is forced to media `100BaseTX mediaopt full-duplex` and connected to a switchport also set to `100-full`, the igb status remains at `no-carrier` while the expected one is `active`.

The same configuration with other NIC drivers, e.g. bge or bce, entails a correct behavior.
Comment 1 Thomas Pasqualini 2022-10-15 12:44:06 UTC
Here is an exemple of hardware on which this uncorrect behavior can be observed:

# pciconf -l -v | grep -i igb -A 4
igb0@pci0:26:0:0:	class=0x020000 rev=0x01 hdr=0x00 vendor=0x8086 device=0x1521 subvendor=0x1028 subdevice=0x1faa
    vendor     = 'Intel Corporation'
    device     = 'I350 Gigabit Network Connection'
    class      = network
    subclass   = ethernet
igb1@pci0:26:0:1:	class=0x020000 rev=0x01 hdr=0x00 vendor=0x8086 device=0x1521 subvendor=0x1028 subdevice=0x1faa
    vendor     = 'Intel Corporation'
    device     = 'I350 Gigabit Network Connection'
    class      = network
    subclass   = ethernet
Comment 2 Kristof Provost freebsd_committer freebsd_triage 2022-11-07 20:50:12 UTC
We've taken a look at the PHY interactions with this dtrace snippet:

dtrace -n 'fbt::e1000_read_phy_reg_82580:entry { printf("read(%#x)", arg1); self->data = arg2; }' -n 'fbt::e1000_read_phy_reg_82580:return { printf("=> %#x", *(uint16_t *)self->data); }' -n 'fbt::e1000_write_phy_reg_82580:entry { printf("write(%#x, %#x)", arg1, arg2); }' -c "ifconfig igb0 media 100BaseTX mediaopt full-duplex"


It's a bit strange that running the command to force 100-full with dtrace does not entail the problem. but running again ifconfig igb1 media auto; ifconfig igb1 media 100BaseTX mediaopt full-duplex; entails the problem again. See the bellow output:

[root@r640fw7m ~]# ifconfig igb1 media auto
[root@r640fw7m ~]# ifconfig igb1
igb1: flags=8863<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
    options=4e100bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN_HWFILTER,RXCSUM_IPV6,TXCSUM_IPV6,NOMAP>
    ether e4:43:4b:de:53:03
    inet 10.2.7.141 netmask 0xffff0000 broadcast 10.2.255.255
    media: Ethernet autoselect (100baseTX )
    status: active
    nd6 options=1
[root@r640fw7m ~]# dtrace -n 'fbt::e1000_read_phy_reg_82580:entry { printf("read(%#x)", arg1); self->data = arg2; }' -n 'fbt::e1000_read_phy_reg_82580:return { printf("=> %#x", *(uint16_t *)self->data); }' -n 'fbt::e1000_write_phy_reg_82580:entry { printf("write(%#x, %#x)", arg1, arg2); }' -c "ifconfig igb1 media 100BaseTX mediaopt full-duplex"
dtrace: description 'fbt::e1000_read_phy_reg_82580:entry ' matched 1 probe
dtrace: description 'fbt::e1000_read_phy_reg_82580:return ' matched 1 probe
dtrace: description 'fbt::e1000_write_phy_reg_82580:entry ' matched 1 probe
dtrace: pid 31422 has exited
CPU     ID                    FUNCTION:NAME
 26   4923   e1000_read_phy_reg_82580:entry read(0x16)
 26   4924  e1000_read_phy_reg_82580:return => 0x7f08
 26   4925  e1000_write_phy_reg_82580:entry write(0x16, 0xff08)
 26   4923   e1000_read_phy_reg_82580:entry read(0x12)
 26   4924  e1000_read_phy_reg_82580:return => 0x840a
 26   4925  e1000_write_phy_reg_82580:entry write(0x12, 0x840a)
 26   4923   e1000_read_phy_reg_82580:entry read(0x9)
 26   4924  e1000_read_phy_reg_82580:return => 0x600
 26   4925  e1000_write_phy_reg_82580:entry write(0x9, 0x600)
 26   4923   e1000_read_phy_reg_82580:entry read(0)
 26   4924  e1000_read_phy_reg_82580:return => 0x1040
 26   4925  e1000_write_phy_reg_82580:entry write(0, 0x2100)
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x16)
 26   4924  e1000_read_phy_reg_82580:return => 0x7f08
 26   4925  e1000_write_phy_reg_82580:entry write(0x16, 0xff08)
 26   4923   e1000_read_phy_reg_82580:entry read(0x12)
 26   4924  e1000_read_phy_reg_82580:return => 0x840a
 26   4925  e1000_write_phy_reg_82580:entry write(0x12, 0x840a)
 26   4923   e1000_read_phy_reg_82580:entry read(0x9)
 26   4924  e1000_read_phy_reg_82580:return => 0x600
 26   4925  e1000_write_phy_reg_82580:entry write(0x9, 0x600)
 26   4923   e1000_read_phy_reg_82580:entry read(0)
 26   4924  e1000_read_phy_reg_82580:return => 0x1040
 26   4925  e1000_write_phy_reg_82580:entry write(0, 0x2100)
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
 26   4923   e1000_read_phy_reg_82580:entry read(0x1)
 26   4924  e1000_read_phy_reg_82580:return => 0x7949
  2   4923   e1000_read_phy_reg_82580:entry read(0x1)

[root@r640fw7m ~]# ifconfig igb1
igb1: flags=8863<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
    options=4e100bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN_HWFILTER,RXCSUM_IPV6,TXCSUM_IPV6,NOMAP>
    ether e4:43:4b:de:53:03
    inet 10.2.7.141 netmask 0xffff0000 broadcast 10.2.255.255
    media: Ethernet 100baseTX 
    status: active
    nd6 options=1
[root@r640fw7m ~]# ifconfig igb1 media 100BaseTX mediaopt full-duplex
[root@r640fw7m ~]# ifconfig igb1
igb1: flags=8863<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
    options=4e100bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN_HWFILTER,RXCSUM_IPV6,TXCSUM_IPV6,NOMAP>
    ether e4:43:4b:de:53:03
    inet 10.2.7.141 netmask 0xffff0000 broadcast 10.2.255.255
    media: Ethernet 100baseTX 
    status: active
    nd6 options=1
[root@r640fw7m ~]# ifconfig igb1 media auto
[root@r640fw7m ~]# ifconfig igb1 media 100BaseTX mediaopt full-duplex
[root@r640fw7m ~]# ifconfig igb1
igb1: flags=8863<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
    options=4e100bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN_HWFILTER,RXCSUM_IPV6,TXCSUM_IPV6,NOMAP>
    ether e4:43:4b:de:53:03
    inet 10.2.7.141 netmask 0xffff0000 broadcast 10.2.255.255
    media: Ethernet 100baseTX  (autoselect)
    status: no carrier
    nd6 options=1
Comment 3 Kristof Provost freebsd_committer freebsd_triage 2022-11-07 20:54:48 UTC
I'm struggling to make sense of this. I can't quite follow how the code produces this PHY access pattern, and can also not work out why we end up getting link when dtrace instrumented, and not when it's not. Unless we're not waiting long enough for the PHY to do its thing, but I also can't see evidence of that in the dtrace output.

There are two series of what looks like a wait for link pattern in the dtrace output> That is, this:

26   4923   e1000_read_phy_reg_82580:entry read(0x1)
26   4924  e1000_read_phy_reg_82580:return => 0x7949

I'd assume that's produced by e1000_phy_has_link_generic() where we do 2x iterations of read_reg(PHY_STATUS), and check for the MII_SR_LINK_STATUS flag. That flag (0x0004) is not set in any of these reads, and yet ifconfig does later report "status: active".
Comment 4 Franco Fichtner 2022-11-08 05:49:43 UTC
Possibly https://reviews.freebsd.org/D34449 which was already reverted after multiple reports of a regression.