aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kubecek <mkubecek@suse.cz>2023-02-21 21:38:23 +0100
committerMichal Kubecek <mkubecek@suse.cz>2023-02-21 21:38:23 +0100
commit5cea67304a3c13e7757a0946aa1a0bff4989b899 (patch)
tree411b2c6099397ed5cd8bfc0f8dccb089a4a1e5cc
parent82642de0751cb0122c73757a906a63f2a272a2d1 (diff)
parenta0d1bd673c16652a2074cc3889193ef482f8b5d5 (diff)
downloadethtool-5cea67304a3c13e7757a0946aa1a0bff4989b899.tar.gz
Merge branch 'next' into master
-rw-r--r--Makefile.am3
-rw-r--r--ethtool.8.in194
-rw-r--r--ethtool.c89
-rw-r--r--netlink/desc-ethtool.c50
-rw-r--r--netlink/extapi.h10
-rw-r--r--netlink/mm.c270
-rw-r--r--netlink/pause.c33
-rw-r--r--netlink/plca.c296
-rw-r--r--netlink/rings.c7
-rw-r--r--netlink/settings.c81
-rw-r--r--netlink/stats.c14
-rw-r--r--uapi/linux/ethtool.h48
-rw-r--r--uapi/linux/ethtool_netlink.h79
-rw-r--r--uapi/linux/if_link.h5
-rw-r--r--uapi/linux/rtnetlink.h1
15 files changed, 1151 insertions, 29 deletions
diff --git a/Makefile.am b/Makefile.am
index 999e769..c83cb18 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,10 +38,11 @@ ethtool_SOURCES += \
netlink/features.c netlink/privflags.c netlink/rings.c \
netlink/channels.c netlink/coalesce.c netlink/pause.c \
netlink/eee.c netlink/tsinfo.c netlink/fec.c \
- netlink/stats.c \
+ netlink/stats.c netlink/mm.c \
netlink/desc-ethtool.c netlink/desc-genlctrl.c \
netlink/module-eeprom.c netlink/module.c netlink/rss.c \
netlink/desc-rtnl.c netlink/cable_test.c netlink/tunnels.c \
+ netlink/plca.c \
uapi/linux/ethtool_netlink.h \
uapi/linux/netlink.h uapi/linux/genetlink.h \
uapi/linux/rtnetlink.h uapi/linux/if_link.h \
diff --git a/ethtool.8.in b/ethtool.8.in
index d5d60d5..3672e44 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -201,6 +201,7 @@ ethtool \- query or control network driver and hardware settings
.BN rx\-buf\-len
.BN cqe\-size
.BN tx\-push
+.BN rx\-push
.HP
.B ethtool \-i|\-\-driver
.I devname
@@ -468,7 +469,6 @@ ethtool \- query or control network driver and hardware settings
.IR %x ]
.I sub_command
.RB ...
- .
.HP
.B ethtool \-\-cable\-test
.I devname
@@ -490,6 +490,38 @@ ethtool \- query or control network driver and hardware settings
.I devname
.RB [ power\-mode\-policy
.BR high | auto ]
+.HP
+.B ethtool \-\-get\-plca\-cfg
+.I devname
+.HP
+.B ethtool \-\-set\-plca\-cfg
+.I devname
+.RB [ enable
+.BR on | off ]
+.BN node\-id N
+.BN node\-cnt N
+.BN to\-tmr N
+.BN burst\-cnt N
+.BN burst\-tmr N
+.HP
+.B ethtool \-\-get\-plca\-status
+.I devname
+.HP
+.B ethtool \-\-show\-mm
+.I devname
+.HP
+.B ethtool \-\-set\-mm
+.I devname
+.RB [ verify\-enabled
+.BR on | off ]
+.RB [ verify\-time
+.BR N ]
+.RB [ tx\-enabled
+.BR on | off ]
+.RB [ pmac\-enabled
+.BR on | off ]
+.RB [ tx\-min\-frag\-size
+.BR N ]
.
.\" Adjust lines (i.e. full justification) and hyphenate.
.ad
@@ -533,6 +565,15 @@ displaying relevant device statistics for selected get commands.
.TP
.B \-a \-\-show\-pause
Queries the specified Ethernet device for pause parameter information.
+.RS 4
+.TP
+.A3 \fB\-\-src \fBaggregate\fP \fBemac\fP \fBpmac\fP
+If the MAC Merge layer is supported, request a particular source of device
+statistics (eMAC or pMAC, or their aggregate). Only valid if ethtool was
+invoked with the
+.B \-I \-\-include\-statistics
+argument.
+.RE
.TP
.B \-A \-\-pause
Changes the pause parameters of the specified Ethernet device.
@@ -581,6 +622,9 @@ Changes the size of completion queue event.
.TP
.BI tx\-push \ on|off
Specifies whether TX push should be enabled.
+.TP
+.BI rx\-push \ on|off
+Specifies whether RX push should be enabled.
.RE
.TP
.B \-i \-\-driver
@@ -698,6 +742,10 @@ naming of NIC- and driver-specific statistics across vendors.
.TP
.B \fB\-\-groups [\fBeth\-phy\fP] [\fBeth\-mac\fP] [\fBeth\-ctrl\fP] [\fBrmon\fP]
Request groups of standard device statistics.
+.TP
+.A3 \fB\-\-src \fBaggregate\fP \fBemac\fP \fBpmac\fP
+If the MAC Merge layer is supported, request a particular source of device
+statistics (eMAC or pMAC, or their aggregate).
.RE
.TP
.B \-\-phy\-statistics
@@ -776,6 +824,9 @@ lB l lB.
0x001 10baseT Half
0x002 10baseT Full
0x100000000000000000000000 10baseT1L Full
+0x8000000000000000000000000 10baseT1S Full
+0x10000000000000000000000000 10baseT1S Half
+0x20000000000000000000000000 10baseT1S_P2MP Half
0x004 100baseT Half
0x008 100baseT Full
0x80000000000000000 100baseT1 Full
@@ -1511,6 +1562,147 @@ administratively up and to low power mode when the last port using it is put
administratively down. The power mode policy can be set before a module is
plugged-in.
.RE
+.TP
+.B \-\-get\-plca\-cfg
+Show the current PLCA parameters for the given interface.
+.RE
+.TP
+.B \-\-set\-plca\-cfg
+Change the PLCA settings for the given interface.
+.RS 4
+.TP
+.A2 enable on off
+Enables or disables the PLCA function. When the PLCA RS is disabled (default),
+the PHY operates in plain CSMA/CD mode. To enable PLCA, the PHY must be assigned
+a unique \fBplca\-id\fR other than 255. This one can be configured concurrently
+with the enable parameter. The \fBenable\fR parameter maps to IEEE 802.3cg-2019
+clause 30.16.1.1.1 (aPLCAAdminState) and clause 30.16.1.2.1 (acPLCAAdminControl).
+.TP
+.BI node\-id \ N
+The unique node identifier in the range [0 .. 255]. Node ID 0 is reserved for
+the coordinator node, the one generating the BEACON signal. There must be
+exactly one coordinator on a PLCA network. Setting the node ID to 255 (default)
+disables the node. This parameter maps to IEEE 802.3cg-2019 clause 30.16.1.1.4
+(aPLCALocalNodeID).
+.TP
+.BI node\-cnt \ N
+The node-cnt [1 .. 255] should be set after the maximum number of nodes that
+can be plugged to the multi-drop network. This parameter regulates the minimum
+length of the PLCA cycle. Therefore, it is only meaningful for the coordinator
+node (\fBnod-id\fR = 0). Setting this parameter on a follower node has no
+effect. The \fBnode\-cnt\fR parameter maps to IEEE 802.3cg-2019 clause
+30.16.1.1.3 (aPLCANodeCount).
+.TP
+.BI to\-tmr \ N
+The TO timer parameter sets the value of the transmit opportunity timer in
+bit-times, and shall be set equal across all the nodes sharing the same
+medium for PLCA to work. The default value of 32 is enough to cover a link of
+roughly 50 mt. This parameter maps to IEEE 802.3cg-2019 clause 30.16.1.1.5
+(aPLCATransmitOpportunityTimer).
+.TP
+.BI burst\-cnt \ N
+The \fBburst\-cnt\fR parameter [0 .. 255] indicates the extra number of packets
+that the node is allowed to send during a single transmit opportunity.
+By default, this attribute is 0, meaning that the node can send a sigle frame
+per TO. When greater than 0, the PLCA RS keeps the TO after any transmission,
+waiting for the MAC to send a new frame for up to \fBburst\-tmr\fR BTs. This can
+only happen a number of times per PLCA cycle up to the value of this parameter.
+After that, the burst is over and the normal counting of TOs resumes.
+This parameter maps to IEEE 802.3cg-2019 clause 30.16.1.1.6 (aPLCAMaxBurstCount).
+.TP
+.BI burst\-tmr \ N
+The \fBburst\-tmr\fR parameter [0 .. 255] sets how many bit-times the PLCA RS
+waits for the MAC to initiate a new transmission when \fBburst\-cnt\fR is
+greater than 0. If the MAC fails to send a new frame within this time, the burst
+ends and the counting of TOs resumes. Otherwise, the new frame is sent as part
+of the current burst. This parameter maps to IEEE 802.3cg-2019 clause
+30.16.1.1.7 (aPLCABurstTimer). The value of \fBburst\-tmr\fR should be set
+greater than the Inter-Frame-Gap (IFG) time of the MAC (plus some margin)
+for PLCA burst mode to work as intended.
+.RE
+.TP
+.B \-\-get\-plca\-status
+Show the current PLCA status for the given interface. If \fBon\fR, the PHY is
+successfully receiving or generating the BEACON signal. If \fBoff\fR, the PLCA
+function is temporarily disabled and the PHY is operating in plain CSMA/CD mode.
+.RE
+.TP
+.B \-\-show\-mm
+Show the MAC Merge layer state. The ethtool argument
+.B \-I \-\-include\-statistics
+can be used with this command, and MAC Merge layer statistics counters will
+also be retrieved.
+.RS 4
+.TP
+.B pmac-enabled
+Shows whether the pMAC is enabled and capable of receiving traffic and SMD-V
+frames (and responding to them with SMD-R replies).
+.TP
+.B tx-enabled
+Shows whether transmission on the pMAC is administratively enabled.
+.TP
+.B tx-active
+Shows whether transmission on the pMAC is active (verification is either
+successful, or was disabled).
+.TP
+.B tx-min-frag-size
+Shows the minimum size (in octets) of transmitted non-final fragments which
+can be received by the link partner. Corresponds to the standard addFragSize
+variable using the formula:
+
+tx-min-frag-size = 64 * (1 + addFragSize) - 4
+.TP
+.B rx-min-frag-size
+Shows the minimum size (in octets) of non-final fragments which the local
+device supports receiving.
+.TP
+.B verify-enabled
+Shows whether the verification state machine is enabled. This process, if
+successful, ensures that preemptible frames transmitted by the local device
+will not be dropped as error frames by the link partner.
+.TP
+.B verify-time
+Shows the interval in ms between verification attempts, represented as an
+integer between 1 and 128 ms. The standard defines a fixed number of
+verification attempts (verifyLimit) before failing the verification process.
+.TP
+.B max-verify-time
+Shows the maximum value for verify-time accepted by the local device, which
+may be less than 128 ms.
+.TP
+.B verify-status
+Shows the current state of the verification state machine of the local device.
+Values can be
+.B INITIAL,
+.B VERIFYING,
+.B SUCCEEDED,
+.B FAILED
+or
+.B DISABLED.
+
+.RE
+.TP
+.B \-\-set\-mm
+Set the MAC Merge layer parameters.
+.RS 4
+.TP
+.A2 pmac-enabled \ on off
+Enable reception for the pMAC.
+.TP
+.A2 tx-enabled \ on off
+Administatively enable transmission for the pMAC.
+.TP
+.B tx-min-frag-size \ N
+Set the minimum size (in octets) of transmitted non-final fragments which can
+be received by the link partner.
+.TP
+.A2 verify-enabled \ on off
+Enable or disable the verification state machine.
+.TP
+.B verify-time \ N
+Set the interval in ms between verification attempts.
+
+.RE
.SH BUGS
Not supported (in part or whole) on all network drivers.
.SH AUTHOR
diff --git a/ethtool.c b/ethtool.c
index 023bb7d..6022a6e 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -484,6 +484,9 @@ static void init_global_link_mode_masks(void)
ETHTOOL_LINK_MODE_800000baseDR8_2_Full_BIT,
ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT,
ETHTOOL_LINK_MODE_800000baseVR8_Full_BIT,
+ ETHTOOL_LINK_MODE_10baseT1S_Full_BIT,
+ ETHTOOL_LINK_MODE_10baseT1S_Half_BIT,
+ ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT,
};
static const enum ethtool_link_mode_bit_indices
additional_advertised_flags_bits[] = {
@@ -738,6 +741,12 @@ static void dump_link_caps(const char *prefix, const char *an_prefix,
"800000baseSR8/Full" },
{ 0, ETHTOOL_LINK_MODE_800000baseVR8_Full_BIT,
"800000baseVR8/Full" },
+ { 0, ETHTOOL_LINK_MODE_10baseT1S_Full_BIT,
+ "10baseT1S/Full" },
+ { 1, ETHTOOL_LINK_MODE_10baseT1S_Half_BIT,
+ "10baseT1S/Half" },
+ { 0, ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT,
+ "10baseT1S/Half" },
};
int indent;
int did1, new_line_pend;
@@ -5673,7 +5682,8 @@ static const struct option args[] = {
.json = true,
.func = do_gpause,
.nlfunc = nl_gpause,
- .help = "Show pause options"
+ .help = "Show pause options",
+ .xhelp = " [ --src aggregate | emac | pmac ]\n"
},
{
.opts = "-A|--pause",
@@ -5737,9 +5747,10 @@ static const struct option args[] = {
" [ rx-mini N ]\n"
" [ rx-jumbo N ]\n"
" [ tx N ]\n"
- " [ rx-buf-len N]\n"
- " [ cqe-size N]\n"
- " [ tx-push on|off]\n"
+ " [ rx-buf-len N ]\n"
+ " [ cqe-size N ]\n"
+ " [ tx-push on|off ]\n"
+ " [ rx-push on|off ]\n"
},
{
.opts = "-k|--show-features|--show-offload",
@@ -5793,13 +5804,13 @@ static const struct option args[] = {
.opts = "-p|--identify",
.func = do_phys_id,
.help = "Show visible port identification (e.g. blinking)",
- .xhelp = " [ TIME-IN-SECONDS ]\n"
+ .xhelp = " [ TIME-IN-SECONDS ]\n"
},
{
.opts = "-t|--test",
.func = do_test,
.help = "Execute adapter self test",
- .xhelp = " [ online | offline | external_lb ]\n"
+ .xhelp = " [ online | offline | external_lb ]\n"
},
{
.opts = "-S|--statistics",
@@ -5808,7 +5819,8 @@ static const struct option args[] = {
.nlchk = nl_gstats_chk,
.nlfunc = nl_gstats,
.help = "Show adapter statistics",
- .xhelp = " [ --all-groups | --groups [eth-phy] [eth-mac] [eth-ctrl] [rmon] ]\n"
+ .xhelp = " [ --all-groups | --groups [eth-phy] [eth-mac] [eth-ctrl] [rmon] ]\n"
+ " [ --src aggregate | emac | pmac ]\n"
},
{
.opts = "--phy-statistics",
@@ -5848,7 +5860,7 @@ static const struct option args[] = {
" [ dst-mac %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ]\n"
" [ action %d ] | [ vf %d queue %d ]\n"
" [ context %d ]\n"
- " [ loc %d]] |\n"
+ " [ loc %d ] |\n"
" delete %d\n"
},
{
@@ -5879,7 +5891,7 @@ static const struct option args[] = {
.opts = "-f|--flash",
.func = do_flash,
.help = "Flash firmware image from the specified file to a region on the device",
- .xhelp = " FILENAME [ REGION-NUMBER-TO-FLASH ]\n"
+ .xhelp = " FILENAME [ REGION-NUMBER-TO-FLASH ]\n"
},
{
.opts = "-P|--show-permaddr",
@@ -5910,10 +5922,10 @@ static const struct option args[] = {
.func = do_schannels,
.nlfunc = nl_schannels,
.help = "Set Channels",
- .xhelp = " [ rx N ]\n"
- " [ tx N ]\n"
- " [ other N ]\n"
- " [ combined N ]\n"
+ .xhelp = " [ rx N ]\n"
+ " [ tx N ]\n"
+ " [ other N ]\n"
+ " [ combined N ]\n"
},
{
.opts = "--show-priv-flags",
@@ -5980,16 +5992,16 @@ static const struct option args[] = {
.xhelp = " [ rx-copybreak ]\n"
" [ tx-copybreak ]\n"
" [ tx-buf-size ]\n"
- " [ pfc-precention-tout ]\n"
+ " [ pfc-prevention-tout ]\n"
},
{
.opts = "--set-tunable",
.func = do_stunable,
.help = "Set tunable",
- .xhelp = " [ rx-copybreak N]\n"
- " [ tx-copybreak N]\n"
- " [ tx-buf-size N]\n"
- " [ pfc-precention-tout N]\n"
+ .xhelp = " [ rx-copybreak N ]\n"
+ " [ tx-copybreak N ]\n"
+ " [ tx-buf-size N ]\n"
+ " [ pfc-prevention-tout N ]\n"
},
{
.opts = "--reset",
@@ -6029,14 +6041,14 @@ static const struct option args[] = {
.func = do_sfec,
.nlfunc = nl_sfec,
.help = "Set FEC settings",
- .xhelp = " [ encoding auto|off|rs|baser|llrs [...]]\n"
+ .xhelp = " [ encoding auto|off|rs|baser|llrs [...] ]\n"
},
{
.opts = "-Q|--per-queue",
.func = do_perqueue,
.help = "Apply per-queue command. ",
.xhelp = "The supported sub commands include --show-coalesce, --coalesce"
- " [queue_mask %x] SUB_COMMAND\n",
+ " [queue_mask %x] SUB_COMMAND\n",
},
{
.opts = "--cable-test",
@@ -6072,6 +6084,43 @@ static const struct option args[] = {
.xhelp = " [ power-mode-policy high|auto ]\n"
},
{
+ .opts = "--get-plca-cfg",
+ .nlfunc = nl_plca_get_cfg,
+ .help = "Get PLCA configuration",
+ },
+ {
+ .opts = "--set-plca-cfg",
+ .nlfunc = nl_plca_set_cfg,
+ .help = "Set PLCA configuration",
+ .xhelp = " [ enable on|off ]\n"
+ " [ node-id N ]\n"
+ " [ node-cnt N ]\n"
+ " [ to-tmr N ]\n"
+ " [ burst-cnt N ]\n"
+ " [ burst-tmr N ]\n"
+ },
+ {
+ .opts = "--get-plca-status",
+ .nlfunc = nl_plca_get_status,
+ .help = "Get PLCA status information",
+ },
+ {
+ .opts = "--show-mm",
+ .json = true,
+ .nlfunc = nl_get_mm,
+ .help = "Show MAC merge layer state",
+ },
+ {
+ .opts = "--set-mm",
+ .nlfunc = nl_set_mm,
+ .help = "Set MAC merge layer parameters",
+ " [ verify-enabled on|off ]\n"
+ " [ verify-time N ]\n"
+ " [ tx-enabled on|off ]\n"
+ " [ pmac-enabled on|off ]\n"
+ " [ tx-min-frag-size 60-252 ]\n"
+ },
+ {
.opts = "-h|--help",
.no_dev = true,
.func = show_usage,
diff --git a/netlink/desc-ethtool.c b/netlink/desc-ethtool.c
index 737196f..2d8aa39 100644
--- a/netlink/desc-ethtool.c
+++ b/netlink/desc-ethtool.c
@@ -158,6 +158,7 @@ static const struct pretty_nla_desc __rings_desc[] = {
NLATTR_DESC_U8_ENUM(ETHTOOL_A_RINGS_TCP_DATA_SPLIT, rings_tcp_data_split),
NLATTR_DESC_U32(ETHTOOL_A_RINGS_CQE_SIZE),
NLATTR_DESC_BOOL(ETHTOOL_A_RINGS_TX_PUSH),
+ NLATTR_DESC_BOOL(ETHTOOL_A_RINGS_RX_PUSH),
};
static const struct pretty_nla_desc __channels_desc[] = {
@@ -451,6 +452,45 @@ static const struct pretty_nla_desc __rss_desc[] = {
NLATTR_DESC_BINARY(ETHTOOL_A_RSS_HKEY),
};
+static const struct pretty_nla_desc __plca_desc[] = {
+ NLATTR_DESC_INVALID(ETHTOOL_A_PLCA_UNSPEC),
+ NLATTR_DESC_NESTED(ETHTOOL_A_PLCA_HEADER, header),
+ NLATTR_DESC_U16(ETHTOOL_A_PLCA_VERSION),
+ NLATTR_DESC_U8(ETHTOOL_A_PLCA_ENABLED),
+ NLATTR_DESC_U8(ETHTOOL_A_PLCA_STATUS),
+ NLATTR_DESC_U32(ETHTOOL_A_PLCA_NODE_CNT),
+ NLATTR_DESC_U32(ETHTOOL_A_PLCA_NODE_ID),
+ NLATTR_DESC_U32(ETHTOOL_A_PLCA_TO_TMR),
+ NLATTR_DESC_U32(ETHTOOL_A_PLCA_BURST_CNT),
+ NLATTR_DESC_U32(ETHTOOL_A_PLCA_BURST_TMR),
+};
+
+static const struct pretty_nla_desc __mm_stat_desc[] = {
+ NLATTR_DESC_INVALID(ETHTOOL_A_MM_STAT_UNSPEC),
+ NLATTR_DESC_BINARY(ETHTOOL_A_MM_STAT_PAD),
+ NLATTR_DESC_U64(ETHTOOL_A_MM_STAT_REASSEMBLY_ERRORS),
+ NLATTR_DESC_U64(ETHTOOL_A_MM_STAT_SMD_ERRORS),
+ NLATTR_DESC_U64(ETHTOOL_A_MM_STAT_REASSEMBLY_OK),
+ NLATTR_DESC_U64(ETHTOOL_A_MM_STAT_RX_FRAG_COUNT),
+ NLATTR_DESC_U64(ETHTOOL_A_MM_STAT_TX_FRAG_COUNT),
+ NLATTR_DESC_U64(ETHTOOL_A_MM_STAT_HOLD_COUNT),
+};
+
+static const struct pretty_nla_desc __mm_desc[] = {
+ NLATTR_DESC_INVALID(ETHTOOL_A_MM_UNSPEC),
+ NLATTR_DESC_NESTED(ETHTOOL_A_MM_HEADER, header),
+ NLATTR_DESC_U8(ETHTOOL_A_MM_PMAC_ENABLED),
+ NLATTR_DESC_U8(ETHTOOL_A_MM_TX_ENABLED),
+ NLATTR_DESC_U8(ETHTOOL_A_MM_TX_ACTIVE),
+ NLATTR_DESC_U32(ETHTOOL_A_MM_TX_MIN_FRAG_SIZE),
+ NLATTR_DESC_U32(ETHTOOL_A_MM_RX_MIN_FRAG_SIZE),
+ NLATTR_DESC_U8(ETHTOOL_A_MM_VERIFY_ENABLED),
+ NLATTR_DESC_U8(ETHTOOL_A_MM_VERIFY_STATUS),
+ NLATTR_DESC_U32(ETHTOOL_A_MM_VERIFY_TIME),
+ NLATTR_DESC_U32(ETHTOOL_A_MM_MAX_VERIFY_TIME),
+ NLATTR_DESC_NESTED(ETHTOOL_A_MM_STATS, mm_stat),
+};
+
const struct pretty_nlmsg_desc ethnl_umsg_desc[] = {
NLMSG_DESC_INVALID(ETHTOOL_MSG_USER_NONE),
NLMSG_DESC(ETHTOOL_MSG_STRSET_GET, strset),
@@ -491,6 +531,11 @@ const struct pretty_nlmsg_desc ethnl_umsg_desc[] = {
NLMSG_DESC(ETHTOOL_MSG_PSE_GET, pse),
NLMSG_DESC(ETHTOOL_MSG_PSE_SET, pse),
NLMSG_DESC(ETHTOOL_MSG_RSS_GET, rss),
+ NLMSG_DESC(ETHTOOL_MSG_PLCA_GET_CFG, plca),
+ NLMSG_DESC(ETHTOOL_MSG_PLCA_SET_CFG, plca),
+ NLMSG_DESC(ETHTOOL_MSG_PLCA_GET_STATUS, plca),
+ NLMSG_DESC(ETHTOOL_MSG_MM_GET, mm),
+ NLMSG_DESC(ETHTOOL_MSG_MM_SET, mm),
};
const unsigned int ethnl_umsg_n_desc = ARRAY_SIZE(ethnl_umsg_desc);
@@ -535,6 +580,11 @@ const struct pretty_nlmsg_desc ethnl_kmsg_desc[] = {
NLMSG_DESC(ETHTOOL_MSG_MODULE_NTF, module),
NLMSG_DESC(ETHTOOL_MSG_PSE_GET_REPLY, pse),
NLMSG_DESC(ETHTOOL_MSG_RSS_GET_REPLY, rss),
+ NLMSG_DESC(ETHTOOL_MSG_PLCA_GET_CFG_REPLY, plca),
+ NLMSG_DESC(ETHTOOL_MSG_PLCA_GET_STATUS_REPLY, plca),
+ NLMSG_DESC(ETHTOOL_MSG_PLCA_NTF, plca),
+ NLMSG_DESC(ETHTOOL_MSG_MM_GET_REPLY, mm),
+ NLMSG_DESC(ETHTOOL_MSG_MM_NTF, mm),
};
const unsigned int ethnl_kmsg_n_desc = ARRAY_SIZE(ethnl_kmsg_desc);
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 9b6dd1a..bbe0633 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -48,6 +48,11 @@ int nl_smodule(struct cmd_context *ctx);
int nl_monitor(struct cmd_context *ctx);
int nl_getmodule(struct cmd_context *ctx);
int nl_grss(struct cmd_context *ctx);
+int nl_plca_get_cfg(struct cmd_context *ctx);
+int nl_plca_set_cfg(struct cmd_context *ctx);
+int nl_plca_get_status(struct cmd_context *ctx);
+int nl_get_mm(struct cmd_context *ctx);
+int nl_set_mm(struct cmd_context *ctx);
void nl_monitor_usage(void);
@@ -116,6 +121,11 @@ nl_get_eeprom_page(struct cmd_context *ctx __maybe_unused,
#define nl_gmodule NULL
#define nl_smodule NULL
#define nl_grss NULL
+#define nl_plca_get_cfg NULL
+#define nl_plca_set_cfg NULL
+#define nl_plca_get_status NULL
+#define nl_get_mm NULL
+#define nl_set_mm NULL
#endif /* ETHTOOL_ENABLE_NETLINK */
diff --git a/netlink/mm.c b/netlink/mm.c
new file mode 100644
index 0000000..d026bc3
--- /dev/null
+++ b/netlink/mm.c
@@ -0,0 +1,270 @@
+/*
+ * mm.c - netlink implementation of MAC merge layer settings
+ *
+ * Implementation of "ethtool --show-mm <dev>" and "ethtool --set-mm <dev> ..."
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+#include "bitset.h"
+#include "parser.h"
+
+/* MM_GET */
+
+static const char *
+mm_verify_state_to_string(enum ethtool_mm_verify_status state)
+{
+ switch (state) {
+ case ETHTOOL_MM_VERIFY_STATUS_INITIAL:
+ return "INITIAL";
+ case ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
+ return "VERIFYING";
+ case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
+ return "SUCCEEDED";
+ case ETHTOOL_MM_VERIFY_STATUS_FAILED:
+ return "FAILED";
+ case ETHTOOL_MM_VERIFY_STATUS_DISABLED:
+ return "DISABLED";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static int show_mm_stats(const struct nlattr *nest)
+{
+ const struct nlattr *tb[ETHTOOL_A_MM_STAT_MAX + 1] = {};
+ DECLARE_ATTR_TB_INFO(tb);
+ static const struct {
+ unsigned int attr;
+ char *name;
+ } stats[] = {
+ { ETHTOOL_A_MM_STAT_REASSEMBLY_ERRORS, "MACMergeFrameAssErrorCount" },
+ { ETHTOOL_A_MM_STAT_SMD_ERRORS, "MACMergeFrameSmdErrorCount" },
+ { ETHTOOL_A_MM_STAT_REASSEMBLY_OK, "MACMergeFrameAssOkCount" },
+ { ETHTOOL_A_MM_STAT_RX_FRAG_COUNT, "MACMergeFragCountRx" },
+ { ETHTOOL_A_MM_STAT_TX_FRAG_COUNT, "MACMergeFragCountTx" },
+ { ETHTOOL_A_MM_STAT_HOLD_COUNT, "MACMergeHoldCount" },
+ };
+ bool header = false;
+ unsigned int i;
+ size_t n;
+ int ret;
+
+ ret = mnl_attr_parse_nested(nest, attr_cb, &tb_info);
+ if (ret < 0)
+ return ret;
+
+ open_json_object("statistics");
+ for (i = 0; i < ARRAY_SIZE(stats); i++) {
+ char fmt[64];
+
+ if (!tb[stats[i].attr])
+ continue;
+
+ if (!header && !is_json_context()) {
+ printf("Statistics:\n");
+ header = true;
+ }
+
+ if (mnl_attr_validate(tb[stats[i].attr], MNL_TYPE_U64)) {
+ fprintf(stderr, "malformed netlink message (statistic)\n");
+ goto err_close_stats;
+ }
+
+ n = snprintf(fmt, sizeof(fmt), " %s: %%" PRIu64 "\n",
+ stats[i].name);
+ if (n >= sizeof(fmt)) {
+ fprintf(stderr, "internal error - malformed label\n");
+ continue;
+ }
+
+ print_u64(PRINT_ANY, stats[i].name, fmt,
+ mnl_attr_get_u64(tb[stats[i].attr]));
+ }
+ close_json_object();
+
+ return 0;
+
+err_close_stats:
+ close_json_object();
+ return -1;
+}
+
+int mm_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+ const struct nlattr *tb[ETHTOOL_A_MM_MAX + 1] = {};
+ struct nl_context *nlctx = data;
+ DECLARE_ATTR_TB_INFO(tb);
+ bool silent;
+ int err_ret;
+ int ret;
+
+ silent = nlctx->is_dump || nlctx->is_monitor;
+ err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
+ ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+ if (ret < 0)
+ return err_ret;
+ nlctx->devname = get_dev_name(tb[ETHTOOL_A_MM_HEADER]);
+ if (!dev_ok(nlctx))
+ return err_ret;
+
+ if (silent)
+ print_nl();
+
+ open_json_object(NULL);
+
+ print_string(PRINT_ANY, "ifname", "MAC Merge layer state for %s:\n",
+ nlctx->devname);
+
+ show_bool("pmac-enabled", "pMAC enabled: %s\n",
+ tb[ETHTOOL_A_MM_PMAC_ENABLED]);
+ show_bool("tx-enabled", "TX enabled: %s\n",
+ tb[ETHTOOL_A_MM_TX_ENABLED]);
+ show_bool("tx-active", "TX active: %s\n", tb[ETHTOOL_A_MM_TX_ACTIVE]);
+ show_u32("tx-min-frag-size", "TX minimum fragment size: ",
+ tb[ETHTOOL_A_MM_TX_MIN_FRAG_SIZE]);
+ show_u32("rx-min-frag-size", "RX minimum fragment size: ",
+ tb[ETHTOOL_A_MM_RX_MIN_FRAG_SIZE]);
+ show_bool("verify-enabled", "Verify enabled: %s\n",
+ tb[ETHTOOL_A_MM_VERIFY_ENABLED]);
+ show_u32("verify-time", "Verify time: ",
+ tb[ETHTOOL_A_MM_VERIFY_TIME]);
+ show_u32("max-verify-time", "Max verify time: ",
+ tb[ETHTOOL_A_MM_MAX_VERIFY_TIME]);
+
+ if (tb[ETHTOOL_A_MM_VERIFY_STATUS]) {
+ u8 val = mnl_attr_get_u8(tb[ETHTOOL_A_MM_VERIFY_STATUS]);
+
+ print_string(PRINT_ANY, "verify-status", "Verification status: %s\n",
+ mm_verify_state_to_string(val));
+ }
+
+ if (tb[ETHTOOL_A_MM_STATS]) {
+ ret = show_mm_stats(tb[ETHTOOL_A_MM_STATS]);
+ if (ret) {
+ fprintf(stderr, "Failed to print stats: %d\n", ret);
+ goto err;
+ }
+ }
+
+ if (!silent)
+ print_nl();
+
+ close_json_object();
+
+ return MNL_CB_OK;
+
+err:
+ close_json_object();
+ return err_ret;
+}
+
+int nl_get_mm(struct cmd_context *ctx)
+{
+ struct nl_context *nlctx = ctx->nlctx;
+ struct nl_socket *nlsk = nlctx->ethnl_socket;
+ u32 flags;
+ int ret;
+
+ if (netlink_cmd_check(ctx, ETHTOOL_MSG_MM_GET, true))
+ return -EOPNOTSUPP;
+ if (ctx->argc > 0) {
+ fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+ *ctx->argp);
+ return 1;
+ }
+
+ flags = get_stats_flag(nlctx, ETHTOOL_MSG_MM_GET, ETHTOOL_A_MM_HEADER);
+ ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_MM_GET,
+ ETHTOOL_A_MM_HEADER, flags);
+ if (ret)
+ return ret;
+
+ new_json_obj(ctx->json);
+ ret = nlsock_send_get_request(nlsk, mm_reply_cb);
+ delete_json_obj();
+ return ret;
+}
+
+/* MM_SET */
+
+static const struct param_parser mm_set_params[] = {
+ {
+ .arg = "verify-enabled",
+ .type = ETHTOOL_A_MM_VERIFY_ENABLED,
+ .handler = nl_parse_u8bool,
+ .min_argc = 1,
+ },
+ {
+ .arg = "verify-time",
+ .type = ETHTOOL_A_MM_VERIFY_TIME,
+ .handler = nl_parse_direct_u32,
+ .min_argc = 1,
+ },
+ {
+ .arg = "tx-enabled",
+ .type = ETHTOOL_A_MM_TX_ENABLED,
+ .handler = nl_parse_u8bool,
+ .min_argc = 1,
+ },
+ {
+ .arg = "pmac-enabled",
+ .type = ETHTOOL_A_MM_PMAC_ENABLED,
+ .handler = nl_parse_u8bool,
+ .min_argc = 1,
+ },
+ {
+ .arg = "tx-min-frag-size",
+ .type = ETHTOOL_A_MM_TX_MIN_FRAG_SIZE,
+ .handler = nl_parse_direct_u32,
+ .min_argc = 1,
+ },
+ {}
+};
+
+int nl_set_mm(struct cmd_context *ctx)
+{
+ struct nl_context *nlctx = ctx->nlctx;
+ struct nl_msg_buff *msgbuff;
+ struct nl_socket *nlsk;
+ int ret;
+
+ if (netlink_cmd_check(ctx, ETHTOOL_MSG_MM_SET, false))
+ return -EOPNOTSUPP;
+
+ nlctx->cmd = "--set-mm";
+ nlctx->argp = ctx->argp;
+ nlctx->argc = ctx->argc;
+ nlctx->devname = ctx->devname;
+ nlsk = nlctx->ethnl_socket;
+ msgbuff = &nlsk->msgbuff;
+
+ ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_MM_SET,
+ NLM_F_REQUEST | NLM_F_ACK);
+ if (ret)
+ return ret;
+
+ if (ethnla_fill_header(msgbuff, ETHTOOL_A_MM_HEADER,
+ ctx->devname, 0))
+ return -EMSGSIZE;
+
+ ret = nl_parser(nlctx, mm_set_params, NULL, PARSER_GROUP_NONE, NULL);
+ if (ret)
+ return ret;
+
+ ret = nlsock_sendmsg(nlsk, NULL);
+ if (ret < 0)
+ return ret;
+
+ ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
+ if (ret)
+ return nlctx->exit_code;
+
+ return 0;
+}
diff --git a/netlink/pause.c b/netlink/pause.c
index 867d0da..da444bd 100644
--- a/netlink/pause.c
+++ b/netlink/pause.c
@@ -216,6 +216,24 @@ err_close_dev:
return err_ret;
}
+static const struct lookup_entry_u32 stats_src_values[] = {
+ { .arg = "aggregate", .val = ETHTOOL_MAC_STATS_SRC_AGGREGATE },
+ { .arg = "emac", .val = ETHTOOL_MAC_STATS_SRC_EMAC },
+ { .arg = "pmac", .val = ETHTOOL_MAC_STATS_SRC_PMAC },
+ {}
+};
+
+static const struct param_parser gpause_params[] = {
+ {
+ .arg = "--src",
+ .type = ETHTOOL_A_PAUSE_STATS_SRC,
+ .handler = nl_parse_lookup_u32,
+ .handler_data = stats_src_values,
+ .min_argc = 1,
+ },
+ {}
+};
+
int nl_gpause(struct cmd_context *ctx)
{
struct nl_context *nlctx = ctx->nlctx;
@@ -225,11 +243,6 @@ int nl_gpause(struct cmd_context *ctx)
if (netlink_cmd_check(ctx, ETHTOOL_MSG_PAUSE_GET, true))
return -EOPNOTSUPP;
- if (ctx->argc > 0) {
- fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
- *ctx->argp);
- return 1;
- }
flags = get_stats_flag(nlctx, ETHTOOL_MSG_PAUSE_GET,
ETHTOOL_A_PAUSE_HEADER);
@@ -238,6 +251,16 @@ int nl_gpause(struct cmd_context *ctx)
if (ret < 0)
return ret;
+ nlctx->cmd = "-a";
+ nlctx->argp = ctx->argp;
+ nlctx->argc = ctx->argc;
+ nlctx->devname = ctx->devname;
+ nlsk = nlctx->ethnl_socket;
+
+ ret = nl_parser(nlctx, gpause_params, NULL, PARSER_GROUP_NONE, NULL);
+ if (ret < 0)
+ return 1;
+
new_json_obj(ctx->json);
ret = nlsock_send_get_request(nlsk, pause_reply_cb);
delete_json_obj();
diff --git a/netlink/plca.c b/netlink/plca.c
new file mode 100644
index 0000000..7d61e3b
--- /dev/null
+++ b/netlink/plca.c
@@ -0,0 +1,296 @@
+/*
+ * plca.c - netlink implementation of plca command
+ *
+ * Implementation of "ethtool --show-plca <dev>" and
+ * "ethtool --set-plca <dev> ..."
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+#include "bitset.h"
+#include "parser.h"
+
+/* PLCA_GET_CFG */
+
+int plca_get_cfg_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+ const struct nlattr *tb[ETHTOOL_A_PLCA_MAX + 1] = {};
+ DECLARE_ATTR_TB_INFO(tb);
+ struct nl_context *nlctx = data;
+ bool silent;
+ int idv = 255;
+ int err_ret;
+ int val;
+ int ret;
+
+ silent = nlctx->is_dump || nlctx->is_monitor;
+ err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
+ ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+ if (ret < 0)
+ return err_ret;
+
+ nlctx->devname = get_dev_name(tb[ETHTOOL_A_PLCA_HEADER]);
+ if (!dev_ok(nlctx))
+ return err_ret;
+
+ if (silent)
+ putchar('\n');
+
+ printf("PLCA settings for %s:\n", nlctx->devname);
+
+ // check if PLCA is enabled
+ printf("\tEnabled: ");
+
+ if (!tb[ETHTOOL_A_PLCA_ENABLED]) {
+ printf("not supported");
+ } else {
+ val = mnl_attr_get_u8(tb[ETHTOOL_A_PLCA_ENABLED]);
+ printf(val ? "Yes" : "No");
+ }
+ putchar('\n');
+
+ // get node ID
+ printf("\tlocal node ID: ");
+
+ if (!tb[ETHTOOL_A_PLCA_NODE_ID]) {
+ printf("not supported");
+ } else {
+ idv = mnl_attr_get_u32(tb[ETHTOOL_A_PLCA_NODE_ID]);
+ printf("%u (%s)", idv,
+ idv == 0 ? "coordinator" :
+ idv == 255 ? "unconfigured" : "follower");
+ }
+ putchar('\n');
+
+ // get node count
+ printf("\tNode count: ");
+ if (!tb[ETHTOOL_A_PLCA_NODE_CNT]) {
+ printf("not supported");
+ } else {
+ val = mnl_attr_get_u32(tb[ETHTOOL_A_PLCA_NODE_CNT]);
+ printf("%u", val);
+
+ // The node count is ignored by follower nodes. However, it can
+ // be pre-set to enable fast coordinator role switchover.
+ // Therefore, on a follower node we still wanto to show it,
+ // indicating it is not currently used.
+ if (tb[ETHTOOL_A_PLCA_NODE_ID] && idv != 0)
+ printf(" (ignored)");
+ }
+ putchar('\n');
+
+ // get TO timer (transmit opportunity timer)
+ printf("\tTO timer: ");
+ if (!tb[ETHTOOL_A_PLCA_TO_TMR]) {
+ printf("not supported");
+ } else {
+ val = mnl_attr_get_u32(tb[ETHTOOL_A_PLCA_TO_TMR]);
+ printf("%u BT", val);
+ }
+ putchar('\n');
+
+ // get burst count
+ printf("\tBurst count: ");
+ if (!tb[ETHTOOL_A_PLCA_BURST_CNT]) {
+ printf("not supported");
+ } else {
+ val = mnl_attr_get_u32(tb[ETHTOOL_A_PLCA_BURST_CNT]);
+ printf("%u (%s)", val,
+ val > 0 ? "enabled" : "disabled");
+ }
+ putchar('\n');
+
+ // get burst timer
+ printf("\tBurst timer: ");
+ if (!tb[ETHTOOL_A_PLCA_BURST_TMR]) {
+ printf("not supported");
+ } else {
+ val = mnl_attr_get_u32(tb[ETHTOOL_A_PLCA_BURST_TMR]);
+ printf("%u BT", val);
+ }
+ putchar('\n');
+
+ return MNL_CB_OK;
+}
+
+
+int nl_plca_get_cfg(struct cmd_context *ctx)
+{
+ struct nl_context *nlctx = ctx->nlctx;
+ struct nl_socket *nlsk = nlctx->ethnl_socket;
+ int ret;
+
+ if (netlink_cmd_check(ctx, ETHTOOL_MSG_PLCA_GET_CFG, true))
+ return -EOPNOTSUPP;
+
+ if (ctx->argc > 0) {
+ fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+ *ctx->argp);
+ return 1;
+ }
+
+ ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_PLCA_GET_CFG,
+ ETHTOOL_A_PLCA_HEADER, 0);
+
+ if (ret < 0)
+ return ret;
+
+ return nlsock_send_get_request(nlsk, plca_get_cfg_reply_cb);
+}
+
+/* PLCA_SET_CFG */
+
+static const struct param_parser set_plca_params[] = {
+ {
+ .arg = "enable",
+ .type = ETHTOOL_A_PLCA_ENABLED,
+ .handler = nl_parse_u8bool,
+ .min_argc = 1,
+ },
+ {
+ .arg = "node-id",
+ .type = ETHTOOL_A_PLCA_NODE_ID,
+ .handler = nl_parse_direct_u32,
+ .min_argc = 1,
+ },
+ {
+ .arg = "node-cnt",
+ .type = ETHTOOL_A_PLCA_NODE_CNT,
+ .handler = nl_parse_direct_u32,
+ .min_argc = 1,
+ },
+ {
+ .arg = "to-tmr",
+ .type = ETHTOOL_A_PLCA_TO_TMR,
+ .handler = nl_parse_direct_u32,
+ .min_argc = 1,
+ },
+ {
+ .arg = "burst-cnt",
+ .type = ETHTOOL_A_PLCA_BURST_CNT,
+ .handler = nl_parse_direct_u32,
+ .min_argc = 1,
+ },
+ {
+ .arg = "burst-tmr",
+ .type = ETHTOOL_A_PLCA_BURST_TMR,
+ .handler = nl_parse_direct_u32,
+ .min_argc = 1,
+ },
+ {}
+};
+
+int nl_plca_set_cfg(struct cmd_context *ctx)
+{
+ struct nl_context *nlctx = ctx->nlctx;
+ struct nl_msg_buff *msgbuff;
+ struct nl_socket *nlsk;
+ int ret;
+
+ if (netlink_cmd_check(ctx, ETHTOOL_MSG_PLCA_SET_CFG, false))
+ return -EOPNOTSUPP;
+ if (!ctx->argc) {
+ fprintf(stderr,
+ "ethtool (--set-plca-cfg): parameters missing\n");
+ return 1;
+ }
+
+ nlctx->cmd = "--set-plca-cfg";
+ nlctx->argp = ctx->argp;
+ nlctx->argc = ctx->argc;
+ nlctx->devname = ctx->devname;
+ nlsk = nlctx->ethnl_socket;
+ msgbuff = &nlsk->msgbuff;
+
+ ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_PLCA_SET_CFG,
+ NLM_F_REQUEST | NLM_F_ACK);
+ if (ret < 0)
+ return 2;
+ if (ethnla_fill_header(msgbuff, ETHTOOL_A_PLCA_HEADER,
+ ctx->devname, 0))
+ return -EMSGSIZE;
+
+ ret = nl_parser(nlctx, set_plca_params, NULL, PARSER_GROUP_NONE, NULL);
+ if (ret < 0)
+ return 1;
+
+ ret = nlsock_sendmsg(nlsk, NULL);
+ if (ret < 0)
+ return 76;
+ ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
+ if (ret == 0)
+ return 0;
+ else
+ return nlctx->exit_code ?: 76;
+}
+
+/* PLCA_GET_STATUS */
+
+int plca_get_status_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+ const struct nlattr *tb[ETHTOOL_A_PLCA_MAX + 1] = {};
+ DECLARE_ATTR_TB_INFO(tb);
+ struct nl_context *nlctx = data;
+ bool silent;
+ int err_ret;
+ int ret;
+ u8 val;
+
+ silent = nlctx->is_dump || nlctx->is_monitor;
+ err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
+ ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+ if (ret < 0)
+ return err_ret;
+
+ nlctx->devname = get_dev_name(tb[ETHTOOL_A_PLCA_HEADER]);
+ if (!dev_ok(nlctx))
+ return err_ret;
+
+ if (silent)
+ putchar('\n');
+
+ printf("PLCA status of %s:\n", nlctx->devname);
+
+ // check whether the Open Alliance TC14 standard memory map is supported
+ printf("\tStatus: ");
+
+ if (!tb[ETHTOOL_A_PLCA_STATUS]) {
+ printf("not supported");
+ } else {
+ val = mnl_attr_get_u8(tb[ETHTOOL_A_PLCA_STATUS]);
+ printf(val ? "on" : "off");
+ }
+ putchar('\n');
+
+ return MNL_CB_OK;
+}
+
+
+int nl_plca_get_status(struct cmd_context *ctx)
+{
+ struct nl_context *nlctx = ctx->nlctx;
+ struct nl_socket *nlsk = nlctx->ethnl_socket;
+ int ret;
+
+ if (netlink_cmd_check(ctx, ETHTOOL_MSG_PLCA_GET_STATUS, true))
+ return -EOPNOTSUPP;
+
+ if (ctx->argc > 0) {
+ fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+ *ctx->argp);
+ return 1;
+ }
+
+ ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_PLCA_GET_STATUS,
+ ETHTOOL_A_PLCA_HEADER, 0);
+
+ if (ret < 0)
+ return ret;
+
+ return nlsock_send_get_request(nlsk, plca_get_status_reply_cb);
+}
diff --git a/netlink/rings.c b/netlink/rings.c
index d51ef78..57bfb36 100644
--- a/netlink/rings.c
+++ b/netlink/rings.c
@@ -57,6 +57,7 @@ int rings_reply_cb(const struct nlmsghdr *nlhdr, void *data)
show_u32("rx-buf-len", "RX Buf Len:\t", tb[ETHTOOL_A_RINGS_RX_BUF_LEN]);
show_u32("cqe-size", "CQE Size:\t", tb[ETHTOOL_A_RINGS_CQE_SIZE]);
show_bool("tx-push", "TX Push:\t%s\n", tb[ETHTOOL_A_RINGS_TX_PUSH]);
+ show_bool("rx-push", "RX Push:\t%s\n", tb[ETHTOOL_A_RINGS_RX_PUSH]);
tcp_hds_fmt = "TCP data split:\t%s\n";
tcp_hds_key = "tcp-data-split";
@@ -154,6 +155,12 @@ static const struct param_parser sring_params[] = {
.handler = nl_parse_u8bool,
.min_argc = 1,
},
+ {
+ .arg = "rx-push",
+ .type = ETHTOOL_A_RINGS_RX_PUSH,
+ .handler = nl_parse_u8bool,
+ .min_argc = 1,
+ },
{}
};
diff --git a/netlink/settings.c b/netlink/settings.c
index f96f324..168b182 100644
--- a/netlink/settings.c
+++ b/netlink/settings.c
@@ -172,6 +172,9 @@ static const struct link_mode_info link_modes[] = {
[ETHTOOL_LINK_MODE_800000baseDR8_2_Full_BIT] = __REAL(800000),
[ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT] = __REAL(800000),
[ETHTOOL_LINK_MODE_800000baseVR8_Full_BIT] = __REAL(800000),
+ [ETHTOOL_LINK_MODE_10baseT1S_Full_BIT] = __REAL(10),
+ [ETHTOOL_LINK_MODE_10baseT1S_Half_BIT] = __HALF_DUPLEX(10),
+ [ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT] = __HALF_DUPLEX(10),
};
const unsigned int link_modes_count = ARRAY_SIZE(link_modes);
@@ -896,6 +899,70 @@ int debug_reply_cb(const struct nlmsghdr *nlhdr, void *data)
return MNL_CB_OK;
}
+int plca_cfg_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+ const struct nlattr *tb[ETHTOOL_A_PLCA_MAX + 1] = {};
+ DECLARE_ATTR_TB_INFO(tb);
+ struct nl_context *nlctx = data;
+ int ret;
+
+ if (nlctx->is_dump || nlctx->is_monitor)
+ nlctx->no_banner = false;
+ ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+ if (ret < 0)
+ return ret;
+ nlctx->devname = get_dev_name(tb[ETHTOOL_A_PLCA_HEADER]);
+ if (!dev_ok(nlctx))
+ return MNL_CB_OK;
+
+ print_banner(nlctx);
+ printf("\tPLCA support: ");
+
+ if (tb[ETHTOOL_A_PLCA_VERSION]) {
+ uint16_t val = mnl_attr_get_u16(tb[ETHTOOL_A_PLCA_VERSION]);
+
+ printf("OPEN Alliance v%u.%u",
+ (unsigned int)((val >> 4) & 0xF),
+ (unsigned int)(val & 0xF));
+ } else
+ printf("non-standard");
+
+ printf("\n");
+
+ return MNL_CB_OK;
+}
+
+int plca_status_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+ const struct nlattr *tb[ETHTOOL_A_PLCA_MAX + 1] = {};
+ DECLARE_ATTR_TB_INFO(tb);
+ struct nl_context *nlctx = data;
+ int ret;
+
+ if (nlctx->is_dump || nlctx->is_monitor)
+ nlctx->no_banner = false;
+ ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+ if (ret < 0)
+ return ret;
+ nlctx->devname = get_dev_name(tb[ETHTOOL_A_PLCA_HEADER]);
+ if (!dev_ok(nlctx))
+ return MNL_CB_OK;
+
+ print_banner(nlctx);
+ printf("\tPLCA status: ");
+
+ if (tb[ETHTOOL_A_PLCA_STATUS]) {
+ uint8_t val = mnl_attr_get_u8(tb[ETHTOOL_A_PLCA_STATUS]);
+
+ printf(val ? "up" : "down");
+ } else
+ printf("unknown");
+
+ printf("\n");
+
+ return MNL_CB_OK;
+}
+
static int gset_request(struct nl_context *nlctx, uint8_t msg_type,
uint16_t hdr_attr, mnl_cb_t cb)
{
@@ -920,7 +987,9 @@ int nl_gset(struct cmd_context *ctx)
netlink_cmd_check(ctx, ETHTOOL_MSG_LINKINFO_GET, true) ||
netlink_cmd_check(ctx, ETHTOOL_MSG_WOL_GET, true) ||
netlink_cmd_check(ctx, ETHTOOL_MSG_DEBUG_GET, true) ||
- netlink_cmd_check(ctx, ETHTOOL_MSG_LINKSTATE_GET, true))
+ netlink_cmd_check(ctx, ETHTOOL_MSG_LINKSTATE_GET, true) ||
+ netlink_cmd_check(ctx, ETHTOOL_MSG_PLCA_GET_CFG, true) ||
+ netlink_cmd_check(ctx, ETHTOOL_MSG_PLCA_GET_STATUS, true))
return -EOPNOTSUPP;
nlctx->suppress_nlerr = 1;
@@ -940,6 +1009,11 @@ int nl_gset(struct cmd_context *ctx)
if (ret == -ENODEV)
return ret;
+ ret = gset_request(nlctx, ETHTOOL_MSG_PLCA_GET_CFG,
+ ETHTOOL_A_PLCA_HEADER, plca_cfg_reply_cb);
+ if (ret == -ENODEV)
+ return ret;
+
ret = gset_request(nlctx, ETHTOOL_MSG_DEBUG_GET, ETHTOOL_A_DEBUG_HEADER,
debug_reply_cb);
if (ret == -ENODEV)
@@ -950,6 +1024,11 @@ int nl_gset(struct cmd_context *ctx)
if (ret == -ENODEV)
return ret;
+ ret = gset_request(nlctx, ETHTOOL_MSG_PLCA_GET_STATUS,
+ ETHTOOL_A_PLCA_HEADER, plca_status_reply_cb);
+ if (ret == -ENODEV)
+ return ret;
+
if (!nlctx->no_banner) {
printf("No data available\n");
return 75;
diff --git a/netlink/stats.c b/netlink/stats.c
index 9f609a4..8620d8d 100644
--- a/netlink/stats.c
+++ b/netlink/stats.c
@@ -268,6 +268,13 @@ err_free:
return ret;
}
+static const struct lookup_entry_u32 stats_src_values[] = {
+ { .arg = "aggregate", .val = ETHTOOL_MAC_STATS_SRC_AGGREGATE },
+ { .arg = "emac", .val = ETHTOOL_MAC_STATS_SRC_EMAC },
+ { .arg = "pmac", .val = ETHTOOL_MAC_STATS_SRC_PMAC },
+ {}
+};
+
static const struct param_parser stats_params[] = {
{
.arg = "--groups",
@@ -283,6 +290,13 @@ static const struct param_parser stats_params[] = {
.handler = stats_parse_all_groups,
.alt_group = 1,
},
+ {
+ .arg = "--src",
+ .type = ETHTOOL_A_STATS_SRC,
+ .handler = nl_parse_lookup_u32,
+ .handler_data = stats_src_values,
+ .min_argc = 1,
+ },
{}
};
diff --git a/uapi/linux/ethtool.h b/uapi/linux/ethtool.h
index d174870..1d0731b 100644
--- a/uapi/linux/ethtool.h
+++ b/uapi/linux/ethtool.h
@@ -710,6 +710,24 @@ enum ethtool_stringset {
};
/**
+ * enum ethtool_mac_stats_src - source of ethtool MAC statistics
+ * @ETHTOOL_MAC_STATS_SRC_AGGREGATE:
+ * if device supports a MAC merge layer, this retrieves the aggregate
+ * statistics of the eMAC and pMAC. Otherwise, it retrieves just the
+ * statistics of the single (express) MAC.
+ * @ETHTOOL_MAC_STATS_SRC_EMAC:
+ * if device supports a MM layer, this retrieves the eMAC statistics.
+ * Otherwise, it retrieves the statistics of the single (express) MAC.
+ * @ETHTOOL_MAC_STATS_SRC_PMAC:
+ * if device supports a MM layer, this retrieves the pMAC statistics.
+ */
+enum ethtool_mac_stats_src {
+ ETHTOOL_MAC_STATS_SRC_AGGREGATE,
+ ETHTOOL_MAC_STATS_SRC_EMAC,
+ ETHTOOL_MAC_STATS_SRC_PMAC,
+};
+
+/**
* enum ethtool_module_power_mode_policy - plug-in module power mode policy
* @ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH: Module is always in high power mode.
* @ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO: Module is transitioned by the host
@@ -778,6 +796,31 @@ enum ethtool_podl_pse_pw_d_status {
};
/**
+ * enum ethtool_mm_verify_status - status of MAC Merge Verify function
+ * @ETHTOOL_MM_VERIFY_STATUS_UNKNOWN:
+ * verification status is unknown
+ * @ETHTOOL_MM_VERIFY_STATUS_INITIAL:
+ * the 802.3 Verify State diagram is in the state INIT_VERIFICATION
+ * @ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
+ * the Verify State diagram is in the state VERIFICATION_IDLE,
+ * SEND_VERIFY or WAIT_FOR_RESPONSE
+ * @ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
+ * indicates that the Verify State diagram is in the state VERIFIED
+ * @ETHTOOL_MM_VERIFY_STATUS_FAILED:
+ * the Verify State diagram is in the state VERIFY_FAIL
+ * @ETHTOOL_MM_VERIFY_STATUS_DISABLED:
+ * verification of preemption operation is disabled
+ */
+enum ethtool_mm_verify_status {
+ ETHTOOL_MM_VERIFY_STATUS_UNKNOWN,
+ ETHTOOL_MM_VERIFY_STATUS_INITIAL,
+ ETHTOOL_MM_VERIFY_STATUS_VERIFYING,
+ ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED,
+ ETHTOOL_MM_VERIFY_STATUS_FAILED,
+ ETHTOOL_MM_VERIFY_STATUS_DISABLED,
+};
+
+/**
* struct ethtool_gstrings - string set for data tagging
* @cmd: Command number = %ETHTOOL_GSTRINGS
* @string_set: String set ID; one of &enum ethtool_stringset
@@ -1181,7 +1224,7 @@ struct ethtool_rxnfc {
__u32 rule_cnt;
__u32 rss_context;
};
- __u32 rule_locs[0];
+ __u32 rule_locs[];
};
@@ -1739,6 +1782,9 @@ enum ethtool_link_mode_bit_indices {
ETHTOOL_LINK_MODE_800000baseDR8_2_Full_BIT = 96,
ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT = 97,
ETHTOOL_LINK_MODE_800000baseVR8_Full_BIT = 98,
+ ETHTOOL_LINK_MODE_10baseT1S_Full_BIT = 99,
+ ETHTOOL_LINK_MODE_10baseT1S_Half_BIT = 100,
+ ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT = 101,
/* must be last entry */
__ETHTOOL_LINK_MODE_MASK_NBITS
diff --git a/uapi/linux/ethtool_netlink.h b/uapi/linux/ethtool_netlink.h
index 0d553ec..13493c9 100644
--- a/uapi/linux/ethtool_netlink.h
+++ b/uapi/linux/ethtool_netlink.h
@@ -52,6 +52,11 @@ enum {
ETHTOOL_MSG_PSE_GET,
ETHTOOL_MSG_PSE_SET,
ETHTOOL_MSG_RSS_GET,
+ ETHTOOL_MSG_PLCA_GET_CFG,
+ ETHTOOL_MSG_PLCA_SET_CFG,
+ ETHTOOL_MSG_PLCA_GET_STATUS,
+ ETHTOOL_MSG_MM_GET,
+ ETHTOOL_MSG_MM_SET,
/* add new constants above here */
__ETHTOOL_MSG_USER_CNT,
@@ -99,6 +104,11 @@ enum {
ETHTOOL_MSG_MODULE_NTF,
ETHTOOL_MSG_PSE_GET_REPLY,
ETHTOOL_MSG_RSS_GET_REPLY,
+ ETHTOOL_MSG_PLCA_GET_CFG_REPLY,
+ ETHTOOL_MSG_PLCA_GET_STATUS_REPLY,
+ ETHTOOL_MSG_PLCA_NTF,
+ ETHTOOL_MSG_MM_GET_REPLY,
+ ETHTOOL_MSG_MM_NTF,
/* add new constants above here */
__ETHTOOL_MSG_KERNEL_CNT,
@@ -346,6 +356,7 @@ enum {
ETHTOOL_A_RINGS_TCP_DATA_SPLIT, /* u8 */
ETHTOOL_A_RINGS_CQE_SIZE, /* u32 */
ETHTOOL_A_RINGS_TX_PUSH, /* u8 */
+ ETHTOOL_A_RINGS_RX_PUSH, /* u8 */
/* add new constants above here */
__ETHTOOL_A_RINGS_CNT,
@@ -400,6 +411,9 @@ enum {
ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL, /* u32 */
ETHTOOL_A_COALESCE_USE_CQE_MODE_TX, /* u8 */
ETHTOOL_A_COALESCE_USE_CQE_MODE_RX, /* u8 */
+ ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES, /* u32 */
+ ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES, /* u32 */
+ ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS, /* u32 */
/* add new constants above here */
__ETHTOOL_A_COALESCE_CNT,
@@ -415,6 +429,7 @@ enum {
ETHTOOL_A_PAUSE_RX, /* u8 */
ETHTOOL_A_PAUSE_TX, /* u8 */
ETHTOOL_A_PAUSE_STATS, /* nest - _PAUSE_STAT_* */
+ ETHTOOL_A_PAUSE_STATS_SRC, /* u32 */
/* add new constants above here */
__ETHTOOL_A_PAUSE_CNT,
@@ -731,6 +746,8 @@ enum {
ETHTOOL_A_STATS_GRP, /* nest - _A_STATS_GRP_* */
+ ETHTOOL_A_STATS_SRC, /* u32 */
+
/* add new constants above here */
__ETHTOOL_A_STATS_CNT,
ETHTOOL_A_STATS_MAX = (__ETHTOOL_A_STATS_CNT - 1)
@@ -894,6 +911,68 @@ enum {
ETHTOOL_A_RSS_MAX = (__ETHTOOL_A_RSS_CNT - 1),
};
+/* PLCA */
+
+enum {
+ ETHTOOL_A_PLCA_UNSPEC,
+ ETHTOOL_A_PLCA_HEADER, /* nest - _A_HEADER_* */
+ ETHTOOL_A_PLCA_VERSION, /* u16 */
+ ETHTOOL_A_PLCA_ENABLED, /* u8 */
+ ETHTOOL_A_PLCA_STATUS, /* u8 */
+ ETHTOOL_A_PLCA_NODE_CNT, /* u32 */
+ ETHTOOL_A_PLCA_NODE_ID, /* u32 */
+ ETHTOOL_A_PLCA_TO_TMR, /* u32 */
+ ETHTOOL_A_PLCA_BURST_CNT, /* u32 */
+ ETHTOOL_A_PLCA_BURST_TMR, /* u32 */
+
+ /* add new constants above here */
+ __ETHTOOL_A_PLCA_CNT,
+ ETHTOOL_A_PLCA_MAX = (__ETHTOOL_A_PLCA_CNT - 1)
+};
+
+/* MAC Merge (802.3) */
+
+enum {
+ ETHTOOL_A_MM_STAT_UNSPEC,
+ ETHTOOL_A_MM_STAT_PAD,
+
+ /* aMACMergeFrameAssErrorCount */
+ ETHTOOL_A_MM_STAT_REASSEMBLY_ERRORS, /* u64 */
+ /* aMACMergeFrameSmdErrorCount */
+ ETHTOOL_A_MM_STAT_SMD_ERRORS, /* u64 */
+ /* aMACMergeFrameAssOkCount */
+ ETHTOOL_A_MM_STAT_REASSEMBLY_OK, /* u64 */
+ /* aMACMergeFragCountRx */
+ ETHTOOL_A_MM_STAT_RX_FRAG_COUNT, /* u64 */
+ /* aMACMergeFragCountTx */
+ ETHTOOL_A_MM_STAT_TX_FRAG_COUNT, /* u64 */
+ /* aMACMergeHoldCount */
+ ETHTOOL_A_MM_STAT_HOLD_COUNT, /* u64 */
+
+ /* add new constants above here */
+ __ETHTOOL_A_MM_STAT_CNT,
+ ETHTOOL_A_MM_STAT_MAX = (__ETHTOOL_A_MM_STAT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MM_UNSPEC,
+ ETHTOOL_A_MM_HEADER, /* nest - _A_HEADER_* */
+ ETHTOOL_A_MM_PMAC_ENABLED, /* u8 */
+ ETHTOOL_A_MM_TX_ENABLED, /* u8 */
+ ETHTOOL_A_MM_TX_ACTIVE, /* u8 */
+ ETHTOOL_A_MM_TX_MIN_FRAG_SIZE, /* u32 */
+ ETHTOOL_A_MM_RX_MIN_FRAG_SIZE, /* u32 */
+ ETHTOOL_A_MM_VERIFY_ENABLED, /* u8 */
+ ETHTOOL_A_MM_VERIFY_STATUS, /* u8 */
+ ETHTOOL_A_MM_VERIFY_TIME, /* u32 */
+ ETHTOOL_A_MM_MAX_VERIFY_TIME, /* u32 */
+ ETHTOOL_A_MM_STATS, /* nest - _A_MM_STAT_* */
+
+ /* add new constants above here */
+ __ETHTOOL_A_MM_CNT,
+ ETHTOOL_A_MM_MAX = (__ETHTOOL_A_MM_CNT - 1)
+};
+
/* generic netlink info */
#define ETHTOOL_GENL_NAME "ethtool"
#define ETHTOOL_GENL_VERSION 1
diff --git a/uapi/linux/if_link.h b/uapi/linux/if_link.h
index 147ad0a..d61bd32 100644
--- a/uapi/linux/if_link.h
+++ b/uapi/linux/if_link.h
@@ -374,6 +374,9 @@ enum {
IFLA_DEVLINK_PORT,
+ IFLA_GSO_IPV4_MAX_SIZE,
+ IFLA_GRO_IPV4_MAX_SIZE,
+
__IFLA_MAX
};
@@ -562,6 +565,8 @@ enum {
IFLA_BRPORT_MCAST_EHT_HOSTS_CNT,
IFLA_BRPORT_LOCKED,
IFLA_BRPORT_MAB,
+ IFLA_BRPORT_MCAST_N_GROUPS,
+ IFLA_BRPORT_MCAST_MAX_GROUPS,
__IFLA_BRPORT_MAX
};
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
diff --git a/uapi/linux/rtnetlink.h b/uapi/linux/rtnetlink.h
index f4a540c..217b25b 100644
--- a/uapi/linux/rtnetlink.h
+++ b/uapi/linux/rtnetlink.h
@@ -635,6 +635,7 @@ enum {
TCA_INGRESS_BLOCK,
TCA_EGRESS_BLOCK,
TCA_DUMP_FLAGS,
+ TCA_EXT_WARN_MSG,
__TCA_MAX
};