diff options
author | Vladimir Oltean <vladimir.oltean@nxp.com> | 2023-01-19 14:26:54 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2023-01-23 12:44:18 +0000 |
commit | 2b30f8291a30305eeedcd787b4d0e352410f7268 (patch) | |
tree | 12eed7a354f6fd74c309cf258d7c06446c3814e2 /include/linux/ethtool.h | |
parent | 40e0b09081420853542571c38875b48b60404ebb (diff) |
net: ethtool: add support for MAC Merge layer
The MAC merge sublayer (IEEE 802.3-2018 clause 99) is one of 2
specifications (the other being Frame Preemption; IEEE 802.1Q-2018
clause 6.7.2), which work together to minimize latency caused by frame
interference at TX. The overall goal of TSN is for normal traffic and
traffic with a bounded deadline to be able to cohabitate on the same L2
network and not bother each other too much.
The standards achieve this (partly) by introducing the concept of
preemptible traffic, i.e. Ethernet frames that have a custom value for
the Start-of-Frame-Delimiter (SFD), and these frames can be fragmented
and reassembled at L2 on a link-local basis. The non-preemptible frames
are called express traffic, they are transmitted using a normal SFD, and
they can preempt preemptible frames, therefore having lower latency,
which can matter at lower (100 Mbps) link speeds, or at high MTUs (jumbo
frames around 9K). Preemption is not recursive, i.e. a P frame cannot
preempt another P frame. Preemption also does not depend upon priority,
or otherwise said, an E frame with prio 0 will still preempt a P frame
with prio 7.
In terms of implementation, the standards talk about the presence of an
express MAC (eMAC) which handles express traffic, and a preemptible MAC
(pMAC) which handles preemptible traffic, and these MACs are multiplexed
on the same MII by a MAC merge layer.
To support frame preemption, the definition of the SFD was generalized
to SMD (Start-of-mPacket-Delimiter), where an mPacket is essentially an
Ethernet frame fragment, or a complete frame. Stations unaware of an SMD
value different from the standard SFD will treat P frames as error
frames. To prevent that from happening, a negotiation process is
defined.
On RX, packets are dispatched to the eMAC or pMAC after being filtered
by their SMD. On TX, the eMAC/pMAC classification decision is taken by
the 802.1Q spec, based on packet priority (each of the 8 user priority
values may have an admin-status of preemptible or express).
The MAC Merge layer and the Frame Preemption parameters have some degree
of independence in terms of how software stacks are supposed to deal
with them. The activation of the MM layer is supposed to be controlled
by an LLDP daemon (after it has been communicated that the link partner
also supports it), after which a (hardware-based or not) verification
handshake takes place, before actually enabling the feature. So the
process is intended to be relatively plug-and-play. Whereas FP settings
are supposed to be coordinated across a network using something
approximating NETCONF.
The support contained here is exclusively for the 802.3 (MAC Merge)
portions and not for the 802.1Q (Frame Preemption) parts. This API is
sufficient for an LLDP daemon to do its job. The FP adminStatus variable
from 802.1Q is outside the scope of an LLDP daemon.
I have taken a few creative licenses and augmented the Linux kernel UAPI
compared to the standard managed objects recommended by IEEE 802.3.
These are:
- ETHTOOL_A_MM_PMAC_ENABLED: According to Figure 99-6: Receive
Processing state diagram, a MAC Merge layer is always supposed to be
able to receive P frames. However, this implies keeping the pMAC
powered on, which will consume needless power in applications where FP
will never be used. If LLDP is used, the reception of an Additional
Ethernet Capabilities TLV from the link partner is sufficient
indication that the pMAC should be enabled. So my proposal is that in
Linux, we keep the pMAC turned off by default and that user space
turns it on when needed.
- ETHTOOL_A_MM_VERIFY_ENABLED: The IEEE managed object is called
aMACMergeVerifyDisableTx. I opted for consistency (positive logic) in
the boolean netlink attributes offered, so this is also positive here.
Other than the meaning being reversed, they correspond to the same
thing.
- ETHTOOL_A_MM_MAX_VERIFY_TIME: I found it most reasonable for a LLDP
daemon to maximize the verifyTime variable (delay between SMD-V
transmissions), to maximize its chances that the LP replies. IEEE says
that the verifyTime can range between 1 and 128 ms, but the NXP ENETC
stupidly keeps this variable in a 7 bit register, so the maximum
supported value is 127 ms. I could have chosen to hardcode this in the
LLDP daemon to a lower value, but why not let the kernel expose its
supported range directly.
- ETHTOOL_A_MM_TX_MIN_FRAG_SIZE: the standard managed object is called
aMACMergeAddFragSize, and expresses the "additional" fragment size
(on top of ETH_ZLEN), whereas this expresses the absolute value of the
fragment size.
- ETHTOOL_A_MM_RX_MIN_FRAG_SIZE: there doesn't appear to exist a managed
object mandated by the standard, but user space clearly needs to know
what is the minimum supported fragment size of our local receiver,
since LLDP must advertise a value no lower than that.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/ethtool.h')
-rw-r--r-- | include/linux/ethtool.h | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 20d197693d34..37eba38da502 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -478,6 +478,98 @@ struct ethtool_module_power_mode_params { }; /** + * struct ethtool_mm_state - 802.3 MAC merge layer state + * @verify_time: + * wait time between verification attempts in ms (according to clause + * 30.14.1.6 aMACMergeVerifyTime) + * @max_verify_time: + * maximum accepted value for the @verify_time variable in set requests + * @verify_status: + * state of the verification state machine of the MM layer (according to + * clause 30.14.1.2 aMACMergeStatusVerify) + * @tx_enabled: + * set if the MM layer is administratively enabled in the TX direction + * (according to clause 30.14.1.3 aMACMergeEnableTx) + * @tx_active: + * set if the MM layer is enabled in the TX direction, which makes FP + * possible (according to 30.14.1.5 aMACMergeStatusTx). This should be + * true if MM is enabled, and the verification status is either verified, + * or disabled. + * @pmac_enabled: + * set if the preemptible MAC is powered on and is able to receive + * preemptible packets and respond to verification frames. + * @verify_enabled: + * set if the Verify function of the MM layer (which sends SMD-V + * verification requests) is administratively enabled (regardless of + * whether it is currently in the ETHTOOL_MM_VERIFY_STATUS_DISABLED state + * or not), according to clause 30.14.1.4 aMACMergeVerifyDisableTx (but + * using positive rather than negative logic). The device should always + * respond to received SMD-V requests as long as @pmac_enabled is set. + * @tx_min_frag_size: + * the minimum size of non-final mPacket fragments that the link partner + * supports receiving, expressed in octets. Compared to the definition + * from clause 30.14.1.7 aMACMergeAddFragSize which is expressed in the + * range 0 to 3 (requiring a translation to the size in octets according + * to the formula 64 * (1 + addFragSize) - 4), a value in a continuous and + * unbounded range can be specified here. + * @rx_min_frag_size: + * the minimum size of non-final mPacket fragments that this device + * supports receiving, expressed in octets. + */ +struct ethtool_mm_state { + u32 verify_time; + u32 max_verify_time; + enum ethtool_mm_verify_status verify_status; + bool tx_enabled; + bool tx_active; + bool pmac_enabled; + bool verify_enabled; + u32 tx_min_frag_size; + u32 rx_min_frag_size; +}; + +/** + * struct ethtool_mm_cfg - 802.3 MAC merge layer configuration + * @verify_time: see struct ethtool_mm_state + * @verify_enabled: see struct ethtool_mm_state + * @tx_enabled: see struct ethtool_mm_state + * @pmac_enabled: see struct ethtool_mm_state + * @tx_min_frag_size: see struct ethtool_mm_state + */ +struct ethtool_mm_cfg { + u32 verify_time; + bool verify_enabled; + bool tx_enabled; + bool pmac_enabled; + u32 tx_min_frag_size; +}; + +/** + * struct ethtool_mm_stats - 802.3 MAC merge layer statistics + * @MACMergeFrameAssErrorCount: + * received MAC frames with reassembly errors + * @MACMergeFrameSmdErrorCount: + * received MAC frames/fragments rejected due to unknown or incorrect SMD + * @MACMergeFrameAssOkCount: + * received MAC frames that were successfully reassembled and passed up + * @MACMergeFragCountRx: + * number of additional correct SMD-C mPackets received due to preemption + * @MACMergeFragCountTx: + * number of additional mPackets sent due to preemption + * @MACMergeHoldCount: + * number of times the MM layer entered the HOLD state, which blocks + * transmission of preemptible traffic + */ +struct ethtool_mm_stats { + u64 MACMergeFrameAssErrorCount; + u64 MACMergeFrameSmdErrorCount; + u64 MACMergeFrameAssOkCount; + u64 MACMergeFragCountRx; + u64 MACMergeFragCountTx; + u64 MACMergeHoldCount; +}; + +/** * struct ethtool_ops - optional netdev operations * @cap_link_lanes_supported: indicates if the driver supports lanes * parameter. @@ -649,6 +741,9 @@ struct ethtool_module_power_mode_params { * plugged-in. * @set_module_power_mode: Set the power mode policy for the plug-in module * used by the network device. + * @get_mm: Query the 802.3 MAC Merge layer state. + * @set_mm: Set the 802.3 MAC Merge layer parameters. + * @get_mm_stats: Query the 802.3 MAC Merge layer statistics. * * All operations are optional (i.e. the function pointer may be set * to %NULL) and callers must take this into account. Callers must @@ -787,6 +882,10 @@ struct ethtool_ops { int (*set_module_power_mode)(struct net_device *dev, const struct ethtool_module_power_mode_params *params, struct netlink_ext_ack *extack); + int (*get_mm)(struct net_device *dev, struct ethtool_mm_state *state); + int (*set_mm)(struct net_device *dev, struct ethtool_mm_cfg *cfg, + struct netlink_ext_ack *extack); + void (*get_mm_stats)(struct net_device *dev, struct ethtool_mm_stats *stats); }; int ethtool_check_ops(const struct ethtool_ops *ops); |